@saasicat/adapter-prisma 0.5.0 → 0.6.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.cjs CHANGED
@@ -27,16 +27,25 @@ __export(index_exports, {
27
27
  PrismaAuditAdapter: () => PrismaAuditAdapter,
28
28
  PrismaAuditQueryAdapter: () => PrismaAuditQueryAdapter,
29
29
  PrismaAuditStatsAdapter: () => PrismaAuditStatsAdapter,
30
+ PrismaBundleRepository: () => PrismaBundleRepository,
31
+ PrismaCatalogEntryRepository: () => PrismaCatalogEntryRepository,
32
+ PrismaMarketingProjectionRepository: () => PrismaMarketingProjectionRepository,
33
+ PrismaMarketingSettingsRepository: () => PrismaMarketingSettingsRepository,
30
34
  PrismaMfaAdapter: () => PrismaMfaAdapter,
31
35
  PrismaPlanCatalogImportSink: () => PrismaPlanCatalogImportSink,
32
36
  PrismaPlanCatalogReadSink: () => PrismaPlanCatalogReadSink,
37
+ PrismaPlanRepository: () => PrismaPlanRepository,
33
38
  PrismaPlanVersionRepository: () => PrismaPlanVersionRepository,
34
39
  PrismaPromoCodeRedemptionRepository: () => PrismaPromoCodeRedemptionRepository,
35
40
  PrismaPromoCodeRepository: () => PrismaPromoCodeRepository,
36
41
  PrismaPromoCodeValidationLogRepository: () => PrismaPromoCodeValidationLogRepository,
37
42
  PrismaPromoSubscriptionLookup: () => PrismaPromoSubscriptionLookup,
43
+ PrismaPromotionRepository: () => PrismaPromotionRepository,
44
+ PrismaSubscriptionBundleRepository: () => PrismaSubscriptionBundleRepository,
45
+ PrismaSubscriptionContractRepository: () => PrismaSubscriptionContractRepository,
38
46
  PrismaSubscriptionRepository: () => PrismaSubscriptionRepository,
39
47
  PrismaSuperAdminBootstrapAdapter: () => PrismaSuperAdminBootstrapAdapter,
48
+ PrismaTenantSubscriptionWriteAdapter: () => PrismaTenantSubscriptionWriteAdapter,
40
49
  PrismaTransactionRunner: () => PrismaTransactionRunner,
41
50
  ZeroPromoRevenueDeductionAggregator: () => ZeroPromoRevenueDeductionAggregator,
42
51
  buildActorTag: () => buildActorTag,
@@ -1203,9 +1212,6 @@ var PrismaSubscriptionRepository = class {
1203
1212
  return this.toRecord(db, row);
1204
1213
  }
1205
1214
  async toRecord(db, row) {
1206
- if (!row.planVersionId) {
1207
- 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.`);
1208
- }
1209
1215
  const planVersion = await db.planVersion.findUnique({
1210
1216
  where: {
1211
1217
  id: row.planVersionId
@@ -1460,6 +1466,2259 @@ function buildProvisioning(client, hasher) {
1460
1466
  return new PrismaSuperAdminBootstrapAdapter(client, hasher);
1461
1467
  }
1462
1468
  __name(buildProvisioning, "buildProvisioning");
1469
+
1470
+ // src/prisma-subscription-bundle.repository.ts
1471
+ var import_common17 = require("@nestjs/common");
1472
+ function _ts_decorate17(decorators, target, key, desc) {
1473
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
1474
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
1475
+ 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;
1476
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
1477
+ }
1478
+ __name(_ts_decorate17, "_ts_decorate");
1479
+ function _ts_metadata15(k, v) {
1480
+ if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
1481
+ }
1482
+ __name(_ts_metadata15, "_ts_metadata");
1483
+ function _ts_param15(paramIndex, decorator) {
1484
+ return function(target, key) {
1485
+ decorator(target, key, paramIndex);
1486
+ };
1487
+ }
1488
+ __name(_ts_param15, "_ts_param");
1489
+ var PrismaSubscriptionBundleRepository = class {
1490
+ static {
1491
+ __name(this, "PrismaSubscriptionBundleRepository");
1492
+ }
1493
+ prisma;
1494
+ constructor(prisma) {
1495
+ this.prisma = prisma;
1496
+ }
1497
+ db(tx) {
1498
+ return resolveClient(this.prisma, tx);
1499
+ }
1500
+ async listBySubscription(subscriptionId) {
1501
+ const rows = await this.db().subscriptionBundle.findMany({
1502
+ where: {
1503
+ subscriptionId
1504
+ },
1505
+ orderBy: {
1506
+ startedAt: "desc"
1507
+ }
1508
+ });
1509
+ return rows.map(toRecord3);
1510
+ }
1511
+ async findById(subscriptionBundleId) {
1512
+ const row = await this.db().subscriptionBundle.findUnique({
1513
+ where: {
1514
+ id: subscriptionBundleId
1515
+ }
1516
+ });
1517
+ return row ? toRecord3(row) : null;
1518
+ }
1519
+ async listActiveBySubscription(subscriptionId, asOf = /* @__PURE__ */ new Date()) {
1520
+ const rows = await this.db().subscriptionBundle.findMany({
1521
+ where: {
1522
+ subscriptionId,
1523
+ OR: [
1524
+ {
1525
+ canceledAt: null
1526
+ },
1527
+ {
1528
+ canceledEffectiveAt: {
1529
+ gt: asOf
1530
+ }
1531
+ }
1532
+ ]
1533
+ },
1534
+ orderBy: {
1535
+ startedAt: "desc"
1536
+ }
1537
+ });
1538
+ return rows.map(toRecord3);
1539
+ }
1540
+ async add(data) {
1541
+ const row = await this.db().subscriptionBundle.create({
1542
+ data: {
1543
+ subscriptionId: data.subscriptionId,
1544
+ bundleVersionId: data.bundleVersionId,
1545
+ startedAt: data.startedAt,
1546
+ minimumTermEndsAt: data.minimumTermEndsAt ?? null
1547
+ }
1548
+ });
1549
+ return toRecord3(row);
1550
+ }
1551
+ async cancel(subscriptionBundleId, data) {
1552
+ const row = await this.db().subscriptionBundle.update({
1553
+ where: {
1554
+ id: subscriptionBundleId
1555
+ },
1556
+ data: {
1557
+ canceledAt: data.canceledAt,
1558
+ canceledEffectiveAt: data.canceledEffectiveAt
1559
+ }
1560
+ });
1561
+ return toRecord3(row);
1562
+ }
1563
+ async reactivate(subscriptionBundleId) {
1564
+ const row = await this.db().subscriptionBundle.update({
1565
+ where: {
1566
+ id: subscriptionBundleId
1567
+ },
1568
+ data: {
1569
+ canceledAt: null,
1570
+ canceledEffectiveAt: null
1571
+ }
1572
+ });
1573
+ return toRecord3(row);
1574
+ }
1575
+ async countActiveByBundleVersionId(bundleVersionId, asOf = /* @__PURE__ */ new Date()) {
1576
+ return this.db().subscriptionBundle.count({
1577
+ where: {
1578
+ bundleVersionId,
1579
+ OR: [
1580
+ {
1581
+ canceledAt: null
1582
+ },
1583
+ {
1584
+ canceledEffectiveAt: {
1585
+ gt: asOf
1586
+ }
1587
+ }
1588
+ ]
1589
+ }
1590
+ });
1591
+ }
1592
+ };
1593
+ PrismaSubscriptionBundleRepository = _ts_decorate17([
1594
+ (0, import_common17.Injectable)(),
1595
+ _ts_param15(0, (0, import_common17.Inject)(PRISMA_CLIENT_TOKEN)),
1596
+ _ts_metadata15("design:type", Function),
1597
+ _ts_metadata15("design:paramtypes", [
1598
+ typeof PrismaLike === "undefined" ? Object : PrismaLike
1599
+ ])
1600
+ ], PrismaSubscriptionBundleRepository);
1601
+ function toRecord3(row) {
1602
+ return {
1603
+ id: row.id,
1604
+ subscriptionId: row.subscriptionId,
1605
+ bundleVersionId: row.bundleVersionId,
1606
+ startedAt: row.startedAt,
1607
+ minimumTermEndsAt: row.minimumTermEndsAt,
1608
+ canceledAt: row.canceledAt,
1609
+ canceledEffectiveAt: row.canceledEffectiveAt,
1610
+ createdAt: row.createdAt,
1611
+ updatedAt: row.updatedAt
1612
+ };
1613
+ }
1614
+ __name(toRecord3, "toRecord");
1615
+
1616
+ // src/prisma-tenant-subscription-write.adapter.ts
1617
+ var import_common18 = require("@nestjs/common");
1618
+ function _ts_decorate18(decorators, target, key, desc) {
1619
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
1620
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
1621
+ 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;
1622
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
1623
+ }
1624
+ __name(_ts_decorate18, "_ts_decorate");
1625
+ function _ts_metadata16(k, v) {
1626
+ if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
1627
+ }
1628
+ __name(_ts_metadata16, "_ts_metadata");
1629
+ function _ts_param16(paramIndex, decorator) {
1630
+ return function(target, key) {
1631
+ decorator(target, key, paramIndex);
1632
+ };
1633
+ }
1634
+ __name(_ts_param16, "_ts_param");
1635
+ var PrismaTenantSubscriptionWriteAdapter = class {
1636
+ static {
1637
+ __name(this, "PrismaTenantSubscriptionWriteAdapter");
1638
+ }
1639
+ prisma;
1640
+ constructor(prisma) {
1641
+ this.prisma = prisma;
1642
+ }
1643
+ db(tx) {
1644
+ return resolveClient(this.prisma, tx);
1645
+ }
1646
+ async changePlanImmediate(tenantId, input) {
1647
+ const updated = await this.db().subscription.update({
1648
+ where: {
1649
+ tenantId
1650
+ },
1651
+ data: {
1652
+ plan: input.planId,
1653
+ billingCycle: input.cycle,
1654
+ pendingPlan: null,
1655
+ pendingBillingCycle: null,
1656
+ pendingEffectiveAt: null,
1657
+ ...input.nextStatus ? {
1658
+ status: input.nextStatus
1659
+ } : {},
1660
+ ...input.periodStart && input.periodEnd ? {
1661
+ currentPeriodStart: input.periodStart,
1662
+ currentPeriodEnd: input.periodEnd
1663
+ } : {},
1664
+ // #17: the platform changePlan path computes the carried-over
1665
+ // trial end and passes it through; null/undefined leaves the
1666
+ // existing trialEndsAt untouched.
1667
+ ...input.trialEndsAt ? {
1668
+ trialEndsAt: input.trialEndsAt
1669
+ } : {}
1670
+ }
1671
+ });
1672
+ return {
1673
+ plan: updated.plan,
1674
+ billingCycle: updated.billingCycle
1675
+ };
1676
+ }
1677
+ async schedulePlanChange(tenantId, input) {
1678
+ await this.db().subscription.update({
1679
+ where: {
1680
+ tenantId
1681
+ },
1682
+ data: {
1683
+ pendingPlan: input.pendingPlan,
1684
+ pendingBillingCycle: input.pendingBillingCycle,
1685
+ pendingEffectiveAt: input.pendingEffectiveAt
1686
+ }
1687
+ });
1688
+ }
1689
+ async acceptPendingPlanVersion(tenantId, userId, now) {
1690
+ const sub = await this.db().subscription.findUnique({
1691
+ where: {
1692
+ tenantId
1693
+ }
1694
+ });
1695
+ if (!sub) {
1696
+ throw new Error(`No subscription for tenant ${tenantId}.`);
1697
+ }
1698
+ if (sub.pendingPlanVersionAccepted) {
1699
+ return {
1700
+ accepted: true,
1701
+ acceptedAt: sub.pendingPlanVersionAcceptedAt,
1702
+ effectiveAt: sub.pendingPlanVersionEffectiveAt,
1703
+ alreadyAccepted: true
1704
+ };
1705
+ }
1706
+ const updated = await this.db().subscription.update({
1707
+ where: {
1708
+ id: sub.id
1709
+ },
1710
+ data: {
1711
+ pendingPlanVersionAccepted: true,
1712
+ pendingPlanVersionAcceptedAt: now,
1713
+ pendingPlanVersionAcceptedByUserId: userId
1714
+ }
1715
+ });
1716
+ return {
1717
+ accepted: true,
1718
+ acceptedAt: updated.pendingPlanVersionAcceptedAt,
1719
+ effectiveAt: updated.pendingPlanVersionEffectiveAt,
1720
+ alreadyAccepted: false
1721
+ };
1722
+ }
1723
+ async cancelSubscription(tenantId, immediate, now) {
1724
+ const sub = await this.db().subscription.findUnique({
1725
+ where: {
1726
+ tenantId
1727
+ }
1728
+ });
1729
+ if (!sub) {
1730
+ throw new Error(`No subscription for tenant ${tenantId}.`);
1731
+ }
1732
+ const canceledAt = immediate ? now : sub.currentPeriodEnd ?? now;
1733
+ const updated = await this.db().subscription.update({
1734
+ where: {
1735
+ tenantId
1736
+ },
1737
+ data: {
1738
+ canceledAt,
1739
+ status: immediate ? "CANCELED" : sub.status
1740
+ }
1741
+ });
1742
+ return {
1743
+ canceledAt: updated.canceledAt,
1744
+ status: updated.status
1745
+ };
1746
+ }
1747
+ };
1748
+ PrismaTenantSubscriptionWriteAdapter = _ts_decorate18([
1749
+ (0, import_common18.Injectable)(),
1750
+ _ts_param16(0, (0, import_common18.Inject)(PRISMA_CLIENT_TOKEN)),
1751
+ _ts_metadata16("design:type", Function),
1752
+ _ts_metadata16("design:paramtypes", [
1753
+ typeof PrismaLike === "undefined" ? Object : PrismaLike
1754
+ ])
1755
+ ], PrismaTenantSubscriptionWriteAdapter);
1756
+
1757
+ // src/prisma-plan.repository.ts
1758
+ var import_common19 = require("@nestjs/common");
1759
+ function _ts_decorate19(decorators, target, key, desc) {
1760
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
1761
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
1762
+ 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;
1763
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
1764
+ }
1765
+ __name(_ts_decorate19, "_ts_decorate");
1766
+ function _ts_metadata17(k, v) {
1767
+ if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
1768
+ }
1769
+ __name(_ts_metadata17, "_ts_metadata");
1770
+ function _ts_param17(paramIndex, decorator) {
1771
+ return function(target, key) {
1772
+ decorator(target, key, paramIndex);
1773
+ };
1774
+ }
1775
+ __name(_ts_param17, "_ts_param");
1776
+ var PrismaPlanRepository = class {
1777
+ static {
1778
+ __name(this, "PrismaPlanRepository");
1779
+ }
1780
+ prisma;
1781
+ constructor(prisma) {
1782
+ this.prisma = prisma;
1783
+ }
1784
+ db(tx) {
1785
+ return resolveClient(this.prisma, tx);
1786
+ }
1787
+ // ─── Stem operations (Pack 1) ───
1788
+ async list(filter) {
1789
+ const excludeDeleted = filter.excludeDeleted ?? true;
1790
+ let publishedKeys = null;
1791
+ if (filter.onlyPublished) {
1792
+ const live = await this.db().planVersion.findMany({
1793
+ where: {
1794
+ publishedAt: {
1795
+ not: null
1796
+ },
1797
+ supersededAt: null
1798
+ }
1799
+ });
1800
+ publishedKeys = [
1801
+ ...new Set(live.map((version) => version.planId))
1802
+ ];
1803
+ }
1804
+ const rows = await this.db().plan.findMany({
1805
+ where: {
1806
+ projectKey: filter.projectKey,
1807
+ ...excludeDeleted ? {
1808
+ deletedAt: null
1809
+ } : {},
1810
+ ...publishedKeys ? {
1811
+ planKey: {
1812
+ in: publishedKeys
1813
+ }
1814
+ } : {}
1815
+ },
1816
+ orderBy: [
1817
+ {
1818
+ sortOrder: "asc"
1819
+ },
1820
+ {
1821
+ planKey: "asc"
1822
+ }
1823
+ ]
1824
+ });
1825
+ return rows.map(toPlanRow2);
1826
+ }
1827
+ async findById(planId) {
1828
+ const row = await this.db().plan.findUnique({
1829
+ where: {
1830
+ id: planId
1831
+ }
1832
+ });
1833
+ return row ? toPlanRow2(row) : null;
1834
+ }
1835
+ async findByKey(projectKey, planKey) {
1836
+ const row = await this.db().plan.findFirst({
1837
+ where: {
1838
+ projectKey,
1839
+ planKey,
1840
+ deletedAt: null
1841
+ }
1842
+ });
1843
+ return row ? toPlanRow2(row) : null;
1844
+ }
1845
+ async create(data) {
1846
+ const created = await this.db().plan.create({
1847
+ data: {
1848
+ projectKey: data.projectKey,
1849
+ planKey: data.planKey,
1850
+ label: data.label,
1851
+ description: data.description ?? null,
1852
+ icon: data.icon ?? null,
1853
+ sortOrder: data.sortOrder ?? 0
1854
+ }
1855
+ });
1856
+ return toPlanRow2(created);
1857
+ }
1858
+ async update(planId, data) {
1859
+ const updated = await this.db().plan.update({
1860
+ where: {
1861
+ id: planId
1862
+ },
1863
+ data: {
1864
+ ...data.label !== void 0 ? {
1865
+ label: data.label
1866
+ } : {},
1867
+ ...data.description !== void 0 ? {
1868
+ description: data.description
1869
+ } : {},
1870
+ ...data.icon !== void 0 ? {
1871
+ icon: data.icon
1872
+ } : {},
1873
+ ...data.sortOrder !== void 0 ? {
1874
+ sortOrder: data.sortOrder
1875
+ } : {}
1876
+ }
1877
+ });
1878
+ return toPlanRow2(updated);
1879
+ }
1880
+ async softDelete(planId) {
1881
+ await this.db().plan.update({
1882
+ where: {
1883
+ id: planId
1884
+ },
1885
+ data: {
1886
+ deletedAt: /* @__PURE__ */ new Date()
1887
+ }
1888
+ });
1889
+ }
1890
+ async hardDelete(planId) {
1891
+ await this.db().plan.deleteMany({
1892
+ where: {
1893
+ id: planId
1894
+ }
1895
+ });
1896
+ }
1897
+ // ─── Lifecycle operations (Pack 2a) — keyed by planKey ───
1898
+ async listVersions(planKey) {
1899
+ const rows = await this.db().planVersion.findMany({
1900
+ where: {
1901
+ planId: planKey
1902
+ },
1903
+ orderBy: {
1904
+ version: "asc"
1905
+ }
1906
+ });
1907
+ return rows.map(toPlanVersionRow2);
1908
+ }
1909
+ async findVersionById(versionId) {
1910
+ const row = await this.db().planVersion.findUnique({
1911
+ where: {
1912
+ id: versionId
1913
+ }
1914
+ });
1915
+ return row ? toPlanVersionRow2(row) : null;
1916
+ }
1917
+ async findCurrentDraft(planKey) {
1918
+ const row = await this.db().planVersion.findFirst({
1919
+ where: {
1920
+ planId: planKey,
1921
+ publishedAt: null
1922
+ }
1923
+ });
1924
+ return row ? toPlanVersionRow2(row) : null;
1925
+ }
1926
+ async findLatestLivePlanVersion(planKey, tx) {
1927
+ const row = await this.db(tx).planVersion.findFirst({
1928
+ where: {
1929
+ planId: planKey,
1930
+ publishedAt: {
1931
+ not: null
1932
+ },
1933
+ supersededAt: null
1934
+ },
1935
+ orderBy: {
1936
+ version: "desc"
1937
+ }
1938
+ });
1939
+ return row ? toPlanVersionRow2(row) : null;
1940
+ }
1941
+ async findActivePlanVersion() {
1942
+ throw new Error("findActivePlanVersion is not supported by the shipped @saasicat/adapter-prisma PlanRepository: the canonical plan_versions schema (03-plan-versions.prisma) has no validFrom/validUntil columns, so a version cannot be resolved by validity window. Use findLatestLivePlanVersion for the newest live version, or provide a custom PlanRepository adapter on a schema that carries the validity-window columns.");
1943
+ }
1944
+ async createPlanVersionDraft(data) {
1945
+ const planKey = data.planId;
1946
+ const latest = await this.db().planVersion.findFirst({
1947
+ where: {
1948
+ planId: planKey
1949
+ },
1950
+ orderBy: {
1951
+ version: "desc"
1952
+ }
1953
+ });
1954
+ const nextVersion = (latest?.version ?? 0) + 1;
1955
+ const created = await this.db().planVersion.create({
1956
+ data: {
1957
+ planId: planKey,
1958
+ version: nextVersion,
1959
+ baseVersionId: data.baseVersionId ?? null,
1960
+ features: data.features,
1961
+ quotas: data.quotas,
1962
+ monthlyNet: data.monthlyNet,
1963
+ yearlyNet: data.yearlyNet,
1964
+ marketed: data.marketed ?? true,
1965
+ changeNote: data.changeNote ?? "",
1966
+ createdByUserId: data.createdByUserId ?? null
1967
+ }
1968
+ });
1969
+ return toPlanVersionRow2(created);
1970
+ }
1971
+ async updatePlanVersionDraft(versionId, data) {
1972
+ const updated = await this.db().planVersion.update({
1973
+ where: {
1974
+ id: versionId
1975
+ },
1976
+ data: {
1977
+ ...data.features !== void 0 ? {
1978
+ features: data.features
1979
+ } : {},
1980
+ ...data.quotas !== void 0 ? {
1981
+ quotas: data.quotas
1982
+ } : {},
1983
+ ...data.monthlyNet !== void 0 ? {
1984
+ monthlyNet: data.monthlyNet
1985
+ } : {},
1986
+ ...data.yearlyNet !== void 0 ? {
1987
+ yearlyNet: data.yearlyNet
1988
+ } : {},
1989
+ ...data.marketed !== void 0 ? {
1990
+ marketed: data.marketed
1991
+ } : {},
1992
+ ...data.changeNote !== void 0 ? {
1993
+ changeNote: data.changeNote
1994
+ } : {}
1995
+ }
1996
+ });
1997
+ return toPlanVersionRow2(updated);
1998
+ }
1999
+ async publishPlanVersionDraft(versionId, publishMeta, tx) {
2000
+ const draft = await this.db(tx).planVersion.findUnique({
2001
+ where: {
2002
+ id: versionId
2003
+ }
2004
+ });
2005
+ if (!draft) {
2006
+ throw new Error(`PlanVersion ${versionId} not found.`);
2007
+ }
2008
+ const planKey = draft.planId;
2009
+ const publish = /* @__PURE__ */ __name(async (db) => {
2010
+ const previous = await db.planVersion.findFirst({
2011
+ where: {
2012
+ planId: planKey,
2013
+ publishedAt: {
2014
+ not: null
2015
+ },
2016
+ supersededAt: null,
2017
+ id: {
2018
+ not: versionId
2019
+ }
2020
+ },
2021
+ orderBy: {
2022
+ version: "desc"
2023
+ }
2024
+ });
2025
+ const now = /* @__PURE__ */ new Date();
2026
+ if (previous) {
2027
+ await db.planVersion.update({
2028
+ where: {
2029
+ id: previous.id
2030
+ },
2031
+ data: {
2032
+ supersededAt: now
2033
+ }
2034
+ });
2035
+ }
2036
+ return db.planVersion.update({
2037
+ where: {
2038
+ id: versionId
2039
+ },
2040
+ data: {
2041
+ publishedAt: now,
2042
+ publishedChanges: publishMeta.publishedChanges,
2043
+ nonRegressive: publishMeta.nonRegressive,
2044
+ publishedByUserId: publishMeta.publishedByUserId
2045
+ }
2046
+ });
2047
+ }, "publish");
2048
+ const published = tx ? await publish(this.db(tx)) : await this.prisma.$transaction((txClient) => publish(txClient));
2049
+ return toPlanVersionRow2(published);
2050
+ }
2051
+ async deletePlanVersionDraft(versionId) {
2052
+ const row = await this.db().planVersion.findUnique({
2053
+ where: {
2054
+ id: versionId
2055
+ }
2056
+ });
2057
+ if (!row) return;
2058
+ if (row.publishedAt !== null) {
2059
+ throw new Error(`PlanVersion ${versionId} is already published and cannot be discarded (published versions are immutable \u2014 contract protection P1).`);
2060
+ }
2061
+ await this.db().planVersion.deleteMany({
2062
+ where: {
2063
+ id: versionId,
2064
+ publishedAt: null
2065
+ }
2066
+ });
2067
+ }
2068
+ async terminate() {
2069
+ throw new Error("terminate is not supported by the shipped @saasicat/adapter-prisma PlanRepository: the canonical plan_versions schema (03-plan-versions.prisma) has no endsAt column. Provide a custom PlanRepository adapter on a schema that carries endsAt to support SuperAdmin-initiated plan-version termination.");
2070
+ }
2071
+ };
2072
+ PrismaPlanRepository = _ts_decorate19([
2073
+ (0, import_common19.Injectable)(),
2074
+ _ts_param17(0, (0, import_common19.Inject)(PRISMA_CLIENT_TOKEN)),
2075
+ _ts_metadata17("design:type", Function),
2076
+ _ts_metadata17("design:paramtypes", [
2077
+ typeof PrismaLike === "undefined" ? Object : PrismaLike
2078
+ ])
2079
+ ], PrismaPlanRepository);
2080
+ function toPlanRow2(row) {
2081
+ return {
2082
+ id: row.id,
2083
+ projectKey: row.projectKey,
2084
+ planKey: row.planKey,
2085
+ label: row.label,
2086
+ description: row.description,
2087
+ icon: row.icon,
2088
+ sortOrder: row.sortOrder,
2089
+ createdAt: row.createdAt.toISOString(),
2090
+ updatedAt: row.updatedAt.toISOString(),
2091
+ deletedAt: row.deletedAt?.toISOString() ?? null
2092
+ };
2093
+ }
2094
+ __name(toPlanRow2, "toPlanRow");
2095
+ function toPlanVersionRow2(row) {
2096
+ return {
2097
+ id: row.id,
2098
+ version: row.version,
2099
+ baseVersionId: row.baseVersionId,
2100
+ planId: row.planId,
2101
+ features: toStringArray(row.features),
2102
+ quotas: toQuotaMap(row.quotas),
2103
+ monthlyNet: row.monthlyNet.toString(),
2104
+ yearlyNet: row.yearlyNet.toString(),
2105
+ marketed: row.marketed,
2106
+ publishedAt: row.publishedAt?.toISOString() ?? null,
2107
+ supersededAt: row.supersededAt?.toISOString() ?? null,
2108
+ publishedChanges: Array.isArray(row.publishedChanges) ? row.publishedChanges : null,
2109
+ changeNote: row.changeNote,
2110
+ nonRegressive: row.nonRegressive,
2111
+ // The canonical plan_versions schema carries no validity-window columns.
2112
+ validFrom: null,
2113
+ validUntil: null,
2114
+ createdByUserId: row.createdByUserId,
2115
+ publishedByUserId: row.publishedByUserId,
2116
+ createdAt: row.createdAt.toISOString(),
2117
+ updatedAt: row.updatedAt.toISOString()
2118
+ };
2119
+ }
2120
+ __name(toPlanVersionRow2, "toPlanVersionRow");
2121
+
2122
+ // src/prisma-bundle.repository.ts
2123
+ var import_common20 = require("@nestjs/common");
2124
+ function _ts_decorate20(decorators, target, key, desc) {
2125
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
2126
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
2127
+ 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;
2128
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
2129
+ }
2130
+ __name(_ts_decorate20, "_ts_decorate");
2131
+ function _ts_metadata18(k, v) {
2132
+ if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
2133
+ }
2134
+ __name(_ts_metadata18, "_ts_metadata");
2135
+ function _ts_param18(paramIndex, decorator) {
2136
+ return function(target, key) {
2137
+ decorator(target, key, paramIndex);
2138
+ };
2139
+ }
2140
+ __name(_ts_param18, "_ts_param");
2141
+ var PrismaBundleRepository = class {
2142
+ static {
2143
+ __name(this, "PrismaBundleRepository");
2144
+ }
2145
+ prisma;
2146
+ constructor(prisma) {
2147
+ this.prisma = prisma;
2148
+ }
2149
+ db(tx) {
2150
+ return resolveClient(this.prisma, tx);
2151
+ }
2152
+ // ─── Stem operations ───
2153
+ async list(filter) {
2154
+ const excludeDeleted = filter.excludeDeleted ?? true;
2155
+ const rows = await this.db().bundle.findMany({
2156
+ where: {
2157
+ projectKey: filter.projectKey,
2158
+ ...excludeDeleted ? {
2159
+ deletedAt: null
2160
+ } : {}
2161
+ },
2162
+ orderBy: [
2163
+ {
2164
+ sortOrder: "asc"
2165
+ },
2166
+ {
2167
+ bundleKey: "asc"
2168
+ }
2169
+ ]
2170
+ });
2171
+ return rows.map(toBundleRow);
2172
+ }
2173
+ async findById(bundleId) {
2174
+ const row = await this.db().bundle.findUnique({
2175
+ where: {
2176
+ id: bundleId
2177
+ }
2178
+ });
2179
+ return row ? toBundleRow(row) : null;
2180
+ }
2181
+ async findByKey(projectKey, bundleKey) {
2182
+ const row = await this.db().bundle.findFirst({
2183
+ where: {
2184
+ projectKey,
2185
+ bundleKey,
2186
+ deletedAt: null
2187
+ }
2188
+ });
2189
+ return row ? toBundleRow(row) : null;
2190
+ }
2191
+ async create(data) {
2192
+ const created = await this.db().bundle.create({
2193
+ data: {
2194
+ projectKey: data.projectKey,
2195
+ bundleKey: data.bundleKey,
2196
+ label: data.label,
2197
+ description: data.description ?? null,
2198
+ icon: data.icon ?? null,
2199
+ sortOrder: data.sortOrder ?? 0,
2200
+ i18n: data.i18n ?? {}
2201
+ }
2202
+ });
2203
+ return toBundleRow(created);
2204
+ }
2205
+ async update(bundleId, data) {
2206
+ const updated = await this.db().bundle.update({
2207
+ where: {
2208
+ id: bundleId
2209
+ },
2210
+ data: {
2211
+ ...data.label !== void 0 ? {
2212
+ label: data.label
2213
+ } : {},
2214
+ ...data.description !== void 0 ? {
2215
+ description: data.description
2216
+ } : {},
2217
+ ...data.icon !== void 0 ? {
2218
+ icon: data.icon
2219
+ } : {},
2220
+ ...data.sortOrder !== void 0 ? {
2221
+ sortOrder: data.sortOrder
2222
+ } : {},
2223
+ ...data.i18n !== void 0 ? {
2224
+ i18n: data.i18n
2225
+ } : {}
2226
+ }
2227
+ });
2228
+ return toBundleRow(updated);
2229
+ }
2230
+ async softDelete(bundleId) {
2231
+ await this.db().bundle.update({
2232
+ where: {
2233
+ id: bundleId
2234
+ },
2235
+ data: {
2236
+ deletedAt: /* @__PURE__ */ new Date()
2237
+ }
2238
+ });
2239
+ }
2240
+ // ─── Version operations ───
2241
+ async listVersions(bundleId) {
2242
+ const bundle = await this.db().bundle.findUnique({
2243
+ where: {
2244
+ id: bundleId
2245
+ }
2246
+ });
2247
+ if (!bundle) return [];
2248
+ const rows = await this.db().bundleVersion.findMany({
2249
+ where: {
2250
+ bundleId
2251
+ },
2252
+ orderBy: {
2253
+ version: "asc"
2254
+ }
2255
+ });
2256
+ return rows.map((row) => toBundleVersionRow(row, bundle));
2257
+ }
2258
+ async findVersionById(versionId) {
2259
+ const row = await this.db().bundleVersion.findUnique({
2260
+ where: {
2261
+ id: versionId
2262
+ }
2263
+ });
2264
+ if (!row) return null;
2265
+ const bundle = await this.db().bundle.findUnique({
2266
+ where: {
2267
+ id: row.bundleId
2268
+ }
2269
+ });
2270
+ return toBundleVersionRow(row, bundle);
2271
+ }
2272
+ async findCurrentDraft(bundleId) {
2273
+ const row = await this.db().bundleVersion.findFirst({
2274
+ where: {
2275
+ bundleId,
2276
+ publishedAt: null
2277
+ }
2278
+ });
2279
+ if (!row) return null;
2280
+ const bundle = await this.db().bundle.findUnique({
2281
+ where: {
2282
+ id: bundleId
2283
+ }
2284
+ });
2285
+ return toBundleVersionRow(row, bundle);
2286
+ }
2287
+ async findLatestLive(bundleId, tx) {
2288
+ const db = this.db(tx);
2289
+ const row = await db.bundleVersion.findFirst({
2290
+ where: {
2291
+ bundleId,
2292
+ publishedAt: {
2293
+ not: null
2294
+ },
2295
+ supersededAt: null
2296
+ },
2297
+ orderBy: {
2298
+ version: "desc"
2299
+ }
2300
+ });
2301
+ if (!row) return null;
2302
+ const bundle = await db.bundle.findUnique({
2303
+ where: {
2304
+ id: bundleId
2305
+ }
2306
+ });
2307
+ return toBundleVersionRow(row, bundle);
2308
+ }
2309
+ async createDraft(data) {
2310
+ const db = this.db();
2311
+ const existingDraft = await db.bundleVersion.findFirst({
2312
+ where: {
2313
+ bundleId: data.bundleId,
2314
+ publishedAt: null
2315
+ }
2316
+ });
2317
+ if (existingDraft) {
2318
+ throw new Error(`Bundle '${data.bundleId}' already has a draft version (v${existingDraft.version}); only one draft per bundle is allowed.`);
2319
+ }
2320
+ const latest = await db.bundleVersion.findFirst({
2321
+ where: {
2322
+ bundleId: data.bundleId
2323
+ },
2324
+ orderBy: {
2325
+ version: "desc"
2326
+ }
2327
+ });
2328
+ const nextVersion = latest ? latest.version + 1 : 1;
2329
+ const created = await db.bundleVersion.create({
2330
+ data: {
2331
+ bundleId: data.bundleId,
2332
+ version: nextVersion,
2333
+ baseVersionId: data.baseVersionId ?? null,
2334
+ features: data.features,
2335
+ quotas: data.quotas ?? {},
2336
+ compatibility: data.compatibility ?? {},
2337
+ pricingOverrides: data.pricingOverrides ?? [],
2338
+ monthlyNet: data.monthlyNet ?? null,
2339
+ yearlyNet: data.yearlyNet ?? null,
2340
+ marketed: data.marketed ?? true,
2341
+ changeNote: data.changeNote ?? "",
2342
+ createdByUserId: data.createdByUserId ?? null
2343
+ }
2344
+ });
2345
+ const bundle = await db.bundle.findUnique({
2346
+ where: {
2347
+ id: data.bundleId
2348
+ }
2349
+ });
2350
+ return toBundleVersionRow(created, bundle);
2351
+ }
2352
+ async updateDraft(versionId, data) {
2353
+ const db = this.db();
2354
+ const updated = await db.bundleVersion.update({
2355
+ where: {
2356
+ id: versionId
2357
+ },
2358
+ data: {
2359
+ ...data.features !== void 0 ? {
2360
+ features: data.features
2361
+ } : {},
2362
+ ...data.quotas !== void 0 ? {
2363
+ quotas: data.quotas
2364
+ } : {},
2365
+ ...data.compatibility !== void 0 ? {
2366
+ compatibility: data.compatibility
2367
+ } : {},
2368
+ ...data.pricingOverrides !== void 0 ? {
2369
+ pricingOverrides: data.pricingOverrides
2370
+ } : {},
2371
+ ...data.monthlyNet !== void 0 ? {
2372
+ monthlyNet: data.monthlyNet
2373
+ } : {},
2374
+ ...data.yearlyNet !== void 0 ? {
2375
+ yearlyNet: data.yearlyNet
2376
+ } : {},
2377
+ ...data.marketed !== void 0 ? {
2378
+ marketed: data.marketed
2379
+ } : {},
2380
+ ...data.changeNote !== void 0 ? {
2381
+ changeNote: data.changeNote
2382
+ } : {}
2383
+ }
2384
+ });
2385
+ const bundle = await db.bundle.findUnique({
2386
+ where: {
2387
+ id: updated.bundleId
2388
+ }
2389
+ });
2390
+ return toBundleVersionRow(updated, bundle);
2391
+ }
2392
+ async publishDraft(versionId, publishMeta, tx) {
2393
+ const db = this.db(tx);
2394
+ const draft = await db.bundleVersion.findUnique({
2395
+ where: {
2396
+ id: versionId
2397
+ }
2398
+ });
2399
+ if (!draft) {
2400
+ throw new Error(`BundleVersion '${versionId}' not found.`);
2401
+ }
2402
+ await db.bundleVersion.updateMany({
2403
+ where: {
2404
+ bundleId: draft.bundleId,
2405
+ publishedAt: {
2406
+ not: null
2407
+ },
2408
+ supersededAt: null,
2409
+ NOT: {
2410
+ id: versionId
2411
+ }
2412
+ },
2413
+ data: {
2414
+ supersededAt: /* @__PURE__ */ new Date()
2415
+ }
2416
+ });
2417
+ const published = await db.bundleVersion.update({
2418
+ where: {
2419
+ id: versionId
2420
+ },
2421
+ data: {
2422
+ publishedAt: /* @__PURE__ */ new Date(),
2423
+ publishedByUserId: publishMeta.publishedByUserId,
2424
+ publishedChanges: publishMeta.publishedChanges,
2425
+ nonRegressive: publishMeta.nonRegressive
2426
+ }
2427
+ });
2428
+ const bundle = await db.bundle.findUnique({
2429
+ where: {
2430
+ id: published.bundleId
2431
+ }
2432
+ });
2433
+ return toBundleVersionRow(published, bundle);
2434
+ }
2435
+ async deleteDraft(versionId) {
2436
+ const db = this.db();
2437
+ const row = await db.bundleVersion.findUnique({
2438
+ where: {
2439
+ id: versionId
2440
+ }
2441
+ });
2442
+ if (!row) return;
2443
+ if (row.publishedAt !== null) {
2444
+ throw new Error(`BundleVersion '${versionId}' is already published and cannot be discarded (published versions are immutable \u2014 contract protection P1).`);
2445
+ }
2446
+ try {
2447
+ await db.bundleVersion.delete({
2448
+ where: {
2449
+ id: versionId
2450
+ }
2451
+ });
2452
+ } catch (err) {
2453
+ if (err?.code === "P2025") return;
2454
+ throw err;
2455
+ }
2456
+ }
2457
+ };
2458
+ PrismaBundleRepository = _ts_decorate20([
2459
+ (0, import_common20.Injectable)(),
2460
+ _ts_param18(0, (0, import_common20.Inject)(PRISMA_CLIENT_TOKEN)),
2461
+ _ts_metadata18("design:type", Function),
2462
+ _ts_metadata18("design:paramtypes", [
2463
+ typeof PrismaLike === "undefined" ? Object : PrismaLike
2464
+ ])
2465
+ ], PrismaBundleRepository);
2466
+ function isPlainObject(value) {
2467
+ return value !== null && typeof value === "object" && !Array.isArray(value);
2468
+ }
2469
+ __name(isPlainObject, "isPlainObject");
2470
+ function toDecimalString(value) {
2471
+ return value == null ? null : value.toString();
2472
+ }
2473
+ __name(toDecimalString, "toDecimalString");
2474
+ function toVersionChanges(value) {
2475
+ return Array.isArray(value) ? value : null;
2476
+ }
2477
+ __name(toVersionChanges, "toVersionChanges");
2478
+ function toCompatibility(value) {
2479
+ return isPlainObject(value) ? value : {};
2480
+ }
2481
+ __name(toCompatibility, "toCompatibility");
2482
+ function toPricingOverrides(value) {
2483
+ return Array.isArray(value) ? value : [];
2484
+ }
2485
+ __name(toPricingOverrides, "toPricingOverrides");
2486
+ function toI18n(value) {
2487
+ return isPlainObject(value) ? value : {};
2488
+ }
2489
+ __name(toI18n, "toI18n");
2490
+ function toBundleRow(row) {
2491
+ return {
2492
+ id: row.id,
2493
+ projectKey: row.projectKey,
2494
+ bundleKey: row.bundleKey,
2495
+ label: row.label,
2496
+ description: row.description,
2497
+ icon: row.icon,
2498
+ sortOrder: row.sortOrder,
2499
+ i18n: toI18n(row.i18n),
2500
+ createdAt: row.createdAt.toISOString(),
2501
+ updatedAt: row.updatedAt.toISOString(),
2502
+ deletedAt: row.deletedAt?.toISOString() ?? null
2503
+ };
2504
+ }
2505
+ __name(toBundleRow, "toBundleRow");
2506
+ function toBundleVersionRow(row, bundle) {
2507
+ return {
2508
+ id: row.id,
2509
+ bundleId: row.bundleId,
2510
+ bundleKey: bundle?.bundleKey ?? "",
2511
+ label: bundle?.label ?? "",
2512
+ version: row.version,
2513
+ baseVersionId: row.baseVersionId,
2514
+ features: toStringArray(row.features),
2515
+ quotas: toQuotaMap(row.quotas),
2516
+ compatibility: toCompatibility(row.compatibility),
2517
+ pricingOverrides: toPricingOverrides(row.pricingOverrides),
2518
+ monthlyNet: toDecimalString(row.monthlyNet),
2519
+ yearlyNet: toDecimalString(row.yearlyNet),
2520
+ marketed: row.marketed,
2521
+ publishedAt: row.publishedAt?.toISOString() ?? null,
2522
+ supersededAt: row.supersededAt?.toISOString() ?? null,
2523
+ // The canonical `bundle_versions` table has no validFrom/validUntil
2524
+ // columns; time-aware validity is not expressible on this schema.
2525
+ validFrom: null,
2526
+ validUntil: null,
2527
+ publishedChanges: toVersionChanges(row.publishedChanges),
2528
+ changeNote: row.changeNote,
2529
+ nonRegressive: row.nonRegressive,
2530
+ createdByUserId: row.createdByUserId,
2531
+ publishedByUserId: row.publishedByUserId,
2532
+ createdAt: row.createdAt.toISOString(),
2533
+ updatedAt: row.updatedAt.toISOString()
2534
+ };
2535
+ }
2536
+ __name(toBundleVersionRow, "toBundleVersionRow");
2537
+
2538
+ // src/prisma-catalog-entry.repository.ts
2539
+ var import_common21 = require("@nestjs/common");
2540
+ function _ts_decorate21(decorators, target, key, desc) {
2541
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
2542
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
2543
+ 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;
2544
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
2545
+ }
2546
+ __name(_ts_decorate21, "_ts_decorate");
2547
+ function _ts_metadata19(k, v) {
2548
+ if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
2549
+ }
2550
+ __name(_ts_metadata19, "_ts_metadata");
2551
+ function _ts_param19(paramIndex, decorator) {
2552
+ return function(target, key) {
2553
+ decorator(target, key, paramIndex);
2554
+ };
2555
+ }
2556
+ __name(_ts_param19, "_ts_param");
2557
+ var PrismaCatalogEntryRepository = class {
2558
+ static {
2559
+ __name(this, "PrismaCatalogEntryRepository");
2560
+ }
2561
+ prisma;
2562
+ constructor(prisma) {
2563
+ this.prisma = prisma;
2564
+ }
2565
+ get db() {
2566
+ return this.prisma;
2567
+ }
2568
+ async listCapabilities(filter) {
2569
+ const rows = await this.db.capabilityCatalogEntry.findMany({
2570
+ where: {
2571
+ projectKey: filter.projectKey,
2572
+ deletedAt: null,
2573
+ ...filter.codeStatus ? {
2574
+ codeStatus: filter.codeStatus
2575
+ } : {}
2576
+ },
2577
+ orderBy: [
2578
+ {
2579
+ sortOrder: "asc"
2580
+ },
2581
+ {
2582
+ capabilityKey: "asc"
2583
+ }
2584
+ ]
2585
+ });
2586
+ return rows.map(toCapabilityRow);
2587
+ }
2588
+ async listFeatures(filter) {
2589
+ const rows = await this.db.featureCatalogEntry.findMany({
2590
+ where: {
2591
+ projectKey: filter.projectKey,
2592
+ deletedAt: null,
2593
+ ...filter.discoveryStatus ? {
2594
+ discoveryStatus: filter.discoveryStatus
2595
+ } : {}
2596
+ },
2597
+ orderBy: [
2598
+ {
2599
+ sortOrder: "asc"
2600
+ },
2601
+ {
2602
+ featureKey: "asc"
2603
+ }
2604
+ ]
2605
+ });
2606
+ return rows.map(toFeatureRow);
2607
+ }
2608
+ async listQuotas(filter) {
2609
+ const rows = await this.db.quotaCatalogEntry.findMany({
2610
+ where: {
2611
+ projectKey: filter.projectKey,
2612
+ deletedAt: null,
2613
+ ...filter.discoveryStatus ? {
2614
+ discoveryStatus: filter.discoveryStatus
2615
+ } : {}
2616
+ },
2617
+ orderBy: [
2618
+ {
2619
+ sortOrder: "asc"
2620
+ },
2621
+ {
2622
+ quotaKey: "asc"
2623
+ }
2624
+ ]
2625
+ });
2626
+ return rows.map(toQuotaRow);
2627
+ }
2628
+ async upsertCapability(data) {
2629
+ const codeFields = {
2630
+ label: data.label,
2631
+ description: data.description,
2632
+ featureKey: data.featureKey,
2633
+ bundleKey: data.bundleKey,
2634
+ codeStatus: data.codeStatus,
2635
+ owner: data.owner,
2636
+ kind: data.kind,
2637
+ replacementKey: data.replacementKey,
2638
+ deprecatedAt: data.deprecatedAt ? new Date(data.deprecatedAt) : null,
2639
+ removalPlannedAt: data.removalPlannedAt ? new Date(data.removalPlannedAt) : null,
2640
+ reason: data.reason
2641
+ };
2642
+ const row = await this.db.capabilityCatalogEntry.upsert({
2643
+ where: {
2644
+ projectKey_capabilityKey: {
2645
+ projectKey: data.projectKey,
2646
+ capabilityKey: data.capabilityKey
2647
+ }
2648
+ },
2649
+ create: {
2650
+ projectKey: data.projectKey,
2651
+ capabilityKey: data.capabilityKey,
2652
+ ...codeFields
2653
+ },
2654
+ update: codeFields
2655
+ });
2656
+ return toCapabilityRow(row);
2657
+ }
2658
+ async upsertFeature(data) {
2659
+ const codeFields = {
2660
+ label: data.label,
2661
+ description: data.description,
2662
+ discoveryStatus: data.discoveryStatus,
2663
+ requires: data.requires,
2664
+ replaces: data.replaces,
2665
+ ...data.core !== void 0 ? {
2666
+ core: data.core
2667
+ } : {}
2668
+ };
2669
+ const row = await this.db.featureCatalogEntry.upsert({
2670
+ where: {
2671
+ projectKey_featureKey: {
2672
+ projectKey: data.projectKey,
2673
+ featureKey: data.featureKey
2674
+ }
2675
+ },
2676
+ create: {
2677
+ projectKey: data.projectKey,
2678
+ featureKey: data.featureKey,
2679
+ ...codeFields
2680
+ },
2681
+ update: codeFields
2682
+ });
2683
+ return toFeatureRow(row);
2684
+ }
2685
+ async upsertQuota(data) {
2686
+ const codeFields = {
2687
+ label: data.label,
2688
+ description: data.description,
2689
+ unit: data.unit,
2690
+ featureKey: data.featureKey,
2691
+ usageProvider: data.usageProvider,
2692
+ enforcementMode: data.enforcementMode,
2693
+ discoveryStatus: data.discoveryStatus,
2694
+ replaces: data.replaces
2695
+ };
2696
+ const row = await this.db.quotaCatalogEntry.upsert({
2697
+ where: {
2698
+ projectKey_quotaKey: {
2699
+ projectKey: data.projectKey,
2700
+ quotaKey: data.quotaKey
2701
+ }
2702
+ },
2703
+ create: {
2704
+ projectKey: data.projectKey,
2705
+ quotaKey: data.quotaKey,
2706
+ ...codeFields
2707
+ },
2708
+ update: codeFields
2709
+ });
2710
+ return toQuotaRow(row);
2711
+ }
2712
+ async retireMissing(projectKey, type, presentKeys) {
2713
+ if (type === "capability") {
2714
+ const res2 = await this.db.capabilityCatalogEntry.updateMany({
2715
+ where: {
2716
+ projectKey,
2717
+ deletedAt: null,
2718
+ codeStatus: {
2719
+ not: "retired"
2720
+ },
2721
+ capabilityKey: {
2722
+ notIn: presentKeys
2723
+ }
2724
+ },
2725
+ data: {
2726
+ codeStatus: "retired"
2727
+ }
2728
+ });
2729
+ return res2.count;
2730
+ }
2731
+ if (type === "feature") {
2732
+ const res2 = await this.db.featureCatalogEntry.updateMany({
2733
+ where: {
2734
+ projectKey,
2735
+ deletedAt: null,
2736
+ discoveryStatus: {
2737
+ not: "obsolete"
2738
+ },
2739
+ featureKey: {
2740
+ notIn: presentKeys
2741
+ }
2742
+ },
2743
+ data: {
2744
+ discoveryStatus: "obsolete"
2745
+ }
2746
+ });
2747
+ return res2.count;
2748
+ }
2749
+ const res = await this.db.quotaCatalogEntry.updateMany({
2750
+ where: {
2751
+ projectKey,
2752
+ deletedAt: null,
2753
+ discoveryStatus: {
2754
+ not: "obsolete"
2755
+ },
2756
+ quotaKey: {
2757
+ notIn: presentKeys
2758
+ }
2759
+ },
2760
+ data: {
2761
+ discoveryStatus: "obsolete"
2762
+ }
2763
+ });
2764
+ return res.count;
2765
+ }
2766
+ async setFeatureSuccessor(projectKey, featureKey, successorKey) {
2767
+ const row = await this.db.featureCatalogEntry.update({
2768
+ where: {
2769
+ projectKey_featureKey: {
2770
+ projectKey,
2771
+ featureKey
2772
+ }
2773
+ },
2774
+ data: {
2775
+ successorKey
2776
+ }
2777
+ });
2778
+ return toFeatureRow(row);
2779
+ }
2780
+ async setQuotaSuccessor(projectKey, quotaKey, successorKey) {
2781
+ const row = await this.db.quotaCatalogEntry.update({
2782
+ where: {
2783
+ projectKey_quotaKey: {
2784
+ projectKey,
2785
+ quotaKey
2786
+ }
2787
+ },
2788
+ data: {
2789
+ successorKey
2790
+ }
2791
+ });
2792
+ return toQuotaRow(row);
2793
+ }
2794
+ async findFeature(projectKey, featureKey) {
2795
+ const row = await this.db.featureCatalogEntry.findUnique({
2796
+ where: {
2797
+ projectKey_featureKey: {
2798
+ projectKey,
2799
+ featureKey
2800
+ }
2801
+ }
2802
+ });
2803
+ return row ? toFeatureRow(row) : null;
2804
+ }
2805
+ async findQuota(projectKey, quotaKey) {
2806
+ const row = await this.db.quotaCatalogEntry.findUnique({
2807
+ where: {
2808
+ projectKey_quotaKey: {
2809
+ projectKey,
2810
+ quotaKey
2811
+ }
2812
+ }
2813
+ });
2814
+ return row ? toQuotaRow(row) : null;
2815
+ }
2816
+ async setFeatureReview(projectKey, featureKey, data) {
2817
+ const row = await this.db.featureCatalogEntry.update({
2818
+ where: {
2819
+ projectKey_featureKey: {
2820
+ projectKey,
2821
+ featureKey
2822
+ }
2823
+ },
2824
+ data: {
2825
+ discoveryStatus: data.discoveryStatus,
2826
+ approvedAt: data.approvedAt ? new Date(data.approvedAt) : null,
2827
+ approvedBy: data.approvedBy,
2828
+ approvedSignature: data.approvedSignature
2829
+ }
2830
+ });
2831
+ return toFeatureRow(row);
2832
+ }
2833
+ async setQuotaReview(projectKey, quotaKey, data) {
2834
+ const row = await this.db.quotaCatalogEntry.update({
2835
+ where: {
2836
+ projectKey_quotaKey: {
2837
+ projectKey,
2838
+ quotaKey
2839
+ }
2840
+ },
2841
+ data: {
2842
+ discoveryStatus: data.discoveryStatus,
2843
+ approvedAt: data.approvedAt ? new Date(data.approvedAt) : null,
2844
+ approvedBy: data.approvedBy,
2845
+ approvedSignature: data.approvedSignature
2846
+ }
2847
+ });
2848
+ return toQuotaRow(row);
2849
+ }
2850
+ async setFeatureI18n(projectKey, featureKey, i18n) {
2851
+ const row = await this.db.featureCatalogEntry.update({
2852
+ where: {
2853
+ projectKey_featureKey: {
2854
+ projectKey,
2855
+ featureKey
2856
+ }
2857
+ },
2858
+ data: {
2859
+ i18n
2860
+ }
2861
+ });
2862
+ return toFeatureRow(row);
2863
+ }
2864
+ async setQuotaI18n(projectKey, quotaKey, i18n) {
2865
+ const row = await this.db.quotaCatalogEntry.update({
2866
+ where: {
2867
+ projectKey_quotaKey: {
2868
+ projectKey,
2869
+ quotaKey
2870
+ }
2871
+ },
2872
+ data: {
2873
+ i18n
2874
+ }
2875
+ });
2876
+ return toQuotaRow(row);
2877
+ }
2878
+ async setFeatureBase(projectKey, featureKey, data) {
2879
+ const row = await this.db.featureCatalogEntry.update({
2880
+ where: {
2881
+ projectKey_featureKey: {
2882
+ projectKey,
2883
+ featureKey
2884
+ }
2885
+ },
2886
+ data: {
2887
+ ...data.label !== void 0 ? {
2888
+ label: data.label
2889
+ } : {},
2890
+ ...data.description !== void 0 ? {
2891
+ description: data.description
2892
+ } : {},
2893
+ ...data.icon !== void 0 ? {
2894
+ icon: data.icon
2895
+ } : {},
2896
+ ...data.tier !== void 0 ? {
2897
+ tier: data.tier
2898
+ } : {}
2899
+ }
2900
+ });
2901
+ return toFeatureRow(row);
2902
+ }
2903
+ async setQuotaBase(projectKey, quotaKey, data) {
2904
+ const row = await this.db.quotaCatalogEntry.update({
2905
+ where: {
2906
+ projectKey_quotaKey: {
2907
+ projectKey,
2908
+ quotaKey
2909
+ }
2910
+ },
2911
+ data: {
2912
+ ...data.label !== void 0 ? {
2913
+ label: data.label
2914
+ } : {},
2915
+ ...data.description !== void 0 ? {
2916
+ description: data.description
2917
+ } : {}
2918
+ }
2919
+ });
2920
+ return toQuotaRow(row);
2921
+ }
2922
+ };
2923
+ PrismaCatalogEntryRepository = _ts_decorate21([
2924
+ (0, import_common21.Injectable)(),
2925
+ _ts_param19(0, (0, import_common21.Inject)(PRISMA_CLIENT_TOKEN)),
2926
+ _ts_metadata19("design:type", Function),
2927
+ _ts_metadata19("design:paramtypes", [
2928
+ typeof PrismaLike === "undefined" ? Object : PrismaLike
2929
+ ])
2930
+ ], PrismaCatalogEntryRepository);
2931
+ function toI18n2(value) {
2932
+ if (value !== null && typeof value === "object" && !Array.isArray(value)) {
2933
+ return value;
2934
+ }
2935
+ return {};
2936
+ }
2937
+ __name(toI18n2, "toI18n");
2938
+ function toCapabilityRow(row) {
2939
+ return {
2940
+ id: row.id,
2941
+ projectKey: row.projectKey,
2942
+ capabilityKey: row.capabilityKey,
2943
+ label: row.label,
2944
+ description: row.description,
2945
+ featureKey: row.featureKey,
2946
+ bundleKey: row.bundleKey,
2947
+ codeStatus: row.codeStatus,
2948
+ owner: row.owner,
2949
+ kind: row.kind,
2950
+ replacementKey: row.replacementKey,
2951
+ deprecatedAt: row.deprecatedAt ? row.deprecatedAt.toISOString() : null,
2952
+ removalPlannedAt: row.removalPlannedAt ? row.removalPlannedAt.toISOString() : null,
2953
+ reason: row.reason,
2954
+ i18n: toI18n2(row.i18n),
2955
+ sortOrder: row.sortOrder,
2956
+ createdAt: row.createdAt.toISOString(),
2957
+ updatedAt: row.updatedAt.toISOString(),
2958
+ deletedAt: row.deletedAt ? row.deletedAt.toISOString() : null
2959
+ };
2960
+ }
2961
+ __name(toCapabilityRow, "toCapabilityRow");
2962
+ function toFeatureRow(row) {
2963
+ return {
2964
+ id: row.id,
2965
+ projectKey: row.projectKey,
2966
+ featureKey: row.featureKey,
2967
+ label: row.label,
2968
+ description: row.description,
2969
+ marketingLabel: row.marketingLabel,
2970
+ marketingDescription: row.marketingDescription,
2971
+ icon: row.icon,
2972
+ tier: row.tier,
2973
+ discoveryStatus: row.discoveryStatus,
2974
+ requires: row.requires,
2975
+ replaces: row.replaces,
2976
+ successorKey: row.successorKey,
2977
+ approvedAt: row.approvedAt ? row.approvedAt.toISOString() : null,
2978
+ approvedBy: row.approvedBy,
2979
+ approvedSignature: row.approvedSignature,
2980
+ plannedOnly: row.plannedOnly,
2981
+ core: row.core,
2982
+ i18n: toI18n2(row.i18n),
2983
+ sortOrder: row.sortOrder,
2984
+ createdAt: row.createdAt.toISOString(),
2985
+ updatedAt: row.updatedAt.toISOString(),
2986
+ deletedAt: row.deletedAt ? row.deletedAt.toISOString() : null
2987
+ };
2988
+ }
2989
+ __name(toFeatureRow, "toFeatureRow");
2990
+ function toQuotaRow(row) {
2991
+ return {
2992
+ id: row.id,
2993
+ projectKey: row.projectKey,
2994
+ quotaKey: row.quotaKey,
2995
+ label: row.label,
2996
+ description: row.description,
2997
+ unit: row.unit,
2998
+ featureKey: row.featureKey,
2999
+ usageProvider: row.usageProvider,
3000
+ enforcementMode: row.enforcementMode,
3001
+ discoveryStatus: row.discoveryStatus,
3002
+ replaces: row.replaces,
3003
+ successorKey: row.successorKey,
3004
+ approvedAt: row.approvedAt ? row.approvedAt.toISOString() : null,
3005
+ approvedBy: row.approvedBy,
3006
+ approvedSignature: row.approvedSignature,
3007
+ i18n: toI18n2(row.i18n),
3008
+ sortOrder: row.sortOrder,
3009
+ createdAt: row.createdAt.toISOString(),
3010
+ updatedAt: row.updatedAt.toISOString(),
3011
+ deletedAt: row.deletedAt ? row.deletedAt.toISOString() : null
3012
+ };
3013
+ }
3014
+ __name(toQuotaRow, "toQuotaRow");
3015
+
3016
+ // src/prisma-marketing-projection.repository.ts
3017
+ var import_common22 = require("@nestjs/common");
3018
+ function _ts_decorate22(decorators, target, key, desc) {
3019
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
3020
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
3021
+ 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;
3022
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
3023
+ }
3024
+ __name(_ts_decorate22, "_ts_decorate");
3025
+ function _ts_metadata20(k, v) {
3026
+ if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
3027
+ }
3028
+ __name(_ts_metadata20, "_ts_metadata");
3029
+ function _ts_param20(paramIndex, decorator) {
3030
+ return function(target, key) {
3031
+ decorator(target, key, paramIndex);
3032
+ };
3033
+ }
3034
+ __name(_ts_param20, "_ts_param");
3035
+ var PrismaMarketingProjectionRepository = class {
3036
+ static {
3037
+ __name(this, "PrismaMarketingProjectionRepository");
3038
+ }
3039
+ prisma;
3040
+ constructor(prisma) {
3041
+ this.prisma = prisma;
3042
+ }
3043
+ get db() {
3044
+ return this.prisma;
3045
+ }
3046
+ async list(filter) {
3047
+ const rows = await this.db.marketingProjection.findMany({
3048
+ where: {
3049
+ projectKey: filter.projectKey,
3050
+ ...filter.targetType ? {
3051
+ targetType: filter.targetType
3052
+ } : {},
3053
+ ...filter.targetVersionId ? {
3054
+ targetVersionId: filter.targetVersionId
3055
+ } : {},
3056
+ ...filter.locale ? {
3057
+ locale: filter.locale
3058
+ } : {}
3059
+ },
3060
+ orderBy: [
3061
+ {
3062
+ priority: "desc"
3063
+ },
3064
+ {
3065
+ displayLabel: "asc"
3066
+ }
3067
+ ]
3068
+ });
3069
+ return rows.map(toRow);
3070
+ }
3071
+ async findById(id) {
3072
+ const row = await this.db.marketingProjection.findUnique({
3073
+ where: {
3074
+ id
3075
+ }
3076
+ });
3077
+ return row ? toRow(row) : null;
3078
+ }
3079
+ async findByTarget(targetType, targetVersionId, locale) {
3080
+ const row = await this.db.marketingProjection.findUnique({
3081
+ where: {
3082
+ targetType_targetVersionId_locale: {
3083
+ targetType,
3084
+ targetVersionId,
3085
+ locale
3086
+ }
3087
+ }
3088
+ });
3089
+ return row ? toRow(row) : null;
3090
+ }
3091
+ async create(data) {
3092
+ const row = await this.db.marketingProjection.create({
3093
+ data: {
3094
+ projectKey: data.projectKey,
3095
+ targetType: data.targetType,
3096
+ targetVersionId: data.targetVersionId,
3097
+ locale: data.locale ?? "de",
3098
+ displayLabel: data.displayLabel,
3099
+ description: data.description,
3100
+ visible: data.visible ?? true,
3101
+ badge: data.badge ?? "",
3102
+ topFeatures: data.topFeatures ?? [],
3103
+ trialEnabled: data.trialEnabled ?? false,
3104
+ trialDays: data.trialDays ?? 30,
3105
+ priceTag: data.priceTag ?? null,
3106
+ ctaLabel: data.ctaLabel ?? null,
3107
+ priority: data.priority ?? 0,
3108
+ highlight: data.highlight ?? false
3109
+ }
3110
+ });
3111
+ return toRow(row);
3112
+ }
3113
+ async update(id, data) {
3114
+ const row = await this.db.marketingProjection.update({
3115
+ where: {
3116
+ id
3117
+ },
3118
+ data: {
3119
+ ...data.displayLabel !== void 0 ? {
3120
+ displayLabel: data.displayLabel
3121
+ } : {},
3122
+ ...data.description !== void 0 ? {
3123
+ description: data.description
3124
+ } : {},
3125
+ ...data.visible !== void 0 ? {
3126
+ visible: data.visible
3127
+ } : {},
3128
+ ...data.badge !== void 0 ? {
3129
+ badge: data.badge
3130
+ } : {},
3131
+ ...data.topFeatures !== void 0 ? {
3132
+ topFeatures: data.topFeatures
3133
+ } : {},
3134
+ ...data.trialEnabled !== void 0 ? {
3135
+ trialEnabled: data.trialEnabled
3136
+ } : {},
3137
+ ...data.trialDays !== void 0 ? {
3138
+ trialDays: data.trialDays
3139
+ } : {},
3140
+ ...data.priceTag !== void 0 ? {
3141
+ priceTag: data.priceTag
3142
+ } : {},
3143
+ ...data.ctaLabel !== void 0 ? {
3144
+ ctaLabel: data.ctaLabel
3145
+ } : {},
3146
+ ...data.priority !== void 0 ? {
3147
+ priority: data.priority
3148
+ } : {},
3149
+ ...data.highlight !== void 0 ? {
3150
+ highlight: data.highlight
3151
+ } : {}
3152
+ }
3153
+ });
3154
+ return toRow(row);
3155
+ }
3156
+ async delete(id) {
3157
+ await this.db.marketingProjection.delete({
3158
+ where: {
3159
+ id
3160
+ }
3161
+ });
3162
+ }
3163
+ };
3164
+ PrismaMarketingProjectionRepository = _ts_decorate22([
3165
+ (0, import_common22.Injectable)(),
3166
+ _ts_param20(0, (0, import_common22.Inject)(PRISMA_CLIENT_TOKEN)),
3167
+ _ts_metadata20("design:type", Function),
3168
+ _ts_metadata20("design:paramtypes", [
3169
+ typeof PrismaLike === "undefined" ? Object : PrismaLike
3170
+ ])
3171
+ ], PrismaMarketingProjectionRepository);
3172
+ function toTopFeatures(value) {
3173
+ return Array.isArray(value) ? value : [];
3174
+ }
3175
+ __name(toTopFeatures, "toTopFeatures");
3176
+ function toRow(row) {
3177
+ return {
3178
+ id: row.id,
3179
+ projectKey: row.projectKey,
3180
+ targetType: row.targetType,
3181
+ targetVersionId: row.targetVersionId,
3182
+ locale: row.locale,
3183
+ displayLabel: row.displayLabel,
3184
+ description: row.description,
3185
+ visible: row.visible,
3186
+ badge: row.badge,
3187
+ topFeatures: toTopFeatures(row.topFeatures),
3188
+ trialEnabled: row.trialEnabled,
3189
+ trialDays: row.trialDays,
3190
+ priceTag: row.priceTag,
3191
+ ctaLabel: row.ctaLabel,
3192
+ priority: row.priority,
3193
+ highlight: row.highlight,
3194
+ createdAt: row.createdAt.toISOString(),
3195
+ updatedAt: row.updatedAt.toISOString()
3196
+ };
3197
+ }
3198
+ __name(toRow, "toRow");
3199
+
3200
+ // src/prisma-marketing-settings.repository.ts
3201
+ var import_common23 = require("@nestjs/common");
3202
+ function _ts_decorate23(decorators, target, key, desc) {
3203
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
3204
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
3205
+ 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;
3206
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
3207
+ }
3208
+ __name(_ts_decorate23, "_ts_decorate");
3209
+ function _ts_metadata21(k, v) {
3210
+ if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
3211
+ }
3212
+ __name(_ts_metadata21, "_ts_metadata");
3213
+ function _ts_param21(paramIndex, decorator) {
3214
+ return function(target, key) {
3215
+ decorator(target, key, paramIndex);
3216
+ };
3217
+ }
3218
+ __name(_ts_param21, "_ts_param");
3219
+ var PrismaMarketingSettingsRepository = class {
3220
+ static {
3221
+ __name(this, "PrismaMarketingSettingsRepository");
3222
+ }
3223
+ prisma;
3224
+ constructor(prisma) {
3225
+ this.prisma = prisma;
3226
+ }
3227
+ get db() {
3228
+ return this.prisma;
3229
+ }
3230
+ async get(projectKey) {
3231
+ const row = await this.db.marketingSettings.findUnique({
3232
+ where: {
3233
+ projectKey
3234
+ }
3235
+ });
3236
+ return row ? toRow2(row) : null;
3237
+ }
3238
+ async upsert(projectKey, data) {
3239
+ const row = await this.db.marketingSettings.upsert({
3240
+ where: {
3241
+ projectKey
3242
+ },
3243
+ create: {
3244
+ projectKey,
3245
+ activeLocales: data.activeLocales
3246
+ },
3247
+ update: {
3248
+ activeLocales: data.activeLocales
3249
+ }
3250
+ });
3251
+ return toRow2(row);
3252
+ }
3253
+ };
3254
+ PrismaMarketingSettingsRepository = _ts_decorate23([
3255
+ (0, import_common23.Injectable)(),
3256
+ _ts_param21(0, (0, import_common23.Inject)(PRISMA_CLIENT_TOKEN)),
3257
+ _ts_metadata21("design:type", Function),
3258
+ _ts_metadata21("design:paramtypes", [
3259
+ typeof PrismaLike === "undefined" ? Object : PrismaLike
3260
+ ])
3261
+ ], PrismaMarketingSettingsRepository);
3262
+ function toRow2(row) {
3263
+ return {
3264
+ projectKey: row.projectKey,
3265
+ activeLocales: toStringArray(row.activeLocales),
3266
+ updatedAt: row.updatedAt.toISOString()
3267
+ };
3268
+ }
3269
+ __name(toRow2, "toRow");
3270
+
3271
+ // src/prisma-promotion.repository.ts
3272
+ var import_common24 = require("@nestjs/common");
3273
+ function _ts_decorate24(decorators, target, key, desc) {
3274
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
3275
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
3276
+ 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;
3277
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
3278
+ }
3279
+ __name(_ts_decorate24, "_ts_decorate");
3280
+ function _ts_metadata22(k, v) {
3281
+ if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
3282
+ }
3283
+ __name(_ts_metadata22, "_ts_metadata");
3284
+ function _ts_param22(paramIndex, decorator) {
3285
+ return function(target, key) {
3286
+ decorator(target, key, paramIndex);
3287
+ };
3288
+ }
3289
+ __name(_ts_param22, "_ts_param");
3290
+ var PrismaPromotionRepository = class {
3291
+ static {
3292
+ __name(this, "PrismaPromotionRepository");
3293
+ }
3294
+ prisma;
3295
+ constructor(prisma) {
3296
+ this.prisma = prisma;
3297
+ }
3298
+ get db() {
3299
+ return this.prisma;
3300
+ }
3301
+ async list(filter) {
3302
+ const rows = await this.db.promotion.findMany({
3303
+ where: {
3304
+ projectKey: filter.projectKey
3305
+ },
3306
+ orderBy: [
3307
+ {
3308
+ validFrom: "desc"
3309
+ }
3310
+ ]
3311
+ });
3312
+ return rows.map(toRow3);
3313
+ }
3314
+ async findById(id) {
3315
+ const row = await this.db.promotion.findUnique({
3316
+ where: {
3317
+ id
3318
+ }
3319
+ });
3320
+ return row ? toRow3(row) : null;
3321
+ }
3322
+ async create(data) {
3323
+ const row = await this.db.promotion.create({
3324
+ data: {
3325
+ projectKey: data.projectKey,
3326
+ internalLabel: data.internalLabel,
3327
+ type: data.type,
3328
+ value: data.value,
3329
+ targetType: data.targetType ?? "PLAN",
3330
+ appliesTo: data.appliesTo ?? [],
3331
+ billingCycle: data.billingCycle ?? "both",
3332
+ validFrom: new Date(data.validFrom),
3333
+ validTo: new Date(data.validTo),
3334
+ priority: data.priority ?? 0,
3335
+ requiresCoupon: data.requiresCoupon ?? false,
3336
+ codes: data.codes ?? [],
3337
+ color: data.color ?? "#2563eb",
3338
+ i18n: data.i18n ?? {},
3339
+ // Null/undefined restriction is left off so the nullable column
3340
+ // stays SQL NULL (= all locales).
3341
+ ...Array.isArray(data.onlyLocales) ? {
3342
+ onlyLocales: data.onlyLocales
3343
+ } : {}
3344
+ }
3345
+ });
3346
+ return toRow3(row);
3347
+ }
3348
+ async update(id, data) {
3349
+ if (data.onlyLocales === null) {
3350
+ await this.prisma.$executeRaw`
3351
+ UPDATE promotions SET "onlyLocales" = NULL, "updatedAt" = NOW() WHERE id = ${id}`;
3352
+ }
3353
+ const row = await this.db.promotion.update({
3354
+ where: {
3355
+ id
3356
+ },
3357
+ data: {
3358
+ ...data.internalLabel !== void 0 ? {
3359
+ internalLabel: data.internalLabel
3360
+ } : {},
3361
+ ...data.type !== void 0 ? {
3362
+ type: data.type
3363
+ } : {},
3364
+ ...data.value !== void 0 ? {
3365
+ value: data.value
3366
+ } : {},
3367
+ ...data.appliesTo !== void 0 ? {
3368
+ appliesTo: data.appliesTo
3369
+ } : {},
3370
+ ...data.targetType !== void 0 ? {
3371
+ targetType: data.targetType
3372
+ } : {},
3373
+ ...data.billingCycle !== void 0 ? {
3374
+ billingCycle: data.billingCycle
3375
+ } : {},
3376
+ ...data.validFrom !== void 0 ? {
3377
+ validFrom: new Date(data.validFrom)
3378
+ } : {},
3379
+ ...data.validTo !== void 0 ? {
3380
+ validTo: new Date(data.validTo)
3381
+ } : {},
3382
+ ...data.priority !== void 0 ? {
3383
+ priority: data.priority
3384
+ } : {},
3385
+ ...data.requiresCoupon !== void 0 ? {
3386
+ requiresCoupon: data.requiresCoupon
3387
+ } : {},
3388
+ ...data.codes !== void 0 ? {
3389
+ codes: data.codes
3390
+ } : {},
3391
+ ...data.color !== void 0 ? {
3392
+ color: data.color
3393
+ } : {},
3394
+ ...data.i18n !== void 0 ? {
3395
+ i18n: data.i18n
3396
+ } : {},
3397
+ ...Array.isArray(data.onlyLocales) ? {
3398
+ onlyLocales: data.onlyLocales
3399
+ } : {}
3400
+ }
3401
+ });
3402
+ return toRow3(row);
3403
+ }
3404
+ async delete(id) {
3405
+ await this.db.promotion.delete({
3406
+ where: {
3407
+ id
3408
+ }
3409
+ });
3410
+ }
3411
+ };
3412
+ PrismaPromotionRepository = _ts_decorate24([
3413
+ (0, import_common24.Injectable)(),
3414
+ _ts_param22(0, (0, import_common24.Inject)(PRISMA_CLIENT_TOKEN)),
3415
+ _ts_metadata22("design:type", Function),
3416
+ _ts_metadata22("design:paramtypes", [
3417
+ typeof PrismaLike === "undefined" ? Object : PrismaLike
3418
+ ])
3419
+ ], PrismaPromotionRepository);
3420
+ function toPromotionValue(value) {
3421
+ if (typeof value === "number") return value;
3422
+ if (value !== null && typeof value === "object" && !Array.isArray(value)) {
3423
+ const obj = value;
3424
+ return {
3425
+ price: Number(obj.price),
3426
+ months: Number(obj.months)
3427
+ };
3428
+ }
3429
+ throw new Error(`Promotion.value has an unexpected shape: ${JSON.stringify(value)}`);
3430
+ }
3431
+ __name(toPromotionValue, "toPromotionValue");
3432
+ function toNullableStringArray(value) {
3433
+ return Array.isArray(value) ? value : null;
3434
+ }
3435
+ __name(toNullableStringArray, "toNullableStringArray");
3436
+ function toPromotionI18n(value) {
3437
+ if (value !== null && typeof value === "object" && !Array.isArray(value)) {
3438
+ return value;
3439
+ }
3440
+ return {};
3441
+ }
3442
+ __name(toPromotionI18n, "toPromotionI18n");
3443
+ function toRow3(row) {
3444
+ return {
3445
+ id: row.id,
3446
+ projectKey: row.projectKey,
3447
+ internalLabel: row.internalLabel,
3448
+ type: row.type,
3449
+ value: toPromotionValue(row.value),
3450
+ appliesTo: toStringArray(row.appliesTo),
3451
+ targetType: row.targetType,
3452
+ billingCycle: row.billingCycle,
3453
+ validFrom: row.validFrom.toISOString().slice(0, 10),
3454
+ validTo: row.validTo.toISOString().slice(0, 10),
3455
+ priority: row.priority,
3456
+ onlyLocales: toNullableStringArray(row.onlyLocales),
3457
+ requiresCoupon: row.requiresCoupon,
3458
+ codes: toStringArray(row.codes),
3459
+ color: row.color,
3460
+ i18n: toPromotionI18n(row.i18n),
3461
+ createdAt: row.createdAt.toISOString(),
3462
+ updatedAt: row.updatedAt.toISOString()
3463
+ };
3464
+ }
3465
+ __name(toRow3, "toRow");
3466
+
3467
+ // src/prisma-subscription-contract.repository.ts
3468
+ var import_common25 = require("@nestjs/common");
3469
+ function _ts_decorate25(decorators, target, key, desc) {
3470
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
3471
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
3472
+ 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;
3473
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
3474
+ }
3475
+ __name(_ts_decorate25, "_ts_decorate");
3476
+ function _ts_metadata23(k, v) {
3477
+ if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
3478
+ }
3479
+ __name(_ts_metadata23, "_ts_metadata");
3480
+ function _ts_param23(paramIndex, decorator) {
3481
+ return function(target, key) {
3482
+ decorator(target, key, paramIndex);
3483
+ };
3484
+ }
3485
+ __name(_ts_param23, "_ts_param");
3486
+ var ACTIVE_CONTRACT_STATUSES = [
3487
+ "active",
3488
+ "scheduled"
3489
+ ];
3490
+ var PrismaSubscriptionContractRepository = class {
3491
+ static {
3492
+ __name(this, "PrismaSubscriptionContractRepository");
3493
+ }
3494
+ prisma;
3495
+ constructor(prisma) {
3496
+ this.prisma = prisma;
3497
+ }
3498
+ get db() {
3499
+ return this.prisma;
3500
+ }
3501
+ async list(filter) {
3502
+ const rows = await this.db.subscriptionContract.findMany({
3503
+ where: {
3504
+ ...filter.projectKey ? {
3505
+ projectKey: filter.projectKey
3506
+ } : {},
3507
+ ...filter.tenantId ? {
3508
+ tenantId: filter.tenantId
3509
+ } : {},
3510
+ ...filter.status ? {
3511
+ status: filter.status
3512
+ } : {},
3513
+ ...filter.asOf ? {
3514
+ effectiveFrom: {
3515
+ lte: filter.asOf
3516
+ },
3517
+ OR: [
3518
+ {
3519
+ effectiveUntil: null
3520
+ },
3521
+ {
3522
+ effectiveUntil: {
3523
+ gt: filter.asOf
3524
+ }
3525
+ }
3526
+ ]
3527
+ } : {}
3528
+ },
3529
+ include: {
3530
+ lineItems: true
3531
+ },
3532
+ orderBy: [
3533
+ {
3534
+ effectiveFrom: "desc"
3535
+ },
3536
+ {
3537
+ createdAt: "desc"
3538
+ }
3539
+ ]
3540
+ });
3541
+ return rows.map(toRecord4);
3542
+ }
3543
+ async findById(contractId) {
3544
+ const row = await this.db.subscriptionContract.findUnique({
3545
+ where: {
3546
+ id: contractId
3547
+ },
3548
+ include: {
3549
+ lineItems: true
3550
+ }
3551
+ });
3552
+ return row ? toRecord4(row) : null;
3553
+ }
3554
+ async findActiveByTenantId(tenantId, asOf = /* @__PURE__ */ new Date()) {
3555
+ const row = await this.db.subscriptionContract.findFirst({
3556
+ where: {
3557
+ tenantId,
3558
+ status: {
3559
+ in: ACTIVE_CONTRACT_STATUSES
3560
+ },
3561
+ effectiveFrom: {
3562
+ lte: asOf
3563
+ },
3564
+ OR: [
3565
+ {
3566
+ effectiveUntil: null
3567
+ },
3568
+ {
3569
+ effectiveUntil: {
3570
+ gt: asOf
3571
+ }
3572
+ }
3573
+ ]
3574
+ },
3575
+ include: {
3576
+ lineItems: true
3577
+ },
3578
+ orderBy: [
3579
+ {
3580
+ effectiveFrom: "desc"
3581
+ },
3582
+ {
3583
+ createdAt: "desc"
3584
+ }
3585
+ ]
3586
+ });
3587
+ return row ? toRecord4(row) : null;
3588
+ }
3589
+ async create(data) {
3590
+ const row = await this.db.subscriptionContract.create({
3591
+ data: {
3592
+ projectKey: data.projectKey,
3593
+ tenantId: data.tenantId,
3594
+ status: data.status ?? "active",
3595
+ effectiveFrom: data.effectiveFrom,
3596
+ effectiveUntil: data.effectiveUntil ?? null,
3597
+ originalOfferId: data.originalOfferId ?? null,
3598
+ originalPlanVersionId: data.originalPlanVersionId ?? null,
3599
+ originalBundleVersionIds: data.originalBundleVersionIds ?? [],
3600
+ priceSnapshot: data.priceSnapshot,
3601
+ promotionSnapshots: data.promotionSnapshots ?? [],
3602
+ promoCodeSnapshots: data.promoCodeSnapshots ?? [],
3603
+ // Nullable JSON columns are omitted when absent so they stay SQL
3604
+ // NULL (the DbNull sentinel is not available in this package).
3605
+ ...data.entitlementSnapshot != null ? {
3606
+ entitlementSnapshot: data.entitlementSnapshot
3607
+ } : {},
3608
+ ...data.termsSnapshot != null ? {
3609
+ termsSnapshot: data.termsSnapshot
3610
+ } : {},
3611
+ lineItems: {
3612
+ create: data.lineItems.map(toLineItemCreate)
3613
+ }
3614
+ },
3615
+ include: {
3616
+ lineItems: true
3617
+ }
3618
+ });
3619
+ return toRecord4(row);
3620
+ }
3621
+ async terminate(contractId, data) {
3622
+ const row = await this.db.subscriptionContract.update({
3623
+ where: {
3624
+ id: contractId
3625
+ },
3626
+ data: {
3627
+ effectiveUntil: data.effectiveUntil,
3628
+ status: data.status
3629
+ },
3630
+ include: {
3631
+ lineItems: true
3632
+ }
3633
+ });
3634
+ return toRecord4(row);
3635
+ }
3636
+ };
3637
+ PrismaSubscriptionContractRepository = _ts_decorate25([
3638
+ (0, import_common25.Injectable)(),
3639
+ _ts_param23(0, (0, import_common25.Inject)(PRISMA_CLIENT_TOKEN)),
3640
+ _ts_metadata23("design:type", Function),
3641
+ _ts_metadata23("design:paramtypes", [
3642
+ typeof PrismaLike === "undefined" ? Object : PrismaLike
3643
+ ])
3644
+ ], PrismaSubscriptionContractRepository);
3645
+ function toLineItemCreate(item) {
3646
+ return {
3647
+ kind: item.kind,
3648
+ sourceKey: item.sourceKey,
3649
+ sourceVersionId: item.sourceVersionId ?? null,
3650
+ titleSnapshot: item.titleSnapshot,
3651
+ descriptionSnapshot: item.descriptionSnapshot ?? null,
3652
+ quantity: item.quantity,
3653
+ unit: item.unit ?? null,
3654
+ priceNet: item.priceNet,
3655
+ priceGross: item.priceGross,
3656
+ billingCycle: item.billingCycle,
3657
+ minimumTermUntil: item.minimumTermUntil ?? null,
3658
+ featuresSnapshot: item.featuresSnapshot,
3659
+ quotaEffectsSnapshot: item.quotaEffectsSnapshot,
3660
+ ...item.metadata != null ? {
3661
+ metadata: item.metadata
3662
+ } : {}
3663
+ };
3664
+ }
3665
+ __name(toLineItemCreate, "toLineItemCreate");
3666
+ function isPlainObject2(value) {
3667
+ return value !== null && typeof value === "object" && !Array.isArray(value);
3668
+ }
3669
+ __name(isPlainObject2, "isPlainObject");
3670
+ function toUnknownArray(value) {
3671
+ return Array.isArray(value) ? value : [];
3672
+ }
3673
+ __name(toUnknownArray, "toUnknownArray");
3674
+ function toRecordOrNull(value) {
3675
+ return isPlainObject2(value) ? value : null;
3676
+ }
3677
+ __name(toRecordOrNull, "toRecordOrNull");
3678
+ function toLineItem(row) {
3679
+ return {
3680
+ id: row.id,
3681
+ contractId: row.contractId,
3682
+ kind: row.kind,
3683
+ sourceKey: row.sourceKey,
3684
+ sourceVersionId: row.sourceVersionId,
3685
+ titleSnapshot: row.titleSnapshot,
3686
+ descriptionSnapshot: row.descriptionSnapshot,
3687
+ quantity: row.quantity,
3688
+ unit: row.unit,
3689
+ priceNet: Number(row.priceNet),
3690
+ priceGross: Number(row.priceGross),
3691
+ billingCycle: row.billingCycle,
3692
+ minimumTermUntil: row.minimumTermUntil,
3693
+ featuresSnapshot: toStringArray(row.featuresSnapshot),
3694
+ quotaEffectsSnapshot: toQuotaMap(row.quotaEffectsSnapshot),
3695
+ metadata: toRecordOrNull(row.metadata),
3696
+ createdAt: row.createdAt
3697
+ };
3698
+ }
3699
+ __name(toLineItem, "toLineItem");
3700
+ function toRecord4(row) {
3701
+ return {
3702
+ id: row.id,
3703
+ projectKey: row.projectKey,
3704
+ tenantId: row.tenantId,
3705
+ status: row.status,
3706
+ effectiveFrom: row.effectiveFrom,
3707
+ effectiveUntil: row.effectiveUntil,
3708
+ originalOfferId: row.originalOfferId,
3709
+ originalPlanVersionId: row.originalPlanVersionId,
3710
+ originalBundleVersionIds: toStringArray(row.originalBundleVersionIds),
3711
+ entitlementSnapshot: isPlainObject2(row.entitlementSnapshot) ? row.entitlementSnapshot : null,
3712
+ priceSnapshot: row.priceSnapshot,
3713
+ promotionSnapshots: toUnknownArray(row.promotionSnapshots),
3714
+ promoCodeSnapshots: toUnknownArray(row.promoCodeSnapshots),
3715
+ termsSnapshot: toRecordOrNull(row.termsSnapshot),
3716
+ lineItems: row.lineItems.map(toLineItem),
3717
+ createdAt: row.createdAt,
3718
+ updatedAt: row.updatedAt
3719
+ };
3720
+ }
3721
+ __name(toRecord4, "toRecord");
1463
3722
  // Annotate the CommonJS export names for ESM import in node:
1464
3723
  0 && (module.exports = {
1465
3724
  AsyncLocalRlsBypassAdapter,
@@ -1468,16 +3727,25 @@ __name(buildProvisioning, "buildProvisioning");
1468
3727
  PrismaAuditAdapter,
1469
3728
  PrismaAuditQueryAdapter,
1470
3729
  PrismaAuditStatsAdapter,
3730
+ PrismaBundleRepository,
3731
+ PrismaCatalogEntryRepository,
3732
+ PrismaMarketingProjectionRepository,
3733
+ PrismaMarketingSettingsRepository,
1471
3734
  PrismaMfaAdapter,
1472
3735
  PrismaPlanCatalogImportSink,
1473
3736
  PrismaPlanCatalogReadSink,
3737
+ PrismaPlanRepository,
1474
3738
  PrismaPlanVersionRepository,
1475
3739
  PrismaPromoCodeRedemptionRepository,
1476
3740
  PrismaPromoCodeRepository,
1477
3741
  PrismaPromoCodeValidationLogRepository,
1478
3742
  PrismaPromoSubscriptionLookup,
3743
+ PrismaPromotionRepository,
3744
+ PrismaSubscriptionBundleRepository,
3745
+ PrismaSubscriptionContractRepository,
1479
3746
  PrismaSubscriptionRepository,
1480
3747
  PrismaSuperAdminBootstrapAdapter,
3748
+ PrismaTenantSubscriptionWriteAdapter,
1481
3749
  PrismaTransactionRunner,
1482
3750
  ZeroPromoRevenueDeductionAggregator,
1483
3751
  buildActorTag,