@rpcbase/db 0.63.0 → 0.64.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -1,11 +1,11 @@
1
- import { a as registerPoliciesFromModules } from "./can-urGFf45M.js";
2
- import { b, d, f, e, g, c, r } from "./can-urGFf45M.js";
1
+ import { a as registerPoliciesFromModules } from "./can-D558uqd-.js";
2
+ import { b, d, f, e, g, c, r } from "./can-D558uqd-.js";
3
3
  import mongoose, { Schema as Schema$1, Types } from "mongoose";
4
4
  import { default as default2 } from "mongoose";
5
5
  import { z } from "zod";
6
6
  import { timingSafeEqual, createHmac } from "node:crypto";
7
- import { w as withLocalizedStringFallback } from "./index-Drge1bnG.js";
8
- import { a, E, L, c as c2, e as e2, m, r as r2, z as z2, b as b2, f as f2, d as d2 } from "./index-Drge1bnG.js";
7
+ import { w as withLocalizedStringFallback } from "./index-g1_0RZ-U.js";
8
+ import { a, E, L, c as c2, e as e2, m, r as r2, z as z2, b as b2, f as f2, d as d2 } from "./index-g1_0RZ-U.js";
9
9
  import assert from "assert";
10
10
  import { accessibleBy, accessibleRecordsPlugin } from "@casl/mongoose";
11
11
  import "@casl/ability";
@@ -34,33 +34,97 @@ const ZRBUser = z.object({
34
34
  emailVerificationExpiresAt: z.date().optional()
35
35
  });
36
36
  const RBUserSchema = new Schema$1({
37
- email: { type: String, unique: true, sparse: true },
38
- phone: { type: String, unique: true, sparse: true },
39
- password: { type: String, required: true },
37
+ email: {
38
+ type: String,
39
+ unique: true,
40
+ sparse: true
41
+ },
42
+ phone: {
43
+ type: String,
44
+ unique: true,
45
+ sparse: true
46
+ },
47
+ password: {
48
+ type: String,
49
+ required: true
50
+ },
40
51
  name: String,
41
- tenants: { type: [String], index: true, required: true },
42
- tenantRoles: { type: Map, of: [String], required: false, default: {} },
52
+ tenants: {
53
+ type: [String],
54
+ index: true,
55
+ required: true
56
+ },
57
+ tenantRoles: {
58
+ type: Map,
59
+ of: [String],
60
+ required: false,
61
+ default: {}
62
+ },
43
63
  oauthProviders: {
44
64
  type: Map,
45
65
  of: new Schema$1({
46
- subject: { type: String, required: true },
47
- email: { type: String, required: false },
48
- name: { type: String, required: false },
49
- accessToken: { type: String, required: false },
50
- refreshToken: { type: String, required: false },
51
- idToken: { type: String, required: false },
52
- scope: { type: String, required: false },
53
- tokenType: { type: String, required: false },
54
- expiresAt: { type: Date, required: false },
55
- rawUserInfo: { type: Schema$1.Types.Mixed, required: false },
56
- createdAt: { type: Date, required: false },
57
- updatedAt: { type: Date, required: false }
58
- }, { _id: false }),
66
+ subject: {
67
+ type: String,
68
+ required: true
69
+ },
70
+ email: {
71
+ type: String,
72
+ required: false
73
+ },
74
+ name: {
75
+ type: String,
76
+ required: false
77
+ },
78
+ accessToken: {
79
+ type: String,
80
+ required: false
81
+ },
82
+ refreshToken: {
83
+ type: String,
84
+ required: false
85
+ },
86
+ idToken: {
87
+ type: String,
88
+ required: false
89
+ },
90
+ scope: {
91
+ type: String,
92
+ required: false
93
+ },
94
+ tokenType: {
95
+ type: String,
96
+ required: false
97
+ },
98
+ expiresAt: {
99
+ type: Date,
100
+ required: false
101
+ },
102
+ rawUserInfo: {
103
+ type: Schema$1.Types.Mixed,
104
+ required: false
105
+ },
106
+ createdAt: {
107
+ type: Date,
108
+ required: false
109
+ },
110
+ updatedAt: {
111
+ type: Date,
112
+ required: false
113
+ }
114
+ }, {
115
+ _id: false
116
+ }),
59
117
  default: {},
60
118
  required: false
61
119
  },
62
- emailVerificationCode: { type: String, required: false },
63
- emailVerificationExpiresAt: { type: Date, required: false }
120
+ emailVerificationCode: {
121
+ type: String,
122
+ required: false
123
+ },
124
+ emailVerificationExpiresAt: {
125
+ type: Date,
126
+ required: false
127
+ }
64
128
  });
