mirror of
https://github.com/zenstackhq/zenstack
synced 2026-05-24 10:08:55 +00:00
82 lines
2.5 KiB
TypeScript
82 lines
2.5 KiB
TypeScript
/* eslint-disable @typescript-eslint/no-explicit-any */
|
|
import { DbClientContract } from '@zenstackhq/runtime';
|
|
import { getModelZodSchemas, ModelZodSchema } from '@zenstackhq/runtime/zod';
|
|
import { FastifyPluginCallback, FastifyReply, FastifyRequest } from 'fastify';
|
|
import fp from 'fastify-plugin';
|
|
import RPCApiHandler from '../api/rpc';
|
|
import { HandleRequestFn, LoggerConfig } from '../api/types';
|
|
|
|
/**
|
|
* Fastify plugin options
|
|
*/
|
|
export interface PluginOptions {
|
|
/**
|
|
* Url prefix, e.g.: /api
|
|
*/
|
|
prefix: string;
|
|
|
|
/**
|
|
* Callback for getting a PrismaClient for the given request
|
|
*/
|
|
getPrisma: (request: FastifyRequest, reply: FastifyReply) => unknown | Promise<unknown>;
|
|
|
|
/**
|
|
* Logger settings
|
|
*/
|
|
logger?: LoggerConfig;
|
|
|
|
/**
|
|
* Zod schemas for validating request input. Pass `true` to load from standard location
|
|
* (need to enable `@core/zod` plugin in schema.zmodel) or omit to disable input validation.
|
|
*/
|
|
zodSchemas?: ModelZodSchema | boolean;
|
|
|
|
/**
|
|
* Api request handler function
|
|
*/
|
|
api: HandleRequestFn;
|
|
}
|
|
|
|
/**
|
|
* Fastify plugin for handling CRUD requests.
|
|
*/
|
|
const pluginHandler: FastifyPluginCallback<PluginOptions> = (fastify, options, done) => {
|
|
const prefix = options.prefix ?? '';
|
|
|
|
if (options.logger?.info === undefined) {
|
|
console.log(`ZenStackPlugin installing routes at prefix: ${prefix}`);
|
|
} else {
|
|
options.logger?.info?.(`ZenStackPlugin installing routes at prefix: ${prefix}`);
|
|
}
|
|
|
|
let schemas: ModelZodSchema | undefined;
|
|
if (typeof options.zodSchemas === 'object') {
|
|
schemas = options.zodSchemas;
|
|
} else if (options.zodSchemas === true) {
|
|
schemas = getModelZodSchemas();
|
|
}
|
|
|
|
const requestHanler = options.api ?? RPCApiHandler({ logger: options.logger, zodSchemas: schemas });
|
|
|
|
fastify.all(`${prefix}/*`, async (request, reply) => {
|
|
const prisma = (await options.getPrisma(request, reply)) as DbClientContract;
|
|
if (!prisma) {
|
|
throw new Error('unable to get prisma from request context');
|
|
}
|
|
const query = request.query as Record<string, string>;
|
|
|
|
const response = await requestHanler({
|
|
method: request.method,
|
|
path: (request.params as any)['*'],
|
|
query,
|
|
requestBody: request.body,
|
|
prisma,
|
|
});
|
|
|
|
reply.status(response.status).send(response.body);
|
|
});
|
|
|
|
done();
|
|
};
|
|
|
|
export default fp(pluginHandler);
|