Integration

Integration

You can integrate PTSQ with multiple backend REST API frameworks such as Express, Koa or vanilla Node.js http.

node:http

import { createServer, IncommingMessage, ServerResponse } from 'http';
import { ptsq } from '@ptsq/server';
import { Type } from '@sinclair/typebox';
 
const { router, resolver, serve } = ptsq({
  ctx: ({ req, res }: { req: IncommingMessage; res: ServerResponse }) => ({
    req,
    res,
  }),
}).create();
 
const baseRouter = router({
  greetings: resolver
    .args(Type.Object({ name: Type.String() }))
    .output(Type.String())
    .query(({ input }) => `Hello, ${input.name}!`),
});
 
const app = createServer(serve(baseRouter));
 
app.listen(4000, () => {
  console.log('Listening on: http://localhost:4000/ptsq');
});
 
export type BaseRouter = typeof baseRouter;

Express

import { ptsq } from '@ptsq/server';
import { Type } from '@sinclair/typebox';
import express, { Request, Response } from 'express';
 
const app = express();
 
const { router, resolver, serve } = ptsq({
  ctx: ({ req, res }: { req: Request; res: Response }) => ({
    req,
    res,
  }),
}).create();
 
const baseRouter = router({
  greetings: resolver
    .args(Type.Object({ name: Type.String() }))
    .output(Type.String())
    .query(({ input }) => `Hello, ${input.name}!`),
});
 
app.use((req, res) => serve(baseRouter)(req, res));
 
app.listen(4000, () => {
  console.log('Listening on: http://localhost:4000/ptsq');
});
 
export type BaseRouter = typeof baseRouter;

Koa

import { ptsq } from '@ptsq/server';
import { Type } from '@sinclair/typebox';
import Koa, { Context } from 'koa';
 
const app = new Koa();
 
const { router, resolver, serve } = ptsq({
  ctx: ({ koa }: { koa: Context }) => ({
    koa,
  }),
}).create();
 
const baseRouter = router({
  greetings: resolver
    .args(Type.Object({ name: Type.String() }))
    .output(Type.String())
    .query(({ input }) => `Hello, ${input.name}!`),
});
 
app.use(async (ctx) => {
  const response = await serve(baseRouter).handleNodeRequest(ctx.req);
 
  // Set status code
  ctx.status = response.status;
 
  // Set headers
  response.headers.forEach((value, key) => {
    ctx.append(key, value);
  });
 
  ctx.body = response.body;
});
 
app.listen(4000, () => {
  console.log('Listening on: http://localhost:4000/ptsq');
});
 
export type BaseRouter = typeof baseRouter;

Fastify

import { ptsq } from '@ptsq/server';
import { Type } from '@sinclair/typebox';
import fastify, { FastifyReply, FastifyRequest } from 'fastify';
 
const app = fastify();
 
const { router, resolver, serve } = ptsq({
  ctx: ({ req, reply }: { req: FastifyRequest; reply: FastifyReply }) => ({
    req,
    reply,
  }),
}).create();
 
const baseRouter = router({
  greetings: resolver
    .args(Type.Object({ name: Type.String() }))
    .output(Type.String())
    .query(({ input }) => `Hello, ${input.name}!`),
});
 
app.route({
  method: ['GET', 'POST', 'PUT', 'PATCH', 'DELETE'],
  url: '/*',
  async handler(req, reply) {
    const response = await serve(baseRouter).handleNodeRequest(req, {
      req,
      reply,
    });
 
    if (response === undefined) {
      reply.status(404).send('Not found.');
      return reply;
    }
 
    response.headers.forEach((value, key) => {
      reply.header(key, value);
    });
 
    reply.status(response.status);
 
    reply.send(response.body);
  },
});
 
app.listen({ port: 4000 }, () => {
  console.log('Listening on: http://localhost:4000/ptsq');
});
 
export type BaseRouter = typeof baseRouter;

Next

import { serve } from '@/server/ptsq';
import { baseRouter } from '@/server/routes/root';
 
export const config = {
  api: {
    bodyParser: false,
  },
};
 
export default serve(baseRouter);

SvelteKit

import { ptsq } from '@ptsq/server';
import { Type } from '@sinclair/typebox';
 
const { router, resolver, serve } = ptsq({
  root: '/api',
  ctx: () => ({}),
}).create();
 
const baseRouter = router({
  greetings: resolver
    .args(Type.Object({ name: Type.String() }))
    .output(Type.String())
    .query(({ input }) => `Hello, ${input.name}!`),
});
 
const server = serve(baseRouter);
 
export type BaseRouter = typeof baseRouter;
 
export { server as POST, server as GET };

Bun

import { ptsq } from '@ptsq/server';
import { Type } from '@sinclair/typebox';
 
const { router, resolver, serve } = ptsq({
  ctx: () => ({}),
}).create();
 
const baseRouter = router({
  greetings: resolver
    .args(
      Type.Object({
        name: Type.String(),
      }),
    )
    .output(Type.String())
    .query(({ input }) => {
      return `Hello, ${input.name}`;
    }),
});
 
const server = Bun.serve(serve(baseRouter));
 
console.log(`Listening on: http://localhost:${server.port}/ptsq`);
 
export type BaseRouter = typeof baseRouter;