65
129
  const ZRBTenant = z.object({
66
130
  tenantId: z.string(),
@@ -68,18 +132,20 @@ const ZRBTenant = z.object({
68
132
  name: z.string().optional()
69
133
  });
70
134
  const RBTenantSchema = new Schema$1({
71
- tenantId: { type: String, required: true, unique: true, index: true },
72
- parentTenantId: { type: String },
73
- name: { type: String }
135
+ tenantId: {
136
+ type: String,
137
+ required: true,
138
+ unique: true,
139
+ index: true
140
+ },
141
+ parentTenantId: {
142
+ type: String
143
+ },
144
+ name: {
145
+ type: String
146
+ }
74
147
  });
75
- const ZRBTenantSubscriptionStatus = z.enum([
76
- "trialing",
77
- "active",
78
- "past_due",
79
- "paused",
80
- "canceled",
81
- "expired"
82
- ]);
148
+ const ZRBTenantSubscriptionStatus = z.enum(["trialing", "active", "past_due", "paused", "canceled", "expired"]);
83
149
  const ZRBTenantSubscriptionIntervalUnit = z.enum(["month", "year"]);
84
150
  const ZRBTenantSubscriptionType = z.enum(["primary", "addon"]);
85
151
  const ZRBTenantSubscriptionScope = z.enum(["tenant", "shop", "custom"]);
@@ -108,46 +174,107 @@ const ZRBTenantSubscription = z.object({
108
174
  latestEventAt: z.date().optional(),
109
175
  metadata: z.record(z.string(), z.unknown()).optional()
110
176
  });
111
- const RBTenantSubscriptionSchema = new Schema$1(
112
- {
113
- tenantId: { type: String, required: true, index: true },
114
- subscriptionId: { type: String, required: true },
115
- type: { type: String, required: true, enum: ZRBTenantSubscriptionType.options, default: "primary" },
116
- parentSubscriptionId: { type: String },
117
- scope: { type: String, enum: ZRBTenantSubscriptionScope.options, default: "tenant" },
118
- scopeId: { type: String },
119
- planKey: { type: String, required: true },
120
- status: { type: String, required: true, enum: ZRBTenantSubscriptionStatus.options },
121
- intervalUnit: { type: String, required: true, enum: ZRBTenantSubscriptionIntervalUnit.options },
122
- intervalCount: { type: Number, min: 1, default: 1 },
123
- modules: { type: [String], default: [] },
124
- currentPeriodStart: { type: Date },
125
- currentPeriodEnd: { type: Date },
126
- trialEndsAt: { type: Date },
127
- cancelAt: { type: Date },
128
- cancelAtPeriodEnd: { type: Boolean, default: false },
129
- canceledAt: { type: Date },
130
- provider: { type: String },
131
- providerCustomerId: { type: String },
132
- providerSubscriptionId: { type: String },
133
- latestEventId: { type: String },
134
- latestEventAt: { type: Date },
135
- metadata: { type: Schema$1.Types.Mixed }
136
- }
137
- );
138
- RBTenantSubscriptionSchema.index({ tenantId: 1, subscriptionId: 1 }, { unique: true });
139
- RBTenantSubscriptionSchema.index({ tenantId: 1, scope: 1, scopeId: 1 });
140
- const ZRBTenantSubscriptionEventSource = z.enum([
141
- "admin",
142
- "system",
143
- "webhook",
144
- "user"
145
- ]);
146
- const ZRBTenantSubscriptionChangeDirection = z.enum([
147
- "upgrade",
148
- "downgrade",
149
- "lateral"
150
- ]);
177
+ const RBTenantSubscriptionSchema = new Schema$1({
178
+ tenantId: {
179
+ type: String,
180
+ required: true,
181
+ index: true
182
+ },
183
+ subscriptionId: {
184
+ type: String,
185
+ required: true
186
+ },
187
+ type: {
188
+ type: String,
189
+ required: true,
190
+ enum: ZRBTenantSubscriptionType.options,
191
+ default: "primary"
192
+ },
193
+ parentSubscriptionId: {
194
+ type: String
195
+ },
196
+ scope: {
197
+ type: String,
198
+ enum: ZRBTenantSubscriptionScope.options,
199
+ default: "tenant"
200
+ },
201
+ scopeId: {
202
+ type: String
203
+ },
204
+ planKey: {
205
+ type: String,
206
+ required: true
207
+ },
208
+ status: {
209
+ type: String,
210
+ required: true,
211
+ enum: ZRBTenantSubscriptionStatus.options
212
+ },
213
+ intervalUnit: {
214
+ type: String,
215
+ required: true,
216
+ enum: ZRBTenantSubscriptionIntervalUnit.options
217
+ },
218
+ intervalCount: {
219
+ type: Number,
220
+ min: 1,
221
+ default: 1
222
+ },
223
+ modules: {
224
+ type: [String],
225
+ default: []
226
+ },
227
+ currentPeriodStart: {
228
+ type: Date
229
+ },
230
+ currentPeriodEnd: {
231
+ type: Date
232
+ },
233
+ trialEndsAt: {
234
+ type: Date
235
+ },
236
+ cancelAt: {
237
+ type: Date
238
+ },
239
+ cancelAtPeriodEnd: {
240
+ type: Boolean,
241
+ default: false
242
+ },
243
+ canceledAt: {
244
+ type: Date
245
+ },
246
+ provider: {
247
+ type: String
248
+ },
249
+ providerCustomerId: {
250
+ type: String
251
+ },
252
+ providerSubscriptionId: {
253
+ type: String
254
+ },
255
+ latestEventId: {
256
+ type: String
257
+ },
258
+ latestEventAt: {
259
+ type: Date
260
+ },
261
+ metadata: {
262
+ type: Schema$1.Types.Mixed
263
+ }
264
+ });
265
+ RBTenantSubscriptionSchema.index({
266
+ tenantId: 1,
267
+ subscriptionId: 1
268
+ }, {
269
+ unique: true
270
+ });
271
+ RBTenantSubscriptionSchema.index({
272
+ tenantId: 1,
273
+ scope: 1,
274
+ scopeId: 1
275
+ });
276
+ const ZRBTenantSubscriptionEventSource = z.enum(["admin", "system", "webhook", "user"]);
277
+ const ZRBTenantSubscriptionChangeDirection = z.enum(["upgrade", "downgrade", "lateral"]);
151
278
  const ZRBTenantSubscriptionEvent = z.object({
152
279
  tenantId: z.string(),
153
280
  subscriptionId: z.string(),
@@ -173,48 +300,123 @@ const ZRBTenantSubscriptionEvent = z.object({
173
300
  providerPayload: z.unknown().optional(),
174
301
  metadata: z.record(z.string(), z.unknown()).optional()
175
302
  });
176
- const RBTenantSubscriptionEventSchema = new Schema$1(
177
- {
178
- tenantId: { type: String, required: true, index: true },
179
- subscriptionId: { type: String, required: true, index: true },
180
- type: { type: String, required: true },
181
- occurredAt: { type: Date, required: true, default: Date.now },
182
- effectiveAt: { type: Date },
183
- fromPlanKey: { type: String },
184
- toPlanKey: { type: String },
185
- fromStatus: { type: String, enum: ZRBTenantSubscriptionStatus.options },
186
- toStatus: { type: String, enum: ZRBTenantSubscriptionStatus.options },
187
- fromModules: { type: [String], default: void 0 },
188
- toModules: { type: [String], default: void 0 },
189
- fromIntervalUnit: { type: String, enum: ZRBTenantSubscriptionIntervalUnit.options },
190
- toIntervalUnit: { type: String, enum: ZRBTenantSubscriptionIntervalUnit.options },
191
- fromIntervalCount: { type: Number, min: 1 },
192
- toIntervalCount: { type: Number, min: 1 },
193
- direction: { type: String, enum: ZRBTenantSubscriptionChangeDirection.options },
194
- actorUserId: { type: String },
195
- source: { type: String, enum: ZRBTenantSubscriptionEventSource.options },
196
- reason: { type: String },
197
- provider: { type: String },
198
- providerEventId: { type: String },
199
- providerPayload: { type: Schema$1.Types.Mixed },
200
- metadata: { type: Schema$1.Types.Mixed }
201
- }
202
- );
203
- RBTenantSubscriptionEventSchema.index({ tenantId: 1, subscriptionId: 1, occurredAt: 1 });
204
- RBTenantSubscriptionEventSchema.index({ provider: 1, providerEventId: 1 }, { unique: true, sparse: true });
303
+ const RBTenantSubscriptionEventSchema = new Schema$1({
304
+ tenantId: {
305
+ type: String,
306
+ required: true,
307
+ index: true
308
+ },
309
+ subscriptionId: {
310
+ type: String,
311
+ required: true,
312
+ index: true
313
+ },
314
+ type: {
315
+ type: String,
316
+ required: true
317
+ },
318
+ occurredAt: {
319
+ type: Date,
320
+ required: true,
321
+ default: Date.now
322
+ },
323
+ effectiveAt: {
324
+ type: Date
325
+ },
326
+ fromPlanKey: {
327
+ type: String
328
+ },
329
+ toPlanKey: {
330
+ type: String
331
+ },
332
+ fromStatus: {
333
+ type: String,
334
+ enum: ZRBTenantSubscriptionStatus.options
335
+ },
336
+ toStatus: {
337
+ type: String,
338
+ enum: ZRBTenantSubscriptionStatus.options
339
+ },
340
+ fromModules: {
341
+ type: [String],
342
+ default: void 0
343
+ },
344
+ toModules: {
345
+ type: [String],
346
+ default: void 0
347
+ },
348
+ fromIntervalUnit: {
349
+ type: String,
350
+ enum: ZRBTenantSubscriptionIntervalUnit.options
351
+ },
352
+ toIntervalUnit: {
353
+ type: String,
354
+ enum: ZRBTenantSubscriptionIntervalUnit.options
355
+ },
356
+ fromIntervalCount: {
357
+ type: Number,
358
+ min: 1
359
+ },
360
+ toIntervalCount: {
361
+ type: Number,
362
+ min: 1
363
+ },
364
+ direction: {
365
+ type: String,
366
+ enum: ZRBTenantSubscriptionChangeDirection.options
367
+ },
368
+ actorUserId: {
369
+ type: String
370
+ },
371
+ source: {
372
+ type: String,
373
+ enum: ZRBTenantSubscriptionEventSource.options
374
+ },
375
+ reason: {
376
+ type: String
377
+ },
378
+ provider: {
379
+ type: String
380
+ },
381
+ providerEventId: {
382
+ type: String
383
+ },
384
+ providerPayload: {
385
+ type: Schema$1.Types.Mixed
386
+ },
387
+ metadata: {
388
+ type: Schema$1.Types.Mixed
389
+ }
390
+ });
391
+ RBTenantSubscriptionEventSchema.index({
392
+ tenantId: 1,
393
+ subscriptionId: 1,
394
+ occurredAt: 1
395
+ });
396
+ RBTenantSubscriptionEventSchema.index({
397
+ provider: 1,
398
+ providerEventId: 1
399
+ }, {
400
+ unique: true,
401
+ sparse: true
402
+ });
205
403
  const ZRBRtsCounter = z.object({
206
404
  _id: z.string(),
207
405
  seq: z.number().int().min(0)
208
406
  });
209
- const RBRtsCounterSchema = new Schema$1(
210
- {
211
- _id: { type: String, required: true },
212
- seq: { type: Number, required: true, default: 0 }
407
+ const RBRtsCounterSchema = new Schema$1({
408
+ _id: {
409
+ type: String,
410
+ required: true
213
411
  },
214
- {
215
- versionKey: false
412
+ seq: {
413
+ type: Number,
414
+ required: true,
415
+ default: 0
216
416
  }
217
- );
417
+ }, {
418
+ versionKey: false
419
+ });
218
420
  const ttlSecondsRaw = process.env.RB_RTS_CHANGES_TTL_S ?? "";
219
421
  const ttlSeconds = Number.isFinite(Number(ttlSecondsRaw)) ? Math.max(60, Math.floor(Number(ttlSecondsRaw))) : 60 * 60 * 24 * 30;
220
422
  const ZRBRtsChangeOp = z.enum(["delete", "reset_model"]);
@@ -225,20 +427,43 @@ const ZRBRtsChange = z.object({
225
427
  docId: z.string().optional(),
226
428
  ts: z.date()
227
429
  });
228
- const RBRtsChangeSchema = new Schema$1(
229
- {
230
- seq: { type: Number, required: true },
231
- modelName: { type: String, required: true, index: true },
232
- op: { type: String, required: true, enum: ZRBRtsChangeOp.options },
233
- docId: { type: String, required: false },
234
- ts: { type: Date, required: true, default: Date.now }
235
- },
236
- {
237
- versionKey: false
238
- }
239
- );
240
- RBRtsChangeSchema.index({ seq: 1 }, { unique: true });
241
- RBRtsChangeSchema.index({ ts: 1 }, { expireAfterSeconds: ttlSeconds });
430
+ const RBRtsChangeSchema = new Schema$1({
431
+ seq: {
432
+ type: Number,
433
+ required: true
434
+ },
435
+ modelName: {
436
+ type: String,
437
+ required: true,
438
+ index: true
439
+ },
440
+ op: {
441
+ type: String,
442
+ required: true,
443
+ enum: ZRBRtsChangeOp.options
444
+ },
445
+ docId: {
446
+ type: String,
447
+ required: false
448
+ },
449
+ ts: {
450
+ type: Date,
451
+ required: true,
452
+ default: Date.now
453
+ }
454
+ }, {
455
+ versionKey: false
456
+ });
457
+ RBRtsChangeSchema.index({
458
+ seq: 1
459
+ }, {
460
+ unique: true
461
+ });
462
+ RBRtsChangeSchema.index({
463
+ ts: 1
464
+ }, {
465
+ expireAfterSeconds: ttlSeconds
466
+ });
242
467
  const ZRBUploadSessionStatus = z.enum(["uploading", "assembling", "done", "error"]);
243
468
  const ZRBUploadSession = z.object({
244
469
  _id: z.string(),
@@ -256,42 +481,100 @@ const ZRBUploadSession = z.object({
256
481
  isPublic: z.boolean().optional(),
257
482
  error: z.string().optional()
258
483
  });
259
- const RBUploadSessionSchema = new Schema$1(
260
- {
261
- _id: { type: String, required: true },
262
- userId: { type: String, required: false, index: true },
263
- ownerKeyHash: { type: String, required: false },
264
- filename: { type: String, required: true },
265
- mimeType: { type: String, required: true },
266
- totalSize: { type: Number, required: true },
267
- chunkSize: { type: Number, required: true },
268
- chunksTotal: { type: Number, required: true },
269
- status: { type: String, required: true, enum: ZRBUploadSessionStatus.options },
270
- createdAt: { type: Date, required: true, default: Date.now },
271
- expiresAt: { type: Date, required: true },
272
- fileId: { type: String, required: false },
273
- isPublic: { type: Boolean, required: false },
274
- error: { type: String, required: false }
275
- },
276
- {
277
- versionKey: false
278
- }
279
- );
280
- RBUploadSessionSchema.index({ expiresAt: 1 }, { expireAfterSeconds: 0 });
484
+ const RBUploadSessionSchema = new Schema$1({
485
+ _id: {
486
+ type: String,
487
+ required: true
488
+ },
489
+ userId: {
490
+ type: String,
491
+ required: false,
492
+ index: true
493
+ },
494
+ ownerKeyHash: {
495
+ type: String,
496
+ required: false
497
+ },
498
+ filename: {
499
+ type: String,
500
+ required: true
501
+ },
502
+ mimeType: {
503
+ type: String,
504
+ required: true
505
+ },
506
+ totalSize: {
507
+ type: Number,
508
+ required: true
509
+ },
510
+ chunkSize: {
511
+ type: Number,
512
+ required: true
513
+ },
514
+ chunksTotal: {
515
+ type: Number,
516
+ required: true
517
+ },
518
+ status: {
519
+ type: String,
520
+ required: true,
521
+ enum: ZRBUploadSessionStatus.options
522
+ },
523
+ createdAt: {
524
+ type: Date,
525
+ required: true,
526
+ default: Date.now
527
+ },
528
+ expiresAt: {
529
+ type: Date,
530
+ required: true
531
+ },
532
+ fileId: {
533
+ type: String,
534
+ required: false
535
+ },
536
+ isPublic: {
537
+ type: Boolean,
538
+ required: false
539
+ },
540
+ error: {
541
+ type: String,
542
+ required: false
543
+ }
544
+ }, {
545
+ versionKey: false
546
+ });
547
+ RBUploadSessionSchema.index({
548
+ expiresAt: 1
549
+ }, {
550
+ expireAfterSeconds: 0
551
+ });
281
552
  const RBUploadSessionPolicy = {
282
553
  subject: "RBUploadSession",
283
554
  define: (builder, ctx) => {
284
555
  builder.can("create", "RBUploadSession");
285
556
  if (ctx.userId) {
286
- builder.can("read", "RBUploadSession", { userId: ctx.userId });
287
- builder.can("update", "RBUploadSession", { userId: ctx.userId });
288
- builder.can("delete", "RBUploadSession", { userId: ctx.userId });
557
+ builder.can("read", "RBUploadSession", {
558
+ userId: ctx.userId
559
+ });
560
+ builder.can("update", "RBUploadSession", {
561
+ userId: ctx.userId
562
+ });
563
+ builder.can("delete", "RBUploadSession", {
564
+ userId: ctx.userId
565
+ });
289
566
  }
290
567
  const uploadKeyHash = typeof ctx.claims?.uploadKeyHash === "string" ? ctx.claims.uploadKeyHash.trim() : "";
291
568
  if (uploadKeyHash) {
292
- builder.can("read", "RBUploadSession", { ownerKeyHash: uploadKeyHash });
293
- builder.can("update", "RBUploadSession", { ownerKeyHash: uploadKeyHash });
294
- builder.can("delete", "RBUploadSession", { ownerKeyHash: uploadKeyHash });
569
+ builder.can("read", "RBUploadSession", {
570
+ ownerKeyHash: uploadKeyHash
571
+ });
572
+ builder.can("update", "RBUploadSession", {
573
+ ownerKeyHash: uploadKeyHash
574
+ });
575
+ builder.can("delete", "RBUploadSession", {
576
+ ownerKeyHash: uploadKeyHash
577
+ });
295
578
  }
296
579
  }
297
580
  };
@@ -304,22 +587,51 @@ const ZRBUploadChunk = z.object({
304
587
  createdAt: z.date(),
305
588
  expiresAt: z.date()
306
589
  });
307
- const RBUploadChunkSchema = new Schema$1(
308
- {
309
- uploadId: { type: String, required: true, index: true },
310
- index: { type: Number, required: true },
311
- data: { type: Buffer, required: true },
312
- size: { type: Number, required: true },
313
- sha256: { type: String, required: false },
314
- createdAt: { type: Date, required: true, default: Date.now },
315
- expiresAt: { type: Date, required: true }
316
- },
317
- {
318
- versionKey: false
319
- }
320
- );
321
- RBUploadChunkSchema.index({ uploadId: 1, index: 1 }, { unique: true });
322
- RBUploadChunkSchema.index({ expiresAt: 1 }, { expireAfterSeconds: 0 });
590
+ const RBUploadChunkSchema = new Schema$1({
591
+ uploadId: {
592
+ type: String,
593
+ required: true,
594
+ index: true
595
+ },
596
+ index: {
597
+ type: Number,
598
+ required: true
599
+ },
600
+ data: {
601
+ type: Buffer,
602
+ required: true
603
+ },
604
+ size: {
605
+ type: Number,
606
+ required: true
607
+ },
608
+ sha256: {
609
+ type: String,
610
+ required: false
611
+ },
612
+ createdAt: {
613
+ type: Date,
614
+ required: true,
615
+ default: Date.now
616
+ },
617
+ expiresAt: {
618
+ type: Date,
619
+ required: true
620
+ }
621
+ }, {
622
+ versionKey: false
623
+ });
624
+ RBUploadChunkSchema.index({
625
+ uploadId: 1,
626
+ index: 1
627
+ }, {
628
+ unique: true
629
+ });
630
+ RBUploadChunkSchema.index({
631
+ expiresAt: 1
632
+ }, {
633
+ expireAfterSeconds: 0
634
+ });
323
635
  const ZRBNotification = z.object({
324
636
  userId: z.string(),
325
637
  topic: z.string().optional(),
@@ -333,35 +645,92 @@ const ZRBNotification = z.object({
333
645
  metadata: z.record(z.string(), z.unknown()).optional()
334
646
  });
335
647
  const TTL_90_DAYS_S = 60 * 60 * 24 * 90;
336
- const RBNotificationSchema = new Schema$1(
337
- {
338
- userId: { type: String, required: true, index: true },
339
- topic: { type: String, required: false, index: true },
340
- title: { type: String, required: true },
341
- body: { type: String, required: false },
342
- url: { type: String, required: false },
343
- createdAt: { type: Date, required: true, default: Date.now, index: true },
344
- seenAt: { type: Date, required: false, index: true },
345
- readAt: { type: Date, required: false, index: true },
346
- archivedAt: { type: Date, required: false },
347
- metadata: { type: Schema$1.Types.Mixed, required: false }
348
- },
349
- {
350
- versionKey: false
351
- }
352
- );
353
- RBNotificationSchema.index({ userId: 1, archivedAt: 1, createdAt: -1 });
354
- RBNotificationSchema.index({ userId: 1, seenAt: 1, archivedAt: 1, createdAt: -1 });
355
- RBNotificationSchema.index({ userId: 1, readAt: 1, archivedAt: 1, createdAt: -1 });
356
- RBNotificationSchema.index({ archivedAt: 1 }, { expireAfterSeconds: TTL_90_DAYS_S });
648
+ const RBNotificationSchema = new Schema$1({
649
+ userId: {
650
+ type: String,
651
+ required: true,
652
+ index: true
653
+ },
654
+ topic: {
655
+ type: String,
656
+ required: false,
657
+ index: true
658
+ },
659
+ title: {
660
+ type: String,
661
+ required: true
662
+ },
663
+ body: {
664
+ type: String,
665
+ required: false
666
+ },
667
+ url: {
668
+ type: String,
669
+ required: false
670
+ },
671
+ createdAt: {
672
+ type: Date,
673
+ required: true,
674
+ default: Date.now,
675
+ index: true
676
+ },
677
+ seenAt: {
678
+ type: Date,
679
+ required: false,
680
+ index: true
681
+ },
682
+ readAt: {
683
+ type: Date,
684
+ required: false,
685
+ index: true
686
+ },
687
+ archivedAt: {
688
+ type: Date,
689
+ required: false
690
+ },
691
+ metadata: {
692
+ type: Schema$1.Types.Mixed,
693
+ required: false
694
+ }
695
+ }, {
696
+ versionKey: false
697
+ });
698
+ RBNotificationSchema.index({
699
+ userId: 1,
700
+ archivedAt: 1,
701
+ createdAt: -1
702
+ });
703
+ RBNotificationSchema.index({
704
+ userId: 1,
705
+ seenAt: 1,
706
+ archivedAt: 1,
707
+ createdAt: -1
708
+ });
709
+ RBNotificationSchema.index({
710
+ userId: 1,
711
+ readAt: 1,
712
+ archivedAt: 1,
713
+ createdAt: -1
714
+ });
715
+ RBNotificationSchema.index({
716
+ archivedAt: 1
717
+ }, {
718
+ expireAfterSeconds: TTL_90_DAYS_S
719
+ });
357
720
  const RBNotificationPolicy = {
358
721
  subject: "RBNotification",
359
722
  define: (builder, ctx) => {
360
723
  if (!ctx.userId) return;
361
724
  builder.can("create", "RBNotification");
362
- builder.can("read", "RBNotification", { userId: ctx.userId });
363
- builder.can("update", "RBNotification", { userId: ctx.userId });
364
- builder.can("delete", "RBNotification", { userId: ctx.userId });
725
+ builder.can("read", "RBNotification", {
726
+ userId: ctx.userId
727
+ });
728
+ builder.can("update", "RBNotification", {
729
+ userId: ctx.userId
730
+ });
731
+ builder.can("delete", "RBNotification", {
732
+ userId: ctx.userId
733
+ });
365
734
  }
366
735
  };
367
736
  const ZRBNotificationDigestFrequency = z.enum(["off", "daily", "weekly"]);
@@ -377,44 +746,72 @@ const ZRBNotificationSettings = z.object({
377
746
  topicPreferences: z.array(ZRBNotificationTopicPreference).optional(),
378
747
  lastDigestSentAt: z.date().optional()
379
748
  });
380
- const TopicPreferenceSchema = new Schema$1(
381
- {
382
- topic: { type: String, required: true },
383
- inApp: { type: Boolean, required: true, default: true },
384
- emailDigest: { type: Boolean, required: true, default: true },
385
- push: { type: Boolean, required: true, default: false }
386
- },
387
- { _id: false }
388
- );
389
- const RBNotificationSettingsSchema = new Schema$1(
390
- {
391
- userId: { type: String, required: true },
392
- digestFrequency: {
393
- type: String,
394
- required: true,
395
- enum: ZRBNotificationDigestFrequency.options,
396
- default: "weekly"
397
- },
398
- topicPreferences: {
399
- type: [TopicPreferenceSchema],
400
- default: []
401
- },
402
- lastDigestSentAt: { type: Date, required: false }
749
+ const TopicPreferenceSchema = new Schema$1({
750
+ topic: {
751
+ type: String,
752
+ required: true
753
+ },
754
+ inApp: {
755
+ type: Boolean,
756
+ required: true,
757
+ default: true
758
+ },
759
+ emailDigest: {
760
+ type: Boolean,
761
+ required: true,
762
+ default: true
763
+ },
764
+ push: {
765
+ type: Boolean,
766
+ required: true,
767
+ default: false
768
+ }
769
+ }, {
770
+ _id: false
771
+ });
772
+ const RBNotificationSettingsSchema = new Schema$1({
773
+ userId: {
774
+ type: String,
775
+ required: true
776
+ },
777
+ digestFrequency: {
778
+ type: String,
779
+ required: true,
780
+ enum: ZRBNotificationDigestFrequency.options,
781
+ default: "weekly"
782
+ },
783
+ topicPreferences: {
784
+ type: [TopicPreferenceSchema],
785
+ default: []
403
786
  },
404
- {
405
- versionKey: false,
406
- timestamps: true
787
+ lastDigestSentAt: {
788
+ type: Date,
789
+ required: false
407
790
  }
408
- );
409
- RBNotificationSettingsSchema.index({ userId: 1 }, { unique: true });
410
- RBNotificationSettingsSchema.index({ userId: 1, "topicPreferences.topic": 1 });
791
+ }, {
792
+ versionKey: false,
793
+ timestamps: true
794
+ });
795
+ RBNotificationSettingsSchema.index({
796
+ userId: 1
797
+ }, {
798
+ unique: true
799
+ });
800
+ RBNotificationSettingsSchema.index({
801
+ userId: 1,
802
+ "topicPreferences.topic": 1
803
+ });
411
804
  const RBNotificationSettingsPolicy = {
412
805
  subject: "RBNotificationSettings",
413
806
  define: (builder, ctx) => {
414
807
  if (!ctx.userId) return;
415
808
  builder.can("create", "RBNotificationSettings");
416
- builder.can("read", "RBNotificationSettings", { userId: ctx.userId });
417
- builder.can("update", "RBNotificationSettings", { userId: ctx.userId });
809
+ builder.can("read", "RBNotificationSettings", {
810
+ userId: ctx.userId
811
+ });
812
+ builder.can("update", "RBNotificationSettings", {
813
+ userId: ctx.userId
814
+ });
418
815
  }
419
816
  };
420
817
  const ZRBOAuthRequest = z.object({
@@ -425,18 +822,41 @@ const ZRBOAuthRequest = z.object({
425
822
  createdAt: z.date(),
426
823
  expiresAt: z.date()
427
824
  });
428
- const RBOAuthRequestSchema = new Schema$1(
429
- {
430
- _id: { type: String, required: true },
431
- providerId: { type: String, required: true, index: true },
432
- codeVerifier: { type: String, required: true },
433
- returnTo: { type: String, required: false },
434
- createdAt: { type: Date, required: true, default: Date.now },
435
- expiresAt: { type: Date, required: true }
436
- },
437
- { versionKey: false }
438
- );
439
- RBOAuthRequestSchema.index({ expiresAt: 1 }, { expireAfterSeconds: 0 });
825
+ const RBOAuthRequestSchema = new Schema$1({
826
+ _id: {
827
+ type: String,
828
+ required: true
829
+ },
830
+ providerId: {
831
+ type: String,
832
+ required: true,
833
+ index: true
834
+ },
835
+ codeVerifier: {
836
+ type: String,
837
+ required: true
838
+ },
839
+ returnTo: {
840
+ type: String,
841
+ required: false
842
+ },
843
+ createdAt: {
844
+ type: Date,
845
+ required: true,
846
+ default: Date.now
847
+ },
848
+ expiresAt: {
849
+ type: Date,
850
+ required: true
851
+ }
852
+ }, {
853
+ versionKey: false
854
+ });
855
+ RBOAuthRequestSchema.index({
856
+ expiresAt: 1
857
+ }, {
858
+ expireAfterSeconds: 0
859
+ });
440
860
  const frameworkSchemas = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.defineProperty({
441
861
  __proto__: null,
442
862
  RBNotificationPolicy,
@@ -493,7 +913,10 @@ function localizedStringField(options) {
493
913
  get: (value) => withLocalizedStringFallback(userGet ? userGet(value) : value)
494
914
  };
495
915
  }
496
- const { Schema, model } = mongoose;
916
+ const {
917
+ Schema,
918
+ model
919
+ } = mongoose;
497
920
  class PaginationValidationError extends Error {
498
921
  code = "invalid_pagination";
499
922
  statusCode = 400;
@@ -515,18 +938,26 @@ const normalizePaginationSpec = (spec) => {
515
938
  const direction = spec.direction ?? "next";
516
939
  if (direction !== "next" && direction !== "prev") throw new PaginationValidationError("Invalid pagination direction");
517
940
  if (!Array.isArray(spec.sort) || spec.sort.length === 0) throw new PaginationValidationError("Invalid pagination sort");
518
- const sort = spec.sort.map(({ field, order }) => ({
941
+ const sort = spec.sort.map(({
942
+ field,
943
+ order
944
+ }) => ({
519
945
  field: assertSafeMongoFieldPath(field),
520
946
  order: normalizeOrder(order)
521
947
  }));
522
948
  const seenFields = /* @__PURE__ */ new Set();
523
- for (const { field } of sort) {
949
+ for (const {
950
+ field
951
+ } of sort) {
524
952
  if (seenFields.has(field)) throw new PaginationValidationError(`Duplicate pagination sort field: ${field}`);
525
953
  seenFields.add(field);
526
954
  }
527
955
  const primaryOrder = sort[0]?.order;
528
956
  if (!seenFields.has("_id")) {
529
- sort.push({ field: "_id", order: primaryOrder });
957
+ sort.push({
958
+ field: "_id",
959
+ order: primaryOrder
960
+ });
530
961
  }
531
962
  return {
532
963
  ...spec,
@@ -562,14 +993,19 @@ const assertSafeMongoFieldPath = (field) => {
562
993
  const encodePaginationCursor = (spec, node, options) => {
563
994
  const normalized = normalizePaginationSpec(spec);
564
995
  const values = /* @__PURE__ */ Object.create(null);
565
- for (const { field } of normalized.sort) {
996
+ for (const {
997
+ field
998
+ } of normalized.sort) {
566
999
  const value = readFieldValue(node, field);
567
1000
  if (typeof value === "undefined") {
568
1001
  throw new Error(`Pagination cursor encode failed (missing field: ${field})`);
569
1002
  }
570
1003
  values[field] = encodeCursorValue(field, value);
571
1004
  }
572
- const payload = { v: 1, values };
1005
+ const payload = {
1006
+ v: 1,
1007
+ values
1008
+ };
573
1009
  const payloadB64 = Buffer.from(JSON.stringify(payload), "utf8").toString("base64url");
574
1010
  const sigB64 = signCursorPayloadB64(payloadB64, options.signingSecret);
575
1011
  return `${payloadB64}.${sigB64}`;
@@ -592,7 +1028,9 @@ const decodePaginationCursor = (spec, cursor, options) => {
592
1028
  if (payload.v !== 1) throw new PaginationValidationError("Unsupported pagination cursor version");
593
1029
  if (!payload.values || typeof payload.values !== "object") throw new PaginationValidationError("Invalid pagination cursor payload");
594
1030
  const decoded = /* @__PURE__ */ Object.create(null);
595
- for (const { field } of normalized.sort) {
1031
+ for (const {
1032
+ field
1033
+ } of normalized.sort) {
596
1034
  if (!Object.prototype.hasOwnProperty.call(payload.values, field)) {
597
1035
  throw new PaginationValidationError(`Pagination cursor missing field: ${field}`);
598
1036
  }
@@ -615,13 +1053,19 @@ const verifyCursorSignature = (payloadB64, sigB64, secret) => {
615
1053
  const encodeCursorValue = (field, value) => {
616
1054
  if (value === null) return null;
617
1055
  if (field === "_id") {
618
- if (value instanceof Types.ObjectId) return { $oid: value.toHexString() };
1056
+ if (value instanceof Types.ObjectId) return {
1057
+ $oid: value.toHexString()
1058
+ };
619
1059
  if (typeof value === "string") return value;
620
1060
  throw new Error("Pagination cursor encode failed (_id must be an ObjectId or string)");
621
1061
  }
622
- if (value instanceof Date) return { $date: value.toISOString() };
1062
+ if (value instanceof Date) return {
1063
+ $date: value.toISOString()
1064
+ };
623
1065
  if (typeof value === "string" || typeof value === "number" || typeof value === "boolean") return value;
624
- if (value instanceof Types.ObjectId) return { $oid: value.toHexString() };
1066
+ if (value instanceof Types.ObjectId) return {
1067
+ $oid: value.toHexString()
1068
+ };
625
1069
  throw new Error(`Unsupported pagination cursor value type for field: ${field}`);
626
1070
  };
627
1071
  const decodeCursorValue = (field, value) => {
@@ -681,7 +1125,10 @@ const compileMongoPagination = (spec, options) => {
681
1125
  };
682
1126
  const toMongoSort = (spec) => {
683
1127
  const mongoSort = /* @__PURE__ */ Object.create(null);
684
- for (const { field, order } of spec.sort) {
1128
+ for (const {
1129
+ field,
1130
+ order
1131
+ } of spec.sort) {
685
1132
  const forQueryOrder = spec.direction === "prev" ? invertOrder(order) : order;
686
1133
  mongoSort[field] = forQueryOrder === "asc" ? 1 : -1;
687
1134
  }
@@ -706,9 +1153,13 @@ const buildKeysetFilterDelta = (spec, cursorValues) => {
706
1153
  const cmp = /* @__PURE__ */ Object.create(null);
707
1154
  cmp[current.field] = cmpOp;
708
1155
  and.push(cmp);
709
- branches.push(and.length === 1 ? and[0] : { $and: and });
1156
+ branches.push(and.length === 1 ? and[0] : {
1157
+ $and: and
1158
+ });
710
1159
  }
711
- return { $or: branches };
1160
+ return {
1161
+ $or: branches
1162
+ };
712
1163
  };
713
1164
  const getKeysetOp = (order, direction) => {
714
1165
  if (direction === "next") return order === "asc" ? "$gt" : "$lt";
@@ -729,7 +1180,10 @@ const materializeMongoPagination = (compiled, fetchedNodes, options) => {
729
1180
  hasPrevPage
730
1181
  };
731
1182
  if (nodes.length === 0) {
732
- return { nodes, pageInfo };
1183
+ return {
1184
+ nodes,
1185
+ pageInfo
1186
+ };
733
1187
  }
734
1188
  if (hasPrevPage) {
735
1189
  pageInfo.prevCursor = encodePaginationCursor(compiled.spec, nodes[0], options.cursor);
@@ -737,7 +1191,10 @@ const materializeMongoPagination = (compiled, fetchedNodes, options) => {
737
1191
  if (hasNextPage) {
738
1192
  pageInfo.nextCursor = encodePaginationCursor(compiled.spec, nodes[nodes.length - 1], options.cursor);
739
1193
  }
740
- return { nodes, pageInfo };
1194
+ return {
1195
+ nodes,
1196
+ pageInfo
1197
+ };
741
1198
  };
742
1199
  const MongoAdapter = {
743
1200
  applyPagination: (query, compiled) => {
@@ -748,13 +1205,17 @@ const MongoAdapter = {
748
1205
  }
749
1206
  };
750
1207
  const paginateMongoQuery = async (query, pagination, options) => {
751
- const compiled = compileMongoPagination(pagination, { cursor: options.cursor });
1208
+ const compiled = compileMongoPagination(pagination, {
1209
+ cursor: options.cursor
1210
+ });
752
1211
  MongoAdapter.applyPagination(query, compiled);
753
1212
  const fetchedNodes = await query.exec();
754
1213
  if (!Array.isArray(fetchedNodes)) {
755
1214
  throw new Error("paginateMongoQuery expects query.exec() to return an array");
756
1215
  }
757
- return materializeMongoPagination(compiled, fetchedNodes, { cursor: options.cursor });
1216
+ return materializeMongoPagination(compiled, fetchedNodes, {
1217
+ cursor: options.cursor
1218
+ });
758
1219
  };
759
1220
  const getQueryOptions$1 = (query) => {
760
1221
  if (!query || typeof query !== "object") return void 0;
@@ -775,7 +1236,9 @@ const mongoPaginationPlugin = (schema, pluginOptions) => {
775
1236
  if (!spec) throw new Error("Missing pagination spec");
776
1237
  const cursor = options?.cursor ?? getCursorFromOptions(this) ?? pluginOptions?.cursor;
777
1238
  if (!cursor?.signingSecret) throw new Error("Missing pagination cursor signingSecret");
778
- return await paginateMongoQuery(this, spec, { cursor });
1239
+ return await paginateMongoQuery(this, spec, {
1240
+ cursor
1241
+ });
779
1242
  };
780
1243
  };
781
1244
  const buildSearchTextStage = (options) => {
@@ -793,14 +1256,20 @@ const buildSearchTextStage = (options) => {
793
1256
  }
794
1257
  };
795
1258
  if (options.highlightPath) {
796
- stage.$search.highlight = { path: options.highlightPath };
1259
+ stage.$search.highlight = {
1260
+ path: options.highlightPath
1261
+ };
797
1262
  }
798
1263
  return stage;
799
1264
  };
800
1265
  const searchMetaProjection = () => {
801
1266
  return {
802
- score: { $meta: "searchScore" },
803
- highlights: { $meta: "searchHighlights" }
1267
+ score: {
1268
+ $meta: "searchScore"
1269
+ },
1270
+ highlights: {
1271
+ $meta: "searchHighlights"
1272
+ }
804
1273
  };
805
1274
  };
806
1275
  const listResultHasIndex = (listResult, name) => {
@@ -826,27 +1295,38 @@ const ensureSearchIndex = async (params) => {
826
1295
  if (!name) throw new Error("Missing search index name");
827
1296
  let listResult;
828
1297
  try {
829
- listResult = await params.db.command({ listSearchIndexes: collection });
1298
+ listResult = await params.db.command({
1299
+ listSearchIndexes: collection
1300
+ });
830
1301
  } catch (error) {
831
1302
  const message = error instanceof Error ? error.message : String(error);
832
1303
  throw new Error(`listSearchIndexes failed for "${collection}": ${message}`);
833
1304
  }
834
1305
  if (listResultHasIndex(listResult, name)) {
835
- return { created: false };
1306
+ return {
1307
+ created: false
1308
+ };
836
1309
  }
837
1310
  try {
838
1311
  await params.db.command({
839
1312
  createSearchIndexes: collection,
840
- indexes: [{ name, definition: params.definition }]
1313
+ indexes: [{
1314
+ name,
1315
+ definition: params.definition
1316
+ }]
841
1317
  });
842
1318
  } catch (error) {
843
1319
  if (isIndexAlreadyExistsError(error)) {
844
- return { created: false };
1320
+ return {
1321
+ created: false
1322
+ };
845
1323
  }
846
1324
  const message = error instanceof Error ? error.message : String(error);
847
1325
  throw new Error(`createSearchIndexes failed for "${collection}" (index "${name}"): ${message}`);
848
1326
  }
849
- return { created: true };
1327
+ return {
1328
+ created: true
1329
+ };
850
1330
  };
851
1331
  const getAppName$1 = (env = process.env) => {
852
1332
  const appName = env.APP_NAME?.trim();
@@ -899,7 +1379,9 @@ const ensureMongooseConnection = async (dbName) => {
899
1379
  });
900
1380
  }
901
1381
  await waitForOpen(rootConnection);
902
- const connection = rootConnection.name === normalizedDbName ? rootConnection : rootConnection.useDb(normalizedDbName, { useCache: true });
1382
+ const connection = rootConnection.name === normalizedDbName ? rootConnection : rootConnection.useDb(normalizedDbName, {
1383
+ useCache: true
1384
+ });
903
1385
  await waitForOpen(connection);
904
1386
  connections.set(normalizedDbName, connection);
905
1387
  return connection;
@@ -937,22 +1419,42 @@ const getQuerySession = (query) => {
937
1419
  const getRtsModels = (db) => {
938
1420
  const RtsCounter = db.models.RBRtsCounter ?? db.model("RBRtsCounter", RBRtsCounterSchema);
939
1421
  const RtsChange = db.models.RBRtsChange ?? db.model("RBRtsChange", RBRtsChangeSchema);
940
- return { RtsCounter, RtsChange };
1422
+ return {
1423
+ RtsCounter,
1424
+ RtsChange
1425
+ };
941
1426
  };
942
1427
  const allocateSeqRange = async (db, count, session) => {
943
- const { RtsCounter } = getRtsModels(db);
944
- const updated = await RtsCounter.findOneAndUpdate(
945
- { _id: RTS_COUNTER_ID },
946
- { $inc: { seq: count } },
947
- { upsert: true, new: true, setDefaultsOnInsert: true, projection: { seq: 1 }, session }
948
- ).lean();
1428
+ const {
1429
+ RtsCounter
1430
+ } = getRtsModels(db);
1431
+ const updated = await RtsCounter.findOneAndUpdate({
1432
+ _id: RTS_COUNTER_ID
1433
+ }, {
1434
+ $inc: {
1435
+ seq: count
1436
+ }
1437
+ }, {
1438
+ upsert: true,
1439
+ new: true,
1440
+ setDefaultsOnInsert: true,
1441
+ projection: {
1442
+ seq: 1
1443
+ },
1444
+ session
1445
+ }).lean();
949
1446
  const end = Number(updated?.seq ?? 0);
950
1447
  const start = end - count + 1;
951
- return { start, end };
1448
+ return {
1449
+ start,
1450
+ end
1451
+ };
952
1452
  };
953
1453
  const insertChanges = async (db, changes, session) => {
954
1454
  if (!changes.length) return;
955
- const { RtsChange } = getRtsModels(db);
1455
+ const {
1456
+ RtsChange
1457
+ } = getRtsModels(db);
956
1458
  const ts = /* @__PURE__ */ new Date();
957
1459
  const docs = changes.map((c3) => ({
958
1460
  seq: c3.seq,
@@ -962,7 +1464,9 @@ const insertChanges = async (db, changes, session) => {
962
1464
  ts
963
1465
  }));
964
1466
  if (session) {
965
- await RtsChange.insertMany(docs, { session });
1467
+ await RtsChange.insertMany(docs, {
1468
+ session
1469
+ });
966
1470
  return;
967
1471
  }
968
1472
  await RtsChange.insertMany(docs);
@@ -970,7 +1474,9 @@ const insertChanges = async (db, changes, session) => {
970
1474
  const recordDeleteChanges = async (db, modelName, ids, session) => {
971
1475
  const uniqueIds = Array.from(new Set(ids)).filter(Boolean);
972
1476
  if (!uniqueIds.length) return;
973
- const { start } = await allocateSeqRange(db, uniqueIds.length, session);
1477
+ const {
1478
+ start
1479
+ } = await allocateSeqRange(db, uniqueIds.length, session);
974
1480
  await insertChanges(db, uniqueIds.map((docId, idx) => ({
975
1481
  seq: start + idx,
976
1482
  modelName,
@@ -979,8 +1485,14 @@ const recordDeleteChanges = async (db, modelName, ids, session) => {
979
1485
  })), session);
980
1486
  };
981
1487
  const recordResetModel = async (db, modelName, session) => {
982
- const { start } = await allocateSeqRange(db, 1, session);
983
- await insertChanges(db, [{ seq: start, modelName, op: "reset_model" }], session);
1488
+ const {
1489
+ start
1490
+ } = await allocateSeqRange(db, 1, session);
1491
+ await insertChanges(db, [{
1492
+ seq: start,
1493
+ modelName,
1494
+ op: "reset_model"
1495
+ }], session);
984
1496
  };
985
1497
  const captureDeleteMeta = async (query, mode) => {
986
1498
  const modelName = String(query?.model?.modelName ?? "");
@@ -988,7 +1500,9 @@ const captureDeleteMeta = async (query, mode) => {
988
1500
  if (isGlobalDb(query?.model?.db)) return;
989
1501
  const filter = typeof query.getFilter === "function" ? query.getFilter() : query.getQuery?.() ?? {};
990
1502
  const session = getQuerySession(query);
991
- const findQuery = query.model.find(filter, { _id: 1 });
1503
+ const findQuery = query.model.find(filter, {
1504
+ _id: 1
1505
+ });
992
1506
  if (session && typeof findQuery.session === "function") {
993
1507
  findQuery.session(session);
994
1508
  }
@@ -1027,19 +1541,34 @@ const flushDeleteMeta = async (query) => {
1027
1541
  }
1028
1542
  };
1029
1543
  const rtsChangeLogPlugin = (schema) => {
1030
- schema.pre("deleteOne", { query: true, document: false }, async function() {
1544
+ schema.pre("deleteOne", {
1545
+ query: true,
1546
+ document: false
1547
+ }, async function() {
1031
1548
  await captureDeleteMeta(this, "one");
1032
1549
  });
1033
- schema.pre("deleteMany", { query: true, document: false }, async function() {
1550
+ schema.pre("deleteMany", {
1551
+ query: true,
1552
+ document: false
1553
+ }, async function() {
1034
1554
  await captureDeleteMeta(this, "many");
1035
1555
  });
1036
- schema.post("deleteOne", { query: true, document: false }, async function() {
1556
+ schema.post("deleteOne", {
1557
+ query: true,
1558
+ document: false
1559
+ }, async function() {
1037
1560
  await flushDeleteMeta(this);
1038
1561
  });
1039
- schema.post("deleteMany", { query: true, document: false }, async function() {
1562
+ schema.post("deleteMany", {
1563
+ query: true,
1564
+ document: false
1565
+ }, async function() {
1040
1566
  await flushDeleteMeta(this);
1041
1567
  });
1042
- schema.post("findOneAndDelete", { query: true, document: false }, async function(doc) {
1568
+ schema.post("findOneAndDelete", {
1569
+ query: true,
1570
+ document: false
1571
+ }, async function(doc) {
1043
1572
  const modelName = String(this?.model?.modelName ?? "");
1044
1573
  if (!modelName || modelName.startsWith("RB") || EXCLUDED_MODEL_NAMES.has(modelName)) return;
1045
1574
  const db = this?.model?.db;
@@ -1060,7 +1589,9 @@ const mergeMongoQuery = (left, right) => {
1060
1589
  const leftQuery = isRecord(left) ? left : {};
1061
1590
  if (Object.keys(leftQuery).length === 0) return right;
1062
1591
  if (Object.keys(right).length === 0) return leftQuery;
1063
- return { $and: [leftQuery, right] };
1592
+ return {
1593
+ $and: [leftQuery, right]
1594
+ };
1064
1595
  };
1065
1596
  const getQueryOptions = (query) => {
1066
1597
  if (!query || typeof query !== "object") return void 0;
@@ -1094,12 +1625,16 @@ const addQueryAclFilter = (query, action) => {
1094
1625
  };
1095
1626
  const injectAggregateMatch = (pipeline, match) => {
1096
1627
  if (pipeline.length === 0) {
1097
- pipeline.unshift({ $match: match });
1628
+ pipeline.unshift({
1629
+ $match: match
1630
+ });
1098
1631
  return;
1099
1632
  }
1100
1633
  const first = pipeline[0];
1101
1634
  if (!isRecord(first)) {
1102
- pipeline.unshift({ $match: match });
1635
+ pipeline.unshift({
1636
+ $match: match
1637
+ });
1103
1638
  return;
1104
1639
  }
1105
1640
  if ("$geoNear" in first) {
@@ -1110,10 +1645,14 @@ const injectAggregateMatch = (pipeline, match) => {
1110
1645
  }
1111
1646
  }
1112
1647
  if ("$search" in first || "$vectorSearch" in first || "$searchMeta" in first) {
1113
- pipeline.splice(1, 0, { $match: match });
1648
+ pipeline.splice(1, 0, {
1649
+ $match: match
1650
+ });
1114
1651
  return;
1115
1652
  }
1116
- pipeline.unshift({ $match: match });
1653
+ pipeline.unshift({
1654
+ $match: match
1655
+ });
1117
1656
  };
1118
1657
  const addAggregateAclFilter = (aggregate, action) => {
1119
1658
  const storedAcl = getStoredAclFromAggregate(aggregate);
@@ -1132,7 +1671,12 @@ const patchAggregateAcl = () => {
1132
1671
  const AggregatePrototype = mongoose.Aggregate.prototype;
1133
1672
  if (typeof AggregatePrototype.acl === "function") return;
1134
1673
  AggregatePrototype.acl = function(ability, action = "read") {
1135
- this.option({ rbAcl: { ability, action } });
1674
+ this.option({
1675
+ rbAcl: {
1676
+ ability,
1677
+ action
1678
+ }
1679
+ });
1136
1680
  return this;
1137
1681
  };
1138
1682
  };
@@ -1154,7 +1698,12 @@ const createModelAclProxy = (model2, ability) => {
1154
1698
  const mongooseAclPlugin = (schema) => {
1155
1699
  patchAggregateAcl();
1156
1700
  schema.query.acl = function(ability, action) {
1157
- this.setOptions({ rbAcl: { ability, action } });
1701
+ this.setOptions({
1702
+ rbAcl: {
1703
+ ability,
1704
+ action
1705
+ }
1706
+ });
1158
1707
  return this;
1159
1708
  };
1160
1709
  schema.statics.acl = function(ability) {
@@ -1201,20 +1750,10 @@ const mongooseAclPlugin = (schema) => {
1201
1750
  });
1202
1751
  };
1203
1752
  let cachedModels = null;
1204
- const DEFAULT_GLOBAL_RB_MODEL_NAMES_SET = /* @__PURE__ */ new Set([
1205
- "RBUser",
1206
- "RBTenant",
1207
- "RBOAuthRequest"
1208
- ]);
1753
+ const DEFAULT_GLOBAL_RB_MODEL_NAMES_SET = /* @__PURE__ */ new Set(["RBUser", "RBTenant", "RBOAuthRequest"]);
1209
1754
  const assertSchema = (exportName, value) => {
1210
1755
  if (value instanceof mongoose.Schema) return value;
1211
- throw new Error(
1212
- [
1213
- `Expected ${exportName} to be an instance of mongoose.Schema, but it was not.`,
1214
- "rpcbase supports mongoose 9+ only.",
1215
- "Fix: ensure the project is using mongoose 9.x and that all packages resolve the same mongoose instance (try `npm ls mongoose`)."
1216
- ].join(" ")
1217
- );
1756
+ throw new Error([`Expected ${exportName} to be an instance of mongoose.Schema, but it was not.`, "rpcbase supports mongoose 9+ only.", "Fix: ensure the project is using mongoose 9.x and that all packages resolve the same mongoose instance (try `npm ls mongoose`)."].join(" "));
1218
1757
  };
1219
1758
  const getFrameworkSchemaForModelName = (modelName) => {
1220
1759
  const exportName = `${modelName}Schema`;
@@ -1237,14 +1776,23 @@ const registerSchema = (target, other, modelName, schema, scope) => {
1237
1776
  const buildSchemasFromModules = (modules) => Object.entries(modules).filter(([key]) => key.endsWith("Schema")).map(([key, schemaValue]) => {
1238
1777
  const schema = assertSchema(key, schemaValue);
1239
1778
  const modelName = key.replace(/Schema$/, "");
1240
- return { modelName, schema };
1779
+ return {
1780
+ modelName,
1781
+ schema
1782
+ };
1241
1783
  });
1242
- const registerModels = ({ tenant, global }) => {
1784
+ const registerModels = ({
1785
+ tenant,
1786
+ global
1787
+ }) => {
1243
1788
  registerPoliciesFromModules(frameworkSchemas);
1244
1789
  registerPoliciesFromModules(tenant);
1245
1790
  const tenantSchemas = {};
1246
1791
  const globalSchemas = {};
1247
- for (const { modelName, schema } of buildSchemasFromModules(frameworkSchemas)) {
1792
+ for (const {
1793
+ modelName,
1794
+ schema
1795
+ } of buildSchemasFromModules(frameworkSchemas)) {
1248
1796
  if (DEFAULT_GLOBAL_RB_MODEL_NAMES_SET.has(modelName)) {
1249
1797
  const cloned = schema.clone();
1250
1798
  registerSchema(globalSchemas, tenantSchemas, modelName, cloned);
@@ -1254,7 +1802,10 @@ const registerModels = ({ tenant, global }) => {
1254
1802
  registerSchema(tenantSchemas, globalSchemas, modelName, cloned);
1255
1803
  }
1256
1804
  }
1257
- for (const { modelName, schema } of buildSchemasFromModules(tenant)) {
1805
+ for (const {
1806
+ modelName,
1807
+ schema
1808
+ } of buildSchemasFromModules(tenant)) {
1258
1809
  if (modelName === "RBUser" || modelName === "RBTenant") {
1259
1810
  throw new Error(`Invalid tenant model name "${modelName}". RBUser/RBTenant are global models.`);
1260
1811
  }
@@ -1267,7 +1818,10 @@ const registerModels = ({ tenant, global }) => {
1267
1818
  applyTenantPlugins(cloned);
1268
1819
  registerSchema(tenantSchemas, globalSchemas, modelName, cloned);
1269
1820
  }
1270
- for (const { modelName, schema } of buildSchemasFromModules(global ?? {})) {
1821
+ for (const {
1822
+ modelName,
1823
+ schema
1824
+ } of buildSchemasFromModules(global ?? {})) {
1271
1825
  if (modelName.startsWith("RB")) {
1272
1826
  const frameworkSchema = getFrameworkSchemaForModelName(modelName);
1273
1827
  if (frameworkSchema && schema === frameworkSchema) continue;
@@ -1276,15 +1830,24 @@ const registerModels = ({ tenant, global }) => {
1276
1830
  const cloned = schema.clone();
1277
1831
  registerSchema(globalSchemas, tenantSchemas, modelName, cloned);
1278
1832
  }
1279
- const allSchemas = { ...globalSchemas, ...tenantSchemas };
1833
+ const allSchemas = {
1834
+ ...globalSchemas,
1835
+ ...tenantSchemas
1836
+ };
1280
1837
  for (const [modelName, schema] of Object.entries(allSchemas)) {
1281
1838
  if (!mongoose.models[modelName]) {
1282
1839
  mongoose.model(modelName, schema);
1283
1840
  }
1284
1841
  }
1285
1842
  cachedModels = {
1286
- tenant: { ...cachedModels?.tenant ?? {}, ...tenantSchemas },
1287
- global: { ...cachedModels?.global ?? {}, ...globalSchemas }
1843
+ tenant: {
1844
+ ...cachedModels?.tenant ?? {},
1845
+ ...tenantSchemas
1846
+ },
1847
+ global: {
1848
+ ...cachedModels?.global ?? {},
1849
+ ...globalSchemas
1850
+ }
1288
1851
  };
1289
1852
  };
1290
1853
  const getRegisteredModels = (scope) => {
@@ -1392,7 +1955,11 @@ async function withTransaction(scope, fn, options) {
1392
1955
  const filesystemDb = await ensureMongooseConnection(filesystemDbName);
1393
1956
  const session = await tenantDb.startSession();
1394
1957
  const tenantCtx = typeof scope === "object" && "ctx" in scope ? scope.ctx : buildTenantLoadModelCtx(normalizedTenantId);
1395
- const globalCtx = { req: { session: null } };
1958
+ const globalCtx = {
1959
+ req: {
1960
+ session: null
1961
+ }
1962
+ };
1396
1963
  try {
1397
1964
  return await session.withTransaction(async () => fn({
1398
1965
  tenantId: normalizedTenantId,