@classytic/mongokit 3.25.0 → 3.29.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.
@@ -1,4 +1,4 @@
1
- import { t as createRepository } from "../create-repository-DA5VJh-3.mjs";
1
+ import { t as createRepository } from "../create-repository-uhKt_oUT.mjs";
2
2
  import { createConnection } from "mongoose";
3
3
  //#region src/testkit/index.ts
4
4
  function idempotentStop(server) {
@@ -1,4 +1,4 @@
1
- import { l as OP_REGISTRY, s as ALL_OPERATIONS, t as HOOK_PRIORITY } from "./Repository-KKR8jxfD.mjs";
1
+ import { c as ALL_OPERATIONS, t as HOOK_PRIORITY, u as OP_REGISTRY } from "./Repository-DThvFCaV.mjs";
2
2
  import { n as warn } from "./logger-K7dPmu2U.mjs";
3
3
  import { t as createError } from "./error-BuByZwKU.mjs";
4
4
  import { throwIfAborted, withRetry } from "@classytic/repo-core/repository";
@@ -1,7 +1,7 @@
1
1
  import { t as __exportAll } from "./rolldown-runtime-D7D4PA-g.mjs";
2
2
  import { n as warn } from "./logger-K7dPmu2U.mjs";
3
3
  import { t as createError } from "./error-BuByZwKU.mjs";
4
- import { isFilter } from "@classytic/repo-core/filter";
4
+ import { coerceFilterDates, isFilter } from "@classytic/repo-core/filter";
5
5
  //#region src/filter/compile.ts
6
6
  /**
7
7
  * Compile a Filter IR node to a MongoDB query object. Returns `{}`
@@ -34,47 +34,41 @@ const SHORTHAND_OPS = /* @__PURE__ */ new Set([
34
34
  "regex",
35
35
  "mod"
36
36
  ]);
37
- /** Range operators whose string values should be coerced to Date. */
38
- const RANGE_OPS = /* @__PURE__ */ new Set([
39
- "gt",
40
- "gte",
41
- "lt",
42
- "lte"
37
+ /** Logical operators whose operand is an array of sub-queries to recurse into. */
38
+ const LOGICAL_ARRAY_OPS = /* @__PURE__ */ new Set([
39
+ "$and",
40
+ "$or",
41
+ "$nor"
43
42
  ]);
44
- /** ISO-8601 date-only or datetime string pattern. */
45
- const ISO_DATE_RE = /^\d{4}-\d{2}-\d{2}/;
46
- /**
47
- * Coerce a string value to a Date when it looks like an ISO-8601 date.
48
- * Needed because MongoDB won't match a BSON Date field against a string
49
- * value even when using range operators — BSON type comparison treats
50
- * Date (type 9) and String (type 2) as distinct, so `{ createdAt: {
51
- * $gte: "2026-05-01" } }` never matches a Date-typed field.
52
- */
53
- function tryCoerceDate(value) {
54
- if (typeof value === "string" && ISO_DATE_RE.test(value)) {
55
- const d = new Date(value);
56
- return Number.isNaN(d.getTime()) ? value : d;
57
- }
58
- return value;
59
- }
60
43
  /**
61
- * Expand operator shorthand values in a plain Mongo-style query object.
44
+ * Expand operator shorthand values in a plain Mongo-style query object —
45
+ * `$`-prefixing is the ONE Mongo-dialect concern this function owns. Date
46
+ * coercion is delegated to `coerceFilterDates` (repo-core) so the ISO
47
+ * pattern has a single source of truth shared with the URL-parsing boundary.
48
+ *
62
49
  * Only expands nested objects whose keys are ALL in `SHORTHAND_OPS` — so
63
50
  * real nested documents (e.g. `address: { city: 'Dhaka' }`) pass through
64
51
  * unchanged, while `createdAt: { gte: '2026-04-01', lte: '2026-05-01' }`
65
- * becomes `createdAt: { $gte: Date(2026-04-01), $lte: Date(2026-05-01) }`.
66
- * String values on range operators are coerced to Date when they match the
67
- * ISO-8601 pattern, so BSON Date fields in MongoDB are compared correctly.
52
+ * becomes `createdAt: { $gte: '2026-04-01', $lte: '2026-05-01' }` for the
53
+ * coercion pass to type.
54
+ *
55
+ * Recurses `$and` / `$or` / `$nor` because a policy-scope merge conjoins the
56
+ * caller filter under `$and`, and un-prefixed shorthand nested there would
57
+ * otherwise reach `$match` as a literal field named `gte`.
68
58
  */
69
59
  function expandShorthands(obj) {
70
60
  const out = {};
71
61
  for (const [key, value] of Object.entries(obj)) {
62
+ if (LOGICAL_ARRAY_OPS.has(key) && Array.isArray(value)) {
63
+ out[key] = value.map((entry) => entry !== null && typeof entry === "object" && !Array.isArray(entry) ? expandShorthands(entry) : entry);
64
+ continue;
65
+ }
72
66
  if (value !== null && typeof value === "object" && !Array.isArray(value)) {
73
67
  const nested = value;
74
68
  const keys = Object.keys(nested);
75
69
  if (keys.length > 0 && keys.every((k) => !k.startsWith("$") && SHORTHAND_OPS.has(k))) {
76
70
  const expanded = {};
77
- for (const [op, opVal] of Object.entries(nested)) expanded[`$${op}`] = RANGE_OPS.has(op) ? tryCoerceDate(opVal) : opVal;
71
+ for (const [op, opVal] of Object.entries(nested)) expanded[`$${op}`] = opVal;
78
72
  out[key] = expanded;
79
73
  continue;
80
74
  }
@@ -85,7 +79,7 @@ function expandShorthands(obj) {
85
79
  }
86
80
  function compileFilterToMongo(input) {
87
81
  if (!input) return {};
88
- if (!isFilter(input)) return expandShorthands(input);
82
+ if (!isFilter(input)) return coerceFilterDates(expandShorthands(input));
89
83
  return compile(input);
90
84
  }
91
85
  function compile(filter) {
@@ -185,6 +185,142 @@ declare function elasticSearchPlugin(options: ElasticSearchOptions): Plugin;
185
185
  */
186
186
  declare function fieldFilterPlugin(fieldPreset: FieldPreset): Plugin;
187
187
  //#endregion
188
+ //#region src/plugins/idempotency-store.plugin.d.ts
189
+ interface IdempotencyStorePluginOptions {
190
+ /** Field carrying the deterministic operation key. @default `'key'` */
191
+ keyField?: string;
192
+ /** Field carrying the row's claim status. @default `'status'` */
193
+ statusField?: string;
194
+ /** Field carrying the current holder's lease token. @default `'leaseToken'` */
195
+ leaseTokenField?: string;
196
+ /** Field carrying the lease expiry timestamp. @default `'leaseExpiresAt'` */
197
+ leaseExpiresAtField?: string;
198
+ /** Field counting claim acquisitions (1 = first). @default `'attempts'` */
199
+ attemptsField?: string;
200
+ /** Field carrying saga resume data (Mixed). @default `'progress'` */
201
+ progressField?: string;
202
+ /** Field carrying the replayable success outcome (Mixed). @default `'result'` */
203
+ resultField?: string;
204
+ /** Field carrying the terminal failure code. @default `'failureCode'` */
205
+ failureCodeField?: string;
206
+ /** Field carrying the last error message (diagnostics). @default `'lastError'` */
207
+ lastErrorField?: string;
208
+ /** Status value of an in-flight claim. @default `'in_flight'` */
209
+ inFlightStatus?: string;
210
+ /** Terminal success status. @default `'succeeded'` */
211
+ succeededStatus?: string;
212
+ /** Terminal failure status. @default `'failed'` */
213
+ failedStatus?: string;
214
+ /** Claim lease (ms) — must outlive the longest guarded execution. @default 60_000 */
215
+ defaultLeaseMs?: number;
216
+ /**
217
+ * Re-acquisition ceiling. When > 0, an expired in-flight claim whose
218
+ * `attempts` already reached this value returns `exhausted` instead of
219
+ * re-acquiring — the bounded-retry escalation valve for operations whose
220
+ * external side effect is idempotent but may be wedged. 0 = unbounded
221
+ * (flow/order semantics: recovery always re-claims). @default 0
222
+ */
223
+ maxAttempts?: number;
224
+ }
225
+ /** Outcome of `claimKey()` — the claim decision matrix. */
226
+ type IdempotencyClaim<TProgress = Record<string, unknown>, TResult = unknown> =
227
+ /**
228
+ * This caller owns the lease — execute. `progress` present ⇒ a stale-lease
229
+ * re-acquire after a previous attempt persisted resume data (crash
230
+ * recovery): resume from it instead of re-running completed pivots.
231
+ * `attempt` is 1 on a fresh claim.
232
+ */
233
+ {
234
+ kind: 'acquired';
235
+ leaseToken: string;
236
+ attempt: number;
237
+ progress?: TProgress;
238
+ } |
239
+ /** A previous execution succeeded — replay its stored outcome. */
240
+ {
241
+ kind: 'completed';
242
+ result?: TResult;
243
+ } |
244
+ /** A previous execution failed terminally — replay the recorded code. */
245
+ {
246
+ kind: 'failed';
247
+ failureCode?: string;
248
+ error?: string;
249
+ } |
250
+ /** Another caller holds a live lease. `progress` (when persisted) lets a
251
+ * domain layer act on completed pivots without owning the lease — e.g.
252
+ * finish an idempotent post-pivot sync while the holder is wedged. */
253
+ {
254
+ kind: 'busy';
255
+ progress?: TProgress;
256
+ leaseToken?: string;
257
+ } |
258
+ /** `maxAttempts` re-acquisitions exhausted — escalate to a human. */
259
+ {
260
+ kind: 'exhausted';
261
+ attempts: number;
262
+ progress?: TProgress;
263
+ };
264
+ /**
265
+ * Methods contributed by `idempotencyStorePlugin()`. Use as a type assertion
266
+ * when constructing the repo (same convention as `LeaseMethods`).
267
+ */
268
+ interface IdempotencyStoreMethods<TProgress = Record<string, unknown>, TResult = unknown> {
269
+ /**
270
+ * Atomically claim `key`. Exactly one concurrent caller acquires; the rest
271
+ * branch on the row's durable state — see {@link IdempotencyClaim}.
272
+ *
273
+ * `seed` merges extra fields into the row on FIRST insert only (domain
274
+ * columns, tenant stamp). It never mutates an existing row.
275
+ */
276
+ claimKey(key: string, opts?: {
277
+ leaseMs?: number;
278
+ seed?: Record<string, unknown>;
279
+ }): Promise<IdempotencyClaim<TProgress, TResult>>;
280
+ /**
281
+ * Persist saga resume data (post-pivot, pre-complete). Lease-token-guarded —
282
+ * a stale crashed holder can't clobber a re-acquirer's record. Optional
283
+ * `where` adds domain guards to the CAS filter.
284
+ */
285
+ saveClaimProgress(key: string, leaseToken: string, progress: TProgress, opts?: {
286
+ where?: Record<string, unknown>;
287
+ }): Promise<boolean>;
288
+ /**
289
+ * CAS the claim to the terminal SUCCESS status, storing `result` for
290
+ * replay. Loses cleanly (returns false) when the lease was re-acquired.
291
+ */
292
+ completeClaim(key: string, leaseToken: string, result?: TResult, opts?: {
293
+ where?: Record<string, unknown>;
294
+ }): Promise<boolean>;
295
+ /**
296
+ * CAS the claim to the terminal FAILURE status. Later claims replay
297
+ * `failureCode` instead of re-executing. Use ONLY for definitive failures
298
+ * where the external side effect is known NOT to have happened.
299
+ */
300
+ failClaim(key: string, leaseToken: string, failure: {
301
+ code: string;
302
+ error?: string;
303
+ }, opts?: {
304
+ where?: Record<string, unknown>;
305
+ }): Promise<boolean>;
306
+ /**
307
+ * Delete the caller's own in-flight row on definitive PRE-side-effect
308
+ * failure so a retry re-executes cleanly. Never deletes a terminal row or
309
+ * a re-acquired lease.
310
+ */
311
+ releaseClaim(key: string, leaseToken: string): Promise<boolean>;
312
+ /**
313
+ * Record an AMBIGUOUS error and lapse the lease immediately (keeps the row
314
+ * in-flight) so a recovery sweep re-claims without waiting out the lease.
315
+ * The bridge between "this attempt is giving up" and "the operation is not
316
+ * over" — e.g. a network error mid-external-call.
317
+ */
318
+ expireClaim(key: string, leaseToken: string, opts?: {
319
+ error?: string;
320
+ }): Promise<boolean>;
321
+ }
322
+ declare function idempotencyStorePlugin(options?: IdempotencyStorePluginOptions): Plugin;
323
+ //#endregion
188
324
  //#region src/plugins/immutable-states.plugin.d.ts
189
325
  /** The slice of a `before:claim` context `allowClaim` predicates see. */
190
326
  interface ImmutableClaimView {
@@ -822,4 +958,4 @@ declare function immutableField(field: string): ValidatorDefinition;
822
958
  */
823
959
  declare function uniqueField(field: string, errorMessage?: string): ValidatorDefinition;
824
960
  //#endregion
825
- export { elasticSearchPlugin as A, LeasePluginOptions as C, immutableStatesPlugin as D, ImmutableStatesPluginOptions as E, auditLogPlugin as F, AppendOnlyPluginOptions as I, appendOnlyPlugin as L, BatchOperationsMethods as M, BulkWriteResult as N, fieldFilterPlugin as O, batchOperationsPlugin as P, AggregateHelpersMethods as R, LeaseMethods as S, ImmutableClaimView as T, observabilityPlugin as _, uniqueField as a, MethodRegistryRepository as b, TenantContext as c, SubdocumentMethods as d, subdocumentPlugin as f, OperationMetric as g, ObservabilityOptions as h, requireField as i, cascadePlugin as j, ElasticSearchOptions as k, TenantStore as l, softDeletePlugin as m, blockIf as n, validationChainPlugin as o, SoftDeleteMethods as p, immutableField as r, timestampPlugin as s, autoInject as t, createTenantContext as u, MongoOperationsMethods as v, leasePlugin as w, methodRegistryPlugin as x, mongoOperationsPlugin as y, aggregateHelpersPlugin as z };
961
+ export { IdempotencyStorePluginOptions as A, AppendOnlyPluginOptions as B, LeasePluginOptions as C, immutableStatesPlugin as D, ImmutableStatesPluginOptions as E, cascadePlugin as F, AggregateHelpersMethods as H, BatchOperationsMethods as I, BulkWriteResult as L, fieldFilterPlugin as M, ElasticSearchOptions as N, IdempotencyClaim as O, elasticSearchPlugin as P, batchOperationsPlugin as R, LeaseMethods as S, ImmutableClaimView as T, aggregateHelpersPlugin as U, appendOnlyPlugin as V, observabilityPlugin as _, uniqueField as a, MethodRegistryRepository as b, TenantContext as c, SubdocumentMethods as d, subdocumentPlugin as f, OperationMetric as g, ObservabilityOptions as h, requireField as i, idempotencyStorePlugin as j, IdempotencyStoreMethods as k, TenantStore as l, softDeletePlugin as m, blockIf as n, validationChainPlugin as o, SoftDeleteMethods as p, immutableField as r, timestampPlugin as s, autoInject as t, createTenantContext as u, MongoOperationsMethods as v, leasePlugin as w, methodRegistryPlugin as x, mongoOperationsPlugin as y, auditLogPlugin as z };
@@ -1,5 +1,5 @@
1
- import { l as OP_REGISTRY, s as ALL_OPERATIONS } from "./Repository-KKR8jxfD.mjs";
2
- import { _ as upsert } from "./update-1Lq9OMD2.mjs";
1
+ import { c as ALL_OPERATIONS, u as OP_REGISTRY } from "./Repository-DThvFCaV.mjs";
2
+ import { _ as upsert } from "./update-CI2NdAW6.mjs";
3
3
  import { n as warn } from "./logger-K7dPmu2U.mjs";
4
4
  import { t as createError } from "./error-BuByZwKU.mjs";
5
5
  import { r as getFieldsForUser } from "./field-selection-FSQFLpsU.mjs";
@@ -476,6 +476,153 @@ function fieldFilterPlugin(fieldPreset) {
476
476
  };
477
477
  }
478
478
  //#endregion
479
+ //#region src/plugins/idempotency-store.plugin.ts
480
+ function randomToken() {
481
+ const bytes = /* @__PURE__ */ new Uint8Array(16);
482
+ globalThis.crypto.getRandomValues(bytes);
483
+ return Array.from(bytes, (b) => b.toString(16).padStart(2, "0")).join("");
484
+ }
485
+ function idempotencyStorePlugin(options = {}) {
486
+ const keyField = options.keyField ?? "key";
487
+ const statusField = options.statusField ?? "status";
488
+ const leaseTokenField = options.leaseTokenField ?? "leaseToken";
489
+ const leaseExpiresAtField = options.leaseExpiresAtField ?? "leaseExpiresAt";
490
+ const attemptsField = options.attemptsField ?? "attempts";
491
+ const progressField = options.progressField ?? "progress";
492
+ const resultField = options.resultField ?? "result";
493
+ const failureCodeField = options.failureCodeField ?? "failureCode";
494
+ const lastErrorField = options.lastErrorField ?? "lastError";
495
+ const inFlightStatus = options.inFlightStatus ?? "in_flight";
496
+ const succeededStatus = options.succeededStatus ?? "succeeded";
497
+ const failedStatus = options.failedStatus ?? "failed";
498
+ const defaultLeaseMs = options.defaultLeaseMs ?? 6e4;
499
+ const maxAttempts = options.maxAttempts ?? 0;
500
+ return {
501
+ name: "idempotencyStore",
502
+ apply(repo) {
503
+ if (!repo.registerMethod) throw new Error("idempotencyStorePlugin requires methodRegistryPlugin. Add methodRegistryPlugin() before idempotencyStorePlugin().");
504
+ const asDoc = (d) => d;
505
+ repo.registerMethod("claimKey", async function(key, opts = {}) {
506
+ if (typeof key !== "string" || key.length === 0) throw createError(400, "idempotencyStorePlugin.claimKey: key must be a non-empty string");
507
+ const leaseMs = opts.leaseMs ?? defaultLeaseMs;
508
+ const now = /* @__PURE__ */ new Date();
509
+ const leaseToken = randomToken();
510
+ const { doc, created } = await this.getOrCreate({ [keyField]: key }, {
511
+ ...opts.seed ?? {},
512
+ [keyField]: key,
513
+ [statusField]: inFlightStatus,
514
+ [leaseTokenField]: leaseToken,
515
+ [leaseExpiresAtField]: new Date(now.getTime() + leaseMs),
516
+ [attemptsField]: 1
517
+ });
518
+ if (created) return {
519
+ kind: "acquired",
520
+ leaseToken,
521
+ attempt: 1
522
+ };
523
+ const row = asDoc(doc);
524
+ if (row[statusField] === succeededStatus) return {
525
+ kind: "completed",
526
+ result: row[resultField]
527
+ };
528
+ if (row[statusField] === failedStatus) return {
529
+ kind: "failed",
530
+ failureCode: row[failureCodeField],
531
+ error: row[lastErrorField]
532
+ };
533
+ const leaseExpiresAt = row[leaseExpiresAtField];
534
+ const progress = row[progressField];
535
+ if (leaseExpiresAt && leaseExpiresAt > now) return {
536
+ kind: "busy",
537
+ ...progress !== void 0 ? { progress } : {},
538
+ ...row[leaseTokenField] !== void 0 ? { leaseToken: row[leaseTokenField] } : {}
539
+ };
540
+ const attempts = row[attemptsField] ?? 1;
541
+ if (maxAttempts > 0 && attempts >= maxAttempts) return {
542
+ kind: "exhausted",
543
+ attempts,
544
+ ...progress !== void 0 ? { progress } : {}
545
+ };
546
+ const reclaimed = await this.findOneAndUpdate({
547
+ [keyField]: key,
548
+ [statusField]: inFlightStatus,
549
+ [leaseExpiresAtField]: { $lte: now }
550
+ }, {
551
+ $set: {
552
+ [leaseTokenField]: leaseToken,
553
+ [leaseExpiresAtField]: new Date(now.getTime() + leaseMs)
554
+ },
555
+ $inc: { [attemptsField]: 1 }
556
+ }, { returnDocument: "after" });
557
+ if (reclaimed) {
558
+ const rec = asDoc(reclaimed);
559
+ const recProgress = rec[progressField];
560
+ return {
561
+ kind: "acquired",
562
+ leaseToken,
563
+ attempt: rec[attemptsField] ?? attempts + 1,
564
+ ...recProgress !== void 0 ? { progress: recProgress } : {}
565
+ };
566
+ }
567
+ return {
568
+ kind: "busy",
569
+ ...progress !== void 0 ? { progress } : {}
570
+ };
571
+ });
572
+ repo.registerMethod("saveClaimProgress", async function(key, leaseToken, progress, opts = {}) {
573
+ return await this.findOneAndUpdate({
574
+ ...opts.where ?? {},
575
+ [keyField]: key,
576
+ [leaseTokenField]: leaseToken,
577
+ [statusField]: inFlightStatus
578
+ }, { $set: { [progressField]: progress } }, { returnDocument: "after" }) !== null;
579
+ });
580
+ repo.registerMethod("completeClaim", async function(key, leaseToken, result, opts = {}) {
581
+ return await this.findOneAndUpdate({
582
+ ...opts.where ?? {},
583
+ [keyField]: key,
584
+ [leaseTokenField]: leaseToken,
585
+ [statusField]: inFlightStatus
586
+ }, { $set: {
587
+ [statusField]: succeededStatus,
588
+ ...result !== void 0 ? { [resultField]: result } : {}
589
+ } }, { returnDocument: "after" }) !== null;
590
+ });
591
+ repo.registerMethod("failClaim", async function(key, leaseToken, failure, opts = {}) {
592
+ if (!failure || typeof failure.code !== "string" || failure.code.length === 0) throw createError(400, "idempotencyStorePlugin.failClaim: failure.code must be a non-empty string");
593
+ return await this.findOneAndUpdate({
594
+ ...opts.where ?? {},
595
+ [keyField]: key,
596
+ [leaseTokenField]: leaseToken,
597
+ [statusField]: inFlightStatus
598
+ }, { $set: {
599
+ [statusField]: failedStatus,
600
+ [failureCodeField]: failure.code,
601
+ ...failure.error !== void 0 ? { [lastErrorField]: failure.error } : {}
602
+ } }, { returnDocument: "after" }) !== null;
603
+ });
604
+ repo.registerMethod("releaseClaim", async function(key, leaseToken) {
605
+ const res = await this.deleteMany({
606
+ [keyField]: key,
607
+ [leaseTokenField]: leaseToken,
608
+ [statusField]: inFlightStatus
609
+ });
610
+ return (typeof res === "number" ? res : res?.deletedCount ?? 0) > 0;
611
+ });
612
+ repo.registerMethod("expireClaim", async function(key, leaseToken, opts = {}) {
613
+ return await this.findOneAndUpdate({
614
+ [keyField]: key,
615
+ [leaseTokenField]: leaseToken,
616
+ [statusField]: inFlightStatus
617
+ }, { $set: {
618
+ [leaseExpiresAtField]: /* @__PURE__ */ new Date(),
619
+ ...opts.error !== void 0 ? { [lastErrorField]: opts.error } : {}
620
+ } }, { returnDocument: "after" }) !== null;
621
+ });
622
+ }
623
+ };
624
+ }
625
+ //#endregion
479
626
  //#region src/plugins/immutable-states.plugin.ts
480
627
  /** Ops this plugin has an explicit strategy for (see module doc). */
481
628
  const STRATEGY_OPS = /* @__PURE__ */ new Set([
@@ -1304,4 +1451,4 @@ function uniqueField(field, errorMessage) {
1304
1451
  };
1305
1452
  }
1306
1453
  //#endregion
1307
- export { appendOnlyPlugin as _, uniqueField as a, subdocumentPlugin as c, mongoOperationsPlugin as d, leasePlugin as f, cascadePlugin as g, elasticSearchPlugin as h, requireField as i, observabilityPlugin as l, fieldFilterPlugin as m, blockIf as n, validationChainPlugin as o, immutableStatesPlugin as p, immutableField as r, createTenantContext as s, autoInject as t, MONGOKIT_PLUGIN_NAMES as u, aggregateHelpersPlugin as v };
1454
+ export { cascadePlugin as _, uniqueField as a, subdocumentPlugin as c, mongoOperationsPlugin as d, leasePlugin as f, elasticSearchPlugin as g, fieldFilterPlugin as h, requireField as i, observabilityPlugin as l, idempotencyStorePlugin as m, blockIf as n, validationChainPlugin as o, immutableStatesPlugin as p, immutableField as r, createTenantContext as s, autoInject as t, MONGOKIT_PLUGIN_NAMES as u, appendOnlyPlugin as v, aggregateHelpersPlugin as y };