@classytic/mongokit 3.5.5 → 3.6.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 +189 -1486
- package/dist/{PaginationEngine-CpsQl471.mjs → PaginationEngine-CunXkR9p.mjs} +100 -4
- package/dist/actions/index.d.mts +1 -1
- package/dist/ai/index.d.mts +1 -1
- package/dist/id-resolution-LZ-cCwR5.mjs +81 -0
- package/dist/{index-Buj7P006.d.mts → index-BSRSsRRx.d.mts} +1 -1
- package/dist/index.d.mts +81 -9
- package/dist/index.mjs +5 -5
- package/dist/{mongooseToJsonSchema-DpjhFfaO.mjs → mongooseToJsonSchema-8Cyu3NFJ.mjs} +50 -45
- package/dist/{mongooseToJsonSchema-BlDfbg_0.d.mts → mongooseToJsonSchema-D2YjHo7W.d.mts} +4 -3
- package/dist/pagination/PaginationEngine.d.mts +8 -1
- package/dist/pagination/PaginationEngine.mjs +1 -1
- package/dist/plugins/index.d.mts +1 -1
- package/dist/plugins/index.mjs +1 -1
- package/dist/query/primitives/coercion.d.mts +1 -1
- package/dist/query/primitives/coercion.mjs +4 -3
- package/dist/query/primitives/indexes.d.mts +1 -1
- package/dist/{types-CWUL0yiw.d.mts → types-DiQfDesD.d.mts} +29 -3
- package/dist/utils/index.d.mts +60 -3
- package/dist/utils/index.mjs +4 -3
- package/dist/{validation-chain.plugin-BCPh2UZG.mjs → validation-chain.plugin-3rr7dlw6.mjs} +308 -164
- package/dist/{validation-chain.plugin-Dn41aAbK.d.mts → validation-chain.plugin-COKNRAwp.d.mts} +15 -12
- package/package.json +2 -2
- /package/dist/{coercion-01tEHsKF.d.mts → coercion-B19MD38s.d.mts} +0 -0
- /package/dist/{field-selection-reyDRzXf.mjs → field-selection-C5o7jyyA.mjs} +0 -0
- /package/dist/{indexes-CiIT-Zli.d.mts → indexes-qIBCZ3mY.d.mts} +0 -0
|
@@ -1,6 +1,72 @@
|
|
|
1
1
|
import { a as warn, t as createError } from "./error-Bpbi_NKo.mjs";
|
|
2
2
|
import { n as encodeCursor, r as resolveCursorFilter } from "./cursor-CHToazHy.mjs";
|
|
3
3
|
import { r as validateKeysetSort, t as getPrimaryField } from "./sort-C-BJEWUZ.mjs";
|
|
4
|
+
//#region src/pagination/utils/index-hint.ts
|
|
5
|
+
/**
|
|
6
|
+
* Read a Mongoose schema's declared indexes, defensively.
|
|
7
|
+
* Returns an empty array on any introspection failure.
|
|
8
|
+
*/
|
|
9
|
+
function readSchemaIndexes(Model) {
|
|
10
|
+
try {
|
|
11
|
+
const schema = Model.schema;
|
|
12
|
+
if (!schema || typeof schema.indexes !== "function") return [];
|
|
13
|
+
const raw = schema.indexes();
|
|
14
|
+
return Array.isArray(raw) ? raw : [];
|
|
15
|
+
} catch {
|
|
16
|
+
return [];
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
/**
|
|
20
|
+
* Does any schema-declared compound index satisfy ESR for the given
|
|
21
|
+
* equality filter fields + sort?
|
|
22
|
+
*
|
|
23
|
+
* Rules:
|
|
24
|
+
* 1. The first N keys of the index (N = filterFields.length) must be
|
|
25
|
+
* exactly the equality filter fields in any order (set equality).
|
|
26
|
+
* 2. The next M keys (M = sortKeys.length) must match the sort keys in
|
|
27
|
+
* exact declared order.
|
|
28
|
+
* 3. Directions must all match OR all be inverse (MongoDB can walk an
|
|
29
|
+
* index in reverse, but only if every sort field flips together).
|
|
30
|
+
* 4. Indexes with more total keys than needed are still accepted when
|
|
31
|
+
* the above prefix holds — Mongo just ignores trailing fields.
|
|
32
|
+
*
|
|
33
|
+
* Notes:
|
|
34
|
+
* - Hashed / text / 2dsphere indexes are skipped (not usable for sort).
|
|
35
|
+
* - Unique, partial, sparse options don't affect compatibility.
|
|
36
|
+
* - When `filterFields` is empty, a sort-only prefix match is sufficient.
|
|
37
|
+
*
|
|
38
|
+
* @param indexes Raw `[spec, options?]` tuples from `schema.indexes()`.
|
|
39
|
+
* @param filterFields Top-level equality filter keys (already stripped of `$*`).
|
|
40
|
+
* @param sort Normalized sort spec `{ field: 1 | -1 }`.
|
|
41
|
+
*/
|
|
42
|
+
function hasCompatibleKeysetIndex(indexes, filterFields, sort) {
|
|
43
|
+
const sortKeys = Object.keys(sort);
|
|
44
|
+
if (sortKeys.length === 0) return true;
|
|
45
|
+
const filterSet = new Set(filterFields);
|
|
46
|
+
const prefixLen = filterFields.length;
|
|
47
|
+
for (const [spec] of indexes) {
|
|
48
|
+
if (!spec || typeof spec !== "object") continue;
|
|
49
|
+
const entries = Object.entries(spec);
|
|
50
|
+
if (entries.length < prefixLen + sortKeys.length) continue;
|
|
51
|
+
if (entries.some(([, dir]) => typeof dir !== "number")) continue;
|
|
52
|
+
const equalityPrefix = entries.slice(0, prefixLen).map(([k]) => k);
|
|
53
|
+
if (equalityPrefix.length !== prefixLen) continue;
|
|
54
|
+
if (!(equalityPrefix.every((k) => filterSet.has(k)) && new Set(equalityPrefix).size === prefixLen)) continue;
|
|
55
|
+
const sortSuffix = entries.slice(prefixLen, prefixLen + sortKeys.length);
|
|
56
|
+
if (sortSuffix.length !== sortKeys.length) continue;
|
|
57
|
+
let namesMatch = true;
|
|
58
|
+
for (let i = 0; i < sortKeys.length; i++) if (sortSuffix[i][0] !== sortKeys[i]) {
|
|
59
|
+
namesMatch = false;
|
|
60
|
+
break;
|
|
61
|
+
}
|
|
62
|
+
if (!namesMatch) continue;
|
|
63
|
+
const forward = sortKeys.every((k, i) => sortSuffix[i][1] === sort[k]);
|
|
64
|
+
const reverse = sortKeys.every((k, i) => sortSuffix[i][1] === -sort[k]);
|
|
65
|
+
if (forward || reverse) return true;
|
|
66
|
+
}
|
|
67
|
+
return false;
|
|
68
|
+
}
|
|
69
|
+
//#endregion
|
|
4
70
|
//#region src/pagination/utils/limits.ts
|
|
5
71
|
/**
|
|
6
72
|
* Validates and sanitizes limit value
|
|
@@ -65,6 +131,24 @@ function calculateTotalPages(total, limit) {
|
|
|
65
131
|
}
|
|
66
132
|
//#endregion
|
|
67
133
|
//#region src/pagination/PaginationEngine.ts
|
|
134
|
+
/**
|
|
135
|
+
* Strip a trailing `_id` tiebreaker from a normalized sort spec.
|
|
136
|
+
*
|
|
137
|
+
* `validateKeysetSort` always appends `_id` to the end of the sort object as
|
|
138
|
+
* a stable-order guarantee. For index-compatibility matching we only care
|
|
139
|
+
* about the primary ordering fields — an index covering those is efficient
|
|
140
|
+
* even without `_id` in the index itself.
|
|
141
|
+
*
|
|
142
|
+
* Returns the sort unchanged if `_id` is the only field (degenerate case).
|
|
143
|
+
*/
|
|
144
|
+
function stripTrailingIdTiebreaker(sort) {
|
|
145
|
+
const keys = Object.keys(sort);
|
|
146
|
+
if (keys.length <= 1) return sort;
|
|
147
|
+
if (keys[keys.length - 1] !== "_id") return sort;
|
|
148
|
+
const out = {};
|
|
149
|
+
for (let i = 0; i < keys.length - 1; i++) out[keys[i]] = sort[keys[i]];
|
|
150
|
+
return out;
|
|
151
|
+
}
|
|
68
152
|
function ensureKeysetSelectIncludesCursorFields(select, sort) {
|
|
69
153
|
if (!select) return select;
|
|
70
154
|
const requiredFields = new Set([...Object.keys(sort), "_id"]);
|
|
@@ -95,6 +179,11 @@ var PaginationEngine = class {
|
|
|
95
179
|
Model;
|
|
96
180
|
config;
|
|
97
181
|
/**
|
|
182
|
+
* Lazily-cached schema index snapshot used by stream() to decide whether
|
|
183
|
+
* to emit the "missing compound index" warning. Computed on first use.
|
|
184
|
+
*/
|
|
185
|
+
_cachedSchemaIndexes = null;
|
|
186
|
+
/**
|
|
98
187
|
* Create a new pagination engine
|
|
99
188
|
*
|
|
100
189
|
* @param Model - Mongoose model to paginate
|
|
@@ -111,6 +200,12 @@ var PaginationEngine = class {
|
|
|
111
200
|
useEstimatedCount: config.useEstimatedCount ?? false
|
|
112
201
|
};
|
|
113
202
|
}
|
|
203
|
+
/** Memoized schema index lookup — avoids re-walking schema on every stream(). */
|
|
204
|
+
_getSchemaIndexes() {
|
|
205
|
+
if (this._cachedSchemaIndexes !== null) return this._cachedSchemaIndexes;
|
|
206
|
+
this._cachedSchemaIndexes = readSchemaIndexes(this.Model);
|
|
207
|
+
return this._cachedSchemaIndexes;
|
|
208
|
+
}
|
|
114
209
|
/**
|
|
115
210
|
* Offset-based pagination using skip/limit
|
|
116
211
|
* Best for small datasets and when users need random page access
|
|
@@ -204,11 +299,12 @@ var PaginationEngine = class {
|
|
|
204
299
|
if (!sort) throw createError(400, "sort is required for keyset pagination");
|
|
205
300
|
const sanitizedLimit = validateLimit(limit, this.config);
|
|
206
301
|
const normalizedSort = validateKeysetSort(sort);
|
|
302
|
+
const sortWithoutIdTail = stripTrailingIdTiebreaker(normalizedSort);
|
|
207
303
|
const filterKeys = Object.keys(filters).filter((k) => !k.startsWith("$"));
|
|
208
|
-
const
|
|
209
|
-
if (filterKeys.length > 0 &&
|
|
210
|
-
const indexFields = [...filterKeys.map((f) => `${f}: 1`), ...
|
|
211
|
-
warn(`[mongokit] Keyset pagination with filters [${filterKeys.join(", ")}] and sort [${
|
|
304
|
+
const effectiveSortFields = Object.keys(sortWithoutIdTail);
|
|
305
|
+
if (process.env.NODE_ENV !== "test" && filterKeys.length > 0 && effectiveSortFields.length > 0 && !hasCompatibleKeysetIndex(this._getSchemaIndexes(), filterKeys, sortWithoutIdTail)) {
|
|
306
|
+
const indexFields = [...filterKeys.map((f) => `${f}: 1`), ...effectiveSortFields.map((f) => `${f}: ${sortWithoutIdTail[f]}`)];
|
|
307
|
+
warn(`[mongokit] Keyset pagination with filters [${filterKeys.join(", ")}] and sort [${effectiveSortFields.join(", ")}] has no matching schema-declared compound index. For O(1) performance, declare: { ${indexFields.join(", ")} }. (Collection-level indexes created outside the schema are not visible here.)`);
|
|
212
308
|
}
|
|
213
309
|
let query = { ...filters };
|
|
214
310
|
if (after) query = resolveCursorFilter(after, normalizedSort, this.config.cursorVersion, query);
|
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-BSRSsRRx.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/ai/index.d.mts
CHANGED
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
import mongoose from "mongoose";
|
|
2
|
+
//#region src/utils/id-resolution.ts
|
|
3
|
+
/**
|
|
4
|
+
* ID Resolution Primitive
|
|
5
|
+
*
|
|
6
|
+
* Pure functions for detecting a Mongoose schema's _id type and validating
|
|
7
|
+
* id values against it. Used by Repository.getById to decide whether to
|
|
8
|
+
* run ObjectId validation (for ObjectId schemas) or skip it (for String /
|
|
9
|
+
* Number / UUID schemas).
|
|
10
|
+
*
|
|
11
|
+
* Also usable standalone — Arc controllers, custom repositories, migration
|
|
12
|
+
* scripts, or test harnesses can import these directly to make the same
|
|
13
|
+
* decision without depending on Repository.
|
|
14
|
+
*
|
|
15
|
+
* Design: no `this`, no Model, no DB calls. Only reads `schema.paths._id.instance`.
|
|
16
|
+
*/
|
|
17
|
+
/**
|
|
18
|
+
* Check if a Mongoose SchemaType `instance` string is an ObjectId variant.
|
|
19
|
+
* Mongoose 9.x uses `'ObjectId'`, older versions use `'ObjectID'`. This
|
|
20
|
+
* is the single source of truth — use it instead of inline
|
|
21
|
+
* `instance === 'ObjectId' || instance === 'ObjectID'` checks.
|
|
22
|
+
*/
|
|
23
|
+
function isObjectIdInstance(instance) {
|
|
24
|
+
return instance === "ObjectId" || instance === "ObjectID";
|
|
25
|
+
}
|
|
26
|
+
const UUID_RE = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
|
|
27
|
+
/**
|
|
28
|
+
* Detect the _id path type from a Mongoose schema.
|
|
29
|
+
*
|
|
30
|
+
* Returns 'objectid' as the safe default when:
|
|
31
|
+
* - No schema is provided (mock models, test harnesses)
|
|
32
|
+
* - The schema has no `paths._id` (auto-generated ObjectId)
|
|
33
|
+
* - The instance string is unrecognized
|
|
34
|
+
*
|
|
35
|
+
* This safe-default means existing callers that don't set _id explicitly
|
|
36
|
+
* get the same ObjectId validation they always had — the behavioral change
|
|
37
|
+
* is strictly opt-in via schema declaration.
|
|
38
|
+
*/
|
|
39
|
+
function getSchemaIdType(schema) {
|
|
40
|
+
const instance = schema?.paths?._id?.instance;
|
|
41
|
+
if (!instance) return "objectid";
|
|
42
|
+
if (isObjectIdInstance(instance)) return "objectid";
|
|
43
|
+
switch (instance) {
|
|
44
|
+
case "String": return "string";
|
|
45
|
+
case "Number": return "number";
|
|
46
|
+
case "UUID": return "uuid";
|
|
47
|
+
default: return "unknown";
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
/**
|
|
51
|
+
* Validate an id value against a known _id type — WITHOUT hitting the DB.
|
|
52
|
+
*
|
|
53
|
+
* Returns `true` when the value is structurally valid for the given type.
|
|
54
|
+
* Returns `false` when it's definitely invalid (Repository should return
|
|
55
|
+
* 404 / null immediately rather than wasting a round-trip).
|
|
56
|
+
*
|
|
57
|
+
* For `'string'` and `'unknown'` types, validation is intentionally
|
|
58
|
+
* permissive: any truthy, non-empty value is accepted. The DB is the
|
|
59
|
+
* authority for whether the document exists — we only reject values that
|
|
60
|
+
* are structurally impossible (null, undefined, empty string).
|
|
61
|
+
*/
|
|
62
|
+
function isValidIdForType(id, idType) {
|
|
63
|
+
if (id === null || id === void 0) return false;
|
|
64
|
+
switch (idType) {
|
|
65
|
+
case "objectid": {
|
|
66
|
+
if (typeof id === "object") return mongoose.Types.ObjectId.isValid(id);
|
|
67
|
+
const s = String(id);
|
|
68
|
+
return s.length > 0 && mongoose.Types.ObjectId.isValid(s);
|
|
69
|
+
}
|
|
70
|
+
case "string": return String(id).length > 0;
|
|
71
|
+
case "number": {
|
|
72
|
+
if (typeof id === "number") return Number.isFinite(id);
|
|
73
|
+
const n = Number(id);
|
|
74
|
+
return Number.isFinite(n);
|
|
75
|
+
}
|
|
76
|
+
case "uuid": return typeof id === "string" && UUID_RE.test(id);
|
|
77
|
+
case "unknown": return String(id).length > 0;
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
//#endregion
|
|
81
|
+
export { isObjectIdInstance as n, isValidIdForType as r, getSchemaIdType as t };
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { $ as ReadPreferenceType, At as LookupOptions, D as GroupResult, V as ObjectId, W as OperationOptions, Z as PopulateSpec, _t as UpdateOptions, a as AnyDocument, b as DeleteResult, g as CreateOptions, gt as UpdateManyResult, pt as SortSpec, st as SelectSpec, vt as UpdateWithValidationResult, z as MinMaxResult } from "./types-
|
|
1
|
+
import { $ as ReadPreferenceType, At as LookupOptions, D as GroupResult, V as ObjectId, W as OperationOptions, Z as PopulateSpec, _t as UpdateOptions, a as AnyDocument, b as DeleteResult, g as CreateOptions, gt as UpdateManyResult, pt as SortSpec, st as SelectSpec, vt as UpdateWithValidationResult, z as MinMaxResult } from "./types-DiQfDesD.mjs";
|
|
2
2
|
import { ClientSession, Model, PipelineStage } from "mongoose";
|
|
3
3
|
|
|
4
4
|
//#region src/actions/aggregate.d.ts
|
package/dist/index.d.mts
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
|
-
import { $ as ReadPreferenceType, A as InferDocument, At as LookupOptions, B as NonNullableFields, C as EventPayload, Ct as WithPlugins, D as GroupResult, Dt as IRequestContext, E as FieldRules, Et as IControllerResponse, F as KeysetPaginationResult, G as PaginationConfig, H as OffsetPaginationOptions, I as Logger, J as Plugin, K as PaginationResult, L as LookupPopulateOptions, M as JsonSchema, N as KeysOfType, O as HookMode, Ot as IResponseFormatter, P as KeysetPaginationOptions, Q as ReadOptions, R as LookupPopulateResult, S as EventHandlers, St as ValidatorDefinition, T as FieldPreset, Tt as IController, U as OffsetPaginationResult, V as ObjectId, W as OperationOptions, X as PluginType, Y as PluginFunction, Z as PopulateSpec, _ as CrudSchemas, _t as UpdateOptions, a as AnyDocument, at as RequiredBy, b as DeleteResult, bt as ValidationChainOptions, c as CacheOperationOptions, ct as SessionOptions, d as CacheableOptions, dt as SoftDeleteRepository, et as RepositoryContext, f as CascadeOptions, ft as SortDirection, g as CreateOptions, gt as UpdateManyResult, h as CreateInput, ht as UpdateInput, i as AllPluginMethods, it as RepositoryOptions, j as InferRawDoc, k as HttpError, kt as LookupBuilder, l as CacheOptions, lt as SoftDeleteFilterMode, m as CollationOptions, mt as Strict, n as AggregatePaginationOptions, nt as RepositoryInstance, o as AnyModel, ot as SchemaBuilderOptions, p as CascadeRelation, pt as SortSpec, q as PartialBy, r as AggregatePaginationResult, rt as RepositoryOperation, s as CacheAdapter, st as SelectSpec, t as AggregateOptions, tt as RepositoryEvent, u as CacheStats, ut as SoftDeleteOptions, v as DecodedCursor, vt as UpdateWithValidationResult, w as EventPhase, wt as WithTransactionOptions, x as DocField, xt as ValidationResult, y as DeepPartial, yt as UserContext, z as MinMaxResult } from "./types-
|
|
2
|
-
import { t as index_d_exports } from "./index-
|
|
1
|
+
import { $ as ReadPreferenceType, A as InferDocument, At as LookupOptions, B as NonNullableFields, C as EventPayload, Ct as WithPlugins, D as GroupResult, Dt as IRequestContext, E as FieldRules, Et as IControllerResponse, F as KeysetPaginationResult, G as PaginationConfig, H as OffsetPaginationOptions, I as Logger, J as Plugin, K as PaginationResult, L as LookupPopulateOptions, M as JsonSchema, N as KeysOfType, O as HookMode, Ot as IResponseFormatter, P as KeysetPaginationOptions, Q as ReadOptions, R as LookupPopulateResult, S as EventHandlers, St as ValidatorDefinition, T as FieldPreset, Tt as IController, U as OffsetPaginationResult, V as ObjectId, W as OperationOptions, X as PluginType, Y as PluginFunction, Z as PopulateSpec, _ as CrudSchemas, _t as UpdateOptions, a as AnyDocument, at as RequiredBy, b as DeleteResult, bt as ValidationChainOptions, c as CacheOperationOptions, ct as SessionOptions, d as CacheableOptions, dt as SoftDeleteRepository, et as RepositoryContext, f as CascadeOptions, ft as SortDirection, g as CreateOptions, gt as UpdateManyResult, h as CreateInput, ht as UpdateInput, i as AllPluginMethods, it as RepositoryOptions, j as InferRawDoc, k as HttpError, kt as LookupBuilder, l as CacheOptions, lt as SoftDeleteFilterMode, m as CollationOptions, mt as Strict, n as AggregatePaginationOptions, nt as RepositoryInstance, o as AnyModel, ot as SchemaBuilderOptions, p as CascadeRelation, pt as SortSpec, q as PartialBy, r as AggregatePaginationResult, rt as RepositoryOperation, s as CacheAdapter, st as SelectSpec, t as AggregateOptions, tt as RepositoryEvent, u as CacheStats, ut as SoftDeleteOptions, v as DecodedCursor, vt as UpdateWithValidationResult, w as EventPhase, wt as WithTransactionOptions, x as DocField, xt as ValidationResult, y as DeepPartial, yt as UserContext, z as MinMaxResult } from "./types-DiQfDesD.mjs";
|
|
2
|
+
import { t as index_d_exports } from "./index-BSRSsRRx.mjs";
|
|
3
3
|
import { PaginationEngine } from "./pagination/PaginationEngine.mjs";
|
|
4
|
-
import { A as dateSequentialId, B as AuditEntry, C as elasticSearchPlugin, D as PrefixedIdOptions, E as IdGenerator, F as CacheMethods, G as AuditTrailOptions, H as AuditQueryOptions, I as cachePlugin, J as auditLogPlugin, K as AuditTrailQuery, L as BatchOperationsMethods, M as prefixedId, N as sequentialId, O as SequentialIdOptions, P as cascadePlugin, R as BulkWriteResult, S as ElasticSearchOptions, T as DateSequentialIdOptions, U as AuditQueryResult, V as AuditOperation, W as AuditTrailMethods, X as aggregateHelpersPlugin, Y as AggregateHelpersMethods, _ as MongoOperationsMethods, a as uniqueField, b as methodRegistryPlugin, c as SubdocumentMethods, d as softDeletePlugin, f as ObservabilityOptions, g as multiTenantPlugin, h as MultiTenantOptions, i as requireField, j as getNextSequence, k as customIdPlugin, l as subdocumentPlugin, m as observabilityPlugin, n as blockIf, o as validationChainPlugin, p as OperationMetric, q as auditTrailPlugin, r as immutableField, s as timestampPlugin, t as autoInject, u as SoftDeleteMethods, v as mongoOperationsPlugin, w as CustomIdOptions, x as fieldFilterPlugin, z as batchOperationsPlugin } from "./validation-chain.plugin-
|
|
5
|
-
import { n as SchemaPathsLike, t as FieldType$1 } from "./coercion-
|
|
6
|
-
import { n as SchemaIndexes } from "./indexes-
|
|
7
|
-
import { a as isFieldUpdateAllowed, c as configureLogger, d as getFieldsForUser, f as getMongooseProjection, i as getSystemManagedFields, l as createFieldPreset, m as parseDuplicateKeyError, n as buildCrudSchemasFromMongooseSchema, o as validateUpdateBody, p as createError, r as getImmutableFields, s as createMemoryCache, t as buildCrudSchemasFromModel, u as filterResponseData } from "./mongooseToJsonSchema-
|
|
4
|
+
import { A as dateSequentialId, B as AuditEntry, C as elasticSearchPlugin, D as PrefixedIdOptions, E as IdGenerator, F as CacheMethods, G as AuditTrailOptions, H as AuditQueryOptions, I as cachePlugin, J as auditLogPlugin, K as AuditTrailQuery, L as BatchOperationsMethods, M as prefixedId, N as sequentialId, O as SequentialIdOptions, P as cascadePlugin, R as BulkWriteResult, S as ElasticSearchOptions, T as DateSequentialIdOptions, U as AuditQueryResult, V as AuditOperation, W as AuditTrailMethods, X as aggregateHelpersPlugin, Y as AggregateHelpersMethods, _ as MongoOperationsMethods, a as uniqueField, b as methodRegistryPlugin, c as SubdocumentMethods, d as softDeletePlugin, f as ObservabilityOptions, g as multiTenantPlugin, h as MultiTenantOptions, i as requireField, j as getNextSequence, k as customIdPlugin, l as subdocumentPlugin, m as observabilityPlugin, n as blockIf, o as validationChainPlugin, p as OperationMetric, q as auditTrailPlugin, r as immutableField, s as timestampPlugin, t as autoInject, u as SoftDeleteMethods, v as mongoOperationsPlugin, w as CustomIdOptions, x as fieldFilterPlugin, z as batchOperationsPlugin } from "./validation-chain.plugin-COKNRAwp.mjs";
|
|
5
|
+
import { n as SchemaPathsLike, t as FieldType$1 } from "./coercion-B19MD38s.mjs";
|
|
6
|
+
import { n as SchemaIndexes } from "./indexes-qIBCZ3mY.mjs";
|
|
7
|
+
import { a as isFieldUpdateAllowed, c as configureLogger, d as getFieldsForUser, f as getMongooseProjection, i as getSystemManagedFields, l as createFieldPreset, m as parseDuplicateKeyError, n as buildCrudSchemasFromMongooseSchema, o as validateUpdateBody, p as createError, r as getImmutableFields, s as createMemoryCache, t as buildCrudSchemasFromModel, u as filterResponseData } from "./mongooseToJsonSchema-D2YjHo7W.mjs";
|
|
8
8
|
import * as _$mongoose from "mongoose";
|
|
9
9
|
import { ClientSession, Expression, Model, PipelineStage, PopulateOptions } from "mongoose";
|
|
10
10
|
|
|
@@ -977,10 +977,29 @@ declare class Repository<TDoc = unknown> {
|
|
|
977
977
|
*/
|
|
978
978
|
update(id: string | ObjectId, data: Record<string, unknown>, options?: UpdateOptions): Promise<TDoc>;
|
|
979
979
|
/**
|
|
980
|
-
* Delete document by ID
|
|
980
|
+
* Delete a document by ID.
|
|
981
|
+
*
|
|
982
|
+
* By default the behavior is decided by the plugin stack:
|
|
983
|
+
* - With `softDeletePlugin` wired → soft delete (sets `deletedAt`)
|
|
984
|
+
* - Without the plugin → physical delete
|
|
985
|
+
*
|
|
986
|
+
* Pass `mode: 'hard'` to force physical deletion regardless of plugins.
|
|
987
|
+
* All policy hooks (multi-tenant scope, audit trails, cache invalidation,
|
|
988
|
+
* cascade) still fire — only the soft-delete interception is skipped. This
|
|
989
|
+
* is the GDPR / admin-cleanup path.
|
|
990
|
+
*
|
|
991
|
+
* @example
|
|
992
|
+
* ```ts
|
|
993
|
+
* // Respects softDeletePlugin — soft if wired
|
|
994
|
+
* await userRepo.delete(userId);
|
|
995
|
+
*
|
|
996
|
+
* // GDPR erasure — physical delete, audit hooks still fire
|
|
997
|
+
* await userRepo.delete(userId, { mode: 'hard', organizationId: 'org_123' });
|
|
998
|
+
* ```
|
|
981
999
|
*/
|
|
982
1000
|
delete(id: string | ObjectId, options?: SessionOptions & {
|
|
983
1001
|
idField?: string;
|
|
1002
|
+
mode?: 'hard' | 'soft';
|
|
984
1003
|
}): Promise<DeleteResult>;
|
|
985
1004
|
/**
|
|
986
1005
|
* Execute aggregation pipeline
|
|
@@ -1096,7 +1115,6 @@ declare class Repository<TDoc = unknown> {
|
|
|
1096
1115
|
* ```
|
|
1097
1116
|
*/
|
|
1098
1117
|
withTransaction<T>(callback: (session: ClientSession) => Promise<T>, options?: WithTransactionOptions): Promise<T>;
|
|
1099
|
-
private _isTransactionUnsupported;
|
|
1100
1118
|
/**
|
|
1101
1119
|
* Execute custom query with event emission
|
|
1102
1120
|
*/
|
|
@@ -1111,6 +1129,21 @@ declare class Repository<TDoc = unknown> {
|
|
|
1111
1129
|
* 4. DEFAULT (500) — user-registered hooks
|
|
1112
1130
|
*/
|
|
1113
1131
|
_buildContext(operation: string, options: Record<string, unknown> | object): Promise<RepositoryContext>;
|
|
1132
|
+
/**
|
|
1133
|
+
* Resolve the effective sort for getAll. Handles $near conflict detection
|
|
1134
|
+
* (warns + drops explicit sort when $near is in filters).
|
|
1135
|
+
*/
|
|
1136
|
+
private _resolveSort;
|
|
1137
|
+
/**
|
|
1138
|
+
* Detect whether to use keyset (cursor) or offset (page) pagination.
|
|
1139
|
+
*/
|
|
1140
|
+
private _detectPaginationMode;
|
|
1141
|
+
/**
|
|
1142
|
+
* Build the MongoDB query filter with search merged in. Handles text
|
|
1143
|
+
* search ($text), regex search ($or of $regex), and the search-resolver
|
|
1144
|
+
* plugin contract (search already cleared by a before:getAll hook).
|
|
1145
|
+
*/
|
|
1146
|
+
private _buildSearchQuery;
|
|
1114
1147
|
/**
|
|
1115
1148
|
* Parse sort string or object
|
|
1116
1149
|
*/
|
|
@@ -1125,6 +1158,45 @@ declare class Repository<TDoc = unknown> {
|
|
|
1125
1158
|
_handleError(error: Error): HttpError;
|
|
1126
1159
|
}
|
|
1127
1160
|
//#endregion
|
|
1161
|
+
//#region src/transaction.d.ts
|
|
1162
|
+
/** Minimal shape we need from a Mongoose connection. */
|
|
1163
|
+
interface SessionStarter {
|
|
1164
|
+
startSession(): Promise<ClientSession>;
|
|
1165
|
+
}
|
|
1166
|
+
/**
|
|
1167
|
+
* Run a callback inside a MongoDB transaction on the given connection.
|
|
1168
|
+
*
|
|
1169
|
+
* - Starts a session, runs `session.withTransaction(callback)` (which auto-retries
|
|
1170
|
+
* on `TransientTransactionError` and `UnknownTransactionCommitResult`), and
|
|
1171
|
+
* always ends the session in `finally`.
|
|
1172
|
+
* - When `allowFallback` is true and the deployment doesn't support transactions
|
|
1173
|
+
* (e.g. standalone MongoDB in dev), the callback runs once without a
|
|
1174
|
+
* transaction on the same session. `onFallback` is invoked with the original
|
|
1175
|
+
* error so hosts can log the degradation.
|
|
1176
|
+
*
|
|
1177
|
+
* @example
|
|
1178
|
+
* ```ts
|
|
1179
|
+
* import mongoose from 'mongoose';
|
|
1180
|
+
* import { withTransaction } from '@classytic/mongokit';
|
|
1181
|
+
*
|
|
1182
|
+
* await withTransaction(mongoose.connection, async (session) => {
|
|
1183
|
+
* const order = await orderRepo.create(data, { session });
|
|
1184
|
+
* await inventoryRepo.decrement(order.items, { session });
|
|
1185
|
+
* return order;
|
|
1186
|
+
* });
|
|
1187
|
+
* ```
|
|
1188
|
+
*/
|
|
1189
|
+
declare function withTransaction<T>(connection: SessionStarter, callback: (session: ClientSession) => Promise<T>, options?: WithTransactionOptions): Promise<T>;
|
|
1190
|
+
/**
|
|
1191
|
+
* Detect whether an error indicates the MongoDB deployment does not support
|
|
1192
|
+
* multi-document transactions (standalone server, older topology, etc.).
|
|
1193
|
+
*
|
|
1194
|
+
* Checks MongoDB error codes first — 263 (standalone) and 20 (unsupported
|
|
1195
|
+
* topology) — with a message-matching fallback for edge cases surfaced by
|
|
1196
|
+
* older driver versions.
|
|
1197
|
+
*/
|
|
1198
|
+
declare function isTransactionUnsupported(error: Error): boolean;
|
|
1199
|
+
//#endregion
|
|
1128
1200
|
//#region src/index.d.ts
|
|
1129
1201
|
/**
|
|
1130
1202
|
* Factory function to create a repository instance
|
|
@@ -1138,4 +1210,4 @@ declare class Repository<TDoc = unknown> {
|
|
|
1138
1210
|
*/
|
|
1139
1211
|
declare function createRepository<TDoc>(Model: _$mongoose.Model<TDoc, any, any, any>, plugins?: PluginType[], paginationConfig?: PaginationConfig, options?: RepositoryOptions): Repository<TDoc>;
|
|
1140
1212
|
//#endregion
|
|
1141
|
-
export { type AggregateHelpersMethods, type AggregateOptions, type AggregatePaginationOptions, type AggregatePaginationResult, AggregationBuilder, type AllPluginMethods, type AnyDocument, type AnyModel, type AuditEntry, type AuditOperation, type AuditQueryOptions, type AuditQueryResult, type AuditTrailMethods, type AuditTrailOptions, AuditTrailQuery, type BatchOperationsMethods, type BulkWriteResult, type CacheAdapter, type CacheMethods, type CacheOperationOptions, type CacheOptions, type CacheStats, type CacheableOptions, type CascadeOptions, type CascadeRelation, type CollationOptions, type CreateInput, type CreateOptions, type CrudSchemas, type CustomIdOptions, type DateSequentialIdOptions, type DecodedCursor, type DeepPartial, type DeleteResult, type DocField, type ElasticSearchOptions, type EventHandlers, type EventPayload, type EventPhase, type FieldPreset, type FieldRules, type FieldType, type FilterQuery, type GroupResult, HOOK_PRIORITY, type HookMode, type HttpError, type IController, type IControllerResponse, type IRequestContext, type IResponseFormatter, type IdGenerator, type InferDocument, type InferRawDoc, type JsonSchema, type KeysOfType, type KeysetPaginationOptions, type KeysetPaginationResult, type Logger, LookupBuilder, type LookupOptions, type LookupPopulateOptions, type LookupPopulateResult, type MinMaxResult, type MongoOperationsMethods, type MultiTenantOptions, type NonNullableFields, type ObjectId, type ObservabilityOptions, type OffsetPaginationOptions, type OffsetPaginationResult, type OperationMetric, type OperationOptions, type PaginationConfig, PaginationEngine, type PaginationResult, type ParsedQuery, type PartialBy, type Plugin, type PluginFunction, type PluginType, type PopulateOption, type PopulateSpec, type PrefixedIdOptions, QueryParser, type QueryParserOptions, type ReadOptions, type ReadPreferenceType, Repository, Repository as default, type RepositoryContext, type RepositoryEvent, type RepositoryInstance, type RepositoryOperation, type RepositoryOptions, type RequiredBy, type SchemaBuilderOptions, 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 UpdateInput, type UpdateManyResult, type UpdateOptions, type UpdateWithValidationResult, type UserContext, type ValidationChainOptions, type ValidationResult, type ValidatorDefinition, type WithPlugins, type WithTransactionOptions, index_d_exports as actions, aggregateHelpersPlugin, auditLogPlugin, auditTrailPlugin, autoInject, batchOperationsPlugin, blockIf, buildCrudSchemasFromModel, buildCrudSchemasFromMongooseSchema, cachePlugin, cascadePlugin, configureLogger, createError, createFieldPreset, createMemoryCache, createRepository, customIdPlugin, dateSequentialId, elasticSearchPlugin, fieldFilterPlugin, filterResponseData, getFieldsForUser, getImmutableFields, getMongooseProjection, getNextSequence, getSystemManagedFields, immutableField, isFieldUpdateAllowed, methodRegistryPlugin, mongoOperationsPlugin, multiTenantPlugin, observabilityPlugin, parseDuplicateKeyError, prefixedId, requireField, sequentialId, softDeletePlugin, subdocumentPlugin, timestampPlugin, uniqueField, validateUpdateBody, validationChainPlugin };
|
|
1213
|
+
export { type AggregateHelpersMethods, type AggregateOptions, type AggregatePaginationOptions, type AggregatePaginationResult, AggregationBuilder, type AllPluginMethods, type AnyDocument, type AnyModel, type AuditEntry, type AuditOperation, type AuditQueryOptions, type AuditQueryResult, type AuditTrailMethods, type AuditTrailOptions, AuditTrailQuery, type BatchOperationsMethods, type BulkWriteResult, type CacheAdapter, type CacheMethods, type CacheOperationOptions, type CacheOptions, type CacheStats, type CacheableOptions, type CascadeOptions, type CascadeRelation, type CollationOptions, type CreateInput, type CreateOptions, type CrudSchemas, type CustomIdOptions, type DateSequentialIdOptions, type DecodedCursor, type DeepPartial, type DeleteResult, type DocField, type ElasticSearchOptions, type EventHandlers, type EventPayload, type EventPhase, type FieldPreset, type FieldRules, type FieldType, type FilterQuery, type GroupResult, HOOK_PRIORITY, type HookMode, type HttpError, type IController, type IControllerResponse, type IRequestContext, type IResponseFormatter, type IdGenerator, type InferDocument, type InferRawDoc, type JsonSchema, type KeysOfType, type KeysetPaginationOptions, type KeysetPaginationResult, type Logger, LookupBuilder, type LookupOptions, type LookupPopulateOptions, type LookupPopulateResult, type MinMaxResult, type MongoOperationsMethods, type MultiTenantOptions, type NonNullableFields, type ObjectId, type ObservabilityOptions, type OffsetPaginationOptions, type OffsetPaginationResult, type OperationMetric, type OperationOptions, type PaginationConfig, PaginationEngine, type PaginationResult, type ParsedQuery, type PartialBy, type Plugin, type PluginFunction, type PluginType, type PopulateOption, type PopulateSpec, type PrefixedIdOptions, QueryParser, type QueryParserOptions, type ReadOptions, type ReadPreferenceType, Repository, Repository as default, type RepositoryContext, type RepositoryEvent, type RepositoryInstance, type RepositoryOperation, type RepositoryOptions, type RequiredBy, type SchemaBuilderOptions, 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 UpdateInput, type UpdateManyResult, type UpdateOptions, type UpdateWithValidationResult, type UserContext, type ValidationChainOptions, type ValidationResult, type ValidatorDefinition, type WithPlugins, type WithTransactionOptions, index_d_exports as actions, aggregateHelpersPlugin, auditLogPlugin, auditTrailPlugin, autoInject, batchOperationsPlugin, blockIf, buildCrudSchemasFromModel, buildCrudSchemasFromMongooseSchema, cachePlugin, cascadePlugin, configureLogger, createError, createFieldPreset, createMemoryCache, createRepository, customIdPlugin, dateSequentialId, elasticSearchPlugin, fieldFilterPlugin, filterResponseData, getFieldsForUser, getImmutableFields, getMongooseProjection, getNextSequence, getSystemManagedFields, immutableField, isFieldUpdateAllowed, isTransactionUnsupported, methodRegistryPlugin, mongoOperationsPlugin, multiTenantPlugin, observabilityPlugin, parseDuplicateKeyError, prefixedId, requireField, sequentialId, softDeletePlugin, subdocumentPlugin, timestampPlugin, uniqueField, validateUpdateBody, validationChainPlugin, withTransaction };
|
package/dist/index.mjs
CHANGED
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
import { a as warn, n as parseDuplicateKeyError, r as configureLogger, t as createError } from "./error-Bpbi_NKo.mjs";
|
|
2
2
|
import { y as LookupBuilder } from "./update-AVfKWNGt.mjs";
|
|
3
3
|
import { t as actions_exports } from "./actions/index.mjs";
|
|
4
|
-
import { t as PaginationEngine } from "./PaginationEngine-
|
|
5
|
-
import { A as
|
|
4
|
+
import { t as PaginationEngine } from "./PaginationEngine-CunXkR9p.mjs";
|
|
5
|
+
import { A as auditTrailPlugin, C as HOOK_PRIORITY, D as AggregationBuilder, E as withTransaction, M as aggregateHelpersPlugin, O as batchOperationsPlugin, S as cachePlugin, T as isTransactionUnsupported, _ as dateSequentialId, a as uniqueField, b as sequentialId, c as subdocumentPlugin, d as multiTenantPlugin, f as mongoOperationsPlugin, g as customIdPlugin, h as elasticSearchPlugin, i as requireField, j as auditLogPlugin, k as AuditTrailQuery, l as softDeletePlugin, m as fieldFilterPlugin, n as blockIf, o as validationChainPlugin, p as methodRegistryPlugin, r as immutableField, s as timestampPlugin, t as autoInject, u as observabilityPlugin, v as getNextSequence, w as Repository, x as cascadePlugin, y as prefixedId } from "./validation-chain.plugin-3rr7dlw6.mjs";
|
|
6
6
|
import { isGeoOperator, parseGeoFilter } from "./query/primitives/geo.mjs";
|
|
7
|
-
import { i as getMongooseProjection, n as filterResponseData, r as getFieldsForUser, t as createFieldPreset } from "./field-selection-
|
|
7
|
+
import { i as getMongooseProjection, n as filterResponseData, r as getFieldsForUser, t as createFieldPreset } from "./field-selection-C5o7jyyA.mjs";
|
|
8
8
|
import { buildFieldTypeMap, coerceFieldValue, coerceHeuristic } from "./query/primitives/coercion.mjs";
|
|
9
9
|
import { extractSchemaIndexes } from "./query/primitives/indexes.mjs";
|
|
10
|
-
import { a as isFieldUpdateAllowed, i as getSystemManagedFields, n as buildCrudSchemasFromMongooseSchema, o as validateUpdateBody, r as getImmutableFields, s as createMemoryCache, t as buildCrudSchemasFromModel } from "./mongooseToJsonSchema-
|
|
10
|
+
import { a as isFieldUpdateAllowed, i as getSystemManagedFields, n as buildCrudSchemasFromMongooseSchema, o as validateUpdateBody, r as getImmutableFields, s as createMemoryCache, t as buildCrudSchemasFromModel } from "./mongooseToJsonSchema-8Cyu3NFJ.mjs";
|
|
11
11
|
//#region src/query/QueryParser.ts
|
|
12
12
|
/**
|
|
13
13
|
* Modern Query Parser
|
|
@@ -945,4 +945,4 @@ function createRepository(Model, plugins = [], paginationConfig = {}, options =
|
|
|
945
945
|
}
|
|
946
946
|
var src_default = Repository;
|
|
947
947
|
//#endregion
|
|
948
|
-
export { AggregationBuilder, AuditTrailQuery, HOOK_PRIORITY, LookupBuilder, PaginationEngine, QueryParser, Repository, actions_exports as actions, aggregateHelpersPlugin, auditLogPlugin, auditTrailPlugin, autoInject, batchOperationsPlugin, blockIf, buildCrudSchemasFromModel, buildCrudSchemasFromMongooseSchema, cachePlugin, cascadePlugin, configureLogger, createError, createFieldPreset, createMemoryCache, createRepository, customIdPlugin, dateSequentialId, src_default as default, elasticSearchPlugin, fieldFilterPlugin, filterResponseData, getFieldsForUser, getImmutableFields, getMongooseProjection, getNextSequence, getSystemManagedFields, immutableField, isFieldUpdateAllowed, methodRegistryPlugin, mongoOperationsPlugin, multiTenantPlugin, observabilityPlugin, parseDuplicateKeyError, prefixedId, requireField, sequentialId, softDeletePlugin, subdocumentPlugin, timestampPlugin, uniqueField, validateUpdateBody, validationChainPlugin };
|
|
948
|
+
export { AggregationBuilder, AuditTrailQuery, HOOK_PRIORITY, LookupBuilder, PaginationEngine, QueryParser, Repository, actions_exports as actions, aggregateHelpersPlugin, auditLogPlugin, auditTrailPlugin, autoInject, batchOperationsPlugin, blockIf, buildCrudSchemasFromModel, buildCrudSchemasFromMongooseSchema, cachePlugin, cascadePlugin, configureLogger, createError, createFieldPreset, createMemoryCache, createRepository, customIdPlugin, dateSequentialId, src_default as default, elasticSearchPlugin, fieldFilterPlugin, filterResponseData, getFieldsForUser, getImmutableFields, getMongooseProjection, getNextSequence, getSystemManagedFields, immutableField, isFieldUpdateAllowed, isTransactionUnsupported, methodRegistryPlugin, mongoOperationsPlugin, multiTenantPlugin, observabilityPlugin, parseDuplicateKeyError, prefixedId, requireField, sequentialId, softDeletePlugin, subdocumentPlugin, timestampPlugin, uniqueField, validateUpdateBody, validationChainPlugin, withTransaction };
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { n as isObjectIdInstance } from "./id-resolution-LZ-cCwR5.mjs";
|
|
1
2
|
import "mongoose";
|
|
2
3
|
//#region src/utils/memory-cache.ts
|
|
3
4
|
/**
|
|
@@ -93,28 +94,56 @@ function buildCrudSchemasFromModel(mongooseModel, options = {}) {
|
|
|
93
94
|
return buildCrudSchemasFromMongooseSchema(mongooseModel.schema, options);
|
|
94
95
|
}
|
|
95
96
|
/**
|
|
96
|
-
*
|
|
97
|
+
* Collect fields to omit from a generated schema based on field rules and
|
|
98
|
+
* explicit omit lists. This is the single source of truth for "which fields
|
|
99
|
+
* should NOT appear in the create/update body" — called by both the
|
|
100
|
+
* path-based and tree-based schema builders.
|
|
101
|
+
*/
|
|
102
|
+
function collectFieldsToOmit(options, purpose) {
|
|
103
|
+
const result = new Set([
|
|
104
|
+
"createdAt",
|
|
105
|
+
"updatedAt",
|
|
106
|
+
"__v"
|
|
107
|
+
]);
|
|
108
|
+
const rules = options?.fieldRules || {};
|
|
109
|
+
for (const [field, rule] of Object.entries(rules)) {
|
|
110
|
+
if (rule.systemManaged) result.add(field);
|
|
111
|
+
if (purpose === "update" && (rule.immutable || rule.immutableAfterCreate)) result.add(field);
|
|
112
|
+
}
|
|
113
|
+
const explicit = purpose === "create" ? options?.create?.omitFields : options?.update?.omitFields;
|
|
114
|
+
if (explicit) for (const f of explicit) result.add(f);
|
|
115
|
+
return result;
|
|
116
|
+
}
|
|
117
|
+
/**
|
|
118
|
+
* Apply omissions + optional-overrides to a built JSON schema in-place.
|
|
119
|
+
* Removes properties and adjusts the `required` array.
|
|
120
|
+
*/
|
|
121
|
+
function applyFieldRules(schema, fieldsToOmit, options) {
|
|
122
|
+
for (const field of fieldsToOmit) {
|
|
123
|
+
if (schema.properties?.[field]) delete schema.properties[field];
|
|
124
|
+
if (schema.required) schema.required = schema.required.filter((k) => k !== field);
|
|
125
|
+
}
|
|
126
|
+
const rules = options?.fieldRules || {};
|
|
127
|
+
for (const [field, rule] of Object.entries(rules)) if (rule.optional && schema.required) schema.required = schema.required.filter((k) => k !== field);
|
|
128
|
+
}
|
|
129
|
+
/**
|
|
130
|
+
* Get fields that are immutable (cannot be updated).
|
|
131
|
+
* Delegates to `collectFieldsToOmit` internally.
|
|
97
132
|
*/
|
|
98
133
|
function getImmutableFields(options = {}) {
|
|
99
134
|
const immutable = [];
|
|
100
|
-
const
|
|
101
|
-
Object.entries(
|
|
102
|
-
|
|
103
|
-
});
|
|
104
|
-
(options?.update?.omitFields || []).forEach((f) => {
|
|
105
|
-
if (!immutable.includes(f)) immutable.push(f);
|
|
106
|
-
});
|
|
135
|
+
const rules = options?.fieldRules || {};
|
|
136
|
+
for (const [field, rule] of Object.entries(rules)) if (rule.immutable || rule.immutableAfterCreate) immutable.push(field);
|
|
137
|
+
for (const f of options?.update?.omitFields || []) if (!immutable.includes(f)) immutable.push(f);
|
|
107
138
|
return immutable;
|
|
108
139
|
}
|
|
109
140
|
/**
|
|
110
|
-
* Get fields that are system-managed (cannot be set by users)
|
|
141
|
+
* Get fields that are system-managed (cannot be set by users).
|
|
111
142
|
*/
|
|
112
143
|
function getSystemManagedFields(options = {}) {
|
|
113
144
|
const systemManaged = [];
|
|
114
|
-
const
|
|
115
|
-
Object.entries(
|
|
116
|
-
if (rules.systemManaged) systemManaged.push(field);
|
|
117
|
-
});
|
|
145
|
+
const rules = options?.fieldRules || {};
|
|
146
|
+
for (const [field, rule] of Object.entries(rules)) if (rule.systemManaged) systemManaged.push(field);
|
|
118
147
|
return systemManaged;
|
|
119
148
|
}
|
|
120
149
|
/**
|
|
@@ -161,7 +190,11 @@ function buildJsonSchemaFromPaths(mongooseSchema, options) {
|
|
|
161
190
|
};
|
|
162
191
|
const rootFields = /* @__PURE__ */ new Map();
|
|
163
192
|
for (const [path, schemaType] of Object.entries(paths)) {
|
|
164
|
-
if (path === "
|
|
193
|
+
if (path === "__v") continue;
|
|
194
|
+
if (path === "_id") {
|
|
195
|
+
const instance = schemaType.instance;
|
|
196
|
+
if (!instance || isObjectIdInstance(instance)) continue;
|
|
197
|
+
}
|
|
165
198
|
const rootField = path.split(".")[0];
|
|
166
199
|
if (!rootFields.has(rootField)) rootFields.set(rootField, []);
|
|
167
200
|
rootFields.get(rootField)?.push({
|
|
@@ -183,30 +216,12 @@ function buildJsonSchemaFromPaths(mongooseSchema, options) {
|
|
|
183
216
|
properties
|
|
184
217
|
};
|
|
185
218
|
if (required.length) schema.required = required;
|
|
186
|
-
|
|
187
|
-
"createdAt",
|
|
188
|
-
"updatedAt",
|
|
189
|
-
"__v"
|
|
190
|
-
]);
|
|
191
|
-
(options?.create?.omitFields || []).forEach((f) => {
|
|
192
|
-
fieldsToOmit.add(f);
|
|
193
|
-
});
|
|
194
|
-
const fieldRules = options?.fieldRules || {};
|
|
195
|
-
Object.entries(fieldRules).forEach(([field, rules]) => {
|
|
196
|
-
if (rules.systemManaged) fieldsToOmit.add(field);
|
|
197
|
-
});
|
|
198
|
-
fieldsToOmit.forEach((field) => {
|
|
199
|
-
if (schema.properties?.[field]) delete schema.properties[field];
|
|
200
|
-
if (schema.required) schema.required = schema.required.filter((k) => k !== field);
|
|
201
|
-
});
|
|
219
|
+
applyFieldRules(schema, collectFieldsToOmit(options, "create"), options);
|
|
202
220
|
const reqOv = options?.create?.requiredOverrides || {};
|
|
203
221
|
const optOv = options?.create?.optionalOverrides || {};
|
|
204
222
|
schema.required = schema.required || [];
|
|
205
223
|
for (const [k, v] of Object.entries(reqOv)) if (v && !schema.required.includes(k)) schema.required.push(k);
|
|
206
224
|
for (const [k, v] of Object.entries(optOv)) if (v && schema.required) schema.required = schema.required.filter((x) => x !== k);
|
|
207
|
-
Object.entries(fieldRules).forEach(([field, rules]) => {
|
|
208
|
-
if (rules.optional && schema.required) schema.required = schema.required.filter((x) => x !== field);
|
|
209
|
-
});
|
|
210
225
|
const schemaOverrides = options?.create?.schemaOverrides || {};
|
|
211
226
|
for (const [k, override] of Object.entries(schemaOverrides)) if (schema.properties?.[k]) schema.properties[k] = override;
|
|
212
227
|
if (options?.strictAdditionalProperties === true) schema.additionalProperties = false;
|
|
@@ -270,7 +285,7 @@ function schemaTypeToJsonSchema(schemaType) {
|
|
|
270
285
|
else if (instance === "Date") {
|
|
271
286
|
result.type = "string";
|
|
272
287
|
result.format = "date-time";
|
|
273
|
-
} else if (instance
|
|
288
|
+
} else if (isObjectIdInstance(instance)) {
|
|
274
289
|
result.type = "string";
|
|
275
290
|
result.pattern = "^[0-9a-fA-F]{24}$";
|
|
276
291
|
} else if (instance === "Array") {
|
|
@@ -285,17 +300,7 @@ function schemaTypeToJsonSchema(schemaType) {
|
|
|
285
300
|
function buildJsonSchemaForUpdate(createJson, options) {
|
|
286
301
|
const clone = JSON.parse(JSON.stringify(createJson));
|
|
287
302
|
delete clone.required;
|
|
288
|
-
|
|
289
|
-
(options?.update?.omitFields || []).forEach((f) => {
|
|
290
|
-
fieldsToOmit.add(f);
|
|
291
|
-
});
|
|
292
|
-
const fieldRules = options?.fieldRules || {};
|
|
293
|
-
Object.entries(fieldRules).forEach(([field, rules]) => {
|
|
294
|
-
if (rules.immutable || rules.immutableAfterCreate) fieldsToOmit.add(field);
|
|
295
|
-
});
|
|
296
|
-
fieldsToOmit.forEach((field) => {
|
|
297
|
-
if (clone.properties?.[field]) delete clone.properties[field];
|
|
298
|
-
});
|
|
303
|
+
applyFieldRules(clone, collectFieldsToOmit(options, "update"), options);
|
|
299
304
|
if (options?.strictAdditionalProperties === true) clone.additionalProperties = false;
|
|
300
305
|
if (options?.update?.requireAtLeastOne === true) clone.minProperties = 1;
|
|
301
306
|
return clone;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { T as FieldPreset, _ as CrudSchemas, k as HttpError, ot as SchemaBuilderOptions, s as CacheAdapter, xt as ValidationResult, yt as UserContext } from "./types-
|
|
1
|
+
import { T as FieldPreset, _ as CrudSchemas, k as HttpError, ot as SchemaBuilderOptions, s as CacheAdapter, xt as ValidationResult, yt as UserContext } from "./types-DiQfDesD.mjs";
|
|
2
2
|
import mongoose, { Schema } from "mongoose";
|
|
3
3
|
|
|
4
4
|
//#region src/utils/error.d.ts
|
|
@@ -146,11 +146,12 @@ declare function buildCrudSchemasFromMongooseSchema(mongooseSchema: Schema, opti
|
|
|
146
146
|
*/
|
|
147
147
|
declare function buildCrudSchemasFromModel(mongooseModel: mongoose.Model<unknown>, options?: SchemaBuilderOptions): CrudSchemas;
|
|
148
148
|
/**
|
|
149
|
-
* Get fields that are immutable (cannot be updated)
|
|
149
|
+
* Get fields that are immutable (cannot be updated).
|
|
150
|
+
* Delegates to `collectFieldsToOmit` internally.
|
|
150
151
|
*/
|
|
151
152
|
declare function getImmutableFields(options?: SchemaBuilderOptions): string[];
|
|
152
153
|
/**
|
|
153
|
-
* Get fields that are system-managed (cannot be set by users)
|
|
154
|
+
* Get fields that are system-managed (cannot be set by users).
|
|
154
155
|
*/
|
|
155
156
|
declare function getSystemManagedFields(options?: SchemaBuilderOptions): string[];
|
|
156
157
|
/**
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { F as KeysetPaginationResult, G as PaginationConfig, H as OffsetPaginationOptions, P as KeysetPaginationOptions, U as OffsetPaginationResult, a as AnyDocument, n as AggregatePaginationOptions, r as AggregatePaginationResult } from "../types-
|
|
1
|
+
import { F as KeysetPaginationResult, G as PaginationConfig, H as OffsetPaginationOptions, P as KeysetPaginationOptions, U as OffsetPaginationResult, a as AnyDocument, n as AggregatePaginationOptions, r as AggregatePaginationResult } from "../types-DiQfDesD.mjs";
|
|
2
2
|
import { Model } from "mongoose";
|
|
3
3
|
|
|
4
4
|
//#region src/pagination/PaginationEngine.d.ts
|
|
@@ -20,6 +20,11 @@ interface ResolvedPaginationConfig {
|
|
|
20
20
|
declare class PaginationEngine<TDoc = AnyDocument> {
|
|
21
21
|
readonly Model: Model<TDoc>;
|
|
22
22
|
readonly config: ResolvedPaginationConfig;
|
|
23
|
+
/**
|
|
24
|
+
* Lazily-cached schema index snapshot used by stream() to decide whether
|
|
25
|
+
* to emit the "missing compound index" warning. Computed on first use.
|
|
26
|
+
*/
|
|
27
|
+
private _cachedSchemaIndexes;
|
|
23
28
|
/**
|
|
24
29
|
* Create a new pagination engine
|
|
25
30
|
*
|
|
@@ -27,6 +32,8 @@ declare class PaginationEngine<TDoc = AnyDocument> {
|
|
|
27
32
|
* @param config - Pagination configuration
|
|
28
33
|
*/
|
|
29
34
|
constructor(Model: Model<TDoc, any, any, any>, config?: PaginationConfig);
|
|
35
|
+
/** Memoized schema index lookup — avoids re-walking schema on every stream(). */
|
|
36
|
+
private _getSchemaIndexes;
|
|
30
37
|
/**
|
|
31
38
|
* Offset-based pagination using skip/limit
|
|
32
39
|
* Best for small datasets and when users need random page access
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { t as PaginationEngine } from "../PaginationEngine-
|
|
1
|
+
import { t as PaginationEngine } from "../PaginationEngine-CunXkR9p.mjs";
|
|
2
2
|
export { PaginationEngine };
|
package/dist/plugins/index.d.mts
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { A as dateSequentialId, B as AuditEntry, C as elasticSearchPlugin, D as PrefixedIdOptions, E as IdGenerator, F as CacheMethods, G as AuditTrailOptions, H as AuditQueryOptions, I as cachePlugin, J as auditLogPlugin, K as AuditTrailQuery, L as BatchOperationsMethods, M as prefixedId, N as sequentialId, O as SequentialIdOptions, P as cascadePlugin, S as ElasticSearchOptions, T as DateSequentialIdOptions, U as AuditQueryResult, V as AuditOperation, W as AuditTrailMethods, X as aggregateHelpersPlugin, Y as AggregateHelpersMethods, _ as MongoOperationsMethods, a as uniqueField, b as methodRegistryPlugin, c as SubdocumentMethods, d as softDeletePlugin, f as ObservabilityOptions, g as multiTenantPlugin, h as MultiTenantOptions, i as requireField, j as getNextSequence, k as customIdPlugin, l as subdocumentPlugin, m as observabilityPlugin, n as blockIf, o as validationChainPlugin, p as OperationMetric, q as auditTrailPlugin, r as immutableField, s as timestampPlugin, t as autoInject, u as SoftDeleteMethods, v as mongoOperationsPlugin, w as CustomIdOptions, x as fieldFilterPlugin, y as MethodRegistryRepository, z as batchOperationsPlugin } from "../validation-chain.plugin-
|
|
1
|
+
import { A as dateSequentialId, B as AuditEntry, C as elasticSearchPlugin, D as PrefixedIdOptions, E as IdGenerator, F as CacheMethods, G as AuditTrailOptions, H as AuditQueryOptions, I as cachePlugin, J as auditLogPlugin, K as AuditTrailQuery, L as BatchOperationsMethods, M as prefixedId, N as sequentialId, O as SequentialIdOptions, P as cascadePlugin, S as ElasticSearchOptions, T as DateSequentialIdOptions, U as AuditQueryResult, V as AuditOperation, W as AuditTrailMethods, X as aggregateHelpersPlugin, Y as AggregateHelpersMethods, _ as MongoOperationsMethods, a as uniqueField, b as methodRegistryPlugin, c as SubdocumentMethods, d as softDeletePlugin, f as ObservabilityOptions, g as multiTenantPlugin, h as MultiTenantOptions, i as requireField, j as getNextSequence, k as customIdPlugin, l as subdocumentPlugin, m as observabilityPlugin, n as blockIf, o as validationChainPlugin, p as OperationMetric, q as auditTrailPlugin, r as immutableField, s as timestampPlugin, t as autoInject, u as SoftDeleteMethods, v as mongoOperationsPlugin, w as CustomIdOptions, x as fieldFilterPlugin, y as MethodRegistryRepository, z as batchOperationsPlugin } from "../validation-chain.plugin-COKNRAwp.mjs";
|
|
2
2
|
export { type AggregateHelpersMethods, type AuditEntry, type AuditOperation, type AuditQueryOptions, type AuditQueryResult, type AuditTrailMethods, type AuditTrailOptions, AuditTrailQuery, type BatchOperationsMethods, type CacheMethods, type CustomIdOptions, type DateSequentialIdOptions, type ElasticSearchOptions, type IdGenerator, type MethodRegistryRepository, type MongoOperationsMethods, type MultiTenantOptions, type ObservabilityOptions, type OperationMetric, type PrefixedIdOptions, type SequentialIdOptions, type SoftDeleteMethods, type SubdocumentMethods, aggregateHelpersPlugin, auditLogPlugin, auditTrailPlugin, autoInject, batchOperationsPlugin, blockIf, cachePlugin, cascadePlugin, customIdPlugin, dateSequentialId, elasticSearchPlugin, fieldFilterPlugin, getNextSequence, immutableField, methodRegistryPlugin, mongoOperationsPlugin, multiTenantPlugin, observabilityPlugin, prefixedId, requireField, sequentialId, softDeletePlugin, subdocumentPlugin, timestampPlugin, uniqueField, validationChainPlugin };
|
package/dist/plugins/index.mjs
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { A as
|
|
1
|
+
import { A as auditTrailPlugin, M as aggregateHelpersPlugin, O as batchOperationsPlugin, S as cachePlugin, _ as dateSequentialId, a as uniqueField, b as sequentialId, c as subdocumentPlugin, d as multiTenantPlugin, f as mongoOperationsPlugin, g as customIdPlugin, h as elasticSearchPlugin, i as requireField, j as auditLogPlugin, k as AuditTrailQuery, l as softDeletePlugin, m as fieldFilterPlugin, n as blockIf, o as validationChainPlugin, p as methodRegistryPlugin, r as immutableField, s as timestampPlugin, t as autoInject, u as observabilityPlugin, v as getNextSequence, x as cascadePlugin, y as prefixedId } from "../validation-chain.plugin-3rr7dlw6.mjs";
|
|
2
2
|
export { AuditTrailQuery, aggregateHelpersPlugin, auditLogPlugin, auditTrailPlugin, autoInject, batchOperationsPlugin, blockIf, cachePlugin, cascadePlugin, customIdPlugin, dateSequentialId, elasticSearchPlugin, fieldFilterPlugin, getNextSequence, immutableField, methodRegistryPlugin, mongoOperationsPlugin, multiTenantPlugin, observabilityPlugin, prefixedId, requireField, sequentialId, softDeletePlugin, subdocumentPlugin, timestampPlugin, uniqueField, validationChainPlugin };
|