@classytic/mongokit 3.16.2 → 3.17.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 (32) hide show
  1. package/dist/{PaginationEngine-0XXTW-9b.mjs → PaginationEngine-BcvaXBQ-.mjs} +4 -4
  2. package/dist/{Repository-DE7D2QeS.mjs → Repository-B01VW_fU.mjs} +79 -79
  3. package/dist/actions/index.d.mts +1 -1
  4. package/dist/actions/index.mjs +1 -1
  5. package/dist/adapter/index.d.mts +1 -1
  6. package/dist/adapter/index.mjs +1 -1
  7. package/dist/{adapter-gG_uyFSZ.mjs → adapter-DYEMkLwK.mjs} +1 -1
  8. package/dist/ai/index.d.mts +1 -1
  9. package/dist/ai/index.mjs +1 -1
  10. package/dist/better-auth/index.mjs +2 -2
  11. package/dist/{id-resolution-DduoO4LI.mjs → id-resolution-CnN0YA8t.mjs} +21 -1
  12. package/dist/{index-CV5vv-8E.d.mts → index-fi91ycQc.d.mts} +1 -1
  13. package/dist/index.d.mts +84 -6
  14. package/dist/index.mjs +139 -8
  15. package/dist/{mongooseToJsonSchema-GhvZUjRO.d.mts → mongooseToJsonSchema-BdQJU39w.d.mts} +76 -2
  16. package/dist/{mongooseToJsonSchema-CMM2QHzd.mjs → mongooseToJsonSchema-CBEQmeEa.mjs} +1 -1
  17. package/dist/pagination/PaginationEngine.d.mts +1 -1
  18. package/dist/pagination/PaginationEngine.mjs +1 -1
  19. package/dist/plugins/index.d.mts +1 -1
  20. package/dist/plugins/index.mjs +1 -1
  21. package/dist/query/primitives/coercion.mjs +1 -1
  22. package/dist/{types-BWZILovv.d.mts → types-CU3SEDbD.d.mts} +4 -4
  23. package/dist/{update-BXMnCvO6.mjs → update-CvCMv5Cl.mjs} +2 -2
  24. package/dist/utils/index.d.mts +1 -59
  25. package/dist/utils/index.mjs +4 -4
  26. package/dist/{validation-chain.plugin-Iee2_puD.d.mts → validation-chain.plugin-BpMfy18N.d.mts} +2 -2
  27. package/dist/{validation-chain.plugin-Crl5nQAY.mjs → validation-chain.plugin-DJtC0KJ-.mjs} +5 -5
  28. package/package.json +1 -1
  29. /package/dist/{cursor-4LMYa4ga.mjs → cursor-_SbWVAn-.mjs} +0 -0
  30. /package/dist/{error-B00pI7dV.mjs → error-BTeepSNL.mjs} +0 -0
  31. /package/dist/{logger-DprijP5h.mjs → logger-B8wf-Mtb.mjs} +0 -0
  32. /package/dist/{sort-RPVz5u0w.mjs → sort-Ca1BPfvE.mjs} +0 -0
@@ -1,7 +1,7 @@
1
- import { n as warn } from "./logger-DprijP5h.mjs";
2
- import { t as createError } from "./error-B00pI7dV.mjs";
3
- import { n as encodeCursor, r as resolveCursorFilter } from "./cursor-4LMYa4ga.mjs";
4
- import { r as validateKeysetSort, t as getPrimaryField } from "./sort-RPVz5u0w.mjs";
1
+ import { n as warn } from "./logger-B8wf-Mtb.mjs";
2
+ import { t as createError } from "./error-BTeepSNL.mjs";
3
+ import { n as encodeCursor, r as resolveCursorFilter } from "./cursor-_SbWVAn-.mjs";
4
+ import { r as validateKeysetSort, t as getPrimaryField } from "./sort-Ca1BPfvE.mjs";
5
5
  //#region src/pagination/utils/index-hint.ts
6
6
  /**
7
7
  * Read a Mongoose schema's declared indexes, defensively.
@@ -1,15 +1,83 @@
1
- import { a as count, b as LookupBuilder, c as getByQuery, d as deleteById, f as deleteByQuery, h as createMany, l as getOrCreate, m as create, n as update, o as exists, r as updateByQuery, s as getById, t as findOneAndUpdate, x as compileFilterToMongo, y as distinct } from "./update-BXMnCvO6.mjs";
2
- import { n as warn } from "./logger-DprijP5h.mjs";
3
- import { n as isDuplicateKeyError, r as parseDuplicateKeyError, t as createError } from "./error-B00pI7dV.mjs";
4
- import { t as PaginationEngine } from "./PaginationEngine-0XXTW-9b.mjs";
1
+ import { i as isValidIdForType, t as getSchemaIdType } from "./id-resolution-CnN0YA8t.mjs";
2
+ import { a as count, b as LookupBuilder, c as getByQuery, d as deleteById, f as deleteByQuery, h as createMany, l as getOrCreate, m as create, n as update, o as exists, r as updateByQuery, s as getById, t as findOneAndUpdate, x as compileFilterToMongo, y as distinct } from "./update-CvCMv5Cl.mjs";
3
+ import { n as warn } from "./logger-B8wf-Mtb.mjs";
4
+ import { n as isDuplicateKeyError, r as parseDuplicateKeyError, t as createError } from "./error-BTeepSNL.mjs";
5
+ import { t as PaginationEngine } from "./PaginationEngine-BcvaXBQ-.mjs";
5
6
  import { hasNearOperator, rewriteNearForCount } from "./query/primitives/geo.mjs";
6
- import { r as isValidIdForType, t as getSchemaIdType } from "./id-resolution-DduoO4LI.mjs";
7
- import { isFilter } from "@classytic/repo-core/filter";
7
+ import { RepositoryBase, runChunkedPurge, throwIfAborted, validatePluginOrder, withRetry } from "@classytic/repo-core/repository";
8
8
  import mongoose from "mongoose";
9
+ import { isFilter } from "@classytic/repo-core/filter";
9
10
  import { HOOK_PRIORITY } from "@classytic/repo-core/hooks";
10
- import { RepositoryBase, runChunkedPurge, throwIfAborted, validatePluginOrder, withRetry } from "@classytic/repo-core/repository";
11
11
  import { compileUpdateSpecToMongo, isUpdateSpec } from "@classytic/repo-core/update";
12
12
  import { decodeAggCursor, encodeAggCursor, isKeysetMode, normalizeGroupBy, validateMeasures } from "@classytic/repo-core/aggregate";
13
+ //#region src/actions/purge.ts
14
+ /**
15
+ * Build a `PurgePort` bound to a repository + the `field = value`
16
+ * predicate the purge targets.
17
+ */
18
+ function createMongoPurgePort(repo, field, value, session) {
19
+ const filter = { [field]: value };
20
+ const baseOpts = {
21
+ session,
22
+ bypassTenant: true
23
+ };
24
+ return { async purgeChunk(strategy, limit) {
25
+ if (strategy.type === "anonymize") {
26
+ if (Object.values(strategy.fields).some((v) => typeof v === "function")) return purgeAnonymizeFunctional(repo, filter, strategy.fields, limit, session);
27
+ }
28
+ const idDocs = await repo.Model.find(filter, { _id: 1 }).limit(limit).session(session ?? null).lean().exec();
29
+ if (idDocs.length === 0) return 0;
30
+ const chunkFilter = {
31
+ _id: { $in: idDocs.map((d) => d._id) },
32
+ [field]: value
33
+ };
34
+ switch (strategy.type) {
35
+ case "hard":
36
+ await repo.deleteMany(chunkFilter, {
37
+ ...baseOpts,
38
+ mode: "hard"
39
+ });
40
+ return idDocs.length;
41
+ case "soft":
42
+ await repo.updateMany(chunkFilter, { $set: {
43
+ [strategy.deletedField ?? "deleted"]: true,
44
+ [strategy.deletedAtField ?? "deletedAt"]: /* @__PURE__ */ new Date()
45
+ } }, baseOpts);
46
+ return idDocs.length;
47
+ case "anonymize":
48
+ await repo.updateMany(chunkFilter, { $set: strategy.fields }, baseOpts);
49
+ return idDocs.length;
50
+ }
51
+ } };
52
+ }
53
+ /**
54
+ * Anonymize with at least one function-form field replacer. Fetches the
55
+ * full docs (function needs the row) and issues ONE `bulkWrite` with N
56
+ * heterogeneous `updateOne` ops. Two round-trips per chunk regardless
57
+ * of N — vs the N+1 of per-doc `update()` fan-out.
58
+ *
59
+ * Mongo's `bulkWrite` is ordered: false → independent failures don't
60
+ * abort the batch. For idempotent anonymize (same row anonymized twice
61
+ * is the same write), this matches the at-least-once contract.
62
+ */
63
+ async function purgeAnonymizeFunctional(repo, filter, fields, limit, session) {
64
+ const docs = await repo.Model.find(filter).limit(limit).session(session ?? null).lean().exec();
65
+ if (docs.length === 0) return 0;
66
+ const operations = docs.map((doc) => {
67
+ const set = {};
68
+ for (const [k, v] of Object.entries(fields)) set[k] = typeof v === "function" ? v(doc) : v;
69
+ return { updateOne: {
70
+ filter: { _id: doc._id },
71
+ update: { $set: set }
72
+ } };
73
+ });
74
+ await repo.Model.bulkWrite(operations, {
75
+ ordered: false,
76
+ session: session ?? void 0
77
+ });
78
+ return docs.length;
79
+ }
80
+ //#endregion
13
81
  //#region src/capabilities.ts
