You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
importflattenfrom"lodash/flatten";importmergefrom"lodash/merge";import{Model}from"mongoose";importm2sfrom"mongoose-to-swagger";import{FernsRouterOptions}from"./api";import{logger}from"./logger";constnoop=(_a,_b,next)=>next();constm2sOptions={props: ["readOnly","required","enum","default"],};constapiErrorContent={"application/json": {schema: {type: "object",properties: {title: {type: "string",description: "The error message",},status: {type: "number",description:
"The HTTP status code applicable to this problem, expressed as a string value.",},id: {type: "string",description: "A unique identifier for this particular occurrence of the problem.",},links: {type: "object",properties: {about: {type: "string",description:
"A link that leads to further details about this particular occurrence of the problem. When derefenced, this URI SHOULD return a human-readable description of the error.",},type: {type: "string",description:
"A link that identifies the type of error that this particular error is an instance of. This URI SHOULD be dereferencable to a human-readable explanation of the general error.",},},},code: {type: "string",description: "An application-specific error code, expressed as a string value.",},detail: {type: "string",description:
"A human-readable explanation specific to this occurrence of the problem. Like title, this field’s value can be localized.",},source: {type: "object",properties: {pointer: {type: "string",description:
'A JSON Pointer [RFC6901] to the associated entity in the request document [e.g. "/data" for a primary data object, or "/data/attributes/title" for a specific attribute].',},parameter: {type: "string",description: "A string indicating which URI query parameter caused the error.",},header: {type: "string",description:
"A string indicating the name of a single request header which caused the error.",},},},meta: {type: "object",description: "A meta object containing non-standard meta-information about the error.",},},},},};// Default error responsesconstdefaultErrorResponses={400: {description: "Bad request",content: apiErrorContent,},401: {description: "The user must be authenticated",},403: {description: "The user is not allowed to perform this action on this document",content: apiErrorContent,},404: {description: "Document not found",content: apiErrorContent,},405: {description: "The user is not allowed to perform this action on any document",content: apiErrorContent,},};exportfunctiongetOpenApiMiddleware<T>(model: Model<T>,options: Partial<FernsRouterOptions<T>>){if(!options.openApi?.path){// Just log this once rather than for each middleware.logger.debug("No options.openApi provided, skipping *OpenApiMiddleware");returnnoop;}if(options.permissions?.read?.length===0){returnnoop;}constmodelSwagger=m2s(model,{props: ["required","enum"]});returnoptions.openApi.path(merge({tags: [model.collection.collectionName],responses: {200: {description: "Successful read",content: {"application/json": {schema: {type: "object",required: [...(modelSwagger.required??[]),"_id","created","updated"],properties: modelSwagger.properties,},},},},
...defaultErrorResponses,},},options.openApiOverwrite?.get??{}));}exportfunctionlistOpenApiMiddleware<T>(model: Model<T>,options: Partial<FernsRouterOptions<T>>){if(!options.openApi?.path){returnnoop;}if(options.permissions?.list?.length===0){returnnoop;}constmodelSwagger=m2s(model,m2sOptions);// TODO: handle permissions// TODO: handle populate// TODO: handle whitelist/transform// Convert fernsRouter queryFields into OpenAPI parametersconstdefaultQueryParams=[{name: "_id",in: "query",schema: {type: "object",properties: {$in: {type: "array",items: {type: "string",},},},},},];constmodelQueryParams=flatten(options.queryFields// Remove _id from queryFields, we handle that above.?.filter((field)=>field!=="_id").map((field)=>{constparams: {name: string;in: "query";schema: any}[]=[];// Check for datetime/number to support gt/gte/lt/lteparams.push({name: field,in: "query",schema: modelSwagger.properties[field],});if(modelSwagger.properties[field]?.type==="number"||modelSwagger.properties[field]?.format==="date-time"){params.push({name: field,in: "query",schema: {type: "object",properties: {$gte: modelSwagger.properties[field],$gt: modelSwagger.properties[field],$lte: modelSwagger.properties[field],$lt: modelSwagger.properties[field],},},});}returnparams;}));returnoptions.openApi.path(merge({tags: [model.collection.collectionName],parameters: [
...defaultQueryParams,
...(modelQueryParams??[]),// pagination{name: "page",in: "query",schema: {type: "number",},},{name: "limit",in: "query",schema: {type: "number",},},// special param for period, like "1d"{name: "period",in: "query",schema: {type: "string",},},],responses: {200: {description: "Successful list",content: {"application/json": {schema: {type: "object",properties: {data: {type: "array",items: {type: "object",required: [...(modelSwagger.required??[]),"_id","created","updated"],properties: modelSwagger.properties,},},more: {type: "boolean",},page: {type: "number",},limit: {type: "number",},total: {type: "number",},},},},},},
...defaultErrorResponses,},},options.openApiOverwrite?.list??{}));}exportfunctioncreateOpenApiMiddleware<T>(model: Model<T>,options: Partial<FernsRouterOptions<T>>){if(!options.openApi?.path){returnnoop;}if(options.permissions?.create?.length===0){returnnoop;}constmodelSwagger=m2s(model,m2sOptions);returnoptions.openApi.path(merge({tags: [model.collection.collectionName],requestBody: {required: true,content: {"application/json": {schema: {type: "object",properties: modelSwagger.properties,},},},},responses: {201: {description: "Successful create",content: {"application/json": {schema: {type: "object",required: [...(modelSwagger.required??[]),"_id","created","updated"],properties: modelSwagger.properties,},},},},
...defaultErrorResponses,},},options.openApiOverwrite?.create??{}));}exportfunctionpatchOpenApiMiddleware<T>(model: Model<T>,options: Partial<FernsRouterOptions<T>>){if(!options.openApi?.path){returnnoop;}if(options.permissions?.update?.length===0){returnnoop;}constmodelSwagger=m2s(model,m2sOptions);returnoptions.openApi.path(merge({tags: [model.collection.collectionName],requestBody: {required: true,content: {"application/json": {schema: {type: "object",properties: modelSwagger.properties,},},},},responses: {200: {description: "Successful update",content: {"application/json": {schema: {type: "object",required: [...(modelSwagger.required??[]),"_id","created","updated"],properties: modelSwagger.properties,},},},},
...defaultErrorResponses,},},options.openApiOverwrite?.update??{}));}exportfunctiondeleteOpenApiMiddleware<T>(model: Model<T>,options: Partial<FernsRouterOptions<T>>){if(!options.openApi?.path){returnnoop;}if(options.permissions?.delete?.length===0){returnnoop;}returnoptions.openApi.path(merge({tags: [model.collection.collectionName],responses: {204: {description: "Successful delete",},
...defaultErrorResponses,},},options.openApiOverwrite?.delete??{}));}
c9fd0b46a7cfb23ee1217c6c60fdf4a9c916f32b
The text was updated successfully, but these errors were encountered:
handle whitelist/transform
ferns-api/src/openApi.ts
Line 159 in ac5250d
c9fd0b46a7cfb23ee1217c6c60fdf4a9c916f32b
The text was updated successfully, but these errors were encountered: