@classytic/mongokit 3.43.1 → 3.45.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.
Files changed (92) hide show
  1. package/README.md +18 -3
  2. package/dist/{PaginationEngine-DZnkbSrr.mjs → PaginationEngine-BRlLTQQz.mjs} +13 -27
  3. package/dist/{PaginationEngine-CRHyuUtw.d.mts → PaginationEngine-BWb-c47a.d.mts} +1 -3
  4. package/dist/{Repository-DnL4xk5w.d.mts → Repository-DJuRmBNx.d.mts} +44 -13
  5. package/dist/{Repository-Dj6xqPxJ.mjs → Repository-DheA7oW-.mjs} +330 -112
  6. package/dist/actions/index.d.mts +1 -1
  7. package/dist/actions/index.mjs +2 -2
  8. package/dist/{actions-ChYfkPYP.mjs → actions-DKQx9ToJ.mjs} +3 -4
  9. package/dist/adapter/index.d.mts +6 -10
  10. package/dist/adapter/index.mjs +1 -1
  11. package/dist/{adapter-CkMoMF83.mjs → adapter-Qzgc3ZD_.mjs} +4 -6
  12. package/dist/ai/index.d.mts +21 -8
  13. package/dist/ai/index.mjs +15 -9
  14. package/dist/better-auth/index.d.mts +21 -20
  15. package/dist/better-auth/index.mjs +12 -23
  16. package/dist/{coercion-BjdPX3YF.d.mts → coercion-COp9DRNw.d.mts} +0 -2
  17. package/dist/{create-repository-UjwPWR1z.mjs → create-repository-C9DHHcl7.mjs} +4 -5
  18. package/dist/{create-repository-CJtVdwig.d.mts → create-repository-DG-gwOf0.d.mts} +5 -7
  19. package/dist/{derive-DRBiegRH.mjs → derive-Dxsc31fV.mjs} +3 -6
  20. package/dist/{error-BuByZwKU.mjs → error-DjdmPLWO.mjs} +1 -2
  21. package/dist/{field-selection-FSQFLpsU.mjs → field-selection-DPFaFw9Y.mjs} +1 -2
  22. package/dist/{id-chunks-BmAwsqNk.mjs → id-chunks-DH-RAZWG.mjs} +13 -8
  23. package/dist/{id-resolution-BqDrk0S2.mjs → id-resolution-Cqh49d9J.mjs} +1 -2
  24. package/dist/idempotency/index.d.mts +4 -7
  25. package/dist/idempotency/index.mjs +1 -2
  26. package/dist/{index-SYF8N28D.d.mts → index-5mhQ63_B.d.mts} +3 -4
  27. package/dist/{index-C0AjVqX3.d.mts → index-ehGZLbrd.d.mts} +2 -8
  28. package/dist/index.d.mts +70 -102
  29. package/dist/index.mjs +36 -52
  30. package/dist/indexes/verify-indexes.d.mts +8 -11
  31. package/dist/indexes/verify-indexes.mjs +1 -2
  32. package/dist/{indexes-DIjMpYES.d.mts → indexes-FfyOuhDK.d.mts} +0 -2
  33. package/dist/{join-scope-DSAznE8E.mjs → join-scope-C1gOtZ59.mjs} +2 -3
  34. package/dist/kernel-conformance/index.d.mts +39 -13
  35. package/dist/kernel-conformance/index.mjs +4 -7
  36. package/dist/lock/index.d.mts +134 -7
  37. package/dist/lock/index.mjs +349 -14
  38. package/dist/{logger-K7dPmu2U.mjs → logger-hbWOlj_X.mjs} +1 -2
  39. package/dist/{method-registry.plugin-C63pGn1d.mjs → method-registry.plugin-BeJfQBJV.mjs} +5 -7
  40. package/dist/{model-registry-ClKtWiHa.mjs → model-registry-DrVfJ3Nt.mjs} +1 -2
  41. package/dist/{mongooseToJsonSchema-C3k4ide0.mjs → mongooseToJsonSchema-DMDotz4_.mjs} +2 -3
  42. package/dist/{multi-tenant.plugin-B_q9NUHc.d.mts → multi-tenant.plugin-BTPtCLNK.d.mts} +143 -11
  43. package/dist/{operations-XiFgG5US.d.mts → operations-D6XsHx4e.d.mts} +19 -11
  44. package/dist/outbox/index.d.mts +24 -9
  45. package/dist/outbox/index.mjs +17 -6
  46. package/dist/pagination/PaginationEngine.d.mts +1 -1
  47. package/dist/pagination/PaginationEngine.mjs +1 -1
  48. package/dist/pagination/utils/limits.d.mts +6 -9
  49. package/dist/pagination/utils/limits.mjs +2 -3
  50. package/dist/{pagination-D6psses0.d.mts → pagination-BAM9cA4N.d.mts} +6 -16
  51. package/dist/{plugin-options-Cirmb4Kp.d.mts → plugin-options-DrNGWV5b.d.mts} +2 -4
  52. package/dist/plugins/index.d.mts +6 -7
  53. package/dist/plugins/index.mjs +6 -7
  54. package/dist/query/primitives/coercion.d.mts +1 -1
  55. package/dist/query/primitives/coercion.mjs +2 -3
  56. package/dist/query/primitives/geo.d.mts +11 -14
  57. package/dist/query/primitives/geo.mjs +1 -2
  58. package/dist/query/primitives/indexes.d.mts +1 -1
  59. package/dist/query/primitives/indexes.mjs +1 -2
  60. package/dist/{query-defaults-BxUcSOoF.mjs → query-defaults-DwvWUjZU.mjs} +18 -54
  61. package/dist/read-model/index.d.mts +18 -21
  62. package/dist/read-model/index.mjs +3 -4
  63. package/dist/{repository-MqAP409e.d.mts → repository-B0aFVgP2.d.mts} +25 -29
  64. package/dist/retention-purge-CCd_VXUf.d.mts +38 -0
  65. package/dist/{rolldown-runtime-D7D4PA-g.mjs → rolldown-runtime-D8jQpDG7.mjs} +1 -2
  66. package/dist/search/index.d.mts +1 -1
  67. package/dist/search/index.mjs +1 -1
  68. package/dist/sync/index.d.mts +113 -17
  69. package/dist/sync/index.mjs +421 -65
  70. package/dist/tenant/index.d.mts +8 -11
  71. package/dist/tenant/index.mjs +1 -2
  72. package/dist/testkit/index.d.mts +179 -23
  73. package/dist/testkit/index.mjs +421 -23
  74. package/dist/{timestamp.plugin-DpOWavVI.mjs → timestamp.plugin-B-IJrlYb.mjs} +192 -49
  75. package/dist/{to-plain-vksRrLtc.mjs → to-plain-CEKv_ylg.mjs} +2 -4
  76. package/dist/{to-plain-o5tUY2nV.d.mts → to-plain-Do-8jTKC.d.mts} +2 -16
  77. package/dist/{transaction-DmiB4k2P.mjs → transaction-C6Oj941P.mjs} +18 -19
  78. package/dist/{type-utils-CLzRFtIA.d.mts → type-utils-CKvuewAL.d.mts} +0 -2
  79. package/dist/{update-WgeAUJ_I.mjs → update-CYaJMu6j.mjs} +13 -23
  80. package/dist/usage/index.d.mts +2 -5
  81. package/dist/usage/index.mjs +8 -6
  82. package/dist/utils/index.d.mts +8 -10
  83. package/dist/utils/index.mjs +7 -7
  84. package/dist/{validation-chain.plugin-BAeC5eVT.d.mts → validation-chain.plugin-COYrUdd8.d.mts} +150 -48
  85. package/dist/{validation-chain.plugin-DRApTmkN.mjs → validation-chain.plugin-DJplVJ12.mjs} +210 -55
  86. package/llms.txt +33 -0
  87. package/package.json +29 -25
  88. package/skills/mongokit/SKILL.md +112 -0
  89. package/skills/mongokit/references/pagination-search.md +87 -0
  90. package/skills/mongokit/references/plugins-tenancy.md +103 -0
  91. package/skills/mongokit/references/repository-api.md +83 -0
  92. package/skills/mongokit/references/transactions-outbox.md +103 -0
