@classytic/mongokit 3.16.2 → 3.18.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +2 -1
- package/dist/{PaginationEngine-0XXTW-9b.mjs → PaginationEngine-BcvaXBQ-.mjs} +4 -4
- package/dist/{Repository-DE7D2QeS.mjs → Repository-B01VW_fU.mjs} +79 -79
- package/dist/actions/index.d.mts +1 -1
- package/dist/actions/index.mjs +1 -1
- package/dist/adapter/index.d.mts +1 -1
- package/dist/adapter/index.mjs +1 -1
- package/dist/{adapter-gG_uyFSZ.mjs → adapter-DYEMkLwK.mjs} +1 -1
- package/dist/ai/index.d.mts +1 -1
- package/dist/ai/index.mjs +1 -1
- package/dist/better-auth/index.mjs +2 -2
- package/dist/{id-resolution-DduoO4LI.mjs → id-resolution-CnN0YA8t.mjs} +21 -1
- package/dist/{index-CV5vv-8E.d.mts → index-fi91ycQc.d.mts} +1 -1
- package/dist/index.d.mts +84 -6
- package/dist/index.mjs +139 -8
- package/dist/{mongooseToJsonSchema-GhvZUjRO.d.mts → mongooseToJsonSchema-BdQJU39w.d.mts} +76 -2
- package/dist/{mongooseToJsonSchema-CMM2QHzd.mjs → mongooseToJsonSchema-CBEQmeEa.mjs} +1 -1
- package/dist/pagination/PaginationEngine.d.mts +1 -1
- package/dist/pagination/PaginationEngine.mjs +1 -1
- package/dist/plugins/index.d.mts +18 -2
- package/dist/plugins/index.mjs +72 -2
- package/dist/query/primitives/coercion.mjs +1 -1
- package/dist/{types-BWZILovv.d.mts → types-CU3SEDbD.d.mts} +4 -4
- package/dist/{update-BXMnCvO6.mjs → update-CvCMv5Cl.mjs} +2 -2
- package/dist/utils/index.d.mts +1 -59
- package/dist/utils/index.mjs +4 -4
- package/dist/{validation-chain.plugin-Iee2_puD.d.mts → validation-chain.plugin-BpMfy18N.d.mts} +2 -2
- package/dist/{validation-chain.plugin-Crl5nQAY.mjs → validation-chain.plugin-DJtC0KJ-.mjs} +5 -5
- package/package.json +8 -4
- /package/dist/{cursor-4LMYa4ga.mjs → cursor-_SbWVAn-.mjs} +0 -0
- /package/dist/{error-B00pI7dV.mjs → error-BTeepSNL.mjs} +0 -0
- /package/dist/{logger-DprijP5h.mjs → logger-B8wf-Mtb.mjs} +0 -0
- /package/dist/{sort-RPVz5u0w.mjs → sort-Ca1BPfvE.mjs} +0 -0
package/README.md
CHANGED
|
@@ -17,7 +17,7 @@ Requirements:
|
|
|
17
17
|
|
|
18
18
|
- Node.js `>=22`
|
|
19
19
|
- Mongoose `>=9.4.1`
|
|
20
|
-
- `@classytic/repo-core >=0.
|
|
20
|
+
- `@classytic/repo-core >=0.7.0`
|
|
21
21
|
|
|
22
22
|
## Quick Start
|
|
23
23
|
|
|
@@ -237,6 +237,7 @@ Supports common URL operators such as `_gt`, `_gte`, `_lt`, `_lte`, `_in`, `_nin
|
|
|
237
237
|
| `mongoOperationsPlugin` | Hook-routed Mongo update helpers |
|
|
238
238
|
| `aggregateHelpersPlugin` | Common aggregation helpers |
|
|
239
239
|
| `subdocumentPlugin` | Nested array document helpers |
|
|
240
|
+
| `changeLogPlugin` | Durable per-doc change feed (`@classytic/repo-core/sync`) for offline-first pull/push and replicas |
|
|
240
241
|
|
|
241
242
|
Import only the plugins you use.
|
|
242
243
|
|
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import { n as warn } from "./logger-
|
|
2
|
-
import { t as createError } from "./error-
|
|
3
|
-
import { n as encodeCursor, r as resolveCursorFilter } from "./cursor-
|
|
4
|
-
import { r as validateKeysetSort, t as getPrimaryField } from "./sort-
|
|
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 {
|
|
2
|
-
import { n as
|
|
3
|
-
import { n as
|
|
4
|
-
import { t as
|
|
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 {
|
|
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-
|
|
3618
|
-
const { encodeCursor, resolveCursorFilter } = await import("./cursor-
|
|
3619
|
-
const { getPrimaryField } = await import("./sort-
|
|
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 };
|
package/dist/actions/index.d.mts
CHANGED
|
@@ -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-
|
|
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 };
|
package/dist/actions/index.mjs
CHANGED
|
@@ -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-
|
|
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,
|
package/dist/adapter/index.d.mts
CHANGED
|
@@ -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
|
|
package/dist/adapter/index.mjs
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { n as createMongooseAdapter, r as isMongooseModel, t as MongooseAdapter } from "../adapter-
|
|
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-
|
|
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
|
package/dist/ai/index.d.mts
CHANGED
package/dist/ai/index.mjs
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { n as Repository } from "../Repository-
|
|
2
|
-
import { n as createMongooseAdapter } from "../adapter-
|
|
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 {
|
|
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-
|
|
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-
|
|
2
|
-
import { t as index_d_exports } from "./index-
|
|
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-
|
|
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 {
|
|
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 {
|
|
2
|
-
import { n as
|
|
3
|
-
import {
|
|
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
|
|
6
|
-
import {
|
|
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-
|
|
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-
|
|
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 {
|
|
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 {
|
|
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-
|
|
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-
|
|
1
|
+
import { t as PaginationEngine } from "../PaginationEngine-BcvaXBQ-.mjs";
|
|
2
2
|
export { PaginationEngine };
|
package/dist/plugins/index.d.mts
CHANGED
|
@@ -1,2 +1,18 @@
|
|
|
1
|
-
import {
|
|
2
|
-
|
|
1
|
+
import { G as Plugin } from "../types-CU3SEDbD.mjs";
|
|
2
|
+
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";
|
|
3
|
+
import { ChangeLogStore } from "@classytic/repo-core/sync";
|
|
4
|
+
|
|
5
|
+
//#region src/plugins/change-log.plugin.d.ts
|
|
6
|
+
interface ChangeLogPluginOptions {
|
|
7
|
+
/** Durable feed implementing the repo-core/sync contract. */
|
|
8
|
+
store: ChangeLogStore;
|
|
9
|
+
/** Logical scope for entries (resource name a client subscribes to). */
|
|
10
|
+
scope: string;
|
|
11
|
+
/** Tenant partition field on docs/context. Default `organizationId`. */
|
|
12
|
+
tenantField?: string;
|
|
13
|
+
/** Monotonic per-doc version field. Default `version` (kernel convention). */
|
|
14
|
+
versionField?: string;
|
|
15
|
+
}
|
|
16
|
+
declare function changeLogPlugin(options: ChangeLogPluginOptions): Plugin;
|
|
17
|
+
//#endregion
|
|
18
|
+
export { type AggregateHelpersMethods, type AuditEntry, type AuditOperation, type AuditQueryOptions, type AuditQueryResult, type AuditTrailMethods, type AuditTrailOptions, AuditTrailQuery, type BatchOperationsMethods, type CacheAdapter, type CacheOptions, type ChangeLogPluginOptions, 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, changeLogPlugin, createTenantContext, customIdPlugin, dateSequentialId, elasticSearchPlugin, fieldFilterPlugin, getNextSequence, immutableField, leasePlugin, methodRegistryPlugin, mongoOperationsPlugin, multiTenantPlugin, observabilityPlugin, prefixedId, requireField, sequentialId, softDeletePlugin, subdocumentPlugin, timestampPlugin, uniqueField, validationChainPlugin };
|
package/dist/plugins/index.mjs
CHANGED
|
@@ -1,2 +1,72 @@
|
|
|
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-
|
|
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-DJtC0KJ-.mjs";
|
|
2
|
+
//#region src/plugins/change-log.plugin.ts
|
|
3
|
+
const PLUGIN_NAME = "changeLog";
|
|
4
|
+
function isSkipped(context) {
|
|
5
|
+
const list = context.skipPlugins;
|
|
6
|
+
return Array.isArray(list) && list.includes(PLUGIN_NAME);
|
|
7
|
+
}
|
|
8
|
+
function changeLogPlugin(options) {
|
|
9
|
+
const { store, scope, tenantField = "organizationId", versionField = "version" } = options;
|
|
10
|
+
const toRecord = (doc) => {
|
|
11
|
+
if (!doc || typeof doc !== "object") return null;
|
|
12
|
+
const d = doc;
|
|
13
|
+
return typeof d.toObject === "function" ? d.toObject() : doc;
|
|
14
|
+
};
|
|
15
|
+
const versionOf = (doc) => {
|
|
16
|
+
const v = doc[versionField] ?? doc.__v;
|
|
17
|
+
if (typeof v === "number") return v;
|
|
18
|
+
const updatedAt = doc.updatedAt;
|
|
19
|
+
return updatedAt instanceof Date ? updatedAt.getTime() : 0;
|
|
20
|
+
};
|
|
21
|
+
const tenantOf = (doc, context) => {
|
|
22
|
+
const raw = doc[tenantField] ?? context.organizationId;
|
|
23
|
+
return raw === void 0 || raw === null ? void 0 : String(raw);
|
|
24
|
+
};
|
|
25
|
+
const capture = async (op, doc, context) => {
|
|
26
|
+
const record = toRecord(doc);
|
|
27
|
+
if (!record || record._id === void 0) return;
|
|
28
|
+
const tenantId = tenantOf(record, context);
|
|
29
|
+
await store.append({
|
|
30
|
+
scope,
|
|
31
|
+
docId: String(record._id),
|
|
32
|
+
op,
|
|
33
|
+
version: versionOf(record),
|
|
34
|
+
...op === "upsert" ? { doc: record } : {},
|
|
35
|
+
...tenantId !== void 0 ? { tenantId } : {}
|
|
36
|
+
}, context.session !== void 0 ? { session: context.session } : void 0);
|
|
37
|
+
};
|
|
38
|
+
return {
|
|
39
|
+
name: PLUGIN_NAME,
|
|
40
|
+
apply(repo) {
|
|
41
|
+
repo.on("after:create", async ({ context, result }) => {
|
|
42
|
+
if (isSkipped(context) || !result) return;
|
|
43
|
+
await capture("upsert", result, context);
|
|
44
|
+
});
|
|
45
|
+
repo.on("after:createMany", async ({ context, result }) => {
|
|
46
|
+
if (isSkipped(context) || !Array.isArray(result)) return;
|
|
47
|
+
for (const doc of result) await capture("upsert", doc, context);
|
|
48
|
+
});
|
|
49
|
+
repo.on("after:update", async ({ context, result }) => {
|
|
50
|
+
if (isSkipped(context) || !result) return;
|
|
51
|
+
await capture("upsert", result, context);
|
|
52
|
+
});
|
|
53
|
+
repo.on("after:delete", async ({ context, result }) => {
|
|
54
|
+
if (isSkipped(context) || !result) return;
|
|
55
|
+
const summary = result;
|
|
56
|
+
const ctxId = context.id;
|
|
57
|
+
const docId = summary.id ?? ctxId;
|
|
58
|
+
if (docId === void 0 || docId === null) return;
|
|
59
|
+
const tenantRaw = context.organizationId;
|
|
60
|
+
await store.append({
|
|
61
|
+
scope,
|
|
62
|
+
docId: String(docId),
|
|
63
|
+
op: "delete",
|
|
64
|
+
version: 0,
|
|
65
|
+
...tenantRaw !== void 0 && tenantRaw !== null ? { tenantId: String(tenantRaw) } : {}
|
|
66
|
+
}, context.session !== void 0 ? { session: context.session } : void 0);
|
|
67
|
+
});
|
|
68
|
+
}
|
|
69
|
+
};
|
|
70
|
+
}
|
|
71
|
+
//#endregion
|
|
72
|
+
export { AuditTrailQuery, aggregateHelpersPlugin, auditLogPlugin, auditTrailPlugin, autoInject, batchOperationsPlugin, blockIf, cachePlugin, cascadePlugin, changeLogPlugin, createTenantContext, customIdPlugin, dateSequentialId, elasticSearchPlugin, fieldFilterPlugin, getNextSequence, immutableField, leasePlugin, methodRegistryPlugin, mongoOperationsPlugin, multiTenantPlugin, observabilityPlugin, prefixedId, requireField, sequentialId, softDeletePlugin, subdocumentPlugin, timestampPlugin, uniqueField, validationChainPlugin };
|
|
@@ -1,10 +1,10 @@
|
|
|
1
|
-
import * as _$
|
|
2
|
-
import {
|
|
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-
|
|
3
|
-
import { t as createError } from "./error-
|
|
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
|
/**
|
package/dist/utils/index.d.mts
CHANGED
|
@@ -1,60 +1,2 @@
|
|
|
1
|
-
import { a as
|
|
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 };
|
package/dist/utils/index.mjs
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { t as
|
|
2
|
-
import { t as
|
|
3
|
-
import {
|
|
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-
|
|
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 };
|
package/dist/{validation-chain.plugin-Iee2_puD.d.mts → validation-chain.plugin-BpMfy18N.d.mts}
RENAMED
|
@@ -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-
|
|
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 {
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
4
|
-
import {
|
|
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.
|
|
3
|
+
"version": "3.18.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,
|
|
@@ -105,7 +105,7 @@
|
|
|
105
105
|
},
|
|
106
106
|
"homepage": "https://github.com/classytic/mongokit#readme",
|
|
107
107
|
"peerDependencies": {
|
|
108
|
-
"@classytic/repo-core": ">=0.
|
|
108
|
+
"@classytic/repo-core": ">=0.7.0",
|
|
109
109
|
"better-auth": ">=1.6.0",
|
|
110
110
|
"mongoose": ">=9.4.1"
|
|
111
111
|
},
|
|
@@ -117,6 +117,9 @@
|
|
|
117
117
|
"engines": {
|
|
118
118
|
"node": ">=22"
|
|
119
119
|
},
|
|
120
|
+
"publishConfig": {
|
|
121
|
+
"access": "public"
|
|
122
|
+
},
|
|
120
123
|
"scripts": {
|
|
121
124
|
"build": "tsdown",
|
|
122
125
|
"dev": "tsdown --watch",
|
|
@@ -138,7 +141,7 @@
|
|
|
138
141
|
"publish:dry": "npm publish --dry-run --access public",
|
|
139
142
|
"publish:npm": "npm publish --access public",
|
|
140
143
|
"release:tag": "node -e \"require('child_process').execSync('npm run push -- v'+require('./package.json').version,{stdio:'inherit'})\"",
|
|
141
|
-
"release": "npm run push -- main && npm run release:tag && npm publish",
|
|
144
|
+
"release": "npm run push -- main && npm run release:tag && npm publish --access public",
|
|
142
145
|
"release:patch": "npm version patch && npm run release",
|
|
143
146
|
"release:minor": "npm version minor && npm run release",
|
|
144
147
|
"release:major": "npm version major && npm run release"
|
|
@@ -149,7 +152,7 @@
|
|
|
149
152
|
"@better-auth/mongo-adapter": "^1.6.22",
|
|
150
153
|
"@biomejs/biome": "^2.4.10",
|
|
151
154
|
"@classytic/dev-tools": "^0.2.0",
|
|
152
|
-
"@classytic/repo-core": "0.
|
|
155
|
+
"@classytic/repo-core": "^0.7.0",
|
|
153
156
|
"@types/node": "^22.0.0",
|
|
154
157
|
"@vitest/coverage-v8": "^4.1.4",
|
|
155
158
|
"ajv": "^8.18.0",
|
|
@@ -157,6 +160,7 @@
|
|
|
157
160
|
"better-auth": "^1.6.22",
|
|
158
161
|
"dotenv": "^17.4.2",
|
|
159
162
|
"knip": "^6.3.0",
|
|
163
|
+
"mongodb": "7.2.0",
|
|
160
164
|
"mongodb-memory-server": "^10.4.3",
|
|
161
165
|
"mongoose": "^9.4.1",
|
|
162
166
|
"publint": "^0.3.18",
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|