NextJS
EmbraceSQL connects into NextJS with a single POST
app route handler.
This provides full access to AutoCRUD and can be extended with your own SQL.
Requirements
You are going to need:
- NodeJs >= 18
- PostgreSQL >= 14
These examples assume you are running locally with your shell able to connect to your PostgreSQL with:
psql
Create a new database dvdrental
on your local PostgeSQL server.
curl "https://embracesql.github.io/dvdrental.sql" | psql
Steps
NextJS App
If you have an NextJS app great! -- if not Create One.
Make sure to pick TypeScript!
Add EmbraceSQL
cd
into the root of your application.
npm install @embracesql/shared
mkdir -p ./src/server
npx embracesqlcli generate express --database postgres://postgres:postgres@localhost/dvdrental > ./src/server/dvdrental.ts
Code up a Route Handler
import { OperationDispatcher, Database } from "../../server/dvdrental";
import { EmbraceSQLRequest, EmbraceSQLResponse } from "@embracesql/shared";
/**
* Connect next app route to EmbraceSQL with a plain
* PostgreSQL connection url.
*/
function embraceSQL(postgresUrl: string) {
let database: Database;
return async (req: Request) => {
// do we already have a connection
if (!database) {
database = await Database.connect(postgresUrl);
}
// dispatcher finds the right method for a request
const dispatcher = new OperationDispatcher(database);
try {
// do we have a valid request?
const request: EmbraceSQLRequest<object, object> = await req.json();
if (!request.operation && !(request.parameters || request.values)) {
throw new Error("Invalid Request");
}
// now we are 🥘
const results = await dispatcher.dispatch(request);
const response: EmbraceSQLResponse<unknown, object, object> = {
...request,
results,
};
return Response.json(response);
} catch (e) {
return new Response((e as Error)?.message, { status: 400 });
}
};
}
/**
* NextJS POST route connection.
*/
export const POST = embraceSQL(
"postgres://postgres:postgres@localhost/dvdrental",
);
Test
Start that server:
npm run dev
And curl for some data:
curl -X POST http://localhost:3000 \
-H 'Content-Type: application/json' \
-d '{"operation":"Public.Tables.Actor.ByActorId.read","parameters":{"actorId": 1}}'
Generate a Client
It's fun to curl
and all, but TypeScript is about types and autocompletion.
Generate a fully typed fetch
wrapping client.
npm install @embracesql/react
npx embracesqlcli generate react --database postgres://postgres:postgres@localhost/dvdrental > ./src/client/dvdrental-react.ts
Create a Page
Create as shown. This is a client component in this simple example to illlustrate the power of the auto-update hooks.
For fun, try typing it to get a sense of the autocomplete.
.card {
padding: 2em;
display: flex;
flex-direction: column;
row-gap: 1rem;
}
"use client";
import {
EmbraceSQLClient,
EmbraceSQLProvider,
Public,
} from "../../client/dvdrental-react";
import "../sample.css";
const Actor = () => {
// this is hooking to an AutoCRUD method to read an actor
const { row: actor } = Public.Tables.Actor.useActorPkey({ actorId: 100 });
// 🪄 - automatic onChange saving though the hook, with debounce to not smoke your DB!
// notice there is no <form> to post back or additional hooks
if (actor) {
return (
<div className="card">
<input value={actor.firstName} onChange={actor.changeFirstName} />
<input value={actor.lastName} onChange={actor.changeLastName} />
</div>
);
} else {
return null;
}
};
export default function Page() {
// connect to where we mounted EmbraceSQL in our server
const client = new EmbraceSQLClient({
url: `/embracesql`,
});
return (
<EmbraceSQLProvider client={client}>
<Actor />
</EmbraceSQLProvider>
);
}