@ignex/ninox 0.1.6 → 0.2.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/dist/index.d.ts CHANGED
@@ -1,7 +1,7 @@
1
1
  import * as mongodb from 'mongodb';
2
- import { Db, MongoClient, ClientSession, Document, Filter, Hint, CollationOptions, ReadPreferenceLike, ReadConcern, WriteConcern, WithId, Condition, RootFilterOperators, Collection, FindOptions, Sort, FindCursor, ObjectId, Decimal128, ReadConcernLike, AggregateOptions, AggregationCursor, CreateCollectionOptions, TransactionOptions, InsertOneOptions, InsertOneResult, InsertManyResult, UpdateOptions, UpdateResult, FindOneAndUpdateOptions, DeleteResult, ChangeStreamOptions, ChangeStream } from 'mongodb';
3
- import { L as LoggerLike } from './timeout-B10CTiGm.js';
4
- export { C as CacheOptions, a as LRU, b as LRUOptions, c as LogFn, d as LogLevel, e as createCachedAsyncFactory, f as createCachedFactory, g as createConsoleLogger, h as createNoopLogger, i as hashString, s as sleep, j as sleepJittered, k as stableHash, l as stableStringify, w as withTimeout } from './timeout-B10CTiGm.js';
2
+ import { Db, MongoClient, ClientSession, Document, Filter, Hint, CollationOptions, ReadPreferenceLike, ReadConcernLike, WriteConcern, WithId, Condition, RootFilterOperators, Collection, FindOptions, Sort, FindCursor, ObjectId, Long, Decimal128, IndexDirection, CreateIndexesOptions, AggregateOptions, AggregationCursor, CreateCollectionOptions, TransactionOptions as TransactionOptions$1, InsertOneOptions, InsertOneResult, InsertManyResult, UpdateOptions, UpdateResult, FindOneAndUpdateOptions, DeleteResult, ChangeStreamOptions, ChangeStream } from 'mongodb';
3
+ import { L as LoggerLike } from './timeout-BaP92Iyg.js';
4
+ export { C as CacheOptions, a as LRU, b as LRUOptions, c as LogFn, d as LogLevel, e as createCachedAsyncFactory, f as createCachedFactory, g as createConsoleLogger, h as createNoopLogger, i as hashString, s as sleep, j as sleepJittered, k as stableHash, l as stableStringify, w as withTimeout } from './timeout-BaP92Iyg.js';
5
5
  import * as bson from 'bson';
6
6
 
7
7
  /**
@@ -297,12 +297,11 @@ declare class InFlight {
297
297
  interface QueryCacheOptions {
298
298
  /** Max cached entries (default 500). */
299
299
  maxSize?: number;
300
- /** Per-entry TTL in ms (default 0 = no expiry). */
300
+ /** Per-entry TTL in ms (default 30_000; set 0 explicitly for no expiry). */
301
301
  ttlMs?: number;
302
302
  /**
303
303
  * Clone results on every read so callers can't mutate the shared cache entry
304
- * (default false — cloning has a per-read cost; treat cached results as
305
- * read-only when disabled).
304
+ * (default true; set false only for read-only results where zero-copy matters).
306
305
  */
307
306
  clone?: boolean;
308
307
  }
@@ -326,15 +325,15 @@ interface QueryCacheStats {
326
325
  evictions: number;
327
326
  }
328
327
  /**
329
- * Compose the "collection" part of a cache key, namespaced by the DATABASE name.
330
- * One service shares a single QueryCache + InFlight across every DB client; without
331
- * the namespace, same-named physical collections in different databases would
332
- * collide — a read on DB A could be served DB B's cached rows, and identical
328
+ * Compose the collection part of a cache key, namespaced by deployment and DB.
329
+ * One service shares a QueryCache + InFlight across every client; without these
330
+ * namespaces, same-named physical collections in different databases/clusters
331
+ * would collide — a read on DB A could be served DB B's cached rows, and identical
333
332
  * concurrent reads across DBs could coalesce into one driver call. Reads,
334
333
  * write-through invalidations, and change-stream invalidations MUST all use the
335
334
  * same namespace so they agree.
336
335
  */
337
- declare const cacheCollectionKey: (dbName: string, physical: string) => string;
336
+ declare const cacheCollectionKey: (dbName: string, physical: string, clusterNamespace?: string) => string;
338
337
  /**
339
338
  * Read-through query cache with per-collection invalidation.
340
339
  *
@@ -345,8 +344,8 @@ declare const cacheCollectionKey: (dbName: string, physical: string) => string;
345
344
  * collections changes. Invalidation is WRITE-THROUGH only: the ORM drops a
346
345
  * collection's entries on every write it performs. Reads are NOT invalidated by
347
346
  * external writers (other processes, the raw `client` escape hatch, or direct
348
- * DB writes) — with `ttlMs: 0` (default) those reads stay stale indefinitely,
349
- * so multi-writer deployments should set `ttlMs` or use the change-stream aware
347
+ * DB writes). The default 30-second TTL bounds staleness; `ttlMs: 0` explicitly
348
+ * disables expiry, so multi-writer deployments can also use the change-stream aware
350
349
  * `createHotCache()`. Perf wins: cache hits perform zero driver round-trips.
351
350
  */
