express-zod-api
Advanced tools
Comparing version 2.0.0-beta2 to 2.0.0-beta3
@@ -7,2 +7,7 @@ # Changelog | ||
### v2.0.0-beta3 | ||
- Some private methods have been made "really private" using the new typescript hashtag syntax. | ||
- Fixed `EndpointOutput<>` type helper for the non-object response type in the `ResultHandlerDefinition`. | ||
### v2.0.0-beta2 | ||
@@ -9,0 +14,0 @@ |
@@ -33,3 +33,3 @@ import { Request, Response } from 'express'; | ||
export declare type EndpointOutput<T> = T extends Endpoint<any, infer OUT, any, any, any, any, any> ? z.output<OUT> : never; | ||
export declare type EndpointResponse<E extends AbstractEndpoint> = z.output<ReturnType<E['getPositiveResponseSchema']> extends z.ZodObject<z.ZodRawShape> ? z.ZodObject<ReplaceMarkerInShape<ReturnType<E['getPositiveResponseSchema']>['_shape'], ReturnType<E['getOutputSchema']>>> : ReturnType<E['getPositiveResponseSchema']> extends OutputMarker ? ReturnType<E['getOutputSchema']> : never> | z.output<ReturnType<E['getNegativeResponseSchema']>>; | ||
export declare type EndpointResponse<E extends AbstractEndpoint> = z.output<ReturnType<E['getPositiveResponseSchema']> extends z.ZodObject<z.ZodRawShape> ? z.ZodObject<ReplaceMarkerInShape<ReturnType<E['getPositiveResponseSchema']>['_shape'], ReturnType<E['getOutputSchema']>>> : ReturnType<E['getPositiveResponseSchema']> extends OutputMarker ? ReturnType<E['getOutputSchema']> : ReturnType<E['getPositiveResponseSchema']>> | z.output<ReturnType<E['getNegativeResponseSchema']>>; | ||
declare type EndpointProps<IN extends IOSchema, OUT extends IOSchema, mIN, OPT, M extends Method, POS extends ApiResponse, NEG extends ApiResponse> = { | ||
@@ -45,2 +45,3 @@ middlewares: MiddlewareDefinition<any, any, any>[]; | ||
export declare class Endpoint<IN extends IOSchema, OUT extends IOSchema, mIN, OPT, M extends Method, POS extends ApiResponse, NEG extends ApiResponse> extends AbstractEndpoint { | ||
#private; | ||
protected methods: M[]; | ||
@@ -60,7 +61,2 @@ protected middlewares: MiddlewareDefinition<any, any, any>[]; | ||
getNegativeMimeTypes(): string[]; | ||
private setupCorsHeaders; | ||
private parseOutput; | ||
private runMiddlewares; | ||
private parseAndRunHandler; | ||
private handleResult; | ||
execute({ request, response, logger, config }: { | ||
@@ -67,0 +63,0 @@ request: Request; |
"use strict"; | ||
var __classPrivateFieldGet = (this && this.__classPrivateFieldGet) || function (receiver, state, kind, f) { | ||
if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a getter"); | ||
if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot read private member from an object whose class did not declare it"); | ||
return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver); | ||
}; | ||
var _Endpoint_instances, _Endpoint_setupCorsHeaders, _Endpoint_parseOutput, _Endpoint_runMiddlewares, _Endpoint_parseAndRunHandler, _Endpoint_handleResult; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
@@ -16,2 +22,3 @@ exports.Endpoint = exports.AbstractEndpoint = void 0; | ||
super(); | ||
_Endpoint_instances.add(this); | ||
this.methods = []; | ||
@@ -53,61 +60,2 @@ this.middlewares = []; | ||
} | ||
setupCorsHeaders(response) { | ||
const accessMethods = this.methods.map((method) => method.toUpperCase()).concat('OPTIONS').join(', '); | ||
response.set('Access-Control-Allow-Origin', '*'); | ||
response.set('Access-Control-Allow-Methods', accessMethods); | ||
response.set('Access-Control-Allow-Headers', 'content-type'); | ||
} | ||
parseOutput(output) { | ||
try { | ||
return this.outputSchema.parse(output); | ||
} | ||
catch (e) { | ||
if (e instanceof zod_1.z.ZodError) { | ||
throw new zod_1.z.ZodError([ | ||
{ | ||
message: 'Invalid format', | ||
code: 'custom', | ||
path: ['output'], | ||
}, | ||
...e.issues.map((issue) => ({ | ||
...issue, | ||
path: issue.path.length === 0 ? ['output'] : issue.path | ||
})) | ||
]); | ||
} | ||
throw e; | ||
} | ||
} | ||
async runMiddlewares({ input, request, response, logger }) { | ||
const options = {}; | ||
for (const def of this.middlewares) { | ||
input = { ...input, ...def.input.parse(input) }; // middleware can transform the input types | ||
Object.assign(options, await def.middleware({ | ||
input, options, request, | ||
response, logger | ||
})); | ||
if (response.writableEnded) { | ||
break; | ||
} | ||
} | ||
return { input, options, isStreamClosed: response.writableEnded }; | ||
} | ||
async parseAndRunHandler({ input, options, logger }) { | ||
return await this.handler({ | ||
input: this.inputSchema.parse(input), | ||
options, logger | ||
}); | ||
} | ||
async handleResult({ error, request, response, logger, initialInput, output }) { | ||
try { | ||
await this.resultHandler.handler({ | ||
error, output, request, response, logger, | ||
input: initialInput | ||
}); | ||
} | ||
catch (e) { | ||
logger.error(`Result handler failure: ${e.message}.`); | ||
// throw e; | ||
} | ||
} | ||
async execute({ request, response, logger, config }) { | ||
@@ -117,3 +65,3 @@ let output; | ||
if (config.cors) { | ||
this.setupCorsHeaders(response); | ||
__classPrivateFieldGet(this, _Endpoint_instances, "m", _Endpoint_setupCorsHeaders).call(this, response); | ||
} | ||
@@ -125,3 +73,3 @@ if (request.method === 'OPTIONS') { | ||
try { | ||
const { input, options, isStreamClosed } = await this.runMiddlewares({ | ||
const { input, options, isStreamClosed } = await __classPrivateFieldGet(this, _Endpoint_instances, "m", _Endpoint_runMiddlewares).call(this, { | ||
input: { ...initialInput }, | ||
@@ -133,3 +81,3 @@ request, response, logger | ||
} | ||
output = this.parseOutput(await this.parseAndRunHandler({ input, options, logger })); | ||
output = __classPrivateFieldGet(this, _Endpoint_instances, "m", _Endpoint_parseOutput).call(this, await __classPrivateFieldGet(this, _Endpoint_instances, "m", _Endpoint_parseAndRunHandler).call(this, { input, options, logger })); | ||
} | ||
@@ -139,3 +87,3 @@ catch (e) { | ||
} | ||
await this.handleResult({ | ||
await __classPrivateFieldGet(this, _Endpoint_instances, "m", _Endpoint_handleResult).call(this, { | ||
initialInput, output, request, | ||
@@ -147,2 +95,57 @@ response, error, logger | ||
exports.Endpoint = Endpoint; | ||
_Endpoint_instances = new WeakSet(), _Endpoint_setupCorsHeaders = function _Endpoint_setupCorsHeaders(response) { | ||
const accessMethods = this.methods.map((method) => method.toUpperCase()).concat('OPTIONS').join(', '); | ||
response.set('Access-Control-Allow-Origin', '*'); | ||
response.set('Access-Control-Allow-Methods', accessMethods); | ||
response.set('Access-Control-Allow-Headers', 'content-type'); | ||
}, _Endpoint_parseOutput = function _Endpoint_parseOutput(output) { | ||
try { | ||
return this.outputSchema.parse(output); | ||
} | ||
catch (e) { | ||
if (e instanceof zod_1.z.ZodError) { | ||
throw new zod_1.z.ZodError([ | ||
{ | ||
message: 'Invalid format', | ||
code: 'custom', | ||
path: ['output'], | ||
}, | ||
...e.issues.map((issue) => ({ | ||
...issue, | ||
path: issue.path.length === 0 ? ['output'] : issue.path | ||
})) | ||
]); | ||
} | ||
throw e; | ||
} | ||
}, _Endpoint_runMiddlewares = async function _Endpoint_runMiddlewares({ input, request, response, logger }) { | ||
const options = {}; | ||
for (const def of this.middlewares) { | ||
input = { ...input, ...def.input.parse(input) }; // middleware can transform the input types | ||
Object.assign(options, await def.middleware({ | ||
input, options, request, | ||
response, logger | ||
})); | ||
if (response.writableEnded) { | ||
break; | ||
} | ||
} | ||
return { input, options, isStreamClosed: response.writableEnded }; | ||
}, _Endpoint_parseAndRunHandler = async function _Endpoint_parseAndRunHandler({ input, options, logger }) { | ||
return await this.handler({ | ||
input: this.inputSchema.parse(input), | ||
options, logger | ||
}); | ||
}, _Endpoint_handleResult = async function _Endpoint_handleResult({ error, request, response, logger, initialInput, output }) { | ||
try { | ||
await this.resultHandler.handler({ | ||
error, output, request, response, logger, | ||
input: initialInput | ||
}); | ||
} | ||
catch (e) { | ||
logger.error(`Result handler failure: ${e.message}.`); | ||
// throw e; | ||
} | ||
}; | ||
//# sourceMappingURL=endpoint.js.map |
@@ -15,6 +15,6 @@ import { z } from 'zod'; | ||
export declare class EndpointsFactory<mIN, mOUT, POS extends ApiResponse, NEG extends ApiResponse> { | ||
#private; | ||
protected resultHandler: ResultHandlerDefinition<POS, NEG>; | ||
protected middlewares: MiddlewareDefinition<any, any, any>[]; | ||
constructor(resultHandler: ResultHandlerDefinition<POS, NEG>); | ||
private static create; | ||
addMiddleware<IN extends IOSchema, OUT extends FlatObject>(definition: MiddlewareDefinition<IN, mOUT, OUT>): EndpointsFactory<Merge<IN, mIN>, mOUT & OUT, POS, NEG>; | ||
@@ -21,0 +21,0 @@ build<IN extends IOSchema, OUT extends IOSchema, M extends Method>({ input, output, handler, description, ...rest }: BuildProps<IN, OUT, mIN, mOUT, M>): Endpoint<IN, OUT, mIN, mOUT, M, POS, NEG>; |
"use strict"; | ||
var __classPrivateFieldGet = (this && this.__classPrivateFieldGet) || function (receiver, state, kind, f) { | ||
if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a getter"); | ||
if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot read private member from an object whose class did not declare it"); | ||
return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver); | ||
}; | ||
var _a, _EndpointsFactory_create; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
@@ -13,9 +19,4 @@ exports.defaultEndpointsFactory = exports.EndpointsFactory = void 0; | ||
} | ||
static create(middlewares, resultHandler) { | ||
const factory = new EndpointsFactory(resultHandler); | ||
factory.middlewares = middlewares; | ||
return factory; | ||
} | ||
addMiddleware(definition) { | ||
return EndpointsFactory.create(this.middlewares.concat(definition), this.resultHandler); | ||
return __classPrivateFieldGet(EndpointsFactory, _a, "m", _EndpointsFactory_create).call(EndpointsFactory, this.middlewares.concat(definition), this.resultHandler); | ||
} | ||
@@ -34,3 +35,8 @@ build({ input, output, handler, description, ...rest }) { | ||
exports.EndpointsFactory = EndpointsFactory; | ||
_a = EndpointsFactory, _EndpointsFactory_create = function _EndpointsFactory_create(middlewares, resultHandler) { | ||
const factory = new EndpointsFactory(resultHandler); | ||
factory.middlewares = middlewares; | ||
return factory; | ||
}; | ||
exports.defaultEndpointsFactory = new EndpointsFactory(result_handler_1.defaultResultHandler); | ||
//# sourceMappingURL=endpoints-factory.js.map |
{ | ||
"name": "express-zod-api", | ||
"version": "2.0.0-beta2", | ||
"version": "2.0.0-beta3", | ||
"description": "A Typescript library to help you get an API server up and running with I/O schema validation and custom middlewares in minutes.", | ||
@@ -5,0 +5,0 @@ "license": "MIT", |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
105081
1081