Daniel Norman – Rapid and type-safe Node.js development with Prisma

(Subtitles sponsored by Prisma) – Hello, welcome, cześć Today we’ll talk about rapid and type-safe Node.js development with Prisma And first I’d like to thank Piotr, Ania and the rest of the WarsawJS team for this invitation During this online, you know it’s quite a thing it’s not as simple as in person events And so it’s really nice to see how the community still gathers, and we have all of us here today So, before I get into the talk, I’d like to say that I’d like this to be the beginning of a conversation And I would love to hear from you, your thoughts and your experiences working with databases in Node.js And so a little bit about myself My background is mostly as a full stack developer for the last 10 years And during that period, I’ve focused on different parts of the stack doing front end, backend, DevOps, infrastructure, Kubernetes and the project I worked on before Prisma was Aragon, which used Ethereum and IPFS as the backend So, before we get into this talk, I’d like to start with a survey and you can join the survey at this WarsawJS link I can try and share the link Oh, let’s see Okay, I’m not sure what happened there, but, you should be able to join it by going to Slido, and typing this, either scanning the QR code or putting WarsawJS as the QR code, you should be able to already do that Let’s see, make sure I’ve got the notes and make this full screen again And so the first question I have is, whether, which database do you use? And so we have one person who’s managed to get this working, that’s great, Postgres And, let’s see Okay, we’re seeing more results coming in So he has some MySQL, MongoDB and Oracle Okay, that’s very interesting Thanks for sharing Schmidt and Dustin Okay, let’s continue to the next question So, which database access library do you use, do you use ORMs? Do you use Query Builders? There’s quite a lot in the Node.js ecosystem Let’s see This is an open question, but okay, you can also reply in the chat if you don’t feel like going to the, okay, I don’t use JS for backed knex plain SQL none No ORM, you can also share the ORM in the chat Okay, And then okay And then lastly, have you used Prisma before? Alright, that’s good, because, so we have a lot of plain SQL users here That’s already interesting to hear So let’s, oh, let’s talk Sorry about that Okay, let’s talk about our agenda for today So, the first thing that we’ll do is we’ll do an introduction and we’ll discuss the problem space of working with databases in Node.js and how Prisma can potentially help with that Then we’ll take a closer look at Prisma and see how it might be a solution for some of those problems And then lastly, we’ll finish with a live demo So, introduction, it’s 2020,

and you want to build a web app And the first thing you probably need to think about is where are you going to store your data? Because most applications today are data intensive in the sense that the functionality that they offer is based on their ability to store, manipulate and retrieve data So most apps rely on some kind of persistent storage, typically in a database And we saw that, you know, in the poll, so people using MySQL, Oracle, PostgreSQL and Mongo DB, and in this diagram, we have a typical architecture for a web app where the API technology could be rest or GraphQL or something a bit more exotic like GRPC, and the Node.js might be a long running, a Node.js server or maybe even just a lambda or a serverless function It could even be a different tech server technology like Python or Rails, or even go Lang And the main point here is that you have a lot of options when it comes to what kind of a backend you wanna choose for building your app The highest sort of level of abstraction, you have the option of a backend as a service, something like Firebase or AWS AppSync, and, these handle a lot of the concerns for you, but they require you to learn proprietary technology that usually comes with a vendor lock in, and are often also not standardized Then you have the self hosted backend as a service options, that include Hasura which supports Postgres and MySQL, and gives you a GraphQL API and Supabase which is also another self hosted backend as a service And these are great if you’re looking to purely be able to GraphQL or REST API, and you wanna get started quite quickly, then you have the option which is probably the most common one of building something yourself And when you go down that route, you usually pick your database technology, either a relational SQL like Postgres, or you go down the route of no SQL with MongoDB or Cassandra or, one of the many other options that exist out there The main point that I’m trying to make here is that the database technology that you choose will influence almost every decision about your application, which leads us to one of the main challenges in the current Node.js ecosystem, working with databases in Node.js is difficult There is generally three categories of tools, and the current landscape of tools, you know, ranges from sending raw SQL strings to higher level abstractions, like, you know these SQL Query Builders, including Next.js, which one of the users, one of the viewers mentioned, and ORMs and the, also the landscape of ORMs is quite varied, and includes different styles of ORMs from active record to data mapper, and there’s many different implementations And the thing is that each of these approaches come with their own set of problems and pitfalls And if you’re really interested to get a bit of a comparison, you can check out this article that has been published on “Prisma’s Data Guide” which does a comparison of some of these We also recently published a specific one for ORMs comparing ORMs and query builders, and then another one on the type safety of these different libraries And so, this is beyond the scope of today’s talk And I can also, I think, close this So what’s the solution Well, Prisma makes working with databases easy So now we come to the second part, and what is Prisma? So, Prisma is an open source database toolkit, and it consists of three tools These are the three main components that comprise Prisma So there’s Prisma Client which is the database access library for Node.js And this is typically what you would use in a Node.js or even a, like a TypeScript project And Prisma client replaces what the ORM or the query builder or the database driver would typically do Then we have Prisma Studio, which is a modern intuitive, and easy to use database GUI, which we’ll also get a look at in the demo And then lastly, we have Prisma Migrate And Prisma Migrate is a declarative database migrations tool that is currently experimental, but we’re hoping to sort of reach a general availability by the end of this year And Prisma Migrate differs from, so first of all, what are database migrations? So database migration is the term that we refer to when changing the database schema over time And that is because relational databases typically require you to define your scheme up front

