@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/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 PrismaLike === "undefined" ? Object : PrismaLike
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 PrismaLike === "undefined" ? Object : PrismaLike
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 PrismaLike === "undefined" ? Object : PrismaLike
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 PrismaLike === "undefined" ? Object : PrismaLike
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
- constructor(prisma) {
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
- const existing = await this.prisma.plan.findFirst({
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 this.prisma.plan.create({
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 existing = await this.prisma.planVersion.findFirst({
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: input.planKey,
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 this.prisma.planVersion.updateMany({
513
+ await planVersion.updateMany({
363
514
  where: {
364
- planId: input.planKey,
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 this.prisma.planVersion.create({
529
+ await planVersion.create({
379
530
  data: {
380
- planId: input.planKey,
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 existing = await this.prisma.featureCatalogEntry.findFirst({
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 this.prisma.featureCatalogEntry.create({
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 PrismaLike === "undefined" ? Object : PrismaLike
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
- constructor(prisma) {
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
- const plans = await this.prisma.plan.findMany({
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 planKeys = plans.map((plan) => plan.planKey);
488
- const livePlanVersions = planKeys.length === 0 ? [] : await this.prisma.planVersion.findMany({
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: planKeys
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 this.prisma.featureCatalogEntry.findMany({
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(toPlanVersionRow),
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 PrismaLike === "undefined" ? Object : PrismaLike
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
- return {
728
+ function toPlanVersionRow(row, planKey, fields) {
729
+ const mapped = {
540
730
  id: row.id,
541
- planId: row.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
- constructor(prisma) {
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 = resolveClient(this.prisma, tx);
621
- const row = await db.planVersion.findFirst({
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 PrismaLike === "undefined" ? Object : PrismaLike
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
- constructor(prisma) {
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.prisma, tenantId);
1379
+ return this.loadByTenantId(this.db(), tenantId);
1119
1380
  }
1120
1381
  async findByTenantIdLocked(tenantId, tx) {
1121
- const db = resolveClient(this.prisma, tx);
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.prisma.subscription.count({
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(_projectKey) {
1140
- const rows = await this.prisma.subscription.findMany({
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 row of rows) {
1149
- counts[row.plan] = (counts[row.plan] ?? 0) + 1;
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.subscription.findUnique({
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
- if (!row.planVersionId) {
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
- plan: row.plan,
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: planVersion.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 PrismaLike === "undefined" ? Object : PrismaLike
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
- return this.prisma.$transaction((tx) => fn(tx));
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 PrismaLike === "undefined" ? Object : PrismaLike
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
- prismaPersistence
4529
+ createPrismaPlanBindingResolver,
4530
+ getPrismaDelegate,
4531
+ prismaPersistence,
4532
+ resolvePrismaSchemaOptions
1441
4533
  };