Skip to content

Commit 2375021

Browse files
committed
fix: allow to pass custom client module to prisma adapter
1 parent c22d5c2 commit 2375021

File tree

9 files changed

+84
-21
lines changed

9 files changed

+84
-21
lines changed

README.md

+53-1
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ import AdminJS from 'adminjs'
1919
AdminJS.registerAdapter({ Database, Resource })
2020
```
2121

22-
## Example
22+
## Example (Basic)
2323

2424
Whole code can be found in `example-app` directory in the repository.
2525

@@ -68,6 +68,58 @@ run()
6868
})
6969
```
7070

71+
## Example (Custom Client Output Path)
72+
73+
If you defined a custom client output path in your Prisma's schema, for example:
74+
75+
```prisma
76+
generator client {
77+
provider = "prisma-client-js"
78+
output = "./client-prisma"
79+
}
80+
```
81+
82+
You must:
83+
* import your custom Prisma client
84+
* provide it to each resource which uses that Prisma client
85+
86+
*Example*:
87+
88+
```typescript
89+
// other imports
90+
import PrismaModule from '../prisma/client-prisma/index.js';
91+
92+
// ...
93+
94+
const prisma = new PrismaModule.PrismaClient();
95+
96+
// ...
97+
98+
// Notice `clientModule` per resource
99+
const admin = new AdminJS({
100+
resources: [{
101+
resource: { model: getModelByName('Post', PrismaModule), client: prisma, clientModule: PrismaModule },
102+
options: {
103+
properties: {
104+
someJson: { type: 'mixed', isArray: true },
105+
'someJson.number': { type: 'number' },
106+
'someJson.string': { type: 'string' },
107+
'someJson.boolean': { type: 'boolean' },
108+
'someJson.date': { type: 'datetime' },
109+
},
110+
},
111+
}, {
112+
resource: { model: getModelByName('Profile', PrismaModule), client: prisma, clientModule: PrismaModule },
113+
options: {},
114+
}, {
115+
resource: { model: getModelByName('Publisher', PrismaModule), client: prisma, clientModule: PrismaModule },
116+
options: {},
117+
}],
118+
});
119+
120+
// ...
121+
```
122+
71123
## ManyToOne / ManyToMany
72124

73125
These relationships are currently not supported by default. You can manage them using custom actions and components.

example-app/.gitignore

+1
Original file line numberDiff line numberDiff line change
@@ -4,3 +4,4 @@ node_modules/
44
build/
55
tmp/
66
temp/
7+
prisma/client-prisma

example-app/prisma/schema.prisma

