@node-tenant/tenant-storage-prisma 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +148 -0
- package/dist/index.cjs +164 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.cts +13 -0
- package/dist/index.d.ts +13 -0
- package/dist/index.js +139 -0
- package/dist/index.js.map +1 -0
- package/package.json +40 -0
- package/schema.prisma +103 -0
package/README.md
ADDED
|
@@ -0,0 +1,148 @@
|
|
|
1
|
+
# @node-tenant/tenant-storage-prisma
|
|
2
|
+
|
|
3
|
+
> **Prisma storage adapter** for the `@node-tenant` ecosystem — manages tenant metadata, relationships, and configuration using Prisma ORM.
|
|
4
|
+
|
|
5
|
+
[](https://www.npmjs.com/package/@node-tenant/tenant-storage-prisma)
|
|
6
|
+
[](./LICENSE)
|
|
7
|
+
|
|
8
|
+
---
|
|
9
|
+
|
|
10
|
+
## Overview
|
|
11
|
+
|
|
12
|
+
`@node-tenant/tenant-storage-prisma` implements the **`TenantStorage`** interface from `@node-tenant/tenant-core`. It acts as the "Control Plane", storing your tenants, their configurations, statuses, and cross-tenant relationships.
|
|
13
|
+
|
|
14
|
+
**Note:** This package does **not** handle tenant data isolation (that's the job of the `DatabaseAdapter` or Mongoose routers). This package only manages the list of tenants themselves.
|
|
15
|
+
|
|
16
|
+
---
|
|
17
|
+
|
|
18
|
+
## Table of Contents
|
|
19
|
+
|
|
20
|
+
- [Installation](#installation)
|
|
21
|
+
- [Quick Start](#quick-start)
|
|
22
|
+
- [Prisma Schema](#prisma-schema)
|
|
23
|
+
- [API Reference](#api-reference)
|
|
24
|
+
- [License](#license)
|
|
25
|
+
|
|
26
|
+
---
|
|
27
|
+
|
|
28
|
+
## Installation
|
|
29
|
+
|
|
30
|
+
```bash
|
|
31
|
+
npm install @node-tenant/tenant-core @node-tenant/tenant-storage-prisma @prisma/client
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
> **Peer dependency**: `@prisma/client >= 5.0.0` must be installed in your project.
|
|
35
|
+
|
|
36
|
+
---
|
|
37
|
+
|
|
38
|
+
## Prisma Schema
|
|
39
|
+
|
|
40
|
+
This package requires a specific set of models in your `schema.prisma` file. A pre-defined schema is included in this package at `node_modules/@node-tenant/tenant-storage-prisma/schema.prisma`.
|
|
41
|
+
|
|
42
|
+
You can manually copy these models into your own `schema.prisma`:
|
|
43
|
+
|
|
44
|
+
```prisma
|
|
45
|
+
model Tenant {
|
|
46
|
+
id String @id @default(uuid())
|
|
47
|
+
slug String @unique
|
|
48
|
+
name String
|
|
49
|
+
status String // e.g., 'active', 'suspended', 'inactive'
|
|
50
|
+
strategy String // e.g., 'tenantId', 'database', 'schema'
|
|
51
|
+
config Json? @default("{}")
|
|
52
|
+
organizationId String?
|
|
53
|
+
createdAt DateTime @default(now())
|
|
54
|
+
updatedAt DateTime @updatedAt
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
model TenantRelationship {
|
|
58
|
+
id String @id @default(uuid())
|
|
59
|
+
sourceTenantId String
|
|
60
|
+
targetTenantId String
|
|
61
|
+
type String // e.g., 'partner', 'parent_child'
|
|
62
|
+
metadata Json? @default("{}")
|
|
63
|
+
createdAt DateTime @default(now())
|
|
64
|
+
updatedAt DateTime @updatedAt
|
|
65
|
+
|
|
66
|
+
@@unique([sourceTenantId, targetTenantId, type])
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
model TenantShare {
|
|
70
|
+
id String @id @default(uuid())
|
|
71
|
+
resourceType String
|
|
72
|
+
resourceId String
|
|
73
|
+
ownerTenantId String
|
|
74
|
+
targetTenantId String
|
|
75
|
+
permission String // e.g., 'read', 'write', 'admin'
|
|
76
|
+
metadata Json? @default("{}")
|
|
77
|
+
createdAt DateTime @default(now())
|
|
78
|
+
updatedAt DateTime @updatedAt
|
|
79
|
+
|
|
80
|
+
@@unique([resourceType, resourceId, ownerTenantId, targetTenantId])
|
|
81
|
+
}
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
After adding these to your schema, run:
|
|
85
|
+
|
|
86
|
+
```bash
|
|
87
|
+
npx prisma generate
|
|
88
|
+
npx prisma db push # Or create a migration
|
|
89
|
+
```
|
|
90
|
+
|
|
91
|
+
---
|
|
92
|
+
|
|
93
|
+
## Quick Start
|
|
94
|
+
|
|
95
|
+
```ts
|
|
96
|
+
import { PrismaClient } from '@prisma/client';
|
|
97
|
+
import { TenantManager } from '@node-tenant/tenant-core';
|
|
98
|
+
import { createPrismaStorage } from '@node-tenant/tenant-storage-prisma';
|
|
99
|
+
|
|
100
|
+
// 1. Initialize your Prisma Client
|
|
101
|
+
const prisma = new PrismaClient();
|
|
102
|
+
|
|
103
|
+
// 2. Create the Storage Adapter
|
|
104
|
+
const storage = createPrismaStorage(prisma);
|
|
105
|
+
|
|
106
|
+
// 3. Pass to the TenantManager
|
|
107
|
+
const manager = new TenantManager({ storage });
|
|
108
|
+
|
|
109
|
+
// Now you can manage tenants!
|
|
110
|
+
async function setup() {
|
|
111
|
+
const tenant = await manager.createTenant({
|
|
112
|
+
slug: 'acme-corp',
|
|
113
|
+
name: 'Acme Corporation',
|
|
114
|
+
status: 'active',
|
|
115
|
+
strategy: 'tenantId',
|
|
116
|
+
});
|
|
117
|
+
|
|
118
|
+
console.log('Created tenant:', tenant);
|
|
119
|
+
}
|
|
120
|
+
```
|
|
121
|
+
|
|
122
|
+
---
|
|
123
|
+
|
|
124
|
+
## API Reference
|
|
125
|
+
|
|
126
|
+
### `createPrismaStorage(prismaClient)`
|
|
127
|
+
|
|
128
|
+
Creates a `TenantStorage` compatible adapter.
|
|
129
|
+
|
|
130
|
+
```ts
|
|
131
|
+
import { createPrismaStorage } from '@node-tenant/tenant-storage-prisma';
|
|
132
|
+
import { PrismaClient } from '@prisma/client';
|
|
133
|
+
|
|
134
|
+
const prisma = new PrismaClient();
|
|
135
|
+
const storage = createPrismaStorage(prisma);
|
|
136
|
+
```
|
|
137
|
+
|
|
138
|
+
| Parameter | Type | Required | Description |
|
|
139
|
+
|---|---|---|---|
|
|
140
|
+
| `prismaClient` | `PrismaClient` | ✅ | An initialized PrismaClient instance |
|
|
141
|
+
|
|
142
|
+
**Returns:** `TenantStorage` object containing all required methods (`getTenantById`, `getTenantBySlug`, `listTenants`, `createTenant`, `updateTenant`, `deleteTenant`, `createRelationship`, etc.)
|
|
143
|
+
|
|
144
|
+
---
|
|
145
|
+
|
|
146
|
+
## License
|
|
147
|
+
|
|
148
|
+
MIT © AdPulseFlow
|
package/dist/index.cjs
ADDED
|
@@ -0,0 +1,164 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __defProp = Object.defineProperty;
|
|
3
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
4
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
5
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
6
|
+
var __export = (target, all) => {
|
|
7
|
+
for (var name in all)
|
|
8
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
9
|
+
};
|
|
10
|
+
var __copyProps = (to, from, except, desc) => {
|
|
11
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
12
|
+
for (let key of __getOwnPropNames(from))
|
|
13
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
14
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
15
|
+
}
|
|
16
|
+
return to;
|
|
17
|
+
};
|
|
18
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
19
|
+
|
|
20
|
+
// src/index.ts
|
|
21
|
+
var index_exports = {};
|
|
22
|
+
__export(index_exports, {
|
|
23
|
+
createPrismaStorage: () => createPrismaStorage
|
|
24
|
+
});
|
|
25
|
+
module.exports = __toCommonJS(index_exports);
|
|
26
|
+
function toTenant(raw) {
|
|
27
|
+
return {
|
|
28
|
+
id: raw.id,
|
|
29
|
+
organizationId: raw.organizationId ?? void 0,
|
|
30
|
+
name: raw.name,
|
|
31
|
+
slug: raw.slug,
|
|
32
|
+
strategy: raw.strategy,
|
|
33
|
+
status: raw.status,
|
|
34
|
+
config: raw.config ?? {},
|
|
35
|
+
metadata: raw.metadata ?? void 0,
|
|
36
|
+
createdAt: raw.createdAt,
|
|
37
|
+
updatedAt: raw.updatedAt
|
|
38
|
+
};
|
|
39
|
+
}
|
|
40
|
+
function toOrg(raw) {
|
|
41
|
+
return {
|
|
42
|
+
id: raw.id,
|
|
43
|
+
name: raw.name,
|
|
44
|
+
slug: raw.slug,
|
|
45
|
+
metadata: raw.metadata ?? void 0,
|
|
46
|
+
createdAt: raw.createdAt,
|
|
47
|
+
updatedAt: raw.updatedAt
|
|
48
|
+
};
|
|
49
|
+
}
|
|
50
|
+
function createPrismaStorage(prisma) {
|
|
51
|
+
return {
|
|
52
|
+
// ── Tenants ──────────────────────────────────────────────────────────────
|
|
53
|
+
async createTenant(data) {
|
|
54
|
+
const raw = await prisma.tenant.create({
|
|
55
|
+
data: {
|
|
56
|
+
name: data.name,
|
|
57
|
+
slug: data.slug,
|
|
58
|
+
organizationId: data.organizationId,
|
|
59
|
+
strategy: data.strategy,
|
|
60
|
+
status: data.status,
|
|
61
|
+
config: data.config ?? {},
|
|
62
|
+
metadata: data.metadata ?? void 0
|
|
63
|
+
}
|
|
64
|
+
});
|
|
65
|
+
return toTenant(raw);
|
|
66
|
+
},
|
|
67
|
+
async getTenant(id) {
|
|
68
|
+
const raw = await prisma.tenant.findUnique({ where: { id } });
|
|
69
|
+
return raw ? toTenant(raw) : null;
|
|
70
|
+
},
|
|
71
|
+
async getTenantBySlug(slug) {
|
|
72
|
+
const raw = await prisma.tenant.findUnique({ where: { slug } });
|
|
73
|
+
return raw ? toTenant(raw) : null;
|
|
74
|
+
},
|
|
75
|
+
async updateTenant(id, data) {
|
|
76
|
+
const raw = await prisma.tenant.update({ where: { id }, data });
|
|
77
|
+
return toTenant(raw);
|
|
78
|
+
},
|
|
79
|
+
async deleteTenant(id) {
|
|
80
|
+
await prisma.tenant.delete({ where: { id } });
|
|
81
|
+
},
|
|
82
|
+
async listTenants(filter) {
|
|
83
|
+
const raws = await prisma.tenant.findMany({ where: filter ?? {} });
|
|
84
|
+
return raws.map(toTenant);
|
|
85
|
+
},
|
|
86
|
+
// ── Organizations ─────────────────────────────────────────────────────────
|
|
87
|
+
async createOrganization(data) {
|
|
88
|
+
const raw = await prisma.tenantOrganization.create({ data });
|
|
89
|
+
return toOrg(raw);
|
|
90
|
+
},
|
|
91
|
+
async getOrganization(id) {
|
|
92
|
+
const raw = await prisma.tenantOrganization.findUnique({ where: { id } });
|
|
93
|
+
return raw ? toOrg(raw) : null;
|
|
94
|
+
},
|
|
95
|
+
async updateOrganization(id, data) {
|
|
96
|
+
const raw = await prisma.tenantOrganization.update({ where: { id }, data });
|
|
97
|
+
return toOrg(raw);
|
|
98
|
+
},
|
|
99
|
+
async deleteOrganization(id) {
|
|
100
|
+
await prisma.tenantOrganization.delete({ where: { id } });
|
|
101
|
+
},
|
|
102
|
+
async listOrganizations() {
|
|
103
|
+
const raws = await prisma.tenantOrganization.findMany();
|
|
104
|
+
return raws.map(toOrg);
|
|
105
|
+
},
|
|
106
|
+
// ── Domains ───────────────────────────────────────────────────────────────
|
|
107
|
+
async createDomain(data) {
|
|
108
|
+
return prisma.tenantDomain.create({ data });
|
|
109
|
+
},
|
|
110
|
+
async getDomainByHost(host) {
|
|
111
|
+
return prisma.tenantDomain.findUnique({ where: { domain: host } });
|
|
112
|
+
},
|
|
113
|
+
async deleteDomain(id) {
|
|
114
|
+
await prisma.tenantDomain.delete({ where: { id } });
|
|
115
|
+
},
|
|
116
|
+
// ── Relationships ─────────────────────────────────────────────────────────
|
|
117
|
+
async createRelationship(data) {
|
|
118
|
+
return prisma.tenantRelationship.create({ data });
|
|
119
|
+
},
|
|
120
|
+
async getRelationships(tenantId) {
|
|
121
|
+
return prisma.tenantRelationship.findMany({
|
|
122
|
+
where: {
|
|
123
|
+
OR: [{ sourceTenantId: tenantId }, { targetTenantId: tenantId }]
|
|
124
|
+
}
|
|
125
|
+
});
|
|
126
|
+
},
|
|
127
|
+
async deleteRelationship(id) {
|
|
128
|
+
await prisma.tenantRelationship.delete({ where: { id } });
|
|
129
|
+
},
|
|
130
|
+
// ── Resource shares ───────────────────────────────────────────────────────
|
|
131
|
+
async createResourceShare(data) {
|
|
132
|
+
return prisma.resourceShare.create({ data });
|
|
133
|
+
},
|
|
134
|
+
async getResourceShares(filter) {
|
|
135
|
+
const where = {};
|
|
136
|
+
if (filter.resourceType) where["resourceType"] = filter.resourceType;
|
|
137
|
+
if (filter.resourceId) where["resourceId"] = filter.resourceId;
|
|
138
|
+
if (filter.ownerTenantId) where["ownerTenantId"] = filter.ownerTenantId;
|
|
139
|
+
if (filter.targetTenantId) where["targetTenantId"] = filter.targetTenantId;
|
|
140
|
+
return prisma.resourceShare.findMany({ where });
|
|
141
|
+
},
|
|
142
|
+
async deleteResourceShare(id) {
|
|
143
|
+
await prisma.resourceShare.delete({ where: { id } });
|
|
144
|
+
},
|
|
145
|
+
// ── Audit ─────────────────────────────────────────────────────────────────
|
|
146
|
+
async createAuditLog(data) {
|
|
147
|
+
return prisma.auditLog.create({
|
|
148
|
+
data: { ...data, createdAt: /* @__PURE__ */ new Date() }
|
|
149
|
+
});
|
|
150
|
+
},
|
|
151
|
+
async listAuditLogs(tenantId, limit = 100) {
|
|
152
|
+
return prisma.auditLog.findMany({
|
|
153
|
+
where: { tenantId },
|
|
154
|
+
orderBy: { createdAt: "desc" },
|
|
155
|
+
take: limit
|
|
156
|
+
});
|
|
157
|
+
}
|
|
158
|
+
};
|
|
159
|
+
}
|
|
160
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
161
|
+
0 && (module.exports = {
|
|
162
|
+
createPrismaStorage
|
|
163
|
+
});
|
|
164
|
+
//# sourceMappingURL=index.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/index.ts"],"sourcesContent":["import type { PrismaClient } from '@prisma/client';\nimport type {\n StorageAdapter,\n Tenant,\n Organization,\n TenantDomain,\n TenantRelationship,\n ResourceShare,\n AuditLog,\n} from '@node-tenant/tenant-core';\n\nfunction toTenant(raw: any): Tenant {\n return {\n id: raw.id,\n organizationId: raw.organizationId ?? undefined,\n name: raw.name,\n slug: raw.slug,\n strategy: raw.strategy as Tenant['strategy'],\n status: raw.status as Tenant['status'],\n config: (raw.config as Record<string, unknown>) ?? {},\n metadata: (raw.metadata as Record<string, unknown>) ?? undefined,\n createdAt: raw.createdAt,\n updatedAt: raw.updatedAt,\n };\n}\n\nfunction toOrg(raw: any): Organization {\n return {\n id: raw.id,\n name: raw.name,\n slug: raw.slug,\n metadata: (raw.metadata as Record<string, unknown>) ?? undefined,\n createdAt: raw.createdAt,\n updatedAt: raw.updatedAt,\n };\n}\n\n/**\n * Create a Prisma-backed StorageAdapter for the @node-tenant/tenant public control layer.\n *\n * Usage:\n * const storage = createPrismaStorage(prisma);\n * const manager = new TenantManager({ storage });\n */\nexport function createPrismaStorage(prisma: PrismaClient): StorageAdapter {\n return {\n // ── Tenants ──────────────────────────────────────────────────────────────\n async createTenant(data) {\n const raw = await (prisma as any).tenant.create({\n data: {\n name: data.name,\n slug: data.slug,\n organizationId: data.organizationId,\n strategy: data.strategy,\n status: data.status,\n config: data.config ?? {},\n metadata: data.metadata ?? undefined,\n },\n });\n return toTenant(raw);\n },\n\n async getTenant(id) {\n const raw = await (prisma as any).tenant.findUnique({ where: { id } });\n return raw ? toTenant(raw) : null;\n },\n\n async getTenantBySlug(slug) {\n const raw = await (prisma as any).tenant.findUnique({ where: { slug } });\n return raw ? toTenant(raw) : null;\n },\n\n async updateTenant(id, data) {\n const raw = await (prisma as any).tenant.update({ where: { id }, data });\n return toTenant(raw);\n },\n\n async deleteTenant(id) {\n await (prisma as any).tenant.delete({ where: { id } });\n },\n\n async listTenants(filter) {\n const raws = await (prisma as any).tenant.findMany({ where: filter ?? {} });\n return raws.map(toTenant);\n },\n\n // ── Organizations ─────────────────────────────────────────────────────────\n async createOrganization(data) {\n const raw = await (prisma as any).tenantOrganization.create({ data });\n return toOrg(raw);\n },\n\n async getOrganization(id) {\n const raw = await (prisma as any).tenantOrganization.findUnique({ where: { id } });\n return raw ? toOrg(raw) : null;\n },\n\n async updateOrganization(id, data) {\n const raw = await (prisma as any).tenantOrganization.update({ where: { id }, data });\n return toOrg(raw);\n },\n\n async deleteOrganization(id) {\n await (prisma as any).tenantOrganization.delete({ where: { id } });\n },\n\n async listOrganizations() {\n const raws = await (prisma as any).tenantOrganization.findMany();\n return raws.map(toOrg);\n },\n\n // ── Domains ───────────────────────────────────────────────────────────────\n async createDomain(data) {\n return (prisma as any).tenantDomain.create({ data }) as Promise<TenantDomain>;\n },\n\n async getDomainByHost(host) {\n return (prisma as any).tenantDomain.findUnique({ where: { domain: host } }) as Promise<TenantDomain | null>;\n },\n\n async deleteDomain(id) {\n await (prisma as any).tenantDomain.delete({ where: { id } });\n },\n\n // ── Relationships ─────────────────────────────────────────────────────────\n async createRelationship(data) {\n return (prisma as any).tenantRelationship.create({ data }) as Promise<TenantRelationship>;\n },\n\n async getRelationships(tenantId) {\n return (prisma as any).tenantRelationship.findMany({\n where: {\n OR: [{ sourceTenantId: tenantId }, { targetTenantId: tenantId }],\n },\n }) as Promise<TenantRelationship[]>;\n },\n\n async deleteRelationship(id) {\n await (prisma as any).tenantRelationship.delete({ where: { id } });\n },\n\n // ── Resource shares ───────────────────────────────────────────────────────\n async createResourceShare(data) {\n return (prisma as any).resourceShare.create({ data }) as Promise<ResourceShare>;\n },\n\n async getResourceShares(filter) {\n const where: Record<string, unknown> = {};\n if (filter.resourceType) where['resourceType'] = filter.resourceType;\n if (filter.resourceId) where['resourceId'] = filter.resourceId;\n if (filter.ownerTenantId) where['ownerTenantId'] = filter.ownerTenantId;\n if (filter.targetTenantId) where['targetTenantId'] = filter.targetTenantId;\n return (prisma as any).resourceShare.findMany({ where }) as Promise<ResourceShare[]>;\n },\n\n async deleteResourceShare(id) {\n await (prisma as any).resourceShare.delete({ where: { id } });\n },\n\n // ── Audit ─────────────────────────────────────────────────────────────────\n async createAuditLog(data) {\n return (prisma as any).auditLog.create({\n data: { ...data, createdAt: new Date() },\n }) as Promise<AuditLog>;\n },\n\n async listAuditLogs(tenantId, limit = 100) {\n return (prisma as any).auditLog.findMany({\n where: { tenantId },\n orderBy: { createdAt: 'desc' },\n take: limit,\n }) as Promise<AuditLog[]>;\n },\n };\n}\n"],"mappings":"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","names":[]}
|
package/dist/index.d.cts
ADDED
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { PrismaClient } from '@prisma/client';
|
|
2
|
+
import { StorageAdapter } from '@node-tenant/tenant-core';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Create a Prisma-backed StorageAdapter for the @node-tenant/tenant public control layer.
|
|
6
|
+
*
|
|
7
|
+
* Usage:
|
|
8
|
+
* const storage = createPrismaStorage(prisma);
|
|
9
|
+
* const manager = new TenantManager({ storage });
|
|
10
|
+
*/
|
|
11
|
+
declare function createPrismaStorage(prisma: PrismaClient): StorageAdapter;
|
|
12
|
+
|
|
13
|
+
export { createPrismaStorage };
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { PrismaClient } from '@prisma/client';
|
|
2
|
+
import { StorageAdapter } from '@node-tenant/tenant-core';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Create a Prisma-backed StorageAdapter for the @node-tenant/tenant public control layer.
|
|
6
|
+
*
|
|
7
|
+
* Usage:
|
|
8
|
+
* const storage = createPrismaStorage(prisma);
|
|
9
|
+
* const manager = new TenantManager({ storage });
|
|
10
|
+
*/
|
|
11
|
+
declare function createPrismaStorage(prisma: PrismaClient): StorageAdapter;
|
|
12
|
+
|
|
13
|
+
export { createPrismaStorage };
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,139 @@
|
|
|
1
|
+
// src/index.ts
|
|
2
|
+
function toTenant(raw) {
|
|
3
|
+
return {
|
|
4
|
+
id: raw.id,
|
|
5
|
+
organizationId: raw.organizationId ?? void 0,
|
|
6
|
+
name: raw.name,
|
|
7
|
+
slug: raw.slug,
|
|
8
|
+
strategy: raw.strategy,
|
|
9
|
+
status: raw.status,
|
|
10
|
+
config: raw.config ?? {},
|
|
11
|
+
metadata: raw.metadata ?? void 0,
|
|
12
|
+
createdAt: raw.createdAt,
|
|
13
|
+
updatedAt: raw.updatedAt
|
|
14
|
+
};
|
|
15
|
+
}
|
|
16
|
+
function toOrg(raw) {
|
|
17
|
+
return {
|
|
18
|
+
id: raw.id,
|
|
19
|
+
name: raw.name,
|
|
20
|
+
slug: raw.slug,
|
|
21
|
+
metadata: raw.metadata ?? void 0,
|
|
22
|
+
createdAt: raw.createdAt,
|
|
23
|
+
updatedAt: raw.updatedAt
|
|
24
|
+
};
|
|
25
|
+
}
|
|
26
|
+
function createPrismaStorage(prisma) {
|
|
27
|
+
return {
|
|
28
|
+
// ── Tenants ──────────────────────────────────────────────────────────────
|
|
29
|
+
async createTenant(data) {
|
|
30
|
+
const raw = await prisma.tenant.create({
|
|
31
|
+
data: {
|
|
32
|
+
name: data.name,
|
|
33
|
+
slug: data.slug,
|
|
34
|
+
organizationId: data.organizationId,
|
|
35
|
+
strategy: data.strategy,
|
|
36
|
+
status: data.status,
|
|
37
|
+
config: data.config ?? {},
|
|
38
|
+
metadata: data.metadata ?? void 0
|
|
39
|
+
}
|
|
40
|
+
});
|
|
41
|
+
return toTenant(raw);
|
|
42
|
+
},
|
|
43
|
+
async getTenant(id) {
|
|
44
|
+
const raw = await prisma.tenant.findUnique({ where: { id } });
|
|
45
|
+
return raw ? toTenant(raw) : null;
|
|
46
|
+
},
|
|
47
|
+
async getTenantBySlug(slug) {
|
|
48
|
+
const raw = await prisma.tenant.findUnique({ where: { slug } });
|
|
49
|
+
return raw ? toTenant(raw) : null;
|
|
50
|
+
},
|
|
51
|
+
async updateTenant(id, data) {
|
|
52
|
+
const raw = await prisma.tenant.update({ where: { id }, data });
|
|
53
|
+
return toTenant(raw);
|
|
54
|
+
},
|
|
55
|
+
async deleteTenant(id) {
|
|
56
|
+
await prisma.tenant.delete({ where: { id } });
|
|
57
|
+
},
|
|
58
|
+
async listTenants(filter) {
|
|
59
|
+
const raws = await prisma.tenant.findMany({ where: filter ?? {} });
|
|
60
|
+
return raws.map(toTenant);
|
|
61
|
+
},
|
|
62
|
+
// ── Organizations ─────────────────────────────────────────────────────────
|
|
63
|
+
async createOrganization(data) {
|
|
64
|
+
const raw = await prisma.tenantOrganization.create({ data });
|
|
65
|
+
return toOrg(raw);
|
|
66
|
+
},
|
|
67
|
+
async getOrganization(id) {
|
|
68
|
+
const raw = await prisma.tenantOrganization.findUnique({ where: { id } });
|
|
69
|
+
return raw ? toOrg(raw) : null;
|
|
70
|
+
},
|
|
71
|
+
async updateOrganization(id, data) {
|
|
72
|
+
const raw = await prisma.tenantOrganization.update({ where: { id }, data });
|
|
73
|
+
return toOrg(raw);
|
|
74
|
+
},
|
|
75
|
+
async deleteOrganization(id) {
|
|
76
|
+
await prisma.tenantOrganization.delete({ where: { id } });
|
|
77
|
+
},
|
|
78
|
+
async listOrganizations() {
|
|
79
|
+
const raws = await prisma.tenantOrganization.findMany();
|
|
80
|
+
return raws.map(toOrg);
|
|
81
|
+
},
|
|
82
|
+
// ── Domains ───────────────────────────────────────────────────────────────
|
|
83
|
+
async createDomain(data) {
|
|
84
|
+
return prisma.tenantDomain.create({ data });
|
|
85
|
+
},
|
|
86
|
+
async getDomainByHost(host) {
|
|
87
|
+
return prisma.tenantDomain.findUnique({ where: { domain: host } });
|
|
88
|
+
},
|
|
89
|
+
async deleteDomain(id) {
|
|
90
|
+
await prisma.tenantDomain.delete({ where: { id } });
|
|
91
|
+
},
|
|
92
|
+
// ── Relationships ─────────────────────────────────────────────────────────
|
|
93
|
+
async createRelationship(data) {
|
|
94
|
+
return prisma.tenantRelationship.create({ data });
|
|
95
|
+
},
|
|
96
|
+
async getRelationships(tenantId) {
|
|
97
|
+
return prisma.tenantRelationship.findMany({
|
|
98
|
+
where: {
|
|
99
|
+
OR: [{ sourceTenantId: tenantId }, { targetTenantId: tenantId }]
|
|
100
|
+
}
|
|
101
|
+
});
|
|
102
|
+
},
|
|
103
|
+
async deleteRelationship(id) {
|
|
104
|
+
await prisma.tenantRelationship.delete({ where: { id } });
|
|
105
|
+
},
|
|
106
|
+
// ── Resource shares ───────────────────────────────────────────────────────
|
|
107
|
+
async createResourceShare(data) {
|
|
108
|
+
return prisma.resourceShare.create({ data });
|
|
109
|
+
},
|
|
110
|
+
async getResourceShares(filter) {
|
|
111
|
+
const where = {};
|
|
112
|
+
if (filter.resourceType) where["resourceType"] = filter.resourceType;
|
|
113
|
+
if (filter.resourceId) where["resourceId"] = filter.resourceId;
|
|
114
|
+
if (filter.ownerTenantId) where["ownerTenantId"] = filter.ownerTenantId;
|
|
115
|
+
if (filter.targetTenantId) where["targetTenantId"] = filter.targetTenantId;
|
|
116
|
+
return prisma.resourceShare.findMany({ where });
|
|
117
|
+
},
|
|
118
|
+
async deleteResourceShare(id) {
|
|
119
|
+
await prisma.resourceShare.delete({ where: { id } });
|
|
120
|
+
},
|
|
121
|
+
// ── Audit ─────────────────────────────────────────────────────────────────
|
|
122
|
+
async createAuditLog(data) {
|
|
123
|
+
return prisma.auditLog.create({
|
|
124
|
+
data: { ...data, createdAt: /* @__PURE__ */ new Date() }
|
|
125
|
+
});
|
|
126
|
+
},
|
|
127
|
+
async listAuditLogs(tenantId, limit = 100) {
|
|
128
|
+
return prisma.auditLog.findMany({
|
|
129
|
+
where: { tenantId },
|
|
130
|
+
orderBy: { createdAt: "desc" },
|
|
131
|
+
take: limit
|
|
132
|
+
});
|
|
133
|
+
}
|
|
134
|
+
};
|
|
135
|
+
}
|
|
136
|
+
export {
|
|
137
|
+
createPrismaStorage
|
|
138
|
+
};
|
|
139
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/index.ts"],"sourcesContent":["import type { PrismaClient } from '@prisma/client';\nimport type {\n StorageAdapter,\n Tenant,\n Organization,\n TenantDomain,\n TenantRelationship,\n ResourceShare,\n AuditLog,\n} from '@node-tenant/tenant-core';\n\nfunction toTenant(raw: any): Tenant {\n return {\n id: raw.id,\n organizationId: raw.organizationId ?? undefined,\n name: raw.name,\n slug: raw.slug,\n strategy: raw.strategy as Tenant['strategy'],\n status: raw.status as Tenant['status'],\n config: (raw.config as Record<string, unknown>) ?? {},\n metadata: (raw.metadata as Record<string, unknown>) ?? undefined,\n createdAt: raw.createdAt,\n updatedAt: raw.updatedAt,\n };\n}\n\nfunction toOrg(raw: any): Organization {\n return {\n id: raw.id,\n name: raw.name,\n slug: raw.slug,\n metadata: (raw.metadata as Record<string, unknown>) ?? undefined,\n createdAt: raw.createdAt,\n updatedAt: raw.updatedAt,\n };\n}\n\n/**\n * Create a Prisma-backed StorageAdapter for the @node-tenant/tenant public control layer.\n *\n * Usage:\n * const storage = createPrismaStorage(prisma);\n * const manager = new TenantManager({ storage });\n */\nexport function createPrismaStorage(prisma: PrismaClient): StorageAdapter {\n return {\n // ── Tenants ──────────────────────────────────────────────────────────────\n async createTenant(data) {\n const raw = await (prisma as any).tenant.create({\n data: {\n name: data.name,\n slug: data.slug,\n organizationId: data.organizationId,\n strategy: data.strategy,\n status: data.status,\n config: data.config ?? {},\n metadata: data.metadata ?? undefined,\n },\n });\n return toTenant(raw);\n },\n\n async getTenant(id) {\n const raw = await (prisma as any).tenant.findUnique({ where: { id } });\n return raw ? toTenant(raw) : null;\n },\n\n async getTenantBySlug(slug) {\n const raw = await (prisma as any).tenant.findUnique({ where: { slug } });\n return raw ? toTenant(raw) : null;\n },\n\n async updateTenant(id, data) {\n const raw = await (prisma as any).tenant.update({ where: { id }, data });\n return toTenant(raw);\n },\n\n async deleteTenant(id) {\n await (prisma as any).tenant.delete({ where: { id } });\n },\n\n async listTenants(filter) {\n const raws = await (prisma as any).tenant.findMany({ where: filter ?? {} });\n return raws.map(toTenant);\n },\n\n // ── Organizations ─────────────────────────────────────────────────────────\n async createOrganization(data) {\n const raw = await (prisma as any).tenantOrganization.create({ data });\n return toOrg(raw);\n },\n\n async getOrganization(id) {\n const raw = await (prisma as any).tenantOrganization.findUnique({ where: { id } });\n return raw ? toOrg(raw) : null;\n },\n\n async updateOrganization(id, data) {\n const raw = await (prisma as any).tenantOrganization.update({ where: { id }, data });\n return toOrg(raw);\n },\n\n async deleteOrganization(id) {\n await (prisma as any).tenantOrganization.delete({ where: { id } });\n },\n\n async listOrganizations() {\n const raws = await (prisma as any).tenantOrganization.findMany();\n return raws.map(toOrg);\n },\n\n // ── Domains ───────────────────────────────────────────────────────────────\n async createDomain(data) {\n return (prisma as any).tenantDomain.create({ data }) as Promise<TenantDomain>;\n },\n\n async getDomainByHost(host) {\n return (prisma as any).tenantDomain.findUnique({ where: { domain: host } }) as Promise<TenantDomain | null>;\n },\n\n async deleteDomain(id) {\n await (prisma as any).tenantDomain.delete({ where: { id } });\n },\n\n // ── Relationships ─────────────────────────────────────────────────────────\n async createRelationship(data) {\n return (prisma as any).tenantRelationship.create({ data }) as Promise<TenantRelationship>;\n },\n\n async getRelationships(tenantId) {\n return (prisma as any).tenantRelationship.findMany({\n where: {\n OR: [{ sourceTenantId: tenantId }, { targetTenantId: tenantId }],\n },\n }) as Promise<TenantRelationship[]>;\n },\n\n async deleteRelationship(id) {\n await (prisma as any).tenantRelationship.delete({ where: { id } });\n },\n\n // ── Resource shares ───────────────────────────────────────────────────────\n async createResourceShare(data) {\n return (prisma as any).resourceShare.create({ data }) as Promise<ResourceShare>;\n },\n\n async getResourceShares(filter) {\n const where: Record<string, unknown> = {};\n if (filter.resourceType) where['resourceType'] = filter.resourceType;\n if (filter.resourceId) where['resourceId'] = filter.resourceId;\n if (filter.ownerTenantId) where['ownerTenantId'] = filter.ownerTenantId;\n if (filter.targetTenantId) where['targetTenantId'] = filter.targetTenantId;\n return (prisma as any).resourceShare.findMany({ where }) as Promise<ResourceShare[]>;\n },\n\n async deleteResourceShare(id) {\n await (prisma as any).resourceShare.delete({ where: { id } });\n },\n\n // ── Audit ─────────────────────────────────────────────────────────────────\n async createAuditLog(data) {\n return (prisma as any).auditLog.create({\n data: { ...data, createdAt: new Date() },\n }) as Promise<AuditLog>;\n },\n\n async listAuditLogs(tenantId, limit = 100) {\n return (prisma as any).auditLog.findMany({\n where: { tenantId },\n orderBy: { createdAt: 'desc' },\n take: limit,\n }) as Promise<AuditLog[]>;\n },\n };\n}\n"],"mappings":"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","names":[]}
|
package/package.json
ADDED
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@node-tenant/tenant-storage-prisma",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "Prisma storage adapter for @node-tenant/tenant",
|
|
5
|
+
"license": "MIT",
|
|
6
|
+
"type": "module",
|
|
7
|
+
"main": "./dist/index.cjs",
|
|
8
|
+
"module": "./dist/index.js",
|
|
9
|
+
"types": "./dist/index.d.ts",
|
|
10
|
+
"exports": {
|
|
11
|
+
".":{
|
|
12
|
+
"types": "./dist/index.d.ts",
|
|
13
|
+
"import": "./dist/index.js",
|
|
14
|
+
"require": "./dist/index.cjs"
|
|
15
|
+
},
|
|
16
|
+
"./schema": "./schema.prisma"
|
|
17
|
+
},
|
|
18
|
+
"files": ["dist", "schema.prisma"],
|
|
19
|
+
"scripts": {
|
|
20
|
+
"build": "tsup",
|
|
21
|
+
"dev": "tsup --watch",
|
|
22
|
+
"test": "vitest run",
|
|
23
|
+
"clean": "rimraf dist"
|
|
24
|
+
},
|
|
25
|
+
"dependencies": {
|
|
26
|
+
"@node-tenant/tenant-core": "^0.1.0"
|
|
27
|
+
},
|
|
28
|
+
"peerDependencies": {
|
|
29
|
+
"@prisma/client": ">=5.0.0"
|
|
30
|
+
},
|
|
31
|
+
"devDependencies": {
|
|
32
|
+
"@prisma/client": "^5.10.0",
|
|
33
|
+
"prisma": "^5.10.0",
|
|
34
|
+
"rimraf": "^5.0.5",
|
|
35
|
+
"tsup": "^8.0.0",
|
|
36
|
+
"typescript": "^5.4.0",
|
|
37
|
+
"vitest": "^1.4.0"
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
|
package/schema.prisma
ADDED
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
// Prisma schema for @node-tenant/tenant public control layer.
|
|
2
|
+
// Copy this into your app's schema.prisma or use prisma merge.
|
|
3
|
+
|
|
4
|
+
generator client {
|
|
5
|
+
provider = "prisma-client-js"
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
datasource db {
|
|
9
|
+
provider = "postgresql"
|
|
10
|
+
url = env("DATABASE_URL")
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
model TenantOrganization {
|
|
14
|
+
id String @id @default(cuid())
|
|
15
|
+
name String
|
|
16
|
+
slug String @unique
|
|
17
|
+
metadata Json?
|
|
18
|
+
createdAt DateTime @default(now())
|
|
19
|
+
updatedAt DateTime @updatedAt
|
|
20
|
+
tenants Tenant[]
|
|
21
|
+
|
|
22
|
+
@@map("tenant_organizations")
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
model Tenant {
|
|
26
|
+
id String @id @default(cuid())
|
|
27
|
+
organizationId String?
|
|
28
|
+
organization TenantOrganization? @relation(fields: [organizationId], references: [id])
|
|
29
|
+
name String
|
|
30
|
+
slug String @unique
|
|
31
|
+
strategy String @default("tenantId")
|
|
32
|
+
status String @default("active")
|
|
33
|
+
config Json @default("{}")
|
|
34
|
+
metadata Json?
|
|
35
|
+
createdAt DateTime @default(now())
|
|
36
|
+
updatedAt DateTime @updatedAt
|
|
37
|
+
|
|
38
|
+
domains TenantDomain[]
|
|
39
|
+
sourceRelationships TenantRelationship[] @relation("SourceTenant")
|
|
40
|
+
targetRelationships TenantRelationship[] @relation("TargetTenant")
|
|
41
|
+
ownedShares ResourceShare[] @relation("OwnerTenant")
|
|
42
|
+
receivedShares ResourceShare[] @relation("TargetTenant")
|
|
43
|
+
auditLogs AuditLog[]
|
|
44
|
+
|
|
45
|
+
@@map("tenants")
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
model TenantDomain {
|
|
49
|
+
id String @id @default(cuid())
|
|
50
|
+
tenantId String
|
|
51
|
+
tenant Tenant @relation(fields: [tenantId], references: [id], onDelete: Cascade)
|
|
52
|
+
domain String @unique
|
|
53
|
+
isPrimary Boolean @default(false)
|
|
54
|
+
createdAt DateTime @default(now())
|
|
55
|
+
|
|
56
|
+
@@map("tenant_domains")
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
model TenantRelationship {
|
|
60
|
+
id String @id @default(cuid())
|
|
61
|
+
sourceTenantId String
|
|
62
|
+
targetTenantId String
|
|
63
|
+
sourceTenant Tenant @relation("SourceTenant", fields: [sourceTenantId], references: [id])
|
|
64
|
+
targetTenant Tenant @relation("TargetTenant", fields: [targetTenantId], references: [id])
|
|
65
|
+
type String
|
|
66
|
+
metadata Json?
|
|
67
|
+
createdAt DateTime @default(now())
|
|
68
|
+
|
|
69
|
+
@@unique([sourceTenantId, targetTenantId, type])
|
|
70
|
+
@@map("tenant_relationships")
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
model ResourceShare {
|
|
74
|
+
id String @id @default(cuid())
|
|
75
|
+
resourceType String
|
|
76
|
+
resourceId String
|
|
77
|
+
ownerTenantId String
|
|
78
|
+
targetTenantId String
|
|
79
|
+
ownerTenant Tenant @relation("OwnerTenant", fields: [ownerTenantId], references: [id])
|
|
80
|
+
targetTenant Tenant @relation("TargetTenant", fields: [targetTenantId], references: [id])
|
|
81
|
+
permission String @default("read")
|
|
82
|
+
expiresAt DateTime?
|
|
83
|
+
metadata Json?
|
|
84
|
+
createdAt DateTime @default(now())
|
|
85
|
+
|
|
86
|
+
@@unique([resourceType, resourceId, ownerTenantId, targetTenantId])
|
|
87
|
+
@@map("resource_shares")
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
model AuditLog {
|
|
91
|
+
id String @id @default(cuid())
|
|
92
|
+
tenantId String
|
|
93
|
+
tenant Tenant @relation(fields: [tenantId], references: [id])
|
|
94
|
+
action String
|
|
95
|
+
actorId String?
|
|
96
|
+
resourceType String?
|
|
97
|
+
resourceId String?
|
|
98
|
+
metadata Json?
|
|
99
|
+
createdAt DateTime @default(now())
|
|
100
|
+
|
|
101
|
+
@@index([tenantId, createdAt])
|
|
102
|
+
@@map("audit_logs")
|
|
103
|
+
}
|