And whenever you wanna change that schema, you have to write these SQL files that will alter the tables and perhaps add new tables, or alter some of the columns by introducing you the new columns or renaming existing columns And, the approach of using SQL files is what we would consider an imperative approach And that is because each time you define the steps, the imperative steps that are required in order to carry out the change to your database schema Prisma Migrate differs by working declarative Essentially, you have this Prisma schema which we’ll also look at and the Prisma schema is like the connecting point It’s sort of the single source of truth for these three components And what it is is this a representation of your database schema And essentially, whenever you wanna carry out changes, you make the change to the database schema, and Prisma Migrate works out the steps that are necessary in order to change and bring your database schema to that updated state So what are the goals of Prisma? Well, first to boost productivity by letting you, query your data in natural and familiar ways in the context of Node.js where you’re working with objects, and then second, increase confidence with type safety, auto completion and a robust query API And we’ll take a look at that very soon in the live demo So, how do we do that? Well, the first thing is that Prisma allows you to think in objects rather than SQL Every Prisma client call maps to a type And so the result is very, it’s predictable ahead of actually running the query Working intuitively with relations, so fetching relations is probably one of the most confusing aspects when working with these relational databases, and this fluent API that comes as part of a Prisma client will actually simplify the whole process of doing joins across tables You also have this auto-completion and type safety for database queries And you have this declarative and human-readable database schema which is essentially the Prisma schema, which is also serving as a single source of truth for your database and application models So, I’ve spoken a lot about type safety and type errors And I thought that it’s, since this is a JavaScript meetup, it’s worth mentioning what type errors are And so I’ll start with a simple definition of a type error And so a type error is when a value in an operation is of a different type from what the code expects And in this code example that I’ve put here, what we see is how a function expects a certain structure and how we get three different kinds of type errors from misuse And this is very, very common in JavaScript And one of the main problems is that these errors in JavaScript, they typically occur at runtime And so that means you either have to run your code either in the browser, in Node.js or through your tests in order to discover these errors And so, TypeScript which is like a superset of JavaScript, allows us to detect these errors ahead of time while we’re actually writing the code And so, a similar example, here, we have the same function However, we define the type that is expected by this getFullName function And then, these three same examples of using this, these three calls to this getFullName function, you get the squiggly lines in VS Code, because it can actually know the types ahead of time and then detect these errors at build time or while you’re actually writing your code And so, hopefully that sort of makes the argument about the value of type safety and TypeScript Now, the great news is that the benefits of type safety can be had at zero cost in a project using JavaScript with Prisma And we’ll see that in the live demo And so now we come to the live demo and, you know, live demos are a tricky thing Things tend to go wrong And so let’s pray to the demo gods, and at least be as calm as the Dalai Lama if things don’t work out Okay, so I’ll open up my editor, and before we get into it I’ll talk about what we’re gonna do So the first thing we’re gonna do is we’re gonna look at the Prisma schema which is our single source of truth for the database schema And we’re going to create a PostGres database with Prisma Migrate, which we’ll use that Prisma schema, and then we’ll install and generate Prisma Client

