@classytic/mongokit 3.5.4 → 3.5.5
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 +129 -4
- package/dist/{PaginationEngine-DCs-zKwZ.mjs → PaginationEngine-CpsQl471.mjs} +5 -3
- package/dist/actions/index.d.mts +1 -1
- package/dist/ai/index.d.mts +1 -1
- package/dist/coercion-01tEHsKF.d.mts +106 -0
- package/dist/{index-BNpVzw_-.d.mts → index-Buj7P006.d.mts} +1 -1
- package/dist/index.d.mts +69 -6
- package/dist/index.mjs +99 -34
- package/dist/indexes-CiIT-Zli.d.mts +41 -0
- package/dist/{mongooseToJsonSchema-Dsx3YAAx.d.mts → mongooseToJsonSchema-BlDfbg_0.d.mts} +1 -1
- package/dist/pagination/PaginationEngine.d.mts +1 -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 +2 -0
- package/dist/query/primitives/coercion.mjs +147 -0
- package/dist/query/primitives/geo.d.mts +116 -0
- package/dist/query/primitives/geo.mjs +211 -0
- package/dist/query/primitives/indexes.d.mts +2 -0
- package/dist/query/primitives/indexes.mjs +46 -0
- package/dist/{types-CkE3mOaW.d.mts → types-CWUL0yiw.d.mts} +25 -0
- package/dist/utils/index.d.mts +2 -2
- package/dist/{validation-chain.plugin-KjPV_6_N.mjs → validation-chain.plugin-BCPh2UZG.mjs} +48 -11
- package/dist/{validation-chain.plugin-BYMZB8dN.d.mts → validation-chain.plugin-Dn41aAbK.d.mts} +1 -1
- package/package.json +15 -3
package/README.md
CHANGED
|
@@ -192,6 +192,45 @@ const repo = new Repository(UserModel, plugins, {
|
|
|
192
192
|
});
|
|
193
193
|
```
|
|
194
194
|
|
|
195
|
+
### Search configuration
|
|
196
|
+
|
|
197
|
+
`Repository.getAll({ search })` has three layers, ordered from simplest to most
|
|
198
|
+
flexible. Pick the lowest one that solves your problem.
|
|
199
|
+
|
|
200
|
+
| Layer | When to use | Where it lives |
|
|
201
|
+
| --------------------------- | ------------------------------------------------------------------------------------------------------------------------ | ------------------------------------------- |
|
|
202
|
+
| **`searchMode: 'text'`** | You have a MongoDB text index and want `$text`-ranked results. | Repository option (default) |
|
|
203
|
+
| **`searchMode: 'regex'`** | Small/medium collection, no text index, simple substring matching across known fields. Works behind any HTTP framework. | Repository option |
|
|
204
|
+
| **Search-resolver plugin** | External engine (Elasticsearch, Meilisearch, Typesense, pgvector, hybrid BM25+vector). Composes with cache, multi-tenant. | `before:getAll` plugin — see Plugins below |
|
|
205
|
+
|
|
206
|
+
```javascript
|
|
207
|
+
// Built-in regex mode — no MongoDB text index required
|
|
208
|
+
const repo = new Repository(
|
|
209
|
+
MemoModel,
|
|
210
|
+
[],
|
|
211
|
+
{},
|
|
212
|
+
{
|
|
213
|
+
// 'text' → default, requires text index
|
|
214
|
+
// 'regex' → case-insensitive $or of $regex across searchFields, no index needed
|
|
215
|
+
// 'auto' → text if a text index exists, otherwise regex
|
|
216
|
+
searchMode: "regex",
|
|
217
|
+
searchFields: ["title", "scope", "body"],
|
|
218
|
+
},
|
|
219
|
+
);
|
|
220
|
+
|
|
221
|
+
await repo.getAll({ search: "alpha", filters: { scope: "public" } });
|
|
222
|
+
```
|
|
223
|
+
|
|
224
|
+
User input is regex-escaped (literal substring match), and any pre-existing
|
|
225
|
+
`$or` filter is preserved by promoting both clauses to `$and`.
|
|
226
|
+
|
|
227
|
+
> **QueryParser ↔ Repository:** `QueryParser` also exposes `searchMode`/`searchFields`
|
|
228
|
+
> for the HTTP boundary (`?search=foo` URL → parsed query). The two layers are
|
|
229
|
+
> independent: configure the parser if you want URL-time consumption (Arc does
|
|
230
|
+
> this), configure the Repository if you want data-layer consumption
|
|
231
|
+
> (Express/Nest/raw handlers), or both for defense in depth — they will not
|
|
232
|
+
> conflict because the parser clears `parsed.search` before it reaches the repo.
|
|
233
|
+
|
|
195
234
|
## Plugins
|
|
196
235
|
|
|
197
236
|
### Using Plugins
|
|
@@ -754,6 +793,62 @@ const results = await repo.searchSimilar({ query: [0.1, 0.2, ...], limit: 5 });
|
|
|
754
793
|
const vector = await repo.embed('some text');
|
|
755
794
|
```
|
|
756
795
|
|
|
796
|
+
### Custom Search Backends (search-resolver plugin contract)
|
|
797
|
+
|
|
798
|
+
The built-in `searchMode: 'text' | 'regex'` is sugar over a more general
|
|
799
|
+
**plugin contract** for any search backend — Elasticsearch, Meilisearch,
|
|
800
|
+
Typesense, Algolia, pgvector, Pinecone, hybrid BM25+vector. The contract
|
|
801
|
+
keeps mongokit core free of backend-specific dependencies, and the same
|
|
802
|
+
plugin works behind any HTTP framework (Arc, Express, Nest, raw handlers)
|
|
803
|
+
without further wiring.
|
|
804
|
+
|
|
805
|
+
**The contract** (4 lines):
|
|
806
|
+
|
|
807
|
+
1. Hook `before:getAll`.
|
|
808
|
+
2. If `ctx.search` is set, resolve it against your backend (returns IDs).
|
|
809
|
+
3. Mutate `ctx.filters` to constrain the Mongo query: `_id: { $in: ids }`.
|
|
810
|
+
4. Set `ctx.search = undefined` so Repository's text-index check is bypassed.
|
|
811
|
+
|
|
812
|
+
```javascript
|
|
813
|
+
function meilisearchPlugin({ client, index }) {
|
|
814
|
+
return (repo) => {
|
|
815
|
+
repo.on("before:getAll", async (ctx) => {
|
|
816
|
+
if (!ctx.search) return;
|
|
817
|
+
const hits = await client.index(index).search(ctx.search, {
|
|
818
|
+
limit: ctx.limit ?? 20,
|
|
819
|
+
});
|
|
820
|
+
const ids = hits.hits.map((h) => h.id);
|
|
821
|
+
ctx.filters = { ...(ctx.filters ?? {}), _id: { $in: ids } };
|
|
822
|
+
ctx.search = undefined; // bypass text-index check
|
|
823
|
+
ctx._meiliRanking = ids; // stash for after:getAll re-sort
|
|
824
|
+
});
|
|
825
|
+
repo.on("after:getAll", (ctx) => {
|
|
826
|
+
if (!ctx._meiliRanking) return;
|
|
827
|
+
const order = new Map(ctx._meiliRanking.map((id, i) => [String(id), i]));
|
|
828
|
+
ctx.result.docs.sort(
|
|
829
|
+
(a, b) => order.get(String(a._id)) - order.get(String(b._id)),
|
|
830
|
+
);
|
|
831
|
+
});
|
|
832
|
+
};
|
|
833
|
+
}
|
|
834
|
+
|
|
835
|
+
// Wire at Repository construction — works in Arc, Express, Nest, anywhere
|
|
836
|
+
const repo = new Repository(ProductModel, [
|
|
837
|
+
meilisearchPlugin({ client: meili, index: "products" }),
|
|
838
|
+
cachePlugin({ adapter: createMemoryCache(), ttl: 60 }), // composes cleanly
|
|
839
|
+
]);
|
|
840
|
+
```
|
|
841
|
+
|
|
842
|
+
**Why this contract works:**
|
|
843
|
+
|
|
844
|
+
- `before:getAll` runs inside `_buildContext`, _before_ Repository reads `search` or hits the text-index check. A plugin that clears `ctx.search` short-circuits the built-in search path entirely.
|
|
845
|
+
- `Repository.getAll` reads `search` only from the post-hook context (no fallback to original params) — this is the framework-level guarantee that makes `ctx.search = undefined` a real clear, not a silently overridden no-op.
|
|
846
|
+
- The caller's existing filters are preserved by spreading: `ctx.filters = { ...(ctx.filters ?? {}), _id: ... }`. Multi-tenant scoping (which also runs in `before:getAll`), soft-delete filters, and the search plugin compose without ordering concerns — they all mutate `ctx.filters` independently and all survive.
|
|
847
|
+
- Cache plugin composes too: it sees the post-hook context (filters with the resolved ID list), so cache keys are accurate. ES/Meili results get cached just like Mongo results.
|
|
848
|
+
- The same plugin shape works for every backend; only the resolver call changes.
|
|
849
|
+
|
|
850
|
+
The bundled `elasticSearchPlugin` (next section) is the canonical reference implementation, and `tests/repository-search-mode.test.ts` exercises this contract end-to-end with multi-tenant + soft-delete + cache composition.
|
|
851
|
+
|
|
757
852
|
### Elasticsearch / OpenSearch Plugin
|
|
758
853
|
|
|
759
854
|
Delegates heavy text and semantic search to an external search engine while fetching full documents from MongoDB. Keeps your OLTP (transactional) MongoDB operations fast by separating search I/O.
|
|
@@ -1044,12 +1139,13 @@ Converts HTTP query strings to MongoDB queries with built-in security:
|
|
|
1044
1139
|
import { QueryParser } from "@classytic/mongokit";
|
|
1045
1140
|
|
|
1046
1141
|
const parser = new QueryParser({
|
|
1142
|
+
schema: ProductModel.schema, // Schema-aware coercion (recommended)
|
|
1047
1143
|
maxLimit: 100, // Prevent excessive queries
|
|
1048
1144
|
maxFilterDepth: 5, // Prevent nested injection
|
|
1049
1145
|
maxRegexLength: 100, // ReDoS protection
|
|
1050
|
-
allowedFilterFields: [
|
|
1051
|
-
allowedSortFields: [
|
|
1052
|
-
allowedOperators: [
|
|
1146
|
+
allowedFilterFields: ["status", "name", "email"], // Whitelist filter fields
|
|
1147
|
+
allowedSortFields: ["createdAt", "name"], // Whitelist sort fields
|
|
1148
|
+
allowedOperators: ["eq", "ne", "in", "gt", "lt"], // Whitelist operators
|
|
1053
1149
|
});
|
|
1054
1150
|
|
|
1055
1151
|
// Parse request query
|
|
@@ -1061,6 +1157,35 @@ parser.allowedSortFields; // ['createdAt', 'name'] or undefined
|
|
|
1061
1157
|
parser.allowedOperators; // ['eq', 'ne', 'in', 'gt', 'lt'] or undefined
|
|
1062
1158
|
```
|
|
1063
1159
|
|
|
1160
|
+
**Schema-aware value coercion (recommended):** Pass `schema: Model.schema` and
|
|
1161
|
+
the parser coerces filter values exactly to each field's declared type. With
|
|
1162
|
+
schema configured, `?stock=50` against a `Number` field becomes `50` (number),
|
|
1163
|
+
`?name=12345` against a `String` field stays `'12345'`, `?releasedAt=2026-04-07`
|
|
1164
|
+
against a `Date` field becomes a `Date` instance, `?address.zip=01234` against
|
|
1165
|
+
a nested `String` field preserves the leading zero. Direct equality and
|
|
1166
|
+
operator syntax (`stock[gte]=50`) coerce identically — no more "why does
|
|
1167
|
+
operator work but direct equality doesn't" surprises. Unknown fields fall
|
|
1168
|
+
through to a safe heuristic so ad-hoc filters still work.
|
|
1169
|
+
|
|
1170
|
+
For DB-agnostic setups (raw MongoDB, Prisma, computed fields, models you
|
|
1171
|
+
don't own), use `fieldTypes` instead of `schema`. The two can be combined —
|
|
1172
|
+
`fieldTypes` overrides `schema` per path:
|
|
1173
|
+
|
|
1174
|
+
```typescript
|
|
1175
|
+
const parser = new QueryParser({
|
|
1176
|
+
schema: ProductModel.schema,
|
|
1177
|
+
fieldTypes: {
|
|
1178
|
+
"address.zip": "string", // override a Mongoose path
|
|
1179
|
+
legacyCount: "number", // declare a non-schema field
|
|
1180
|
+
},
|
|
1181
|
+
});
|
|
1182
|
+
```
|
|
1183
|
+
|
|
1184
|
+
Without either option, the parser falls back to a string-shape heuristic
|
|
1185
|
+
(numeric strings without leading zeros and ≤15 chars become numbers; ObjectId
|
|
1186
|
+
hex stays a string; `'true'`/`'false'` become booleans). The heuristic is
|
|
1187
|
+
safe but inherently lossy — schema-aware mode is strictly better.
|
|
1188
|
+
|
|
1064
1189
|
**Supported query patterns:**
|
|
1065
1190
|
|
|
1066
1191
|
```bash
|
|
@@ -1078,7 +1203,7 @@ GET /users?after=eyJfaWQiOi...&limit=20 # Cursor-based
|
|
|
1078
1203
|
# Sorting
|
|
1079
1204
|
GET /users?sort=-createdAt,name
|
|
1080
1205
|
|
|
1081
|
-
# Search (
|
|
1206
|
+
# Search (default: text index; or configure searchMode: 'regex' / 'auto')
|
|
1082
1207
|
GET /users?search=john
|
|
1083
1208
|
|
|
1084
1209
|
# Simple populate
|
|
@@ -129,7 +129,7 @@ var PaginationEngine = class {
|
|
|
129
129
|
* console.log(result.docs, result.total, result.hasNext);
|
|
130
130
|
*/
|
|
131
131
|
async paginate(options = {}) {
|
|
132
|
-
const { filters = {}, sort
|
|
132
|
+
const { filters = {}, sort, countFilters, page = 1, limit = this.config.defaultLimit, select, populate = [], lean = true, session, hint, maxTimeMS, countStrategy = "exact", readPreference, collation } = options;
|
|
133
133
|
const sanitizedPage = validatePage(page, this.config);
|
|
134
134
|
const sanitizedLimit = validateLimit(limit, this.config);
|
|
135
135
|
const skip = calculateSkip(sanitizedPage, sanitizedLimit);
|
|
@@ -137,7 +137,8 @@ var PaginationEngine = class {
|
|
|
137
137
|
let query = this.Model.find(filters);
|
|
138
138
|
if (select) query = query.select(select);
|
|
139
139
|
if (populate && (Array.isArray(populate) ? populate.length : populate)) query = query.populate(populate);
|
|
140
|
-
query = query.sort(sort)
|
|
140
|
+
if (sort) query = query.sort(sort);
|
|
141
|
+
query = query.skip(skip).limit(fetchLimit).lean(lean);
|
|
141
142
|
if (collation) query = query.collation(collation);
|
|
142
143
|
if (session) query = query.session(session);
|
|
143
144
|
if (hint) query = query.hint(hint);
|
|
@@ -149,7 +150,8 @@ var PaginationEngine = class {
|
|
|
149
150
|
if ((countStrategy === "estimated" || useEstimated) && !hasFilters) countPromise = this.Model.estimatedDocumentCount();
|
|
150
151
|
else if (countStrategy === "none") countPromise = Promise.resolve(0);
|
|
151
152
|
else {
|
|
152
|
-
const
|
|
153
|
+
const countTarget = countFilters ?? filters;
|
|
154
|
+
const countQuery = this.Model.countDocuments(countTarget).session(session ?? null);
|
|
153
155
|
if (hint) countQuery.hint(hint);
|
|
154
156
|
if (maxTimeMS) countQuery.maxTimeMS(maxTimeMS);
|
|
155
157
|
if (readPreference) countQuery.read(readPreference);
|
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-Buj7P006.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,106 @@
|
|
|
1
|
+
//#region src/query/primitives/coercion.d.ts
|
|
2
|
+
/**
|
|
3
|
+
* Value coercion primitives
|
|
4
|
+
*
|
|
5
|
+
* Pure functions that convert raw URL-decoded values into typed values
|
|
6
|
+
* suitable for MongoDB queries. Two layers:
|
|
7
|
+
*
|
|
8
|
+
* 1. `coerceHeuristic(value)` — string-shape based, used when no schema
|
|
9
|
+
* is configured. Safe defaults: rejects leading zeros, scientific
|
|
10
|
+
* notation, and strings >15 chars to preserve zip codes, phone codes,
|
|
11
|
+
* and long numeric IDs that exceed JS safe-integer precision.
|
|
12
|
+
*
|
|
13
|
+
* 2. `coerceToType(value, type)` — type-directed, used when a Mongoose
|
|
14
|
+
* schema or `fieldTypes` map declares the field's type. Strictly
|
|
15
|
+
* better than the heuristic when type information is available.
|
|
16
|
+
*
|
|
17
|
+
* QueryParser composes these via `coerceFieldValue(field, value, types)`
|
|
18
|
+
* which prefers the type-directed path and falls back to the heuristic.
|
|
19
|
+
*
|
|
20
|
+
* Field-type extraction from a Mongoose schema is also here so the
|
|
21
|
+
* normalization logic lives next to the coercion that consumes it.
|
|
22
|
+
*/
|
|
23
|
+
/** Normalized field type used for schema-aware coercion */
|
|
24
|
+
type FieldType = 'string' | 'number' | 'boolean' | 'date' | 'objectid' | 'mixed';
|
|
25
|
+
/**
|
|
26
|
+
* Minimal structural type for a Mongoose schema (read-only `.paths`).
|
|
27
|
+
* Mongoose stores array element types in two different shadow properties
|
|
28
|
+
* depending on version and declaration style:
|
|
29
|
+
* - `caster.instance` — older / some array forms
|
|
30
|
+
* - `embeddedSchemaType.instance` — Mongoose 8+, both `[Type]` and `[{ type: Type }]`
|
|
31
|
+
* We read both and prefer whichever is populated.
|
|
32
|
+
*/
|
|
33
|
+
interface SchemaPathsLike {
|
|
34
|
+
paths: Record<string, {
|
|
35
|
+
instance?: string;
|
|
36
|
+
caster?: {
|
|
37
|
+
instance?: string;
|
|
38
|
+
};
|
|
39
|
+
embeddedSchemaType?: {
|
|
40
|
+
instance?: string;
|
|
41
|
+
};
|
|
42
|
+
}>;
|
|
43
|
+
}
|
|
44
|
+
/**
|
|
45
|
+
* Map a Mongoose `SchemaType.instance` string to our normalized FieldType.
|
|
46
|
+
* For arrays (`type: [Number]` or `type: [{ type: Number }]`), Mongoose
|
|
47
|
+
* stores the element type on `embeddedSchemaType.instance` (Mongoose 8+) or
|
|
48
|
+
* `caster.instance` (older). We probe both — element-level coercion is what
|
|
49
|
+
* `[in]`/`[nin]` operators need against typed arrays.
|
|
50
|
+
*
|
|
51
|
+
* Returns null for paths we cannot classify (embedded documents handled by
|
|
52
|
+
* their own nested paths).
|
|
53
|
+
*/
|
|
54
|
+
declare function normalizeMongooseType(schemaType: {
|
|
55
|
+
instance?: string;
|
|
56
|
+
caster?: {
|
|
57
|
+
instance?: string;
|
|
58
|
+
};
|
|
59
|
+
embeddedSchemaType?: {
|
|
60
|
+
instance?: string;
|
|
61
|
+
};
|
|
62
|
+
}): FieldType | null;
|
|
63
|
+
/**
|
|
64
|
+
* Build a normalized field-type map from a Mongoose schema and an optional
|
|
65
|
+
* override map. The override wins on a per-path basis. Paths with unmappable
|
|
66
|
+
* types are silently skipped — `coerceFieldValue` will fall back to the
|
|
67
|
+
* heuristic for them.
|
|
68
|
+
*/
|
|
69
|
+
declare function buildFieldTypeMap(schema?: SchemaPathsLike | null, overrides?: Record<string, FieldType>): Map<string, FieldType>;
|
|
70
|
+
/**
|
|
71
|
+
* String-shape heuristic — used when no field type is known.
|
|
72
|
+
*
|
|
73
|
+
* Rules (deliberately conservative — silent miscoercion is worse than
|
|
74
|
+
* leaving a string):
|
|
75
|
+
* - `null`/`undefined` pass through
|
|
76
|
+
* - Already-typed primitives (number, boolean) pass through
|
|
77
|
+
* - Arrays recurse element-wise
|
|
78
|
+
* - Objects pass through (filter operator objects, etc.)
|
|
79
|
+
* - `'true'`/`'false'` → boolean
|
|
80
|
+
* - 24-char hex → kept as string (ObjectId)
|
|
81
|
+
* - Strings 1–15 chars matching `^-?(0|[1-9]\d*)(\.\d+)?$` → number
|
|
82
|
+
* (rejects leading zeros, scientific notation, hex/octal, NaN, Infinity)
|
|
83
|
+
* - Everything else stays a string
|
|
84
|
+
*/
|
|
85
|
+
declare function coerceHeuristic(value: unknown): unknown;
|
|
86
|
+
/**
|
|
87
|
+
* Type-directed coercion — used when a field's declared type is known.
|
|
88
|
+
*
|
|
89
|
+
* Returns the original value unchanged when coercion is impossible
|
|
90
|
+
* (invalid date, non-numeric string for a Number field) — better to surface
|
|
91
|
+
* a no-match than to silently produce `Invalid Date` or `NaN` which MongoDB
|
|
92
|
+
* treats as legitimate query values.
|
|
93
|
+
*/
|
|
94
|
+
declare function coerceToType(value: unknown, type: FieldType): unknown;
|
|
95
|
+
/**
|
|
96
|
+
* Field-aware coercion. Looks up `field` in `types` and uses
|
|
97
|
+
* `coerceToType` when found, otherwise falls back to `coerceHeuristic`.
|
|
98
|
+
*
|
|
99
|
+
* This is the single choke point QueryParser uses for typed coercion of
|
|
100
|
+
* direct equality, `[eq]`, `[in]`, `[nin]`, `[gt]`/`[gte]`/`[lt]`/`[lte]`
|
|
101
|
+
* (the last only when a type is declared — see QueryParser for the
|
|
102
|
+
* preserves-pre-3.5.5-behavior fallback).
|
|
103
|
+
*/
|
|
104
|
+
declare function coerceFieldValue(field: string, value: unknown, types: Map<string, FieldType>): unknown;
|
|
105
|
+
//#endregion
|
|
106
|
+
export { coerceHeuristic as a, coerceFieldValue as i, SchemaPathsLike as n, coerceToType as o, buildFieldTypeMap as r, normalizeMongooseType as s, FieldType 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-CWUL0yiw.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,8 +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-CWUL0yiw.mjs";
|
|
2
|
+
import { t as index_d_exports } from "./index-Buj7P006.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 {
|
|
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-Dn41aAbK.mjs";
|
|
5
|
+
import { n as SchemaPathsLike, t as FieldType$1 } from "./coercion-01tEHsKF.mjs";
|
|
6
|
+
import { n as SchemaIndexes } from "./indexes-CiIT-Zli.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-BlDfbg_0.mjs";
|
|
6
8
|
import * as _$mongoose from "mongoose";
|
|
7
9
|
import { ClientSession, Expression, Model, PipelineStage, PopulateOptions } from "mongoose";
|
|
8
10
|
|
|
@@ -487,6 +489,22 @@ interface ParsedQuery {
|
|
|
487
489
|
}
|
|
488
490
|
/** Search mode for query parser */
|
|
489
491
|
type SearchMode = 'text' | 'regex';
|
|
492
|
+
/**
|
|
493
|
+
* Normalized field type used for schema-aware value coercion. Re-exported
|
|
494
|
+
* from `primitives/coercion` so the public QueryParser API stays unchanged
|
|
495
|
+
* while the actual logic lives in a single, unit-tested primitive module.
|
|
496
|
+
*/
|
|
497
|
+
type FieldType = FieldType$1;
|
|
498
|
+
/**
|
|
499
|
+
* Minimal structural type for a Mongoose schema. We only read `.paths` and
|
|
500
|
+
* (optionally) `.indexes()`, so the parser stays decoupled from a specific
|
|
501
|
+
* Mongoose major version and is easy to mock in tests. Re-exported from the
|
|
502
|
+
* primitives module — the canonical definition lives there.
|
|
503
|
+
*/
|
|
504
|
+
interface SchemaLike extends SchemaPathsLike {
|
|
505
|
+
/** Optional — when present, schema indexes are introspected for geo/text fields */
|
|
506
|
+
indexes?: () => Array<[Record<string, unknown>, Record<string, unknown>?]>;
|
|
507
|
+
}
|
|
490
508
|
interface QueryParserOptions {
|
|
491
509
|
/** Maximum allowed regex pattern length (default: 500) */
|
|
492
510
|
maxRegexLength?: number;
|
|
@@ -534,6 +552,25 @@ interface QueryParserOptions {
|
|
|
534
552
|
* @example ['eq', 'ne', 'gt', 'gte', 'lt', 'lte', 'in']
|
|
535
553
|
*/
|
|
536
554
|
allowedOperators?: string[];
|
|
555
|
+
/**
|
|
556
|
+
* Mongoose schema (or schema-like object exposing `.paths`) used for
|
|
557
|
+
* authoritative, schema-aware value coercion. When provided, filter values
|
|
558
|
+
* are coerced to the declared field type instead of guessed from the
|
|
559
|
+
* string shape — `?stock=50` becomes a number against a `Number` field but
|
|
560
|
+
* `?name=12345` stays a string against a `String` field. Nested paths like
|
|
561
|
+
* `address.zip` are looked up via dot-notation, matching Mongoose's
|
|
562
|
+
* `schema.paths` reflection. Unknown fields fall through to the heuristic.
|
|
563
|
+
*/
|
|
564
|
+
schema?: SchemaLike;
|
|
565
|
+
/**
|
|
566
|
+
* Plain field-type map used for authoritative coercion when no Mongoose
|
|
567
|
+
* schema is available (raw MongoDB, Prisma, computed fields, upstream
|
|
568
|
+
* models you don't own). Takes precedence over `schema` for paths declared
|
|
569
|
+
* in both — useful for runtime overrides. Use dot-notation for nested
|
|
570
|
+
* paths (`'address.zip': 'string'`).
|
|
571
|
+
* @example { stock: 'number', active: 'boolean', releasedAt: 'date' }
|
|
572
|
+
*/
|
|
573
|
+
fieldTypes?: Record<string, FieldType>;
|
|
537
574
|
}
|
|
538
575
|
/**
|
|
539
576
|
* Modern Query Parser
|
|
@@ -543,6 +580,21 @@ declare class QueryParser {
|
|
|
543
580
|
private readonly options;
|
|
544
581
|
private readonly operators;
|
|
545
582
|
private readonly dangerousOperators;
|
|
583
|
+
/**
|
|
584
|
+
* Normalized dot-notation field-type map. Built once at construction from
|
|
585
|
+
* `options.schema` (Mongoose) and `options.fieldTypes` (override map), with
|
|
586
|
+
* `fieldTypes` taking precedence. An empty map means schema-aware coercion
|
|
587
|
+
* is disabled and the heuristic in `_convertValue` runs unchanged — this
|
|
588
|
+
* preserves backwards compatibility for callers that don't opt in.
|
|
589
|
+
*/
|
|
590
|
+
private readonly _fieldTypes;
|
|
591
|
+
/**
|
|
592
|
+
* Structured schema-index info (geo / text / other), built once from
|
|
593
|
+
* `options.schema?.indexes()`. Used by the operator router to validate
|
|
594
|
+
* geo operators against actual geo-indexed fields, and exposed publicly
|
|
595
|
+
* via `parser.schemaIndexes` for downstream tools (Arc MCP, query planners).
|
|
596
|
+
*/
|
|
597
|
+
private readonly _schemaIndexes;
|
|
546
598
|
/**
|
|
547
599
|
* Regex patterns that can cause catastrophic backtracking (ReDoS attacks)
|
|
548
600
|
* Detects:
|
|
@@ -554,6 +606,16 @@ declare class QueryParser {
|
|
|
554
606
|
*/
|
|
555
607
|
private readonly dangerousRegexPatterns;
|
|
556
608
|
constructor(options?: QueryParserOptions);
|
|
609
|
+
/**
|
|
610
|
+
* Structured view of the configured schema's indexes — geo fields, text
|
|
611
|
+
* fields, and other compound indexes. Empty arrays when no schema was
|
|
612
|
+
* provided. Stable across the parser's lifetime; mutating the returned
|
|
613
|
+
* object does not affect parser behavior.
|
|
614
|
+
*
|
|
615
|
+
* Useful for downstream tooling (Arc MCP, query planners, doc generators)
|
|
616
|
+
* that needs to know which fields support which query types.
|
|
617
|
+
*/
|
|
618
|
+
get schemaIndexes(): SchemaIndexes;
|
|
557
619
|
/**
|
|
558
620
|
* Get the configured allowed filter fields.
|
|
559
621
|
* Returns `undefined` if no whitelist is set (all fields allowed).
|
|
@@ -738,7 +800,6 @@ declare class QueryParser {
|
|
|
738
800
|
* // ]
|
|
739
801
|
*/
|
|
740
802
|
private _buildRegexSearch;
|
|
741
|
-
private _convertValue;
|
|
742
803
|
private _parseOr;
|
|
743
804
|
private _enhanceWithBetween;
|
|
744
805
|
private _pluralize;
|
|
@@ -774,6 +835,8 @@ declare class Repository<TDoc = unknown> {
|
|
|
774
835
|
readonly _pagination: PaginationEngine<TDoc>;
|
|
775
836
|
private readonly _hookMode;
|
|
776
837
|
readonly idField: string;
|
|
838
|
+
readonly searchMode: 'text' | 'regex' | 'auto';
|
|
839
|
+
readonly searchFields: string[] | undefined;
|
|
777
840
|
[key: string]: unknown;
|
|
778
841
|
private _hasTextIndex;
|
|
779
842
|
constructor(Model: Model<TDoc, any, any, any>, plugins?: PluginType[], paginationConfig?: PaginationConfig, options?: RepositoryOptions);
|
|
@@ -1075,4 +1138,4 @@ declare class Repository<TDoc = unknown> {
|
|
|
1075
1138
|
*/
|
|
1076
1139
|
declare function createRepository<TDoc>(Model: _$mongoose.Model<TDoc, any, any, any>, plugins?: PluginType[], paginationConfig?: PaginationConfig, options?: RepositoryOptions): Repository<TDoc>;
|
|
1077
1140
|
//#endregion
|
|
1078
|
-
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 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 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 };
|
|
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 };
|