@typicalday/firegraph 0.13.0 → 0.14.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -997,6 +997,14 @@ import type {
997
997
  } from 'firegraph';
998
998
  ```
999
999
 
1000
+ The Enterprise backend also exports its own narrowed return type:
1001
+
1002
+ ```ts
1003
+ import type { FirestoreEnterpriseBackend } from 'firegraph/firestore-enterprise';
1004
+ ```
1005
+
1006
+ `FirestoreEnterpriseBackend` is the type returned by `createFirestoreEnterpriseBackend`. It adds a `readonly queryMode` field so you can inspect the effective query mode after construction without losing type information.
1007
+
1000
1008
  > **Note:** Several types are defined in the library but not yet exported from the `'firegraph'` entry point: the parameter and result types for `fullTextSearch()`, `geoSearch()`, and `runEngineTraversal()` (`FullTextSearchParams`, `GeoSearchParams`, `GeoPointLiteral`, `EngineHopSpec`, `EngineTraversalParams`, `EngineTraversalResult`), and the extension interface `EngineTraversalExtension`. Rely on type inference or declare local `Parameters<typeof client.fullTextSearch>[0]`-style helpers until these types are promoted to the public export.
1001
1009
 
1002
1010
  ## How It Works
@@ -1078,10 +1086,58 @@ Uses the Firestore Pipeline API (`db.pipeline()`) by default. Requires **Firesto
1078
1086
  - Enables queries on `data.*` fields without composite indexes
1079
1087
  - Unlocks additional capabilities: `query.dml`, `traversal.serverSide`, `search.fullText`, `search.geo`
1080
1088
 
1081
- **Emulator auto-fallback:** when `FIRESTORE_EMULATOR_HOST` is detected, the Enterprise backend automatically switches to the classic query path (pipelines aren't supported in the emulator). No configuration needed.
1089
+ **Emulator auto-fallback:** when `FIRESTORE_EMULATOR_HOST` is detected, the Enterprise backend automatically switches to the classic query path because the default Firestore emulator does not execute pipelines. See [Local emulator](#local-emulator) below for opting into the enterprise-edition emulator (firebase-tools v15.14+), which does support pipelines.
1082
1090
 
1083
1091
  **Transactions** always use the classic query path regardless of `defaultQueryMode`, because Pipeline queries are not transactionally bound.
1084
1092
 
1093
+ #### Local emulator
1094
+
1095
+ The default (standard-edition) Firestore emulator does not execute the Pipeline API, so when `FIRESTORE_EMULATOR_HOST` is set the Enterprise backend coerces `defaultQueryMode: 'pipeline'` to `'classic'` automatically.
1096
+
1097
+ [firebase-tools v15.14+](https://firebase.google.com/docs/emulator-suite/install_and_configure) ships an **enterprise-edition** emulator that does support pipelines end-to-end. Two pieces are required:
1098
+
1099
+ 1. Start the emulator in enterprise mode — either via the CLI flag:
1100
+
1101
+ ```bash
1102
+ firebase emulators:start --database-edition enterprise
1103
+ ```
1104
+
1105
+ or via `firebase.json`:
1106
+
1107
+ ```jsonc
1108
+ {
1109
+ "firestore": { "edition": "enterprise" },
1110
+ "emulators": {
1111
+ "firestore": {
1112
+ "port": 8080,
1113
+ "edition": "enterprise",
1114
+ },
1115
+ },
1116
+ }
1117
+ ```
1118
+
1119
+ 2. Tell firegraph the emulator is enterprise-edition by exporting `FIRESTORE_EMULATOR_EDITION=enterprise` in the same environment that sets `FIRESTORE_EMULATOR_HOST`:
1120
+
1121
+ ```bash
1122
+ export FIRESTORE_EMULATOR_HOST=127.0.0.1:8080
1123
+ export FIRESTORE_EMULATOR_EDITION=enterprise
1124
+ ```
1125
+
1126
+ With both set, `defaultQueryMode: 'pipeline'` is honored against the local emulator and engine traversal (`traversal.serverSide` / `runEngineTraversal`) is enabled. Without `FIRESTORE_EMULATOR_EDITION=enterprise`, engine traversal throws `UNSUPPORTED_OPERATION` when `FIRESTORE_EMULATOR_HOST` is set (or silently degrades to per-hop looping when `engineTraversal` is `'auto'`). To introspect the effective mode (post emulator-edition coercion), keep a reference to the backend before passing it to `createGraphClient`:
1127
+
1128
+ ```ts
1129
+ import { createFirestoreEnterpriseBackend } from 'firegraph/firestore-enterprise';
1130
+ import { createGraphClient } from 'firegraph';
1131
+
1132
+ const backend = createFirestoreEnterpriseBackend(db, 'firegraph', {
1133
+ defaultQueryMode: 'pipeline',
1134
+ });
1135
+ console.log(backend.queryMode); // 'pipeline' under the enterprise emulator, 'classic' under the default emulator
1136
+ const client = createGraphClient(backend);
1137
+ ```
1138
+
1139
+ The match on `FIRESTORE_EMULATOR_EDITION` is case-insensitive and whitespace-trimmed (`enterprise`, `Enterprise`, `ENTERPRISE`, `" enterprise "` all work); any other value (unset, empty, `standard`, garbage) keeps the historical "force classic" behavior. Production (`FIRESTORE_EMULATOR_HOST` unset) never reads the variable.
1140
+
1085
1141
  ### SQLite Backend (`firegraph/sqlite`)
1086
1142
 
1087
1143
  Shared-table SQLite backend for Node.js (`better-sqlite3`) and Cloudflare D1. Supports all four core capabilities plus `query.aggregate`, `query.select`, `query.join`, and `query.dml`. Does not support `search.*`.
@@ -3292,10 +3292,13 @@ function decodeTree(rootRows, hops) {
3292
3292
  }
3293
3293
  async function runFirestoreEngineTraversal(db, collectionPath, params) {
3294
3294
  if (process.env.FIRESTORE_EMULATOR_HOST) {
3295
- throw new FiregraphError(
3296
- "engine traversal requires Pipelines \u2014 not supported on the Firestore emulator",
3297
- "UNSUPPORTED_OPERATION"
3298
- );
3295
+ const emulatorEdition = (process.env.FIRESTORE_EMULATOR_EDITION ?? "").trim().toLowerCase();
3296
+ if (emulatorEdition !== "enterprise") {
3297
+ throw new FiregraphError(
3298
+ "engine traversal requires Pipelines \u2014 not supported on the default Firestore emulator. Run firebase-tools v15.14+ with `--database-edition enterprise` and set `FIRESTORE_EMULATOR_EDITION=enterprise` to opt in.",
3299
+ "UNSUPPORTED_OPERATION"
3300
+ );
3301
+ }
3299
3302
  }
3300
3303
  const compiled = compileEngineTraversal(params);
3301
3304
  if (!compiled.eligible) {
@@ -3560,8 +3563,8 @@ var FirestoreEnterpriseBatchBackend = class {
3560
3563
  var FirestoreEnterpriseBackendImpl = class _FirestoreEnterpriseBackendImpl {
3561
3564
  constructor(db, collectionPath, queryMode, scopePath, previewDml) {
3562
3565
  this.db = db;
3563
- this.queryMode = queryMode;
3564
3566
  this.previewDml = previewDml;
3567
+ this.queryMode = queryMode;
3565
3568
  this.collectionPath = collectionPath;
3566
3569
  this.scopePath = scopePath;
3567
3570
  this.adapter = createFirestoreAdapter(db, collectionPath);
@@ -3574,6 +3577,7 @@ var FirestoreEnterpriseBackendImpl = class _FirestoreEnterpriseBackendImpl {
3574
3577
  capabilities;
3575
3578
  collectionPath;
3576
3579
  scopePath;
3580
+ queryMode;
3577
3581
  adapter;
3578
3582
  pipelineAdapter;
3579
3583
  // --- Reads ---
@@ -3835,11 +3839,14 @@ var FirestoreEnterpriseBackendImpl = class _FirestoreEnterpriseBackendImpl {
3835
3839
  function createFirestoreEnterpriseBackend(db, collectionPath, options = {}) {
3836
3840
  const requestedMode = options.defaultQueryMode ?? "pipeline";
3837
3841
  const isEmulator = !!process.env.FIRESTORE_EMULATOR_HOST;
3838
- const effectiveMode = isEmulator && requestedMode === "pipeline" ? "classic" : requestedMode;
3839
- if (isEmulator && requestedMode === "pipeline" && effectiveMode === "classic" && !_emulatorFallbackWarned) {
3842
+ const emulatorEdition = (process.env.FIRESTORE_EMULATOR_EDITION ?? "").trim().toLowerCase();
3843
+ const emulatorIsEnterprise = emulatorEdition === "enterprise";
3844
+ const emulatorForcesClassic = isEmulator && !emulatorIsEnterprise;
3845
+ const effectiveMode = emulatorForcesClassic && requestedMode === "pipeline" ? "classic" : requestedMode;
3846
+ if (emulatorForcesClassic && requestedMode === "pipeline" && effectiveMode === "classic" && !_emulatorFallbackWarned) {
3840
3847
  _emulatorFallbackWarned = true;
3841
3848
  console.warn(
3842
- "[firegraph] Firestore Enterprise pipeline mode is unavailable in the emulator; falling back to classic Query API for this run. Set `defaultQueryMode: 'classic'` to silence this warning."
3849
+ "[firegraph] Firestore Enterprise pipeline mode is unavailable in the default emulator; falling back to classic Query API for this run. If you are running firebase-tools v15.14+ with the enterprise-edition emulator (`firebase emulators:start --database-edition enterprise`), set `FIRESTORE_EMULATOR_EDITION=enterprise` in your environment to honor pipeline mode. Otherwise set `defaultQueryMode: 'classic'` to silence this warning."
3843
3850
  );
3844
3851
  }
3845
3852
  if (!isEmulator && requestedMode === "classic" && !_classicInProductionWarned) {