And then I’ll show how actually Prisma Client can be used to perform database operations like doing queries, where you’re saving an entity and relations, and you’re also fetching relations And then lastly, we’ll look at Prisma Studio, which will allow us to explore our data in a similar way to, I don’t know, some of you might be familiar with phpMyAdmin or one of the many database GUIs that exist out there So let’s get started So, I have a Prisma schema here that I’ve defined and the basic structure, let’s, I hope that the text is big enough Let me just leave this open, and I’ll just make sure that you can view that So, I see also a question from Daniel Janus here Does Prisma only work with relational SQL databases At this point, yes However that might change in the future, because the whole idea of Prisma is supporting multiple databases So right now we only support MySQL, Postgres and MariaDB, and also SQL Lite I should say However, that might change in the future So, coming in back to this database schema, the basic structure of of this Prisma schema is that we have these model blocks, and each one of these model blocks maps to a database And so what I’ve defined here is I’ve defined a user with a one to many relation to posts So typically in the post, we would have this user ID, and here we just call it author ID for it to have more semantic meaning So, every single user can have multiple posts And that’s also represented with this relation field here And then, every post can have multiple comments So this would be the kind of database schema that we would use for a blogging application, which is a really good example And each one of these comments as you know, one of these string fields, and every one of these rows maps to a database, a table column And so, a comment is associated with the post and also with the user who wrote that comment So, we have this database, this Prisma schema here, and we also have this status source block which defines the connection to the database And so what I’m gonna do now is I’m gonna actually run the migration using Prisma Migrate And I already have a Postgres running on my server, on my local machine with Docker And so the command to do this is Prisma Migrate And this involves two steps The first thing you do is you save your migration, and it’s a text that the database doesn’t exist And so, now a snapshot of the database of the Prisma Schema was taken and saved And now we can run the migration with the migrate up command And so now, it’s run our migration I can also open up the PostgreSQL CLI and also have a look at the tables And so, indeed, we have this comment, post and user table, and we can also look at the actual schema for the, oh, it gives a table and indeed it maps to what we had in the Prisma schema So now that we have the database created, we can actually get started with Prisma Client And so, I’ll open up here First of all, I wanna show the package JSON So, the dependencies that I have here are the Prisma CLI and Prisma Client And, what happens is, so, as I said, the Prisma schema is a single source of truth for the database schema, but also for the clients so that it’s all type safe And for that, I have to generate the Prisma Client, which loads the Prisma schema, and then generates that into your node modules And, now I can go ahead and open up I have this script file that I’ve created I’ll make the text a bit bigger And so I’ve created a couple of to do’s here to feel out for me So the first thing we’re gonna do is we’re gonna create a user And you can already see the reach auto completion that you get along as you’re writing So here we have the data, and I do a Ctrl + Space and I have, you know, the comments, for example, the name, the posts these are all optional, but the email is required, piotr@prisma.io, and I’ll give it a name

And now, if I use a number for a field that is of type string, this is actually a type error And so, when I mentioned before that you can get a lot of these type safety benefits, I’m gonna show you how you can do that And so, what you can do is, you can add this ts-check comment to the top of your file, and what will happen is that, VS Code will actually run your code through the TypeScript compiler And again, this is just plain JavaScript And because Prisma uses all of these underlying types under the hood, which we can see here it’s able to detect these kind of errors And so, I’m gonna change that to a valid input And I also wanna create two associated posts And so I can do that using this API and I have two options here, I can connect or I can create Connecting would be in order to connect an existing post with this new user that I’m creating But since I don’t have any, I’m gonna create, and I’m gonna create two And again, if I do Ctrl + Space here I already get the possible fields that I can use in order to create a post So I’m gonna write first posts, and let’s set published to true, and let’s create in fact two And for this one, we can also give it some content Okay, so that was our comb And I can actually go ahead and run that then, so that’s what I’m gonna do I’m running demo, which will run our script, and we’d get this a user Now imagine that we wanted to also get these associated posts that we just created Well, we can use this include property, and then select the kind of relations that we wanna fetch along And so here, I can also fetch the posts and here we have it We have Piotr and we have these two posts that were created and are associated with Piotr So now, I wanna show how you could also create a second user, and while we’re creating the second user, we’re gonna create a comment that is associated with one of the posts by Piotr And so, again, we use the prisma.user.create, and here we get to pass some data, anna@prisma.io, and then here we could create the comments And so here, we want to create a comment, and the comment is the actual field, interesting post And now we wanna link it to a post And this is why we’re probably getting the squiggly line, because we are missing the property post And so let’s pass this post property, and here we can connect it And here we pass the ID, and then we’re gonna take user1 And because we also included the posts, we have that also in the auto-completion, and let’s do that, let’s leave the comment on the second post And, I think, and let’s give this a go Okay, so we created this Ana, but we didn’t include in our response all of the relations And let’s try to have it look using Prisma Studio at some of the data in our database And so for that, I’m gonna run Prisma Studio And that has opened up here I’m gonna move that to this screen And so, here if we look at the users, we have indeed Piotr and Anna, and Piotr has these two posts One of them doesn’t have any content but they both have the titles, which is a required field And if we looked at the posts, we’re also able to see the comments And so here we have this comment by let’s, I’ll make it a bit smaller And so, interesting thing, and then the author of this post was Piotr And if we look at the comment, then indeed we see that it was about this And then the user who created, it was Anna So, that was Prisma Studio

