• Skip to primary navigation
  • Skip to main content

Full Stack Data Solutions

  • About
  • Write for Us
  • Recommended Study

GraphQL

GraphQL: Prisma, how to use typescript to seed data.

September 30, 2019 By Andrew Obrigewitsch Leave a Comment

When one is using Prisma and needs to seed a database with data. One should always use a Typescript file instead of a seed.graphql file.

Using a Typescript file allows for much more control to ensure data that is being used in multiple locations is uniform. It reduces the amount of repetitive code you have to write (DRY) and and allows for typescript error checking. So why are people seeding with a GraphQL file? And why is it the default? I have no idea.

To start with we will need to edit the prisma.yml file to tell it what to do when we seed. I’m also generating a client which will be used in the seed file.

# Specifies the HTTP endpoint of your Prisma API.
endpoint: ${env:EXAMPLE_ENDPOINT}

# Defines your models, each model is mapped to the database as a table.
datamodel: datamodel.graphql
# Specifies the language and directory for the generated Prisma client.
generate:
  - generator: typescript-client
    output: ../../src/generated/example-client
# Seed your service with initial data based on `seed.ts`.
seed:
  run: ts-node ./seed.ts

Now wee need to create the seed.ts file.

import { $enum } from "ts-enum-util";
import { Example} from "../src/generated/";
import { roles } from "../src/schema/types";

const roleNames = $enum(roles).getValues();

admins =["joe", "bill"]

const setup = async (roles: string[], rolesEnum) => {
  await roles.forEach(async role => {
    Example.createRole({ name: role }).catch(err => console.log(err));
  });
  await admins.forEach(async i => {
    Example.createUser({
      name: i,
      roles: { connect: { name: rolesEnum.admin } }
    }).catch(err => console.log(err));
  });
};


setup(roleNames, roles);

I recommend creating a Prisma client that can be passed around to the server config and other locations. This makes it easy to include multiple Prisma endpoints as well as other clients as well. Here’s how I did it:

import { prisma as Example} from "./example-client";

export {
  Example
};

Please do let me know if you run into problems or have any questions.

Filed Under: GraphQL

GraphQL: How to Make a Relay Connection Type with Nexus by Prisma

September 20, 2019 By Andrew Obrigewitsch Leave a Comment

I really like using the format of Relay Connection Types as they create uniform output on GetAll<name> queries. It’s very easy on the front end to only have to check for edges and nodes, and makes for very reusable code.

The question was, how does one create Relay connections with Nexus by Prisma? Well it actually isn’t that hard to create the types, what took some thought was how to resolve the data retrieval into the types. I’m going to first place all types below.

export const PageInfo = objectType({
  name: "PageInfo",
  definition(t) {
    t.string("startCursor", { nullable: true });
    t.boolean("hasPreviousPage");
    t.string("endCursor", { nullable: true });
    t.boolean("hasNextPage");
  }
});

const userConnection = objectType({
  name: "userConnection",
  definition(t) {
    t.int("total_count");
    t.list.field("edges", { type: userEdge });
    t.field("pageInfo", { type: PageInfo });
  }
});
export const userEdge = objectType({
  name: "userEdge",
  definition(t) {
    t.string("cursor");
    t.field("node", { type: "user" });
  }
});

const User = objectType({
  name: "user",
  definition(t) {
    t.id("id");
    t.string("name");
    t.field("signedUp", { type: "dateTime" });
  }
});

Now that’s not too bad, but how do you get data into the page info, and total count? I’m going to do a real generic example of a resolver for the agove, as there are many way to retrieve the data.

