@zenstackhq/server 2.20.1 → 3.0.0-beta.12
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +1 -1
- package/dist/api.cjs +299 -0
- package/dist/api.cjs.map +1 -0
- package/dist/api.d.cts +28 -0
- package/dist/api.d.ts +28 -0
- package/dist/api.js +264 -0
- package/dist/api.js.map +1 -0
- package/dist/express.cjs +75 -0
- package/dist/express.cjs.map +1 -0
- package/dist/express.d.cts +31 -0
- package/dist/express.d.ts +31 -0
- package/dist/express.js +50 -0
- package/dist/express.js.map +1 -0
- package/dist/types-BH-88xJo.d.cts +68 -0
- package/dist/types-BH-88xJo.d.ts +68 -0
- package/package.json +57 -58
- package/README.md +0 -5
- package/api/base.d.ts +0 -49
- package/api/base.js +0 -19
- package/api/base.js.map +0 -1
- package/api/index.d.ts +0 -2
- package/api/index.js +0 -8
- package/api/index.js.map +0 -1
- package/api/rest/index.d.ts +0 -34
- package/api/rest/index.js +0 -1598
- package/api/rest/index.js.map +0 -1
- package/api/rpc/index.d.ts +0 -4
- package/api/rpc/index.js +0 -248
- package/api/rpc/index.js.map +0 -1
- package/api/utils.d.ts +0 -8
- package/api/utils.js +0 -54
- package/api/utils.js.map +0 -1
- package/elysia/handler.d.ts +0 -44
- package/elysia/handler.js +0 -62
- package/elysia/handler.js.map +0 -1
- package/elysia/index.d.ts +0 -1
- package/elysia/index.js +0 -18
- package/elysia/index.js.map +0 -1
- package/express/index.d.ts +0 -2
- package/express/index.js +0 -21
- package/express/index.js.map +0 -1
- package/express/middleware.d.ts +0 -27
- package/express/middleware.js +0 -58
- package/express/middleware.js.map +0 -1
- package/fastify/index.d.ts +0 -2
- package/fastify/index.js +0 -21
- package/fastify/index.js.map +0 -1
- package/fastify/plugin.d.ts +0 -18
- package/fastify/plugin.js +0 -48
- package/fastify/plugin.js.map +0 -1
- package/hono/handler.d.ts +0 -12
- package/hono/handler.js +0 -47
- package/hono/handler.js.map +0 -1
- package/hono/index.d.ts +0 -1
- package/hono/index.js +0 -18
- package/hono/index.js.map +0 -1
- package/nestjs/api-handler.service.d.ts +0 -15
- package/nestjs/api-handler.service.js +0 -72
- package/nestjs/api-handler.service.js.map +0 -1
- package/nestjs/index.d.ts +0 -3
- package/nestjs/index.js +0 -20
- package/nestjs/index.js.map +0 -1
- package/nestjs/interfaces/api-handler-options.interface.d.ts +0 -17
- package/nestjs/interfaces/api-handler-options.interface.js +0 -3
- package/nestjs/interfaces/api-handler-options.interface.js.map +0 -1
- package/nestjs/interfaces/index.d.ts +0 -2
- package/nestjs/interfaces/index.js +0 -19
- package/nestjs/interfaces/index.js.map +0 -1
- package/nestjs/interfaces/zenstack-module-options.interface.d.ts +0 -35
- package/nestjs/interfaces/zenstack-module-options.interface.js +0 -3
- package/nestjs/interfaces/zenstack-module-options.interface.js.map +0 -1
- package/nestjs/zenstack.constants.d.ts +0 -4
- package/nestjs/zenstack.constants.js +0 -8
- package/nestjs/zenstack.constants.js.map +0 -1
- package/nestjs/zenstack.module.d.ts +0 -12
- package/nestjs/zenstack.module.js +0 -61
- package/nestjs/zenstack.module.js.map +0 -1
- package/next/app-route-handler.d.ts +0 -16
- package/next/app-route-handler.js +0 -65
- package/next/app-route-handler.js.map +0 -1
- package/next/index.d.ts +0 -38
- package/next/index.js +0 -17
- package/next/index.js.map +0 -1
- package/next/pages-route-handler.d.ts +0 -9
- package/next/pages-route-handler.js +0 -45
- package/next/pages-route-handler.js.map +0 -1
- package/nuxt/handler.d.ts +0 -12
- package/nuxt/handler.js +0 -45
- package/nuxt/handler.js.map +0 -1
- package/nuxt/index.d.ts +0 -1
- package/nuxt/index.js +0 -18
- package/nuxt/index.js.map +0 -1
- package/shared.d.ts +0 -20
- package/shared.js +0 -50
- package/shared.js.map +0 -1
- package/sveltekit/handler.d.ts +0 -20
- package/sveltekit/handler.js +0 -68
- package/sveltekit/handler.js.map +0 -1
- package/sveltekit/index.d.ts +0 -2
- package/sveltekit/index.js +0 -21
- package/sveltekit/index.js.map +0 -1
- package/tanstack-start/handler.d.ts +0 -11
- package/tanstack-start/handler.js +0 -75
- package/tanstack-start/handler.js.map +0 -1
- package/tanstack-start/index.d.ts +0 -17
- package/tanstack-start/index.js +0 -16
- package/tanstack-start/index.js.map +0 -1
- package/types.d.ts +0 -49
- package/types.js +0 -3
- package/types.js.map +0 -1
package/dist/api.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/api/rpc/index.ts","../src/api/utils.ts"],"sourcesContent":["import { lowerCaseFirst, safeJSONStringify } from '@zenstackhq/common-helpers';\nimport {\n InputValidationError,\n NotFoundError,\n RejectedByPolicyError,\n ZenStackError,\n type ClientContract,\n} from '@zenstackhq/runtime';\nimport type { SchemaDef } from '@zenstackhq/runtime/schema';\nimport SuperJSON from 'superjson';\nimport type { ApiHandler, LogConfig, RequestContext, Response } from '../../types';\nimport { log, registerCustomSerializers } from '../utils';\n\nregisterCustomSerializers();\n\n/**\n * Options for {@link RPCApiHandler}\n */\nexport type RPCApiHandlerOptions<Schema extends SchemaDef> = {\n schema: Schema;\n log?: LogConfig;\n};\n\n/**\n * RPC style API request handler that mirrors the ZenStackClient API\n */\nexport class RPCApiHandler<Schema extends SchemaDef> implements ApiHandler<Schema> {\n constructor(private readonly options: RPCApiHandlerOptions<Schema>) {}\n\n get schema(): Schema {\n return this.options.schema;\n }\n\n async handleRequest({ client, method, path, query, requestBody }: RequestContext<Schema>): Promise<Response> {\n const parts = path.split('/').filter((p) => !!p);\n const op = parts.pop();\n let model = parts.pop();\n\n if (parts.length !== 0 || !op || !model) {\n return this.makeBadInputErrorResponse('invalid request path');\n }\n\n model = lowerCaseFirst(model);\n method = method.toUpperCase();\n let args: unknown;\n let resCode = 200;\n\n switch (op) {\n case 'create':\n case 'createMany':\n case 'createManyAndReturn':\n case 'upsert':\n if (method !== 'POST') {\n return this.makeBadInputErrorResponse('invalid request method, only POST is supported');\n }\n if (!requestBody) {\n return this.makeBadInputErrorResponse('missing request body');\n }\n\n args = requestBody;\n resCode = 201;\n break;\n\n case 'findFirst':\n case 'findUnique':\n case 'findMany':\n case 'aggregate':\n case 'groupBy':\n case 'count':\n if (method !== 'GET') {\n return this.makeBadInputErrorResponse('invalid request method, only GET is supported');\n }\n try {\n args = query?.['q']\n ? this.unmarshalQ(query['q'] as string, query['meta'] as string | undefined)\n : {};\n } catch {\n return this.makeBadInputErrorResponse('invalid \"q\" query parameter');\n }\n break;\n\n case 'update':\n case 'updateMany':\n case 'updateManyAndReturn':\n if (method !== 'PUT' && method !== 'PATCH') {\n return this.makeBadInputErrorResponse('invalid request method, only PUT or PATCH are supported');\n }\n if (!requestBody) {\n return this.makeBadInputErrorResponse('missing request body');\n }\n\n args = requestBody;\n break;\n\n case 'delete':\n case 'deleteMany':\n if (method !== 'DELETE') {\n return this.makeBadInputErrorResponse('invalid request method, only DELETE is supported');\n }\n try {\n args = query?.['q']\n ? this.unmarshalQ(query['q'] as string, query['meta'] as string | undefined)\n : {};\n } catch (err) {\n return this.makeBadInputErrorResponse(\n err instanceof Error ? err.message : 'invalid \"q\" query parameter',\n );\n }\n break;\n\n default:\n return this.makeBadInputErrorResponse('invalid operation: ' + op);\n }\n\n const { result: processedArgs, error } = await this.processRequestPayload(args);\n if (error) {\n return this.makeBadInputErrorResponse(error);\n }\n\n try {\n if (!this.isValidModel(client, model)) {\n return this.makeBadInputErrorResponse(`unknown model name: ${model}`);\n }\n\n log(\n this.options.log,\n 'debug',\n () => `handling \"${model}.${op}\" request with args: ${safeJSONStringify(processedArgs)}`,\n );\n\n const clientResult = await (client as any)[model][op](processedArgs);\n let responseBody: any = { data: clientResult };\n\n // superjson serialize response\n if (clientResult) {\n const { json, meta } = SuperJSON.serialize(clientResult);\n responseBody = { data: json };\n if (meta) {\n responseBody.meta = { serialization: meta };\n }\n }\n\n const response = { status: resCode, body: responseBody };\n log(\n this.options.log,\n 'debug',\n () => `sending response for \"${model}.${op}\" request: ${safeJSONStringify(response)}`,\n );\n return response;\n } catch (err) {\n log(this.options.log, 'error', `error occurred when handling \"${model}.${op}\" request`, err);\n if (err instanceof ZenStackError) {\n return this.makeZenStackErrorResponse(err);\n } else {\n return this.makeGenericErrorResponse(err);\n }\n }\n }\n\n private isValidModel(client: ClientContract<Schema>, model: string) {\n return Object.keys(client.$schema.models).some((m) => lowerCaseFirst(m) === lowerCaseFirst(model));\n }\n\n private makeBadInputErrorResponse(message: string) {\n const resp = {\n status: 400,\n body: { error: { message } },\n };\n log(this.options.log, 'debug', () => `sending error response: ${safeJSONStringify(resp)}`);\n return resp;\n }\n\n private makeGenericErrorResponse(err: unknown) {\n const resp = {\n status: 500,\n body: { error: { message: (err as Error).message || 'unknown error' } },\n };\n log(this.options.log, 'debug', () => `sending error response: ${safeJSONStringify(resp)}`);\n return resp;\n }\n\n private makeZenStackErrorResponse(err: ZenStackError) {\n let status = 400;\n const error: any = { message: err.message };\n if (err.cause && err.cause instanceof Error) {\n error.cause = err.cause.message;\n }\n\n if (err instanceof NotFoundError) {\n status = 404;\n error.model = err.model;\n } else if (err instanceof InputValidationError) {\n status = 422;\n error.rejectedByValidation = true;\n error.model = err.model;\n } else if (err instanceof RejectedByPolicyError) {\n status = 403;\n error.rejectedByPolicy = true;\n error.rejectReason = err.reason;\n error.model = err.model;\n }\n\n const resp = { status, body: { error } };\n log(this.options.log, 'debug', () => `sending error response: ${safeJSONStringify(resp)}`);\n return resp;\n }\n\n private async processRequestPayload(args: any) {\n const { meta, ...rest } = args;\n if (meta?.serialization) {\n try {\n // superjson deserialization\n args = SuperJSON.deserialize({ json: rest, meta: meta.serialization });\n } catch (err) {\n return { result: undefined, error: `failed to deserialize request payload: ${(err as Error).message}` };\n }\n }\n return { result: args, error: undefined };\n }\n\n private unmarshalQ(value: string, meta: string | undefined) {\n let parsedValue: any;\n try {\n parsedValue = JSON.parse(value);\n } catch {\n throw new Error('invalid \"q\" query parameter');\n }\n\n if (meta) {\n let parsedMeta: any;\n try {\n parsedMeta = JSON.parse(meta);\n } catch {\n throw new Error('invalid \"meta\" query parameter');\n }\n\n if (parsedMeta.serialization) {\n return SuperJSON.deserialize({ json: parsedValue, meta: parsedMeta.serialization });\n }\n }\n\n return parsedValue;\n }\n}\n","import { Decimal } from 'decimal.js';\nimport SuperJSON from 'superjson';\nimport { match } from 'ts-pattern';\nimport type { LogConfig, LogLevel } from '../types';\n\nexport function log(logger: LogConfig | undefined, level: LogLevel, message: string | (() => string), error?: unknown) {\n if (!logger) {\n return;\n }\n\n const getMessage = typeof message === 'function' ? message : () => message;\n\n if (typeof logger === 'function') {\n logger(level, getMessage(), error);\n } else if (logger.includes(level)) {\n const logFn = match(level)\n .with('debug', () => console.debug)\n .with('info', () => console.info)\n .with('warn', () => console.warn)\n .with('error', () => console.error)\n .exhaustive();\n logFn(`@zenstackhq/server: [${level}] ${getMessage()}${error ? `\\n${error}` : ''}`);\n }\n}\n\n/**\n * Registers custom superjson serializers.\n */\nexport function registerCustomSerializers() {\n SuperJSON.registerCustom<Decimal, string>(\n {\n isApplicable: (v): v is Decimal => Decimal.isDecimal(v),\n serialize: (v) => v.toJSON(),\n deserialize: (v) => new Decimal(v),\n },\n 'Decimal',\n );\n\n // `Buffer` is not available in edge runtime\n if (globalThis.Buffer) {\n SuperJSON.registerCustom<Buffer, string>(\n {\n isApplicable: (v): v is Buffer => Buffer.isBuffer(v),\n serialize: (v) => v.toString('base64'),\n deserialize: (v) => Buffer.from(v, 'base64'),\n },\n 'Bytes',\n );\n }\n}\n"],"mappings":"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","names":["lowerCaseFirst","safeJSONStringify","InputValidationError","NotFoundError","RejectedByPolicyError","ZenStackError","SuperJSON","Decimal","SuperJSON","match","log","logger","level","message","error","getMessage","includes","logFn","match","with","console","debug","info","warn","exhaustive","registerCustomSerializers","SuperJSON","registerCustom","isApplicable","v","Decimal","isDecimal","serialize","toJSON","deserialize","globalThis","Buffer","isBuffer","toString","from","registerCustomSerializers","RPCApiHandler","options","schema","handleRequest","client","method","path","query","requestBody","parts","split","filter","p","op","pop","model","length","makeBadInputErrorResponse","lowerCaseFirst","toUpperCase","args","resCode","unmarshalQ","err","Error","message","result","processedArgs","error","processRequestPayload","isValidModel","log","safeJSONStringify","clientResult","responseBody","data","json","meta","SuperJSON","serialize","serialization","response","status","body","ZenStackError","makeZenStackErrorResponse","makeGenericErrorResponse","Object","keys","$schema","models","some","m","resp","cause","NotFoundError","InputValidationError","rejectedByValidation","RejectedByPolicyError","rejectedByPolicy","rejectReason","reason","rest","deserialize","undefined","value","parsedValue","JSON","parse","parsedMeta"]}
|
package/dist/express.cjs
ADDED
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __defProp = Object.defineProperty;
|
|
3
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
4
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
5
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
6
|
+
var __name = (target, value) => __defProp(target, "name", { value, configurable: true });
|
|
7
|
+
var __export = (target, all) => {
|
|
8
|
+
for (var name in all)
|
|
9
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
10
|
+
};
|
|
11
|
+
var __copyProps = (to, from, except, desc) => {
|
|
12
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
13
|
+
for (let key of __getOwnPropNames(from))
|
|
14
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
15
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
16
|
+
}
|
|
17
|
+
return to;
|
|
18
|
+
};
|
|
19
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
20
|
+
|
|
21
|
+
// src/express/index.ts
|
|
22
|
+
var express_exports = {};
|
|
23
|
+
__export(express_exports, {
|
|
24
|
+
ZenStackMiddleware: () => factory
|
|
25
|
+
});
|
|
26
|
+
module.exports = __toCommonJS(express_exports);
|
|
27
|
+
|
|
28
|
+
// src/express/middleware.ts
|
|
29
|
+
var factory = /* @__PURE__ */ __name((options) => {
|
|
30
|
+
const requestHandler = options.apiHandler;
|
|
31
|
+
return async (request, response, next) => {
|
|
32
|
+
const client = await options.getClient(request, response);
|
|
33
|
+
const { sendResponse } = options;
|
|
34
|
+
if (sendResponse === false && !client) {
|
|
35
|
+
throw new Error("unable to get ZenStackClient from request context");
|
|
36
|
+
}
|
|
37
|
+
if (!client) {
|
|
38
|
+
return response.status(500).json({
|
|
39
|
+
message: "unable to get ZenStackClient from request context"
|
|
40
|
+
});
|
|
41
|
+
}
|
|
42
|
+
const url = request.protocol + "://" + request.get("host") + request.originalUrl;
|
|
43
|
+
const searchParams = new URL(url).searchParams;
|
|
44
|
+
const query = Object.fromEntries(searchParams);
|
|
45
|
+
try {
|
|
46
|
+
const r = await requestHandler.handleRequest({
|
|
47
|
+
method: request.method,
|
|
48
|
+
path: request.path,
|
|
49
|
+
query,
|
|
50
|
+
requestBody: request.body,
|
|
51
|
+
client
|
|
52
|
+
});
|
|
53
|
+
if (sendResponse === false) {
|
|
54
|
+
response.locals["zenstack"] = {
|
|
55
|
+
status: r.status,
|
|
56
|
+
body: r.body
|
|
57
|
+
};
|
|
58
|
+
return next();
|
|
59
|
+
}
|
|
60
|
+
return response.status(r.status).json(r.body);
|
|
61
|
+
} catch (err) {
|
|
62
|
+
if (sendResponse === false) {
|
|
63
|
+
throw err;
|
|
64
|
+
}
|
|
65
|
+
return response.status(500).json({
|
|
66
|
+
message: `An unhandled error occurred: ${err}`
|
|
67
|
+
});
|
|
68
|
+
}
|
|
69
|
+
};
|
|
70
|
+
}, "factory");
|
|
71
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
72
|
+
0 && (module.exports = {
|
|
73
|
+
ZenStackMiddleware
|
|
74
|
+
});
|
|
75
|
+
//# sourceMappingURL=express.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/express/index.ts","../src/express/middleware.ts"],"sourcesContent":["export { ZenStackMiddleware, type MiddlewareOptions } from './middleware';\n","import type { ClientContract } from '@zenstackhq/runtime';\nimport type { SchemaDef } from '@zenstackhq/runtime/schema';\nimport type { Handler, Request, Response } from 'express';\nimport type { ApiHandler } from '../types';\n\n/**\n * Express middleware options\n */\nexport interface MiddlewareOptions<Schema extends SchemaDef> {\n apiHandler: ApiHandler<Schema>;\n\n /**\n * Callback for getting a ZenStackClient for the given request\n */\n getClient: (req: Request, res: Response) => ClientContract<Schema> | Promise<ClientContract<Schema>>;\n\n /**\n * Controls if the middleware directly sends a response. If set to false,\n * the response is stored in the `res.locals` object and then the middleware\n * calls the `next()` function to pass the control to the next middleware.\n * Subsequent middleware or request handlers need to make sure to send\n * a response.\n *\n * Defaults to true;\n */\n sendResponse?: boolean;\n}\n\n/**\n * Creates an Express middleware for handling CRUD requests.\n */\nconst factory = <Schema extends SchemaDef>(options: MiddlewareOptions<Schema>): Handler => {\n const requestHandler = options.apiHandler;\n\n return async (request, response, next) => {\n const client = await options.getClient(request, response);\n const { sendResponse } = options;\n\n if (sendResponse === false && !client) {\n throw new Error('unable to get ZenStackClient from request context');\n }\n\n if (!client) {\n return response.status(500).json({ message: 'unable to get ZenStackClient from request context' });\n }\n\n // express converts query parameters with square brackets into object\n // e.g.: filter[foo]=bar is parsed to { filter: { foo: 'bar' } }\n // we need to revert this behavior and reconstruct params from original URL\n const url = request.protocol + '://' + request.get('host') + request.originalUrl;\n const searchParams = new URL(url).searchParams;\n const query = Object.fromEntries(searchParams);\n\n try {\n const r = await requestHandler.handleRequest({\n method: request.method,\n path: request.path,\n query,\n requestBody: request.body,\n client,\n });\n if (sendResponse === false) {\n // attach response and pass control to the next middleware\n response.locals['zenstack'] = {\n status: r.status,\n body: r.body,\n };\n return next();\n }\n return response.status(r.status).json(r.body);\n } catch (err) {\n if (sendResponse === false) {\n throw err;\n }\n return response.status(500).json({ message: `An unhandled error occurred: ${err}` });\n }\n };\n};\n\nexport default factory;\n\nexport { factory as ZenStackMiddleware };\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;AAAA;;;;;;;AC+BA,IAAMA,UAAU,wBAA2BC,YAAAA;AACvC,QAAMC,iBAAiBD,QAAQE;AAE/B,SAAO,OAAOC,SAASC,UAAUC,SAAAA;AAC7B,UAAMC,SAAS,MAAMN,QAAQO,UAAUJ,SAASC,QAAAA;AAChD,UAAM,EAAEI,aAAY,IAAKR;AAEzB,QAAIQ,iBAAiB,SAAS,CAACF,QAAQ;AACnC,YAAM,IAAIG,MAAM,mDAAA;IACpB;AAEA,QAAI,CAACH,QAAQ;AACT,aAAOF,SAASM,OAAO,GAAA,EAAKC,KAAK;QAAEC,SAAS;MAAoD,CAAA;IACpG;AAKA,UAAMC,MAAMV,QAAQW,WAAW,QAAQX,QAAQY,IAAI,MAAA,IAAUZ,QAAQa;AACrE,UAAMC,eAAe,IAAIC,IAAIL,GAAAA,EAAKI;AAClC,UAAME,QAAQC,OAAOC,YAAYJ,YAAAA;AAEjC,QAAI;AACA,YAAMK,IAAI,MAAMrB,eAAesB,cAAc;QACzCC,QAAQrB,QAAQqB;QAChBC,MAAMtB,QAAQsB;QACdN;QACAO,aAAavB,QAAQwB;QACrBrB;MACJ,CAAA;AACA,UAAIE,iBAAiB,OAAO;AAExBJ,iBAASwB,OAAO,UAAA,IAAc;UAC1BlB,QAAQY,EAAEZ;UACViB,MAAML,EAAEK;QACZ;AACA,eAAOtB,KAAAA;MACX;AACA,aAAOD,SAASM,OAAOY,EAAEZ,MAAM,EAAEC,KAAKW,EAAEK,IAAI;IAChD,SAASE,KAAK;AACV,UAAIrB,iBAAiB,OAAO;AACxB,cAAMqB;MACV;AACA,aAAOzB,SAASM,OAAO,GAAA,EAAKC,KAAK;QAAEC,SAAS,gCAAgCiB,GAAAA;MAAM,CAAA;IACtF;EACJ;AACJ,GA9CgB;","names":["factory","options","requestHandler","apiHandler","request","response","next","client","getClient","sendResponse","Error","status","json","message","url","protocol","get","originalUrl","searchParams","URL","query","Object","fromEntries","r","handleRequest","method","path","requestBody","body","locals","err"]}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import { ClientContract } from '@zenstackhq/runtime';
|
|
2
|
+
import { SchemaDef } from '@zenstackhq/runtime/schema';
|
|
3
|
+
import { Request, Response, Handler } from 'express';
|
|
4
|
+
import { A as ApiHandler } from './types-BH-88xJo.cjs';
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* Express middleware options
|
|
8
|
+
*/
|
|
9
|
+
interface MiddlewareOptions<Schema extends SchemaDef> {
|
|
10
|
+
apiHandler: ApiHandler<Schema>;
|
|
11
|
+
/**
|
|
12
|
+
* Callback for getting a ZenStackClient for the given request
|
|
13
|
+
*/
|
|
14
|
+
getClient: (req: Request, res: Response) => ClientContract<Schema> | Promise<ClientContract<Schema>>;
|
|
15
|
+
/**
|
|
16
|
+
* Controls if the middleware directly sends a response. If set to false,
|
|
17
|
+
* the response is stored in the `res.locals` object and then the middleware
|
|
18
|
+
* calls the `next()` function to pass the control to the next middleware.
|
|
19
|
+
* Subsequent middleware or request handlers need to make sure to send
|
|
20
|
+
* a response.
|
|
21
|
+
*
|
|
22
|
+
* Defaults to true;
|
|
23
|
+
*/
|
|
24
|
+
sendResponse?: boolean;
|
|
25
|
+
}
|
|
26
|
+
/**
|
|
27
|
+
* Creates an Express middleware for handling CRUD requests.
|
|
28
|
+
*/
|
|
29
|
+
declare const factory: <Schema extends SchemaDef>(options: MiddlewareOptions<Schema>) => Handler;
|
|
30
|
+
|
|
31
|
+
export { type MiddlewareOptions, factory as ZenStackMiddleware };
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import { ClientContract } from '@zenstackhq/runtime';
|
|
2
|
+
import { SchemaDef } from '@zenstackhq/runtime/schema';
|
|
3
|
+
import { Request, Response, Handler } from 'express';
|
|
4
|
+
import { A as ApiHandler } from './types-BH-88xJo.js';
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* Express middleware options
|
|
8
|
+
*/
|
|
9
|
+
interface MiddlewareOptions<Schema extends SchemaDef> {
|
|
10
|
+
apiHandler: ApiHandler<Schema>;
|
|
11
|
+
/**
|
|
12
|
+
* Callback for getting a ZenStackClient for the given request
|
|
13
|
+
*/
|
|
14
|
+
getClient: (req: Request, res: Response) => ClientContract<Schema> | Promise<ClientContract<Schema>>;
|
|
15
|
+
/**
|
|
16
|
+
* Controls if the middleware directly sends a response. If set to false,
|
|
17
|
+
* the response is stored in the `res.locals` object and then the middleware
|
|
18
|
+
* calls the `next()` function to pass the control to the next middleware.
|
|
19
|
+
* Subsequent middleware or request handlers need to make sure to send
|
|
20
|
+
* a response.
|
|
21
|
+
*
|
|
22
|
+
* Defaults to true;
|
|
23
|
+
*/
|
|
24
|
+
sendResponse?: boolean;
|
|
25
|
+
}
|
|
26
|
+
/**
|
|
27
|
+
* Creates an Express middleware for handling CRUD requests.
|
|
28
|
+
*/
|
|
29
|
+
declare const factory: <Schema extends SchemaDef>(options: MiddlewareOptions<Schema>) => Handler;
|
|
30
|
+
|
|
31
|
+
export { type MiddlewareOptions, factory as ZenStackMiddleware };
|
package/dist/express.js
ADDED
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
var __defProp = Object.defineProperty;
|
|
2
|
+
var __name = (target, value) => __defProp(target, "name", { value, configurable: true });
|
|
3
|
+
|
|
4
|
+
// src/express/middleware.ts
|
|
5
|
+
var factory = /* @__PURE__ */ __name((options) => {
|
|
6
|
+
const requestHandler = options.apiHandler;
|
|
7
|
+
return async (request, response, next) => {
|
|
8
|
+
const client = await options.getClient(request, response);
|
|
9
|
+
const { sendResponse } = options;
|
|
10
|
+
if (sendResponse === false && !client) {
|
|
11
|
+
throw new Error("unable to get ZenStackClient from request context");
|
|
12
|
+
}
|
|
13
|
+
if (!client) {
|
|
14
|
+
return response.status(500).json({
|
|
15
|
+
message: "unable to get ZenStackClient from request context"
|
|
16
|
+
});
|
|
17
|
+
}
|
|
18
|
+
const url = request.protocol + "://" + request.get("host") + request.originalUrl;
|
|
19
|
+
const searchParams = new URL(url).searchParams;
|
|
20
|
+
const query = Object.fromEntries(searchParams);
|
|
21
|
+
try {
|
|
22
|
+
const r = await requestHandler.handleRequest({
|
|
23
|
+
method: request.method,
|
|
24
|
+
path: request.path,
|
|
25
|
+
query,
|
|
26
|
+
requestBody: request.body,
|
|
27
|
+
client
|
|
28
|
+
});
|
|
29
|
+
if (sendResponse === false) {
|
|
30
|
+
response.locals["zenstack"] = {
|
|
31
|
+
status: r.status,
|
|
32
|
+
body: r.body
|
|
33
|
+
};
|
|
34
|
+
return next();
|
|
35
|
+
}
|
|
36
|
+
return response.status(r.status).json(r.body);
|
|
37
|
+
} catch (err) {
|
|
38
|
+
if (sendResponse === false) {
|
|
39
|
+
throw err;
|
|
40
|
+
}
|
|
41
|
+
return response.status(500).json({
|
|
42
|
+
message: `An unhandled error occurred: ${err}`
|
|
43
|
+
});
|
|
44
|
+
}
|
|
45
|
+
};
|
|
46
|
+
}, "factory");
|
|
47
|
+
export {
|
|
48
|
+
factory as ZenStackMiddleware
|
|
49
|
+
};
|
|
50
|
+
//# sourceMappingURL=express.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/express/middleware.ts"],"sourcesContent":["import type { ClientContract } from '@zenstackhq/runtime';\nimport type { SchemaDef } from '@zenstackhq/runtime/schema';\nimport type { Handler, Request, Response } from 'express';\nimport type { ApiHandler } from '../types';\n\n/**\n * Express middleware options\n */\nexport interface MiddlewareOptions<Schema extends SchemaDef> {\n apiHandler: ApiHandler<Schema>;\n\n /**\n * Callback for getting a ZenStackClient for the given request\n */\n getClient: (req: Request, res: Response) => ClientContract<Schema> | Promise<ClientContract<Schema>>;\n\n /**\n * Controls if the middleware directly sends a response. If set to false,\n * the response is stored in the `res.locals` object and then the middleware\n * calls the `next()` function to pass the control to the next middleware.\n * Subsequent middleware or request handlers need to make sure to send\n * a response.\n *\n * Defaults to true;\n */\n sendResponse?: boolean;\n}\n\n/**\n * Creates an Express middleware for handling CRUD requests.\n */\nconst factory = <Schema extends SchemaDef>(options: MiddlewareOptions<Schema>): Handler => {\n const requestHandler = options.apiHandler;\n\n return async (request, response, next) => {\n const client = await options.getClient(request, response);\n const { sendResponse } = options;\n\n if (sendResponse === false && !client) {\n throw new Error('unable to get ZenStackClient from request context');\n }\n\n if (!client) {\n return response.status(500).json({ message: 'unable to get ZenStackClient from request context' });\n }\n\n // express converts query parameters with square brackets into object\n // e.g.: filter[foo]=bar is parsed to { filter: { foo: 'bar' } }\n // we need to revert this behavior and reconstruct params from original URL\n const url = request.protocol + '://' + request.get('host') + request.originalUrl;\n const searchParams = new URL(url).searchParams;\n const query = Object.fromEntries(searchParams);\n\n try {\n const r = await requestHandler.handleRequest({\n method: request.method,\n path: request.path,\n query,\n requestBody: request.body,\n client,\n });\n if (sendResponse === false) {\n // attach response and pass control to the next middleware\n response.locals['zenstack'] = {\n status: r.status,\n body: r.body,\n };\n return next();\n }\n return response.status(r.status).json(r.body);\n } catch (err) {\n if (sendResponse === false) {\n throw err;\n }\n return response.status(500).json({ message: `An unhandled error occurred: ${err}` });\n }\n };\n};\n\nexport default factory;\n\nexport { factory as ZenStackMiddleware };\n"],"mappings":";;;;AA+BA,IAAMA,UAAU,wBAA2BC,YAAAA;AACvC,QAAMC,iBAAiBD,QAAQE;AAE/B,SAAO,OAAOC,SAASC,UAAUC,SAAAA;AAC7B,UAAMC,SAAS,MAAMN,QAAQO,UAAUJ,SAASC,QAAAA;AAChD,UAAM,EAAEI,aAAY,IAAKR;AAEzB,QAAIQ,iBAAiB,SAAS,CAACF,QAAQ;AACnC,YAAM,IAAIG,MAAM,mDAAA;IACpB;AAEA,QAAI,CAACH,QAAQ;AACT,aAAOF,SAASM,OAAO,GAAA,EAAKC,KAAK;QAAEC,SAAS;MAAoD,CAAA;IACpG;AAKA,UAAMC,MAAMV,QAAQW,WAAW,QAAQX,QAAQY,IAAI,MAAA,IAAUZ,QAAQa;AACrE,UAAMC,eAAe,IAAIC,IAAIL,GAAAA,EAAKI;AAClC,UAAME,QAAQC,OAAOC,YAAYJ,YAAAA;AAEjC,QAAI;AACA,YAAMK,IAAI,MAAMrB,eAAesB,cAAc;QACzCC,QAAQrB,QAAQqB;QAChBC,MAAMtB,QAAQsB;QACdN;QACAO,aAAavB,QAAQwB;QACrBrB;MACJ,CAAA;AACA,UAAIE,iBAAiB,OAAO;AAExBJ,iBAASwB,OAAO,UAAA,IAAc;UAC1BlB,QAAQY,EAAEZ;UACViB,MAAML,EAAEK;QACZ;AACA,eAAOtB,KAAAA;MACX;AACA,aAAOD,SAASM,OAAOY,EAAEZ,MAAM,EAAEC,KAAKW,EAAEK,IAAI;IAChD,SAASE,KAAK;AACV,UAAIrB,iBAAiB,OAAO;AACxB,cAAMqB;MACV;AACA,aAAOzB,SAASM,OAAO,GAAA,EAAKC,KAAK;QAAEC,SAAS,gCAAgCiB,GAAAA;MAAM,CAAA;IACtF;EACJ;AACJ,GA9CgB;","names":["factory","options","requestHandler","apiHandler","request","response","next","client","getClient","sendResponse","Error","status","json","message","url","protocol","get","originalUrl","searchParams","URL","query","Object","fromEntries","r","handleRequest","method","path","requestBody","body","locals","err"]}
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
import { ClientContract } from '@zenstackhq/runtime';
|
|
2
|
+
import { SchemaDef } from '@zenstackhq/runtime/schema';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Log levels
|
|
6
|
+
*/
|
|
7
|
+
type LogLevel = 'debug' | 'info' | 'warn' | 'error';
|
|
8
|
+
/**
|
|
9
|
+
* Logger function
|
|
10
|
+
*/
|
|
11
|
+
type Logger = (level: LogLevel, message: string, error?: unknown) => void;
|
|
12
|
+
/**
|
|
13
|
+
* Log configuration
|
|
14
|
+
*/
|
|
15
|
+
type LogConfig = ReadonlyArray<LogLevel> | Logger;
|
|
16
|
+
/**
|
|
17
|
+
* API request context
|
|
18
|
+
*/
|
|
19
|
+
type RequestContext<Schema extends SchemaDef> = {
|
|
20
|
+
/**
|
|
21
|
+
* The ZenStackClient instance
|
|
22
|
+
*/
|
|
23
|
+
client: ClientContract<Schema>;
|
|
24
|
+
/**
|
|
25
|
+
* The HTTP method
|
|
26
|
+
*/
|
|
27
|
+
method: string;
|
|
28
|
+
/**
|
|
29
|
+
* The request endpoint path (excluding any prefix)
|
|
30
|
+
*/
|
|
31
|
+
path: string;
|
|
32
|
+
/**
|
|
33
|
+
* The query parameters
|
|
34
|
+
*/
|
|
35
|
+
query?: Record<string, string | string[]>;
|
|
36
|
+
/**
|
|
37
|
+
* The request body object
|
|
38
|
+
*/
|
|
39
|
+
requestBody?: unknown;
|
|
40
|
+
};
|
|
41
|
+
/**
|
|
42
|
+
* API response
|
|
43
|
+
*/
|
|
44
|
+
type Response = {
|
|
45
|
+
/**
|
|
46
|
+
* HTTP status code
|
|
47
|
+
*/
|
|
48
|
+
status: number;
|
|
49
|
+
/**
|
|
50
|
+
* Response body
|
|
51
|
+
*/
|
|
52
|
+
body: unknown;
|
|
53
|
+
};
|
|
54
|
+
/**
|
|
55
|
+
* Framework-agnostic API handler.
|
|
56
|
+
*/
|
|
57
|
+
interface ApiHandler<Schema extends SchemaDef> {
|
|
58
|
+
/**
|
|
59
|
+
* The schema associated with this handler.
|
|
60
|
+
*/
|
|
61
|
+
get schema(): Schema;
|
|
62
|
+
/**
|
|
63
|
+
* Handle an API request.
|
|
64
|
+
*/
|
|
65
|
+
handleRequest(context: RequestContext<Schema>): Promise<Response>;
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
export type { ApiHandler as A, LogConfig as L, RequestContext as R, Response as a };
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
import { ClientContract } from '@zenstackhq/runtime';
|
|
2
|
+
import { SchemaDef } from '@zenstackhq/runtime/schema';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Log levels
|
|
6
|
+
*/
|
|
7
|
+
type LogLevel = 'debug' | 'info' | 'warn' | 'error';
|
|
8
|
+
/**
|
|
9
|
+
* Logger function
|
|
10
|
+
*/
|
|
11
|
+
type Logger = (level: LogLevel, message: string, error?: unknown) => void;
|
|
12
|
+
/**
|
|
13
|
+
* Log configuration
|
|
14
|
+
*/
|
|
15
|
+
type LogConfig = ReadonlyArray<LogLevel> | Logger;
|
|
16
|
+
/**
|
|
17
|
+
* API request context
|
|
18
|
+
*/
|
|
19
|
+
type RequestContext<Schema extends SchemaDef> = {
|
|
20
|
+
/**
|
|
21
|
+
* The ZenStackClient instance
|
|
22
|
+
*/
|
|
23
|
+
client: ClientContract<Schema>;
|
|
24
|
+
/**
|
|
25
|
+
* The HTTP method
|
|
26
|
+
*/
|
|
27
|
+
method: string;
|
|
28
|
+
/**
|
|
29
|
+
* The request endpoint path (excluding any prefix)
|
|
30
|
+
*/
|
|
31
|
+
path: string;
|
|
32
|
+
/**
|
|
33
|
+
* The query parameters
|
|
34
|
+
*/
|
|
35
|
+
query?: Record<string, string | string[]>;
|
|
36
|
+
/**
|
|
37
|
+
* The request body object
|
|
38
|
+
*/
|
|
39
|
+
requestBody?: unknown;
|
|
40
|
+
};
|
|
41
|
+
/**
|
|
42
|
+
* API response
|
|
43
|
+
*/
|
|
44
|
+
type Response = {
|
|
45
|
+
/**
|
|
46
|
+
* HTTP status code
|
|
47
|
+
*/
|
|
48
|
+
status: number;
|
|
49
|
+
/**
|
|
50
|
+
* Response body
|
|
51
|
+
*/
|
|
52
|
+
body: unknown;
|
|
53
|
+
};
|
|
54
|
+
/**
|
|
55
|
+
* Framework-agnostic API handler.
|
|
56
|
+
*/
|
|
57
|
+
interface ApiHandler<Schema extends SchemaDef> {
|
|
58
|
+
/**
|
|
59
|
+
* The schema associated with this handler.
|
|
60
|
+
*/
|
|
61
|
+
get schema(): Schema;
|
|
62
|
+
/**
|
|
63
|
+
* Handle an API request.
|
|
64
|
+
*/
|
|
65
|
+
handleRequest(context: RequestContext<Schema>): Promise<Response>;
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
export type { ApiHandler as A, LogConfig as L, RequestContext as R, Response as a };
|
package/package.json
CHANGED
|
@@ -1,13 +1,8 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@zenstackhq/server",
|
|
3
|
-
"version": "
|
|
4
|
-
"
|
|
5
|
-
"
|
|
6
|
-
"homepage": "https://zenstack.dev",
|
|
7
|
-
"publishConfig": {
|
|
8
|
-
"directory": "dist",
|
|
9
|
-
"linkDirectory": true
|
|
10
|
-
},
|
|
3
|
+
"version": "3.0.0-beta.12",
|
|
4
|
+
"description": "ZenStack automatic CRUD API handlers and server adapters",
|
|
5
|
+
"type": "module",
|
|
11
6
|
"keywords": [
|
|
12
7
|
"fastify",
|
|
13
8
|
"express",
|
|
@@ -19,62 +14,66 @@
|
|
|
19
14
|
],
|
|
20
15
|
"author": "ZenStack Team",
|
|
21
16
|
"license": "MIT",
|
|
22
|
-
"
|
|
23
|
-
"
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
"
|
|
27
|
-
|
|
17
|
+
"files": [
|
|
18
|
+
"dist"
|
|
19
|
+
],
|
|
20
|
+
"exports": {
|
|
21
|
+
"./package.json": {
|
|
22
|
+
"import": "./package.json",
|
|
23
|
+
"require": "./package.json"
|
|
24
|
+
},
|
|
25
|
+
"./api": {
|
|
26
|
+
"import": {
|
|
27
|
+
"types": "./dist/api.d.ts",
|
|
28
|
+
"default": "./dist/api.js"
|
|
29
|
+
},
|
|
30
|
+
"require": {
|
|
31
|
+
"types": "./dist/api.d.cts",
|
|
32
|
+
"default": "./dist/api.cjs"
|
|
33
|
+
}
|
|
34
|
+
},
|
|
35
|
+
"./express": {
|
|
36
|
+
"import": {
|
|
37
|
+
"types": "./dist/express.d.ts",
|
|
38
|
+
"default": "./dist/express.js"
|
|
39
|
+
},
|
|
40
|
+
"require": {
|
|
41
|
+
"types": "./dist/express.d.cts",
|
|
42
|
+
"default": "./dist/express.cjs"
|
|
43
|
+
}
|
|
44
|
+
}
|
|
28
45
|
},
|
|
29
|
-
"
|
|
30
|
-
"
|
|
46
|
+
"dependencies": {
|
|
47
|
+
"decimal.js": "^10.4.3",
|
|
48
|
+
"superjson": "^2.2.3",
|
|
49
|
+
"ts-pattern": "^5.7.1",
|
|
50
|
+
"@zenstackhq/common-helpers": "3.0.0-beta.13",
|
|
51
|
+
"@zenstackhq/runtime": "3.0.0-beta.13"
|
|
31
52
|
},
|
|
32
53
|
"devDependencies": {
|
|
33
|
-
"@
|
|
34
|
-
"@
|
|
35
|
-
"@
|
|
36
|
-
"
|
|
37
|
-
"
|
|
38
|
-
"@
|
|
39
|
-
"@
|
|
40
|
-
"
|
|
41
|
-
"
|
|
42
|
-
"express": "^4.19.2",
|
|
43
|
-
"fastify": "^4.14.1",
|
|
44
|
-
"fastify-plugin": "^4.5.0",
|
|
45
|
-
"h3": "^1.8.2",
|
|
46
|
-
"hono": "^4.6.3",
|
|
47
|
-
"isomorphic-fetch": "^3.0.0",
|
|
48
|
-
"next": "14.2.4",
|
|
49
|
-
"nuxt": "^3.7.4",
|
|
50
|
-
"reflect-metadata": "^0.2.2",
|
|
51
|
-
"supertest": "^6.3.3",
|
|
52
|
-
"zod": "^3.25.0",
|
|
53
|
-
"@zenstackhq/testtools": "2.20.1"
|
|
54
|
+
"@types/body-parser": "^1.19.6",
|
|
55
|
+
"@types/express": "^5.0.0",
|
|
56
|
+
"@types/supertest": "^6.0.3",
|
|
57
|
+
"body-parser": "^2.2.0",
|
|
58
|
+
"supertest": "^7.1.4",
|
|
59
|
+
"@zenstackhq/testtools": "3.0.0-beta.13",
|
|
60
|
+
"@zenstackhq/typescript-config": "3.0.0-beta.13",
|
|
61
|
+
"@zenstackhq/eslint-config": "3.0.0-beta.13",
|
|
62
|
+
"@zenstackhq/vitest-config": "3.0.0-beta.13"
|
|
54
63
|
},
|
|
55
|
-
"
|
|
56
|
-
"
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
"
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
"./next/app-route-handler": "./next/app-route-handler.js",
|
|
63
|
-
"./next": "./next/index.js",
|
|
64
|
-
"./next/pages-route-handler": "./next/pages-route-handler.js",
|
|
65
|
-
"./sveltekit": "./sveltekit/index.js",
|
|
66
|
-
"./nuxt": "./nuxt/index.js",
|
|
67
|
-
"./nestjs": "./nestjs/index.js",
|
|
68
|
-
"./hono": "./hono/index.js",
|
|
69
|
-
"./elysia": "./elysia/index.js",
|
|
70
|
-
"./tanstack-start": "./tanstack-start/index.js",
|
|
71
|
-
"./types": "./types.js"
|
|
64
|
+
"peerDependencies": {
|
|
65
|
+
"express": "^5.0.0"
|
|
66
|
+
},
|
|
67
|
+
"peerDependenciesMeta": {
|
|
68
|
+
"express": {
|
|
69
|
+
"optional": true
|
|
70
|
+
}
|
|
72
71
|
},
|
|
73
72
|
"scripts": {
|
|
74
|
-
"
|
|
75
|
-
"
|
|
76
|
-
"watch": "tsc --watch",
|
|
73
|
+
"build": "tsc --noEmit && tsup-node",
|
|
74
|
+
"watch": "tsup-node --watch",
|
|
77
75
|
"lint": "eslint src --ext ts",
|
|
78
|
-
"test": "
|
|
76
|
+
"test": "vitest run",
|
|
77
|
+
"pack": "pnpm pack"
|
|
79
78
|
}
|
|
80
79
|
}
|
package/README.md
DELETED
package/api/base.d.ts
DELETED
|
@@ -1,49 +0,0 @@
|
|
|
1
|
-
import type { DbClientContract, ModelMeta, ZodSchemas } from '@zenstackhq/runtime';
|
|
2
|
-
import type { LoggerConfig } from '../types';
|
|
3
|
-
/**
|
|
4
|
-
* API request context
|
|
5
|
-
*/
|
|
6
|
-
export type RequestContext = {
|
|
7
|
-
/**
|
|
8
|
-
* The PrismaClient instance
|
|
9
|
-
*/
|
|
10
|
-
prisma: DbClientContract;
|
|
11
|
-
/**
|
|
12
|
-
* The HTTP method
|
|
13
|
-
*/
|
|
14
|
-
method: string;
|
|
15
|
-
/**
|
|
16
|
-
* The request endpoint path (excluding any prefix)
|
|
17
|
-
*/
|
|
18
|
-
path: string;
|
|
19
|
-
/**
|
|
20
|
-
* The query parameters
|
|
21
|
-
*/
|
|
22
|
-
query?: Record<string, string | string[]>;
|
|
23
|
-
/**
|
|
24
|
-
* The request body object
|
|
25
|
-
*/
|
|
26
|
-
requestBody?: unknown;
|
|
27
|
-
/**
|
|
28
|
-
* Model metadata. By default loaded from the @see loadPath path. You can pass
|
|
29
|
-
* it in explicitly to override.
|
|
30
|
-
*/
|
|
31
|
-
modelMeta?: ModelMeta;
|
|
32
|
-
/**
|
|
33
|
-
* Zod schemas for validating create and update payloads. By default loaded from
|
|
34
|
-
* the @see loadPath path. You can pass it in explicitly to override.
|
|
35
|
-
*/
|
|
36
|
-
zodSchemas?: ZodSchemas;
|
|
37
|
-
/**
|
|
38
|
-
* Logging configuration. Set to `null` to disable logging.
|
|
39
|
-
* If unset or set to `undefined`, log will be output to console.
|
|
40
|
-
*/
|
|
41
|
-
logger?: LoggerConfig;
|
|
42
|
-
};
|
|
43
|
-
/**
|
|
44
|
-
* Base class for API handlers
|
|
45
|
-
*/
|
|
46
|
-
export declare abstract class APIHandlerBase {
|
|
47
|
-
protected readonly defaultModelMeta: ModelMeta | undefined;
|
|
48
|
-
constructor();
|
|
49
|
-
}
|
package/api/base.js
DELETED
|
@@ -1,19 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.APIHandlerBase = void 0;
|
|
4
|
-
const shared_1 = require("../shared");
|
|
5
|
-
/**
|
|
6
|
-
* Base class for API handlers
|
|
7
|
-
*/
|
|
8
|
-
class APIHandlerBase {
|
|
9
|
-
constructor() {
|
|
10
|
-
try {
|
|
11
|
-
this.defaultModelMeta = (0, shared_1.getDefaultModelMeta)();
|
|
12
|
-
}
|
|
13
|
-
catch {
|
|
14
|
-
// noop
|
|
15
|
-
}
|
|
16
|
-
}
|
|
17
|
-
}
|
|
18
|
-
exports.APIHandlerBase = APIHandlerBase;
|
|
19
|
-
//# sourceMappingURL=base.js.map
|
package/api/base.js.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"base.js","sourceRoot":"","sources":["../../src/api/base.ts"],"names":[],"mappings":";;;AACA,sCAAgD;AAmDhD;;GAEG;AACH,MAAsB,cAAc;IAIhC;QACI,IAAI,CAAC;YACD,IAAI,CAAC,gBAAgB,GAAG,IAAA,4BAAmB,GAAE,CAAC;QAClD,CAAC;QAAC,MAAM,CAAC;YACL,OAAO;QACX,CAAC;IACL,CAAC;CACJ;AAXD,wCAWC"}
|
package/api/index.d.ts
DELETED
package/api/index.js
DELETED
|
@@ -1,8 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.RestApiHandler = exports.RPCApiHandler = void 0;
|
|
4
|
-
var rpc_1 = require("./rpc");
|
|
5
|
-
Object.defineProperty(exports, "RPCApiHandler", { enumerable: true, get: function () { return rpc_1.RPCApiHandler; } });
|
|
6
|
-
var rest_1 = require("./rest");
|
|
7
|
-
Object.defineProperty(exports, "RestApiHandler", { enumerable: true, get: function () { return rest_1.RestApiHandler; } });
|
|
8
|
-
//# sourceMappingURL=index.js.map
|
package/api/index.js.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/api/index.ts"],"names":[],"mappings":";;;AAAA,6BAAsC;AAA7B,oGAAA,aAAa,OAAA;AACtB,+BAAwC;AAA/B,sGAAA,cAAc,OAAA"}
|