352
351
  declare class QueryCache {
@@ -411,14 +410,6 @@ declare const createMongoCapabilitiesStore: () => MongoCapabilitiesStore;
411
410
  /** Probe a connected client/db via `hello`. */
412
411
  declare const probeMongoCapabilities: (client: MongoClient | Db | null | undefined) => Promise<MongoCapabilities>;
413
412
 
414
- /**
415
- * The ORM's error classes (`AppError` → `DomainError` / `InfraError` /
416
- * `BadRequest`), their type guards, and the `ERROR_HTTP_STATUS` table that sets
417
- * each error's `statusCode` at construction.
418
- *
419
- * A leaf module: nothing else in `src/errors/` imports this (so `driver-map.ts`
420
- * and `http-status.ts` can depend on it without cycles).
421
- */
422
413
  interface ErrorContext {
423
414
  db?: string;
424
415
  collection?: string;
@@ -437,23 +428,47 @@ declare class AppError extends Error {
437
428
  readonly code: string;
438
429
  readonly statusCode: number;
439
430
  readonly extra?: Record<string, unknown>;
440
- constructor(code: string, message: string, statusCode?: number, extra?: Record<string, unknown>);
441
431
  /**
442
- * Stable, client-safe serialization for framework error middleware: a
443
- * framework can forward `JSON.stringify(error)` (or `error.toJSON()`) straight
444
- * to the client — no parsing of server internals. `stack` is dropped; the
445
- * shape is always `{ name, code, message, statusCode, ...(extra) }`.
432
+ * Whether `message`/`extra` may be sent to a CLIENT.
433
+ *
434
+ * Fail-closed: a 4xx message is the caller's contract, a 5xx message is an
435
+ * operator detail that may quote a driver, a host or a query. Pass `expose`
436
+ * explicitly to override — only for a 5xx whose text was written for callers
437
+ * (e.g. `new InfraError("DRAINING", "queue is draining", extra, true)`).
438
+ */
439
+ readonly expose: boolean;
440
+ constructor(code: string, message: string, statusCode?: number, extra?: Record<string, unknown>, expose?: boolean);
441
+ /**
442
+ * Full, stack-free shape for LOGS and typed consumers:
443
+ * `{ name, code, message, statusCode, ...(extra) }`.
444
+ *
445
+ * It carries the real message, so it is NOT the client path — use
446
+ * {@link toClientPayload} (or `serializeError`) for anything a caller sees, and
447
+ * prefer `logger.error({ err })` so pino's own serializer keeps the stack in the
448
+ * log rather than in a payload.
446
449
  */
447
450
  toJSON(): Record<string, unknown>;
451
+ /**
452
+ * The client-safe payload — the same shape as {@link toJSON}, except that a
453
+ * non-exposed error's `message` is replaced by the canonical reason phrase and
454
+ * its `extra` is dropped. A framework can forward this (or `serializeError`'s
455
+ * result) without auditing what the message might contain.
456
+ *
457
+ * @param options - `expose: true` forces the real (masked) message + extra.
458
+ * @returns The client payload.
459
+ */
460
+ toClientPayload(options?: {
461
+ expose?: boolean;
462
+ }): Record<string, unknown>;
448
463
  }
449
464
  declare class DomainError extends AppError {
450
- constructor(code: string, message: string, extra?: Record<string, unknown>);
465
+ constructor(code: string, message: string, extra?: Record<string, unknown>, expose?: boolean);
451
466
  }
452
467
  declare class InfraError extends AppError {
453
- constructor(code: string, message: string, extra?: Record<string, unknown>);
468
+ constructor(code: string, message: string, extra?: Record<string, unknown>, expose?: boolean);
454
469
  }
455
470
  declare class BadRequest extends DomainError {
456
- constructor(message: string, extra?: Record<string, unknown>);
471
+ constructor(message: string, extra?: Record<string, unknown>, expose?: boolean);
457
472
  }
458
473
  declare const isAppError: (err: unknown) => err is AppError;
459
474
  declare const isDomainError: (err: unknown) => err is DomainError;
@@ -483,8 +498,16 @@ declare const isMappedMongoError: (error: unknown) => error is AppError;
483
498
 
484
499
  /** Effective HTTP status for any thrown value: AppError-aware, raw → 500 (503 transient). */
485
500
  declare const httpStatusForError: (err: unknown) => number;
501
+ /** Options for {@link serializeError}. */
502
+ interface SerializeErrorOptions {
503
+ /**
504
+ * Include the real message (and `extra`) even for a non-exposed error — the
505
+ * development / trusted-caller path. It is still credential-masked.
506
+ */
507
+ expose?: boolean;
508
+ }
486
509
  /**
487
- * Reduce any thrown value to a stable, client-safe error payload:
510
+ * Reduce any thrown value to a stable, CLIENT-SAFE error payload:
488
511
  * `{ name, code, message, statusCode, ...(extra) }`.
489
512
  *
490
513
  * Raw driver errors are mapped through `mapMongoDriverError` first, so a
@@ -495,8 +518,15 @@ declare const httpStatusForError: (err: unknown) => number;
495
518
  * const payload = serializeError(err, { db, collection, op });
496
519
  * res.status(payload.statusCode).json(payload);
497
520
  * });
521
+ *
522
+ * Fail-closed by default: a 4xx message/extra is the caller's contract, while a
523
+ * 5xx message is replaced by the canonical reason phrase (`Internal Server
524
+ * Error`, `Service Unavailable`, …) and `extra` is dropped — a driver message
525
+ * that quotes a host, a query or a stored value never reaches a client. The
526
+ * detail stays on the error itself for logs; pass `{ expose: true }` (or a
527
+ * per-error `expose`) to opt out for a trusted caller.
498
528
  */
499
- declare const serializeError: (err: unknown, ctx?: ErrorContext) => Record<string, unknown>;
529
+ declare const serializeError: (err: unknown, ctx?: ErrorContext, options?: SerializeErrorOptions) => Record<string, unknown>;
500
530
 
501
531
  /**
502
532
  * Transient-error detection: which MongoDB errors are safe to retry. This is a
@@ -526,7 +556,9 @@ declare const isTransactionUnsupportedError: (error: unknown) => boolean;
526
556
 
527
557
  /** Minimal transaction runner surface (satisfied by the service `transaction`). */
528
558
  interface MongoTransactionRunner {
529
- transaction: <T>(fn: (session: ClientSession | null) => Promise<T>) => Promise<T>;
559
+ transaction: <T>(fn: (session: ClientSession | null) => Promise<T>, options?: {
560
+ allowNonTransactionalFallback?: boolean;
561
+ }) => Promise<T>;
530
562
  }
531
563
  interface GracefulTransactionOptions {
532
564
  capabilities?: ReturnType<typeof createMongoCapabilitiesStore>;
@@ -534,17 +566,18 @@ interface GracefulTransactionOptions {
534
566
  logger?: LoggerLike;
535
567
  /** Map driver errors to typed DomainError/InfraError before rethrowing (default true). */
536
568
  wrapMongoErrors?: boolean;
569
+ /** Explicitly permit non-atomic execution on deployments without transactions. */
570
+ allowNonTransactionalFallback?: boolean;
537
571
  }
538
572
  /**
539
- * Run `fn` inside a transaction when the deployment supports it; otherwise run
540
- * with a `null` session (no-op fallback). Also handles "transactions
541
- * unsupported" errors by re-running with a null session.
573
+ * Run `fn` inside a transaction. Unsupported deployments throw unless
574
+ * `allowNonTransactionalFallback: true` explicitly permits a `null` session.
542
575
  *
543
576
  * When capability state is UNKNOWN (probe failed/timed out and no URL hint or
544
577
  * env override says otherwise), we ATTEMPT the real transaction rather than
545
578
  * silently downgrading — a transient startup blip must not turn an atomic
546
579
  * write into a non-atomic one. The catch path still falls back cleanly on a
547
- * genuinely unsupported deployment (at the cost of one failed round trip).
580
+ * genuinely unsupported deployment only after explicit opt-in.
548
581
  */
549
582
  declare const withGracefulMongoTransaction: <T>(runner: MongoTransactionRunner, fn: (session: ClientSession | null) => Promise<T>, options?: GracefulTransactionOptions) => Promise<T>;
550
583
 
@@ -661,9 +694,8 @@ interface MongoMigrationRunnerOptions {
661
694
  * - `./journal.ts` — lease-based `_migrations` journal (atomic, crash-safe)
662
695
  *
663
696
  * `up()` applies pending migrations in numeric order under an exclusive claim
664
- * with an auto-renewed lease (long migrations can't be stolen by another
665
- * runner, but a crashed runner's claim expires); `down()` rolls back applied
666
- * migrations in reverse order and validates its target BEFORE destroying
697
+ * with an auto-renewed, owner-fenced lease; `down()` uses the same fencing,
698
+ * rolls back in reverse order, and validates its target BEFORE destroying
667
699
  * anything; `status()` reports applied/pending; `create()` scaffolds a new file
668
700
  * atomically (`wx` — concurrent scaffolds never clobber each other).
669
701
  */
@@ -827,7 +859,7 @@ interface DoubleField extends FieldMeta {
827
859
  exclusiveMinimum?: boolean;
828
860
  exclusiveMaximum?: boolean;
829
861
  }
830
- /** Strict BSON `long` (int64) field — inferred as `number` (precision caveat). */
862
+ /** BSON `long` (int64) field — inferred as the driver's lossless `Long` type. */
831
863
  interface LongField extends FieldMeta {
832
864
  kind: 'long';
833
865
  minimum?: number;
@@ -1045,14 +1077,14 @@ interface QueryOptions {
1045
1077
  * Per-op schema-drift policy override for reads (see `MongoServiceConfig.drift`).
1046
1078
  * `true` → `'throw'`, `false` → `'off'`, or an explicit `DriftMode` string.
1047
1079
  * Unset inherits the service-level default (`'report'`). Only checked when a
1048
- * document is fetched from the DB (cache-miss); projected/partial reads are
1049
- * skipped.
1080
+ * document is fetched from the DB (cache-miss); projections ignore absent
1081
+ * required fields but still validate returned values.
1050
1082
  */
1051
1083
  drift?: DriftMode | boolean;
1052
1084
  /** Driver-level options forwarded untouched to the underlying call. */
1053
1085
  collation?: CollationOptions;
1054
1086
  readPreference?: ReadPreferenceLike;
1055
- readConcern?: ReadConcern;
1087
+ readConcern?: ReadConcernLike;
1056
1088
  writeConcern?: WriteConcern;
1057
1089
  comment?: string | Document;
1058
1090
  let?: Document;
@@ -1222,7 +1254,7 @@ type InferField<T extends SchemaType> = T extends {
1222
1254
  kind: 'double';
1223
1255
  } ? number : T extends {
1224
1256
  kind: 'long';
1225
- } ? number : T extends {
1257
+ } ? Long : T extends {
1226
1258
  kind: 'decimal';
1227
1259
  } ? Decimal128 : T extends {
1228
1260
  kind: 'geoPoint';
@@ -1254,13 +1286,8 @@ type InferDoc<T extends ObjectField> = InferObject<T>;
1254
1286
 
1255
1287
  /** A Mongo index definition usable by `createIndexes`. */
1256
1288
  interface IndexSpec {
1257
- key: Record<string, 1 | -1 | 'text' | 'hashed' | '2dsphere'>;
1258
- options?: {
1259
- name?: string;
1260
- unique?: boolean;
1261
- sparse?: boolean;
1262
- expireAfterSeconds?: number;
1263
- };
1289
+ key: Record<string, IndexDirection>;
1290
+ options?: CreateIndexesOptions;
1264
1291
  }
1265
1292
  /** Auto-timestamp field names maintained by the ORM when `timestamps` is set. */
1266
1293
  interface CollectionTimestamps {
@@ -1303,6 +1330,8 @@ interface DBClientDefinition<TCollections extends Record<string, CollectionLike>
1303
1330
  /** Per-logical-collection physical-name overrides. */
1304
1331
  collectionPhysicalNames?: Partial<Record<string, string>>;
1305
1332
  connectTimeoutMs?: number;
1333
+ /** Enable driver command events before pools open (required for wire tracing). */
1334
+ monitorCommands?: boolean;
1306
1335
  readPreference?: ReadPreferenceLike;
1307
1336
  readConcern?: ReadConcernLike;
1308
1337
  writeConcern?: WriteConcern;
@@ -1452,13 +1481,16 @@ declare const manyToMany: <const C extends string, const A extends string, const
1452
1481
 
1453
1482
  interface PopulateOptions {
1454
1483
  maxBatchSize?: number;
1484
+ /** Cache keys only within this populate call (default true). */
1455
1485
  cache?: boolean;
1456
- /**
1457
- * Cap on docs fetched per foreign-key batch (default 10_000). A `hasMany` /
1458
- * `manyToMany` relation with more children than this is silently truncated —
1459
- * raise the cap when you expect larger joins.
1460
- */
1486
+ /** Opt into the shared read-through query cache (default false for fresh joins). */
1487
+ queryCache?: boolean;
1488
+ /** Safety cap per foreign-key batch. Exceeding it throws instead of truncating. */
1461
1489
  maxDocs?: number;
1490
+ session?: ClientSession;
1491
+ maxTimeMS?: number;
1492
+ readPreference?: ReadPreferenceLike;
1493
+ readConcern?: ReadConcernLike;
1462
1494
  }
1463
1495
 
1464
1496
  /** Structured metadata attached to every logged DB operation. */
@@ -1475,12 +1507,14 @@ interface DbOpMeta {
1475
1507
  */
1476
1508
  params?: unknown;
1477
1509
  }
1478
-
1479
1510
  /**
1480
- * Aggregation types + the shared context handed to the aggregation op-group
1481
- * factories (`./aggregate.ts`, `./group.ts`, `./text-search.ts`,
1482
- * `./lookup-join.ts`). Type-only plus the `AggregationCtx` interface.
1511
+ * The ignex-debugbar `debugQuery` free helper (`@ignex/core/debug`), resolved
1512
+ * lazily so the ORM stays standalone: `undefined` until probed, `null` when
1513
+ * `@ignex/core` is not installed (plain ORM usage), the function otherwise.
1514
+ * `debugQuery` itself is a zero-cost pass-through when no request trace is
1515
+ * active, so production ignex apps pay nothing either.
1483
1516
  */
1517
+ type DebugQuery = <T>(sql: string, params: unknown, fn: () => T | Promise<T>) => T | Promise<T>;
1484
1518
 
1485
1519
  interface GroupByConfig {
1486
1520
  /** Group key: a field name or a document of `$`-expressions. */
@@ -1524,7 +1558,9 @@ interface PipelineCustomization {
1524
1558
  }
1525
1559
  interface AggregationOpsOptions {
1526
1560
  resolveCollectionName: (logical: string) => string;
1561
+ cacheNamespace?: string;
1527
1562
  wrapMongoErrors?: boolean;
1563
+ debugQuery?: DebugQuery | null;
1528
1564
  /** Shared read cache (`undefined` = caching disabled). */
1529
1565
  cache?: QueryCache;
1530
1566
  /** Service default for in-flight read dedup. */
@@ -1980,17 +2016,6 @@ type UpdateOperators<T> = {
1980
2016
  */
1981
2017
  type UpdateInput<T> = Partial<T> | UpdateOperators<T>;
1982
2018
 
1983
- /**
1984
- * Shared CRUD context: the cross-cutting helpers every CRUD op group depends
1985
- * on (collection resolution, tracing, retry plumbing, cache/dedup/drift read
1986
- * pipeline, auto-timestamps, `select` normalization).
1987
- *
1988
- * `makeCrudOps` (see `./index.ts`) builds ONE context via `createCrudContext`
1989
- * and hands it to the read / write / watch op-group factories, so the helpers
1990
- * live in exactly one place instead of being duplicated per op. This module is
1991
- * the dependency-injection seam of the CRUD layer.
1992
- */
1993
-
1994
2019
  type ColNames<TClients extends DbClientsDefinition, TDb extends ExtractDbNames<TClients>> = ExtractCollectionNames<TClients, TDb>;
1995
2020
  /** Input accepted by insert ops: the doc without `_id`, or with an explicit `_id`. */
1996
2021
  type InsertInput<T> = Omit<T, '_id'> & {
@@ -2018,13 +2043,17 @@ type FindQueryOptions<T> = FindOptions & QueryOptions & {
2018
2043
  type TimestampsByCollection = Record<string, CollectionTimestamps | undefined>;
2019
2044
  interface CrudOpsOptions {
2020
2045
  resolveCollectionName: (logical: string) => string;
2046
+ /** Stable, non-secret identity of the MongoDB deployment for shared caches. */
2047
+ cacheNamespace?: string;
2021
2048
  wrapMongoErrors?: boolean;
2049
+ debugQuery?: DebugQuery | null;
2022
2050
  cache?: QueryCache;
2023
2051
  dedupeReads?: boolean;
2024
2052
  inFlight?: InFlight;
2025
2053
  hooks?: HooksRegistry;
2026
2054
  /** Auto-timestamp field names per collection (from the collection definition). */
2027
2055
  timestamps?: TimestampsByCollection;
2056
+ validateWrites?: boolean;
2028
2057
  /** Service-level schema-drift policy for reads (default `'report'`). */
2029
2058
  drift?: DriftMode;
2030
2059
  /** Resolve the declared schema for a logical collection (drift detection). */
@@ -2083,6 +2112,8 @@ interface MongoServiceConfig {
2083
2112
  migrationDir?: string;
2084
2113
  appName?: string;
2085
2114
  logger?: LoggerLike;
2115
+ /** Explicit host tracer (Ignex debugQuery); null disables the optional probe. */
2116
+ debugQuery?: DebugQuery | null;
2086
2117
  /**
2087
2118
  * Map driver errors to typed DomainError/InfraError before rethrowing. ON by
2088
2119
  * default — set `false` to surface raw driver errors instead.
@@ -2096,9 +2127,9 @@ interface MongoServiceConfig {
2096
2127
  * INVALIDATION: entries are dropped write-through — every ORM write
2097
2128
  * invalidates that collection's cached reads. External writers (other
2098
2129
  * processes, the raw `client` escape hatch, direct DB writes) do NOT
2099
- * invalidate; with the default `ttlMs: 0` those reads stay stale
2100
- * indefinitely, so multi-writer deployments should set `QueryCacheOptions.ttlMs`,
2101
- * disable the cache, route latency-critical reads through the
2130
+ * invalidate. The default 30-second TTL bounds staleness; `ttlMs: 0`
2131
+ * explicitly selects unbounded entries. Multi-writer deployments can disable
2132
+ * the cache, route latency-critical reads through the
2102
2133
  * change-stream aware `createHotCache()`, or set `cacheWatch: true`.
2103
2134
  */
2104
2135
  cache?: QueryCache | QueryCacheOptions | null;
@@ -2113,6 +2144,8 @@ interface MongoServiceConfig {
2113
2144
  * `closeConnections()`. Default: false.
2114
2145
  */
2115
2146
  cacheWatch?: boolean;
2147
+ /** Permit transaction callbacks to run non-atomically on unsupported servers. Default: false. */
2148
+ allowNonTransactionalFallback?: boolean;
2116
2149
  /** Coalesce identical concurrent reads into one driver call. ON by default. */
2117
2150
  dedupeReads?: boolean;
2118
2151
  /**
@@ -2120,6 +2153,8 @@ interface MongoServiceConfig {
2120
2153
  * in-flight dedup even when the granular options are set. Defaults to true.
2121
2154
  */
2122
2155
  perf?: boolean;
2156
+ /** Validate inserts and replacements against the schema before sending them. Default: true. */
2157
+ validateWrites?: boolean;
2123
2158
  /**
2124
2159
  * Schema-drift policy for reads. When a document fetched from the DB
2125
2160
  * (cache-miss) doesn't match its declared schema:
@@ -2127,8 +2162,8 @@ interface MongoServiceConfig {
2127
2162
  * - `'throw'` — throw `DomainError SCHEMA_DRIFT` (the document is never
2128
2163
  * cached or returned)
2129
2164
  * - `'off'` — no drift checking (previous behavior)
2130
- * Detection-only: documents are never mutated. Projected/partial reads are
2131
- * skipped. Overridable per op via `QueryOptions.drift`.
2165
+ * Detection-only: documents are never mutated. Projected reads ignore absent
2166
+ * fields but validate returned values. Overridable via `QueryOptions.drift`.
2132
2167
  */
2133
2168
  drift?: DriftMode;
2134
2169
  }
@@ -2221,6 +2256,8 @@ interface CacheInvalidationRef {
2221
2256
  db: Db;
2222
2257
  /** PHYSICAL collection name — cache keys use it, so invalidation must too. */
2223
2258
  collection: string;
2259
+ /** Stable deployment identity shared with the manager's cache keys. */
2260
+ namespace?: string;
2224
2261
  }
2225
2262
  declare class CacheInvalidator {
2226
2263
  private cache;
@@ -2246,25 +2283,19 @@ declare class CacheInvalidator {
2246
2283
  private watchLoop;
2247
2284
  }
2248
2285
 
2249
- /**
2250
- * Pagination types + the shared context handed to the two pagination
2251
- * strategies (`./offset.ts`, `./cursor.ts`). Type-only plus the `PaginationCtx`
2252
- * interface, so the strategy modules and the composing `makePaginationOps`
2253
- * (in `./index.ts`) share one vocabulary without importing each other's logic.
2254
- */
2255
-
2256
2286
  interface PaginationConfig {
2257
2287
  page?: number;
2258
2288
  limit?: number;
2259
2289
  sort?: Record<string, 1 | -1>;
2260
2290
  /** Cap on the requested limit (default DEFAULT_MAX_LIMIT=1000). */
2261
2291
  maxLimit?: number;
2292
+ /** Maximum offset before callers must switch to keyset pagination (default 10_000). */
2293
+ maxOffset?: number;
2262
2294
  /**
2263
2295
  * Projection applied to the data facet (e.g. `{ _id: 1, updatedAt: 1 }`).
2264
2296
  *
2265
- * Enables lean list reads — only the projected fields cross the wire. When
2266
- * set, the schema-drift check is skipped for the page (projected docs
2267
- * intentionally lack the collection's full field set).
2297
+ * Enables lean list reads — only the projected fields cross the wire. Drift
2298
+ * checks ignore absent fields but still validate the returned values.
2268
2299
  */
2269
2300
  projection?: Document;
2270
2301
  /** Stages prepended to the data facet (e.g. extra $match). */
@@ -2281,6 +2312,8 @@ interface CursorPaginationConfig {
2281
2312
  * exist on every document for deterministic ordering.
2282
2313
  */
2283
2314
  sort: Record<string, 1 | -1>;
2315
+ /** Unique final sort field. Defaults to `_id`; custom fields must have a unique index. */
2316
+ uniqueTiebreaker?: string;
2284
2317
  /** Opaque cursor from a previous `nextCursor` — fetch the page after it. */
2285
2318
  after?: string;
2286
2319
  /** Opaque cursor — fetch the page before it (backward navigation). */
@@ -2298,7 +2331,9 @@ interface CursorPage<T> {
2298
2331
  }
2299
2332
  interface PaginationOpsOptions {
2300
2333
  resolveCollectionName: (logical: string) => string;
2334
+ cacheNamespace?: string;
2301
2335
  wrapMongoErrors?: boolean;
2336
+ debugQuery?: DebugQuery | null;
2302
2337
  /** Service-level schema-drift policy for reads (default `'report'`). */
2303
2338
  drift?: DriftMode;
2304
2339
  /** Resolve the declared schema for a logical collection (drift detection). */
@@ -2447,29 +2482,23 @@ declare const makeSchemaOps: (client: Db, _logger: LoggerLike, opts: SchemaOpsOp
2447
2482
  syncIndexes: (collection: string) => Promise<SyncIndexesResult>;
2448
2483
  };
2449
2484
 
2485
+ interface TransactionOptions extends TransactionOptions$1 {
2486
+ /** Explicitly permit non-atomic execution when transactions are unsupported. */
2487
+ allowNonTransactionalFallback?: boolean;
2488
+ }
2450
2489
  interface TransactionOpsOptions {
2451
2490
  migrationCollectionPhysical: string;
2452
- /** Map driver errors to typed DomainError/InfraError before rethrowing. */
2453
2491
  wrapMongoErrors?: boolean;
2492
+ allowNonTransactionalFallback?: boolean;
2454
2493
  }
2455
- /**
2456
- * Transaction + idempotent-migration ops for one database handle.
2457
- */
2494
+ /** Transaction + fenced idempotent-migration ops for one database handle. */
2458
2495
  declare const makeTransactionOps: (client: MongoClient, handle: Db, logger: LoggerLike, _config: Record<string, unknown>, opts: TransactionOpsOptions) => {
2459
2496
  transaction: <T>(fn: (session: ClientSession | null) => Promise<T>, options?: TransactionOptions) => Promise<T>;
2460
- migrate: (name: string, fn: (session: ClientSession | null) => Promise<void>, filePath?: string) => Promise<void>;
2497
+ migrate: (name: string, fn: (session: ClientSession | null) => Promise<void>, filePath?: string, options?: {
2498
+ allowNonTransactionalFallback?: boolean;
2499
+ }) => Promise<void>;
2461
2500
  };
2462
2501
 
2463
- /**
2464
- * Per-database manager assembly. `buildManager` is the composition point of the
2465
- * op-factory pattern: it builds the collection registry (schema/hooks/
2466
- * timestamps), resolves logical→physical names, and **spreads** every
2467
- * `make*Ops` factory into one `CollectionManager` object per database.
2468
- *
2469
- * The `CollectionManager` type mirrors that spread as an intersection so both
2470
- * the runtime value and its type stay in sync from a single source.
2471
- */
2472
-
2473
2502
  /** One collection manager per connected DB — the ORM's primary surface. */
2474
2503
  type CollectionManager<TClients extends DbClientsDefinition, TDb extends ExtractDbNames<TClients>> = CrudOps<TClients, TDb> & ReturnType<typeof makePaginationOps<TClients, TDb>> & ReturnType<typeof makeAggregationOps<TClients, TDb>> & ReturnType<typeof makeSchemaOps> & ReturnType<typeof makeTransactionOps> & {
2475
2504
  /**
@@ -2482,6 +2511,8 @@ type CollectionManager<TClients extends DbClientsDefinition, TDb extends Extract
2482
2511
  }, options?: PopulateOptions) => Promise<Array<T & JoinedFields<TClients, TDb, R>>>;
2483
2512
  /** Raw `db()` handle escape hatch. */
2484
2513
  client: Db;
2514
+ /** Raw pooled client for host integrations (e.g. command monitoring). */
2515
+ mongoClient: MongoClient;
2485
2516
  /** Reference to sibling managers (cross-DB). */
2486
2517
  db: Record<string, unknown>;
2487
2518
  };
@@ -2768,4 +2799,4 @@ declare const createMongoToolkit: <TClients extends DbClientsDefinition = DbClie
2768
2799
  };
2769
2800
  type MongoToolkit<TClients extends DbClientsDefinition> = ReturnType<typeof createMongoToolkit<TClients>>;
2770
2801
 
2771
- export { type AccumulatorResult, type AccumulatorSpec, type Added, type AggregationMeta, type AggregationStages, type AnyField, AppError, type ArrayField, BadRequest, type BelongsToRelation, type BooleanField, type CacheInvalidationRef, CacheInvalidator, type Chainable, type CollectionDefinition, type CollectionDoc, type CollectionLike, type CollectionManager, type CollectionMap, type CollectionName, type CollectionTimestamps, type CollectionValue, type CrudListQuery, type CrudOps, type CursorPage, type CursorPaginationConfig, type DBClientDefinition, DEFAULT_FIND_LIMIT, DEFAULT_MAX_LIMIT, DataLoader, type DataLoaderOptions, type DateField, type DateRangeConfig, type DbClientsDefinition, type DbHealthResult, type DecimalField, DomainError, type DoubleField, type DriftIssue, type DriftIssueCode, type DriftMode, ERROR_HTTP_STATUS, type EnumField, type ErrorContext, type ExprResult, type ExtractCollectionNames, type ExtractCollectionType, type ExtractDbNames, type FacetOutput, type FacetPipelineStage, type FacetSpec, type FieldFlags, type FieldMeta, type FieldName, type FieldRef, type FilterInput, type FindQueryOptions, type ForeignDocOf, type GeoNearOutput, type GeoNearSpec, type GeoPoint, type GeoPointField, type GracefulTransactionOptions, type GroupByConfig, type GroupSpec, type Grouped, HOOK_NAMES, type HasManyRelation, type HealthReport, type Hook, type HookContext, type HookMap, type HookName, type HooksRegistry, HotCache, type HotCacheMode, type HotCacheOptions, type HotCacheStats, type HotCollectionRef, type HotQueryAccessor, type HotQueryConfig, type HotQueryStats, InFlight, type IndexSpec, type InferDoc, type InferField, InfraError, type InsertInput, type IntegerField, type JoinedFields, type KeysetCursor, LoggerLike, type LongField, type LookupConfig, type LookupJoinedFor, type LookupParams, type LookupSpecFor, MAX_BATCH_OPS, type ManyToManyRelation, type MigrationContext, type MigrationModule, type MongoCapabilities, type MongoCapabilitiesStore, type MongoJsonSchema, type MongoMigrationRunner, type MongoMigrationRunnerOptions, type MongoService, type MongoServiceConfig, type MongoToolkit, type MongoToolkitOptions, type MongoTransactionRunner, type NamedCollection, type NamedCollectionDefinition, type NamedObjectField, type NormalizedPagination, type NullField, type NumberBounds, type NumberField, type ObjectField, type ObjectIdField, type PaginationConfig, type PaginationResult, PipelineBuilder, type PipelineCustomization, type PipelineStage, type PopulateOptions, type Projected, type Projection, QueryBuilder, type QueryBuilderContext, QueryCache, type QueryCacheOptions, type QueryCacheStats, type QueryOptions, type RawField, type RelationDef, type RelationDefBase, type RemoveIndexSignature, type Repository, type RepositoryOptions, type ResolvedQueryOptions, type RetryOptions, type SchemaType, type SearchConfig, type SortKeys, type StringField, type SyncIndexesResult, TRANSIENT_MONGO_ERROR_CODES, type TimestampsByCollection, type Unsetted, type UnwindSpec, type Unwound, type UpdateInput, type UpdateOperators, type ValidRelation, type VersionedUpdateResult, belongsTo, buildKeysetFilter, buildMongoActiveFilter, buildPaginationResult, cacheCollectionKey, canonicalKey, createHotCache, createMongoCapabilitiesStore, createMongoMigrationRunner, createMongoService, createMongoToolkit, createRepository, createResolveCollectionName, decodeCursor, defineCollection, defineCollections, encodeCursor, hasMany, httpStatusForError, isAppError, isDomainError, isInfraError, isMappedMongoError, isMongoDuplicateKeyError, isMongoTransientError, isTransactionUnsupportedError, manyToMany, mapMongoDriverError, mergeMongoActiveFilter, mergeMongoFilters, normalizeMongoUrl, normalizePageLimit, optional, probeMongoCapabilities, runHooks, s, serializeError, stripDocumentId, stripPrimaryKey, toMongoSchema, toMongoValidator, validateDoc, withDefault, withGracefulMongoTransaction, withRetry, withTransaction };
2802
+ export { type AccumulatorResult, type AccumulatorSpec, type Added, type AggregationMeta, type AggregationStages, type AnyField, AppError, type ArrayField, BadRequest, type BelongsToRelation, type BooleanField, type CacheInvalidationRef, CacheInvalidator, type Chainable, type CollectionDefinition, type CollectionDoc, type CollectionLike, type CollectionManager, type CollectionMap, type CollectionName, type CollectionTimestamps, type CollectionValue, type CrudListQuery, type CrudOps, type CursorPage, type CursorPaginationConfig, type DBClientDefinition, DEFAULT_FIND_LIMIT, DEFAULT_MAX_LIMIT, DataLoader, type DataLoaderOptions, type DateField, type DateRangeConfig, type DbClientsDefinition, type DbHealthResult, type DebugQuery, type DecimalField, DomainError, type DoubleField, type DriftIssue, type DriftIssueCode, type DriftMode, ERROR_HTTP_STATUS, type EnumField, type ErrorContext, type ExprResult, type ExtractCollectionNames, type ExtractCollectionType, type ExtractDbNames, type FacetOutput, type FacetPipelineStage, type FacetSpec, type FieldFlags, type FieldMeta, type FieldName, type FieldRef, type FilterInput, type FindQueryOptions, type ForeignDocOf, type GeoNearOutput, type GeoNearSpec, type GeoPoint, type GeoPointField, type GracefulTransactionOptions, type GroupByConfig, type GroupSpec, type Grouped, HOOK_NAMES, type HasManyRelation, type HealthReport, type Hook, type HookContext, type HookMap, type HookName, type HooksRegistry, HotCache, type HotCacheMode, type HotCacheOptions, type HotCacheStats, type HotCollectionRef, type HotQueryAccessor, type HotQueryConfig, type HotQueryStats, InFlight, type IndexSpec, type InferDoc, type InferField, InfraError, type InsertInput, type IntegerField, type JoinedFields, type KeysetCursor, LoggerLike, type LongField, type LookupConfig, type LookupJoinedFor, type LookupParams, type LookupSpecFor, MAX_BATCH_OPS, type ManyToManyRelation, type MigrationContext, type MigrationModule, type MongoCapabilities, type MongoCapabilitiesStore, type MongoJsonSchema, type MongoMigrationRunner, type MongoMigrationRunnerOptions, type MongoService, type MongoServiceConfig, type MongoToolkit, type MongoToolkitOptions, type MongoTransactionRunner, type NamedCollection, type NamedCollectionDefinition, type NamedObjectField, type NormalizedPagination, type NullField, type NumberBounds, type NumberField, type ObjectField, type ObjectIdField, type PaginationConfig, type PaginationResult, PipelineBuilder, type PipelineCustomization, type PipelineStage, type PopulateOptions, type Projected, type Projection, QueryBuilder, type QueryBuilderContext, QueryCache, type QueryCacheOptions, type QueryCacheStats, type QueryOptions, type RawField, type RelationDef, type RelationDefBase, type RemoveIndexSignature, type Repository, type RepositoryOptions, type ResolvedQueryOptions, type RetryOptions, type SchemaType, type SearchConfig, type SortKeys, type StringField, type SyncIndexesResult, TRANSIENT_MONGO_ERROR_CODES, type TimestampsByCollection, type TransactionOptions, type Unsetted, type UnwindSpec, type Unwound, type UpdateInput, type UpdateOperators, type ValidRelation, type VersionedUpdateResult, belongsTo, buildKeysetFilter, buildMongoActiveFilter, buildPaginationResult, cacheCollectionKey, canonicalKey, createHotCache, createMongoCapabilitiesStore, createMongoMigrationRunner, createMongoService, createMongoToolkit, createRepository, createResolveCollectionName, decodeCursor, defineCollection, defineCollections, encodeCursor, hasMany, httpStatusForError, isAppError, isDomainError, isInfraError, isMappedMongoError, isMongoDuplicateKeyError, isMongoTransientError, isTransactionUnsupportedError, manyToMany, mapMongoDriverError, mergeMongoActiveFilter, mergeMongoFilters, normalizeMongoUrl, normalizePageLimit, optional, probeMongoCapabilities, runHooks, s, serializeError, stripDocumentId, stripPrimaryKey, toMongoSchema, toMongoValidator, validateDoc, withDefault, withGracefulMongoTransaction, withRetry, withTransaction };