@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
package/dist/lock/index.mjs
CHANGED
|
@@ -1,5 +1,276 @@
|
|
|
1
1
|
import mongoose, { Schema } from "mongoose";
|
|
2
|
-
|
|
2
|
+
import { randomUUID } from "node:crypto";
|
|
3
|
+
import { AsyncLocalStorage } from "node:async_hooks";
|
|
4
|
+
// src/lock/daily-ledger.ts
|
|
5
|
+
/**
|
|
6
|
+
* Mongo-backed daily ledger — one claim row per `(key, civilDate)`.
|
|
7
|
+
*
|
|
8
|
+
* Structurally implements arc's `DailyLedger` (`@classytic/arc` →
|
|
9
|
+
* `createDailyGate` / `ScheduleDefinition.daily`) without importing arc:
|
|
10
|
+
* pass the returned object as `ledger`. Exactly one replica wins
|
|
11
|
+
* `claimDay` for a given key and civil date (unique `_id` + upsert; the
|
|
12
|
+
* loser's upsert hits E11000 and returns `false`). An uncompleted claim
|
|
13
|
+
* older than `info.staleAfterMs` may be re-granted (crash mid-run); a
|
|
14
|
+
* completed day never is.
|
|
15
|
+
*
|
|
16
|
+
* {
|
|
17
|
+
* _id: 'cron.digest|2026-10-30',
|
|
18
|
+
* key: 'cron.digest',
|
|
19
|
+
* civilDate: '2026-10-30',
|
|
20
|
+
* claimedAt: 2026-10-30T06:00:01.000Z, // the gate's clock (info.now)
|
|
21
|
+
* completed: true,
|
|
22
|
+
* completedAt: 2026-10-30T06:00:04.000Z,
|
|
23
|
+
* result: { sent: 12 },
|
|
24
|
+
* }
|
|
25
|
+
*
|
|
26
|
+
* `civilDate` must be `YYYY-MM-DD` (what arc passes), so the composite
|
|
27
|
+
* `_id` stays unambiguous whatever the key contains.
|
|
28
|
+
*
|
|
29
|
+
* Fencing is per INVOCATION, not per ledger instance: every won claim
|
|
30
|
+
* gets a unique `claimToken` (stored on the row), and completing or
|
|
31
|
+
* releasing only touches the row while it still carries that token. A
|
|
32
|
+
* run that outlived `staleAfterMs` and was re-granted (by another
|
|
33
|
+
* replica, or by this same instance on a later tick) can therefore
|
|
34
|
+
* neither delete nor complete the newer claim, and a retry of its
|
|
35
|
+
* completion stays fenced.
|
|
36
|
+
*
|
|
37
|
+
* - `claim()` returns a handle carrying the token; its `complete()` /
|
|
38
|
+
* `release()` are fenced by it. Prefer it in host code.
|
|
39
|
+
* - `claimDay` / `completeDay` / `releaseDay` (arc's token-less
|
|
40
|
+
* `DailyLedger` shape) bind the token to the calling async context:
|
|
41
|
+
* `completeDay` / `releaseDay` act on the claim that THIS invocation
|
|
42
|
+
* (the async flow that awaited `claimDay`) won. Called from a flow
|
|
43
|
+
* that won nothing, they fall back to the instance's claim on the row
|
|
44
|
+
* only when it holds exactly one, and are otherwise a no-op.
|
|
45
|
+
* - `adminCompleteDay` is the separate, explicit, unfenced manual
|
|
46
|
+
* completion. Nothing ever falls through to it.
|
|
47
|
+
*/
|
|
48
|
+
const CIVIL_DATE = /^\d{4}-\d{2}-\d{2}$/;
|
|
49
|
+
function rowId(key, civilDate) {
|
|
50
|
+
if (typeof key !== "string" || key.length === 0) throw new Error("MongoDailyLedger: key must be a non-empty string");
|
|
51
|
+
if (typeof civilDate !== "string" || !CIVIL_DATE.test(civilDate)) throw new Error(`MongoDailyLedger: civilDate must be YYYY-MM-DD, got "${String(civilDate)}"`);
|
|
52
|
+
return `${key}|${civilDate}`;
|
|
53
|
+
}
|
|
54
|
+
/**
|
|
55
|
+
* Build a Mongo-backed daily ledger. Idempotent per `(connection,
|
|
56
|
+
* modelName)` like `createMongoLockAdapter`.
|
|
57
|
+
*
|
|
58
|
+
* @example
|
|
59
|
+
* import { createDailyGate } from '@classytic/arc/plugins';
|
|
60
|
+
* import { createMongoDailyLedger } from '@classytic/mongokit/lock';
|
|
61
|
+
*
|
|
62
|
+
* const gate = createDailyGate({
|
|
63
|
+
* key: 'digest', zone: 'Asia/Dubai', hour: 6, staleAfterMs: 15 * 60_000,
|
|
64
|
+
* ledger: createMongoDailyLedger({ connection, collectionName: 'app_daily_ledger' }),
|
|
65
|
+
* });
|
|
66
|
+
*/
|
|
67
|
+
function createMongoDailyLedger(options = {}) {
|
|
68
|
+
const { connection, collectionName = "mongo_daily_ledger", modelName = "MongoDailyLedger", nowFn = () => /* @__PURE__ */ new Date() } = options;
|
|
69
|
+
const model = getOrCreateLedgerModel(connection ?? mongoose, modelName, collectionName);
|
|
70
|
+
const sessionOpt = () => {
|
|
71
|
+
const s = options.session?.();
|
|
72
|
+
return s ? { session: s } : {};
|
|
73
|
+
};
|
|
74
|
+
/**
|
|
75
|
+
* Token-less (arc-shaped) claims this instance won and has not finished: rowId → tokens. The
|
|
76
|
+
* fallback for a `completeDay` / `releaseDay` called outside the invocation that claimed.
|
|
77
|
+
*/
|
|
78
|
+
const live = /* @__PURE__ */ new Map();
|
|
79
|
+
const invocation = new AsyncLocalStorage();
|
|
80
|
+
const slotToken = (slot) => {
|
|
81
|
+
for (let s = slot; s; s = s.prev) if (s.token !== void 0) return s.token;
|
|
82
|
+
};
|
|
83
|
+
const isLive = (id, token) => live.get(id)?.has(token) === true;
|
|
84
|
+
const forget = (id, token) => {
|
|
85
|
+
const set = live.get(id);
|
|
86
|
+
set?.delete(token);
|
|
87
|
+
if (set?.size === 0) live.delete(id);
|
|
88
|
+
};
|
|
89
|
+
/** The token-less caller's claim on the row: its invocation's, else the instance's only one. */
|
|
90
|
+
const tokenFor = (id) => {
|
|
91
|
+
const own = slotToken(invocation.getStore()?.get(id));
|
|
92
|
+
if (own !== void 0) return own;
|
|
93
|
+
const set = live.get(id);
|
|
94
|
+
return set?.size === 1 ? [...set][0] : void 0;
|
|
95
|
+
};
|
|
96
|
+
const validate = (key, civilDate, info) => {
|
|
97
|
+
const _id = rowId(key, civilDate);
|
|
98
|
+
const now = info?.now;
|
|
99
|
+
if (!(now instanceof Date) || Number.isNaN(now.getTime())) throw new Error("MongoDailyLedger.claimDay: info.now must be a valid Date");
|
|
100
|
+
const staleAfterMs = info.staleAfterMs;
|
|
101
|
+
if (staleAfterMs !== void 0 && (typeof staleAfterMs !== "number" || !Number.isFinite(staleAfterMs) || staleAfterMs < 0)) throw new Error("MongoDailyLedger.claimDay: info.staleAfterMs must be a finite number >= 0");
|
|
102
|
+
return {
|
|
103
|
+
_id,
|
|
104
|
+
now,
|
|
105
|
+
staleAfterMs
|
|
106
|
+
};
|
|
107
|
+
};
|
|
108
|
+
/** Try to win the row; the new claim's token, or `undefined` when not won. */
|
|
109
|
+
const claimRow = async (key, civilDate, v) => {
|
|
110
|
+
const { _id, now, staleAfterMs } = v;
|
|
111
|
+
const claimToken = randomUUID();
|
|
112
|
+
try {
|
|
113
|
+
if (staleAfterMs === void 0) {
|
|
114
|
+
await model.create([{
|
|
115
|
+
_id,
|
|
116
|
+
key,
|
|
117
|
+
civilDate,
|
|
118
|
+
claimedAt: now,
|
|
119
|
+
claimToken,
|
|
120
|
+
completed: false
|
|
121
|
+
}]);
|
|
122
|
+
return claimToken;
|
|
123
|
+
}
|
|
124
|
+
const res = await model.updateOne({
|
|
125
|
+
_id,
|
|
126
|
+
completed: false,
|
|
127
|
+
claimedAt: { $lt: new Date(now.getTime() - staleAfterMs) }
|
|
128
|
+
}, {
|
|
129
|
+
$set: {
|
|
130
|
+
key,
|
|
131
|
+
civilDate,
|
|
132
|
+
claimedAt: now,
|
|
133
|
+
claimToken,
|
|
134
|
+
completed: false
|
|
135
|
+
},
|
|
136
|
+
$unset: {
|
|
137
|
+
result: "",
|
|
138
|
+
completedAt: ""
|
|
139
|
+
}
|
|
140
|
+
}, { upsert: true });
|
|
141
|
+
return res.upsertedCount + res.modifiedCount > 0 ? claimToken : void 0;
|
|
142
|
+
} catch (err) {
|
|
143
|
+
if (err?.code === 11e3) return void 0;
|
|
144
|
+
throw err;
|
|
145
|
+
}
|
|
146
|
+
};
|
|
147
|
+
/** Complete the row while `token` still holds it uncompleted. */
|
|
148
|
+
const completeRow = async (_id, token, result) => {
|
|
149
|
+
return (await model.updateOne({
|
|
150
|
+
_id,
|
|
151
|
+
claimToken: token,
|
|
152
|
+
completed: false
|
|
153
|
+
}, { $set: {
|
|
154
|
+
completed: true,
|
|
155
|
+
completedAt: nowFn(),
|
|
156
|
+
...result !== void 0 ? { result } : {}
|
|
157
|
+
} }, sessionOpt())).modifiedCount > 0;
|
|
158
|
+
};
|
|
159
|
+
/** Delete the row while `token` still holds it uncompleted. */
|
|
160
|
+
const releaseRow = async (_id, token) => {
|
|
161
|
+
return (await model.deleteOne({
|
|
162
|
+
_id,
|
|
163
|
+
claimToken: token,
|
|
164
|
+
completed: false
|
|
165
|
+
}, sessionOpt())).deletedCount > 0;
|
|
166
|
+
};
|
|
167
|
+
return {
|
|
168
|
+
async claimDay(key, civilDate, info) {
|
|
169
|
+
const v = validate(key, civilDate, info);
|
|
170
|
+
const outer = invocation.getStore();
|
|
171
|
+
const scope = /* @__PURE__ */ new Map();
|
|
172
|
+
if (outer) for (const [id, slot] of outer) {
|
|
173
|
+
const t = slotToken(slot);
|
|
174
|
+
if (t === void 0 || isLive(id, t)) scope.set(id, slot);
|
|
175
|
+
}
|
|
176
|
+
const slot = { prev: outer?.get(v._id) };
|
|
177
|
+
scope.set(v._id, slot);
|
|
178
|
+
invocation.enterWith(scope);
|
|
179
|
+
const token = await claimRow(key, civilDate, v);
|
|
180
|
+
if (token === void 0) return false;
|
|
181
|
+
slot.token = token;
|
|
182
|
+
const set = live.get(v._id) ?? /* @__PURE__ */ new Set();
|
|
183
|
+
set.add(token);
|
|
184
|
+
live.set(v._id, set);
|
|
185
|
+
return true;
|
|
186
|
+
},
|
|
187
|
+
async completeDay(key, civilDate, result) {
|
|
188
|
+
const _id = rowId(key, civilDate);
|
|
189
|
+
const token = tokenFor(_id);
|
|
190
|
+
if (token === void 0) return;
|
|
191
|
+
await completeRow(_id, token, result);
|
|
192
|
+
forget(_id, token);
|
|
193
|
+
},
|
|
194
|
+
async releaseDay(key, civilDate) {
|
|
195
|
+
const _id = rowId(key, civilDate);
|
|
196
|
+
const token = tokenFor(_id);
|
|
197
|
+
if (token === void 0) return;
|
|
198
|
+
forget(_id, token);
|
|
199
|
+
await releaseRow(_id, token);
|
|
200
|
+
},
|
|
201
|
+
async claim(key, civilDate, info) {
|
|
202
|
+
const v = validate(key, civilDate, info);
|
|
203
|
+
const token = await claimRow(key, civilDate, v);
|
|
204
|
+
if (token === void 0) return null;
|
|
205
|
+
return {
|
|
206
|
+
key,
|
|
207
|
+
civilDate,
|
|
208
|
+
token,
|
|
209
|
+
claimedAt: v.now,
|
|
210
|
+
complete: (result) => completeRow(v._id, token, result),
|
|
211
|
+
release: () => releaseRow(v._id, token)
|
|
212
|
+
};
|
|
213
|
+
},
|
|
214
|
+
async adminCompleteDay(key, civilDate, result) {
|
|
215
|
+
const _id = rowId(key, civilDate);
|
|
216
|
+
return (await model.updateOne({
|
|
217
|
+
_id,
|
|
218
|
+
completed: false
|
|
219
|
+
}, { $set: {
|
|
220
|
+
completed: true,
|
|
221
|
+
completedAt: nowFn(),
|
|
222
|
+
...result !== void 0 ? { result } : {}
|
|
223
|
+
} }, sessionOpt())).modifiedCount > 0;
|
|
224
|
+
},
|
|
225
|
+
async inspect(key, civilDate) {
|
|
226
|
+
const doc = await model.findById(rowId(key, civilDate), null, sessionOpt()).lean();
|
|
227
|
+
if (!doc) return null;
|
|
228
|
+
const { _id: _ignored, ...row } = doc;
|
|
229
|
+
return row;
|
|
230
|
+
}
|
|
231
|
+
};
|
|
232
|
+
}
|
|
233
|
+
function getOrCreateLedgerModel(conn, modelName, collectionName) {
|
|
234
|
+
const existing = "models" in conn ? conn.models[modelName] : void 0;
|
|
235
|
+
if (existing) return existing;
|
|
236
|
+
const schema = new Schema({
|
|
237
|
+
_id: {
|
|
238
|
+
type: String,
|
|
239
|
+
required: true
|
|
240
|
+
},
|
|
241
|
+
key: {
|
|
242
|
+
type: String,
|
|
243
|
+
required: true
|
|
244
|
+
},
|
|
245
|
+
civilDate: {
|
|
246
|
+
type: String,
|
|
247
|
+
required: true
|
|
248
|
+
},
|
|
249
|
+
claimedAt: {
|
|
250
|
+
type: Date,
|
|
251
|
+
required: true
|
|
252
|
+
},
|
|
253
|
+
claimToken: { type: String },
|
|
254
|
+
completed: {
|
|
255
|
+
type: Boolean,
|
|
256
|
+
required: true,
|
|
257
|
+
default: false
|
|
258
|
+
},
|
|
259
|
+
completedAt: { type: Date },
|
|
260
|
+
result: { type: Schema.Types.Mixed }
|
|
261
|
+
}, {
|
|
262
|
+
versionKey: false,
|
|
263
|
+
timestamps: false,
|
|
264
|
+
_id: false,
|
|
265
|
+
minimize: false
|
|
266
|
+
});
|
|
267
|
+
schema.index({
|
|
268
|
+
key: 1,
|
|
269
|
+
civilDate: -1
|
|
270
|
+
});
|
|
271
|
+
return conn.model(modelName, schema, collectionName);
|
|
272
|
+
}
|
|
273
|
+
// src/lock/index.ts
|
|
3
274
|
/**
|
|
4
275
|
* Build a Mongo-backed lock adapter. Idempotent — the underlying
|
|
5
276
|
* model is registered once per `(connection, modelName)` pair, so
|
|
@@ -7,27 +278,30 @@ import mongoose, { Schema } from "mongoose";
|
|
|
7
278
|
* collection (no duplicate-model errors).
|
|
8
279
|
*/
|
|
9
280
|
function createMongoLockAdapter(options = {}) {
|
|
10
|
-
const { connection, collectionName = "mongo_locks", modelName = "MongoLock", defaultLeaseMs = 3e4 } = options;
|
|
281
|
+
const { connection, collectionName = "mongo_locks", modelName = "MongoLock", defaultLeaseMs = 3e4, nowFn = () => /* @__PURE__ */ new Date() } = options;
|
|
11
282
|
const model = getOrCreateModel(connection ?? mongoose, modelName, collectionName);
|
|
12
283
|
return {
|
|
13
284
|
async tryAcquire(name, holderId, leaseMs) {
|
|
14
285
|
const ms = leaseMs > 0 ? leaseMs : defaultLeaseMs;
|
|
15
|
-
const now =
|
|
286
|
+
const now = nowFn();
|
|
16
287
|
const expiresAt = new Date(now.getTime() + ms);
|
|
17
288
|
try {
|
|
289
|
+
const holder = { $literal: holderId };
|
|
18
290
|
const result = await model.findOneAndUpdate({
|
|
19
291
|
_id: name,
|
|
20
292
|
$or: [{ expiresAt: { $lt: now } }, { holder: holderId }]
|
|
21
|
-
}, {
|
|
22
|
-
$
|
|
23
|
-
holder:
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
293
|
+
}, [{ $set: {
|
|
294
|
+
acquiredAt: { $cond: [
|
|
295
|
+
{ $and: [{ $eq: ["$holder", holder] }, { $ne: [{ $type: "$acquiredAt" }, "missing"] }] },
|
|
296
|
+
"$acquiredAt",
|
|
297
|
+
{ $literal: now }
|
|
298
|
+
] },
|
|
299
|
+
holder,
|
|
300
|
+
expiresAt: { $literal: expiresAt }
|
|
301
|
+
} }], {
|
|
28
302
|
upsert: true,
|
|
29
303
|
returnDocument: "after",
|
|
30
|
-
|
|
304
|
+
updatePipeline: true
|
|
31
305
|
}).lean();
|
|
32
306
|
return !!result && result.holder === holderId;
|
|
33
307
|
} catch (err) {
|
|
@@ -35,6 +309,68 @@ function createMongoLockAdapter(options = {}) {
|
|
|
35
309
|
throw err;
|
|
36
310
|
}
|
|
37
311
|
},
|
|
312
|
+
async acquire(name, holderId, leaseMs) {
|
|
313
|
+
const ms = leaseMs > 0 ? leaseMs : defaultLeaseMs;
|
|
314
|
+
const now = nowFn();
|
|
315
|
+
const expiresAt = new Date(now.getTime() + ms);
|
|
316
|
+
const holder = { $literal: holderId };
|
|
317
|
+
const won = "$__lockWon";
|
|
318
|
+
const pipeline = [
|
|
319
|
+
{ $set: { __lockWon: { $or: [{ $lt: ["$expiresAt", { $literal: now }] }, { $eq: ["$holder", holder] }] } } },
|
|
320
|
+
{ $set: {
|
|
321
|
+
acquiredAt: { $cond: [
|
|
322
|
+
won,
|
|
323
|
+
{ $cond: [
|
|
324
|
+
{ $and: [{ $eq: ["$holder", holder] }, { $ne: [{ $type: "$acquiredAt" }, "missing"] }] },
|
|
325
|
+
"$acquiredAt",
|
|
326
|
+
{ $literal: now }
|
|
327
|
+
] },
|
|
328
|
+
"$acquiredAt"
|
|
329
|
+
] },
|
|
330
|
+
holder: { $cond: [
|
|
331
|
+
won,
|
|
332
|
+
holder,
|
|
333
|
+
"$holder"
|
|
334
|
+
] },
|
|
335
|
+
expiresAt: { $cond: [
|
|
336
|
+
won,
|
|
337
|
+
{ $literal: expiresAt },
|
|
338
|
+
"$expiresAt"
|
|
339
|
+
] }
|
|
340
|
+
} },
|
|
341
|
+
{ $unset: "__lockWon" }
|
|
342
|
+
];
|
|
343
|
+
for (let attempt = 0;; attempt++) try {
|
|
344
|
+
const before = await model.findOneAndUpdate({ _id: name }, pipeline, {
|
|
345
|
+
upsert: true,
|
|
346
|
+
returnDocument: "before",
|
|
347
|
+
updatePipeline: true
|
|
348
|
+
}).lean();
|
|
349
|
+
if (!before) return {
|
|
350
|
+
acquired: true,
|
|
351
|
+
holder: holderId,
|
|
352
|
+
acquiredAt: now,
|
|
353
|
+
expiresAt
|
|
354
|
+
};
|
|
355
|
+
const mine = before.holder === holderId;
|
|
356
|
+
if (mine || before.expiresAt.getTime() < now.getTime()) return {
|
|
357
|
+
acquired: true,
|
|
358
|
+
holder: holderId,
|
|
359
|
+
previousHolder: before.holder,
|
|
360
|
+
acquiredAt: mine && before.acquiredAt ? before.acquiredAt : now,
|
|
361
|
+
expiresAt
|
|
362
|
+
};
|
|
363
|
+
return {
|
|
364
|
+
acquired: false,
|
|
365
|
+
holder: before.holder,
|
|
366
|
+
acquiredAt: before.acquiredAt,
|
|
367
|
+
expiresAt: before.expiresAt
|
|
368
|
+
};
|
|
369
|
+
} catch (err) {
|
|
370
|
+
if (err?.code === 11e3 && attempt < 3) continue;
|
|
371
|
+
throw err;
|
|
372
|
+
}
|
|
373
|
+
},
|
|
38
374
|
async release(name, holderId) {
|
|
39
375
|
return !!await model.findOneAndDelete({
|
|
40
376
|
_id: name,
|
|
@@ -44,7 +380,7 @@ function createMongoLockAdapter(options = {}) {
|
|
|
44
380
|
async inspect(name) {
|
|
45
381
|
const doc = await model.findById(name).lean();
|
|
46
382
|
if (!doc) return null;
|
|
47
|
-
if (doc.expiresAt.getTime() <=
|
|
383
|
+
if (doc.expiresAt.getTime() <= nowFn().getTime()) return null;
|
|
48
384
|
return {
|
|
49
385
|
name,
|
|
50
386
|
holder: doc.holder,
|
|
@@ -88,5 +424,4 @@ function getOrCreateModel(conn, modelName, collectionName) {
|
|
|
88
424
|
schema.index({ expiresAt: 1 }, { expireAfterSeconds: 0 });
|
|
89
425
|
return conn.model(modelName, schema, collectionName);
|
|
90
426
|
}
|
|
91
|
-
|
|
92
|
-
export { createMongoLockAdapter };
|
|
427
|
+
export { createMongoDailyLedger, createMongoLockAdapter };
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
|
|
1
|
+
// src/utils/logger.ts
|
|
2
2
|
const noop = () => {};
|
|
3
3
|
let current = {
|
|
4
4
|
warn: console.warn.bind(console),
|
|
@@ -22,5 +22,4 @@ function configureLogger(config) {
|
|
|
22
22
|
function warn(message, ...args) {
|
|
23
23
|
current.warn(message, ...args);
|
|
24
24
|
}
|
|
25
|
-
//#endregion
|
|
26
25
|
export { warn as n, configureLogger as t };
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { t as createError } from "./error-
|
|
2
|
-
|
|
1
|
+
import { t as createError } from "./error-DjdmPLWO.mjs";
|
|
2
|
+
// src/plugins/batch-operations.plugin.ts
|
|
3
3
|
/**
|
|
4
4
|
* Batch operations plugin.
|
|
5
5
|
*
|
|
@@ -123,8 +123,7 @@ function batchOperationsPlugin() {
|
|
|
123
123
|
}
|
|
124
124
|
};
|
|
125
125
|
}
|
|
126
|
-
|
|
127
|
-
//#region src/plugins/method-registry.plugin.ts
|
|
126
|
+
// src/plugins/method-registry.plugin.ts
|
|
128
127
|
/**
|
|
129
128
|
* Method registry plugin that enables dynamic method registration
|
|
130
129
|
*/
|
|
@@ -158,5 +157,4 @@ function methodRegistryPlugin() {
|
|
|
158
157
|
}
|
|
159
158
|
};
|
|
160
159
|
}
|
|
161
|
-
//#endregion
|
|
162
160
|
export { batchOperationsPlugin as n, methodRegistryPlugin as t };
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import mongoose from "mongoose";
|
|
2
|
-
|
|
2
|
+
// src/model-registry.ts
|
|
3
3
|
/**
|
|
4
4
|
* Model registration — the ONE place `mongoose.models` is touched.
|
|
5
5
|
*
|
|
@@ -63,5 +63,4 @@ function defineModel(name, schema, options) {
|
|
|
63
63
|
}
|
|
64
64
|
return target ? target.model(name, schema(), options.collection) : mongoose.model(name, schema(), options.collection);
|
|
65
65
|
}
|
|
66
|
-
//#endregion
|
|
67
66
|
export { defineModel as n, isModelRegistered as r, ModelCollisionError as t };
|
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import { r as isObjectIdInstance } from "./id-resolution-
|
|
1
|
+
import { r as isObjectIdInstance } from "./id-resolution-Cqh49d9J.mjs";
|
|
2
2
|
import mongoose from "mongoose";
|
|
3
3
|
import { applyFieldRules, collectFieldsToOmit } from "@classytic/repo-core/schema";
|
|
4
|
-
|
|
4
|
+
// src/utils/mongooseToJsonSchema.ts
|
|
5
5
|
/**
|
|
6
6
|
* Mongoose → JSON Schema converter.
|
|
7
7
|
*
|
|
@@ -600,5 +600,4 @@ function buildJsonSchemaForQuery(_tree, options) {
|
|
|
600
600
|
for (const [k, v] of Object.entries(filterable)) if (basePagination.properties) basePagination.properties[k] = v && typeof v === "object" && "type" in v ? v : { type: "string" };
|
|
601
601
|
return basePagination;
|
|
602
602
|
}
|
|
603
|
-
//#endregion
|
|
604
603
|
export { buildCrudSchemasFromMongooseSchema as n, buildCrudSchemasFromModel as t };
|
|
@@ -1,9 +1,8 @@
|
|
|
1
|
-
import { A as ObjectId } from "./pagination-
|
|
2
|
-
import { l as Plugin, p as RepositoryContext } from "./repository-
|
|
1
|
+
import { A as ObjectId } from "./pagination-DAUg5zOY.mjs";
|
|
2
|
+
import { l as Plugin, p as RepositoryContext } from "./repository-DzVIwhU2.mjs";
|
|
3
3
|
import mongoose, { Connection } from "mongoose";
|
|
4
4
|
import { CacheAdapter as CacheAdapter$1, CacheOptions, RepositoryCacheHandle as RepositoryCacheHandle$1, RepositoryCachePluginOptions, cachePlugin } from "@classytic/repo-core/cache";
|
|
5
5
|
import { TenantConfig } from "@classytic/repo-core/tenant";
|
|
6
|
-
//#region src/plugins/audit-trail.plugin.d.ts
|
|
7
6
|
/**
|
|
8
7
|
* Audit write delivery mode.
|
|
9
8
|
*
|
|
@@ -262,8 +261,6 @@ interface AuditTrailMethods {
|
|
|
262
261
|
operation?: AuditOperation;
|
|
263
262
|
}): Promise<AuditQueryResult>;
|
|
264
263
|
}
|
|
265
|
-
//#endregion
|
|
266
|
-
//#region src/plugins/custom-id.plugin.d.ts
|
|
267
264
|
/**
|
|
268
265
|
* Generator function that produces a unique ID.
|
|
269
266
|
* Receives the full repository context for conditional logic.
|
|
@@ -277,6 +274,45 @@ interface CustomIdOptions {
|
|
|
277
274
|
/** Only generate if the field is missing/empty (default: true) */
|
|
278
275
|
generateOnlyIfEmpty?: boolean;
|
|
279
276
|
}
|
|
277
|
+
/** Options for {@link createSequenceCounter}. */
|
|
278
|
+
interface SequenceCounterOptions {
|
|
279
|
+
/** Mongoose connection. @default the default `mongoose.connection` */
|
|
280
|
+
connection?: mongoose.Connection;
|
|
281
|
+
/**
|
|
282
|
+
* Collection holding the counters, for hosts with a collection-naming
|
|
283
|
+
* rule (e.g. an app prefix). @default `'_mongokit_counters'`
|
|
284
|
+
*/
|
|
285
|
+
collection?: string;
|
|
286
|
+
}
|
|
287
|
+
/**
|
|
288
|
+
* The atomic counter API bound to one connection + collection. Same
|
|
289
|
+
* semantics as {@link getNextSequence} / {@link readSequence} /
|
|
290
|
+
* {@link ensureSequenceAtLeast}, with an optional session on every call.
|
|
291
|
+
*/
|
|
292
|
+
interface SequenceCounter {
|
|
293
|
+
/** Atomic `$inc` + upsert; returns the value after the increment. */
|
|
294
|
+
next(counterKey: string, increment?: number, session?: mongoose.ClientSession): Promise<number>;
|
|
295
|
+
/** Current value, or `null` when the counter was never created. */
|
|
296
|
+
read(counterKey: string, session?: mongoose.ClientSession): Promise<number | null>;
|
|
297
|
+
/** Raise to at least `floor` (`$max` + upsert); never lowers. Returns the value after. */
|
|
298
|
+
ensureAtLeast(counterKey: string, floor: number, session?: mongoose.ClientSession): Promise<number>;
|
|
299
|
+
/**
|
|
300
|
+
* Next value of the counter `'<baseKey><sep><civil period>'`, which resets
|
|
301
|
+
* every civil year / month / day in `timeZone`. See {@link getNextPeriodSequence}.
|
|
302
|
+
*/
|
|
303
|
+
nextInPeriod(baseKey: string, options: PeriodSequenceOptions): Promise<PeriodSequenceResult>;
|
|
304
|
+
}
|
|
305
|
+
/**
|
|
306
|
+
* Bind the atomic counter API to a connection and, optionally, a
|
|
307
|
+
* collection other than `_mongokit_counters`.
|
|
308
|
+
*
|
|
309
|
+
* @example
|
|
310
|
+
* const counters = createSequenceCounter({ connection, collection: 'app_counters' });
|
|
311
|
+
* await withTransaction(connection, async (session) => {
|
|
312
|
+
* const seq = await counters.next('alert.stream', 1, session);
|
|
313
|
+
* });
|
|
314
|
+
*/
|
|
315
|
+
declare function createSequenceCounter(options?: SequenceCounterOptions): SequenceCounter;
|
|
280
316
|
/**
|
|
281
317
|
* Atomically increment and return the next sequence value for a given key.
|
|
282
318
|
* Uses `findOneAndUpdate` with `upsert` + `$inc` — fully atomic even under
|
|
@@ -311,7 +347,7 @@ declare function getNextSequence(counterKey: string, increment?: number, connect
|
|
|
311
347
|
* Current value of a counter, or `null` when it has never been created.
|
|
312
348
|
* `null` and `0` differ: only a missing counter needs seeding.
|
|
313
349
|
*/
|
|
314
|
-
declare function readSequence(counterKey: string, connection?: mongoose.Connection): Promise<number | null>;
|
|
350
|
+
declare function readSequence(counterKey: string, connection?: mongoose.Connection, session?: mongoose.ClientSession): Promise<number | null>;
|
|
315
351
|
/**
|
|
316
352
|
* Raise a counter to at least `floor` — never lowers it. Atomic (`$max` +
|
|
317
353
|
* upsert), so concurrent seeders converge on the highest floor.
|
|
@@ -322,7 +358,77 @@ declare function readSequence(counterKey: string, connection?: mongoose.Connecti
|
|
|
322
358
|
*
|
|
323
359
|
* @returns The counter's value after the raise.
|
|
324
360
|
*/
|
|
325
|
-
declare function ensureSequenceAtLeast(counterKey: string, floor: number, connection?: mongoose.Connection): Promise<number>;
|
|
361
|
+
declare function ensureSequenceAtLeast(counterKey: string, floor: number, connection?: mongoose.Connection, session?: mongoose.ClientSession): Promise<number>;
|
|
362
|
+
/** The civil period a period-scoped counter resets on. */
|
|
363
|
+
type SequencePeriod = 'year' | 'month' | 'day';
|
|
364
|
+
/**
|
|
365
|
+
* The civil period of an instant in an IANA time zone: `'2026'` (year),
|
|
366
|
+
* `'2026-03'` (month) or `'2026-03-14'` (day). The period suffix every
|
|
367
|
+
* period-scoped counter key ends with.
|
|
368
|
+
*
|
|
369
|
+
* @example
|
|
370
|
+
* civilPeriodKey(new Date('2026-12-31T21:00:00Z'), 'year', 'Asia/Riyadh'); // '2027'
|
|
371
|
+
* civilPeriodKey(new Date('2026-12-31T21:00:00Z'), 'year', 'UTC'); // '2026'
|
|
372
|
+
*/
|
|
373
|
+
declare function civilPeriodKey(at: Date, period: SequencePeriod, timeZone: string): string;
|
|
374
|
+
/** Options for {@link periodCounterKey}, {@link getNextPeriodSequence} and `SequenceCounter.nextInPeriod`. */
|
|
375
|
+
interface PeriodSequenceKeyOptions {
|
|
376
|
+
/** Civil period the counter resets on. */
|
|
377
|
+
period: SequencePeriod;
|
|
378
|
+
/** IANA time zone whose civil calendar decides the period (e.g. `'Asia/Riyadh'`, `'UTC'`). */
|
|
379
|
+
timeZone: string;
|
|
380
|
+
/**
|
|
381
|
+
* The instant whose civil date picks the period (e.g. the record's
|
|
382
|
+
* `reportedAt`, so a backdated record numbers in its own year).
|
|
383
|
+
* @default now
|
|
384
|
+
*/
|
|
385
|
+
at?: Date;
|
|
386
|
+
/**
|
|
387
|
+
* Joins the base key and the period: `'<base><sep><period>'`.
|
|
388
|
+
* Pass `'.'` to keep counters an app already created as `occ.occurrence.2026`.
|
|
389
|
+
* @default ':'
|
|
390
|
+
*/
|
|
391
|
+
keySeparator?: string;
|
|
392
|
+
}
|
|
393
|
+
/** Options for {@link getNextPeriodSequence} / `SequenceCounter.nextInPeriod`. */
|
|
394
|
+
interface PeriodSequenceOptions extends PeriodSequenceKeyOptions {
|
|
395
|
+
/** @default 1 */
|
|
396
|
+
increment?: number;
|
|
397
|
+
/** Client session: the bump joins the caller's transaction. */
|
|
398
|
+
session?: mongoose.ClientSession;
|
|
399
|
+
}
|
|
400
|
+
/** A period-scoped counter value plus the period it was issued in. */
|
|
401
|
+
interface PeriodSequenceResult {
|
|
402
|
+
/** Value after the increment; `1` for the first value of a new period. */
|
|
403
|
+
seq: number;
|
|
404
|
+
/** The civil period (`'2026'`, `'2026-03'`, `'2026-03-14'`), for formatting the id. */
|
|
405
|
+
period: string;
|
|
406
|
+
/** The counter document's key (`'<base><sep><period>'`), for `read` / `ensureAtLeast`. */
|
|
407
|
+
counterKey: string;
|
|
408
|
+
}
|
|
409
|
+
/**
|
|
410
|
+
* The counter key and civil period for a base key at an instant. Use it to
|
|
411
|
+
* `read` / `ensureAtLeast` the same counter `getNextPeriodSequence` bumps.
|
|
412
|
+
*/
|
|
413
|
+
declare function periodCounterKey(baseKey: string, options: PeriodSequenceKeyOptions): {
|
|
414
|
+
counterKey: string;
|
|
415
|
+
period: string;
|
|
416
|
+
};
|
|
417
|
+
/**
|
|
418
|
+
* Atomically issue the next value of a counter that resets every civil
|
|
419
|
+
* year / month / day in an IANA time zone. The period is derived from `at`
|
|
420
|
+
* (default now) in `timeZone`, so every replica agrees on it whatever its
|
|
421
|
+
* `TZ`, and DST never moves a boundary.
|
|
422
|
+
*
|
|
423
|
+
* @example Yearly reference `OC-2026-000123` in Riyadh
|
|
424
|
+
* const { seq, period } = await getNextPeriodSequence('occ.occurrence', {
|
|
425
|
+
* period: 'year', timeZone: 'Asia/Riyadh', at: reportedAt, connection, session,
|
|
426
|
+
* });
|
|
427
|
+
* const ref = `OC-${period}-${String(seq).padStart(6, '0')}`;
|
|
428
|
+
*/
|
|
429
|
+
declare function getNextPeriodSequence(baseKey: string, options: PeriodSequenceOptions & {
|
|
430
|
+
connection?: mongoose.Connection;
|
|
431
|
+
}): Promise<PeriodSequenceResult>;
|
|
326
432
|
interface SequentialIdOptions {
|
|
327
433
|
/** Prefix string (e.g., 'INV', 'ORD') */
|
|
328
434
|
prefix: string;
|
|
@@ -337,6 +443,11 @@ interface SequentialIdOptions {
|
|
|
337
443
|
separator?: string;
|
|
338
444
|
/** Custom counter key override (default: model.modelName) */
|
|
339
445
|
counterKey?: string;
|
|
446
|
+
/**
|
|
447
|
+
* Counter collection, same as `createSequenceCounter({ collection })`
|
|
448
|
+
* (for hosts with a collection-naming rule). @default `'_mongokit_counters'`
|
|
449
|
+
*/
|
|
450
|
+
counterCollection?: string;
|
|
340
451
|
}
|
|
341
452
|
/**
|
|
342
453
|
* Generator: Simple sequential counter.
|
|
@@ -413,6 +524,30 @@ interface DateSequentialIdOptions {
|
|
|
413
524
|
* stays invisible until one host is configured otherwise.
|
|
414
525
|
*/
|
|
415
526
|
timezone?: 'local' | 'utc';
|
|
527
|
+
/**
|
|
528
|
+
* IANA time zone whose civil calendar decides the period (e.g.
|
|
529
|
+
* `'Asia/Riyadh'`). Wins over `timezone`. Read through Intl, so every
|
|
530
|
+
* replica agrees on the boundary whatever its `TZ`, and DST never moves it.
|
|
531
|
+
* Invalid zones throw when the generator is built.
|
|
532
|
+
*/
|
|
533
|
+
timeZone?: string;
|
|
534
|
+
/**
|
|
535
|
+
* The instant whose civil date picks the period, e.g.
|
|
536
|
+
* `(ctx) => ctx.data?.reportedAt` so a backdated record numbers in its own
|
|
537
|
+
* period. `undefined` / `null` falls back to now; any other non-Date throws.
|
|
538
|
+
* @default now
|
|
539
|
+
*/
|
|
540
|
+
at?: (context: RepositoryContext) => Date | undefined | null;
|
|
541
|
+
/**
|
|
542
|
+
* Base counter key (the tenant id, under `scope: 'tenant'`, and the period
|
|
543
|
+
* are appended). @default `model.modelName`
|
|
544
|
+
*/
|
|
545
|
+
counterKey?: string;
|
|
546
|
+
/**
|
|
547
|
+
* Counter collection, same as `createSequenceCounter({ collection })`
|
|
548
|
+
* (for hosts with a collection-naming rule). @default `'_mongokit_counters'`
|
|
549
|
+
*/
|
|
550
|
+
counterCollection?: string;
|
|
416
551
|
}
|
|
417
552
|
/**
|
|
418
553
|
* Generator: Date-partitioned sequential counter.
|
|
@@ -493,8 +628,6 @@ declare function prefixedId(options: PrefixedIdOptions): IdGenerator;
|
|
|
493
628
|
* ```
|
|
494
629
|
*/
|
|
495
630
|
declare function customIdPlugin(options: CustomIdOptions): Plugin;
|
|
496
|
-
//#endregion
|
|
497
|
-
//#region src/plugins/multi-tenant.plugin.d.ts
|
|
498
631
|
/**
|
|
499
632
|
* Static tenant fields are picked from `@classytic/repo-core/tenant` so the
|
|
500
633
|
* vocabulary (`tenantField`, `contextKey`, `required`, `fieldType`) stays
|
|
@@ -653,5 +786,4 @@ declare function adminBypass(options: {
|
|
|
653
786
|
roleField?: string;
|
|
654
787
|
adminRoles: readonly string[];
|
|
655
788
|
}): (context: RepositoryContext, operation: string) => boolean;
|
|
656
|
-
|
|
657
|
-
export { EnsureAuditTrailReadyOptions as A, AuditQueryOptions as C, AuditTrailOptions as D, AuditTrailMode as E, ensureAuditTrailReady as M, AuditTrailQuery as O, AuditOperation as S, AuditTrailMethods as T, CacheOptions as _, DateSequentialIdOptions as a, cachePlugin as b, SequentialIdOptions as c, ensureSequenceAtLeast as d, getNextSequence as f, CacheAdapter$1 as g, sequentialId as h, CustomIdOptions as i, auditTrailPlugin as j, AuditTrailQueryOptions as k, customIdPlugin as l, readSequence as m, adminBypass as n, IdGenerator as o, prefixedId as p, multiTenantPlugin as r, PrefixedIdOptions as s, MultiTenantOptions as t, dateSequentialId as u, RepositoryCacheHandle$1 as v, AuditQueryResult as w, AuditEntry as x, RepositoryCachePluginOptions as y };
|
|
789
|
+
export { cachePlugin as A, EnsureAuditTrailReadyOptions as B, prefixedId as C, CacheOptions as D, CacheAdapter$1 as E, AuditTrailMethods as F, ensureAuditTrailReady as H, AuditTrailMode as I, AuditTrailOptions as L, AuditOperation as M, AuditQueryOptions as N, RepositoryCacheHandle$1 as O, AuditQueryResult as P, AuditTrailQuery as R, periodCounterKey as S, sequentialId as T, auditTrailPlugin as V, customIdPlugin as _, DateSequentialIdOptions as a, getNextPeriodSequence as b, PeriodSequenceOptions as c, SequenceCounter as d, SequenceCounterOptions as f, createSequenceCounter as g, civilPeriodKey as h, CustomIdOptions as i, AuditEntry as j, RepositoryCachePluginOptions as k, PeriodSequenceResult as l, SequentialIdOptions as m, adminBypass as n, IdGenerator as o, SequencePeriod as p, multiTenantPlugin as r, PeriodSequenceKeyOptions as s, MultiTenantOptions as t, PrefixedIdOptions as u, dateSequentialId as v, readSequence as w, getNextSequence as x, ensureSequenceAtLeast as y, AuditTrailQueryOptions as z };
|