@x12i/catalox 5.1.3 → 5.9.6
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/CHANGELOG.md +135 -0
- package/README.md +90 -2
- package/package.json +36 -68
- package/packages/engine/dist/adapters/api/api-adapter.d.ts +22 -0
- package/packages/engine/dist/adapters/api/api-adapter.d.ts.map +1 -0
- package/packages/engine/dist/adapters/api/api-adapter.js +64 -0
- package/packages/engine/dist/adapters/api/api-adapter.js.map +1 -0
- package/packages/engine/dist/adapters/api/index.d.ts.map +1 -0
- package/packages/engine/dist/adapters/api/index.js.map +1 -0
- package/packages/engine/dist/adapters/mongo/index.d.ts.map +1 -0
- package/packages/engine/dist/adapters/mongo/index.js.map +1 -0
- package/packages/engine/dist/adapters/mongo/mongo-adapter.d.ts +21 -0
- package/packages/engine/dist/adapters/mongo/mongo-adapter.d.ts.map +1 -0
- package/packages/engine/dist/adapters/mongo/mongo-adapter.js +61 -0
- package/packages/engine/dist/adapters/mongo/mongo-adapter.js.map +1 -0
- package/packages/engine/dist/adapters/mongo/resolve-db.d.ts +4 -0
- package/packages/engine/dist/adapters/mongo/resolve-db.d.ts.map +1 -0
- package/packages/engine/dist/adapters/mongo/resolve-db.js.map +1 -0
- package/packages/engine/dist/bindings/index.d.ts.map +1 -0
- package/packages/engine/dist/bindings/index.js.map +1 -0
- package/packages/engine/dist/catalog-content/derived-items.d.ts +19 -0
- package/packages/engine/dist/catalog-content/derived-items.d.ts.map +1 -0
- package/packages/engine/dist/catalog-content/derived-items.js +59 -0
- package/packages/engine/dist/catalog-content/derived-items.js.map +1 -0
- package/packages/engine/dist/catalog-content/field-codec.d.ts +13 -0
- package/packages/engine/dist/catalog-content/field-codec.d.ts.map +1 -0
- package/packages/engine/dist/catalog-content/field-codec.js +24 -0
- package/packages/engine/dist/catalog-content/field-codec.js.map +1 -0
- package/packages/engine/dist/catalog-content/index.d.ts +4 -0
- package/packages/engine/dist/catalog-content/index.d.ts.map +1 -0
- package/packages/engine/dist/catalog-content/index.js +4 -0
- package/packages/engine/dist/catalog-content/index.js.map +1 -0
- package/packages/engine/dist/catalog-content/template-tokens.d.ts +10 -0
- package/packages/engine/dist/catalog-content/template-tokens.d.ts.map +1 -0
- package/packages/engine/dist/catalog-content/template-tokens.js +50 -0
- package/packages/engine/dist/catalog-content/template-tokens.js.map +1 -0
- package/packages/engine/dist/catalox/authorization.d.ts +20 -0
- package/packages/engine/dist/catalox/authorization.d.ts.map +1 -0
- package/packages/engine/dist/catalox/authorization.js +55 -0
- package/packages/engine/dist/catalox/authorization.js.map +1 -0
- package/packages/engine/dist/catalox/backup-data.d.ts +70 -0
- package/packages/engine/dist/catalox/backup-data.d.ts.map +1 -0
- package/packages/engine/dist/catalox/backup-data.js.map +1 -0
- package/packages/engine/dist/catalox/catalog-discovery.d.ts +9 -0
- package/packages/engine/dist/catalox/catalog-discovery.d.ts.map +1 -0
- package/packages/engine/dist/catalox/catalog-discovery.js.map +1 -0
- package/packages/engine/dist/catalox/catalog-lifecycle.d.ts +29 -0
- package/packages/engine/dist/catalox/catalog-lifecycle.d.ts.map +1 -0
- package/packages/engine/dist/catalox/catalog-lifecycle.js.map +1 -0
- package/packages/engine/dist/catalox/catalog-snapshot-export.d.ts +46 -0
- package/packages/engine/dist/catalox/catalog-snapshot-export.d.ts.map +1 -0
- package/packages/engine/dist/catalox/catalog-snapshot-export.js +103 -0
- package/packages/engine/dist/catalox/catalog-snapshot-export.js.map +1 -0
- package/packages/engine/dist/catalox/catalox-bound.d.ts +199 -0
- package/packages/engine/dist/catalox/catalox-bound.d.ts.map +1 -0
- package/packages/engine/dist/catalox/catalox-bound.js +256 -0
- package/packages/engine/dist/catalox/catalox-bound.js.map +1 -0
- package/packages/engine/dist/catalox/catalox-gcs-backup-export-manifest.d.ts +13 -0
- package/packages/engine/dist/catalox/catalox-gcs-backup-export-manifest.d.ts.map +1 -0
- package/packages/engine/dist/catalox/catalox-gcs-backup-export-manifest.js.map +1 -0
- package/packages/engine/dist/catalox/catalox.d.ts +382 -0
- package/packages/engine/dist/catalox/catalox.d.ts.map +1 -0
- package/packages/engine/dist/catalox/catalox.js +2892 -0
- package/packages/engine/dist/catalox/catalox.js.map +1 -0
- package/packages/engine/dist/catalox/context.d.ts +17 -0
- package/packages/engine/dist/catalox/context.d.ts.map +1 -0
- package/packages/engine/dist/catalox/context.js.map +1 -0
- package/packages/engine/dist/catalox/create-catalox.d.ts +45 -0
- package/packages/engine/dist/catalox/create-catalox.d.ts.map +1 -0
- package/packages/engine/dist/catalox/create-catalox.js +132 -0
- package/packages/engine/dist/catalox/create-catalox.js.map +1 -0
- package/packages/engine/dist/catalox/field-source-resolution.d.ts +16 -0
- package/packages/engine/dist/catalox/field-source-resolution.d.ts.map +1 -0
- package/packages/engine/dist/catalox/field-source-resolution.js.map +1 -0
- package/packages/engine/dist/catalox/firestore-gcs-compare.d.ts +15 -0
- package/packages/engine/dist/catalox/firestore-gcs-compare.d.ts.map +1 -0
- package/packages/engine/dist/catalox/firestore-gcs-compare.js.map +1 -0
- package/packages/engine/dist/catalox/firestore-gcs-transfer.d.ts +28 -0
- package/packages/engine/dist/catalox/firestore-gcs-transfer.d.ts.map +1 -0
- package/packages/engine/dist/catalox/firestore-gcs-transfer.js.map +1 -0
- package/packages/engine/dist/catalox/identity.d.ts +7 -0
- package/packages/engine/dist/catalox/identity.d.ts.map +1 -0
- package/packages/engine/dist/catalox/identity.js.map +1 -0
- package/packages/engine/dist/catalox/index.d.ts +18 -0
- package/packages/engine/dist/catalox/index.d.ts.map +1 -0
- package/packages/engine/dist/catalox/index.js +18 -0
- package/packages/engine/dist/catalox/index.js.map +1 -0
- package/packages/engine/dist/catalox/item-scope-match.d.ts +39 -0
- package/packages/engine/dist/catalox/item-scope-match.d.ts.map +1 -0
- package/packages/engine/dist/catalox/item-scope-match.js.map +1 -0
- package/packages/engine/dist/catalox/item-scope.d.ts +36 -0
- package/packages/engine/dist/catalox/item-scope.d.ts.map +1 -0
- package/packages/engine/dist/catalox/item-scope.js +137 -0
- package/packages/engine/dist/catalox/item-scope.js.map +1 -0
- package/packages/engine/dist/catalox/json-io.d.ts.map +1 -0
- package/packages/engine/dist/catalox/json-io.js.map +1 -0
- package/packages/engine/dist/catalox/native-catalog-layout-diagnostics.d.ts +29 -0
- package/packages/engine/dist/catalox/native-catalog-layout-diagnostics.d.ts.map +1 -0
- package/packages/engine/dist/catalox/native-catalog-layout-diagnostics.js.map +1 -0
- package/packages/engine/dist/catalox/native-catalog-merge.d.ts +10 -0
- package/packages/engine/dist/catalox/native-catalog-merge.d.ts.map +1 -0
- package/packages/engine/dist/catalox/native-catalog-merge.js +40 -0
- package/packages/engine/dist/catalox/native-catalog-merge.js.map +1 -0
- package/packages/engine/dist/catalox/native-item-resolve.d.ts +28 -0
- package/packages/engine/dist/catalox/native-item-resolve.d.ts.map +1 -0
- package/packages/engine/dist/catalox/native-item-resolve.js.map +1 -0
- package/packages/engine/dist/catalox/record-history-field.d.ts +23 -0
- package/packages/engine/dist/catalox/record-history-field.d.ts.map +1 -0
- package/packages/engine/dist/catalox/record-history-field.js +90 -0
- package/packages/engine/dist/catalox/record-history-field.js.map +1 -0
- package/packages/engine/dist/catalox/record-history.d.ts +53 -0
- package/packages/engine/dist/catalox/record-history.d.ts.map +1 -0
- package/packages/engine/dist/catalox/record-history.js.map +1 -0
- package/packages/engine/dist/catalox/reporting/render-inventory-report.d.ts +3 -0
- package/packages/engine/dist/catalox/reporting/render-inventory-report.d.ts.map +1 -0
- package/packages/engine/dist/catalox/reporting/render-inventory-report.js.map +1 -0
- package/packages/engine/dist/catalox/restore-firestore-backup-from-gcs.d.ts +21 -0
- package/packages/engine/dist/catalox/restore-firestore-backup-from-gcs.d.ts.map +1 -0
- package/packages/engine/dist/catalox/restore-firestore-backup-from-gcs.js.map +1 -0
- package/packages/engine/dist/catalox/restore-firestore-backup.d.ts +32 -0
- package/packages/engine/dist/catalox/restore-firestore-backup.d.ts.map +1 -0
- package/packages/engine/dist/catalox/restore-firestore-backup.js.map +1 -0
- package/packages/engine/dist/catalox/scope-legacy-convert.d.ts +19 -0
- package/packages/engine/dist/catalox/scope-legacy-convert.d.ts.map +1 -0
- package/packages/engine/dist/catalox/scope-legacy-convert.js.map +1 -0
- package/packages/engine/dist/catalox/seed-preset-resolve.d.ts.map +1 -0
- package/packages/engine/dist/catalox/seed-preset-resolve.js.map +1 -0
- package/packages/engine/dist/catalox/seed-preset.d.ts +85 -0
- package/packages/engine/dist/catalox/seed-preset.d.ts.map +1 -0
- package/packages/engine/dist/catalox/seed-preset.js.map +1 -0
- package/packages/engine/dist/catalox/smart-properties.d.ts +33 -0
- package/packages/engine/dist/catalox/smart-properties.d.ts.map +1 -0
- package/packages/engine/dist/catalox/smart-properties.js +242 -0
- package/packages/engine/dist/catalox/smart-properties.js.map +1 -0
- package/packages/engine/dist/cli/index.d.ts.map +1 -0
- package/packages/engine/dist/cli/index.js +1508 -0
- package/packages/engine/dist/cli/index.js.map +1 -0
- package/packages/engine/dist/cli/item-json.d.ts.map +1 -0
- package/packages/engine/dist/cli/item-json.js.map +1 -0
- package/packages/engine/dist/diagrams/render-catalog-diagram.d.ts +3 -0
- package/packages/engine/dist/diagrams/render-catalog-diagram.d.ts.map +1 -0
- package/packages/engine/dist/diagrams/render-catalog-diagram.js.map +1 -0
- package/packages/engine/dist/diagrams/render-item-diagram.d.ts +3 -0
- package/packages/engine/dist/diagrams/render-item-diagram.d.ts.map +1 -0
- package/packages/engine/dist/diagrams/render-item-diagram.js.map +1 -0
- package/packages/engine/dist/embedder.d.ts +29 -0
- package/packages/engine/dist/embedder.d.ts.map +1 -0
- package/packages/engine/dist/embedder.js +28 -0
- package/packages/engine/dist/embedder.js.map +1 -0
- package/packages/engine/dist/errors/index.d.ts.map +1 -0
- package/packages/engine/dist/errors/index.js.map +1 -0
- package/packages/engine/dist/firebase/adapter-store.d.ts +16 -0
- package/packages/engine/dist/firebase/adapter-store.d.ts.map +1 -0
- package/packages/engine/dist/firebase/adapter-store.js.map +1 -0
- package/packages/engine/dist/firebase/agent-store.d.ts +18 -0
- package/packages/engine/dist/firebase/agent-store.d.ts.map +1 -0
- package/packages/engine/dist/firebase/agent-store.js.map +1 -0
- package/packages/engine/dist/firebase/app-store.d.ts +11 -0
- package/packages/engine/dist/firebase/app-store.d.ts.map +1 -0
- package/packages/engine/dist/firebase/app-store.js.map +1 -0
- package/packages/engine/dist/firebase/binding-store.d.ts +15 -0
- package/packages/engine/dist/firebase/binding-store.d.ts.map +1 -0
- package/packages/engine/dist/firebase/binding-store.js.map +1 -0
- package/packages/engine/dist/firebase/bootstrap.d.ts.map +1 -0
- package/packages/engine/dist/firebase/bootstrap.js.map +1 -0
- package/packages/engine/dist/firebase/catalog-data-index-store.d.ts +15 -0
- package/packages/engine/dist/firebase/catalog-data-index-store.d.ts.map +1 -0
- package/packages/engine/dist/firebase/catalog-data-index-store.js.map +1 -0
- package/packages/engine/dist/firebase/catalog-data-paths.d.ts +14 -0
- package/packages/engine/dist/firebase/catalog-data-paths.d.ts.map +1 -0
- package/packages/engine/dist/firebase/catalog-data-paths.js.map +1 -0
- package/packages/engine/dist/firebase/catalog-item-history-store.d.ts +21 -0
- package/packages/engine/dist/firebase/catalog-item-history-store.d.ts.map +1 -0
- package/packages/engine/dist/firebase/catalog-item-history-store.js.map +1 -0
- package/packages/engine/dist/firebase/catalog-store.d.ts +13 -0
- package/packages/engine/dist/firebase/catalog-store.d.ts.map +1 -0
- package/packages/engine/dist/firebase/catalog-store.js.map +1 -0
- package/packages/engine/dist/firebase/catalog-type-store.d.ts +22 -0
- package/packages/engine/dist/firebase/catalog-type-store.d.ts.map +1 -0
- package/packages/engine/dist/firebase/catalog-type-store.js.map +1 -0
- package/packages/engine/dist/firebase/definition-store.d.ts +25 -0
- package/packages/engine/dist/firebase/definition-store.d.ts.map +1 -0
- package/packages/engine/dist/firebase/definition-store.js.map +1 -0
- package/packages/engine/dist/firebase/descriptor-store.d.ts +11 -0
- package/packages/engine/dist/firebase/descriptor-store.d.ts.map +1 -0
- package/packages/engine/dist/firebase/descriptor-store.js.map +1 -0
- package/packages/engine/dist/firebase/design-object-store.d.ts +15 -0
- package/packages/engine/dist/firebase/design-object-store.d.ts.map +1 -0
- package/packages/engine/dist/firebase/design-object-store.js.map +1 -0
- package/packages/engine/dist/firebase/domain-store.d.ts +18 -0
- package/packages/engine/dist/firebase/domain-store.d.ts.map +1 -0
- package/packages/engine/dist/firebase/domain-store.js.map +1 -0
- package/packages/engine/dist/firebase/firestore-collection-path.d.ts.map +1 -0
- package/packages/engine/dist/firebase/firestore-collection-path.js.map +1 -0
- package/packages/engine/dist/firebase/firestore-store.d.ts.map +1 -0
- package/packages/engine/dist/firebase/firestore-store.js.map +1 -0
- package/packages/engine/dist/firebase/identity-binding-store.d.ts +18 -0
- package/packages/engine/dist/firebase/identity-binding-store.d.ts.map +1 -0
- package/packages/engine/dist/firebase/identity-binding-store.js.map +1 -0
- package/packages/engine/dist/firebase/index.d.ts.map +1 -0
- package/packages/engine/dist/firebase/index.js.map +1 -0
- package/packages/engine/dist/firebase/mapping-store.d.ts +12 -0
- package/packages/engine/dist/firebase/mapping-store.d.ts.map +1 -0
- package/packages/engine/dist/firebase/mapping-store.js.map +1 -0
- package/packages/engine/dist/firebase/native-item-store.d.ts +41 -0
- package/packages/engine/dist/firebase/native-item-store.d.ts.map +1 -0
- package/packages/engine/dist/firebase/native-item-store.js +129 -0
- package/packages/engine/dist/firebase/native-item-store.js.map +1 -0
- package/packages/engine/dist/firebase/presentation-profile-store.d.ts +18 -0
- package/packages/engine/dist/firebase/presentation-profile-store.d.ts.map +1 -0
- package/packages/engine/dist/firebase/presentation-profile-store.js.map +1 -0
- package/packages/engine/dist/firebase/reference-store.d.ts +21 -0
- package/packages/engine/dist/firebase/reference-store.d.ts.map +1 -0
- package/packages/engine/dist/firebase/reference-store.js.map +1 -0
- package/packages/engine/dist/firebase/renderer-snippet-store.d.ts +15 -0
- package/packages/engine/dist/firebase/renderer-snippet-store.d.ts.map +1 -0
- package/packages/engine/dist/firebase/renderer-snippet-store.js.map +1 -0
- package/packages/engine/dist/firebase/snapshot-store.d.ts +19 -0
- package/packages/engine/dist/firebase/snapshot-store.d.ts.map +1 -0
- package/packages/engine/dist/firebase/snapshot-store.js.map +1 -0
- package/packages/engine/dist/firebase/store-app-binding-store.d.ts +14 -0
- package/packages/engine/dist/firebase/store-app-binding-store.d.ts.map +1 -0
- package/packages/engine/dist/firebase/store-app-binding-store.js.map +1 -0
- package/packages/engine/dist/index.d.ts.map +1 -0
- package/packages/engine/dist/index.js.map +1 -0
- package/packages/engine/dist/jsx/index.d.ts +70 -0
- package/packages/engine/dist/jsx/index.d.ts.map +1 -0
- package/packages/engine/dist/jsx/index.js +178 -0
- package/packages/engine/dist/jsx/index.js.map +1 -0
- package/packages/engine/dist/local/in-memory-native-item-store.d.ts +29 -0
- package/packages/engine/dist/local/in-memory-native-item-store.d.ts.map +1 -0
- package/packages/engine/dist/local/in-memory-native-item-store.js +117 -0
- package/packages/engine/dist/local/in-memory-native-item-store.js.map +1 -0
- package/packages/engine/dist/local/in-memory-stores.d.ts +35 -0
- package/packages/engine/dist/local/in-memory-stores.d.ts.map +1 -0
- package/packages/engine/dist/local/in-memory-stores.js +89 -0
- package/packages/engine/dist/local/in-memory-stores.js.map +1 -0
- package/packages/engine/dist/local/index.d.ts +4 -0
- package/packages/engine/dist/local/index.d.ts.map +1 -0
- package/packages/engine/dist/local/index.js +4 -0
- package/packages/engine/dist/local/index.js.map +1 -0
- package/packages/engine/dist/local/local-file-store.d.ts +19 -0
- package/packages/engine/dist/local/local-file-store.d.ts.map +1 -0
- package/packages/engine/dist/local/local-file-store.js +25 -0
- package/packages/engine/dist/local/local-file-store.js.map +1 -0
- package/packages/engine/dist/local/local-store-error.d.ts +14 -0
- package/packages/engine/dist/local/local-store-error.d.ts.map +1 -0
- package/packages/engine/dist/local/local-store-error.js +22 -0
- package/packages/engine/dist/local/local-store-error.js.map +1 -0
- package/packages/engine/dist/local/snapshot.d.ts +36 -0
- package/packages/engine/dist/local/snapshot.d.ts.map +1 -0
- package/packages/engine/dist/local/snapshot.js +192 -0
- package/packages/engine/dist/local/snapshot.js.map +1 -0
- package/packages/engine/dist/local/stub-deps.d.ts +65 -0
- package/packages/engine/dist/local/stub-deps.d.ts.map +1 -0
- package/packages/engine/dist/local/stub-deps.js +40 -0
- package/packages/engine/dist/local/stub-deps.js.map +1 -0
- package/packages/engine/dist/local/unavailable-firestore-store.d.ts +13 -0
- package/packages/engine/dist/local/unavailable-firestore-store.d.ts.map +1 -0
- package/packages/engine/dist/local/unavailable-firestore-store.js +26 -0
- package/packages/engine/dist/local/unavailable-firestore-store.js.map +1 -0
- package/packages/engine/dist/local/wire-local-catalox.d.ts +10 -0
- package/packages/engine/dist/local/wire-local-catalox.d.ts.map +1 -0
- package/packages/engine/dist/local/wire-local-catalox.js +37 -0
- package/packages/engine/dist/local/wire-local-catalox.js.map +1 -0
- package/packages/engine/dist/logging.d.ts.map +1 -0
- package/packages/engine/dist/logging.js.map +1 -0
- package/packages/engine/dist/mapping/execute-mapping.d.ts +8 -0
- package/packages/engine/dist/mapping/execute-mapping.d.ts.map +1 -0
- package/packages/engine/dist/mapping/execute-mapping.js.map +1 -0
- package/packages/engine/dist/mapping/helper-gap-report.d.ts.map +1 -0
- package/packages/engine/dist/mapping/helper-gap-report.js.map +1 -0
- package/packages/engine/dist/mapping/index.d.ts.map +1 -0
- package/packages/engine/dist/mapping/index.js.map +1 -0
- package/packages/engine/dist/mapping/validate-mapping.d.ts +3 -0
- package/packages/engine/dist/mapping/validate-mapping.d.ts.map +1 -0
- package/packages/engine/dist/mapping/validate-mapping.js.map +1 -0
- package/packages/engine/dist/markdown/render-item-markdown.d.ts +5 -0
- package/packages/engine/dist/markdown/render-item-markdown.d.ts.map +1 -0
- package/packages/engine/dist/markdown/render-item-markdown.js.map +1 -0
- package/packages/engine/dist/markdown/render-list-markdown.d.ts +5 -0
- package/packages/engine/dist/markdown/render-list-markdown.d.ts.map +1 -0
- package/packages/engine/dist/markdown/render-list-markdown.js.map +1 -0
- package/packages/engine/dist/migrations/backfill-catalog-model.d.ts +29 -0
- package/packages/engine/dist/migrations/backfill-catalog-model.d.ts.map +1 -0
- package/packages/engine/dist/migrations/backfill-catalog-model.js.map +1 -0
- package/packages/engine/dist/migrations/index.d.ts.map +1 -0
- package/packages/engine/dist/migrations/index.js.map +1 -0
- package/packages/engine/dist/migrations/migrate-native-catalog-layout.d.ts +51 -0
- package/packages/engine/dist/migrations/migrate-native-catalog-layout.d.ts.map +1 -0
- package/packages/engine/dist/migrations/migrate-native-catalog-layout.js.map +1 -0
- package/packages/engine/dist/migrations/migrate-native-item-scope.d.ts +36 -0
- package/packages/engine/dist/migrations/migrate-native-item-scope.d.ts.map +1 -0
- package/packages/engine/dist/migrations/migrate-native-item-scope.js.map +1 -0
- package/packages/engine/dist/migrations/renderer-metadata.d.ts +7 -0
- package/packages/engine/dist/migrations/renderer-metadata.d.ts.map +1 -0
- package/packages/engine/dist/migrations/renderer-metadata.js.map +1 -0
- package/packages/engine/dist/mongo/adapter-store.d.ts +15 -0
- package/packages/engine/dist/mongo/adapter-store.d.ts.map +1 -0
- package/packages/engine/dist/mongo/adapter-store.js +18 -0
- package/packages/engine/dist/mongo/adapter-store.js.map +1 -0
- package/packages/engine/dist/mongo/agent-store.d.ts +18 -0
- package/packages/engine/dist/mongo/agent-store.d.ts.map +1 -0
- package/packages/engine/dist/mongo/agent-store.js +45 -0
- package/packages/engine/dist/mongo/agent-store.js.map +1 -0
- package/packages/engine/dist/mongo/app-store.d.ts +10 -0
- package/packages/engine/dist/mongo/app-store.d.ts.map +1 -0
- package/packages/engine/dist/mongo/app-store.js +16 -0
- package/packages/engine/dist/mongo/app-store.js.map +1 -0
- package/packages/engine/dist/mongo/binding-store.d.ts +15 -0
- package/packages/engine/dist/mongo/binding-store.d.ts.map +1 -0
- package/packages/engine/dist/mongo/binding-store.js +28 -0
- package/packages/engine/dist/mongo/binding-store.js.map +1 -0
- package/packages/engine/dist/mongo/bootstrap.d.ts +37 -0
- package/packages/engine/dist/mongo/bootstrap.d.ts.map +1 -0
- package/packages/engine/dist/mongo/bootstrap.js +41 -0
- package/packages/engine/dist/mongo/bootstrap.js.map +1 -0
- package/packages/engine/dist/mongo/catalog-data-index-store.d.ts +14 -0
- package/packages/engine/dist/mongo/catalog-data-index-store.d.ts.map +1 -0
- package/packages/engine/dist/mongo/catalog-data-index-store.js +33 -0
- package/packages/engine/dist/mongo/catalog-data-index-store.js.map +1 -0
- package/packages/engine/dist/mongo/catalog-item-history-store.d.ts +14 -0
- package/packages/engine/dist/mongo/catalog-item-history-store.d.ts.map +1 -0
- package/packages/engine/dist/mongo/catalog-item-history-store.js +41 -0
- package/packages/engine/dist/mongo/catalog-item-history-store.js.map +1 -0
- package/packages/engine/dist/mongo/catalog-store.d.ts +12 -0
- package/packages/engine/dist/mongo/catalog-store.d.ts.map +1 -0
- package/packages/engine/dist/mongo/catalog-store.js +23 -0
- package/packages/engine/dist/mongo/catalog-store.js.map +1 -0
- package/packages/engine/dist/mongo/catalog-type-store.d.ts +18 -0
- package/packages/engine/dist/mongo/catalog-type-store.d.ts.map +1 -0
- package/packages/engine/dist/mongo/catalog-type-store.js +45 -0
- package/packages/engine/dist/mongo/catalog-type-store.js.map +1 -0
- package/packages/engine/dist/mongo/definition-store.d.ts +24 -0
- package/packages/engine/dist/mongo/definition-store.d.ts.map +1 -0
- package/packages/engine/dist/mongo/definition-store.js +15 -0
- package/packages/engine/dist/mongo/definition-store.js.map +1 -0
- package/packages/engine/dist/mongo/descriptor-store.d.ts +10 -0
- package/packages/engine/dist/mongo/descriptor-store.d.ts.map +1 -0
- package/packages/engine/dist/mongo/descriptor-store.js +15 -0
- package/packages/engine/dist/mongo/descriptor-store.js.map +1 -0
- package/packages/engine/dist/mongo/design-object-store.d.ts +11 -0
- package/packages/engine/dist/mongo/design-object-store.d.ts.map +1 -0
- package/packages/engine/dist/mongo/design-object-store.js +43 -0
- package/packages/engine/dist/mongo/design-object-store.js.map +1 -0
- package/packages/engine/dist/mongo/domain-store.d.ts +18 -0
- package/packages/engine/dist/mongo/domain-store.d.ts.map +1 -0
- package/packages/engine/dist/mongo/domain-store.js +45 -0
- package/packages/engine/dist/mongo/domain-store.js.map +1 -0
- package/packages/engine/dist/mongo/identity-binding-store.d.ts +13 -0
- package/packages/engine/dist/mongo/identity-binding-store.d.ts.map +1 -0
- package/packages/engine/dist/mongo/identity-binding-store.js +22 -0
- package/packages/engine/dist/mongo/identity-binding-store.js.map +1 -0
- package/packages/engine/dist/mongo/index.d.ts +9 -0
- package/packages/engine/dist/mongo/index.d.ts.map +1 -0
- package/packages/engine/dist/mongo/index.js +9 -0
- package/packages/engine/dist/mongo/index.js.map +1 -0
- package/packages/engine/dist/mongo/mapping-store.d.ts +11 -0
- package/packages/engine/dist/mongo/mapping-store.d.ts.map +1 -0
- package/packages/engine/dist/mongo/mapping-store.js +18 -0
- package/packages/engine/dist/mongo/mapping-store.js.map +1 -0
- package/packages/engine/dist/mongo/mongo-store.d.ts +43 -0
- package/packages/engine/dist/mongo/mongo-store.d.ts.map +1 -0
- package/packages/engine/dist/mongo/mongo-store.js +23 -0
- package/packages/engine/dist/mongo/mongo-store.js.map +1 -0
- package/packages/engine/dist/mongo/mongo-utils.d.ts +5 -0
- package/packages/engine/dist/mongo/mongo-utils.d.ts.map +1 -0
- package/packages/engine/dist/mongo/mongo-utils.js +21 -0
- package/packages/engine/dist/mongo/mongo-utils.js.map +1 -0
- package/packages/engine/dist/mongo/native-item-store.d.ts +29 -0
- package/packages/engine/dist/mongo/native-item-store.d.ts.map +1 -0
- package/packages/engine/dist/mongo/native-item-store.js +107 -0
- package/packages/engine/dist/mongo/native-item-store.js.map +1 -0
- package/packages/engine/dist/mongo/presentation-profile-store.d.ts +14 -0
- package/packages/engine/dist/mongo/presentation-profile-store.d.ts.map +1 -0
- package/packages/engine/dist/mongo/presentation-profile-store.js +33 -0
- package/packages/engine/dist/mongo/presentation-profile-store.js.map +1 -0
- package/packages/engine/dist/mongo/reference-store.d.ts +21 -0
- package/packages/engine/dist/mongo/reference-store.d.ts.map +1 -0
- package/packages/engine/dist/mongo/reference-store.js +35 -0
- package/packages/engine/dist/mongo/reference-store.js.map +1 -0
- package/packages/engine/dist/mongo/renderer-snippet-store.d.ts +14 -0
- package/packages/engine/dist/mongo/renderer-snippet-store.d.ts.map +1 -0
- package/packages/engine/dist/mongo/renderer-snippet-store.js +28 -0
- package/packages/engine/dist/mongo/renderer-snippet-store.js.map +1 -0
- package/packages/engine/dist/mongo/snapshot-store.d.ts +19 -0
- package/packages/engine/dist/mongo/snapshot-store.d.ts.map +1 -0
- package/packages/engine/dist/mongo/snapshot-store.js +43 -0
- package/packages/engine/dist/mongo/snapshot-store.js.map +1 -0
- package/packages/engine/dist/mongo/store-app-binding-store.d.ts +14 -0
- package/packages/engine/dist/mongo/store-app-binding-store.d.ts.map +1 -0
- package/packages/engine/dist/mongo/store-app-binding-store.js +25 -0
- package/packages/engine/dist/mongo/store-app-binding-store.js.map +1 -0
- package/packages/engine/dist/mongo/wire-mongo-catalox.d.ts +14 -0
- package/packages/engine/dist/mongo/wire-mongo-catalox.d.ts.map +1 -0
- package/packages/engine/dist/mongo/wire-mongo-catalox.js +84 -0
- package/packages/engine/dist/mongo/wire-mongo-catalox.js.map +1 -0
- package/packages/engine/dist/operator.d.ts.map +1 -0
- package/packages/engine/dist/operator.js.map +1 -0
- package/packages/engine/dist/validation/index.d.ts.map +1 -0
- package/packages/engine/dist/validation/index.js.map +1 -0
- package/packages/engine/dist/validation/payload-schema-registry.d.ts.map +1 -0
- package/packages/engine/dist/validation/payload-schema-registry.js.map +1 -0
- package/packages/engine/dist/validation/payload-schema.d.ts +30 -0
- package/packages/engine/dist/validation/payload-schema.d.ts.map +1 -0
- package/packages/engine/dist/validation/payload-schema.js.map +1 -0
- package/packages/engine/dist/validation/ui-spec-schema.d.ts.map +1 -0
- package/packages/engine/dist/validation/ui-spec-schema.js.map +1 -0
- package/packages/engine/dist/validation/ui-spec-validate.d.ts.map +1 -0
- package/packages/engine/dist/validation/ui-spec-validate.js.map +1 -0
- package/dist/src/adapters/api/api-adapter.d.ts +0 -22
- package/dist/src/adapters/api/api-adapter.d.ts.map +0 -1
- package/dist/src/adapters/api/api-adapter.js +0 -64
- package/dist/src/adapters/api/api-adapter.js.map +0 -1
- package/dist/src/adapters/api/index.d.ts.map +0 -1
- package/dist/src/adapters/api/index.js.map +0 -1
- package/dist/src/adapters/mongo/index.d.ts.map +0 -1
- package/dist/src/adapters/mongo/index.js.map +0 -1
- package/dist/src/adapters/mongo/mongo-adapter.d.ts +0 -21
- package/dist/src/adapters/mongo/mongo-adapter.d.ts.map +0 -1
- package/dist/src/adapters/mongo/mongo-adapter.js +0 -61
- package/dist/src/adapters/mongo/mongo-adapter.js.map +0 -1
- package/dist/src/adapters/mongo/resolve-db.d.ts +0 -4
- package/dist/src/adapters/mongo/resolve-db.d.ts.map +0 -1
- package/dist/src/adapters/mongo/resolve-db.js.map +0 -1
- package/dist/src/bindings/index.d.ts.map +0 -1
- package/dist/src/bindings/index.js.map +0 -1
- package/dist/src/catalox/authorization.d.ts +0 -20
- package/dist/src/catalox/authorization.d.ts.map +0 -1
- package/dist/src/catalox/authorization.js +0 -55
- package/dist/src/catalox/authorization.js.map +0 -1
- package/dist/src/catalox/backup-data.d.ts +0 -70
- package/dist/src/catalox/backup-data.d.ts.map +0 -1
- package/dist/src/catalox/backup-data.js.map +0 -1
- package/dist/src/catalox/catalog-discovery.d.ts +0 -9
- package/dist/src/catalox/catalog-discovery.d.ts.map +0 -1
- package/dist/src/catalox/catalog-discovery.js.map +0 -1
- package/dist/src/catalox/catalog-lifecycle.d.ts +0 -29
- package/dist/src/catalox/catalog-lifecycle.d.ts.map +0 -1
- package/dist/src/catalox/catalog-lifecycle.js.map +0 -1
- package/dist/src/catalox/catalog-snapshot-export.d.ts +0 -46
- package/dist/src/catalox/catalog-snapshot-export.d.ts.map +0 -1
- package/dist/src/catalox/catalog-snapshot-export.js +0 -103
- package/dist/src/catalox/catalog-snapshot-export.js.map +0 -1
- package/dist/src/catalox/catalox-bound.d.ts +0 -191
- package/dist/src/catalox/catalox-bound.d.ts.map +0 -1
- package/dist/src/catalox/catalox-bound.js +0 -241
- package/dist/src/catalox/catalox-bound.js.map +0 -1
- package/dist/src/catalox/catalox-gcs-backup-export-manifest.d.ts +0 -13
- package/dist/src/catalox/catalox-gcs-backup-export-manifest.d.ts.map +0 -1
- package/dist/src/catalox/catalox-gcs-backup-export-manifest.js.map +0 -1
- package/dist/src/catalox/catalox.d.ts +0 -348
- package/dist/src/catalox/catalox.d.ts.map +0 -1
- package/dist/src/catalox/catalox.js +0 -2599
- package/dist/src/catalox/catalox.js.map +0 -1
- package/dist/src/catalox/context.d.ts +0 -17
- package/dist/src/catalox/context.d.ts.map +0 -1
- package/dist/src/catalox/context.js.map +0 -1
- package/dist/src/catalox/create-catalox.d.ts +0 -35
- package/dist/src/catalox/create-catalox.d.ts.map +0 -1
- package/dist/src/catalox/create-catalox.js +0 -116
- package/dist/src/catalox/create-catalox.js.map +0 -1
- package/dist/src/catalox/field-source-resolution.d.ts +0 -16
- package/dist/src/catalox/field-source-resolution.d.ts.map +0 -1
- package/dist/src/catalox/field-source-resolution.js.map +0 -1
- package/dist/src/catalox/firestore-gcs-compare.d.ts +0 -15
- package/dist/src/catalox/firestore-gcs-compare.d.ts.map +0 -1
- package/dist/src/catalox/firestore-gcs-compare.js.map +0 -1
- package/dist/src/catalox/firestore-gcs-transfer.d.ts +0 -28
- package/dist/src/catalox/firestore-gcs-transfer.d.ts.map +0 -1
- package/dist/src/catalox/firestore-gcs-transfer.js.map +0 -1
- package/dist/src/catalox/identity.d.ts +0 -7
- package/dist/src/catalox/identity.d.ts.map +0 -1
- package/dist/src/catalox/identity.js.map +0 -1
- package/dist/src/catalox/index.d.ts +0 -17
- package/dist/src/catalox/index.d.ts.map +0 -1
- package/dist/src/catalox/index.js +0 -17
- package/dist/src/catalox/index.js.map +0 -1
- package/dist/src/catalox/item-scope-match.d.ts +0 -39
- package/dist/src/catalox/item-scope-match.d.ts.map +0 -1
- package/dist/src/catalox/item-scope-match.js.map +0 -1
- package/dist/src/catalox/item-scope.d.ts +0 -36
- package/dist/src/catalox/item-scope.d.ts.map +0 -1
- package/dist/src/catalox/item-scope.js +0 -137
- package/dist/src/catalox/item-scope.js.map +0 -1
- package/dist/src/catalox/json-io.d.ts.map +0 -1
- package/dist/src/catalox/json-io.js.map +0 -1
- package/dist/src/catalox/native-catalog-layout-diagnostics.d.ts +0 -29
- package/dist/src/catalox/native-catalog-layout-diagnostics.d.ts.map +0 -1
- package/dist/src/catalox/native-catalog-layout-diagnostics.js.map +0 -1
- package/dist/src/catalox/native-catalog-merge.d.ts +0 -10
- package/dist/src/catalox/native-catalog-merge.d.ts.map +0 -1
- package/dist/src/catalox/native-catalog-merge.js +0 -40
- package/dist/src/catalox/native-catalog-merge.js.map +0 -1
- package/dist/src/catalox/native-item-resolve.d.ts +0 -28
- package/dist/src/catalox/native-item-resolve.d.ts.map +0 -1
- package/dist/src/catalox/native-item-resolve.js.map +0 -1
- package/dist/src/catalox/record-history.d.ts +0 -53
- package/dist/src/catalox/record-history.d.ts.map +0 -1
- package/dist/src/catalox/record-history.js.map +0 -1
- package/dist/src/catalox/reporting/render-inventory-report.d.ts +0 -3
- package/dist/src/catalox/reporting/render-inventory-report.d.ts.map +0 -1
- package/dist/src/catalox/reporting/render-inventory-report.js.map +0 -1
- package/dist/src/catalox/restore-firestore-backup-from-gcs.d.ts +0 -21
- package/dist/src/catalox/restore-firestore-backup-from-gcs.d.ts.map +0 -1
- package/dist/src/catalox/restore-firestore-backup-from-gcs.js.map +0 -1
- package/dist/src/catalox/restore-firestore-backup.d.ts +0 -32
- package/dist/src/catalox/restore-firestore-backup.d.ts.map +0 -1
- package/dist/src/catalox/restore-firestore-backup.js.map +0 -1
- package/dist/src/catalox/scope-legacy-convert.d.ts +0 -19
- package/dist/src/catalox/scope-legacy-convert.d.ts.map +0 -1
- package/dist/src/catalox/scope-legacy-convert.js.map +0 -1
- package/dist/src/catalox/seed-preset-resolve.d.ts.map +0 -1
- package/dist/src/catalox/seed-preset-resolve.js.map +0 -1
- package/dist/src/catalox/seed-preset.d.ts +0 -85
- package/dist/src/catalox/seed-preset.d.ts.map +0 -1
- package/dist/src/catalox/seed-preset.js.map +0 -1
- package/dist/src/catalox/smart-properties.d.ts +0 -33
- package/dist/src/catalox/smart-properties.d.ts.map +0 -1
- package/dist/src/catalox/smart-properties.js +0 -242
- package/dist/src/catalox/smart-properties.js.map +0 -1
- package/dist/src/cli/index.d.ts.map +0 -1
- package/dist/src/cli/index.js +0 -1426
- package/dist/src/cli/index.js.map +0 -1
- package/dist/src/cli/item-json.d.ts.map +0 -1
- package/dist/src/cli/item-json.js.map +0 -1
- package/dist/src/contracts/adapters.d.ts +0 -40
- package/dist/src/contracts/adapters.d.ts.map +0 -1
- package/dist/src/contracts/adapters.js +0 -2
- package/dist/src/contracts/adapters.js.map +0 -1
- package/dist/src/contracts/agents.d.ts +0 -19
- package/dist/src/contracts/agents.d.ts.map +0 -1
- package/dist/src/contracts/agents.js +0 -2
- package/dist/src/contracts/agents.js.map +0 -1
- package/dist/src/contracts/apps.d.ts +0 -13
- package/dist/src/contracts/apps.d.ts.map +0 -1
- package/dist/src/contracts/apps.js +0 -2
- package/dist/src/contracts/apps.js.map +0 -1
- package/dist/src/contracts/backup.d.ts +0 -46
- package/dist/src/contracts/backup.d.ts.map +0 -1
- package/dist/src/contracts/backup.js +0 -2
- package/dist/src/contracts/backup.js.map +0 -1
- package/dist/src/contracts/bindings.d.ts +0 -52
- package/dist/src/contracts/bindings.d.ts.map +0 -1
- package/dist/src/contracts/bindings.js +0 -2
- package/dist/src/contracts/bindings.js.map +0 -1
- package/dist/src/contracts/bootstrap.d.ts +0 -33
- package/dist/src/contracts/bootstrap.d.ts.map +0 -1
- package/dist/src/contracts/bootstrap.js +0 -2
- package/dist/src/contracts/bootstrap.js.map +0 -1
- package/dist/src/contracts/catalog-data-index.d.ts +0 -13
- package/dist/src/contracts/catalog-data-index.d.ts.map +0 -1
- package/dist/src/contracts/catalog-data-index.js +0 -2
- package/dist/src/contracts/catalog-data-index.js.map +0 -1
- package/dist/src/contracts/catalog-lifecycle.d.ts +0 -70
- package/dist/src/contracts/catalog-lifecycle.d.ts.map +0 -1
- package/dist/src/contracts/catalog-lifecycle.js +0 -2
- package/dist/src/contracts/catalog-lifecycle.js.map +0 -1
- package/dist/src/contracts/catalog-snapshot-export.d.ts +0 -55
- package/dist/src/contracts/catalog-snapshot-export.d.ts.map +0 -1
- package/dist/src/contracts/catalog-snapshot-export.js +0 -3
- package/dist/src/contracts/catalog-snapshot-export.js.map +0 -1
- package/dist/src/contracts/catalog-types.d.ts +0 -31
- package/dist/src/contracts/catalog-types.d.ts.map +0 -1
- package/dist/src/contracts/catalog-types.js +0 -2
- package/dist/src/contracts/catalog-types.js.map +0 -1
- package/dist/src/contracts/catalogs.d.ts +0 -152
- package/dist/src/contracts/catalogs.d.ts.map +0 -1
- package/dist/src/contracts/catalogs.js +0 -19
- package/dist/src/contracts/catalogs.js.map +0 -1
- package/dist/src/contracts/config.d.ts +0 -14
- package/dist/src/contracts/config.d.ts.map +0 -1
- package/dist/src/contracts/config.js +0 -2
- package/dist/src/contracts/config.js.map +0 -1
- package/dist/src/contracts/context.d.ts +0 -50
- package/dist/src/contracts/context.d.ts.map +0 -1
- package/dist/src/contracts/context.js +0 -2
- package/dist/src/contracts/context.js.map +0 -1
- package/dist/src/contracts/custom-renderer-resolve.d.ts +0 -15
- package/dist/src/contracts/custom-renderer-resolve.d.ts.map +0 -1
- package/dist/src/contracts/custom-renderer-resolve.js +0 -55
- package/dist/src/contracts/custom-renderer-resolve.js.map +0 -1
- package/dist/src/contracts/descriptor-rules.d.ts +0 -76
- package/dist/src/contracts/descriptor-rules.d.ts.map +0 -1
- package/dist/src/contracts/descriptor-rules.js +0 -2
- package/dist/src/contracts/descriptor-rules.js.map +0 -1
- package/dist/src/contracts/descriptors.d.ts +0 -115
- package/dist/src/contracts/descriptors.d.ts.map +0 -1
- package/dist/src/contracts/descriptors.js +0 -2
- package/dist/src/contracts/descriptors.js.map +0 -1
- package/dist/src/contracts/design-objects.d.ts +0 -38
- package/dist/src/contracts/design-objects.d.ts.map +0 -1
- package/dist/src/contracts/design-objects.js +0 -2
- package/dist/src/contracts/design-objects.js.map +0 -1
- package/dist/src/contracts/diagram-map.d.ts +0 -24
- package/dist/src/contracts/diagram-map.d.ts.map +0 -1
- package/dist/src/contracts/diagram-map.js +0 -2
- package/dist/src/contracts/diagram-map.js.map +0 -1
- package/dist/src/contracts/discovery.d.ts +0 -99
- package/dist/src/contracts/discovery.d.ts.map +0 -1
- package/dist/src/contracts/discovery.js +0 -2
- package/dist/src/contracts/discovery.js.map +0 -1
- package/dist/src/contracts/domains.d.ts +0 -19
- package/dist/src/contracts/domains.d.ts.map +0 -1
- package/dist/src/contracts/domains.js +0 -2
- package/dist/src/contracts/domains.js.map +0 -1
- package/dist/src/contracts/errors.d.ts +0 -37
- package/dist/src/contracts/errors.d.ts.map +0 -1
- package/dist/src/contracts/errors.js +0 -64
- package/dist/src/contracts/errors.js.map +0 -1
- package/dist/src/contracts/field-source.d.ts +0 -43
- package/dist/src/contracts/field-source.d.ts.map +0 -1
- package/dist/src/contracts/field-source.js +0 -2
- package/dist/src/contracts/field-source.js.map +0 -1
- package/dist/src/contracts/filters.d.ts +0 -59
- package/dist/src/contracts/filters.d.ts.map +0 -1
- package/dist/src/contracts/filters.js +0 -2
- package/dist/src/contracts/filters.js.map +0 -1
- package/dist/src/contracts/gcs-firestore-compare.d.ts +0 -64
- package/dist/src/contracts/gcs-firestore-compare.d.ts.map +0 -1
- package/dist/src/contracts/gcs-firestore-compare.js +0 -2
- package/dist/src/contracts/gcs-firestore-compare.js.map +0 -1
- package/dist/src/contracts/gcs-firestore-transfer.d.ts +0 -108
- package/dist/src/contracts/gcs-firestore-transfer.d.ts.map +0 -1
- package/dist/src/contracts/gcs-firestore-transfer.js +0 -2
- package/dist/src/contracts/gcs-firestore-transfer.js.map +0 -1
- package/dist/src/contracts/ids.d.ts +0 -10
- package/dist/src/contracts/ids.d.ts.map +0 -1
- package/dist/src/contracts/ids.js +0 -2
- package/dist/src/contracts/ids.js.map +0 -1
- package/dist/src/contracts/index.d.ts +0 -53
- package/dist/src/contracts/index.d.ts.map +0 -1
- package/dist/src/contracts/index.js +0 -6
- package/dist/src/contracts/index.js.map +0 -1
- package/dist/src/contracts/inputs.d.ts +0 -51
- package/dist/src/contracts/inputs.d.ts.map +0 -1
- package/dist/src/contracts/inputs.js +0 -2
- package/dist/src/contracts/inputs.js.map +0 -1
- package/dist/src/contracts/inventory-export.d.ts +0 -40
- package/dist/src/contracts/inventory-export.d.ts.map +0 -1
- package/dist/src/contracts/inventory-export.js +0 -2
- package/dist/src/contracts/inventory-export.js.map +0 -1
- package/dist/src/contracts/inventory-report.d.ts +0 -61
- package/dist/src/contracts/inventory-report.d.ts.map +0 -1
- package/dist/src/contracts/inventory-report.js +0 -2
- package/dist/src/contracts/inventory-report.js.map +0 -1
- package/dist/src/contracts/item-validation.d.ts +0 -11
- package/dist/src/contracts/item-validation.d.ts.map +0 -1
- package/dist/src/contracts/item-validation.js +0 -2
- package/dist/src/contracts/item-validation.js.map +0 -1
- package/dist/src/contracts/items.d.ts +0 -63
- package/dist/src/contracts/items.d.ts.map +0 -1
- package/dist/src/contracts/items.js +0 -2
- package/dist/src/contracts/items.js.map +0 -1
- package/dist/src/contracts/mappings.d.ts +0 -35
- package/dist/src/contracts/mappings.d.ts.map +0 -1
- package/dist/src/contracts/mappings.js +0 -2
- package/dist/src/contracts/mappings.js.map +0 -1
- package/dist/src/contracts/markdown-map.d.ts +0 -42
- package/dist/src/contracts/markdown-map.d.ts.map +0 -1
- package/dist/src/contracts/markdown-map.js +0 -2
- package/dist/src/contracts/markdown-map.js.map +0 -1
- package/dist/src/contracts/presentation-binding.d.ts +0 -116
- package/dist/src/contracts/presentation-binding.d.ts.map +0 -1
- package/dist/src/contracts/presentation-binding.js +0 -215
- package/dist/src/contracts/presentation-binding.js.map +0 -1
- package/dist/src/contracts/presentation.d.ts +0 -225
- package/dist/src/contracts/presentation.d.ts.map +0 -1
- package/dist/src/contracts/presentation.js +0 -2
- package/dist/src/contracts/presentation.js.map +0 -1
- package/dist/src/contracts/query.d.ts +0 -10
- package/dist/src/contracts/query.d.ts.map +0 -1
- package/dist/src/contracts/query.js +0 -2
- package/dist/src/contracts/query.js.map +0 -1
- package/dist/src/contracts/record-history.d.ts +0 -66
- package/dist/src/contracts/record-history.d.ts.map +0 -1
- package/dist/src/contracts/record-history.js +0 -2
- package/dist/src/contracts/record-history.js.map +0 -1
- package/dist/src/contracts/references.d.ts +0 -51
- package/dist/src/contracts/references.d.ts.map +0 -1
- package/dist/src/contracts/references.js +0 -2
- package/dist/src/contracts/references.js.map +0 -1
- package/dist/src/contracts/render-map.d.ts +0 -173
- package/dist/src/contracts/render-map.d.ts.map +0 -1
- package/dist/src/contracts/render-map.js +0 -2
- package/dist/src/contracts/render-map.js.map +0 -1
- package/dist/src/contracts/renderer-snippets.d.ts +0 -45
- package/dist/src/contracts/renderer-snippets.d.ts.map +0 -1
- package/dist/src/contracts/renderer-snippets.js +0 -2
- package/dist/src/contracts/renderer-snippets.js.map +0 -1
- package/dist/src/contracts/restore.d.ts +0 -60
- package/dist/src/contracts/restore.d.ts.map +0 -1
- package/dist/src/contracts/restore.js +0 -2
- package/dist/src/contracts/restore.js.map +0 -1
- package/dist/src/contracts/search.d.ts +0 -20
- package/dist/src/contracts/search.d.ts.map +0 -1
- package/dist/src/contracts/search.js +0 -2
- package/dist/src/contracts/search.js.map +0 -1
- package/dist/src/contracts/snapshots.d.ts +0 -12
- package/dist/src/contracts/snapshots.d.ts.map +0 -1
- package/dist/src/contracts/snapshots.js +0 -2
- package/dist/src/contracts/snapshots.js.map +0 -1
- package/dist/src/contracts/stores.d.ts +0 -21
- package/dist/src/contracts/stores.d.ts.map +0 -1
- package/dist/src/contracts/stores.js +0 -2
- package/dist/src/contracts/stores.js.map +0 -1
- package/dist/src/contracts/sync.d.ts +0 -7
- package/dist/src/contracts/sync.d.ts.map +0 -1
- package/dist/src/contracts/sync.js +0 -2
- package/dist/src/contracts/sync.js.map +0 -1
- package/dist/src/contracts/validation.d.ts +0 -13
- package/dist/src/contracts/validation.d.ts.map +0 -1
- package/dist/src/contracts/validation.js +0 -2
- package/dist/src/contracts/validation.js.map +0 -1
- package/dist/src/diagrams/render-catalog-diagram.d.ts +0 -3
- package/dist/src/diagrams/render-catalog-diagram.d.ts.map +0 -1
- package/dist/src/diagrams/render-catalog-diagram.js.map +0 -1
- package/dist/src/diagrams/render-item-diagram.d.ts +0 -3
- package/dist/src/diagrams/render-item-diagram.d.ts.map +0 -1
- package/dist/src/diagrams/render-item-diagram.js.map +0 -1
- package/dist/src/embedder.d.ts +0 -25
- package/dist/src/embedder.d.ts.map +0 -1
- package/dist/src/embedder.js +0 -24
- package/dist/src/embedder.js.map +0 -1
- package/dist/src/errors/index.d.ts.map +0 -1
- package/dist/src/errors/index.js.map +0 -1
- package/dist/src/firebase/adapter-store.d.ts +0 -16
- package/dist/src/firebase/adapter-store.d.ts.map +0 -1
- package/dist/src/firebase/adapter-store.js.map +0 -1
- package/dist/src/firebase/agent-store.d.ts +0 -18
- package/dist/src/firebase/agent-store.d.ts.map +0 -1
- package/dist/src/firebase/agent-store.js.map +0 -1
- package/dist/src/firebase/app-store.d.ts +0 -11
- package/dist/src/firebase/app-store.d.ts.map +0 -1
- package/dist/src/firebase/app-store.js.map +0 -1
- package/dist/src/firebase/binding-store.d.ts +0 -15
- package/dist/src/firebase/binding-store.d.ts.map +0 -1
- package/dist/src/firebase/binding-store.js.map +0 -1
- package/dist/src/firebase/bootstrap.d.ts.map +0 -1
- package/dist/src/firebase/bootstrap.js.map +0 -1
- package/dist/src/firebase/catalog-data-index-store.d.ts +0 -15
- package/dist/src/firebase/catalog-data-index-store.d.ts.map +0 -1
- package/dist/src/firebase/catalog-data-index-store.js.map +0 -1
- package/dist/src/firebase/catalog-data-paths.d.ts +0 -14
- package/dist/src/firebase/catalog-data-paths.d.ts.map +0 -1
- package/dist/src/firebase/catalog-data-paths.js.map +0 -1
- package/dist/src/firebase/catalog-item-history-store.d.ts +0 -21
- package/dist/src/firebase/catalog-item-history-store.d.ts.map +0 -1
- package/dist/src/firebase/catalog-item-history-store.js.map +0 -1
- package/dist/src/firebase/catalog-store.d.ts +0 -13
- package/dist/src/firebase/catalog-store.d.ts.map +0 -1
- package/dist/src/firebase/catalog-store.js.map +0 -1
- package/dist/src/firebase/catalog-type-store.d.ts +0 -22
- package/dist/src/firebase/catalog-type-store.d.ts.map +0 -1
- package/dist/src/firebase/catalog-type-store.js.map +0 -1
- package/dist/src/firebase/definition-store.d.ts +0 -25
- package/dist/src/firebase/definition-store.d.ts.map +0 -1
- package/dist/src/firebase/definition-store.js.map +0 -1
- package/dist/src/firebase/descriptor-store.d.ts +0 -11
- package/dist/src/firebase/descriptor-store.d.ts.map +0 -1
- package/dist/src/firebase/descriptor-store.js.map +0 -1
- package/dist/src/firebase/design-object-store.d.ts +0 -15
- package/dist/src/firebase/design-object-store.d.ts.map +0 -1
- package/dist/src/firebase/design-object-store.js.map +0 -1
- package/dist/src/firebase/domain-store.d.ts +0 -18
- package/dist/src/firebase/domain-store.d.ts.map +0 -1
- package/dist/src/firebase/domain-store.js.map +0 -1
- package/dist/src/firebase/firestore-collection-path.d.ts.map +0 -1
- package/dist/src/firebase/firestore-collection-path.js.map +0 -1
- package/dist/src/firebase/firestore-store.d.ts.map +0 -1
- package/dist/src/firebase/firestore-store.js.map +0 -1
- package/dist/src/firebase/identity-binding-store.d.ts +0 -18
- package/dist/src/firebase/identity-binding-store.d.ts.map +0 -1
- package/dist/src/firebase/identity-binding-store.js.map +0 -1
- package/dist/src/firebase/index.d.ts.map +0 -1
- package/dist/src/firebase/index.js.map +0 -1
- package/dist/src/firebase/mapping-store.d.ts +0 -12
- package/dist/src/firebase/mapping-store.d.ts.map +0 -1
- package/dist/src/firebase/mapping-store.js.map +0 -1
- package/dist/src/firebase/native-item-store.d.ts +0 -38
- package/dist/src/firebase/native-item-store.d.ts.map +0 -1
- package/dist/src/firebase/native-item-store.js +0 -110
- package/dist/src/firebase/native-item-store.js.map +0 -1
- package/dist/src/firebase/presentation-profile-store.d.ts +0 -18
- package/dist/src/firebase/presentation-profile-store.d.ts.map +0 -1
- package/dist/src/firebase/presentation-profile-store.js.map +0 -1
- package/dist/src/firebase/reference-store.d.ts +0 -21
- package/dist/src/firebase/reference-store.d.ts.map +0 -1
- package/dist/src/firebase/reference-store.js.map +0 -1
- package/dist/src/firebase/renderer-snippet-store.d.ts +0 -15
- package/dist/src/firebase/renderer-snippet-store.d.ts.map +0 -1
- package/dist/src/firebase/renderer-snippet-store.js.map +0 -1
- package/dist/src/firebase/snapshot-store.d.ts +0 -19
- package/dist/src/firebase/snapshot-store.d.ts.map +0 -1
- package/dist/src/firebase/snapshot-store.js.map +0 -1
- package/dist/src/firebase/store-app-binding-store.d.ts +0 -14
- package/dist/src/firebase/store-app-binding-store.d.ts.map +0 -1
- package/dist/src/firebase/store-app-binding-store.js.map +0 -1
- package/dist/src/index.d.ts.map +0 -1
- package/dist/src/index.js.map +0 -1
- package/dist/src/jsx/index.d.ts +0 -70
- package/dist/src/jsx/index.d.ts.map +0 -1
- package/dist/src/jsx/index.js +0 -175
- package/dist/src/jsx/index.js.map +0 -1
- package/dist/src/logging.d.ts.map +0 -1
- package/dist/src/logging.js.map +0 -1
- package/dist/src/mapping/execute-mapping.d.ts +0 -8
- package/dist/src/mapping/execute-mapping.d.ts.map +0 -1
- package/dist/src/mapping/execute-mapping.js.map +0 -1
- package/dist/src/mapping/helper-gap-report.d.ts.map +0 -1
- package/dist/src/mapping/helper-gap-report.js.map +0 -1
- package/dist/src/mapping/index.d.ts.map +0 -1
- package/dist/src/mapping/index.js.map +0 -1
- package/dist/src/mapping/validate-mapping.d.ts +0 -3
- package/dist/src/mapping/validate-mapping.d.ts.map +0 -1
- package/dist/src/mapping/validate-mapping.js.map +0 -1
- package/dist/src/markdown/render-item-markdown.d.ts +0 -5
- package/dist/src/markdown/render-item-markdown.d.ts.map +0 -1
- package/dist/src/markdown/render-item-markdown.js.map +0 -1
- package/dist/src/markdown/render-list-markdown.d.ts +0 -5
- package/dist/src/markdown/render-list-markdown.d.ts.map +0 -1
- package/dist/src/markdown/render-list-markdown.js.map +0 -1
- package/dist/src/migrations/backfill-catalog-model.d.ts +0 -29
- package/dist/src/migrations/backfill-catalog-model.d.ts.map +0 -1
- package/dist/src/migrations/backfill-catalog-model.js.map +0 -1
- package/dist/src/migrations/index.d.ts.map +0 -1
- package/dist/src/migrations/index.js.map +0 -1
- package/dist/src/migrations/migrate-native-catalog-layout.d.ts +0 -51
- package/dist/src/migrations/migrate-native-catalog-layout.d.ts.map +0 -1
- package/dist/src/migrations/migrate-native-catalog-layout.js.map +0 -1
- package/dist/src/migrations/migrate-native-item-scope.d.ts +0 -36
- package/dist/src/migrations/migrate-native-item-scope.d.ts.map +0 -1
- package/dist/src/migrations/migrate-native-item-scope.js.map +0 -1
- package/dist/src/migrations/renderer-metadata.d.ts +0 -7
- package/dist/src/migrations/renderer-metadata.d.ts.map +0 -1
- package/dist/src/migrations/renderer-metadata.js.map +0 -1
- package/dist/src/operator.d.ts.map +0 -1
- package/dist/src/operator.js.map +0 -1
- package/dist/src/validation/index.d.ts.map +0 -1
- package/dist/src/validation/index.js.map +0 -1
- package/dist/src/validation/payload-schema-registry.d.ts.map +0 -1
- package/dist/src/validation/payload-schema-registry.js.map +0 -1
- package/dist/src/validation/payload-schema.d.ts +0 -30
- package/dist/src/validation/payload-schema.d.ts.map +0 -1
- package/dist/src/validation/payload-schema.js.map +0 -1
- package/dist/src/validation/ui-spec-schema.d.ts.map +0 -1
- package/dist/src/validation/ui-spec-schema.js.map +0 -1
- package/dist/src/validation/ui-spec-validate.d.ts.map +0 -1
- package/dist/src/validation/ui-spec-validate.js.map +0 -1
- package/docs/catalox-ui-contract.md +0 -132
- package/docs/cli-items.md +0 -94
- package/docs/cli-snapshot-export.md +0 -65
- package/docs/cli-toolbox.md +0 -166
- package/firestore.indexes.json +0 -39
- /package/{dist/src → packages/engine/dist}/adapters/api/index.d.ts +0 -0
- /package/{dist/src → packages/engine/dist}/adapters/api/index.js +0 -0
- /package/{dist/src → packages/engine/dist}/adapters/mongo/index.d.ts +0 -0
- /package/{dist/src → packages/engine/dist}/adapters/mongo/index.js +0 -0
- /package/{dist/src → packages/engine/dist}/adapters/mongo/resolve-db.js +0 -0
- /package/{dist/src → packages/engine/dist}/bindings/index.d.ts +0 -0
- /package/{dist/src → packages/engine/dist}/bindings/index.js +0 -0
- /package/{dist/src → packages/engine/dist}/catalox/backup-data.js +0 -0
- /package/{dist/src → packages/engine/dist}/catalox/catalog-discovery.js +0 -0
- /package/{dist/src → packages/engine/dist}/catalox/catalog-lifecycle.js +0 -0
- /package/{dist/src → packages/engine/dist}/catalox/catalox-gcs-backup-export-manifest.js +0 -0
- /package/{dist/src → packages/engine/dist}/catalox/context.js +0 -0
- /package/{dist/src → packages/engine/dist}/catalox/field-source-resolution.js +0 -0
- /package/{dist/src → packages/engine/dist}/catalox/firestore-gcs-compare.js +0 -0
- /package/{dist/src → packages/engine/dist}/catalox/firestore-gcs-transfer.js +0 -0
- /package/{dist/src → packages/engine/dist}/catalox/identity.js +0 -0
- /package/{dist/src → packages/engine/dist}/catalox/item-scope-match.js +0 -0
- /package/{dist/src → packages/engine/dist}/catalox/json-io.d.ts +0 -0
- /package/{dist/src → packages/engine/dist}/catalox/json-io.js +0 -0
- /package/{dist/src → packages/engine/dist}/catalox/native-catalog-layout-diagnostics.js +0 -0
- /package/{dist/src → packages/engine/dist}/catalox/native-item-resolve.js +0 -0
- /package/{dist/src → packages/engine/dist}/catalox/record-history.js +0 -0
- /package/{dist/src → packages/engine/dist}/catalox/reporting/render-inventory-report.js +0 -0
- /package/{dist/src → packages/engine/dist}/catalox/restore-firestore-backup-from-gcs.js +0 -0
- /package/{dist/src → packages/engine/dist}/catalox/restore-firestore-backup.js +0 -0
- /package/{dist/src → packages/engine/dist}/catalox/scope-legacy-convert.js +0 -0
- /package/{dist/src → packages/engine/dist}/catalox/seed-preset-resolve.d.ts +0 -0
- /package/{dist/src → packages/engine/dist}/catalox/seed-preset-resolve.js +0 -0
- /package/{dist/src → packages/engine/dist}/catalox/seed-preset.js +0 -0
- /package/{dist/src → packages/engine/dist}/cli/index.d.ts +0 -0
- /package/{dist/src → packages/engine/dist}/cli/item-json.d.ts +0 -0
- /package/{dist/src → packages/engine/dist}/cli/item-json.js +0 -0
- /package/{dist/src → packages/engine/dist}/diagrams/render-catalog-diagram.js +0 -0
- /package/{dist/src → packages/engine/dist}/diagrams/render-item-diagram.js +0 -0
- /package/{dist/src → packages/engine/dist}/errors/index.d.ts +0 -0
- /package/{dist/src → packages/engine/dist}/errors/index.js +0 -0
- /package/{dist/src → packages/engine/dist}/firebase/adapter-store.js +0 -0
- /package/{dist/src → packages/engine/dist}/firebase/agent-store.js +0 -0
- /package/{dist/src → packages/engine/dist}/firebase/app-store.js +0 -0
- /package/{dist/src → packages/engine/dist}/firebase/binding-store.js +0 -0
- /package/{dist/src → packages/engine/dist}/firebase/bootstrap.d.ts +0 -0
- /package/{dist/src → packages/engine/dist}/firebase/bootstrap.js +0 -0
- /package/{dist/src → packages/engine/dist}/firebase/catalog-data-index-store.js +0 -0
- /package/{dist/src → packages/engine/dist}/firebase/catalog-data-paths.js +0 -0
- /package/{dist/src → packages/engine/dist}/firebase/catalog-item-history-store.js +0 -0
- /package/{dist/src → packages/engine/dist}/firebase/catalog-store.js +0 -0
- /package/{dist/src → packages/engine/dist}/firebase/catalog-type-store.js +0 -0
- /package/{dist/src → packages/engine/dist}/firebase/definition-store.js +0 -0
- /package/{dist/src → packages/engine/dist}/firebase/descriptor-store.js +0 -0
- /package/{dist/src → packages/engine/dist}/firebase/design-object-store.js +0 -0
- /package/{dist/src → packages/engine/dist}/firebase/domain-store.js +0 -0
- /package/{dist/src → packages/engine/dist}/firebase/firestore-collection-path.d.ts +0 -0
- /package/{dist/src → packages/engine/dist}/firebase/firestore-collection-path.js +0 -0
- /package/{dist/src → packages/engine/dist}/firebase/firestore-store.d.ts +0 -0
- /package/{dist/src → packages/engine/dist}/firebase/firestore-store.js +0 -0
- /package/{dist/src → packages/engine/dist}/firebase/identity-binding-store.js +0 -0
- /package/{dist/src → packages/engine/dist}/firebase/index.d.ts +0 -0
- /package/{dist/src → packages/engine/dist}/firebase/index.js +0 -0
- /package/{dist/src → packages/engine/dist}/firebase/mapping-store.js +0 -0
- /package/{dist/src → packages/engine/dist}/firebase/presentation-profile-store.js +0 -0
- /package/{dist/src → packages/engine/dist}/firebase/reference-store.js +0 -0
- /package/{dist/src → packages/engine/dist}/firebase/renderer-snippet-store.js +0 -0
- /package/{dist/src → packages/engine/dist}/firebase/snapshot-store.js +0 -0
- /package/{dist/src → packages/engine/dist}/firebase/store-app-binding-store.js +0 -0
- /package/{dist/src → packages/engine/dist}/index.d.ts +0 -0
- /package/{dist/src → packages/engine/dist}/index.js +0 -0
- /package/{dist/src → packages/engine/dist}/logging.d.ts +0 -0
- /package/{dist/src → packages/engine/dist}/logging.js +0 -0
- /package/{dist/src → packages/engine/dist}/mapping/execute-mapping.js +0 -0
- /package/{dist/src → packages/engine/dist}/mapping/helper-gap-report.d.ts +0 -0
- /package/{dist/src → packages/engine/dist}/mapping/helper-gap-report.js +0 -0
- /package/{dist/src → packages/engine/dist}/mapping/index.d.ts +0 -0
- /package/{dist/src → packages/engine/dist}/mapping/index.js +0 -0
- /package/{dist/src → packages/engine/dist}/mapping/validate-mapping.js +0 -0
- /package/{dist/src → packages/engine/dist}/markdown/render-item-markdown.js +0 -0
- /package/{dist/src → packages/engine/dist}/markdown/render-list-markdown.js +0 -0
- /package/{dist/src → packages/engine/dist}/migrations/backfill-catalog-model.js +0 -0
- /package/{dist/src → packages/engine/dist}/migrations/index.d.ts +0 -0
- /package/{dist/src → packages/engine/dist}/migrations/index.js +0 -0
- /package/{dist/src → packages/engine/dist}/migrations/migrate-native-catalog-layout.js +0 -0
- /package/{dist/src → packages/engine/dist}/migrations/migrate-native-item-scope.js +0 -0
- /package/{dist/src → packages/engine/dist}/migrations/renderer-metadata.js +0 -0
- /package/{dist/src → packages/engine/dist}/operator.d.ts +0 -0
- /package/{dist/src → packages/engine/dist}/operator.js +0 -0
- /package/{dist/src → packages/engine/dist}/validation/index.d.ts +0 -0
- /package/{dist/src → packages/engine/dist}/validation/index.js +0 -0
- /package/{dist/src → packages/engine/dist}/validation/payload-schema-registry.d.ts +0 -0
- /package/{dist/src → packages/engine/dist}/validation/payload-schema-registry.js +0 -0
- /package/{dist/src → packages/engine/dist}/validation/payload-schema.js +0 -0
- /package/{dist/src → packages/engine/dist}/validation/ui-spec-schema.d.ts +0 -0
- /package/{dist/src → packages/engine/dist}/validation/ui-spec-schema.js +0 -0
- /package/{dist/src → packages/engine/dist}/validation/ui-spec-validate.d.ts +0 -0
- /package/{dist/src → packages/engine/dist}/validation/ui-spec-validate.js +0 -0
- /package/{presets → packages/engine/presets}/native-map-v1.json +0 -0
- /package/{presets → packages/engine/presets}/registry.json +0 -0
- /package/{schemas → packages/engine/schemas}/native-map-item/v1.json +0 -0
- /package/{schemas → packages/engine/schemas}/registry.json +0 -0
|
@@ -0,0 +1,1508 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import "dotenv/config";
|
|
3
|
+
import { Command } from "commander";
|
|
4
|
+
import { writeFile } from "node:fs/promises";
|
|
5
|
+
import { createRequire } from "node:module";
|
|
6
|
+
import { readFileSync } from "node:fs";
|
|
7
|
+
import { resolve as resolvePath } from "node:path";
|
|
8
|
+
import { CATALOX_GCS_BACKUP_MANIFEST_FILENAME, createCataloxHelpersGcsClient } from "../catalox/backup-data.js";
|
|
9
|
+
import { cataloxGcsBackupManifestToFirestoreExportManifest } from "../catalox/catalox-gcs-backup-export-manifest.js";
|
|
10
|
+
import { normalizeGcsPrefix, ndjsonObjectPath } from "../catalox/firestore-gcs-transfer.js";
|
|
11
|
+
import { createCataloxFromEnv, testFirestoreConnectionFromEnv } from "../firebase/bootstrap.js";
|
|
12
|
+
import { applyCataloxSeedPreset, loadCataloxSeedManifestFromPath } from "../catalox/seed-preset.js";
|
|
13
|
+
import { resolveCataloxSeedPresetPath } from "../catalox/seed-preset-resolve.js";
|
|
14
|
+
import { normalizeNativePatchBody, normalizeNativeUpsertBody, parseJsonArrayOrNdjson, parseJsonObject, readUtf8FromFileOrStdin, } from "./item-json.js";
|
|
15
|
+
import { buildCatalogListMarkdownMap, renderCatalogListMarkdown } from "../markdown/render-list-markdown.js";
|
|
16
|
+
import { buildCatalogItemMarkdownMap, renderCatalogItemMarkdown } from "../markdown/render-item-markdown.js";
|
|
17
|
+
import { renderCatalogRelationsMermaid } from "../diagrams/render-catalog-diagram.js";
|
|
18
|
+
import { renderItemRelationsMermaid } from "../diagrams/render-item-diagram.js";
|
|
19
|
+
function createCatalox() {
|
|
20
|
+
return createCataloxFromEnv().catalox;
|
|
21
|
+
}
|
|
22
|
+
/** CLI `--store` wins over `CATALOX_STORE_ID` when both are set. */
|
|
23
|
+
function resolvedStoreId(cliStore) {
|
|
24
|
+
const id = (cliStore ?? process.env.CATALOX_STORE_ID ?? "").trim();
|
|
25
|
+
return id || undefined;
|
|
26
|
+
}
|
|
27
|
+
function parseScopeJson(raw) {
|
|
28
|
+
const t = raw?.trim();
|
|
29
|
+
if (!t)
|
|
30
|
+
return undefined;
|
|
31
|
+
const parsed = JSON.parse(t);
|
|
32
|
+
if (parsed == null || typeof parsed !== "object" || Array.isArray(parsed)) {
|
|
33
|
+
throw new Error("scope JSON must be an object of string arrays");
|
|
34
|
+
}
|
|
35
|
+
const out = {};
|
|
36
|
+
for (const [k, v] of Object.entries(parsed)) {
|
|
37
|
+
if (!Array.isArray(v))
|
|
38
|
+
throw new Error(`scope.${k} must be a string array`);
|
|
39
|
+
out[k] = v.filter((x) => typeof x === "string" && x.trim() !== "");
|
|
40
|
+
}
|
|
41
|
+
return out;
|
|
42
|
+
}
|
|
43
|
+
function baseContext(opts) {
|
|
44
|
+
const appId = (opts.app ?? process.env.CATALOX_APP_ID ?? "").trim();
|
|
45
|
+
if (!appId)
|
|
46
|
+
throw new Error("Missing --app or CATALOX_APP_ID");
|
|
47
|
+
const userId = (process.env.CATALOX_USER_ID ?? "").trim() || undefined;
|
|
48
|
+
const storeId = resolvedStoreId(opts.store);
|
|
49
|
+
const scope = parseScopeJson(opts.scopeJson) ??
|
|
50
|
+
parseScopeJson(process.env.CATALOX_SCOPE_JSON) ??
|
|
51
|
+
undefined;
|
|
52
|
+
return {
|
|
53
|
+
appId,
|
|
54
|
+
...(storeId ? { storeId } : {}),
|
|
55
|
+
...(opts.god ? { superAdmin: true } : {}),
|
|
56
|
+
...(opts.unrestricted ? { unrestrictedScope: true } : {}),
|
|
57
|
+
...(scope ? { scope } : {}),
|
|
58
|
+
...(userId ? { userId, actor: { type: "user", id: userId } } : {}),
|
|
59
|
+
};
|
|
60
|
+
}
|
|
61
|
+
async function writeOrStdout(text, outPath) {
|
|
62
|
+
if (outPath) {
|
|
63
|
+
await writeFile(outPath, text, "utf8");
|
|
64
|
+
}
|
|
65
|
+
else {
|
|
66
|
+
process.stdout.write(text);
|
|
67
|
+
if (!text.endsWith("\n"))
|
|
68
|
+
process.stdout.write("\n");
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
const require = createRequire(import.meta.url);
|
|
72
|
+
const pkg = (() => {
|
|
73
|
+
try {
|
|
74
|
+
const p = resolvePath(process.cwd(), "package.json");
|
|
75
|
+
return JSON.parse(readFileSync(p, "utf8"));
|
|
76
|
+
}
|
|
77
|
+
catch {
|
|
78
|
+
return { version: "0.0.0" };
|
|
79
|
+
}
|
|
80
|
+
})();
|
|
81
|
+
const program = new Command();
|
|
82
|
+
program
|
|
83
|
+
.name("catalox")
|
|
84
|
+
.description("Catalox CLI")
|
|
85
|
+
.version(pkg.version ?? "0.0.0");
|
|
86
|
+
program
|
|
87
|
+
.command("report")
|
|
88
|
+
.description("Generate a smart inventory report (Markdown)")
|
|
89
|
+
.requiredOption("--app <appId>", "AppId context")
|
|
90
|
+
.option("--store <storeId>", "StoreId context (overrides CATALOX_STORE_ID)")
|
|
91
|
+
.option("--catalog <catalogId...>", "Limit to specific catalogIds")
|
|
92
|
+
.option("--top <n>", "Top examples per catalog", (v) => Number(v), 10)
|
|
93
|
+
.option("--diff", "Include snapshot run diff section", false)
|
|
94
|
+
.option("--out <path>", "Write markdown to file instead of stdout")
|
|
95
|
+
.option("--god", "God mode (bypass binding checks)", false)
|
|
96
|
+
.action(async (opts) => {
|
|
97
|
+
const catalox = createCatalox();
|
|
98
|
+
const ctx = baseContext(opts);
|
|
99
|
+
const storeId = resolvedStoreId(opts.store);
|
|
100
|
+
const { markdown } = await catalox.generateInventoryReport(ctx, {
|
|
101
|
+
...(storeId ? { storeId } : {}),
|
|
102
|
+
...(opts.catalog?.length ? { catalogIds: opts.catalog } : {}),
|
|
103
|
+
top: opts.top,
|
|
104
|
+
includeDiff: Boolean(opts.diff),
|
|
105
|
+
});
|
|
106
|
+
await writeOrStdout(markdown, opts.out);
|
|
107
|
+
});
|
|
108
|
+
const snapshotCmd = program.command("snapshot").description("Versioned catalog snapshots for backup and drift (catalox-export/v1)");
|
|
109
|
+
snapshotCmd
|
|
110
|
+
.command("export")
|
|
111
|
+
.description("Export native (default) catalogs with full item pagination; deterministic catalog/item ordering (read-only bindings)")
|
|
112
|
+
.requiredOption("--app <appId>", "AppId context")
|
|
113
|
+
.option("--store <storeId>", "StoreId context (overrides CATALOX_STORE_ID)")
|
|
114
|
+
.option("--catalog <catalogId...>", "Limit to specific catalogIds")
|
|
115
|
+
.option("--catalog-type <type...>", "Filter by catalogType")
|
|
116
|
+
.option("--include-mapped", "Include mapped catalogs (default: native only)", false)
|
|
117
|
+
.option("--include-disabled", "Include disabled catalogs", false)
|
|
118
|
+
.option("--include-hidden", "Include hidden catalogs (or use --god)", false)
|
|
119
|
+
.option("--no-item-data", "Metadata-only items (omit item.data)", false)
|
|
120
|
+
.option("--page-size <n>", "Items per list request", (v) => Number(v), 200)
|
|
121
|
+
.option("--max-items-per-catalog <n>", "Safety cap per catalog (omit for no cap)")
|
|
122
|
+
.option("--no-all-native-scopes", "Do not super-list all native scope layers (even with --god)", false)
|
|
123
|
+
.option("--pretty", "Pretty-print JSON", false)
|
|
124
|
+
.option("--out <path>", "Write JSON to file instead of stdout")
|
|
125
|
+
.option("--god", "God mode: super-admin context + all native physical rows", false)
|
|
126
|
+
.action(async (opts) => {
|
|
127
|
+
const catalox = createCatalox();
|
|
128
|
+
const ctx = baseContext(opts);
|
|
129
|
+
const storeId = resolvedStoreId(opts.store);
|
|
130
|
+
const sourceModes = opts.includeMapped ? ["native", "mapped"] : ["native"];
|
|
131
|
+
const maxRaw = opts.maxItemsPerCatalog;
|
|
132
|
+
const maxItemsPerCatalog = maxRaw != null && String(maxRaw).trim() !== "" ? Number(maxRaw) : undefined;
|
|
133
|
+
const json = await catalox.exportCatalogSnapshotToJson(ctx, {
|
|
134
|
+
...(storeId ? { storeId } : {}),
|
|
135
|
+
...(opts.catalog?.length ? { catalogIds: opts.catalog } : {}),
|
|
136
|
+
...(opts.catalogType?.length ? { catalogTypes: opts.catalogType } : {}),
|
|
137
|
+
sourceModes: [...sourceModes],
|
|
138
|
+
includeDisabledCatalogs: Boolean(opts.includeDisabled),
|
|
139
|
+
includeHiddenCatalogs: Boolean(opts.includeHidden) || Boolean(opts.god),
|
|
140
|
+
includeItemData: Boolean(opts.itemData),
|
|
141
|
+
pageSize: opts.pageSize,
|
|
142
|
+
...(maxItemsPerCatalog != null && Number.isFinite(maxItemsPerCatalog)
|
|
143
|
+
? { maxItemsPerCatalog }
|
|
144
|
+
: {}),
|
|
145
|
+
includeAllNativeScopes: !opts.noAllNativeScopes,
|
|
146
|
+
}, Boolean(opts.pretty));
|
|
147
|
+
await writeOrStdout(json, opts.out);
|
|
148
|
+
});
|
|
149
|
+
program
|
|
150
|
+
.command("export")
|
|
151
|
+
.description("Export inventory to JSON (legacy inventory shape; use snapshot export for backup/drift)")
|
|
152
|
+
.requiredOption("--app <appId>", "AppId context")
|
|
153
|
+
.option("--store <storeId>", "StoreId context (overrides CATALOX_STORE_ID)")
|
|
154
|
+
.option("--catalog <catalogId...>", "Limit to specific catalogIds")
|
|
155
|
+
.option("--include-items", "Include items in export", false)
|
|
156
|
+
.option("--no-item-data", "Exclude `items[].data` (metadata-only items)")
|
|
157
|
+
.option("--limit-per-catalog <n>", "Item limit per catalog", (v) => Number(v), 50)
|
|
158
|
+
.option("--pretty", "Pretty-print JSON", false)
|
|
159
|
+
.option("--out <path>", "Write JSON to file instead of stdout")
|
|
160
|
+
.option("--god", "God mode (bypass binding checks)", false)
|
|
161
|
+
.action(async (opts) => {
|
|
162
|
+
const catalox = createCatalox();
|
|
163
|
+
const ctx = baseContext(opts);
|
|
164
|
+
const storeId = resolvedStoreId(opts.store);
|
|
165
|
+
const json = await catalox.exportInventoryToJson(ctx, {
|
|
166
|
+
...(storeId ? { storeId } : {}),
|
|
167
|
+
...(opts.catalog?.length ? { catalogIds: opts.catalog } : {}),
|
|
168
|
+
includeItems: Boolean(opts.includeItems),
|
|
169
|
+
includeItemData: Boolean(opts.itemData),
|
|
170
|
+
limitPerCatalog: opts.limitPerCatalog,
|
|
171
|
+
}, Boolean(opts.pretty));
|
|
172
|
+
await writeOrStdout(json, opts.out);
|
|
173
|
+
});
|
|
174
|
+
const renderCmd = program.command("render").description("Render helpers (Markdown/diagrams)");
|
|
175
|
+
renderCmd
|
|
176
|
+
.command("list-md")
|
|
177
|
+
.description("Render a catalog list as Markdown (using CatalogListRenderMap)")
|
|
178
|
+
.requiredOption("--app <appId>", "AppId context")
|
|
179
|
+
.requiredOption("--catalog <catalogId>", "CatalogId")
|
|
180
|
+
.option("--limit <n>", "Max items to include", (v) => Number(v), 50)
|
|
181
|
+
.option("--out <path>", "Write markdown to file instead of stdout")
|
|
182
|
+
.option("--god", "God mode (bypass binding checks)", false)
|
|
183
|
+
.action(async (opts) => {
|
|
184
|
+
const catalox = createCatalox();
|
|
185
|
+
const ctx = baseContext(opts);
|
|
186
|
+
const catalogId = String(opts.catalog);
|
|
187
|
+
const map = await catalox.buildCatalogListRenderMap(ctx, catalogId, {
|
|
188
|
+
limit: opts.limit,
|
|
189
|
+
resolveSources: true,
|
|
190
|
+
displayContext: "grid",
|
|
191
|
+
});
|
|
192
|
+
const mdMap = buildCatalogListMarkdownMap(map, { maxRows: opts.limit });
|
|
193
|
+
const markdown = renderCatalogListMarkdown(mdMap);
|
|
194
|
+
await writeOrStdout(markdown, opts.out);
|
|
195
|
+
});
|
|
196
|
+
renderCmd
|
|
197
|
+
.command("item-md")
|
|
198
|
+
.description("Render a single catalog item as Markdown (using CatalogItemRenderMap)")
|
|
199
|
+
.requiredOption("--app <appId>", "AppId context")
|
|
200
|
+
.requiredOption("--catalog <catalogId>", "CatalogId")
|
|
201
|
+
.requiredOption("--item <itemId>", "ItemId")
|
|
202
|
+
.option("--out <path>", "Write markdown to file instead of stdout")
|
|
203
|
+
.option("--refs", "Include references section", false)
|
|
204
|
+
.option("--god", "God mode (bypass binding checks)", false)
|
|
205
|
+
.action(async (opts) => {
|
|
206
|
+
const catalox = createCatalox();
|
|
207
|
+
const ctx = baseContext(opts);
|
|
208
|
+
const catalogId = String(opts.catalog);
|
|
209
|
+
const itemId = String(opts.item);
|
|
210
|
+
const map = await catalox.buildCatalogItemRenderMap(ctx, catalogId, itemId, {
|
|
211
|
+
includeReferences: Boolean(opts.refs),
|
|
212
|
+
resolveSources: true,
|
|
213
|
+
displayContext: "form",
|
|
214
|
+
});
|
|
215
|
+
const mdMap = buildCatalogItemMarkdownMap(map, { includeReferences: Boolean(opts.refs) });
|
|
216
|
+
const markdown = renderCatalogItemMarkdown(mdMap);
|
|
217
|
+
await writeOrStdout(markdown, opts.out);
|
|
218
|
+
});
|
|
219
|
+
renderCmd
|
|
220
|
+
.command("catalog-diagram")
|
|
221
|
+
.description("Render a catalog relations diagram as Mermaid (flowchart)")
|
|
222
|
+
.requiredOption("--app <appId>", "AppId context")
|
|
223
|
+
.requiredOption("--catalog <catalogId>", "CatalogId (used as root node)")
|
|
224
|
+
.option("--out <path>", "Write mermaid to file instead of stdout")
|
|
225
|
+
.option("--god", "God mode (bypass binding checks)", false)
|
|
226
|
+
.action(async (opts) => {
|
|
227
|
+
const catalox = createCatalox();
|
|
228
|
+
const ctx = baseContext(opts);
|
|
229
|
+
const rootCatalogId = String(opts.catalog);
|
|
230
|
+
// Minimal map: only root catalog node. Relations are consumer-owned today.
|
|
231
|
+
const descriptor = await catalox.getCatalogDescriptor(ctx, rootCatalogId);
|
|
232
|
+
const map = {
|
|
233
|
+
title: `Catalog relations: ${descriptor?.label ?? rootCatalogId}`,
|
|
234
|
+
catalogs: [{ id: rootCatalogId, label: descriptor?.label ?? rootCatalogId }],
|
|
235
|
+
relations: [],
|
|
236
|
+
};
|
|
237
|
+
const mermaid = renderCatalogRelationsMermaid(map);
|
|
238
|
+
await writeOrStdout(mermaid, opts.out);
|
|
239
|
+
});
|
|
240
|
+
renderCmd
|
|
241
|
+
.command("item-diagram")
|
|
242
|
+
.description("Render an item relations diagram as Mermaid (flowchart)")
|
|
243
|
+
.requiredOption("--app <appId>", "AppId context")
|
|
244
|
+
.requiredOption("--catalog <catalogId>", "CatalogId")
|
|
245
|
+
.requiredOption("--item <itemId>", "ItemId")
|
|
246
|
+
.option("--out <path>", "Write mermaid to file instead of stdout")
|
|
247
|
+
.option("--god", "God mode (bypass binding checks)", false)
|
|
248
|
+
.action(async (opts) => {
|
|
249
|
+
const catalox = createCatalox();
|
|
250
|
+
const ctx = baseContext(opts);
|
|
251
|
+
const catalogId = String(opts.catalog);
|
|
252
|
+
const itemId = String(opts.item);
|
|
253
|
+
const got = await catalox.getCatalogItem(ctx, catalogId, itemId);
|
|
254
|
+
if (got.outcome === "mapping_blocked") {
|
|
255
|
+
throw new Error(`Mapping blocked for catalog ${catalogId}: ${JSON.stringify(got.issues)}`);
|
|
256
|
+
}
|
|
257
|
+
if (got.outcome === "not_found")
|
|
258
|
+
throw new Error(`Item not found: ${catalogId}/${itemId}`);
|
|
259
|
+
const item = got.item;
|
|
260
|
+
const refs = await catalox.getCatalogItemReferences(ctx, catalogId, itemId);
|
|
261
|
+
const nodes = [
|
|
262
|
+
{ id: `${catalogId}:${itemId}`, label: item.title ?? `${catalogId}:${itemId}` },
|
|
263
|
+
...refs.map((r) => ({
|
|
264
|
+
id: `${String(r.toCatalogId)}:${String(r.toItemId)}`,
|
|
265
|
+
label: `${String(r.toCatalogId)}:${String(r.toItemId)}`,
|
|
266
|
+
})),
|
|
267
|
+
];
|
|
268
|
+
const edges = refs.map((r) => ({
|
|
269
|
+
from: `${catalogId}:${itemId}`,
|
|
270
|
+
to: `${String(r.toCatalogId)}:${String(r.toItemId)}`,
|
|
271
|
+
label: String(r.relationType),
|
|
272
|
+
}));
|
|
273
|
+
const map = {
|
|
274
|
+
title: `Item relations: ${catalogId}:${itemId}`,
|
|
275
|
+
items: nodes,
|
|
276
|
+
relations: edges,
|
|
277
|
+
};
|
|
278
|
+
const mermaid = renderItemRelationsMermaid(map);
|
|
279
|
+
await writeOrStdout(mermaid, opts.out);
|
|
280
|
+
});
|
|
281
|
+
const storeCmd = program.command("store").description("Manage storeId bindings");
|
|
282
|
+
storeCmd
|
|
283
|
+
.command("bind-app")
|
|
284
|
+
.requiredOption("--store <storeId>", "StoreId")
|
|
285
|
+
.requiredOption("--app <appId>", "AppId")
|
|
286
|
+
.option("--god", "God mode (required to bind other apps)", false)
|
|
287
|
+
.action(async (opts) => {
|
|
288
|
+
const catalox = createCatalox();
|
|
289
|
+
const ctx = baseContext({ app: opts.app, store: opts.store, god: opts.god });
|
|
290
|
+
const rec = await catalox.bindAppToStore(ctx, { storeId: opts.store, appId: opts.app });
|
|
291
|
+
await writeOrStdout(JSON.stringify(rec, null, 2));
|
|
292
|
+
});
|
|
293
|
+
storeCmd
|
|
294
|
+
.command("unbind-app")
|
|
295
|
+
.requiredOption("--store <storeId>", "StoreId")
|
|
296
|
+
.requiredOption("--app <appId>", "AppId")
|
|
297
|
+
.option("--god", "God mode (required to unbind other apps)", false)
|
|
298
|
+
.action(async (opts) => {
|
|
299
|
+
const catalox = createCatalox();
|
|
300
|
+
const ctx = baseContext({ app: opts.app, store: opts.store, god: opts.god });
|
|
301
|
+
await catalox.unbindAppFromStore(ctx, opts.store, opts.app);
|
|
302
|
+
});
|
|
303
|
+
storeCmd
|
|
304
|
+
.command("list-apps")
|
|
305
|
+
.requiredOption("--store <storeId>", "StoreId")
|
|
306
|
+
.requiredOption("--app <appId>", "AppId context for authz")
|
|
307
|
+
.option("--god", "God mode (list all apps)", false)
|
|
308
|
+
.action(async (opts) => {
|
|
309
|
+
const catalox = createCatalox();
|
|
310
|
+
const ctx = baseContext({ app: opts.app, store: opts.store, god: opts.god });
|
|
311
|
+
const rows = await catalox.listAppsForStore(ctx, opts.store);
|
|
312
|
+
await writeOrStdout(JSON.stringify(rows, null, 2));
|
|
313
|
+
});
|
|
314
|
+
const seedCmd = program.command("seed").description("Declarative catalog seed manifests (idempotent apply)");
|
|
315
|
+
seedCmd
|
|
316
|
+
.command("apply")
|
|
317
|
+
.description("Apply a JSON preset: catalogs, optional descriptors/bindings/items")
|
|
318
|
+
.requiredOption("--app <appId>", "AppId context (CataloxContext.appId)")
|
|
319
|
+
.option("--file <path>", "Path to preset JSON manifest")
|
|
320
|
+
.option("--preset <id>", "Logical preset: builtin:native-map-v1, registry alias (native-map@v1), npm package name, or path to .json")
|
|
321
|
+
.option("--god", "Super-admin context (required for descriptor section and bindings to other apps)", false)
|
|
322
|
+
.action(async (opts) => {
|
|
323
|
+
const fileRaw = opts.file != null ? String(opts.file).trim() : "";
|
|
324
|
+
const presetRaw = opts.preset != null ? String(opts.preset).trim() : "";
|
|
325
|
+
if ((fileRaw !== "") === (presetRaw !== "")) {
|
|
326
|
+
throw new Error("Specify exactly one of --file <path> or --preset <id>");
|
|
327
|
+
}
|
|
328
|
+
const catalox = createCatalox();
|
|
329
|
+
const ctx = baseContext({ app: opts.app, god: opts.god });
|
|
330
|
+
const res = presetRaw
|
|
331
|
+
? await applyCataloxSeedPreset(catalox, ctx, { preset: presetRaw })
|
|
332
|
+
: await applyCataloxSeedPreset(catalox, ctx, { presetPath: fileRaw });
|
|
333
|
+
await writeOrStdout(JSON.stringify(res, null, 2));
|
|
334
|
+
});
|
|
335
|
+
seedCmd
|
|
336
|
+
.command("validate")
|
|
337
|
+
.description("Parse and AJV-validate a seed manifest (--file or --preset); no Firestore writes")
|
|
338
|
+
.option("--file <path>", "Path to preset JSON manifest")
|
|
339
|
+
.option("--preset <id>", "Logical preset: builtin:native-map-v1, registry alias, npm package name, or path to .json")
|
|
340
|
+
.action(async (opts) => {
|
|
341
|
+
const fileRaw = opts.file != null ? String(opts.file).trim() : "";
|
|
342
|
+
const presetRaw = opts.preset != null ? String(opts.preset).trim() : "";
|
|
343
|
+
if ((fileRaw !== "") === (presetRaw !== "")) {
|
|
344
|
+
throw new Error("Specify exactly one of --file <path> or --preset <id>");
|
|
345
|
+
}
|
|
346
|
+
const manifest = presetRaw
|
|
347
|
+
? await loadCataloxSeedManifestFromPath(resolveCataloxSeedPresetPath(presetRaw))
|
|
348
|
+
: await loadCataloxSeedManifestFromPath(fileRaw);
|
|
349
|
+
const { validateCataloxSeedManifestItemPayloads } = await import("../catalox/seed-preset.js");
|
|
350
|
+
const itemPayloadIssues = validateCataloxSeedManifestItemPayloads(manifest);
|
|
351
|
+
const ok = itemPayloadIssues.length === 0;
|
|
352
|
+
await writeOrStdout(JSON.stringify({
|
|
353
|
+
ok,
|
|
354
|
+
presetVersion: manifest.presetVersion,
|
|
355
|
+
id: manifest.id ?? null,
|
|
356
|
+
name: manifest.name ?? null,
|
|
357
|
+
counts: {
|
|
358
|
+
catalogs: manifest.catalogs.length,
|
|
359
|
+
descriptors: manifest.descriptors?.length ?? 0,
|
|
360
|
+
bindings: manifest.bindings?.length ?? 0,
|
|
361
|
+
items: manifest.items?.length ?? 0,
|
|
362
|
+
},
|
|
363
|
+
...(itemPayloadIssues.length ? { itemPayloadIssues } : {}),
|
|
364
|
+
}, null, 2));
|
|
365
|
+
if (!ok)
|
|
366
|
+
process.exitCode = 1;
|
|
367
|
+
});
|
|
368
|
+
const itemsCmd = program.command("items").description("Catalog items: validate, list, CRUD, batch upsert, export (native + mapped read paths)");
|
|
369
|
+
itemsCmd
|
|
370
|
+
.command("validate")
|
|
371
|
+
.description("validateCatalog, validateCatalogItem (--item), or offline payload validate (--file; optional --catalog-type)")
|
|
372
|
+
.option("--app <appId>", "AppId context (required unless --file with --catalog-type only)")
|
|
373
|
+
.option("--store <storeId>", "StoreId context (overrides CATALOX_STORE_ID)")
|
|
374
|
+
.option("--catalog <catalogId>", "Catalog id")
|
|
375
|
+
.option("--item <itemId>", "When set, validateCatalogItem; otherwise validateCatalog")
|
|
376
|
+
.option("--file <path>", "Offline: validate item JSON from file (or stdin when omitted)")
|
|
377
|
+
.option("--catalog-type <type>", "Offline with --file: resolve schema by catalogType + registry")
|
|
378
|
+
.option("--schema-version <id>", "Offline: payload schema id (e.g. catalox.payload.generic-map/v1)")
|
|
379
|
+
.option("--out <path>", "Write JSON to file instead of stdout")
|
|
380
|
+
.option("--no-auto-create", "Fail validate when smart-property target codes are missing", false)
|
|
381
|
+
.option("--god", "God mode (bypass binding checks where applicable)", false)
|
|
382
|
+
.action(async (opts) => {
|
|
383
|
+
const fileRaw = opts.file != null ? String(opts.file).trim() : "";
|
|
384
|
+
const catalogTypeRaw = opts.catalogType != null ? String(opts.catalogType).trim() : "";
|
|
385
|
+
const schemaVersionRaw = opts.schemaVersion != null ? String(opts.schemaVersion).trim() : "";
|
|
386
|
+
if (fileRaw !== "" || (catalogTypeRaw !== "" && !opts.catalog)) {
|
|
387
|
+
const { catalogRecordFromCreateInput, validateNativeItemPayloadOrMissing, resolvePayloadSchema, validateNativeItemPayload } = await import("../validation/payload-schema.js");
|
|
388
|
+
const { createBundledPayloadSchemaRegistry } = await import("../validation/payload-schema-registry.js");
|
|
389
|
+
const registry = createBundledPayloadSchemaRegistry();
|
|
390
|
+
const rawText = await readUtf8FromFileOrStdin(fileRaw || undefined);
|
|
391
|
+
let parsed;
|
|
392
|
+
try {
|
|
393
|
+
parsed = JSON.parse(rawText);
|
|
394
|
+
}
|
|
395
|
+
catch (e) {
|
|
396
|
+
const msg = e instanceof Error ? e.message : String(e);
|
|
397
|
+
throw new Error(`Item JSON is not valid: ${msg}`);
|
|
398
|
+
}
|
|
399
|
+
const body = parsed != null && typeof parsed === "object" && !Array.isArray(parsed) && "data" in parsed
|
|
400
|
+
? parsed.data
|
|
401
|
+
: parsed;
|
|
402
|
+
let report;
|
|
403
|
+
if (opts.catalog != null && String(opts.catalog).trim() !== "") {
|
|
404
|
+
const catalox = createCatalox();
|
|
405
|
+
const appId = opts.app != null ? String(opts.app).trim() : String(process.env.CATALOX_APP_ID ?? "").trim();
|
|
406
|
+
if (!appId)
|
|
407
|
+
throw new Error("--app or CATALOX_APP_ID is required with --catalog and --file");
|
|
408
|
+
const ctx = baseContext({ app: appId, store: opts.store, god: opts.god });
|
|
409
|
+
const catalogId = String(opts.catalog).trim();
|
|
410
|
+
const catalog = await catalox.getCatalog(ctx, catalogId);
|
|
411
|
+
if (!catalog)
|
|
412
|
+
throw new Error(`Catalog not found: ${catalogId}`);
|
|
413
|
+
const resolved = resolvePayloadSchema({ catalog, registry });
|
|
414
|
+
report = resolved
|
|
415
|
+
? validateNativeItemPayload(body, resolved, registry)
|
|
416
|
+
: validateNativeItemPayloadOrMissing(body, { catalog, registry });
|
|
417
|
+
}
|
|
418
|
+
else if (catalogTypeRaw !== "") {
|
|
419
|
+
const catalog = catalogRecordFromCreateInput({
|
|
420
|
+
catalogId: "_offline_",
|
|
421
|
+
name: "_offline_",
|
|
422
|
+
catalogType: catalogTypeRaw,
|
|
423
|
+
...(schemaVersionRaw ? { schemaVersion: schemaVersionRaw } : {}),
|
|
424
|
+
sourceMode: "native",
|
|
425
|
+
native: { type: "native" },
|
|
426
|
+
});
|
|
427
|
+
report = validateNativeItemPayloadOrMissing(body, { catalog, registry });
|
|
428
|
+
}
|
|
429
|
+
else {
|
|
430
|
+
throw new Error("Offline validate requires --catalog-type or --catalog with --app");
|
|
431
|
+
}
|
|
432
|
+
await writeOrStdout(JSON.stringify({ scope: "payload", ...report }, null, 2), opts.out);
|
|
433
|
+
if (!report.isValid)
|
|
434
|
+
process.exitCode = 1;
|
|
435
|
+
return;
|
|
436
|
+
}
|
|
437
|
+
const appId = opts.app != null ? String(opts.app).trim() : String(process.env.CATALOX_APP_ID ?? "").trim();
|
|
438
|
+
if (!appId)
|
|
439
|
+
throw new Error("--app or CATALOX_APP_ID is required");
|
|
440
|
+
if (opts.catalog == null || String(opts.catalog).trim() === "") {
|
|
441
|
+
throw new Error("--catalog is required for live validate");
|
|
442
|
+
}
|
|
443
|
+
const catalox = createCatalox();
|
|
444
|
+
const ctx = baseContext({ app: appId, store: opts.store, god: opts.god });
|
|
445
|
+
const catalogId = String(opts.catalog);
|
|
446
|
+
if (opts.item != null && String(opts.item).trim() !== "") {
|
|
447
|
+
const report = await catalox.validateCatalogItem(ctx, catalogId, String(opts.item).trim(), opts.noAutoCreate ? { noAutoCreate: true } : undefined);
|
|
448
|
+
await writeOrStdout(JSON.stringify({ scope: "item", catalogId, itemId: String(opts.item).trim(), ...report }, null, 2), opts.out);
|
|
449
|
+
if (!report.isValid)
|
|
450
|
+
process.exitCode = 1;
|
|
451
|
+
return;
|
|
452
|
+
}
|
|
453
|
+
const report = await catalox.validateCatalog(ctx, catalogId);
|
|
454
|
+
await writeOrStdout(JSON.stringify({ scope: "catalog", catalogId, ...report }, null, 2), opts.out);
|
|
455
|
+
if (!report.isValid)
|
|
456
|
+
process.exitCode = 1;
|
|
457
|
+
});
|
|
458
|
+
itemsCmd
|
|
459
|
+
.command("get")
|
|
460
|
+
.description("getCatalogItem JSON (outcome: found | not_found | mapping_blocked)")
|
|
461
|
+
.requiredOption("--app <appId>", "AppId context")
|
|
462
|
+
.option("--store <storeId>", "StoreId context (overrides CATALOX_STORE_ID)")
|
|
463
|
+
.requiredOption("--catalog <catalogId>", "Catalog id")
|
|
464
|
+
.requiredOption("--item <itemId>", "Logical item id")
|
|
465
|
+
.option("--storage-doc-id <id>", "Native: target a specific physical storage doc id")
|
|
466
|
+
.option("--scope-json <json>", "Fetch scope narrowing (JSON object of string arrays)")
|
|
467
|
+
.option("--scoped-only", "Exclude generic items", false)
|
|
468
|
+
.option("--generic-only", "Return only generic items", false)
|
|
469
|
+
.option("--out <path>", "Write JSON to file instead of stdout")
|
|
470
|
+
.option("--god", "God mode", false)
|
|
471
|
+
.option("--scope-json-token <json>", "Token scope on context (defaults to CATALOX_SCOPE_JSON)")
|
|
472
|
+
.action(async (opts) => {
|
|
473
|
+
const catalox = createCatalox();
|
|
474
|
+
const fetchScope = parseScopeJson(opts.scopeJson != null ? String(opts.scopeJson) : undefined);
|
|
475
|
+
const ctx = baseContext({
|
|
476
|
+
app: opts.app,
|
|
477
|
+
store: opts.store,
|
|
478
|
+
god: opts.god,
|
|
479
|
+
...(opts.scopeJsonToken != null ? { scopeJson: String(opts.scopeJsonToken) } : {}),
|
|
480
|
+
});
|
|
481
|
+
const catalogId = String(opts.catalog);
|
|
482
|
+
const itemId = String(opts.item);
|
|
483
|
+
const storageDocId = opts.storageDocId != null && String(opts.storageDocId).trim() ? String(opts.storageDocId).trim() : undefined;
|
|
484
|
+
const got = await catalox.getCatalogItem(ctx, catalogId, itemId, {
|
|
485
|
+
...(storageDocId ? { storageDocId } : {}),
|
|
486
|
+
...(fetchScope || opts.scopedOnly || opts.genericOnly
|
|
487
|
+
? {
|
|
488
|
+
scope: {
|
|
489
|
+
...(fetchScope ? { scope: fetchScope } : {}),
|
|
490
|
+
...(opts.scopedOnly ? { scopedOnly: true } : {}),
|
|
491
|
+
...(opts.genericOnly ? { genericOnly: true } : {}),
|
|
492
|
+
},
|
|
493
|
+
}
|
|
494
|
+
: {}),
|
|
495
|
+
});
|
|
496
|
+
await writeOrStdout(JSON.stringify(got, null, 2), opts.out);
|
|
497
|
+
if (got.outcome !== "found")
|
|
498
|
+
process.exitCode = 1;
|
|
499
|
+
});
|
|
500
|
+
itemsCmd
|
|
501
|
+
.command("list")
|
|
502
|
+
.description("listCatalogItemsWithOutcome (explicit outcome for scripts)")
|
|
503
|
+
.requiredOption("--app <appId>", "AppId context")
|
|
504
|
+
.option("--store <storeId>", "StoreId context (overrides CATALOX_STORE_ID)")
|
|
505
|
+
.requiredOption("--catalog <catalogId>", "Catalog id")
|
|
506
|
+
.option("--limit <n>", "Page size", (v) => Number(v), 50)
|
|
507
|
+
.option("--offset <n>", "Offset (native)", (v) => Number(v), 0)
|
|
508
|
+
.option("--cursor <token>", "Mapped catalogs: pass nextCursor from a prior response")
|
|
509
|
+
.option("--filter-json <json>", "JSON object merged into list filter (compact empty strings ignored by server)")
|
|
510
|
+
.option("--scope-json <json>", "Fetch scope narrowing (JSON object of string arrays)")
|
|
511
|
+
.option("--scope-json-token <json>", "Token scope on context (defaults to CATALOX_SCOPE_JSON)")
|
|
512
|
+
.option("--scoped-only", "Exclude generic items", false)
|
|
513
|
+
.option("--generic-only", "Return only generic items", false)
|
|
514
|
+
.option("--no-generic", "Same as --scoped-only", false)
|
|
515
|
+
.option("--out <path>", "Write JSON to file instead of stdout")
|
|
516
|
+
.option("--god", "God mode", false)
|
|
517
|
+
.action(async (opts) => {
|
|
518
|
+
const catalox = createCatalox();
|
|
519
|
+
const fetchScope = parseScopeJson(opts.scopeJson != null ? String(opts.scopeJson) : undefined);
|
|
520
|
+
const ctx = baseContext({
|
|
521
|
+
app: opts.app,
|
|
522
|
+
store: opts.store,
|
|
523
|
+
god: opts.god,
|
|
524
|
+
...(opts.scopeJsonToken != null ? { scopeJson: String(opts.scopeJsonToken) } : {}),
|
|
525
|
+
});
|
|
526
|
+
const catalogId = String(opts.catalog);
|
|
527
|
+
let filter;
|
|
528
|
+
const fj = opts.filterJson != null ? String(opts.filterJson).trim() : "";
|
|
529
|
+
if (fj) {
|
|
530
|
+
const parsed = JSON.parse(fj);
|
|
531
|
+
if (parsed == null || typeof parsed !== "object" || Array.isArray(parsed)) {
|
|
532
|
+
throw new Error("--filter-json must be a JSON object");
|
|
533
|
+
}
|
|
534
|
+
filter = parsed;
|
|
535
|
+
}
|
|
536
|
+
const scopedOnly = Boolean(opts.scopedOnly || opts.noGeneric);
|
|
537
|
+
const res = await catalox.listCatalogItemsWithOutcome(ctx, catalogId, {
|
|
538
|
+
limit: opts.limit,
|
|
539
|
+
offset: opts.offset,
|
|
540
|
+
...(fetchScope || scopedOnly || opts.genericOnly
|
|
541
|
+
? {
|
|
542
|
+
scope: {
|
|
543
|
+
...(fetchScope ? { scope: fetchScope } : {}),
|
|
544
|
+
...(scopedOnly ? { scopedOnly: true } : {}),
|
|
545
|
+
...(opts.genericOnly ? { genericOnly: true } : {}),
|
|
546
|
+
},
|
|
547
|
+
}
|
|
548
|
+
: {}),
|
|
549
|
+
...(filter ? { filter } : {}),
|
|
550
|
+
...(opts.cursor != null && String(opts.cursor).trim()
|
|
551
|
+
? { cursor: String(opts.cursor).trim() }
|
|
552
|
+
: {}),
|
|
553
|
+
});
|
|
554
|
+
await writeOrStdout(JSON.stringify(res, null, 2), opts.out);
|
|
555
|
+
if (res.outcome !== "ok" && res.outcome !== "empty")
|
|
556
|
+
process.exitCode = 1;
|
|
557
|
+
});
|
|
558
|
+
itemsCmd
|
|
559
|
+
.command("upsert")
|
|
560
|
+
.description("upsertNativeCatalogItem: JSON body is item fields at top level, or { data, scope?, relations? }")
|
|
561
|
+
.requiredOption("--app <appId>", "AppId context")
|
|
562
|
+
.option("--store <storeId>", "StoreId context (overrides CATALOX_STORE_ID)")
|
|
563
|
+
.requiredOption("--catalog <catalogId>", "Native catalog id")
|
|
564
|
+
.option("--file <path>", "JSON file (otherwise read stdin)")
|
|
565
|
+
.option("--out <path>", "Write result JSON to file instead of stdout")
|
|
566
|
+
.option("--god", "God mode (non-global scope rows require super-admin)", false)
|
|
567
|
+
.action(async (opts) => {
|
|
568
|
+
const raw = await readUtf8FromFileOrStdin(opts.file != null ? String(opts.file).trim() : undefined);
|
|
569
|
+
const body = normalizeNativeUpsertBody(parseJsonObject(raw, "items upsert"));
|
|
570
|
+
const catalox = createCatalox();
|
|
571
|
+
const ctx = baseContext({ app: opts.app, store: opts.store, god: opts.god });
|
|
572
|
+
const item = await catalox.upsertNativeCatalogItem(ctx, String(opts.catalog), body);
|
|
573
|
+
await writeOrStdout(JSON.stringify(item, null, 2), opts.out);
|
|
574
|
+
});
|
|
575
|
+
itemsCmd
|
|
576
|
+
.command("patch")
|
|
577
|
+
.description("updateNativeCatalogItem: shallow-merge patch into existing item data (+ optional scope/relations)")
|
|
578
|
+
.requiredOption("--app <appId>", "AppId context")
|
|
579
|
+
.option("--store <storeId>", "StoreId context (overrides CATALOX_STORE_ID)")
|
|
580
|
+
.requiredOption("--catalog <catalogId>", "Native catalog id")
|
|
581
|
+
.requiredOption("--item <itemId>", "Logical item id")
|
|
582
|
+
.option("--file <path>", "JSON patch file (otherwise read stdin)")
|
|
583
|
+
.option("--storage-doc-id <id>", "Disambiguate physical row when multiple scopes share logical id")
|
|
584
|
+
.option("--out <path>", "Write result JSON to file instead of stdout")
|
|
585
|
+
.option("--god", "God mode", false)
|
|
586
|
+
.action(async (opts) => {
|
|
587
|
+
const raw = await readUtf8FromFileOrStdin(opts.file != null ? String(opts.file).trim() : undefined);
|
|
588
|
+
const patch = normalizeNativePatchBody(parseJsonObject(raw, "items patch"));
|
|
589
|
+
const catalox = createCatalox();
|
|
590
|
+
const ctx = baseContext({ app: opts.app, store: opts.store, god: opts.god });
|
|
591
|
+
const storageDocId = opts.storageDocId != null && String(opts.storageDocId).trim() ? String(opts.storageDocId).trim() : undefined;
|
|
592
|
+
const item = await catalox.updateNativeCatalogItem(ctx, String(opts.catalog), String(opts.item).trim(), patch, { ...(storageDocId ? { storageDocId } : {}) });
|
|
593
|
+
await writeOrStdout(JSON.stringify(item, null, 2), opts.out);
|
|
594
|
+
});
|
|
595
|
+
itemsCmd
|
|
596
|
+
.command("delete")
|
|
597
|
+
.description("deleteNativeCatalogItem (requires --confirm)")
|
|
598
|
+
.requiredOption("--app <appId>", "AppId context")
|
|
599
|
+
.option("--store <storeId>", "StoreId context (overrides CATALOX_STORE_ID)")
|
|
600
|
+
.requiredOption("--catalog <catalogId>", "Native catalog id")
|
|
601
|
+
.requiredOption("--item <itemId>", "Logical item id")
|
|
602
|
+
.option("--storage-doc-id <id>", "Target a specific physical storage doc id")
|
|
603
|
+
.option("--confirm", "Must pass --confirm to run", false)
|
|
604
|
+
.option("--god", "God mode", false)
|
|
605
|
+
.action(async (opts) => {
|
|
606
|
+
if (!opts.confirm) {
|
|
607
|
+
// eslint-disable-next-line no-console
|
|
608
|
+
console.error("Refusing to delete without --confirm");
|
|
609
|
+
process.exitCode = 1;
|
|
610
|
+
return;
|
|
611
|
+
}
|
|
612
|
+
const catalox = createCatalox();
|
|
613
|
+
const ctx = baseContext({ app: opts.app, store: opts.store, god: opts.god });
|
|
614
|
+
const storageDocId = opts.storageDocId != null && String(opts.storageDocId).trim() ? String(opts.storageDocId).trim() : undefined;
|
|
615
|
+
await catalox.deleteNativeCatalogItem(ctx, String(opts.catalog), String(opts.item).trim(), {
|
|
616
|
+
...(storageDocId ? { storageDocId } : {}),
|
|
617
|
+
});
|
|
618
|
+
await writeOrStdout(JSON.stringify({ ok: true, catalogId: String(opts.catalog), itemId: String(opts.item).trim() }, null, 2));
|
|
619
|
+
});
|
|
620
|
+
itemsCmd
|
|
621
|
+
.command("batch-upsert")
|
|
622
|
+
.description("batchUpsertNativeCatalogItems: JSON array or NDJSON lines (≤450 rows per Firestore batch internally). Item shape matches items upsert.")
|
|
623
|
+
.requiredOption("--app <appId>", "AppId context")
|
|
624
|
+
.option("--store <storeId>", "StoreId context (overrides CATALOX_STORE_ID)")
|
|
625
|
+
.requiredOption("--catalog <catalogId>", "Native catalog id")
|
|
626
|
+
.option("--file <path>", "JSON array or NDJSON file (otherwise read stdin)")
|
|
627
|
+
.option("--god", "God mode (non-global scope rows require super-admin)", false)
|
|
628
|
+
.action(async (opts) => {
|
|
629
|
+
const raw = await readUtf8FromFileOrStdin(opts.file != null ? String(opts.file).trim() : undefined);
|
|
630
|
+
const rows = parseJsonArrayOrNdjson(raw, "items batch-upsert");
|
|
631
|
+
const catalox = createCatalox();
|
|
632
|
+
const ctx = baseContext({ app: opts.app, store: opts.store, god: opts.god });
|
|
633
|
+
await catalox.batchUpsertNativeCatalogItems(ctx, String(opts.catalog), rows);
|
|
634
|
+
await writeOrStdout(JSON.stringify({ ok: true, count: rows.length, catalogId: String(opts.catalog) }, null, 2));
|
|
635
|
+
});
|
|
636
|
+
itemsCmd
|
|
637
|
+
.command("replace")
|
|
638
|
+
.description("replaceNativeCatalogItem: full-document native replace (no merge). Body is a NativeCatalogItemRecord JSON object.")
|
|
639
|
+
.requiredOption("--app <appId>", "AppId context")
|
|
640
|
+
.option("--store <storeId>", "StoreId context (overrides CATALOX_STORE_ID)")
|
|
641
|
+
.requiredOption("--catalog <catalogId>", "Native catalog id")
|
|
642
|
+
.option("--file <path>", "JSON file (otherwise read stdin)")
|
|
643
|
+
.option("--god", "God mode (non-global scope rows require super-admin)", false)
|
|
644
|
+
.action(async (opts) => {
|
|
645
|
+
const raw = await readUtf8FromFileOrStdin(opts.file != null ? String(opts.file).trim() : undefined);
|
|
646
|
+
const record = JSON.parse(raw);
|
|
647
|
+
const catalox = createCatalox();
|
|
648
|
+
const ctx = baseContext({ app: opts.app, store: opts.store, god: opts.god });
|
|
649
|
+
await catalox.replaceNativeCatalogItem(ctx, String(opts.catalog), record);
|
|
650
|
+
await writeOrStdout(JSON.stringify({ ok: true, catalogId: String(opts.catalog), itemId: record.itemId }, null, 2));
|
|
651
|
+
});
|
|
652
|
+
itemsCmd
|
|
653
|
+
.command("batch-replace")
|
|
654
|
+
.description("replaceNativeCatalogItems: JSON array or NDJSON lines of NativeCatalogItemRecord (≤450 rows per Firestore batch internally).")
|
|
655
|
+
.requiredOption("--app <appId>", "AppId context")
|
|
656
|
+
.option("--store <storeId>", "StoreId context (overrides CATALOX_STORE_ID)")
|
|
657
|
+
.requiredOption("--catalog <catalogId>", "Native catalog id")
|
|
658
|
+
.option("--file <path>", "JSON array or NDJSON file (otherwise read stdin)")
|
|
659
|
+
.option("--no-atomic", "Write rows one at a time instead of batched replace", false)
|
|
660
|
+
.option("--god", "God mode (non-global scope rows require super-admin)", false)
|
|
661
|
+
.action(async (opts) => {
|
|
662
|
+
const raw = await readUtf8FromFileOrStdin(opts.file != null ? String(opts.file).trim() : undefined);
|
|
663
|
+
const rows = parseJsonArrayOrNdjson(raw, "items batch-replace");
|
|
664
|
+
const catalox = createCatalox();
|
|
665
|
+
const ctx = baseContext({ app: opts.app, store: opts.store, god: opts.god });
|
|
666
|
+
await catalox.replaceNativeCatalogItems(ctx, String(opts.catalog), rows, {
|
|
667
|
+
atomic: !opts.noAtomic,
|
|
668
|
+
});
|
|
669
|
+
await writeOrStdout(JSON.stringify({ ok: true, count: rows.length, catalogId: String(opts.catalog) }, null, 2));
|
|
670
|
+
});
|
|
671
|
+
itemsCmd
|
|
672
|
+
.command("export")
|
|
673
|
+
.description("Export one catalog's items to { catalogId, items } JSON (paginates nextCursor when present)")
|
|
674
|
+
.requiredOption("--app <appId>", "AppId context")
|
|
675
|
+
.option("--store <storeId>", "StoreId context (overrides CATALOX_STORE_ID)")
|
|
676
|
+
.requiredOption("--catalog <catalogId>", "Catalog id")
|
|
677
|
+
.option("--page-size <n>", "Per request", (v) => Number(v), 200)
|
|
678
|
+
.option("--max-total <n>", "Stop after this many items (safety cap)", (v) => Number(v), 10000)
|
|
679
|
+
.option("--pretty", "Pretty-print JSON", false)
|
|
680
|
+
.option("--out <path>", "Write JSON to file instead of stdout")
|
|
681
|
+
.option("--god", "God mode", false)
|
|
682
|
+
.action(async (opts) => {
|
|
683
|
+
const catalox = createCatalox();
|
|
684
|
+
const ctx = baseContext({ app: opts.app, store: opts.store, god: opts.god });
|
|
685
|
+
const catalogId = String(opts.catalog);
|
|
686
|
+
const pageSize = Math.max(1, Math.min(500, Number(opts.pageSize) || 200));
|
|
687
|
+
const maxTotal = Math.max(1, Number(opts.maxTotal) || 10000);
|
|
688
|
+
const items = [];
|
|
689
|
+
let offset = 0;
|
|
690
|
+
let cursor;
|
|
691
|
+
const indent = opts.pretty ? 2 : undefined;
|
|
692
|
+
for (;;) {
|
|
693
|
+
const page = await catalox.listCatalogItems(ctx, catalogId, {
|
|
694
|
+
limit: pageSize,
|
|
695
|
+
...(cursor ? { cursor: cursor } : { offset }),
|
|
696
|
+
});
|
|
697
|
+
if (page.listOutcome === "mapping_blocked") {
|
|
698
|
+
await writeOrStdout(JSON.stringify({ catalogId, error: "mapping_blocked", issues: page.issues ?? [] }, null, indent), opts.out);
|
|
699
|
+
process.exitCode = 1;
|
|
700
|
+
return;
|
|
701
|
+
}
|
|
702
|
+
for (const it of page.items) {
|
|
703
|
+
items.push(it);
|
|
704
|
+
if (items.length >= maxTotal)
|
|
705
|
+
break;
|
|
706
|
+
}
|
|
707
|
+
if (items.length >= maxTotal)
|
|
708
|
+
break;
|
|
709
|
+
if (page.nextCursor) {
|
|
710
|
+
cursor = page.nextCursor;
|
|
711
|
+
offset = 0;
|
|
712
|
+
continue;
|
|
713
|
+
}
|
|
714
|
+
if (!page.items.length)
|
|
715
|
+
break;
|
|
716
|
+
if (page.items.length < pageSize)
|
|
717
|
+
break;
|
|
718
|
+
offset += page.items.length;
|
|
719
|
+
cursor = undefined;
|
|
720
|
+
}
|
|
721
|
+
const payload = {
|
|
722
|
+
catalogId,
|
|
723
|
+
exportedCount: items.length,
|
|
724
|
+
truncated: items.length >= maxTotal,
|
|
725
|
+
items,
|
|
726
|
+
};
|
|
727
|
+
await writeOrStdout(JSON.stringify(payload, null, indent), opts.out);
|
|
728
|
+
});
|
|
729
|
+
const itemsRelationCmd = itemsCmd.command("relation").description("Item↔item relations (catalogReferences)");
|
|
730
|
+
itemsRelationCmd
|
|
731
|
+
.command("upsert")
|
|
732
|
+
.description("Create or update one relation edge")
|
|
733
|
+
.requiredOption("--app <appId>", "AppId context")
|
|
734
|
+
.option("--store <storeId>", "StoreId context (overrides CATALOX_STORE_ID)")
|
|
735
|
+
.option("--file <path>", "JSON file (otherwise stdin): fromCatalogId, fromItemId, toCatalogId, toItemId, relationType, optional label/metadata")
|
|
736
|
+
.option("--god", "God mode", false)
|
|
737
|
+
.action(async (opts) => {
|
|
738
|
+
const raw = await readUtf8FromFileOrStdin(opts.file != null ? String(opts.file).trim() : undefined);
|
|
739
|
+
const input = parseJsonObject(raw, "items relation upsert");
|
|
740
|
+
const catalox = createCatalox();
|
|
741
|
+
const ctx = baseContext({ app: opts.app, store: opts.store, god: opts.god });
|
|
742
|
+
const res = await catalox.upsertCatalogItemRelation(ctx, input);
|
|
743
|
+
await writeOrStdout(JSON.stringify(res, null, 2));
|
|
744
|
+
});
|
|
745
|
+
itemsRelationCmd
|
|
746
|
+
.command("delete")
|
|
747
|
+
.description("Delete by referenceId or by endpoint tuple (fromCatalogId, fromItemId, toCatalogId, toItemId, relationType)")
|
|
748
|
+
.requiredOption("--app <appId>", "AppId context")
|
|
749
|
+
.option("--store <storeId>", "StoreId context (overrides CATALOX_STORE_ID)")
|
|
750
|
+
.option("--file <path>", "JSON file (otherwise stdin)")
|
|
751
|
+
.option("--god", "God mode", false)
|
|
752
|
+
.action(async (opts) => {
|
|
753
|
+
const raw = await readUtf8FromFileOrStdin(opts.file != null ? String(opts.file).trim() : undefined);
|
|
754
|
+
const input = parseJsonObject(raw, "items relation delete");
|
|
755
|
+
const catalox = createCatalox();
|
|
756
|
+
const ctx = baseContext({ app: opts.app, store: opts.store, god: opts.god });
|
|
757
|
+
await catalox.deleteCatalogItemRelation(ctx, input);
|
|
758
|
+
await writeOrStdout(JSON.stringify({ ok: true }, null, 2));
|
|
759
|
+
});
|
|
760
|
+
const firestoreCmd = program
|
|
761
|
+
.command("firestore")
|
|
762
|
+
.description("Firestore backup (GCS), restore-from-GCS, native layout migration, and connectivity probe");
|
|
763
|
+
firestoreCmd
|
|
764
|
+
.command("probe")
|
|
765
|
+
.description("Minimal Firestore read to verify credentials (disposable Admin app; same env as createCataloxFromEnv)")
|
|
766
|
+
.action(async () => {
|
|
767
|
+
const res = await testFirestoreConnectionFromEnv();
|
|
768
|
+
const body = res.ok
|
|
769
|
+
? { ok: true, credentialSource: res.credentialSource }
|
|
770
|
+
: {
|
|
771
|
+
ok: false,
|
|
772
|
+
...(res.credentialSource != null ? { credentialSource: res.credentialSource } : {}),
|
|
773
|
+
error: res.error instanceof Error ? res.error.message : String(res.error),
|
|
774
|
+
};
|
|
775
|
+
await writeOrStdout(JSON.stringify(body, null, 2));
|
|
776
|
+
if (!res.ok)
|
|
777
|
+
process.exitCode = 1;
|
|
778
|
+
});
|
|
779
|
+
firestoreCmd
|
|
780
|
+
.command("backup")
|
|
781
|
+
.description("Catalox backup to GCS only (NDJSON + catalox-backup-manifest.json)")
|
|
782
|
+
.requiredOption("--app <appId>", "AppId for Catalox context")
|
|
783
|
+
.option("--bucket <name>", "GCS bucket name (default: catalox)", "catalox")
|
|
784
|
+
.option("--gcs-prefix <path>", "Optional prefix before timestamp folder (default: catalox-firestore-backups/)", "")
|
|
785
|
+
.option("--label <text>", "Backup label stored on manifest")
|
|
786
|
+
.option("--snapshots", "Include catalogSnapshots data", false)
|
|
787
|
+
.option("--catalog <catalogId...>", "Restrict which native catalogs are copied")
|
|
788
|
+
.option("--god", "God mode", false)
|
|
789
|
+
.action(async (opts) => {
|
|
790
|
+
// Bucket defaults to "catalox" when omitted.
|
|
791
|
+
const catalox = createCatalox();
|
|
792
|
+
const ctx = baseContext({ app: opts.app, god: opts.god });
|
|
793
|
+
const gcsPrefixOpt = opts.gcsPrefix != null && String(opts.gcsPrefix).trim() ? String(opts.gcsPrefix).trim() : undefined;
|
|
794
|
+
const res = await catalox.backupData(ctx, {
|
|
795
|
+
mode: "gcs",
|
|
796
|
+
gcsBucket: String(opts.bucket ?? "catalox").trim(),
|
|
797
|
+
...(gcsPrefixOpt !== undefined ? { gcsPrefix: gcsPrefixOpt } : {}),
|
|
798
|
+
includeSnapshots: Boolean(opts.snapshots),
|
|
799
|
+
...(opts.catalog?.length ? { catalogIds: opts.catalog } : {}),
|
|
800
|
+
...(opts.label != null && String(opts.label) !== "" ? { backupLabel: String(opts.label) } : {}),
|
|
801
|
+
});
|
|
802
|
+
await writeOrStdout(JSON.stringify(res, null, 2));
|
|
803
|
+
if (!res.ok)
|
|
804
|
+
process.exitCode = 1;
|
|
805
|
+
});
|
|
806
|
+
firestoreCmd
|
|
807
|
+
.command("undo-restore-backup")
|
|
808
|
+
.description("Revert a prior restore-backup-from-gcs using backup-restoreSessions/{sessionId} and preRestore collections")
|
|
809
|
+
.requiredOption("--app <appId>", "AppId for Catalox context")
|
|
810
|
+
.requiredOption("--session <restoreSessionId>", "restoreSessionId returned by restore-backup-from-gcs")
|
|
811
|
+
.option("--god", "God mode", false)
|
|
812
|
+
.action(async (opts) => {
|
|
813
|
+
const catalox = createCatalox();
|
|
814
|
+
const ctx = baseContext({ app: opts.app, god: opts.god });
|
|
815
|
+
const res = await catalox.undoFirestoreRestore(ctx, {
|
|
816
|
+
restoreSessionId: String(opts.session),
|
|
817
|
+
});
|
|
818
|
+
await writeOrStdout(JSON.stringify(res, null, 2));
|
|
819
|
+
if (!res.ok)
|
|
820
|
+
process.exitCode = 1;
|
|
821
|
+
});
|
|
822
|
+
firestoreCmd
|
|
823
|
+
.command("restore-backup-from-gcs")
|
|
824
|
+
.description("Restore live Firestore from one backupData GCS run (NDJSON under --run-folder). Uses pre-restore sidecars so undo works.")
|
|
825
|
+
.requiredOption("--app <appId>", "AppId for Catalox context")
|
|
826
|
+
.option("--bucket <name>", "GCS bucket name (default: catalox)", "catalox")
|
|
827
|
+
.requiredOption("--run-folder <path>", "Run folder within bucket (e.g. catalox-firestore-backups/2026_04_18T12_00_00Z)")
|
|
828
|
+
.option("--snapshots", "Also restore catalogSnapshots NDJSON from the run", false)
|
|
829
|
+
.option("--catalog <catalogId...>", "Restrict which native catalogs are restored")
|
|
830
|
+
.option("--god", "God mode", false)
|
|
831
|
+
.action(async (opts) => {
|
|
832
|
+
const catalox = createCatalox();
|
|
833
|
+
const ctx = baseContext({ app: opts.app, god: opts.god });
|
|
834
|
+
const res = await catalox.restoreFirestoreBackupFromGcs(ctx, {
|
|
835
|
+
gcsBucket: String(opts.bucket ?? "catalox").trim(),
|
|
836
|
+
gcsRunFolder: String(opts.runFolder).trim(),
|
|
837
|
+
includeSnapshots: Boolean(opts.snapshots),
|
|
838
|
+
...(opts.catalog?.length ? { catalogIds: opts.catalog } : {}),
|
|
839
|
+
});
|
|
840
|
+
await writeOrStdout(JSON.stringify(res, null, 2));
|
|
841
|
+
if (!res.ok)
|
|
842
|
+
process.exitCode = 1;
|
|
843
|
+
});
|
|
844
|
+
firestoreCmd
|
|
845
|
+
.command("prune-gcs-backups")
|
|
846
|
+
.description("Delete oldest GCS Catalox backup run folders (children of --gcs-prefix) until --keep-last remain (lexicographic sort on folder names)")
|
|
847
|
+
.option("--bucket <name>", "GCS bucket name (default: catalox)", "catalox")
|
|
848
|
+
.option("--gcs-prefix <path>", "Base prefix containing timestamp folders (default: catalox-firestore-backups/)", "")
|
|
849
|
+
.requiredOption("--keep-last <n>", "Number of newest run folders to keep", (v) => parseInt(String(v), 10))
|
|
850
|
+
.action(async (opts) => {
|
|
851
|
+
const catalox = createCatalox();
|
|
852
|
+
const ctx = baseContext({ app: "cli", god: true });
|
|
853
|
+
const keepRaw = opts.keepLast;
|
|
854
|
+
const keepLast = typeof keepRaw === "number" && Number.isFinite(keepRaw) ? keepRaw : parseInt(String(keepRaw), 10);
|
|
855
|
+
const res = await catalox.pruneGcsBackupRuns(ctx, {
|
|
856
|
+
bucket: String(opts.bucket ?? "catalox").trim(),
|
|
857
|
+
...(opts.gcsPrefix != null && String(opts.gcsPrefix).trim() !== ""
|
|
858
|
+
? { gcsBasePrefix: String(opts.gcsPrefix).trim() }
|
|
859
|
+
: {}),
|
|
860
|
+
keepLast,
|
|
861
|
+
});
|
|
862
|
+
await writeOrStdout(JSON.stringify(res, null, 2));
|
|
863
|
+
if (!res.ok)
|
|
864
|
+
process.exitCode = 1;
|
|
865
|
+
});
|
|
866
|
+
firestoreCmd
|
|
867
|
+
.command("delete-gcs-backup-run")
|
|
868
|
+
.description("Delete all objects under one GCS backup run folder (e.g. after a failed partial backup)")
|
|
869
|
+
.option("--bucket <name>", "GCS bucket name (default: catalox)", "catalox")
|
|
870
|
+
.requiredOption("--run-folder <path>", "Run folder prefix within the bucket")
|
|
871
|
+
.action(async (opts) => {
|
|
872
|
+
const catalox = createCatalox();
|
|
873
|
+
const ctx = baseContext({ app: "cli", god: true });
|
|
874
|
+
const res = await catalox.deleteCataloxGcsBackupRun(ctx, {
|
|
875
|
+
gcsBucket: String(opts.bucket ?? "catalox").trim(),
|
|
876
|
+
gcsRunFolder: String(opts.runFolder).trim(),
|
|
877
|
+
});
|
|
878
|
+
await writeOrStdout(JSON.stringify(res, null, 2));
|
|
879
|
+
if (!res.ok)
|
|
880
|
+
process.exitCode = 1;
|
|
881
|
+
});
|
|
882
|
+
firestoreCmd
|
|
883
|
+
.command("gcs-backup-to-export-manifest")
|
|
884
|
+
.description("Read catalox-backup-manifest.json from a GCS run and print catalox-firestore-export-manifest.json JSON (for import-gcs --restore-all)")
|
|
885
|
+
.option("--bucket <name>", "GCS bucket name (default: catalox)", "catalox")
|
|
886
|
+
.requiredOption("--run-folder <path>", "Run folder within bucket")
|
|
887
|
+
.action(async (opts) => {
|
|
888
|
+
try {
|
|
889
|
+
const bucket = String(opts.bucket ?? "catalox").trim();
|
|
890
|
+
const runFolder = String(opts.runFolder).trim().replace(/^\/+/, "").replace(/\/+$/, "");
|
|
891
|
+
const gcs = createCataloxHelpersGcsClient(bucket, runFolder);
|
|
892
|
+
const buf = await gcs.readObjectBuffer(CATALOX_GCS_BACKUP_MANIFEST_FILENAME);
|
|
893
|
+
const manifest = JSON.parse(buf.toString("utf8"));
|
|
894
|
+
const exportManifest = cataloxGcsBackupManifestToFirestoreExportManifest(manifest, runFolder);
|
|
895
|
+
await writeOrStdout(JSON.stringify(exportManifest, null, 2));
|
|
896
|
+
}
|
|
897
|
+
catch (e) {
|
|
898
|
+
// eslint-disable-next-line no-console
|
|
899
|
+
console.error(e instanceof Error ? e.message : String(e));
|
|
900
|
+
process.exitCode = 1;
|
|
901
|
+
}
|
|
902
|
+
});
|
|
903
|
+
firestoreCmd
|
|
904
|
+
.command("report-native-layout")
|
|
905
|
+
.description("JSON report: legacy vs flat doc counts per native catalog (when you still see catalogData/{id}/items in console)")
|
|
906
|
+
.requiredOption("--app <appId>", "AppId for Catalox context")
|
|
907
|
+
.option("--catalog <catalogId...>", "Restrict to these catalog ids")
|
|
908
|
+
.option("--god", "God mode", false)
|
|
909
|
+
.action(async (opts) => {
|
|
910
|
+
const catalox = createCatalox();
|
|
911
|
+
const ctx = baseContext({ app: opts.app, god: opts.god });
|
|
912
|
+
const rows = await catalox.reportNativeCatalogLayoutDiagnostics(ctx, {
|
|
913
|
+
...(opts.catalog?.length ? { catalogIds: opts.catalog } : {}),
|
|
914
|
+
});
|
|
915
|
+
const summary = {
|
|
916
|
+
hint: "If needsLegacyToFlatMigration is true, run: catalox firestore migrate-native-catalog-data --app <sameApp>",
|
|
917
|
+
catalogs: rows,
|
|
918
|
+
};
|
|
919
|
+
await writeOrStdout(JSON.stringify(summary, null, 2));
|
|
920
|
+
});
|
|
921
|
+
firestoreCmd
|
|
922
|
+
.command("migrate-native-catalog-data")
|
|
923
|
+
.description("Optional pre-migrate backup to GCS, then copy legacy catalogData/{catalogId}/items → flat catalogData-{catalogId}-items")
|
|
924
|
+
.requiredOption("--app <appId>", "AppId for Catalox context")
|
|
925
|
+
.option("--skip-backup", "Skip pre-migrate GCS backup", false)
|
|
926
|
+
.option("--backup-bucket <name>", "GCS bucket for pre-migrate backup (default: catalox)", "catalox")
|
|
927
|
+
.option("--backup-prefix <path>", "Optional gcsPrefix for pre-migrate backupData")
|
|
928
|
+
.option("--backup-label <text>", "Label for pre-migrate backup", "pre-native-layout-migration")
|
|
929
|
+
.option("--snapshots", "Include snapshots in pre-migrate backup", false)
|
|
930
|
+
.option("--dry-run", "Count/copy simulation only for migrate", false)
|
|
931
|
+
.option("--verify-only", "Compare legacy vs flat doc counts", false)
|
|
932
|
+
.option("--overwrite", "Overwrite existing flat docs", false)
|
|
933
|
+
.option("--delete-legacy", "Delete legacy catalogData/{id}/items after migrate", false)
|
|
934
|
+
.option("--i-have-backups", "Required with --delete-legacy", false)
|
|
935
|
+
.option("--continue-on-error", "Continue other catalogs if one fails", false)
|
|
936
|
+
.option("--also-export-files", "Write NDJSON+manifest under .catalox-migration-backups/", false)
|
|
937
|
+
.option("--god", "God mode", false)
|
|
938
|
+
.action(async (opts) => {
|
|
939
|
+
const catalox = createCatalox();
|
|
940
|
+
const ctx = baseContext({ app: opts.app, god: opts.god });
|
|
941
|
+
if (!opts.skipBackup) {
|
|
942
|
+
const b = await catalox.backupData(ctx, {
|
|
943
|
+
mode: "gcs",
|
|
944
|
+
gcsBucket: String(opts.backupBucket ?? "catalox").trim(),
|
|
945
|
+
...(opts.backupPrefix != null && String(opts.backupPrefix).trim() !== ""
|
|
946
|
+
? { gcsPrefix: String(opts.backupPrefix).trim() }
|
|
947
|
+
: {}),
|
|
948
|
+
backupLabel: String(opts.backupLabel != null ? opts.backupLabel : "pre-native-layout-migration"),
|
|
949
|
+
includeSnapshots: Boolean(opts.snapshots),
|
|
950
|
+
});
|
|
951
|
+
await writeOrStdout(JSON.stringify({ phase: "backup", result: b }, null, 2));
|
|
952
|
+
if (!b.ok) {
|
|
953
|
+
process.exitCode = 1;
|
|
954
|
+
return;
|
|
955
|
+
}
|
|
956
|
+
}
|
|
957
|
+
const exportDir = opts.alsoExportFiles
|
|
958
|
+
? resolvePath(process.cwd(), ".catalox-migration-backups")
|
|
959
|
+
: undefined;
|
|
960
|
+
const m = await catalox.migrateNativeCatalogLayout(ctx, {
|
|
961
|
+
dryRun: Boolean(opts.dryRun),
|
|
962
|
+
verifyOnly: Boolean(opts.verifyOnly),
|
|
963
|
+
overwrite: Boolean(opts.overwrite),
|
|
964
|
+
deleteLegacy: Boolean(opts.deleteLegacy),
|
|
965
|
+
iHaveBackups: Boolean(opts.iHaveBackups),
|
|
966
|
+
continueOnError: Boolean(opts.continueOnError),
|
|
967
|
+
...(exportDir ? { exportFilesDir: exportDir } : {}),
|
|
968
|
+
});
|
|
969
|
+
await writeOrStdout(JSON.stringify({ phase: "migrate", result: m }, null, 2));
|
|
970
|
+
if (!m.ok)
|
|
971
|
+
process.exitCode = 1;
|
|
972
|
+
});
|
|
973
|
+
firestoreCmd
|
|
974
|
+
.command("migrate-native-item-scope")
|
|
975
|
+
.description("One-time: convert legacy/native scope shapes to flexible scope maps (domains[], agents[], …)")
|
|
976
|
+
.requiredOption("--app <appId>", "AppId for Catalox context")
|
|
977
|
+
.option("--dry-run", "Report only; no writes", false)
|
|
978
|
+
.option("--verify-only", "Fail if any legacy scope shapes remain", false)
|
|
979
|
+
.option("--i-have-backups", "Required to apply writes (not dry-run/verify-only)", false)
|
|
980
|
+
.option("--continue-on-error", "Continue other catalogs if one fails", false)
|
|
981
|
+
.option("--catalog <catalogId...>", "Limit to catalog ids")
|
|
982
|
+
.option("--scope-mapping <path>", "JSON map accountId:agentId → { domains, agents }")
|
|
983
|
+
.option("--also-export-files", "Write NDJSON under .catalox-migration-backups/", false)
|
|
984
|
+
.option("--god", "God mode", false)
|
|
985
|
+
.action(async (opts) => {
|
|
986
|
+
const catalox = createCatalox();
|
|
987
|
+
const ctx = baseContext({ app: opts.app, god: opts.god });
|
|
988
|
+
const exportDir = opts.alsoExportFiles
|
|
989
|
+
? resolvePath(process.cwd(), ".catalox-migration-backups")
|
|
990
|
+
: undefined;
|
|
991
|
+
const m = await catalox.migrateNativeItemScope(ctx, {
|
|
992
|
+
dryRun: Boolean(opts.dryRun),
|
|
993
|
+
verifyOnly: Boolean(opts.verifyOnly),
|
|
994
|
+
iHaveBackups: Boolean(opts.iHaveBackups),
|
|
995
|
+
continueOnError: Boolean(opts.continueOnError),
|
|
996
|
+
...(opts.catalog?.length ? { catalogIds: opts.catalog } : {}),
|
|
997
|
+
...(opts.scopeMapping ? { scopeMappingPath: String(opts.scopeMapping) } : {}),
|
|
998
|
+
...(exportDir ? { exportFilesDir: exportDir } : {}),
|
|
999
|
+
});
|
|
1000
|
+
await writeOrStdout(JSON.stringify({ phase: "migrate-native-item-scope", result: m }, null, 2));
|
|
1001
|
+
if (!m.ok)
|
|
1002
|
+
process.exitCode = 1;
|
|
1003
|
+
});
|
|
1004
|
+
firestoreCmd
|
|
1005
|
+
.command("export-gcs")
|
|
1006
|
+
.description("Export Firestore collection(s) to a GCS bucket as NDJSON + manifest (for --all). Uses Application Default Credentials for GCS.")
|
|
1007
|
+
.requiredOption("--app <appId>", "AppId for Catalox context")
|
|
1008
|
+
.requiredOption("--bucket <name>", "GCS bucket name")
|
|
1009
|
+
.option("--prefix <path>", "Object key prefix inside the bucket", "")
|
|
1010
|
+
.option("--postfix <suffix>", "Optional suffix before .ndjson in each object name", "")
|
|
1011
|
+
.option("--path <collectionPath>", "Single collection path (e.g. apps or catalogData/myId/items)")
|
|
1012
|
+
.option("--all", "Export every root collection; writes catalox-firestore-export-manifest.json", false)
|
|
1013
|
+
.option("--recursive", "With --all: include all document subcollections (expensive)", false)
|
|
1014
|
+
.option("--god", "God mode", false)
|
|
1015
|
+
.action(async (opts) => {
|
|
1016
|
+
const hasPath = Boolean(opts.path && String(opts.path).trim());
|
|
1017
|
+
const all = Boolean(opts.all);
|
|
1018
|
+
if (hasPath === all) {
|
|
1019
|
+
// eslint-disable-next-line no-console
|
|
1020
|
+
console.error("Specify exactly one of: --path <collectionPath> OR --all");
|
|
1021
|
+
process.exitCode = 1;
|
|
1022
|
+
return;
|
|
1023
|
+
}
|
|
1024
|
+
const catalox = createCatalox();
|
|
1025
|
+
const ctx = baseContext({ app: opts.app, god: opts.god });
|
|
1026
|
+
const bucket = String(opts.bucket);
|
|
1027
|
+
const gcsPrefix = String(opts.prefix ?? "");
|
|
1028
|
+
const objectNamePostfix = opts.postfix != null ? String(opts.postfix) : undefined;
|
|
1029
|
+
if (hasPath) {
|
|
1030
|
+
const res = await catalox.exportFirestoreCollectionToGcs(ctx, {
|
|
1031
|
+
bucket,
|
|
1032
|
+
gcsPrefix,
|
|
1033
|
+
...(objectNamePostfix !== undefined && objectNamePostfix !== "" ? { objectNamePostfix } : {}),
|
|
1034
|
+
collectionPath: String(opts.path).trim(),
|
|
1035
|
+
});
|
|
1036
|
+
await writeOrStdout(JSON.stringify(res, null, 2));
|
|
1037
|
+
if (!res.ok)
|
|
1038
|
+
process.exitCode = 1;
|
|
1039
|
+
return;
|
|
1040
|
+
}
|
|
1041
|
+
const res = await catalox.exportAllFirestoreCollectionsToGcs(ctx, {
|
|
1042
|
+
bucket,
|
|
1043
|
+
gcsPrefix,
|
|
1044
|
+
...(objectNamePostfix !== undefined && objectNamePostfix !== "" ? { objectNamePostfix } : {}),
|
|
1045
|
+
recursive: Boolean(opts.recursive),
|
|
1046
|
+
});
|
|
1047
|
+
await writeOrStdout(JSON.stringify(res, null, 2));
|
|
1048
|
+
if (!res.ok)
|
|
1049
|
+
process.exitCode = 1;
|
|
1050
|
+
});
|
|
1051
|
+
firestoreCmd
|
|
1052
|
+
.command("import-gcs")
|
|
1053
|
+
.description("Restore Firestore from GCS NDJSON produced by export-gcs (single collection or manifest for all). Uses ADC for GCS.")
|
|
1054
|
+
.requiredOption("--app <appId>", "AppId for Catalox context")
|
|
1055
|
+
.requiredOption("--bucket <name>", "GCS bucket name")
|
|
1056
|
+
.option("--prefix <path>", "Object key prefix (must match export)", "")
|
|
1057
|
+
.option("--postfix <suffix>", "Suffix used at export time", "")
|
|
1058
|
+
.option("--path <collectionPath>", "Target Firestore collection path for single-file restore")
|
|
1059
|
+
.option("--object <objectPath>", "Full GCS object path within bucket (overrides prefix/path/postfix inference)")
|
|
1060
|
+
.option("--manifest <objectPath>", "Restore all entries from this manifest object path in the bucket")
|
|
1061
|
+
.option("--restore-all", "Restore all entries using default manifest name under --prefix (same as export --all)", false)
|
|
1062
|
+
.option("--replace", "Delete each destination collection before writing", false)
|
|
1063
|
+
.option("--god", "God mode", false)
|
|
1064
|
+
.action(async (opts) => {
|
|
1065
|
+
const catalox = createCatalox();
|
|
1066
|
+
const ctx = baseContext({ app: opts.app, god: opts.god });
|
|
1067
|
+
const bucket = String(opts.bucket);
|
|
1068
|
+
const gcsPrefix = String(opts.prefix ?? "");
|
|
1069
|
+
const postfix = opts.postfix != null ? String(opts.postfix) : undefined;
|
|
1070
|
+
const replace = Boolean(opts.replace);
|
|
1071
|
+
const manifestPath = opts.manifest != null && String(opts.manifest).trim() ? String(opts.manifest).trim() : "";
|
|
1072
|
+
const restoreAll = Boolean(opts.restoreAll);
|
|
1073
|
+
if (manifestPath || restoreAll) {
|
|
1074
|
+
const res = await catalox.restoreAllFirestoreCollectionsFromGcsManifest(ctx, {
|
|
1075
|
+
bucket,
|
|
1076
|
+
gcsPrefix,
|
|
1077
|
+
...(postfix !== undefined && postfix !== "" ? { objectNamePostfix: postfix } : {}),
|
|
1078
|
+
...(manifestPath ? { manifestObjectPath: manifestPath } : {}),
|
|
1079
|
+
replaceDestinationCollection: replace,
|
|
1080
|
+
});
|
|
1081
|
+
await writeOrStdout(JSON.stringify(res, null, 2));
|
|
1082
|
+
if (!res.ok)
|
|
1083
|
+
process.exitCode = 1;
|
|
1084
|
+
return;
|
|
1085
|
+
}
|
|
1086
|
+
const collectionPath = opts.path != null && String(opts.path).trim() ? String(opts.path).trim() : "";
|
|
1087
|
+
if (!collectionPath) {
|
|
1088
|
+
// eslint-disable-next-line no-console
|
|
1089
|
+
console.error("For single-collection restore, pass --path (and optionally --object), or use --manifest / --restore-all");
|
|
1090
|
+
process.exitCode = 1;
|
|
1091
|
+
return;
|
|
1092
|
+
}
|
|
1093
|
+
const explicitObject = opts.object != null && String(opts.object).trim() ? String(opts.object).trim() : "";
|
|
1094
|
+
const objectPath = explicitObject ||
|
|
1095
|
+
ndjsonObjectPath({
|
|
1096
|
+
gcsPrefix: normalizeGcsPrefix(gcsPrefix),
|
|
1097
|
+
collectionPath,
|
|
1098
|
+
...(postfix != null && postfix !== "" ? { objectNamePostfix: postfix } : {}),
|
|
1099
|
+
});
|
|
1100
|
+
const res = await catalox.restoreFirestoreCollectionFromGcs(ctx, {
|
|
1101
|
+
bucket,
|
|
1102
|
+
gcsPrefix,
|
|
1103
|
+
...(postfix !== undefined && postfix !== "" ? { objectNamePostfix: postfix } : {}),
|
|
1104
|
+
collectionPath,
|
|
1105
|
+
objectPath,
|
|
1106
|
+
replaceDestinationCollection: replace,
|
|
1107
|
+
});
|
|
1108
|
+
await writeOrStdout(JSON.stringify(res, null, 2));
|
|
1109
|
+
if (!res.ok)
|
|
1110
|
+
process.exitCode = 1;
|
|
1111
|
+
});
|
|
1112
|
+
firestoreCmd
|
|
1113
|
+
.command("compare-gcs")
|
|
1114
|
+
.description("Compare live Firestore to NDJSON in GCS: identical, changed, only-in-Firestore, only-in-bucket (see docs/firestore-gcs-export.md)")
|
|
1115
|
+
.requiredOption("--app <appId>", "AppId for Catalox context")
|
|
1116
|
+
.requiredOption("--bucket <name>", "GCS bucket name")
|
|
1117
|
+
.option("--prefix <path>", "Object key prefix (must match export)", "")
|
|
1118
|
+
.option("--postfix <suffix>", "Suffix used at export time (single-collection mode)", "")
|
|
1119
|
+
.option("--path <collectionPath>", "Firestore collection path for single-object compare")
|
|
1120
|
+
.option("--object <objectPath>", "Full GCS object path (overrides prefix/path/postfix inference)")
|
|
1121
|
+
.option("--manifest <objectPath>", "Compare all entries from this manifest object path")
|
|
1122
|
+
.option("--restore-all", "Compare all entries using default manifest name under --prefix (same as export --all)", false)
|
|
1123
|
+
.option("--max-ids <n>", "Max document ids listed per category (counts are always full)", "500")
|
|
1124
|
+
.option("--god", "God mode", false)
|
|
1125
|
+
.action(async (opts) => {
|
|
1126
|
+
const catalox = createCatalox();
|
|
1127
|
+
const ctx = baseContext({ app: opts.app, god: opts.god });
|
|
1128
|
+
const bucket = String(opts.bucket);
|
|
1129
|
+
const gcsPrefix = String(opts.prefix ?? "");
|
|
1130
|
+
const postfix = opts.postfix != null ? String(opts.postfix) : undefined;
|
|
1131
|
+
const maxIds = Math.max(0, Number.parseInt(String(opts.maxIds ?? "500"), 10) || 0);
|
|
1132
|
+
const manifestPath = opts.manifest != null && String(opts.manifest).trim() ? String(opts.manifest).trim() : "";
|
|
1133
|
+
const restoreAll = Boolean(opts.restoreAll);
|
|
1134
|
+
if (manifestPath || restoreAll) {
|
|
1135
|
+
const res = await catalox.compareAllFirestoreCollectionsWithGcsManifest(ctx, {
|
|
1136
|
+
bucket,
|
|
1137
|
+
gcsPrefix,
|
|
1138
|
+
...(manifestPath ? { manifestObjectPath: manifestPath } : {}),
|
|
1139
|
+
maxListedIdsPerCategory: maxIds,
|
|
1140
|
+
});
|
|
1141
|
+
await writeOrStdout(JSON.stringify(res, null, 2));
|
|
1142
|
+
if (!res.ok)
|
|
1143
|
+
process.exitCode = 1;
|
|
1144
|
+
return;
|
|
1145
|
+
}
|
|
1146
|
+
const collectionPath = opts.path != null && String(opts.path).trim() ? String(opts.path).trim() : "";
|
|
1147
|
+
if (!collectionPath) {
|
|
1148
|
+
// eslint-disable-next-line no-console
|
|
1149
|
+
console.error("Pass --path for single-collection compare, or --manifest / --restore-all for manifest-driven compare");
|
|
1150
|
+
process.exitCode = 1;
|
|
1151
|
+
return;
|
|
1152
|
+
}
|
|
1153
|
+
const explicitObject = opts.object != null && String(opts.object).trim() ? String(opts.object).trim() : "";
|
|
1154
|
+
const objectPath = explicitObject ||
|
|
1155
|
+
ndjsonObjectPath({
|
|
1156
|
+
gcsPrefix: normalizeGcsPrefix(gcsPrefix),
|
|
1157
|
+
collectionPath,
|
|
1158
|
+
...(postfix != null && postfix !== "" ? { objectNamePostfix: postfix } : {}),
|
|
1159
|
+
});
|
|
1160
|
+
const res = await catalox.compareFirestoreCollectionWithGcsNdjson(ctx, {
|
|
1161
|
+
bucket,
|
|
1162
|
+
gcsPrefix,
|
|
1163
|
+
...(postfix != null && postfix !== "" ? { objectNamePostfix: postfix } : {}),
|
|
1164
|
+
collectionPath,
|
|
1165
|
+
objectPath,
|
|
1166
|
+
maxListedIdsPerCategory: maxIds,
|
|
1167
|
+
});
|
|
1168
|
+
await writeOrStdout(JSON.stringify(res, null, 2));
|
|
1169
|
+
if (!res.ok)
|
|
1170
|
+
process.exitCode = 1;
|
|
1171
|
+
});
|
|
1172
|
+
const historyCmd = program.command("history").description("Native item history (Firestore index + GCS payloads)");
|
|
1173
|
+
historyCmd
|
|
1174
|
+
.command("list")
|
|
1175
|
+
.description("List catalogItemHistory rows for a catalog (newest first)")
|
|
1176
|
+
.requiredOption("--app <appId>", "AppId for authz")
|
|
1177
|
+
.requiredOption("--catalog <catalogId>", "Catalog id")
|
|
1178
|
+
.option("--item <itemId>", "Filter by logical item id")
|
|
1179
|
+
.option("--op <op>", "Filter by op (update|delete|restore|catalog_delete_bulk|catalog_rename)")
|
|
1180
|
+
.option("--since <iso>", "Client-side filter: ts >= since")
|
|
1181
|
+
.option("--until <iso>", "Client-side filter: ts <= until")
|
|
1182
|
+
.option("--limit <n>", "Page size", "50")
|
|
1183
|
+
.option("--cursor <eventId>", "startAfterEventId for pagination")
|
|
1184
|
+
.option("--god", "God mode", false)
|
|
1185
|
+
.action(async (opts) => {
|
|
1186
|
+
const catalox = createCatalox();
|
|
1187
|
+
const ctx = baseContext({ app: opts.app, god: opts.god });
|
|
1188
|
+
const limit = Math.max(1, Math.min(500, parseInt(String(opts.limit ?? "50"), 10) || 50));
|
|
1189
|
+
const res = await catalox.listCatalogItemHistory(ctx, String(opts.catalog), {
|
|
1190
|
+
...(opts.item ? { itemId: String(opts.item) } : {}),
|
|
1191
|
+
...(opts.op ? { op: String(opts.op) } : {}),
|
|
1192
|
+
...(opts.since ? { since: String(opts.since) } : {}),
|
|
1193
|
+
...(opts.until ? { until: String(opts.until) } : {}),
|
|
1194
|
+
limit,
|
|
1195
|
+
...(opts.cursor ? { startAfterEventId: String(opts.cursor) } : {}),
|
|
1196
|
+
});
|
|
1197
|
+
await writeOrStdout(JSON.stringify(res, null, 2));
|
|
1198
|
+
});
|
|
1199
|
+
historyCmd
|
|
1200
|
+
.command("show")
|
|
1201
|
+
.description("Load index row + GCS payload for one eventId")
|
|
1202
|
+
.requiredOption("--app <appId>", "AppId for authz")
|
|
1203
|
+
.argument("<eventId>", "catalogItemHistory document id")
|
|
1204
|
+
.option("--god", "God mode", false)
|
|
1205
|
+
.action(async (eventId, opts) => {
|
|
1206
|
+
const catalox = createCatalox();
|
|
1207
|
+
const ctx = baseContext({ app: opts.app, god: opts.god });
|
|
1208
|
+
const res = await catalox.getCatalogItemHistoryEvent(ctx, String(eventId));
|
|
1209
|
+
await writeOrStdout(JSON.stringify(res, null, 2));
|
|
1210
|
+
if (!res)
|
|
1211
|
+
process.exitCode = 1;
|
|
1212
|
+
});
|
|
1213
|
+
historyCmd
|
|
1214
|
+
.command("restore")
|
|
1215
|
+
.description("Restore a native row from a history event (before or after snapshot)")
|
|
1216
|
+
.requiredOption("--app <appId>", "AppId for authz")
|
|
1217
|
+
.argument("<eventId>", "catalogItemHistory document id")
|
|
1218
|
+
.option("--mode <before|after>", "Which snapshot to apply", "before")
|
|
1219
|
+
.option("--god", "God mode", false)
|
|
1220
|
+
.action(async (eventId, opts) => {
|
|
1221
|
+
const catalox = createCatalox();
|
|
1222
|
+
const ctx = baseContext({ app: opts.app, god: opts.god });
|
|
1223
|
+
const mode = String(opts.mode ?? "before").toLowerCase() === "after" ? "after" : "before";
|
|
1224
|
+
const res = await catalox.restoreCatalogItemFromHistory(ctx, String(eventId), { mode });
|
|
1225
|
+
await writeOrStdout(JSON.stringify(res, null, 2));
|
|
1226
|
+
});
|
|
1227
|
+
historyCmd
|
|
1228
|
+
.command("field-list")
|
|
1229
|
+
.description("List changes to one item field (derived from row-level history snapshots)")
|
|
1230
|
+
.requiredOption("--app <appId>", "AppId for authz")
|
|
1231
|
+
.requiredOption("--catalog <catalogId>", "Catalog id")
|
|
1232
|
+
.requiredOption("--item <itemId>", "Logical item id")
|
|
1233
|
+
.requiredOption("--field <path>", "Field path (e.g. instructions or data.instructions)")
|
|
1234
|
+
.option("--since <iso>", "Client-side filter: ts >= since")
|
|
1235
|
+
.option("--until <iso>", "Client-side filter: ts <= until")
|
|
1236
|
+
.option("--limit <n>", "Max field changes to return", "50")
|
|
1237
|
+
.option("--max-scan <n>", "Max history index rows to scan", "500")
|
|
1238
|
+
.option("--cursor <eventId>", "startAfterEventId from a previous page")
|
|
1239
|
+
.option("--god", "God mode", false)
|
|
1240
|
+
.action(async (opts) => {
|
|
1241
|
+
const catalox = createCatalox();
|
|
1242
|
+
const ctx = baseContext({ app: opts.app, god: opts.god });
|
|
1243
|
+
const limit = Math.max(1, Math.min(500, parseInt(String(opts.limit ?? "50"), 10) || 50));
|
|
1244
|
+
const maxScan = Math.max(limit, Math.min(5000, parseInt(String(opts.maxScan ?? "500"), 10) || 500));
|
|
1245
|
+
const res = await catalox.listCatalogItemFieldHistory(ctx, String(opts.catalog), {
|
|
1246
|
+
itemId: String(opts.item),
|
|
1247
|
+
fieldPath: String(opts.field),
|
|
1248
|
+
...(opts.since ? { since: String(opts.since) } : {}),
|
|
1249
|
+
...(opts.until ? { until: String(opts.until) } : {}),
|
|
1250
|
+
limit,
|
|
1251
|
+
maxScan,
|
|
1252
|
+
...(opts.cursor ? { startAfterEventId: String(opts.cursor) } : {}),
|
|
1253
|
+
});
|
|
1254
|
+
await writeOrStdout(JSON.stringify(res, null, 2));
|
|
1255
|
+
});
|
|
1256
|
+
historyCmd
|
|
1257
|
+
.command("field-restore")
|
|
1258
|
+
.description("Restore one data or indexed field from a history event")
|
|
1259
|
+
.requiredOption("--app <appId>", "AppId for authz")
|
|
1260
|
+
.requiredOption("--field <path>", "Field path (e.g. instructions or data.instructions)")
|
|
1261
|
+
.argument("<eventId>", "catalogItemHistory document id")
|
|
1262
|
+
.option("--mode <before|after>", "Use before or after snapshot value", "before")
|
|
1263
|
+
.option("--god", "God mode", false)
|
|
1264
|
+
.action(async (eventId, opts) => {
|
|
1265
|
+
const catalox = createCatalox();
|
|
1266
|
+
const ctx = baseContext({ app: opts.app, god: opts.god });
|
|
1267
|
+
const mode = String(opts.mode ?? "before").toLowerCase() === "after" ? "after" : "before";
|
|
1268
|
+
const res = await catalox.restoreCatalogItemFieldFromHistory(ctx, String(eventId), {
|
|
1269
|
+
fieldPath: String(opts.field),
|
|
1270
|
+
mode,
|
|
1271
|
+
});
|
|
1272
|
+
await writeOrStdout(JSON.stringify(res, null, 2));
|
|
1273
|
+
});
|
|
1274
|
+
historyCmd
|
|
1275
|
+
.command("replay")
|
|
1276
|
+
.description("Replay history up to --as-of and diff-apply to live native items")
|
|
1277
|
+
.requiredOption("--app <appId>", "AppId for authz")
|
|
1278
|
+
.requiredOption("--catalog <catalogId>", "Catalog id")
|
|
1279
|
+
.requiredOption("--as-of <iso>", "Inclusive upper bound on event ts")
|
|
1280
|
+
.option("--god", "God mode", false)
|
|
1281
|
+
.action(async (opts) => {
|
|
1282
|
+
const catalox = createCatalox();
|
|
1283
|
+
const ctx = baseContext({ app: opts.app, god: opts.god });
|
|
1284
|
+
const res = await catalox.replayCatalogToPointInTime(ctx, String(opts.catalog), { asOf: String(opts.asOf) });
|
|
1285
|
+
await writeOrStdout(JSON.stringify(res, null, 2));
|
|
1286
|
+
});
|
|
1287
|
+
const catalogCmd = program.command("catalog").description("Catalog lifecycle (delete / restore / hard rename)");
|
|
1288
|
+
catalogCmd
|
|
1289
|
+
.command("delete")
|
|
1290
|
+
.description("Snapshot catalog to GCS, write delete manifest, then hard-delete Firestore rows (requires record history bucket)")
|
|
1291
|
+
.requiredOption("--app <appId>", "AppId for authz")
|
|
1292
|
+
.requiredOption("--catalog <catalogId>", "Catalog id")
|
|
1293
|
+
.option("--confirm", "Must pass --confirm to run", false)
|
|
1294
|
+
.option("--backup-bucket <name>", "Optional: run backupData mode=gcs to this bucket before delete")
|
|
1295
|
+
.option("--backup-prefix <path>", "Optional gcsPrefix for pre-delete backupData")
|
|
1296
|
+
.option("--god", "God mode", false)
|
|
1297
|
+
.action(async (opts) => {
|
|
1298
|
+
if (!opts.confirm) {
|
|
1299
|
+
// eslint-disable-next-line no-console
|
|
1300
|
+
console.error("Refusing to delete without --confirm");
|
|
1301
|
+
process.exitCode = 1;
|
|
1302
|
+
return;
|
|
1303
|
+
}
|
|
1304
|
+
const catalox = createCatalox();
|
|
1305
|
+
const ctx = baseContext({ app: opts.app, god: opts.god });
|
|
1306
|
+
const res = await catalox.deleteCatalog(ctx, String(opts.catalog), {
|
|
1307
|
+
confirm: true,
|
|
1308
|
+
...(opts.backupBucket ? { gcsBackupBucket: String(opts.backupBucket).trim() } : {}),
|
|
1309
|
+
...(opts.backupPrefix ? { gcsBackupPrefix: String(opts.backupPrefix).trim() } : {}),
|
|
1310
|
+
});
|
|
1311
|
+
await writeOrStdout(JSON.stringify(res, null, 2));
|
|
1312
|
+
if (!res.ok)
|
|
1313
|
+
process.exitCode = 1;
|
|
1314
|
+
});
|
|
1315
|
+
catalogCmd
|
|
1316
|
+
.command("restore")
|
|
1317
|
+
.description("Restore a catalog from a delete manifest path (requires superAdmin context / --god)")
|
|
1318
|
+
.requiredOption("--app <appId>", "AppId (superAdmin)")
|
|
1319
|
+
.requiredOption("--manifest <relativePath>", "GCS object path relative to record-history prefix, ending in manifest.json")
|
|
1320
|
+
.option("--god", "God mode (superAdmin)", true)
|
|
1321
|
+
.action(async (opts) => {
|
|
1322
|
+
const catalox = createCatalox();
|
|
1323
|
+
const ctx = baseContext({ app: opts.app, god: true });
|
|
1324
|
+
const res = await catalox.restoreDeletedCatalog(ctx, {
|
|
1325
|
+
gcsManifestRelativePath: String(opts.manifest).trim(),
|
|
1326
|
+
});
|
|
1327
|
+
await writeOrStdout(JSON.stringify(res, null, 2));
|
|
1328
|
+
if (!res.ok)
|
|
1329
|
+
process.exitCode = 1;
|
|
1330
|
+
});
|
|
1331
|
+
catalogCmd
|
|
1332
|
+
.command("rename")
|
|
1333
|
+
.description("Hard rename catalog id (copy + rewrite + delete source; requires record history bucket)")
|
|
1334
|
+
.requiredOption("--app <appId>", "AppId for authz")
|
|
1335
|
+
.requiredOption("--from <catalogId>", "Source catalog id")
|
|
1336
|
+
.requiredOption("--to <catalogId>", "Target catalog id (must not exist)")
|
|
1337
|
+
.option("--backup-bucket <name>", "Optional: backupData gcs bucket before rename")
|
|
1338
|
+
.option("--backup-prefix <path>", "Optional gcsPrefix for pre-rename backup")
|
|
1339
|
+
.option("--god", "God mode", false)
|
|
1340
|
+
.action(async (opts) => {
|
|
1341
|
+
const catalox = createCatalox();
|
|
1342
|
+
const ctx = baseContext({ app: opts.app, god: opts.god });
|
|
1343
|
+
const res = await catalox.renameCatalog(ctx, String(opts.from), String(opts.to), {
|
|
1344
|
+
...(opts.backupBucket ? { gcsBackupBucket: String(opts.backupBucket).trim() } : {}),
|
|
1345
|
+
...(opts.backupPrefix ? { gcsBackupPrefix: String(opts.backupPrefix).trim() } : {}),
|
|
1346
|
+
});
|
|
1347
|
+
await writeOrStdout(JSON.stringify(res, null, 2));
|
|
1348
|
+
if (!res.ok)
|
|
1349
|
+
process.exitCode = 1;
|
|
1350
|
+
});
|
|
1351
|
+
const toolboxCmd = program
|
|
1352
|
+
.command("toolbox")
|
|
1353
|
+
.description("Operator helpers: diagnose app↔catalog access (bindings) and repair common mistakes");
|
|
1354
|
+
toolboxCmd
|
|
1355
|
+
.command("check-access")
|
|
1356
|
+
.description("Read Firestore catalogBindings doc, catalog row, and run listCatalogItemsWithOutcome (same auth rules as runtime)")
|
|
1357
|
+
.requiredOption("--app <appId>", "App id (must match CataloxContext.appId in your host)")
|
|
1358
|
+
.requiredOption("--catalog <catalogId>", "Catalog id (e.g. entities)")
|
|
1359
|
+
.option("--show-all-bindings", "List every catalogBindings row for this catalogId (who else is bound)", false)
|
|
1360
|
+
.action(async (opts) => {
|
|
1361
|
+
const { catalox, firestore } = createCataloxFromEnv();
|
|
1362
|
+
const appId = String(opts.app).trim();
|
|
1363
|
+
const catalogId = String(opts.catalog).trim();
|
|
1364
|
+
const bindingDocId = `${appId}:${catalogId}`;
|
|
1365
|
+
const bindingSnap = await firestore.collection("catalogBindings").doc(bindingDocId).get();
|
|
1366
|
+
const catalog = await catalox.getCatalog({ appId }, catalogId);
|
|
1367
|
+
const listSim = await catalox.listCatalogItemsWithOutcome({ appId }, catalogId, { limit: 1 });
|
|
1368
|
+
const recommendations = [];
|
|
1369
|
+
if (!catalog) {
|
|
1370
|
+
recommendations.push("Catalog document missing under `catalogs` (typo in catalogId, or catalog never created in this project).");
|
|
1371
|
+
}
|
|
1372
|
+
if (!bindingSnap.exists) {
|
|
1373
|
+
recommendations.push(`No binding document at catalogBindings/${bindingDocId}. Fix: catalox toolbox ensure-binding --app ${appId} --catalog ${catalogId} (use --god if your CLI context app differs from --app).`);
|
|
1374
|
+
}
|
|
1375
|
+
else {
|
|
1376
|
+
const b = bindingSnap.data();
|
|
1377
|
+
const status = b?.status;
|
|
1378
|
+
const access = b?.access;
|
|
1379
|
+
if (status !== "active") {
|
|
1380
|
+
recommendations.push(`Binding status is "${String(status)}" (expected active). Fix: catalox toolbox repair-binding --god --app ${appId} --catalog ${catalogId}`);
|
|
1381
|
+
}
|
|
1382
|
+
if (!access?.canRead) {
|
|
1383
|
+
recommendations.push("Binding has canRead false or missing; readers will be denied.");
|
|
1384
|
+
}
|
|
1385
|
+
}
|
|
1386
|
+
if (listSim.outcome === "denied") {
|
|
1387
|
+
recommendations.push("Simulated list returned denied — matches missing/inactive binding or insufficient access flags.");
|
|
1388
|
+
}
|
|
1389
|
+
if (listSim.outcome === "misconfigured") {
|
|
1390
|
+
recommendations.push("Simulated list returned misconfigured (catalog/adapter/descriptor issue after authz).");
|
|
1391
|
+
}
|
|
1392
|
+
if (listSim.outcome === "mapping_blocked") {
|
|
1393
|
+
recommendations.push("Simulated list returned mapping_blocked (mapping spec / adapter execution).");
|
|
1394
|
+
}
|
|
1395
|
+
let allBindingsForCatalog;
|
|
1396
|
+
if (opts.showAllBindings) {
|
|
1397
|
+
const q = await firestore.collection("catalogBindings").where("catalogId", "==", catalogId).get();
|
|
1398
|
+
allBindingsForCatalog = q.docs.map((d) => ({ id: d.id, ...d.data() }));
|
|
1399
|
+
}
|
|
1400
|
+
const payload = {
|
|
1401
|
+
appId,
|
|
1402
|
+
catalogId,
|
|
1403
|
+
bindingDocId,
|
|
1404
|
+
bindingDocExists: bindingSnap.exists,
|
|
1405
|
+
binding: bindingSnap.exists ? bindingSnap.data() : null,
|
|
1406
|
+
catalogExists: Boolean(catalog),
|
|
1407
|
+
...(catalog ? { catalogMetadataStatus: catalog.metadata?.status } : {}),
|
|
1408
|
+
simulatedListOutcome: listSim.outcome,
|
|
1409
|
+
...(listSim.outcome === "denied" && "error" in listSim
|
|
1410
|
+
? { deniedMessage: listSim.error?.message }
|
|
1411
|
+
: {}),
|
|
1412
|
+
...(allBindingsForCatalog ? { allBindingsForCatalog } : {}),
|
|
1413
|
+
recommendations,
|
|
1414
|
+
};
|
|
1415
|
+
await writeOrStdout(JSON.stringify(payload, null, 2));
|
|
1416
|
+
if (listSim.outcome !== "ok" && listSim.outcome !== "empty")
|
|
1417
|
+
process.exitCode = 1;
|
|
1418
|
+
});
|
|
1419
|
+
toolboxCmd
|
|
1420
|
+
.command("ensure-binding")
|
|
1421
|
+
.description("Create catalogBindings/{appId:catalogId} if absent (Catalox ensureBinding). Does not upgrade access if a row already exists.")
|
|
1422
|
+
.requiredOption("--app <appId>", "App id that should receive catalog access")
|
|
1423
|
+
.requiredOption("--catalog <catalogId>", "Catalog id")
|
|
1424
|
+
.option("--write", "Set canWrite true (default false)", false)
|
|
1425
|
+
.option("--admin", "Set canAdmin true", false)
|
|
1426
|
+
.option("--god", "Super-admin context: required when CLI context app is not the same as --app (see ensureBinding rules)", false)
|
|
1427
|
+
.action(async (opts) => {
|
|
1428
|
+
const catalox = createCatalox();
|
|
1429
|
+
const appId = String(opts.app).trim();
|
|
1430
|
+
const ctx = baseContext({ app: appId, god: Boolean(opts.god) });
|
|
1431
|
+
await catalox.ensureBinding(ctx, {
|
|
1432
|
+
appId,
|
|
1433
|
+
catalogId: String(opts.catalog).trim(),
|
|
1434
|
+
access: {
|
|
1435
|
+
canRead: true,
|
|
1436
|
+
canWrite: Boolean(opts.write),
|
|
1437
|
+
...(opts.admin ? { canAdmin: true } : {}),
|
|
1438
|
+
},
|
|
1439
|
+
});
|
|
1440
|
+
await writeOrStdout(JSON.stringify({
|
|
1441
|
+
ok: true,
|
|
1442
|
+
hint: "If a binding already existed, ensureBinding is a no-op (use toolbox repair-binding to change access or reactivate).",
|
|
1443
|
+
}, null, 2));
|
|
1444
|
+
});
|
|
1445
|
+
toolboxCmd
|
|
1446
|
+
.command("repair-binding")
|
|
1447
|
+
.description("Merge-write catalogBindings doc to status=active and access flags (use when ensure-binding no-ops on a disabled or wrong-access row)")
|
|
1448
|
+
.requiredOption("--app <appId>", "App id")
|
|
1449
|
+
.requiredOption("--catalog <catalogId>", "Catalog id")
|
|
1450
|
+
.option("--write", "Set canWrite true", false)
|
|
1451
|
+
.option("--admin", "Set canAdmin true", false)
|
|
1452
|
+
.option("--god", "Required: confirms operator intent (writes Firestore as Admin SDK)", false)
|
|
1453
|
+
.action(async (opts) => {
|
|
1454
|
+
if (!opts.god) {
|
|
1455
|
+
// eslint-disable-next-line no-console
|
|
1456
|
+
console.error("repair-binding requires --god");
|
|
1457
|
+
process.exitCode = 1;
|
|
1458
|
+
return;
|
|
1459
|
+
}
|
|
1460
|
+
const { firestore } = createCataloxFromEnv();
|
|
1461
|
+
const appId = String(opts.app).trim();
|
|
1462
|
+
const catalogId = String(opts.catalog).trim();
|
|
1463
|
+
const bindingDocId = `${appId}:${catalogId}`;
|
|
1464
|
+
const now = new Date().toISOString();
|
|
1465
|
+
const snap = await firestore.collection("catalogBindings").doc(bindingDocId).get();
|
|
1466
|
+
const prev = snap.exists ? snap.data() : {};
|
|
1467
|
+
const createdAt = typeof prev.createdAt === "string" ? prev.createdAt : now;
|
|
1468
|
+
await firestore
|
|
1469
|
+
.collection("catalogBindings")
|
|
1470
|
+
.doc(bindingDocId)
|
|
1471
|
+
.set({
|
|
1472
|
+
bindingId: bindingDocId,
|
|
1473
|
+
appId,
|
|
1474
|
+
catalogId,
|
|
1475
|
+
access: {
|
|
1476
|
+
canRead: true,
|
|
1477
|
+
canWrite: Boolean(opts.write),
|
|
1478
|
+
...(opts.admin ? { canAdmin: true } : {}),
|
|
1479
|
+
},
|
|
1480
|
+
status: "active",
|
|
1481
|
+
createdAt,
|
|
1482
|
+
updatedAt: now,
|
|
1483
|
+
}, { merge: true });
|
|
1484
|
+
await writeOrStdout(JSON.stringify({ ok: true, bindingDocId, updatedAt: now }, null, 2));
|
|
1485
|
+
});
|
|
1486
|
+
toolboxCmd
|
|
1487
|
+
.command("unbind-catalog")
|
|
1488
|
+
.description("Disable app↔catalog binding (sets catalogBindings status to disabled; same row id as ensure-binding)")
|
|
1489
|
+
.requiredOption("--app <appId>", "App id")
|
|
1490
|
+
.requiredOption("--catalog <catalogId>", "Catalog id")
|
|
1491
|
+
.option("--god", "Super-admin context: required when CLI context app is not the same as --app (see bindCatalogToApp / unbind rules)", false)
|
|
1492
|
+
.action(async (opts) => {
|
|
1493
|
+
const catalox = createCatalox();
|
|
1494
|
+
const appId = String(opts.app).trim();
|
|
1495
|
+
const ctx = baseContext({ app: appId, god: Boolean(opts.god) });
|
|
1496
|
+
await catalox.unbindCatalogFromApp(ctx, appId, String(opts.catalog).trim());
|
|
1497
|
+
await writeOrStdout(JSON.stringify({
|
|
1498
|
+
ok: true,
|
|
1499
|
+
bindingDocId: `${appId}:${String(opts.catalog).trim()}`,
|
|
1500
|
+
hint: "Binding row is disabled (not deleted). Re-enable with toolbox repair-binding --god ...",
|
|
1501
|
+
}, null, 2));
|
|
1502
|
+
});
|
|
1503
|
+
program.parseAsync(process.argv).catch((err) => {
|
|
1504
|
+
// eslint-disable-next-line no-console
|
|
1505
|
+
console.error(err instanceof Error ? err.message : err);
|
|
1506
|
+
process.exitCode = 1;
|
|
1507
|
+
});
|
|
1508
|
+
//# sourceMappingURL=index.js.map
|