New Case Study:See how Anthropic automated 95% of dependency reviews with Socket.Learn More
Socket
Sign inDemoInstall
Socket

express-zod-api

Package Overview
Dependencies
Maintainers
1
Versions
430
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

express-zod-api - npm Package Compare versions

Comparing version 1.3.1 to 2.0.0-beta1

107

CHANGELOG.md
# Changelog
## Version 2
While v2 is beta some methods and properties might be renamed or changed without backward compatibility.
### v2.0.0-beta1
- **Warning**: There are breaking changes described below.
In general, if you used the `defaultResultHandler` before, then you won't have to change much of code.
- **Motivation**. I really like the first version of the library for its simplicity and elegance,
but there is one imperfection in it. The available methods and type helpers do not allow to disclose the complete
response of the endpoint, including the specification of a successful and error response for which the
`ResultHandler` is responsible. So I decided to fix it, although it made the implementation somewhat more
complicated, but I found it important. However, it brought a number of benefits, which are also described below.
- Node version required: at least `10.0.0` and the library target now is `ES6`.
- Type `ResultHandler` is no longer exported, please use `createResultHandler()` or `defaultResultHandler`.
- The `setResultHandler()` method of `EndpointsFactory` class has been removed. The `ResultHandlerDefinition` has
to be specified as an argument of `EndpointsFactory` constructor. You can use `defaultResultHandler` or
`createResultHandler()` for this, or you can use `defaultEndpointsFactory`.
```typescript
// before
export const endpointsFactoryBefore = new EndpointsFactory();
// after
export const endpointsFactoryAfter = new EndpointsFactory(defaultResultHandler);
// which is the same as
import {defaultEndpointsFactory} from 'express-zod-api';
```
- The optional property `resultHandler` of `ConfigType` has been replaced with `errorHandler`.
```typescript
// before
resultHandler: ResultHandler; // optional
// after
errorHandler: ResultHandlerDefinition<any, any>; // optional, default: defaultResultHandler
```
- New methods of `Endpoint` class `getPositiveResponseSchema()` and `getNegativeResponseSchema()` return the
complete response of the endpoint taking into account the `ResultHandlerDefinition` schemas.
New methods: `getPositiveMimeTypes()` and `getNegativeMimeTypes()` return the array of mime types.
- New type helping utility: `EndpointResponse<E extends AbstractEndpoint>` to be used instead of `EndpointOutput`
returns the complete type of the endpoint response including both positive and negative cases.
```typescript
// Example. Before (v1):
import {EndpointOutput} from 'express-zod-api';
const myEndpointV1 = endpointsFactory
.build({
method: 'get',
input: z.object({...}),
output: z.object({
name: z.string(),
}),
handler: async () => ({...}),
});
type MyEndpointOutput = EndpointOutput<typeof myEndpointV1>; // => { name: string }
// and after (v2):
import {defaultEndpointsFactory, EndpointResponse} from 'express-zod-api';
const myEndpointV2 = defaultEndpointsFactory
.build({
method: 'get',
input: z.object({...}),
output: z.object({
name: z.string(),
}),
handler: async () => ({...}),
});
type MyEndpointResponse = EndpointResponse<typeof myEndpointV2>; // => the following type
// {
// status: 'success';
// data: { name: string };
// } | {
// status: 'error',
// error: { message: string };
// }
```
- Obtaining the OpenAPI / Swagger specification has been simplified: now you can call `getSpecAsYaml()` method
directly on `OpenAPI` class instance. There is also a new option `errorResponseDescription`.
```typescript
// before
new OpenAPI({...}).builder.getSpecAsYaml();
// after
new OpenAPI({...}).getSpecAsYaml();
```
- OpenAPI / Swagger specification no longer uses references for schemas and parameters, so they are inline now.
Instead of `default` entry in `responses` there are HTTP status codes `200` and `400` that represent positive
and negative responses accordingly. Response schemas are now complete as well.
- For creating your own `ResultHandlerDefinition` please use `createResultHandler()`. It also requires
`createApiResponse()` to be used that takes a response schema and optional mime types as arguments.
The endpoint output should be wrapped in `markOutput()`. So far this is the only way I have come up with to
facilitate type inference with essentially double nesting of generic types. Typescript does not yet support such
features as `MyGenericType<A<B>>`.
```typescript
// before
const myResultHandlerV1: ResultHandler = ({error, request, response, input, output, logger}) => {};
// after
const myResultHandlerV2 = createResultHandler({
getPositiveResponse: <OUT extends IOSchema>(output: OUT) => createApiResponse(
z.object({
...,
someProperty: markOutput(output)
}),
['mime/type1', 'mime/type2'] // optional, default: application/json
),
getNegativeResponse: () => createApiResponse(z.object({...})),
handler: ({error, input, output, request, response, logger}) => {}
});
```
## Version 1

@@ -4,0 +111,0 @@

4

dist/config-type.d.ts
import { NextHandleFunction } from 'connect';
import { Express } from 'express';
import { Logger } from 'winston';
import { ResultHandler } from './result-handler';
import { ResultHandlerDefinition } from './result-handler';
export declare const loggerLevels: {

@@ -23,4 +23,4 @@ silent: boolean;

cors: boolean;
resultHandler?: ResultHandler;
errorHandler?: ResultHandlerDefinition<any, any>;
logger: LoggerConfig | Logger;
};

@@ -5,6 +5,6 @@ import { Request, Response } from 'express';