14
82
  const MONGOKIT_CAPABILITIES = {
15
83
  transactions: true,
@@ -845,74 +913,6 @@ function buildKeysetPredicate(sort, cursor) {
845
913
  return { $match: branches.length === 1 ? branches[0] : { $or: branches } };
846
914
  }
847
915
  //#endregion
848
- //#region src/actions/purge.ts
849
- /**
850
- * Build a `PurgePort` bound to a repository + the `field = value`
851
- * predicate the purge targets.
852
- */
853
- function createMongoPurgePort(repo, field, value, session) {
854
- const filter = { [field]: value };
855
- const baseOpts = {
856
- session,
857
- bypassTenant: true
858
- };
859
- return { async purgeChunk(strategy, limit) {
860
- if (strategy.type === "anonymize") {
861
- if (Object.values(strategy.fields).some((v) => typeof v === "function")) return purgeAnonymizeFunctional(repo, filter, strategy.fields, limit, session);
862
- }
863
- const idDocs = await repo.Model.find(filter, { _id: 1 }).limit(limit).session(session ?? null).lean().exec();
864
- if (idDocs.length === 0) return 0;
865
- const chunkFilter = {
866
- _id: { $in: idDocs.map((d) => d._id) },
867
- [field]: value
868
- };
869
- switch (strategy.type) {
870
- case "hard":
871
- await repo.deleteMany(chunkFilter, {
872
- ...baseOpts,
873
- mode: "hard"
874
- });
875
- return idDocs.length;
876
- case "soft":
877
- await repo.updateMany(chunkFilter, { $set: {
878
- [strategy.deletedField ?? "deleted"]: true,
879
- [strategy.deletedAtField ?? "deletedAt"]: /* @__PURE__ */ new Date()
880
- } }, baseOpts);
881
- return idDocs.length;
882
- case "anonymize":
883
- await repo.updateMany(chunkFilter, { $set: strategy.fields }, baseOpts);
884
- return idDocs.length;
885
- }
886
- } };
887
- }
888
- /**
889
- * Anonymize with at least one function-form field replacer. Fetches the
890
- * full docs (function needs the row) and issues ONE `bulkWrite` with N
891
- * heterogeneous `updateOne` ops. Two round-trips per chunk regardless
892
- * of N — vs the N+1 of per-doc `update()` fan-out.
893
- *
894
- * Mongo's `bulkWrite` is ordered: false → independent failures don't
895
- * abort the batch. For idempotent anonymize (same row anonymized twice
896
- * is the same write), this matches the at-least-once contract.
897
- */
898
- async function purgeAnonymizeFunctional(repo, filter, fields, limit, session) {
899
- const docs = await repo.Model.find(filter).limit(limit).session(session ?? null).lean().exec();
900
- if (docs.length === 0) return 0;
901
- const operations = docs.map((doc) => {
902
- const set = {};
903
- for (const [k, v] of Object.entries(fields)) set[k] = typeof v === "function" ? v(doc) : v;
904
- return { updateOne: {
905
- filter: { _id: doc._id },
906
- update: { $set: set }
907
- } };
908
- });
909
- await repo.Model.bulkWrite(operations, {
910
- ordered: false,
911
- session: session ?? void 0
912
- });
913
- return docs.length;
914
- }
915
- //#endregion
916
916
  //#region src/query/AggregationBuilder.ts
917
917
  /**
918
918
  * Normalize SortSpec to MongoDB's strict format (1 | -1)
@@ -3614,9 +3614,9 @@ var Repository = class extends RepositoryBase {
3614
3614
  };
3615
3615
  if (isKeyset && sort) {
3616
3616
  const parsedSort = this._parseSort(sort);
3617
- const { validateKeysetSort } = await import("./sort-RPVz5u0w.mjs").then((n) => n.n);
3618
- const { encodeCursor, resolveCursorFilter } = await import("./cursor-4LMYa4ga.mjs").then((n) => n.t);
3619
- const { getPrimaryField } = await import("./sort-RPVz5u0w.mjs").then((n) => n.n);
3617
+ const { validateKeysetSort } = await import("./sort-Ca1BPfvE.mjs").then((n) => n.n);
3618
+ const { encodeCursor, resolveCursorFilter } = await import("./cursor-_SbWVAn-.mjs").then((n) => n.t);
3619
+ const { getPrimaryField } = await import("./sort-Ca1BPfvE.mjs").then((n) => n.n);
3620
3620
  const normalizedSort = validateKeysetSort(parsedSort, this._pagination.config.strictKeysetSortFields);
3621
3621
  const cursorVersion = this._pagination.config.cursorVersion ?? 1;
3622
3622
  const minCursorVersion = this._pagination.config.minCursorVersion ?? 1;
@@ -4016,4 +4016,4 @@ var Repository = class extends RepositoryBase {
4016
4016
  }
4017
4017
  };
4018
4018
  //#endregion
4019
- export { withTransaction as a, MUTATING_OPERATIONS as c, operationsByPolicyKey as d, MONGOKIT_CAPABILITIES as f, isTransactionUnsupported as i, OP_REGISTRY as l, Repository as n, AggregationBuilder as o, batchTransaction as r, ALL_OPERATIONS as s, HOOK_PRIORITY$1 as t, READ_OPERATIONS as u };
4019
+ export { withTransaction as a, MUTATING_OPERATIONS as c, operationsByPolicyKey as d, MONGOKIT_CAPABILITIES as f, isTransactionUnsupported as i, OP_REGISTRY as l, Repository as n, AggregationBuilder as o, createMongoPurgePort as p, batchTransaction as r, ALL_OPERATIONS as s, HOOK_PRIORITY$1 as t, READ_OPERATIONS as u };
@@ -1,2 +1,2 @@
1
- import { a as create_d_exports, i as delete_d_exports, n as update_d_exports, o as aggregate_d_exports, r as read_d_exports } from "../index-CV5vv-8E.mjs";
1
+ import { a as create_d_exports, i as delete_d_exports, n as update_d_exports, o as aggregate_d_exports, r as read_d_exports } from "../index-fi91ycQc.mjs";
2
2
  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 };
@@ -1,5 +1,5 @@
1
1
  import { t as __exportAll } from "../chunk-CfYAbeIz.mjs";
2
- import { g as create_exports, i as update_exports, p as delete_exports, u as read_exports, v as aggregate_exports } from "../update-BXMnCvO6.mjs";
2
+ import { g as create_exports, i as update_exports, p as delete_exports, u as read_exports, v as aggregate_exports } from "../update-CvCMv5Cl.mjs";
3
3
  //#region src/actions/index.ts
4
4
  var actions_exports = /* @__PURE__ */ __exportAll({
5
5
  aggregate: () => aggregate_exports,
@@ -1,5 +1,5 @@
1
- import { Document, Model } from "mongoose";
2
1
  import { StandardRepo } from "@classytic/repo-core/repository";
2
+ import { Document, Model } from "mongoose";
3
3
  import { SchemaBuilderOptions, SchemaGenerator } from "@classytic/repo-core/schema";
4
4
  import { AdapterRepositoryInput, AdapterSchemaContext, AdapterValidationResult, DataAdapter, OpenApiSchemas, RepositoryLike, SchemaMetadata } from "@classytic/repo-core/adapter";
5
5
 
@@ -1,2 +1,2 @@
1
- import { n as createMongooseAdapter, r as isMongooseModel, t as MongooseAdapter } from "../adapter-gG_uyFSZ.mjs";
1
+ import { n as createMongooseAdapter, r as isMongooseModel, t as MongooseAdapter } from "../adapter-DYEMkLwK.mjs";
2
2
  export { MongooseAdapter, createMongooseAdapter, isMongooseModel };
@@ -1,4 +1,4 @@
1
- import { n as warn } from "./logger-DprijP5h.mjs";
1
+ import { n as warn } from "./logger-B8wf-Mtb.mjs";
2
2
  import { mergeFieldRuleConstraints } from "@classytic/repo-core/schema";
3
3
  import { asRepositoryLike, isRepository } from "@classytic/repo-core/adapter";
4
4
  //#region src/adapter/types.ts
@@ -1,4 +1,4 @@
1
- import { G as Plugin } from "../types-BWZILovv.mjs";
1
+ import { G as Plugin } from "../types-CU3SEDbD.mjs";
2
2
  import { PipelineStage } from "mongoose";
3
3
 
4
4
  //#region src/ai/types.d.ts
package/dist/ai/index.mjs CHANGED
@@ -1,4 +1,4 @@
1
- import { n as warn } from "../logger-DprijP5h.mjs";
1
+ import { n as warn } from "../logger-B8wf-Mtb.mjs";
2
2
  //#region src/ai/url-policy.ts
3
3
  /**
4
4
  * URL policy helpers for the vector plugin media pipeline.
@@ -1,5 +1,5 @@
1
- import { n as Repository } from "../Repository-DE7D2QeS.mjs";
2
- import { n as createMongooseAdapter } from "../adapter-gG_uyFSZ.mjs";
1
+ import { n as Repository } from "../Repository-B01VW_fU.mjs";
2
+ import { n as createMongooseAdapter } from "../adapter-DYEMkLwK.mjs";
3
3
  import { pluralizeBetterAuthCollection, resolveBetterAuthCollections } from "@classytic/repo-core/better-auth";
4
4
  //#region src/better-auth/index.ts
5
5
  /**
@@ -77,5 +77,25 @@ function isValidIdForType(id, idType) {
77
77
  case "unknown": return String(id).length > 0;
78
78
  }
79
79
  }
80
+ /**
81
+ * Return every form an id might be stored as, for use in a `{ field: { $in: ... } }`
82
+ * match. The Better Auth mongo adapter (and mixed mongoose/overlay writes) store
83
+ * the same logical id as either a hex STRING or an ObjectId depending on the code
84
+ * path, so a query keyed on one form silently misses rows stored as the other.
85
+ *
86
+ * - A 12-byte / 24-hex string that `ObjectId.isValid` accepts → `[hex, ObjectId(hex)]`.
87
+ * - Anything else (non-ObjectId string, number, an ObjectId instance, …) → `[id]`.
88
+ *
89
+ * Over-matching is harmless — the extra `$in` term can't match a non-existent doc.
90
+ * Replaces the `Types.ObjectId.isValid(id) ? [id, new Types.ObjectId(id)] : [id]`
91
+ * one-liner that tends to get re-implemented at every call site.
92
+ *
93
+ * @example
94
+ * await col.deleteMany({ customerId: { $in: idVariants(userId) } });
95
+ */
96
+ function idVariants(id) {
97
+ if (typeof id === "string" && id.length > 0 && mongoose.Types.ObjectId.isValid(id)) return [id, new mongoose.Types.ObjectId(id)];
98
+ return [id];
99
+ }
80
100
  //#endregion
81
- export { isObjectIdInstance as n, isValidIdForType as r, getSchemaIdType as t };
101
+ export { isValidIdForType as i, idVariants as n, isObjectIdInstance as r, getSchemaIdType as t };
@@ -1,4 +1,4 @@
1
- import { B as ObjectId, Dt as LookupOptions, H as OperationOptions, I as MinMaxResult, J as PopulateSpec, T as GroupResult, Z as ReadPreferenceType, ft as UpdateManyResult, ht as UpdateWithValidationResult, i as AnyDocument, it as SelectSpec, p as CreateOptions, pt as UpdateOptions, ut as SortSpec, v as DeleteResult, w as FindOneAndUpdateOptions } from "./types-BWZILovv.mjs";
1
+ import { B as ObjectId, Dt as LookupOptions, H as OperationOptions, I as MinMaxResult, J as PopulateSpec, T as GroupResult, Z as ReadPreferenceType, ft as UpdateManyResult, ht as UpdateWithValidationResult, i as AnyDocument, it as SelectSpec, p as CreateOptions, pt as UpdateOptions, ut as SortSpec, v as DeleteResult, w as FindOneAndUpdateOptions } from "./types-CU3SEDbD.mjs";
2
2
  import { Model, PipelineStage } from "mongoose";
3
3
 
4
4
  //#region src/actions/aggregate.d.ts
package/dist/index.d.mts CHANGED
@@ -1,17 +1,95 @@
1
- import { $ as RepositoryEvent, A as KeysetPaginationOptions, B as ObjectId, C as FieldPreset, Ct as IControllerResponse, D as InferDocument, Dt as LookupOptions, E as HookMode, Et as LookupBuilder, F as MiddlewareContext, G as Plugin, H as OperationOptions, I as MinMaxResult, J as PopulateSpec, K as PluginFunction, L as MinimalRepoView, M as LookupPopulateOptions, N as LookupPopulateResult, O as InferRawDoc, P as Middleware, Q as RepositoryContext, R as MongoOperatorUpdate, S as EventPhase, St as IController, T as GroupResult, Tt as IResponseFormatter, U as PaginationConfig, V as OffsetPaginationOptions, W as PartialBy, X as ReadOptions, Y as PrioritizedHook, Z as ReadPreferenceType, _ as DeleteManyResult, _t as ValidationChainOptions, a as AnyModel, at as SessionOptions, b as EventHandlers, bt as WithPlugins, c as CacheableOptions, ct as SoftDeleteRepository, d as CollationOptions, dt as Strict, et as RepositoryInstance, f as CreateInput, ft as UpdateManyResult, g as DeepPartial, gt as UserContext, h as DecodedCursor, ht as UpdateWithValidationResult, i as AnyDocument, it as SelectSpec, j as Logger, k as KeysOfType, l as CascadeOptions, lt as SortDirection, m as CursorPayload, mt as UpdatePatch, n as AggregatePaginationOptions, nt as RepositoryOptions, o as BasePaginationOptions, ot as SoftDeleteFilterMode, p as CreateOptions, pt as UpdateOptions, q as PluginType, r as AllPluginMethods, rt as RequiredBy, s as CacheOperationOptions, st as SoftDeleteOptions, t as AggregateOptions, tt as RepositoryOperation, u as CascadeRelation, ut as SortSpec, v as DeleteResult, vt as ValidatorDefinition, w as FindOneAndUpdateOptions, wt as IRequestContext, x as EventPayload, xt as WithTransactionOptions, y as DocField, yt as ValueType, z as NonNullableFields } from "./types-BWZILovv.mjs";
2
- import { t as index_d_exports } from "./index-CV5vv-8E.mjs";
3
- import { $ as AuditEntry, A as BulkWriteResult, B as IdGenerator, C as LeasePluginOptions, D as elasticSearchPlugin, E as ElasticSearchOptions, F as MultiTenantOptions, G as getNextSequence, H as SequentialIdOptions, I as adminBypass, J as CacheAdapter, K as prefixedId, L as multiTenantPlugin, M as auditLogPlugin, N as AggregateHelpersMethods, O as cascadePlugin, P as aggregateHelpersPlugin, Q as cachePlugin, R as CustomIdOptions, S as LeaseMethods, T as fieldFilterPlugin, U as customIdPlugin, V as PrefixedIdOptions, W as dateSequentialId, X as RepositoryCacheHandle, Y as CacheOptions, Z as RepositoryCachePluginOptions, _ as observabilityPlugin, a as uniqueField, at as AuditTrailQuery, c as TenantContext, d as SubdocumentMethods, et as AuditOperation, f as subdocumentPlugin, g as OperationMetric, h as ObservabilityOptions, i as requireField, it as AuditTrailOptions, j as batchOperationsPlugin, k as BatchOperationsMethods, l as TenantStore, m as softDeletePlugin, n as blockIf, nt as AuditQueryResult, o as validationChainPlugin, ot as auditTrailPlugin, p as SoftDeleteMethods, q as sequentialId, r as immutableField, rt as AuditTrailMethods, s as timestampPlugin, t as autoInject, tt as AuditQueryOptions, u as createTenantContext, v as MongoOperationsMethods, w as leasePlugin, x as methodRegistryPlugin, y as mongoOperationsPlugin, z as DateSequentialIdOptions } from "./validation-chain.plugin-Iee2_puD.mjs";
1
+ import { $ as RepositoryEvent, A as KeysetPaginationOptions, B as ObjectId, C as FieldPreset, Ct as IControllerResponse, D as InferDocument, Dt as LookupOptions, E as HookMode, Et as LookupBuilder, F as MiddlewareContext, G as Plugin, H as OperationOptions, I as MinMaxResult, J as PopulateSpec, K as PluginFunction, L as MinimalRepoView, M as LookupPopulateOptions, N as LookupPopulateResult, O as InferRawDoc, P as Middleware, Q as RepositoryContext, R as MongoOperatorUpdate, S as EventPhase, St as IController, T as GroupResult, Tt as IResponseFormatter, U as PaginationConfig, V as OffsetPaginationOptions, W as PartialBy, X as ReadOptions, Y as PrioritizedHook, Z as ReadPreferenceType, _ as DeleteManyResult, _t as ValidationChainOptions, a as AnyModel, at as SessionOptions, b as EventHandlers, bt as WithPlugins, c as CacheableOptions, ct as SoftDeleteRepository, d as CollationOptions, dt as Strict, et as RepositoryInstance, f as CreateInput, ft as UpdateManyResult, g as DeepPartial, gt as UserContext, h as DecodedCursor, ht as UpdateWithValidationResult, i as AnyDocument, it as SelectSpec, j as Logger, k as KeysOfType, l as CascadeOptions, lt as SortDirection, m as CursorPayload, mt as UpdatePatch, n as AggregatePaginationOptions, nt as RepositoryOptions, o as BasePaginationOptions, ot as SoftDeleteFilterMode, p as CreateOptions, pt as UpdateOptions, q as PluginType, r as AllPluginMethods, rt as RequiredBy, s as CacheOperationOptions, st as SoftDeleteOptions, t as AggregateOptions, tt as RepositoryOperation, u as CascadeRelation, ut as SortSpec, v as DeleteResult, vt as ValidatorDefinition, w as FindOneAndUpdateOptions, wt as IRequestContext, x as EventPayload, xt as WithTransactionOptions, y as DocField, yt as ValueType, z as NonNullableFields } from "./types-CU3SEDbD.mjs";
2
+ import { t as index_d_exports } from "./index-fi91ycQc.mjs";
3
+ import { $ as AuditEntry, A as BulkWriteResult, B as IdGenerator, C as LeasePluginOptions, D as elasticSearchPlugin, E as ElasticSearchOptions, F as MultiTenantOptions, G as getNextSequence, H as SequentialIdOptions, I as adminBypass, J as CacheAdapter, K as prefixedId, L as multiTenantPlugin, M as auditLogPlugin, N as AggregateHelpersMethods, O as cascadePlugin, P as aggregateHelpersPlugin, Q as cachePlugin, R as CustomIdOptions, S as LeaseMethods, T as fieldFilterPlugin, U as customIdPlugin, V as PrefixedIdOptions, W as dateSequentialId, X as RepositoryCacheHandle, Y as CacheOptions, Z as RepositoryCachePluginOptions, _ as observabilityPlugin, a as uniqueField, at as AuditTrailQuery, c as TenantContext, d as SubdocumentMethods, et as AuditOperation, f as subdocumentPlugin, g as OperationMetric, h as ObservabilityOptions, i as requireField, it as AuditTrailOptions, j as batchOperationsPlugin, k as BatchOperationsMethods, l as TenantStore, m as softDeletePlugin, n as blockIf, nt as AuditQueryResult, o as validationChainPlugin, ot as auditTrailPlugin, p as SoftDeleteMethods, q as sequentialId, r as immutableField, rt as AuditTrailMethods, s as timestampPlugin, t as autoInject, tt as AuditQueryOptions, u as createTenantContext, v as MongoOperationsMethods, w as leasePlugin, x as methodRegistryPlugin, y as mongoOperationsPlugin, z as DateSequentialIdOptions } from "./validation-chain.plugin-BpMfy18N.mjs";
4
4
  import { PaginationEngine } from "./pagination/PaginationEngine.mjs";
5
5
  import { n as SchemaPathsLike, t as FieldType$1 } from "./coercion-TRMmR49h.mjs";
6
6
  import { n as SchemaIndexes } from "./indexes-CgOF7Wjd.mjs";
7
- import { a as createFieldPreset, c as getMongooseProjection, d as parseDuplicateKeyError, i as configureLogger, l as createError, n as buildCrudSchemasFromMongooseSchema, o as filterResponseData, r as createMemoryCache, s as getFieldsForUser, t as buildCrudSchemasFromModel, u as isDuplicateKeyError } from "./mongooseToJsonSchema-GhvZUjRO.mjs";
7
+ import { d as filterResponseData, f as getFieldsForUser, g as parseDuplicateKeyError, h as isDuplicateKeyError, i as configureLogger, m as createError, n as buildCrudSchemasFromMongooseSchema, p as getMongooseProjection, r as createMemoryCache, s as idVariants, t as buildCrudSchemasFromModel, u as createFieldPreset } from "./mongooseToJsonSchema-BdQJU39w.mjs";
8
+ import { AggPaginationRequest, AggRequest, AggResult, ChangeEvent, FilterInput, KeysetAggPaginationResult, QueryOptions, RepoCapabilities, RepositoryBase, TenantPurgeOptions, TenantPurgeResult, TenantPurgeStrategy, WatchOptions } from "@classytic/repo-core/repository";
8
9
  import * as _$mongoose from "mongoose";
9
10
  import { ClientSession, Expression, Model, PipelineStage, PopulateOptions } from "mongoose";
10
- import { AggPaginationRequest, AggRequest, AggResult, ChangeEvent, FilterInput, KeysetAggPaginationResult, QueryOptions, RepoCapabilities, RepositoryBase, TenantPurgeOptions, TenantPurgeResult, TenantPurgeStrategy, WatchOptions } from "@classytic/repo-core/repository";
11
11
  import { UpdateInput } from "@classytic/repo-core/update";
12
12
  import { AggregatePaginationResult, KeysetPaginationResult, OffsetPaginationResult, OffsetPaginationResultCore } from "@classytic/repo-core/pagination";
13
13
  import { HttpError } from "@classytic/repo-core/errors";
14
14
 
15
+ //#region src/actions/cascade-references.d.ts
16
+ type PurgeMode = 'hard' | 'soft' | 'anonymize';
17
+ /** Raw collection surface — a native MongoDB `Collection` or a Mongoose `Model`. */
18
+ interface CollectionRWLike {
19
+ readonly collectionName?: string;
20
+ deleteMany(filter: Record<string, unknown>): Promise<{
21
+ deletedCount?: number;
22
+ }>;
23
+ updateMany(filter: Record<string, unknown>, update: Record<string, unknown>): Promise<{
24
+ modifiedCount?: number;
25
+ }>;
26
+ }
27
+ /** Repository surface for the policy-preserving path (matches `createMongoPurgePort`). */
28
+ interface PurgeableRepoLike {
29
+ readonly Model: {
30
+ readonly modelName?: string;
31
+ };
32
+ deleteMany(filter: Record<string, unknown>, options?: Record<string, unknown>): Promise<unknown>;
33
+ updateMany(filter: Record<string, unknown>, data: Record<string, unknown>, options?: Record<string, unknown>): Promise<unknown>;
34
+ }
35
+ interface ReferenceRelation {
36
+ /** Policy-preserving target — a mongokit Repository (chunked via repo-core). */
37
+ repo?: PurgeableRepoLike;
38
+ /** Raw target — a collection with no Repository (e.g. a Better Auth table). */
39
+ collection?: CollectionRWLike;
40
+ /** Field on the target holding the reference id. */
41
+ field: string;
42
+ /** Override the call-level `mode` for this relation. */
43
+ mode?: PurgeMode;
44
+ /** `$set` patch applied when the resolved mode is `'anonymize'`. */
45
+ anonymizeFields?: Record<string, unknown>;
46
+ /** Soft-delete field names (default `'deleted'` / `'deletedAt'`). */
47
+ softDeletedField?: string;
48
+ softDeletedAtField?: string;
49
+ }
50
+ interface CascadePurgeReferencesOptions {
51
+ /** The value every relation's `field` is matched against (usually an id). */
52
+ value: unknown;
53
+ /** Targets to purge. */
54
+ relations: ReferenceRelation[];
55
+ /** Default mode for relations without an override. Default `'hard'`. */
56
+ mode?: PurgeMode;
57
+ /** Also match the ObjectId/hex variant of `value`. Default `true`. */
58
+ matchIdVariants?: boolean;
59
+ /** Run relations concurrently. Default `true`. */
60
+ parallel?: boolean;
61
+ /** Chunk size for repo-routed relations. Default `1000`. */
62
+ batchSize?: number;
63
+ session?: ClientSession;
64
+ }
65
+ interface ReferencePurgeResult {
66
+ /** Model or collection name. */
67
+ target: string;
68
+ field: string;
69
+ mode: PurgeMode;
70
+ /** Rows deleted (hard) or modified (soft / anonymize). */
71
+ affected: number;
72
+ ok: boolean;
73
+ error?: string;
74
+ }
75
+ /**
76
+ * Purge every relation that references `value`. Returns a per-relation report
77
+ * (never rejects for in-strategy errors). Pass arrays/objects as actual values.
78
+ *
79
+ * @example Better Auth user-delete cleanup (raw collections, hard delete):
80
+ * ```ts
81
+ * await cascadePurgeReferences({
82
+ * value: userId,
83
+ * relations: [
84
+ * { collection: db.collection('downloadgrants'), field: 'customerId' },
85
+ * { collection: db.collection('enrollments'), field: 'customerId' },
86
+ * { collection: db.collection('member'), field: 'userId' },
87
+ * ],
88
+ * });
89
+ * ```
90
+ */
91
+ declare function cascadePurgeReferences(options: CascadePurgeReferencesOptions): Promise<ReferencePurgeResult[]>;
92
+ //#endregion
15
93
  //#region src/capabilities.d.ts
16
94
  declare const MONGOKIT_CAPABILITIES: RepoCapabilities;
17
95
  //#endregion
@@ -2429,4 +2507,4 @@ declare function createOptionsExtractor<TCtx extends Record<string, unknown>>(fi
2429
2507
  */
2430
2508
  declare function systemContext(extra?: SessionOptions): SessionOptions;
2431
2509
  //#endregion
2432
- export { ALL_OPERATIONS, type AggregateHelpersMethods, type AggregateOptions, type AggregatePaginationOptions, AggregationBuilder, type AllPluginMethods, type AnyDocument, type AnyModel, type AuditConfig, type AuditEntry, type AuditOperation, type AuditQueryOptions, type AuditQueryResult, type AuditTrailMethods, type AuditTrailOptions, AuditTrailQuery, type BasePaginationOptions, type BatchOperationsMethods, type BulkWriteResult, type CacheAdapter, type CacheOperationOptions, type CacheOptions, type CacheableOptions, type CascadeOptions, type CascadeRelation, type CollationOptions, type CreateInput, type CreateOptions, type CreateRepositoryConfig, type CursorPayload, type CustomIdOptions, type DateSequentialIdOptions, type DecodedCursor, type DeepPartial, type DeleteResult, type DocField, type ElasticSearchOptions, type EventHandlers, type EventPayload, type EventPhase, type FieldPreset, type FieldType, type FilterQuery, type FindOneAndUpdateOptions, type GroupResult, HOOK_PRIORITY, type HookMode, type IController, type IControllerResponse, type IRequestContext, type IResponseFormatter, type IdGenerator, type InferDocument, type InferRawDoc, type KeysOfType, type KeysetPaginationOptions, type LeaseMethods, type LeasePluginOptions, type Logger, LookupBuilder, type LookupOptions, type LookupPopulateOptions, type LookupPopulateResult, MONGOKIT_CAPABILITIES, MUTATING_OPERATIONS, type Middleware, type MiddlewareContext, type MinMaxResult, type MinimalRepoView, type MongoOperationsMethods, type MongoOperatorUpdate, type MultiTenantOptions, type NonNullableFields, OP_REGISTRY, type ObjectId, type ObservabilityOptions, type OffsetPaginationOptions, type OperationDescriptor, type OperationMetric, type OperationOptions, type PaginationConfig, PaginationEngine, type ParsedQuery, type PartialBy, type Plugin, type PluginFunction, type PluginType, type PolicyKey, type PopulateOption, type PopulateSpec, type PrefixedIdOptions, type PrioritizedHook, QueryParser, type QueryParserOptions, READ_OPERATIONS, type ReadOptions, type ReadPreferenceType, Repository, Repository as default, type RepositoryCacheHandle, type RepositoryCachePluginOptions, type RepositoryContext, type RepositoryEvent, type RepositoryInstance, type RepositoryOperation, type RepositoryOptions, type RequiredBy, type SchemaLike, type SearchMode, type SelectSpec, type SequentialIdOptions, type SessionOptions, type SoftDeleteFilterMode, type SoftDeleteMethods, type SoftDeleteOptions, type SoftDeleteRepository, type SortDirection, type SortSpec, type Strict, type SubdocumentMethods, type TenantContext, type TenantStore, type UpdateManyResult, type UpdateOptions, type UpdatePatch, type UpdateWithValidationResult, type UserContext, type ValidationChainOptions, type ValidatorDefinition, type ValueType, type WithPlugins, type WithTransactionOptions, index_d_exports as actions, adminBypass, aggregateHelpersPlugin, auditLogPlugin, auditTrailPlugin, autoInject, batchOperationsPlugin, batchTransaction, blockIf, buildCrudSchemasFromModel, buildCrudSchemasFromMongooseSchema, cachePlugin, cascadePlugin, compileFilterToMongo, configureLogger, createError, createFieldPreset, createMemoryCache, createOptionsExtractor, createRepository, createTenantContext, customIdPlugin, dateSequentialId, elasticSearchPlugin, fieldFilterPlugin, filterResponseData, getFieldsForUser, getMongooseProjection, getNextSequence, immutableField, isDuplicateKeyError, isTransactionUnsupported, leasePlugin, methodRegistryPlugin, mongoOperationsPlugin, multiTenantPlugin, observabilityPlugin, operationsByPolicyKey, parseDuplicateKeyError, prefixedId, repoOptionsFromCtx, requireField, sequentialId, softDeletePlugin, subdocumentPlugin, systemContext, timestampPlugin, uniqueField, validationChainPlugin, withTransaction };
2510
+ export { ALL_OPERATIONS, type AggregateHelpersMethods, type AggregateOptions, type AggregatePaginationOptions, AggregationBuilder, type AllPluginMethods, type AnyDocument, type AnyModel, type AuditConfig, type AuditEntry, type AuditOperation, type AuditQueryOptions, type AuditQueryResult, type AuditTrailMethods, type AuditTrailOptions, AuditTrailQuery, type BasePaginationOptions, type BatchOperationsMethods, type BulkWriteResult, type CacheAdapter, type CacheOperationOptions, type CacheOptions, type CacheableOptions, type CascadeOptions, type CascadePurgeReferencesOptions, type CascadeRelation, type CollationOptions, type CollectionRWLike, type CreateInput, type CreateOptions, type CreateRepositoryConfig, type CursorPayload, type CustomIdOptions, type DateSequentialIdOptions, type DecodedCursor, type DeepPartial, type DeleteResult, type DocField, type ElasticSearchOptions, type EventHandlers, type EventPayload, type EventPhase, type FieldPreset, type FieldType, type FilterQuery, type FindOneAndUpdateOptions, type GroupResult, HOOK_PRIORITY, type HookMode, type IController, type IControllerResponse, type IRequestContext, type IResponseFormatter, type IdGenerator, type InferDocument, type InferRawDoc, type KeysOfType, type KeysetPaginationOptions, type LeaseMethods, type LeasePluginOptions, type Logger, LookupBuilder, type LookupOptions, type LookupPopulateOptions, type LookupPopulateResult, MONGOKIT_CAPABILITIES, MUTATING_OPERATIONS, type Middleware, type MiddlewareContext, type MinMaxResult, type MinimalRepoView, type MongoOperationsMethods, type MongoOperatorUpdate, type MultiTenantOptions, type NonNullableFields, OP_REGISTRY, type ObjectId, type ObservabilityOptions, type OffsetPaginationOptions, type OperationDescriptor, type OperationMetric, type OperationOptions, type PaginationConfig, PaginationEngine, type ParsedQuery, type PartialBy, type Plugin, type PluginFunction, type PluginType, type PolicyKey, type PopulateOption, type PopulateSpec, type PrefixedIdOptions, type PrioritizedHook, type PurgeMode, type PurgeableRepoLike, QueryParser, type QueryParserOptions, READ_OPERATIONS, type ReadOptions, type ReadPreferenceType, type ReferencePurgeResult, type ReferenceRelation, Repository, Repository as default, type RepositoryCacheHandle, type RepositoryCachePluginOptions, type RepositoryContext, type RepositoryEvent, type RepositoryInstance, type RepositoryOperation, type RepositoryOptions, type RequiredBy, type SchemaLike, type SearchMode, type SelectSpec, type SequentialIdOptions, type SessionOptions, type SoftDeleteFilterMode, type SoftDeleteMethods, type SoftDeleteOptions, type SoftDeleteRepository, type SortDirection, type SortSpec, type Strict, type SubdocumentMethods, type TenantContext, type TenantStore, type UpdateManyResult, type UpdateOptions, type UpdatePatch, type UpdateWithValidationResult, type UserContext, type ValidationChainOptions, type ValidatorDefinition, type ValueType, type WithPlugins, type WithTransactionOptions, index_d_exports as actions, adminBypass, aggregateHelpersPlugin, auditLogPlugin, auditTrailPlugin, autoInject, batchOperationsPlugin, batchTransaction, blockIf, buildCrudSchemasFromModel, buildCrudSchemasFromMongooseSchema, cachePlugin, cascadePlugin, cascadePurgeReferences, compileFilterToMongo, configureLogger, createError, createFieldPreset, createMemoryCache, createOptionsExtractor, createRepository, createTenantContext, customIdPlugin, dateSequentialId, elasticSearchPlugin, fieldFilterPlugin, filterResponseData, getFieldsForUser, getMongooseProjection, getNextSequence, idVariants, immutableField, isDuplicateKeyError, isTransactionUnsupported, leasePlugin, methodRegistryPlugin, mongoOperationsPlugin, multiTenantPlugin, observabilityPlugin, operationsByPolicyKey, parseDuplicateKeyError, prefixedId, repoOptionsFromCtx, requireField, sequentialId, softDeletePlugin, subdocumentPlugin, systemContext, timestampPlugin, uniqueField, validationChainPlugin, withTransaction };
package/dist/index.mjs CHANGED
@@ -1,16 +1,147 @@
1
- import { b as LookupBuilder, x as compileFilterToMongo } from "./update-BXMnCvO6.mjs";
2
- import { n as warn, t as configureLogger } from "./logger-DprijP5h.mjs";
3
- import { n as isDuplicateKeyError, r as parseDuplicateKeyError, t as createError } from "./error-B00pI7dV.mjs";
1
+ import { n as idVariants } from "./id-resolution-CnN0YA8t.mjs";
2
+ import { a as withTransaction, c as MUTATING_OPERATIONS, d as operationsByPolicyKey, f as MONGOKIT_CAPABILITIES, i as isTransactionUnsupported, l as OP_REGISTRY, n as Repository, o as AggregationBuilder, p as createMongoPurgePort, r as batchTransaction, s as ALL_OPERATIONS, t as HOOK_PRIORITY, u as READ_OPERATIONS } from "./Repository-B01VW_fU.mjs";
3
+ import { b as LookupBuilder, x as compileFilterToMongo } from "./update-CvCMv5Cl.mjs";
4
+ import { n as warn, t as configureLogger } from "./logger-B8wf-Mtb.mjs";
5
+ import { n as isDuplicateKeyError, r as parseDuplicateKeyError, t as createError } from "./error-BTeepSNL.mjs";
4
6
  import { t as actions_exports } from "./actions/index.mjs";
5
- import { a as withTransaction, c as MUTATING_OPERATIONS, d as operationsByPolicyKey, f as MONGOKIT_CAPABILITIES, i as isTransactionUnsupported, l as OP_REGISTRY, n as Repository, o as AggregationBuilder, r as batchTransaction, s as ALL_OPERATIONS, t as HOOK_PRIORITY, u as READ_OPERATIONS } from "./Repository-DE7D2QeS.mjs";
6
- import { A as auditLogPlugin, C as getNextSequence, D as batchOperationsPlugin, E as cachePlugin, O as AuditTrailQuery, S as dateSequentialId, T as sequentialId, _ as softDeletePlugin, a as uniqueField, b as methodRegistryPlugin, c as subdocumentPlugin, d as leasePlugin, f as fieldFilterPlugin, g as timestampPlugin, h as aggregateHelpersPlugin, i as requireField, k as auditTrailPlugin, l as observabilityPlugin, m as cascadePlugin, n as blockIf, o as validationChainPlugin, p as elasticSearchPlugin, r as immutableField, s as createTenantContext, t as autoInject, u as mongoOperationsPlugin, v as adminBypass, w as prefixedId, x as customIdPlugin, y as multiTenantPlugin } from "./validation-chain.plugin-Crl5nQAY.mjs";
7
- import { t as PaginationEngine } from "./PaginationEngine-0XXTW-9b.mjs";
7
+ import { A as auditLogPlugin, C as getNextSequence, D as batchOperationsPlugin, E as cachePlugin, O as AuditTrailQuery, S as dateSequentialId, T as sequentialId, _ as softDeletePlugin, a as uniqueField, b as methodRegistryPlugin, c as subdocumentPlugin, d as leasePlugin, f as fieldFilterPlugin, g as timestampPlugin, h as aggregateHelpersPlugin, i as requireField, k as auditTrailPlugin, l as observabilityPlugin, m as cascadePlugin, n as blockIf, o as validationChainPlugin, p as elasticSearchPlugin, r as immutableField, s as createTenantContext, t as autoInject, u as mongoOperationsPlugin, v as adminBypass, w as prefixedId, x as customIdPlugin, y as multiTenantPlugin } from "./validation-chain.plugin-DJtC0KJ-.mjs";
8
+ import { t as PaginationEngine } from "./PaginationEngine-BcvaXBQ-.mjs";
8
9
  import { isGeoOperator, parseGeoFilter } from "./query/primitives/geo.mjs";
9
10
  import { i as getMongooseProjection, n as filterResponseData, r as getFieldsForUser, t as createFieldPreset } from "./field-selection-CQW3WBiK.mjs";
10
11
  import { buildFieldTypeMap, coerceFieldValue, coerceHeuristic } from "./query/primitives/coercion.mjs";
11
12
  import { extractSchemaIndexes } from "./query/primitives/indexes.mjs";
12
- import { n as buildCrudSchemasFromMongooseSchema, r as createMemoryCache, t as buildCrudSchemasFromModel } from "./mongooseToJsonSchema-CMM2QHzd.mjs";
13
+ import { n as buildCrudSchemasFromMongooseSchema, r as createMemoryCache, t as buildCrudSchemasFromModel } from "./mongooseToJsonSchema-CBEQmeEa.mjs";
14
+ import { runChunkedPurge } from "@classytic/repo-core/repository";
13
15
  import { isControlParam } from "@classytic/repo-core/query-parser";
16
+ //#region src/actions/cascade-references.ts
17
+ /**
18
+ * cascadePurgeReferences — imperative, multi-relation "purge by reference".
19
+ *
20
+ * Given a value (typically an id) and a set of relations (each a target +
21
+ * the field that references the value), purge every matching row. The
22
+ * imperative sibling of `cascadePlugin` (which is Repository-delete-EVENT
23
+ * driven): use this when the delete happens OUTSIDE a mongokit Repository —
24
+ * e.g. a Better Auth `user.delete` hook, where BA deletes its own `user` row
25
+ * and the app must clean up its FK-referencing collections (Mongo has no
26
+ * foreign-key cascades; SQL kits get this for free via `onDelete: 'cascade'`).
27
+ *
28
+ * Composition, not duplication:
29
+ * - **repo-routed** relations reuse repo-core's `runChunkedPurge` +
30
+ * `createMongoPurgePort` → chunking, soft/anonymize strategies, plugin
31
+ * hooks (audit / cache), and tenant-bypass all come from the existing
32
+ * layers. No purge logic is re-implemented here.
33
+ * - **collection-routed** relations hit a raw `Collection` (for BA-owned
34
+ * tables that have no Repository) with a direct deleteMany / updateMany.
35
+ * - id matching uses `idVariants` so a value stored as either a hex string
36
+ * or an ObjectId is caught.
37
+ *
38
+ * Never throws for in-strategy failures (mirrors `runChunkedPurge`): each
39
+ * relation returns a `{ ok, error }` line so a partial failure doesn't abort
40
+ * siblings and the caller can log/inspect the full report.
41
+ */
42
+ function toStrategy(mode, rel) {
43
+ if (mode === "soft") return {
44
+ type: "soft",
45
+ deletedField: rel.softDeletedField,
46
+ deletedAtField: rel.softDeletedAtField
47
+ };
48
+ if (mode === "anonymize") return {
49
+ type: "anonymize",
50
+ fields: rel.anonymizeFields ?? {}
51
+ };
52
+ return { type: "hard" };
53
+ }
54
+ async function purgeRelation(rel, match, defaultMode, ctx) {
55
+ const mode = rel.mode ?? defaultMode;
56
+ const target = rel.repo ? rel.repo.Model?.modelName ?? "<repo>" : rel.collection?.collectionName ?? "<collection>";
57
+ if (!rel.repo && !rel.collection) return {
58
+ target: "<unrouted>",
59
+ field: rel.field,
60
+ mode,
61
+ affected: 0,
62
+ ok: false,
63
+ error: "relation needs `repo` or `collection`"
64
+ };
65
+ try {
66
+ if (rel.repo) {
67
+ const repo = rel.repo;
68
+ const port = createMongoPurgePort(repo, rel.field, match, ctx.session);
69
+ const r = await runChunkedPurge(toStrategy(mode, rel), { batchSize: ctx.batchSize ?? 1e3 }, port);
70
+ return {
71
+ target,
72
+ field: rel.field,
73
+ mode,
74
+ affected: r.processed,
75
+ ok: r.ok,
76
+ error: r.error?.message
77
+ };
78
+ }
79
+ const col = rel.collection;
80
+ const filter = { [rel.field]: match };
81
+ if (mode === "hard") {
82
+ const res = await col.deleteMany(filter);
83
+ return {
84
+ target,
85
+ field: rel.field,
86
+ mode,
87
+ affected: res.deletedCount ?? 0,
88
+ ok: true
89
+ };
90
+ }
91
+ const update = mode === "soft" ? { $set: {
92
+ [rel.softDeletedField ?? "deleted"]: true,
93
+ [rel.softDeletedAtField ?? "deletedAt"]: /* @__PURE__ */ new Date()
94
+ } } : { $set: rel.anonymizeFields ?? {} };
95
+ const res = await col.updateMany(filter, update);
96
+ return {
97
+ target,
98
+ field: rel.field,
99
+ mode,
100
+ affected: res.modifiedCount ?? 0,
101
+ ok: true
102
+ };
103
+ } catch (err) {
104
+ return {
105
+ target,
106
+ field: rel.field,
107
+ mode,
108
+ affected: 0,
109
+ ok: false,
110
+ error: err instanceof Error ? err.message : String(err)
111
+ };
112
+ }
113
+ }
114
+ /**
115
+ * Purge every relation that references `value`. Returns a per-relation report
116
+ * (never rejects for in-strategy errors). Pass arrays/objects as actual values.
117
+ *
118
+ * @example Better Auth user-delete cleanup (raw collections, hard delete):
119
+ * ```ts
120
+ * await cascadePurgeReferences({
121
+ * value: userId,
122
+ * relations: [
123
+ * { collection: db.collection('downloadgrants'), field: 'customerId' },
124
+ * { collection: db.collection('enrollments'), field: 'customerId' },
125
+ * { collection: db.collection('member'), field: 'userId' },
126
+ * ],
127
+ * });
128
+ * ```
129
+ */
130
+ async function cascadePurgeReferences(options) {
131
+ const { value, relations, mode = "hard", matchIdVariants = true, parallel = true, session, batchSize } = options;
132
+ if (!relations?.length || value === void 0 || value === null) return [];
133
+ const variants = matchIdVariants ? idVariants(value) : [value];
134
+ const match = variants.length > 1 ? { $in: variants } : variants[0];
135
+ const ctx = {
136
+ session,
137
+ batchSize
138
+ };
139
+ if (parallel) return Promise.all(relations.map((rel) => purgeRelation(rel, match, mode, ctx)));
140
+ const out = [];
141
+ for (const rel of relations) out.push(await purgeRelation(rel, match, mode, ctx));
142
+ return out;
143
+ }
144
+ //#endregion
14
145
  //#region src/create-repository.ts
15
146
  function isLoggerAudit(value) {
16
147
  const v = value;
@@ -1316,4 +1447,4 @@ function systemContext(extra) {
1316
1447
  //#region src/index.ts
1317
1448
  var src_default = Repository;
1318
1449
  //#endregion
1319
- export { ALL_OPERATIONS, AggregationBuilder, AuditTrailQuery, HOOK_PRIORITY, LookupBuilder, MONGOKIT_CAPABILITIES, MUTATING_OPERATIONS, OP_REGISTRY, PaginationEngine, QueryParser, READ_OPERATIONS, Repository, actions_exports as actions, adminBypass, aggregateHelpersPlugin, auditLogPlugin, auditTrailPlugin, autoInject, batchOperationsPlugin, batchTransaction, blockIf, buildCrudSchemasFromModel, buildCrudSchemasFromMongooseSchema, cachePlugin, cascadePlugin, compileFilterToMongo, configureLogger, createError, createFieldPreset, createMemoryCache, createOptionsExtractor, createRepository, createTenantContext, customIdPlugin, dateSequentialId, src_default as default, elasticSearchPlugin, fieldFilterPlugin, filterResponseData, getFieldsForUser, getMongooseProjection, getNextSequence, immutableField, isDuplicateKeyError, isTransactionUnsupported, leasePlugin, methodRegistryPlugin, mongoOperationsPlugin, multiTenantPlugin, observabilityPlugin, operationsByPolicyKey, parseDuplicateKeyError, prefixedId, repoOptionsFromCtx, requireField, sequentialId, softDeletePlugin, subdocumentPlugin, systemContext, timestampPlugin, uniqueField, validationChainPlugin, withTransaction };
1450
+ export { ALL_OPERATIONS, AggregationBuilder, AuditTrailQuery, HOOK_PRIORITY, LookupBuilder, MONGOKIT_CAPABILITIES, MUTATING_OPERATIONS, OP_REGISTRY, PaginationEngine, QueryParser, READ_OPERATIONS, Repository, actions_exports as actions, adminBypass, aggregateHelpersPlugin, auditLogPlugin, auditTrailPlugin, autoInject, batchOperationsPlugin, batchTransaction, blockIf, buildCrudSchemasFromModel, buildCrudSchemasFromMongooseSchema, cachePlugin, cascadePlugin, cascadePurgeReferences, compileFilterToMongo, configureLogger, createError, createFieldPreset, createMemoryCache, createOptionsExtractor, createRepository, createTenantContext, customIdPlugin, dateSequentialId, src_default as default, elasticSearchPlugin, fieldFilterPlugin, filterResponseData, getFieldsForUser, getMongooseProjection, getNextSequence, idVariants, immutableField, isDuplicateKeyError, isTransactionUnsupported, leasePlugin, methodRegistryPlugin, mongoOperationsPlugin, multiTenantPlugin, observabilityPlugin, operationsByPolicyKey, parseDuplicateKeyError, prefixedId, repoOptionsFromCtx, requireField, sequentialId, softDeletePlugin, subdocumentPlugin, systemContext, timestampPlugin, uniqueField, validationChainPlugin, withTransaction };
@@ -1,4 +1,4 @@
1
- import { C as FieldPreset, gt as UserContext } from "./types-BWZILovv.mjs";
1
+ import { C as FieldPreset, gt as UserContext } from "./types-CU3SEDbD.mjs";
2
2
  import mongoose, { Schema } from "mongoose";
3
3
  import { CacheAdapter } from "@classytic/repo-core/cache";
4
4
  import { CrudSchemas, SchemaBuilderOptions } from "@classytic/repo-core/schema";
@@ -139,6 +139,80 @@ declare function filterResponseData<T extends Record<string, unknown>>(data: T |
139
139
  */
140
140
  declare function createFieldPreset(config: Partial<FieldPreset>): FieldPreset;
141
141
  //#endregion
142
+ //#region src/utils/id-resolution.d.ts
143
+ /**
144
+ * ID Resolution Primitive
145
+ *
146
+ * Pure functions for detecting a Mongoose schema's _id type and validating
147
+ * id values against it. Used by Repository.getById to decide whether to
148
+ * run ObjectId validation (for ObjectId schemas) or skip it (for String /
149
+ * Number / UUID schemas).
150
+ *
151
+ * Also usable standalone — Arc controllers, custom repositories, migration
152
+ * scripts, or test harnesses can import these directly to make the same
153
+ * decision without depending on Repository.
154
+ *
155
+ * Design: no `this`, no Model, no DB calls. Only reads `schema.paths._id.instance`.
156
+ */
157
+ /** Normalized _id type — covers the common Mongoose _id declarations */
158
+ type IdType = 'objectid' | 'string' | 'number' | 'uuid' | 'unknown';
159
+ /**
160
+ * Check if a Mongoose SchemaType `instance` string is an ObjectId variant.
161
+ * Mongoose 9.x uses `'ObjectId'`, older versions use `'ObjectID'`. This
162
+ * is the single source of truth — use it instead of inline
163
+ * `instance === 'ObjectId' || instance === 'ObjectID'` checks.
164
+ */
165
+ declare function isObjectIdInstance(instance: string | undefined): boolean;
166
+ /** Minimal structural type for schema introspection (decoupled from Mongoose version) */
167
+ interface SchemaLike {
168
+ paths?: Record<string, {
169
+ instance?: string;
170
+ }>;
171
+ }
172
+ /**
173
+ * Detect the _id path type from a Mongoose schema.
174
+ *
175
+ * Returns 'objectid' as the safe default when:
176
+ * - No schema is provided (mock models, test harnesses)
177
+ * - The schema has no `paths._id` (auto-generated ObjectId)
178
+ * - The instance string is unrecognized
179
+ *
180
+ * This safe-default means existing callers that don't set _id explicitly
181
+ * get the same ObjectId validation they always had — the behavioral change
182
+ * is strictly opt-in via schema declaration.
183
+ */
184
+ declare function getSchemaIdType(schema?: SchemaLike | null): IdType;
185
+ /**
186
+ * Validate an id value against a known _id type — WITHOUT hitting the DB.
187
+ *
188
+ * Returns `true` when the value is structurally valid for the given type.
189
+ * Returns `false` when it's definitely invalid (Repository should return
190
+ * 404 / null immediately rather than wasting a round-trip).
191
+ *
192
+ * For `'string'` and `'unknown'` types, validation is intentionally
193
+ * permissive: any truthy, non-empty value is accepted. The DB is the
194
+ * authority for whether the document exists — we only reject values that
195
+ * are structurally impossible (null, undefined, empty string).
196
+ */
197
+ declare function isValidIdForType(id: unknown, idType: IdType): boolean;
198
+ /**
199
+ * Return every form an id might be stored as, for use in a `{ field: { $in: ... } }`
200
+ * match. The Better Auth mongo adapter (and mixed mongoose/overlay writes) store
201
+ * the same logical id as either a hex STRING or an ObjectId depending on the code
202
+ * path, so a query keyed on one form silently misses rows stored as the other.
203
+ *
204
+ * - A 12-byte / 24-hex string that `ObjectId.isValid` accepts → `[hex, ObjectId(hex)]`.
205
+ * - Anything else (non-ObjectId string, number, an ObjectId instance, …) → `[id]`.
206
+ *
207
+ * Over-matching is harmless — the extra `$in` term can't match a non-existent doc.
208
+ * Replaces the `Types.ObjectId.isValid(id) ? [id, new Types.ObjectId(id)] : [id]`
209
+ * one-liner that tends to get re-implemented at every call site.
210
+ *
211
+ * @example
212
+ * await col.deleteMany({ customerId: { $in: idVariants(userId) } });
213
+ */
214
+ declare function idVariants(id: unknown): unknown[];
215
+ //#endregion
142
216
  //#region src/utils/logger.d.ts
143
217
  /**
144
218
  * Internal Logger
@@ -217,4 +291,4 @@ declare function buildCrudSchemasFromMongooseSchema(mongooseSchema: Schema, opti
217
291
  */
218
292
  declare function buildCrudSchemasFromModel(mongooseModel: mongoose.Model<unknown>, options?: SchemaBuilderOptions): CrudSchemasFramework;
219
293
  //#endregion
220
- export { createFieldPreset as a, getMongooseProjection as c, parseDuplicateKeyError as d, configureLogger as i, createError as l, buildCrudSchemasFromMongooseSchema as n, filterResponseData as o, createMemoryCache as r, getFieldsForUser as s, buildCrudSchemasFromModel as t, isDuplicateKeyError as u };
294
+ export { IdType as a, isObjectIdInstance as c, filterResponseData as d, getFieldsForUser as f, parseDuplicateKeyError as g, isDuplicateKeyError as h, configureLogger as i, isValidIdForType as l, createError as m, buildCrudSchemasFromMongooseSchema as n, getSchemaIdType as o, getMongooseProjection as p, createMemoryCache as r, idVariants as s, buildCrudSchemasFromModel as t, createFieldPreset as u };
@@ -1,4 +1,4 @@
1
- import { n as isObjectIdInstance } from "./id-resolution-DduoO4LI.mjs";
1
+ import { r as isObjectIdInstance } from "./id-resolution-CnN0YA8t.mjs";
2
2
  import mongoose from "mongoose";
3
3
  import { applyFieldRules, collectFieldsToOmit } from "@classytic/repo-core/schema";
4
4
  //#region src/utils/memory-cache.ts
@@ -1,4 +1,4 @@
1
- import { A as KeysetPaginationOptions, U as PaginationConfig, V as OffsetPaginationOptions, i as AnyDocument, n as AggregatePaginationOptions } from "../types-BWZILovv.mjs";
1
+ import { A as KeysetPaginationOptions, U as PaginationConfig, V as OffsetPaginationOptions, i as AnyDocument, n as AggregatePaginationOptions } from "../types-CU3SEDbD.mjs";
2
2
  import { Model } from "mongoose";
3
3
  import { AggregatePaginationResult, KeysetPaginationResult, OffsetPaginationResult } from "@classytic/repo-core/pagination";
4
4
 
@@ -1,2 +1,2 @@
1
- import { t as PaginationEngine } from "../PaginationEngine-0XXTW-9b.mjs";
1
+ import { t as PaginationEngine } from "../PaginationEngine-BcvaXBQ-.mjs";
2
2
  export { PaginationEngine };
@@ -1,2 +1,2 @@
1
- import { $ as AuditEntry, B as IdGenerator, C as LeasePluginOptions, D as elasticSearchPlugin, E as ElasticSearchOptions, F as MultiTenantOptions, G as getNextSequence, H as SequentialIdOptions, J as CacheAdapter, K as prefixedId, L as multiTenantPlugin, M as auditLogPlugin, N as AggregateHelpersMethods, O as cascadePlugin, P as aggregateHelpersPlugin, Q as cachePlugin, R as CustomIdOptions, S as LeaseMethods, T as fieldFilterPlugin, U as customIdPlugin, V as PrefixedIdOptions, W as dateSequentialId, X as RepositoryCacheHandle, Y as CacheOptions, Z as RepositoryCachePluginOptions, _ as observabilityPlugin, a as uniqueField, at as AuditTrailQuery, b as MethodRegistryRepository, c as TenantContext, d as SubdocumentMethods, et as AuditOperation, f as subdocumentPlugin, g as OperationMetric, h as ObservabilityOptions, i as requireField, it as AuditTrailOptions, j as batchOperationsPlugin, k as BatchOperationsMethods, l as TenantStore, m as softDeletePlugin, n as blockIf, nt as AuditQueryResult, o as validationChainPlugin, ot as auditTrailPlugin, p as SoftDeleteMethods, q as sequentialId, r as immutableField, rt as AuditTrailMethods, s as timestampPlugin, t as autoInject, tt as AuditQueryOptions, u as createTenantContext, v as MongoOperationsMethods, w as leasePlugin, x as methodRegistryPlugin, y as mongoOperationsPlugin, z as DateSequentialIdOptions } from "../validation-chain.plugin-Iee2_puD.mjs";
1
+ import { $ as AuditEntry, B as IdGenerator, C as LeasePluginOptions, D as elasticSearchPlugin, E as ElasticSearchOptions, F as MultiTenantOptions, G as getNextSequence, H as SequentialIdOptions, J as CacheAdapter, K as prefixedId, L as multiTenantPlugin, M as auditLogPlugin, N as AggregateHelpersMethods, O as cascadePlugin, P as aggregateHelpersPlugin, Q as cachePlugin, R as CustomIdOptions, S as LeaseMethods, T as fieldFilterPlugin, U as customIdPlugin, V as PrefixedIdOptions, W as dateSequentialId, X as RepositoryCacheHandle, Y as CacheOptions, Z as RepositoryCachePluginOptions, _ as observabilityPlugin, a as uniqueField, at as AuditTrailQuery, b as MethodRegistryRepository, c as TenantContext, d as SubdocumentMethods, et as AuditOperation, f as subdocumentPlugin, g as OperationMetric, h as ObservabilityOptions, i as requireField, it as AuditTrailOptions, j as batchOperationsPlugin, k as BatchOperationsMethods, l as TenantStore, m as softDeletePlugin, n as blockIf, nt as AuditQueryResult, o as validationChainPlugin, ot as auditTrailPlugin, p as SoftDeleteMethods, q as sequentialId, r as immutableField, rt as AuditTrailMethods, s as timestampPlugin, t as autoInject, tt as AuditQueryOptions, u as createTenantContext, v as MongoOperationsMethods, w as leasePlugin, x as methodRegistryPlugin, y as mongoOperationsPlugin, z as DateSequentialIdOptions } from "../validation-chain.plugin-BpMfy18N.mjs";
2
2
  export { type AggregateHelpersMethods, type AuditEntry, type AuditOperation, type AuditQueryOptions, type AuditQueryResult, type AuditTrailMethods, type AuditTrailOptions, AuditTrailQuery, type BatchOperationsMethods, type CacheAdapter, type CacheOptions, type CustomIdOptions, type DateSequentialIdOptions, type ElasticSearchOptions, type IdGenerator, type LeaseMethods, type LeasePluginOptions, type MethodRegistryRepository, type MongoOperationsMethods, type MultiTenantOptions, type ObservabilityOptions, type OperationMetric, type PrefixedIdOptions, type RepositoryCacheHandle, type RepositoryCachePluginOptions, type SequentialIdOptions, type SoftDeleteMethods, type SubdocumentMethods, type TenantContext, type TenantStore, aggregateHelpersPlugin, auditLogPlugin, auditTrailPlugin, autoInject, batchOperationsPlugin, blockIf, cachePlugin, cascadePlugin, createTenantContext, customIdPlugin, dateSequentialId, elasticSearchPlugin, fieldFilterPlugin, getNextSequence, immutableField, leasePlugin, methodRegistryPlugin, mongoOperationsPlugin, multiTenantPlugin, observabilityPlugin, prefixedId, requireField, sequentialId, softDeletePlugin, subdocumentPlugin, timestampPlugin, uniqueField, validationChainPlugin };
@@ -1,2 +1,2 @@
1
- import { A as auditLogPlugin, C as getNextSequence, D as batchOperationsPlugin, E as cachePlugin, O as AuditTrailQuery, S as dateSequentialId, T as sequentialId, _ as softDeletePlugin, a as uniqueField, b as methodRegistryPlugin, c as subdocumentPlugin, d as leasePlugin, f as fieldFilterPlugin, g as timestampPlugin, h as aggregateHelpersPlugin, i as requireField, k as auditTrailPlugin, l as observabilityPlugin, m as cascadePlugin, n as blockIf, o as validationChainPlugin, p as elasticSearchPlugin, r as immutableField, s as createTenantContext, t as autoInject, u as mongoOperationsPlugin, w as prefixedId, x as customIdPlugin, y as multiTenantPlugin } from "../validation-chain.plugin-Crl5nQAY.mjs";
1
+ import { A as auditLogPlugin, C as getNextSequence, D as batchOperationsPlugin, E as cachePlugin, O as AuditTrailQuery, S as dateSequentialId, T as sequentialId, _ as softDeletePlugin, a as uniqueField, b as methodRegistryPlugin, c as subdocumentPlugin, d as leasePlugin, f as fieldFilterPlugin, g as timestampPlugin, h as aggregateHelpersPlugin, i as requireField, k as auditTrailPlugin, l as observabilityPlugin, m as cascadePlugin, n as blockIf, o as validationChainPlugin, p as elasticSearchPlugin, r as immutableField, s as createTenantContext, t as autoInject, u as mongoOperationsPlugin, w as prefixedId, x as customIdPlugin, y as multiTenantPlugin } from "../validation-chain.plugin-DJtC0KJ-.mjs";
2
2
  export { AuditTrailQuery, aggregateHelpersPlugin, auditLogPlugin, auditTrailPlugin, autoInject, batchOperationsPlugin, blockIf, cachePlugin, cascadePlugin, createTenantContext, customIdPlugin, dateSequentialId, elasticSearchPlugin, fieldFilterPlugin, getNextSequence, immutableField, leasePlugin, methodRegistryPlugin, mongoOperationsPlugin, multiTenantPlugin, observabilityPlugin, prefixedId, requireField, sequentialId, softDeletePlugin, subdocumentPlugin, timestampPlugin, uniqueField, validationChainPlugin };
@@ -1,4 +1,4 @@
1
- import { n as isObjectIdInstance } from "../../id-resolution-DduoO4LI.mjs";
1
+ import { r as isObjectIdInstance } from "../../id-resolution-CnN0YA8t.mjs";
2
2
  import mongoose from "mongoose";
3
3
  //#region src/query/primitives/coercion.ts
4
4
  /**
@@ -1,10 +1,10 @@
1
- import * as _$_classytic_repo_core_filter0 from "@classytic/repo-core/filter";
2
- import { Filter } from "@classytic/repo-core/filter";
1
+ import * as _$_classytic_repo_core_repository0 from "@classytic/repo-core/repository";
2
+ import { DeleteManyResult, DeleteResult, LookupPopulateResult, RepositoryBase, UpdateManyResult } from "@classytic/repo-core/repository";
3
3
  import * as _$mongoose from "mongoose";
4
4
  import { Document, Model, PipelineStage, PopulateOptions, Types } from "mongoose";
5
+ import * as _$_classytic_repo_core_filter0 from "@classytic/repo-core/filter";
6
+ import { Filter } from "@classytic/repo-core/filter";
5
7
  import * as _$_classytic_repo_core_cache0 from "@classytic/repo-core/cache";
6
- import * as _$_classytic_repo_core_repository0 from "@classytic/repo-core/repository";
7
- import { DeleteManyResult, DeleteResult, LookupPopulateResult, RepositoryBase, UpdateManyResult } from "@classytic/repo-core/repository";
8
8
  import * as _$_classytic_repo_core_schema0 from "@classytic/repo-core/schema";
9
9
  import { ValidationResult } from "@classytic/repo-core/schema";
10
10
  import * as _$_classytic_repo_core_events0 from "@classytic/repo-core/events";
@@ -1,6 +1,6 @@
1
1
  import { t as __exportAll } from "./chunk-CfYAbeIz.mjs";
2
- import { n as warn } from "./logger-DprijP5h.mjs";
3
- import { t as createError } from "./error-B00pI7dV.mjs";
2
+ import { n as warn } from "./logger-B8wf-Mtb.mjs";
3
+ import { t as createError } from "./error-BTeepSNL.mjs";
4
4
  import { isFilter } from "@classytic/repo-core/filter";
5
5
  //#region src/filter/compile.ts
6
6
  /**
@@ -1,60 +1,2 @@
1
- import { a as createFieldPreset, c as getMongooseProjection, i as configureLogger, l as createError, n as buildCrudSchemasFromMongooseSchema, o as filterResponseData, r as createMemoryCache, s as getFieldsForUser, t as buildCrudSchemasFromModel } from "../mongooseToJsonSchema-GhvZUjRO.mjs";
2
-
3
- //#region src/utils/id-resolution.d.ts
4
- /**
5
- * ID Resolution Primitive
6
- *
7
- * Pure functions for detecting a Mongoose schema's _id type and validating
8
- * id values against it. Used by Repository.getById to decide whether to
9
- * run ObjectId validation (for ObjectId schemas) or skip it (for String /
10
- * Number / UUID schemas).
11
- *
12
- * Also usable standalone — Arc controllers, custom repositories, migration
13
- * scripts, or test harnesses can import these directly to make the same
14
- * decision without depending on Repository.
15
- *
16
- * Design: no `this`, no Model, no DB calls. Only reads `schema.paths._id.instance`.
17
- */
18
- /** Normalized _id type — covers the common Mongoose _id declarations */
19
- type IdType = 'objectid' | 'string' | 'number' | 'uuid' | 'unknown';
20
- /**
21
- * Check if a Mongoose SchemaType `instance` string is an ObjectId variant.
22
- * Mongoose 9.x uses `'ObjectId'`, older versions use `'ObjectID'`. This
23
- * is the single source of truth — use it instead of inline
24
- * `instance === 'ObjectId' || instance === 'ObjectID'` checks.
25
- */
26
- declare function isObjectIdInstance(instance: string | undefined): boolean;
27
- /** Minimal structural type for schema introspection (decoupled from Mongoose version) */
28
- interface SchemaLike {
29
- paths?: Record<string, {
30
- instance?: string;
31
- }>;
32
- }
33
- /**
34
- * Detect the _id path type from a Mongoose schema.
35
- *
36
- * Returns 'objectid' as the safe default when:
37
- * - No schema is provided (mock models, test harnesses)
38
- * - The schema has no `paths._id` (auto-generated ObjectId)
39
- * - The instance string is unrecognized
40
- *
41
- * This safe-default means existing callers that don't set _id explicitly
42
- * get the same ObjectId validation they always had — the behavioral change
43
- * is strictly opt-in via schema declaration.
44
- */
45
- declare function getSchemaIdType(schema?: SchemaLike | null): IdType;
46
- /**
47
- * Validate an id value against a known _id type — WITHOUT hitting the DB.
48
- *
49
- * Returns `true` when the value is structurally valid for the given type.
50
- * Returns `false` when it's definitely invalid (Repository should return
51
- * 404 / null immediately rather than wasting a round-trip).
52
- *
53
- * For `'string'` and `'unknown'` types, validation is intentionally
54
- * permissive: any truthy, non-empty value is accepted. The DB is the
55
- * authority for whether the document exists — we only reject values that
56
- * are structurally impossible (null, undefined, empty string).
57
- */
58
- declare function isValidIdForType(id: unknown, idType: IdType): boolean;
59
- //#endregion
1
+ import { a as IdType, c as isObjectIdInstance, d as filterResponseData, f as getFieldsForUser, i as configureLogger, l as isValidIdForType, m as createError, n as buildCrudSchemasFromMongooseSchema, o as getSchemaIdType, p as getMongooseProjection, r as createMemoryCache, t as buildCrudSchemasFromModel, u as createFieldPreset } from "../mongooseToJsonSchema-BdQJU39w.mjs";
60
2
  export { type IdType, buildCrudSchemasFromModel, buildCrudSchemasFromMongooseSchema, configureLogger, createError, createFieldPreset, createMemoryCache, filterResponseData, getFieldsForUser, getMongooseProjection, getSchemaIdType, isObjectIdInstance, isValidIdForType };
@@ -1,6 +1,6 @@
1
- import { t as configureLogger } from "../logger-DprijP5h.mjs";
2
- import { t as createError } from "../error-B00pI7dV.mjs";
3
- import { n as isObjectIdInstance, r as isValidIdForType, t as getSchemaIdType } from "../id-resolution-DduoO4LI.mjs";
1
+ import { i as isValidIdForType, r as isObjectIdInstance, t as getSchemaIdType } from "../id-resolution-CnN0YA8t.mjs";
2
+ import { t as configureLogger } from "../logger-B8wf-Mtb.mjs";
3
+ import { t as createError } from "../error-BTeepSNL.mjs";
4
4
  import { i as getMongooseProjection, n as filterResponseData, r as getFieldsForUser, t as createFieldPreset } from "../field-selection-CQW3WBiK.mjs";
5
- import { n as buildCrudSchemasFromMongooseSchema, r as createMemoryCache, t as buildCrudSchemasFromModel } from "../mongooseToJsonSchema-CMM2QHzd.mjs";
5
+ import { n as buildCrudSchemasFromMongooseSchema, r as createMemoryCache, t as buildCrudSchemasFromModel } from "../mongooseToJsonSchema-CBEQmeEa.mjs";
6
6
  export { buildCrudSchemasFromModel, buildCrudSchemasFromMongooseSchema, configureLogger, createError, createFieldPreset, createMemoryCache, filterResponseData, getFieldsForUser, getMongooseProjection, getSchemaIdType, isObjectIdInstance, isValidIdForType };
@@ -1,7 +1,7 @@
1
- import { B as ObjectId, C as FieldPreset, G as Plugin, J as PopulateSpec, Q as RepositoryContext, _t as ValidationChainOptions, et as RepositoryInstance, it as SelectSpec, j as Logger, l as CascadeOptions, st as SoftDeleteOptions, ut as SortSpec, vt as ValidatorDefinition } from "./types-BWZILovv.mjs";
1
+ import { B as ObjectId, C as FieldPreset, G as Plugin, J as PopulateSpec, Q as RepositoryContext, _t as ValidationChainOptions, et as RepositoryInstance, it as SelectSpec, j as Logger, l as CascadeOptions, st as SoftDeleteOptions, ut as SortSpec, vt as ValidatorDefinition } from "./types-CU3SEDbD.mjs";
2
+ import { BulkWriteResult } from "@classytic/repo-core/repository";
2
3
  import mongoose from "mongoose";
3
4
  import { CacheAdapter as CacheAdapter$1, CacheOptions, RepositoryCacheHandle, RepositoryCachePluginOptions, cachePlugin } from "@classytic/repo-core/cache";
4
- import { BulkWriteResult } from "@classytic/repo-core/repository";
5
5
  import { AsyncLocalStorage } from "node:async_hooks";
6
6
  import { OffsetPaginationResult } from "@classytic/repo-core/pagination";
7
7
  import { TenantConfig } from "@classytic/repo-core/tenant";
@@ -1,12 +1,12 @@
1
- import { _ as upsert } from "./update-BXMnCvO6.mjs";
2
- import { n as warn } from "./logger-DprijP5h.mjs";
3
- import { t as createError } from "./error-B00pI7dV.mjs";
4
- import { l as OP_REGISTRY, s as ALL_OPERATIONS, t as HOOK_PRIORITY } from "./Repository-DE7D2QeS.mjs";
1
+ import { l as OP_REGISTRY, s as ALL_OPERATIONS, t as HOOK_PRIORITY } from "./Repository-B01VW_fU.mjs";
2
+ import { _ as upsert } from "./update-CvCMv5Cl.mjs";
3
+ import { n as warn } from "./logger-B8wf-Mtb.mjs";
4
+ import { t as createError } from "./error-BTeepSNL.mjs";
5
5
  import { r as getFieldsForUser } from "./field-selection-CQW3WBiK.mjs";
6
+ import { throwIfAborted, withRetry } from "@classytic/repo-core/repository";
6
7
  import mongoose from "mongoose";
7
8
  import { cachePlugin } from "@classytic/repo-core/cache";
8
9
  import { adminBypass, payloadHasTenantField } from "@classytic/repo-core/plugins";
9
- import { throwIfAborted, withRetry } from "@classytic/repo-core/repository";
10
10
  import { AsyncLocalStorage } from "node:async_hooks";
11
11
  //#region src/plugins/audit-log.plugin.ts
12
12
  /**
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@classytic/mongokit",
3
- "version": "3.16.2",
3
+ "version": "3.17.0",
4
4
  "description": "Production-grade MongoDB repositories - smart pagination, events, and plugins. Built on @classytic/repo-core.",
5
5
  "type": "module",
6
6
  "sideEffects": false,
File without changes
File without changes