@classytic/mongokit 3.43.1 → 3.44.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 +14 -0
- package/dist/{PaginationEngine-DZnkbSrr.mjs → PaginationEngine-C9iS0U5l.mjs} +13 -27
- package/dist/{PaginationEngine-CRHyuUtw.d.mts → PaginationEngine-D17AthKw.d.mts} +1 -3
- package/dist/{Repository-DnL4xk5w.d.mts → Repository-B6oL6OMv.d.mts} +33 -11
- package/dist/{Repository-Dj6xqPxJ.mjs → Repository-eMRYZ_2Y.mjs} +204 -92
- package/dist/actions/index.d.mts +1 -1
- package/dist/actions/index.mjs +2 -2
- package/dist/{actions-ChYfkPYP.mjs → actions-DExyXMTy.mjs} +3 -4
- package/dist/adapter/index.d.mts +6 -10
- package/dist/adapter/index.mjs +1 -1
- package/dist/{adapter-CkMoMF83.mjs → adapter-Qzgc3ZD_.mjs} +4 -6
- package/dist/ai/index.d.mts +21 -8
- package/dist/ai/index.mjs +15 -9
- package/dist/better-auth/index.d.mts +17 -19
- package/dist/better-auth/index.mjs +3 -4
- package/dist/{coercion-BjdPX3YF.d.mts → coercion-COp9DRNw.d.mts} +0 -2
- package/dist/{create-repository-CJtVdwig.d.mts → create-repository-BOFUYj1l.d.mts} +5 -7
- package/dist/{create-repository-UjwPWR1z.mjs → create-repository-D7MQpIZo.mjs} +4 -5
- package/dist/{derive-DRBiegRH.mjs → derive-Dxsc31fV.mjs} +3 -6
- package/dist/{error-BuByZwKU.mjs → error-DjdmPLWO.mjs} +1 -2
- package/dist/{field-selection-FSQFLpsU.mjs → field-selection-DPFaFw9Y.mjs} +1 -2
- package/dist/{id-chunks-BmAwsqNk.mjs → id-chunks-DH-RAZWG.mjs} +13 -8
- package/dist/{id-resolution-BqDrk0S2.mjs → id-resolution-Cqh49d9J.mjs} +1 -2
- package/dist/idempotency/index.d.mts +4 -7
- package/dist/idempotency/index.mjs +1 -2
- package/dist/{index-SYF8N28D.d.mts → index-8QUEsOFI.d.mts} +3 -4
- package/dist/{index-C0AjVqX3.d.mts → index-ehGZLbrd.d.mts} +2 -8
- package/dist/index.d.mts +63 -96
- package/dist/index.mjs +36 -52
- package/dist/indexes/verify-indexes.d.mts +8 -11
- package/dist/indexes/verify-indexes.mjs +1 -2
- package/dist/{indexes-DIjMpYES.d.mts → indexes-FfyOuhDK.d.mts} +0 -2
- package/dist/{join-scope-DSAznE8E.mjs → join-scope-C1gOtZ59.mjs} +2 -3
- package/dist/kernel-conformance/index.d.mts +39 -13
- package/dist/kernel-conformance/index.mjs +4 -7
- package/dist/lock/index.d.mts +134 -7
- package/dist/lock/index.mjs +349 -14
- package/dist/{logger-K7dPmu2U.mjs → logger-hbWOlj_X.mjs} +1 -2
- package/dist/{method-registry.plugin-C63pGn1d.mjs → method-registry.plugin-CGAepsBU.mjs} +3 -5
- package/dist/{model-registry-ClKtWiHa.mjs → model-registry-DrVfJ3Nt.mjs} +1 -2
- package/dist/{mongooseToJsonSchema-C3k4ide0.mjs → mongooseToJsonSchema-DMDotz4_.mjs} +2 -3
- package/dist/{multi-tenant.plugin-B_q9NUHc.d.mts → multi-tenant.plugin-DfeDMiI8.d.mts} +143 -11
- package/dist/{operations-XiFgG5US.d.mts → operations-Dw9OFV0V.d.mts} +14 -5
- package/dist/outbox/index.d.mts +24 -9
- package/dist/outbox/index.mjs +17 -6
- package/dist/pagination/PaginationEngine.d.mts +1 -1
- package/dist/pagination/PaginationEngine.mjs +1 -1
- package/dist/pagination/utils/limits.d.mts +6 -9
- package/dist/pagination/utils/limits.mjs +2 -3
- package/dist/{pagination-D6psses0.d.mts → pagination-DAUg5zOY.d.mts} +2 -10
- package/dist/{plugin-options-Cirmb4Kp.d.mts → plugin-options-Bpcuz9kS.d.mts} +2 -4
- package/dist/plugins/index.d.mts +6 -7
- package/dist/plugins/index.mjs +6 -7
- package/dist/query/primitives/coercion.d.mts +1 -1
- package/dist/query/primitives/coercion.mjs +2 -3
- package/dist/query/primitives/geo.d.mts +11 -14
- package/dist/query/primitives/geo.mjs +1 -2
- package/dist/query/primitives/indexes.d.mts +1 -1
- package/dist/query/primitives/indexes.mjs +1 -2
- package/dist/{query-defaults-BxUcSOoF.mjs → query-defaults-aUoKlEbh.mjs} +2 -3
- package/dist/read-model/index.d.mts +18 -21
- package/dist/read-model/index.mjs +3 -4
- package/dist/{repository-MqAP409e.d.mts → repository-DzVIwhU2.d.mts} +25 -29
- package/dist/retention-purge-DqcYvRnG.d.mts +35 -0
- package/dist/{rolldown-runtime-D7D4PA-g.mjs → rolldown-runtime-D8jQpDG7.mjs} +1 -2
- package/dist/search/index.d.mts +1 -1
- package/dist/search/index.mjs +1 -1
- package/dist/sync/index.d.mts +95 -15
- package/dist/sync/index.mjs +308 -62
- package/dist/tenant/index.d.mts +8 -11
- package/dist/tenant/index.mjs +1 -2
- package/dist/testkit/index.d.mts +179 -23
- package/dist/testkit/index.mjs +421 -23
- package/dist/{timestamp.plugin-DpOWavVI.mjs → timestamp.plugin-Bz_zL9PX.mjs} +192 -49
- package/dist/{to-plain-vksRrLtc.mjs → to-plain-CEKv_ylg.mjs} +2 -4
- package/dist/{to-plain-o5tUY2nV.d.mts → to-plain-PO5r1Qoy.d.mts} +2 -16
- package/dist/{transaction-DmiB4k2P.mjs → transaction-C2PFxfIv.mjs} +5 -8
- package/dist/{type-utils-CLzRFtIA.d.mts → type-utils-CKvuewAL.d.mts} +0 -2
- package/dist/{update-WgeAUJ_I.mjs → update-DcfmNbJe.mjs} +12 -20
- package/dist/usage/index.d.mts +2 -5
- package/dist/usage/index.mjs +8 -6
- package/dist/utils/index.d.mts +8 -10
- package/dist/utils/index.mjs +7 -7
- package/dist/{validation-chain.plugin-BAeC5eVT.d.mts → validation-chain.plugin-B3gZCZj4.d.mts} +135 -48
- package/dist/{validation-chain.plugin-DRApTmkN.mjs → validation-chain.plugin-DNY6MIF6.mjs} +207 -55
- package/llms.txt +33 -0
- package/package.json +29 -25
- package/skills/mongokit/SKILL.md +112 -0
- package/skills/mongokit/references/pagination-search.md +87 -0
- package/skills/mongokit/references/plugins-tenancy.md +102 -0
- package/skills/mongokit/references/repository-api.md +83 -0
- package/skills/mongokit/references/transactions-outbox.md +101 -0
|
@@ -1,15 +1,15 @@
|
|
|
1
|
-
import { i as isValidIdForType, t as getSchemaIdType } from "./id-resolution-
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
4
|
-
import { n as
|
|
5
|
-
import { n as
|
|
6
|
-
import { i as applyToQuery, n as applyCursorTimeoutMode, r as applyToAggregate, u as resolveQueryOptions } from "./query-defaults-
|
|
7
|
-
import { o as withTransaction, p as resolveMongoCapabilities, s as createTxBoundRepo } from "./transaction-
|
|
8
|
-
import { _ as resolveCursorSecrets, d as withGroupTiebreak, f as withIdTiebreak, g as attachSignature, i as validateKeysetSort, l as assertOffsetWithinCap, n as getPrimaryField, o as encodeCursor, s as resolveCursorFilter, t as PaginationEngine, u as cursorScope, v as verifySignature } from "./PaginationEngine-
|
|
1
|
+
import { i as isValidIdForType, t as getSchemaIdType } from "./id-resolution-Cqh49d9J.mjs";
|
|
2
|
+
import { n as isDuplicateKeyError, r as parseDuplicateKeyError, t as createError } from "./error-DjdmPLWO.mjs";
|
|
3
|
+
import { a as narrowToIds, i as keysetFilter, o as selectKeysetChunk, r as idChunks, t as DEFAULT_ID_CHUNK } from "./id-chunks-DH-RAZWG.mjs";
|
|
4
|
+
import { _ as SHORTHAND_OPS, a as count, b as create, c as getByQuery, d as deleteById, f as deleteByQuery, g as LookupBuilder, h as distinct, l as getOrCreate, n as update, o as exists, r as updateByQuery, s as getById, t as findOneAndUpdate, v as compileFilterToMongo, x as createMany, y as castFilterToSchema } from "./update-DcfmNbJe.mjs";
|
|
5
|
+
import { n as warn } from "./logger-hbWOlj_X.mjs";
|
|
6
|
+
import { i as applyToQuery, n as applyCursorTimeoutMode, r as applyToAggregate, u as resolveQueryOptions } from "./query-defaults-aUoKlEbh.mjs";
|
|
7
|
+
import { o as withTransaction, p as resolveMongoCapabilities, s as createTxBoundRepo } from "./transaction-C2PFxfIv.mjs";
|
|
8
|
+
import { _ as resolveCursorSecrets, d as withGroupTiebreak, f as withIdTiebreak, g as attachSignature, i as validateKeysetSort, l as assertOffsetWithinCap, n as getPrimaryField, o as encodeCursor, s as resolveCursorFilter, t as PaginationEngine, u as cursorScope, v as verifySignature } from "./PaginationEngine-C9iS0U5l.mjs";
|
|
9
9
|
import { calculateTotalPages } from "./pagination/utils/limits.mjs";
|
|
10
|
-
import { a as insertValues, c as writeKeys, d as buildSearchKeys, f as prefixSearchFilter, i as fieldValuesOf, n as SearchKeysWriteError, o as keysFromValues, r as analyzeUpdate, s as unresolvedForUpdate, t as SEARCH_KEYS_ERROR_CODES } from "./derive-
|
|
10
|
+
import { a as insertValues, c as writeKeys, d as buildSearchKeys, f as prefixSearchFilter, i as fieldValuesOf, n as SearchKeysWriteError, o as keysFromValues, r as analyzeUpdate, s as unresolvedForUpdate, t as SEARCH_KEYS_ERROR_CODES } from "./derive-Dxsc31fV.mjs";
|
|
11
11
|
import { hasNearOperator, rewriteNearForCount } from "./query/primitives/geo.mjs";
|
|
12
|
-
import { a as scopeJoins, r as markGoverned } from "./join-scope-
|
|
12
|
+
import { a as scopeJoins, r as markGoverned } from "./join-scope-C1gOtZ59.mjs";
|
|
13
13
|
import { BULK_UPSERT_ERROR_CODES, BULK_UPSERT_FAILURE_CODES, RepositoryBase, bulkUpsertOptionsError, createDistributionGuard, runChunkedArchive, runChunkedPurge, summarizeBulkUpsert, throwIfAborted, validatePluginOrder, withRetry } from "@classytic/repo-core/repository";
|
|
14
14
|
import mongoose from "mongoose";
|
|
15
15
|
import { isFilter } from "@classytic/repo-core/filter";
|
|
@@ -17,13 +17,91 @@ import { VersionConflictError, conservativeMongoIsTransientConflict } from "@cla
|
|
|
17
17
|
import { HOOK_PRIORITY } from "@classytic/repo-core/hooks";
|
|
18
18
|
import { compileUpdateSpecToMongo, isUpdateSpec } from "@classytic/repo-core/update";
|
|
19
19
|
import { decodeAggCursor, encodeAggCursor, isKeysetMode, normalizeGroupBy, validateMeasures } from "@classytic/repo-core/aggregate";
|
|
20
|
-
|
|
20
|
+
// src/plugins/retention-purge.ts
|
|
21
|
+
/** Error codes thrown for a malformed or unauthorized retention purge. */
|
|
22
|
+
const RETENTION_PURGE_ERROR_CODES = {
|
|
23
|
+
DISABLED: "RETENTION_PURGE_DISABLED",
|
|
24
|
+
REASON_REQUIRED: "RETENTION_PURGE_REASON_REQUIRED",
|
|
25
|
+
INVALID_ACTOR: "RETENTION_PURGE_INVALID_ACTOR",
|
|
26
|
+
HARD_ONLY: "RETENTION_PURGE_HARD_ONLY"
|
|
27
|
+
};
|
|
28
|
+
/** Validates the request's shape (reason, actor). Throws 400 on a malformed one. */
|
|
29
|
+
function assertRetentionPurgeShape(raw, op) {
|
|
30
|
+
const req = raw;
|
|
31
|
+
if (!req || typeof req !== "object" || typeof req.reason !== "string" || !req.reason.trim()) throw createError(400, `'${op}' with retentionPurge needs a non-blank reason.`, {
|
|
32
|
+
code: RETENTION_PURGE_ERROR_CODES.REASON_REQUIRED,
|
|
33
|
+
meta: { operation: op }
|
|
34
|
+
});
|
|
35
|
+
if (req.actor !== void 0 && (typeof req.actor !== "string" || !req.actor.trim())) throw createError(400, `'${op}' with retentionPurge: actor must be a non-blank string.`, {
|
|
36
|
+
code: RETENTION_PURGE_ERROR_CODES.INVALID_ACTOR,
|
|
37
|
+
meta: { operation: op }
|
|
38
|
+
});
|
|
39
|
+
return {
|
|
40
|
+
reason: req.reason,
|
|
41
|
+
actor: req.actor
|
|
42
|
+
};
|
|
43
|
+
}
|
|
44
|
+
/**
|
|
45
|
+
* The validated purge request on a delete context, or `undefined` for an
|
|
46
|
+
* ordinary delete. Refuses every malformed or unauthorized form rather than
|
|
47
|
+
* falling back to the fence: a purge that silently became a refused delete
|
|
48
|
+
* would hide the misconfiguration from the job.
|
|
49
|
+
*/
|
|
50
|
+
function readRetentionPurge(ctx, op, guard) {
|
|
51
|
+
const raw = ctx.retentionPurge;
|
|
52
|
+
if (raw === void 0 || raw === null || raw === false) return void 0;
|
|
53
|
+
if (!guard.allowPurge) throw createError(403, `'${op}' with retentionPurge is not enabled on this repository: construct ${guard.plugin} with allowPurge: true for the retention path.`, {
|
|
54
|
+
code: RETENTION_PURGE_ERROR_CODES.DISABLED,
|
|
55
|
+
meta: {
|
|
56
|
+
operation: op,
|
|
57
|
+
plugin: guard.plugin
|
|
58
|
+
}
|
|
59
|
+
});
|
|
60
|
+
const req = assertRetentionPurgeShape(raw, op);
|
|
61
|
+
if (ctx.deleteMode !== "hard") throw createError(400, `'${op}' with retentionPurge must be a physical delete: pass mode: 'hard'.`, {
|
|
62
|
+
code: RETENTION_PURGE_ERROR_CODES.HARD_ONLY,
|
|
63
|
+
meta: { operation: op }
|
|
64
|
+
});
|
|
65
|
+
return req;
|
|
66
|
+
}
|
|
67
|
+
/** Builds the common audit payload from an `after:delete` / `after:deleteMany` emission. */
|
|
68
|
+
function retentionPurgeEvent(operation, context, result) {
|
|
69
|
+
const req = context.retentionPurge;
|
|
70
|
+
if (!req || typeof req !== "object") return void 0;
|
|
71
|
+
const ctx = context;
|
|
72
|
+
return {
|
|
73
|
+
operation,
|
|
74
|
+
reason: req.reason,
|
|
75
|
+
actor: req.actor,
|
|
76
|
+
id: operation === "delete" ? ctx.id : void 0,
|
|
77
|
+
filter: operation === "deleteMany" ? ctx.query : void 0,
|
|
78
|
+
deletedCount: operation === "delete" ? result ? 1 : 0 : result?.deletedCount ?? 0,
|
|
79
|
+
session: context.session,
|
|
80
|
+
context
|
|
81
|
+
};
|
|
82
|
+
}
|
|
83
|
+
// src/actions/purge.ts
|
|
84
|
+
/**
|
|
85
|
+
* Validates the run's `retentionPurge` up front (before any chunk is
|
|
86
|
+
* selected) and returns the port options. A purge request is a physical
|
|
87
|
+
* delete only: with a `soft` / `anonymize` strategy it is refused.
|
|
88
|
+
*/
|
|
89
|
+
function purgePortOptions(op, strategy, options) {
|
|
90
|
+
const raw = options.retentionPurge;
|
|
91
|
+
if (raw === void 0 || raw === null || raw === false) return {};
|
|
92
|
+
const retentionPurge = assertRetentionPurgeShape(raw, op);
|
|
93
|
+
if (strategy.type !== "hard") throw createError(400, `'${op}' with retentionPurge must use the 'hard' strategy (got '${strategy.type}').`, {
|
|
94
|
+
code: RETENTION_PURGE_ERROR_CODES.HARD_ONLY,
|
|
95
|
+
meta: { operation: op }
|
|
96
|
+
});
|
|
97
|
+
return { retentionPurge };
|
|
98
|
+
}
|
|
21
99
|
/**
|
|
22
100
|
* Build a `PurgePort` bound to a repository + the `field = value`
|
|
23
101
|
* predicate the purge targets.
|
|
24
102
|
*/
|
|
25
|
-
function createMongoPurgePort(repo, field, value, session) {
|
|
26
|
-
return createKeysetPurgePort(repo, { [field]: value }, session);
|
|
103
|
+
function createMongoPurgePort(repo, field, value, session, portOptions = {}) {
|
|
104
|
+
return createKeysetPurgePort(repo, { [field]: value }, session, portOptions);
|
|
27
105
|
}
|
|
28
106
|
/**
|
|
29
107
|
* Build a `PurgePort` bound to a repository + a pre-compiled Mongo filter
|
|
@@ -42,24 +120,29 @@ function createMongoPurgePort(repo, field, value, session) {
|
|
|
42
120
|
* Mirrors `createMongoArchivePort`, which likewise binds a pre-compiled
|
|
43
121
|
* filter rather than a `field/value` pair.
|
|
44
122
|
*/
|
|
45
|
-
function createMongoPurgePortFromFilter(repo, filter, session) {
|
|
46
|
-
return createKeysetPurgePort(repo, filter, session);
|
|
123
|
+
function createMongoPurgePortFromFilter(repo, filter, session, portOptions = {}) {
|
|
124
|
+
return createKeysetPurgePort(repo, filter, session, portOptions);
|
|
47
125
|
}
|
|
48
126
|
/**
|
|
49
127
|
* Shared keyset-progressed port both public factories delegate to. The
|
|
50
128
|
* closure's `cursor` is the port's single-run progression state.
|
|
51
129
|
*/
|
|
52
|
-
function createKeysetPurgePort(repo, baseFilter, session) {
|
|
130
|
+
function createKeysetPurgePort(repo, baseFilter, session, portOptions) {
|
|
53
131
|
const baseOpts = {
|
|
54
132
|
session,
|
|
55
133
|
bypassTenant: true
|
|
56
134
|
};
|
|
135
|
+
const hardOpts = {
|
|
136
|
+
...baseOpts,
|
|
137
|
+
mode: "hard",
|
|
138
|
+
...portOptions.retentionPurge ? { retentionPurge: portOptions.retentionPurge } : {}
|
|
139
|
+
};
|
|
57
140
|
let cursor = null;
|
|
58
141
|
const selectFilter = () => keysetFilter(baseFilter, cursor);
|
|
59
142
|
return { async purgeChunk(strategy, limit) {
|
|
60
143
|
if (strategy.type === "anonymize") {
|
|
61
144
|
if (Object.values(strategy.fields).some((v) => typeof v === "function")) {
|
|
62
|
-
const { processed, lastId } = await purgeAnonymizeFunctional(repo, selectFilter(), strategy.fields, limit, session);
|
|
145
|
+
const { processed, lastId } = await purgeAnonymizeFunctional(repo, selectFilter(), baseFilter, strategy.fields, limit, session, baseOpts);
|
|
63
146
|
if (lastId != null) cursor = lastId;
|
|
64
147
|
return processed;
|
|
65
148
|
}
|
|
@@ -73,10 +156,7 @@ function createKeysetPurgePort(repo, baseFilter, session) {
|
|
|
73
156
|
const chunkFilter = narrowToIds(baseFilter, ids);
|
|
74
157
|
switch (strategy.type) {
|
|
75
158
|
case "hard":
|
|
76
|
-
await repo.deleteMany(chunkFilter,
|
|
77
|
-
...baseOpts,
|
|
78
|
-
mode: "hard"
|
|
79
|
-
});
|
|
159
|
+
await repo.deleteMany(chunkFilter, hardOpts);
|
|
80
160
|
break;
|
|
81
161
|
case "soft":
|
|
82
162
|
await repo.updateMany(chunkFilter, { $set: {
|
|
@@ -92,47 +172,68 @@ function createKeysetPurgePort(repo, baseFilter, session) {
|
|
|
92
172
|
}
|
|
93
173
|
/**
|
|
94
174
|
* Anonymize with at least one function-form field replacer. Fetches the
|
|
95
|
-
* full docs (function needs the row)
|
|
96
|
-
*
|
|
97
|
-
*
|
|
175
|
+
* full docs (function needs the row), computes each row's values, and
|
|
176
|
+
* writes the chunk with ONE `repo.updateMany` whose pipeline picks each
|
|
177
|
+
* row's value by its `_id`. Two round-trips per chunk regardless of N.
|
|
178
|
+
*
|
|
179
|
+
* Through the repository, never a raw `Model.bulkWrite`: the write meets
|
|
180
|
+
* the same `before:updateMany` fences as the static form —
|
|
181
|
+
* `immutableStatesPlugin` refuses a chunk holding a frozen row,
|
|
182
|
+
* `appendOnlyPlugin` refuses the edit, tenant / soft-delete scope apply —
|
|
183
|
+
* and `after:updateMany` reaches the change log, cache and audit plugins.
|
|
98
184
|
*
|
|
99
185
|
* Selection is `_id`-ascending against the caller's keyset-narrowed
|
|
100
186
|
* filter; returns the chunk's last `_id` so the port can advance its
|
|
101
|
-
* cursor after the write commits.
|
|
102
|
-
*
|
|
103
|
-
*
|
|
104
|
-
*
|
|
105
|
-
* is the same write), this matches the at-least-once contract.
|
|
187
|
+
* cursor after the write commits. Values are cast by the field's schema
|
|
188
|
+
* type where it is a scalar (a pipeline update is not cast by mongoose);
|
|
189
|
+
* `undefined` is written as `null`. Idempotent per row, so the
|
|
190
|
+
* at-least-once contract holds.
|
|
106
191
|
*/
|
|
107
|
-
async function purgeAnonymizeFunctional(repo, selectFilter, fields, limit, session) {
|
|
192
|
+
async function purgeAnonymizeFunctional(repo, selectFilter, baseFilter, fields, limit, session, writeOpts) {
|
|
108
193
|
const docs = await selectKeysetChunk(repo.Model, selectFilter, limit, { session });
|
|
109
194
|
if (docs.length === 0) return {
|
|
110
195
|
processed: 0,
|
|
111
196
|
lastId: null
|
|
112
197
|
};
|
|
113
|
-
const
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
198
|
+
const ids = docs.map((doc) => doc._id);
|
|
199
|
+
const set = {};
|
|
200
|
+
for (const [k, v] of Object.entries(fields)) {
|
|
201
|
+
const values = docs.map((doc) => castScalar(repo.Model, k, typeof v === "function" ? v(doc) : v));
|
|
202
|
+
set[k] = { $let: {
|
|
203
|
+
vars: { i: { $indexOfArray: [{ $literal: ids }, "$_id"] } },
|
|
204
|
+
in: { $arrayElemAt: [{ $literal: values }, "$$i"] }
|
|
119
205
|
} };
|
|
120
|
-
}
|
|
121
|
-
await repo.
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
});
|
|
125
|
-
await repo.emitAsync("after:anonymize", {
|
|
126
|
-
context: { ...session ? { session } : {} },
|
|
127
|
-
result: { ids: docs.map((doc) => doc._id) }
|
|
206
|
+
}
|
|
207
|
+
await repo.updateMany(narrowToIds(baseFilter, ids), [{ $set: set }], {
|
|
208
|
+
...writeOpts,
|
|
209
|
+
updatePipeline: true
|
|
128
210
|
});
|
|
129
211
|
return {
|
|
130
212
|
processed: docs.length,
|
|
131
213
|
lastId: docs[docs.length - 1]?._id ?? null
|
|
132
214
|
};
|
|
133
215
|
}
|
|
134
|
-
|
|
135
|
-
|
|
216
|
+
/** Scalar schema types a pipeline write must be cast to by hand (mongoose casts `$set`, not pipelines). */
|
|
217
|
+
const SCALAR_INSTANCES = /* @__PURE__ */ new Set([
|
|
218
|
+
"String",
|
|
219
|
+
"Number",
|
|
220
|
+
"Date",
|
|
221
|
+
"Boolean",
|
|
222
|
+
"ObjectId",
|
|
223
|
+
"ObjectID",
|
|
224
|
+
"Decimal128",
|
|
225
|
+
"UUID",
|
|
226
|
+
"BigInt",
|
|
227
|
+
"Double",
|
|
228
|
+
"Int32"
|
|
229
|
+
]);
|
|
230
|
+
function castScalar(model, path, value) {
|
|
231
|
+
if (value === void 0 || value === null) return null;
|
|
232
|
+
const type = model.schema.path(path);
|
|
233
|
+
if (!type?.instance || !SCALAR_INSTANCES.has(type.instance) || !type.cast) return value;
|
|
234
|
+
return type.cast(value);
|
|
235
|
+
}
|
|
236
|
+
// src/operations.ts
|
|
136
237
|
/**
|
|
137
238
|
* The registry. Order intentionally groups by category for readability.
|
|
138
239
|
* Adding a new RepositoryOperation requires exactly one entry here, after
|
|
@@ -295,8 +396,7 @@ const READ_OPERATIONS = ALL_OPERATIONS.filter((op) => !OP_REGISTRY[op].mutates);
|
|
|
295
396
|
function operationsByPolicyKey(key) {
|
|
296
397
|
return ALL_OPERATIONS.filter((op) => OP_REGISTRY[op].policyKey === key);
|
|
297
398
|
}
|
|
298
|
-
|
|
299
|
-
//#region src/actions/aggregate-ir/hints.ts
|
|
399
|
+
// src/actions/aggregate-ir/hints.ts
|
|
300
400
|
function applyExecutionHints(aggregation, hints) {
|
|
301
401
|
if (!hints) return;
|
|
302
402
|
if (hints.allowDiskUse) aggregation.allowDiskUse(true);
|
|
@@ -328,8 +428,7 @@ function assertExpectedIndex(model, leadingKeys) {
|
|
|
328
428
|
if (!keys.some((key) => startsWith(key, 0) || startsWith(key, 1))) throw new Error(`[mongokit] ${model.modelName}: an aggregation expects an index leading with (${id}), but none is declared — declared: ${keys.map((k) => `(${k.join(",")})`).join(" ") || "none"}. Declare one, or drop the hint.`);
|
|
329
429
|
checked.set(model, (done ?? /* @__PURE__ */ new Set()).add(id));
|
|
330
430
|
}
|
|
331
|
-
|
|
332
|
-
//#region src/actions/aggregate-ir/dateBucket.ts
|
|
431
|
+
// src/actions/aggregate-ir/dateBucket.ts
|
|
333
432
|
/**
|
|
334
433
|
* Compile a `AggDateBucket` to the mongo expression that produces the
|
|
335
434
|
* bucket label string for a single document. Used in two places:
|
|
@@ -458,8 +557,7 @@ function formatForUnit(unit) {
|
|
|
458
557
|
case "year": return "%Y";
|
|
459
558
|
}
|
|
460
559
|
}
|
|
461
|
-
|
|
462
|
-
//#region src/filter/compile-expr.ts
|
|
560
|
+
// src/filter/compile-expr.ts
|
|
463
561
|
/**
|
|
464
562
|
* Compile a Filter IR node (or already-built expression) to a MongoDB
|
|
465
563
|
* aggregation expression. Returns the literal `true` for empty `and`
|
|
@@ -773,8 +871,7 @@ function likeToRegexPattern(pattern) {
|
|
|
773
871
|
function escapeRegexChar(ch) {
|
|
774
872
|
return /[.*+?^${}()|[\]\\]/.test(ch) ? `\\${ch}` : ch;
|
|
775
873
|
}
|
|
776
|
-
|
|
777
|
-
//#region src/actions/aggregate-ir/measure.ts
|
|
874
|
+
// src/actions/aggregate-ir/measure.ts
|
|
778
875
|
function compileMeasure(measure) {
|
|
779
876
|
const whereExpr = measure.where !== void 0 ? compileFilterToMongoExpr(measure.where) : void 0;
|
|
780
877
|
switch (measure.op) {
|
|
@@ -843,8 +940,7 @@ function compileMeasure(measure) {
|
|
|
843
940
|
};
|
|
844
941
|
}
|
|
845
942
|
}
|
|
846
|
-
|
|
847
|
-
//#region src/actions/aggregate-ir/normalize.ts
|
|
943
|
+
// src/actions/aggregate-ir/normalize.ts
|
|
848
944
|
/**
|
|
849
945
|
* AggRequest → input normalization (mongokit binding).
|
|
850
946
|
*
|
|
@@ -857,8 +953,7 @@ function compileMeasure(measure) {
|
|
|
857
953
|
function validateMeasures$1(measures) {
|
|
858
954
|
validateMeasures(measures, "mongokit");
|
|
859
955
|
}
|
|
860
|
-
|
|
861
|
-
//#region src/actions/aggregate-ir/pipeline.ts
|
|
956
|
+
// src/actions/aggregate-ir/pipeline.ts
|
|
862
957
|
function buildAggPipeline(req, schema) {
|
|
863
958
|
validateMeasures$1(req.measures);
|
|
864
959
|
const groupCols = normalizeGroupBy(req.groupBy);
|
|
@@ -1251,8 +1346,7 @@ function irReferencesAlias(filter, aliasSet) {
|
|
|
1251
1346
|
if (node.child) return irReferencesAlias(node.child, aliasSet);
|
|
1252
1347
|
return false;
|
|
1253
1348
|
}
|
|
1254
|
-
|
|
1255
|
-
//#region src/actions/aggregate-ir/execute.ts
|
|
1349
|
+
// src/actions/aggregate-ir/execute.ts
|
|
1256
1350
|
/** Build the aggregate for `stages` with every execution option applied, unexecuted. */
|
|
1257
1351
|
function prepareAgg(Model, stages, req, options = {}) {
|
|
1258
1352
|
const aggregation = Model.aggregate(options.finalize ? options.finalize(stages) : stages);
|
|
@@ -1271,8 +1365,7 @@ async function executeAgg(Model, req, options = {}) {
|
|
|
1271
1365
|
const { pipeline } = buildAggPipeline(req, Model.schema);
|
|
1272
1366
|
return runAgg(Model, pipeline, req, options);
|
|
1273
1367
|
}
|
|
1274
|
-
|
|
1275
|
-
//#region src/actions/aggregate-ir/count.ts
|
|
1368
|
+
// src/actions/aggregate-ir/count.ts
|
|
1276
1369
|
async function countAggGroups(Model, req, options = {}) {
|
|
1277
1370
|
const groupCols = normalizeGroupBy(req.groupBy);
|
|
1278
1371
|
const hasDottedGroupBy = groupCols.some((f) => f.includes("."));
|
|
@@ -1302,8 +1395,7 @@ async function countAggGroups(Model, req, options = {}) {
|
|
|
1302
1395
|
const [row] = await runAgg(Model, pipeline, req, options);
|
|
1303
1396
|
return row?.n ?? 0;
|
|
1304
1397
|
}
|
|
1305
|
-
|
|
1306
|
-
//#region src/actions/aggregate-ir/keyset.ts
|
|
1398
|
+
// src/actions/aggregate-ir/keyset.ts
|
|
1307
1399
|
/**
|
|
1308
1400
|
* Keyset (cursor) pagination helpers — mongokit binding.
|
|
1309
1401
|
*
|
|
@@ -1366,8 +1458,7 @@ function buildKeysetPredicate(sort, cursor) {
|
|
|
1366
1458
|
}
|
|
1367
1459
|
return { $match: branches.length === 1 ? branches[0] : { $or: branches } };
|
|
1368
1460
|
}
|
|
1369
|
-
|
|
1370
|
-
//#region src/actions/archive.ts
|
|
1461
|
+
// src/actions/archive.ts
|
|
1371
1462
|
/**
|
|
1372
1463
|
* Build an `ArchivePort` bound to a repository + a pre-compiled Mongo
|
|
1373
1464
|
* filter (the repository compiles Filter IR before calling this).
|
|
@@ -1387,8 +1478,7 @@ function createMongoArchivePort(repo, filter, session) {
|
|
|
1387
1478
|
}
|
|
1388
1479
|
};
|
|
1389
1480
|
}
|
|
1390
|
-
|
|
1391
|
-
//#region src/actions/bulk-upsert.ts
|
|
1481
|
+
// src/actions/bulk-upsert.ts
|
|
1392
1482
|
/**
|
|
1393
1483
|
* `bulkUpsert` execution: keyed `updateOne` + `upsert` sub-ops in ONE `client.bulkWrite` with
|
|
1394
1484
|
* `verboseResults`, the only form that reports matched / modified / upserted PER OP (server 8.0,
|
|
@@ -1569,8 +1659,7 @@ async function executeUpserts(model, ops, options) {
|
|
|
1569
1659
|
});
|
|
1570
1660
|
return results;
|
|
1571
1661
|
}
|
|
1572
|
-
|
|
1573
|
-
//#region src/plugins/search-keys.plugin.ts
|
|
1662
|
+
// src/plugins/search-keys.plugin.ts
|
|
1574
1663
|
/**
|
|
1575
1664
|
* Search-keys plugin: keeps the `searchMode: 'prefix'` keys field in step with
|
|
1576
1665
|
* its source fields on EVERY write path, inside the same write.
|
|
@@ -1680,8 +1769,7 @@ function searchKeysPlugin(options) {
|
|
|
1680
1769
|
}
|
|
1681
1770
|
};
|
|
1682
1771
|
}
|
|
1683
|
-
|
|
1684
|
-
//#region src/query/AggregationBuilder.ts
|
|
1772
|
+
// src/query/AggregationBuilder.ts
|
|
1685
1773
|
/**
|
|
1686
1774
|
* Normalize SortSpec to MongoDB's strict format (1 | -1)
|
|
1687
1775
|
* Converts 'asc' -> 1, 'desc' -> -1
|
|
@@ -2212,8 +2300,7 @@ var AggregationBuilder = class AggregationBuilder {
|
|
|
2212
2300
|
* .exec(Model)
|
|
2213
2301
|
* ```
|
|
2214
2302
|
*/
|
|
2215
|
-
|
|
2216
|
-
//#region src/repository/lookup-populate.ts
|
|
2303
|
+
// src/repository/lookup-populate.ts
|
|
2217
2304
|
/**
|
|
2218
2305
|
* Inclusion projections must carry the keyset sort fields (plus `_id`) or
|
|
2219
2306
|
* cursor encoding has no values to serialize. No-op for exclusion
|
|
@@ -2265,8 +2352,16 @@ function appendLookupStages(pipeline, lookups, projection, keysetSort) {
|
|
|
2265
2352
|
const finalProjection = ensureLookupProjectionIncludesCursorFields(projection, keysetSort);
|
|
2266
2353
|
if (finalProjection) pipeline.push({ $project: finalProjection });
|
|
2267
2354
|
}
|
|
2268
|
-
|
|
2269
|
-
|
|
2355
|
+
// src/Repository.ts
|
|
2356
|
+
/**
|
|
2357
|
+
* A CAS guard (`claim` / `claimVersion` `where`) as Mongo: Filter IR compiled, a plain
|
|
2358
|
+
* record (Mongo operators) as is. Spreading an IR node raw made the match require
|
|
2359
|
+
* `doc.op === 'eq'` — no document matched, and the miss read as a lost race.
|
|
2360
|
+
*/
|
|
2361
|
+
function casGuard(where) {
|
|
2362
|
+
if (where === void 0) return {};
|
|
2363
|
+
return isFilter(where) ? compileFilterToMongo(where) : where;
|
|
2364
|
+
}
|
|
2270
2365
|
/**
|
|
2271
2366
|
* Validates that an update patch is homogeneous — either all top-level
|
|
2272
2367
|
* keys are `$`-prefixed Mongo operators OR none are. Mixed shapes (e.g.
|
|
@@ -3885,7 +3980,7 @@ var Repository = class extends RepositoryBase {
|
|
|
3885
3980
|
const effectiveIdField = options.idField ?? this.idField;
|
|
3886
3981
|
const fromSpec = Array.isArray(transition.from) ? { $in: transition.from } : transition.from;
|
|
3887
3982
|
const filter = {
|
|
3888
|
-
...transition.where
|
|
3983
|
+
...casGuard(transition.where),
|
|
3889
3984
|
[effectiveIdField]: id,
|
|
3890
3985
|
[stateField]: fromSpec
|
|
3891
3986
|
};
|
|
@@ -4008,13 +4103,32 @@ var Repository = class extends RepositoryBase {
|
|
|
4008
4103
|
machine.assertTransition(entityId, from, args.to);
|
|
4009
4104
|
}
|
|
4010
4105
|
const historyField = args.history === false ? null : args.history ?? "statusHistory";
|
|
4106
|
+
if (historyField === null && (args.priorAt !== void 0 || args.historyExtra !== void 0)) throw createError(400, "applyTransition: priorAt / historyExtra need history (got history: false)", { code: "TRANSITION_HISTORY_DISABLED" });
|
|
4107
|
+
if (args.priorAt !== void 0 && (!(args.priorAt instanceof Date) || Number.isNaN(args.priorAt.getTime()))) throw createError(400, "applyTransition: priorAt must be a valid Date", { code: "TRANSITION_INVALID_PRIOR_AT" });
|
|
4108
|
+
if (args.priorAt !== void 0 && args.at !== void 0 && (!(args.at instanceof Date) || Number.isNaN(args.at.getTime()))) throw createError(400, "applyTransition: at must be a valid Date when priorAt is given", { code: "TRANSITION_INVALID_AT" });
|
|
4109
|
+
if (args.historyExtra !== void 0 && (args.historyExtra === null || typeof args.historyExtra !== "object" || Array.isArray(args.historyExtra))) throw createError(400, "applyTransition: historyExtra must be a plain object", { code: "TRANSITION_INVALID_HISTORY_EXTRA" });
|
|
4110
|
+
if (args.historyExtra !== void 0) {
|
|
4111
|
+
const reserved = [
|
|
4112
|
+
"status",
|
|
4113
|
+
"occurredAt",
|
|
4114
|
+
"by",
|
|
4115
|
+
"note",
|
|
4116
|
+
"durationInPriorMs"
|
|
4117
|
+
].filter((k) => k in args.historyExtra);
|
|
4118
|
+
if (reserved.length > 0) throw createError(400, `applyTransition: historyExtra may not set reserved key(s) ${reserved.join(", ")}`, { code: "TRANSITION_HISTORY_RESERVED_KEY" });
|
|
4119
|
+
}
|
|
4011
4120
|
const pushSpec = { ...args.push ?? {} };
|
|
4012
|
-
if (historyField !== null)
|
|
4013
|
-
|
|
4014
|
-
|
|
4015
|
-
|
|
4016
|
-
|
|
4017
|
-
|
|
4121
|
+
if (historyField !== null) {
|
|
4122
|
+
const occurredAt = args.at ?? /* @__PURE__ */ new Date();
|
|
4123
|
+
pushSpec[historyField] = {
|
|
4124
|
+
...args.historyExtra ?? {},
|
|
4125
|
+
status: args.to,
|
|
4126
|
+
occurredAt,
|
|
4127
|
+
...args.by !== void 0 ? { by: args.by } : {},
|
|
4128
|
+
...args.note !== void 0 ? { note: args.note } : {},
|
|
4129
|
+
...args.priorAt !== void 0 ? { durationInPriorMs: Math.max(0, occurredAt.getTime() - args.priorAt.getTime()) } : {}
|
|
4130
|
+
};
|
|
4131
|
+
}
|
|
4018
4132
|
const patch = {
|
|
4019
4133
|
...args.set !== void 0 && Object.keys(args.set).length > 0 ? { $set: args.set } : {},
|
|
4020
4134
|
...Object.keys(pushSpec).length > 0 ? { $push: pushSpec } : {},
|
|
@@ -4156,7 +4270,7 @@ var Repository = class extends RepositoryBase {
|
|
|
4156
4270
|
};
|
|
4157
4271
|
const versionMatch = transition.from === void 0 ? null : transition.from;
|
|
4158
4272
|
const filter = {
|
|
4159
|
-
...transition.where
|
|
4273
|
+
...casGuard(transition.where),
|
|
4160
4274
|
[effectiveIdField]: id,
|
|
4161
4275
|
[versionField]: versionMatch
|
|
4162
4276
|
};
|
|
@@ -4370,7 +4484,7 @@ var Repository = class extends RepositoryBase {
|
|
|
4370
4484
|
* the port implementation.
|
|
4371
4485
|
*/
|
|
4372
4486
|
async purgeByField(field, value, strategy, options = {}) {
|
|
4373
|
-
const port = createMongoPurgePort(this, field, value, options.session);
|
|
4487
|
+
const port = createMongoPurgePort(this, field, value, options.session, purgePortOptions("purgeByField", strategy, options));
|
|
4374
4488
|
return runChunkedPurge(strategy, options, port);
|
|
4375
4489
|
}
|
|
4376
4490
|
/**
|
|
@@ -4388,8 +4502,7 @@ var Repository = class extends RepositoryBase {
|
|
|
4388
4502
|
* See [actions/purge.ts](./actions/purge.ts) for the port.
|
|
4389
4503
|
*/
|
|
4390
4504
|
async purgeByFilter(filter, strategy, options = {}) {
|
|
4391
|
-
const
|
|
4392
|
-
const port = createMongoPurgePortFromFilter(this, compiled, options.session);
|
|
4505
|
+
const port = createMongoPurgePortFromFilter(this, compileFilterToMongo(filter), options.session, purgePortOptions("purgeByFilter", strategy, options));
|
|
4393
4506
|
return runChunkedPurge(strategy, options, port);
|
|
4394
4507
|
}
|
|
4395
4508
|
/**
|
|
@@ -4827,9 +4940,9 @@ var Repository = class extends RepositoryBase {
|
|
|
4827
4940
|
const appendLookupStages$2 = (pipeline) => appendLookupStages(pipeline, lookups, projection, isKeyset && sort ? this._parseSort(sort) : void 0);
|
|
4828
4941
|
if (isKeyset && sort) {
|
|
4829
4942
|
const parsedSort = this._parseSort(sort);
|
|
4830
|
-
const { validateKeysetSort } = await import("./PaginationEngine-
|
|
4831
|
-
const { encodeCursor, resolveCursorFilter } = await import("./PaginationEngine-
|
|
4832
|
-
const { getPrimaryField } = await import("./PaginationEngine-
|
|
4943
|
+
const { validateKeysetSort } = await import("./PaginationEngine-C9iS0U5l.mjs").then((n) => n.r);
|
|
4944
|
+
const { encodeCursor, resolveCursorFilter } = await import("./PaginationEngine-C9iS0U5l.mjs").then((n) => n.a);
|
|
4945
|
+
const { getPrimaryField } = await import("./PaginationEngine-C9iS0U5l.mjs").then((n) => n.r);
|
|
4833
4946
|
const normalizedSort = validateKeysetSort(parsedSort, this._pagination.config.strictKeysetSortFields);
|
|
4834
4947
|
const cursorVersion = this._pagination.config.cursorVersion ?? 1;
|
|
4835
4948
|
const minCursorVersion = this._pagination.config.minCursorVersion ?? 1;
|
|
@@ -5392,5 +5505,4 @@ var Repository = class extends RepositoryBase {
|
|
|
5392
5505
|
return createError(500, error.message || "Internal Server Error");
|
|
5393
5506
|
}
|
|
5394
5507
|
};
|
|
5395
|
-
|
|
5396
|
-
export { ALL_OPERATIONS as a, READ_OPERATIONS as c, searchKeysPlugin as i, operationsByPolicyKey as l, Repository as n, MUTATING_OPERATIONS as o, AggregationBuilder as r, OP_REGISTRY as s, HOOK_PRIORITY$1 as t, createMongoPurgePort as u };
|
|
5508
|
+
export { ALL_OPERATIONS as a, READ_OPERATIONS as c, RETENTION_PURGE_ERROR_CODES as d, readRetentionPurge as f, searchKeysPlugin as i, operationsByPolicyKey as l, Repository as n, MUTATING_OPERATIONS as o, retentionPurgeEvent as p, AggregationBuilder as r, OP_REGISTRY as s, HOOK_PRIORITY$1 as t, createMongoPurgePort as u };
|
package/dist/actions/index.d.mts
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { c as create_d_exports, i as delete_d_exports, n as update_d_exports, r as read_d_exports, u as aggregate_d_exports } from "../index-
|
|
1
|
+
import { c as create_d_exports, i as delete_d_exports, n as update_d_exports, r as read_d_exports, u as aggregate_d_exports } from "../index-8QUEsOFI.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,2 +1,2 @@
|
|
|
1
|
-
export { m as aggregate, S as create, p as deleteActions, u as read, i as update } from "../update-
|
|
2
|
-
import "../actions-
|
|
1
|
+
export { m as aggregate, S as create, p as deleteActions, u as read, i as update } from "../update-DcfmNbJe.mjs";
|
|
2
|
+
import "../actions-DExyXMTy.mjs";
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { t as __exportAll } from "./rolldown-runtime-
|
|
2
|
-
import { S as create_exports, i as update_exports, m as aggregate_exports, p as delete_exports, u as read_exports } from "./update-
|
|
3
|
-
|
|
1
|
+
import { t as __exportAll } from "./rolldown-runtime-D8jQpDG7.mjs";
|
|
2
|
+
import { S as create_exports, i as update_exports, m as aggregate_exports, p as delete_exports, u as read_exports } from "./update-DcfmNbJe.mjs";
|
|
3
|
+
// src/actions/index.ts
|
|
4
4
|
var actions_exports = /* @__PURE__ */ __exportAll({
|
|
5
5
|
aggregate: () => aggregate_exports,
|
|
6
6
|
create: () => create_exports,
|
|
@@ -8,5 +8,4 @@ var actions_exports = /* @__PURE__ */ __exportAll({
|
|
|
8
8
|
read: () => read_exports,
|
|
9
9
|
update: () => update_exports
|
|
10
10
|
});
|
|
11
|
-
//#endregion
|
|
12
11
|
export { actions_exports as t };
|
package/dist/adapter/index.d.mts
CHANGED
|
@@ -2,7 +2,6 @@ import { StandardRepo } from "@classytic/repo-core/repository";
|
|
|
2
2
|
import { Document, Model } from "mongoose";
|
|
3
3
|
import { SchemaBuilderOptions, SchemaGenerator } from "@classytic/repo-core/schema";
|
|
4
4
|
import { AdapterRepositoryInput, AdapterSchemaContext, AdapterValidationResult, DataAdapter, OpenApiSchemas, RepositoryLike, SchemaMetadata } from "@classytic/repo-core/adapter";
|
|
5
|
-
//#region src/adapter/mongoose-adapter.d.ts
|
|
6
5
|
interface MongooseAdapterOptions<TDoc = unknown, TModelDoc = unknown> {
|
|
7
6
|
/**
|
|
8
7
|
* The Mongoose model. Still a real `Model`, so a Schema or a hand-built
|
|
@@ -68,8 +67,8 @@ interface MongooseAdapterOptions<TDoc = unknown, TModelDoc = unknown> {
|
|
|
68
67
|
* Mongoose data adapter — implements the `DataAdapter<TDoc>` contract from
|
|
69
68
|
* `@classytic/repo-core/adapter`.
|
|
70
69
|
*/
|
|
71
|
-
declare class MongooseAdapter<TDoc = unknown, TModelDoc = unknown> implements DataAdapter<TDoc> {
|
|
72
|
-
readonly type:
|
|
70
|
+
export declare class MongooseAdapter<TDoc = unknown, TModelDoc = unknown> implements DataAdapter<TDoc> {
|
|
71
|
+
readonly type: 'mongoose';
|
|
73
72
|
readonly name: string;
|
|
74
73
|
/**
|
|
75
74
|
* The model as given. Its document type is NOT `TDoc` — a lean repository
|
|
@@ -196,10 +195,8 @@ declare class MongooseAdapter<TDoc = unknown, TModelDoc = unknown> implements Da
|
|
|
196
195
|
* const adapter = createMongooseAdapter(ProductModel, productRepository);
|
|
197
196
|
* ```
|
|
198
197
|
*/
|
|
199
|
-
declare function createMongooseAdapter<TDoc = unknown, TModelDoc = unknown>(model: Model<TModelDoc>, repository: AdapterRepositoryInput<TDoc>): DataAdapter<TDoc>;
|
|
200
|
-
declare function createMongooseAdapter<TDoc = unknown, TModelDoc = unknown>(options: MongooseAdapterOptions<TDoc, TModelDoc>): DataAdapter<TDoc>;
|
|
201
|
-
//#endregion
|
|
202
|
-
//#region src/adapter/types.d.ts
|
|
198
|
+
export declare function createMongooseAdapter<TDoc = unknown, TModelDoc = unknown>(model: Model<TModelDoc>, repository: AdapterRepositoryInput<TDoc>): DataAdapter<TDoc>;
|
|
199
|
+
export declare function createMongooseAdapter<TDoc = unknown, TModelDoc = unknown>(options: MongooseAdapterOptions<TDoc, TModelDoc>): DataAdapter<TDoc>;
|
|
203
200
|
/**
|
|
204
201
|
* Infer document type from a Mongoose model.
|
|
205
202
|
*
|
|
@@ -233,7 +230,7 @@ type MatchingModel<TDoc> = Model<TDoc & Document>;
|
|
|
233
230
|
/**
|
|
234
231
|
* Runtime guard: is `value` a Mongoose model?
|
|
235
232
|
*/
|
|
236
|
-
declare function isMongooseModel(value: unknown): value is Model<Document>;
|
|
233
|
+
export declare function isMongooseModel(value: unknown): value is Model<Document>;
|
|
237
234
|
/**
|
|
238
235
|
* Mongoose SchemaType internal shape (not fully exposed by `@types/mongoose`).
|
|
239
236
|
* Used to extract field metadata from schema paths.
|
|
@@ -252,5 +249,4 @@ interface MongooseSchemaType {
|
|
|
252
249
|
};
|
|
253
250
|
[key: string]: unknown;
|
|
254
251
|
}
|
|
255
|
-
|
|
256
|
-
export { type CleanDoc, type InferAdapterDoc, type InferMongooseDoc, type InferRepoDoc, type MatchingModel, MongooseAdapter, type MongooseAdapterOptions, type MongooseDocument, type MongooseSchemaType, createMongooseAdapter, isMongooseModel };
|
|
252
|
+
export type { CleanDoc, InferAdapterDoc, InferMongooseDoc, InferRepoDoc, MatchingModel, MongooseAdapterOptions, MongooseDocument, MongooseSchemaType };
|
package/dist/adapter/index.mjs
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
export { t as MongooseAdapter, n as createMongooseAdapter, r as isMongooseModel } from "../adapter-
|
|
1
|
+
export { t as MongooseAdapter, n as createMongooseAdapter, r as isMongooseModel } from "../adapter-Qzgc3ZD_.mjs";
|
|
@@ -1,17 +1,16 @@
|
|
|
1
|
-
import { n as warn } from "./logger-
|
|
2
|
-
import { t as buildCrudSchemasFromModel } from "./mongooseToJsonSchema-
|
|
1
|
+
import { n as warn } from "./logger-hbWOlj_X.mjs";
|
|
2
|
+
import { t as buildCrudSchemasFromModel } from "./mongooseToJsonSchema-DMDotz4_.mjs";
|
|
3
3
|
import { matchesRecordFilter } from "@classytic/repo-core/filter";
|
|
4
4
|
import { mergeFieldRuleConstraints } from "@classytic/repo-core/schema";
|
|
5
5
|
import { asRepositoryLike, isRepository } from "@classytic/repo-core/adapter";
|
|
6
|
-
|
|
6
|
+
// src/adapter/types.ts
|
|
7
7
|
/**
|
|
8
8
|
* Runtime guard: is `value` a Mongoose model?
|
|
9
9
|
*/
|
|
10
10
|
function isMongooseModel(value) {
|
|
11
11
|
return typeof value === "function" && value.prototype && "modelName" in value && "schema" in value;
|
|
12
12
|
}
|
|
13
|
-
|
|
14
|
-
//#region src/adapter/mongoose-adapter.ts
|
|
13
|
+
// src/adapter/mongoose-adapter.ts
|
|
15
14
|
const REQUIRED_REPO_METHODS = [
|
|
16
15
|
"getAll",
|
|
17
16
|
"getById",
|
|
@@ -325,5 +324,4 @@ function createMongooseAdapter(modelOrOptions, repository) {
|
|
|
325
324
|
}
|
|
326
325
|
return new MongooseAdapter(modelOrOptions);
|
|
327
326
|
}
|
|
328
|
-
//#endregion
|
|
329
327
|
export { createMongooseAdapter as n, isMongooseModel as r, MongooseAdapter as t };
|