@x12i/catalox 2.7.0 → 3.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/README.md +73 -31
- package/dist/src/catalox/authorization.js +1 -1
- package/dist/src/catalox/authorization.js.map +1 -1
- package/dist/src/catalox/catalog-lifecycle.d.ts +29 -0
- package/dist/src/catalox/catalog-lifecycle.d.ts.map +1 -0
- package/dist/src/catalox/catalog-lifecycle.js +480 -0
- package/dist/src/catalox/catalog-lifecycle.js.map +1 -0
- package/dist/src/catalox/catalox-bound.d.ts +135 -0
- package/dist/src/catalox/catalox-bound.d.ts.map +1 -0
- package/dist/src/catalox/catalox-bound.js +190 -0
- package/dist/src/catalox/catalox-bound.js.map +1 -0
- package/dist/src/catalox/catalox.d.ts +34 -4
- package/dist/src/catalox/catalox.d.ts.map +1 -1
- package/dist/src/catalox/catalox.js +508 -72
- package/dist/src/catalox/catalox.js.map +1 -1
- package/dist/src/catalox/context.js +2 -2
- package/dist/src/catalox/context.js.map +1 -1
- package/dist/src/catalox/create-catalox.d.ts +28 -0
- package/dist/src/catalox/create-catalox.d.ts.map +1 -0
- package/dist/src/catalox/create-catalox.js +90 -0
- package/dist/src/catalox/create-catalox.js.map +1 -0
- package/dist/src/catalox/index.d.ts +4 -0
- package/dist/src/catalox/index.d.ts.map +1 -1
- package/dist/src/catalox/index.js +4 -0
- package/dist/src/catalox/index.js.map +1 -1
- package/dist/src/catalox/native-catalog-merge.d.ts +12 -0
- package/dist/src/catalox/native-catalog-merge.d.ts.map +1 -0
- package/dist/src/catalox/native-catalog-merge.js +102 -0
- package/dist/src/catalox/native-catalog-merge.js.map +1 -0
- package/dist/src/catalox/native-scope.d.ts +28 -0
- package/dist/src/catalox/native-scope.d.ts.map +1 -0
- package/dist/src/catalox/native-scope.js +184 -0
- package/dist/src/catalox/native-scope.js.map +1 -0
- package/dist/src/catalox/record-history.d.ts +53 -0
- package/dist/src/catalox/record-history.d.ts.map +1 -0
- package/dist/src/catalox/record-history.js +158 -0
- package/dist/src/catalox/record-history.js.map +1 -0
- package/dist/src/cli/index.js +148 -42
- package/dist/src/cli/index.js.map +1 -1
- package/dist/src/contracts/apps.d.ts +2 -0
- package/dist/src/contracts/apps.d.ts.map +1 -1
- package/dist/src/contracts/catalog-lifecycle.d.ts +70 -0
- package/dist/src/contracts/catalog-lifecycle.d.ts.map +1 -0
- package/dist/src/contracts/catalog-lifecycle.js +2 -0
- package/dist/src/contracts/catalog-lifecycle.js.map +1 -0
- package/dist/src/contracts/catalogs.d.ts +54 -0
- package/dist/src/contracts/catalogs.d.ts.map +1 -1
- package/dist/src/contracts/catalogs.js.map +1 -1
- package/dist/src/contracts/context.d.ts +5 -1
- package/dist/src/contracts/context.d.ts.map +1 -1
- package/dist/src/contracts/descriptors.d.ts +6 -0
- package/dist/src/contracts/descriptors.d.ts.map +1 -1
- package/dist/src/contracts/index.d.ts +5 -2
- package/dist/src/contracts/index.d.ts.map +1 -1
- package/dist/src/contracts/index.js.map +1 -1
- package/dist/src/contracts/items.d.ts +19 -0
- package/dist/src/contracts/items.d.ts.map +1 -1
- package/dist/src/contracts/record-history.d.ts +66 -0
- package/dist/src/contracts/record-history.d.ts.map +1 -0
- package/dist/src/contracts/record-history.js +2 -0
- package/dist/src/contracts/record-history.js.map +1 -0
- package/dist/src/embedder.d.ts +17 -0
- package/dist/src/embedder.d.ts.map +1 -0
- package/dist/src/embedder.js +17 -0
- package/dist/src/embedder.js.map +1 -0
- package/dist/src/firebase/adapter-store.d.ts +1 -0
- package/dist/src/firebase/adapter-store.d.ts.map +1 -1
- package/dist/src/firebase/adapter-store.js +3 -0
- package/dist/src/firebase/adapter-store.js.map +1 -1
- package/dist/src/firebase/binding-store.d.ts +2 -0
- package/dist/src/firebase/binding-store.d.ts.map +1 -1
- package/dist/src/firebase/binding-store.js +10 -0
- package/dist/src/firebase/binding-store.js.map +1 -1
- package/dist/src/firebase/catalog-data-index-store.d.ts +1 -0
- package/dist/src/firebase/catalog-data-index-store.d.ts.map +1 -1
- package/dist/src/firebase/catalog-data-index-store.js +3 -0
- package/dist/src/firebase/catalog-data-index-store.js.map +1 -1
- package/dist/src/firebase/catalog-item-history-store.d.ts +21 -0
- package/dist/src/firebase/catalog-item-history-store.d.ts.map +1 -0
- package/dist/src/firebase/catalog-item-history-store.js +61 -0
- package/dist/src/firebase/catalog-item-history-store.js.map +1 -0
- package/dist/src/firebase/catalog-store.d.ts +1 -0
- package/dist/src/firebase/catalog-store.d.ts.map +1 -1
- package/dist/src/firebase/catalog-store.js +3 -0
- package/dist/src/firebase/catalog-store.js.map +1 -1
- package/dist/src/firebase/index.d.ts +1 -0
- package/dist/src/firebase/index.d.ts.map +1 -1
- package/dist/src/firebase/index.js +1 -0
- package/dist/src/firebase/index.js.map +1 -1
- package/dist/src/firebase/mapping-store.d.ts +1 -0
- package/dist/src/firebase/mapping-store.d.ts.map +1 -1
- package/dist/src/firebase/mapping-store.js +3 -0
- package/dist/src/firebase/mapping-store.js.map +1 -1
- package/dist/src/firebase/native-item-store.d.ts +8 -2
- package/dist/src/firebase/native-item-store.d.ts.map +1 -1
- package/dist/src/firebase/native-item-store.js +22 -6
- package/dist/src/firebase/native-item-store.js.map +1 -1
- package/dist/src/firebase/reference-store.d.ts +3 -0
- package/dist/src/firebase/reference-store.d.ts.map +1 -1
- package/dist/src/firebase/reference-store.js +16 -0
- package/dist/src/firebase/reference-store.js.map +1 -1
- package/dist/src/firebase/renderer-snippet-store.d.ts +3 -0
- package/dist/src/firebase/renderer-snippet-store.d.ts.map +1 -1
- package/dist/src/firebase/renderer-snippet-store.js +17 -0
- package/dist/src/firebase/renderer-snippet-store.js.map +1 -1
- package/dist/src/firebase/snapshot-store.d.ts +1 -0
- package/dist/src/firebase/snapshot-store.d.ts.map +1 -1
- package/dist/src/firebase/snapshot-store.js +8 -0
- package/dist/src/firebase/snapshot-store.js.map +1 -1
- package/dist/src/index.d.ts +2 -15
- package/dist/src/index.d.ts.map +1 -1
- package/dist/src/index.js +2 -15
- package/dist/src/index.js.map +1 -1
- package/dist/src/operator.d.ts +24 -0
- package/dist/src/operator.d.ts.map +1 -0
- package/dist/src/operator.js +25 -0
- package/dist/src/operator.js.map +1 -0
- package/dist/test/integration/firestore.emulator.test.js +16 -29
- package/dist/test/integration/firestore.emulator.test.js.map +1 -1
- package/dist/test/integration/record-history.live.test.d.ts +2 -0
- package/dist/test/integration/record-history.live.test.d.ts.map +1 -0
- package/dist/test/integration/record-history.live.test.js +126 -0
- package/dist/test/integration/record-history.live.test.js.map +1 -0
- package/dist/test/unit/native-catalog-merge.test.d.ts +2 -0
- package/dist/test/unit/native-catalog-merge.test.d.ts.map +1 -0
- package/dist/test/unit/native-catalog-merge.test.js +33 -0
- package/dist/test/unit/native-catalog-merge.test.js.map +1 -0
- package/dist/test/unit/native-scope.test.d.ts +2 -0
- package/dist/test/unit/native-scope.test.d.ts.map +1 -0
- package/dist/test/unit/native-scope.test.js +29 -0
- package/dist/test/unit/native-scope.test.js.map +1 -0
- package/dist/test/unit/record-history-path.test.d.ts +2 -0
- package/dist/test/unit/record-history-path.test.d.ts.map +1 -0
- package/dist/test/unit/record-history-path.test.js +24 -0
- package/dist/test/unit/record-history-path.test.js.map +1 -0
- package/firestore.indexes.json +39 -0
- package/package.json +23 -6
package/README.md
CHANGED
|
@@ -8,6 +8,8 @@ Catalox is a **data-tier** package for managing **app-scoped catalogs** in Fireb
|
|
|
8
8
|
- **Mapped catalogs** (items normalized from MongoDB or APIs)
|
|
9
9
|
- **References + validation contracts** (standardized cross-catalog shapes)
|
|
10
10
|
- **Seed/import/export + batch upsert** workflows for native catalogs
|
|
11
|
+
- **Optional per-record native history** — NDJSON payloads in GCS plus a Firestore `catalogItemHistory` index; list/show/restore/replay APIs and `catalox history …` ([`docs/record-history.md`](docs/record-history.md))
|
|
12
|
+
- **Optional catalog lifecycle** — hard delete (with manifest), restore from manifest, and hard rename across collections; APIs + `catalox catalog …` ([`docs/catalog-crud.md`](docs/catalog-crud.md))
|
|
11
13
|
- **Optional GCS tools** — NDJSON export/import of Firestore collections to a bucket, **compare** live data vs bucket snapshots, **`backupData` mode `gcs`** (Catalox-shaped NDJSON + manifest under a bucket prefix), and matching CLI commands (`firestore export-gcs`, `import-gcs`, `compare-gcs`, `firestore backup --mode gcs`; see [`docs/firestore-gcs-export.md`](docs/firestore-gcs-export.md), [`docs/backup.md`](docs/backup.md))
|
|
12
14
|
|
|
13
15
|
Catalox **does not** own UI, workflow orchestration, remote execution, artifact blobs, or secret storage.
|
|
@@ -23,6 +25,16 @@ This repo is currently set up as a workspace package.
|
|
|
23
25
|
|
|
24
26
|
**Direct dependency:** `@google-cloud/storage` is declared for GCS export/import/compare; it uses the same **Application Default Credentials** pattern as Firestore Admin (bucket IAM required).
|
|
25
27
|
|
|
28
|
+
### Package exports (v3)
|
|
29
|
+
|
|
30
|
+
| Import path | Intended use |
|
|
31
|
+
|-------------|----------------|
|
|
32
|
+
| **`@x12i/catalox`** | Full surface: embedder API + operator tooling (markdown, diagrams, migrations, Firebase stores, backup/GCS helpers, etc.). |
|
|
33
|
+
| **`@x12i/catalox/embedder`** | Catalog runtime only: **`createCatalox`**, **`Catalox`**, **`withContext` / `CataloxBound`**, contracts, errors, adapters, **`validateMappingSpec` / `executeMapping`**. |
|
|
34
|
+
| **`@x12i/catalox/operator`** | Markdown/diagrams/JSX, validation, bindings, **`ContextResolver`**, backup/GCS transfer helpers, identity/json-io, etc. |
|
|
35
|
+
| **`@x12i/catalox/firebase`** | Firestore-backed store classes for advanced wiring. |
|
|
36
|
+
| **`@x12i/catalox/mapping`** | Full mapping module (including **`helper-gap-report`**). |
|
|
37
|
+
|
|
26
38
|
## Configuration (real connections)
|
|
27
39
|
|
|
28
40
|
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).
|
|
@@ -73,6 +85,9 @@ GOOGLE_APPLICATION_CREDENTIALS=/path/to/service-account.json
|
|
|
73
85
|
FIREBASE_SERVICE_ACCOUNT_PATH=/path/to/service-account.json
|
|
74
86
|
FIREBASE_PROJECT_ID=your-project-id
|
|
75
87
|
FIRESTORE_LIVE_TESTS=1
|
|
88
|
+
# Optional: record-history live test + CLI (`createCatalox`); use a dedicated test bucket:
|
|
89
|
+
# CATALOX_RECORD_HISTORY_BUCKET=your-test-bucket
|
|
90
|
+
# CATALOX_RECORD_HISTORY_PREFIX=catalox-record-history/
|
|
76
91
|
# Optional defaults for the packaged `catalox` CLI (Catalox app/store context, not GCP):
|
|
77
92
|
# CATALOX_APP_ID=myAppId
|
|
78
93
|
# CATALOX_STORE_ID=myStoreId
|
|
@@ -87,7 +102,10 @@ The `catalox` binary loads `.env` via `dotenv`. Use **`CATALOX_*`** for **Catalo
|
|
|
87
102
|
- **`CATALOX_APP_ID`** — Default `appId` in CLI context when a command does not pass `--app` (when present, `--app` overrides).
|
|
88
103
|
- **`CATALOX_STORE_ID`** — Default `storeId` for **`report`** and **`export`** when `--store` is omitted (`--store` overrides).
|
|
89
104
|
- **`CATALOX_USER_ID`** — Optional user id / actor for authz-sensitive CLI paths.
|
|
90
|
-
- **`CATALOX_MONGO_URI`** — If set, enables the Mongo catalog adapter in the CLI (
|
|
105
|
+
- **`CATALOX_MONGO_URI`** — If set, enables the Mongo catalog adapter in the CLI (wired via **`createCatalox`** in `src/catalox/create-catalox.ts`, called from `src/cli/index.ts`).
|
|
106
|
+
- **`CATALOX_RECORD_HISTORY_BUCKET`** — If set, **`createCatalox`** wires **`recordHistory`** (GCS payloads + **`catalogItemHistory`** on native writes; also required for **`catalox history …`** to persist new events).
|
|
107
|
+
- **`CATALOX_RECORD_HISTORY_PREFIX`** — Optional GCS prefix for record history (default `catalox-record-history/`).
|
|
108
|
+
- **`CATALOX_RECORD_HISTORY_FAIL_CLOSED`** — When **`1`**, failed history writes fail the parent Firestore mutation.
|
|
91
109
|
|
|
92
110
|
**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:
|
|
93
111
|
|
|
@@ -110,6 +128,13 @@ npm run cli -- firestore report-native-layout --app "narrix"
|
|
|
110
128
|
| `firestore export-gcs` / `import-gcs` | NDJSON per collection + optional manifest ([`docs/firestore-gcs-export.md`](docs/firestore-gcs-export.md)). |
|
|
111
129
|
| `firestore compare-gcs` | Diff live Firestore vs bucket NDJSON (single collection or manifest). |
|
|
112
130
|
|
|
131
|
+
#### `history` / `catalog` CLI (3.1+)
|
|
132
|
+
|
|
133
|
+
| Command | Purpose |
|
|
134
|
+
|---------|---------|
|
|
135
|
+
| `history list` / `history show` / `history restore` / `history replay` | Per-record native history from **`catalogItemHistory`** + GCS ([`docs/record-history.md`](docs/record-history.md)). |
|
|
136
|
+
| `catalog delete` / `catalog restore` / `catalog rename` | Hard delete with manifest, restore from manifest, or hard rename ([`docs/catalog-crud.md`](docs/catalog-crud.md)). |
|
|
137
|
+
|
|
113
138
|
## Firestore data model (logical collections)
|
|
114
139
|
|
|
115
140
|
For a **full layout** (subcollections, document id conventions, snapshot runs, and query notes), see [`docs/firestore-data-model.md`](docs/firestore-data-model.md). For **native** catalogs specifically (per-catalog `catalogData-*-items`, layout resolution, `listCatalogItems`, filters, troubleshooting), see [`docs/native-catalog-storage-and-api.md`](docs/native-catalog-storage-and-api.md).
|
|
@@ -126,6 +151,7 @@ Metadata:
|
|
|
126
151
|
- `catalogDescriptors/{catalogId}` (**descriptor metadata** for generic consumption)
|
|
127
152
|
- `catalogRendererSnippets/{catalogId}:{role}[:{mode}]` (**stored renderer snippets** for list/grid/item/report/dashboard rendering)
|
|
128
153
|
- `catalogReferences/{referenceId}` (standardized reference records)
|
|
154
|
+
- `catalogItemHistory/{eventId}` (optional **native write history** index; payloads in GCS — [`docs/record-history.md`](docs/record-history.md))
|
|
129
155
|
|
|
130
156
|
Data:
|
|
131
157
|
|
|
@@ -143,39 +169,31 @@ See [`docs/backup.md`](docs/backup.md) for `backupData` / CLI backup (including
|
|
|
143
169
|
|
|
144
170
|
## Core usage (generic from `appId`)
|
|
145
171
|
|
|
146
|
-
### Create
|
|
172
|
+
### Create `Catalox` (recommended)
|
|
147
173
|
|
|
148
|
-
|
|
149
|
-
import { FirestoreStore } from "@x12i/catalox";
|
|
150
|
-
import { AppStore, CatalogStore, BindingStore, DefinitionStore, MappingStore, DescriptorStore, ReferenceStore, NativeItemStore, CatalogDataIndexStore, SnapshotStore, AdapterStore } from "@x12i/catalox";
|
|
151
|
-
import { AuthorizationService, Catalox } from "@x12i/catalox";
|
|
174
|
+
Use **`createCatalox`** so you do not wire every Firestore store by hand. Optional **`mongoUri`** enables Mongo mapped catalogs; API mapped catalogs use an internal adapter unless you set `enableApiAdapter: false`.
|
|
152
175
|
|
|
153
|
-
|
|
176
|
+
```ts
|
|
177
|
+
import { createCatalox } from "@x12i/catalox";
|
|
154
178
|
import { getFirestore } from "firebase-admin/firestore";
|
|
155
179
|
|
|
156
180
|
const firestore = getFirestore();
|
|
157
|
-
const
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
catalogs: new CatalogStore(store),
|
|
163
|
-
bindings,
|
|
164
|
-
definitions: new DefinitionStore(store),
|
|
165
|
-
mappings: new MappingStore(store),
|
|
166
|
-
descriptors: new DescriptorStore(store),
|
|
167
|
-
references: new ReferenceStore(store),
|
|
168
|
-
nativeItems: new NativeItemStore(store),
|
|
169
|
-
catalogDataIndex: new CatalogDataIndexStore(store),
|
|
170
|
-
snapshots: new SnapshotStore(store),
|
|
171
|
-
adapters: new AdapterStore(store),
|
|
172
|
-
firestoreStore: store,
|
|
173
|
-
authz: new AuthorizationService(bindings),
|
|
174
|
-
};
|
|
181
|
+
const catalox = createCatalox({
|
|
182
|
+
firestore,
|
|
183
|
+
// Optional: per-record native history to GCS + `catalogItemHistory` (or set CATALOX_RECORD_HISTORY_BUCKET for CLI)
|
|
184
|
+
// recordHistory: { gcsBucket: "my-bucket", gcsPrefix: "catalox-record-history/" },
|
|
185
|
+
});
|
|
175
186
|
|
|
176
|
-
|
|
187
|
+
// Optional: bind app/tenant context once (no globals; same semantics as passing context each call).
|
|
188
|
+
const scoped = catalox.withContext({ appId: "myApp" });
|
|
189
|
+
const list = await scoped.listCatalogItems("myCatalog", { limit: 50 });
|
|
190
|
+
// list.listOutcome is "ok" | "mapping_blocked"; empty items with "ok" means zero rows.
|
|
177
191
|
```
|
|
178
192
|
|
|
193
|
+
### Advanced: manual `CataloxDependencies`
|
|
194
|
+
|
|
195
|
+
If you need a non-default dependency graph, import stores from `@x12i/catalox/firebase`, construct `AuthorizationService`, and pass **`new Catalox(deps)`** as before (see source under `src/catalox/catalox.ts`).
|
|
196
|
+
|
|
179
197
|
## Descriptor contract (planning-critical)
|
|
180
198
|
|
|
181
199
|
Catalox is designed so upstream packages can be “generic” (no hardcoded catalog registrations). The stable contract is the persisted **descriptor**:
|
|
@@ -346,8 +364,8 @@ const bootstrap = await catalox.getAppCatalogBootstrap(context, "myAppId");
|
|
|
346
364
|
|
|
347
365
|
1) `listAppCatalogs(appId)` → get catalog list + access
|
|
348
366
|
2) `getAppCatalogBootstrap(appId)` → get descriptors (capabilities/query/identity/fields)
|
|
349
|
-
3) `listCatalogItems(catalogId, filter/sort)` →
|
|
350
|
-
4) `getCatalogItem(catalogId, itemId)` →
|
|
367
|
+
3) `listCatalogItems(catalogId, filter/sort)` → `{ listOutcome, items, issues? }` (`listOutcome` distinguishes OK empty lists vs mapping validation blocking)
|
|
368
|
+
4) `getCatalogItem(catalogId, itemId)` → `{ outcome: "found" | "not_found" | "mapping_blocked", ... }`
|
|
351
369
|
5) Optional: `getCatalogItemReferences(...)`, `validateCatalogItem(...)`
|
|
352
370
|
|
|
353
371
|
## Provisioning (create catalog + bind + descriptor)
|
|
@@ -357,7 +375,7 @@ Catalox includes provisioning helpers to reduce “manual Firestore wiring”.
|
|
|
357
375
|
### Create a native catalog (also seeds a minimal descriptor)
|
|
358
376
|
|
|
359
377
|
```ts
|
|
360
|
-
const ctx = { appId: "myAppId",
|
|
378
|
+
const ctx = { appId: "myAppId", superAdmin: true }; // set only after host auth; often from AppRecord.superAdminApp
|
|
361
379
|
|
|
362
380
|
await catalox.createCatalog(ctx, {
|
|
363
381
|
catalogId: "signals",
|
|
@@ -453,6 +471,7 @@ await catalox.batchUpsertNativeCatalogItems({ appId: "myAppId" }, "signals", ite
|
|
|
453
471
|
const res = await catalox.listCatalogItems({ appId: "myAppId" }, "signals", {
|
|
454
472
|
filter: { categoryId: "core" }
|
|
455
473
|
});
|
|
474
|
+
// `res.listOutcome`: "ok" (list ran) or "mapping_blocked" (see `res.issues`). Empty `items` with "ok" means zero matches.
|
|
456
475
|
```
|
|
457
476
|
|
|
458
477
|
Filtering is performed on `indexed.<field>` in stored native records (payload remains in `data`). **Blank filter values** (`""`, whitespace-only strings, `null`, `undefined`) are **not** sent as Firestore constraints so empty UI fields do not zero out lists; see [`docs/native-catalog-storage-and-api.md`](docs/native-catalog-storage-and-api.md) and **`compactCatalogFilter`** in the published API.
|
|
@@ -486,7 +505,7 @@ Validation APIs exist with standardized contracts, but **current behavior is min
|
|
|
486
505
|
|
|
487
506
|
## Publishing
|
|
488
507
|
|
|
489
|
-
From a clean tree, **`npm publish`** runs **`prepublishOnly`**, which executes **`npm run build`** then **`npm test`** (unit tests). Ensure `dist/` is build output only; the published tarball includes **`dist`**, **`README.md`**, and **`
|
|
508
|
+
From a clean tree, **`npm publish`** runs **`prepublishOnly`**, which executes **`npm run build`** then **`npm test`** (unit tests). Ensure `dist/` is build output only; the published tarball includes **`dist`**, **`README.md`**, **`LICENSE`**, and **`firestore.indexes.json`** (composite indexes for `catalogItemHistory` queries) per `package.json` **`files`**.
|
|
490
509
|
|
|
491
510
|
## Tests
|
|
492
511
|
|
|
@@ -508,14 +527,37 @@ Integration tests are **live-only** (no mocks, no emulators). They require:
|
|
|
508
527
|
- `FIREBASE_SERVICE_ACCOUNT_PATH=...`
|
|
509
528
|
- `FIREBASE_PROJECT_ID=...`
|
|
510
529
|
|
|
530
|
+
The **`Firestore live integration`** test (`test/integration/firestore.emulator.test.ts`) uses **`createCatalox`** and asserts v3 contracts: **`listCatalogItems`** returns **`listOutcome: "ok"`**, and **`getCatalogItem`** returns **`{ outcome: "found", item }`** for the seeded row. The descriptor patch in that test includes **`queryableFields` with `indexed: true`** for filtered fields so **`deriveIndexed`** persists **`indexed.*`** (see **Canonical `indexed` rule** above).
|
|
531
|
+
|
|
532
|
+
When **`CATALOX_RECORD_HISTORY_BUCKET`** is set, **`test/integration/record-history.live.test.ts`** runs as well: ephemeral app/catalog, **`upsert` → `update` → `listCatalogItemHistory` → `getCatalogItemHistoryEvent` → `restoreCatalogItemFromHistory`**, then best-effort Firestore + GCS cleanup for the created history objects.
|
|
533
|
+
|
|
511
534
|
### Live test safety (read before running)
|
|
512
535
|
|
|
513
536
|
- **Never run against production credentials/projects.** Use a dedicated Firebase project for tests.
|
|
514
|
-
- **Touched collections**: `apps`, `catalogs`, `catalogBindings`, `catalogDefinitions`, `catalogDescriptors`, `catalogData/{catalogId}`,
|
|
537
|
+
- **Touched collections**: `apps`, `catalogs`, `catalogBindings`, `catalogDefinitions`, `catalogDescriptors`, `catalogData/{catalogId}`, `catalogData-{catalogId}-items/...`, and (when record history is enabled) `catalogItemHistory/...`. 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)).
|
|
515
538
|
- **Cleanup**: tests do best-effort deletes of the docs they created, but do not guarantee full teardown.
|
|
516
539
|
|
|
517
540
|
## Changelog
|
|
518
541
|
|
|
542
|
+
### 3.1.1
|
|
543
|
+
|
|
544
|
+
- **Live tests:** Firestore integration test now sets **`queryableFields`** on the patched descriptor so equality filters match stored **`indexed.*`** rows (same rule as production descriptors).
|
|
545
|
+
- **Live tests:** Record-history integration test covers **update**, **get event**, **restore**, and **GCS object** cleanup when a bucket is configured.
|
|
546
|
+
- **Package:** publish **`firestore.indexes.json`** in the npm tarball for operators deploying **`catalogItemHistory`** queries.
|
|
547
|
+
|
|
548
|
+
### 3.1.0
|
|
549
|
+
|
|
550
|
+
- **Per-record history:** optional **`recordHistory`** on **`createCatalox`** (or **`CATALOX_RECORD_HISTORY_*`** env for CLI) writes **GCS NDJSON** + Firestore **`catalogItemHistory`** on native upsert/update/delete/batch/move. APIs: **`listCatalogItemHistory`**, **`getCatalogItemHistoryEvent`**, **`restoreCatalogItemFromHistory`**, **`replayCatalogToPointInTime`**. CLI: **`catalox history …`**. See [`docs/record-history.md`](docs/record-history.md), [`firestore.indexes.json`](firestore.indexes.json).
|
|
551
|
+
- **Catalog lifecycle:** **`deleteCatalog`**, **`restoreDeletedCatalog`**, **`renameCatalog`** (hard rename) + CLI **`catalox catalog …`**. See [`docs/catalog-crud.md`](docs/catalog-crud.md).
|
|
552
|
+
|
|
553
|
+
### 3.0.0
|
|
554
|
+
|
|
555
|
+
- **`createCatalox(config)`** — single factory for Firestore-backed stores, authz, optional Mongo/API adapters, optional renderer snippet store (`src/catalox/create-catalox.ts`).
|
|
556
|
+
- **`catalox.withContext(ctx)`** / **`bindCataloxContext(catalox, ctx)`** — **`CataloxBound`**: same APIs without repeating `CataloxContext` on every call (`src/catalox/catalox-bound.ts`).
|
|
557
|
+
- **Breaking — lists:** **`CatalogListResult`** includes **`listOutcome: "ok" | "mapping_blocked"`**. Mapping validation failures use **`mapping_blocked`** (see **`issues`**). Empty **`items`** with **`listOutcome === "ok"`** means zero matching rows.
|
|
558
|
+
- **Breaking — get item:** **`getCatalogItem`** returns **`CatalogGetItemResult`** (`found` | `not_found` | `mapping_blocked`), not **`null`**.
|
|
559
|
+
- **Package:** **`main` / `types`** and **`exports["."]`** resolve to **`dist/src/...`**. Subpaths **`@x12i/catalox/embedder`**, **`/operator`**, **`/mapping`**, **`/firebase`**. Root **`@x12i/catalox`** re-exports embedder + operator (preserves most existing root imports).
|
|
560
|
+
|
|
519
561
|
### 2.7.0
|
|
520
562
|
|
|
521
563
|
- **GCS restore:** **`restoreFirestoreBackupFromGcs`** + CLI **`firestore restore-backup-from-gcs`** — same pre-restore / **`undoFirestoreRestore`** model as mirror restore.
|
|
@@ -6,7 +6,7 @@ export class AuthorizationService {
|
|
|
6
6
|
this.bindings = bindings;
|
|
7
7
|
}
|
|
8
8
|
async requireBindingAccess(context, appId, catalogId, required) {
|
|
9
|
-
if (context.
|
|
9
|
+
if (context.superAdmin) {
|
|
10
10
|
// God-mode policy: bypass binding for read/admin checks if needed.
|
|
11
11
|
// We still return a synthetic binding for uniformity.
|
|
12
12
|
return {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"authorization.js","sourceRoot":"","sources":["../../../src/catalox/authorization.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,wBAAwB,EAAE,MAAM,wBAAwB,CAAC;AAClE,OAAO,EAAE,YAAY,EAAE,MAAM,8BAA8B,CAAC;AAI5D,MAAM,OAAO,oBAAoB;IACF;IAA7B,YAA6B,QAAsB;QAAtB,aAAQ,GAAR,QAAQ,CAAc;IAAG,CAAC;IAEvD,KAAK,CAAC,oBAAoB,CACxB,OAAuB,EACvB,KAAY,EACZ,SAAoB,EACpB,QAAwB;QAExB,IAAI,OAAO,CAAC,
|
|
1
|
+
{"version":3,"file":"authorization.js","sourceRoot":"","sources":["../../../src/catalox/authorization.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,wBAAwB,EAAE,MAAM,wBAAwB,CAAC;AAClE,OAAO,EAAE,YAAY,EAAE,MAAM,8BAA8B,CAAC;AAI5D,MAAM,OAAO,oBAAoB;IACF;IAA7B,YAA6B,QAAsB;QAAtB,aAAQ,GAAR,QAAQ,CAAc;IAAG,CAAC;IAEvD,KAAK,CAAC,oBAAoB,CACxB,OAAuB,EACvB,KAAY,EACZ,SAAoB,EACpB,QAAwB;QAExB,IAAI,OAAO,CAAC,UAAU,EAAE,CAAC;YACvB,mEAAmE;YACnE,sDAAsD;YACtD,OAAO;gBACL,SAAS,EAAE,GAAG,MAAM,CAAC,KAAK,CAAC,IAAI,MAAM,CAAC,SAAS,CAAC,EAAE;gBAClD,KAAK;gBACL,SAAS;gBACT,MAAM,EAAE,EAAE,OAAO,EAAE,IAAI,EAAE,QAAQ,EAAE,IAAI,EAAE,QAAQ,EAAE,IAAI,EAAE;gBACzD,MAAM,EAAE,QAAQ;gBAChB,SAAS,EAAE,IAAI,IAAI,CAAC,CAAC,CAAC,CAAC,WAAW,EAAE;gBACpC,SAAS,EAAE,IAAI,IAAI,CAAC,CAAC,CAAC,CAAC,WAAW,EAAE;aACrC,CAAC;QACJ,CAAC;QAED,MAAM,OAAO,GAAG,MAAM,IAAI,CAAC,QAAQ,CAAC,gBAAgB,CAAC,KAAK,EAAE,SAAS,CAAC,CAAC;QACvE,IAAI,CAAC,OAAO,IAAI,OAAO,CAAC,MAAM,KAAK,QAAQ,EAAE,CAAC;YAC5C,MAAM,IAAI,wBAAwB,CAAC,EAAE,KAAK,EAAE,SAAS,EAAE,MAAM,EAAE,+BAA+B,EAAE,CAAC,CAAC;QACpG,CAAC;QAED,MAAM,EAAE,GACN,QAAQ,KAAK,MAAM;YACjB,CAAC,CAAC,OAAO,CAAC,OAAO,CAAC,MAAM,CAAC,OAAO,CAAC;YACjC,CAAC,CAAC,QAAQ,KAAK,OAAO;gBACpB,CAAC,CAAC,OAAO,CAAC,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC;gBAClC,CAAC,CAAC,OAAO,CAAC,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC;QAEzC,IAAI,CAAC,EAAE,EAAE,CAAC;YACR,MAAM,IAAI,wBAAwB,CAAC,EAAE,KAAK,EAAE,SAAS,EAAE,QAAQ,EAAE,CAAC,CAAC;QACrE,CAAC;QAED,OAAO,OAAO,CAAC;IACjB,CAAC;CACF"}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import type { CatalogId } from "../contracts/ids.js";
|
|
2
|
+
import type { DeleteCatalogInput, DeleteCatalogResult, RenameCatalogInput, RenameCatalogResult, RestoreDeletedCatalogInput, RestoreDeletedCatalogResult } from "../contracts/catalog-lifecycle.js";
|
|
3
|
+
import type { CataloxContext } from "../contracts/context.js";
|
|
4
|
+
import { AdapterStore } from "../firebase/adapter-store.js";
|
|
5
|
+
import { CatalogDataIndexStore } from "../firebase/catalog-data-index-store.js";
|
|
6
|
+
import { DefinitionStore } from "../firebase/definition-store.js";
|
|
7
|
+
import { DescriptorStore } from "../firebase/descriptor-store.js";
|
|
8
|
+
import { MappingStore } from "../firebase/mapping-store.js";
|
|
9
|
+
import { NativeItemStore } from "../firebase/native-item-store.js";
|
|
10
|
+
import { ReferenceStore } from "../firebase/reference-store.js";
|
|
11
|
+
import { RendererSnippetStore } from "../firebase/renderer-snippet-store.js";
|
|
12
|
+
import { SnapshotStore } from "../firebase/snapshot-store.js";
|
|
13
|
+
import { type BackupDataDeps } from "./backup-data.js";
|
|
14
|
+
import { type RecordHistoryDeps } from "./record-history.js";
|
|
15
|
+
export type CatalogLifecycleDeps = BackupDataDeps & {
|
|
16
|
+
definitions: DefinitionStore;
|
|
17
|
+
descriptors: DescriptorStore;
|
|
18
|
+
mappings: MappingStore;
|
|
19
|
+
adapters: AdapterStore;
|
|
20
|
+
references: ReferenceStore;
|
|
21
|
+
nativeItems: NativeItemStore;
|
|
22
|
+
snapshots: SnapshotStore;
|
|
23
|
+
catalogDataIndex: CatalogDataIndexStore;
|
|
24
|
+
rendererSnippets?: RendererSnippetStore;
|
|
25
|
+
};
|
|
26
|
+
export declare function runDeleteCatalog(deps: CatalogLifecycleDeps, recordHistory: RecordHistoryDeps | undefined, context: CataloxContext, catalogId: CatalogId, input: DeleteCatalogInput): Promise<DeleteCatalogResult>;
|
|
27
|
+
export declare function runRestoreDeletedCatalog(deps: CatalogLifecycleDeps, recordHistory: RecordHistoryDeps, input: RestoreDeletedCatalogInput): Promise<RestoreDeletedCatalogResult>;
|
|
28
|
+
export declare function runRenameCatalog(deps: CatalogLifecycleDeps, recordHistory: RecordHistoryDeps | undefined, context: CataloxContext, fromCatalogId: CatalogId, toCatalogId: CatalogId, input: RenameCatalogInput): Promise<RenameCatalogResult>;
|
|
29
|
+
//# sourceMappingURL=catalog-lifecycle.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"catalog-lifecycle.d.ts","sourceRoot":"","sources":["../../../src/catalox/catalog-lifecycle.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,qBAAqB,CAAC;AACrD,OAAO,KAAK,EAEV,kBAAkB,EAClB,mBAAmB,EACnB,kBAAkB,EAClB,mBAAmB,EACnB,0BAA0B,EAC1B,2BAA2B,EAC5B,MAAM,mCAAmC,CAAC;AAQ3C,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,yBAAyB,CAAC;AAQ9D,OAAO,EAAE,YAAY,EAAE,MAAM,8BAA8B,CAAC;AAE5D,OAAO,EAAE,qBAAqB,EAAE,MAAM,yCAAyC,CAAC;AAEhF,OAAO,EAAE,eAAe,EAAE,MAAM,iCAAiC,CAAC;AAClE,OAAO,EAAE,eAAe,EAAE,MAAM,iCAAiC,CAAC;AAClE,OAAO,EAAE,YAAY,EAAE,MAAM,8BAA8B,CAAC;AAC5D,OAAO,EAAE,eAAe,EAAE,MAAM,kCAAkC,CAAC;AACnE,OAAO,EAAE,cAAc,EAAE,MAAM,gCAAgC,CAAC;AAChE,OAAO,EAAE,oBAAoB,EAAE,MAAM,uCAAuC,CAAC;AAC7E,OAAO,EAAE,aAAa,EAAE,MAAM,+BAA+B,CAAC;AAC9D,OAAO,EAIL,KAAK,cAAc,EACpB,MAAM,kBAAkB,CAAC;AAC1B,OAAO,EAGL,KAAK,iBAAiB,EACvB,MAAM,qBAAqB,CAAC;AAG7B,MAAM,MAAM,oBAAoB,GAAG,cAAc,GAAG;IAClD,WAAW,EAAE,eAAe,CAAC;IAC7B,WAAW,EAAE,eAAe,CAAC;IAC7B,QAAQ,EAAE,YAAY,CAAC;IACvB,QAAQ,EAAE,YAAY,CAAC;IACvB,UAAU,EAAE,cAAc,CAAC;IAC3B,WAAW,EAAE,eAAe,CAAC;IAC7B,SAAS,EAAE,aAAa,CAAC;IACzB,gBAAgB,EAAE,qBAAqB,CAAC;IACxC,gBAAgB,CAAC,EAAE,oBAAoB,CAAC;CACzC,CAAC;AAwDF,wBAAsB,gBAAgB,CACpC,IAAI,EAAE,oBAAoB,EAC1B,aAAa,EAAE,iBAAiB,GAAG,SAAS,EAC5C,OAAO,EAAE,cAAc,EACvB,SAAS,EAAE,SAAS,EACpB,KAAK,EAAE,kBAAkB,GACxB,OAAO,CAAC,mBAAmB,CAAC,CAoL9B;AAED,wBAAsB,wBAAwB,CAC5C,IAAI,EAAE,oBAAoB,EAC1B,aAAa,EAAE,iBAAiB,EAChC,KAAK,EAAE,0BAA0B,GAChC,OAAO,CAAC,2BAA2B,CAAC,CAuFtC;AAED,wBAAsB,gBAAgB,CACpC,IAAI,EAAE,oBAAoB,EAC1B,aAAa,EAAE,iBAAiB,GAAG,SAAS,EAC5C,OAAO,EAAE,cAAc,EACvB,aAAa,EAAE,SAAS,EACxB,WAAW,EAAE,SAAS,EACtB,KAAK,EAAE,kBAAkB,GACxB,OAAO,CAAC,mBAAmB,CAAC,CAgM9B"}
|