@classytic/mongokit 3.6.3 → 3.7.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/dist/{PaginationEngine-CunXkR9p.mjs → PaginationEngine-CPmZv7Ds.mjs} +8 -5
- package/dist/actions/index.d.mts +1 -1
- package/dist/actions/index.mjs +1 -1
- package/dist/ai/index.d.mts +23 -1
- package/dist/ai/index.mjs +194 -12
- package/dist/{cursor-CHToazHy.mjs → cursor-DZ9JSoMM.mjs} +11 -7
- package/dist/error-Lw9GEAro.mjs +46 -0
- package/dist/{index-BSRSsRRx.d.mts → index-C-qZUqv8.d.mts} +1 -1
- package/dist/index.d.mts +31 -9
- package/dist/index.mjs +53 -12
- package/dist/logger-DJ7egMnd.mjs +30 -0
- package/dist/{mongooseToJsonSchema-MlaD3C0B.mjs → mongooseToJsonSchema-DUwXPStK.mjs} +25 -21
- package/dist/{mongooseToJsonSchema-D2YjHo7W.d.mts → mongooseToJsonSchema-Du-UopRK.d.mts} +18 -2
- package/dist/pagination/PaginationEngine.d.mts +3 -1
- package/dist/pagination/PaginationEngine.mjs +1 -1
- package/dist/plugins/index.d.mts +2 -2
- package/dist/plugins/index.mjs +2 -2
- package/dist/query/primitives/coercion.d.mts +1 -1
- package/dist/query/primitives/coercion.mjs +1 -1
- package/dist/query/primitives/indexes.d.mts +1 -1
- package/dist/{sort-C-BJEWUZ.mjs → sort-ffe-9JBg.mjs} +19 -4
- package/dist/{types-DiQfDesD.d.mts → types-BgdeBXI1.d.mts} +68 -0
- package/dist/{update-AVfKWNGt.mjs → update-BDsQ3cdy.mjs} +2 -1
- package/dist/utils/index.d.mts +2 -2
- package/dist/utils/index.mjs +5 -4
- package/dist/{validation-chain.plugin-BsFzKVnO.d.mts → validation-chain.plugin-Be9rG04B.d.mts} +25 -2
- package/dist/{validation-chain.plugin-7A5qGEQq.mjs → validation-chain.plugin-CEyJssZl.mjs} +129 -17
- package/package.json +8 -3
- package/dist/error-Bpbi_NKo.mjs +0 -63
- /package/dist/{coercion-B19MD38s.d.mts → coercion-oM8G4b6m.d.mts} +0 -0
- /package/dist/{field-selection-C5o7jyyA.mjs → field-selection-dI0m4RBs.mjs} +0 -0
- /package/dist/{id-resolution-LZ-cCwR5.mjs → id-resolution-e4BT9zAV.mjs} +0 -0
- /package/dist/{indexes-qIBCZ3mY.d.mts → indexes-C26GNZRU.d.mts} +0 -0
|
@@ -1,6 +1,7 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
1
|
+
import { r as warn } from "./logger-DJ7egMnd.mjs";
|
|
2
|
+
import { t as createError } from "./error-Lw9GEAro.mjs";
|
|
3
|
+
import { n as encodeCursor, r as resolveCursorFilter } from "./cursor-DZ9JSoMM.mjs";
|
|
4
|
+
import { r as validateKeysetSort, t as getPrimaryField } from "./sort-ffe-9JBg.mjs";
|
|
4
5
|
//#region src/pagination/utils/index-hint.ts
|
|
5
6
|
/**
|
|
6
7
|
* Read a Mongoose schema's declared indexes, defensively.
|
|
@@ -197,6 +198,8 @@ var PaginationEngine = class {
|
|
|
197
198
|
maxPage: config.maxPage ?? 1e4,
|
|
198
199
|
deepPageThreshold: config.deepPageThreshold ?? 100,
|
|
199
200
|
cursorVersion: config.cursorVersion ?? 1,
|
|
201
|
+
minCursorVersion: config.minCursorVersion ?? 1,
|
|
202
|
+
strictKeysetSortFields: config.strictKeysetSortFields,
|
|
200
203
|
useEstimatedCount: config.useEstimatedCount ?? false
|
|
201
204
|
};
|
|
202
205
|
}
|
|
@@ -298,7 +301,7 @@ var PaginationEngine = class {
|
|
|
298
301
|
const { filters = {}, sort, after, limit = this.config.defaultLimit, select, populate = [], lean = true, session, hint, maxTimeMS, readPreference, collation } = options;
|
|
299
302
|
if (!sort) throw createError(400, "sort is required for keyset pagination");
|
|
300
303
|
const sanitizedLimit = validateLimit(limit, this.config);
|
|
301
|
-
const normalizedSort = validateKeysetSort(sort);
|
|
304
|
+
const normalizedSort = validateKeysetSort(sort, this.config.strictKeysetSortFields);
|
|
302
305
|
const sortWithoutIdTail = stripTrailingIdTiebreaker(normalizedSort);
|
|
303
306
|
const filterKeys = Object.keys(filters).filter((k) => !k.startsWith("$"));
|
|
304
307
|
const effectiveSortFields = Object.keys(sortWithoutIdTail);
|
|
@@ -307,7 +310,7 @@ var PaginationEngine = class {
|
|
|
307
310
|
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.)`);
|
|
308
311
|
}
|
|
309
312
|
let query = { ...filters };
|
|
310
|
-
if (after) query = resolveCursorFilter(after, normalizedSort, this.config.cursorVersion, query);
|
|
313
|
+
if (after) query = resolveCursorFilter(after, normalizedSort, this.config.cursorVersion, query, this.config.minCursorVersion);
|
|
311
314
|
const effectiveSelect = ensureKeysetSelectIncludesCursorFields(select, normalizedSort);
|
|
312
315
|
let mongoQuery = this.Model.find(query);
|
|
313
316
|
if (effectiveSelect) mongoQuery = mongoQuery.select(effectiveSelect);
|
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-C-qZUqv8.mjs";
|
|
2
2
|
export { aggregate_d_exports as aggregate, create_d_exports as create, delete_d_exports as deleteActions, read_d_exports as read, update_d_exports as update };
|
package/dist/actions/index.mjs
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { t as __exportAll } from "../chunk-CfYAbeIz.mjs";
|
|
2
|
-
import { _ as aggregate_exports, f as delete_exports, h as create_exports, l as read_exports, r as update_exports } from "../update-
|
|
2
|
+
import { _ as aggregate_exports, f as delete_exports, h as create_exports, l as read_exports, r as update_exports } from "../update-BDsQ3cdy.mjs";
|
|
3
3
|
//#region src/actions/index.ts
|
|
4
4
|
var actions_exports = /* @__PURE__ */ __exportAll({
|
|
5
5
|
aggregate: () => aggregate_exports,
|
package/dist/ai/index.d.mts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { J as Plugin } from "../types-
|
|
1
|
+
import { J as Plugin } from "../types-BgdeBXI1.mjs";
|
|
2
2
|
import { ClientSession, PipelineStage } from "mongoose";
|
|
3
3
|
|
|
4
4
|
//#region src/ai/types.d.ts
|
|
@@ -106,6 +106,28 @@ interface VectorPluginOptions {
|
|
|
106
106
|
* If not provided, the error propagates and blocks the write.
|
|
107
107
|
*/
|
|
108
108
|
onEmbedError?: (error: Error, doc: unknown) => void;
|
|
109
|
+
/**
|
|
110
|
+
* SSRF defense for media URLs (`image`, `audio`, entries in `media`).
|
|
111
|
+
*
|
|
112
|
+
* If set, only URLs whose origin (`scheme://host[:port]`) matches one of
|
|
113
|
+
* these entries are forwarded to `embedFn`. Entries can be exact origins
|
|
114
|
+
* (`https://cdn.example.com`) or wildcard hosts (`https://*.example.com`).
|
|
115
|
+
* When the allowlist is active, URLs failing validation are dropped with a
|
|
116
|
+
* warning and the doc is embedded without them (never passed to embedFn).
|
|
117
|
+
*
|
|
118
|
+
* Undefined (default) = no allowlist check — same as prior behavior.
|
|
119
|
+
*/
|
|
120
|
+
allowedMediaOrigins?: string[];
|
|
121
|
+
/**
|
|
122
|
+
* When true, reject URLs that resolve to a private, loopback, or
|
|
123
|
+
* link-local IP literal (e.g., `http://169.254.169.254/…` cloud metadata,
|
|
124
|
+
* `http://127.0.0.1`, RFC1918 addresses). Hostnames that later resolve to
|
|
125
|
+
* private IPs via DNS are NOT caught here — that rebinding class of SSRF
|
|
126
|
+
* must be handled in your network/egress layer.
|
|
127
|
+
*
|
|
128
|
+
* Default: `false` (legacy behavior). Flip to `true` for production setups.
|
|
129
|
+
*/
|
|
130
|
+
blockPrivateIpUrls?: boolean;
|
|
109
131
|
}
|
|
110
132
|
//#endregion
|
|
111
133
|
//#region src/ai/vector.plugin.d.ts
|
package/dist/ai/index.mjs
CHANGED
|
@@ -1,3 +1,163 @@
|
|
|
1
|
+
import { r as warn } from "../logger-DJ7egMnd.mjs";
|
|
2
|
+
//#region src/ai/url-policy.ts
|
|
3
|
+
/**
|
|
4
|
+
* URL policy helpers for the vector plugin media pipeline.
|
|
5
|
+
*
|
|
6
|
+
* Protects callers from passing hostile document URLs straight into an
|
|
7
|
+
* embedding service that may fetch them. The policy is pure / side-effect-
|
|
8
|
+
* free so it can be reused by anyone composing their own embed pipeline.
|
|
9
|
+
*/
|
|
10
|
+
/**
|
|
11
|
+
* Returns true when the string is a safe media URL under the given policy.
|
|
12
|
+
*
|
|
13
|
+
* - Non-URL strings (data URLs, base64 blobs, relative paths) are accepted —
|
|
14
|
+
* they never trigger an outbound HTTP fetch, so SSRF isn't a concern.
|
|
15
|
+
* - `data:` URLs are accepted.
|
|
16
|
+
* - `http` / `https` URLs must pass:
|
|
17
|
+
* a) origin allowlist (if `allowedOrigins` is set)
|
|
18
|
+
* b) private-IP rejection (if `blockPrivateIpUrls` is true)
|
|
19
|
+
*
|
|
20
|
+
* Any parse failure returns `true` only when strict mode is off — a string
|
|
21
|
+
* that doesn't parse as a URL cannot be used to SSRF either. In strict mode
|
|
22
|
+
* (either option set), unparseable http(s)-looking strings are rejected.
|
|
23
|
+
*/
|
|
24
|
+
function isMediaUrlAllowed(value, policy = {}) {
|
|
25
|
+
if (typeof value !== "string" || value.length === 0) return false;
|
|
26
|
+
if (value.startsWith("data:")) return true;
|
|
27
|
+
if (!/^https?:\/\//i.test(value)) return true;
|
|
28
|
+
let url;
|
|
29
|
+
try {
|
|
30
|
+
url = new URL(value);
|
|
31
|
+
} catch {
|
|
32
|
+
return false;
|
|
33
|
+
}
|
|
34
|
+
if (policy.blockPrivateIpUrls && isPrivateOrLocalHost(url.hostname)) return false;
|
|
35
|
+
if (policy.allowedOrigins && policy.allowedOrigins.length > 0) {
|
|
36
|
+
const origin = `${url.protocol}//${url.host}`;
|
|
37
|
+
if (!policy.allowedOrigins.some((entry) => matchesOriginEntry(origin, entry, url))) return false;
|
|
38
|
+
}
|
|
39
|
+
return true;
|
|
40
|
+
}
|
|
41
|
+
function matchesOriginEntry(origin, entry, url) {
|
|
42
|
+
if (!entry) return false;
|
|
43
|
+
if (entry === origin) return true;
|
|
44
|
+
const wildcardMatch = entry.match(/^(https?:)\/\/\*\.(.+)$/i);
|
|
45
|
+
if (wildcardMatch) {
|
|
46
|
+
const [, entryProtocol, suffix] = wildcardMatch;
|
|
47
|
+
if (url.protocol.toLowerCase() !== entryProtocol.toLowerCase()) return false;
|
|
48
|
+
return url.hostname.toLowerCase().endsWith("." + suffix.toLowerCase());
|
|
49
|
+
}
|
|
50
|
+
return false;
|
|
51
|
+
}
|
|
52
|
+
/**
|
|
53
|
+
* Literal-IP private/loopback/link-local checks. Does NOT perform DNS
|
|
54
|
+
* resolution — callers who need rebinding-proof behavior must handle that
|
|
55
|
+
* at the HTTP layer.
|
|
56
|
+
*/
|
|
57
|
+
function isPrivateOrLocalHost(hostname) {
|
|
58
|
+
const h = hostname.toLowerCase().replace(/^\[|\]$/g, "");
|
|
59
|
+
if (h === "::1" || h.startsWith("fe80:") || h.startsWith("fc") || h.startsWith("fd")) return true;
|
|
60
|
+
if (h === "localhost" || h === "localhost.localdomain") return true;
|
|
61
|
+
const ipv4 = h.match(/^(\d{1,3})\.(\d{1,3})\.(\d{1,3})\.(\d{1,3})$/);
|
|
62
|
+
if (!ipv4) return false;
|
|
63
|
+
const octets = ipv4.slice(1).map(Number);
|
|
64
|
+
if (octets.some((o) => o < 0 || o > 255)) return false;
|
|
65
|
+
const [a, b] = octets;
|
|
66
|
+
if (a === 10) return true;
|
|
67
|
+
if (a === 127) return true;
|
|
68
|
+
if (a === 169 && b === 254) return true;
|
|
69
|
+
if (a === 172 && b >= 16 && b <= 31) return true;
|
|
70
|
+
if (a === 192 && b === 168) return true;
|
|
71
|
+
if (a === 0) return true;
|
|
72
|
+
if (a === 100 && b >= 64 && b <= 127) return true;
|
|
73
|
+
return false;
|
|
74
|
+
}
|
|
75
|
+
//#endregion
|
|
76
|
+
//#region src/ai/vector-error-hints.ts
|
|
77
|
+
/**
|
|
78
|
+
* Pure classifier. Takes the raw error and the context the plugin knows
|
|
79
|
+
* (index name, dimensions, filter paths it tried to use) and returns a hint.
|
|
80
|
+
*
|
|
81
|
+
* Returns `{ code: 'UNKNOWN', ... }` when no pattern matches — callers
|
|
82
|
+
* should then fall back to rethrowing the original.
|
|
83
|
+
*/
|
|
84
|
+
function classifyVectorSearchError(err, ctx) {
|
|
85
|
+
const lower = extractErrorMessage(err).toLowerCase();
|
|
86
|
+
if (lower.includes("unrecognized pipeline stage name: '$vectorsearch'") || lower.includes("unrecognized pipeline stage name: \"$vectorsearch\"") || lower.includes("$vectorsearch is only supported") || lower.includes("$vectorsearch stage is only allowed") || lower.includes("$vectorsearch is only allowed") || lower.includes("unknown top level operator: $vectorsearch") || lower.includes("$vectorsearch") && lower.includes("atlas") && (lower.includes("only") || lower.includes("require"))) return {
|
|
87
|
+
code: "NOT_ATLAS",
|
|
88
|
+
summary: "MongoDB did not recognize the `$vectorSearch` stage. This stage is Atlas-only — it doesn't exist on standalone MongoDB, self-hosted Community/Enterprise, or mongodb-memory-server.",
|
|
89
|
+
hints: [
|
|
90
|
+
"Run against MongoDB Atlas — create a cluster and point your app at its connection string.",
|
|
91
|
+
"If you're testing locally, use the integration suite that mocks `$vectorSearch` (see tests/integration/vector-*.test.ts) rather than calling `searchSimilar` directly.",
|
|
92
|
+
"Atlas Free tier (M0) supports Vector Search as of late 2024; older free tiers do not."
|
|
93
|
+
]
|
|
94
|
+
};
|
|
95
|
+
if (lower.includes("$vectorsearch") && lower.includes("index") || lower.includes("couldn't find index") || lower.includes("search index") && lower.includes("not found") || lower.includes("no such index") || lower.includes("index") && lower.includes(ctx.indexName.toLowerCase())) return {
|
|
96
|
+
code: "INDEX_NOT_FOUND",
|
|
97
|
+
summary: `Atlas reported the vector search index "${ctx.indexName}" is not available on the target collection.`,
|
|
98
|
+
hints: [
|
|
99
|
+
`Verify an index named "${ctx.indexName}" exists on the collection in the Atlas UI (Search → Indexes) or via \`db.collection.listSearchIndexes()\`.`,
|
|
100
|
+
`If you just created the index, wait until it reports \`queryable: true\`. Builds typically take 1–3 minutes on new clusters.`,
|
|
101
|
+
`The index's \`numDimensions\` must match your vector config (${ctx.dimensions}), and \`path\` must match the field name.`
|
|
102
|
+
]
|
|
103
|
+
};
|
|
104
|
+
if (lower.includes("not a supported filter field") || lower.includes("is not a filter field") || lower.includes("filter") && lower.includes("path") && lower.includes("not") || lower.includes("unknown filter path")) return {
|
|
105
|
+
code: "FILTER_FIELD_NOT_INDEXED",
|
|
106
|
+
summary: "Atlas rejected the `filter` clause because at least one of its paths is not declared as a `filter`-typed field in the vector search index.",
|
|
107
|
+
hints: [
|
|
108
|
+
`Add every path you filter on as \`{ type: "filter", path: "<field>" }\` in the index definition.`,
|
|
109
|
+
`Paths passed in this call: ${ctx.filterPaths?.length ? ctx.filterPaths.join(", ") : "(none declared)"}.`,
|
|
110
|
+
`Example for multi-tenant: index must include \`{ type: "filter", path: "tenantId" }\` when you call \`searchSimilar({ filter: { tenantId: "..." } })\`.`
|
|
111
|
+
]
|
|
112
|
+
};
|
|
113
|
+
if (lower.includes("dimension") && (lower.includes("mismatch") || lower.includes("expected"))) return {
|
|
114
|
+
code: "DIMENSION_MISMATCH",
|
|
115
|
+
summary: "Atlas rejected the query vector — its length does not match the index definition.",
|
|
116
|
+
hints: [`Your vectorPlugin config says \`dimensions: ${ctx.dimensions}\`. The Atlas index for "${ctx.indexName}" must declare the same \`numDimensions\`.`, `If the index was created with a different dimension count, re-create it with the correct value (indexes are immutable for dimensions).`]
|
|
117
|
+
};
|
|
118
|
+
if (lower.includes("vectorsearch") && (lower.includes("requires") || lower.includes("expected") || lower.includes("missing"))) return {
|
|
119
|
+
code: "MALFORMED_PIPELINE",
|
|
120
|
+
summary: "The `$vectorSearch` stage is missing a required argument. This is almost always a mongokit bug — please file an issue with the full error text.",
|
|
121
|
+
hints: ["Capture the original error (`err.cause`) and attach it to the bug report."]
|
|
122
|
+
};
|
|
123
|
+
return {
|
|
124
|
+
code: "UNKNOWN",
|
|
125
|
+
summary: "",
|
|
126
|
+
hints: []
|
|
127
|
+
};
|
|
128
|
+
}
|
|
129
|
+
/**
|
|
130
|
+
* Wrap an error-producing promise so known-recognizable failures become
|
|
131
|
+
* mongokit errors with hint context. On unrecognized errors, rethrows the
|
|
132
|
+
* original untouched.
|
|
133
|
+
*/
|
|
134
|
+
async function withVectorErrorHints(op, ctx) {
|
|
135
|
+
try {
|
|
136
|
+
return await op();
|
|
137
|
+
} catch (err) {
|
|
138
|
+
const hint = classifyVectorSearchError(err, ctx);
|
|
139
|
+
if (hint.code === "UNKNOWN") throw err;
|
|
140
|
+
const message = `[mongokit:vector] ${hint.summary}\n` + hint.hints.map((h) => ` • ${h}`).join("\n");
|
|
141
|
+
const wrapped = new Error(message, { cause: err });
|
|
142
|
+
wrapped.code = hint.code;
|
|
143
|
+
throw wrapped;
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
function extractErrorMessage(err) {
|
|
147
|
+
if (typeof err === "string") return err;
|
|
148
|
+
if (err && typeof err === "object") {
|
|
149
|
+
const e = err;
|
|
150
|
+
if (typeof e.message === "string") return e.message;
|
|
151
|
+
if (typeof e.errmsg === "string") return e.errmsg;
|
|
152
|
+
try {
|
|
153
|
+
return JSON.stringify(err);
|
|
154
|
+
} catch {
|
|
155
|
+
return String(err);
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
return String(err);
|
|
159
|
+
}
|
|
160
|
+
//#endregion
|
|
1
161
|
//#region src/ai/vector.plugin.ts
|
|
2
162
|
/** Maximum numCandidates allowed by Atlas Vector Search */
|
|
3
163
|
const MAX_NUM_CANDIDATES = 1e4;
|
|
@@ -28,23 +188,35 @@ function getNestedValue(obj, path) {
|
|
|
28
188
|
}, obj);
|
|
29
189
|
}
|
|
30
190
|
/**
|
|
31
|
-
* Builds EmbeddingInput from document source fields
|
|
191
|
+
* Builds EmbeddingInput from document source fields.
|
|
192
|
+
*
|
|
193
|
+
* `urlPolicy` is applied to every media value that looks like an http(s)
|
|
194
|
+
* URL. Values that fail the policy are silently dropped (with a warn log)
|
|
195
|
+
* — never forwarded to the embedding service. Non-URL strings (base64,
|
|
196
|
+
* data URLs, file paths) are untouched.
|
|
32
197
|
*/
|
|
33
|
-
function buildInputFromDoc(data, field) {
|
|
198
|
+
function buildInputFromDoc(data, field, urlPolicy = {}) {
|
|
34
199
|
const input = {};
|
|
35
200
|
if (field.sourceFields?.length) {
|
|
36
201
|
const text = field.sourceFields.map((f) => getNestedValue(data, f)).filter(Boolean).join(" ");
|
|
37
202
|
if (text.trim()) input.text = text;
|
|
38
203
|
}
|
|
204
|
+
const policyActive = urlPolicy.allowedOrigins && urlPolicy.allowedOrigins.length > 0 || urlPolicy.blockPrivateIpUrls === true;
|
|
205
|
+
const screenMediaValue = (mf, value) => {
|
|
206
|
+
if (!policyActive) return value;
|
|
207
|
+
if (typeof value !== "string") return value;
|
|
208
|
+
if (isMediaUrlAllowed(value, urlPolicy)) return value;
|
|
209
|
+
warn(`[mongokit] vectorPlugin: blocked media URL in field "${mf}" by URL policy`);
|
|
210
|
+
};
|
|
39
211
|
if (field.mediaFields?.length) {
|
|
40
212
|
const firstImageField = field.mediaFields[0];
|
|
41
|
-
const
|
|
42
|
-
if (typeof
|
|
213
|
+
const screenedImage = screenMediaValue(firstImageField, getNestedValue(data, firstImageField));
|
|
214
|
+
if (typeof screenedImage === "string") input.image = screenedImage;
|
|
43
215
|
if (field.mediaFields.length > 1) {
|
|
44
216
|
input.media = {};
|
|
45
217
|
for (const mf of field.mediaFields) {
|
|
46
|
-
const
|
|
47
|
-
if (
|
|
218
|
+
const screened = screenMediaValue(mf, getNestedValue(data, mf));
|
|
219
|
+
if (screened != null) input.media[mf] = screened;
|
|
48
220
|
}
|
|
49
221
|
}
|
|
50
222
|
}
|
|
@@ -88,7 +260,11 @@ function buildVectorSearchPipeline(field, queryVector, params) {
|
|
|
88
260
|
function vectorPlugin(options) {
|
|
89
261
|
const { fields, autoEmbed = false } = options;
|
|
90
262
|
if (!fields?.length) throw new Error("[mongokit] vectorPlugin requires at least one field config");
|
|
91
|
-
const { embedFn, batchEmbedFn } = options;
|
|
263
|
+
const { embedFn, batchEmbedFn, allowedMediaOrigins, blockPrivateIpUrls } = options;
|
|
264
|
+
const urlPolicy = {
|
|
265
|
+
allowedOrigins: allowedMediaOrigins,
|
|
266
|
+
blockPrivateIpUrls
|
|
267
|
+
};
|
|
92
268
|
return {
|
|
93
269
|
name: "vector",
|
|
94
270
|
apply(repo) {
|
|
@@ -105,7 +281,11 @@ function vectorPlugin(options) {
|
|
|
105
281
|
const pipeline = buildVectorSearchPipeline(field, queryVector, params);
|
|
106
282
|
const agg = repo.Model.aggregate(pipeline);
|
|
107
283
|
if (params.session) agg.session(params.session);
|
|
108
|
-
return (await agg.exec()
|
|
284
|
+
return (await withVectorErrorHints(() => agg.exec(), {
|
|
285
|
+
indexName: field.index,
|
|
286
|
+
dimensions: field.dimensions,
|
|
287
|
+
filterPaths: params.filter ? Object.keys(params.filter) : void 0
|
|
288
|
+
})).map((doc) => {
|
|
109
289
|
const score = doc._score ?? 0;
|
|
110
290
|
const { _score, ...rest } = doc;
|
|
111
291
|
return {
|
|
@@ -133,7 +313,7 @@ function vectorPlugin(options) {
|
|
|
133
313
|
};
|
|
134
314
|
const embedFromSource = async (data, field) => {
|
|
135
315
|
if (data[field.path] && Array.isArray(data[field.path])) return;
|
|
136
|
-
const input = buildInputFromDoc(data, field);
|
|
316
|
+
const input = buildInputFromDoc(data, field, urlPolicy);
|
|
137
317
|
if (!hasContent(input)) return;
|
|
138
318
|
const vector = await safeEmbed(input, data);
|
|
139
319
|
if (vector) data[field.path] = vector;
|
|
@@ -143,7 +323,7 @@ function vectorPlugin(options) {
|
|
|
143
323
|
for (let i = 0; i < dataArray.length; i++) {
|
|
144
324
|
const data = dataArray[i];
|
|
145
325
|
if (data[field.path] && Array.isArray(data[field.path])) continue;
|
|
146
|
-
const input = buildInputFromDoc(data, field);
|
|
326
|
+
const input = buildInputFromDoc(data, field, urlPolicy);
|
|
147
327
|
if (hasContent(input)) toEmbed.push({
|
|
148
328
|
idx: i,
|
|
149
329
|
input
|
|
@@ -181,7 +361,9 @@ function vectorPlugin(options) {
|
|
|
181
361
|
return allFields.length > 0 && contextData && allFields.some((f) => f in contextData);
|
|
182
362
|
});
|
|
183
363
|
if (!fieldsToEmbed.length) return;
|
|
184
|
-
const
|
|
364
|
+
const idField = repo.idField || "_id";
|
|
365
|
+
const lookupQuery = idField === "_id" ? { _id: context.id } : { [idField]: context.id };
|
|
366
|
+
const existing = await repo.Model.findOne(lookupQuery).lean().session(context.session ?? null);
|
|
185
367
|
if (!existing) return;
|
|
186
368
|
for (const field of fieldsToEmbed) {
|
|
187
369
|
const merged = {
|
|
@@ -189,7 +371,7 @@ function vectorPlugin(options) {
|
|
|
189
371
|
...context.data
|
|
190
372
|
};
|
|
191
373
|
delete merged[field.path];
|
|
192
|
-
const input = buildInputFromDoc(merged, field);
|
|
374
|
+
const input = buildInputFromDoc(merged, field, urlPolicy);
|
|
193
375
|
if (!hasContent(input)) continue;
|
|
194
376
|
const vector = await safeEmbed(input, merged);
|
|
195
377
|
if (vector) context.data[field.path] = vector;
|
|
@@ -180,14 +180,18 @@ function validateCursorSort(cursorSort, currentSort) {
|
|
|
180
180
|
if (JSON.stringify(cursorSort) !== JSON.stringify(currentSort)) throw new Error("Cursor sort does not match current query sort");
|
|
181
181
|
}
|
|
182
182
|
/**
|
|
183
|
-
* Validates cursor version
|
|
183
|
+
* Validates cursor version against the server's expected range.
|
|
184
184
|
*
|
|
185
|
-
*
|
|
186
|
-
*
|
|
187
|
-
*
|
|
185
|
+
* - Cursors newer than `expectedVersion` are rejected (client ahead of server).
|
|
186
|
+
* - Cursors older than `minVersion` are rejected (client cached a cursor from
|
|
187
|
+
* a pre-breaking-change deploy). Default `minVersion = 1` keeps the legacy
|
|
188
|
+
* "accept anything <= expected" behavior; bump it when you ship a breaking
|
|
189
|
+
* cursor format change so old clients restart pagination cleanly instead of
|
|
190
|
+
* silently paginating from the wrong position.
|
|
188
191
|
*/
|
|
189
|
-
function validateCursorVersion(cursorVersion, expectedVersion) {
|
|
192
|
+
function validateCursorVersion(cursorVersion, expectedVersion, minVersion = 1) {
|
|
190
193
|
if (cursorVersion > expectedVersion) throw new Error(`Cursor version ${cursorVersion} is newer than expected version ${expectedVersion}. Please upgrade.`);
|
|
194
|
+
if (cursorVersion < minVersion) throw new Error(`Cursor version ${cursorVersion} is older than minimum supported ${minVersion}. Pagination must restart.`);
|
|
191
195
|
}
|
|
192
196
|
/**
|
|
193
197
|
* Serializes a value for cursor storage
|
|
@@ -232,7 +236,7 @@ function rehydrateValue(serialized, type) {
|
|
|
232
236
|
* - Base64-encoded cursor tokens (standard cursor)
|
|
233
237
|
* - Cursor version and sort validation
|
|
234
238
|
*/
|
|
235
|
-
function resolveCursorFilter(after, sort, cursorVersion, baseFilters = {}) {
|
|
239
|
+
function resolveCursorFilter(after, sort, cursorVersion, baseFilters = {}, minCursorVersion = 1) {
|
|
236
240
|
if (/^[a-f0-9]{24}$/i.test(after)) {
|
|
237
241
|
const objectId = new mongoose.Types.ObjectId(after);
|
|
238
242
|
const idOperator = (sort._id || -1) === 1 ? "$gt" : "$lt";
|
|
@@ -242,7 +246,7 @@ function resolveCursorFilter(after, sort, cursorVersion, baseFilters = {}) {
|
|
|
242
246
|
};
|
|
243
247
|
}
|
|
244
248
|
const cursor = decodeCursor(after);
|
|
245
|
-
validateCursorVersion(cursor.version, cursorVersion);
|
|
249
|
+
validateCursorVersion(cursor.version, cursorVersion, minCursorVersion);
|
|
246
250
|
validateCursorSort(cursor.sort, sort);
|
|
247
251
|
return buildKeysetFilter(baseFilters, sort, cursor.value, cursor.id, cursor.values);
|
|
248
252
|
}
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
//#region src/utils/error.ts
|
|
2
|
+
/**
|
|
3
|
+
* Creates an error with HTTP status code
|
|
4
|
+
*
|
|
5
|
+
* @param status - HTTP status code
|
|
6
|
+
* @param message - Error message
|
|
7
|
+
* @returns Error with status property
|
|
8
|
+
*
|
|
9
|
+
* @example
|
|
10
|
+
* throw createError(404, 'Document not found');
|
|
11
|
+
* throw createError(400, 'Invalid input');
|
|
12
|
+
* throw createError(403, 'Access denied');
|
|
13
|
+
*/
|
|
14
|
+
function createError(status, message) {
|
|
15
|
+
const error = new Error(message);
|
|
16
|
+
error.status = status;
|
|
17
|
+
return error;
|
|
18
|
+
}
|
|
19
|
+
/**
|
|
20
|
+
* Detect and convert a MongoDB E11000 duplicate-key error into
|
|
21
|
+
* a 409 HttpError with an actionable message.
|
|
22
|
+
*
|
|
23
|
+
* PII-safe by default: the error message lists only the conflicting field
|
|
24
|
+
* names, never the values. Structured field names are attached under
|
|
25
|
+
* `error.duplicate.fields` for downstream handlers. Pass
|
|
26
|
+
* `{ exposeValues: true }` to opt into including the values (dev or trusted
|
|
27
|
+
* server-to-server contexts only).
|
|
28
|
+
*
|
|
29
|
+
* Returns `null` when the error is not a duplicate-key error.
|
|
30
|
+
*/
|
|
31
|
+
function parseDuplicateKeyError(error, options = {}) {
|
|
32
|
+
if (!error || typeof error !== "object") return null;
|
|
33
|
+
const mongoErr = error;
|
|
34
|
+
if (mongoErr.code !== 11e3) return null;
|
|
35
|
+
const fields = mongoErr.keyPattern ? Object.keys(mongoErr.keyPattern) : [];
|
|
36
|
+
const exposed = options.exposeValues === true;
|
|
37
|
+
const valuesString = exposed && mongoErr.keyValue ? Object.entries(mongoErr.keyValue).map(([k, v]) => `${k}: ${JSON.stringify(v)}`).join(", ") : "";
|
|
38
|
+
const httpError = createError(409, fields.length ? `Duplicate value for ${fields.join(", ")}${valuesString ? ` (${valuesString})` : ""}` : "Duplicate key error");
|
|
39
|
+
httpError.duplicate = {
|
|
40
|
+
fields,
|
|
41
|
+
...exposed && mongoErr.keyValue ? { values: { ...mongoErr.keyValue } } : {}
|
|
42
|
+
};
|
|
43
|
+
return httpError;
|
|
44
|
+
}
|
|
45
|
+
//#endregion
|
|
46
|
+
export { parseDuplicateKeyError as n, createError 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-BgdeBXI1.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-BgdeBXI1.mjs";
|
|
2
|
+
import { t as index_d_exports } from "./index-C-qZUqv8.mjs";
|
|
3
3
|
import { PaginationEngine } from "./pagination/PaginationEngine.mjs";
|
|
4
|
-
import { A as
|
|
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 { $ as aggregateHelpersPlugin, A as PrefixedIdOptions, B as BatchOperationsMethods, C as methodRegistryPlugin, D as CustomIdOptions, E as elasticSearchPlugin, F as prefixedId, G as AuditQueryOptions, H as batchOperationsPlugin, I as sequentialId, J as AuditTrailOptions, K as AuditQueryResult, L as cascadePlugin, M as customIdPlugin, N as dateSequentialId, O as DateSequentialIdOptions, P as getNextSequence, Q as AggregateHelpersMethods, R as CacheMethods, T as ElasticSearchOptions, U as AuditEntry, V as BulkWriteResult, W as AuditOperation, X as auditTrailPlugin, Y as AuditTrailQuery, Z as auditLogPlugin, _ as observabilityPlugin, a as uniqueField, b as MongoOperationsMethods, c as TenantContext, d as SubdocumentMethods, f as subdocumentPlugin, g as OperationMetric, h as ObservabilityOptions, i as requireField, j as SequentialIdOptions, k as IdGenerator, l as TenantStore, m as softDeletePlugin, n as blockIf, o as validationChainPlugin, p as SoftDeleteMethods, q as AuditTrailMethods, r as immutableField, s as timestampPlugin, t as autoInject, u as createTenantContext, v as MultiTenantOptions, w as fieldFilterPlugin, x as mongoOperationsPlugin, y as multiTenantPlugin, z as cachePlugin } from "./validation-chain.plugin-Be9rG04B.mjs";
|
|
5
|
+
import { n as SchemaPathsLike, t as FieldType$1 } from "./coercion-oM8G4b6m.mjs";
|
|
6
|
+
import { n as SchemaIndexes } from "./indexes-C26GNZRU.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-Du-UopRK.mjs";
|
|
8
8
|
import * as _$mongoose from "mongoose";
|
|
9
9
|
import { ClientSession, Expression, Model, PipelineStage, PopulateOptions } from "mongoose";
|
|
10
10
|
|
|
@@ -596,15 +596,37 @@ declare class QueryParser {
|
|
|
596
596
|
*/
|
|
597
597
|
private readonly _schemaIndexes;
|
|
598
598
|
/**
|
|
599
|
-
* Regex patterns that can cause catastrophic backtracking (ReDoS attacks)
|
|
600
|
-
* Detects:
|
|
599
|
+
* Regex patterns that can cause catastrophic backtracking (ReDoS attacks).
|
|
600
|
+
* Detects common footguns:
|
|
601
601
|
* - Quantifiers: {n,m}
|
|
602
602
|
* - Possessive quantifiers: *+, ++, ?+
|
|
603
603
|
* - Nested quantifiers: (a+)+, (a*)*
|
|
604
604
|
* - Backreferences: \1, \2, etc.
|
|
605
605
|
* - Complex character classes: [...]...[...]
|
|
606
|
+
*
|
|
607
|
+
* This pattern detector is FAIL-SAFE (on match, the input is escaped), but
|
|
608
|
+
* it is not exhaustive. {@link _regexComplexityExceedsBudget} complements
|
|
609
|
+
* it with a deterministic static complexity budget so patterns that happen
|
|
610
|
+
* to evade the detector still fail over when their unbounded-quantifier
|
|
611
|
+
* density is pathological.
|
|
606
612
|
*/
|
|
607
613
|
private readonly dangerousRegexPatterns;
|
|
614
|
+
/**
|
|
615
|
+
* Static complexity budget for user-supplied regex patterns.
|
|
616
|
+
* Returns `true` if the pattern crosses a budget that empirically correlates
|
|
617
|
+
* with ReDoS risk — independent of the heuristic regex detector.
|
|
618
|
+
*
|
|
619
|
+
* Budget components (any single threshold crossed → over budget):
|
|
620
|
+
* - unbounded quantifiers (`*`, `+`, `?`) — hard cap 20
|
|
621
|
+
* - nested groups `(` — hard cap 8
|
|
622
|
+
* - alternations `|` — hard cap 10
|
|
623
|
+
* - combined: (quantifiers * groups) — hard cap 40
|
|
624
|
+
*
|
|
625
|
+
* These thresholds are intentionally permissive for legitimate queries and
|
|
626
|
+
* tight enough to refuse known-pathological patterns like `(a+)+b` with
|
|
627
|
+
* heavy repetition.
|
|
628
|
+
*/
|
|
629
|
+
private _regexComplexityExceedsBudget;
|
|
608
630
|
constructor(options?: QueryParserOptions);
|
|
609
631
|
/**
|
|
610
632
|
* Structured view of the configured schema's indexes — geo fields, text
|
|
@@ -1210,4 +1232,4 @@ declare function isTransactionUnsupported(error: Error): boolean;
|
|
|
1210
1232
|
*/
|
|
1211
1233
|
declare function createRepository<TDoc>(Model: _$mongoose.Model<TDoc, any, any, any>, plugins?: PluginType[], paginationConfig?: PaginationConfig, options?: RepositoryOptions): Repository<TDoc>;
|
|
1212
1234
|
//#endregion
|
|
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 };
|
|
1235
|
+
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 TenantContext, type TenantStore, 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, createTenantContext, 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 };
|