Skip to content

Commit a99be9e

Browse files
committed
Initial commit
0 parents  commit a99be9e

20 files changed

+2847
-0
lines changed

.gitignore

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
node_modules/
2+
build/
3+
coverage/
4+
5+
npm-debug.log
6+
7+
# Lockfiles for apps, but not for packages.
8+
# https://github.com/sindresorhus/ama/issues/479#issuecomment-310661514
9+
package-lock.json

LICENSE

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
MIT License
2+
3+
Copyright (c) 2024 Santosh Bandichode
4+
5+
Permission is hereby granted, free of charge, to any person obtaining a copy
6+
of this software and associated documentation files (the "Software"), to deal
7+
in the Software without restriction, including without limitation the rights
8+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9+
copies of the Software, and to permit persons to whom the Software is
10+
furnished to do so, subject to the following conditions:
11+
12+
The above copyright notice and this permission notice shall be included in all
13+
copies or substantial portions of the Software.
14+
15+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21+
SOFTWARE.

README.md

Lines changed: 126 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,126 @@
1+
## Sequelize To OpenAPI
2+
3+
Based on [sequelize-to-json-schemas](https://github.com/alt3/sequelize-to-json-schemas)
4+
5+
With following changes:
6+
7+
1. Rewrite in TypeScript
8+
2. Added OpenAPI validations based on Sequelize validations
9+
3. Only OpenAPI is supported.
10+
4. Focused only on Sequelize 6
11+
12+
## Installation
13+
14+
```bash
15+
npm install --save @techntools/sequelize-to-openapi
16+
```
17+
18+
## Usage
19+
20+
```typescript
21+
import { SchemaManager, OpenApiStrategy } from '@techntools/sequelize-to-openapi'
22+
23+
const schemaManager = new SchemaManager
24+
const strategy = new OpenApiStrategy
25+
26+
oapi.schema('User', schemaManager.generate(UserModel, strategy))
27+
```
28+
29+
## Configuration Options
30+
31+
Pass (per) model options to the generate() method:
32+
33+
```typescript
34+
const userSchema = schemaManager.generate(userModel, strategy, {
35+
exclude: ['someAttribute'],
36+
include: ['someAttribute'],
37+
associations: true,
38+
excludeAssociations: ['someAssociation'],
39+
includeAssociations: ['someAssociation'],
40+
});
41+
```
42+
43+
`title` and `description` are dropped
44+
45+
`jsonSchema` and `schema` works the same as sequelize-to-json-schemas
46+
47+
## Unsupported Types
48+
49+
* GEOMETRY
50+
* RANGE
51+
* ABSTRACT
52+
* GEOGRAPHY
53+
* HSTORE
54+
55+
While sequelize-to-json-schemas throws error for these, this package simply ignores them so that you can use generated schema for rest of the types and support these types the way you see fit
56+
57+
## Validators
58+
59+
Following validators are supported:
60+
61+
| Sequelize | OpenAPI Keyword |
62+
| :-------- | :-------------------------- |
63+
| min | minimum |
64+
| max | maximum |
65+
| len | minLength/maxLength |
66+
| notEmpty | minLength |
67+
| notIn | `{ not: { enum: [] } }`<br> |
68+
69+
| Sequelize | OpenAPI Format |
70+
| :-------- | :------------- |
71+
| isEmail | email |
72+
| isUrl | url |
73+
| isUUID | uuid |
74+
75+
| Sequelize | OpenAPI Pattern |
76+
| :------------- | :------------------------------------------------------------------------------------------ |
77+
| isAlpha | `^[a-zA-Z]+$` |
78+
| isNumeric | `^[0-9]+$` |
79+
| isAlphanumeric | `^[a-zA-Z0-9]+$` |
80+
| isLowercase | `^[a-z]+$` |
81+
| isUppercase | `^[A-Z]+$` |
82+
| contains | `^.*' + val + '.*$` |
83+
| notContains | `^(?!.*' + val + ').*$`<br><br>With array:<br><br>`^(?!.*(' + val.args.join('\|') + ')).*$` |
84+
85+
| Sequelize | AJV |
86+
| -------------------------------------- | ------------------------------------------------------ |
87+
| `is` as string | `{ regexp: '' }` |
88+
| `is` as RegExp | `{ regexp: '' }` |
89+
| `is` as `{ args: '', msg }` | `{ regexp: '' }` |
90+
| `is` as `{ args: RegExp, msg }` | `{ regexp: '' }` |
91+
| `is` as `{ args: ['pat', 'f'], msg }` | `{ regexp: { pattern: pat, flag: f }}` |
92+
| `is` as array | `{ regexp: { pattern: val[0], flag: val[1] }}` |
93+
| `not` as string | `{ not: { regexp: '' }}` |
94+
| `not` as RegExp | `{ not: { regexp: '' }}` |
95+
| `not` as `{ args: '', msg }` | `{ not: { regexp: '' }}` |
96+
| `not` as `{ args: RegExp, msg }` | `{ not: { regexp: '' }}` |
97+
| `not` as `{ args: ['pat', 'f'], msg }` | `{ not: { regexp: { pattern: pat, flag: f }}}` |
98+
| `not` as array | `{ not: { regexp: { pattern: val[0], flag: val[1] }}}` |
99+
100+
## Case with regular expression
101+
102+
Flags such as i, g etc. are not supported in OpenAPI. Sequelize can use string or RegExp class for regex. So, to avoid these limitations, I have used `regexp` keyword from [ajv-keywords](https://github.com/ajv-validator/ajv-keywords) package for `is` and `not` validators.
103+
104+
This makes generated OpenAPI schema not fully compliant with the standard. But you can drop those validators if you face issues.
105+
106+
## Demo
107+
108+
Check my [repo](https://github.com/techntools/sequelize-to-openapi-demo) for usage of the package. It uses sequelize-typescript.
109+
110+
Visit the OpenAPI documentation powered by [scalar](https://www.scalar.com/)
111+
112+
[express-openapi](https://github.com/wesleytodd/express-openapi) generates OpenAPI spec
113+
114+
## License
115+
116+
This project is released under [MIT LICENSE](https://github.com/techntools/sequelize-to-openapi/blob/master/LICENSE.txt)
117+
118+
## Contributing
119+
120+
1. Keep the changes small
121+
2. Add the tests
122+
3. Existing tests have to pass
123+
124+
## Credits
125+
126+
Full credits to the authors and contributors of [sequelize-to-json-schemas](https://github.com/alt3/sequelize-to-json-schemas) for the great work

package.json

Lines changed: 93 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,93 @@
1+
{
2+
"name": "@techntools/sequelize-to-openapi",
3+
"version": "0.4.8",
4+
"description": "OpenAPI 3 schemas from Sequelize models",
5+
"publishConfig": {
6+
"access": "public"
7+
},
8+
"main": "build/index.js",
9+
"types": "build/index.d.ts",
10+
"scripts": {
11+
"clean": "rimraf coverage build",
12+
"build": "tsc",
13+
"compile": "tsc --watch",
14+
"dev": "nodemon try-me.ts",
15+
"dev:debug": "nodemon --exec 'node --inspect --require ts-node/register try-me.ts'",
16+
"test": "jest --coverage",
17+
"test:watch": "jest --watch",
18+
"test:debug": "node --nolazy --inspect-brk node_modules/.bin/jest --runInBand --colors --verbose --watch --coverage false",
19+
"release": "release-it",
20+
"release-dr": "release-it --dry-run --release-version --changelog"
21+
},
22+
"files": [
23+
"build"
24+
],
25+
"keywords": [
26+
"typescript",
27+
"javascript",
28+
"sequelize",
29+
"json-schema",
30+
"strategy-pattern",
31+
"swagger",
32+
"openapi",
33+
"oas",
34+
"oasv3"
35+
],
36+
"license": "MIT",
37+
"repository": {
38+
"type": "git",
39+
"url": "git+https://github.com/techntools/sequelize-to-openapi.git"
40+
},
41+
"author": {
42+
"name": "Santosh Bandichode",
43+
"url": "https://github.com/techntools/sequelize-to-openapi"
44+
},
45+
"bugs": "https://github.com/techntools/sequelize-to-openapi/issues",
46+
"engines": {
47+
"node": ">=18"
48+
},
49+
"devDependencies": {
50+
"@apidevtools/swagger-parser": "^10.1.0",
51+
"@release-it/conventional-changelog": "^8.0.1",
52+
"@types/jest": "^29.5.12",
53+
"ajv-formats": "^3.0.1",
54+
"ajv-keywords": "^5.1.0",
55+
"jest": "^29.7.0",
56+
"mysql2": "^3.10.1",
57+
"release-it": "^17.4.0",
58+
"rimraf": "^5.0.7",
59+
"sequelize": "^6.37.3",
60+
"ts-jest": "^29.1.5",
61+
"ts-node": "^10.9.2",
62+
"typescript": "^5.5.2"
63+
},
64+
"jest": {
65+
"preset": "ts-jest",
66+
"testEnvironment": "node",
67+
"coverageReporters": [
68+
"lcov",
69+
"text",
70+
"html"
71+
],
72+
"collectCoverageFrom": [
73+
"src/**/*"
74+
]
75+
},
76+
"release-it": {
77+
"git": {
78+
"commit": true,
79+
"commitMessage": "Chore: Release ${version}",
80+
"requireUpstream": false
81+
},
82+
"github": {
83+
"release": true
84+
},
85+
"hooks": {
86+
"before:init": [
87+
"npm run clean",
88+
"npm run build",
89+
"npm run test"
90+
]
91+
}
92+
}
93+
}

src/attribute-validator.ts

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
import { type ModelAttributeColumnOptions } from 'sequelize'
2+
3+
import OpenApiStrategy from './strategies/openapi'
4+
5+
6+
/**
7+
* Class responsible for adding strategy-compatible Sequelize attribute
8+
* validators
9+
*
10+
* @copyright Copyright (c) 2024 Santosh Bandichode.
11+
* @license Licensed under the MIT License
12+
*/
13+
export default class AttributeValidator {
14+
/**
15+
* Returns the strategy-specific validators for the given Sequelize DataType
16+
*
17+
* @see {@link https://sequelize.org/docs/v6/core-concepts/validations-and-constraints}
18+
*/
19+
map(properties: ModelAttributeColumnOptions, strategy: OpenApiStrategy) {
20+
if (!properties.validate)
21+
return
22+
23+
let result = {}
24+
let attributeType = properties && properties.type && properties.type['key']
25+
26+
// ----------------------------------------------------------------------
27+
// Sequelize validations
28+
// ----------------------------------------------------------------------
29+
switch (attributeType) {
30+
case 'INTEGER':
31+
case 'STRING':
32+
result = strategy.getPropertiesForValidate(properties.validate)
33+
break
34+
35+
default:
36+
break
37+
}
38+
39+
return result
40+
}
41+
}

src/index.ts

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
import SchemaManager from './schema-manager'
2+
import OpenApiStrategy from './strategies/openapi'
3+
4+
5+
export {
6+
SchemaManager,
7+
OpenApiStrategy,
8+
}

0 commit comments

Comments
 (0)