@rpcbase/db 0.121.0 → 0.123.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/billingStorage.d.ts +7 -0
- package/dist/billingStorage.d.ts.map +1 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +412 -13
- package/dist/index.js.map +1 -1
- package/dist/models/RBTenantSubscriptionEvent.d.ts +376 -5
- package/dist/models/RBTenantSubscriptionEvent.d.ts.map +1 -1
- package/dist/models/RBTenantSubscriptionProjection.d.ts +49 -0
- package/dist/models/RBTenantSubscriptionProjection.d.ts.map +1 -0
- package/dist/models/index.d.ts +1 -0
- package/dist/models/index.d.ts.map +1 -1
- package/package.json +4 -2
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import { BillingStorage } from '@rpcbase/billing';
|
|
2
|
+
import { LoadModelCtx } from './modelsApi';
|
|
3
|
+
export declare const createTenantBillingStorage: (params: {
|
|
4
|
+
ctx: LoadModelCtx;
|
|
5
|
+
tenantId: string;
|
|
6
|
+
}) => BillingStorage;
|
|
7
|
+
//# sourceMappingURL=billingStorage.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"billingStorage.d.ts","sourceRoot":"","sources":["../src/billingStorage.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EACV,cAAc,EAKf,MAAM,kBAAkB,CAAA;AAGzB,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,aAAa,CAAA;AA8D/C,eAAO,MAAM,0BAA0B,GAAI,QAAQ;IACjD,GAAG,EAAE,YAAY,CAAA;IACjB,QAAQ,EAAE,MAAM,CAAA;CACjB,KAAG,cAsEH,CAAA"}
|
package/dist/index.d.ts
CHANGED
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,OAAO,CAAA;AACrB,cAAc,UAAU,CAAA;AACxB,cAAc,YAAY,CAAA;AAC1B,cAAc,cAAc,CAAA;AAC5B,cAAc,UAAU,CAAA;AACxB,cAAc,OAAO,CAAA;AAErB,cAAc,cAAc,CAAA;AAC5B,cAAc,gBAAgB,CAAA;AAC9B,cAAc,aAAa,CAAA;AAC3B,cAAc,sBAAsB,CAAA;AACpC,cAAc,gBAAgB,CAAA"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,OAAO,CAAA;AACrB,cAAc,UAAU,CAAA;AACxB,cAAc,YAAY,CAAA;AAC1B,cAAc,cAAc,CAAA;AAC5B,cAAc,UAAU,CAAA;AACxB,cAAc,OAAO,CAAA;AAErB,cAAc,cAAc,CAAA;AAC5B,cAAc,gBAAgB,CAAA;AAC9B,cAAc,kBAAkB,CAAA;AAChC,cAAc,aAAa,CAAA;AAC3B,cAAc,sBAAsB,CAAA;AACpC,cAAc,gBAAgB,CAAA"}
|
package/dist/index.js
CHANGED
|
@@ -3,6 +3,7 @@ import { b, a, c, g, d, e, f } from "./can-B4pD_pnR.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
|
+
import { SUBSCRIPTION_STATUSES, SUBSCRIPTION_INTERVAL_UNITS, SUBSCRIPTION_TYPES, SUBSCRIPTION_SCOPES, SUBSCRIPTION_EVENT_TYPES, SUBSCRIPTION_CHANGE_DIRECTIONS } from "@rpcbase/billing";
|
|
6
7
|
import { timingSafeEqual, createHmac } from "node:crypto";
|
|
7
8
|
import { w as withLocalizedStringFallback } from "./index-DrIoUXc2.js";
|
|
8
9
|
import { E, a as a2, L, b as b2, e as e2, m, r, z as z2, c as c2, d as d2, f as f2 } from "./index-DrIoUXc2.js";
|
|
@@ -166,16 +167,22 @@ const RBTenantSchema = new Schema$1({
|
|
|
166
167
|
type: String
|
|
167
168
|
}
|
|
168
169
|
});
|
|
169
|
-
const ZRBTenantSubscriptionStatus = z.enum(
|
|
170
|
-
const ZRBTenantSubscriptionIntervalUnit = z.enum(
|
|
170
|
+
const ZRBTenantSubscriptionStatus = z.enum(SUBSCRIPTION_STATUSES);
|
|
171
|
+
const ZRBTenantSubscriptionIntervalUnit = z.enum(SUBSCRIPTION_INTERVAL_UNITS);
|
|
172
|
+
const ZRBTenantSubscriptionType = z.enum(SUBSCRIPTION_TYPES);
|
|
173
|
+
const ZRBTenantSubscriptionScope = z.enum(SUBSCRIPTION_SCOPES);
|
|
174
|
+
const ZRBTenantSubscriptionEventType = z.enum(SUBSCRIPTION_EVENT_TYPES);
|
|
171
175
|
const ZRBTenantSubscriptionEventSource = z.enum(["admin", "system", "webhook", "user"]);
|
|
172
|
-
const ZRBTenantSubscriptionChangeDirection = z.enum(
|
|
173
|
-
const
|
|
174
|
-
tenantId: z.string(),
|
|
175
|
-
subscriptionId: z.string(),
|
|
176
|
-
type: z.string(),
|
|
176
|
+
const ZRBTenantSubscriptionChangeDirection = z.enum(SUBSCRIPTION_CHANGE_DIRECTIONS);
|
|
177
|
+
const subscriptionEventBaseSchema = z.object({
|
|
178
|
+
tenantId: z.string().trim().min(1),
|
|
179
|
+
subscriptionId: z.string().trim().min(1),
|
|
177
180
|
occurredAt: z.date(),
|
|
178
|
-
effectiveAt: z.date()
|
|
181
|
+
effectiveAt: z.date(),
|
|
182
|
+
subscriptionType: ZRBTenantSubscriptionType,
|
|
183
|
+
parentSubscriptionId: z.string().optional(),
|
|
184
|
+
scope: ZRBTenantSubscriptionScope,
|
|
185
|
+
scopeId: z.string().optional(),
|
|
179
186
|
fromPlanKey: z.string().optional(),
|
|
180
187
|
toPlanKey: z.string().optional(),
|
|
181
188
|
fromStatus: ZRBTenantSubscriptionStatus.optional(),
|
|
@@ -186,6 +193,11 @@ const ZRBTenantSubscriptionEvent = z.object({
|
|
|
186
193
|
toIntervalUnit: ZRBTenantSubscriptionIntervalUnit.optional(),
|
|
187
194
|
fromIntervalCount: z.number().int().min(1).optional(),
|
|
188
195
|
toIntervalCount: z.number().int().min(1).optional(),
|
|
196
|
+
fromPriceId: z.string().optional(),
|
|
197
|
+
toPriceId: z.string().optional(),
|
|
198
|
+
billingAnchor: z.date().optional(),
|
|
199
|
+
supersedesEventId: z.string().optional(),
|
|
200
|
+
idempotencyKey: z.string().trim().min(1),
|
|
189
201
|
direction: ZRBTenantSubscriptionChangeDirection.optional(),
|
|
190
202
|
actorUserId: z.string().optional(),
|
|
191
203
|
source: ZRBTenantSubscriptionEventSource.optional(),
|
|
@@ -195,6 +207,65 @@ const ZRBTenantSubscriptionEvent = z.object({
|
|
|
195
207
|
providerPayload: z.unknown().optional(),
|
|
196
208
|
metadata: z.record(z.string(), z.unknown()).optional()
|
|
197
209
|
});
|
|
210
|
+
const subscriptionCreatedEventSchema = subscriptionEventBaseSchema.extend({
|
|
211
|
+
type: z.literal("created"),
|
|
212
|
+
toPlanKey: z.string().trim().min(1),
|
|
213
|
+
toStatus: ZRBTenantSubscriptionStatus,
|
|
214
|
+
toModules: z.array(z.string()),
|
|
215
|
+
toIntervalUnit: ZRBTenantSubscriptionIntervalUnit,
|
|
216
|
+
toIntervalCount: z.number().int().min(1),
|
|
217
|
+
billingAnchor: z.date()
|
|
218
|
+
});
|
|
219
|
+
const subscriptionPlanChangedEventSchema = subscriptionEventBaseSchema.extend({
|
|
220
|
+
type: z.literal("plan_changed"),
|
|
221
|
+
fromPlanKey: z.string().trim().min(1),
|
|
222
|
+
toPlanKey: z.string().trim().min(1),
|
|
223
|
+
fromModules: z.array(z.string()),
|
|
224
|
+
toModules: z.array(z.string()),
|
|
225
|
+
fromIntervalUnit: ZRBTenantSubscriptionIntervalUnit,
|
|
226
|
+
toIntervalUnit: ZRBTenantSubscriptionIntervalUnit,
|
|
227
|
+
fromIntervalCount: z.number().int().min(1),
|
|
228
|
+
toIntervalCount: z.number().int().min(1)
|
|
229
|
+
});
|
|
230
|
+
const subscriptionStatusChangedEventSchema = subscriptionEventBaseSchema.extend({
|
|
231
|
+
type: z.literal("status_changed"),
|
|
232
|
+
fromStatus: ZRBTenantSubscriptionStatus,
|
|
233
|
+
toStatus: ZRBTenantSubscriptionStatus
|
|
234
|
+
});
|
|
235
|
+
const subscriptionResumedEventSchema = subscriptionEventBaseSchema.extend({
|
|
236
|
+
type: z.literal("resumed"),
|
|
237
|
+
fromStatus: ZRBTenantSubscriptionStatus,
|
|
238
|
+
toStatus: z.literal("active")
|
|
239
|
+
});
|
|
240
|
+
const subscriptionCanceledEventSchema = subscriptionEventBaseSchema.extend({
|
|
241
|
+
type: z.literal("canceled"),
|
|
242
|
+
fromStatus: ZRBTenantSubscriptionStatus,
|
|
243
|
+
toStatus: z.literal("canceled")
|
|
244
|
+
});
|
|
245
|
+
const subscriptionRenewedEventSchema = subscriptionEventBaseSchema.extend({
|
|
246
|
+
type: z.literal("renewed"),
|
|
247
|
+
fromStatus: ZRBTenantSubscriptionStatus,
|
|
248
|
+
toStatus: ZRBTenantSubscriptionStatus
|
|
249
|
+
});
|
|
250
|
+
const ZRBTenantSubscriptionEvent = z.discriminatedUnion("type", [subscriptionCreatedEventSchema, subscriptionPlanChangedEventSchema, subscriptionStatusChangedEventSchema, subscriptionResumedEventSchema, subscriptionCanceledEventSchema, subscriptionRenewedEventSchema]).superRefine((event, ctx) => {
|
|
251
|
+
if (event.subscriptionType === "addon" && !event.parentSubscriptionId?.trim()) {
|
|
252
|
+
ctx.addIssue({
|
|
253
|
+
code: "custom",
|
|
254
|
+
message: "parentSubscriptionId is required for add-on subscriptions",
|
|
255
|
+
path: ["parentSubscriptionId"]
|
|
256
|
+
});
|
|
257
|
+
}
|
|
258
|
+
if (event.scope !== "tenant" && !event.scopeId?.trim()) {
|
|
259
|
+
ctx.addIssue({
|
|
260
|
+
code: "custom",
|
|
261
|
+
message: "scopeId is required for non-tenant subscriptions",
|
|
262
|
+
path: ["scopeId"]
|
|
263
|
+
});
|
|
264
|
+
}
|
|
265
|
+
});
|
|
266
|
+
const requiredForEventTypes = (...types) => function requiredForEventType() {
|
|
267
|
+
return Boolean(this.type && types.includes(this.type));
|
|
268
|
+
};
|
|
198
269
|
const RBTenantSubscriptionEventSchema = new Schema$1({
|
|
199
270
|
tenantId: {
|
|
200
271
|
type: String,
|
|
@@ -208,7 +279,8 @@ const RBTenantSubscriptionEventSchema = new Schema$1({
|
|
|
208
279
|
},
|
|
209
280
|
type: {
|
|
210
281
|
type: String,
|
|
211
|
-
required: true
|
|
282
|
+
required: true,
|
|
283
|
+
enum: ZRBTenantSubscriptionEventType.options
|
|
212
284
|
},
|
|
213
285
|
occurredAt: {
|
|
214
286
|
type: Date,
|
|
@@ -216,46 +288,96 @@ const RBTenantSubscriptionEventSchema = new Schema$1({
|
|
|
216
288
|
default: Date.now
|
|
217
289
|
},
|
|
218
290
|
effectiveAt: {
|
|
219
|
-
type: Date
|
|
291
|
+
type: Date,
|
|
292
|
+
required: true
|
|
293
|
+
},
|
|
294
|
+
subscriptionType: {
|
|
295
|
+
type: String,
|
|
296
|
+
required: true,
|
|
297
|
+
enum: ZRBTenantSubscriptionType.options
|
|
298
|
+
},
|
|
299
|
+
parentSubscriptionId: {
|
|
300
|
+
type: String,
|
|
301
|
+
required() {
|
|
302
|
+
return this.subscriptionType === "addon";
|
|
303
|
+
}
|
|
304
|
+
},
|
|
305
|
+
scope: {
|
|
306
|
+
type: String,
|
|
307
|
+
required: true,
|
|
308
|
+
enum: ZRBTenantSubscriptionScope.options
|
|
309
|
+
},
|
|
310
|
+
scopeId: {
|
|
311
|
+
type: String,
|
|
312
|
+
required() {
|
|
313
|
+
return Boolean(this.scope && this.scope !== "tenant");
|
|
314
|
+
}
|
|
220
315
|
},
|
|
221
316
|
fromPlanKey: {
|
|
222
|
-
type: String
|
|
317
|
+
type: String,
|
|
318
|
+
required: requiredForEventTypes("plan_changed")
|
|
223
319
|
},
|
|
224
320
|
toPlanKey: {
|
|
225
|
-
type: String
|
|
321
|
+
type: String,
|
|
322
|
+
required: requiredForEventTypes("created", "plan_changed")
|
|
226
323
|
},
|
|
227
324
|
fromStatus: {
|
|
228
325
|
type: String,
|
|
326
|
+
required: requiredForEventTypes("status_changed", "resumed", "canceled", "renewed"),
|
|
229
327
|
enum: ZRBTenantSubscriptionStatus.options
|
|
230
328
|
},
|
|
231
329
|
toStatus: {
|
|
232
330
|
type: String,
|
|
331
|
+
required: requiredForEventTypes("created", "status_changed", "resumed", "canceled", "renewed"),
|
|
233
332
|
enum: ZRBTenantSubscriptionStatus.options
|
|
234
333
|
},
|
|
235
334
|
fromModules: {
|
|
236
335
|
type: [String],
|
|
336
|
+
required: requiredForEventTypes("plan_changed"),
|
|
237
337
|
default: void 0
|
|
238
338
|
},
|
|
239
339
|
toModules: {
|
|
240
340
|
type: [String],
|
|
341
|
+
required: requiredForEventTypes("created", "plan_changed"),
|
|
241
342
|
default: void 0
|
|
242
343
|
},
|
|
243
344
|
fromIntervalUnit: {
|
|
244
345
|
type: String,
|
|
346
|
+
required: requiredForEventTypes("plan_changed"),
|
|
245
347
|
enum: ZRBTenantSubscriptionIntervalUnit.options
|
|
246
348
|
},
|
|
247
349
|
toIntervalUnit: {
|
|
248
350
|
type: String,
|
|
351
|
+
required: requiredForEventTypes("created", "plan_changed"),
|
|
249
352
|
enum: ZRBTenantSubscriptionIntervalUnit.options
|
|
250
353
|
},
|
|
251
354
|
fromIntervalCount: {
|
|
252
355
|
type: Number,
|
|
356
|
+
required: requiredForEventTypes("plan_changed"),
|
|
253
357
|
min: 1
|
|
254
358
|
},
|
|
255
359
|
toIntervalCount: {
|
|
256
360
|
type: Number,
|
|
361
|
+
required: requiredForEventTypes("created", "plan_changed"),
|
|
257
362
|
min: 1
|
|
258
363
|
},
|
|
364
|
+
fromPriceId: {
|
|
365
|
+
type: String
|
|
366
|
+
},
|
|
367
|
+
toPriceId: {
|
|
368
|
+
type: String
|
|
369
|
+
},
|
|
370
|
+
billingAnchor: {
|
|
371
|
+
type: Date,
|
|
372
|
+
required: requiredForEventTypes("created")
|
|
373
|
+
},
|
|
374
|
+
supersedesEventId: {
|
|
375
|
+
type: String
|
|
376
|
+
},
|
|
377
|
+
idempotencyKey: {
|
|
378
|
+
type: String,
|
|
379
|
+
required: true
|
|
380
|
+
},
|
|
259
381
|
direction: {
|
|
260
382
|
type: String,
|
|
261
383
|
enum: ZRBTenantSubscriptionChangeDirection.options
|
|
@@ -286,6 +408,7 @@ const RBTenantSubscriptionEventSchema = new Schema$1({
|
|
|
286
408
|
RBTenantSubscriptionEventSchema.index({
|
|
287
409
|
tenantId: 1,
|
|
288
410
|
subscriptionId: 1,
|
|
411
|
+
effectiveAt: 1,
|
|
289
412
|
occurredAt: 1
|
|
290
413
|
});
|
|
291
414
|
RBTenantSubscriptionEventSchema.index({
|
|
@@ -293,7 +416,155 @@ RBTenantSubscriptionEventSchema.index({
|
|
|
293
416
|
providerEventId: 1
|
|
294
417
|
}, {
|
|
295
418
|
unique: true,
|
|
296
|
-
|
|
419
|
+
partialFilterExpression: {
|
|
420
|
+
provider: {
|
|
421
|
+
$type: "string"
|
|
422
|
+
},
|
|
423
|
+
providerEventId: {
|
|
424
|
+
$type: "string"
|
|
425
|
+
}
|
|
426
|
+
}
|
|
427
|
+
});
|
|
428
|
+
RBTenantSubscriptionEventSchema.index({
|
|
429
|
+
tenantId: 1,
|
|
430
|
+
idempotencyKey: 1
|
|
431
|
+
}, {
|
|
432
|
+
unique: true
|
|
433
|
+
});
|
|
434
|
+
const ZRBTenantSubscriptionProjection = z.object({
|
|
435
|
+
tenantId: z.string(),
|
|
436
|
+
subscriptionId: z.string(),
|
|
437
|
+
type: ZRBTenantSubscriptionType,
|
|
438
|
+
parentSubscriptionId: z.string().optional(),
|
|
439
|
+
scope: ZRBTenantSubscriptionScope,
|
|
440
|
+
scopeId: z.string().optional(),
|
|
441
|
+
planKey: z.string(),
|
|
442
|
+
priceId: z.string().optional(),
|
|
443
|
+
status: ZRBTenantSubscriptionStatus,
|
|
444
|
+
intervalUnit: ZRBTenantSubscriptionIntervalUnit,
|
|
445
|
+
intervalCount: z.number().int().min(1),
|
|
446
|
+
modules: z.array(z.string()),
|
|
447
|
+
billingAnchor: z.date(),
|
|
448
|
+
currentPeriodStart: z.date(),
|
|
449
|
+
currentPeriodEnd: z.date(),
|
|
450
|
+
cancelAtPeriodEnd: z.boolean(),
|
|
451
|
+
cancelAt: z.date().optional(),
|
|
452
|
+
canceledAt: z.date().optional(),
|
|
453
|
+
scheduledPlanKey: z.string().optional(),
|
|
454
|
+
scheduledPlanEffectiveAt: z.date().optional(),
|
|
455
|
+
provider: z.string().optional(),
|
|
456
|
+
latestEventId: z.string(),
|
|
457
|
+
latestEventAt: z.date(),
|
|
458
|
+
projectedAt: z.date()
|
|
459
|
+
});
|
|
460
|
+
const RBTenantSubscriptionProjectionSchema = new Schema$1({
|
|
461
|
+
tenantId: {
|
|
462
|
+
type: String,
|
|
463
|
+
required: true,
|
|
464
|
+
index: true
|
|
465
|
+
},
|
|
466
|
+
subscriptionId: {
|
|
467
|
+
type: String,
|
|
468
|
+
required: true
|
|
469
|
+
},
|
|
470
|
+
type: {
|
|
471
|
+
type: String,
|
|
472
|
+
required: true,
|
|
473
|
+
enum: ZRBTenantSubscriptionType.options
|
|
474
|
+
},
|
|
475
|
+
parentSubscriptionId: {
|
|
476
|
+
type: String
|
|
477
|
+
},
|
|
478
|
+
scope: {
|
|
479
|
+
type: String,
|
|
480
|
+
required: true,
|
|
481
|
+
enum: ZRBTenantSubscriptionScope.options
|
|
482
|
+
},
|
|
483
|
+
scopeId: {
|
|
484
|
+
type: String
|
|
485
|
+
},
|
|
486
|
+
planKey: {
|
|
487
|
+
type: String,
|
|
488
|
+
required: true
|
|
489
|
+
},
|
|
490
|
+
priceId: {
|
|
491
|
+
type: String
|
|
492
|
+
},
|
|
493
|
+
status: {
|
|
494
|
+
type: String,
|
|
495
|
+
required: true,
|
|
496
|
+
enum: ZRBTenantSubscriptionStatus.options
|
|
497
|
+
},
|
|
498
|
+
intervalUnit: {
|
|
499
|
+
type: String,
|
|
500
|
+
required: true,
|
|
501
|
+
enum: ZRBTenantSubscriptionIntervalUnit.options
|
|
502
|
+
},
|
|
503
|
+
intervalCount: {
|
|
504
|
+
type: Number,
|
|
505
|
+
required: true,
|
|
506
|
+
min: 1
|
|
507
|
+
},
|
|
508
|
+
modules: {
|
|
509
|
+
type: [String],
|
|
510
|
+
required: true,
|
|
511
|
+
default: []
|
|
512
|
+
},
|
|
513
|
+
billingAnchor: {
|
|
514
|
+
type: Date,
|
|
515
|
+
required: true
|
|
516
|
+
},
|
|
517
|
+
currentPeriodStart: {
|
|
518
|
+
type: Date,
|
|
519
|
+
required: true
|
|
520
|
+
},
|
|
521
|
+
currentPeriodEnd: {
|
|
522
|
+
type: Date,
|
|
523
|
+
required: true
|
|
524
|
+
},
|
|
525
|
+
cancelAtPeriodEnd: {
|
|
526
|
+
type: Boolean,
|
|
527
|
+
required: true,
|
|
528
|
+
default: false
|
|
529
|
+
},
|
|
530
|
+
cancelAt: {
|
|
531
|
+
type: Date
|
|
532
|
+
},
|
|
533
|
+
canceledAt: {
|
|
534
|
+
type: Date
|
|
535
|
+
},
|
|
536
|
+
scheduledPlanKey: {
|
|
537
|
+
type: String
|
|
538
|
+
},
|
|
539
|
+
scheduledPlanEffectiveAt: {
|
|
540
|
+
type: Date
|
|
541
|
+
},
|
|
542
|
+
provider: {
|
|
543
|
+
type: String
|
|
544
|
+
},
|
|
545
|
+
latestEventId: {
|
|
546
|
+
type: String,
|
|
547
|
+
required: true
|
|
548
|
+
},
|
|
549
|
+
latestEventAt: {
|
|
550
|
+
type: Date,
|
|
551
|
+
required: true
|
|
552
|
+
},
|
|
553
|
+
projectedAt: {
|
|
554
|
+
type: Date,
|
|
555
|
+
required: true
|
|
556
|
+
}
|
|
557
|
+
});
|
|
558
|
+
RBTenantSubscriptionProjectionSchema.index({
|
|
559
|
+
tenantId: 1,
|
|
560
|
+
subscriptionId: 1
|
|
561
|
+
}, {
|
|
562
|
+
unique: true
|
|
563
|
+
});
|
|
564
|
+
RBTenantSubscriptionProjectionSchema.index({
|
|
565
|
+
tenantId: 1,
|
|
566
|
+
scope: 1,
|
|
567
|
+
scopeId: 1
|
|
297
568
|
});
|
|
298
569
|
const ZRBRtsCounter = z.object({
|
|
299
570
|
_id: z.string(),
|
|
@@ -889,6 +1160,7 @@ const frameworkSchemas = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.de
|
|
|
889
1160
|
RBRtsCounterSchema,
|
|
890
1161
|
RBTenantSchema,
|
|
891
1162
|
RBTenantSubscriptionEventSchema,
|
|
1163
|
+
RBTenantSubscriptionProjectionSchema,
|
|
892
1164
|
RBUploadChunkSchema,
|
|
893
1165
|
RBUploadSessionPolicy,
|
|
894
1166
|
RBUploadSessionSchema,
|
|
@@ -907,8 +1179,12 @@ const frameworkSchemas = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.de
|
|
|
907
1179
|
ZRBTenantSubscriptionChangeDirection,
|
|
908
1180
|
ZRBTenantSubscriptionEvent,
|
|
909
1181
|
ZRBTenantSubscriptionEventSource,
|
|
1182
|
+
ZRBTenantSubscriptionEventType,
|
|
910
1183
|
ZRBTenantSubscriptionIntervalUnit,
|
|
1184
|
+
ZRBTenantSubscriptionProjection,
|
|
1185
|
+
ZRBTenantSubscriptionScope,
|
|
911
1186
|
ZRBTenantSubscriptionStatus,
|
|
1187
|
+
ZRBTenantSubscriptionType,
|
|
912
1188
|
ZRBUploadChunk,
|
|
913
1189
|
ZRBUploadSession,
|
|
914
1190
|
ZRBUploadSessionStatus,
|
|
@@ -2045,6 +2321,123 @@ async function withTransaction(scope, fn, options) {
|
|
|
2045
2321
|
await session.endSession();
|
|
2046
2322
|
}
|
|
2047
2323
|
}
|
|
2324
|
+
const getTransactionSession = (transaction) => {
|
|
2325
|
+
if (!transaction || typeof transaction !== "object" || !("session" in transaction)) return void 0;
|
|
2326
|
+
return transaction.session;
|
|
2327
|
+
};
|
|
2328
|
+
const toSubscriptionEvent = (document) => {
|
|
2329
|
+
const parsed = ZRBTenantSubscriptionEvent.parse(document);
|
|
2330
|
+
if (!document._id) throw new Error("Persisted subscription event is missing its id");
|
|
2331
|
+
return {
|
|
2332
|
+
...parsed,
|
|
2333
|
+
id: String(document._id)
|
|
2334
|
+
};
|
|
2335
|
+
};
|
|
2336
|
+
const getExistingEventQuery = (event, tenantId) => ({
|
|
2337
|
+
tenantId,
|
|
2338
|
+
idempotencyKey: event.idempotencyKey
|
|
2339
|
+
});
|
|
2340
|
+
const isDuplicateKeyError = (error) => Boolean(error && typeof error === "object" && "code" in error && error.code === 11e3);
|
|
2341
|
+
const toProjectionDocument = (projection) => ({
|
|
2342
|
+
tenantId: projection.tenantId,
|
|
2343
|
+
subscriptionId: projection.subscriptionId,
|
|
2344
|
+
type: projection.type,
|
|
2345
|
+
parentSubscriptionId: projection.parentSubscriptionId ?? void 0,
|
|
2346
|
+
scope: projection.scope,
|
|
2347
|
+
scopeId: projection.scopeId ?? void 0,
|
|
2348
|
+
planKey: projection.planKey,
|
|
2349
|
+
priceId: projection.priceId ?? void 0,
|
|
2350
|
+
status: projection.status,
|
|
2351
|
+
intervalUnit: projection.intervalUnit,
|
|
2352
|
+
intervalCount: projection.intervalCount,
|
|
2353
|
+
modules: projection.modules,
|
|
2354
|
+
billingAnchor: projection.billingAnchor,
|
|
2355
|
+
currentPeriodStart: projection.currentPeriodStart,
|
|
2356
|
+
currentPeriodEnd: projection.currentPeriodEnd,
|
|
2357
|
+
cancelAtPeriodEnd: projection.cancelAtPeriodEnd,
|
|
2358
|
+
cancelAt: projection.cancelAt ?? void 0,
|
|
2359
|
+
canceledAt: projection.canceledAt ?? void 0,
|
|
2360
|
+
scheduledPlanKey: projection.scheduledPlan?.planKey,
|
|
2361
|
+
scheduledPlanEffectiveAt: projection.scheduledPlan?.effectiveAt,
|
|
2362
|
+
provider: projection.provider ?? void 0,
|
|
2363
|
+
latestEventId: projection.latestEventId,
|
|
2364
|
+
latestEventAt: projection.latestEventAt,
|
|
2365
|
+
projectedAt: projection.projectedAt
|
|
2366
|
+
});
|
|
2367
|
+
const createTenantBillingStorage = (params) => {
|
|
2368
|
+
const findExistingEvent = async (query, transaction) => {
|
|
2369
|
+
const EventModel = await models.get("RBTenantSubscriptionEvent", params.ctx);
|
|
2370
|
+
const request = EventModel.findOne(query);
|
|
2371
|
+
const session = getTransactionSession(transaction);
|
|
2372
|
+
if (session) request.session(session);
|
|
2373
|
+
const document = await request.lean();
|
|
2374
|
+
return document ? toSubscriptionEvent(document) : null;
|
|
2375
|
+
};
|
|
2376
|
+
return {
|
|
2377
|
+
runInTransaction: (operation) => withTransaction({
|
|
2378
|
+
ctx: params.ctx
|
|
2379
|
+
}, ({
|
|
2380
|
+
session
|
|
2381
|
+
}) => operation({
|
|
2382
|
+
session
|
|
2383
|
+
})),
|
|
2384
|
+
createEvent: async (event, transaction) => {
|
|
2385
|
+
if (event.tenantId !== params.tenantId) {
|
|
2386
|
+
throw new Error("Billing event tenantId does not match the storage tenant");
|
|
2387
|
+
}
|
|
2388
|
+
const existingQuery = getExistingEventQuery(event, params.tenantId);
|
|
2389
|
+
const existing = await findExistingEvent(existingQuery, transaction);
|
|
2390
|
+
if (existing) return existing;
|
|
2391
|
+
const EventModel = await models.get("RBTenantSubscriptionEvent", params.ctx);
|
|
2392
|
+
const eventDocument = ZRBTenantSubscriptionEvent.parse(event);
|
|
2393
|
+
const session = getTransactionSession(transaction);
|
|
2394
|
+
try {
|
|
2395
|
+
const documents = await EventModel.create([eventDocument], session ? {
|
|
2396
|
+
session
|
|
2397
|
+
} : void 0);
|
|
2398
|
+
const document = documents[0]?.toObject();
|
|
2399
|
+
if (!document) throw new Error("Subscription event was not persisted");
|
|
2400
|
+
return toSubscriptionEvent(document);
|
|
2401
|
+
} catch (error) {
|
|
2402
|
+
if (!isDuplicateKeyError(error)) throw error;
|
|
2403
|
+
const duplicate = await findExistingEvent(existingQuery, transaction);
|
|
2404
|
+
if (!duplicate) throw error;
|
|
2405
|
+
return duplicate;
|
|
2406
|
+
}
|
|
2407
|
+
},
|
|
2408
|
+
listEvents: async (tenantId, subscriptionId, transaction) => {
|
|
2409
|
+
if (tenantId !== params.tenantId) throw new Error("Billing storage tenant mismatch");
|
|
2410
|
+
const EventModel = await models.get("RBTenantSubscriptionEvent", params.ctx);
|
|
2411
|
+
const request = EventModel.find({
|
|
2412
|
+
tenantId,
|
|
2413
|
+
subscriptionId
|
|
2414
|
+
}).sort({
|
|
2415
|
+
effectiveAt: 1,
|
|
2416
|
+
occurredAt: 1,
|
|
2417
|
+
_id: 1
|
|
2418
|
+
});
|
|
2419
|
+
const session = getTransactionSession(transaction);
|
|
2420
|
+
if (session) request.session(session);
|
|
2421
|
+
const documents = await request.lean();
|
|
2422
|
+
return documents.map(toSubscriptionEvent);
|
|
2423
|
+
},
|
|
2424
|
+
upsertProjection: async (projection, transaction) => {
|
|
2425
|
+
if (projection.tenantId !== params.tenantId) throw new Error("Billing projection tenant mismatch");
|
|
2426
|
+
const ProjectionModel = await models.get("RBTenantSubscriptionProjection", params.ctx);
|
|
2427
|
+
const session = getTransactionSession(transaction);
|
|
2428
|
+
await ProjectionModel.replaceOne({
|
|
2429
|
+
tenantId: params.tenantId,
|
|
2430
|
+
subscriptionId: projection.subscriptionId
|
|
2431
|
+
}, toProjectionDocument(projection), {
|
|
2432
|
+
upsert: true,
|
|
2433
|
+
runValidators: true,
|
|
2434
|
+
...session ? {
|
|
2435
|
+
session
|
|
2436
|
+
} : {}
|
|
2437
|
+
});
|
|
2438
|
+
}
|
|
2439
|
+
};
|
|
2440
|
+
};
|
|
2048
2441
|
export {
|
|
2049
2442
|
E as E164_PHONE_OR_EMPTY_REGEX,
|
|
2050
2443
|
a2 as E164_PHONE_REGEX,
|
|
@@ -2061,6 +2454,7 @@ export {
|
|
|
2061
2454
|
RBRtsCounterSchema,
|
|
2062
2455
|
RBTenantSchema,
|
|
2063
2456
|
RBTenantSubscriptionEventSchema,
|
|
2457
|
+
RBTenantSubscriptionProjectionSchema,
|
|
2064
2458
|
RBUploadChunkSchema,
|
|
2065
2459
|
RBUploadSessionPolicy,
|
|
2066
2460
|
RBUploadSessionSchema,
|
|
@@ -2080,8 +2474,12 @@ export {
|
|
|
2080
2474
|
ZRBTenantSubscriptionChangeDirection,
|
|
2081
2475
|
ZRBTenantSubscriptionEvent,
|
|
2082
2476
|
ZRBTenantSubscriptionEventSource,
|
|
2477
|
+
ZRBTenantSubscriptionEventType,
|
|
2083
2478
|
ZRBTenantSubscriptionIntervalUnit,
|
|
2479
|
+
ZRBTenantSubscriptionProjection,
|
|
2480
|
+
ZRBTenantSubscriptionScope,
|
|
2084
2481
|
ZRBTenantSubscriptionStatus,
|
|
2482
|
+
ZRBTenantSubscriptionType,
|
|
2085
2483
|
ZRBUploadChunk,
|
|
2086
2484
|
ZRBUploadSession,
|
|
2087
2485
|
ZRBUploadSessionStatus,
|
|
@@ -2092,6 +2490,7 @@ export {
|
|
|
2092
2490
|
buildSearchTextStage,
|
|
2093
2491
|
c as can,
|
|
2094
2492
|
createModels,
|
|
2493
|
+
createTenantBillingStorage,
|
|
2095
2494
|
ensureSearchIndex,
|
|
2096
2495
|
extendMongooseSchema,
|
|
2097
2496
|
e2 as extendZod,
|