Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Question] Use prisma-client #16

Open
ecwyne opened this issue Sep 25, 2018 · 5 comments
Open

[Question] Use prisma-client #16

ecwyne opened this issue Sep 25, 2018 · 5 comments
Labels
enhancement New feature or request

Comments

@ecwyne
Copy link
Contributor

ecwyne commented Sep 25, 2018

I've been tinkering with the new prisma-client and think there's huge potential to simplify this project.

The following is a rough (but I think mostly working) implementation of how this would be done. Updates/creates still need to be converted to use {connect: {}, disconnect: {}, set: {}} etc.

I would love to hear your thoughts!

import {
    GET_LIST,
    GET_ONE,
    GET_MANY,
    GET_MANY_REFERENCE,
    CREATE,
    UPDATE,
    UPDATE_MANY,
    DELETE,
    DELETE_MANY,
} from 'react-admin';
import { makePrismaLink } from 'prisma-binding';
import { introspectSchema } from 'graphql-tools';
import { printSchema, DocumentNode } from 'graphql';
import camelcase from 'camelcase';
import pluralize from 'pluralize';
import { Client } from 'prisma-client-lib';

interface IParams {
    filter?: { [key: string]: string };
    pagination?: { page: number; perPage: number };
    sort?: { field: string; order: string };
    id?: string;
    data?: { [key: string]: any };
    ids?: string[];
}

interface IOptions {
    endpoint: string;
    fragments?: { [key: string]: DocumentNode };
}

export default async ({ endpoint, fragments = {} }: IOptions) => {
    const link = makePrismaLink({ endpoint });
    const schema = await introspectSchema(link);
    const typeDefs = printSchema(schema);
    const client = new Client({ endpoint, typeDefs, debug: false }) as any;
    return async (
        type: string,
        resource: string,
        params: IParams,
    ): Promise<any> => {
        const f = fragments[resource];
        switch (type) {
            case GET_LIST:
                return await client[camelcase(pluralize(resource))]({
                    where: params.filter,
                    orderBy: `${params.sort!.field}_${params.sort!.order}`,
                    first: params.pagination!.perPage,
                    skip:
                        (params.pagination!.page - 1) *
                        params.pagination!.perPage,
                }).$fragment(f);

            case GET_ONE:
                return client[camelcase(resource)](params).$fragment(f);

            case CREATE:
                return client[camelcase(`create${resource}`)](params.data); // TODO connect/set relations

            case DELETE:
                return client[camelcase(`delete${resource}`)](params);

            case DELETE_MANY:
                return client[camelcase(`deleteMany${pluralize(resource)}`)]({
                    where: { id_in: params.ids },
                });
            case GET_MANY:
                return client[camelcase(pluralize(resource))]({
                    where: { id_in: params.ids },
                }).$fragment(f);

            case UPDATE_MANY:
                return client[camelcase(`updateMany${pluralize(resource)}`)]({
                    where: { id_in: params.ids },
                    data: params.data, // TODO connect/set relations
                });
        }
    };
};

It would then be used like so:

createOpenCrudDataProvider({
    endpoint: 'YOUR_ENDPOINT_URL',
    fragments: {
        User: gql`
            fragment user on User {
                id
                email
                phone
            }
        `,
    },
})
@Weakky
Copy link
Owner

Weakky commented Sep 26, 2018

I've been thinking about either using gql bindings or prisma client in the past, and I think this wouldn't work/solve much problems for several reasons:

  • Using prisma-client would only replace most of the logic done in buildGqlQuery.js. We'd still have to transform the params object into input arguments that prisma accepts. One benefit though is that we'd have type-safety for free.

  • Because graphql-binding and prisma-client not only generates the graphql queries but also send http requests, we can't use them with proper GraphQL clients. This means that we'd loose features from Apollo Client, such as caching, smart re-rendering, optimistic updates and so on

@ecwyne
Copy link
Contributor Author

ecwyne commented Sep 26, 2018

  1. I believe the whole point of using something like prisma-client would be so that you don't have to write buildGqlQuery.js (let the library authors do it, they deal with all of the strange edge cases that may come up) Most of the transforming of params is extremely straightforward. The only ones that need any real consideration are CREATE, UPDATE, and UPDATE_MANY

  2. ra-data-graphql always sets fetchPolicy to network-only so I don't believe you're ever getting any caching anyway. My understanding is that react-admin updates its own cache outside of anything ApolloClient would do (though I can't find that reference now)

@ecwyne
Copy link
Contributor Author

ecwyne commented Sep 26, 2018

From the ra-data-grapql docs

react-admin maintain its own cache of resources data but, by default, so does the Apollo client. For every queries, we inject a default fetchPolicy set to network-only so that the Apollo client always refetch the data when requested.
Do not override this fetchPolicy.

@ecwyne
Copy link
Contributor Author

ecwyne commented Sep 26, 2018

Trying to explore this further I'm coming up against this issue.

prisma/prisma#3142

@Weakky
Copy link
Owner

Weakky commented Sep 27, 2018

Excellent arguments here. Looking at the issue, allowing prisma-client-lib to run in the browser seems like a trivial job. I might find time to send a PR, and then we'll be able to migrate the graphql query generation.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request
Projects
None yet
Development

No branches or pull requests

2 participants