import { ConfigType } from './config-type';
import { IOSchema, Merge } from './helpers';
import { ApiResponse, IOSchema, Merge, OutputMarker, ReplaceMarkerInShape } from './helpers';
import { Method, MethodsDefinition } from './method';
import { MiddlewareDefinition } from './middleware';
import { ResultHandler } from './result-handler';
import { ResultHandlerDefinition } from './result-handler';
export declare type Handler<IN, OUT, OPT> = (params: {

@@ -27,6 +27,11 @@ input: IN;

abstract getOutputSchema(): IOSchema;
abstract getPositiveResponseSchema(): z.ZodTypeAny;
abstract getNegativeResponseSchema(): z.ZodTypeAny;
abstract getPositiveMimeTypes(): string[];
abstract getNegativeMimeTypes(): string[];
}
export declare type EndpointInput<T> = T extends Endpoint<infer IN, any, infer mIN, any, any> ? z.input<Merge<IN, mIN>> : never;
export declare type EndpointOutput<T> = T extends Endpoint<any, infer OUT, any, any, any> ? z.output<OUT> : never;
declare type EndpointProps<IN extends IOSchema, OUT extends IOSchema, mIN, OPT, M extends Method> = {
export declare type EndpointInput<T> = T extends Endpoint<infer IN, any, infer mIN, any, any, any, any> ? z.input<Merge<IN, mIN>> : never;
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']>>;
declare type EndpointProps<IN extends IOSchema, OUT extends IOSchema, mIN, OPT, M extends Method, POS extends ApiResponse, NEG extends ApiResponse> = {
middlewares: MiddlewareDefinition<any, any, any>[];

@@ -36,7 +41,7 @@ inputSchema: IN;

handler: Handler<z.output<Merge<IN, mIN>>, z.input<OUT>, OPT>;
resultHandler: ResultHandler | null;
resultHandler: ResultHandlerDefinition<POS, NEG>;
description?: string;
} & MethodsDefinition<M>;
/** mIN, OPT - from Middlewares */
export declare class Endpoint<IN extends IOSchema, OUT extends IOSchema, mIN, OPT, M extends Method> extends AbstractEndpoint {
export declare class Endpoint<IN extends IOSchema, OUT extends IOSchema, mIN, OPT, M extends Method, POS extends ApiResponse, NEG extends ApiResponse> extends AbstractEndpoint {
protected methods: M[];

@@ -47,7 +52,11 @@ protected middlewares: MiddlewareDefinition<any, any, any>[];

protected handler: Handler<z.output<Merge<IN, mIN>>, z.input<OUT>, OPT>;
protected resultHandler: ResultHandler | null;
constructor({ middlewares, inputSchema, outputSchema, handler, resultHandler, description, ...rest }: EndpointProps<IN, OUT, mIN, OPT, M>);
protected resultHandler: ResultHandlerDefinition<POS, NEG>;
constructor({ middlewares, inputSchema, outputSchema, handler, resultHandler, description, ...rest }: EndpointProps<IN, OUT, mIN, OPT, M, POS, NEG>);
getMethods(): M[];
getInputSchema(): Merge<IN, mIN>;
getOutputSchema(): OUT;
getPositiveResponseSchema(): POS['schema'];
getNegativeResponseSchema(): NEG['schema'];
getNegativeMimeTypes(): string[];
getPositiveMimeTypes(): string[];
private setupCorsHeaders;

@@ -54,0 +63,0 @@ private parseOutput;

"use strict";
var __extends = (this && this.__extends) || (function () {
var extendStatics = function (d, b) {
extendStatics = Object.setPrototypeOf ||
({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
function (d, b) { for (var p in b) if (Object.prototype.hasOwnProperty.call(b, p)) d[p] = b[p]; };
return extendStatics(d, b);
};
return function (d, b) {
if (typeof b !== "function" && b !== null)
throw new TypeError("Class extends value " + String(b) + " is not a constructor or null");
extendStatics(d, b);
function __() { this.constructor = d; }
d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
};
})();
var __assign = (this && this.__assign) || function () {
__assign = Object.assign || function(t) {
for (var s, i = 1, n = arguments.length; i < n; i++) {
s = arguments[i];
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p))
t[p] = s[p];
}
return t;
};
return __assign.apply(this, arguments);
};
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
return new (P || (P = Promise))(function (resolve, reject) {
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
step((generator = generator.apply(thisArg, _arguments || [])).next());
});
};
var __generator = (this && this.__generator) || function (thisArg, body) {
var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g;
return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
function verb(n) { return function (v) { return step([n, v]); }; }
function step(op) {
if (f) throw new TypeError("Generator is already executing.");
while (_) try {
if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
if (y = 0, t) op = [op[0] & 2, t.value];
switch (op[0]) {
case 0: case 1: t = op; break;
case 4: _.label++; return { value: op[1], done: false };
case 5: _.label++; y = op[1]; op = [0]; continue;
case 7: op = _.ops.pop(); _.trys.pop(); continue;
default:
if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
if (t[2]) _.ops.pop();
_.trys.pop(); continue;
}
op = body.call(thisArg, _);
} catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
}
};
var __rest = (this && this.__rest) || function (s, e) {
var t = {};
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)
t[p] = s[p];
if (s != null && typeof Object.getOwnPropertySymbols === "function")
for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) {
if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i]))
t[p[i]] = s[p[i]];
}
return t;
};
var __spreadArray = (this && this.__spreadArray) || function (to, from) {
for (var i = 0, il = from.length, j = to.length; i < il; i++, j++)
to[j] = from[i];
return to;
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.Endpoint = exports.AbstractEndpoint = void 0;
var zod_1 = require("zod");
var helpers_1 = require("./helpers");
var result_handler_1 = require("./result-handler");
var AbstractEndpoint = /** @class */ (function () {
function AbstractEndpoint() {
const zod_1 = require("zod");
const helpers_1 = require("./helpers");
class AbstractEndpoint {
getDescription() {
return this.description;
}
AbstractEndpoint.prototype.getDescription = function () {
return this.description;
};
return AbstractEndpoint;
}());
}
exports.AbstractEndpoint = AbstractEndpoint;
/** mIN, OPT - from Middlewares */
var Endpoint = /** @class */ (function (_super) {
__extends(Endpoint, _super);
function Endpoint(_a) {
var middlewares = _a.middlewares, inputSchema = _a.inputSchema, outputSchema = _a.outputSchema, handler = _a.handler, resultHandler = _a.resultHandler, description = _a.description, rest = __rest(_a, ["middlewares", "inputSchema", "outputSchema", "handler", "resultHandler", "description"]);
var _this = _super.call(this) || this;
_this.methods = [];
_this.middlewares = [];
_this.middlewares = middlewares;
_this.inputSchema = helpers_1.combineEndpointAndMiddlewareInputSchemas(inputSchema, middlewares);
_this.outputSchema = outputSchema;
_this.handler = handler;
_this.resultHandler = resultHandler;
_this.description = description;
class Endpoint extends AbstractEndpoint {
constructor({ middlewares, inputSchema, outputSchema, handler, resultHandler, description, ...rest }) {
super();
this.methods = [];
this.middlewares = [];
this.middlewares = middlewares;
this.inputSchema = helpers_1.combineEndpointAndMiddlewareInputSchemas(inputSchema, middlewares);
this.outputSchema = outputSchema;
this.handler = handler;
this.resultHandler = resultHandler;
this.description = description;
if ('methods' in rest) {
_this.methods = rest.methods;
this.methods = rest.methods;
}
else {
_this.methods = [rest.method];
this.methods = [rest.method];
}
return _this;
}
Endpoint.prototype.getMethods = function () {
getMethods() {
return this.methods;
};
Endpoint.prototype.getInputSchema = function () {
}
getInputSchema() {
return this.inputSchema;
};
Endpoint.prototype.getOutputSchema = function () {
}
getOutputSchema() {
return this.outputSchema;
};
Endpoint.prototype.setupCorsHeaders = function (response) {
var accessMethods = this.methods.map(function (method) { return method.toUpperCase(); }).concat('OPTIONS').join(', ');
}
getPositiveResponseSchema() {
return this.resultHandler.getPositiveResponse(this.outputSchema).schema;
}
getNegativeResponseSchema() {
return this.resultHandler.getNegativeResponse().schema;
}
getNegativeMimeTypes() {
return this.resultHandler.getPositiveResponse(this.outputSchema).mimeTypes;
}
getPositiveMimeTypes() {
return this.resultHandler.getNegativeResponse().mimeTypes;
}
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.prototype.parseOutput = function (output) {
}
parseOutput(output) {
try {

@@ -137,3 +64,3 @@ return this.outputSchema.parse(output);

if (e instanceof zod_1.z.ZodError) {
throw new zod_1.z.ZodError(__spreadArray([
throw new zod_1.z.ZodError([
{

@@ -143,133 +70,74 @@ message: 'Invalid format',

path: ['output'],
}
], e.issues.map(function (issue) { return (__assign(__assign({}, issue), { path: issue.path.length === 0 ? ['output'] : issue.path })); })));
},
...e.issues.map((issue) => ({
...issue,
path: issue.path.length === 0 ? ['output'] : issue.path
}))
]);
}
throw e;
}
};
Endpoint.prototype.runMiddlewares = function (_a) {
var input = _a.input, request = _a.request, response = _a.response, logger = _a.logger;
return __awaiter(this, void 0, void 0, function () {
var options, _i, _b, def, _c, _d, _e;
return __generator(this, function (_f) {
switch (_f.label) {
case 0:
options = {};
_i = 0, _b = this.middlewares;
_f.label = 1;
case 1:
if (!(_i < _b.length)) return [3 /*break*/, 4];
def = _b[_i];
input = __assign(__assign({}, input), def.input.parse(input)); // middleware can transform the input types
_d = (_c = Object).assign;
_e = [options];
return [4 /*yield*/, def.middleware({
input: input, options: options, request: request,
response: response, logger: logger
})];
case 2:
_d.apply(_c, _e.concat([_f.sent()]));
if (response.writableEnded) {
return [3 /*break*/, 4];
}
_f.label = 3;
case 3:
_i++;
return [3 /*break*/, 1];
case 4: return [2 /*return*/, { input: input, options: options, isStreamClosed: response.writableEnded }];
}
});
}
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
});
};
Endpoint.prototype.parseAndRunHandler = function (_a) {
var input = _a.input, options = _a.options, logger = _a.logger;
return __awaiter(this, void 0, void 0, function () {
return __generator(this, function (_b) {
switch (_b.label) {
case 0: return [4 /*yield*/, this.handler({
input: this.inputSchema.parse(input),
options: options, logger: logger
})];
case 1: return [2 /*return*/, _b.sent()];
}
}
async handleResult({ error, request, response, logger, initialInput, output }) {
try {
await this.resultHandler.handler({
error, output, request, response, logger,
input: initialInput
});
});
};
Endpoint.prototype.handleResult = function (_a) {
var config = _a.config, error = _a.error, request = _a.request, response = _a.response, logger = _a.logger, initialInput = _a.initialInput, output = _a.output;
return __awaiter(this, void 0, void 0, function () {
var resultHandler, e_1;
return __generator(this, function (_b) {
switch (_b.label) {
case 0:
resultHandler = this.resultHandler || config.resultHandler || result_handler_1.defaultResultHandler;
_b.label = 1;
case 1:
_b.trys.push([1, 3, , 4]);
return [4 /*yield*/, resultHandler({
error: error, output: output, request: request, response: response, logger: logger,
input: initialInput
})];
case 2:
_b.sent();
return [3 /*break*/, 4];
case 3:
e_1 = _b.sent();
logger.error("Result handler failure: " + e_1.message + ".");
return [3 /*break*/, 4];
case 4: return [2 /*return*/];
}
}
catch (e) {
logger.error(`Result handler failure: ${e.message}.`);
// throw e;
}
}
async execute({ request, response, logger, config }) {
let output;
let error = null;
if (config.cors) {
this.setupCorsHeaders(response);
}
if (request.method === 'OPTIONS') {
return response.end();
}
const initialInput = helpers_1.getInitialInput(request);
try {
const { input, options, isStreamClosed } = await this.runMiddlewares({
input: { ...initialInput },
request, response, logger
});
if (isStreamClosed) {
return;
}
output = this.parseOutput(await this.parseAndRunHandler({ input, options, logger }));
}
catch (e) {
error = e;
}
await this.handleResult({
initialInput, output, request,
response, error, logger
});
};
Endpoint.prototype.execute = function (_a) {
var request = _a.request, response = _a.response, logger = _a.logger, config = _a.config;
return __awaiter(this, void 0, void 0, function () {
var output, error, initialInput, _b, input, options, isStreamClosed, _c, e_2;
return __generator(this, function (_d) {
switch (_d.label) {
case 0:
error = null;
if (config.cors) {
this.setupCorsHeaders(response);
}
if (request.method === 'OPTIONS') {
return [2 /*return*/, response.end()];
}
initialInput = helpers_1.getInitialInput(request);
_d.label = 1;
case 1:
_d.trys.push([1, 4, , 5]);
return [4 /*yield*/, this.runMiddlewares({
input: __assign({}, initialInput),
request: request, response: response, logger: logger
})];
case 2:
_b = _d.sent(), input = _b.input, options = _b.options, isStreamClosed = _b.isStreamClosed;
if (isStreamClosed) {
return [2 /*return*/];
}
_c = this.parseOutput;
return [4 /*yield*/, this.parseAndRunHandler({ input: input, options: options, logger: logger })];
case 3:
output = _c.apply(this, [_d.sent()]);
return [3 /*break*/, 5];
case 4:
e_2 = _d.sent();
error = e_2;
return [3 /*break*/, 5];
case 5: return [4 /*yield*/, this.handleResult({
initialInput: initialInput, output: output, request: request,
response: response, error: error, logger: logger, config: config
})];
case 6:
_d.sent();
return [2 /*return*/];
}
});
});
};
return Endpoint;
}(AbstractEndpoint));
}
}
exports.Endpoint = Endpoint;
//# sourceMappingURL=endpoint.js.map
import { z } from 'zod';
import { Endpoint, Handler } from './endpoint';
import { FlatObject, IOSchema, Merge } from './helpers';
import { ApiResponse, FlatObject, IOSchema, Merge } from './helpers';
import { Method, MethodsDefinition } from './method';
import { MiddlewareDefinition } from './middleware';
import { ResultHandler } from './result-handler';
import { ResultHandlerDefinition } from './result-handler';
declare type BuildProps<IN extends IOSchema, OUT extends IOSchema, mIN, mOUT, M extends Method> = {

@@ -14,10 +14,45 @@ input: IN;

/** mIN, mOUT - accumulated from all middlewares */
export declare class EndpointsFactory<mIN, mOUT> {
export declare class EndpointsFactory<mIN, mOUT, POS extends ApiResponse, NEG extends ApiResponse> {
protected resultHandler: ResultHandlerDefinition<POS, NEG>;
protected middlewares: MiddlewareDefinition<any, any, any>[];
protected resultHandler: ResultHandler | null;
constructor(resultHandler: ResultHandlerDefinition<POS, NEG>);
private static create;
setResultHandler(resultHandler: ResultHandler): EndpointsFactory<mIN, mOUT>;
addMiddleware<IN extends IOSchema, OUT extends FlatObject>(definition: MiddlewareDefinition<IN, mOUT, OUT>): EndpointsFactory<Merge<IN, mIN>, mOUT & OUT>;
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>;
addMiddleware<IN extends IOSchema, OUT extends FlatObject>(definition: MiddlewareDefinition<IN, mOUT, OUT>): EndpointsFactory<Merge<IN, mIN>, mOUT & OUT, POS, NEG>;
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>;
}
export declare const defaultEndpointsFactory: EndpointsFactory<unknown, unknown, ApiResponse<z.ZodObject<{
status: z.ZodLiteral<"success">;
data: import("./helpers").OutputMarker;
}, "strip", z.ZodTypeAny, {
data: {
[x: string]: any;
[x: number]: any;
};
status: "success";
}, {
data: {
[x: string]: any;
[x: number]: any;
};
status: "success";
}>>, ApiResponse<z.ZodObject<{
status: z.ZodLiteral<"error">;
error: z.ZodObject<{
message: z.ZodString;
}, "strip", z.ZodTypeAny, {
message: string;
}, {
message: string;
}>;
}, "strip", z.ZodTypeAny, {
status: "error";
error: {
message: string;
};
}, {
status: "error";
error: {
message: string;
};
}>>>;
export {};
"use strict";
var __assign = (this && this.__assign) || function () {
__assign = Object.assign || function(t) {
for (var s, i = 1, n = arguments.length; i < n; i++) {
s = arguments[i];
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p))
t[p] = s[p];
}
return t;
};
return __assign.apply(this, arguments);
};
var __rest = (this && this.__rest) || function (s, e) {
var t = {};
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)
t[p] = s[p];
if (s != null && typeof Object.getOwnPropertySymbols === "function")
for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) {
if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i]))
t[p[i]] = s[p[i]];
}
return t;
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.EndpointsFactory = void 0;
var endpoint_1 = require("./endpoint");
exports.defaultEndpointsFactory = exports.EndpointsFactory = void 0;
const endpoint_1 = require("./endpoint");
const result_handler_1 = require("./result-handler");
/** mIN, mOUT - accumulated from all middlewares */
var EndpointsFactory = /** @class */ (function () {
function EndpointsFactory() {
class EndpointsFactory {
constructor(resultHandler) {
this.resultHandler = resultHandler;
this.middlewares = [];
this.resultHandler = null;
this.resultHandler = resultHandler;
}
EndpointsFactory.create = function (middlewares, resultHandler) {
var factory = new EndpointsFactory();
static create(middlewares, resultHandler) {
const factory = new EndpointsFactory(resultHandler);
factory.middlewares = middlewares;
factory.resultHandler = resultHandler;
return factory;
};
EndpointsFactory.prototype.setResultHandler = function (resultHandler) {
return EndpointsFactory.create(this.middlewares, resultHandler);
};
EndpointsFactory.prototype.addMiddleware = function (definition) {
}
addMiddleware(definition) {
return EndpointsFactory.create(this.middlewares.concat(definition), this.resultHandler);
};
EndpointsFactory.prototype.build = function (_a) {
var input = _a.input, output = _a.output, handler = _a.handler, description = _a.description, rest = __rest(_a, ["input", "output", "handler", "description"]);
return new endpoint_1.Endpoint(__assign({ handler: handler, description: description, middlewares: this.middlewares, inputSchema: input, outputSchema: output, resultHandler: this.resultHandler }, rest));
};
return EndpointsFactory;
}());
}
build({ input, output, handler, description, ...rest }) {
return new endpoint_1.Endpoint({
handler, description,
middlewares: this.middlewares,
inputSchema: input,
outputSchema: output,
resultHandler: this.resultHandler,
...rest
});
}
}
exports.EndpointsFactory = EndpointsFactory;
exports.defaultEndpointsFactory = new EndpointsFactory(result_handler_1.defaultResultHandler);
//# sourceMappingURL=endpoints-factory.js.map
"use strict";
var __extends = (this && this.__extends) || (function () {
var extendStatics = function (d, b) {
extendStatics = Object.setPrototypeOf ||
({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
function (d, b) { for (var p in b) if (Object.prototype.hasOwnProperty.call(b, p)) d[p] = b[p]; };
return extendStatics(d, b);
};
return function (d, b) {
if (typeof b !== "function" && b !== null)
throw new TypeError("Class extends value " + String(b) + " is not a constructor or null");
extendStatics(d, b);
function __() { this.constructor = d; }
d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
};
})();
Object.defineProperty(exports, "__esModule", { value: true });
exports.OpenAPIError = exports.DependsOnMethodError = exports.RoutingError = void 0;
var RoutingError = /** @class */ (function (_super) {
__extends(RoutingError, _super);
function RoutingError() {
return _super !== null && _super.apply(this, arguments) || this;
}
return RoutingError;
}(Error));
class RoutingError extends Error {
}
exports.RoutingError = RoutingError;
var DependsOnMethodError = /** @class */ (function (_super) {
__extends(DependsOnMethodError, _super);
function DependsOnMethodError() {
return _super !== null && _super.apply(this, arguments) || this;
}
return DependsOnMethodError;
}(RoutingError));
class DependsOnMethodError extends RoutingError {
}
exports.DependsOnMethodError = DependsOnMethodError;
var OpenAPIError = /** @class */ (function (_super) {
__extends(OpenAPIError, _super);
function OpenAPIError() {
return _super !== null && _super.apply(this, arguments) || this;
}
return OpenAPIError;
}(Error));
class OpenAPIError extends Error {
}
exports.OpenAPIError = OpenAPIError;
//# sourceMappingURL=errors.js.map

@@ -16,2 +16,9 @@ import { Request } from 'express';

export declare type Merge<A extends IOSchema, B extends IOSchema | any> = z.ZodObject<IOExtract<A, 'shape'> & IOExtract<B, 'shape'>, IOExtract<A, '_unknownKeys'>, IOExtract<A, '_catchall'>, IOExtract<A, '_output'> & IOExtract<B, '_output'>, IOExtract<A, '_input'> & IOExtract<B, '_input'>>;
export declare type OutputMarker = IOSchema & {
_typeGuard: 'OutputMarker';
};
export declare const markOutput: (output: IOSchema) => OutputMarker;
export declare type ReplaceMarkerInShape<S extends z.ZodRawShape, OUT extends IOSchema> = {
[K in keyof S]: S[K] extends OutputMarker ? OUT : S[K];
};
export declare function extractObjectSchema(subject: IOSchema): ObjectSchema;

@@ -23,2 +30,7 @@ export declare function combineEndpointAndMiddlewareInputSchemas<IN extends IOSchema, mIN>(input: IN, middlewares: MiddlewareDefinition<IOSchema, any, any>[]): Merge<IN, mIN>;

export declare function getStatusCodeFromError(error: Error): number;
export declare type ApiResponse<A = z.ZodTypeAny> = {
schema: A;
mimeTypes: string[];
};
export declare const createApiResponse: <S extends z.ZodTypeAny>(schema: S, mimeTypes?: string | string[]) => ApiResponse<S>;
export {};
"use strict";
var __assign = (this && this.__assign) || function () {
__assign = Object.assign || function(t) {
for (var s, i = 1, n = arguments.length; i < n; i++) {
s = arguments[i];
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p))
t[p] = s[p];
}
return t;
};
return __assign.apply(this, arguments);
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.getStatusCodeFromError = exports.getMessageFromError = exports.isLoggerConfig = exports.getInitialInput = exports.combineEndpointAndMiddlewareInputSchemas = exports.extractObjectSchema = void 0;
var http_errors_1 = require("http-errors");
var zod_1 = require("zod");
var config_type_1 = require("./config-type");
exports.createApiResponse = exports.getStatusCodeFromError = exports.getMessageFromError = exports.isLoggerConfig = exports.getInitialInput = exports.combineEndpointAndMiddlewareInputSchemas = exports.extractObjectSchema = exports.markOutput = void 0;
const http_errors_1 = require("http-errors");
const mime_1 = require("mime");
const zod_1 = require("zod");
const config_type_1 = require("./config-type");
const markOutput = (output) => output;
exports.markOutput = markOutput;
function extractObjectSchema(subject) {
if (subject instanceof zod_1.z.ZodUnion) {
return subject.options.reduce(function (acc, option) {
return acc.partial().merge(option.partial());
});
return subject.options.reduce((acc, option) => acc.partial().merge(option.partial()));
}

@@ -34,7 +24,5 @@ if (subject instanceof zod_1.z.ZodIntersection) {

}
var mSchema = middlewares
.map(function (middleware) { return middleware.input; })
.reduce(function (carry, schema) {
return extractObjectSchema(carry).merge(extractObjectSchema(schema));
});
const mSchema = middlewares
.map((middleware) => middleware.input)
.reduce((carry, schema) => extractObjectSchema(carry).merge(extractObjectSchema(schema)));
return extractObjectSchema(mSchema).merge(extractObjectSchema(input));

@@ -53,3 +41,3 @@ }

default:
return __assign(__assign({}, request.query), request.body);
return { ...request.query, ...request.body };
}

@@ -67,6 +55,3 @@ }

return error instanceof zod_1.z.ZodError
? error.issues.map(function (_a) {
var path = _a.path, message = _a.message;
return path.join('/') + ": " + message;
}).join('; ')
? error.issues.map(({ path, message }) => `${path.join('/')}: ${message}`).join('; ')
: error.message;

@@ -85,2 +70,9 @@ }

exports.getStatusCodeFromError = getStatusCodeFromError;
const createApiResponse = (schema, mimeTypes = mime_1.lookup('json')) => {
return {
schema,
mimeTypes: typeof mimeTypes === 'string' ? [mimeTypes] : mimeTypes,
};
};
exports.createApiResponse = createApiResponse;
//# sourceMappingURL=helpers.js.map
export { ConfigType, LoggerConfig } from './config-type';
export { AbstractEndpoint, EndpointInput, EndpointOutput } from './endpoint';
export { AbstractEndpoint, EndpointInput, EndpointOutput, EndpointResponse } from './endpoint';
export { Method } from './method';
export { EndpointsFactory } from './endpoints-factory';
export { IOSchema, FlatObject } from './helpers';
export { EndpointsFactory, defaultEndpointsFactory } from './endpoints-factory';
export { IOSchema, FlatObject, markOutput, createApiResponse } from './helpers';
export { createLogger } from './logger';
export { createMiddleware } from './middleware';
export { ResultHandler } from './result-handler';
export { createResultHandler, defaultResultHandler } from './result-handler';
export { Routing, DependsOnMethod } from './routing';

@@ -14,3 +14,3 @@ export { createServer, attachRouting } from './server';

import { z } from 'zod';
import * as createHttpError from 'http-errors';
import createHttpError from 'http-errors';
export { createHttpError, z };
"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.z = exports.createHttpError = exports.RoutingError = exports.DependsOnMethodError = exports.OpenAPIError = exports.OpenAPI = exports.attachRouting = exports.createServer = exports.DependsOnMethod = exports.createMiddleware = exports.createLogger = exports.EndpointsFactory = exports.AbstractEndpoint = void 0;
exports.z = exports.createHttpError = exports.RoutingError = exports.DependsOnMethodError = exports.OpenAPIError = exports.OpenAPI = exports.attachRouting = exports.createServer = exports.DependsOnMethod = exports.defaultResultHandler = exports.createResultHandler = exports.createMiddleware = exports.createLogger = exports.createApiResponse = exports.markOutput = exports.defaultEndpointsFactory = exports.EndpointsFactory = exports.AbstractEndpoint = void 0;
var endpoint_1 = require("./endpoint");

@@ -8,2 +11,6 @@ Object.defineProperty(exports, "AbstractEndpoint", { enumerable: true, get: function () { return endpoint_1.AbstractEndpoint; } });

Object.defineProperty(exports, "EndpointsFactory", { enumerable: true, get: function () { return endpoints_factory_1.EndpointsFactory; } });
Object.defineProperty(exports, "defaultEndpointsFactory", { enumerable: true, get: function () { return endpoints_factory_1.defaultEndpointsFactory; } });
var helpers_1 = require("./helpers");
Object.defineProperty(exports, "markOutput", { enumerable: true, get: function () { return helpers_1.markOutput; } });
Object.defineProperty(exports, "createApiResponse", { enumerable: true, get: function () { return helpers_1.createApiResponse; } });
var logger_1 = require("./logger");

@@ -13,2 +20,5 @@ Object.defineProperty(exports, "createLogger", { enumerable: true, get: function () { return logger_1.createLogger; } });

Object.defineProperty(exports, "createMiddleware", { enumerable: true, get: function () { return middleware_1.createMiddleware; } });
var result_handler_1 = require("./result-handler");
Object.defineProperty(exports, "createResultHandler", { enumerable: true, get: function () { return result_handler_1.createResultHandler; } });
Object.defineProperty(exports, "defaultResultHandler", { enumerable: true, get: function () { return result_handler_1.defaultResultHandler; } });
var routing_1 = require("./routing");

@@ -25,6 +35,6 @@ Object.defineProperty(exports, "DependsOnMethod", { enumerable: true, get: function () { return routing_1.DependsOnMethod; } });

Object.defineProperty(exports, "RoutingError", { enumerable: true, get: function () { return errors_1.RoutingError; } });
var zod_1 = require("zod");
const zod_1 = require("zod");
Object.defineProperty(exports, "z", { enumerable: true, get: function () { return zod_1.z; } });
var createHttpError = require("http-errors");
exports.createHttpError = createHttpError;
const http_errors_1 = __importDefault(require("http-errors"));
exports.createHttpError = http_errors_1.default;
//# sourceMappingURL=index.js.map

@@ -1,3 +0,3 @@

import * as winston from 'winston';
import winston from 'winston';
import { LoggerConfig } from './config-type';
export declare function createLogger(loggerConfig: LoggerConfig): winston.Logger;
"use strict";
var __rest = (this && this.__rest) || function (s, e) {
var t = {};
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)
t[p] = s[p];
if (s != null && typeof Object.getOwnPropertySymbols === "function")
for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) {
if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i]))
t[p[i]] = s[p[i]];
}
return t;
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.createLogger = void 0;
var util_1 = require("util");
var triple_beam_1 = require("triple-beam");
var winston = require("winston");
var _a = winston.format, combine = _a.combine, colorize = _a.colorize, useTimestamp = _a.timestamp, printf = _a.printf;
const util_1 = require("util");
const triple_beam_1 = require("triple-beam");
const winston_1 = __importDefault(require("winston"));
const { combine, colorize, timestamp: useTimestamp, printf } = winston_1.default.format;
function createLogger(loggerConfig) {
var prettyPrint = function (meta) {
const prettyPrint = (meta) => {
delete meta[triple_beam_1.LEVEL];

@@ -26,12 +18,9 @@ delete meta[triple_beam_1.MESSAGE];

};
var getOutputFormat = function (isPretty) { return printf(function (_a) {
var timestamp = _a.timestamp, message = _a.message, level = _a.level, durationMs = _a.durationMs, meta = __rest(_a, ["timestamp", "message", "level", "durationMs"]);
return timestamp + " " + level + ": " + message +
(durationMs === undefined ? '' : " duration: " + durationMs + "ms") +
(Object.keys(meta).length === 0
? ''
: ' ' + (isPretty ? prettyPrint(meta) : JSON.stringify(meta)));
}); };
var formats = [useTimestamp()];
var consoleOutputOptions = {
const getOutputFormat = (isPretty) => printf(({ timestamp, message, level, durationMs, ...meta }) => `${timestamp} ${level}: ${message}` +
(durationMs === undefined ? '' : ` duration: ${durationMs}ms`) +
(Object.keys(meta).length === 0
? ''
: ' ' + (isPretty ? prettyPrint(meta) : JSON.stringify(meta))));
const formats = [useTimestamp()];
const consoleOutputOptions = {
handleExceptions: true,

@@ -53,7 +42,7 @@ };

}
consoleOutputOptions.format = combine.apply(void 0, formats);
return winston.createLogger({
consoleOutputOptions.format = combine(...formats);
return winston_1.default.createLogger({
silent: loggerConfig.level === 'silent',
levels: winston.config.npm.levels,
transports: [new winston.transports.Console(consoleOutputOptions)],
levels: winston_1.default.config.npm.levels,
transports: [new winston_1.default.transports.Console(consoleOutputOptions)],
exitOnError: false,

@@ -60,0 +49,0 @@ });

"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.createMiddleware = void 0;
var createMiddleware = function (definition) { return definition; };
const createMiddleware = (definition) => definition;
exports.createMiddleware = createMiddleware;
//# sourceMappingURL=middleware.js.map

@@ -9,9 +9,7 @@ import { OpenApiBuilder } from 'openapi3-ts';

successfulResponseDescription?: string;
errorResponseDescription?: string;
}
export declare class OpenAPI {
private _usedRef;
builder: OpenApiBuilder;
private createRef;
constructor({ routing, title, version, serverUrl, successfulResponseDescription }: GenerationParams);
export declare class OpenAPI extends OpenApiBuilder {
constructor({ routing, title, version, serverUrl, successfulResponseDescription, errorResponseDescription }: GenerationParams);
}
export {};
"use strict";
var __assign = (this && this.__assign) || function () {
__assign = Object.assign || function(t) {
for (var s, i = 1, n = arguments.length; i < n; i++) {
s = arguments[i];
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p))
t[p] = s[p];
}
return t;
};
return __assign.apply(this, arguments);
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.OpenAPI = void 0;
var openapi3_ts_1 = require("openapi3-ts");
var zod_1 = require("zod");
var errors_1 = require("./errors");
var helpers_1 = require("./helpers");
var routing_1 = require("./routing");
var mime_1 = require("mime");
var describeSchema = function (value, isResponse) {
var otherProps = {};
const openapi3_ts_1 = require("openapi3-ts");
const zod_1 = require("zod");
const errors_1 = require("./errors");
const helpers_1 = require("./helpers");
const routing_1 = require("./routing");
const mime_1 = require("mime");
const describeSchema = (value, isResponse) => {
const otherProps = {};
if (value.isNullable()) {

@@ -28,40 +17,69 @@ otherProps.nullable = true;

case value instanceof zod_1.z.ZodString:
return __assign(__assign({}, otherProps), { type: 'string' });
return { ...otherProps, type: 'string' };
case value instanceof zod_1.z.ZodNumber:
return __assign(__assign({}, otherProps), { type: 'number' });
return { ...otherProps, type: 'number' };
case value instanceof zod_1.z.ZodBigInt:
return __assign(__assign({}, otherProps), { type: 'integer', format: 'int64' });
return { ...otherProps, type: 'integer', format: 'int64' };
case value instanceof zod_1.z.ZodBoolean:
return __assign(__assign({}, otherProps), { type: 'boolean' });
return { ...otherProps, type: 'boolean' };
case value instanceof zod_1.z.ZodDate:
return __assign(__assign({}, otherProps), { type: 'string', format: 'date' });
return { ...otherProps, type: 'string', format: 'date' };
case value instanceof zod_1.z.ZodNull:
// null is not supported https://swagger.io/docs/specification/data-models/data-types/
// return {...otherProps, type: 'null'};
return __assign(__assign({}, otherProps), { type: 'string', nullable: true, format: 'null' });
return { ...otherProps, type: 'string', nullable: true, format: 'null' };
case value instanceof zod_1.z.ZodArray:
return __assign(__assign({}, otherProps), { type: 'array', items: describeSchema(value._def.type, isResponse) });
return {
...otherProps,
type: 'array',
items: describeSchema(value._def.type, isResponse)
};
case value instanceof zod_1.z.ZodObject:
case value instanceof zod_1.z.ZodRecord:
return __assign(__assign({}, otherProps), { type: 'object', properties: describeObject(value, isResponse), required: Object.keys(value.shape)
.filter(function (key) { return !value.shape[key].isOptional(); }) });
return {
...otherProps,
type: 'object',
properties: describeObject(value, isResponse),
required: Object.keys(value.shape)
.filter((key) => !value.shape[key].isOptional())
};
case value instanceof zod_1.z.ZodLiteral:
return __assign(__assign({}, otherProps), { type: typeof value._def.value, enum: [value._def.value] });
return {
...otherProps,
type: typeof value._def.value,
enum: [value._def.value]
};
case value instanceof zod_1.z.ZodEnum:
case value instanceof zod_1.z.ZodNativeEnum:
return __assign(__assign({}, otherProps), { type: typeof Object.values(value._def.values)[0], enum: Object.values(value._def.values) });
return {
...otherProps,
type: typeof Object.values(value._def.values)[0],
enum: Object.values(value._def.values)
};
case value instanceof zod_1.z.ZodTransformer:
case value instanceof zod_1.z.ZodEffects:
return __assign(__assign({}, otherProps), describeTransformation(value, isResponse));
return {
...otherProps,
...describeTransformation(value, isResponse)
};
case value instanceof zod_1.z.ZodOptional:
case value instanceof zod_1.z.ZodNullable:
return __assign(__assign({}, otherProps), describeSchema(value.unwrap(), isResponse));
return {
...otherProps,
...describeSchema(value.unwrap(), isResponse)
};
case value instanceof zod_1.z.ZodIntersection:
return __assign(__assign({}, otherProps), { allOf: [
return {
...otherProps,
allOf: [
describeSchema(value._def.left, isResponse),
describeSchema(value._def.right, isResponse)
] });
]
};
case value instanceof zod_1.z.ZodUnion:
return __assign(__assign({}, otherProps), { oneOf: value._def.options
.map(function (schema) { return describeSchema(schema, isResponse); }) });
return {
...otherProps,
oneOf: value._def.options
.map((schema) => describeSchema(schema, isResponse))
};
case value instanceof zod_1.z.ZodUndefined:

@@ -78,19 +96,19 @@ case value instanceof zod_1.z.ZodTuple:

default:
throw new errors_1.OpenAPIError("Zod type " + value.constructor.name + " is unsupported");
throw new errors_1.OpenAPIError(`Zod type ${value.constructor.name} is unsupported`);
}
};
var describeObject = function (schema, isResponse) {
return Object.keys(schema.shape).reduce(function (carry, key) {
var _a;
return (__assign(__assign({}, carry), (_a = {}, _a[key] = describeSchema(schema.shape[key], isResponse), _a)));
}, {});
const describeObject = (schema, isResponse) => {
return Object.keys(schema.shape).reduce((carry, key) => ({
...carry,
[key]: describeSchema(schema.shape[key], isResponse)
}), {});
};
var describeTransformation = function (value, isResponse) {
var input = describeSchema(value._def.schema, isResponse);
var output = 'undefined';
const describeTransformation = (value, isResponse) => {
const input = describeSchema(value._def.schema, isResponse);
let output = 'undefined';
if (isResponse && value._def.effects && value._def.effects.length > 0) {
var effect = value._def.effects.filter(function (ef) { return ef.type === 'transform'; }).slice(-1)[0];
const effect = value._def.effects.filter((ef) => ef.type === 'transform').slice(-1)[0];
if (effect && 'transform' in effect) {
try {
output = typeof effect.transform(['integer', 'number'].includes("" + input.type) ? 0 :
output = typeof effect.transform(['integer', 'number'].includes(`${input.type}`) ? 0 :
'string' === input.type ? '' :

@@ -105,30 +123,42 @@ 'boolean' === input.type ? false :

}
return __assign(__assign({}, input), (['number', 'string', 'boolean', 'null'].includes(output) ? {
type: output
} : {}));
return {
...input,
...(['number', 'string', 'boolean', 'null'].includes(output) ? {
type: output
} : {})
};
};
var OpenAPI = /** @class */ (function () {
function OpenAPI(_a) {
var _this = this;
var routing = _a.routing, title = _a.title, version = _a.version, serverUrl = _a.serverUrl, successfulResponseDescription = _a.successfulResponseDescription;
this._usedRef = {};
var mimeJson = mime_1.lookup('.json');
this.builder = new openapi3_ts_1.OpenApiBuilder()
.addInfo({ title: title, version: version })
.addServer({ url: serverUrl });
var cb = function (endpoint, fullPath, method) {
var _a, _b, _c;
var _d;
var responseSchemaRef = _this.createRef('responseSchema');
_this.builder.addSchema(responseSchemaRef.name, __assign(__assign({}, describeSchema(endpoint.getOutputSchema(), true)), { description: fullPath + " " + method.toUpperCase() + " response schema" }));
var operation = {
const mimeJson = mime_1.lookup('json');
class OpenAPI extends openapi3_ts_1.OpenApiBuilder {
constructor({ routing, title, version, serverUrl, successfulResponseDescription = 'Successful response', errorResponseDescription = 'Error response' }) {
super();
this.addInfo({ title, version }).addServer({ url: serverUrl });
const cb = (endpoint, fullPath, method) => {
var _a;
const operation = {
responses: {
default: {
description: successfulResponseDescription || 'Successful response',
content: (_a = {},
_a[mimeJson] = {
schema: responseSchemaRef.link
},
_a)
'200': {
description: successfulResponseDescription,
content: endpoint.getPositiveMimeTypes().reduce((carry, mimeType) => ({
...carry,
[mimeType]: {
schema: {
...describeSchema(endpoint.getPositiveResponseSchema(), true),
description: `${method.toUpperCase()} ${fullPath} ${successfulResponseDescription}`
}
}
}), {}),
},
'400': {
description: errorResponseDescription,
content: endpoint.getNegativeMimeTypes().reduce((carry, mimeType) => ({
...carry,
[mimeType]: {
schema: {
...describeSchema(endpoint.getNegativeResponseSchema(), true),
description: `${method.toUpperCase()} ${fullPath} ${errorResponseDescription}`
}
}
}), {}),
}
}

@@ -141,46 +171,36 @@ };

operation.parameters = [];
var subject_1 = helpers_1.extractObjectSchema(endpoint.getInputSchema()).shape;
Object.keys(subject_1).forEach(function (name) {
var parameterRef = _this.createRef('parameter', 'parameters');
_this.builder.addParameter(parameterRef.name, {
name: name,
const subject = helpers_1.extractObjectSchema(endpoint.getInputSchema()).shape;
Object.keys(subject).forEach((name) => {
operation.parameters.push({
name,
in: 'query',
required: !subject_1[name].isOptional(),
schema: __assign(__assign({}, describeSchema(subject_1[name], false)), { description: fullPath + " " + method.toUpperCase() + " parameter" }),
required: !subject[name].isOptional(),
schema: {
...describeSchema(subject[name], false),
description: `${method.toUpperCase()} ${fullPath} parameter`
},
});
operation.parameters.push(parameterRef.link);
});
}
else {
var bodySchemaRef = _this.createRef('requestBody');
_this.builder.addSchema(bodySchemaRef.name, __assign(__assign({}, describeSchema(endpoint.getInputSchema(), false)), { description: fullPath + " " + method.toUpperCase() + " request body" }));
operation.requestBody = {
content: (_b = {},
_b[mimeJson] = {
schema: bodySchemaRef.link
},
_b)
content: {
[mimeJson]: {
schema: {
...describeSchema(endpoint.getInputSchema(), false),
description: `${method.toUpperCase()} ${fullPath} request body`
}
}
}
};
}
_this.builder.addPath(fullPath, __assign(__assign({}, (((_d = _this.builder.rootDoc.paths) === null || _d === void 0 ? void 0 : _d[fullPath]) || {})), (_c = {}, _c[method] = operation, _c)));
this.addPath(fullPath, {
...(((_a = this.rootDoc.paths) === null || _a === void 0 ? void 0 : _a[fullPath]) || {}),
[method]: operation,
});
};
routing_1.routingCycle({ routing: routing, cb: cb });
routing_1.routingCycle({ routing, cb });
}
OpenAPI.prototype.createRef = function (str, section) {
if (section === void 0) { section = 'schemas'; }
var name = str.replace(/[^A-Za-z0-9\-._]/g, '');
var n = 1;
while (this._usedRef["" + name + n]) {
n++;
}
var ref = "" + name + n;
this._usedRef[ref] = true;
return {
name: ref,
link: { $ref: "#/components/" + section + "/" + ref }
};
};
return OpenAPI;
}());
}
exports.OpenAPI = OpenAPI;
//# sourceMappingURL=open-api.js.map
import { Request, Response } from 'express';
import { Logger } from 'winston';
interface ResultHandlerParams {
import { z } from 'zod';
import { ApiResponse, IOSchema } from './helpers';
interface ResultHandlerParams<RES> {
error: Error | null;

@@ -8,7 +10,47 @@ input: any;

request: Request;
response: Response;
response: Response<RES>;
logger: Logger;
}
export declare type ResultHandler = (params: ResultHandlerParams) => void | Promise<void>;
export declare const defaultResultHandler: ResultHandler;
declare type ResultHandler<RES> = (params: ResultHandlerParams<RES>) => void | Promise<void>;
export interface ResultHandlerDefinition<POS extends ApiResponse, NEG extends ApiResponse> {
getPositiveResponse: <OUT extends IOSchema>(output: OUT) => POS;
getNegativeResponse: () => NEG;
handler: ResultHandler<z.output<POS['schema']> | z.output<NEG['schema']>>;
}
export declare const createResultHandler: <POS extends ApiResponse<z.ZodTypeAny>, NEG extends ApiResponse<z.ZodTypeAny>>(definition: ResultHandlerDefinition<POS, NEG>) => ResultHandlerDefinition<POS, NEG>;
export declare const defaultResultHandler: ResultHandlerDefinition<ApiResponse<z.ZodObject<{
status: z.ZodLiteral<"success">;
data: import("./helpers").OutputMarker;
}, "strip", z.ZodTypeAny, {
data: {
[x: string]: any;
[x: number]: any;
};
status: "success";
}, {
data: {
[x: string]: any;
[x: number]: any;
};
status: "success";
}>>, ApiResponse<z.ZodObject<{
status: z.ZodLiteral<"error">;
error: z.ZodObject<{
message: z.ZodString;
}, "strip", z.ZodTypeAny, {
message: string;
}, {
message: string;
}>;
}, "strip", z.ZodTypeAny, {
status: "error";
error: {
message: string;
};
}, {
status: "error";
error: {
message: string;
};
}>>>;
export {};
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.defaultResultHandler = void 0;
var helpers_1 = require("./helpers");
var defaultResultHandler = function (_a) {
var error = _a.error, request = _a.request, response = _a.response, input = _a.input, output = _a.output, logger = _a.logger;
if (!error) {
var result_1 = { status: 'success', data: output };
response.status(200).json(result_1);
return;
}
var statusCode = helpers_1.getStatusCodeFromError(error);
if (statusCode === 500) {
logger.error("Internal server error\n" + error.stack + "\n", {
url: request.url,
payload: input
exports.defaultResultHandler = exports.createResultHandler = void 0;
const zod_1 = require("zod");
const helpers_1 = require("./helpers");
const createResultHandler = (definition) => definition;
exports.createResultHandler = createResultHandler;
exports.defaultResultHandler = exports.createResultHandler({
getPositiveResponse: (output) => helpers_1.createApiResponse(zod_1.z.object({
status: zod_1.z.literal('success'),
data: helpers_1.markOutput(output)
})),
getNegativeResponse: () => helpers_1.createApiResponse(zod_1.z.object({
status: zod_1.z.literal('error'),
error: zod_1.z.object({
message: zod_1.z.string()
})
})),
handler: ({ error, input, output, request, response, logger }) => {
if (!error) {
response.status(200).json({
status: 'success',
data: output
});
return;
}
const statusCode = helpers_1.getStatusCodeFromError(error);
if (statusCode === 500) {
logger.error(`Internal server error\n${error.stack}\n`, {
url: request.url,
payload: input
});
}
response.status(statusCode).json({
status: 'error',
error: { message: helpers_1.getMessageFromError(error) }
});
}
var result = {
status: 'error',
error: { message: helpers_1.getMessageFromError(error) }
};
response.status(statusCode).json(result);
};
exports.defaultResultHandler = defaultResultHandler;
});
//# sourceMappingURL=result-handler.js.map

@@ -8,6 +8,6 @@ import { Express } from 'express';

readonly methods: {
[K in Method]?: Endpoint<any, any, any, any, K> | Endpoint<any, any, any, any, Method>;
[K in Method]?: Endpoint<any, any, any, any, K, any, any> | Endpoint<any, any, any, any, Method, any, any>;
};
constructor(methods: {
[K in Method]?: Endpoint<any, any, any, any, K> | Endpoint<any, any, any, any, Method>;
[K in Method]?: Endpoint<any, any, any, any, K, any, any> | Endpoint<any, any, any, any, Method, any, any>;
});

@@ -14,0 +14,0 @@ }

"use strict";
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
return new (P || (P = Promise))(function (resolve, reject) {
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
step((generator = generator.apply(thisArg, _arguments || [])).next());
});
};
var __generator = (this && this.__generator) || function (thisArg, body) {
var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g;
return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
function verb(n) { return function (v) { return step([n, v]); }; }
function step(op) {
if (f) throw new TypeError("Generator is already executing.");
while (_) try {
if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
if (y = 0, t) op = [op[0] & 2, t.value];
switch (op[0]) {
case 0: case 1: t = op; break;
case 4: _.label++; return { value: op[1], done: false };
case 5: _.label++; y = op[1]; op = [0]; continue;
case 7: op = _.ops.pop(); _.trys.pop(); continue;
default:
if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
if (t[2]) _.ops.pop();
_.trys.pop(); continue;
}
op = body.call(thisArg, _);
} catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
}
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.initRouting = exports.routingCycle = exports.DependsOnMethod = void 0;
var endpoint_1 = require("./endpoint");
var errors_1 = require("./errors");
var DependsOnMethod = /** @class */ (function () {
function DependsOnMethod(methods) {
var _this = this;
const endpoint_1 = require("./endpoint");
const errors_1 = require("./errors");
class DependsOnMethod {
constructor(methods) {
this.methods = methods;
Object.keys(methods).forEach(function (key) {
Object.keys(methods).forEach((key) => {
var _a, _b;
if (key in methods) {
var endpointMethods = ((_a = methods[key]) === null || _a === void 0 ? void 0 : _a.getMethods()) || [];
const endpointMethods = ((_a = methods[key]) === null || _a === void 0 ? void 0 : _a.getMethods()) || [];
if (!endpointMethods.includes(key)) {
throw new errors_1.DependsOnMethodError("The endpoint assigned to the '" + key + "' parameter must have at least this method in its specification.\n" +
throw new errors_1.DependsOnMethodError(`The endpoint assigned to the '${key}' parameter must have at least this method in its specification.\n` +
'This error should prevent mistakes during the development process.\n' +
'Example:\n\n' +
("new " + _this.constructor.name + "({\n") +
(" " + key + ": endpointsFactory.build({\n") +
(" methods: ['" + key + "', ") + ((((_b = methods[key]) === null || _b === void 0 ? void 0 : _b.getMethods()) || [])
.map(function (m) { return "'" + m + "'"; })
`new ${this.constructor.name}({\n` +
` ${key}: endpointsFactory.build({\n` +
` methods: ['${key}', ` + ((((_b = methods[key]) === null || _b === void 0 ? void 0 : _b.getMethods()) || [])
.map((m) => `'${m}'`)
.join(', ')
|| '...') + ']\n' +
(" // or method: '" + key + "'\n") +
` // or method: '${key}'\n` +
' ...\n' +

@@ -68,21 +31,18 @@ ' })\n' +

}
return DependsOnMethod;
}());
}
exports.DependsOnMethod = DependsOnMethod;
var routingCycle = function (_a) {
var routing = _a.routing, cb = _a.cb, parentPath = _a.parentPath, cors = _a.cors;
Object.entries(routing).forEach(function (_a) {
var path = _a[0], element = _a[1];
const routingCycle = ({ routing, cb, parentPath, cors }) => {
Object.entries(routing).forEach(([path, element]) => {
path = path.trim();
if (path.match(/\//)) {
throw new errors_1.RoutingError('Routing elements should not contain \'/\' character.\n' +
("The error caused by " + (parentPath ? "'" + parentPath + "' route that has a '" + path + "'" : "'" + path + "'") + " entry."));
`The error caused by ${parentPath ? `'${parentPath}' route that has a '${path}'` : `'${path}'`} entry.`);
}
var fullPath = "" + (parentPath || '') + (path ? "/" + path : '');
const fullPath = `${parentPath || ''}${path ? `/${path}` : ''}`;
if (element instanceof endpoint_1.AbstractEndpoint) {
var methods = element.getMethods();
const methods = element.getMethods();
if (cors) {
methods.push('options');
}
methods.forEach(function (method) {
methods.forEach((method) => {
cb(element, fullPath, method);

@@ -92,8 +52,7 @@ });

else if (element instanceof DependsOnMethod) {
Object.entries(element.methods).forEach(function (_a) {
var method = _a[0], endpoint = _a[1];
Object.entries(element.methods).forEach(([method, endpoint]) => {
cb(endpoint, fullPath, method);
});
if (cors && Object.keys(element.methods).length > 0) {
var firstEndpoint = Object.values(element.methods)[0];
const firstEndpoint = Object.values(element.methods)[0];
cb(firstEndpoint, fullPath, 'options');

@@ -105,3 +64,3 @@ }

routing: element,
cb: cb, cors: cors,
cb, cors,
parentPath: fullPath

@@ -113,20 +72,11 @@ });

exports.routingCycle = routingCycle;
var initRouting = function (_a) {
var app = _a.app, logger = _a.logger, config = _a.config, routing = _a.routing;
const initRouting = ({ app, logger, config, routing }) => {
exports.routingCycle({
routing: routing,
routing,
cors: config.cors,
cb: function (endpoint, fullPath, method) {
app[method](fullPath, function (request, response) { return __awaiter(void 0, void 0, void 0, function () {
return __generator(this, function (_a) {
switch (_a.label) {
case 0:
logger.info(request.method + ": " + fullPath);
return [4 /*yield*/, endpoint.execute({ request: request, response: response, logger: logger, config: config })];
case 1:
_a.sent();
return [2 /*return*/];
}
});
}); });
cb: (endpoint, fullPath, method) => {
app[method](fullPath, async (request, response) => {
logger.info(`${request.method}: ${fullPath}`);
await endpoint.execute({ request, response, logger, config });
});
}

@@ -133,0 +83,0 @@ });

"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.createServer = exports.attachRouting = void 0;
var express = require("express");
var helpers_1 = require("./helpers");
var logger_1 = require("./logger");
var result_handler_1 = require("./result-handler");
var routing_1 = require("./routing");
var createHttpError = require("http-errors");
const express_1 = __importDefault(require("express"));
const helpers_1 = require("./helpers");
const logger_1 = require("./logger");
const result_handler_1 = require("./result-handler");
const routing_1 = require("./routing");
const http_errors_1 = __importDefault(require("http-errors"));
function attachRouting(config, routing) {
var logger = helpers_1.isLoggerConfig(config.logger) ? logger_1.createLogger(config.logger) : config.logger;
return routing_1.initRouting({ app: config.app, routing: routing, logger: logger, config: config });
const logger = helpers_1.isLoggerConfig(config.logger) ? logger_1.createLogger(config.logger) : config.logger;
return routing_1.initRouting({ app: config.app, routing, logger, config });
}
exports.attachRouting = attachRouting;
function createServer(config, routing) {
var logger = helpers_1.isLoggerConfig(config.logger) ? logger_1.createLogger(config.logger) : config.logger;
var app = express();
var resultHandler = config.resultHandler || result_handler_1.defaultResultHandler;
var jsonParser = config.server.jsonParser || express.json();
var jsonFailureHandler = function (error, request, response, next) {
const logger = helpers_1.isLoggerConfig(config.logger) ? logger_1.createLogger(config.logger) : config.logger;
const app = express_1.default();
const errorHandler = config.errorHandler || result_handler_1.defaultResultHandler;
const jsonParser = config.server.jsonParser || express_1.default.json();
const jsonFailureHandler = (error, request, response, next) => {
if (!error) {
return next();
}
resultHandler({
error: error, request: request, response: response, logger: logger,
errorHandler.handler({
error, request, response, logger,
input: request.body,

@@ -30,6 +33,6 @@ output: null

};
var lastResortHandler = function (request, response) {
resultHandler({
request: request, response: response, logger: logger,
error: createHttpError(404, "Can not " + request.method + " " + request.path),
const lastResortHandler = (request, response) => {
errorHandler.handler({
request, response, logger,
error: http_errors_1.default(404, `Can not ${request.method} ${request.path}`),
input: null,

@@ -40,6 +43,6 @@ output: null

app.use([jsonParser, jsonFailureHandler]);
routing_1.initRouting({ app: app, routing: routing, logger: logger, config: config });
routing_1.initRouting({ app, routing, logger, config });
app.use(lastResortHandler);
return app.listen(config.server.listen, function () {
logger.info("Listening " + config.server.listen);
return app.listen(config.server.listen, () => {
logger.info(`Listening ${config.server.listen}`);
});

@@ -46,0 +49,0 @@ }

{
"name": "express-zod-api",
"version": "1.3.1",
"version": "2.0.0-beta1",
"description": "A Typescript library to help you get an API server up and running with I/O schema validation and custom middlewares in minutes.",

@@ -10,6 +10,7 @@ "license": "MIT",

"build:cleanup": "rm -rf ./dist && rm -f example/example.swagger.yaml && rm -f ./LICENSE",
"build:compile": "tsc",
"build:compile": "tsc --build tsconfig.build.json",
"build:swagger": "ts-node example/generate-open-api-schema.ts > example/example.swagger.yaml",
"build:license": "ts-node tools/generate-license.ts > ./LICENSE",
"test": "yarn test:jest && yarn test:badge",
"test:u": "yarn test:jest -u",
"test:jest": "yarn jest --detectOpenHandles ./tests/unit ./tests/system",

@@ -33,2 +34,3 @@ "test:badge": "yarn make-coverage-badge --output-path ./coverage.svg",

"devDependencies": {
"@tsconfig/node10": "^1.0.8",
"@types/express": "^4.17.11",

@@ -51,2 +53,5 @@ "@types/http-errors": "^1.8.0",

},
"engines": {
"node": ">=10.0.0"
},
"repository": {

@@ -53,0 +58,0 @@ "type": "git",

@@ -39,4 +39,7 @@ # Express Zod API

[Changelog](CHANGELOG.md)
**Important notice**: v2 is currently beta. Some methods and properties might be renamed or changed without backward
compatibility. Please use stable v1 for production.
If you're upgrading from v1 please check out the information in [Changelog](CHANGELOG.md).
# Technologies

@@ -75,3 +78,3 @@

Add the following options to your `tsconfig.json` file in order to make it work as expected:
Add the following option to your `tsconfig.json` file in order to make it work as expected:

@@ -81,4 +84,3 @@ ```json

"compilerOptions": {
"noImplicitAny": true,
"strictNullChecks": true
"strict": true
}

@@ -113,5 +115,5 @@ }

```typescript
import {EndpointsFactory} from 'express-zod-api';
const endpointsFactory = new EndpointsFactory();
import {defaultEndpointsFactory} from './endpoints-factory';
// same as: new EndpointsFactory(defaultResultHandler)
const endpointsFactory = defaultEndpointsFactory;
```

@@ -251,4 +253,8 @@

`ResultHandler` is the [type](https://github.com/RobinTail/express-zod-api/blob/master/src/result-handler.ts) of function that is responsible for transmission of the final response or possible error.
The `defaultResultHandler` sets the HTTP status code and ensures the following type of the response:
`ResultHandler` is the [type](https://github.com/RobinTail/express-zod-api/blob/master/src/result-handler.ts) of
function that is responsible for transmission of the final response or possible error.
`ResultHandlerDefinition` contains this handler and additional methods defining the schema of the positive and
negative responses as well as their MIME types for the further disclosing to consumers and documentation.
Positive schema is the schema of successful response. Negative schema is the one that describes the response in case
of error. The `defaultResultHandler` sets the HTTP status code and ensures the following type of the response:

@@ -267,18 +273,32 @@ ```typescript

You have two options to customize the `ResultHandler`: globally or at the endpoint level:
In order to customize the result handler you need to use `createResultHandler()` first wrapping the response schema in
`createApiResponse()` optionally specifying its mime types, and wrapping the endpoint output schema in `markOutput()`.
Here is an example you can use as a template:
```typescript
import {ConfigType, ResultHandler} from 'express-zod-api';
import {createResultHandler, IOSchema, createApiResponse, markOutput, z} from 'express-zod-api';
const resultHandler: ResultHandler =
({error, input, output, request, response, logger}) => {};
const myResultHandler = createResultHandler({
getPositiveResponse: <OUT extends IOSchema>(output: OUT) => createApiResponse(
z.object({
...,
someProperty: markOutput(output)
}),
['mime/type1', 'mime/type2'] // optional, default: application/json
),
getNegativeResponse: () => createApiResponse(z.object({
error: z.string()
})),
handler: ({error, input, output, request, response, logger}) => {
// your implementation
}
});
```
const config: ConfigType = { resultHandler, ... };
Then you need to use it as an argument for `EndpointsFactory` instance creation:
// or
```typescript
import {EndpointsFactory} from 'express-zod-api';
const endpointsFactory = new EndpointsFactory().setResultHandler(
({error, input, output, request, response, logger}) => {}
);
const endpointsFactory = new EndpointsFactory(myResultHandler);
```

@@ -322,3 +342,3 @@

Thanks to the `DependsOnMethod` class a route may have multiple Endpoints attached depending on different methods.
It can also be the same Endpoint that handle multiple methods as well.
It can also be the same Endpoint that handles multiple methods as well.
```typescript

@@ -350,9 +370,9 @@ import {DependsOnMethod} from 'express-zod-api';

Then use provided helpers to obtain their input and output types:
Then use provided helpers to obtain their input and response types:
```typescript
import {EndpointInput, EndpointOutput} from 'express-zod-api';
import {EndpointInput, EndpointResponse} from 'express-zod-api';
import {MyEndpointType} from '../your/backend';
type MyEndpointInput = EndpointInput<MyEndpointType>;
type MyEndpointOutput = EndpointOutput<MyEndpointType>;
type MyEndpointResponse = EndpointResponse<MyEndpointType>; // unions positive and negative schemas
```

@@ -362,3 +382,4 @@

You can generate the specification of your API the following way and write it to a `.yaml` file:
You can generate the specification of your API the following way and write it to a `.yaml` file,
that can be used as documentation:

@@ -373,3 +394,3 @@ ```typescript

serverUrl: 'http://example.com'
}).builder.getSpecAsYaml();
}).getSpecAsYaml();
```

@@ -376,0 +397,0 @@

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc