Create an entity resource file for OAS Tools with Prisma

Make an entity resource file with Prisma that can be used with OAS Tools to generate an Open API document and a Node.js/Express server.

In the most recent episode of I’d Rather Be Scripting, Kerri and I discussed OAS Tools in depth.

OAS Tools is an open source Node.js server-side framework with full support for OpenAPI v3. You can use it to generate Express servers based on a given OpenAPI document.

Interestingly, OAS Tools also lets you generate the OpenAPI document itself using something called an entity resource file.

This is a super interesting option since, if you’re building an API, it’s almost certain that you’re doing so to provide an entry point for manipulating data. If so, why not start scaffolding the API by using the data itself?

By starting from the entity resource file, we can achieve a workflow that looks like this:

  1. Create the entity resource file that contains the data types your API will work with
  2. Generate an OpenAPI document with OAS Tools
  3. Generate a Node.js and Express server with OAS Tools using the generated OpenAPI document

OAS Tools does the heavy lifting for steps 2 and 3. It's the first step—creating the entity resource file—that we’ll look at in this post.

What goes into an entity resource file?

An entity resource file contains a JSON array of example objects that each represent the types of data stored in your database.

The OAS Tools Quickstart provides this example with two objects, one for a User type and one for a Pet type:

[
    {
        "id": 1,
        "name": "User",
        "email": "user@example.com"
    },
    {
        "id": 1,
        "petName": "Garfield",
        "type": "Cat"
    }
]

Each object in the array above is the JSON representation you’d get back from your database by selecting a single result for that type. In other words, if I selected a single Pet from my database, I'd get back a JSON object with properties for id, petName, and type.

What is the entity resource file used for?

If you continue with the OAS Tools Quickstart, you’ll see that you can use your entity resource file as the starting point for the 3-step workflow noted at the outset of this post:

  1. You have the entity resource file. (More on this in the next section.)
  2. You’ll pass the entity resource file to the OAS Tools CLI which will generate an OpenAPI document.
  3. You can then pass the generated OpenAPI document to the OAS Tools CLI to generate your server.

So preparing an entity resource file is the crucial first step.

How do I create the entity resource file?

Since the entity resource file is just a JSON array, there's really no limit to how you go about creating it. If you're starting a new project, you could even just write the file by hand.

However, if you already have a database with data in it, then you'll likely want to pull an example of each data type from your database.

Below, we'll do just that.

Creating the entity resource file with Prisma and Node.js

The following example uses the Prisma ORM for Node.js connected to a SQLite database.

First, my Prisma schema is as follows, with a model for User, Todolist, and Todo:

// This is your Prisma schema file,
// learn more about it in the docs: https://pris.ly/d/prisma-schema

generator client {
  provider = "prisma-client-js"
}

datasource db {
  provider = "sqlite"
  url      = env("DATABASE_URL")
}

model User {
  id        String     @id @default(uuid())
  name      String
  createdAt DateTime   @default(now())
  updatedAt DateTime   @updatedAt
  email     String     @unique
  todolists Todolist[] @relation("User")
}

model Todolist {
  id        String   @id @default(uuid())
  title     String
  createdAt DateTime @default(now())
  updatedAt DateTime @updatedAt
  userId    String
  user      User     @relation("User", fields: [userId], references: [id], onDelete: Cascade)
  todos     Todo[]   @relation("Todolist")
}

model Todo {
  id         String   @id @default(uuid())
  title      String
  createdAt  DateTime @default(now())
  updatedAt  DateTime @updatedAt
  todolistId String
  todolist   Todolist @relation("Todolist", fields: [todolistId], references: [id], onDelete: Cascade)
}

Based on my schema above, Prisma will create a Node.js client with a .findFirst() method on each entity type, which I'll use like this:

  const user = await prisma.user.findFirst();
  const todolist = await prisma.todolist.findFirst();
  const todo = await prisma.todo.findFirst();

These 3 lines of code get us most of the way to creating the entity resource file for OAS Tools. Each line queries the database and gives us an example object of that entity type.

Now we just write a JSON file with an array containing each type:

  const filePath = path.join(__dirname, "entityResource.json");
  const data = [user, todolist, todo];
  fs.writeFileSync(filePath, JSON.stringify(data, null, 2));

So taking the boilerplate directly from the Prisma Getting Started guide, we can add both blocks of code to a file that queries the database then writes the file:

import { PrismaClient } from "@prisma/client";
import fs from "fs";
import path from "path";

const prisma = new PrismaClient();

async function main() {
  // ... you will write your Prisma Client queries here
  const user = await prisma.user.findFirst();
  const todolist = await prisma.todolist.findFirst();
  const todo = await prisma.todo.findFirst();

  // write file
  const filePath = path.join(__dirname, "entityResource.json");
  const data = [user, todolist, todo];
  fs.writeFileSync(filePath, JSON.stringify(data, null, 2));
}

main()
  .then(async () => {
    await prisma.$disconnect();
  })
  .catch(async (e) => {
    console.error(e);
    await prisma.$disconnect();
    process.exit(1);
  });
Filename: createEntityResource.js

To write the entity resource file, just execute the script via the terminal:

$ node createEntityResource.js

And out pops our new entity resource file:

[
  {
    "id": "502d0959-086b-4aee-a46d-828ac5dc8adc",
    "name": "Ash",
    "createdAt": "2022-11-02T23:14:27.000Z",
    "updatedAt": "2022-11-02T23:14:27.000Z",
    "email": "ash@example.com"
  },
  {
    "id": "98893579-0397-468d-9f62-0062b8c584f7",
    "title": "My first todo list",
    "createdAt": "2022-11-02T23:14:27.000Z",
    "updatedAt": "2022-11-02T23:14:27.000Z",
    "userId": "502d0959-086b-4aee-a46d-828ac5dc8adc"
  },
  {
    "id": "55d5a6fd-63f7-4575-87be-3aae8cf21db2",
    "title": "My first todo",
    "createdAt": "2022-11-02T23:14:27.000Z",
    "updatedAt": "2022-11-02T23:14:27.000Z",
    "todolistId": "98893579-0397-468d-9f62-0062b8c584f7"
  }
]
Filename: entityResource.json

As you can see, each type of entity from my database is stored in the array: a User, a Todolist, and a Todo.

What do I do next?

From here, you can continue on with our original workflow:

  1. Create the entity resource file that contains the data types your API will work with
  2. Using the entity resource file, generate an OpenAPI document with OAS Tools
  3. Using the generated OpenAPI document, generate a Node.js and Express server with OAS Tools

To learn more about steps 2 and 3, visit the OAS Tools Quickstart where you'll use the OAS Tools CLI to interact with a prompt two generate both items.