/ Deploying a FREE Nodejs Serverless API i...
By Evan Dangol
14 Feb 2024
09
35
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
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
You can now use swagger to send request to Api
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
Enter your email to receive our latest newsletter.
Don't worry, we don't spam
zenstack
machine-learning
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
Unveiling Machine Learning's Power- Detecting Toxic Comments with C# -by Evan Dangol
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...