@@ -1,5 +1,276 @@
1
1
  import mongoose, { Schema } from "mongoose";
2
- //#region src/lock/index.ts
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 = /* @__PURE__ */ new Date();
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
- $set: {
23
- holder: holderId,
24
- expiresAt
25
- },
26
- $setOnInsert: { acquiredAt: now }
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
- setDefaultsOnInsert: true
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() <= Date.now()) return null;
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
- //#endregion
92
- export { createMongoLockAdapter };
427
+ export { createMongoDailyLedger, createMongoLockAdapter };
@@ -1,4 +1,4 @@
1
- //#region src/utils/logger.ts
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-BuByZwKU.mjs";
2
- //#region src/plugins/batch-operations.plugin.ts
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
  *
@@ -31,7 +31,8 @@ const BULK_WRITE_OPTIONS = [
31
31
  "bypassDocumentValidation",
32
32
  "comment",
33
33
  "let",
34
- "ignoreUndefined"
34
+ "ignoreUndefined",
35
+ "maxTimeMS"
35
36
  ];
36
37
  /**
37
38
  * Driver options that EXIST but this method does not forward.
@@ -51,7 +52,6 @@ const BULK_WRITE_OPTIONS = [
51
52
  const UNSUPPORTED_DRIVER_OPTIONS = /* @__PURE__ */ new Set([
52
53
  "forceServerObjectId",
53
54
  "timeoutMS",
54
- "maxTimeMS",
55
55
  "retryWrites",
56
56
  "checkKeys",
57
57
  "serializeFunctions",
@@ -123,8 +123,7 @@ function batchOperationsPlugin() {
123
123
  }
124
124
  };
125
125
  }
126
- //#endregion
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
- //#region src/model-registry.ts
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-BqDrk0S2.mjs";
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
- //#region src/utils/mongooseToJsonSchema.ts
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 };