Now, we can go back to our presentation And, so far I mentioned like the example that I showed was an example of how we create a new database using Prisma Migrate And this is what we call a Greenfield approach And this approach works well for new projects, but what about existing projects? What if you were wanting to adopt Prisma today in an existing project that already uses Postgres in the app And so, in this diagram, we, this diagram illustrates how this introspection workflow works And the basic idea is that you define the Prisma schema, but you don’t define any of the models at first, you just define your data source and then you run Prisma introspect And what Prisma introspect does is it actually looks at your database and then populates the schema with all of the fields from your database so that you can actually start using it And so coming back to this diagram, the idea is that you introspect your database that populates your Prisma schema and then you run Prisma generate which generates the Prisma Client which you can then use in your application And so that is the sort of a path to gradual adoption And Prisma in the real world, so, I mean, this example that I gave was just a simple script, a Node.js script, but of course, Prisma works well in the context of building applications So if you wanted to build a rest API, you have this example here on the right hand side where you use a Prisma to create a post inside the handler of one of the endpoints And then similarly, I have an example here of some GraphQL resolvers in a GraphQL API And so these are just sort of to showcase that Prisma works with, you know, many different kinds of frameworks And in fact, we have this Prisma examples repo, which you can check out, and we have some examples with Apollo type GraphQL, Nexus Schema, Express and Next.js And so in that note, I’m finished And I think the main takeaway here is that if you’re working with a relational database, Prisma makes you more productive and confident by reducing a lot of the manual work and reducing a lot of the type errors that you might have And so you can really focus on your application by thinking in these JavaScript objects And yeah, thank you – Congratulations Daniel, thank you very much for the presentation I’m really impressed How, what’s the stadium of the development of that too? There are some questions, for some you already answered I’m not sure if you covered answer to this question, how does Prisma work with Postgres functions? – Yes, so that’s a very good question So essentially, you can define Prisma function, sorry, Postgres functions, and use them if you’re using the introspection workflow However, you can’t find these functions inside your Prisma schema, and it’s possible to use Prisma So if you’re using Prisma Client you don’t actually have to use the API at all times You can also use, you can send raw SQL queries, and in those raw SQL queries essentially, you can use these Postgres functions – Okay – It doesn’t sort of natively support it, but you can still work with these Postgres functions – All right, and next question, it looks like it’s quite robust, said Dastin, is there a documentation? – Yes absolutely, we have quite a lot of documentation and I highly suggest you check it out And so we have this, this is the main page, it’s prisma.io/docs And, you also have this setup Prisma which gives you the two sort of workflows, which I’ve discussed, the one is adding it to an existing project where you would use the introspection workflow And then, the second would be starting from scratch using SQL migration And then lastly, starting from scratch with Prisma Migrate, which is the first demo that I did – Okay, awesome, and there are three questions from Luke, I’m not sure which is the, well let’s start with the first one You have a big experience So I want you to ask what’s a proper way Prisma

or ORMs, one person developing database, backend, front end and maybe DevOps topics – Yes, so first of all, I don’t think that there is one right way to do it, but I think that one of the most important things when working with a database is really type safety, because, essentially you’re communicating with a component that isn’t living inside your application And so, when you’re writing, say raw SQL, you, like, you don’t really have a verifiable way at built time to know what’s the data that you’re gonna actually get back or what’s the shape of it And so it’s up to you as the developer to ensure that you’re writing these queries correctly As of now, there’s not many database access tools for a Node.js that have this level of type safety with a programmatic API as I showed where you’re using this Prisma, the Prisma Client API essentially There are some tools for TypeScript that allow you to get that level of type safety by writing raw SQL However, I’m personally a big fan of like Prisma, because of that kind of intuitive thing However, if you’re really comfortable with raw SQL, you know, that might be a good path for you And you can also do that with Prisma or one of the many sort of TypeScript libraries for working with databases, and especially, so, if you’re one person working on the database backend and front end, I think that personally is a great fit for that kind of situation And, you know I’ve myself, I’ve sort of bootstrapped a lot of small projects on the side using Prisma, and it’s been quite nice, you know, not having and I’ve worked a lot with Nex and I’ve worked with SQLis before And so, ultimately I think the question of like raw SQL versus a higher level of abstraction is a matter of taste, but type safety’s important whichever sort of level of abstruction you choose So I hope that answers the question