@saasicat/adapter-prisma 0.5.0 → 0.7.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +147 -27
- package/dist/index.cjs +3167 -61
- package/dist/index.d.cts +544 -31
- package/dist/index.d.ts +544 -31
- package/dist/index.js +3154 -62
- package/package.json +4 -4
package/dist/index.js
CHANGED
|
@@ -86,7 +86,7 @@ PrismaAuditAdapter = _ts_decorate2([
|
|
|
86
86
|
_ts_param(0, Inject(PRISMA_CLIENT_TOKEN)),
|
|
87
87
|
_ts_metadata("design:type", Function),
|
|
88
88
|
_ts_metadata("design:paramtypes", [
|
|
89
|
-
typeof
|
|
89
|
+
typeof Pick === "undefined" ? Object : Pick
|
|
90
90
|
])
|
|
91
91
|
], PrismaAuditAdapter);
|
|
92
92
|
|
|
@@ -149,7 +149,7 @@ PrismaAuditQueryAdapter = _ts_decorate3([
|
|
|
149
149
|
_ts_param2(0, Inject2(PRISMA_CLIENT_TOKEN)),
|
|
150
150
|
_ts_metadata2("design:type", Function),
|
|
151
151
|
_ts_metadata2("design:paramtypes", [
|
|
152
|
-
typeof
|
|
152
|
+
typeof Pick === "undefined" ? Object : Pick
|
|
153
153
|
])
|
|
154
154
|
], PrismaAuditQueryAdapter);
|
|
155
155
|
function toActorTagFilter(actorTag) {
|
|
@@ -221,7 +221,7 @@ PrismaAuditStatsAdapter = _ts_decorate4([
|
|
|
221
221
|
_ts_param3(0, Inject3(PRISMA_CLIENT_TOKEN)),
|
|
222
222
|
_ts_metadata3("design:type", Function),
|
|
223
223
|
_ts_metadata3("design:paramtypes", [
|
|
224
|
-
typeof
|
|
224
|
+
typeof Pick === "undefined" ? Object : Pick
|
|
225
225
|
])
|
|
226
226
|
], PrismaAuditStatsAdapter);
|
|
227
227
|
|
|
@@ -291,12 +291,149 @@ PrismaMfaAdapter = _ts_decorate5([
|
|
|
291
291
|
_ts_param4(0, Inject4(PRISMA_CLIENT_TOKEN)),
|
|
292
292
|
_ts_metadata4("design:type", Function),
|
|
293
293
|
_ts_metadata4("design:paramtypes", [
|
|
294
|
-
typeof
|
|
294
|
+
typeof Pick === "undefined" ? Object : Pick
|
|
295
295
|
])
|
|
296
296
|
], PrismaMfaAdapter);
|
|
297
297
|
|
|
298
298
|
// src/prisma-plan-catalog-import-sink.ts
|
|
299
|
-
import { Inject as Inject5, Injectable as Injectable6 } from "@nestjs/common";
|
|
299
|
+
import { Inject as Inject5, Injectable as Injectable6, Optional } from "@nestjs/common";
|
|
300
|
+
|
|
301
|
+
// src/prisma-plan-binding.ts
|
|
302
|
+
var PRISMA_SCHEMA_OPTIONS_TOKEN = /* @__PURE__ */ Symbol.for("saasicat/adapter-prisma/PrismaSchemaOptions");
|
|
303
|
+
var DEFAULT_SCHEMA_OPTIONS = {
|
|
304
|
+
planBinding: {
|
|
305
|
+
mode: "legacy-plan-key"
|
|
306
|
+
},
|
|
307
|
+
delegates: {
|
|
308
|
+
catalogPlanVersion: "planVersion",
|
|
309
|
+
entitlementPlanVersion: "planVersion"
|
|
310
|
+
},
|
|
311
|
+
planVersionFields: {
|
|
312
|
+
catalog: {
|
|
313
|
+
validityWindows: false,
|
|
314
|
+
endsAt: false
|
|
315
|
+
},
|
|
316
|
+
entitlement: {
|
|
317
|
+
validityWindows: false,
|
|
318
|
+
endsAt: false
|
|
319
|
+
}
|
|
320
|
+
},
|
|
321
|
+
tenantSubscription: {
|
|
322
|
+
delegate: "subscription",
|
|
323
|
+
subscriptionBundleDelegate: false,
|
|
324
|
+
synchronizePlanVersion: false,
|
|
325
|
+
atomicOnboardingSelection: false,
|
|
326
|
+
activeVersionSelection: "latest-live",
|
|
327
|
+
withEndsAt: false
|
|
328
|
+
}
|
|
329
|
+
};
|
|
330
|
+
function resolvePrismaSchemaOptions(options) {
|
|
331
|
+
const mode = options?.planBinding?.mode ?? "legacy-plan-key";
|
|
332
|
+
const projectKey = options?.planBinding?.projectKey;
|
|
333
|
+
if (mode === "normalized-plan-id" && !projectKey?.trim()) {
|
|
334
|
+
throw new Error("Prisma plan binding mode 'normalized-plan-id' requires a non-empty projectKey.");
|
|
335
|
+
}
|
|
336
|
+
const sharedFields = options?.planVersionFields;
|
|
337
|
+
const catalogFields = sharedFields?.catalog;
|
|
338
|
+
const entitlementFields = sharedFields?.entitlement;
|
|
339
|
+
return {
|
|
340
|
+
planBinding: {
|
|
341
|
+
mode,
|
|
342
|
+
...projectKey ? {
|
|
343
|
+
projectKey
|
|
344
|
+
} : {}
|
|
345
|
+
},
|
|
346
|
+
delegates: {
|
|
347
|
+
catalogPlanVersion: options?.delegates?.catalogPlanVersion ?? DEFAULT_SCHEMA_OPTIONS.delegates.catalogPlanVersion,
|
|
348
|
+
entitlementPlanVersion: options?.delegates?.entitlementPlanVersion ?? DEFAULT_SCHEMA_OPTIONS.delegates.entitlementPlanVersion
|
|
349
|
+
},
|
|
350
|
+
planVersionFields: {
|
|
351
|
+
catalog: {
|
|
352
|
+
validityWindows: catalogFields?.validityWindows ?? sharedFields?.validityWindows ?? false,
|
|
353
|
+
endsAt: catalogFields?.endsAt ?? sharedFields?.endsAt ?? false
|
|
354
|
+
},
|
|
355
|
+
entitlement: {
|
|
356
|
+
validityWindows: entitlementFields?.validityWindows ?? sharedFields?.validityWindows ?? false,
|
|
357
|
+
endsAt: entitlementFields?.endsAt ?? sharedFields?.endsAt ?? false
|
|
358
|
+
}
|
|
359
|
+
},
|
|
360
|
+
tenantSubscription: {
|
|
361
|
+
delegate: options?.tenantSubscription?.delegate ?? DEFAULT_SCHEMA_OPTIONS.tenantSubscription.delegate,
|
|
362
|
+
subscriptionBundleDelegate: options?.tenantSubscription?.subscriptionBundleDelegate ?? DEFAULT_SCHEMA_OPTIONS.tenantSubscription.subscriptionBundleDelegate,
|
|
363
|
+
synchronizePlanVersion: options?.tenantSubscription?.synchronizePlanVersion ?? DEFAULT_SCHEMA_OPTIONS.tenantSubscription.synchronizePlanVersion,
|
|
364
|
+
atomicOnboardingSelection: options?.tenantSubscription?.atomicOnboardingSelection ?? DEFAULT_SCHEMA_OPTIONS.tenantSubscription.atomicOnboardingSelection,
|
|
365
|
+
activeVersionSelection: options?.tenantSubscription?.activeVersionSelection ?? DEFAULT_SCHEMA_OPTIONS.tenantSubscription.activeVersionSelection,
|
|
366
|
+
withEndsAt: options?.tenantSubscription?.withEndsAt ?? DEFAULT_SCHEMA_OPTIONS.tenantSubscription.withEndsAt
|
|
367
|
+
}
|
|
368
|
+
};
|
|
369
|
+
}
|
|
370
|
+
__name(resolvePrismaSchemaOptions, "resolvePrismaSchemaOptions");
|
|
371
|
+
function createPrismaPlanBindingResolver(options) {
|
|
372
|
+
const resolved = resolvePrismaSchemaOptions({
|
|
373
|
+
planBinding: options
|
|
374
|
+
}).planBinding;
|
|
375
|
+
return {
|
|
376
|
+
mode: resolved.mode,
|
|
377
|
+
projectKey: resolved.projectKey,
|
|
378
|
+
async toStoragePlanId(client, planKey, projectKey) {
|
|
379
|
+
if (resolved.mode === "legacy-plan-key") return planKey;
|
|
380
|
+
const scope = resolveProjectKey(resolved.projectKey, projectKey);
|
|
381
|
+
const plan = await asPlanIdentityClient(client).plan.findFirst({
|
|
382
|
+
where: {
|
|
383
|
+
projectKey: scope,
|
|
384
|
+
planKey,
|
|
385
|
+
deletedAt: null
|
|
386
|
+
}
|
|
387
|
+
});
|
|
388
|
+
if (!plan) {
|
|
389
|
+
throw new Error(`Plan '${planKey}' not found in project '${scope}'.`);
|
|
390
|
+
}
|
|
391
|
+
return plan.id;
|
|
392
|
+
},
|
|
393
|
+
async toPlanKey(client, storedPlanId, projectKey) {
|
|
394
|
+
if (resolved.mode === "legacy-plan-key") return storedPlanId;
|
|
395
|
+
const scope = resolveProjectKey(resolved.projectKey, projectKey);
|
|
396
|
+
const plan = await asPlanIdentityClient(client).plan.findUnique({
|
|
397
|
+
where: {
|
|
398
|
+
id: storedPlanId
|
|
399
|
+
}
|
|
400
|
+
});
|
|
401
|
+
if (!plan || plan.projectKey !== scope) {
|
|
402
|
+
throw new Error(`Plan id '${storedPlanId}' not found in project '${scope}'.`);
|
|
403
|
+
}
|
|
404
|
+
return plan.planKey;
|
|
405
|
+
}
|
|
406
|
+
};
|
|
407
|
+
}
|
|
408
|
+
__name(createPrismaPlanBindingResolver, "createPrismaPlanBindingResolver");
|
|
409
|
+
function getPrismaDelegate(client, delegateName) {
|
|
410
|
+
const delegate = client?.[delegateName];
|
|
411
|
+
if (!delegate || typeof delegate !== "object") {
|
|
412
|
+
throw new Error(`Prisma client has no '${delegateName}' delegate.`);
|
|
413
|
+
}
|
|
414
|
+
return delegate;
|
|
415
|
+
}
|
|
416
|
+
__name(getPrismaDelegate, "getPrismaDelegate");
|
|
417
|
+
function resolveProjectKey(configured, requested) {
|
|
418
|
+
const projectKey = requested ?? configured;
|
|
419
|
+
if (!projectKey) {
|
|
420
|
+
throw new Error("Prisma plan binding mode 'normalized-plan-id' requires a projectKey.");
|
|
421
|
+
}
|
|
422
|
+
if (configured && requested && configured !== requested) {
|
|
423
|
+
throw new Error(`Prisma plan binding is configured for project '${configured}', not '${requested}'.`);
|
|
424
|
+
}
|
|
425
|
+
return projectKey;
|
|
426
|
+
}
|
|
427
|
+
__name(resolveProjectKey, "resolveProjectKey");
|
|
428
|
+
function asPlanIdentityClient(client) {
|
|
429
|
+
if (!client || typeof client !== "object" || !("plan" in client)) {
|
|
430
|
+
throw new Error("Prisma client has no 'plan' delegate.");
|
|
431
|
+
}
|
|
432
|
+
return client;
|
|
433
|
+
}
|
|
434
|
+
__name(asPlanIdentityClient, "asPlanIdentityClient");
|
|
435
|
+
|
|
436
|
+
// src/prisma-plan-catalog-import-sink.ts
|
|
300
437
|
function _ts_decorate6(decorators, target, key, desc) {
|
|
301
438
|
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
302
439
|
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
@@ -319,11 +456,23 @@ var PrismaPlanCatalogImportSink = class {
|
|
|
319
456
|
__name(this, "PrismaPlanCatalogImportSink");
|
|
320
457
|
}
|
|
321
458
|
prisma;
|
|
322
|
-
|
|
459
|
+
binding;
|
|
460
|
+
delegateName;
|
|
461
|
+
constructor(prisma, options) {
|
|
323
462
|
this.prisma = prisma;
|
|
463
|
+
const schema = resolvePrismaSchemaOptions(options);
|
|
464
|
+
this.binding = createPrismaPlanBindingResolver(options?.planBinding);
|
|
465
|
+
this.delegateName = schema.delegates.catalogPlanVersion;
|
|
466
|
+
}
|
|
467
|
+
db() {
|
|
468
|
+
return this.prisma;
|
|
324
469
|
}
|
|
325
470
|
async upsertPlan(input) {
|
|
326
|
-
|
|
471
|
+
if (this.binding.mode === "normalized-plan-id" && this.binding.projectKey !== input.projectKey) {
|
|
472
|
+
throw new Error(`Prisma plan binding is configured for project '${this.binding.projectKey}', not '${input.projectKey}'.`);
|
|
473
|
+
}
|
|
474
|
+
const db = this.db();
|
|
475
|
+
const existing = await db.plan.findFirst({
|
|
327
476
|
where: {
|
|
328
477
|
projectKey: input.projectKey,
|
|
329
478
|
planKey: input.planKey
|
|
@@ -333,7 +482,7 @@ var PrismaPlanCatalogImportSink = class {
|
|
|
333
482
|
created: false,
|
|
334
483
|
skipReason: "exists"
|
|
335
484
|
};
|
|
336
|
-
await
|
|
485
|
+
await db.plan.create({
|
|
337
486
|
data: {
|
|
338
487
|
projectKey: input.projectKey,
|
|
339
488
|
planKey: input.planKey,
|
|
@@ -347,9 +496,11 @@ var PrismaPlanCatalogImportSink = class {
|
|
|
347
496
|
};
|
|
348
497
|
}
|
|
349
498
|
async upsertPlanVersion(input) {
|
|
350
|
-
const
|
|
499
|
+
const planVersion = this.planVersions();
|
|
500
|
+
const storedPlanId = await this.binding.toStoragePlanId(this.prisma, input.planKey);
|
|
501
|
+
const existing = await planVersion.findFirst({
|
|
351
502
|
where: {
|
|
352
|
-
planId:
|
|
503
|
+
planId: storedPlanId,
|
|
353
504
|
version: input.version
|
|
354
505
|
}
|
|
355
506
|
});
|
|
@@ -359,9 +510,9 @@ var PrismaPlanCatalogImportSink = class {
|
|
|
359
510
|
};
|
|
360
511
|
const now = /* @__PURE__ */ new Date();
|
|
361
512
|
if (input.publish) {
|
|
362
|
-
await
|
|
513
|
+
await planVersion.updateMany({
|
|
363
514
|
where: {
|
|
364
|
-
planId:
|
|
515
|
+
planId: storedPlanId,
|
|
365
516
|
publishedAt: {
|
|
366
517
|
not: null
|
|
367
518
|
},
|
|
@@ -375,9 +526,9 @@ var PrismaPlanCatalogImportSink = class {
|
|
|
375
526
|
}
|
|
376
527
|
});
|
|
377
528
|
}
|
|
378
|
-
await
|
|
529
|
+
await planVersion.create({
|
|
379
530
|
data: {
|
|
380
|
-
planId:
|
|
531
|
+
planId: storedPlanId,
|
|
381
532
|
version: input.version,
|
|
382
533
|
features: input.features,
|
|
383
534
|
quotas: input.quotas,
|
|
@@ -392,8 +543,12 @@ var PrismaPlanCatalogImportSink = class {
|
|
|
392
543
|
created: true
|
|
393
544
|
};
|
|
394
545
|
}
|
|
546
|
+
planVersions() {
|
|
547
|
+
return getPrismaDelegate(this.prisma, this.delegateName);
|
|
548
|
+
}
|
|
395
549
|
async upsertFeatureCatalogEntry(input) {
|
|
396
|
-
const
|
|
550
|
+
const db = this.db();
|
|
551
|
+
const existing = await db.featureCatalogEntry.findFirst({
|
|
397
552
|
where: {
|
|
398
553
|
projectKey: input.projectKey,
|
|
399
554
|
featureKey: input.featureKey
|
|
@@ -403,7 +558,7 @@ var PrismaPlanCatalogImportSink = class {
|
|
|
403
558
|
created: false,
|
|
404
559
|
skipReason: "exists"
|
|
405
560
|
};
|
|
406
|
-
await
|
|
561
|
+
await db.featureCatalogEntry.create({
|
|
407
562
|
data: {
|
|
408
563
|
projectKey: input.projectKey,
|
|
409
564
|
featureKey: input.featureKey,
|
|
@@ -422,14 +577,17 @@ var PrismaPlanCatalogImportSink = class {
|
|
|
422
577
|
PrismaPlanCatalogImportSink = _ts_decorate6([
|
|
423
578
|
Injectable6(),
|
|
424
579
|
_ts_param5(0, Inject5(PRISMA_CLIENT_TOKEN)),
|
|
580
|
+
_ts_param5(1, Optional()),
|
|
581
|
+
_ts_param5(1, Inject5(PRISMA_SCHEMA_OPTIONS_TOKEN)),
|
|
425
582
|
_ts_metadata5("design:type", Function),
|
|
426
583
|
_ts_metadata5("design:paramtypes", [
|
|
427
|
-
typeof
|
|
584
|
+
typeof PlanCatalogImportClient === "undefined" ? Object : PlanCatalogImportClient,
|
|
585
|
+
typeof PrismaSchemaOptions === "undefined" ? Object : PrismaSchemaOptions
|
|
428
586
|
])
|
|
429
587
|
], PrismaPlanCatalogImportSink);
|
|
430
588
|
|
|
431
589
|
// src/prisma-plan-catalog-read-sink.ts
|
|
432
|
-
import { Inject as Inject6, Injectable as Injectable7 } from "@nestjs/common";
|
|
590
|
+
import { Inject as Inject6, Injectable as Injectable7, Optional as Optional2 } from "@nestjs/common";
|
|
433
591
|
|
|
434
592
|
// src/tx.ts
|
|
435
593
|
function resolveClient(client, tx) {
|
|
@@ -471,11 +629,25 @@ var PrismaPlanCatalogReadSink = class {
|
|
|
471
629
|
__name(this, "PrismaPlanCatalogReadSink");
|
|
472
630
|
}
|
|
473
631
|
prisma;
|
|
474
|
-
|
|
632
|
+
binding;
|
|
633
|
+
delegateName;
|
|
634
|
+
fields;
|
|
635
|
+
constructor(prisma, options) {
|
|
475
636
|
this.prisma = prisma;
|
|
637
|
+
const schema = resolvePrismaSchemaOptions(options);
|
|
638
|
+
this.binding = createPrismaPlanBindingResolver(options?.planBinding);
|
|
639
|
+
this.delegateName = schema.delegates.catalogPlanVersion;
|
|
640
|
+
this.fields = schema.planVersionFields.catalog;
|
|
641
|
+
}
|
|
642
|
+
db() {
|
|
643
|
+
return this.prisma;
|
|
476
644
|
}
|
|
477
645
|
async loadSnapshot(projectKey) {
|
|
478
|
-
|
|
646
|
+
if (this.binding.mode === "normalized-plan-id" && this.binding.projectKey !== projectKey) {
|
|
647
|
+
throw new Error(`Prisma plan binding is configured for project '${this.binding.projectKey}', not '${projectKey}'.`);
|
|
648
|
+
}
|
|
649
|
+
const db = this.db();
|
|
650
|
+
const plans = await db.plan.findMany({
|
|
479
651
|
where: {
|
|
480
652
|
projectKey,
|
|
481
653
|
deletedAt: null
|
|
@@ -484,11 +656,17 @@ var PrismaPlanCatalogReadSink = class {
|
|
|
484
656
|
sortOrder: "asc"
|
|
485
657
|
}
|
|
486
658
|
});
|
|
487
|
-
const
|
|
488
|
-
|
|
659
|
+
const planKeysByStoredId = new Map(plans.map((plan) => [
|
|
660
|
+
this.binding.mode === "normalized-plan-id" ? plan.id : plan.planKey,
|
|
661
|
+
plan.planKey
|
|
662
|
+
]));
|
|
663
|
+
const storedPlanIds = [
|
|
664
|
+
...planKeysByStoredId.keys()
|
|
665
|
+
];
|
|
666
|
+
const livePlanVersions = storedPlanIds.length === 0 ? [] : await this.planVersions().findMany({
|
|
489
667
|
where: {
|
|
490
668
|
planId: {
|
|
491
|
-
in:
|
|
669
|
+
in: storedPlanIds
|
|
492
670
|
},
|
|
493
671
|
publishedAt: {
|
|
494
672
|
not: null
|
|
@@ -496,7 +674,7 @@ var PrismaPlanCatalogReadSink = class {
|
|
|
496
674
|
supersededAt: null
|
|
497
675
|
}
|
|
498
676
|
});
|
|
499
|
-
const featureEntries = await
|
|
677
|
+
const featureEntries = await db.featureCatalogEntry.findMany({
|
|
500
678
|
where: {
|
|
501
679
|
projectKey,
|
|
502
680
|
deletedAt: null
|
|
@@ -507,17 +685,29 @@ var PrismaPlanCatalogReadSink = class {
|
|
|
507
685
|
});
|
|
508
686
|
return {
|
|
509
687
|
plans: plans.map(toPlanRow),
|
|
510
|
-
livePlanVersions: livePlanVersions.map(
|
|
688
|
+
livePlanVersions: livePlanVersions.map((row) => {
|
|
689
|
+
const planKey = planKeysByStoredId.get(row.planId);
|
|
690
|
+
if (!planKey) {
|
|
691
|
+
throw new Error(`PlanVersion ${row.id} references plan '${row.planId}' outside project '${projectKey}'.`);
|
|
692
|
+
}
|
|
693
|
+
return toPlanVersionRow(row, planKey, this.fields);
|
|
694
|
+
}),
|
|
511
695
|
featureEntries: featureEntries.map(toFeatureCatalogEntryRow)
|
|
512
696
|
};
|
|
513
697
|
}
|
|
698
|
+
planVersions() {
|
|
699
|
+
return getPrismaDelegate(this.prisma, this.delegateName);
|
|
700
|
+
}
|
|
514
701
|
};
|
|
515
702
|
PrismaPlanCatalogReadSink = _ts_decorate7([
|
|
516
703
|
Injectable7(),
|
|
517
704
|
_ts_param6(0, Inject6(PRISMA_CLIENT_TOKEN)),
|
|
705
|
+
_ts_param6(1, Optional2()),
|
|
706
|
+
_ts_param6(1, Inject6(PRISMA_SCHEMA_OPTIONS_TOKEN)),
|
|
518
707
|
_ts_metadata6("design:type", Function),
|
|
519
708
|
_ts_metadata6("design:paramtypes", [
|
|
520
|
-
typeof
|
|
709
|
+
typeof PlanCatalogReadClient === "undefined" ? Object : PlanCatalogReadClient,
|
|
710
|
+
typeof PrismaSchemaOptions === "undefined" ? Object : PrismaSchemaOptions
|
|
521
711
|
])
|
|
522
712
|
], PrismaPlanCatalogReadSink);
|
|
523
713
|
function toPlanRow(row) {
|
|
@@ -535,10 +725,10 @@ function toPlanRow(row) {
|
|
|
535
725
|
};
|
|
536
726
|
}
|
|
537
727
|
__name(toPlanRow, "toPlanRow");
|
|
538
|
-
function toPlanVersionRow(row) {
|
|
539
|
-
|
|
728
|
+
function toPlanVersionRow(row, planKey, fields) {
|
|
729
|
+
const mapped = {
|
|
540
730
|
id: row.id,
|
|
541
|
-
planId:
|
|
731
|
+
planId: planKey,
|
|
542
732
|
version: row.version,
|
|
543
733
|
baseVersionId: row.baseVersionId,
|
|
544
734
|
publishedAt: row.publishedAt ? row.publishedAt.toISOString() : null,
|
|
@@ -546,8 +736,8 @@ function toPlanVersionRow(row) {
|
|
|
546
736
|
publishedChanges: row.publishedChanges ?? null,
|
|
547
737
|
changeNote: row.changeNote,
|
|
548
738
|
nonRegressive: row.nonRegressive,
|
|
549
|
-
validFrom: null,
|
|
550
|
-
validUntil: null,
|
|
739
|
+
validFrom: fields.validityWindows && row.validFrom ? row.validFrom.toISOString() : null,
|
|
740
|
+
validUntil: fields.validityWindows && row.validUntil ? row.validUntil.toISOString() : null,
|
|
551
741
|
createdByUserId: row.createdByUserId,
|
|
552
742
|
publishedByUserId: row.publishedByUserId,
|
|
553
743
|
createdAt: row.createdAt.toISOString(),
|
|
@@ -558,6 +748,10 @@ function toPlanVersionRow(row) {
|
|
|
558
748
|
yearlyNet: String(row.yearlyNet),
|
|
559
749
|
marketed: row.marketed
|
|
560
750
|
};
|
|
751
|
+
if (fields.endsAt) {
|
|
752
|
+
mapped.endsAt = row.endsAt?.toISOString() ?? null;
|
|
753
|
+
}
|
|
754
|
+
return mapped;
|
|
561
755
|
}
|
|
562
756
|
__name(toPlanVersionRow, "toPlanVersionRow");
|
|
563
757
|
function toFeatureCatalogEntryRow(row) {
|
|
@@ -590,7 +784,8 @@ function toFeatureCatalogEntryRow(row) {
|
|
|
590
784
|
__name(toFeatureCatalogEntryRow, "toFeatureCatalogEntryRow");
|
|
591
785
|
|
|
592
786
|
// src/prisma-plan-version.repository.ts
|
|
593
|
-
import { Inject as Inject7, Injectable as Injectable8 } from "@nestjs/common";
|
|
787
|
+
import { Inject as Inject7, Injectable as Injectable8, Optional as Optional3 } from "@nestjs/common";
|
|
788
|
+
import { buildActivePlanVersionWhere } from "@saasicat/types";
|
|
594
789
|
function _ts_decorate8(decorators, target, key, desc) {
|
|
595
790
|
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
596
791
|
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
@@ -613,14 +808,29 @@ var PrismaPlanVersionRepository = class {
|
|
|
613
808
|
__name(this, "PrismaPlanVersionRepository");
|
|
614
809
|
}
|
|
615
810
|
prisma;
|
|
616
|
-
|
|
811
|
+
findActive;
|
|
812
|
+
binding;
|
|
813
|
+
delegateName;
|
|
814
|
+
fields;
|
|
815
|
+
constructor(prisma, options) {
|
|
617
816
|
this.prisma = prisma;
|
|
817
|
+
const schema = resolvePrismaSchemaOptions(options);
|
|
818
|
+
this.binding = createPrismaPlanBindingResolver(options?.planBinding);
|
|
819
|
+
this.delegateName = schema.delegates.entitlementPlanVersion;
|
|
820
|
+
this.fields = schema.planVersionFields.entitlement;
|
|
821
|
+
if (this.fields.validityWindows) {
|
|
822
|
+
this.findActive = (planId, asOf = /* @__PURE__ */ new Date(), tx) => this.findActivePlanVersion(planId, asOf, tx);
|
|
823
|
+
}
|
|
824
|
+
}
|
|
825
|
+
db(tx) {
|
|
826
|
+
return tx ?? this.prisma;
|
|
618
827
|
}
|
|
619
828
|
async findLatestLive(planId, tx) {
|
|
620
|
-
const db =
|
|
621
|
-
const
|
|
829
|
+
const db = this.db(tx);
|
|
830
|
+
const storedPlanId = await this.binding.toStoragePlanId(db, planId);
|
|
831
|
+
const row = await this.versions(db).findFirst({
|
|
622
832
|
where: {
|
|
623
|
-
planId,
|
|
833
|
+
planId: storedPlanId,
|
|
624
834
|
publishedAt: {
|
|
625
835
|
not: null
|
|
626
836
|
},
|
|
@@ -631,8 +841,40 @@ var PrismaPlanVersionRepository = class {
|
|
|
631
841
|
}
|
|
632
842
|
});
|
|
633
843
|
if (!row) return null;
|
|
844
|
+
return this.toRecord(db, row);
|
|
845
|
+
}
|
|
846
|
+
async findActivePlanVersion(planId, asOf, tx) {
|
|
847
|
+
const db = this.db(tx);
|
|
848
|
+
const storedPlanId = await this.binding.toStoragePlanId(db, planId);
|
|
849
|
+
const activeWhere = this.fields.endsAt ? buildActivePlanVersionWhere(asOf, {
|
|
850
|
+
withEndsAt: true
|
|
851
|
+
}) : buildActivePlanVersionWhere(asOf);
|
|
852
|
+
const row = await this.versions(db).findFirst({
|
|
853
|
+
where: {
|
|
854
|
+
planId: storedPlanId,
|
|
855
|
+
...activeWhere
|
|
856
|
+
},
|
|
857
|
+
orderBy: [
|
|
858
|
+
{
|
|
859
|
+
validFrom: {
|
|
860
|
+
sort: "desc",
|
|
861
|
+
nulls: "last"
|
|
862
|
+
}
|
|
863
|
+
},
|
|
864
|
+
{
|
|
865
|
+
version: "desc"
|
|
866
|
+
}
|
|
867
|
+
]
|
|
868
|
+
});
|
|
869
|
+
if (!row) return null;
|
|
870
|
+
return this.toRecord(db, row);
|
|
871
|
+
}
|
|
872
|
+
versions(client) {
|
|
873
|
+
return getPrismaDelegate(client, this.delegateName);
|
|
874
|
+
}
|
|
875
|
+
async toRecord(client, row) {
|
|
634
876
|
return {
|
|
635
|
-
planId: row.planId,
|
|
877
|
+
planId: await this.binding.toPlanKey(client, row.planId),
|
|
636
878
|
quotas: toQuotaMap(row.quotas),
|
|
637
879
|
features: toStringArray(row.features)
|
|
638
880
|
};
|
|
@@ -641,9 +883,12 @@ var PrismaPlanVersionRepository = class {
|
|
|
641
883
|
PrismaPlanVersionRepository = _ts_decorate8([
|
|
642
884
|
Injectable8(),
|
|
643
885
|
_ts_param7(0, Inject7(PRISMA_CLIENT_TOKEN)),
|
|
886
|
+
_ts_param7(1, Optional3()),
|
|
887
|
+
_ts_param7(1, Inject7(PRISMA_SCHEMA_OPTIONS_TOKEN)),
|
|
644
888
|
_ts_metadata7("design:type", Function),
|
|
645
889
|
_ts_metadata7("design:paramtypes", [
|
|
646
|
-
typeof
|
|
890
|
+
typeof PlanVersionRepositoryClient === "undefined" ? Object : PlanVersionRepositoryClient,
|
|
891
|
+
typeof PrismaSchemaOptions === "undefined" ? Object : PrismaSchemaOptions
|
|
647
892
|
])
|
|
648
893
|
], PrismaPlanVersionRepository);
|
|
649
894
|
|
|
@@ -1084,7 +1329,7 @@ PrismaPromoSubscriptionLookup = _ts_decorate12([
|
|
|
1084
1329
|
], PrismaPromoSubscriptionLookup);
|
|
1085
1330
|
|
|
1086
1331
|
// src/prisma-subscription.repository.ts
|
|
1087
|
-
import { Inject as Inject12, Injectable as Injectable13 } from "@nestjs/common";
|
|
1332
|
+
import { Inject as Inject12, Injectable as Injectable13, Optional as Optional4 } from "@nestjs/common";
|
|
1088
1333
|
function _ts_decorate13(decorators, target, key, desc) {
|
|
1089
1334
|
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
1090
1335
|
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
@@ -1111,19 +1356,35 @@ var PrismaSubscriptionRepository = class {
|
|
|
1111
1356
|
__name(this, "PrismaSubscriptionRepository");
|
|
1112
1357
|
}
|
|
1113
1358
|
prisma;
|
|
1114
|
-
|
|
1359
|
+
countByBundleVersionId;
|
|
1360
|
+
binding;
|
|
1361
|
+
planVersionDelegateName;
|
|
1362
|
+
subscriptionDelegateName;
|
|
1363
|
+
subscriptionBundleDelegateName;
|
|
1364
|
+
constructor(prisma, options) {
|
|
1115
1365
|
this.prisma = prisma;
|
|
1366
|
+
const schema = resolvePrismaSchemaOptions(options);
|
|
1367
|
+
this.binding = createPrismaPlanBindingResolver(options?.planBinding);
|
|
1368
|
+
this.planVersionDelegateName = schema.delegates.entitlementPlanVersion;
|
|
1369
|
+
this.subscriptionDelegateName = schema.tenantSubscription.delegate;
|
|
1370
|
+
this.subscriptionBundleDelegateName = schema.tenantSubscription.subscriptionBundleDelegate;
|
|
1371
|
+
if (this.subscriptionBundleDelegateName) {
|
|
1372
|
+
this.countByBundleVersionId = (bundleVersionId) => this.countActiveBundleBindings(bundleVersionId);
|
|
1373
|
+
}
|
|
1374
|
+
}
|
|
1375
|
+
db(tx) {
|
|
1376
|
+
return tx ?? this.prisma;
|
|
1116
1377
|
}
|
|
1117
1378
|
async findByTenantId(tenantId) {
|
|
1118
|
-
return this.loadByTenantId(this.
|
|
1379
|
+
return this.loadByTenantId(this.db(), tenantId);
|
|
1119
1380
|
}
|
|
1120
1381
|
async findByTenantIdLocked(tenantId, tx) {
|
|
1121
|
-
const db =
|
|
1382
|
+
const db = this.db(tx);
|
|
1122
1383
|
await db.$queryRaw`SELECT id FROM subscriptions WHERE "tenantId" = ${tenantId} FOR UPDATE`;
|
|
1123
1384
|
return this.loadByTenantId(db, tenantId);
|
|
1124
1385
|
}
|
|
1125
1386
|
async countByPlanVersionId(planVersionId) {
|
|
1126
|
-
return this.
|
|
1387
|
+
return this.subscriptions(this.db()).count({
|
|
1127
1388
|
where: {
|
|
1128
1389
|
OR: [
|
|
1129
1390
|
{
|
|
@@ -1136,22 +1397,72 @@ var PrismaSubscriptionRepository = class {
|
|
|
1136
1397
|
}
|
|
1137
1398
|
});
|
|
1138
1399
|
}
|
|
1139
|
-
async countActiveByPlanKey(
|
|
1140
|
-
const
|
|
1400
|
+
async countActiveByPlanKey(projectKey) {
|
|
1401
|
+
const db = this.db();
|
|
1402
|
+
const subscriptions = await this.subscriptions(db).findMany({
|
|
1141
1403
|
where: {
|
|
1142
1404
|
status: {
|
|
1143
1405
|
in: ACTIVE_STATUSES
|
|
1144
1406
|
}
|
|
1407
|
+
},
|
|
1408
|
+
select: {
|
|
1409
|
+
planVersionId: true
|
|
1410
|
+
}
|
|
1411
|
+
});
|
|
1412
|
+
const versionIds = [
|
|
1413
|
+
...new Set(subscriptions.map((subscription) => subscription.planVersionId))
|
|
1414
|
+
];
|
|
1415
|
+
if (versionIds.length === 0) return {};
|
|
1416
|
+
const planVersions = await this.planVersions(db).findMany({
|
|
1417
|
+
where: {
|
|
1418
|
+
id: {
|
|
1419
|
+
in: versionIds
|
|
1420
|
+
}
|
|
1421
|
+
},
|
|
1422
|
+
select: {
|
|
1423
|
+
id: true,
|
|
1424
|
+
planId: true
|
|
1145
1425
|
}
|
|
1146
1426
|
});
|
|
1427
|
+
const planVersionById = new Map(planVersions.map((planVersion) => [
|
|
1428
|
+
planVersion.id,
|
|
1429
|
+
planVersion
|
|
1430
|
+
]));
|
|
1431
|
+
const storedPlanIds = [
|
|
1432
|
+
...new Set(planVersions.map((planVersion) => planVersion.planId))
|
|
1433
|
+
];
|
|
1434
|
+
const planKeyByStoredId = await this.planKeysForProject(db, storedPlanIds, projectKey);
|
|
1147
1435
|
const counts = {};
|
|
1148
|
-
for (const
|
|
1149
|
-
|
|
1436
|
+
for (const subscription of subscriptions) {
|
|
1437
|
+
const planVersion = planVersionById.get(subscription.planVersionId);
|
|
1438
|
+
const planKey = planVersion ? planKeyByStoredId.get(planVersion.planId) : void 0;
|
|
1439
|
+
if (!planKey) continue;
|
|
1440
|
+
counts[planKey] = (counts[planKey] ?? 0) + 1;
|
|
1150
1441
|
}
|
|
1151
1442
|
return counts;
|
|
1152
1443
|
}
|
|
1444
|
+
async countActiveBundleBindings(bundleVersionId) {
|
|
1445
|
+
if (!this.subscriptionBundleDelegateName) {
|
|
1446
|
+
throw new Error("SubscriptionBundle counting is not configured.");
|
|
1447
|
+
}
|
|
1448
|
+
return getPrismaDelegate(this.prisma, this.subscriptionBundleDelegateName).count({
|
|
1449
|
+
where: {
|
|
1450
|
+
bundleVersionId,
|
|
1451
|
+
OR: [
|
|
1452
|
+
{
|
|
1453
|
+
canceledAt: null
|
|
1454
|
+
},
|
|
1455
|
+
{
|
|
1456
|
+
canceledEffectiveAt: {
|
|
1457
|
+
gt: /* @__PURE__ */ new Date()
|
|
1458
|
+
}
|
|
1459
|
+
}
|
|
1460
|
+
]
|
|
1461
|
+
}
|
|
1462
|
+
});
|
|
1463
|
+
}
|
|
1153
1464
|
async loadByTenantId(db, tenantId) {
|
|
1154
|
-
const row = await db.
|
|
1465
|
+
const row = await this.subscriptions(db).findUnique({
|
|
1155
1466
|
where: {
|
|
1156
1467
|
tenantId
|
|
1157
1468
|
}
|
|
@@ -1160,10 +1471,7 @@ var PrismaSubscriptionRepository = class {
|
|
|
1160
1471
|
return this.toRecord(db, row);
|
|
1161
1472
|
}
|
|
1162
1473
|
async toRecord(db, row) {
|
|
1163
|
-
|
|
1164
|
-
throw new Error(`Subscription ${row.id} binds no planVersionId (businessType-only composition). The shipped @saasicat/adapter-prisma SubscriptionRepository does not support BusinessType aggregation \u2014 provide a custom SubscriptionRepository adapter.`);
|
|
1165
|
-
}
|
|
1166
|
-
const planVersion = await db.planVersion.findUnique({
|
|
1474
|
+
const planVersion = await this.planVersions(db).findUnique({
|
|
1167
1475
|
where: {
|
|
1168
1476
|
id: row.planVersionId
|
|
1169
1477
|
}
|
|
@@ -1171,10 +1479,13 @@ var PrismaSubscriptionRepository = class {
|
|
|
1171
1479
|
if (!planVersion) {
|
|
1172
1480
|
throw new Error(`Subscription ${row.id} references missing PlanVersion ${row.planVersionId}.`);
|
|
1173
1481
|
}
|
|
1482
|
+
const planKey = await this.binding.toPlanKey(db, planVersion.planId);
|
|
1174
1483
|
return {
|
|
1175
1484
|
id: row.id,
|
|
1176
1485
|
tenantId: row.tenantId,
|
|
1177
|
-
|
|
1486
|
+
// The concrete PlanVersion is authoritative. This also normalizes
|
|
1487
|
+
// legacy rows whose denormalized `Subscription.plan` drifted.
|
|
1488
|
+
plan: planKey,
|
|
1178
1489
|
status: row.status,
|
|
1179
1490
|
isPilot: row.isPilot,
|
|
1180
1491
|
trialEntitlementPlan: row.trialEntitlementPlan,
|
|
@@ -1183,19 +1494,78 @@ var PrismaSubscriptionRepository = class {
|
|
|
1183
1494
|
customLimits: row.customLimits ?? null,
|
|
1184
1495
|
planVersionId: row.planVersionId,
|
|
1185
1496
|
planVersion: {
|
|
1186
|
-
planId:
|
|
1497
|
+
planId: planKey,
|
|
1187
1498
|
quotas: toQuotaMap(planVersion.quotas),
|
|
1188
1499
|
features: toStringArray(planVersion.features)
|
|
1189
1500
|
}
|
|
1190
1501
|
};
|
|
1191
1502
|
}
|
|
1503
|
+
planVersions(client) {
|
|
1504
|
+
return getPrismaDelegate(client, this.planVersionDelegateName);
|
|
1505
|
+
}
|
|
1506
|
+
subscriptions(client) {
|
|
1507
|
+
return getPrismaDelegate(client, this.subscriptionDelegateName);
|
|
1508
|
+
}
|
|
1509
|
+
async planKeysForProject(db, storedPlanIds, projectKey) {
|
|
1510
|
+
if (storedPlanIds.length === 0) return /* @__PURE__ */ new Map();
|
|
1511
|
+
if (this.binding.mode === "normalized-plan-id") {
|
|
1512
|
+
if (this.binding.projectKey && this.binding.projectKey !== projectKey) {
|
|
1513
|
+
throw new Error(`Prisma plan binding is configured for project '${this.binding.projectKey}', not '${projectKey}'.`);
|
|
1514
|
+
}
|
|
1515
|
+
const plans2 = await db.plan.findMany({
|
|
1516
|
+
where: {
|
|
1517
|
+
projectKey,
|
|
1518
|
+
id: {
|
|
1519
|
+
in: storedPlanIds
|
|
1520
|
+
}
|
|
1521
|
+
},
|
|
1522
|
+
select: {
|
|
1523
|
+
id: true,
|
|
1524
|
+
planKey: true
|
|
1525
|
+
}
|
|
1526
|
+
});
|
|
1527
|
+
return new Map(plans2.map((plan) => [
|
|
1528
|
+
plan.id,
|
|
1529
|
+
plan.planKey
|
|
1530
|
+
]));
|
|
1531
|
+
}
|
|
1532
|
+
const plans = await db.plan.findMany({
|
|
1533
|
+
where: {
|
|
1534
|
+
planKey: {
|
|
1535
|
+
in: storedPlanIds
|
|
1536
|
+
}
|
|
1537
|
+
},
|
|
1538
|
+
select: {
|
|
1539
|
+
projectKey: true,
|
|
1540
|
+
planKey: true
|
|
1541
|
+
}
|
|
1542
|
+
});
|
|
1543
|
+
const projectsByPlanKey = /* @__PURE__ */ new Map();
|
|
1544
|
+
for (const plan of plans) {
|
|
1545
|
+
const projects = projectsByPlanKey.get(plan.planKey) ?? /* @__PURE__ */ new Set();
|
|
1546
|
+
projects.add(plan.projectKey);
|
|
1547
|
+
projectsByPlanKey.set(plan.planKey, projects);
|
|
1548
|
+
}
|
|
1549
|
+
return new Map(storedPlanIds.flatMap((planKey) => {
|
|
1550
|
+
const projects = projectsByPlanKey.get(planKey);
|
|
1551
|
+
return projects?.size === 1 && projects.has(projectKey) ? [
|
|
1552
|
+
[
|
|
1553
|
+
planKey,
|
|
1554
|
+
planKey
|
|
1555
|
+
]
|
|
1556
|
+
] : [];
|
|
1557
|
+
}));
|
|
1558
|
+
}
|
|
1192
1559
|
};
|
|
1193
1560
|
PrismaSubscriptionRepository = _ts_decorate13([
|
|
1194
1561
|
Injectable13(),
|
|
1195
1562
|
_ts_param12(0, Inject12(PRISMA_CLIENT_TOKEN)),
|
|
1563
|
+
_ts_param12(1, Optional4()),
|
|
1564
|
+
_ts_param12(1, Inject12(PRISMA_SCHEMA_OPTIONS_TOKEN)),
|
|
1196
1565
|
_ts_metadata12("design:type", Function),
|
|
1197
1566
|
_ts_metadata12("design:paramtypes", [
|
|
1198
|
-
typeof
|
|
1567
|
+
typeof SubscriptionRepositoryClient === "undefined" ? Object : SubscriptionRepositoryClient,
|
|
1568
|
+
typeof PrismaSchemaOptions === "undefined" ? Object : PrismaSchemaOptions
|
|
1199
1569
|
])
|
|
1200
1570
|
], PrismaSubscriptionRepository);
|
|
1201
1571
|
|
|
@@ -1307,7 +1677,8 @@ var PrismaTransactionRunner = class {
|
|
|
1307
1677
|
this.prisma = prisma;
|
|
1308
1678
|
}
|
|
1309
1679
|
async run(fn) {
|
|
1310
|
-
|
|
1680
|
+
const transaction = this.prisma.$transaction.bind(this.prisma);
|
|
1681
|
+
return transaction((tx) => fn(tx));
|
|
1311
1682
|
}
|
|
1312
1683
|
};
|
|
1313
1684
|
PrismaTransactionRunner = _ts_decorate15([
|
|
@@ -1315,7 +1686,7 @@ PrismaTransactionRunner = _ts_decorate15([
|
|
|
1315
1686
|
_ts_param14(0, Inject14(PRISMA_CLIENT_TOKEN)),
|
|
1316
1687
|
_ts_metadata14("design:type", Function),
|
|
1317
1688
|
_ts_metadata14("design:paramtypes", [
|
|
1318
|
-
typeof
|
|
1689
|
+
typeof Record === "undefined" ? Object : Record
|
|
1319
1690
|
])
|
|
1320
1691
|
], PrismaTransactionRunner);
|
|
1321
1692
|
|
|
@@ -1366,8 +1737,8 @@ function prismaPersistence(options) {
|
|
|
1366
1737
|
superAdminProvisioning: buildProvisioning(client, options.passwordHasher)
|
|
1367
1738
|
},
|
|
1368
1739
|
entitlement: {
|
|
1369
|
-
subscriptionRepository: provide((prisma) => new PrismaSubscriptionRepository(prisma)),
|
|
1370
|
-
planVersionRepository: provide((prisma) => new PrismaPlanVersionRepository(prisma))
|
|
1740
|
+
subscriptionRepository: provide((prisma) => new PrismaSubscriptionRepository(prisma, options.schema)),
|
|
1741
|
+
planVersionRepository: provide((prisma) => new PrismaPlanVersionRepository(prisma, options.schema))
|
|
1371
1742
|
},
|
|
1372
1743
|
promo: {
|
|
1373
1744
|
promoCodeRepository: provide((prisma) => new PrismaPromoCodeRepository(prisma)),
|
|
@@ -1376,8 +1747,8 @@ function prismaPersistence(options) {
|
|
|
1376
1747
|
subscriptionLookup: provide((prisma) => new PrismaPromoSubscriptionLookup(prisma)),
|
|
1377
1748
|
revenueAggregator: new ZeroPromoRevenueDeductionAggregator()
|
|
1378
1749
|
},
|
|
1379
|
-
planCatalogReadSink: provide((prisma) => new PrismaPlanCatalogReadSink(prisma)),
|
|
1380
|
-
planCatalogImportSink: provide((prisma) => new PrismaPlanCatalogImportSink(prisma))
|
|
1750
|
+
planCatalogReadSink: provide((prisma) => new PrismaPlanCatalogReadSink(prisma, options.schema)),
|
|
1751
|
+
planCatalogImportSink: provide((prisma) => new PrismaPlanCatalogImportSink(prisma, options.schema))
|
|
1381
1752
|
};
|
|
1382
1753
|
}
|
|
1383
1754
|
__name(prismaPersistence, "prismaPersistence");
|
|
@@ -1417,25 +1788,2746 @@ function buildProvisioning(client, hasher) {
|
|
|
1417
1788
|
return new PrismaSuperAdminBootstrapAdapter(client, hasher);
|
|
1418
1789
|
}
|
|
1419
1790
|
__name(buildProvisioning, "buildProvisioning");
|
|
1791
|
+
|
|
1792
|
+
// src/prisma-subscription-bundle.repository.ts
|
|
1793
|
+
import { Inject as Inject15, Injectable as Injectable17 } from "@nestjs/common";
|
|
1794
|
+
function _ts_decorate17(decorators, target, key, desc) {
|
|
1795
|
+
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
1796
|
+
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
1797
|
+
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
1798
|
+
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
1799
|
+
}
|
|
1800
|
+
__name(_ts_decorate17, "_ts_decorate");
|
|
1801
|
+
function _ts_metadata15(k, v) {
|
|
1802
|
+
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
|
|
1803
|
+
}
|
|
1804
|
+
__name(_ts_metadata15, "_ts_metadata");
|
|
1805
|
+
function _ts_param15(paramIndex, decorator) {
|
|
1806
|
+
return function(target, key) {
|
|
1807
|
+
decorator(target, key, paramIndex);
|
|
1808
|
+
};
|
|
1809
|
+
}
|
|
1810
|
+
__name(_ts_param15, "_ts_param");
|
|
1811
|
+
var PrismaSubscriptionBundleRepository = class {
|
|
1812
|
+
static {
|
|
1813
|
+
__name(this, "PrismaSubscriptionBundleRepository");
|
|
1814
|
+
}
|
|
1815
|
+
prisma;
|
|
1816
|
+
constructor(prisma) {
|
|
1817
|
+
this.prisma = prisma;
|
|
1818
|
+
}
|
|
1819
|
+
db(tx) {
|
|
1820
|
+
return tx ?? this.prisma;
|
|
1821
|
+
}
|
|
1822
|
+
async listBySubscription(subscriptionId) {
|
|
1823
|
+
const rows = await this.db().subscriptionBundle.findMany({
|
|
1824
|
+
where: {
|
|
1825
|
+
subscriptionId
|
|
1826
|
+
},
|
|
1827
|
+
orderBy: {
|
|
1828
|
+
startedAt: "desc"
|
|
1829
|
+
}
|
|
1830
|
+
});
|
|
1831
|
+
return rows.map(toRecord3);
|
|
1832
|
+
}
|
|
1833
|
+
async findById(subscriptionBundleId) {
|
|
1834
|
+
const row = await this.db().subscriptionBundle.findUnique({
|
|
1835
|
+
where: {
|
|
1836
|
+
id: subscriptionBundleId
|
|
1837
|
+
}
|
|
1838
|
+
});
|
|
1839
|
+
return row ? toRecord3(row) : null;
|
|
1840
|
+
}
|
|
1841
|
+
async listActiveBySubscription(subscriptionId, asOf = /* @__PURE__ */ new Date()) {
|
|
1842
|
+
const rows = await this.db().subscriptionBundle.findMany({
|
|
1843
|
+
where: {
|
|
1844
|
+
subscriptionId,
|
|
1845
|
+
OR: [
|
|
1846
|
+
{
|
|
1847
|
+
canceledAt: null
|
|
1848
|
+
},
|
|
1849
|
+
{
|
|
1850
|
+
canceledEffectiveAt: {
|
|
1851
|
+
gt: asOf
|
|
1852
|
+
}
|
|
1853
|
+
}
|
|
1854
|
+
]
|
|
1855
|
+
},
|
|
1856
|
+
orderBy: {
|
|
1857
|
+
startedAt: "desc"
|
|
1858
|
+
}
|
|
1859
|
+
});
|
|
1860
|
+
return rows.map(toRecord3);
|
|
1861
|
+
}
|
|
1862
|
+
async add(data) {
|
|
1863
|
+
const row = await this.db().subscriptionBundle.create({
|
|
1864
|
+
data: {
|
|
1865
|
+
subscriptionId: data.subscriptionId,
|
|
1866
|
+
bundleVersionId: data.bundleVersionId,
|
|
1867
|
+
startedAt: data.startedAt,
|
|
1868
|
+
minimumTermEndsAt: data.minimumTermEndsAt ?? null
|
|
1869
|
+
}
|
|
1870
|
+
});
|
|
1871
|
+
return toRecord3(row);
|
|
1872
|
+
}
|
|
1873
|
+
async cancel(subscriptionBundleId, data) {
|
|
1874
|
+
const row = await this.db().subscriptionBundle.update({
|
|
1875
|
+
where: {
|
|
1876
|
+
id: subscriptionBundleId
|
|
1877
|
+
},
|
|
1878
|
+
data: {
|
|
1879
|
+
canceledAt: data.canceledAt,
|
|
1880
|
+
canceledEffectiveAt: data.canceledEffectiveAt
|
|
1881
|
+
}
|
|
1882
|
+
});
|
|
1883
|
+
return toRecord3(row);
|
|
1884
|
+
}
|
|
1885
|
+
async reactivate(subscriptionBundleId) {
|
|
1886
|
+
const row = await this.db().subscriptionBundle.update({
|
|
1887
|
+
where: {
|
|
1888
|
+
id: subscriptionBundleId
|
|
1889
|
+
},
|
|
1890
|
+
data: {
|
|
1891
|
+
canceledAt: null,
|
|
1892
|
+
canceledEffectiveAt: null
|
|
1893
|
+
}
|
|
1894
|
+
});
|
|
1895
|
+
return toRecord3(row);
|
|
1896
|
+
}
|
|
1897
|
+
async countActiveByBundleVersionId(bundleVersionId, asOf = /* @__PURE__ */ new Date()) {
|
|
1898
|
+
return this.db().subscriptionBundle.count({
|
|
1899
|
+
where: {
|
|
1900
|
+
bundleVersionId,
|
|
1901
|
+
OR: [
|
|
1902
|
+
{
|
|
1903
|
+
canceledAt: null
|
|
1904
|
+
},
|
|
1905
|
+
{
|
|
1906
|
+
canceledEffectiveAt: {
|
|
1907
|
+
gt: asOf
|
|
1908
|
+
}
|
|
1909
|
+
}
|
|
1910
|
+
]
|
|
1911
|
+
}
|
|
1912
|
+
});
|
|
1913
|
+
}
|
|
1914
|
+
};
|
|
1915
|
+
PrismaSubscriptionBundleRepository = _ts_decorate17([
|
|
1916
|
+
Injectable17(),
|
|
1917
|
+
_ts_param15(0, Inject15(PRISMA_CLIENT_TOKEN)),
|
|
1918
|
+
_ts_metadata15("design:type", Function),
|
|
1919
|
+
_ts_metadata15("design:paramtypes", [
|
|
1920
|
+
typeof SubscriptionBundleClient === "undefined" ? Object : SubscriptionBundleClient
|
|
1921
|
+
])
|
|
1922
|
+
], PrismaSubscriptionBundleRepository);
|
|
1923
|
+
function toRecord3(row) {
|
|
1924
|
+
return {
|
|
1925
|
+
id: row.id,
|
|
1926
|
+
subscriptionId: row.subscriptionId,
|
|
1927
|
+
bundleVersionId: row.bundleVersionId,
|
|
1928
|
+
startedAt: row.startedAt,
|
|
1929
|
+
minimumTermEndsAt: row.minimumTermEndsAt,
|
|
1930
|
+
canceledAt: row.canceledAt,
|
|
1931
|
+
canceledEffectiveAt: row.canceledEffectiveAt,
|
|
1932
|
+
createdAt: row.createdAt,
|
|
1933
|
+
updatedAt: row.updatedAt
|
|
1934
|
+
};
|
|
1935
|
+
}
|
|
1936
|
+
__name(toRecord3, "toRecord");
|
|
1937
|
+
|
|
1938
|
+
// src/prisma-tenant-subscription-write.adapter.ts
|
|
1939
|
+
import { Inject as Inject16, Injectable as Injectable18, Optional as Optional5 } from "@nestjs/common";
|
|
1940
|
+
import { buildActivePlanVersionWhere as buildActivePlanVersionWhere2 } from "@saasicat/types";
|
|
1941
|
+
function _ts_decorate18(decorators, target, key, desc) {
|
|
1942
|
+
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
1943
|
+
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
1944
|
+
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
1945
|
+
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
1946
|
+
}
|
|
1947
|
+
__name(_ts_decorate18, "_ts_decorate");
|
|
1948
|
+
function _ts_metadata16(k, v) {
|
|
1949
|
+
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
|
|
1950
|
+
}
|
|
1951
|
+
__name(_ts_metadata16, "_ts_metadata");
|
|
1952
|
+
function _ts_param16(paramIndex, decorator) {
|
|
1953
|
+
return function(target, key) {
|
|
1954
|
+
decorator(target, key, paramIndex);
|
|
1955
|
+
};
|
|
1956
|
+
}
|
|
1957
|
+
__name(_ts_param16, "_ts_param");
|
|
1958
|
+
var PrismaTenantSubscriptionWriteAdapter = class {
|
|
1959
|
+
static {
|
|
1960
|
+
__name(this, "PrismaTenantSubscriptionWriteAdapter");
|
|
1961
|
+
}
|
|
1962
|
+
prisma;
|
|
1963
|
+
applyOnboardingSelection;
|
|
1964
|
+
schema;
|
|
1965
|
+
planBinding;
|
|
1966
|
+
constructor(prisma, options) {
|
|
1967
|
+
this.prisma = prisma;
|
|
1968
|
+
this.schema = resolvePrismaSchemaOptions(options);
|
|
1969
|
+
this.planBinding = createPrismaPlanBindingResolver(options?.planBinding);
|
|
1970
|
+
this.assertConfiguration();
|
|
1971
|
+
if (this.schema.tenantSubscription.atomicOnboardingSelection) {
|
|
1972
|
+
this.applyOnboardingSelection = (tenantId, input, redeemPromo) => this.applyOnboardingSelectionAtomic(tenantId, input, redeemPromo);
|
|
1973
|
+
}
|
|
1974
|
+
}
|
|
1975
|
+
async changePlanImmediate(tenantId, input) {
|
|
1976
|
+
if (this.schema.tenantSubscription.synchronizePlanVersion) {
|
|
1977
|
+
return this.prisma.$transaction((tx) => this.changePlanImmediateInClient(tx, tenantId, input));
|
|
1978
|
+
}
|
|
1979
|
+
return this.changePlanImmediateInClient(this.prisma, tenantId, input);
|
|
1980
|
+
}
|
|
1981
|
+
async changePlanImmediateInClient(client, tenantId, input) {
|
|
1982
|
+
const subscription = this.subscription(client);
|
|
1983
|
+
const data = {
|
|
1984
|
+
plan: input.planId,
|
|
1985
|
+
billingCycle: input.cycle,
|
|
1986
|
+
pendingPlan: null,
|
|
1987
|
+
pendingBillingCycle: null,
|
|
1988
|
+
pendingEffectiveAt: null,
|
|
1989
|
+
...input.nextStatus ? {
|
|
1990
|
+
status: input.nextStatus
|
|
1991
|
+
} : {},
|
|
1992
|
+
...input.periodStart && input.periodEnd ? {
|
|
1993
|
+
currentPeriodStart: input.periodStart,
|
|
1994
|
+
currentPeriodEnd: input.periodEnd
|
|
1995
|
+
} : {},
|
|
1996
|
+
// #17: the platform changePlan path computes the carried-over
|
|
1997
|
+
// trial end and passes it through; null/undefined leaves the
|
|
1998
|
+
// existing trialEndsAt untouched.
|
|
1999
|
+
...input.trialEndsAt ? {
|
|
2000
|
+
trialEndsAt: input.trialEndsAt
|
|
2001
|
+
} : {}
|
|
2002
|
+
};
|
|
2003
|
+
if (this.schema.tenantSubscription.synchronizePlanVersion) {
|
|
2004
|
+
const current = await subscription.findUnique({
|
|
2005
|
+
where: {
|
|
2006
|
+
tenantId
|
|
2007
|
+
}
|
|
2008
|
+
});
|
|
2009
|
+
if (!current) {
|
|
2010
|
+
throw new Error(`No subscription for tenant ${tenantId}.`);
|
|
2011
|
+
}
|
|
2012
|
+
const storagePlanId = await this.planBinding.toStoragePlanId(client, input.planId);
|
|
2013
|
+
data.planVersionId = await this.findTargetPlanVersionId(client, storagePlanId, input.periodStart ?? /* @__PURE__ */ new Date());
|
|
2014
|
+
if (await this.pendingVersionBelongsToAnotherPlan(client, current.pendingPlanVersionId, storagePlanId)) {
|
|
2015
|
+
Object.assign(data, clearedPendingVersionData());
|
|
2016
|
+
}
|
|
2017
|
+
}
|
|
2018
|
+
const updated = await subscription.update({
|
|
2019
|
+
where: {
|
|
2020
|
+
tenantId
|
|
2021
|
+
},
|
|
2022
|
+
data
|
|
2023
|
+
});
|
|
2024
|
+
return {
|
|
2025
|
+
plan: updated.plan,
|
|
2026
|
+
billingCycle: updated.billingCycle
|
|
2027
|
+
};
|
|
2028
|
+
}
|
|
2029
|
+
async schedulePlanChange(tenantId, input) {
|
|
2030
|
+
await this.subscription(this.prisma).update({
|
|
2031
|
+
where: {
|
|
2032
|
+
tenantId
|
|
2033
|
+
},
|
|
2034
|
+
data: {
|
|
2035
|
+
pendingPlan: input.pendingPlan,
|
|
2036
|
+
pendingBillingCycle: input.pendingBillingCycle,
|
|
2037
|
+
pendingEffectiveAt: input.pendingEffectiveAt
|
|
2038
|
+
}
|
|
2039
|
+
});
|
|
2040
|
+
}
|
|
2041
|
+
async acceptPendingPlanVersion(tenantId, userId, now) {
|
|
2042
|
+
const subscription = this.subscription(this.prisma);
|
|
2043
|
+
const sub = await subscription.findUnique({
|
|
2044
|
+
where: {
|
|
2045
|
+
tenantId
|
|
2046
|
+
}
|
|
2047
|
+
});
|
|
2048
|
+
if (!sub) {
|
|
2049
|
+
throw new Error(`No subscription for tenant ${tenantId}.`);
|
|
2050
|
+
}
|
|
2051
|
+
if (!sub.pendingPlanVersionId) {
|
|
2052
|
+
throw new Error(`No pending PlanVersion for tenant ${tenantId}.`);
|
|
2053
|
+
}
|
|
2054
|
+
const pendingPlanVersionId = sub.pendingPlanVersionId;
|
|
2055
|
+
const claimed = await subscription.updateMany({
|
|
2056
|
+
where: {
|
|
2057
|
+
id: sub.id,
|
|
2058
|
+
pendingPlanVersionId,
|
|
2059
|
+
pendingPlanVersionAccepted: false
|
|
2060
|
+
},
|
|
2061
|
+
data: {
|
|
2062
|
+
pendingPlanVersionAccepted: true,
|
|
2063
|
+
pendingPlanVersionAcceptedAt: now,
|
|
2064
|
+
pendingPlanVersionAcceptedByUserId: userId
|
|
2065
|
+
}
|
|
2066
|
+
});
|
|
2067
|
+
const updated = await subscription.findUnique({
|
|
2068
|
+
where: {
|
|
2069
|
+
id: sub.id
|
|
2070
|
+
}
|
|
2071
|
+
});
|
|
2072
|
+
if (!updated) {
|
|
2073
|
+
throw new Error(`No subscription for tenant ${tenantId}.`);
|
|
2074
|
+
}
|
|
2075
|
+
if (claimed.count === 0 && (updated.pendingPlanVersionId !== pendingPlanVersionId || !updated.pendingPlanVersionAccepted)) {
|
|
2076
|
+
throw new Error(`Pending PlanVersion changed while accepting it for tenant ${tenantId}.`);
|
|
2077
|
+
}
|
|
2078
|
+
return {
|
|
2079
|
+
accepted: true,
|
|
2080
|
+
acceptedAt: updated.pendingPlanVersionAcceptedAt,
|
|
2081
|
+
effectiveAt: updated.pendingPlanVersionEffectiveAt,
|
|
2082
|
+
alreadyAccepted: claimed.count === 0
|
|
2083
|
+
};
|
|
2084
|
+
}
|
|
2085
|
+
async applyOnboardingSelectionAtomic(tenantId, input, redeemPromo) {
|
|
2086
|
+
return this.prisma.$transaction(async (tx) => {
|
|
2087
|
+
const data = {
|
|
2088
|
+
plan: input.planId,
|
|
2089
|
+
billingCycle: input.cycle,
|
|
2090
|
+
pendingPlan: null,
|
|
2091
|
+
pendingBillingCycle: null,
|
|
2092
|
+
pendingEffectiveAt: null,
|
|
2093
|
+
...clearedPendingVersionData(),
|
|
2094
|
+
...input.nextStatus ? {
|
|
2095
|
+
status: input.nextStatus
|
|
2096
|
+
} : {},
|
|
2097
|
+
...input.periodStart && input.periodEnd ? {
|
|
2098
|
+
currentPeriodStart: input.periodStart,
|
|
2099
|
+
currentPeriodEnd: input.periodEnd
|
|
2100
|
+
} : {}
|
|
2101
|
+
};
|
|
2102
|
+
if (this.schema.tenantSubscription.synchronizePlanVersion) {
|
|
2103
|
+
const storagePlanId = await this.planBinding.toStoragePlanId(tx, input.planId);
|
|
2104
|
+
data.planVersionId = await this.findTargetPlanVersionId(tx, storagePlanId, input.periodStart ?? /* @__PURE__ */ new Date());
|
|
2105
|
+
}
|
|
2106
|
+
const updated = await this.subscription(tx).update({
|
|
2107
|
+
where: {
|
|
2108
|
+
tenantId
|
|
2109
|
+
},
|
|
2110
|
+
data
|
|
2111
|
+
});
|
|
2112
|
+
let promoRedemption = null;
|
|
2113
|
+
if (redeemPromo) {
|
|
2114
|
+
promoRedemption = await redeemPromo(tx, updated.id);
|
|
2115
|
+
}
|
|
2116
|
+
return {
|
|
2117
|
+
plan: updated.plan,
|
|
2118
|
+
billingCycle: updated.billingCycle,
|
|
2119
|
+
subscriptionId: updated.id,
|
|
2120
|
+
promoRedemption
|
|
2121
|
+
};
|
|
2122
|
+
});
|
|
2123
|
+
}
|
|
2124
|
+
async cancelSubscription(tenantId, immediate, now) {
|
|
2125
|
+
const subscription = this.subscription(this.prisma);
|
|
2126
|
+
const sub = await subscription.findUnique({
|
|
2127
|
+
where: {
|
|
2128
|
+
tenantId
|
|
2129
|
+
}
|
|
2130
|
+
});
|
|
2131
|
+
if (!sub) {
|
|
2132
|
+
throw new Error(`No subscription for tenant ${tenantId}.`);
|
|
2133
|
+
}
|
|
2134
|
+
const canceledAt = immediate ? now : sub.currentPeriodEnd ?? now;
|
|
2135
|
+
const updated = await subscription.update({
|
|
2136
|
+
where: {
|
|
2137
|
+
tenantId
|
|
2138
|
+
},
|
|
2139
|
+
data: {
|
|
2140
|
+
canceledAt,
|
|
2141
|
+
status: immediate ? "CANCELED" : sub.status
|
|
2142
|
+
}
|
|
2143
|
+
});
|
|
2144
|
+
return {
|
|
2145
|
+
canceledAt: updated.canceledAt,
|
|
2146
|
+
status: updated.status
|
|
2147
|
+
};
|
|
2148
|
+
}
|
|
2149
|
+
subscription(client) {
|
|
2150
|
+
return getPrismaDelegate(client, this.schema.tenantSubscription.delegate);
|
|
2151
|
+
}
|
|
2152
|
+
planVersions(client) {
|
|
2153
|
+
return getPrismaDelegate(client, this.schema.delegates.entitlementPlanVersion);
|
|
2154
|
+
}
|
|
2155
|
+
async findTargetPlanVersionId(client, storagePlanId, asOf) {
|
|
2156
|
+
const activeWindow = this.schema.tenantSubscription.activeVersionSelection === "validity-window";
|
|
2157
|
+
const activeVersionWhere = this.schema.tenantSubscription.withEndsAt ? buildActivePlanVersionWhere2(asOf, {
|
|
2158
|
+
withEndsAt: true
|
|
2159
|
+
}) : buildActivePlanVersionWhere2(asOf);
|
|
2160
|
+
const where = activeWindow ? {
|
|
2161
|
+
planId: storagePlanId,
|
|
2162
|
+
...activeVersionWhere
|
|
2163
|
+
} : {
|
|
2164
|
+
planId: storagePlanId,
|
|
2165
|
+
publishedAt: {
|
|
2166
|
+
not: null
|
|
2167
|
+
},
|
|
2168
|
+
supersededAt: null,
|
|
2169
|
+
...this.schema.tenantSubscription.withEndsAt ? {
|
|
2170
|
+
OR: [
|
|
2171
|
+
{
|
|
2172
|
+
endsAt: null
|
|
2173
|
+
},
|
|
2174
|
+
{
|
|
2175
|
+
endsAt: {
|
|
2176
|
+
gt: asOf
|
|
2177
|
+
}
|
|
2178
|
+
}
|
|
2179
|
+
]
|
|
2180
|
+
} : {}
|
|
2181
|
+
};
|
|
2182
|
+
const target = await this.planVersions(client).findFirst({
|
|
2183
|
+
where,
|
|
2184
|
+
orderBy: activeWindow ? [
|
|
2185
|
+
{
|
|
2186
|
+
validFrom: {
|
|
2187
|
+
sort: "desc",
|
|
2188
|
+
nulls: "last"
|
|
2189
|
+
}
|
|
2190
|
+
},
|
|
2191
|
+
{
|
|
2192
|
+
version: "desc"
|
|
2193
|
+
}
|
|
2194
|
+
] : {
|
|
2195
|
+
version: "desc"
|
|
2196
|
+
}
|
|
2197
|
+
});
|
|
2198
|
+
if (!target) {
|
|
2199
|
+
throw new Error(`No active PlanVersion for plan '${storagePlanId}'.`);
|
|
2200
|
+
}
|
|
2201
|
+
return target.id;
|
|
2202
|
+
}
|
|
2203
|
+
async pendingVersionBelongsToAnotherPlan(client, pendingPlanVersionId, targetStoragePlanId) {
|
|
2204
|
+
if (!pendingPlanVersionId) return false;
|
|
2205
|
+
const pending = await this.planVersions(client).findUnique({
|
|
2206
|
+
where: {
|
|
2207
|
+
id: pendingPlanVersionId
|
|
2208
|
+
}
|
|
2209
|
+
});
|
|
2210
|
+
return !pending || pending.planId !== targetStoragePlanId;
|
|
2211
|
+
}
|
|
2212
|
+
assertConfiguration() {
|
|
2213
|
+
if (!this.schema.tenantSubscription.synchronizePlanVersion) return;
|
|
2214
|
+
const entitlementFields = this.schema.planVersionFields.entitlement;
|
|
2215
|
+
if (this.schema.tenantSubscription.activeVersionSelection === "validity-window" && !entitlementFields.validityWindows) {
|
|
2216
|
+
throw new Error("tenantSubscription.activeVersionSelection='validity-window' requires planVersionFields.entitlement.validityWindows=true.");
|
|
2217
|
+
}
|
|
2218
|
+
if (this.schema.tenantSubscription.withEndsAt && !entitlementFields.endsAt) {
|
|
2219
|
+
throw new Error("tenantSubscription.withEndsAt=true requires planVersionFields.entitlement.endsAt=true.");
|
|
2220
|
+
}
|
|
2221
|
+
}
|
|
2222
|
+
};
|
|
2223
|
+
PrismaTenantSubscriptionWriteAdapter = _ts_decorate18([
|
|
2224
|
+
Injectable18(),
|
|
2225
|
+
_ts_param16(0, Inject16(PRISMA_CLIENT_TOKEN)),
|
|
2226
|
+
_ts_param16(1, Optional5()),
|
|
2227
|
+
_ts_param16(1, Inject16(PRISMA_SCHEMA_OPTIONS_TOKEN)),
|
|
2228
|
+
_ts_metadata16("design:type", Function),
|
|
2229
|
+
_ts_metadata16("design:paramtypes", [
|
|
2230
|
+
typeof TransactionalPrismaClient === "undefined" ? Object : TransactionalPrismaClient,
|
|
2231
|
+
typeof PrismaSchemaOptions === "undefined" ? Object : PrismaSchemaOptions
|
|
2232
|
+
])
|
|
2233
|
+
], PrismaTenantSubscriptionWriteAdapter);
|
|
2234
|
+
function clearedPendingVersionData() {
|
|
2235
|
+
return {
|
|
2236
|
+
pendingPlanVersionId: null,
|
|
2237
|
+
pendingPlanVersionEffectiveAt: null,
|
|
2238
|
+
pendingPlanVersionAccepted: false,
|
|
2239
|
+
pendingPlanVersionAcceptedAt: null,
|
|
2240
|
+
pendingPlanVersionAcceptedByUserId: null,
|
|
2241
|
+
pendingPlanVersionNotifiedAt: null,
|
|
2242
|
+
pendingPlanVersionReminderSentAt: null
|
|
2243
|
+
};
|
|
2244
|
+
}
|
|
2245
|
+
__name(clearedPendingVersionData, "clearedPendingVersionData");
|
|
2246
|
+
|
|
2247
|
+
// src/prisma-plan.repository.ts
|
|
2248
|
+
import { Inject as Inject17, Injectable as Injectable19, Optional as Optional6 } from "@nestjs/common";
|
|
2249
|
+
import { buildActivePlanVersionWhere as buildActivePlanVersionWhere3 } from "@saasicat/types";
|
|
2250
|
+
function _ts_decorate19(decorators, target, key, desc) {
|
|
2251
|
+
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
2252
|
+
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
2253
|
+
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
2254
|
+
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
2255
|
+
}
|
|
2256
|
+
__name(_ts_decorate19, "_ts_decorate");
|
|
2257
|
+
function _ts_metadata17(k, v) {
|
|
2258
|
+
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
|
|
2259
|
+
}
|
|
2260
|
+
__name(_ts_metadata17, "_ts_metadata");
|
|
2261
|
+
function _ts_param17(paramIndex, decorator) {
|
|
2262
|
+
return function(target, key) {
|
|
2263
|
+
decorator(target, key, paramIndex);
|
|
2264
|
+
};
|
|
2265
|
+
}
|
|
2266
|
+
__name(_ts_param17, "_ts_param");
|
|
2267
|
+
var PrismaPlanRepository = class {
|
|
2268
|
+
static {
|
|
2269
|
+
__name(this, "PrismaPlanRepository");
|
|
2270
|
+
}
|
|
2271
|
+
prisma;
|
|
2272
|
+
binding;
|
|
2273
|
+
delegateName;
|
|
2274
|
+
fields;
|
|
2275
|
+
constructor(prisma, options) {
|
|
2276
|
+
this.prisma = prisma;
|
|
2277
|
+
const schema = resolvePrismaSchemaOptions(options);
|
|
2278
|
+
this.binding = createPrismaPlanBindingResolver(options?.planBinding);
|
|
2279
|
+
this.delegateName = schema.delegates.catalogPlanVersion;
|
|
2280
|
+
this.fields = schema.planVersionFields.catalog;
|
|
2281
|
+
}
|
|
2282
|
+
db(tx) {
|
|
2283
|
+
return tx ?? this.prisma;
|
|
2284
|
+
}
|
|
2285
|
+
versions(client) {
|
|
2286
|
+
return getPrismaDelegate(client, this.delegateName);
|
|
2287
|
+
}
|
|
2288
|
+
// ─── Stem operations (Pack 1) ───
|
|
2289
|
+
async list(filter) {
|
|
2290
|
+
const excludeDeleted = filter.excludeDeleted ?? true;
|
|
2291
|
+
const db = this.db();
|
|
2292
|
+
let publishedKeys = null;
|
|
2293
|
+
if (filter.onlyPublished) {
|
|
2294
|
+
if (this.binding.mode === "legacy-plan-key") {
|
|
2295
|
+
const projectPlans = await db.plan.findMany({
|
|
2296
|
+
where: {
|
|
2297
|
+
projectKey: filter.projectKey,
|
|
2298
|
+
...excludeDeleted ? {
|
|
2299
|
+
deletedAt: null
|
|
2300
|
+
} : {}
|
|
2301
|
+
}
|
|
2302
|
+
});
|
|
2303
|
+
const candidateKeys = [
|
|
2304
|
+
...new Set(projectPlans.map((plan) => plan.planKey))
|
|
2305
|
+
];
|
|
2306
|
+
const allMatchingPlans = candidateKeys.length === 0 ? [] : await db.plan.findMany({
|
|
2307
|
+
where: {
|
|
2308
|
+
planKey: {
|
|
2309
|
+
in: candidateKeys
|
|
2310
|
+
}
|
|
2311
|
+
}
|
|
2312
|
+
});
|
|
2313
|
+
const projectsByKey = /* @__PURE__ */ new Map();
|
|
2314
|
+
for (const plan of allMatchingPlans) {
|
|
2315
|
+
const projects = projectsByKey.get(plan.planKey) ?? /* @__PURE__ */ new Set();
|
|
2316
|
+
projects.add(plan.projectKey);
|
|
2317
|
+
projectsByKey.set(plan.planKey, projects);
|
|
2318
|
+
}
|
|
2319
|
+
const unambiguousKeys = candidateKeys.filter((planKey) => projectsByKey.get(planKey)?.size === 1);
|
|
2320
|
+
const live = await this.versions(db).findMany({
|
|
2321
|
+
where: {
|
|
2322
|
+
planId: {
|
|
2323
|
+
in: unambiguousKeys
|
|
2324
|
+
},
|
|
2325
|
+
publishedAt: {
|
|
2326
|
+
not: null
|
|
2327
|
+
},
|
|
2328
|
+
supersededAt: null
|
|
2329
|
+
}
|
|
2330
|
+
});
|
|
2331
|
+
publishedKeys = [
|
|
2332
|
+
...new Set(live.map((version) => version.planId))
|
|
2333
|
+
];
|
|
2334
|
+
} else {
|
|
2335
|
+
const projectPlans = await db.plan.findMany({
|
|
2336
|
+
where: {
|
|
2337
|
+
projectKey: filter.projectKey,
|
|
2338
|
+
...excludeDeleted ? {
|
|
2339
|
+
deletedAt: null
|
|
2340
|
+
} : {}
|
|
2341
|
+
}
|
|
2342
|
+
});
|
|
2343
|
+
const planKeyById = new Map(projectPlans.map((plan) => [
|
|
2344
|
+
plan.id,
|
|
2345
|
+
plan.planKey
|
|
2346
|
+
]));
|
|
2347
|
+
const live = await this.versions(db).findMany({
|
|
2348
|
+
where: {
|
|
2349
|
+
planId: {
|
|
2350
|
+
in: [
|
|
2351
|
+
...planKeyById.keys()
|
|
2352
|
+
]
|
|
2353
|
+
},
|
|
2354
|
+
publishedAt: {
|
|
2355
|
+
not: null
|
|
2356
|
+
},
|
|
2357
|
+
supersededAt: null
|
|
2358
|
+
}
|
|
2359
|
+
});
|
|
2360
|
+
publishedKeys = [
|
|
2361
|
+
...new Set(live.flatMap((version) => {
|
|
2362
|
+
const planKey = planKeyById.get(version.planId);
|
|
2363
|
+
return planKey ? [
|
|
2364
|
+
planKey
|
|
2365
|
+
] : [];
|
|
2366
|
+
}))
|
|
2367
|
+
];
|
|
2368
|
+
}
|
|
2369
|
+
}
|
|
2370
|
+
const rows = await db.plan.findMany({
|
|
2371
|
+
where: {
|
|
2372
|
+
projectKey: filter.projectKey,
|
|
2373
|
+
...excludeDeleted ? {
|
|
2374
|
+
deletedAt: null
|
|
2375
|
+
} : {},
|
|
2376
|
+
...publishedKeys ? {
|
|
2377
|
+
planKey: {
|
|
2378
|
+
in: publishedKeys
|
|
2379
|
+
}
|
|
2380
|
+
} : {}
|
|
2381
|
+
},
|
|
2382
|
+
orderBy: [
|
|
2383
|
+
{
|
|
2384
|
+
sortOrder: "asc"
|
|
2385
|
+
},
|
|
2386
|
+
{
|
|
2387
|
+
planKey: "asc"
|
|
2388
|
+
}
|
|
2389
|
+
]
|
|
2390
|
+
});
|
|
2391
|
+
return rows.map(toPlanRow2);
|
|
2392
|
+
}
|
|
2393
|
+
async findById(planId) {
|
|
2394
|
+
const row = await this.db().plan.findUnique({
|
|
2395
|
+
where: {
|
|
2396
|
+
id: planId
|
|
2397
|
+
}
|
|
2398
|
+
});
|
|
2399
|
+
return row ? toPlanRow2(row) : null;
|
|
2400
|
+
}
|
|
2401
|
+
async findByKey(projectKey, planKey) {
|
|
2402
|
+
const row = await this.db().plan.findFirst({
|
|
2403
|
+
where: {
|
|
2404
|
+
projectKey,
|
|
2405
|
+
planKey,
|
|
2406
|
+
deletedAt: null
|
|
2407
|
+
}
|
|
2408
|
+
});
|
|
2409
|
+
return row ? toPlanRow2(row) : null;
|
|
2410
|
+
}
|
|
2411
|
+
async create(data) {
|
|
2412
|
+
const created = await this.db().plan.create({
|
|
2413
|
+
data: {
|
|
2414
|
+
projectKey: data.projectKey,
|
|
2415
|
+
planKey: data.planKey,
|
|
2416
|
+
label: data.label,
|
|
2417
|
+
description: data.description ?? null,
|
|
2418
|
+
icon: data.icon ?? null,
|
|
2419
|
+
sortOrder: data.sortOrder ?? 0
|
|
2420
|
+
}
|
|
2421
|
+
});
|
|
2422
|
+
return toPlanRow2(created);
|
|
2423
|
+
}
|
|
2424
|
+
async update(planId, data) {
|
|
2425
|
+
const updated = await this.db().plan.update({
|
|
2426
|
+
where: {
|
|
2427
|
+
id: planId
|
|
2428
|
+
},
|
|
2429
|
+
data: {
|
|
2430
|
+
...data.label !== void 0 ? {
|
|
2431
|
+
label: data.label
|
|
2432
|
+
} : {},
|
|
2433
|
+
...data.description !== void 0 ? {
|
|
2434
|
+
description: data.description
|
|
2435
|
+
} : {},
|
|
2436
|
+
...data.icon !== void 0 ? {
|
|
2437
|
+
icon: data.icon
|
|
2438
|
+
} : {},
|
|
2439
|
+
...data.sortOrder !== void 0 ? {
|
|
2440
|
+
sortOrder: data.sortOrder
|
|
2441
|
+
} : {}
|
|
2442
|
+
}
|
|
2443
|
+
});
|
|
2444
|
+
return toPlanRow2(updated);
|
|
2445
|
+
}
|
|
2446
|
+
async softDelete(planId) {
|
|
2447
|
+
await this.db().plan.update({
|
|
2448
|
+
where: {
|
|
2449
|
+
id: planId
|
|
2450
|
+
},
|
|
2451
|
+
data: {
|
|
2452
|
+
deletedAt: /* @__PURE__ */ new Date()
|
|
2453
|
+
}
|
|
2454
|
+
});
|
|
2455
|
+
}
|
|
2456
|
+
async hardDelete(planId) {
|
|
2457
|
+
await this.db().plan.deleteMany({
|
|
2458
|
+
where: {
|
|
2459
|
+
id: planId
|
|
2460
|
+
}
|
|
2461
|
+
});
|
|
2462
|
+
}
|
|
2463
|
+
// ─── Lifecycle operations (Pack 2a) — keyed by planKey ───
|
|
2464
|
+
async listVersions(planKey) {
|
|
2465
|
+
const db = this.db();
|
|
2466
|
+
const storedPlanId = await this.binding.toStoragePlanId(db, planKey);
|
|
2467
|
+
const rows = await this.versions(db).findMany({
|
|
2468
|
+
where: {
|
|
2469
|
+
planId: storedPlanId
|
|
2470
|
+
},
|
|
2471
|
+
orderBy: {
|
|
2472
|
+
version: "asc"
|
|
2473
|
+
}
|
|
2474
|
+
});
|
|
2475
|
+
return rows.map((row) => this.toPlanVersionRow(row, planKey));
|
|
2476
|
+
}
|
|
2477
|
+
async findVersionById(versionId) {
|
|
2478
|
+
const db = this.db();
|
|
2479
|
+
const row = await this.versions(db).findUnique({
|
|
2480
|
+
where: {
|
|
2481
|
+
id: versionId
|
|
2482
|
+
}
|
|
2483
|
+
});
|
|
2484
|
+
return row ? this.toPlanVersionRow(row, await this.binding.toPlanKey(db, row.planId)) : null;
|
|
2485
|
+
}
|
|
2486
|
+
async findCurrentDraft(planKey) {
|
|
2487
|
+
const db = this.db();
|
|
2488
|
+
const storedPlanId = await this.binding.toStoragePlanId(db, planKey);
|
|
2489
|
+
const row = await this.versions(db).findFirst({
|
|
2490
|
+
where: {
|
|
2491
|
+
planId: storedPlanId,
|
|
2492
|
+
publishedAt: null
|
|
2493
|
+
}
|
|
2494
|
+
});
|
|
2495
|
+
return row ? this.toPlanVersionRow(row, planKey) : null;
|
|
2496
|
+
}
|
|
2497
|
+
async findLatestLivePlanVersion(planKey, tx) {
|
|
2498
|
+
const db = this.db(tx);
|
|
2499
|
+
const storedPlanId = await this.binding.toStoragePlanId(db, planKey);
|
|
2500
|
+
const row = await this.versions(db).findFirst({
|
|
2501
|
+
where: {
|
|
2502
|
+
planId: storedPlanId,
|
|
2503
|
+
publishedAt: {
|
|
2504
|
+
not: null
|
|
2505
|
+
},
|
|
2506
|
+
supersededAt: null,
|
|
2507
|
+
...this.fields.endsAt ? {
|
|
2508
|
+
OR: [
|
|
2509
|
+
{
|
|
2510
|
+
endsAt: null
|
|
2511
|
+
},
|
|
2512
|
+
{
|
|
2513
|
+
endsAt: {
|
|
2514
|
+
gt: /* @__PURE__ */ new Date()
|
|
2515
|
+
}
|
|
2516
|
+
}
|
|
2517
|
+
]
|
|
2518
|
+
} : {}
|
|
2519
|
+
},
|
|
2520
|
+
orderBy: {
|
|
2521
|
+
version: "desc"
|
|
2522
|
+
}
|
|
2523
|
+
});
|
|
2524
|
+
return row ? this.toPlanVersionRow(row, planKey) : null;
|
|
2525
|
+
}
|
|
2526
|
+
async findActivePlanVersion(planKey, asOf = /* @__PURE__ */ new Date(), tx) {
|
|
2527
|
+
if (!this.fields.validityWindows) {
|
|
2528
|
+
throw new Error("findActivePlanVersion requires schema.planVersionFields.catalog.validityWindows=true and the current @saasicat/spec PlanVersion validity columns. Apply the additive schema first, or use findLatestLivePlanVersion for a 0.6-compatible newest-live lookup.");
|
|
2529
|
+
}
|
|
2530
|
+
const db = this.db(tx);
|
|
2531
|
+
const storedPlanId = await this.binding.toStoragePlanId(db, planKey);
|
|
2532
|
+
const activeWhere = this.fields.endsAt ? buildActivePlanVersionWhere3(asOf, {
|
|
2533
|
+
withEndsAt: true
|
|
2534
|
+
}) : buildActivePlanVersionWhere3(asOf);
|
|
2535
|
+
const row = await this.versions(db).findFirst({
|
|
2536
|
+
where: {
|
|
2537
|
+
planId: storedPlanId,
|
|
2538
|
+
...activeWhere
|
|
2539
|
+
},
|
|
2540
|
+
orderBy: [
|
|
2541
|
+
{
|
|
2542
|
+
validFrom: {
|
|
2543
|
+
sort: "desc",
|
|
2544
|
+
nulls: "last"
|
|
2545
|
+
}
|
|
2546
|
+
},
|
|
2547
|
+
{
|
|
2548
|
+
version: "desc"
|
|
2549
|
+
}
|
|
2550
|
+
]
|
|
2551
|
+
});
|
|
2552
|
+
return row ? this.toPlanVersionRow(row, planKey) : null;
|
|
2553
|
+
}
|
|
2554
|
+
async createPlanVersionDraft(data) {
|
|
2555
|
+
const planKey = data.planId;
|
|
2556
|
+
const db = this.db();
|
|
2557
|
+
const planVersion = this.versions(db);
|
|
2558
|
+
const storedPlanId = await this.binding.toStoragePlanId(db, planKey);
|
|
2559
|
+
const latest = await planVersion.findFirst({
|
|
2560
|
+
where: {
|
|
2561
|
+
planId: storedPlanId
|
|
2562
|
+
},
|
|
2563
|
+
orderBy: {
|
|
2564
|
+
version: "desc"
|
|
2565
|
+
}
|
|
2566
|
+
});
|
|
2567
|
+
const nextVersion = (latest?.version ?? 0) + 1;
|
|
2568
|
+
const created = await planVersion.create({
|
|
2569
|
+
data: {
|
|
2570
|
+
planId: storedPlanId,
|
|
2571
|
+
version: nextVersion,
|
|
2572
|
+
baseVersionId: data.baseVersionId ?? null,
|
|
2573
|
+
features: data.features,
|
|
2574
|
+
quotas: data.quotas,
|
|
2575
|
+
monthlyNet: data.monthlyNet,
|
|
2576
|
+
yearlyNet: data.yearlyNet,
|
|
2577
|
+
marketed: data.marketed ?? true,
|
|
2578
|
+
changeNote: data.changeNote ?? "",
|
|
2579
|
+
createdByUserId: data.createdByUserId ?? null,
|
|
2580
|
+
...this.fields.validityWindows ? {
|
|
2581
|
+
validFrom: data.validFrom ? new Date(data.validFrom) : null,
|
|
2582
|
+
validUntil: data.validUntil ? new Date(data.validUntil) : null
|
|
2583
|
+
} : {}
|
|
2584
|
+
}
|
|
2585
|
+
});
|
|
2586
|
+
return this.toPlanVersionRow(created, planKey);
|
|
2587
|
+
}
|
|
2588
|
+
async updatePlanVersionDraft(versionId, data) {
|
|
2589
|
+
const updated = await this.versions(this.db()).update({
|
|
2590
|
+
where: {
|
|
2591
|
+
id: versionId
|
|
2592
|
+
},
|
|
2593
|
+
data: {
|
|
2594
|
+
...data.features !== void 0 ? {
|
|
2595
|
+
features: data.features
|
|
2596
|
+
} : {},
|
|
2597
|
+
...data.quotas !== void 0 ? {
|
|
2598
|
+
quotas: data.quotas
|
|
2599
|
+
} : {},
|
|
2600
|
+
...data.monthlyNet !== void 0 ? {
|
|
2601
|
+
monthlyNet: data.monthlyNet
|
|
2602
|
+
} : {},
|
|
2603
|
+
...data.yearlyNet !== void 0 ? {
|
|
2604
|
+
yearlyNet: data.yearlyNet
|
|
2605
|
+
} : {},
|
|
2606
|
+
...data.marketed !== void 0 ? {
|
|
2607
|
+
marketed: data.marketed
|
|
2608
|
+
} : {},
|
|
2609
|
+
...data.changeNote !== void 0 ? {
|
|
2610
|
+
changeNote: data.changeNote
|
|
2611
|
+
} : {},
|
|
2612
|
+
...this.fields.validityWindows && data.validFrom !== void 0 ? {
|
|
2613
|
+
validFrom: data.validFrom ? new Date(data.validFrom) : null
|
|
2614
|
+
} : {},
|
|
2615
|
+
...this.fields.validityWindows && data.validUntil !== void 0 ? {
|
|
2616
|
+
validUntil: data.validUntil ? new Date(data.validUntil) : null
|
|
2617
|
+
} : {}
|
|
2618
|
+
}
|
|
2619
|
+
});
|
|
2620
|
+
const planKey = await this.binding.toPlanKey(this.db(), updated.planId);
|
|
2621
|
+
return this.toPlanVersionRow(updated, planKey);
|
|
2622
|
+
}
|
|
2623
|
+
async publishPlanVersionDraft(versionId, publishMeta, tx) {
|
|
2624
|
+
const operationDb = this.db(tx);
|
|
2625
|
+
const draft = await this.versions(operationDb).findUnique({
|
|
2626
|
+
where: {
|
|
2627
|
+
id: versionId
|
|
2628
|
+
}
|
|
2629
|
+
});
|
|
2630
|
+
if (!draft) {
|
|
2631
|
+
throw new Error(`PlanVersion ${versionId} not found.`);
|
|
2632
|
+
}
|
|
2633
|
+
const storedPlanId = draft.planId;
|
|
2634
|
+
const publish = /* @__PURE__ */ __name(async (db) => {
|
|
2635
|
+
const planVersion = this.versions(db);
|
|
2636
|
+
const previous = await planVersion.findFirst({
|
|
2637
|
+
where: {
|
|
2638
|
+
planId: storedPlanId,
|
|
2639
|
+
publishedAt: {
|
|
2640
|
+
not: null
|
|
2641
|
+
},
|
|
2642
|
+
supersededAt: null,
|
|
2643
|
+
id: {
|
|
2644
|
+
not: versionId
|
|
2645
|
+
}
|
|
2646
|
+
},
|
|
2647
|
+
orderBy: {
|
|
2648
|
+
version: "desc"
|
|
2649
|
+
}
|
|
2650
|
+
});
|
|
2651
|
+
const now = /* @__PURE__ */ new Date();
|
|
2652
|
+
if (previous) {
|
|
2653
|
+
const predecessorValidUntil = new Date(publishMeta.validFrom.getTime() - 24 * 60 * 60 * 1e3);
|
|
2654
|
+
await planVersion.update({
|
|
2655
|
+
where: {
|
|
2656
|
+
id: previous.id
|
|
2657
|
+
},
|
|
2658
|
+
data: {
|
|
2659
|
+
supersededAt: now,
|
|
2660
|
+
...this.fields.validityWindows ? {
|
|
2661
|
+
validUntil: predecessorValidUntil
|
|
2662
|
+
} : {}
|
|
2663
|
+
}
|
|
2664
|
+
});
|
|
2665
|
+
}
|
|
2666
|
+
return planVersion.update({
|
|
2667
|
+
where: {
|
|
2668
|
+
id: versionId
|
|
2669
|
+
},
|
|
2670
|
+
data: {
|
|
2671
|
+
publishedAt: now,
|
|
2672
|
+
publishedChanges: publishMeta.publishedChanges,
|
|
2673
|
+
nonRegressive: publishMeta.nonRegressive,
|
|
2674
|
+
publishedByUserId: publishMeta.publishedByUserId,
|
|
2675
|
+
...this.fields.validityWindows ? {
|
|
2676
|
+
validFrom: publishMeta.validFrom,
|
|
2677
|
+
validUntil: publishMeta.validUntil
|
|
2678
|
+
} : {}
|
|
2679
|
+
}
|
|
2680
|
+
});
|
|
2681
|
+
}, "publish");
|
|
2682
|
+
const published = tx ? await publish(this.db(tx)) : await this.prisma.$transaction((txClient) => publish(txClient));
|
|
2683
|
+
const planKey = await this.binding.toPlanKey(operationDb, storedPlanId);
|
|
2684
|
+
return this.toPlanVersionRow(published, planKey);
|
|
2685
|
+
}
|
|
2686
|
+
async deletePlanVersionDraft(versionId) {
|
|
2687
|
+
const planVersion = this.versions(this.db());
|
|
2688
|
+
const row = await planVersion.findUnique({
|
|
2689
|
+
where: {
|
|
2690
|
+
id: versionId
|
|
2691
|
+
}
|
|
2692
|
+
});
|
|
2693
|
+
if (!row) return;
|
|
2694
|
+
if (row.publishedAt !== null) {
|
|
2695
|
+
throw new Error(`PlanVersion ${versionId} is already published and cannot be discarded (published versions are immutable \u2014 contract protection P1).`);
|
|
2696
|
+
}
|
|
2697
|
+
await planVersion.deleteMany({
|
|
2698
|
+
where: {
|
|
2699
|
+
id: versionId,
|
|
2700
|
+
publishedAt: null
|
|
2701
|
+
}
|
|
2702
|
+
});
|
|
2703
|
+
}
|
|
2704
|
+
async terminate(versionId, endsAt) {
|
|
2705
|
+
if (!this.fields.endsAt) {
|
|
2706
|
+
throw new Error("terminate requires schema.planVersionFields.catalog.endsAt=true and the current @saasicat/spec PlanVersion.endsAt column. Apply the additive schema before enabling SuperAdmin-initiated plan-version termination.");
|
|
2707
|
+
}
|
|
2708
|
+
const db = this.db();
|
|
2709
|
+
const updated = await this.versions(db).update({
|
|
2710
|
+
where: {
|
|
2711
|
+
id: versionId
|
|
2712
|
+
},
|
|
2713
|
+
data: {
|
|
2714
|
+
endsAt
|
|
2715
|
+
}
|
|
2716
|
+
});
|
|
2717
|
+
const planKey = await this.binding.toPlanKey(db, updated.planId);
|
|
2718
|
+
return this.toPlanVersionRow(updated, planKey);
|
|
2719
|
+
}
|
|
2720
|
+
toPlanVersionRow(row, planKey) {
|
|
2721
|
+
return toPlanVersionRow2(row, planKey, this.fields);
|
|
2722
|
+
}
|
|
2723
|
+
};
|
|
2724
|
+
PrismaPlanRepository = _ts_decorate19([
|
|
2725
|
+
Injectable19(),
|
|
2726
|
+
_ts_param17(0, Inject17(PRISMA_CLIENT_TOKEN)),
|
|
2727
|
+
_ts_param17(1, Optional6()),
|
|
2728
|
+
_ts_param17(1, Inject17(PRISMA_SCHEMA_OPTIONS_TOKEN)),
|
|
2729
|
+
_ts_metadata17("design:type", Function),
|
|
2730
|
+
_ts_metadata17("design:paramtypes", [
|
|
2731
|
+
typeof PlanRepositoryClient === "undefined" ? Object : PlanRepositoryClient,
|
|
2732
|
+
typeof PrismaSchemaOptions === "undefined" ? Object : PrismaSchemaOptions
|
|
2733
|
+
])
|
|
2734
|
+
], PrismaPlanRepository);
|
|
2735
|
+
function toPlanRow2(row) {
|
|
2736
|
+
return {
|
|
2737
|
+
id: row.id,
|
|
2738
|
+
projectKey: row.projectKey,
|
|
2739
|
+
planKey: row.planKey,
|
|
2740
|
+
label: row.label,
|
|
2741
|
+
description: row.description,
|
|
2742
|
+
icon: row.icon,
|
|
2743
|
+
sortOrder: row.sortOrder,
|
|
2744
|
+
createdAt: row.createdAt.toISOString(),
|
|
2745
|
+
updatedAt: row.updatedAt.toISOString(),
|
|
2746
|
+
deletedAt: row.deletedAt?.toISOString() ?? null
|
|
2747
|
+
};
|
|
2748
|
+
}
|
|
2749
|
+
__name(toPlanRow2, "toPlanRow");
|
|
2750
|
+
function toPlanVersionRow2(row, planKey, fields) {
|
|
2751
|
+
const mapped = {
|
|
2752
|
+
id: row.id,
|
|
2753
|
+
version: row.version,
|
|
2754
|
+
baseVersionId: row.baseVersionId,
|
|
2755
|
+
planId: planKey,
|
|
2756
|
+
features: toStringArray(row.features),
|
|
2757
|
+
quotas: toQuotaMap(row.quotas),
|
|
2758
|
+
monthlyNet: row.monthlyNet.toString(),
|
|
2759
|
+
yearlyNet: row.yearlyNet.toString(),
|
|
2760
|
+
marketed: row.marketed,
|
|
2761
|
+
publishedAt: row.publishedAt?.toISOString() ?? null,
|
|
2762
|
+
supersededAt: row.supersededAt?.toISOString() ?? null,
|
|
2763
|
+
publishedChanges: Array.isArray(row.publishedChanges) ? row.publishedChanges : null,
|
|
2764
|
+
changeNote: row.changeNote,
|
|
2765
|
+
nonRegressive: row.nonRegressive,
|
|
2766
|
+
validFrom: fields.validityWindows && row.validFrom ? row.validFrom.toISOString() : null,
|
|
2767
|
+
validUntil: fields.validityWindows && row.validUntil ? row.validUntil.toISOString() : null,
|
|
2768
|
+
createdByUserId: row.createdByUserId,
|
|
2769
|
+
publishedByUserId: row.publishedByUserId,
|
|
2770
|
+
createdAt: row.createdAt.toISOString(),
|
|
2771
|
+
updatedAt: row.updatedAt.toISOString()
|
|
2772
|
+
};
|
|
2773
|
+
if (fields.endsAt) {
|
|
2774
|
+
mapped.endsAt = row.endsAt?.toISOString() ?? null;
|
|
2775
|
+
}
|
|
2776
|
+
return mapped;
|
|
2777
|
+
}
|
|
2778
|
+
__name(toPlanVersionRow2, "toPlanVersionRow");
|
|
2779
|
+
|
|
2780
|
+
// src/prisma-bundle.repository.ts
|
|
2781
|
+
import { Inject as Inject18, Injectable as Injectable20, Optional as Optional7 } from "@nestjs/common";
|
|
2782
|
+
import { buildActiveVersionWhere } from "@saasicat/types";
|
|
2783
|
+
function _ts_decorate20(decorators, target, key, desc) {
|
|
2784
|
+
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
2785
|
+
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
2786
|
+
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
2787
|
+
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
2788
|
+
}
|
|
2789
|
+
__name(_ts_decorate20, "_ts_decorate");
|
|
2790
|
+
function _ts_metadata18(k, v) {
|
|
2791
|
+
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
|
|
2792
|
+
}
|
|
2793
|
+
__name(_ts_metadata18, "_ts_metadata");
|
|
2794
|
+
function _ts_param18(paramIndex, decorator) {
|
|
2795
|
+
return function(target, key) {
|
|
2796
|
+
decorator(target, key, paramIndex);
|
|
2797
|
+
};
|
|
2798
|
+
}
|
|
2799
|
+
__name(_ts_param18, "_ts_param");
|
|
2800
|
+
var PRISMA_BUNDLE_REPOSITORY_OPTIONS = /* @__PURE__ */ Symbol.for("saasicat/adapter-prisma/PrismaBundleRepositoryOptions");
|
|
2801
|
+
var PrismaBundleRepository = class {
|
|
2802
|
+
static {
|
|
2803
|
+
__name(this, "PrismaBundleRepository");
|
|
2804
|
+
}
|
|
2805
|
+
prisma;
|
|
2806
|
+
validityWindows;
|
|
2807
|
+
/**
|
|
2808
|
+
* Present only when validity-window mode is enabled. This mirrors the
|
|
2809
|
+
* optional port capability and lets 0.6-schema consumers detect that an
|
|
2810
|
+
* active-at-time lookup is unavailable.
|
|
2811
|
+
*/
|
|
2812
|
+
findActiveBundleVersion;
|
|
2813
|
+
constructor(prisma, options = {}) {
|
|
2814
|
+
this.prisma = prisma;
|
|
2815
|
+
this.validityWindows = options.validityWindows ?? false;
|
|
2816
|
+
if (this.validityWindows) {
|
|
2817
|
+
this.findActiveBundleVersion = (bundleId, asOf, tx) => this.findActiveBundleVersionWithValidity(bundleId, asOf ?? /* @__PURE__ */ new Date(), tx);
|
|
2818
|
+
}
|
|
2819
|
+
}
|
|
2820
|
+
db(tx) {
|
|
2821
|
+
return tx ?? this.prisma;
|
|
2822
|
+
}
|
|
2823
|
+
transaction(work) {
|
|
2824
|
+
const transaction = this.prisma.$transaction;
|
|
2825
|
+
return transaction.call(this.prisma, (tx) => work(tx));
|
|
2826
|
+
}
|
|
2827
|
+
// ─── Stem operations ───
|
|
2828
|
+
async list(filter) {
|
|
2829
|
+
const excludeDeleted = filter.excludeDeleted ?? true;
|
|
2830
|
+
const rows = await this.db().bundle.findMany({
|
|
2831
|
+
where: {
|
|
2832
|
+
projectKey: filter.projectKey,
|
|
2833
|
+
...excludeDeleted ? {
|
|
2834
|
+
deletedAt: null
|
|
2835
|
+
} : {}
|
|
2836
|
+
},
|
|
2837
|
+
orderBy: [
|
|
2838
|
+
{
|
|
2839
|
+
sortOrder: "asc"
|
|
2840
|
+
},
|
|
2841
|
+
{
|
|
2842
|
+
bundleKey: "asc"
|
|
2843
|
+
}
|
|
2844
|
+
]
|
|
2845
|
+
});
|
|
2846
|
+
return rows.map(toBundleRow);
|
|
2847
|
+
}
|
|
2848
|
+
async findById(bundleId) {
|
|
2849
|
+
const row = await this.db().bundle.findUnique({
|
|
2850
|
+
where: {
|
|
2851
|
+
id: bundleId
|
|
2852
|
+
}
|
|
2853
|
+
});
|
|
2854
|
+
return row ? toBundleRow(row) : null;
|
|
2855
|
+
}
|
|
2856
|
+
async findByKey(projectKey, bundleKey) {
|
|
2857
|
+
const row = await this.db().bundle.findFirst({
|
|
2858
|
+
where: {
|
|
2859
|
+
projectKey,
|
|
2860
|
+
bundleKey,
|
|
2861
|
+
deletedAt: null
|
|
2862
|
+
}
|
|
2863
|
+
});
|
|
2864
|
+
return row ? toBundleRow(row) : null;
|
|
2865
|
+
}
|
|
2866
|
+
async create(data) {
|
|
2867
|
+
const created = await this.db().bundle.create({
|
|
2868
|
+
data: {
|
|
2869
|
+
projectKey: data.projectKey,
|
|
2870
|
+
bundleKey: data.bundleKey,
|
|
2871
|
+
label: data.label,
|
|
2872
|
+
description: data.description ?? null,
|
|
2873
|
+
icon: data.icon ?? null,
|
|
2874
|
+
sortOrder: data.sortOrder ?? 0,
|
|
2875
|
+
i18n: data.i18n ?? {}
|
|
2876
|
+
}
|
|
2877
|
+
});
|
|
2878
|
+
return toBundleRow(created);
|
|
2879
|
+
}
|
|
2880
|
+
async update(bundleId, data) {
|
|
2881
|
+
const updated = await this.db().bundle.update({
|
|
2882
|
+
where: {
|
|
2883
|
+
id: bundleId
|
|
2884
|
+
},
|
|
2885
|
+
data: {
|
|
2886
|
+
...data.label !== void 0 ? {
|
|
2887
|
+
label: data.label
|
|
2888
|
+
} : {},
|
|
2889
|
+
...data.description !== void 0 ? {
|
|
2890
|
+
description: data.description
|
|
2891
|
+
} : {},
|
|
2892
|
+
...data.icon !== void 0 ? {
|
|
2893
|
+
icon: data.icon
|
|
2894
|
+
} : {},
|
|
2895
|
+
...data.sortOrder !== void 0 ? {
|
|
2896
|
+
sortOrder: data.sortOrder
|
|
2897
|
+
} : {},
|
|
2898
|
+
...data.i18n !== void 0 ? {
|
|
2899
|
+
i18n: data.i18n
|
|
2900
|
+
} : {}
|
|
2901
|
+
}
|
|
2902
|
+
});
|
|
2903
|
+
return toBundleRow(updated);
|
|
2904
|
+
}
|
|
2905
|
+
async softDelete(bundleId) {
|
|
2906
|
+
await this.db().bundle.update({
|
|
2907
|
+
where: {
|
|
2908
|
+
id: bundleId
|
|
2909
|
+
},
|
|
2910
|
+
data: {
|
|
2911
|
+
deletedAt: /* @__PURE__ */ new Date()
|
|
2912
|
+
}
|
|
2913
|
+
});
|
|
2914
|
+
}
|
|
2915
|
+
// ─── Version operations ───
|
|
2916
|
+
async listVersions(bundleId) {
|
|
2917
|
+
const bundle = await this.db().bundle.findUnique({
|
|
2918
|
+
where: {
|
|
2919
|
+
id: bundleId
|
|
2920
|
+
}
|
|
2921
|
+
});
|
|
2922
|
+
if (!bundle) return [];
|
|
2923
|
+
const rows = await this.db().bundleVersion.findMany({
|
|
2924
|
+
where: {
|
|
2925
|
+
bundleId
|
|
2926
|
+
},
|
|
2927
|
+
orderBy: {
|
|
2928
|
+
version: "asc"
|
|
2929
|
+
}
|
|
2930
|
+
});
|
|
2931
|
+
return rows.map((row) => toBundleVersionRow(row, bundle, this.validityWindows));
|
|
2932
|
+
}
|
|
2933
|
+
async findVersionById(versionId) {
|
|
2934
|
+
const row = await this.db().bundleVersion.findUnique({
|
|
2935
|
+
where: {
|
|
2936
|
+
id: versionId
|
|
2937
|
+
}
|
|
2938
|
+
});
|
|
2939
|
+
if (!row) return null;
|
|
2940
|
+
const bundle = await this.db().bundle.findUnique({
|
|
2941
|
+
where: {
|
|
2942
|
+
id: row.bundleId
|
|
2943
|
+
}
|
|
2944
|
+
});
|
|
2945
|
+
return toBundleVersionRow(row, bundle, this.validityWindows);
|
|
2946
|
+
}
|
|
2947
|
+
async findCurrentDraft(bundleId) {
|
|
2948
|
+
const row = await this.db().bundleVersion.findFirst({
|
|
2949
|
+
where: {
|
|
2950
|
+
bundleId,
|
|
2951
|
+
publishedAt: null
|
|
2952
|
+
}
|
|
2953
|
+
});
|
|
2954
|
+
if (!row) return null;
|
|
2955
|
+
const bundle = await this.db().bundle.findUnique({
|
|
2956
|
+
where: {
|
|
2957
|
+
id: bundleId
|
|
2958
|
+
}
|
|
2959
|
+
});
|
|
2960
|
+
return toBundleVersionRow(row, bundle, this.validityWindows);
|
|
2961
|
+
}
|
|
2962
|
+
async findLatestLive(bundleId, tx) {
|
|
2963
|
+
const db = this.db(tx);
|
|
2964
|
+
const row = await db.bundleVersion.findFirst({
|
|
2965
|
+
where: {
|
|
2966
|
+
bundleId,
|
|
2967
|
+
publishedAt: {
|
|
2968
|
+
not: null
|
|
2969
|
+
},
|
|
2970
|
+
supersededAt: null
|
|
2971
|
+
},
|
|
2972
|
+
orderBy: {
|
|
2973
|
+
version: "desc"
|
|
2974
|
+
}
|
|
2975
|
+
});
|
|
2976
|
+
if (!row) return null;
|
|
2977
|
+
const bundle = await db.bundle.findUnique({
|
|
2978
|
+
where: {
|
|
2979
|
+
id: bundleId
|
|
2980
|
+
}
|
|
2981
|
+
});
|
|
2982
|
+
return toBundleVersionRow(row, bundle, this.validityWindows);
|
|
2983
|
+
}
|
|
2984
|
+
async findActiveBundleVersionWithValidity(bundleId, asOf, tx) {
|
|
2985
|
+
const db = this.db(tx);
|
|
2986
|
+
const row = await db.bundleVersion.findFirst({
|
|
2987
|
+
where: {
|
|
2988
|
+
bundleId,
|
|
2989
|
+
...buildActiveVersionWhere(asOf)
|
|
2990
|
+
},
|
|
2991
|
+
orderBy: [
|
|
2992
|
+
{
|
|
2993
|
+
validFrom: {
|
|
2994
|
+
sort: "desc",
|
|
2995
|
+
nulls: "last"
|
|
2996
|
+
}
|
|
2997
|
+
},
|
|
2998
|
+
{
|
|
2999
|
+
version: "desc"
|
|
3000
|
+
}
|
|
3001
|
+
]
|
|
3002
|
+
});
|
|
3003
|
+
if (!row) return null;
|
|
3004
|
+
const bundle = await db.bundle.findUnique({
|
|
3005
|
+
where: {
|
|
3006
|
+
id: bundleId
|
|
3007
|
+
}
|
|
3008
|
+
});
|
|
3009
|
+
return toBundleVersionRow(row, bundle, true);
|
|
3010
|
+
}
|
|
3011
|
+
async createDraft(data) {
|
|
3012
|
+
const db = this.db();
|
|
3013
|
+
const existingDraft = await db.bundleVersion.findFirst({
|
|
3014
|
+
where: {
|
|
3015
|
+
bundleId: data.bundleId,
|
|
3016
|
+
publishedAt: null
|
|
3017
|
+
}
|
|
3018
|
+
});
|
|
3019
|
+
if (existingDraft) {
|
|
3020
|
+
throw new Error(`Bundle '${data.bundleId}' already has a draft version (v${existingDraft.version}); only one draft per bundle is allowed.`);
|
|
3021
|
+
}
|
|
3022
|
+
const latest = await db.bundleVersion.findFirst({
|
|
3023
|
+
where: {
|
|
3024
|
+
bundleId: data.bundleId
|
|
3025
|
+
},
|
|
3026
|
+
orderBy: {
|
|
3027
|
+
version: "desc"
|
|
3028
|
+
}
|
|
3029
|
+
});
|
|
3030
|
+
const nextVersion = latest ? latest.version + 1 : 1;
|
|
3031
|
+
const created = await db.bundleVersion.create({
|
|
3032
|
+
data: {
|
|
3033
|
+
bundleId: data.bundleId,
|
|
3034
|
+
version: nextVersion,
|
|
3035
|
+
baseVersionId: data.baseVersionId ?? null,
|
|
3036
|
+
features: data.features,
|
|
3037
|
+
quotas: data.quotas ?? {},
|
|
3038
|
+
compatibility: data.compatibility ?? {},
|
|
3039
|
+
pricingOverrides: data.pricingOverrides ?? [],
|
|
3040
|
+
monthlyNet: data.monthlyNet ?? null,
|
|
3041
|
+
yearlyNet: data.yearlyNet ?? null,
|
|
3042
|
+
marketed: data.marketed ?? true,
|
|
3043
|
+
changeNote: data.changeNote ?? "",
|
|
3044
|
+
createdByUserId: data.createdByUserId ?? null,
|
|
3045
|
+
...this.validityWindows ? {
|
|
3046
|
+
validFrom: toNullableDate(data.validFrom),
|
|
3047
|
+
validUntil: toNullableDate(data.validUntil)
|
|
3048
|
+
} : {}
|
|
3049
|
+
}
|
|
3050
|
+
});
|
|
3051
|
+
const bundle = await db.bundle.findUnique({
|
|
3052
|
+
where: {
|
|
3053
|
+
id: data.bundleId
|
|
3054
|
+
}
|
|
3055
|
+
});
|
|
3056
|
+
return toBundleVersionRow(created, bundle, this.validityWindows);
|
|
3057
|
+
}
|
|
3058
|
+
async updateDraft(versionId, data) {
|
|
3059
|
+
const db = this.db();
|
|
3060
|
+
const updated = await db.bundleVersion.update({
|
|
3061
|
+
where: {
|
|
3062
|
+
id: versionId
|
|
3063
|
+
},
|
|
3064
|
+
data: {
|
|
3065
|
+
...data.features !== void 0 ? {
|
|
3066
|
+
features: data.features
|
|
3067
|
+
} : {},
|
|
3068
|
+
...data.quotas !== void 0 ? {
|
|
3069
|
+
quotas: data.quotas
|
|
3070
|
+
} : {},
|
|
3071
|
+
...data.compatibility !== void 0 ? {
|
|
3072
|
+
compatibility: data.compatibility
|
|
3073
|
+
} : {},
|
|
3074
|
+
...data.pricingOverrides !== void 0 ? {
|
|
3075
|
+
pricingOverrides: data.pricingOverrides
|
|
3076
|
+
} : {},
|
|
3077
|
+
...data.monthlyNet !== void 0 ? {
|
|
3078
|
+
monthlyNet: data.monthlyNet
|
|
3079
|
+
} : {},
|
|
3080
|
+
...data.yearlyNet !== void 0 ? {
|
|
3081
|
+
yearlyNet: data.yearlyNet
|
|
3082
|
+
} : {},
|
|
3083
|
+
...data.marketed !== void 0 ? {
|
|
3084
|
+
marketed: data.marketed
|
|
3085
|
+
} : {},
|
|
3086
|
+
...data.changeNote !== void 0 ? {
|
|
3087
|
+
changeNote: data.changeNote
|
|
3088
|
+
} : {},
|
|
3089
|
+
...this.validityWindows && data.validFrom !== void 0 ? {
|
|
3090
|
+
validFrom: toNullableDate(data.validFrom)
|
|
3091
|
+
} : {},
|
|
3092
|
+
...this.validityWindows && data.validUntil !== void 0 ? {
|
|
3093
|
+
validUntil: toNullableDate(data.validUntil)
|
|
3094
|
+
} : {}
|
|
3095
|
+
}
|
|
3096
|
+
});
|
|
3097
|
+
const bundle = await db.bundle.findUnique({
|
|
3098
|
+
where: {
|
|
3099
|
+
id: updated.bundleId
|
|
3100
|
+
}
|
|
3101
|
+
});
|
|
3102
|
+
return toBundleVersionRow(updated, bundle, this.validityWindows);
|
|
3103
|
+
}
|
|
3104
|
+
async publishDraft(versionId, publishMeta, tx) {
|
|
3105
|
+
if (this.validityWindows && tx === void 0) {
|
|
3106
|
+
return this.transaction((transaction) => this.publishDraftWithValidity(transaction, versionId, publishMeta));
|
|
3107
|
+
}
|
|
3108
|
+
if (this.validityWindows) {
|
|
3109
|
+
return this.publishDraftWithValidity(this.db(tx), versionId, publishMeta);
|
|
3110
|
+
}
|
|
3111
|
+
const db = this.db(tx);
|
|
3112
|
+
const draft = await db.bundleVersion.findUnique({
|
|
3113
|
+
where: {
|
|
3114
|
+
id: versionId
|
|
3115
|
+
}
|
|
3116
|
+
});
|
|
3117
|
+
if (!draft) {
|
|
3118
|
+
throw new Error(`BundleVersion '${versionId}' not found.`);
|
|
3119
|
+
}
|
|
3120
|
+
await db.bundleVersion.updateMany({
|
|
3121
|
+
where: {
|
|
3122
|
+
bundleId: draft.bundleId,
|
|
3123
|
+
publishedAt: {
|
|
3124
|
+
not: null
|
|
3125
|
+
},
|
|
3126
|
+
supersededAt: null,
|
|
3127
|
+
NOT: {
|
|
3128
|
+
id: versionId
|
|
3129
|
+
}
|
|
3130
|
+
},
|
|
3131
|
+
data: {
|
|
3132
|
+
supersededAt: /* @__PURE__ */ new Date()
|
|
3133
|
+
}
|
|
3134
|
+
});
|
|
3135
|
+
const published = await db.bundleVersion.update({
|
|
3136
|
+
where: {
|
|
3137
|
+
id: versionId
|
|
3138
|
+
},
|
|
3139
|
+
data: {
|
|
3140
|
+
publishedAt: /* @__PURE__ */ new Date(),
|
|
3141
|
+
publishedByUserId: publishMeta.publishedByUserId,
|
|
3142
|
+
publishedChanges: publishMeta.publishedChanges,
|
|
3143
|
+
nonRegressive: publishMeta.nonRegressive
|
|
3144
|
+
}
|
|
3145
|
+
});
|
|
3146
|
+
const bundle = await db.bundle.findUnique({
|
|
3147
|
+
where: {
|
|
3148
|
+
id: published.bundleId
|
|
3149
|
+
}
|
|
3150
|
+
});
|
|
3151
|
+
return toBundleVersionRow(published, bundle, false);
|
|
3152
|
+
}
|
|
3153
|
+
async publishDraftWithValidity(db, versionId, publishMeta) {
|
|
3154
|
+
const draft = await db.bundleVersion.findUnique({
|
|
3155
|
+
where: {
|
|
3156
|
+
id: versionId
|
|
3157
|
+
}
|
|
3158
|
+
});
|
|
3159
|
+
if (!draft) {
|
|
3160
|
+
throw new Error(`BundleVersion '${versionId}' not found.`);
|
|
3161
|
+
}
|
|
3162
|
+
const now = /* @__PURE__ */ new Date();
|
|
3163
|
+
await db.bundleVersion.updateMany({
|
|
3164
|
+
where: {
|
|
3165
|
+
bundleId: draft.bundleId,
|
|
3166
|
+
publishedAt: {
|
|
3167
|
+
not: null
|
|
3168
|
+
},
|
|
3169
|
+
supersededAt: null,
|
|
3170
|
+
NOT: {
|
|
3171
|
+
id: versionId
|
|
3172
|
+
}
|
|
3173
|
+
},
|
|
3174
|
+
data: {
|
|
3175
|
+
supersededAt: now,
|
|
3176
|
+
validUntil: previousUtcDay(publishMeta.validFrom)
|
|
3177
|
+
}
|
|
3178
|
+
});
|
|
3179
|
+
const published = await db.bundleVersion.update({
|
|
3180
|
+
where: {
|
|
3181
|
+
id: versionId
|
|
3182
|
+
},
|
|
3183
|
+
data: {
|
|
3184
|
+
publishedAt: now,
|
|
3185
|
+
publishedByUserId: publishMeta.publishedByUserId,
|
|
3186
|
+
publishedChanges: publishMeta.publishedChanges,
|
|
3187
|
+
nonRegressive: publishMeta.nonRegressive,
|
|
3188
|
+
validFrom: publishMeta.validFrom,
|
|
3189
|
+
validUntil: publishMeta.validUntil
|
|
3190
|
+
}
|
|
3191
|
+
});
|
|
3192
|
+
const bundle = await db.bundle.findUnique({
|
|
3193
|
+
where: {
|
|
3194
|
+
id: published.bundleId
|
|
3195
|
+
}
|
|
3196
|
+
});
|
|
3197
|
+
return toBundleVersionRow(published, bundle, true);
|
|
3198
|
+
}
|
|
3199
|
+
async deleteDraft(versionId) {
|
|
3200
|
+
const db = this.db();
|
|
3201
|
+
const row = await db.bundleVersion.findUnique({
|
|
3202
|
+
where: {
|
|
3203
|
+
id: versionId
|
|
3204
|
+
}
|
|
3205
|
+
});
|
|
3206
|
+
if (!row) return;
|
|
3207
|
+
if (row.publishedAt !== null) {
|
|
3208
|
+
throw new Error(`BundleVersion '${versionId}' is already published and cannot be discarded (published versions are immutable \u2014 contract protection P1).`);
|
|
3209
|
+
}
|
|
3210
|
+
try {
|
|
3211
|
+
await db.bundleVersion.delete({
|
|
3212
|
+
where: {
|
|
3213
|
+
id: versionId
|
|
3214
|
+
}
|
|
3215
|
+
});
|
|
3216
|
+
} catch (err) {
|
|
3217
|
+
if (err?.code === "P2025") return;
|
|
3218
|
+
throw err;
|
|
3219
|
+
}
|
|
3220
|
+
}
|
|
3221
|
+
};
|
|
3222
|
+
PrismaBundleRepository = _ts_decorate20([
|
|
3223
|
+
Injectable20(),
|
|
3224
|
+
_ts_param18(0, Inject18(PRISMA_CLIENT_TOKEN)),
|
|
3225
|
+
_ts_param18(1, Optional7()),
|
|
3226
|
+
_ts_param18(1, Inject18(PRISMA_BUNDLE_REPOSITORY_OPTIONS)),
|
|
3227
|
+
_ts_metadata18("design:type", Function),
|
|
3228
|
+
_ts_metadata18("design:paramtypes", [
|
|
3229
|
+
typeof BundlePrismaClient === "undefined" ? Object : BundlePrismaClient,
|
|
3230
|
+
typeof PrismaBundleRepositoryOptions === "undefined" ? Object : PrismaBundleRepositoryOptions
|
|
3231
|
+
])
|
|
3232
|
+
], PrismaBundleRepository);
|
|
3233
|
+
function isPlainObject(value) {
|
|
3234
|
+
return value !== null && typeof value === "object" && !Array.isArray(value);
|
|
3235
|
+
}
|
|
3236
|
+
__name(isPlainObject, "isPlainObject");
|
|
3237
|
+
function toDecimalString(value) {
|
|
3238
|
+
return value == null ? null : value.toString();
|
|
3239
|
+
}
|
|
3240
|
+
__name(toDecimalString, "toDecimalString");
|
|
3241
|
+
function toNullableDate(value) {
|
|
3242
|
+
return value ? new Date(value) : null;
|
|
3243
|
+
}
|
|
3244
|
+
__name(toNullableDate, "toNullableDate");
|
|
3245
|
+
function previousUtcDay(value) {
|
|
3246
|
+
const result = new Date(value);
|
|
3247
|
+
result.setUTCDate(result.getUTCDate() - 1);
|
|
3248
|
+
return result;
|
|
3249
|
+
}
|
|
3250
|
+
__name(previousUtcDay, "previousUtcDay");
|
|
3251
|
+
function toVersionChanges(value) {
|
|
3252
|
+
return Array.isArray(value) ? value : null;
|
|
3253
|
+
}
|
|
3254
|
+
__name(toVersionChanges, "toVersionChanges");
|
|
3255
|
+
function toCompatibility(value) {
|
|
3256
|
+
return isPlainObject(value) ? value : {};
|
|
3257
|
+
}
|
|
3258
|
+
__name(toCompatibility, "toCompatibility");
|
|
3259
|
+
function toPricingOverrides(value) {
|
|
3260
|
+
return Array.isArray(value) ? value : [];
|
|
3261
|
+
}
|
|
3262
|
+
__name(toPricingOverrides, "toPricingOverrides");
|
|
3263
|
+
function toI18n(value) {
|
|
3264
|
+
return isPlainObject(value) ? value : {};
|
|
3265
|
+
}
|
|
3266
|
+
__name(toI18n, "toI18n");
|
|
3267
|
+
function toBundleRow(row) {
|
|
3268
|
+
return {
|
|
3269
|
+
id: row.id,
|
|
3270
|
+
projectKey: row.projectKey,
|
|
3271
|
+
bundleKey: row.bundleKey,
|
|
3272
|
+
label: row.label,
|
|
3273
|
+
description: row.description,
|
|
3274
|
+
icon: row.icon,
|
|
3275
|
+
sortOrder: row.sortOrder,
|
|
3276
|
+
i18n: toI18n(row.i18n),
|
|
3277
|
+
createdAt: row.createdAt.toISOString(),
|
|
3278
|
+
updatedAt: row.updatedAt.toISOString(),
|
|
3279
|
+
deletedAt: row.deletedAt?.toISOString() ?? null
|
|
3280
|
+
};
|
|
3281
|
+
}
|
|
3282
|
+
__name(toBundleRow, "toBundleRow");
|
|
3283
|
+
function toBundleVersionRow(row, bundle, validityWindows) {
|
|
3284
|
+
return {
|
|
3285
|
+
id: row.id,
|
|
3286
|
+
bundleId: row.bundleId,
|
|
3287
|
+
bundleKey: bundle?.bundleKey ?? "",
|
|
3288
|
+
label: bundle?.label ?? "",
|
|
3289
|
+
version: row.version,
|
|
3290
|
+
baseVersionId: row.baseVersionId,
|
|
3291
|
+
features: toStringArray(row.features),
|
|
3292
|
+
quotas: toQuotaMap(row.quotas),
|
|
3293
|
+
compatibility: toCompatibility(row.compatibility),
|
|
3294
|
+
pricingOverrides: toPricingOverrides(row.pricingOverrides),
|
|
3295
|
+
monthlyNet: toDecimalString(row.monthlyNet),
|
|
3296
|
+
yearlyNet: toDecimalString(row.yearlyNet),
|
|
3297
|
+
marketed: row.marketed,
|
|
3298
|
+
publishedAt: row.publishedAt?.toISOString() ?? null,
|
|
3299
|
+
supersededAt: row.supersededAt?.toISOString() ?? null,
|
|
3300
|
+
validFrom: validityWindows && row.validFrom instanceof Date ? row.validFrom.toISOString() : null,
|
|
3301
|
+
validUntil: validityWindows && row.validUntil instanceof Date ? row.validUntil.toISOString() : null,
|
|
3302
|
+
publishedChanges: toVersionChanges(row.publishedChanges),
|
|
3303
|
+
changeNote: row.changeNote,
|
|
3304
|
+
nonRegressive: row.nonRegressive,
|
|
3305
|
+
createdByUserId: row.createdByUserId,
|
|
3306
|
+
publishedByUserId: row.publishedByUserId,
|
|
3307
|
+
createdAt: row.createdAt.toISOString(),
|
|
3308
|
+
updatedAt: row.updatedAt.toISOString()
|
|
3309
|
+
};
|
|
3310
|
+
}
|
|
3311
|
+
__name(toBundleVersionRow, "toBundleVersionRow");
|
|
3312
|
+
|
|
3313
|
+
// src/prisma-catalog-entry.repository.ts
|
|
3314
|
+
import { Inject as Inject19, Injectable as Injectable21 } from "@nestjs/common";
|
|
3315
|
+
function _ts_decorate21(decorators, target, key, desc) {
|
|
3316
|
+
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
3317
|
+
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
3318
|
+
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
3319
|
+
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
3320
|
+
}
|
|
3321
|
+
__name(_ts_decorate21, "_ts_decorate");
|
|
3322
|
+
function _ts_metadata19(k, v) {
|
|
3323
|
+
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
|
|
3324
|
+
}
|
|
3325
|
+
__name(_ts_metadata19, "_ts_metadata");
|
|
3326
|
+
function _ts_param19(paramIndex, decorator) {
|
|
3327
|
+
return function(target, key) {
|
|
3328
|
+
decorator(target, key, paramIndex);
|
|
3329
|
+
};
|
|
3330
|
+
}
|
|
3331
|
+
__name(_ts_param19, "_ts_param");
|
|
3332
|
+
var PrismaCatalogEntryRepository = class {
|
|
3333
|
+
static {
|
|
3334
|
+
__name(this, "PrismaCatalogEntryRepository");
|
|
3335
|
+
}
|
|
3336
|
+
prisma;
|
|
3337
|
+
constructor(prisma) {
|
|
3338
|
+
this.prisma = prisma;
|
|
3339
|
+
}
|
|
3340
|
+
get db() {
|
|
3341
|
+
return this.prisma;
|
|
3342
|
+
}
|
|
3343
|
+
async listCapabilities(filter) {
|
|
3344
|
+
const rows = await this.db.capabilityCatalogEntry.findMany({
|
|
3345
|
+
where: {
|
|
3346
|
+
projectKey: filter.projectKey,
|
|
3347
|
+
deletedAt: null,
|
|
3348
|
+
...filter.codeStatus ? {
|
|
3349
|
+
codeStatus: filter.codeStatus
|
|
3350
|
+
} : {}
|
|
3351
|
+
},
|
|
3352
|
+
orderBy: [
|
|
3353
|
+
{
|
|
3354
|
+
sortOrder: "asc"
|
|
3355
|
+
},
|
|
3356
|
+
{
|
|
3357
|
+
capabilityKey: "asc"
|
|
3358
|
+
}
|
|
3359
|
+
]
|
|
3360
|
+
});
|
|
3361
|
+
return rows.map(toCapabilityRow);
|
|
3362
|
+
}
|
|
3363
|
+
async listFeatures(filter) {
|
|
3364
|
+
const rows = await this.db.featureCatalogEntry.findMany({
|
|
3365
|
+
where: {
|
|
3366
|
+
projectKey: filter.projectKey,
|
|
3367
|
+
deletedAt: null,
|
|
3368
|
+
...filter.discoveryStatus ? {
|
|
3369
|
+
discoveryStatus: filter.discoveryStatus
|
|
3370
|
+
} : {}
|
|
3371
|
+
},
|
|
3372
|
+
orderBy: [
|
|
3373
|
+
{
|
|
3374
|
+
sortOrder: "asc"
|
|
3375
|
+
},
|
|
3376
|
+
{
|
|
3377
|
+
featureKey: "asc"
|
|
3378
|
+
}
|
|
3379
|
+
]
|
|
3380
|
+
});
|
|
3381
|
+
return rows.map(toFeatureRow);
|
|
3382
|
+
}
|
|
3383
|
+
async listQuotas(filter) {
|
|
3384
|
+
const rows = await this.db.quotaCatalogEntry.findMany({
|
|
3385
|
+
where: {
|
|
3386
|
+
projectKey: filter.projectKey,
|
|
3387
|
+
deletedAt: null,
|
|
3388
|
+
...filter.discoveryStatus ? {
|
|
3389
|
+
discoveryStatus: filter.discoveryStatus
|
|
3390
|
+
} : {}
|
|
3391
|
+
},
|
|
3392
|
+
orderBy: [
|
|
3393
|
+
{
|
|
3394
|
+
sortOrder: "asc"
|
|
3395
|
+
},
|
|
3396
|
+
{
|
|
3397
|
+
quotaKey: "asc"
|
|
3398
|
+
}
|
|
3399
|
+
]
|
|
3400
|
+
});
|
|
3401
|
+
return rows.map(toQuotaRow);
|
|
3402
|
+
}
|
|
3403
|
+
async upsertCapability(data) {
|
|
3404
|
+
const codeFields = {
|
|
3405
|
+
label: data.label,
|
|
3406
|
+
description: data.description,
|
|
3407
|
+
featureKey: data.featureKey,
|
|
3408
|
+
bundleKey: data.bundleKey,
|
|
3409
|
+
codeStatus: data.codeStatus,
|
|
3410
|
+
owner: data.owner,
|
|
3411
|
+
kind: data.kind,
|
|
3412
|
+
replacementKey: data.replacementKey,
|
|
3413
|
+
deprecatedAt: data.deprecatedAt ? new Date(data.deprecatedAt) : null,
|
|
3414
|
+
removalPlannedAt: data.removalPlannedAt ? new Date(data.removalPlannedAt) : null,
|
|
3415
|
+
reason: data.reason
|
|
3416
|
+
};
|
|
3417
|
+
const row = await this.db.capabilityCatalogEntry.upsert({
|
|
3418
|
+
where: {
|
|
3419
|
+
projectKey_capabilityKey: {
|
|
3420
|
+
projectKey: data.projectKey,
|
|
3421
|
+
capabilityKey: data.capabilityKey
|
|
3422
|
+
}
|
|
3423
|
+
},
|
|
3424
|
+
create: {
|
|
3425
|
+
projectKey: data.projectKey,
|
|
3426
|
+
capabilityKey: data.capabilityKey,
|
|
3427
|
+
...codeFields
|
|
3428
|
+
},
|
|
3429
|
+
update: codeFields
|
|
3430
|
+
});
|
|
3431
|
+
return toCapabilityRow(row);
|
|
3432
|
+
}
|
|
3433
|
+
async upsertFeature(data) {
|
|
3434
|
+
const codeFields = {
|
|
3435
|
+
label: data.label,
|
|
3436
|
+
description: data.description,
|
|
3437
|
+
discoveryStatus: data.discoveryStatus,
|
|
3438
|
+
requires: data.requires,
|
|
3439
|
+
replaces: data.replaces,
|
|
3440
|
+
...data.core !== void 0 ? {
|
|
3441
|
+
core: data.core
|
|
3442
|
+
} : {}
|
|
3443
|
+
};
|
|
3444
|
+
const row = await this.db.featureCatalogEntry.upsert({
|
|
3445
|
+
where: {
|
|
3446
|
+
projectKey_featureKey: {
|
|
3447
|
+
projectKey: data.projectKey,
|
|
3448
|
+
featureKey: data.featureKey
|
|
3449
|
+
}
|
|
3450
|
+
},
|
|
3451
|
+
create: {
|
|
3452
|
+
projectKey: data.projectKey,
|
|
3453
|
+
featureKey: data.featureKey,
|
|
3454
|
+
...codeFields
|
|
3455
|
+
},
|
|
3456
|
+
update: codeFields
|
|
3457
|
+
});
|
|
3458
|
+
return toFeatureRow(row);
|
|
3459
|
+
}
|
|
3460
|
+
async upsertQuota(data) {
|
|
3461
|
+
const codeFields = {
|
|
3462
|
+
label: data.label,
|
|
3463
|
+
description: data.description,
|
|
3464
|
+
unit: data.unit,
|
|
3465
|
+
featureKey: data.featureKey,
|
|
3466
|
+
usageProvider: data.usageProvider,
|
|
3467
|
+
enforcementMode: data.enforcementMode,
|
|
3468
|
+
discoveryStatus: data.discoveryStatus,
|
|
3469
|
+
replaces: data.replaces
|
|
3470
|
+
};
|
|
3471
|
+
const row = await this.db.quotaCatalogEntry.upsert({
|
|
3472
|
+
where: {
|
|
3473
|
+
projectKey_quotaKey: {
|
|
3474
|
+
projectKey: data.projectKey,
|
|
3475
|
+
quotaKey: data.quotaKey
|
|
3476
|
+
}
|
|
3477
|
+
},
|
|
3478
|
+
create: {
|
|
3479
|
+
projectKey: data.projectKey,
|
|
3480
|
+
quotaKey: data.quotaKey,
|
|
3481
|
+
...codeFields
|
|
3482
|
+
},
|
|
3483
|
+
update: codeFields
|
|
3484
|
+
});
|
|
3485
|
+
return toQuotaRow(row);
|
|
3486
|
+
}
|
|
3487
|
+
async retireMissing(projectKey, type, presentKeys) {
|
|
3488
|
+
if (type === "capability") {
|
|
3489
|
+
const res2 = await this.db.capabilityCatalogEntry.updateMany({
|
|
3490
|
+
where: {
|
|
3491
|
+
projectKey,
|
|
3492
|
+
deletedAt: null,
|
|
3493
|
+
codeStatus: {
|
|
3494
|
+
not: "retired"
|
|
3495
|
+
},
|
|
3496
|
+
capabilityKey: {
|
|
3497
|
+
notIn: presentKeys
|
|
3498
|
+
}
|
|
3499
|
+
},
|
|
3500
|
+
data: {
|
|
3501
|
+
codeStatus: "retired"
|
|
3502
|
+
}
|
|
3503
|
+
});
|
|
3504
|
+
return res2.count;
|
|
3505
|
+
}
|
|
3506
|
+
if (type === "feature") {
|
|
3507
|
+
const res2 = await this.db.featureCatalogEntry.updateMany({
|
|
3508
|
+
where: {
|
|
3509
|
+
projectKey,
|
|
3510
|
+
deletedAt: null,
|
|
3511
|
+
discoveryStatus: {
|
|
3512
|
+
not: "obsolete"
|
|
3513
|
+
},
|
|
3514
|
+
featureKey: {
|
|
3515
|
+
notIn: presentKeys
|
|
3516
|
+
}
|
|
3517
|
+
},
|
|
3518
|
+
data: {
|
|
3519
|
+
discoveryStatus: "obsolete"
|
|
3520
|
+
}
|
|
3521
|
+
});
|
|
3522
|
+
return res2.count;
|
|
3523
|
+
}
|
|
3524
|
+
const res = await this.db.quotaCatalogEntry.updateMany({
|
|
3525
|
+
where: {
|
|
3526
|
+
projectKey,
|
|
3527
|
+
deletedAt: null,
|
|
3528
|
+
discoveryStatus: {
|
|
3529
|
+
not: "obsolete"
|
|
3530
|
+
},
|
|
3531
|
+
quotaKey: {
|
|
3532
|
+
notIn: presentKeys
|
|
3533
|
+
}
|
|
3534
|
+
},
|
|
3535
|
+
data: {
|
|
3536
|
+
discoveryStatus: "obsolete"
|
|
3537
|
+
}
|
|
3538
|
+
});
|
|
3539
|
+
return res.count;
|
|
3540
|
+
}
|
|
3541
|
+
async setFeatureSuccessor(projectKey, featureKey, successorKey) {
|
|
3542
|
+
const row = await this.db.featureCatalogEntry.update({
|
|
3543
|
+
where: {
|
|
3544
|
+
projectKey_featureKey: {
|
|
3545
|
+
projectKey,
|
|
3546
|
+
featureKey
|
|
3547
|
+
}
|
|
3548
|
+
},
|
|
3549
|
+
data: {
|
|
3550
|
+
successorKey
|
|
3551
|
+
}
|
|
3552
|
+
});
|
|
3553
|
+
return toFeatureRow(row);
|
|
3554
|
+
}
|
|
3555
|
+
async setQuotaSuccessor(projectKey, quotaKey, successorKey) {
|
|
3556
|
+
const row = await this.db.quotaCatalogEntry.update({
|
|
3557
|
+
where: {
|
|
3558
|
+
projectKey_quotaKey: {
|
|
3559
|
+
projectKey,
|
|
3560
|
+
quotaKey
|
|
3561
|
+
}
|
|
3562
|
+
},
|
|
3563
|
+
data: {
|
|
3564
|
+
successorKey
|
|
3565
|
+
}
|
|
3566
|
+
});
|
|
3567
|
+
return toQuotaRow(row);
|
|
3568
|
+
}
|
|
3569
|
+
async findFeature(projectKey, featureKey) {
|
|
3570
|
+
const row = await this.db.featureCatalogEntry.findUnique({
|
|
3571
|
+
where: {
|
|
3572
|
+
projectKey_featureKey: {
|
|
3573
|
+
projectKey,
|
|
3574
|
+
featureKey
|
|
3575
|
+
}
|
|
3576
|
+
}
|
|
3577
|
+
});
|
|
3578
|
+
return row ? toFeatureRow(row) : null;
|
|
3579
|
+
}
|
|
3580
|
+
async findQuota(projectKey, quotaKey) {
|
|
3581
|
+
const row = await this.db.quotaCatalogEntry.findUnique({
|
|
3582
|
+
where: {
|
|
3583
|
+
projectKey_quotaKey: {
|
|
3584
|
+
projectKey,
|
|
3585
|
+
quotaKey
|
|
3586
|
+
}
|
|
3587
|
+
}
|
|
3588
|
+
});
|
|
3589
|
+
return row ? toQuotaRow(row) : null;
|
|
3590
|
+
}
|
|
3591
|
+
async setFeatureReview(projectKey, featureKey, data) {
|
|
3592
|
+
const row = await this.db.featureCatalogEntry.update({
|
|
3593
|
+
where: {
|
|
3594
|
+
projectKey_featureKey: {
|
|
3595
|
+
projectKey,
|
|
3596
|
+
featureKey
|
|
3597
|
+
}
|
|
3598
|
+
},
|
|
3599
|
+
data: {
|
|
3600
|
+
discoveryStatus: data.discoveryStatus,
|
|
3601
|
+
approvedAt: data.approvedAt ? new Date(data.approvedAt) : null,
|
|
3602
|
+
approvedBy: data.approvedBy,
|
|
3603
|
+
approvedSignature: data.approvedSignature
|
|
3604
|
+
}
|
|
3605
|
+
});
|
|
3606
|
+
return toFeatureRow(row);
|
|
3607
|
+
}
|
|
3608
|
+
async setQuotaReview(projectKey, quotaKey, data) {
|
|
3609
|
+
const row = await this.db.quotaCatalogEntry.update({
|
|
3610
|
+
where: {
|
|
3611
|
+
projectKey_quotaKey: {
|
|
3612
|
+
projectKey,
|
|
3613
|
+
quotaKey
|
|
3614
|
+
}
|
|
3615
|
+
},
|
|
3616
|
+
data: {
|
|
3617
|
+
discoveryStatus: data.discoveryStatus,
|
|
3618
|
+
approvedAt: data.approvedAt ? new Date(data.approvedAt) : null,
|
|
3619
|
+
approvedBy: data.approvedBy,
|
|
3620
|
+
approvedSignature: data.approvedSignature
|
|
3621
|
+
}
|
|
3622
|
+
});
|
|
3623
|
+
return toQuotaRow(row);
|
|
3624
|
+
}
|
|
3625
|
+
async setFeatureI18n(projectKey, featureKey, i18n) {
|
|
3626
|
+
const row = await this.db.featureCatalogEntry.update({
|
|
3627
|
+
where: {
|
|
3628
|
+
projectKey_featureKey: {
|
|
3629
|
+
projectKey,
|
|
3630
|
+
featureKey
|
|
3631
|
+
}
|
|
3632
|
+
},
|
|
3633
|
+
data: {
|
|
3634
|
+
i18n
|
|
3635
|
+
}
|
|
3636
|
+
});
|
|
3637
|
+
return toFeatureRow(row);
|
|
3638
|
+
}
|
|
3639
|
+
async setQuotaI18n(projectKey, quotaKey, i18n) {
|
|
3640
|
+
const row = await this.db.quotaCatalogEntry.update({
|
|
3641
|
+
where: {
|
|
3642
|
+
projectKey_quotaKey: {
|
|
3643
|
+
projectKey,
|
|
3644
|
+
quotaKey
|
|
3645
|
+
}
|
|
3646
|
+
},
|
|
3647
|
+
data: {
|
|
3648
|
+
i18n
|
|
3649
|
+
}
|
|
3650
|
+
});
|
|
3651
|
+
return toQuotaRow(row);
|
|
3652
|
+
}
|
|
3653
|
+
async setFeatureBase(projectKey, featureKey, data) {
|
|
3654
|
+
const row = await this.db.featureCatalogEntry.update({
|
|
3655
|
+
where: {
|
|
3656
|
+
projectKey_featureKey: {
|
|
3657
|
+
projectKey,
|
|
3658
|
+
featureKey
|
|
3659
|
+
}
|
|
3660
|
+
},
|
|
3661
|
+
data: {
|
|
3662
|
+
...data.label !== void 0 ? {
|
|
3663
|
+
label: data.label
|
|
3664
|
+
} : {},
|
|
3665
|
+
...data.description !== void 0 ? {
|
|
3666
|
+
description: data.description
|
|
3667
|
+
} : {},
|
|
3668
|
+
...data.icon !== void 0 ? {
|
|
3669
|
+
icon: data.icon
|
|
3670
|
+
} : {},
|
|
3671
|
+
...data.tier !== void 0 ? {
|
|
3672
|
+
tier: data.tier
|
|
3673
|
+
} : {}
|
|
3674
|
+
}
|
|
3675
|
+
});
|
|
3676
|
+
return toFeatureRow(row);
|
|
3677
|
+
}
|
|
3678
|
+
async setQuotaBase(projectKey, quotaKey, data) {
|
|
3679
|
+
const row = await this.db.quotaCatalogEntry.update({
|
|
3680
|
+
where: {
|
|
3681
|
+
projectKey_quotaKey: {
|
|
3682
|
+
projectKey,
|
|
3683
|
+
quotaKey
|
|
3684
|
+
}
|
|
3685
|
+
},
|
|
3686
|
+
data: {
|
|
3687
|
+
...data.label !== void 0 ? {
|
|
3688
|
+
label: data.label
|
|
3689
|
+
} : {},
|
|
3690
|
+
...data.description !== void 0 ? {
|
|
3691
|
+
description: data.description
|
|
3692
|
+
} : {}
|
|
3693
|
+
}
|
|
3694
|
+
});
|
|
3695
|
+
return toQuotaRow(row);
|
|
3696
|
+
}
|
|
3697
|
+
};
|
|
3698
|
+
PrismaCatalogEntryRepository = _ts_decorate21([
|
|
3699
|
+
Injectable21(),
|
|
3700
|
+
_ts_param19(0, Inject19(PRISMA_CLIENT_TOKEN)),
|
|
3701
|
+
_ts_metadata19("design:type", Function),
|
|
3702
|
+
_ts_metadata19("design:paramtypes", [
|
|
3703
|
+
typeof CatalogEntryRepositoryClient === "undefined" ? Object : CatalogEntryRepositoryClient
|
|
3704
|
+
])
|
|
3705
|
+
], PrismaCatalogEntryRepository);
|
|
3706
|
+
function toI18n2(value) {
|
|
3707
|
+
if (value !== null && typeof value === "object" && !Array.isArray(value)) {
|
|
3708
|
+
return value;
|
|
3709
|
+
}
|
|
3710
|
+
return {};
|
|
3711
|
+
}
|
|
3712
|
+
__name(toI18n2, "toI18n");
|
|
3713
|
+
function toCapabilityRow(row) {
|
|
3714
|
+
return {
|
|
3715
|
+
id: row.id,
|
|
3716
|
+
projectKey: row.projectKey,
|
|
3717
|
+
capabilityKey: row.capabilityKey,
|
|
3718
|
+
label: row.label,
|
|
3719
|
+
description: row.description,
|
|
3720
|
+
featureKey: row.featureKey,
|
|
3721
|
+
bundleKey: row.bundleKey,
|
|
3722
|
+
codeStatus: row.codeStatus,
|
|
3723
|
+
owner: row.owner,
|
|
3724
|
+
kind: row.kind,
|
|
3725
|
+
replacementKey: row.replacementKey,
|
|
3726
|
+
deprecatedAt: row.deprecatedAt ? row.deprecatedAt.toISOString() : null,
|
|
3727
|
+
removalPlannedAt: row.removalPlannedAt ? row.removalPlannedAt.toISOString() : null,
|
|
3728
|
+
reason: row.reason,
|
|
3729
|
+
i18n: toI18n2(row.i18n),
|
|
3730
|
+
sortOrder: row.sortOrder,
|
|
3731
|
+
createdAt: row.createdAt.toISOString(),
|
|
3732
|
+
updatedAt: row.updatedAt.toISOString(),
|
|
3733
|
+
deletedAt: row.deletedAt ? row.deletedAt.toISOString() : null
|
|
3734
|
+
};
|
|
3735
|
+
}
|
|
3736
|
+
__name(toCapabilityRow, "toCapabilityRow");
|
|
3737
|
+
function toFeatureRow(row) {
|
|
3738
|
+
return {
|
|
3739
|
+
id: row.id,
|
|
3740
|
+
projectKey: row.projectKey,
|
|
3741
|
+
featureKey: row.featureKey,
|
|
3742
|
+
label: row.label,
|
|
3743
|
+
description: row.description,
|
|
3744
|
+
marketingLabel: row.marketingLabel,
|
|
3745
|
+
marketingDescription: row.marketingDescription,
|
|
3746
|
+
icon: row.icon,
|
|
3747
|
+
tier: row.tier,
|
|
3748
|
+
discoveryStatus: row.discoveryStatus,
|
|
3749
|
+
requires: row.requires,
|
|
3750
|
+
replaces: row.replaces,
|
|
3751
|
+
successorKey: row.successorKey,
|
|
3752
|
+
approvedAt: row.approvedAt ? row.approvedAt.toISOString() : null,
|
|
3753
|
+
approvedBy: row.approvedBy,
|
|
3754
|
+
approvedSignature: row.approvedSignature,
|
|
3755
|
+
plannedOnly: row.plannedOnly,
|
|
3756
|
+
core: row.core,
|
|
3757
|
+
i18n: toI18n2(row.i18n),
|
|
3758
|
+
sortOrder: row.sortOrder,
|
|
3759
|
+
createdAt: row.createdAt.toISOString(),
|
|
3760
|
+
updatedAt: row.updatedAt.toISOString(),
|
|
3761
|
+
deletedAt: row.deletedAt ? row.deletedAt.toISOString() : null
|
|
3762
|
+
};
|
|
3763
|
+
}
|
|
3764
|
+
__name(toFeatureRow, "toFeatureRow");
|
|
3765
|
+
function toQuotaRow(row) {
|
|
3766
|
+
return {
|
|
3767
|
+
id: row.id,
|
|
3768
|
+
projectKey: row.projectKey,
|
|
3769
|
+
quotaKey: row.quotaKey,
|
|
3770
|
+
label: row.label,
|
|
3771
|
+
description: row.description,
|
|
3772
|
+
unit: row.unit,
|
|
3773
|
+
featureKey: row.featureKey,
|
|
3774
|
+
usageProvider: row.usageProvider,
|
|
3775
|
+
enforcementMode: row.enforcementMode,
|
|
3776
|
+
discoveryStatus: row.discoveryStatus,
|
|
3777
|
+
replaces: row.replaces,
|
|
3778
|
+
successorKey: row.successorKey,
|
|
3779
|
+
approvedAt: row.approvedAt ? row.approvedAt.toISOString() : null,
|
|
3780
|
+
approvedBy: row.approvedBy,
|
|
3781
|
+
approvedSignature: row.approvedSignature,
|
|
3782
|
+
i18n: toI18n2(row.i18n),
|
|
3783
|
+
sortOrder: row.sortOrder,
|
|
3784
|
+
createdAt: row.createdAt.toISOString(),
|
|
3785
|
+
updatedAt: row.updatedAt.toISOString(),
|
|
3786
|
+
deletedAt: row.deletedAt ? row.deletedAt.toISOString() : null
|
|
3787
|
+
};
|
|
3788
|
+
}
|
|
3789
|
+
__name(toQuotaRow, "toQuotaRow");
|
|
3790
|
+
|
|
3791
|
+
// src/prisma-marketing-projection.repository.ts
|
|
3792
|
+
import { Inject as Inject20, Injectable as Injectable22 } from "@nestjs/common";
|
|
3793
|
+
function _ts_decorate22(decorators, target, key, desc) {
|
|
3794
|
+
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
3795
|
+
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
3796
|
+
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
3797
|
+
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
3798
|
+
}
|
|
3799
|
+
__name(_ts_decorate22, "_ts_decorate");
|
|
3800
|
+
function _ts_metadata20(k, v) {
|
|
3801
|
+
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
|
|
3802
|
+
}
|
|
3803
|
+
__name(_ts_metadata20, "_ts_metadata");
|
|
3804
|
+
function _ts_param20(paramIndex, decorator) {
|
|
3805
|
+
return function(target, key) {
|
|
3806
|
+
decorator(target, key, paramIndex);
|
|
3807
|
+
};
|
|
3808
|
+
}
|
|
3809
|
+
__name(_ts_param20, "_ts_param");
|
|
3810
|
+
var PrismaMarketingProjectionRepository = class {
|
|
3811
|
+
static {
|
|
3812
|
+
__name(this, "PrismaMarketingProjectionRepository");
|
|
3813
|
+
}
|
|
3814
|
+
prisma;
|
|
3815
|
+
constructor(prisma) {
|
|
3816
|
+
this.prisma = prisma;
|
|
3817
|
+
}
|
|
3818
|
+
get db() {
|
|
3819
|
+
return this.prisma;
|
|
3820
|
+
}
|
|
3821
|
+
async list(filter) {
|
|
3822
|
+
const rows = await this.db.marketingProjection.findMany({
|
|
3823
|
+
where: {
|
|
3824
|
+
projectKey: filter.projectKey,
|
|
3825
|
+
...filter.targetType ? {
|
|
3826
|
+
targetType: filter.targetType
|
|
3827
|
+
} : {},
|
|
3828
|
+
...filter.targetVersionId ? {
|
|
3829
|
+
targetVersionId: filter.targetVersionId
|
|
3830
|
+
} : {},
|
|
3831
|
+
...filter.locale ? {
|
|
3832
|
+
locale: filter.locale
|
|
3833
|
+
} : {}
|
|
3834
|
+
},
|
|
3835
|
+
orderBy: [
|
|
3836
|
+
{
|
|
3837
|
+
priority: "desc"
|
|
3838
|
+
},
|
|
3839
|
+
{
|
|
3840
|
+
displayLabel: "asc"
|
|
3841
|
+
}
|
|
3842
|
+
]
|
|
3843
|
+
});
|
|
3844
|
+
return rows.map(toRow);
|
|
3845
|
+
}
|
|
3846
|
+
async findById(id) {
|
|
3847
|
+
const row = await this.db.marketingProjection.findUnique({
|
|
3848
|
+
where: {
|
|
3849
|
+
id
|
|
3850
|
+
}
|
|
3851
|
+
});
|
|
3852
|
+
return row ? toRow(row) : null;
|
|
3853
|
+
}
|
|
3854
|
+
async findByTarget(targetType, targetVersionId, locale) {
|
|
3855
|
+
const row = await this.db.marketingProjection.findUnique({
|
|
3856
|
+
where: {
|
|
3857
|
+
targetType_targetVersionId_locale: {
|
|
3858
|
+
targetType,
|
|
3859
|
+
targetVersionId,
|
|
3860
|
+
locale
|
|
3861
|
+
}
|
|
3862
|
+
}
|
|
3863
|
+
});
|
|
3864
|
+
return row ? toRow(row) : null;
|
|
3865
|
+
}
|
|
3866
|
+
async create(data) {
|
|
3867
|
+
const row = await this.db.marketingProjection.create({
|
|
3868
|
+
data: {
|
|
3869
|
+
projectKey: data.projectKey,
|
|
3870
|
+
targetType: data.targetType,
|
|
3871
|
+
targetVersionId: data.targetVersionId,
|
|
3872
|
+
locale: data.locale ?? "de",
|
|
3873
|
+
displayLabel: data.displayLabel,
|
|
3874
|
+
description: data.description,
|
|
3875
|
+
visible: data.visible ?? true,
|
|
3876
|
+
badge: data.badge ?? "",
|
|
3877
|
+
topFeatures: data.topFeatures ?? [],
|
|
3878
|
+
trialEnabled: data.trialEnabled ?? false,
|
|
3879
|
+
trialDays: data.trialDays ?? 30,
|
|
3880
|
+
priceTag: data.priceTag ?? null,
|
|
3881
|
+
ctaLabel: data.ctaLabel ?? null,
|
|
3882
|
+
priority: data.priority ?? 0,
|
|
3883
|
+
highlight: data.highlight ?? false
|
|
3884
|
+
}
|
|
3885
|
+
});
|
|
3886
|
+
return toRow(row);
|
|
3887
|
+
}
|
|
3888
|
+
async update(id, data) {
|
|
3889
|
+
const row = await this.db.marketingProjection.update({
|
|
3890
|
+
where: {
|
|
3891
|
+
id
|
|
3892
|
+
},
|
|
3893
|
+
data: {
|
|
3894
|
+
...data.displayLabel !== void 0 ? {
|
|
3895
|
+
displayLabel: data.displayLabel
|
|
3896
|
+
} : {},
|
|
3897
|
+
...data.description !== void 0 ? {
|
|
3898
|
+
description: data.description
|
|
3899
|
+
} : {},
|
|
3900
|
+
...data.visible !== void 0 ? {
|
|
3901
|
+
visible: data.visible
|
|
3902
|
+
} : {},
|
|
3903
|
+
...data.badge !== void 0 ? {
|
|
3904
|
+
badge: data.badge
|
|
3905
|
+
} : {},
|
|
3906
|
+
...data.topFeatures !== void 0 ? {
|
|
3907
|
+
topFeatures: data.topFeatures
|
|
3908
|
+
} : {},
|
|
3909
|
+
...data.trialEnabled !== void 0 ? {
|
|
3910
|
+
trialEnabled: data.trialEnabled
|
|
3911
|
+
} : {},
|
|
3912
|
+
...data.trialDays !== void 0 ? {
|
|
3913
|
+
trialDays: data.trialDays
|
|
3914
|
+
} : {},
|
|
3915
|
+
...data.priceTag !== void 0 ? {
|
|
3916
|
+
priceTag: data.priceTag
|
|
3917
|
+
} : {},
|
|
3918
|
+
...data.ctaLabel !== void 0 ? {
|
|
3919
|
+
ctaLabel: data.ctaLabel
|
|
3920
|
+
} : {},
|
|
3921
|
+
...data.priority !== void 0 ? {
|
|
3922
|
+
priority: data.priority
|
|
3923
|
+
} : {},
|
|
3924
|
+
...data.highlight !== void 0 ? {
|
|
3925
|
+
highlight: data.highlight
|
|
3926
|
+
} : {}
|
|
3927
|
+
}
|
|
3928
|
+
});
|
|
3929
|
+
return toRow(row);
|
|
3930
|
+
}
|
|
3931
|
+
async delete(id) {
|
|
3932
|
+
await this.db.marketingProjection.delete({
|
|
3933
|
+
where: {
|
|
3934
|
+
id
|
|
3935
|
+
}
|
|
3936
|
+
});
|
|
3937
|
+
}
|
|
3938
|
+
};
|
|
3939
|
+
PrismaMarketingProjectionRepository = _ts_decorate22([
|
|
3940
|
+
Injectable22(),
|
|
3941
|
+
_ts_param20(0, Inject20(PRISMA_CLIENT_TOKEN)),
|
|
3942
|
+
_ts_metadata20("design:type", Function),
|
|
3943
|
+
_ts_metadata20("design:paramtypes", [
|
|
3944
|
+
typeof MarketingProjectionRepositoryClient === "undefined" ? Object : MarketingProjectionRepositoryClient
|
|
3945
|
+
])
|
|
3946
|
+
], PrismaMarketingProjectionRepository);
|
|
3947
|
+
function toTopFeatures(value) {
|
|
3948
|
+
return Array.isArray(value) ? value : [];
|
|
3949
|
+
}
|
|
3950
|
+
__name(toTopFeatures, "toTopFeatures");
|
|
3951
|
+
function toRow(row) {
|
|
3952
|
+
return {
|
|
3953
|
+
id: row.id,
|
|
3954
|
+
projectKey: row.projectKey,
|
|
3955
|
+
targetType: row.targetType,
|
|
3956
|
+
targetVersionId: row.targetVersionId,
|
|
3957
|
+
locale: row.locale,
|
|
3958
|
+
displayLabel: row.displayLabel,
|
|
3959
|
+
description: row.description,
|
|
3960
|
+
visible: row.visible,
|
|
3961
|
+
badge: row.badge,
|
|
3962
|
+
topFeatures: toTopFeatures(row.topFeatures),
|
|
3963
|
+
trialEnabled: row.trialEnabled,
|
|
3964
|
+
trialDays: row.trialDays,
|
|
3965
|
+
priceTag: row.priceTag,
|
|
3966
|
+
ctaLabel: row.ctaLabel,
|
|
3967
|
+
priority: row.priority,
|
|
3968
|
+
highlight: row.highlight,
|
|
3969
|
+
createdAt: row.createdAt.toISOString(),
|
|
3970
|
+
updatedAt: row.updatedAt.toISOString()
|
|
3971
|
+
};
|
|
3972
|
+
}
|
|
3973
|
+
__name(toRow, "toRow");
|
|
3974
|
+
|
|
3975
|
+
// src/prisma-marketing-settings.repository.ts
|
|
3976
|
+
import { Inject as Inject21, Injectable as Injectable23 } from "@nestjs/common";
|
|
3977
|
+
function _ts_decorate23(decorators, target, key, desc) {
|
|
3978
|
+
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
3979
|
+
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
3980
|
+
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
3981
|
+
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
3982
|
+
}
|
|
3983
|
+
__name(_ts_decorate23, "_ts_decorate");
|
|
3984
|
+
function _ts_metadata21(k, v) {
|
|
3985
|
+
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
|
|
3986
|
+
}
|
|
3987
|
+
__name(_ts_metadata21, "_ts_metadata");
|
|
3988
|
+
function _ts_param21(paramIndex, decorator) {
|
|
3989
|
+
return function(target, key) {
|
|
3990
|
+
decorator(target, key, paramIndex);
|
|
3991
|
+
};
|
|
3992
|
+
}
|
|
3993
|
+
__name(_ts_param21, "_ts_param");
|
|
3994
|
+
var PrismaMarketingSettingsRepository = class {
|
|
3995
|
+
static {
|
|
3996
|
+
__name(this, "PrismaMarketingSettingsRepository");
|
|
3997
|
+
}
|
|
3998
|
+
prisma;
|
|
3999
|
+
constructor(prisma) {
|
|
4000
|
+
this.prisma = prisma;
|
|
4001
|
+
}
|
|
4002
|
+
get db() {
|
|
4003
|
+
return this.prisma;
|
|
4004
|
+
}
|
|
4005
|
+
async get(projectKey) {
|
|
4006
|
+
const row = await this.db.marketingSettings.findUnique({
|
|
4007
|
+
where: {
|
|
4008
|
+
projectKey
|
|
4009
|
+
}
|
|
4010
|
+
});
|
|
4011
|
+
return row ? toRow2(row) : null;
|
|
4012
|
+
}
|
|
4013
|
+
async upsert(projectKey, data) {
|
|
4014
|
+
const row = await this.db.marketingSettings.upsert({
|
|
4015
|
+
where: {
|
|
4016
|
+
projectKey
|
|
4017
|
+
},
|
|
4018
|
+
create: {
|
|
4019
|
+
projectKey,
|
|
4020
|
+
activeLocales: data.activeLocales
|
|
4021
|
+
},
|
|
4022
|
+
update: {
|
|
4023
|
+
activeLocales: data.activeLocales
|
|
4024
|
+
}
|
|
4025
|
+
});
|
|
4026
|
+
return toRow2(row);
|
|
4027
|
+
}
|
|
4028
|
+
};
|
|
4029
|
+
PrismaMarketingSettingsRepository = _ts_decorate23([
|
|
4030
|
+
Injectable23(),
|
|
4031
|
+
_ts_param21(0, Inject21(PRISMA_CLIENT_TOKEN)),
|
|
4032
|
+
_ts_metadata21("design:type", Function),
|
|
4033
|
+
_ts_metadata21("design:paramtypes", [
|
|
4034
|
+
typeof MarketingSettingsRepositoryClient === "undefined" ? Object : MarketingSettingsRepositoryClient
|
|
4035
|
+
])
|
|
4036
|
+
], PrismaMarketingSettingsRepository);
|
|
4037
|
+
function toRow2(row) {
|
|
4038
|
+
return {
|
|
4039
|
+
projectKey: row.projectKey,
|
|
4040
|
+
activeLocales: toStringArray(row.activeLocales),
|
|
4041
|
+
updatedAt: row.updatedAt.toISOString()
|
|
4042
|
+
};
|
|
4043
|
+
}
|
|
4044
|
+
__name(toRow2, "toRow");
|
|
4045
|
+
|
|
4046
|
+
// src/prisma-promotion.repository.ts
|
|
4047
|
+
import { Inject as Inject22, Injectable as Injectable24 } from "@nestjs/common";
|
|
4048
|
+
function _ts_decorate24(decorators, target, key, desc) {
|
|
4049
|
+
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
4050
|
+
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
4051
|
+
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
4052
|
+
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
4053
|
+
}
|
|
4054
|
+
__name(_ts_decorate24, "_ts_decorate");
|
|
4055
|
+
function _ts_metadata22(k, v) {
|
|
4056
|
+
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
|
|
4057
|
+
}
|
|
4058
|
+
__name(_ts_metadata22, "_ts_metadata");
|
|
4059
|
+
function _ts_param22(paramIndex, decorator) {
|
|
4060
|
+
return function(target, key) {
|
|
4061
|
+
decorator(target, key, paramIndex);
|
|
4062
|
+
};
|
|
4063
|
+
}
|
|
4064
|
+
__name(_ts_param22, "_ts_param");
|
|
4065
|
+
var PrismaPromotionRepository = class {
|
|
4066
|
+
static {
|
|
4067
|
+
__name(this, "PrismaPromotionRepository");
|
|
4068
|
+
}
|
|
4069
|
+
prisma;
|
|
4070
|
+
constructor(prisma) {
|
|
4071
|
+
this.prisma = prisma;
|
|
4072
|
+
}
|
|
4073
|
+
get db() {
|
|
4074
|
+
return this.prisma;
|
|
4075
|
+
}
|
|
4076
|
+
async list(filter) {
|
|
4077
|
+
const rows = await this.db.promotion.findMany({
|
|
4078
|
+
where: {
|
|
4079
|
+
projectKey: filter.projectKey
|
|
4080
|
+
},
|
|
4081
|
+
orderBy: [
|
|
4082
|
+
{
|
|
4083
|
+
validFrom: "desc"
|
|
4084
|
+
}
|
|
4085
|
+
]
|
|
4086
|
+
});
|
|
4087
|
+
return rows.map(toRow3);
|
|
4088
|
+
}
|
|
4089
|
+
async findById(id) {
|
|
4090
|
+
const row = await this.db.promotion.findUnique({
|
|
4091
|
+
where: {
|
|
4092
|
+
id
|
|
4093
|
+
}
|
|
4094
|
+
});
|
|
4095
|
+
return row ? toRow3(row) : null;
|
|
4096
|
+
}
|
|
4097
|
+
async create(data) {
|
|
4098
|
+
const row = await this.db.promotion.create({
|
|
4099
|
+
data: {
|
|
4100
|
+
projectKey: data.projectKey,
|
|
4101
|
+
internalLabel: data.internalLabel,
|
|
4102
|
+
type: data.type,
|
|
4103
|
+
value: data.value,
|
|
4104
|
+
targetType: data.targetType ?? "PLAN",
|
|
4105
|
+
appliesTo: data.appliesTo ?? [],
|
|
4106
|
+
billingCycle: data.billingCycle ?? "both",
|
|
4107
|
+
validFrom: new Date(data.validFrom),
|
|
4108
|
+
validTo: new Date(data.validTo),
|
|
4109
|
+
priority: data.priority ?? 0,
|
|
4110
|
+
requiresCoupon: data.requiresCoupon ?? false,
|
|
4111
|
+
codes: data.codes ?? [],
|
|
4112
|
+
color: data.color ?? "#2563eb",
|
|
4113
|
+
i18n: data.i18n ?? {},
|
|
4114
|
+
// Null/undefined restriction is left off so the nullable column
|
|
4115
|
+
// stays SQL NULL (= all locales).
|
|
4116
|
+
...Array.isArray(data.onlyLocales) ? {
|
|
4117
|
+
onlyLocales: data.onlyLocales
|
|
4118
|
+
} : {}
|
|
4119
|
+
}
|
|
4120
|
+
});
|
|
4121
|
+
return toRow3(row);
|
|
4122
|
+
}
|
|
4123
|
+
async update(id, data) {
|
|
4124
|
+
if (data.onlyLocales === null) {
|
|
4125
|
+
const executeRaw = this.prisma.$executeRaw.bind(this.prisma);
|
|
4126
|
+
await executeRaw`
|
|
4127
|
+
UPDATE promotions SET "onlyLocales" = NULL, "updatedAt" = NOW() WHERE id = ${id}`;
|
|
4128
|
+
}
|
|
4129
|
+
const row = await this.db.promotion.update({
|
|
4130
|
+
where: {
|
|
4131
|
+
id
|
|
4132
|
+
},
|
|
4133
|
+
data: {
|
|
4134
|
+
...data.internalLabel !== void 0 ? {
|
|
4135
|
+
internalLabel: data.internalLabel
|
|
4136
|
+
} : {},
|
|
4137
|
+
...data.type !== void 0 ? {
|
|
4138
|
+
type: data.type
|
|
4139
|
+
} : {},
|
|
4140
|
+
...data.value !== void 0 ? {
|
|
4141
|
+
value: data.value
|
|
4142
|
+
} : {},
|
|
4143
|
+
...data.appliesTo !== void 0 ? {
|
|
4144
|
+
appliesTo: data.appliesTo
|
|
4145
|
+
} : {},
|
|
4146
|
+
...data.targetType !== void 0 ? {
|
|
4147
|
+
targetType: data.targetType
|
|
4148
|
+
} : {},
|
|
4149
|
+
...data.billingCycle !== void 0 ? {
|
|
4150
|
+
billingCycle: data.billingCycle
|
|
4151
|
+
} : {},
|
|
4152
|
+
...data.validFrom !== void 0 ? {
|
|
4153
|
+
validFrom: new Date(data.validFrom)
|
|
4154
|
+
} : {},
|
|
4155
|
+
...data.validTo !== void 0 ? {
|
|
4156
|
+
validTo: new Date(data.validTo)
|
|
4157
|
+
} : {},
|
|
4158
|
+
...data.priority !== void 0 ? {
|
|
4159
|
+
priority: data.priority
|
|
4160
|
+
} : {},
|
|
4161
|
+
...data.requiresCoupon !== void 0 ? {
|
|
4162
|
+
requiresCoupon: data.requiresCoupon
|
|
4163
|
+
} : {},
|
|
4164
|
+
...data.codes !== void 0 ? {
|
|
4165
|
+
codes: data.codes
|
|
4166
|
+
} : {},
|
|
4167
|
+
...data.color !== void 0 ? {
|
|
4168
|
+
color: data.color
|
|
4169
|
+
} : {},
|
|
4170
|
+
...data.i18n !== void 0 ? {
|
|
4171
|
+
i18n: data.i18n
|
|
4172
|
+
} : {},
|
|
4173
|
+
...Array.isArray(data.onlyLocales) ? {
|
|
4174
|
+
onlyLocales: data.onlyLocales
|
|
4175
|
+
} : {}
|
|
4176
|
+
}
|
|
4177
|
+
});
|
|
4178
|
+
return toRow3(row);
|
|
4179
|
+
}
|
|
4180
|
+
async delete(id) {
|
|
4181
|
+
await this.db.promotion.delete({
|
|
4182
|
+
where: {
|
|
4183
|
+
id
|
|
4184
|
+
}
|
|
4185
|
+
});
|
|
4186
|
+
}
|
|
4187
|
+
};
|
|
4188
|
+
PrismaPromotionRepository = _ts_decorate24([
|
|
4189
|
+
Injectable24(),
|
|
4190
|
+
_ts_param22(0, Inject22(PRISMA_CLIENT_TOKEN)),
|
|
4191
|
+
_ts_metadata22("design:type", Function),
|
|
4192
|
+
_ts_metadata22("design:paramtypes", [
|
|
4193
|
+
typeof PromotionRepositoryClient === "undefined" ? Object : PromotionRepositoryClient
|
|
4194
|
+
])
|
|
4195
|
+
], PrismaPromotionRepository);
|
|
4196
|
+
function toPromotionValue(value) {
|
|
4197
|
+
if (typeof value === "number") return value;
|
|
4198
|
+
if (value !== null && typeof value === "object" && !Array.isArray(value)) {
|
|
4199
|
+
const obj = value;
|
|
4200
|
+
return {
|
|
4201
|
+
price: Number(obj.price),
|
|
4202
|
+
months: Number(obj.months)
|
|
4203
|
+
};
|
|
4204
|
+
}
|
|
4205
|
+
throw new Error(`Promotion.value has an unexpected shape: ${JSON.stringify(value)}`);
|
|
4206
|
+
}
|
|
4207
|
+
__name(toPromotionValue, "toPromotionValue");
|
|
4208
|
+
function toNullableStringArray(value) {
|
|
4209
|
+
return Array.isArray(value) ? value : null;
|
|
4210
|
+
}
|
|
4211
|
+
__name(toNullableStringArray, "toNullableStringArray");
|
|
4212
|
+
function toPromotionI18n(value) {
|
|
4213
|
+
if (value !== null && typeof value === "object" && !Array.isArray(value)) {
|
|
4214
|
+
return value;
|
|
4215
|
+
}
|
|
4216
|
+
return {};
|
|
4217
|
+
}
|
|
4218
|
+
__name(toPromotionI18n, "toPromotionI18n");
|
|
4219
|
+
function toRow3(row) {
|
|
4220
|
+
return {
|
|
4221
|
+
id: row.id,
|
|
4222
|
+
projectKey: row.projectKey,
|
|
4223
|
+
internalLabel: row.internalLabel,
|
|
4224
|
+
type: row.type,
|
|
4225
|
+
value: toPromotionValue(row.value),
|
|
4226
|
+
appliesTo: toStringArray(row.appliesTo),
|
|
4227
|
+
targetType: row.targetType,
|
|
4228
|
+
billingCycle: row.billingCycle,
|
|
4229
|
+
validFrom: row.validFrom.toISOString().slice(0, 10),
|
|
4230
|
+
validTo: row.validTo.toISOString().slice(0, 10),
|
|
4231
|
+
priority: row.priority,
|
|
4232
|
+
onlyLocales: toNullableStringArray(row.onlyLocales),
|
|
4233
|
+
requiresCoupon: row.requiresCoupon,
|
|
4234
|
+
codes: toStringArray(row.codes),
|
|
4235
|
+
color: row.color,
|
|
4236
|
+
i18n: toPromotionI18n(row.i18n),
|
|
4237
|
+
createdAt: row.createdAt.toISOString(),
|
|
4238
|
+
updatedAt: row.updatedAt.toISOString()
|
|
4239
|
+
};
|
|
4240
|
+
}
|
|
4241
|
+
__name(toRow3, "toRow");
|
|
4242
|
+
|
|
4243
|
+
// src/prisma-subscription-contract.repository.ts
|
|
4244
|
+
import { Inject as Inject23, Injectable as Injectable25 } from "@nestjs/common";
|
|
4245
|
+
function _ts_decorate25(decorators, target, key, desc) {
|
|
4246
|
+
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
4247
|
+
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
4248
|
+
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
4249
|
+
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
4250
|
+
}
|
|
4251
|
+
__name(_ts_decorate25, "_ts_decorate");
|
|
4252
|
+
function _ts_metadata23(k, v) {
|
|
4253
|
+
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
|
|
4254
|
+
}
|
|
4255
|
+
__name(_ts_metadata23, "_ts_metadata");
|
|
4256
|
+
function _ts_param23(paramIndex, decorator) {
|
|
4257
|
+
return function(target, key) {
|
|
4258
|
+
decorator(target, key, paramIndex);
|
|
4259
|
+
};
|
|
4260
|
+
}
|
|
4261
|
+
__name(_ts_param23, "_ts_param");
|
|
4262
|
+
var ACTIVE_CONTRACT_STATUSES = [
|
|
4263
|
+
"active",
|
|
4264
|
+
"scheduled"
|
|
4265
|
+
];
|
|
4266
|
+
var PrismaSubscriptionContractRepository = class {
|
|
4267
|
+
static {
|
|
4268
|
+
__name(this, "PrismaSubscriptionContractRepository");
|
|
4269
|
+
}
|
|
4270
|
+
prisma;
|
|
4271
|
+
constructor(prisma) {
|
|
4272
|
+
this.prisma = prisma;
|
|
4273
|
+
}
|
|
4274
|
+
get db() {
|
|
4275
|
+
return this.prisma;
|
|
4276
|
+
}
|
|
4277
|
+
async list(filter) {
|
|
4278
|
+
const rows = await this.db.subscriptionContract.findMany({
|
|
4279
|
+
where: {
|
|
4280
|
+
...filter.projectKey ? {
|
|
4281
|
+
projectKey: filter.projectKey
|
|
4282
|
+
} : {},
|
|
4283
|
+
...filter.tenantId ? {
|
|
4284
|
+
tenantId: filter.tenantId
|
|
4285
|
+
} : {},
|
|
4286
|
+
...filter.status ? {
|
|
4287
|
+
status: filter.status
|
|
4288
|
+
} : {},
|
|
4289
|
+
...filter.asOf ? {
|
|
4290
|
+
effectiveFrom: {
|
|
4291
|
+
lte: filter.asOf
|
|
4292
|
+
},
|
|
4293
|
+
OR: [
|
|
4294
|
+
{
|
|
4295
|
+
effectiveUntil: null
|
|
4296
|
+
},
|
|
4297
|
+
{
|
|
4298
|
+
effectiveUntil: {
|
|
4299
|
+
gt: filter.asOf
|
|
4300
|
+
}
|
|
4301
|
+
}
|
|
4302
|
+
]
|
|
4303
|
+
} : {}
|
|
4304
|
+
},
|
|
4305
|
+
include: {
|
|
4306
|
+
lineItems: true
|
|
4307
|
+
},
|
|
4308
|
+
orderBy: [
|
|
4309
|
+
{
|
|
4310
|
+
effectiveFrom: "desc"
|
|
4311
|
+
},
|
|
4312
|
+
{
|
|
4313
|
+
createdAt: "desc"
|
|
4314
|
+
}
|
|
4315
|
+
]
|
|
4316
|
+
});
|
|
4317
|
+
return rows.map(toRecord4);
|
|
4318
|
+
}
|
|
4319
|
+
async findById(contractId) {
|
|
4320
|
+
const row = await this.db.subscriptionContract.findUnique({
|
|
4321
|
+
where: {
|
|
4322
|
+
id: contractId
|
|
4323
|
+
},
|
|
4324
|
+
include: {
|
|
4325
|
+
lineItems: true
|
|
4326
|
+
}
|
|
4327
|
+
});
|
|
4328
|
+
return row ? toRecord4(row) : null;
|
|
4329
|
+
}
|
|
4330
|
+
async findActiveByTenantId(tenantId, asOf = /* @__PURE__ */ new Date()) {
|
|
4331
|
+
const row = await this.db.subscriptionContract.findFirst({
|
|
4332
|
+
where: {
|
|
4333
|
+
tenantId,
|
|
4334
|
+
status: {
|
|
4335
|
+
in: ACTIVE_CONTRACT_STATUSES
|
|
4336
|
+
},
|
|
4337
|
+
effectiveFrom: {
|
|
4338
|
+
lte: asOf
|
|
4339
|
+
},
|
|
4340
|
+
OR: [
|
|
4341
|
+
{
|
|
4342
|
+
effectiveUntil: null
|
|
4343
|
+
},
|
|
4344
|
+
{
|
|
4345
|
+
effectiveUntil: {
|
|
4346
|
+
gt: asOf
|
|
4347
|
+
}
|
|
4348
|
+
}
|
|
4349
|
+
]
|
|
4350
|
+
},
|
|
4351
|
+
include: {
|
|
4352
|
+
lineItems: true
|
|
4353
|
+
},
|
|
4354
|
+
orderBy: [
|
|
4355
|
+
{
|
|
4356
|
+
effectiveFrom: "desc"
|
|
4357
|
+
},
|
|
4358
|
+
{
|
|
4359
|
+
createdAt: "desc"
|
|
4360
|
+
}
|
|
4361
|
+
]
|
|
4362
|
+
});
|
|
4363
|
+
return row ? toRecord4(row) : null;
|
|
4364
|
+
}
|
|
4365
|
+
async create(data) {
|
|
4366
|
+
const row = await this.db.subscriptionContract.create({
|
|
4367
|
+
data: {
|
|
4368
|
+
projectKey: data.projectKey,
|
|
4369
|
+
tenantId: data.tenantId,
|
|
4370
|
+
status: data.status ?? "active",
|
|
4371
|
+
effectiveFrom: data.effectiveFrom,
|
|
4372
|
+
effectiveUntil: data.effectiveUntil ?? null,
|
|
4373
|
+
originalOfferId: data.originalOfferId ?? null,
|
|
4374
|
+
originalPlanVersionId: data.originalPlanVersionId ?? null,
|
|
4375
|
+
originalBundleVersionIds: data.originalBundleVersionIds ?? [],
|
|
4376
|
+
priceSnapshot: data.priceSnapshot,
|
|
4377
|
+
promotionSnapshots: data.promotionSnapshots ?? [],
|
|
4378
|
+
promoCodeSnapshots: data.promoCodeSnapshots ?? [],
|
|
4379
|
+
// Nullable JSON columns are omitted when absent so they stay SQL
|
|
4380
|
+
// NULL (the DbNull sentinel is not available in this package).
|
|
4381
|
+
...data.entitlementSnapshot != null ? {
|
|
4382
|
+
entitlementSnapshot: data.entitlementSnapshot
|
|
4383
|
+
} : {},
|
|
4384
|
+
...data.termsSnapshot != null ? {
|
|
4385
|
+
termsSnapshot: data.termsSnapshot
|
|
4386
|
+
} : {},
|
|
4387
|
+
lineItems: {
|
|
4388
|
+
create: data.lineItems.map(toLineItemCreate)
|
|
4389
|
+
}
|
|
4390
|
+
},
|
|
4391
|
+
include: {
|
|
4392
|
+
lineItems: true
|
|
4393
|
+
}
|
|
4394
|
+
});
|
|
4395
|
+
return toRecord4(row);
|
|
4396
|
+
}
|
|
4397
|
+
async terminate(contractId, data) {
|
|
4398
|
+
const row = await this.db.subscriptionContract.update({
|
|
4399
|
+
where: {
|
|
4400
|
+
id: contractId
|
|
4401
|
+
},
|
|
4402
|
+
data: {
|
|
4403
|
+
effectiveUntil: data.effectiveUntil,
|
|
4404
|
+
status: data.status
|
|
4405
|
+
},
|
|
4406
|
+
include: {
|
|
4407
|
+
lineItems: true
|
|
4408
|
+
}
|
|
4409
|
+
});
|
|
4410
|
+
return toRecord4(row);
|
|
4411
|
+
}
|
|
4412
|
+
};
|
|
4413
|
+
PrismaSubscriptionContractRepository = _ts_decorate25([
|
|
4414
|
+
Injectable25(),
|
|
4415
|
+
_ts_param23(0, Inject23(PRISMA_CLIENT_TOKEN)),
|
|
4416
|
+
_ts_metadata23("design:type", Function),
|
|
4417
|
+
_ts_metadata23("design:paramtypes", [
|
|
4418
|
+
typeof PrismaLike === "undefined" ? Object : PrismaLike
|
|
4419
|
+
])
|
|
4420
|
+
], PrismaSubscriptionContractRepository);
|
|
4421
|
+
function toLineItemCreate(item) {
|
|
4422
|
+
return {
|
|
4423
|
+
kind: item.kind,
|
|
4424
|
+
sourceKey: item.sourceKey,
|
|
4425
|
+
sourceVersionId: item.sourceVersionId ?? null,
|
|
4426
|
+
titleSnapshot: item.titleSnapshot,
|
|
4427
|
+
descriptionSnapshot: item.descriptionSnapshot ?? null,
|
|
4428
|
+
quantity: item.quantity,
|
|
4429
|
+
unit: item.unit ?? null,
|
|
4430
|
+
priceNet: item.priceNet,
|
|
4431
|
+
priceGross: item.priceGross,
|
|
4432
|
+
billingCycle: item.billingCycle,
|
|
4433
|
+
minimumTermUntil: item.minimumTermUntil ?? null,
|
|
4434
|
+
featuresSnapshot: item.featuresSnapshot,
|
|
4435
|
+
quotaEffectsSnapshot: item.quotaEffectsSnapshot,
|
|
4436
|
+
...item.metadata != null ? {
|
|
4437
|
+
metadata: item.metadata
|
|
4438
|
+
} : {}
|
|
4439
|
+
};
|
|
4440
|
+
}
|
|
4441
|
+
__name(toLineItemCreate, "toLineItemCreate");
|
|
4442
|
+
function isPlainObject2(value) {
|
|
4443
|
+
return value !== null && typeof value === "object" && !Array.isArray(value);
|
|
4444
|
+
}
|
|
4445
|
+
__name(isPlainObject2, "isPlainObject");
|
|
4446
|
+
function toUnknownArray(value) {
|
|
4447
|
+
return Array.isArray(value) ? value : [];
|
|
4448
|
+
}
|
|
4449
|
+
__name(toUnknownArray, "toUnknownArray");
|
|
4450
|
+
function toRecordOrNull(value) {
|
|
4451
|
+
return isPlainObject2(value) ? value : null;
|
|
4452
|
+
}
|
|
4453
|
+
__name(toRecordOrNull, "toRecordOrNull");
|
|
4454
|
+
function toLineItem(row) {
|
|
4455
|
+
return {
|
|
4456
|
+
id: row.id,
|
|
4457
|
+
contractId: row.contractId,
|
|
4458
|
+
kind: row.kind,
|
|
4459
|
+
sourceKey: row.sourceKey,
|
|
4460
|
+
sourceVersionId: row.sourceVersionId,
|
|
4461
|
+
titleSnapshot: row.titleSnapshot,
|
|
4462
|
+
descriptionSnapshot: row.descriptionSnapshot,
|
|
4463
|
+
quantity: row.quantity,
|
|
4464
|
+
unit: row.unit,
|
|
4465
|
+
priceNet: Number(row.priceNet),
|
|
4466
|
+
priceGross: Number(row.priceGross),
|
|
4467
|
+
billingCycle: row.billingCycle,
|
|
4468
|
+
minimumTermUntil: row.minimumTermUntil,
|
|
4469
|
+
featuresSnapshot: toStringArray(row.featuresSnapshot),
|
|
4470
|
+
quotaEffectsSnapshot: toQuotaMap(row.quotaEffectsSnapshot),
|
|
4471
|
+
metadata: toRecordOrNull(row.metadata),
|
|
4472
|
+
createdAt: row.createdAt
|
|
4473
|
+
};
|
|
4474
|
+
}
|
|
4475
|
+
__name(toLineItem, "toLineItem");
|
|
4476
|
+
function toRecord4(row) {
|
|
4477
|
+
return {
|
|
4478
|
+
id: row.id,
|
|
4479
|
+
projectKey: row.projectKey,
|
|
4480
|
+
tenantId: row.tenantId,
|
|
4481
|
+
status: row.status,
|
|
4482
|
+
effectiveFrom: row.effectiveFrom,
|
|
4483
|
+
effectiveUntil: row.effectiveUntil,
|
|
4484
|
+
originalOfferId: row.originalOfferId,
|
|
4485
|
+
originalPlanVersionId: row.originalPlanVersionId,
|
|
4486
|
+
originalBundleVersionIds: toStringArray(row.originalBundleVersionIds),
|
|
4487
|
+
entitlementSnapshot: isPlainObject2(row.entitlementSnapshot) ? row.entitlementSnapshot : null,
|
|
4488
|
+
priceSnapshot: row.priceSnapshot,
|
|
4489
|
+
promotionSnapshots: toUnknownArray(row.promotionSnapshots),
|
|
4490
|
+
promoCodeSnapshots: toUnknownArray(row.promoCodeSnapshots),
|
|
4491
|
+
termsSnapshot: toRecordOrNull(row.termsSnapshot),
|
|
4492
|
+
lineItems: row.lineItems.map(toLineItem),
|
|
4493
|
+
createdAt: row.createdAt,
|
|
4494
|
+
updatedAt: row.updatedAt
|
|
4495
|
+
};
|
|
4496
|
+
}
|
|
4497
|
+
__name(toRecord4, "toRecord");
|
|
1420
4498
|
export {
|
|
1421
4499
|
AsyncLocalRlsBypassAdapter,
|
|
1422
4500
|
PASSWORD_HASHER_TOKEN,
|
|
4501
|
+
PRISMA_BUNDLE_REPOSITORY_OPTIONS,
|
|
1423
4502
|
PRISMA_CLIENT_TOKEN,
|
|
4503
|
+
PRISMA_SCHEMA_OPTIONS_TOKEN,
|
|
1424
4504
|
PrismaAuditAdapter,
|
|
1425
4505
|
PrismaAuditQueryAdapter,
|
|
1426
4506
|
PrismaAuditStatsAdapter,
|
|
4507
|
+
PrismaBundleRepository,
|
|
4508
|
+
PrismaCatalogEntryRepository,
|
|
4509
|
+
PrismaMarketingProjectionRepository,
|
|
4510
|
+
PrismaMarketingSettingsRepository,
|
|
1427
4511
|
PrismaMfaAdapter,
|
|
1428
4512
|
PrismaPlanCatalogImportSink,
|
|
1429
4513
|
PrismaPlanCatalogReadSink,
|
|
4514
|
+
PrismaPlanRepository,
|
|
1430
4515
|
PrismaPlanVersionRepository,
|
|
1431
4516
|
PrismaPromoCodeRedemptionRepository,
|
|
1432
4517
|
PrismaPromoCodeRepository,
|
|
1433
4518
|
PrismaPromoCodeValidationLogRepository,
|
|
1434
4519
|
PrismaPromoSubscriptionLookup,
|
|
4520
|
+
PrismaPromotionRepository,
|
|
4521
|
+
PrismaSubscriptionBundleRepository,
|
|
4522
|
+
PrismaSubscriptionContractRepository,
|
|
1435
4523
|
PrismaSubscriptionRepository,
|
|
1436
4524
|
PrismaSuperAdminBootstrapAdapter,
|
|
4525
|
+
PrismaTenantSubscriptionWriteAdapter,
|
|
1437
4526
|
PrismaTransactionRunner,
|
|
1438
4527
|
ZeroPromoRevenueDeductionAggregator,
|
|
1439
4528
|
buildActorTag,
|
|
1440
|
-
|
|
4529
|
+
createPrismaPlanBindingResolver,
|
|
4530
|
+
getPrismaDelegate,
|
|
4531
|
+
prismaPersistence,
|
|
4532
|
+
resolvePrismaSchemaOptions
|
|
1441
4533
|
};
|