+1
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ datasource db {
55

66
generator client {
77
provider = "prisma-client-js"
8+
output = "./client-prisma"
89
}
910

1011
enum Status {

example-app/src/index.ts

+7-5
Original file line numberDiff line numberDiff line change
@@ -2,12 +2,14 @@
22
import express from 'express';
33
import AdminJS from 'adminjs';
44
import AdminJSExpress from '@adminjs/express';
5-
import { PrismaClient } from '@prisma/client';
65
import { Database, Resource, getModelByName } from '@adminjs/prisma';
76

7+
// eslint-disable-next-line import/no-relative-packages
8+
import PrismaModule from '../prisma/client-prisma/index.js';
9+
810
const PORT = process.env.port || 3000;
911

10-
const prisma = new PrismaClient();
12+
const prisma = new PrismaModule.PrismaClient();
1113

1214
AdminJS.registerAdapter({ Database, Resource });
1315

@@ -16,7 +18,7 @@ const run = async () => {
1618

1719
const admin = new AdminJS({
1820
resources: [{
19-
resource: { model: getModelByName('Post'), client: prisma },
21+
resource: { model: getModelByName('Post', PrismaModule), client: prisma, clientModule: PrismaModule },
2022
options: {
2123
properties: {
2224
someJson: { type: 'mixed', isArray: true },
@@ -27,10 +29,10 @@ const run = async () => {
2729
},
2830
},
2931
}, {
30-
resource: { model: getModelByName('Profile'), client: prisma },
32+
resource: { model: getModelByName('Profile', PrismaModule), client: prisma, clientModule: PrismaModule },
3133
options: {},
3234
}, {
33-
resource: { model: getModelByName('Publisher'), client: prisma },
35+
resource: { model: getModelByName('Publisher', PrismaModule), client: prisma, clientModule: PrismaModule },
3436
options: {},
3537
}],
3638
});

spec/Database.spec.ts

+2-2
Original file line numberDiff line numberDiff line change
@@ -18,13 +18,13 @@ describe('Database', () => {
1818

1919
describe('.isAdapterFor', () => {
2020
it('returns true when Prisma is properly initialized', () => {
21-
expect(Database.isAdapterFor(prisma)).toEqual(true);
21+
expect(Database.isAdapterFor({ client: prisma })).toEqual(true);
2222
});
2323
});
2424

2525
describe('#resources', () => {
2626
it('returns all entities', async () => {
27-
expect(new Database(prisma).resources()).toHaveLength(4);
27+
expect(new Database({ client: prisma }).resources()).toHaveLength(4);
2828
});
2929
});
3030
});

src/Database.ts

+13-6
Original file line numberDiff line numberDiff line change
@@ -8,13 +8,18 @@ import { Resource } from './Resource.js';
88
export class Database extends BaseDatabase {
99
private client: PrismaClient;
1010

11-
public constructor(public readonly prisma: PrismaClient) {
12-
super(prisma);
13-
this.client = prisma;
11+
private clientModule?: any;
12+
13+
public constructor(args: { client: PrismaClient, clientModule?: any }) {
14+
super(args);
15+
const { client, clientModule } = args;
16+
17+
this.client = client;
18+
this.clientModule = clientModule;
1419
}
1520

1621
public resources(): Array<Resource> {
17-
const dmmf = Prisma.dmmf.datamodel;
22+
const dmmf = this.clientModule?.Prisma.dmmf.datamodel ?? Prisma.dmmf.datamodel;
1823

1924
if (!dmmf?.models) return [];
2025

@@ -25,8 +30,10 @@ export class Database extends BaseDatabase {
2530
}
2631

2732
// eslint-disable-next-line @typescript-eslint/no-unused-vars
28-
public static isAdapterFor(_prisma?: PrismaClient): boolean {
29-
const dmmf = Prisma.dmmf.datamodel;
33+
public static isAdapterFor(args: { client?: PrismaClient, clientModule?: any }): boolean {
34+
const { clientModule } = args;
35+
36+
const dmmf = clientModule?.Prisma.dmmf.datamodel ?? Prisma.dmmf.datamodel;
3037

3138
return dmmf?.models?.length > 0;
3239
}

src/Resource.ts

+3-3
Original file line numberDiff line numberDiff line change
@@ -22,13 +22,13 @@ export class Resource extends BaseResource {
2222

2323
private propertiesObject: Record<string, any>;
2424

25-
constructor(args: { model: DMMF.Model, client: PrismaClient }) {
25+
constructor(args: { model: DMMF.Model, client: PrismaClient, clientModule?: any }) {
2626
super(args);
2727

28-
const { model, client } = args;
28+
const { model, client, clientModule } = args;
2929
this.model = model;
3030
this.client = client;
31-
this.enums = getEnums();
31+
this.enums = getEnums(clientModule);
3232
this.manager = this.client[lowerCase(model.name)];
3333
this.propertiesObject = this.prepareProperties();
3434
}

src/utils/get-enums.ts

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
import { Prisma } from '@prisma/client';
22
import { Enums } from '../types.js';
33

4-
export const getEnums = (): Enums => {
5-
const dmmf = Prisma.dmmf.datamodel;
4+
export const getEnums = (clientModule?: any): Enums => {
5+
const dmmf = clientModule?.Prisma.dmmf.datamodel ?? Prisma.dmmf.datamodel;
66

77
return dmmf.enums.reduce((memo, current) => {
88
// eslint-disable-next-line no-param-reassign

src/utils/get-model-by-name.ts

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import { Prisma } from '@prisma/client';
22

3-
export const getModelByName = (name: string) => {
4-
const dmmf = Prisma.dmmf.datamodel;
3+
export const getModelByName = (name: string, clientModule?: any) => {
4+
const dmmf = clientModule?.Prisma.dmmf.datamodel ?? Prisma.dmmf.datamodel;
55

66
const model = dmmf.models.find(({ name: modelName }) => modelName === name);
77

0 commit comments

Comments
 (0)