@classytic/mongokit 3.43.0 → 3.44.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.
Files changed (92) hide show
  1. package/README.md +14 -0
  2. package/dist/{PaginationEngine-DZnkbSrr.mjs → PaginationEngine-C9iS0U5l.mjs} +13 -27
  3. package/dist/{PaginationEngine-CRHyuUtw.d.mts → PaginationEngine-D17AthKw.d.mts} +1 -3
  4. package/dist/{Repository-DnL4xk5w.d.mts → Repository-B6oL6OMv.d.mts} +33 -11
  5. package/dist/{Repository-Dj6xqPxJ.mjs → Repository-eMRYZ_2Y.mjs} +204 -92
  6. package/dist/actions/index.d.mts +1 -1
  7. package/dist/actions/index.mjs +2 -12
  8. package/dist/actions-DExyXMTy.mjs +11 -0
  9. package/dist/adapter/index.d.mts +6 -10
  10. package/dist/adapter/index.mjs +1 -2
  11. package/dist/{adapter-CkMoMF83.mjs → adapter-Qzgc3ZD_.mjs} +4 -6
  12. package/dist/ai/index.d.mts +21 -8
  13. package/dist/ai/index.mjs +15 -9
  14. package/dist/better-auth/index.d.mts +18 -32
  15. package/dist/better-auth/index.mjs +3 -4
  16. package/dist/{coercion-BjdPX3YF.d.mts → coercion-COp9DRNw.d.mts} +0 -2
  17. package/dist/{create-repository-CJtVdwig.d.mts → create-repository-BOFUYj1l.d.mts} +5 -7
  18. package/dist/{create-repository-UjwPWR1z.mjs → create-repository-D7MQpIZo.mjs} +4 -5
  19. package/dist/{derive-DRBiegRH.mjs → derive-Dxsc31fV.mjs} +3 -6
  20. package/dist/{error-BuByZwKU.mjs → error-DjdmPLWO.mjs} +1 -2
  21. package/dist/{field-selection-FSQFLpsU.mjs → field-selection-DPFaFw9Y.mjs} +1 -2
  22. package/dist/{id-chunks-BmAwsqNk.mjs → id-chunks-DH-RAZWG.mjs} +13 -8
  23. package/dist/{id-resolution-BqDrk0S2.mjs → id-resolution-Cqh49d9J.mjs} +1 -2
  24. package/dist/idempotency/index.d.mts +4 -7
  25. package/dist/idempotency/index.mjs +1 -2
  26. package/dist/{index-SYF8N28D.d.mts → index-8QUEsOFI.d.mts} +3 -4
  27. package/dist/{index-C0AjVqX3.d.mts → index-ehGZLbrd.d.mts} +2 -8
  28. package/dist/index.d.mts +63 -96
  29. package/dist/index.mjs +36 -52
  30. package/dist/indexes/verify-indexes.d.mts +8 -11
  31. package/dist/indexes/verify-indexes.mjs +1 -2
  32. package/dist/{indexes-DIjMpYES.d.mts → indexes-FfyOuhDK.d.mts} +0 -2
  33. package/dist/{join-scope-DSAznE8E.mjs → join-scope-C1gOtZ59.mjs} +2 -3
  34. package/dist/kernel-conformance/index.d.mts +39 -13
  35. package/dist/kernel-conformance/index.mjs +4 -7
  36. package/dist/lock/index.d.mts +134 -7
  37. package/dist/lock/index.mjs +349 -14
  38. package/dist/{logger-K7dPmu2U.mjs → logger-hbWOlj_X.mjs} +1 -2
  39. package/dist/{method-registry.plugin-C63pGn1d.mjs → method-registry.plugin-CGAepsBU.mjs} +3 -5
  40. package/dist/{model-registry-ClKtWiHa.mjs → model-registry-DrVfJ3Nt.mjs} +1 -2
  41. package/dist/{mongooseToJsonSchema-C3k4ide0.mjs → mongooseToJsonSchema-DMDotz4_.mjs} +2 -3
  42. package/dist/{multi-tenant.plugin-B_q9NUHc.d.mts → multi-tenant.plugin-DfeDMiI8.d.mts} +143 -11
  43. package/dist/{operations-XiFgG5US.d.mts → operations-Dw9OFV0V.d.mts} +14 -5
  44. package/dist/outbox/index.d.mts +24 -9
  45. package/dist/outbox/index.mjs +17 -6
  46. package/dist/pagination/PaginationEngine.d.mts +1 -1
  47. package/dist/pagination/PaginationEngine.mjs +1 -2
  48. package/dist/pagination/utils/limits.d.mts +6 -9
  49. package/dist/pagination/utils/limits.mjs +2 -3
  50. package/dist/{pagination-D6psses0.d.mts → pagination-DAUg5zOY.d.mts} +2 -10
  51. package/dist/{plugin-options-Cirmb4Kp.d.mts → plugin-options-Bpcuz9kS.d.mts} +2 -4
  52. package/dist/plugins/index.d.mts +6 -7
  53. package/dist/plugins/index.mjs +6 -7
  54. package/dist/query/primitives/coercion.d.mts +1 -1
  55. package/dist/query/primitives/coercion.mjs +2 -3
  56. package/dist/query/primitives/geo.d.mts +11 -14
  57. package/dist/query/primitives/geo.mjs +1 -2
  58. package/dist/query/primitives/indexes.d.mts +1 -1
  59. package/dist/query/primitives/indexes.mjs +1 -2
  60. package/dist/{query-defaults-BxUcSOoF.mjs → query-defaults-aUoKlEbh.mjs} +2 -3
  61. package/dist/read-model/index.d.mts +18 -21
  62. package/dist/read-model/index.mjs +3 -4
  63. package/dist/{repository-MqAP409e.d.mts → repository-DzVIwhU2.d.mts} +25 -29
  64. package/dist/retention-purge-DqcYvRnG.d.mts +35 -0
  65. package/dist/{rolldown-runtime-D7D4PA-g.mjs → rolldown-runtime-D8jQpDG7.mjs} +1 -2
  66. package/dist/search/index.d.mts +1 -1
  67. package/dist/search/index.mjs +1 -2
  68. package/dist/sync/index.d.mts +95 -15
  69. package/dist/sync/index.mjs +308 -62
  70. package/dist/tenant/index.d.mts +8 -11
  71. package/dist/tenant/index.mjs +1 -2
  72. package/dist/testkit/index.d.mts +179 -23
  73. package/dist/testkit/index.mjs +421 -23
  74. package/dist/{timestamp.plugin-DpOWavVI.mjs → timestamp.plugin-Bz_zL9PX.mjs} +192 -49
  75. package/dist/{to-plain-vksRrLtc.mjs → to-plain-CEKv_ylg.mjs} +2 -4
  76. package/dist/{to-plain-o5tUY2nV.d.mts → to-plain-PO5r1Qoy.d.mts} +2 -16
  77. package/dist/{transaction-DmiB4k2P.mjs → transaction-C2PFxfIv.mjs} +5 -8
  78. package/dist/{type-utils-CLzRFtIA.d.mts → type-utils-CKvuewAL.d.mts} +0 -2
  79. package/dist/{update-WgeAUJ_I.mjs → update-DcfmNbJe.mjs} +12 -20
  80. package/dist/usage/index.d.mts +2 -5
  81. package/dist/usage/index.mjs +8 -6
  82. package/dist/utils/index.d.mts +8 -10
  83. package/dist/utils/index.mjs +7 -7
  84. package/dist/{validation-chain.plugin-BAeC5eVT.d.mts → validation-chain.plugin-B3gZCZj4.d.mts} +135 -48
  85. package/dist/{validation-chain.plugin-DRApTmkN.mjs → validation-chain.plugin-DNY6MIF6.mjs} +207 -55
  86. package/llms.txt +33 -0
  87. package/package.json +29 -25
  88. package/skills/mongokit/SKILL.md +112 -0
  89. package/skills/mongokit/references/pagination-search.md +87 -0
  90. package/skills/mongokit/references/plugins-tenancy.md +102 -0
  91. package/skills/mongokit/references/repository-api.md +83 -0
  92. package/skills/mongokit/references/transactions-outbox.md +101 -0
