Skip to content

Commit

Permalink
[WIP] Convert prisma adapter to typescript
Browse files Browse the repository at this point in the history
  • Loading branch information
timleslie committed Mar 31, 2021
1 parent 1261c39 commit 9d87148
Showing 1 changed file with 70 additions and 31 deletions.
Original file line number Diff line number Diff line change
@@ -1,26 +1,48 @@
import pWaterfall from 'p-waterfall';
import { defaultObj, mapKeys, identity, flatten } from '@keystone-next/utils-legacy';

type Rels = any[];

type ListAdapterConfig = {};

class PrismaAdapter {
config?: {
prismaClient?: any;
provider?: 'postgresql' | 'sqlite';
enableLogging?: boolean;
url?: string;
};
listAdapters: Record<string, PrismaListAdapter>;
listAdapterClass?: any;
_prismaClient?: any;
name: 'prisma';
provider: 'postgresql' | 'sqlite';
enableLogging: boolean;
url: string;

schemaPath?: string;
clientPath?: string;
prisma: any;

constructor(config = {}) {
this.config = { ...config };
this.listAdapters = {};
this.name = 'prisma';
this.provider = this.config.provider || 'postgresql';
this.enableLogging = this.config.enableLogging || false;
this.url = this.config.url || process.env.DATABASE_URL;
this.url = this.config.url || process.env.DATABASE_URL || '';
}

newListAdapter(key, adapterConfig) {
newListAdapter(key: string, adapterConfig: ListAdapterConfig) {
this.listAdapters[key] = new PrismaListAdapter(key, this, adapterConfig);
return this.listAdapters[key];
}

getListAdapterByKey(key) {
getListAdapterByKey(key: string) {
return this.listAdapters[key];
}

async connect({ rels }) {
async connect({ rels }: { rels: Rels }) {
// Connect to the database
// the adapter was already connected since we have a prisma client
// it may have been disconnected since it was connected though
Expand All @@ -29,7 +51,7 @@ class PrismaAdapter {
await this.prisma.$connect();
return;
}
if (!this.config.prismaClient) {
if (!this.config?.prismaClient) {
throw new Error('You must pass the prismaClient option to connect to a database');
}
this.prisma = new this.config.prismaClient({
Expand All @@ -45,7 +67,7 @@ class PrismaAdapter {
await this.prisma.$connect();
}

_generatePrismaSchema({ rels, clientDir }) {
_generatePrismaSchema({ rels, clientDir }: { rels: Rels; clientDir: string }) {
const models = Object.values(this.listAdapters).map(listAdapter => {
const scalarFields = flatten(
listAdapter.fieldAdapters.filter(f => !f.field.isRelationship).map(f => f.getPrismaSchema())
Expand Down Expand Up @@ -154,7 +176,12 @@ class PrismaAdapter {
}

class PrismaListAdapter {
constructor(key, parentAdapter, config) {
key: string;
parentAdapter: PrismaAdapter;
fieldAdapters: PrismaFieldAdapter[];
fieldAdaptersByPath: Record<string, PrismaFieldAdapter>;
config: ListAdapterConfig;
constructor(key: string, parentAdapter: PrismaAdapter, config: ListAdapterConfig) {
this.key = key;
this.parentAdapter = parentAdapter;
this.fieldAdapters = [];
Expand All @@ -173,7 +200,7 @@ class PrismaListAdapter {
this.getListAdapterByKey = parentAdapter.getListAdapterByKey.bind(parentAdapter);
}

newFieldAdapter(fieldAdapterClass, name, path, field, getListByKey, config) {
newFieldAdapter(fieldAdapterClass, name: string, path: string, field, getListByKey, config) {
const adapter = new fieldAdapterClass(name, path, field, this, getListByKey, config);
adapter.setupHooks({
addPreSaveHook: this.addPreSaveHook.bind(this),
Expand Down Expand Up @@ -234,12 +261,12 @@ class PrismaListAdapter {
return this.onPostRead((await this._itemsQuery({ where: condition, first: 1 }))[0]);
}

async itemsQuery(args, { meta = false, from = {} } = {}) {
async itemsQuery(args: ItemQueryArgs, { meta = false, from = {} } = {}) {
const results = await this._itemsQuery(args, { meta, from });
return meta ? results : Promise.all(results.map(item => this.onPostRead(item)));
}

itemsQueryMeta(args) {
itemsQueryMeta(args: ItemQueryArgs) {
return this.itemsQuery(args, { meta: true });
}

Expand All @@ -251,7 +278,7 @@ class PrismaListAdapter {
return this.fieldAdaptersByPath['id'];
}

_setupModel({ rels, prisma }) {
_setupModel({ rels, prisma }: { rels: Rels }) {
// https://www.prisma.io/docs/reference/tools-and-interfaces/prisma-schema/models#queries-crud
// "By default the name of the property is the lowercase form of the model name,
// e.g. user for a User model or post for a Post model."
Expand Down Expand Up @@ -333,7 +360,7 @@ class PrismaListAdapter {
}

////////// Queries //////////
async _itemsQuery(args, { meta = false, from = {} } = {}) {
async _itemsQuery(args: ItemQueryArgs, { meta = false, from = {} } = {}) {
const filter = this.prismaFilter({ args, meta, from });
if (meta) {
let count = await this.model.count(filter);
Expand Down Expand Up @@ -483,7 +510,19 @@ class PrismaListAdapter {
}

class PrismaFieldAdapter {
constructor(fieldName, path, field, listAdapter, getListByKey, config = {}) {
fieldName: string;
path: string;
field: Field;
dbPath: string;

constructor(
fieldName: string,
path: string,
field: Field,
listAdapter,
getListByKey,
config = {}
) {
this.fieldName = fieldName;
this.path = path;
this.field = field;
Expand Down Expand Up @@ -515,7 +554,7 @@ class PrismaFieldAdapter {
// `dbPath`: The database field/column name to be used in the comparison
// `f`: (non-string methods only) A value transformation function which converts from a string type
// provided by graphQL into a native adapter type.
equalityConditions(dbPath, f = identity) {
equalityConditions(dbPath: string, f = identity) {
return {
[this.path]: value => ({ [dbPath]: { equals: f(value) } }),
[`${this.path}_not`]: value =>
Expand All @@ -527,7 +566,7 @@ class PrismaFieldAdapter {
};
}

equalityConditionsInsensitive(dbPath, f = identity) {
equalityConditionsInsensitive(dbPath: string, f = identity) {
return {
[`${this.path}_i`]: value => ({ [dbPath]: { equals: f(value), mode: 'insensitive' } }),
[`${this.path}_not_i`]: value =>
Expand All @@ -542,7 +581,7 @@ class PrismaFieldAdapter {
};
}

inConditions(dbPath, f = identity) {
inConditions(dbPath: string, f = identity) {
return {
[`${this.path}_in`]: value =>
value.includes(null)
Expand All @@ -562,7 +601,7 @@ class PrismaFieldAdapter {
};
}

orderingConditions(dbPath, f = identity) {
orderingConditions(dbPath: string, f = identity) {
return {
[`${this.path}_lt`]: value => ({ [dbPath]: { lt: f(value) } }),
[`${this.path}_lte`]: value => ({ [dbPath]: { lte: f(value) } }),
Expand All @@ -571,47 +610,47 @@ class PrismaFieldAdapter {
};
}

stringConditions(dbPath, f = identity) {
stringConditions(dbPath: string, f = identity) {
return {
[`${this.path}_contains`]: value => ({ [dbPath]: { contains: f(value) } }),
[`${this.path}_not_contains`]: value => ({
[`${this.path}_contains`]: (value: string) => ({ [dbPath]: { contains: f(value) } }),
[`${this.path}_not_contains`]: (value: string) => ({
OR: [{ NOT: { [dbPath]: { contains: f(value) } } }, { [dbPath]: null }],
}),
[`${this.path}_starts_with`]: value => ({ [dbPath]: { startsWith: f(value) } }),
[`${this.path}_not_starts_with`]: value => ({
[`${this.path}_starts_with`]: (value: string) => ({ [dbPath]: { startsWith: f(value) } }),
[`${this.path}_not_starts_with`]: (value: string) => ({
OR: [{ NOT: { [dbPath]: { startsWith: f(value) } } }, { [dbPath]: null }],
}),
[`${this.path}_ends_with`]: value => ({ [dbPath]: { endsWith: f(value) } }),
[`${this.path}_not_ends_with`]: value => ({
[`${this.path}_ends_with`]: (value: string) => ({ [dbPath]: { endsWith: f(value) } }),
[`${this.path}_not_ends_with`]: (value: string) => ({
OR: [{ NOT: { [dbPath]: { endsWith: f(value) } } }, { [dbPath]: null }],
}),
};
}

stringConditionsInsensitive(dbPath, f = identity) {
stringConditionsInsensitive(dbPath: string, f = identity) {
return {
[`${this.path}_contains_i`]: value => ({
[`${this.path}_contains_i`]: (value: string) => ({
[dbPath]: { contains: f(value), mode: 'insensitive' },
}),
[`${this.path}_not_contains_i`]: value => ({
[`${this.path}_not_contains_i`]: (value: string) => ({
OR: [
{ NOT: { [dbPath]: { contains: f(value), mode: 'insensitive' } } },
{ [dbPath]: null },
],
}),
[`${this.path}_starts_with_i`]: value => ({
[`${this.path}_starts_with_i`]: (value: string) => ({
[dbPath]: { startsWith: f(value), mode: 'insensitive' },
}),
[`${this.path}_not_starts_with_i`]: value => ({
[`${this.path}_not_starts_with_i`]: (value: string) => ({
OR: [
{ NOT: { [dbPath]: { startsWith: f(value), mode: 'insensitive' } } },
{ [dbPath]: null },
],
}),
[`${this.path}_ends_with_i`]: value => ({
[`${this.path}_ends_with_i`]: (value: string) => ({
[dbPath]: { endsWith: f(value), mode: 'insensitive' },
}),
[`${this.path}_not_ends_with_i`]: value => ({
[`${this.path}_not_ends_with_i`]: (value: string) => ({
OR: [
{ NOT: { [dbPath]: { endsWith: f(value), mode: 'insensitive' } } },
{ [dbPath]: null },
Expand Down

0 comments on commit 9d87148

Please sign in to comment.