Deploying a FREE Nodejs Serverless API i...

  • Home
  • / Deploying a FREE Nodejs Serverless API i...

image

14 Feb 2024

09

35

Steps

Install Nodejs project with Typescript support.

mkdir vercel-api
cd vercel-api
npm init -y
npm install express  @zenstackhq/server swagger-ui-express bcryptjs jsonwebtoken dotenv
npm install -D typescript tsx @types/node @types/express @zenstackhq/openapi 
@types/swagger-ui-express @types/jsonwebtoken
npx tsc --init

Create a folder called api, then create two files app.ts and index.ts

/api/index.ts

import { PrismaClient } from '@prisma/client';
import { ZenStackMiddleware } from '@zenstackhq/server/express';
import RestApiHandler from '@zenstackhq/server/api/rest';
import express from 'express';
import dotenv from 'dotenv';
import jwt from 'jsonwebtoken';
import { compareSync } from 'bcryptjs';
import { enhance } from '@zenstackhq/runtime';
import swaggerUI from 'swagger-ui-express';
import fs from 'fs';
import path from 'path';
dotenv.config();
const options = { customCssUrl: 'https://cdnjs.cloudflare.com/ajax/libs/swagger-ui/5.11.4/swagger-ui.css' };
const spec = JSON.parse(
    fs.readFileSync(path.join(__dirname, '../evandangol-api.json'), 'utf8')
);
const app = express();
app.use(express.json());

const prisma = new PrismaClient();

const apiHandler = RestApiHandler({ endpoint: 'http://localhost:3000/api' });
 
app.use('/api/swagger', swaggerUI.serve, swaggerUI.setup(spec, options));

app.post('/api/login', async (req, res) => {
    const { email, password } = req.body;
    const user = await prisma.user.findFirst({
        where: { email },
    });
    if (!user || !compareSync(password, user.password)) {
        res.status(401).json({ error: 'Invalid credentials' });
    } else {
        // sign a JWT token and return it in the response
        const token = jwt.sign({ sub: user.id }, process.env.JWT_SECRET!);
        res.json({ id: user.id, email: user.email, token });
    }
});
app.use('/api', ZenStackMiddleware({ 
    getPrisma: () => enhance(prisma),
    handler: apiHandler 
}));

export default app;

/api/app.ts

import app from '.';
app.listen(3000, () => console.log('🚀 Server ready at: http://localhost:3000'));

Go to https://console.neon.tech and get your self free postgres db

Copy connection string for you postgres db

neon

create .env file and create env variables

POSTGRES_URL_NON_POOLING="postgresql://e..."
POSTGRES_PRISMA_URL="postgresql://e..."
JWT_SECRET=Rr0NXTeX38ixNum6NDzU8DmwfI16kLZg

Run this command

npx zenstack@latest init

The zenstack CLI installs Prisma and creates schema.zmodel file. Update it with models

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

datasource db {
  provider  = "postgresql"
  url       = env("POSTGRES_PRISMA_URL")
  directUrl = env("POSTGRES_URL_NON_POOLING")
}

model Album {
  id       Int    @id @default(autoincrement())
  name     String
  year     String
  artistId Int
  Artist   Artist @relation(fields: [artistId], references: [id])
}

model Artist {
  id    Int     @id @default(autoincrement())
  name  String
  url   String
  Album Album[]
}

model Evan {
  id   String  @id
  name String?
}

model Post {
  id        String  @id
  title     String
  content   String?
  published Boolean @default(false)
  authorId  String?
  users     users?  @relation(fields: [authorId], references: [id])
}

model users {
  id         String   @id
  name       String?
  email      String?  @unique
  created_at DateTime @default(now())
  updated_at DateTime
  Post       Post[]
}
model User {
  id       String  @id @default(cuid())
  email    String  @unique
   password String @password @omit
  orders   Order[]
   // everybody can signup
    @@allow('create', true)

    // user profile is publicly readable
    @@allow('read', true)
}


plugin openapi {
    provider = '@zenstackhq/openapi'
    prefix = '/api'
    flavor = 'rest'
    title = 'Evan Dangol API'
    specVersion = '3.0.0'
    version = '0.1.0'
    description = 'Evan Dangol API'
    output = 'evandangol-api.json'
    securitySchemes = { 
        myBearer: { type: 'http', scheme: 'bearer', bearerFormat: 'JWT' }
    }
}

Run the following command to generate Prisma schema and migrate

npx zenstack generate
npx prisma db push

Navigate Run the project using following command

npx ts-node api/app.ts

various CURL Commands to us Api

curl -X POST localhost:3000/api/user \
    -H 'Content-Type: application/json' \
    -d '{ "data": { "type": "user", "attributes": { "email": "dangolevan@gmail.com", "password": "secret" } } }'

    curl -X POST localhost:3000/api/login \
    -H 'Content-Type: application/json' \
    -d '{ "email": "dangolevan@gmail.com", "password": "secret" }'
    etc...

Navigate to localhost:3000/api/swagger startwsl

You can now use swagger to send request to Api

Deploy project to vercel

Create vercel.json file

{
    "rewrites": [{ "source": "/api/(.*)", "destination": "/api" }]
}

Push your code to github

Create a project in vercel

Import your project to vercel

copy your .env file and drop to the vercel's env variable page

Finally deploy your project using vercel's CI/CD system

vercel dep api1

Join our newsletter!

Enter your email to receive our latest newsletter.

Don't worry, we don't spam

image

Related Articles

image
14 Feb 2024

Deploying a FREE Nodejs Serverless API in Vercel with Zenstack, Prisma and Neon's Free PostgreSQL

Explore the process of deploying a serverless API with Vercel, leveraging Zenstack for Prisma integration, TypeScript for enhanced development, and Neon's complimentary PostgreSQL database for your project. -by Evan Dangol

image
07 Feb 2024

Harnessing Machine Learning to Detect Toxic Comments - Using Calibrated Binary Classification Metrics Module

Unveiling Machine Learning's Power- Detecting Toxic Comments with C# -by Evan Dangol

image
06 Feb 2024

Will gRPC ultimately replace REST Api in future? A simple gRPC using nodejs with Nextjs

It's unlikely that gRPC will entirely replace REST (Representational State Transfer) API in the near future, as both technologies have their own strengths and are suitable for different use cases.gRPC (Google Remote Procedure Call) is a high-performance...