@saasicat/adapter-prisma 0.26.1 → 1.0.0-rc.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/LICENSE +90 -201
- package/README.md +4 -4
- package/dist/.build-stamp +1 -0
- package/dist/index.cjs +149 -55
- package/dist/index.d.cts +100 -5
- package/dist/index.d.ts +100 -5
- package/dist/index.js +147 -55
- package/package.json +8 -8
package/dist/index.cjs
CHANGED
|
@@ -52,10 +52,12 @@ __export(index_exports, {
|
|
|
52
52
|
PrismaTenantSubscriptionWriteAdapter: () => PrismaTenantSubscriptionWriteAdapter,
|
|
53
53
|
PrismaTransactionRunner: () => PrismaTransactionRunner,
|
|
54
54
|
ZeroPromoRevenueDeductionAggregator: () => ZeroPromoRevenueDeductionAggregator,
|
|
55
|
+
assertDelegatesExist: () => assertDelegatesExist,
|
|
55
56
|
buildActorTag: () => buildActorTag,
|
|
56
57
|
createPrismaPlanBindingResolver: () => createPrismaPlanBindingResolver,
|
|
57
58
|
getPrismaDelegate: () => getPrismaDelegate,
|
|
58
59
|
prismaPersistence: () => prismaPersistence,
|
|
60
|
+
resolveAdminResourcesSchema: () => resolveAdminResourcesSchema,
|
|
59
61
|
resolvePrismaSchemaOptions: () => resolvePrismaSchemaOptions
|
|
60
62
|
});
|
|
61
63
|
module.exports = __toCommonJS(index_exports);
|
|
@@ -410,7 +412,7 @@ __name(createPrismaPlanBindingResolver, "createPrismaPlanBindingResolver");
|
|
|
410
412
|
function getPrismaDelegate(client, delegateName) {
|
|
411
413
|
const delegate = client?.[delegateName];
|
|
412
414
|
if (!delegate || typeof delegate !== "object") {
|
|
413
|
-
throw new Error(`Prisma client has no '${delegateName}' delegate.`);
|
|
415
|
+
throw new Error(`Prisma client has no '${delegateName}' delegate. If your model is called something else, map it \u2014 \`adminResources: { delegates: { tenant: "organization" } }\` for the SuperAdmin resources, \`schema\` for the plan binding.`);
|
|
414
416
|
}
|
|
415
417
|
return delegate;
|
|
416
418
|
}
|
|
@@ -434,6 +436,65 @@ function asPlanIdentityClient(client) {
|
|
|
434
436
|
}
|
|
435
437
|
__name(asPlanIdentityClient, "asPlanIdentityClient");
|
|
436
438
|
|
|
439
|
+
// src/admin-resources-schema.ts
|
|
440
|
+
var DEFAULTS = {
|
|
441
|
+
delegates: {
|
|
442
|
+
tenant: "tenant",
|
|
443
|
+
user: "user",
|
|
444
|
+
subscription: "subscription"
|
|
445
|
+
},
|
|
446
|
+
tenant: {
|
|
447
|
+
slug: "slug",
|
|
448
|
+
name: "name",
|
|
449
|
+
isActive: "isActive",
|
|
450
|
+
deletedAt: "deletedAt",
|
|
451
|
+
users: "users",
|
|
452
|
+
subscription: "subscription"
|
|
453
|
+
},
|
|
454
|
+
user: {
|
|
455
|
+
email: "email",
|
|
456
|
+
firstName: "firstName",
|
|
457
|
+
lastName: "lastName",
|
|
458
|
+
isActive: "isActive",
|
|
459
|
+
tenant: "tenant"
|
|
460
|
+
}
|
|
461
|
+
};
|
|
462
|
+
function resolveAdminResourcesSchema(delegates = {}, fields = {}) {
|
|
463
|
+
return {
|
|
464
|
+
delegates: {
|
|
465
|
+
...DEFAULTS.delegates,
|
|
466
|
+
...delegates
|
|
467
|
+
},
|
|
468
|
+
tenant: {
|
|
469
|
+
...DEFAULTS.tenant,
|
|
470
|
+
...fields.tenant
|
|
471
|
+
},
|
|
472
|
+
user: {
|
|
473
|
+
...DEFAULTS.user,
|
|
474
|
+
...fields.user
|
|
475
|
+
}
|
|
476
|
+
};
|
|
477
|
+
}
|
|
478
|
+
__name(resolveAdminResourcesSchema, "resolveAdminResourcesSchema");
|
|
479
|
+
function assertDelegatesExist(client, schema) {
|
|
480
|
+
const available = new Set(delegateNamesOf(client));
|
|
481
|
+
const missing = Object.entries(schema.delegates).filter(([, delegateName]) => !available.has(delegateName)).map(([role, delegateName]) => `${role} \u2192 '${delegateName}'`);
|
|
482
|
+
if (missing.length === 0) return;
|
|
483
|
+
throw new Error(`PrismaAdminResourcesAdapter is mapped to delegates the Prisma client does not have: ${missing.join(", ")}. The client offers: ${[
|
|
484
|
+
...available
|
|
485
|
+
].sort().join(", ") || "(none)"}. Map them with \`adminResources: { delegates: { tenant: "organization" } }\`, or implement \`AdminResourcesPort\` yourself if the shape differs rather than the names.`);
|
|
486
|
+
}
|
|
487
|
+
__name(assertDelegatesExist, "assertDelegatesExist");
|
|
488
|
+
function delegateNamesOf(client) {
|
|
489
|
+
if (!client || typeof client !== "object") return [];
|
|
490
|
+
return Object.keys(client).filter((key) => {
|
|
491
|
+
if (key.startsWith("$") || key.startsWith("_")) return false;
|
|
492
|
+
const value = client[key];
|
|
493
|
+
return typeof value === "object" && value !== null && typeof value.findMany === "function";
|
|
494
|
+
});
|
|
495
|
+
}
|
|
496
|
+
__name(delegateNamesOf, "delegateNamesOf");
|
|
497
|
+
|
|
437
498
|
// src/prisma-admin-resources.adapter.ts
|
|
438
499
|
var DEFAULT_LIST_LIMIT = 200;
|
|
439
500
|
var DEFAULT_AUDIT_LIMIT = 100;
|
|
@@ -445,41 +506,45 @@ var PrismaAdminResourcesAdapter = class {
|
|
|
445
506
|
metrics;
|
|
446
507
|
listLimit;
|
|
447
508
|
audit;
|
|
509
|
+
schema;
|
|
448
510
|
constructor(prisma, options = {}) {
|
|
449
511
|
this.prisma = prisma;
|
|
450
|
-
this.metrics = options.tenantMetrics ?? [
|
|
451
|
-
"users"
|
|
452
|
-
];
|
|
453
512
|
this.listLimit = options.listLimit ?? DEFAULT_LIST_LIMIT;
|
|
454
513
|
this.audit = new PrismaAuditQueryAdapter(prisma);
|
|
514
|
+
this.schema = resolveAdminResourcesSchema(options.delegates, options.fields);
|
|
515
|
+
this.metrics = options.tenantMetrics ?? [
|
|
516
|
+
this.schema.tenant.users
|
|
517
|
+
];
|
|
518
|
+
if (options.delegates) assertDelegatesExist(prisma, this.schema);
|
|
455
519
|
}
|
|
456
520
|
async listTenants(filter) {
|
|
521
|
+
const t = this.schema.tenant;
|
|
457
522
|
const where = {};
|
|
458
523
|
const active = parseActiveFilter(filter.status);
|
|
459
|
-
if (active !== void 0) where.isActive = active;
|
|
524
|
+
if (active !== void 0) where[t.isActive] = active;
|
|
460
525
|
if (filter.search) {
|
|
461
526
|
where.OR = [
|
|
462
527
|
{
|
|
463
|
-
slug: {
|
|
528
|
+
[t.slug]: {
|
|
464
529
|
contains: filter.search,
|
|
465
530
|
mode: "insensitive"
|
|
466
531
|
}
|
|
467
532
|
},
|
|
468
533
|
{
|
|
469
|
-
name: {
|
|
534
|
+
[t.name]: {
|
|
470
535
|
contains: filter.search,
|
|
471
536
|
mode: "insensitive"
|
|
472
537
|
}
|
|
473
538
|
}
|
|
474
539
|
];
|
|
475
540
|
}
|
|
476
|
-
if (filter.plan) where.subscription = {
|
|
541
|
+
if (filter.plan) where[t.subscription] = {
|
|
477
542
|
plan: filter.plan
|
|
478
543
|
};
|
|
479
544
|
const rows = await this.tenants().findMany({
|
|
480
545
|
where,
|
|
481
546
|
include: {
|
|
482
|
-
subscription: {
|
|
547
|
+
[t.subscription]: {
|
|
483
548
|
select: {
|
|
484
549
|
plan: true,
|
|
485
550
|
status: true
|
|
@@ -496,24 +561,25 @@ var PrismaAdminResourcesAdapter = class {
|
|
|
496
561
|
});
|
|
497
562
|
return rows.map((row) => ({
|
|
498
563
|
id: row.id,
|
|
499
|
-
slug: row.slug,
|
|
500
|
-
name: row.name,
|
|
501
|
-
isActive: row.isActive,
|
|
502
|
-
deletedAt: row.deletedAt?.toISOString() ?? null,
|
|
503
|
-
plan: row
|
|
504
|
-
status: row
|
|
564
|
+
slug: this.read(row, t.slug) ?? "",
|
|
565
|
+
name: this.read(row, t.name) ?? "",
|
|
566
|
+
isActive: this.read(row, t.isActive) ?? true,
|
|
567
|
+
deletedAt: this.read(row, t.deletedAt)?.toISOString() ?? null,
|
|
568
|
+
plan: this.subscriptionOf(row)?.plan ?? null,
|
|
569
|
+
status: this.subscriptionOf(row)?.status ?? null,
|
|
505
570
|
createdAt: row.createdAt.toISOString(),
|
|
506
571
|
...row._count ?? {}
|
|
507
572
|
}));
|
|
508
573
|
}
|
|
509
574
|
async getTenantDetail(slug) {
|
|
575
|
+
const t = this.schema.tenant;
|
|
510
576
|
const row = await this.tenants().findUnique({
|
|
511
577
|
where: {
|
|
512
|
-
slug
|
|
578
|
+
[t.slug]: slug
|
|
513
579
|
},
|
|
514
580
|
include: {
|
|
515
|
-
subscription: true,
|
|
516
|
-
users: {
|
|
581
|
+
[t.subscription]: true,
|
|
582
|
+
[t.users]: {
|
|
517
583
|
orderBy: {
|
|
518
584
|
createdAt: "asc"
|
|
519
585
|
}
|
|
@@ -526,31 +592,32 @@ var PrismaAdminResourcesAdapter = class {
|
|
|
526
592
|
if (!row) return null;
|
|
527
593
|
return {
|
|
528
594
|
id: row.id,
|
|
529
|
-
slug: row.slug,
|
|
530
|
-
name: row.name,
|
|
531
|
-
isActive: row.isActive,
|
|
532
|
-
subscription: row
|
|
533
|
-
plan: row.
|
|
534
|
-
status: row.
|
|
535
|
-
billingCycle: row.
|
|
536
|
-
isPilot: row.
|
|
537
|
-
trialEndsAt: row.
|
|
538
|
-
pilotEndsAt: row.
|
|
595
|
+
slug: this.read(row, t.slug) ?? slug,
|
|
596
|
+
name: this.read(row, t.name) ?? "",
|
|
597
|
+
isActive: this.read(row, t.isActive) ?? true,
|
|
598
|
+
subscription: this.subscriptionOf(row) ? {
|
|
599
|
+
plan: this.subscriptionOf(row).plan,
|
|
600
|
+
status: this.subscriptionOf(row).status,
|
|
601
|
+
billingCycle: this.subscriptionOf(row).billingCycle,
|
|
602
|
+
isPilot: this.subscriptionOf(row).isPilot,
|
|
603
|
+
trialEndsAt: this.subscriptionOf(row).trialEndsAt?.toISOString() ?? null,
|
|
604
|
+
pilotEndsAt: this.subscriptionOf(row).pilotEndsAt?.toISOString() ?? null
|
|
539
605
|
} : null,
|
|
540
|
-
users: (row.users ?? []).map((user) => ({
|
|
606
|
+
users: (this.read(row, t.users) ?? []).map((user) => ({
|
|
541
607
|
id: user.id,
|
|
542
|
-
email: user.email,
|
|
543
|
-
firstName: user.firstName ?? void 0,
|
|
544
|
-
lastName: user.lastName ?? void 0,
|
|
608
|
+
email: this.read(user, this.schema.user.email) ?? "",
|
|
609
|
+
firstName: this.read(user, this.schema.user.firstName) ?? void 0,
|
|
610
|
+
lastName: this.read(user, this.schema.user.lastName) ?? void 0,
|
|
545
611
|
createdAt: user.createdAt.toISOString()
|
|
546
612
|
})),
|
|
547
613
|
counts: row._count ?? {}
|
|
548
614
|
};
|
|
549
615
|
}
|
|
550
616
|
async setTenantActive(slug, active, subscriptionStatus) {
|
|
617
|
+
const t = this.schema.tenant;
|
|
551
618
|
const tenant = await this.tenants().findUnique({
|
|
552
619
|
where: {
|
|
553
|
-
slug
|
|
620
|
+
[t.slug]: slug
|
|
554
621
|
}
|
|
555
622
|
});
|
|
556
623
|
if (!tenant) return null;
|
|
@@ -559,7 +626,7 @@ var PrismaAdminResourcesAdapter = class {
|
|
|
559
626
|
id: tenant.id
|
|
560
627
|
},
|
|
561
628
|
data: {
|
|
562
|
-
isActive: active
|
|
629
|
+
[t.isActive]: active
|
|
563
630
|
}
|
|
564
631
|
});
|
|
565
632
|
await this.subscriptions().updateMany({
|
|
@@ -579,20 +646,22 @@ var PrismaAdminResourcesAdapter = class {
|
|
|
579
646
|
};
|
|
580
647
|
}
|
|
581
648
|
async listUsers(filter) {
|
|
649
|
+
const u = this.schema.user;
|
|
650
|
+
const tenantSlug = this.schema.tenant.slug;
|
|
582
651
|
const where = {};
|
|
583
|
-
if (filter.q) where.email = {
|
|
652
|
+
if (filter.q) where[u.email] = {
|
|
584
653
|
contains: filter.q,
|
|
585
654
|
mode: "insensitive"
|
|
586
655
|
};
|
|
587
|
-
if (filter.tenant) where.tenant = {
|
|
588
|
-
|
|
656
|
+
if (filter.tenant) where[u.tenant] = {
|
|
657
|
+
[tenantSlug]: filter.tenant
|
|
589
658
|
};
|
|
590
659
|
const rows = await this.users().findMany({
|
|
591
660
|
where,
|
|
592
661
|
include: {
|
|
593
|
-
tenant: {
|
|
662
|
+
[u.tenant]: {
|
|
594
663
|
select: {
|
|
595
|
-
|
|
664
|
+
[tenantSlug]: true
|
|
596
665
|
}
|
|
597
666
|
}
|
|
598
667
|
},
|
|
@@ -603,12 +672,12 @@ var PrismaAdminResourcesAdapter = class {
|
|
|
603
672
|
});
|
|
604
673
|
return rows.map((row) => ({
|
|
605
674
|
id: row.id,
|
|
606
|
-
email: row.email,
|
|
607
|
-
firstName: row.firstName ?? "",
|
|
608
|
-
lastName: row.lastName ?? "",
|
|
675
|
+
email: this.read(row, u.email) ?? "",
|
|
676
|
+
firstName: this.read(row, u.firstName) ?? "",
|
|
677
|
+
lastName: this.read(row, u.lastName) ?? "",
|
|
609
678
|
role: row.platformRole ?? row.role ?? "MEMBER",
|
|
610
|
-
isActive: row.isActive ?? true,
|
|
611
|
-
tenantSlug: row.tenant
|
|
679
|
+
isActive: this.read(row, u.isActive) ?? true,
|
|
680
|
+
tenantSlug: this.tenantSlugOf(row, u.tenant, tenantSlug),
|
|
612
681
|
lastLoginAt: row.lastLoginAt?.toISOString() ?? null,
|
|
613
682
|
createdAt: row.createdAt.toISOString()
|
|
614
683
|
}));
|
|
@@ -623,12 +692,13 @@ var PrismaAdminResourcesAdapter = class {
|
|
|
623
692
|
});
|
|
624
693
|
}
|
|
625
694
|
async listSubscriptions() {
|
|
695
|
+
const t = this.schema.tenant;
|
|
626
696
|
const rows = await this.subscriptions().findMany({
|
|
627
697
|
include: {
|
|
628
698
|
tenant: {
|
|
629
699
|
select: {
|
|
630
|
-
slug: true,
|
|
631
|
-
name: true
|
|
700
|
+
[t.slug]: true,
|
|
701
|
+
[t.name]: true
|
|
632
702
|
}
|
|
633
703
|
},
|
|
634
704
|
planVersion: {
|
|
@@ -644,7 +714,10 @@ var PrismaAdminResourcesAdapter = class {
|
|
|
644
714
|
});
|
|
645
715
|
return rows.map((row) => ({
|
|
646
716
|
id: row.id,
|
|
647
|
-
tenant:
|
|
717
|
+
tenant: {
|
|
718
|
+
slug: this.read(row.tenant, t.slug) ?? "",
|
|
719
|
+
name: this.read(row.tenant, t.name) ?? ""
|
|
720
|
+
},
|
|
648
721
|
plan: row.plan,
|
|
649
722
|
status: row.status,
|
|
650
723
|
billingCycle: row.billingCycle,
|
|
@@ -653,13 +726,32 @@ var PrismaAdminResourcesAdapter = class {
|
|
|
653
726
|
}));
|
|
654
727
|
}
|
|
655
728
|
tenants() {
|
|
656
|
-
return getPrismaDelegate(this.prisma,
|
|
729
|
+
return getPrismaDelegate(this.prisma, this.schema.delegates.tenant);
|
|
657
730
|
}
|
|
658
731
|
users() {
|
|
659
|
-
return getPrismaDelegate(this.prisma,
|
|
732
|
+
return getPrismaDelegate(this.prisma, this.schema.delegates.user);
|
|
660
733
|
}
|
|
661
734
|
subscriptions() {
|
|
662
|
-
return getPrismaDelegate(this.prisma,
|
|
735
|
+
return getPrismaDelegate(this.prisma, this.schema.delegates.subscription);
|
|
736
|
+
}
|
|
737
|
+
/** The subscription relation of a tenant row, under whatever it is called. */
|
|
738
|
+
subscriptionOf(row) {
|
|
739
|
+
return this.read(row, this.schema.tenant.subscription) ?? null;
|
|
740
|
+
}
|
|
741
|
+
/** The tenant slug on a user row, through both mapped names. */
|
|
742
|
+
tenantSlugOf(row, relation, slugField) {
|
|
743
|
+
const tenant = this.read(row, relation);
|
|
744
|
+
return tenant ? this.read(tenant, slugField) ?? null : null;
|
|
745
|
+
}
|
|
746
|
+
/**
|
|
747
|
+
* Reads a mapped field off a row.
|
|
748
|
+
*
|
|
749
|
+
* The rows come back keyed by the APP's field names, so every read of a
|
|
750
|
+
* mapped field goes through here — and the row type stays the shape the
|
|
751
|
+
* adapter promises rather than becoming `Record<string, unknown>`.
|
|
752
|
+
*/
|
|
753
|
+
read(row, field) {
|
|
754
|
+
return row[field];
|
|
663
755
|
}
|
|
664
756
|
};
|
|
665
757
|
function metricSelect(metrics) {
|
|
@@ -2039,7 +2131,7 @@ PrismaMfaAdapter = _ts_decorate9([
|
|
|
2039
2131
|
])
|
|
2040
2132
|
], PrismaMfaAdapter);
|
|
2041
2133
|
|
|
2042
|
-
// src/prisma-plan-catalog-import-sink.ts
|
|
2134
|
+
// src/prisma-plan-catalog-import-sink.adapter.ts
|
|
2043
2135
|
var import_common10 = require("@nestjs/common");
|
|
2044
2136
|
function _ts_decorate10(decorators, target, key, desc) {
|
|
2045
2137
|
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
@@ -2193,7 +2285,7 @@ PrismaPlanCatalogImportSink = _ts_decorate10([
|
|
|
2193
2285
|
])
|
|
2194
2286
|
], PrismaPlanCatalogImportSink);
|
|
2195
2287
|
|
|
2196
|
-
// src/prisma-plan-catalog-read-sink.ts
|
|
2288
|
+
// src/prisma-plan-catalog-read-sink.adapter.ts
|
|
2197
2289
|
var import_common11 = require("@nestjs/common");
|
|
2198
2290
|
function _ts_decorate11(decorators, target, key, desc) {
|
|
2199
2291
|
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
@@ -3623,7 +3715,7 @@ PrismaPromoCodeValidationLogRepository = _ts_decorate17([
|
|
|
3623
3715
|
])
|
|
3624
3716
|
], PrismaPromoCodeValidationLogRepository);
|
|
3625
3717
|
|
|
3626
|
-
// src/prisma-promo-subscription-lookup.ts
|
|
3718
|
+
// src/prisma-promo-subscription-lookup.adapter.ts
|
|
3627
3719
|
var import_common18 = require("@nestjs/common");
|
|
3628
3720
|
function _ts_decorate18(decorators, target, key, desc) {
|
|
3629
3721
|
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
@@ -4821,7 +4913,7 @@ function clearedPendingVersionData() {
|
|
|
4821
4913
|
}
|
|
4822
4914
|
__name(clearedPendingVersionData, "clearedPendingVersionData");
|
|
4823
4915
|
|
|
4824
|
-
// src/prisma-transaction-runner.ts
|
|
4916
|
+
// src/prisma-transaction-runner.adapter.ts
|
|
4825
4917
|
var import_common25 = require("@nestjs/common");
|
|
4826
4918
|
function _ts_decorate25(decorators, target, key, desc) {
|
|
4827
4919
|
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
@@ -4862,7 +4954,7 @@ PrismaTransactionRunner = _ts_decorate25([
|
|
|
4862
4954
|
])
|
|
4863
4955
|
], PrismaTransactionRunner);
|
|
4864
4956
|
|
|
4865
|
-
// src/zero-promo-revenue-aggregator.ts
|
|
4957
|
+
// src/zero-promo-revenue-aggregator.adapter.ts
|
|
4866
4958
|
var import_common26 = require("@nestjs/common");
|
|
4867
4959
|
function _ts_decorate26(decorators, target, key, desc) {
|
|
4868
4960
|
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
@@ -5016,9 +5108,11 @@ __name(buildProvisioning, "buildProvisioning");
|
|
|
5016
5108
|
PrismaTenantSubscriptionWriteAdapter,
|
|
5017
5109
|
PrismaTransactionRunner,
|
|
5018
5110
|
ZeroPromoRevenueDeductionAggregator,
|
|
5111
|
+
assertDelegatesExist,
|
|
5019
5112
|
buildActorTag,
|
|
5020
5113
|
createPrismaPlanBindingResolver,
|
|
5021
5114
|
getPrismaDelegate,
|
|
5022
5115
|
prismaPersistence,
|
|
5116
|
+
resolveAdminResourcesSchema,
|
|
5023
5117
|
resolvePrismaSchemaOptions
|
|
5024
5118
|
});
|
package/dist/index.d.cts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { AdminResourcesPort, AdminTenantListFilter, AdminTenantListRow, AdminTenantDetail, AdminTenantStateResult, AdminUserListFilter, AdminUserListRow, AdminAuditListFilter, AuditEntry, AdminSubscriptionListRow, BundleRepository, TransactionContext, BundleVersionRow, BundleListFilter, BundleRow, CreateBundleData, UpdateBundleData, CreateBundleVersionDraftData, UpdateBundleVersionDraftData, VersionChange, PersistenceInjectionToken, PasswordHasher,
|
|
1
|
+
import { AdminResourcesPort, AdminTenantListFilter, AdminTenantListRow, AdminTenantDetail, AdminTenantStateResult, AdminUserListFilter, AdminUserListRow, AdminAuditListFilter, AuditEntry, AdminSubscriptionListRow, BundleRepository, TransactionContext, BundleVersionRow, BundleListFilter, BundleRow, CreateBundleData, UpdateBundleData, CreateBundleVersionDraftData, UpdateBundleVersionDraftData, VersionChange, PersistenceInjectionToken, PasswordHasher, SaaSiCatPersistenceAdapter, TransactionRunner, MfaPort, AuditPort, AdminActor, AuditQueryPort, AuditQuery, AuditStatsPort, RlsBypassPort, SubscriptionRepository, SubscriptionRecord, SubscriptionUsagePort, SubscriptionUsageRecord, SubscriptionBundleRepository, SubscriptionBundleRecord, CreateSubscriptionBundleData, CancelSubscriptionBundleData, TenantSubscriptionWritePort, ApplyOnboardingSelectionInput, RedeemPromoInTransactionCallback, ApplyOnboardingSelectionResult, ImmediatePlanChangeInput, ScheduledPlanChangeInput, PlanVersionRepository, PlanVersionRecord, PromoCodeRepository, PromoCodeRecord, PromoCodeFilter, CreatePromoCodeData, UpdatePromoCodeData, PromoCodeRedemptionRepository, PromoCodeRedemptionRecord, PromoCodeRedemptionStatus, PromoCodeRedemptionListItem, PromoCodeValidationLogRepository, PromoSubscriptionLookup, BillingCycle, PromoRevenueDeductionAggregator, SuperAdminProvisioningPort, CreateSuperAdminCliInput, PlatformUserDto, PlanCatalogReadSink, PlanCatalogReadSnapshot, PlanCatalogImportSink, UpsertPlanInput, UpsertResult, UpsertPlanVersionInput, UpsertFeatureCatalogEntryInput, PlanRepository, PlanListFilter, PlanRow, CreatePlanData, UpdatePlanData, PlanVersionRow, CreatePlanVersionDraftData, UpdatePlanVersionDraftData, CatalogEntryRepository, CatalogEntryFilter, CapabilityCatalogEntryRow, FeatureCatalogEntryRow, QuotaCatalogEntryRow, UpsertCapabilityEntryData, UpsertFeatureEntryData, UpsertQuotaEntryData, SetCatalogEntryReviewData, CatalogEntryI18n, UpdateCatalogEntryBaseData, MarketingProjectionRepository, MarketingProjectionFilter, MarketingProjectionRow, CreateMarketingProjectionData, UpdateMarketingProjectionData, MarketingSettingsRepository, MarketingSettingsRow, UpdateMarketingSettingsData, PromotionRepository, PromotionFilter, PromotionRow, CreatePromotionData, UpdatePromotionData, SubscriptionContractRepository, SubscriptionContractFilter, SubscriptionContractRecord, CreateSubscriptionContractData, TerminateSubscriptionContractData } from '@saasicat/types';
|
|
2
2
|
|
|
3
3
|
declare const PRISMA_CLIENT_TOKEN: unique symbol;
|
|
4
4
|
/** Prisma `Decimal` values arrive as objects with `toString()`; tests may use plain values. */
|
|
@@ -703,6 +703,81 @@ declare function createPrismaPlanBindingResolver(options?: PrismaPlanBindingOpti
|
|
|
703
703
|
/** Resolves a configurable Prisma delegate and fails early on misspellings. */
|
|
704
704
|
declare function getPrismaDelegate<Row>(client: unknown, delegateName: string): PrismaModelDelegateLike<Row>;
|
|
705
705
|
|
|
706
|
+
/** The Prisma delegates the adapter needs, by the name your client uses. */
|
|
707
|
+
interface AdminResourcesDelegates {
|
|
708
|
+
/** Default `tenant`. */
|
|
709
|
+
tenant?: string;
|
|
710
|
+
/** Default `user`. */
|
|
711
|
+
user?: string;
|
|
712
|
+
/** Default `subscription`. */
|
|
713
|
+
subscription?: string;
|
|
714
|
+
}
|
|
715
|
+
/** The scalar and relation fields the adapter reads, by your name for them. */
|
|
716
|
+
interface AdminResourcesFields {
|
|
717
|
+
tenant?: {
|
|
718
|
+
/** Default `slug` — the stable identifier every admin route addresses. */
|
|
719
|
+
slug?: string;
|
|
720
|
+
/** Default `name`. */
|
|
721
|
+
name?: string;
|
|
722
|
+
/** Default `isActive`. */
|
|
723
|
+
isActive?: string;
|
|
724
|
+
/** Default `deletedAt`. */
|
|
725
|
+
deletedAt?: string;
|
|
726
|
+
/** The tenant→users relation. Default `users`. */
|
|
727
|
+
users?: string;
|
|
728
|
+
/**
|
|
729
|
+
* The tenant→subscription relation. Default `subscription`.
|
|
730
|
+
*
|
|
731
|
+
* On YOUR model, so your name for it: Prisma names a relation field
|
|
732
|
+
* after what it points at, and an app whose tenant is `Organization`
|
|
733
|
+
* has usually not renamed this one — but it may have.
|
|
734
|
+
*/
|
|
735
|
+
subscription?: string;
|
|
736
|
+
};
|
|
737
|
+
user?: {
|
|
738
|
+
/** Default `email`. */
|
|
739
|
+
email?: string;
|
|
740
|
+
/** Default `firstName`. */
|
|
741
|
+
firstName?: string;
|
|
742
|
+
/** Default `lastName`. */
|
|
743
|
+
lastName?: string;
|
|
744
|
+
/** Default `isActive`. */
|
|
745
|
+
isActive?: string;
|
|
746
|
+
/**
|
|
747
|
+
* The user→tenant relation. Default `tenant`.
|
|
748
|
+
*
|
|
749
|
+
* The one the documented example gets wrong by omission: an app whose
|
|
750
|
+
* tenant model is `Organization` calls this field `organization`, by
|
|
751
|
+
* the same Prisma convention that named the delegate.
|
|
752
|
+
*/
|
|
753
|
+
tenant?: string;
|
|
754
|
+
};
|
|
755
|
+
}
|
|
756
|
+
/** The mapping with every default filled in — what the adapter actually reads. */
|
|
757
|
+
interface ResolvedAdminResourcesSchema {
|
|
758
|
+
readonly delegates: Required<AdminResourcesDelegates>;
|
|
759
|
+
readonly tenant: Required<NonNullable<AdminResourcesFields['tenant']>>;
|
|
760
|
+
readonly user: Required<NonNullable<AdminResourcesFields['user']>>;
|
|
761
|
+
}
|
|
762
|
+
declare function resolveAdminResourcesSchema(delegates?: AdminResourcesDelegates, fields?: AdminResourcesFields): ResolvedAdminResourcesSchema;
|
|
763
|
+
/**
|
|
764
|
+
* Refuses a mapping that names a delegate the client does not have.
|
|
765
|
+
*
|
|
766
|
+
* At construction, which is boot: a mapped delegate is resolved lazily, so a
|
|
767
|
+
* typo used to surface as a 500 on the tenants page long after deployment —
|
|
768
|
+
* and only if somebody opened it. The message lists what the client does have,
|
|
769
|
+
* because the answer is almost always a near miss (`organisation` for
|
|
770
|
+
* `organization`, `users` for `user`).
|
|
771
|
+
*
|
|
772
|
+
* Only for an EXPLICIT mapping. `prismaPersistence()` builds this adapter for
|
|
773
|
+
* every bundle, including for applications that never switch `adminResources`
|
|
774
|
+
* on, and several of them have no `tenant` delegate at all — asserting the
|
|
775
|
+
* defaults here would refuse to construct a bundle nobody was going to ask
|
|
776
|
+
* about. Those keep failing where they always did, at the first request, with
|
|
777
|
+
* a message that now names the way out.
|
|
778
|
+
*/
|
|
779
|
+
declare function assertDelegatesExist(client: unknown, schema: ResolvedAdminResourcesSchema): void;
|
|
780
|
+
|
|
706
781
|
interface PrismaAdminResourcesOptions {
|
|
707
782
|
/**
|
|
708
783
|
* Relation counters exposed on tenant rows and tenant details. The names
|
|
@@ -710,6 +785,13 @@ interface PrismaAdminResourcesOptions {
|
|
|
710
785
|
*/
|
|
711
786
|
tenantMetrics?: readonly string[];
|
|
712
787
|
listLimit?: number;
|
|
788
|
+
/**
|
|
789
|
+
* Delegate names, when the app's models are not called `tenant`, `user`
|
|
790
|
+
* and `subscription`. Checked against the client at construction.
|
|
791
|
+
*/
|
|
792
|
+
delegates?: AdminResourcesDelegates;
|
|
793
|
+
/** Field names, when the app's columns differ. See `AdminResourcesFields`. */
|
|
794
|
+
fields?: AdminResourcesFields;
|
|
713
795
|
}
|
|
714
796
|
/**
|
|
715
797
|
* Convention-based adapter for the standard SuperAdmin resource pages.
|
|
@@ -724,6 +806,7 @@ declare class PrismaAdminResourcesAdapter implements AdminResourcesPort {
|
|
|
724
806
|
private readonly metrics;
|
|
725
807
|
private readonly listLimit;
|
|
726
808
|
private readonly audit;
|
|
809
|
+
private readonly schema;
|
|
727
810
|
constructor(prisma: PrismaLike, options?: PrismaAdminResourcesOptions);
|
|
728
811
|
listTenants(filter: AdminTenantListFilter): Promise<AdminTenantListRow[]>;
|
|
729
812
|
getTenantDetail(slug: string): Promise<AdminTenantDetail | null>;
|
|
@@ -734,6 +817,18 @@ declare class PrismaAdminResourcesAdapter implements AdminResourcesPort {
|
|
|
734
817
|
private tenants;
|
|
735
818
|
private users;
|
|
736
819
|
private subscriptions;
|
|
820
|
+
/** The subscription relation of a tenant row, under whatever it is called. */
|
|
821
|
+
private subscriptionOf;
|
|
822
|
+
/** The tenant slug on a user row, through both mapped names. */
|
|
823
|
+
private tenantSlugOf;
|
|
824
|
+
/**
|
|
825
|
+
* Reads a mapped field off a row.
|
|
826
|
+
*
|
|
827
|
+
* The rows come back keyed by the APP's field names, so every read of a
|
|
828
|
+
* mapped field goes through here — and the row type stays the shape the
|
|
829
|
+
* adapter promises rather than becoming `Record<string, unknown>`.
|
|
830
|
+
*/
|
|
831
|
+
private read;
|
|
737
832
|
}
|
|
738
833
|
|
|
739
834
|
/**
|
|
@@ -859,11 +954,11 @@ interface PrismaPersistenceOptions {
|
|
|
859
954
|
bundle?: PrismaBundleRepositoryOptions;
|
|
860
955
|
}
|
|
861
956
|
/**
|
|
862
|
-
* Builds the `
|
|
957
|
+
* Builds the `SaaSiCatPersistenceAdapter` bundle for Prisma + PostgreSQL on
|
|
863
958
|
* the canonical schema (`@saasicat/spec` prisma-fragments):
|
|
864
959
|
*
|
|
865
960
|
* ```ts
|
|
866
|
-
*
|
|
961
|
+
* SaaSiCatModule.forRoot({
|
|
867
962
|
* persistence: prismaPersistence({ client: PrismaService }),
|
|
868
963
|
* // ...
|
|
869
964
|
* });
|
|
@@ -873,7 +968,7 @@ interface PrismaPersistenceOptions {
|
|
|
873
968
|
* tenant-billing, promo and plan-catalog persistence. App-specific behavior
|
|
874
969
|
* such as quota counters and authentication remains in the consumer.
|
|
875
970
|
*/
|
|
876
|
-
declare function prismaPersistence(options: PrismaPersistenceOptions):
|
|
971
|
+
declare function prismaPersistence(options: PrismaPersistenceOptions): SaaSiCatPersistenceAdapter;
|
|
877
972
|
|
|
878
973
|
/**
|
|
879
974
|
* `TransactionRunner` over `prisma.$transaction`. The interactive transaction
|
|
@@ -1461,4 +1556,4 @@ declare class PrismaSubscriptionContractRepository implements SubscriptionContra
|
|
|
1461
1556
|
terminate(contractId: string, data: TerminateSubscriptionContractData): Promise<SubscriptionContractRecord>;
|
|
1462
1557
|
}
|
|
1463
1558
|
|
|
1464
|
-
export { AsyncLocalRlsBypassAdapter, type DecimalLike, PASSWORD_HASHER_TOKEN, PRISMA_BUNDLE_REPOSITORY_OPTIONS, PRISMA_CLIENT_TOKEN, PRISMA_SCHEMA_OPTIONS_TOKEN, PrismaAdminResourcesAdapter, type PrismaAdminResourcesOptions, PrismaAuditAdapter, PrismaAuditQueryAdapter, PrismaAuditStatsAdapter, PrismaBundleRepository, type PrismaBundleRepositoryOptions, PrismaCatalogEntryRepository, type PrismaLike, PrismaMarketingProjectionRepository, PrismaMarketingSettingsRepository, PrismaMfaAdapter, type PrismaModelDelegateLike, type PrismaPersistenceOptions, type PrismaPlanBindingMode, type PrismaPlanBindingOptions, type PrismaPlanBindingResolver, PrismaPlanCatalogImportSink, PrismaPlanCatalogReadSink, type PrismaPlanDelegateOptions, PrismaPlanRepository, type PrismaPlanVersionFieldCapabilities, type PrismaPlanVersionFieldOptions, PrismaPlanVersionRepository, PrismaPromoCodeRedemptionRepository, PrismaPromoCodeRepository, PrismaPromoCodeValidationLogRepository, PrismaPromoSubscriptionLookup, PrismaPromotionRepository, type PrismaSchemaOptions, PrismaSubscriptionBundleRepository, PrismaSubscriptionContractRepository, PrismaSubscriptionRepository, PrismaSubscriptionUsageAdapter, PrismaSuperAdminBootstrapAdapter, type PrismaTenantSubscriptionOptions, PrismaTenantSubscriptionWriteAdapter, PrismaTransactionRunner, type PrismaTxLike, type ResolvedPrismaSchemaOptions, ZeroPromoRevenueDeductionAggregator, buildActorTag, createPrismaPlanBindingResolver, getPrismaDelegate, prismaPersistence, resolvePrismaSchemaOptions };
|
|
1559
|
+
export { type AdminResourcesDelegates, type AdminResourcesFields, AsyncLocalRlsBypassAdapter, type DecimalLike, PASSWORD_HASHER_TOKEN, PRISMA_BUNDLE_REPOSITORY_OPTIONS, PRISMA_CLIENT_TOKEN, PRISMA_SCHEMA_OPTIONS_TOKEN, PrismaAdminResourcesAdapter, type PrismaAdminResourcesOptions, PrismaAuditAdapter, PrismaAuditQueryAdapter, PrismaAuditStatsAdapter, PrismaBundleRepository, type PrismaBundleRepositoryOptions, PrismaCatalogEntryRepository, type PrismaLike, PrismaMarketingProjectionRepository, PrismaMarketingSettingsRepository, PrismaMfaAdapter, type PrismaModelDelegateLike, type PrismaPersistenceOptions, type PrismaPlanBindingMode, type PrismaPlanBindingOptions, type PrismaPlanBindingResolver, PrismaPlanCatalogImportSink, PrismaPlanCatalogReadSink, type PrismaPlanDelegateOptions, PrismaPlanRepository, type PrismaPlanVersionFieldCapabilities, type PrismaPlanVersionFieldOptions, PrismaPlanVersionRepository, PrismaPromoCodeRedemptionRepository, PrismaPromoCodeRepository, PrismaPromoCodeValidationLogRepository, PrismaPromoSubscriptionLookup, PrismaPromotionRepository, type PrismaSchemaOptions, PrismaSubscriptionBundleRepository, PrismaSubscriptionContractRepository, PrismaSubscriptionRepository, PrismaSubscriptionUsageAdapter, PrismaSuperAdminBootstrapAdapter, type PrismaTenantSubscriptionOptions, PrismaTenantSubscriptionWriteAdapter, PrismaTransactionRunner, type PrismaTxLike, type ResolvedAdminResourcesSchema, type ResolvedPrismaSchemaOptions, ZeroPromoRevenueDeductionAggregator, assertDelegatesExist, buildActorTag, createPrismaPlanBindingResolver, getPrismaDelegate, prismaPersistence, resolveAdminResourcesSchema, resolvePrismaSchemaOptions };
|