const Query = objectType({
  name: "Query",
  definition(t) {
    t.field("users", {
      type: "userConnection",
      nullable: true,
      args: {
        where: arg({
          type: "UserInputType",
          required: true
        })
      },
      resolve: async (
        root,
        { where }: { where: userArgs },
        ctx: Context,
        info
      ) => {
        const { nextToken, previousToken, users } = await ctx.getUsers({
          where
        });

        // many ORMs and APIs have ways to get tokens
        const pageInfo = {
          hasPreviousPage: !!previousToken,
          startCursor: previousToken ? previousToken : null,
          hasNextPage: !!nextToken,
          endCursor: nextToken ? nextToken : null
        };

        let edges = [];
        if (users && users[0]) {
          edges = users.map(user => ({
            node: { ...user },
            cursor: user.id // this is up to your implementation
          }));
        }

        const total_count = users ? users.length : 0;

        return { pageInfo, edges, total_count };
      }
    });
  }
});

I hope this helps those trying to implement a Relay Connection Type with Nexus. Let me know if you have any questions.

Filed Under: GraphQL

Intro AWS Amplify CLI with React & GraphQL

September 18, 2019 By Andrew Obrigewitsch Leave a Comment

Andrew will walk you through AWS Amplify. AWS Amplify allows developers to quickly prototype and build scalable applications with minimal coding. Learn how to have your database and API up in minutes and serving data to your application.

Filed Under: AWS, GraphQL

What is GraphQL? Why use it over Rest?

September 18, 2019 By Andrew Obrigewitsch Leave a Comment

Find out the theory behind GraphQL, what you can do with it, why you should be using it and how to implement GraphQL in your React Application.

This talk is great for people want are looking for an introduction to GraphQL with the context of React. If you’re already familiar with GraphQL, you’ll gain some insights on React. If you’re already familiar with React, you may learn something new about GraphQL.

Filed Under: GraphQL

Creating a Custom Scalar with Nexus. GraphQL

September 17, 2019 By Andrew Obrigewitsch 1 Comment

I’m using Nexus and TypeScript as a code first approach for a GraphQL server at work. Today I needed to have one of the fields be a DateTime Scalar type to match with an AWS-SDK library I’m creating an GraphQL API for.

I found an example in the documentation on Nexus, but it wasn’t fully explained. So I thought I would write this post to help others that are creating custom GraphQL Scalars with Nexus.

Below is the example given in the Nexus documentation, which I’ve slightly changed to match how I had to use it in my case.

So let me just explain what it does and then I will show how to use it.

const DateScalar = scalarType({
  name: "dateTime",
  asNexusMethod: "dateTime",
  description: "Date custom scalar type",
  parseValue(value) {
    const date = new Date(value);
    return date.getTime();
  },
  serialize(value) {
    return new Date(value);
  },
  parseLiteral(ast) {
    if (ast.kind === Kind.INT) {
      return new Date(ast.value);
    }
    return null;
  },
});

For my use case the AWS API was returning the date and time in milliseconds, such as 1239809804. So the first function I will cover is the one that handles data coming from the backend.

When you do a query and pull data from the backend the serialize() function is applied and will transform the data as you specify. In this case I want to send a Date to the front end.

The parseValue() function is used in input from the front end. So if you call a query with:

getData(Where: { DateTime: "someDateTime" }){}

Then the function, in my use case will execute the parseValue() function and turn it into milliseconds.

Once you have created your scalar you will need to add it into the makeSchema() function of Nexus to make it appear in the auto-generated schema.

Then it will need to be added to types and input objects. As shown below:

const sampleType = objectType({
    name: "sampleType",
    definition(t) {
        t.id("id");
        t.string("someData");
        t.field("timestamp",{ type: "dateTime"})
    }
});

const sampleInput = inputObjectType({
    name: "sampleInput",
    definition(t) {
        t.string("sampleData", { required: true});
        t.field("startTime", { type: "dateTime" })
    }
});

I have yet to use parseLiteral(), so I’m not sure when that’s applied. If someone wants to further explain that part please do inform me.

Please let me know if you have any questions. I would also like to know what difficulties you may be having with GraphQL to address in future blog posts.

Filed Under: GraphQL

Copyright © 2019 · Full Stack Data Solutions