@@ -1,6 +1,5 @@
1
- import { l as Plugin } from "../repository-MqAP409e.mjs";
1
+ import { l as Plugin } from "../repository-DzVIwhU2.mjs";
2
2
  import { PipelineStage } from "mongoose";
3
- //#region src/ai/types.d.ts
4
3
  /** Supported similarity metrics for vector search */
5
4
  type SimilarityMetric = 'cosine' | 'euclidean' | 'dotProduct';
6
5
  /** A single piece of content to embed — text, image, or any media */
@@ -65,7 +64,11 @@ interface VectorSearchParams {
65
64
  limit?: number;
66
65
  /** Candidates to consider (higher = more accurate, slower). Default: limit * 10 */
67
66
  numCandidates?: number;
68
- /** Pre-filter documents before vector search */
67
+ /**
68
+ * Pre-filter documents before vector search (`$vectorSearch.filter`). Every path
69
+ * must be declared as a `{ type: 'filter', path }` field on the vector index.
70
+ * With `multiTenantPlugin`, the tenant clause is merged in here automatically.
71
+ */
69
72
  filter?: Record<string, unknown>;
70
73
  /** Use exact KNN instead of approximate (slower but precise) */
71
74
  exact?: boolean;
@@ -81,6 +84,19 @@ interface VectorSearchParams {
81
84
  minScore?: number;
82
85
  /** Additional pipeline stages to append after search */
83
86
  postPipeline?: PipelineStage[];
87
+ /**
88
+ * Tenant scope for `multiTenantPlugin` (default `contextKey`). `searchSimilar`
89
+ * runs the same `before:searchSimilar` policy hooks as other reads, so a
90
+ * required tenant that is missing here (and not resolved via `resolveContext`)
91
+ * throws, exactly like `getAll`.
92
+ */
93
+ organizationId?: string;
94
+ /** Per-call tenant bypass — same semantics as every other repository read. */
95
+ bypassTenant?: boolean;
96
+ /** Abort signal, checked before the policy hooks run. */
97
+ signal?: AbortSignal;
98
+ /** Any other context key a policy plugin reads (e.g. a custom `contextKey` like `branchId`). */
99
+ [contextKey: string]: unknown;
84
100
  }
85
101
  /** Vector search result with score */
86
102
  interface ScoredResult<T = Record<string, unknown>> {
@@ -128,8 +144,6 @@ interface VectorPluginOptions {
128
144
  */
129
145
  blockPrivateIpUrls?: boolean;
130
146
  }
131
- //#endregion
132
- //#region src/ai/vector.plugin.d.ts
133
147
  interface VectorMethods {
134
148
  searchSimilar<T = Record<string, unknown>>(params: VectorSearchParams): Promise<ScoredResult<T>[]>;
135
149
  embed(input: EmbeddingInput | string): Promise<number[]>;
@@ -141,6 +155,5 @@ declare function buildVectorSearchPipeline(field: VectorFieldConfig, queryVector
141
155
  /**
142
156
  * Creates the vector search plugin
143
157
  */
144
- declare function vectorPlugin(options: VectorPluginOptions): Plugin;
145
- //#endregion
146
- export { type BatchEmbedFn, type EmbedFn, type EmbeddingInput, type ScoredResult, type SimilarityMetric, type VectorFieldConfig, type VectorMethods, type VectorPluginOptions, type VectorSearchParams, buildVectorSearchPipeline, vectorPlugin };
158
+ export declare function vectorPlugin(options: VectorPluginOptions): Plugin;
159
+ export { type BatchEmbedFn, type EmbedFn, type EmbeddingInput, type ScoredResult, type SimilarityMetric, type VectorFieldConfig, type VectorMethods, type VectorPluginOptions, type VectorSearchParams, buildVectorSearchPipeline };
package/dist/ai/index.mjs CHANGED
@@ -1,5 +1,5 @@
1
- import { n as warn } from "../logger-K7dPmu2U.mjs";
2
- //#region src/ai/url-policy.ts
1
+ import { n as warn } from "../logger-hbWOlj_X.mjs";
2
+ // src/ai/url-policy.ts
3
3
  /**
4
4
  * URL policy helpers for the vector plugin media pipeline.
5
5
  *
@@ -72,8 +72,7 @@ function isPrivateOrLocalHost(hostname) {
72
72
  if (a === 100 && b >= 64 && b <= 127) return true;
73
73
  return false;
74
74
  }
75
- //#endregion
76
- //#region src/ai/vector-error-hints.ts
75
+ // src/ai/vector-error-hints.ts
77
76
  /**
78
77
  * Pure classifier. Takes the raw error and the context the plugin knows
79
78
  * (index name, dimensions, filter paths it tried to use) and returns a hint.
@@ -157,8 +156,7 @@ function extractErrorMessage(err) {
157
156
  }
158
157
  return String(err);
159
158
  }
160
- //#endregion
161
- //#region src/ai/vector.plugin.ts
159
+ // src/ai/vector.plugin.ts
162
160
  /** Maximum numCandidates allowed by Atlas Vector Search */
163
161
  const MAX_NUM_CANDIDATES = 1e4;
164
162
  /**
@@ -273,6 +271,12 @@ function vectorPlugin(options) {
273
271
  repo.registerMethod("searchSimilar", async function searchSimilar(params) {
274
272
  if (vectorSearchUnavailable) throw vectorSearchUnavailable;
275
273
  const field = resolveField(fields, params.field);
274
+ const { query: _query, filter: callerFilter, ...contextOptions } = params;
275
+ const scopedFilter = (await repo._buildContext("searchSimilar", {
276
+ ...contextOptions,
277
+ ...callerFilter && { filters: callerFilter }
278
+ })).filters;
279
+ const filter = scopedFilter && Object.keys(scopedFilter).length > 0 ? scopedFilter : void 0;
276
280
  let queryVector;
277
281
  if (Array.isArray(params.query)) queryVector = params.query;
278
282
  else {
@@ -281,7 +285,10 @@ function vectorPlugin(options) {
281
285
  queryVector = await embedFn(input);
282
286
  }
283
287
  if (queryVector.length !== field.dimensions) throw new Error(`[mongokit] Query vector has ${queryVector.length} dimensions, expected ${field.dimensions}`);
284
- const pipeline = buildVectorSearchPipeline(field, queryVector, params);
288
+ const pipeline = buildVectorSearchPipeline(field, queryVector, {
289
+ ...params,
290
+ filter
291
+ });
285
292
  const agg = repo.Model.aggregate(pipeline);
286
293
  if (params.session) agg.session(params.session);
287
294
  let results;
@@ -289,7 +296,7 @@ function vectorPlugin(options) {
289
296
  results = await withVectorErrorHints(() => agg.exec(), {
290
297
  indexName: field.index,
291
298
  dimensions: field.dimensions,
292
- filterPaths: params.filter ? Object.keys(params.filter) : void 0
299
+ filterPaths: filter ? Object.keys(filter) : void 0
293
300
  });
294
301
  } catch (err) {
295
302
  if (err.code === "NOT_ATLAS") vectorSearchUnavailable = err;
@@ -391,5 +398,4 @@ function vectorPlugin(options) {
391
398
  }
392
399
  };
393
400
  }
394
- //#endregion
395
401
  export { buildVectorSearchPipeline, vectorPlugin };
@@ -1,12 +1,11 @@
1
1
  import { DataAdapter, RepositoryLike } from "@classytic/repo-core/adapter";
2
2
  import { BetterAuthPluginKey, BetterAuthPluginKey as BetterAuthPluginKey$1 } from "@classytic/repo-core/better-auth";
3
- //#region src/better-auth/index.d.ts
4
3
  /**
5
4
  * Minimal structural type for the Mongoose surface this module touches.
6
5
  * Declared structurally so the file has zero runtime `import` of mongoose —
7
6
  * mongoose stays a peer dep and is never bundled with mongokit.
8
7
  */
9
- interface MongooseLike {
8
+ export interface MongooseLike {
10
9
  models: Record<string, unknown>;
11
10
  Schema: new (definition?: Record<string, unknown>, options?: Record<string, unknown>) => MongooseSchemaLike;
12
11
  model: (name: string, schema?: unknown) => MongooseModelLike;
@@ -26,7 +25,7 @@ interface MongooseModelLike {
26
25
  * `better-auth` from this module — declared as an *optional* peer in
27
26
  * package.json for hosts that import this subpath.
28
27
  */
29
- interface BetterAuthInstance {
28
+ export interface BetterAuthInstance {
30
29
  $context: Promise<{
31
30
  tables: Record<string, BATableConfig>;
32
31
  }> | {
@@ -35,19 +34,7 @@ interface BetterAuthInstance {
35
34
  }
36
35
  interface BATableConfig {
37
36
  modelName: string;
38
- fields: Record<string, BAFieldAttribute>;
39
- }
40
- interface BAFieldAttribute {
41
- type: 'string' | 'number' | 'boolean' | 'date' | 'string[]' | 'number[]';
42
- required?: boolean;
43
- unique?: boolean;
44
- fieldName?: string;
45
- references?: {
46
- model: string;
47
- field: string;
48
- onDelete?: string;
49
- };
50
- defaultValue?: unknown;
37
+ fields?: unknown;
51
38
  }
52
39
  /**
53
40
  * How Better Auth's `_id` values are stored, so mongoose casts queries the same way.
@@ -69,8 +56,8 @@ interface BAFieldAttribute {
69
56
  * There is no safe default that covers both, which is why this is an explicit
70
57
  * option rather than a guess: read `typeof doc._id` from a live row.
71
58
  */
72
- type BetterAuthIdType = 'objectid' | 'string';
73
- interface RegisterBetterAuthStubsOptions {
59
+ export type BetterAuthIdType = 'objectid' | 'string';
60
+ export interface RegisterBetterAuthStubsOptions {
74
61
  /** Plugin sets to include. `core` is always implied. */
75
62
  plugins?: BetterAuthPluginKey$1[];
76
63
  /** How BA stores `_id` — see {@link BetterAuthIdType}. Default `'objectid'`. */
@@ -114,8 +101,8 @@ interface RegisterBetterAuthStubsOptions {
114
101
  * @returns the model names that were newly registered (excluding any that
115
102
  * already existed on `mongoose.models`).
116
103
  */
117
- declare function registerBetterAuthStubs(mongoose: MongooseLike, options?: RegisterBetterAuthStubsOptions): string[];
118
- interface BetterAuthOverlayOptions<TDoc = Record<string, unknown>> {
104
+ export declare function registerBetterAuthStubs(mongoose: MongooseLike, options?: RegisterBetterAuthStubsOptions): string[];
105
+ export interface BetterAuthOverlayOptions<TDoc = Record<string, unknown>> {
119
106
  /** A `betterAuth()` instance. Used to read the resolved schema (`auth.$context.tables`). */
120
107
  auth: BetterAuthInstance;
121
108
  /** Mongoose instance — passed in to keep mongoose a peer dep. */
@@ -218,7 +205,7 @@ interface BetterAuthOverlayOptions<TDoc = Record<string, unknown>> {
218
205
  * registered on `mongoose.models` from a prior call (re-registration
219
206
  * would silently drop this call's `additionalFields` / `indexes`).
220
207
  */
221
- declare function createBetterAuthOverlay<TDoc = Record<string, unknown>>(options: BetterAuthOverlayOptions<TDoc>): Promise<DataAdapter<TDoc>>;
208
+ export declare function createBetterAuthOverlay<TDoc = Record<string, unknown>>(options: BetterAuthOverlayOptions<TDoc>): Promise<DataAdapter<TDoc>>;
222
209
  /**
223
210
  * Minimal structural surface for the one write we need. Satisfied by BOTH a
224
211
  * native MongoDB `Collection` (`db.collection('session')`) and a Mongoose
@@ -251,7 +238,7 @@ declare function createBetterAuthOverlay<TDoc = Record<string, unknown>>(options
251
238
  * the attempt failed (logged by the caller, never thrown — a missing
252
239
  * TTL degrades storage, and refusing to boot over it is worse).
253
240
  */
254
- declare function ensureBetterAuthSessionTtl(connection: {
241
+ export declare function ensureBetterAuthSessionTtl(connection: {
255
242
  collection(name: string): {
256
243
  createIndex(keys: Record<string, 1>, opts: Record<string, unknown>): Promise<unknown>;
257
244
  };
@@ -267,7 +254,7 @@ declare function ensureBetterAuthSessionTtl(connection: {
267
254
  * because failing a boot over historical duplicates is worse than running with
268
255
  * a plain lookup index and reporting the degradation.
269
256
  */
270
- interface BetterAuthIndexSpec {
257
+ export interface BetterAuthIndexSpec {
271
258
  /** Canonical collection name (`'user'`, `'session'`, ...). */
272
259
  collection: string;
273
260
  keys: Record<string, 1 | -1>;
@@ -292,16 +279,16 @@ interface BetterAuthIndexSpec {
292
279
  * TTL entries (`expiresAt`) additionally keep the collection BOUNDED — see
293
280
  * {@link ensureBetterAuthSessionTtl} for the measurements that motivated it.
294
281
  */
295
- declare const BA_INDEXES_BY_PLUGIN: Record<string, readonly BetterAuthIndexSpec[]>;
282
+ export declare const BA_INDEXES_BY_PLUGIN: Record<string, readonly BetterAuthIndexSpec[]>;
296
283
  /** Outcome of one declared index. */
297
- interface BetterAuthIndexResult {
284
+ export interface BetterAuthIndexResult {
298
285
  collection: string;
299
286
  name: string;
300
287
  status: 'created' | 'degraded' | 'failed';
301
288
  /** Set on `degraded` (unique dropped) and `failed`. */
302
289
  reason?: string;
303
290
  }
304
- interface EnsureBetterAuthIndexesOptions {
291
+ export interface EnsureBetterAuthIndexesOptions {
305
292
  /** Plugin sets to include beyond `core` (always implied). */
306
293
  plugins?: BetterAuthPluginKey$1[];
307
294
  /** Mirror BA's `usePlural` — appends `s` to every collection name. */
@@ -311,7 +298,7 @@ interface EnsureBetterAuthIndexesOptions {
311
298
  /** Canonical collection names to skip entirely. */
312
299
  exclude?: string[];
313
300
  }
314
- interface IndexCreator {
301
+ export interface IndexCreator {
315
302
  collection(name: string): {
316
303
  createIndex(keys: Record<string, 1 | -1>, opts: Record<string, unknown>): Promise<unknown>;
317
304
  };
@@ -335,8 +322,8 @@ interface IndexCreator {
335
322
  *
336
323
  * Call once at boot, after the connection is live. Safe to call again.
337
324
  */
338
- declare function ensureBetterAuthIndexes(connection: IndexCreator, options?: EnsureBetterAuthIndexesOptions): Promise<BetterAuthIndexResult[]>;
339
- interface SessionUpdaterLike {
325
+ export declare function ensureBetterAuthIndexes(connection: IndexCreator, options?: EnsureBetterAuthIndexesOptions): Promise<BetterAuthIndexResult[]>;
326
+ export interface SessionUpdaterLike {
340
327
  updateMany(filter: Record<string, unknown>, update: Record<string, unknown>): Promise<{
341
328
  modifiedCount?: number;
342
329
  }>;
@@ -366,8 +353,7 @@ interface SessionUpdaterLike {
366
353
  *
367
354
  * @returns the number of sessions whose pointer was cleared.
368
355
  */
369
- declare function clearActiveOrganizationFromSessions(sessions: SessionUpdaterLike, organizationId: string, options?: {
356
+ export declare function clearActiveOrganizationFromSessions(sessions: SessionUpdaterLike, organizationId: string, options?: {
370
357
  userId?: unknown;
371
358
  }): Promise<number>;
372
- //#endregion
373
- export { BA_INDEXES_BY_PLUGIN, BetterAuthIdType, BetterAuthIndexResult, BetterAuthIndexSpec, BetterAuthInstance, BetterAuthOverlayOptions, type BetterAuthPluginKey, EnsureBetterAuthIndexesOptions, IndexCreator, MongooseLike, RegisterBetterAuthStubsOptions, SessionUpdaterLike, clearActiveOrganizationFromSessions, createBetterAuthOverlay, ensureBetterAuthIndexes, ensureBetterAuthSessionTtl, registerBetterAuthStubs };
359
+ export type { BetterAuthPluginKey };
@@ -1,8 +1,8 @@
1
- import { n as Repository } from "../Repository-Dj6xqPxJ.mjs";
2
- import { n as createMongooseAdapter } from "../adapter-CkMoMF83.mjs";
1
+ import { n as createMongooseAdapter } from "../adapter-Qzgc3ZD_.mjs";
2
+ import { n as Repository } from "../Repository-eMRYZ_2Y.mjs";
3
3
  import { asReadOnlyRepo } from "@classytic/repo-core/repository";
4
4
  import { pluralizeBetterAuthCollection, resolveBetterAuthCollections } from "@classytic/repo-core/better-auth";
5
- //#region src/better-auth/index.ts
5
+ // src/better-auth/index.ts
6
6
  /**
7
7
  * Field key with ORDER PRESERVED — a compound index is identified by its key sequence.
8
8
  * `{ organizationId: 1, createdAt: -1 }` is a DIFFERENT index from `{ createdAt: -1, organizationId: 1 }`
@@ -462,5 +462,4 @@ async function clearActiveOrganizationFromSessions(sessions, organizationId, opt
462
462
  if (options?.userId != null) filter.userId = options.userId;
463
463
  return (await sessions.updateMany(filter, { $set: { activeOrganizationId: null } })).modifiedCount ?? 0;
464
464
  }
465
- //#endregion
466
465
  export { BA_INDEXES_BY_PLUGIN, clearActiveOrganizationFromSessions, createBetterAuthOverlay, ensureBetterAuthIndexes, ensureBetterAuthSessionTtl, registerBetterAuthStubs };
@@ -1,4 +1,3 @@
1
- //#region src/query/primitives/coercion.d.ts
2
1
  /**
3
2
  * Value coercion primitives
4
3
  *
@@ -102,5 +101,4 @@ declare function coerceToType(value: unknown, type: FieldType): unknown;
102
101
  * preserves-pre-3.5.5-behavior fallback).
103
102
  */
104
103
  declare function coerceFieldValue(field: string, value: unknown, types: Map<string, FieldType>): unknown;
105
- //#endregion
106
104
  export { coerceHeuristic as a, coerceFieldValue as i, SchemaPathsLike as n, coerceToType as o, buildFieldTypeMap as r, normalizeMongooseType as s, FieldType as t };
@@ -1,10 +1,9 @@
1
- import { u as PaginationConfig } from "./pagination-D6psses0.mjs";
2
- import { _ as RepositoryOptions, d as PluginType } from "./repository-MqAP409e.mjs";
3
- import { D as AuditTrailOptions, i as CustomIdOptions, t as MultiTenantOptions, y as RepositoryCachePluginOptions } from "./multi-tenant.plugin-B_q9NUHc.mjs";
4
- import { r as Repository } from "./Repository-DnL4xk5w.mjs";
5
- import { i as Logger, o as SoftDeleteOptions } from "./plugin-options-Cirmb4Kp.mjs";
1
+ import { L as AuditTrailOptions, i as CustomIdOptions, k as RepositoryCachePluginOptions, t as MultiTenantOptions } from "./multi-tenant.plugin-DfeDMiI8.mjs";
2
+ import { r as Repository } from "./Repository-B6oL6OMv.mjs";
3
+ import { u as PaginationConfig } from "./pagination-DAUg5zOY.mjs";
4
+ import { i as Logger, o as SoftDeleteOptions } from "./plugin-options-Bpcuz9kS.mjs";
5
+ import { _ as RepositoryOptions, d as PluginType } from "./repository-DzVIwhU2.mjs";
6
6
  import { Model } from "mongoose";
7
- //#region src/create-repository.d.ts
8
7
  /**
9
8
  * Audit config — either a `Logger` (routes to `auditLogPlugin`, which
10
9
  * writes structured log lines through your logger) or an
@@ -50,5 +49,4 @@ interface CreateRepositoryConfig extends RepositoryOptions {
50
49
  * ordering guarantees and an example.
51
50
  */
52
51
  declare function createRepository<TDoc>(model: Model<TDoc, any, any, any>, config?: CreateRepositoryConfig): Repository<TDoc>;
53
- //#endregion
54
52
  export { CreateRepositoryConfig as n, createRepository as r, AuditConfig as t };
@@ -1,7 +1,7 @@
1
- import { n as Repository } from "./Repository-Dj6xqPxJ.mjs";
2
- import { b as auditLogPlugin, g as cachePlugin, i as multiTenantPlugin, l as customIdPlugin, n as softDeletePlugin, t as timestampPlugin, v as auditTrailPlugin } from "./timestamp.plugin-DpOWavVI.mjs";
3
- import { n as batchOperationsPlugin, t as methodRegistryPlugin } from "./method-registry.plugin-C63pGn1d.mjs";
4
- //#region src/create-repository.ts
1
+ import { S as auditTrailPlugin, b as cachePlugin, d as customIdPlugin, i as multiTenantPlugin, n as softDeletePlugin, t as timestampPlugin, w as auditLogPlugin } from "./timestamp.plugin-Bz_zL9PX.mjs";
2
+ import { n as batchOperationsPlugin, t as methodRegistryPlugin } from "./method-registry.plugin-CGAepsBU.mjs";
3
+ import { n as Repository } from "./Repository-eMRYZ_2Y.mjs";
4
+ // src/create-repository.ts
5
5
  function isLoggerAudit(value) {
6
6
  const v = value;
7
7
  return typeof v.info === "function" || typeof v.warn === "function" || typeof v.error === "function" || typeof v.debug === "function";
@@ -26,5 +26,4 @@ function createRepository(model, config = {}) {
26
26
  ...repositoryOptions
27
27
  });
28
28
  }
29
- //#endregion
30
29
  export { createRepository as t };
@@ -1,4 +1,4 @@
1
- //#region src/search/normalize.ts
1
+ // src/search/normalize.ts
2
2
  /**
3
3
  * Search-as-you-type text rules, shared by the WRITER (the search keys stored on
4
4
  * every document) and the READER (the query typed into a search box).
@@ -97,8 +97,7 @@ function findSearchMatches(text, query) {
97
97
  }
98
98
  return out;
99
99
  }
100
- //#endregion
101
- //#region src/search/prefix.ts
100
+ // src/search/prefix.ts
102
101
  /**
103
102
  * Indexed search-as-you-type (`searchMode: 'prefix'`): the stored keys, the
104
103
  * query filter, and the index/schema declarations. Pure: no mongoose import.
@@ -228,8 +227,7 @@ function searchKeysIndex(field = DEFAULT_SEARCH_KEYS_FIELD, options = {}) {
228
227
  options: { name: options.name ?? `${field}_1` }
229
228
  };
230
229
  }
231
- //#endregion
232
- //#region src/search/derive.ts
230
+ // src/search/derive.ts
233
231
  /**
234
232
  * How a write changes the search fields: the pure analysis behind the
235
233
  * search-keys plugin. Given one write (a document, a replacement, or an update
@@ -371,5 +369,4 @@ function fieldValuesOf(doc, fields) {
371
369
  function keysFromValues(values, fields) {
372
370
  return collectSearchTokens(fields.map((f) => values[f]));
373
371
  }
374
- //#endregion
375
372
  export { tokenizeSearchText as _, insertValues as a, writeKeys as c, buildSearchKeys as d, prefixSearchFilter as f, normalizeSearchText as g, findSearchMatches as h, fieldValuesOf as i, DEFAULT_SEARCH_KEYS_FIELD as l, searchKeysPath as m, SearchKeysWriteError as n, keysFromValues as o, searchKeysIndex as p, analyzeUpdate as r, unresolvedForUpdate as s, SEARCH_KEYS_ERROR_CODES as t, MAX_PREFIX_SEARCH_TERMS as u };
@@ -1,4 +1,4 @@
1
- //#region src/utils/error.ts
1
+ // src/utils/error.ts
2
2
  /**
3
3
  * Creates an error with HTTP status code, plus optional stable `code` /
4
4
  * `meta` so callers can `catch` on the code instead of regex-matching the
@@ -71,5 +71,4 @@ function parseDuplicateKeyError(error, options = {}) {
71
71
  };
72
72
  return httpError;
73
73
  }
74
- //#endregion
75
74
  export { isDuplicateKeyError as n, parseDuplicateKeyError as r, createError as t };
@@ -1,4 +1,4 @@
1
- //#region src/utils/field-selection.ts
1
+ // src/utils/field-selection.ts
2
2
  /**
3
3
  * Get allowed fields for a user based on their context
4
4
  *
@@ -95,5 +95,4 @@ function createFieldPreset(config) {
95
95
  admin: config.admin || []
96
96
  };
97
97
  }
98
- //#endregion
99
98
  export { getMongooseProjection as i, filterResponseData as n, getFieldsForUser as r, createFieldPreset as t };
@@ -1,4 +1,4 @@
1
- //#region src/utils/id-chunks.ts
1
+ // src/utils/id-chunks.ts
2
2
  /**
3
3
  * Default slice for `$in` fan-out. Larger than `runChunkedPurge`'s 1000 on purpose:
4
4
  * a purge chunk bounds the WRITE LOCK SCOPE of each progressive strategy step, while a
@@ -35,9 +35,18 @@ function* idChunks(ids, size) {
35
35
  * `baseFilter`.
36
36
  */
37
37
  function keysetFilter(baseFilter, cursor) {
38
- return cursor == null ? baseFilter : {
38
+ return cursor == null ? baseFilter : withIdPredicate(baseFilter, { $gt: cursor });
39
+ }
40
+ /**
41
+ * `baseFilter` AND an `_id` predicate. A base that already constrains `_id` (an ID-bounded
42
+ * purge: `{ _id: { $nin: keep } }`, `{ _id: { $lte: last } }`) is combined with `$and`;
43
+ * spreading would REPLACE the caller's `_id` predicate with the chunk's, so every chunk after
44
+ * the first would escape the caller's bound. Without a base `_id` the flat shape is kept.
45
+ */
46
+ function withIdPredicate(baseFilter, idPredicate) {
47
+ return Object.hasOwn(baseFilter, "_id") ? { $and: [baseFilter, { _id: idPredicate }] } : {
39
48
  ...baseFilter,
40
- _id: { $gt: cursor }
49
+ _id: idPredicate
41
50
  };
42
51
  }
43
52
  /**
@@ -58,10 +67,6 @@ async function selectKeysetChunk(model, filter, limit, options = {}) {
58
67
  * action ports use this shape; use it for any select-then-write over a chunk.
59
68
  */
60
69
  function narrowToIds(baseFilter, ids) {
61
- return {
62
- ...baseFilter,
63
- _id: { $in: ids }
64
- };
70
+ return withIdPredicate(baseFilter, { $in: ids });
65
71
  }
66
- //#endregion
67
72
  export { narrowToIds as a, keysetFilter as i, collectIds as n, selectKeysetChunk as o, idChunks as r, DEFAULT_ID_CHUNK as t };
@@ -1,5 +1,5 @@
1
1
  import mongoose from "mongoose";
2
- //#region src/utils/id-resolution.ts
2
+ // src/utils/id-resolution.ts
3
3
  /**
4
4
  * ID Resolution Primitive
5
5
  *
@@ -113,5 +113,4 @@ function idVariants(id) {
113
113
  if (typeof id === "string" && id.length > 0 && mongoose.Types.ObjectId.isValid(id)) return [id, new mongoose.Types.ObjectId(id)];
114
114
  return [id];
115
115
  }
116
- //#endregion
117
116
  export { toObjectId as a, isValidIdForType as i, idVariants as n, isObjectIdInstance as r, getSchemaIdType as t };
@@ -1,13 +1,12 @@
1
1
  import { Connection, Model } from "mongoose";
2
2
  import { IdempotencyClaimStore } from "@classytic/repo-core/idempotency";
3
- //#region src/idempotency/index.d.ts
4
- interface IdempotencyModelOptions {
3
+ export interface IdempotencyModelOptions {
5
4
  /** Collection name. Default `idempotency_claims`. */
6
5
  collection?: string;
7
6
  /** Mongoose model name. Default `IdempotencyClaim`. Must be unique per connection. */
8
7
  modelName?: string;
9
8
  }
10
- interface IdempotencyStoreOptions {
9
+ export interface IdempotencyStoreOptions {
11
10
  /**
12
11
  * How long a claim is kept after its last write before the TTL monitor removes it.
13
12
  * Default 7 days. Size it to the longest a caller may retry — a retry after the claim
@@ -16,8 +15,6 @@ interface IdempotencyStoreOptions {
16
15
  retentionSeconds?: number;
17
16
  }
18
17
  /** Build (or return) the claims model on `connection`. Idempotent per connection. */
19
- declare function createIdempotencyModel(connection: Connection, options?: IdempotencyModelOptions): Model<Record<string, unknown>>;
18
+ export declare function createIdempotencyModel(connection: Connection, options?: IdempotencyModelOptions): Model<Record<string, unknown>>;
20
19
  /** The store over a model from {@link createIdempotencyModel}. */
21
- declare function createIdempotencyStore(model: Model<Record<string, unknown>>, options?: IdempotencyStoreOptions): IdempotencyClaimStore;
22
- //#endregion
23
- export { IdempotencyModelOptions, IdempotencyStoreOptions, createIdempotencyModel, createIdempotencyStore };
20
+ export declare function createIdempotencyStore(model: Model<Record<string, unknown>>, options?: IdempotencyStoreOptions): IdempotencyClaimStore;
@@ -1,6 +1,6 @@
1
1
  import { Schema } from "mongoose";
2
2
  import { identityKey } from "@classytic/repo-core/idempotency";
3
- //#region src/idempotency/index.ts
3
+ // src/idempotency/index.ts
4
4
  /**
5
5
  * The mongo {@link IdempotencyClaimStore} — use this with `runIdempotent` from
6
6
  * `@classytic/repo-core/idempotency`; never keep a per-module claims table.
@@ -130,5 +130,4 @@ function createIdempotencyStore(model, options = {}) {
130
130
  }
131
131
  };
132
132
  }
133
- //#endregion
134
133
  export { createIdempotencyModel, createIdempotencyStore };
@@ -1,6 +1,6 @@
1
- import { S as LookupOptions, c as DeleteResult, d as GroupResult, h as OperationOptions, l as FindOneAndUpdateOptions, m as MinMaxResult, o as CreateOptions, v as UpdateManyResult, y as UpdateOptions } from "./operations-XiFgG5US.mjs";
2
- import { A as ObjectId, D as AnyDocument, F as SortSpec, N as SelectSpec, j as PopulateSpec, y as ResolvedQueryOptions } from "./pagination-D6psses0.mjs";
3
- import { p as UpdateWithValidationResult } from "./type-utils-CLzRFtIA.mjs";
1
+ import { S as LookupOptions, c as DeleteResult, d as GroupResult, h as OperationOptions, l as FindOneAndUpdateOptions, m as MinMaxResult, o as CreateOptions, v as UpdateManyResult, y as UpdateOptions } from "./operations-Dw9OFV0V.mjs";
2
+ import { A as ObjectId, D as AnyDocument, F as SortSpec, N as SelectSpec, j as PopulateSpec, y as ResolvedQueryOptions } from "./pagination-DAUg5zOY.mjs";
3
+ import { p as UpdateWithValidationResult } from "./type-utils-CKvuewAL.mjs";
4
4
  import { Model, PipelineStage } from "mongoose";
5
5
  declare namespace aggregate_d_exports {
6
6
  export { aggregate, aggregatePaginate, average, countBy, distinct, facet, groupBy, lookup, minMax, sum, unwind };
@@ -377,5 +377,4 @@ declare function pullFromArray<TDoc = AnyDocument>(Model: Model<TDoc>, id: strin
377
377
  declare namespace index_d_exports {
378
378
  export { aggregate_d_exports as aggregate, create_d_exports as create, delete_d_exports as deleteActions, read_d_exports as read, update_d_exports as update };
379
379
  }
380
- //#endregion
381
380
  export { CreateManyFailure as a, create_d_exports as c, delete_d_exports as i, isCreateManyPartialError as l, update_d_exports as n, CreateManyPartial as o, read_d_exports as r, CreateManyPartialError as s, index_d_exports as t, aggregate_d_exports as u };
@@ -1,4 +1,3 @@
1
- //#region src/search/derive.d.ts
2
1
  /**
3
2
  * How a write changes the search fields: the pure analysis behind the
4
3
  * search-keys plugin. Given one write (a document, a replacement, or an update
@@ -9,17 +8,15 @@
9
8
  /** Thrown (as `status: 400` with a `code`) for a write the keys cannot follow. */
10
9
  declare const SEARCH_KEYS_ERROR_CODES: {
11
10
  /** An operator or path the plugin cannot evaluate touches a search field. */
12
- readonly UNSUPPORTED_UPDATE: "SEARCH_KEYS_UNSUPPORTED_UPDATE";
11
+ readonly UNSUPPORTED_UPDATE: 'SEARCH_KEYS_UNSUPPORTED_UPDATE';
13
12
  /** A multi-document update sets SOME search fields; the rest differ per document. */
14
- readonly PARTIAL_MULTI_UPDATE: "SEARCH_KEYS_PARTIAL_MULTI_UPDATE";
13
+ readonly PARTIAL_MULTI_UPDATE: 'SEARCH_KEYS_PARTIAL_MULTI_UPDATE';
15
14
  };
16
15
  declare class SearchKeysWriteError extends Error {
17
16
  readonly code: (typeof SEARCH_KEYS_ERROR_CODES)[keyof typeof SEARCH_KEYS_ERROR_CODES];
18
17
  readonly status = 400;
19
18
  constructor(message: string, code: (typeof SEARCH_KEYS_ERROR_CODES)[keyof typeof SEARCH_KEYS_ERROR_CODES]);
20
19
  }
21
- //#endregion
22
- //#region src/search/normalize.d.ts
23
20
  /**
24
21
  * Search-as-you-type text rules, shared by the WRITER (the search keys stored on
25
22
  * every document) and the READER (the query typed into a search box).
@@ -76,8 +73,6 @@ interface SearchMatchRange {
76
73
  * // [{ start: 0, end: 3 }, { start: 12, end: 15 }]
77
74
  */
78
75
  declare function findSearchMatches(text: string, query: string): SearchMatchRange[];
79
- //#endregion
80
- //#region src/search/prefix.d.ts
81
76
  /**
82
77
  * Indexed search-as-you-type (`searchMode: 'prefix'`): the stored keys, the
83
78
  * query filter, and the index/schema declarations. Pure: no mongoose import.
@@ -165,5 +160,4 @@ declare function searchKeysIndex(field?: string, options?: {
165
160
  name: string;
166
161
  };
167
162
  };
168
- //#endregion
169
163
  export { prefixSearchFilter as a, SearchMatchRange as c, tokenizeSearchText as d, SEARCH_KEYS_ERROR_CODES as f, buildSearchKeys as i, findSearchMatches as l, MAX_PREFIX_SEARCH_TERMS as n, searchKeysIndex as o, SearchKeysWriteError as p, PrefixSearchFilterOptions as r, searchKeysPath as s, DEFAULT_SEARCH_KEYS_FIELD as t, normalizeSearchText as u };