giddyinc / mongoose-to-swagger Goto Github PK
View Code? Open in Web Editor NEWConversion library for transforming Mongoose schema objects into Swagger schema definitions.
License: MIT License
Conversion library for transforming Mongoose schema objects into Swagger schema definitions.
License: MIT License
Hi. I found the bug when nested fields in the schema are not omitted, for example:
const User = mongoose.model("User", { name: { type: String }, phone: { type: String }, email: { title: "email", type: String, lowercase: true, required: false }, address: { default: {}, required: true, type: new mongoose.Schema({ country: { title: "Country", type: String } }) } });
const swaggerSchema = m2s(User, { props: ["title"], omitFields: ["address.country"] }); console.log(swaggerSchema);
So the swaggerSchema.address.country
not omitted.
The bug in this line
It happens, because the country
field is not exists in the root schema, country
field has another path: schema.tree.address.type.tree.country
TypeError: Cannot read properties of undefined (reading 'tree')
at getFieldsFromMongooseSchema (/Users/****/Projects/*****/node_modules/mongoose-to-swagger/dist/index.js:138:25)
"mongoose-to-swagger": "1.4.0",
"swagger-jsdoc": "^6.2.7",
"swagger-ui-express": "^4.6.0",
Sorry for my ignorance, but how can I exclude a specific field from being exported? In my case, I want exclude the "_id" field because it's automatically generated. Is it supported?
Hi there,
Just found a bug. For instance if having a schema like this :
{
address: {
type: { type: String },
postalCode: String
}
}
Your lib outputs :
{
address: {
type: String
}
}
All properties are lost.
I fixed it by modifying 2 places :
mongoose-to-swagger/lib/index.ts
Line 56 in 82808a4
if (type.type != null) {
if (type.type != null && !type.type?.type) {
mongoose-to-swagger/lib/index.ts
Line 142 in 82808a4
const subSchema = value.type ? value.type : value;
const subSchema = value.type && !value.type?.type ? value.type : value;
I can open a PR if you want.
Cheers
Hi @blugavere ,
I have a part of the schema of the model of this type, but the problem library correctly deciphers the "actions" part, he simply sees it as an array of objects,
in reality it is an array of enumerative strings.
ex:
{
...
action: ["create","delete",...]
...
}
Schema model:
scopes: [
{
scope: { type: String, enum: scopes },
actions: [{ type: String, enum: actions }]
}
]
Could something be done?
Hi there,
By default, description, enum, and required fields are extracted from the mongoose schema definitions and placed into the correspoding swagger properties definitions.
The problem I encountered is that "require" is used instead of "required" in the models' property of the project I am working on. And the result I get when I use props: ["require"]
is;
{
title: 'User',
properties: {
active: { type: 'boolean', require: false },
firstName: { type: 'string', require: false },
lastName: { type: 'string', require: false },
...
The result I am trying to get is;
{
title: 'User',
require: [ 'username', 'email', 'password', 'language' ],
properties:
...
Is there a way to get this result?
Thank you.
so for whatever reason i cannot run m2s inside a next.js route.
"next": "^13.0.5",
"react": "^18.2.0",
"typescript": "latest",
when i run m2s from a command (schema.ts) with ts-node-dev with a tsconfig with module"commonjs" everything works fine.
"target": "es2017",
"module": "CommonJS",
but if i try to run the same code from inside a next.js .tsx file it crashes. i can get it to work if i do m2s(new Model()) instead of m2s(Model) but then it mangles certain things like Scehma.Types.ObjectIds.
my next.js tsconfig is set to:
"target": "es5",
"module": "esnext"
Is there any way to make m2s work in a .tsx file (NextJs "page")?
as a workaround for now i have a commands/ folder which has a schema.ts file which i run with ts-node-dev to create the schemas and write them to .json files.
i then load those .json files for use with react-jsonschema-form and swagger-jsdoc. this is really nice cuz i can build my schema definitions with m2s and load them into swagger-jsdoc and use @Swagger comments to markup my api routes.
the only downside is every time i change the model i have to re-run schema.ts instead of being able to build the schema dynamically for react-jsonschema-form. but being able to run m2s inside a tsx file would change that and make the framework more developer friendly.
Problem occurs when setting Schema option "typeKey" with non "type" value. Seems that "type" is hardcoded in m2s for obtaining SchemaTypes.
Probably would be better to use schema.options.typeKey reference instead of hardcoded "type".
Hi @blugavere ,
It would be possible to add if user wants the possibility of being able to compactly declare a property if it has no other elements than just the type.
For example:
"key": {
"type": "string"
},
"expiration": {
"type": "string",
"format": "date-time"
},
"active": {
"type": "boolean"
}
Could become:
"key": "string",
"expiration": {
"type": "string",
"format": "date-time"
},
"active": "boolean"
It looks like the algorithm can't differentiate a field named description from the attribute description.
I have a model like this:
//... more properties before here
date: { type: Date, default: Date.now },
servicesRendered: [{
_id: false,
Service: { type: mongoose.Schema.Types.ObjectId, ref: 'Service' },
description: String,
quantity: Number,
price: Number
}],
paymentTerms: String,
//more properties after...
the property "description" is not the description of the model but a property with type String.
When converting it to swagger it generates as follows:
"date": {
"type": "string",
"format": "date-time"
},
"servicesRendered": {
"type": "array",
"items": {
"type": "object",
"description": function String() { [native code] },
"properties": {
"Service": {
"type": "string"
},
"description": {
"type": "string"
},
"quantity": {
"type": "number"
},
"price": {
"type": "number"
}
},
"required": []
}
},
"paymentTerms": {
"type": "string"
},
As you can see, it generates a description "description": function String() { [native code] },
and if failed to load the Swagger UI.
The mongoose-to-swagger plugin fails when using the minimal example provided by the author with the error RangeError: Maximum call stack size exceeded
.
System
Window 10
node v13.5.0
yarn 1.21.1
Test File
// generate_swager.js
const mongoose = require('mongoose');
const m2s = require('mongoose-to-swagger');
const Cat = mongoose.model('Cat', { name: String });
const swaggerSchema = m2s(Cat);
console.log(swaggerSchema);
Steps to Recreate
PS C:\> yarn init mongoose-to-swagger-test -y
PS C:\> cd .\mongoose-to-swagger-test
PS C:\mongoose-to-swagger-test> yarn add mongoose mongoose-to-swagger
PS C:\mongoose-to-swagger-test> node generate_swagger.js
PS C:\mongoose-to-swagger-test> node .\generate_swagger.js
C:\mongoose-to-swagger-test\node_modules\mongoose-to-swagger\dist\index.js:113
const getFieldsFromMongooseSchema = (schema, options) => {
^
RangeError: Maximum call stack size exceeded
at getFieldsFromMongooseSchema (C:\mongoose-to-swagger-test\node_modules\mongoose-to-swagger\dist\index.js:113:37)
at mapSchemaTypeToFieldSchema (C:\mongoose-to-swagger-test\node_modules\mongoose-to-swagger\dist\index.js:98:22)
at getFieldsFromMongooseSchema (C:\mongoose-to-swagger-test\node_modules\mongoose-to-swagger\dist\index.js:121:23)
at mapSchemaTypeToFieldSchema (C:\mongoose-to-swagger-test\node_modules\mongoose-to-swagger\dist\index.js:98:22)
at getFieldsFromMongooseSchema (C:\mongoose-to-swagger-test\node_modules\mongoose-to-swagger\dist\index.js:121:23)
at mapSchemaTypeToFieldSchema (C:\mongoose-to-swagger-test\node_modules\mongoose-to-swagger\dist\index.js:98:22)
at getFieldsFromMongooseSchema (C:\mongoose-to-swagger-test\node_modules\mongoose-to-swagger\dist\index.js:121:23)
at mapSchemaTypeToFieldSchema (C:\mongoose-to-swagger-test\node_modules\mongoose-to-swagger\dist\index.js:98:22)
at getFieldsFromMongooseSchema (C:\mongoose-to-swagger-test\node_modules\mongoose-to-swagger\dist\index.js:121:23)
at mapSchemaTypeToFieldSchema (C:\mongoose-to-swagger-test\node_modules\mongoose-to-swagger\dist\index.js:98:22)
at getFieldsFromMongooseSchema (C:\mongoose-to-swagger-test\node_modules\mongoose-to-swagger\dist\index.js:121:23)
at mapSchemaTypeToFieldSchema (C:\mongoose-to-swagger-test\node_modules\mongoose-to-swagger\dist\index.js:98:22)
at getFieldsFromMongooseSchema (C:\mongoose-to-swagger-test\node_modules\mongoose-to-swagger\dist\index.js:121:23)
at mapSchemaTypeToFieldSchema (C:\mongoose-to-swagger-test\node_modules\mongoose-to-swagger\dist\index.js:98:22)
at getFieldsFromMongooseSchema (C:\mongoose-to-swagger-test\node_modules\mongoose-to-swagger\dist\index.js:121:23)
at mapSchemaTypeToFieldSchema (C:\mongoose-to-swagger-test\node_modules\mongoose-to-swagger\dist\index.js:98:22)
With [email protected]
the type.instance
property is not defined. There is a type.schemaName
defined with Mixed
value though.
I have a schema that uses "id" (not "_id") as a property in a nested object.
Hi! ๐
Firstly, thanks for your work on this project! ๐
Today I used patch-package to patch [email protected]
for the project I'm working on.
Here is the diff that solved my problem:
diff --git a/node_modules/mongoose-to-swagger/dist/index.js b/node_modules/mongoose-to-swagger/dist/index.js
index 453b96a..2b804f6 100644
--- a/node_modules/mongoose-to-swagger/dist/index.js
+++ b/node_modules/mongoose-to-swagger/dist/index.js
@@ -88,6 +88,9 @@ const defaultSupportedMetaProps = [
const mapSchemaTypeToFieldSchema = ({ key = null, value, props, omitFields }) => {
const swaggerType = mapMongooseTypeToSwaggerType(value);
const meta = {};
+
+
+
for (const metaProp of props) {
if (value && value[metaProp] != null) {
meta[metaProp] = value[metaProp];
@@ -100,8 +103,18 @@ const mapSchemaTypeToFieldSchema = ({ key = null, value, props, omitFields }) =>
const arraySchema = Array.isArray(value) ? value[0] : value.type[0];
const items = mapSchemaTypeToFieldSchema({ value: arraySchema || {}, props, omitFields });
meta.items = items;
+
+ if(value.ref !== undefined){
+ meta.items.$ref= `#/components/schemas/${value.ref}`
+
+ delete meta.items.type
+ }
}
else if (swaggerType === 'object') {
+ if(value.ref !== undefined){
+ meta.$ref= `#/components/schemas/${value.ref}`
+ }
+
let fields = [];
if (value && value.constructor && value.constructor.name === 'Schema') {
fields = getFieldsFromMongooseSchema(value, { props, omitFields });
@@ -123,10 +136,21 @@ const mapSchemaTypeToFieldSchema = ({ key = null, value, props, omitFields }) =>
meta.properties = properties;
}
else if (swaggerType === 'map') {
+ if(value.ref !== undefined){
+ meta.$ref= `#/components/schemas/${value.ref}`
+ }
+
const subSchema = mapSchemaTypeToFieldSchema({ value: value.of || {}, props, omitFields });
meta.type = 'object';
meta.additionalProperties = subSchema;
}
+ else{
+ if(value.ref !== undefined){
+ meta.$ref= `#/components/schemas/${value.ref}`
+
+ delete meta.type
+ }
+ }
const result = Object.assign({ type: swaggerType }, meta);
if (key) {
result.field = key;
This issue body was partially generated by patch-package.
const userSchema = mongoose.Schema({ movies_ids: Array })
When specifying the field as "Array", I get this error:
const arraySchema = Array.isArray(value) ? value[0] : value.type[0];
^
TypeError: Cannot read properties of undefined (reading '0')
But if you specify so, then everything works
const userSchema = mongoose.Schema({ movies_ids: [] })
Hiya,
Not sure if I have missed something or not but I seem to only be able to get Swagger 2.0 out of the code. have I missed a config seeting to be able to output OpenApi 3? If not do you have plans to support the newer format?
unnecessary
https://github.com/giddyinc/mongoose-to-swagger/blob/master/lib/index.js#L16
required accepts an array of strings
https://github.com/giddyinc/mongoose-to-swagger/blob/master/lib/index.js#L50
If the schema contains an array of sub-document schemas I'm getting call stack size exceeded.
Example schema:
const subSchema= new Schema<any>(
example: {
type: 'string',
required: true
},
},
{
timestamps: false,
_id: false,
}
)
const exampleSchema = new Schema<any>(
subschema: {
type: [subSchema],
default: [],
},
},
{
timestamps: true,
_id: true,
}
)
/home/node/app/node_modules/mongoose-to-swagger/dist/index.js:136
const getFieldsFromMongooseSchema = (schema, options) => {
^
RangeError: Maximum call stack size exceeded
at getFieldsFromMongooseSchema (/home/node/app/node_modules/mongoose-to-swagger/dist/index.js:136:37)
at mapSchemaTypeToFieldSchema (/home/node/app/node_modules/mongoose-to-swagger/dist/index.js:115:26)
at getFieldsFromMongooseSchema (/home/node/app/node_modules/mongoose-to-swagger/dist/index.js:145:23)
at mapSchemaTypeToFieldSchema (/home/node/app/node_modules/mongoose-to-swagger/dist/index.js:115:26)
at getFieldsFromMongooseSchema (/home/node/app/node_modules/mongoose-to-swagger/dist/index.js:145:23)
at mapSchemaTypeToFieldSchema (/home/node/app/node_modules/mongoose-to-swagger/dist/index.js:115:26)
at getFieldsFromMongooseSchema (/home/node/app/node_modules/mongoose-to-swagger/dist/index.js:145:23)
at mapSchemaTypeToFieldSchema (/home/node/app/node_modules/mongoose-to-swagger/dist/index.js:115:26)
at getFieldsFromMongooseSchema (/home/node/app/node_modules/mongoose-to-swagger/dist/index.js:145:23)
at mapSchemaTypeToFieldSchema (/home/node/app/node_modules/mongoose-to-swagger/dist/index.js:115:26)
Node.js v18.16.1
Can someone try to recreate this?
The omitFields option only omits fields in the top level schema and does nothing for nested schemas.
I have a pull request created including a unit test.
for instance:
const m2s = require('mongoose-to-swagger');
const temp = mongoose.model('test' , new mongoose.Schema( {
a:
new mongoose.Schema({
b: {
type : new mongoose.Schema({})
}
})
}));
m2s(temp);
returns error
but writing this way will work:
const temp = mongoose.model('test' , new mongoose.Schema( {
a:
new mongoose.Schema({
b: new mongoose.Schema({})
})
}));
m2s(temp);
A declarative, efficient, and flexible JavaScript library for building user interfaces.
๐ Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. ๐๐๐
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google โค๏ธ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.