Comparing version 3.0.3 to 3.0.4
@@ -115,5 +115,8 @@ "use strict"; | ||
for (const layer of router.stack) { | ||
// Skip the path | ||
if (skipPathPredicate(layer.path)) { | ||
continue; | ||
} | ||
// String array of path parameter keys | ||
const pathParameterKeys = [...layer.path.matchAll(/:(\w+)/g)].map((d) => d[1]); | ||
const methods = layer.methods; | ||
@@ -133,2 +136,3 @@ let pathItem = {}; | ||
layer.stack.map((stack) => { | ||
// try to access the metadata defined within the stack | ||
const keys = Reflect.getMetadataKeys(stack).filter((k) => __1.ALL_METADATA_KEYS.has(k)); | ||
@@ -140,2 +144,3 @@ for (const key of keys) { | ||
const builder = new __1.OperationDocumentBuilder({ ...opDoc, ...opSpecFn() }); | ||
// FIXME: Handle the path definition | ||
// merge? | ||
@@ -153,2 +158,4 @@ if (validationSpecBuffer.body) { | ||
} | ||
// Add default doc first | ||
const undocumentedParams = new Set(pathParameterKeys); | ||
if (validationSpecBuffer.parameters) { | ||
@@ -158,2 +165,3 @@ const shape = validationSpecBuffer.parameters; | ||
const { description } = shape.properties[key]; | ||
undocumentedParams.delete(key); | ||
builder.useParameter('path', key, { | ||
@@ -166,2 +174,12 @@ schema: shape.properties[key], | ||
} | ||
if (undocumentedParams.size > 0) { | ||
for (const key of undocumentedParams) { | ||
builder.useParameter('path', key, { | ||
schema: { | ||
type: 'string', | ||
}, | ||
required: true, | ||
}); | ||
} | ||
} | ||
if (validationSpecBuffer.headers) { | ||
@@ -168,0 +186,0 @@ const shape = validationSpecBuffer.headers; |
@@ -16,3 +16,3 @@ import type { BaseParameterObject, MediaTypeObject, OperationObject, ParameterLocation, SchemaObject, RequestBodyObject, ResponseObject } from 'openapi3-ts/oas31'; | ||
*/ | ||
export declare const extractSchema: (spec: SchemableObject, required?: boolean) => ['zod' | 'ajv' | 'literal', SchemaObject]; | ||
export declare const extractSchema: (spec: SchemableObject, required?: boolean, mode?: 'read' | 'write') => ['zod' | 'ajv' | 'literal', SchemaObject]; | ||
/** | ||
@@ -26,2 +26,7 @@ * The general interface that fits `ajv-ts` which allow us to use | ||
schema?: any; | ||
/** | ||
* The alternative scheme that is used in readonly mode | ||
* useful when automatically generate an API document that emits readonly version | ||
*/ | ||
readonlySchema?: any; | ||
} | ||
@@ -51,2 +56,8 @@ /** | ||
constructor(baseDoc?: OperationObject); | ||
/** | ||
* replace the current document | ||
*/ | ||
from(baseDoc: OperationObject): this; | ||
deprecated(deprecated: boolean): this; | ||
describe(description: string): this; | ||
summary(summary: string): this; | ||
@@ -89,5 +100,9 @@ /** | ||
* Server rejected the request due to invalid user's input | ||
* TODO: Add other additional cases!, so that this method can call repeatedly and aggregates | ||
*/ | ||
onErrorBadRequest(contentOrMessage?: string | MediaTypeObject): this; | ||
onErrorUnauthorized(contentOrMessage?: string | MediaTypeObject): this; | ||
onErrorForbidden(contentOrMessage?: string | MediaTypeObject): this; | ||
onErrorNotFound(contentOrMessage?: string | MediaTypeObject): this; | ||
onErrorInternal(contentOrMessage?: string | MediaTypeObject): this; | ||
onErrorResponse(status: number, defaultMessage: string, contentOrMessage?: string | MediaTypeObject): this; | ||
onResponse(status: number, doc: ResponseObject, content?: MediaTypeObject): this; | ||
@@ -94,0 +109,0 @@ /** |
@@ -28,3 +28,3 @@ "use strict"; | ||
*/ | ||
const extractSchema = (spec, required = false) => { | ||
const extractSchema = (spec, required = false, mode = 'read') => { | ||
if (z2js && isZod(spec)) { | ||
@@ -39,2 +39,5 @@ const forDocuments = z2js(spec, { | ||
} | ||
if (mode === 'read' && spec.readonlySchema) { | ||
return ['literal', spec.readonlySchema]; | ||
} | ||
if (spec.schema) { | ||
@@ -44,2 +47,4 @@ return ['literal', spec.schema]; | ||
if (required) { | ||
// Given | ||
__1.Loggy.error('Failed to extract schema from', JSON.stringify(spec)); | ||
throw __1.KobpError.fromServer(__1.ServerErrorCode.notImplemented, 'You are using invalid schema provider. If you are using Zod, please install zod-to-json-schema (https://www.npmjs.com/package/zod-to-json-schema). If your are using other interface please make sure it has `schema` property that provides OpenAPI3.1 Schema compatible object!'); | ||
@@ -56,2 +61,17 @@ } | ||
} | ||
/** | ||
* replace the current document | ||
*/ | ||
from(baseDoc) { | ||
this.doc = { ...(baseDoc || {}) }; | ||
return this; | ||
} | ||
deprecated(deprecated) { | ||
this.doc.deprecated = deprecated; | ||
return this; | ||
} | ||
describe(description) { | ||
this.doc.description = description; | ||
return this; | ||
} | ||
summary(summary) { | ||
@@ -99,3 +119,7 @@ this.doc.summary = summary; | ||
useParameter(location, name, doc) { | ||
const params = this.doc.parameters || []; | ||
const params = (this.doc.parameters || []); | ||
// safe push | ||
if (params.findIndex((p) => p.name === name && p.in === location) >= 0) { | ||
return this; | ||
} | ||
params.push({ ...doc, in: location, name }); | ||
@@ -139,7 +163,21 @@ this.doc.parameters = params; | ||
* Server rejected the request due to invalid user's input | ||
* TODO: Add other additional cases!, so that this method can call repeatedly and aggregates | ||
*/ | ||
onErrorBadRequest(contentOrMessage) { | ||
return this.onErrorResponse(400, 'Bad request', contentOrMessage); | ||
} | ||
onErrorUnauthorized(contentOrMessage) { | ||
return this.onErrorResponse(401, 'Unauthorized', contentOrMessage); | ||
} | ||
onErrorForbidden(contentOrMessage) { | ||
return this.onErrorResponse(403, 'Forbidden', contentOrMessage); | ||
} | ||
onErrorNotFound(contentOrMessage) { | ||
return this.onErrorResponse(404, 'Resource not found', contentOrMessage); | ||
} | ||
onErrorInternal(contentOrMessage) { | ||
return this.onErrorResponse(500, 'Internal server error', contentOrMessage); | ||
} | ||
onErrorResponse(status, defaultMessage, contentOrMessage) { | ||
if (typeof contentOrMessage === 'string') { | ||
return this.onResponse(400, { description: 'Bad request' }, { | ||
return this.onResponse(status, { description: defaultMessage }, { | ||
schema: { | ||
@@ -156,3 +194,3 @@ type: 'object', | ||
} | ||
return this.onResponse(400, { description: 'Bad Request' }, contentOrMessage); | ||
return this.onResponse(status, { description: defaultMessage }, contentOrMessage); | ||
} | ||
@@ -159,0 +197,0 @@ onResponse(status, doc, content) { |
@@ -112,5 +112,8 @@ import 'reflect-metadata'; | ||
for (const layer of router.stack) { | ||
// Skip the path | ||
if (skipPathPredicate(layer.path)) { | ||
continue; | ||
} | ||
// String array of path parameter keys | ||
const pathParameterKeys = [...layer.path.matchAll(/:(\w+)/g)].map((d) => d[1]); | ||
const methods = layer.methods; | ||
@@ -130,2 +133,3 @@ let pathItem = {}; | ||
layer.stack.map((stack) => { | ||
// try to access the metadata defined within the stack | ||
const keys = Reflect.getMetadataKeys(stack).filter((k) => ALL_METADATA_KEYS.has(k)); | ||
@@ -137,2 +141,3 @@ for (const key of keys) { | ||
const builder = new OperationDocumentBuilder({ ...opDoc, ...opSpecFn() }); | ||
// FIXME: Handle the path definition | ||
// merge? | ||
@@ -150,2 +155,4 @@ if (validationSpecBuffer.body) { | ||
} | ||
// Add default doc first | ||
const undocumentedParams = new Set(pathParameterKeys); | ||
if (validationSpecBuffer.parameters) { | ||
@@ -155,2 +162,3 @@ const shape = validationSpecBuffer.parameters; | ||
const { description } = shape.properties[key]; | ||
undocumentedParams.delete(key); | ||
builder.useParameter('path', key, { | ||
@@ -163,2 +171,12 @@ schema: shape.properties[key], | ||
} | ||
if (undocumentedParams.size > 0) { | ||
for (const key of undocumentedParams) { | ||
builder.useParameter('path', key, { | ||
schema: { | ||
type: 'string', | ||
}, | ||
required: true, | ||
}); | ||
} | ||
} | ||
if (validationSpecBuffer.headers) { | ||
@@ -165,0 +183,0 @@ const shape = validationSpecBuffer.headers; |
@@ -16,3 +16,3 @@ import type { BaseParameterObject, MediaTypeObject, OperationObject, ParameterLocation, SchemaObject, RequestBodyObject, ResponseObject } from 'openapi3-ts/oas31'; | ||
*/ | ||
export declare const extractSchema: (spec: SchemableObject, required?: boolean) => ['zod' | 'ajv' | 'literal', SchemaObject]; | ||
export declare const extractSchema: (spec: SchemableObject, required?: boolean, mode?: 'read' | 'write') => ['zod' | 'ajv' | 'literal', SchemaObject]; | ||
/** | ||
@@ -26,2 +26,7 @@ * The general interface that fits `ajv-ts` which allow us to use | ||
schema?: any; | ||
/** | ||
* The alternative scheme that is used in readonly mode | ||
* useful when automatically generate an API document that emits readonly version | ||
*/ | ||
readonlySchema?: any; | ||
} | ||
@@ -51,2 +56,8 @@ /** | ||
constructor(baseDoc?: OperationObject); | ||
/** | ||
* replace the current document | ||
*/ | ||
from(baseDoc: OperationObject): this; | ||
deprecated(deprecated: boolean): this; | ||
describe(description: string): this; | ||
summary(summary: string): this; | ||
@@ -89,5 +100,9 @@ /** | ||
* Server rejected the request due to invalid user's input | ||
* TODO: Add other additional cases!, so that this method can call repeatedly and aggregates | ||
*/ | ||
onErrorBadRequest(contentOrMessage?: string | MediaTypeObject): this; | ||
onErrorUnauthorized(contentOrMessage?: string | MediaTypeObject): this; | ||
onErrorForbidden(contentOrMessage?: string | MediaTypeObject): this; | ||
onErrorNotFound(contentOrMessage?: string | MediaTypeObject): this; | ||
onErrorInternal(contentOrMessage?: string | MediaTypeObject): this; | ||
onErrorResponse(status: number, defaultMessage: string, contentOrMessage?: string | MediaTypeObject): this; | ||
onResponse(status: number, doc: ResponseObject, content?: MediaTypeObject): this; | ||
@@ -94,0 +109,0 @@ /** |
@@ -1,2 +0,2 @@ | ||
import { withDocument, KobpError, ServerErrorCode } from '..'; | ||
import { withDocument, KobpError, ServerErrorCode, Loggy } from '..'; | ||
export const METADATA_KEYS = { | ||
@@ -25,3 +25,3 @@ // compiled documents | ||
*/ | ||
export const extractSchema = (spec, required = false) => { | ||
export const extractSchema = (spec, required = false, mode = 'read') => { | ||
if (z2js && isZod(spec)) { | ||
@@ -36,2 +36,5 @@ const forDocuments = z2js(spec, { | ||
} | ||
if (mode === 'read' && spec.readonlySchema) { | ||
return ['literal', spec.readonlySchema]; | ||
} | ||
if (spec.schema) { | ||
@@ -41,2 +44,4 @@ return ['literal', spec.schema]; | ||
if (required) { | ||
// Given | ||
Loggy.error('Failed to extract schema from', JSON.stringify(spec)); | ||
throw KobpError.fromServer(ServerErrorCode.notImplemented, 'You are using invalid schema provider. If you are using Zod, please install zod-to-json-schema (https://www.npmjs.com/package/zod-to-json-schema). If your are using other interface please make sure it has `schema` property that provides OpenAPI3.1 Schema compatible object!'); | ||
@@ -52,2 +57,17 @@ } | ||
} | ||
/** | ||
* replace the current document | ||
*/ | ||
from(baseDoc) { | ||
this.doc = { ...(baseDoc || {}) }; | ||
return this; | ||
} | ||
deprecated(deprecated) { | ||
this.doc.deprecated = deprecated; | ||
return this; | ||
} | ||
describe(description) { | ||
this.doc.description = description; | ||
return this; | ||
} | ||
summary(summary) { | ||
@@ -95,3 +115,7 @@ this.doc.summary = summary; | ||
useParameter(location, name, doc) { | ||
const params = this.doc.parameters || []; | ||
const params = (this.doc.parameters || []); | ||
// safe push | ||
if (params.findIndex((p) => p.name === name && p.in === location) >= 0) { | ||
return this; | ||
} | ||
params.push({ ...doc, in: location, name }); | ||
@@ -135,7 +159,21 @@ this.doc.parameters = params; | ||
* Server rejected the request due to invalid user's input | ||
* TODO: Add other additional cases!, so that this method can call repeatedly and aggregates | ||
*/ | ||
onErrorBadRequest(contentOrMessage) { | ||
return this.onErrorResponse(400, 'Bad request', contentOrMessage); | ||
} | ||
onErrorUnauthorized(contentOrMessage) { | ||
return this.onErrorResponse(401, 'Unauthorized', contentOrMessage); | ||
} | ||
onErrorForbidden(contentOrMessage) { | ||
return this.onErrorResponse(403, 'Forbidden', contentOrMessage); | ||
} | ||
onErrorNotFound(contentOrMessage) { | ||
return this.onErrorResponse(404, 'Resource not found', contentOrMessage); | ||
} | ||
onErrorInternal(contentOrMessage) { | ||
return this.onErrorResponse(500, 'Internal server error', contentOrMessage); | ||
} | ||
onErrorResponse(status, defaultMessage, contentOrMessage) { | ||
if (typeof contentOrMessage === 'string') { | ||
return this.onResponse(400, { description: 'Bad request' }, { | ||
return this.onResponse(status, { description: defaultMessage }, { | ||
schema: { | ||
@@ -152,3 +190,3 @@ type: 'object', | ||
} | ||
return this.onResponse(400, { description: 'Bad Request' }, contentOrMessage); | ||
return this.onResponse(status, { description: defaultMessage }, contentOrMessage); | ||
} | ||
@@ -155,0 +193,0 @@ onResponse(status, doc, content) { |
{ | ||
"name": "kobp", | ||
"version": "3.0.3", | ||
"version": "3.0.4", | ||
"description": "Koa Boilerplate with MikroORM", | ||
@@ -5,0 +5,0 @@ "main": "lib/cjs/src/index.js", |
@@ -211,5 +211,8 @@ import 'reflect-metadata' | ||
for (const layer of router.stack) { | ||
// Skip the path | ||
if (skipPathPredicate(layer.path)) { | ||
continue | ||
} | ||
// String array of path parameter keys | ||
const pathParameterKeys = [...layer.path.matchAll(/:(\w+)/g)].map((d) => d[1]) | ||
const methods = layer.methods | ||
@@ -234,2 +237,3 @@ let pathItem: PathItemObject = {} | ||
layer.stack.map((stack) => { | ||
// try to access the metadata defined within the stack | ||
const keys = Reflect.getMetadataKeys(stack).filter((k) => ALL_METADATA_KEYS.has(k)) | ||
@@ -241,2 +245,3 @@ for (const key of keys) { | ||
const builder = new OperationDocumentBuilder({ ...opDoc, ...opSpecFn() }) | ||
// FIXME: Handle the path definition | ||
// merge? | ||
@@ -254,2 +259,4 @@ if (validationSpecBuffer.body) { | ||
} | ||
// Add default doc first | ||
const undocumentedParams = new Set<string>(pathParameterKeys) | ||
if (validationSpecBuffer.parameters) { | ||
@@ -259,2 +266,3 @@ const shape = validationSpecBuffer.parameters | ||
const { description } = shape.properties[key] | ||
undocumentedParams.delete(key) | ||
builder.useParameter('path', key, { | ||
@@ -267,2 +275,12 @@ schema: shape.properties[key], | ||
} | ||
if (undocumentedParams.size > 0) { | ||
for (const key of undocumentedParams) { | ||
builder.useParameter('path', key, { | ||
schema: { | ||
type: 'string', | ||
}, | ||
required: true, | ||
}) | ||
} | ||
} | ||
if (validationSpecBuffer.headers) { | ||
@@ -269,0 +287,0 @@ const shape = validationSpecBuffer.headers |
@@ -9,5 +9,6 @@ import type { | ||
ResponseObject, | ||
ParameterObject, | ||
} from 'openapi3-ts/oas31' | ||
import { Middleware, withDocument, KobpError, ServerErrorCode } from '..' | ||
import { Middleware, withDocument, KobpError, ServerErrorCode, Loggy } from '..' | ||
@@ -43,2 +44,3 @@ export const METADATA_KEYS = { | ||
required: boolean = false, | ||
mode: 'read' | 'write' = 'read', | ||
): ['zod' | 'ajv' | 'literal', SchemaObject] => { | ||
@@ -54,2 +56,5 @@ if (z2js && isZod(spec)) { | ||
} | ||
if (mode === 'read' && spec.readonlySchema) { | ||
return ['literal', spec.readonlySchema] | ||
} | ||
if (spec.schema) { | ||
@@ -59,2 +64,4 @@ return ['literal', spec.schema] | ||
if (required) { | ||
// Given | ||
Loggy.error('Failed to extract schema from', JSON.stringify(spec)) | ||
throw KobpError.fromServer( | ||
@@ -76,2 +83,7 @@ ServerErrorCode.notImplemented, | ||
schema?: any | ||
/** | ||
* The alternative scheme that is used in readonly mode | ||
* useful when automatically generate an API document that emits readonly version | ||
*/ | ||
readonlySchema?: any | ||
} | ||
@@ -108,2 +120,20 @@ | ||
/** | ||
* replace the current document | ||
*/ | ||
from(baseDoc: OperationObject): this { | ||
this.doc = { ...(baseDoc || {}) } | ||
return this | ||
} | ||
deprecated(deprecated: boolean): this { | ||
this.doc.deprecated = deprecated | ||
return this | ||
} | ||
describe(description: string): this { | ||
this.doc.description = description | ||
return this | ||
} | ||
summary(summary: string): this { | ||
@@ -169,3 +199,7 @@ this.doc.summary = summary | ||
useParameter(location: ParameterLocation, name: string, doc: BaseParameterObject): this { | ||
const params = this.doc.parameters || [] | ||
const params = (this.doc.parameters || []) as ParameterObject[] | ||
// safe push | ||
if (params.findIndex((p) => p.name === name && p.in === location) >= 0) { | ||
return this | ||
} | ||
params.push({ ...doc, in: location, name }) | ||
@@ -218,9 +252,28 @@ this.doc.parameters = params | ||
* Server rejected the request due to invalid user's input | ||
* TODO: Add other additional cases!, so that this method can call repeatedly and aggregates | ||
*/ | ||
onErrorBadRequest(contentOrMessage?: string | MediaTypeObject): this { | ||
return this.onErrorResponse(400, 'Bad request', contentOrMessage) | ||
} | ||
onErrorUnauthorized(contentOrMessage?: string | MediaTypeObject): this { | ||
return this.onErrorResponse(401, 'Unauthorized', contentOrMessage) | ||
} | ||
onErrorForbidden(contentOrMessage?: string | MediaTypeObject): this { | ||
return this.onErrorResponse(403, 'Forbidden', contentOrMessage) | ||
} | ||
onErrorNotFound(contentOrMessage?: string | MediaTypeObject): this { | ||
return this.onErrorResponse(404, 'Resource not found', contentOrMessage) | ||
} | ||
onErrorInternal(contentOrMessage?: string | MediaTypeObject): this { | ||
return this.onErrorResponse(500, 'Internal server error', contentOrMessage) | ||
} | ||
onErrorResponse(status: number, defaultMessage: string, contentOrMessage?: string | MediaTypeObject): this { | ||
if (typeof contentOrMessage === 'string') { | ||
return this.onResponse( | ||
400, | ||
{ description: 'Bad request' }, | ||
status, | ||
{ description: defaultMessage }, | ||
{ | ||
@@ -239,3 +292,3 @@ schema: { | ||
} | ||
return this.onResponse(400, { description: 'Bad Request' }, contentOrMessage) | ||
return this.onResponse(status, { description: defaultMessage }, contentOrMessage) | ||
} | ||
@@ -242,0 +295,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
390653
5969