├── .eslintrc.json ├── .gitignore ├── .npmignore ├── LICENSE.md ├── README.md ├── doc └── assets │ ├── repository-open-graph-template.png │ └── sequelize-logo-443x512.png ├── example ├── .env.sample ├── .sequelizerc ├── db │ ├── config.example.json │ ├── config.json │ ├── migrations │ │ └── 00000001-init.js │ └── models │ │ └── index.js ├── models │ ├── car.model.ts │ └── car_brand.model.ts ├── package-lock.json ├── package.json ├── practice.ts └── tsconfig.json ├── jest.config.js ├── package-lock.json ├── package.json ├── src ├── constants.ts ├── index.ts └── utils │ ├── createMigrationTable.ts │ ├── getDiffActionsFromTables.ts │ ├── getLastMigrationState.ts │ ├── getMigration.ts │ ├── getTablesFromModels.ts │ ├── makeColumnName.ts │ ├── parseIndex.ts │ ├── removeCurrentRevisionMigrations.ts │ ├── reverseSequelizeColType.ts │ ├── reverseSequelizeDefValueType.ts │ ├── snakeCase.spec.ts │ ├── snakeCase.ts │ ├── sortActions.ts │ └── writeMigration.ts └── tsconfig.json /.eslintrc.json: -------------------------------------------------------------------------------- 1 | { 2 | "parser": "@typescript-eslint/parser", 3 | "parserOptions": { 4 | "ecmaVersion": 12, 5 | "sourceType": "module" 6 | }, 7 | "plugins": [ 8 | "@typescript-eslint" 9 | ], 10 | "extends": [ 11 | "eslint:recommended", 12 | "plugin:@typescript-eslint/recommended" 13 | ], 14 | "rules": { 15 | "@typescript-eslint/no-explicit-any": "off" 16 | }, 17 | "env": { 18 | "browser": true, 19 | "es2021": true 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | package-lock.json 2 | 3 | # Logs 4 | logs 5 | *.log 6 | npm-debug.log* 7 | yarn-debug.log* 8 | yarn-error.log* 9 | lerna-debug.log* 10 | 11 | # Diagnostic reports (https://nodejs.org/api/report.html) 12 | report.[0-9]*.[0-9]*.[0-9]*.[0-9]*.json 13 | 14 | # Runtime data 15 | pids 16 | *.pid 17 | *.seed 18 | *.pid.lock 19 | 20 | # Directory for instrumented libs generated by jscoverage/JSCover 21 | lib-cov 22 | 23 | # Coverage directory used by tools like istanbul 24 | coverage 25 | *.lcov 26 | 27 | # Compiled binary addons (https://nodejs.org/api/addons.html) 28 | build/Release 29 | 30 | # Dependency directories 31 | node_modules/ 32 | 33 | # TypeScript v1 declaration files 34 | typings/ 35 | 36 | # TypeScript cache 37 | *.tsbuildinfo 38 | 39 | # Optional npm cache directory 40 | .npm 41 | 42 | # Optional eslint cache 43 | .eslintcache 44 | 45 | # Output of 'npm pack' 46 | *.tgz 47 | 48 | # dotenv environment variables file 49 | .env 50 | .env.test 51 | 52 | dist/ 53 | 54 | # Gatsby files 55 | .cache/ 56 | # Comment in the public line in if your project uses Gatsby and *not* Next.js 57 | # https://nextjs.org/blog/next-9-1#public-directory-support 58 | # public 59 | 60 | 61 | # Serverless directories 62 | .serverless/ 63 | 64 | # FuseBox cache 65 | .fusebox/ 66 | 67 | # DynamoDB Local files 68 | .dynamodb/ 69 | 70 | # TernJS port file 71 | .tern-port 72 | 73 | #ide 74 | .idea/* 75 | .vscode/* 76 | 77 | example/db/migrations/ 78 | example/db/config.json 79 | -------------------------------------------------------------------------------- /.npmignore: -------------------------------------------------------------------------------- 1 | src/ 2 | 3 | .git/ 4 | 5 | node_modules/ 6 | 7 | typings 8 | .tscache 9 | 10 | test/ 11 | 12 | example/ 13 | .gitignore 14 | .editorconfig 15 | 16 | npm-debug.log 17 | 18 | tsconfig.json 19 | 20 | package-lock.json -------------------------------------------------------------------------------- /LICENSE.md: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2020 KIMJBSTAR 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. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # sequelize-typescript-migration-lts 2 | 3 | #### Idea: founded the best changes at each 27th fork from the main repository and merge them together. 4 | 5 | - Use it from [here](https://www.npmjs.com/package/sequelize-typescript-migration-lts) by the name of `sequelize-typescript-migration-lts` 6 | 7 | - Here is the [Github discussion](https://github.com/mmRoshani/sequelize-typescript-migration/discussions), any ideas/improves are very welcome. 8 | 9 | #### Tutorial 10 | 11 | [youtube video](https://www.youtube.com/embed/bBv75hssPKk) 12 | 13 | [![video](https://img.youtube.com/vi/bBv75hssPKk/0.jpg)](https://www.youtube.com/embed/bBv75hssPKk) 14 | 15 | 16 | #### Installation 17 | 18 | ```js 19 | npm i sequelize-typescript-migration-lts 20 | // Or 21 | yarn add sequelize-typescript-migration-lts 22 | ``` 23 | 24 | Thanks kimjbstar, mricharz, syon-development, viinzzz and lou2013 for the awesome lib. 25 | 26 | ## General info 27 | 28 | It is based on [sequelize-typescript](https://www.npmjs.com/package/sequelize-typescript), not supports "sequelize" based model codes. 29 | and you need prior knowledge of migration of Sequelize. 30 | 31 | [Sequelize Migration Manual](https://sequelize.org/master/manual/migrations.html) 32 | 33 | This scans models and its decorators to find changes, and generates migration code with this changes so don't need to write up, down function manually. this is like "makemigration" in django framework. 34 | 35 | After generate successfully, you can use "migrate" in [Sequelize](https://sequelize.org/) 36 | [Sequelize Migration Manual](https://sequelize.org/master/manual/migrations.html) 37 | 38 | **This refers to [GitHub - flexxnn/sequelize-auto-migrations: Migration generator && runner for sequelize](https://github.com/flexxnn/sequelize-auto-migrations) and its forks, and modified to typescript.** 39 | 40 | Sometimes, undo(down) action may not work, then you should modify manually. Maybe it's because of ordering of relations of models. 41 | That issue is currently in the works. 42 | 43 | ### Compatibility 44 | 45 | - Use version `~2.0.0` for `sequelize@~6.0.0` 46 | - Use version `~1.0.0` for `sequelize@~4.0.0` 47 | 48 | ## Usage Example 49 | 50 | ```typescript 51 | import { join } from 'path' 52 | import { Sequelize } from "sequelize-typescript"; 53 | import { SequelizeTypescriptMigration } from "sequelize-typescript-migration-lts"; 54 | 55 | const sequelize: Sequelize = new Sequelize({ 56 | // .. options 57 | }); 58 | 59 | await SequelizeTypescriptMigration.makeMigration(sequelize, { 60 | outDir: join(__dirname, './migrations'), 61 | migrationName: "add-awesome-field-in-my-table", 62 | preview: false, 63 | }); 64 | ``` 65 | 66 | let's see example, if you have this two models and run first makeMigration, it detects all table change from nothing. 67 | 68 | ```typescript 69 | @Table 70 | export class CarBrand extends Model { 71 | @Column 72 | name: string; 73 | 74 | @Default(true) 75 | @Column(DataType.BOOLEAN) 76 | isCertified: boolean; 77 | 78 | @Column 79 | imgUrl: string; 80 | 81 | @Column 82 | orderNo: number; 83 | 84 | @Column 85 | carsCount: number; 86 | } 87 | ``` 88 | 89 | ```typescript 90 | @Table 91 | export class Car extends Model { 92 | @Column 93 | name: string; 94 | 95 | @ForeignKey(() => CarBrand) 96 | @Column 97 | carBrandId: number; 98 | 99 | @BelongsTo(() => CarBrand) 100 | carBrand: CarBrand; 101 | } 102 | ``` 103 | 104 | then this code written to 00000001-noname.js in migrations path. 105 | 106 | ```javascript 107 | "use strict"; 108 | 109 | var Sequelize = require("sequelize"); 110 | 111 | /** 112 | * Actions summary: 113 | * 114 | * createTable "CarBrands", deps: [] 115 | * createTable "Cars", deps: [CarBrands] 116 | * 117 | **/ 118 | 119 | var info = { 120 | revision: 1, 121 | name: "noname", 122 | created: "2020-04-12T15:49:58.814Z", 123 | comment: "", 124 | }; 125 | 126 | var migrationCommands = [ 127 | { 128 | fn: "createTable", 129 | params: [ 130 | "CarBrands", 131 | { 132 | id: { 133 | autoIncrement: true, 134 | primaryKey: true, 135 | allowNull: false, 136 | type: Sequelize.INTEGER, 137 | }, 138 | name: { 139 | type: Sequelize.STRING, 140 | }, 141 | isCertified: { 142 | type: Sequelize.BOOLEAN, 143 | }, 144 | imgUrl: { 145 | type: Sequelize.STRING, 146 | }, 147 | orderNo: { 148 | type: Sequelize.INTEGER, 149 | }, 150 | carsCount: { 151 | type: Sequelize.INTEGER, 152 | }, 153 | createdAt: { 154 | allowNull: false, 155 | type: Sequelize.DATE, 156 | }, 157 | updatedAt: { 158 | allowNull: false, 159 | type: Sequelize.DATE, 160 | }, 161 | }, 162 | {}, 163 | ], 164 | }, 165 | 166 | { 167 | fn: "createTable", 168 | params: [ 169 | "Cars", 170 | { 171 | id: { 172 | autoIncrement: true, 173 | primaryKey: true, 174 | allowNull: false, 175 | type: Sequelize.INTEGER, 176 | }, 177 | name: { 178 | type: Sequelize.STRING, 179 | }, 180 | carBrandId: { 181 | onDelete: "NO ACTION", 182 | onUpdate: "CASCADE", 183 | references: { 184 | model: "CarBrands", 185 | key: "id", 186 | }, 187 | allowNull: true, 188 | type: Sequelize.INTEGER, 189 | }, 190 | createdAt: { 191 | allowNull: false, 192 | type: Sequelize.DATE, 193 | }, 194 | updatedAt: { 195 | allowNull: false, 196 | type: Sequelize.DATE, 197 | }, 198 | }, 199 | {}, 200 | ], 201 | }, 202 | ]; 203 | 204 | var rollbackCommands = [ 205 | { 206 | fn: "dropTable", 207 | params: ["Cars"], 208 | }, 209 | { 210 | fn: "dropTable", 211 | params: ["CarBrands"], 212 | }, 213 | ]; 214 | 215 | module.exports = { 216 | pos: 0, 217 | up: function (queryInterface, Sequelize) { 218 | var index = this.pos; 219 | return new Promise(function (resolve, reject) { 220 | function next() { 221 | if (index < migrationCommands.length) { 222 | let command = migrationCommands[index]; 223 | console.log("[#" + index + "] execute: " + command.fn); 224 | index++; 225 | queryInterface[command.fn] 226 | .apply(queryInterface, command.params) 227 | .then(next, reject); 228 | } else resolve(); 229 | } 230 | next(); 231 | }); 232 | }, 233 | down: function (queryInterface, Sequelize) { 234 | var index = this.pos; 235 | return new Promise(function (resolve, reject) { 236 | function next() { 237 | if (index < rollbackCommands.length) { 238 | let command = rollbackCommands[index]; 239 | console.log("[#" + index + "] execute: " + command.fn); 240 | index++; 241 | queryInterface[command.fn] 242 | .apply(queryInterface, command.params) 243 | .then(next, reject); 244 | } else resolve(); 245 | } 246 | next(); 247 | }); 248 | }, 249 | info: info, 250 | }; 251 | ``` 252 | 253 | then you can apply this `npx sequelize db:migrate --to 00000001-noname.js` 254 | 255 | ## Possible Usage Scenario 256 | Make sure to have writeMigration in your System under development and that sequelize is all set up 257 | 258 | If you change a model and re-run the backend there should be a new file under `db/migrations`, but the database won't update automatically. There are easy but important steps: 259 | 260 | 1) Rename the file's name as well as the content (Info: name), so that everyone knows what this migration is about 261 | 2) Migrate your database `sequelize db:migrate` 262 | 3) Re-Serve the backend. You Should see 'No changes found'. 263 | 4) Test the automatically created file's down function `sequelize db:migrate:undo` 264 | 5) If there are any troubles, fix the auto-generated file (ordering!) 265 | 6) Run `sequelize db:migrate:undo` and continue your amazing work 266 | 267 | ## Documentation 268 | 269 | Will be ready soon! 270 | 271 | ## Contributors 272 | 273 | - [MohammadMojtaba Roshani](https://github.com/mmRoshani) 274 | - [Anthony Luzquiños](https://github.com/anthonylzq) 275 | - [Alexandr Cherednichenko](https://github.com/alexandr2110pro) 276 | -------------------------------------------------------------------------------- /doc/assets/repository-open-graph-template.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mmRoshani/sequelize-typescript-migration/7124d5c108302fcab6bca381cca74a4d5f8eec8e/doc/assets/repository-open-graph-template.png -------------------------------------------------------------------------------- /doc/assets/sequelize-logo-443x512.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mmRoshani/sequelize-typescript-migration/7124d5c108302fcab6bca381cca74a4d5f8eec8e/doc/assets/sequelize-logo-443x512.png -------------------------------------------------------------------------------- /example/.env.sample: -------------------------------------------------------------------------------- 1 | DATABASE_USER=postgres 2 | DATABASE_PASS=6939 3 | DATABASE_PORT=5432 4 | DATABASE_NAME=STM 5 | DATABASE_DIALECT=postgres 6 | DATABASE_TIMEZONE=+03:30 -------------------------------------------------------------------------------- /example/.sequelizerc: -------------------------------------------------------------------------------- 1 | const path = require("path") 2 | 3 | module.exports = { 4 | config: path.resolve("db", "config.json"), 5 | "migrations-path": path.resolve("db", "migrations"), 6 | "models-path": path.resolve("db", "models"), 7 | "seeders-path": path.resolve("db", "seeders") 8 | } 9 | -------------------------------------------------------------------------------- /example/db/config.example.json: -------------------------------------------------------------------------------- 1 | { 2 | "development": { 3 | "username": "postgres", 4 | "password": "6939", 5 | "database": "STM", 6 | "host": "127.0.0.1", 7 | "dialect": "postgres" 8 | }, 9 | "test": { 10 | "username": "root", 11 | "password": null, 12 | "database": "database_test", 13 | "host": "127.0.0.1", 14 | "dialect": "mysql" 15 | }, 16 | "production": { 17 | "username": "root", 18 | "password": null, 19 | "database": "database_production", 20 | "host": "127.0.0.1", 21 | "dialect": "mysql" 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /example/db/config.json: -------------------------------------------------------------------------------- 1 | { 2 | "development": { 3 | "username": "postgres", 4 | "password": "6939", 5 | "database": "STM", 6 | "host": "127.0.0.1", 7 | "dialect": "postgres" 8 | }, 9 | "test": { 10 | "username": "root", 11 | "password": null, 12 | "database": "database_test", 13 | "host": "127.0.0.1", 14 | "dialect": "mysql" 15 | }, 16 | "production": { 17 | "username": "root", 18 | "password": null, 19 | "database": "database_production", 20 | "host": "127.0.0.1", 21 | "dialect": "mysql" 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /example/db/migrations/00000001-init.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | const Sequelize = require('sequelize'); 4 | 5 | /** 6 | * Actions summary: 7 | * 8 | * createTable "CarBrands", deps: [] 9 | * createTable "Cars", deps: [CarBrands] 10 | * 11 | **/ 12 | 13 | const info = { 14 | "revision": 1, 15 | "name": "init", 16 | "created": "2022-09-29T10:45:59.104Z", 17 | "comment": "" 18 | }; 19 | 20 | const migrationCommands = [ 21 | 22 | { 23 | fn: "createTable", 24 | params: [ 25 | "SequelizeMigrationsMeta", 26 | { 27 | "revision": { 28 | "primaryKey": true, 29 | "type": Sequelize.INTEGER 30 | }, 31 | "name": { 32 | "allowNull": false, 33 | "type": Sequelize.STRING 34 | }, 35 | "state": { 36 | "allowNull": false, 37 | "type": Sequelize.JSON 38 | }, 39 | }, 40 | {} 41 | ] 42 | }, 43 | { 44 | fn: "bulkDelete", 45 | params: [ 46 | "SequelizeMigrationsMeta", 47 | [{ 48 | revision: info.revision 49 | }], 50 | {} 51 | ] 52 | }, 53 | { 54 | fn: "bulkInsert", 55 | params: [ 56 | "SequelizeMigrationsMeta", 57 | [{ 58 | revision: info.revision, 59 | name: info.name, 60 | state: '{"revision":1,"tables":{"CarBrands":{"tableName":"CarBrands","schema":{"id":{"seqType":"Sequelize.INTEGER","allowNull":false,"primaryKey":true,"autoIncrement":true},"name":{"seqType":"Sequelize.STRING"},"isCertified":{"seqType":"Sequelize.BOOLEAN"},"imgUrl":{"seqType":"Sequelize.STRING"},"orderNo":{"seqType":"Sequelize.INTEGER"},"carsCount":{"seqType":"Sequelize.INTEGER"},"createdAt":{"seqType":"Sequelize.DATE","allowNull":false},"updatedAt":{"seqType":"Sequelize.DATE","allowNull":false}},"indexes":{}},"Cars":{"tableName":"Cars","schema":{"id":{"seqType":"Sequelize.INTEGER","allowNull":false,"primaryKey":true,"autoIncrement":true},"name":{"seqType":"Sequelize.STRING"},"carBrandId":{"seqType":"Sequelize.INTEGER","allowNull":true,"references":{"model":"CarBrands","key":"id"},"onUpdate":"CASCADE","onDelete":"NO ACTION"},"createdAt":{"seqType":"Sequelize.DATE","allowNull":false},"updatedAt":{"seqType":"Sequelize.DATE","allowNull":false}},"indexes":{}}}}' 61 | }], 62 | {} 63 | ] 64 | }, 65 | 66 | 67 | 68 | 69 | { 70 | fn: "createTable", 71 | params: [ 72 | "CarBrands", 73 | { 74 | "id": { 75 | "autoIncrement": true, 76 | "primaryKey": true, 77 | "allowNull": false, 78 | "type": Sequelize.INTEGER 79 | }, 80 | "name": { 81 | "type": Sequelize.STRING 82 | }, 83 | "isCertified": { 84 | "type": Sequelize.BOOLEAN 85 | }, 86 | "imgUrl": { 87 | "type": Sequelize.STRING 88 | }, 89 | "orderNo": { 90 | "type": Sequelize.INTEGER 91 | }, 92 | "carsCount": { 93 | "type": Sequelize.INTEGER 94 | }, 95 | "createdAt": { 96 | "allowNull": false, 97 | "type": Sequelize.DATE 98 | }, 99 | "updatedAt": { 100 | "allowNull": false, 101 | "type": Sequelize.DATE 102 | } 103 | }, 104 | {} 105 | ] 106 | }, 107 | 108 | { 109 | fn: "createTable", 110 | params: [ 111 | "Cars", 112 | { 113 | "id": { 114 | "autoIncrement": true, 115 | "primaryKey": true, 116 | "allowNull": false, 117 | "type": Sequelize.INTEGER 118 | }, 119 | "name": { 120 | "type": Sequelize.STRING 121 | }, 122 | "carBrandId": { 123 | "onDelete": "NO ACTION", 124 | "onUpdate": "CASCADE", 125 | "references": { 126 | "model": "CarBrands", 127 | "key": "id" 128 | }, 129 | "allowNull": true, 130 | "type": Sequelize.INTEGER 131 | }, 132 | "createdAt": { 133 | "allowNull": false, 134 | "type": Sequelize.DATE 135 | }, 136 | "updatedAt": { 137 | "allowNull": false, 138 | "type": Sequelize.DATE 139 | } 140 | }, 141 | {} 142 | ] 143 | } 144 | ]; 145 | 146 | const rollbackCommands = [ 147 | 148 | { 149 | fn: "bulkDelete", 150 | params: [ 151 | "SequelizeMigrationsMeta", 152 | [{ 153 | revision: info.revision, 154 | }], 155 | {} 156 | ] 157 | }, 158 | 159 | 160 | 161 | { 162 | fn: "dropTable", 163 | params: ["Cars"] 164 | }, 165 | { 166 | fn: "dropTable", 167 | params: ["CarBrands"] 168 | } 169 | ]; 170 | 171 | module.exports = { 172 | pos: 0, 173 | up: function(queryInterface, Sequelize) { 174 | let index = this.pos; 175 | 176 | return new Promise(function(resolve, reject) { 177 | function next() { 178 | if (index < migrationCommands.length) { 179 | let command = migrationCommands[index]; 180 | console.log("[#"+index+"] execute: " + command.fn); 181 | index++; 182 | queryInterface[command.fn].apply(queryInterface, command.params).then(next, reject); 183 | } else resolve(); 184 | } 185 | 186 | next(); 187 | }); 188 | }, 189 | down: function(queryInterface, Sequelize) { 190 | let index = this.pos; 191 | 192 | return new Promise(function(resolve, reject) { 193 | function next() { 194 | if (index < rollbackCommands.length) { 195 | let command = rollbackCommands[index]; 196 | console.log("[#"+index+"] execute: " + command.fn); 197 | index++; 198 | queryInterface[command.fn].apply(queryInterface, command.params).then(next, reject); 199 | } 200 | else resolve(); 201 | } 202 | 203 | next(); 204 | }); 205 | }, 206 | info 207 | }; 208 | -------------------------------------------------------------------------------- /example/db/models/index.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | const fs = require("fs"); 4 | const path = require("path"); 5 | const Sequelize = require("sequelize"); 6 | const basename = path.basename(__filename); 7 | const config = require("../config.json"); 8 | const db = {}; 9 | 10 | const sequelize = new Sequelize({ 11 | username: config.development.username, 12 | password: config.development.password, 13 | database: config.development.database, 14 | host: config.development.host, 15 | dialect: config.development.dialect, 16 | port: process.env.DATABASE_PORT, 17 | timezone: process.env.DATABASE_TIMEZONE, 18 | protocol: "tcp", 19 | }); 20 | 21 | fs.readdirSync(__dirname) 22 | .filter((file) => { 23 | return ( 24 | file.indexOf(".") !== 0 && file !== basename && file.slice(-3) === ".js" 25 | ); 26 | }) 27 | .forEach((file) => { 28 | const model = require(path.join(__dirname, file))( 29 | sequelize, 30 | Sequelize.DataTypes 31 | ); 32 | db[model.name] = model; 33 | }); 34 | 35 | Object.keys(db).forEach((modelName) => { 36 | if (db[modelName].associate) db[modelName].associate(db); 37 | }); 38 | 39 | db.sequelize = sequelize; 40 | db.Sequelize = Sequelize; 41 | 42 | module.exports = db; 43 | -------------------------------------------------------------------------------- /example/models/car.model.ts: -------------------------------------------------------------------------------- 1 | import { 2 | Table, 3 | Model, 4 | Column, 5 | ForeignKey, 6 | BelongsTo, 7 | } from "sequelize-typescript"; 8 | 9 | import { CarBrand } from "./car_brand.model"; 10 | 11 | @Table 12 | export class Car extends Model { 13 | @Column 14 | name!: string; 15 | 16 | @ForeignKey(() => CarBrand) 17 | @Column 18 | carBrandId!: number; 19 | 20 | @BelongsTo(() => CarBrand) 21 | carBrand!: CarBrand; 22 | } 23 | -------------------------------------------------------------------------------- /example/models/car_brand.model.ts: -------------------------------------------------------------------------------- 1 | import { Table, Model, Column, Default, DataType } from "sequelize-typescript"; 2 | 3 | @Table 4 | export class CarBrand extends Model { 5 | @Column 6 | name!: string; 7 | 8 | @Default(true) 9 | @Column(DataType.BOOLEAN) 10 | isCertified!: boolean; 11 | 12 | @Column 13 | imgUrl!: string; 14 | 15 | @Column 16 | orderNo!: number; 17 | 18 | @Column 19 | carsCount!: number; 20 | } 21 | -------------------------------------------------------------------------------- /example/package-lock.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "example", 3 | "lockfileVersion": 2, 4 | "requires": true, 5 | "packages": { 6 | "": { 7 | "dependencies": { 8 | "dotenv": "^16.0.1", 9 | "pg": "^8.7.3", 10 | "sequelize": "^6.23.2", 11 | "sequelize-cli": "^6.5.1", 12 | "sequelize-typescript": "^2.1.3", 13 | "typescript": "^4.3.5" 14 | }, 15 | "devDependencies": { 16 | "ts-node": "^10.0.0" 17 | } 18 | }, 19 | "node_modules/@tsconfig/node10": { 20 | "version": "1.0.8", 21 | "resolved": "https://registry.npmjs.org/@tsconfig/node10/-/node10-1.0.8.tgz", 22 | "integrity": "sha512-6XFfSQmMgq0CFLY1MslA/CPUfhIL919M1rMsa5lP2P097N2Wd1sSX0tx1u4olM16fLNhtHZpRhedZJphNJqmZg==", 23 | "dev": true 24 | }, 25 | "node_modules/@tsconfig/node12": { 26 | "version": "1.0.9", 27 | "resolved": "https://registry.npmjs.org/@tsconfig/node12/-/node12-1.0.9.tgz", 28 | "integrity": "sha512-/yBMcem+fbvhSREH+s14YJi18sp7J9jpuhYByADT2rypfajMZZN4WQ6zBGgBKp53NKmqI36wFYDb3yaMPurITw==", 29 | "dev": true 30 | }, 31 | "node_modules/@tsconfig/node14": { 32 | "version": "1.0.1", 33 | "resolved": "https://registry.npmjs.org/@tsconfig/node14/-/node14-1.0.1.tgz", 34 | "integrity": "sha512-509r2+yARFfHHE7T6Puu2jjkoycftovhXRqW328PDXTVGKihlb1P8Z9mMZH04ebyajfRY7dedfGynlrFHJUQCg==", 35 | "dev": true 36 | }, 37 | "node_modules/@tsconfig/node16": { 38 | "version": "1.0.1", 39 | "resolved": "https://registry.npmjs.org/@tsconfig/node16/-/node16-1.0.1.tgz", 40 | "integrity": "sha512-FTgBI767POY/lKNDNbIzgAX6miIDBs6NTCbdlDb8TrWovHsSvaVIZDlTqym29C6UqhzwcJx4CYr+AlrMywA0cA==", 41 | "dev": true 42 | }, 43 | "node_modules/@types/debug": { 44 | "version": "4.1.7", 45 | "resolved": "https://registry.npmjs.org/@types/debug/-/debug-4.1.7.tgz", 46 | "integrity": "sha512-9AonUzyTjXXhEOa0DnqpzZi6VHlqKMswga9EXjpXnnqxwLtdvPPtlO8evrI5D9S6asFRCQ6v+wpiUKbw+vKqyg==", 47 | "dependencies": { 48 | "@types/ms": "*" 49 | } 50 | }, 51 | "node_modules/@types/ms": { 52 | "version": "0.7.31", 53 | "resolved": "https://registry.npmjs.org/@types/ms/-/ms-0.7.31.tgz", 54 | "integrity": "sha512-iiUgKzV9AuaEkZqkOLDIvlQiL6ltuZd9tGcW3gwpnX8JbuiuhFlEGmmFXEXkN50Cvq7Os88IY2v0dkDqXYWVgA==" 55 | }, 56 | "node_modules/@types/node": { 57 | "version": "18.6.1", 58 | "resolved": "https://registry.npmjs.org/@types/node/-/node-18.6.1.tgz", 59 | "integrity": "sha512-z+2vB6yDt1fNwKOeGbckpmirO+VBDuQqecXkgeIqDlaOtmKn6hPR/viQ8cxCfqLU4fTlvM3+YjM367TukWdxpg==" 60 | }, 61 | "node_modules/@types/validator": { 62 | "version": "13.7.4", 63 | "resolved": "https://registry.npmjs.org/@types/validator/-/validator-13.7.4.tgz", 64 | "integrity": "sha512-uAaSWegu2lymY18l+s5nmcXu3sFeeTOl1zhSGoYzcr6T3wz1M+3OcW4UjfPhIhHGd13tIMRDsEpR+d8w/MexwQ==" 65 | }, 66 | "node_modules/abbrev": { 67 | "version": "1.1.1", 68 | "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.1.1.tgz", 69 | "integrity": "sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==" 70 | }, 71 | "node_modules/ansi-regex": { 72 | "version": "5.0.1", 73 | "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", 74 | "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", 75 | "engines": { 76 | "node": ">=8" 77 | } 78 | }, 79 | "node_modules/ansi-styles": { 80 | "version": "4.3.0", 81 | "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", 82 | "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", 83 | "dependencies": { 84 | "color-convert": "^2.0.1" 85 | }, 86 | "engines": { 87 | "node": ">=8" 88 | }, 89 | "funding": { 90 | "url": "https://github.com/chalk/ansi-styles?sponsor=1" 91 | } 92 | }, 93 | "node_modules/arg": { 94 | "version": "4.1.3", 95 | "resolved": "https://registry.npmjs.org/arg/-/arg-4.1.3.tgz", 96 | "integrity": "sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA==", 97 | "dev": true 98 | }, 99 | "node_modules/at-least-node": { 100 | "version": "1.0.0", 101 | "resolved": "https://registry.npmjs.org/at-least-node/-/at-least-node-1.0.0.tgz", 102 | "integrity": "sha512-+q/t7Ekv1EDY2l6Gda6LLiX14rU9TV20Wa3ofeQmwPFZbOMo9DXrLbOjFaaclkXKWidIaopwAObQDqwWtGUjqg==", 103 | "engines": { 104 | "node": ">= 4.0.0" 105 | } 106 | }, 107 | "node_modules/balanced-match": { 108 | "version": "1.0.2", 109 | "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", 110 | "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==" 111 | }, 112 | "node_modules/bluebird": { 113 | "version": "3.7.2", 114 | "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.7.2.tgz", 115 | "integrity": "sha512-XpNj6GDQzdfW+r2Wnn7xiSAd7TM3jzkxGXBGTtWKuSXv1xUV+azxAm8jdWZN06QTQk+2N2XB9jRDkvbmQmcRtg==" 116 | }, 117 | "node_modules/brace-expansion": { 118 | "version": "1.1.11", 119 | "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", 120 | "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", 121 | "dependencies": { 122 | "balanced-match": "^1.0.0", 123 | "concat-map": "0.0.1" 124 | } 125 | }, 126 | "node_modules/buffer-from": { 127 | "version": "1.1.1", 128 | "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.1.tgz", 129 | "integrity": "sha512-MQcXEUbCKtEo7bhqEs6560Hyd4XaovZlO/k9V3hjVUF/zwW7KBVdSK4gIt/bzwS9MbR5qob+F5jusZsb0YQK2A==", 130 | "dev": true 131 | }, 132 | "node_modules/buffer-writer": { 133 | "version": "2.0.0", 134 | "resolved": "https://registry.npmjs.org/buffer-writer/-/buffer-writer-2.0.0.tgz", 135 | "integrity": "sha512-a7ZpuTZU1TRtnwyCNW3I5dc0wWNC3VR9S++Ewyk2HHZdrO3CQJqSpd+95Us590V6AL7JqUAH2IwZ/398PmNFgw==", 136 | "engines": { 137 | "node": ">=4" 138 | } 139 | }, 140 | "node_modules/cli-color": { 141 | "version": "2.0.3", 142 | "resolved": "https://registry.npmjs.org/cli-color/-/cli-color-2.0.3.tgz", 143 | "integrity": "sha512-OkoZnxyC4ERN3zLzZaY9Emb7f/MhBOIpePv0Ycok0fJYT+Ouo00UBEIwsVsr0yoow++n5YWlSUgST9GKhNHiRQ==", 144 | "dependencies": { 145 | "d": "^1.0.1", 146 | "es5-ext": "^0.10.61", 147 | "es6-iterator": "^2.0.3", 148 | "memoizee": "^0.4.15", 149 | "timers-ext": "^0.1.7" 150 | }, 151 | "engines": { 152 | "node": ">=0.10" 153 | } 154 | }, 155 | "node_modules/cliui": { 156 | "version": "7.0.4", 157 | "resolved": "https://registry.npmjs.org/cliui/-/cliui-7.0.4.tgz", 158 | "integrity": "sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ==", 159 | "dependencies": { 160 | "string-width": "^4.2.0", 161 | "strip-ansi": "^6.0.0", 162 | "wrap-ansi": "^7.0.0" 163 | } 164 | }, 165 | "node_modules/color-convert": { 166 | "version": "2.0.1", 167 | "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", 168 | "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", 169 | "dependencies": { 170 | "color-name": "~1.1.4" 171 | }, 172 | "engines": { 173 | "node": ">=7.0.0" 174 | } 175 | }, 176 | "node_modules/color-name": { 177 | "version": "1.1.4", 178 | "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", 179 | "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==" 180 | }, 181 | "node_modules/commander": { 182 | "version": "2.20.3", 183 | "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", 184 | "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==" 185 | }, 186 | "node_modules/concat-map": { 187 | "version": "0.0.1", 188 | "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", 189 | "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==" 190 | }, 191 | "node_modules/config-chain": { 192 | "version": "1.1.13", 193 | "resolved": "https://registry.npmjs.org/config-chain/-/config-chain-1.1.13.tgz", 194 | "integrity": "sha512-qj+f8APARXHrM0hraqXYb2/bOVSV4PvJQlNZ/DVj0QrmNM2q2euizkeuVckQ57J+W0mRH6Hvi+k50M4Jul2VRQ==", 195 | "dependencies": { 196 | "ini": "^1.3.4", 197 | "proto-list": "~1.2.1" 198 | } 199 | }, 200 | "node_modules/create-require": { 201 | "version": "1.1.1", 202 | "resolved": "https://registry.npmjs.org/create-require/-/create-require-1.1.1.tgz", 203 | "integrity": "sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ==", 204 | "dev": true 205 | }, 206 | "node_modules/d": { 207 | "version": "1.0.1", 208 | "resolved": "https://registry.npmjs.org/d/-/d-1.0.1.tgz", 209 | "integrity": "sha512-m62ShEObQ39CfralilEQRjH6oAMtNCV1xJyEx5LpRYUVN+EviphDgUc/F3hnYbADmkiNs67Y+3ylmlG7Lnu+FA==", 210 | "dependencies": { 211 | "es5-ext": "^0.10.50", 212 | "type": "^1.0.1" 213 | } 214 | }, 215 | "node_modules/debug": { 216 | "version": "4.3.4", 217 | "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", 218 | "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", 219 | "dependencies": { 220 | "ms": "2.1.2" 221 | }, 222 | "engines": { 223 | "node": ">=6.0" 224 | }, 225 | "peerDependenciesMeta": { 226 | "supports-color": { 227 | "optional": true 228 | } 229 | } 230 | }, 231 | "node_modules/diff": { 232 | "version": "4.0.2", 233 | "resolved": "https://registry.npmjs.org/diff/-/diff-4.0.2.tgz", 234 | "integrity": "sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==", 235 | "dev": true, 236 | "engines": { 237 | "node": ">=0.3.1" 238 | } 239 | }, 240 | "node_modules/dotenv": { 241 | "version": "16.0.1", 242 | "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-16.0.1.tgz", 243 | "integrity": "sha512-1K6hR6wtk2FviQ4kEiSjFiH5rpzEVi8WW0x96aztHVMhEspNpc4DVOUTEHtEva5VThQ8IaBX1Pe4gSzpVVUsKQ==", 244 | "engines": { 245 | "node": ">=12" 246 | } 247 | }, 248 | "node_modules/dottie": { 249 | "version": "2.0.2", 250 | "resolved": "https://registry.npmjs.org/dottie/-/dottie-2.0.2.tgz", 251 | "integrity": "sha512-fmrwR04lsniq/uSr8yikThDTrM7epXHBAAjH9TbeH3rEA8tdCO7mRzB9hdmdGyJCxF8KERo9CITcm3kGuoyMhg==" 252 | }, 253 | "node_modules/editorconfig": { 254 | "version": "0.15.3", 255 | "resolved": "https://registry.npmjs.org/editorconfig/-/editorconfig-0.15.3.tgz", 256 | "integrity": "sha512-M9wIMFx96vq0R4F+gRpY3o2exzb8hEj/n9S8unZtHSvYjibBp/iMufSzvmOcV/laG0ZtuTVGtiJggPOSW2r93g==", 257 | "dependencies": { 258 | "commander": "^2.19.0", 259 | "lru-cache": "^4.1.5", 260 | "semver": "^5.6.0", 261 | "sigmund": "^1.0.1" 262 | }, 263 | "bin": { 264 | "editorconfig": "bin/editorconfig" 265 | } 266 | }, 267 | "node_modules/editorconfig/node_modules/lru-cache": { 268 | "version": "4.1.5", 269 | "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-4.1.5.tgz", 270 | "integrity": "sha512-sWZlbEP2OsHNkXrMl5GYk/jKk70MBng6UU4YI/qGDYbgf6YbP4EvmqISbXCoJiRKs+1bSpFHVgQxvJ17F2li5g==", 271 | "dependencies": { 272 | "pseudomap": "^1.0.2", 273 | "yallist": "^2.1.2" 274 | } 275 | }, 276 | "node_modules/editorconfig/node_modules/semver": { 277 | "version": "5.7.1", 278 | "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", 279 | "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", 280 | "bin": { 281 | "semver": "bin/semver" 282 | } 283 | }, 284 | "node_modules/editorconfig/node_modules/yallist": { 285 | "version": "2.1.2", 286 | "resolved": "https://registry.npmjs.org/yallist/-/yallist-2.1.2.tgz", 287 | "integrity": "sha512-ncTzHV7NvsQZkYe1DW7cbDLm0YpzHmZF5r/iyP3ZnQtMiJ+pjzisCiMNI+Sj+xQF5pXhSHxSB3uDbsBTzY/c2A==" 288 | }, 289 | "node_modules/emoji-regex": { 290 | "version": "8.0.0", 291 | "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", 292 | "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==" 293 | }, 294 | "node_modules/es5-ext": { 295 | "version": "0.10.61", 296 | "resolved": "https://registry.npmjs.org/es5-ext/-/es5-ext-0.10.61.tgz", 297 | "integrity": "sha512-yFhIqQAzu2Ca2I4SE2Au3rxVfmohU9Y7wqGR+s7+H7krk26NXhIRAZDgqd6xqjCEFUomDEA3/Bo/7fKmIkW1kA==", 298 | "hasInstallScript": true, 299 | "dependencies": { 300 | "es6-iterator": "^2.0.3", 301 | "es6-symbol": "^3.1.3", 302 | "next-tick": "^1.1.0" 303 | }, 304 | "engines": { 305 | "node": ">=0.10" 306 | } 307 | }, 308 | "node_modules/es6-iterator": { 309 | "version": "2.0.3", 310 | "resolved": "https://registry.npmjs.org/es6-iterator/-/es6-iterator-2.0.3.tgz", 311 | "integrity": "sha512-zw4SRzoUkd+cl+ZoE15A9o1oQd920Bb0iOJMQkQhl3jNc03YqVjAhG7scf9C5KWRU/R13Orf588uCC6525o02g==", 312 | "dependencies": { 313 | "d": "1", 314 | "es5-ext": "^0.10.35", 315 | "es6-symbol": "^3.1.1" 316 | } 317 | }, 318 | "node_modules/es6-symbol": { 319 | "version": "3.1.3", 320 | "resolved": "https://registry.npmjs.org/es6-symbol/-/es6-symbol-3.1.3.tgz", 321 | "integrity": "sha512-NJ6Yn3FuDinBaBRWl/q5X/s4koRHBrgKAu+yGI6JCBeiu3qrcbJhwT2GeR/EXVfylRk8dpQVJoLEFhK+Mu31NA==", 322 | "dependencies": { 323 | "d": "^1.0.1", 324 | "ext": "^1.1.2" 325 | } 326 | }, 327 | "node_modules/es6-weak-map": { 328 | "version": "2.0.3", 329 | "resolved": "https://registry.npmjs.org/es6-weak-map/-/es6-weak-map-2.0.3.tgz", 330 | "integrity": "sha512-p5um32HOTO1kP+w7PRnB+5lQ43Z6muuMuIMffvDN8ZB4GcnjLBV6zGStpbASIMk4DCAvEaamhe2zhyCb/QXXsA==", 331 | "dependencies": { 332 | "d": "1", 333 | "es5-ext": "^0.10.46", 334 | "es6-iterator": "^2.0.3", 335 | "es6-symbol": "^3.1.1" 336 | } 337 | }, 338 | "node_modules/escalade": { 339 | "version": "3.1.1", 340 | "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz", 341 | "integrity": "sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==", 342 | "engines": { 343 | "node": ">=6" 344 | } 345 | }, 346 | "node_modules/event-emitter": { 347 | "version": "0.3.5", 348 | "resolved": "https://registry.npmjs.org/event-emitter/-/event-emitter-0.3.5.tgz", 349 | "integrity": "sha512-D9rRn9y7kLPnJ+hMq7S/nhvoKwwvVJahBi2BPmx3bvbsEdK3W9ii8cBSGjP+72/LnM4n6fo3+dkCX5FeTQruXA==", 350 | "dependencies": { 351 | "d": "1", 352 | "es5-ext": "~0.10.14" 353 | } 354 | }, 355 | "node_modules/ext": { 356 | "version": "1.6.0", 357 | "resolved": "https://registry.npmjs.org/ext/-/ext-1.6.0.tgz", 358 | "integrity": "sha512-sdBImtzkq2HpkdRLtlLWDa6w4DX22ijZLKx8BMPUuKe1c5lbN6xwQDQCxSfxBQnHZ13ls/FH0MQZx/q/gr6FQg==", 359 | "dependencies": { 360 | "type": "^2.5.0" 361 | } 362 | }, 363 | "node_modules/ext/node_modules/type": { 364 | "version": "2.6.0", 365 | "resolved": "https://registry.npmjs.org/type/-/type-2.6.0.tgz", 366 | "integrity": "sha512-eiDBDOmkih5pMbo9OqsqPRGMljLodLcwd5XD5JbtNB0o89xZAwynY9EdCDsJU7LtcVCClu9DvM7/0Ep1hYX3EQ==" 367 | }, 368 | "node_modules/fs-extra": { 369 | "version": "9.1.0", 370 | "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-9.1.0.tgz", 371 | "integrity": "sha512-hcg3ZmepS30/7BSFqRvoo3DOMQu7IjqxO5nCDt+zM9XWjb33Wg7ziNT+Qvqbuc3+gWpzO02JubVyk2G4Zvo1OQ==", 372 | "dependencies": { 373 | "at-least-node": "^1.0.0", 374 | "graceful-fs": "^4.2.0", 375 | "jsonfile": "^6.0.1", 376 | "universalify": "^2.0.0" 377 | }, 378 | "engines": { 379 | "node": ">=10" 380 | } 381 | }, 382 | "node_modules/fs.realpath": { 383 | "version": "1.0.0", 384 | "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", 385 | "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==" 386 | }, 387 | "node_modules/function-bind": { 388 | "version": "1.1.1", 389 | "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", 390 | "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==" 391 | }, 392 | "node_modules/get-caller-file": { 393 | "version": "2.0.5", 394 | "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", 395 | "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", 396 | "engines": { 397 | "node": "6.* || 8.* || >= 10.*" 398 | } 399 | }, 400 | "node_modules/glob": { 401 | "version": "8.0.3", 402 | "resolved": "https://registry.npmjs.org/glob/-/glob-8.0.3.tgz", 403 | "integrity": "sha512-ull455NHSHI/Y1FqGaaYFaLGkNMMJbavMrEGFXG/PGrg6y7sutWHUHrz6gy6WEBH6akM1M414dWKCNs+IhKdiQ==", 404 | "dependencies": { 405 | "fs.realpath": "^1.0.0", 406 | "inflight": "^1.0.4", 407 | "inherits": "2", 408 | "minimatch": "^5.0.1", 409 | "once": "^1.3.0" 410 | }, 411 | "engines": { 412 | "node": ">=12" 413 | }, 414 | "funding": { 415 | "url": "https://github.com/sponsors/isaacs" 416 | } 417 | }, 418 | "node_modules/glob/node_modules/brace-expansion": { 419 | "version": "2.0.1", 420 | "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", 421 | "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", 422 | "dependencies": { 423 | "balanced-match": "^1.0.0" 424 | } 425 | }, 426 | "node_modules/glob/node_modules/minimatch": { 427 | "version": "5.1.0", 428 | "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.1.0.tgz", 429 | "integrity": "sha512-9TPBGGak4nHfGZsPBohm9AWg6NoT7QTCehS3BIJABslyZbzxfV78QM2Y6+i741OPZIafFAaiiEMh5OyIrJPgtg==", 430 | "dependencies": { 431 | "brace-expansion": "^2.0.1" 432 | }, 433 | "engines": { 434 | "node": ">=10" 435 | } 436 | }, 437 | "node_modules/graceful-fs": { 438 | "version": "4.2.10", 439 | "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.10.tgz", 440 | "integrity": "sha512-9ByhssR2fPVsNZj478qUUbKfmL0+t5BDVyjShtyZZLiK7ZDAArFFfopyOTj0M05wE2tJPisA4iTnnXl2YoPvOA==" 441 | }, 442 | "node_modules/has": { 443 | "version": "1.0.3", 444 | "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", 445 | "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", 446 | "dependencies": { 447 | "function-bind": "^1.1.1" 448 | }, 449 | "engines": { 450 | "node": ">= 0.4.0" 451 | } 452 | }, 453 | "node_modules/inflection": { 454 | "version": "1.13.2", 455 | "resolved": "https://registry.npmjs.org/inflection/-/inflection-1.13.2.tgz", 456 | "integrity": "sha512-cmZlljCRTBFouT8UzMzrGcVEvkv6D/wBdcdKG7J1QH5cXjtU75Dm+P27v9EKu/Y43UYyCJd1WC4zLebRrC8NBw==", 457 | "engines": [ 458 | "node >= 0.4.0" 459 | ] 460 | }, 461 | "node_modules/inflight": { 462 | "version": "1.0.6", 463 | "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", 464 | "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==", 465 | "dependencies": { 466 | "once": "^1.3.0", 467 | "wrappy": "1" 468 | } 469 | }, 470 | "node_modules/inherits": { 471 | "version": "2.0.4", 472 | "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", 473 | "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" 474 | }, 475 | "node_modules/ini": { 476 | "version": "1.3.8", 477 | "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.8.tgz", 478 | "integrity": "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==" 479 | }, 480 | "node_modules/is-core-module": { 481 | "version": "2.9.0", 482 | "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.9.0.tgz", 483 | "integrity": "sha512-+5FPy5PnwmO3lvfMb0AsoPaBG+5KHUI0wYFXOtYPnVVVspTFUuMZNfNaNVRt3FZadstu2c8x23vykRW/NBoU6A==", 484 | "dependencies": { 485 | "has": "^1.0.3" 486 | }, 487 | "funding": { 488 | "url": "https://github.com/sponsors/ljharb" 489 | } 490 | }, 491 | "node_modules/is-fullwidth-code-point": { 492 | "version": "3.0.0", 493 | "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", 494 | "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", 495 | "engines": { 496 | "node": ">=8" 497 | } 498 | }, 499 | "node_modules/is-promise": { 500 | "version": "2.2.2", 501 | "resolved": "https://registry.npmjs.org/is-promise/-/is-promise-2.2.2.tgz", 502 | "integrity": "sha512-+lP4/6lKUBfQjZ2pdxThZvLUAafmZb8OAxFb8XXtiQmS35INgr85hdOGoEs124ez1FCnZJt6jau/T+alh58QFQ==" 503 | }, 504 | "node_modules/js-beautify": { 505 | "version": "1.14.6", 506 | "resolved": "https://registry.npmjs.org/js-beautify/-/js-beautify-1.14.6.tgz", 507 | "integrity": "sha512-GfofQY5zDp+cuHc+gsEXKPpNw2KbPddreEo35O6jT6i0RVK6LhsoYBhq5TvK4/n74wnA0QbK8gGd+jUZwTMKJw==", 508 | "dependencies": { 509 | "config-chain": "^1.1.13", 510 | "editorconfig": "^0.15.3", 511 | "glob": "^8.0.3", 512 | "nopt": "^6.0.0" 513 | }, 514 | "bin": { 515 | "css-beautify": "js/bin/css-beautify.js", 516 | "html-beautify": "js/bin/html-beautify.js", 517 | "js-beautify": "js/bin/js-beautify.js" 518 | }, 519 | "engines": { 520 | "node": ">=10" 521 | } 522 | }, 523 | "node_modules/jsonfile": { 524 | "version": "6.1.0", 525 | "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz", 526 | "integrity": "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==", 527 | "dependencies": { 528 | "universalify": "^2.0.0" 529 | }, 530 | "optionalDependencies": { 531 | "graceful-fs": "^4.1.6" 532 | } 533 | }, 534 | "node_modules/lodash": { 535 | "version": "4.17.21", 536 | "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", 537 | "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==" 538 | }, 539 | "node_modules/lru-cache": { 540 | "version": "6.0.0", 541 | "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", 542 | "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", 543 | "dependencies": { 544 | "yallist": "^4.0.0" 545 | }, 546 | "engines": { 547 | "node": ">=10" 548 | } 549 | }, 550 | "node_modules/lru-queue": { 551 | "version": "0.1.0", 552 | "resolved": "https://registry.npmjs.org/lru-queue/-/lru-queue-0.1.0.tgz", 553 | "integrity": "sha512-BpdYkt9EvGl8OfWHDQPISVpcl5xZthb+XPsbELj5AQXxIC8IriDZIQYjBJPEm5rS420sjZ0TLEzRcq5KdBhYrQ==", 554 | "dependencies": { 555 | "es5-ext": "~0.10.2" 556 | } 557 | }, 558 | "node_modules/make-error": { 559 | "version": "1.3.6", 560 | "resolved": "https://registry.npmjs.org/make-error/-/make-error-1.3.6.tgz", 561 | "integrity": "sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw==", 562 | "dev": true 563 | }, 564 | "node_modules/memoizee": { 565 | "version": "0.4.15", 566 | "resolved": "https://registry.npmjs.org/memoizee/-/memoizee-0.4.15.tgz", 567 | "integrity": "sha512-UBWmJpLZd5STPm7PMUlOw/TSy972M+z8gcyQ5veOnSDRREz/0bmpyTfKt3/51DhEBqCZQn1udM/5flcSPYhkdQ==", 568 | "dependencies": { 569 | "d": "^1.0.1", 570 | "es5-ext": "^0.10.53", 571 | "es6-weak-map": "^2.0.3", 572 | "event-emitter": "^0.3.5", 573 | "is-promise": "^2.2.2", 574 | "lru-queue": "^0.1.0", 575 | "next-tick": "^1.1.0", 576 | "timers-ext": "^0.1.7" 577 | } 578 | }, 579 | "node_modules/minimatch": { 580 | "version": "3.1.2", 581 | "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", 582 | "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", 583 | "dependencies": { 584 | "brace-expansion": "^1.1.7" 585 | }, 586 | "engines": { 587 | "node": "*" 588 | } 589 | }, 590 | "node_modules/moment": { 591 | "version": "2.29.4", 592 | "resolved": "https://registry.npmjs.org/moment/-/moment-2.29.4.tgz", 593 | "integrity": "sha512-5LC9SOxjSc2HF6vO2CyuTDNivEdoz2IvyJJGj6X8DJ0eFyfszE0QiEd+iXmBvUP3WHxSjFH/vIsA0EN00cgr8w==", 594 | "engines": { 595 | "node": "*" 596 | } 597 | }, 598 | "node_modules/moment-timezone": { 599 | "version": "0.5.37", 600 | "resolved": "https://registry.npmjs.org/moment-timezone/-/moment-timezone-0.5.37.tgz", 601 | "integrity": "sha512-uEDzDNFhfaywRl+vwXxffjjq1q0Vzr+fcQpQ1bU0kbzorfS7zVtZnCnGc8mhWmF39d4g4YriF6kwA75mJKE/Zg==", 602 | "dependencies": { 603 | "moment": ">= 2.9.0" 604 | }, 605 | "engines": { 606 | "node": "*" 607 | } 608 | }, 609 | "node_modules/ms": { 610 | "version": "2.1.2", 611 | "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", 612 | "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" 613 | }, 614 | "node_modules/next-tick": { 615 | "version": "1.1.0", 616 | "resolved": "https://registry.npmjs.org/next-tick/-/next-tick-1.1.0.tgz", 617 | "integrity": "sha512-CXdUiJembsNjuToQvxayPZF9Vqht7hewsvy2sOWafLvi2awflj9mOC6bHIg50orX8IJvWKY9wYQ/zB2kogPslQ==" 618 | }, 619 | "node_modules/nopt": { 620 | "version": "6.0.0", 621 | "resolved": "https://registry.npmjs.org/nopt/-/nopt-6.0.0.tgz", 622 | "integrity": "sha512-ZwLpbTgdhuZUnZzjd7nb1ZV+4DoiC6/sfiVKok72ym/4Tlf+DFdlHYmT2JPmcNNWV6Pi3SDf1kT+A4r9RTuT9g==", 623 | "dependencies": { 624 | "abbrev": "^1.0.0" 625 | }, 626 | "bin": { 627 | "nopt": "bin/nopt.js" 628 | }, 629 | "engines": { 630 | "node": "^12.13.0 || ^14.15.0 || >=16.0.0" 631 | } 632 | }, 633 | "node_modules/once": { 634 | "version": "1.4.0", 635 | "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", 636 | "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", 637 | "dependencies": { 638 | "wrappy": "1" 639 | } 640 | }, 641 | "node_modules/packet-reader": { 642 | "version": "1.0.0", 643 | "resolved": "https://registry.npmjs.org/packet-reader/-/packet-reader-1.0.0.tgz", 644 | "integrity": "sha512-HAKu/fG3HpHFO0AA8WE8q2g+gBJaZ9MG7fcKk+IJPLTGAD6Psw4443l+9DGRbOIh3/aXr7Phy0TjilYivJo5XQ==" 645 | }, 646 | "node_modules/path-is-absolute": { 647 | "version": "1.0.1", 648 | "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", 649 | "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==", 650 | "engines": { 651 | "node": ">=0.10.0" 652 | } 653 | }, 654 | "node_modules/path-parse": { 655 | "version": "1.0.7", 656 | "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", 657 | "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==" 658 | }, 659 | "node_modules/pg": { 660 | "version": "8.7.3", 661 | "resolved": "https://registry.npmjs.org/pg/-/pg-8.7.3.tgz", 662 | "integrity": "sha512-HPmH4GH4H3AOprDJOazoIcpI49XFsHCe8xlrjHkWiapdbHK+HLtbm/GQzXYAZwmPju/kzKhjaSfMACG+8cgJcw==", 663 | "dependencies": { 664 | "buffer-writer": "2.0.0", 665 | "packet-reader": "1.0.0", 666 | "pg-connection-string": "^2.5.0", 667 | "pg-pool": "^3.5.1", 668 | "pg-protocol": "^1.5.0", 669 | "pg-types": "^2.1.0", 670 | "pgpass": "1.x" 671 | }, 672 | "engines": { 673 | "node": ">= 8.0.0" 674 | }, 675 | "peerDependencies": { 676 | "pg-native": ">=2.0.0" 677 | }, 678 | "peerDependenciesMeta": { 679 | "pg-native": { 680 | "optional": true 681 | } 682 | } 683 | }, 684 | "node_modules/pg-connection-string": { 685 | "version": "2.5.0", 686 | "resolved": "https://registry.npmjs.org/pg-connection-string/-/pg-connection-string-2.5.0.tgz", 687 | "integrity": "sha512-r5o/V/ORTA6TmUnyWZR9nCj1klXCO2CEKNRlVuJptZe85QuhFayC7WeMic7ndayT5IRIR0S0xFxFi2ousartlQ==" 688 | }, 689 | "node_modules/pg-int8": { 690 | "version": "1.0.1", 691 | "resolved": "https://registry.npmjs.org/pg-int8/-/pg-int8-1.0.1.tgz", 692 | "integrity": "sha512-WCtabS6t3c8SkpDBUlb1kjOs7l66xsGdKpIPZsg4wR+B3+u9UAum2odSsF9tnvxg80h4ZxLWMy4pRjOsFIqQpw==", 693 | "engines": { 694 | "node": ">=4.0.0" 695 | } 696 | }, 697 | "node_modules/pg-pool": { 698 | "version": "3.5.1", 699 | "resolved": "https://registry.npmjs.org/pg-pool/-/pg-pool-3.5.1.tgz", 700 | "integrity": "sha512-6iCR0wVrro6OOHFsyavV+i6KYL4lVNyYAB9RD18w66xSzN+d8b66HiwuP30Gp1SH5O9T82fckkzsRjlrhD0ioQ==", 701 | "peerDependencies": { 702 | "pg": ">=8.0" 703 | } 704 | }, 705 | "node_modules/pg-protocol": { 706 | "version": "1.5.0", 707 | "resolved": "https://registry.npmjs.org/pg-protocol/-/pg-protocol-1.5.0.tgz", 708 | "integrity": "sha512-muRttij7H8TqRNu/DxrAJQITO4Ac7RmX3Klyr/9mJEOBeIpgnF8f9jAfRz5d3XwQZl5qBjF9gLsUtMPJE0vezQ==" 709 | }, 710 | "node_modules/pg-types": { 711 | "version": "2.2.0", 712 | "resolved": "https://registry.npmjs.org/pg-types/-/pg-types-2.2.0.tgz", 713 | "integrity": "sha512-qTAAlrEsl8s4OiEQY69wDvcMIdQN6wdz5ojQiOy6YRMuynxenON0O5oCpJI6lshc6scgAY8qvJ2On/p+CXY0GA==", 714 | "dependencies": { 715 | "pg-int8": "1.0.1", 716 | "postgres-array": "~2.0.0", 717 | "postgres-bytea": "~1.0.0", 718 | "postgres-date": "~1.0.4", 719 | "postgres-interval": "^1.1.0" 720 | }, 721 | "engines": { 722 | "node": ">=4" 723 | } 724 | }, 725 | "node_modules/pgpass": { 726 | "version": "1.0.5", 727 | "resolved": "https://registry.npmjs.org/pgpass/-/pgpass-1.0.5.tgz", 728 | "integrity": "sha512-FdW9r/jQZhSeohs1Z3sI1yxFQNFvMcnmfuj4WBMUTxOrAyLMaTcE1aAMBiTlbMNaXvBCQuVi0R7hd8udDSP7ug==", 729 | "dependencies": { 730 | "split2": "^4.1.0" 731 | } 732 | }, 733 | "node_modules/postgres-array": { 734 | "version": "2.0.0", 735 | "resolved": "https://registry.npmjs.org/postgres-array/-/postgres-array-2.0.0.tgz", 736 | "integrity": "sha512-VpZrUqU5A69eQyW2c5CA1jtLecCsN2U/bD6VilrFDWq5+5UIEVO7nazS3TEcHf1zuPYO/sqGvUvW62g86RXZuA==", 737 | "engines": { 738 | "node": ">=4" 739 | } 740 | }, 741 | "node_modules/postgres-bytea": { 742 | "version": "1.0.0", 743 | "resolved": "https://registry.npmjs.org/postgres-bytea/-/postgres-bytea-1.0.0.tgz", 744 | "integrity": "sha512-xy3pmLuQqRBZBXDULy7KbaitYqLcmxigw14Q5sj8QBVLqEwXfeybIKVWiqAXTlcvdvb0+xkOtDbfQMOf4lST1w==", 745 | "engines": { 746 | "node": ">=0.10.0" 747 | } 748 | }, 749 | "node_modules/postgres-date": { 750 | "version": "1.0.7", 751 | "resolved": "https://registry.npmjs.org/postgres-date/-/postgres-date-1.0.7.tgz", 752 | "integrity": "sha512-suDmjLVQg78nMK2UZ454hAG+OAW+HQPZ6n++TNDUX+L0+uUlLywnoxJKDou51Zm+zTCjrCl0Nq6J9C5hP9vK/Q==", 753 | "engines": { 754 | "node": ">=0.10.0" 755 | } 756 | }, 757 | "node_modules/postgres-interval": { 758 | "version": "1.2.0", 759 | "resolved": "https://registry.npmjs.org/postgres-interval/-/postgres-interval-1.2.0.tgz", 760 | "integrity": "sha512-9ZhXKM/rw350N1ovuWHbGxnGh/SNJ4cnxHiM0rxE4VN41wsg8P8zWn9hv/buK00RP4WvlOyr/RBDiptyxVbkZQ==", 761 | "dependencies": { 762 | "xtend": "^4.0.0" 763 | }, 764 | "engines": { 765 | "node": ">=0.10.0" 766 | } 767 | }, 768 | "node_modules/proto-list": { 769 | "version": "1.2.4", 770 | "resolved": "https://registry.npmjs.org/proto-list/-/proto-list-1.2.4.tgz", 771 | "integrity": "sha512-vtK/94akxsTMhe0/cbfpR+syPuszcuwhqVjJq26CuNDgFGj682oRBXOP5MJpv2r7JtE8MsiepGIqvvOTBwn2vA==" 772 | }, 773 | "node_modules/pseudomap": { 774 | "version": "1.0.2", 775 | "resolved": "https://registry.npmjs.org/pseudomap/-/pseudomap-1.0.2.tgz", 776 | "integrity": "sha512-b/YwNhb8lk1Zz2+bXXpS/LK9OisiZZ1SNsSLxN1x2OXVEhW2Ckr/7mWE5vrC1ZTiJlD9g19jWszTmJsB+oEpFQ==" 777 | }, 778 | "node_modules/reflect-metadata": { 779 | "version": "0.1.13", 780 | "resolved": "https://registry.npmjs.org/reflect-metadata/-/reflect-metadata-0.1.13.tgz", 781 | "integrity": "sha512-Ts1Y/anZELhSsjMcU605fU9RE4Oi3p5ORujwbIKXfWa+0Zxs510Qrmrce5/Jowq3cHSZSJqBjypxmHarc+vEWg==", 782 | "peer": true 783 | }, 784 | "node_modules/require-directory": { 785 | "version": "2.1.1", 786 | "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", 787 | "integrity": "sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==", 788 | "engines": { 789 | "node": ">=0.10.0" 790 | } 791 | }, 792 | "node_modules/resolve": { 793 | "version": "1.22.1", 794 | "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.1.tgz", 795 | "integrity": "sha512-nBpuuYuY5jFsli/JIs1oldw6fOQCBioohqWZg/2hiaOybXOft4lonv85uDOKXdf8rhyK159cxU5cDcK/NKk8zw==", 796 | "dependencies": { 797 | "is-core-module": "^2.9.0", 798 | "path-parse": "^1.0.7", 799 | "supports-preserve-symlinks-flag": "^1.0.0" 800 | }, 801 | "bin": { 802 | "resolve": "bin/resolve" 803 | }, 804 | "funding": { 805 | "url": "https://github.com/sponsors/ljharb" 806 | } 807 | }, 808 | "node_modules/retry-as-promised": { 809 | "version": "6.1.0", 810 | "resolved": "https://registry.npmjs.org/retry-as-promised/-/retry-as-promised-6.1.0.tgz", 811 | "integrity": "sha512-Hj/jY+wFC+SB9SDlIIFWiGOHnNG0swYbGYsOj2BJ8u2HKUaobNKab0OIC0zOLYzDy0mb7A4xA5BMo4LMz5YtEA==" 812 | }, 813 | "node_modules/semver": { 814 | "version": "7.3.7", 815 | "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.7.tgz", 816 | "integrity": "sha512-QlYTucUYOews+WeEujDoEGziz4K6c47V/Bd+LjSSYcA94p+DmINdf7ncaUinThfvZyu13lN9OY1XDxt8C0Tw0g==", 817 | "dependencies": { 818 | "lru-cache": "^6.0.0" 819 | }, 820 | "bin": { 821 | "semver": "bin/semver.js" 822 | }, 823 | "engines": { 824 | "node": ">=10" 825 | } 826 | }, 827 | "node_modules/sequelize": { 828 | "version": "6.23.2", 829 | "resolved": "https://registry.npmjs.org/sequelize/-/sequelize-6.23.2.tgz", 830 | "integrity": "sha512-0jy5pkRV7LZlBArIrYKfpKa+DowC+fIcI6LrWDfvdqFmuXZfmS4qq8gzFmIu0C210ts2Mmw/dghzRhX73xPoMg==", 831 | "funding": [ 832 | { 833 | "type": "opencollective", 834 | "url": "https://opencollective.com/sequelize" 835 | } 836 | ], 837 | "dependencies": { 838 | "@types/debug": "^4.1.7", 839 | "@types/validator": "^13.7.1", 840 | "debug": "^4.3.3", 841 | "dottie": "^2.0.2", 842 | "inflection": "^1.13.2", 843 | "lodash": "^4.17.21", 844 | "moment": "^2.29.1", 845 | "moment-timezone": "^0.5.34", 846 | "pg-connection-string": "^2.5.0", 847 | "retry-as-promised": "^6.1.0", 848 | "semver": "^7.3.5", 849 | "sequelize-pool": "^7.1.0", 850 | "toposort-class": "^1.0.1", 851 | "uuid": "^8.3.2", 852 | "validator": "^13.7.0", 853 | "wkx": "^0.5.0" 854 | }, 855 | "engines": { 856 | "node": ">=10.0.0" 857 | }, 858 | "peerDependenciesMeta": { 859 | "ibm_db": { 860 | "optional": true 861 | }, 862 | "mariadb": { 863 | "optional": true 864 | }, 865 | "mysql2": { 866 | "optional": true 867 | }, 868 | "oracledb": { 869 | "optional": true 870 | }, 871 | "pg": { 872 | "optional": true 873 | }, 874 | "pg-hstore": { 875 | "optional": true 876 | }, 877 | "snowflake-sdk": { 878 | "optional": true 879 | }, 880 | "sqlite3": { 881 | "optional": true 882 | }, 883 | "tedious": { 884 | "optional": true 885 | } 886 | } 887 | }, 888 | "node_modules/sequelize-cli": { 889 | "version": "6.5.1", 890 | "resolved": "https://registry.npmjs.org/sequelize-cli/-/sequelize-cli-6.5.1.tgz", 891 | "integrity": "sha512-36hfZKNeZkIshp6L0jPVQ27xNLzgDPpiZokQsvo0M882AtAm+KhGOIViR0BecWb0Xz8+uSq03xxcl7RfMgyIRA==", 892 | "dependencies": { 893 | "cli-color": "^2.0.3", 894 | "fs-extra": "^9.1.0", 895 | "js-beautify": "^1.14.5", 896 | "lodash": "^4.17.21", 897 | "resolve": "^1.22.1", 898 | "umzug": "^2.3.0", 899 | "yargs": "^16.2.0" 900 | }, 901 | "bin": { 902 | "sequelize": "lib/sequelize", 903 | "sequelize-cli": "lib/sequelize" 904 | }, 905 | "engines": { 906 | "node": ">=10.0.0" 907 | } 908 | }, 909 | "node_modules/sequelize-pool": { 910 | "version": "7.1.0", 911 | "resolved": "https://registry.npmjs.org/sequelize-pool/-/sequelize-pool-7.1.0.tgz", 912 | "integrity": "sha512-G9c0qlIWQSK29pR/5U2JF5dDQeqqHRragoyahj/Nx4KOOQ3CPPfzxnfqFPCSB7x5UgjOgnZ61nSxz+fjDpRlJg==", 913 | "engines": { 914 | "node": ">= 10.0.0" 915 | } 916 | }, 917 | "node_modules/sequelize-typescript": { 918 | "version": "2.1.3", 919 | "resolved": "https://registry.npmjs.org/sequelize-typescript/-/sequelize-typescript-2.1.3.tgz", 920 | "integrity": "sha512-0mejGAaLywuCoOOLSXCQs2sMBNudU/QtWZkGY5VT2dfTHToXZi5bOxCa3/CukNNk7wJwXnLuIdeHdlqjvVoj1g==", 921 | "dependencies": { 922 | "glob": "7.2.0" 923 | }, 924 | "engines": { 925 | "node": ">=10.0.0" 926 | }, 927 | "peerDependencies": { 928 | "@types/node": "*", 929 | "@types/validator": "*", 930 | "reflect-metadata": "*", 931 | "sequelize": ">=6.8.0" 932 | } 933 | }, 934 | "node_modules/sequelize-typescript/node_modules/glob": { 935 | "version": "7.2.0", 936 | "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.0.tgz", 937 | "integrity": "sha512-lmLf6gtyrPq8tTjSmrO94wBeQbFR3HbLHbuyD69wuyQkImp2hWqMGB47OX65FBkPffO641IP9jWa1z4ivqG26Q==", 938 | "dependencies": { 939 | "fs.realpath": "^1.0.0", 940 | "inflight": "^1.0.4", 941 | "inherits": "2", 942 | "minimatch": "^3.0.4", 943 | "once": "^1.3.0", 944 | "path-is-absolute": "^1.0.0" 945 | }, 946 | "engines": { 947 | "node": "*" 948 | }, 949 | "funding": { 950 | "url": "https://github.com/sponsors/isaacs" 951 | } 952 | }, 953 | "node_modules/sigmund": { 954 | "version": "1.0.1", 955 | "resolved": "https://registry.npmjs.org/sigmund/-/sigmund-1.0.1.tgz", 956 | "integrity": "sha512-fCvEXfh6NWpm+YSuY2bpXb/VIihqWA6hLsgboC+0nl71Q7N7o2eaCW8mJa/NLvQhs6jpd3VZV4UiUQlV6+lc8g==" 957 | }, 958 | "node_modules/source-map": { 959 | "version": "0.6.1", 960 | "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", 961 | "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", 962 | "dev": true, 963 | "engines": { 964 | "node": ">=0.10.0" 965 | } 966 | }, 967 | "node_modules/source-map-support": { 968 | "version": "0.5.19", 969 | "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.19.tgz", 970 | "integrity": "sha512-Wonm7zOCIJzBGQdB+thsPar0kYuCIzYvxZwlBa87yi/Mdjv7Tip2cyVbLj5o0cFPN4EVkuTwb3GDDyUx2DGnGw==", 971 | "dev": true, 972 | "dependencies": { 973 | "buffer-from": "^1.0.0", 974 | "source-map": "^0.6.0" 975 | } 976 | }, 977 | "node_modules/split2": { 978 | "version": "4.1.0", 979 | "resolved": "https://registry.npmjs.org/split2/-/split2-4.1.0.tgz", 980 | "integrity": "sha512-VBiJxFkxiXRlUIeyMQi8s4hgvKCSjtknJv/LVYbrgALPwf5zSKmEwV9Lst25AkvMDnvxODugjdl6KZgwKM1WYQ==", 981 | "engines": { 982 | "node": ">= 10.x" 983 | } 984 | }, 985 | "node_modules/string-width": { 986 | "version": "4.2.3", 987 | "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", 988 | "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", 989 | "dependencies": { 990 | "emoji-regex": "^8.0.0", 991 | "is-fullwidth-code-point": "^3.0.0", 992 | "strip-ansi": "^6.0.1" 993 | }, 994 | "engines": { 995 | "node": ">=8" 996 | } 997 | }, 998 | "node_modules/strip-ansi": { 999 | "version": "6.0.1", 1000 | "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", 1001 | "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", 1002 | "dependencies": { 1003 | "ansi-regex": "^5.0.1" 1004 | }, 1005 | "engines": { 1006 | "node": ">=8" 1007 | } 1008 | }, 1009 | "node_modules/supports-preserve-symlinks-flag": { 1010 | "version": "1.0.0", 1011 | "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz", 1012 | "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==", 1013 | "engines": { 1014 | "node": ">= 0.4" 1015 | }, 1016 | "funding": { 1017 | "url": "https://github.com/sponsors/ljharb" 1018 | } 1019 | }, 1020 | "node_modules/timers-ext": { 1021 | "version": "0.1.7", 1022 | "resolved": "https://registry.npmjs.org/timers-ext/-/timers-ext-0.1.7.tgz", 1023 | "integrity": "sha512-b85NUNzTSdodShTIbky6ZF02e8STtVVfD+fu4aXXShEELpozH+bCpJLYMPZbsABN2wDH7fJpqIoXxJpzbf0NqQ==", 1024 | "dependencies": { 1025 | "es5-ext": "~0.10.46", 1026 | "next-tick": "1" 1027 | } 1028 | }, 1029 | "node_modules/toposort-class": { 1030 | "version": "1.0.1", 1031 | "resolved": "https://registry.npmjs.org/toposort-class/-/toposort-class-1.0.1.tgz", 1032 | "integrity": "sha512-OsLcGGbYF3rMjPUf8oKktyvCiUxSbqMMS39m33MAjLTC1DVIH6x3WSt63/M77ihI09+Sdfk1AXvfhCEeUmC7mg==" 1033 | }, 1034 | "node_modules/ts-node": { 1035 | "version": "10.0.0", 1036 | "resolved": "https://registry.npmjs.org/ts-node/-/ts-node-10.0.0.tgz", 1037 | "integrity": "sha512-ROWeOIUvfFbPZkoDis0L/55Fk+6gFQNZwwKPLinacRl6tsxstTF1DbAcLKkovwnpKMVvOMHP1TIbnwXwtLg1gg==", 1038 | "dev": true, 1039 | "dependencies": { 1040 | "@tsconfig/node10": "^1.0.7", 1041 | "@tsconfig/node12": "^1.0.7", 1042 | "@tsconfig/node14": "^1.0.0", 1043 | "@tsconfig/node16": "^1.0.1", 1044 | "arg": "^4.1.0", 1045 | "create-require": "^1.1.0", 1046 | "diff": "^4.0.1", 1047 | "make-error": "^1.1.1", 1048 | "source-map-support": "^0.5.17", 1049 | "yn": "3.1.1" 1050 | }, 1051 | "bin": { 1052 | "ts-node": "dist/bin.js", 1053 | "ts-node-cwd": "dist/bin-cwd.js", 1054 | "ts-node-script": "dist/bin-script.js", 1055 | "ts-node-transpile-only": "dist/bin-transpile.js", 1056 | "ts-script": "dist/bin-script-deprecated.js" 1057 | }, 1058 | "engines": { 1059 | "node": ">=12.0.0" 1060 | }, 1061 | "peerDependencies": { 1062 | "@swc/core": ">=1.2.45", 1063 | "@swc/wasm": ">=1.2.45", 1064 | "@types/node": "*", 1065 | "typescript": ">=2.7" 1066 | }, 1067 | "peerDependenciesMeta": { 1068 | "@swc/core": { 1069 | "optional": true 1070 | }, 1071 | "@swc/wasm": { 1072 | "optional": true 1073 | } 1074 | } 1075 | }, 1076 | "node_modules/type": { 1077 | "version": "1.2.0", 1078 | "resolved": "https://registry.npmjs.org/type/-/type-1.2.0.tgz", 1079 | "integrity": "sha512-+5nt5AAniqsCnu2cEQQdpzCAh33kVx8n0VoFidKpB1dVVLAN/F+bgVOqOJqOnEnrhp222clB5p3vUlD+1QAnfg==" 1080 | }, 1081 | "node_modules/typescript": { 1082 | "version": "4.7.4", 1083 | "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.7.4.tgz", 1084 | "integrity": "sha512-C0WQT0gezHuw6AdY1M2jxUO83Rjf0HP7Sk1DtXj6j1EwkQNZrHAg2XPWlq62oqEhYvONq5pkC2Y9oPljWToLmQ==", 1085 | "bin": { 1086 | "tsc": "bin/tsc", 1087 | "tsserver": "bin/tsserver" 1088 | }, 1089 | "engines": { 1090 | "node": ">=4.2.0" 1091 | } 1092 | }, 1093 | "node_modules/umzug": { 1094 | "version": "2.3.0", 1095 | "resolved": "https://registry.npmjs.org/umzug/-/umzug-2.3.0.tgz", 1096 | "integrity": "sha512-Z274K+e8goZK8QJxmbRPhl89HPO1K+ORFtm6rySPhFKfKc5GHhqdzD0SGhSWHkzoXasqJuItdhorSvY7/Cgflw==", 1097 | "dependencies": { 1098 | "bluebird": "^3.7.2" 1099 | }, 1100 | "engines": { 1101 | "node": ">=6.0.0" 1102 | } 1103 | }, 1104 | "node_modules/universalify": { 1105 | "version": "2.0.0", 1106 | "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.0.tgz", 1107 | "integrity": "sha512-hAZsKq7Yy11Zu1DE0OzWjw7nnLZmJZYTDZZyEFHZdUhV8FkH5MCfoU1XMaxXovpyW5nq5scPqq0ZDP9Zyl04oQ==", 1108 | "engines": { 1109 | "node": ">= 10.0.0" 1110 | } 1111 | }, 1112 | "node_modules/uuid": { 1113 | "version": "8.3.2", 1114 | "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz", 1115 | "integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==", 1116 | "bin": { 1117 | "uuid": "dist/bin/uuid" 1118 | } 1119 | }, 1120 | "node_modules/validator": { 1121 | "version": "13.7.0", 1122 | "resolved": "https://registry.npmjs.org/validator/-/validator-13.7.0.tgz", 1123 | "integrity": "sha512-nYXQLCBkpJ8X6ltALua9dRrZDHVYxjJ1wgskNt1lH9fzGjs3tgojGSCBjmEPwkWS1y29+DrizMTW19Pr9uB2nw==", 1124 | "engines": { 1125 | "node": ">= 0.10" 1126 | } 1127 | }, 1128 | "node_modules/wkx": { 1129 | "version": "0.5.0", 1130 | "resolved": "https://registry.npmjs.org/wkx/-/wkx-0.5.0.tgz", 1131 | "integrity": "sha512-Xng/d4Ichh8uN4l0FToV/258EjMGU9MGcA0HV2d9B/ZpZB3lqQm7nkOdZdm5GhKtLLhAE7PiVQwN4eN+2YJJUg==", 1132 | "dependencies": { 1133 | "@types/node": "*" 1134 | } 1135 | }, 1136 | "node_modules/wrap-ansi": { 1137 | "version": "7.0.0", 1138 | "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", 1139 | "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", 1140 | "dependencies": { 1141 | "ansi-styles": "^4.0.0", 1142 | "string-width": "^4.1.0", 1143 | "strip-ansi": "^6.0.0" 1144 | }, 1145 | "engines": { 1146 | "node": ">=10" 1147 | }, 1148 | "funding": { 1149 | "url": "https://github.com/chalk/wrap-ansi?sponsor=1" 1150 | } 1151 | }, 1152 | "node_modules/wrappy": { 1153 | "version": "1.0.2", 1154 | "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", 1155 | "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==" 1156 | }, 1157 | "node_modules/xtend": { 1158 | "version": "4.0.2", 1159 | "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz", 1160 | "integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==", 1161 | "engines": { 1162 | "node": ">=0.4" 1163 | } 1164 | }, 1165 | "node_modules/y18n": { 1166 | "version": "5.0.8", 1167 | "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", 1168 | "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==", 1169 | "engines": { 1170 | "node": ">=10" 1171 | } 1172 | }, 1173 | "node_modules/yallist": { 1174 | "version": "4.0.0", 1175 | "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", 1176 | "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" 1177 | }, 1178 | "node_modules/yargs": { 1179 | "version": "16.2.0", 1180 | "resolved": "https://registry.npmjs.org/yargs/-/yargs-16.2.0.tgz", 1181 | "integrity": "sha512-D1mvvtDG0L5ft/jGWkLpG1+m0eQxOfaBvTNELraWj22wSVUMWxZUvYgJYcKh6jGGIkJFhH4IZPQhR4TKpc8mBw==", 1182 | "dependencies": { 1183 | "cliui": "^7.0.2", 1184 | "escalade": "^3.1.1", 1185 | "get-caller-file": "^2.0.5", 1186 | "require-directory": "^2.1.1", 1187 | "string-width": "^4.2.0", 1188 | "y18n": "^5.0.5", 1189 | "yargs-parser": "^20.2.2" 1190 | }, 1191 | "engines": { 1192 | "node": ">=10" 1193 | } 1194 | }, 1195 | "node_modules/yargs-parser": { 1196 | "version": "20.2.9", 1197 | "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-20.2.9.tgz", 1198 | "integrity": "sha512-y11nGElTIV+CT3Zv9t7VKl+Q3hTQoT9a1Qzezhhl6Rp21gJ/IVTW7Z3y9EWXhuUBC2Shnf+DX0antecpAwSP8w==", 1199 | "engines": { 1200 | "node": ">=10" 1201 | } 1202 | }, 1203 | "node_modules/yn": { 1204 | "version": "3.1.1", 1205 | "resolved": "https://registry.npmjs.org/yn/-/yn-3.1.1.tgz", 1206 | "integrity": "sha512-Ux4ygGWsu2c7isFWe8Yu1YluJmqVhxqK2cLXNQA5AcC3QfbGNpM7fu0Y8b/z16pXLnFxZYvWhd3fhBY9DLmC6Q==", 1207 | "dev": true, 1208 | "engines": { 1209 | "node": ">=6" 1210 | } 1211 | } 1212 | }, 1213 | "dependencies": { 1214 | "@tsconfig/node10": { 1215 | "version": "1.0.8", 1216 | "resolved": "https://registry.npmjs.org/@tsconfig/node10/-/node10-1.0.8.tgz", 1217 | "integrity": "sha512-6XFfSQmMgq0CFLY1MslA/CPUfhIL919M1rMsa5lP2P097N2Wd1sSX0tx1u4olM16fLNhtHZpRhedZJphNJqmZg==", 1218 | "dev": true 1219 | }, 1220 | "@tsconfig/node12": { 1221 | "version": "1.0.9", 1222 | "resolved": "https://registry.npmjs.org/@tsconfig/node12/-/node12-1.0.9.tgz", 1223 | "integrity": "sha512-/yBMcem+fbvhSREH+s14YJi18sp7J9jpuhYByADT2rypfajMZZN4WQ6zBGgBKp53NKmqI36wFYDb3yaMPurITw==", 1224 | "dev": true 1225 | }, 1226 | "@tsconfig/node14": { 1227 | "version": "1.0.1", 1228 | "resolved": "https://registry.npmjs.org/@tsconfig/node14/-/node14-1.0.1.tgz", 1229 | "integrity": "sha512-509r2+yARFfHHE7T6Puu2jjkoycftovhXRqW328PDXTVGKihlb1P8Z9mMZH04ebyajfRY7dedfGynlrFHJUQCg==", 1230 | "dev": true 1231 | }, 1232 | "@tsconfig/node16": { 1233 | "version": "1.0.1", 1234 | "resolved": "https://registry.npmjs.org/@tsconfig/node16/-/node16-1.0.1.tgz", 1235 | "integrity": "sha512-FTgBI767POY/lKNDNbIzgAX6miIDBs6NTCbdlDb8TrWovHsSvaVIZDlTqym29C6UqhzwcJx4CYr+AlrMywA0cA==", 1236 | "dev": true 1237 | }, 1238 | "@types/debug": { 1239 | "version": "4.1.7", 1240 | "resolved": "https://registry.npmjs.org/@types/debug/-/debug-4.1.7.tgz", 1241 | "integrity": "sha512-9AonUzyTjXXhEOa0DnqpzZi6VHlqKMswga9EXjpXnnqxwLtdvPPtlO8evrI5D9S6asFRCQ6v+wpiUKbw+vKqyg==", 1242 | "requires": { 1243 | "@types/ms": "*" 1244 | } 1245 | }, 1246 | "@types/ms": { 1247 | "version": "0.7.31", 1248 | "resolved": "https://registry.npmjs.org/@types/ms/-/ms-0.7.31.tgz", 1249 | "integrity": "sha512-iiUgKzV9AuaEkZqkOLDIvlQiL6ltuZd9tGcW3gwpnX8JbuiuhFlEGmmFXEXkN50Cvq7Os88IY2v0dkDqXYWVgA==" 1250 | }, 1251 | "@types/node": { 1252 | "version": "18.6.1", 1253 | "resolved": "https://registry.npmjs.org/@types/node/-/node-18.6.1.tgz", 1254 | "integrity": "sha512-z+2vB6yDt1fNwKOeGbckpmirO+VBDuQqecXkgeIqDlaOtmKn6hPR/viQ8cxCfqLU4fTlvM3+YjM367TukWdxpg==" 1255 | }, 1256 | "@types/validator": { 1257 | "version": "13.7.4", 1258 | "resolved": "https://registry.npmjs.org/@types/validator/-/validator-13.7.4.tgz", 1259 | "integrity": "sha512-uAaSWegu2lymY18l+s5nmcXu3sFeeTOl1zhSGoYzcr6T3wz1M+3OcW4UjfPhIhHGd13tIMRDsEpR+d8w/MexwQ==" 1260 | }, 1261 | "abbrev": { 1262 | "version": "1.1.1", 1263 | "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.1.1.tgz", 1264 | "integrity": "sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==" 1265 | }, 1266 | "ansi-regex": { 1267 | "version": "5.0.1", 1268 | "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", 1269 | "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==" 1270 | }, 1271 | "ansi-styles": { 1272 | "version": "4.3.0", 1273 | "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", 1274 | "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", 1275 | "requires": { 1276 | "color-convert": "^2.0.1" 1277 | } 1278 | }, 1279 | "arg": { 1280 | "version": "4.1.3", 1281 | "resolved": "https://registry.npmjs.org/arg/-/arg-4.1.3.tgz", 1282 | "integrity": "sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA==", 1283 | "dev": true 1284 | }, 1285 | "at-least-node": { 1286 | "version": "1.0.0", 1287 | "resolved": "https://registry.npmjs.org/at-least-node/-/at-least-node-1.0.0.tgz", 1288 | "integrity": "sha512-+q/t7Ekv1EDY2l6Gda6LLiX14rU9TV20Wa3ofeQmwPFZbOMo9DXrLbOjFaaclkXKWidIaopwAObQDqwWtGUjqg==" 1289 | }, 1290 | "balanced-match": { 1291 | "version": "1.0.2", 1292 | "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", 1293 | "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==" 1294 | }, 1295 | "bluebird": { 1296 | "version": "3.7.2", 1297 | "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.7.2.tgz", 1298 | "integrity": "sha512-XpNj6GDQzdfW+r2Wnn7xiSAd7TM3jzkxGXBGTtWKuSXv1xUV+azxAm8jdWZN06QTQk+2N2XB9jRDkvbmQmcRtg==" 1299 | }, 1300 | "brace-expansion": { 1301 | "version": "1.1.11", 1302 | "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", 1303 | "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", 1304 | "requires": { 1305 | "balanced-match": "^1.0.0", 1306 | "concat-map": "0.0.1" 1307 | } 1308 | }, 1309 | "buffer-from": { 1310 | "version": "1.1.1", 1311 | "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.1.tgz", 1312 | "integrity": "sha512-MQcXEUbCKtEo7bhqEs6560Hyd4XaovZlO/k9V3hjVUF/zwW7KBVdSK4gIt/bzwS9MbR5qob+F5jusZsb0YQK2A==", 1313 | "dev": true 1314 | }, 1315 | "buffer-writer": { 1316 | "version": "2.0.0", 1317 | "resolved": "https://registry.npmjs.org/buffer-writer/-/buffer-writer-2.0.0.tgz", 1318 | "integrity": "sha512-a7ZpuTZU1TRtnwyCNW3I5dc0wWNC3VR9S++Ewyk2HHZdrO3CQJqSpd+95Us590V6AL7JqUAH2IwZ/398PmNFgw==" 1319 | }, 1320 | "cli-color": { 1321 | "version": "2.0.3", 1322 | "resolved": "https://registry.npmjs.org/cli-color/-/cli-color-2.0.3.tgz", 1323 | "integrity": "sha512-OkoZnxyC4ERN3zLzZaY9Emb7f/MhBOIpePv0Ycok0fJYT+Ouo00UBEIwsVsr0yoow++n5YWlSUgST9GKhNHiRQ==", 1324 | "requires": { 1325 | "d": "^1.0.1", 1326 | "es5-ext": "^0.10.61", 1327 | "es6-iterator": "^2.0.3", 1328 | "memoizee": "^0.4.15", 1329 | "timers-ext": "^0.1.7" 1330 | } 1331 | }, 1332 | "cliui": { 1333 | "version": "7.0.4", 1334 | "resolved": "https://registry.npmjs.org/cliui/-/cliui-7.0.4.tgz", 1335 | "integrity": "sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ==", 1336 | "requires": { 1337 | "string-width": "^4.2.0", 1338 | "strip-ansi": "^6.0.0", 1339 | "wrap-ansi": "^7.0.0" 1340 | } 1341 | }, 1342 | "color-convert": { 1343 | "version": "2.0.1", 1344 | "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", 1345 | "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", 1346 | "requires": { 1347 | "color-name": "~1.1.4" 1348 | } 1349 | }, 1350 | "color-name": { 1351 | "version": "1.1.4", 1352 | "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", 1353 | "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==" 1354 | }, 1355 | "commander": { 1356 | "version": "2.20.3", 1357 | "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", 1358 | "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==" 1359 | }, 1360 | "concat-map": { 1361 | "version": "0.0.1", 1362 | "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", 1363 | "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==" 1364 | }, 1365 | "config-chain": { 1366 | "version": "1.1.13", 1367 | "resolved": "https://registry.npmjs.org/config-chain/-/config-chain-1.1.13.tgz", 1368 | "integrity": "sha512-qj+f8APARXHrM0hraqXYb2/bOVSV4PvJQlNZ/DVj0QrmNM2q2euizkeuVckQ57J+W0mRH6Hvi+k50M4Jul2VRQ==", 1369 | "requires": { 1370 | "ini": "^1.3.4", 1371 | "proto-list": "~1.2.1" 1372 | } 1373 | }, 1374 | "create-require": { 1375 | "version": "1.1.1", 1376 | "resolved": "https://registry.npmjs.org/create-require/-/create-require-1.1.1.tgz", 1377 | "integrity": "sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ==", 1378 | "dev": true 1379 | }, 1380 | "d": { 1381 | "version": "1.0.1", 1382 | "resolved": "https://registry.npmjs.org/d/-/d-1.0.1.tgz", 1383 | "integrity": "sha512-m62ShEObQ39CfralilEQRjH6oAMtNCV1xJyEx5LpRYUVN+EviphDgUc/F3hnYbADmkiNs67Y+3ylmlG7Lnu+FA==", 1384 | "requires": { 1385 | "es5-ext": "^0.10.50", 1386 | "type": "^1.0.1" 1387 | } 1388 | }, 1389 | "debug": { 1390 | "version": "4.3.4", 1391 | "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", 1392 | "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", 1393 | "requires": { 1394 | "ms": "2.1.2" 1395 | } 1396 | }, 1397 | "diff": { 1398 | "version": "4.0.2", 1399 | "resolved": "https://registry.npmjs.org/diff/-/diff-4.0.2.tgz", 1400 | "integrity": "sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==", 1401 | "dev": true 1402 | }, 1403 | "dotenv": { 1404 | "version": "16.0.1", 1405 | "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-16.0.1.tgz", 1406 | "integrity": "sha512-1K6hR6wtk2FviQ4kEiSjFiH5rpzEVi8WW0x96aztHVMhEspNpc4DVOUTEHtEva5VThQ8IaBX1Pe4gSzpVVUsKQ==" 1407 | }, 1408 | "dottie": { 1409 | "version": "2.0.2", 1410 | "resolved": "https://registry.npmjs.org/dottie/-/dottie-2.0.2.tgz", 1411 | "integrity": "sha512-fmrwR04lsniq/uSr8yikThDTrM7epXHBAAjH9TbeH3rEA8tdCO7mRzB9hdmdGyJCxF8KERo9CITcm3kGuoyMhg==" 1412 | }, 1413 | "editorconfig": { 1414 | "version": "0.15.3", 1415 | "resolved": "https://registry.npmjs.org/editorconfig/-/editorconfig-0.15.3.tgz", 1416 | "integrity": "sha512-M9wIMFx96vq0R4F+gRpY3o2exzb8hEj/n9S8unZtHSvYjibBp/iMufSzvmOcV/laG0ZtuTVGtiJggPOSW2r93g==", 1417 | "requires": { 1418 | "commander": "^2.19.0", 1419 | "lru-cache": "^4.1.5", 1420 | "semver": "^5.6.0", 1421 | "sigmund": "^1.0.1" 1422 | }, 1423 | "dependencies": { 1424 | "lru-cache": { 1425 | "version": "4.1.5", 1426 | "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-4.1.5.tgz", 1427 | "integrity": "sha512-sWZlbEP2OsHNkXrMl5GYk/jKk70MBng6UU4YI/qGDYbgf6YbP4EvmqISbXCoJiRKs+1bSpFHVgQxvJ17F2li5g==", 1428 | "requires": { 1429 | "pseudomap": "^1.0.2", 1430 | "yallist": "^2.1.2" 1431 | } 1432 | }, 1433 | "semver": { 1434 | "version": "5.7.1", 1435 | "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", 1436 | "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==" 1437 | }, 1438 | "yallist": { 1439 | "version": "2.1.2", 1440 | "resolved": "https://registry.npmjs.org/yallist/-/yallist-2.1.2.tgz", 1441 | "integrity": "sha512-ncTzHV7NvsQZkYe1DW7cbDLm0YpzHmZF5r/iyP3ZnQtMiJ+pjzisCiMNI+Sj+xQF5pXhSHxSB3uDbsBTzY/c2A==" 1442 | } 1443 | } 1444 | }, 1445 | "emoji-regex": { 1446 | "version": "8.0.0", 1447 | "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", 1448 | "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==" 1449 | }, 1450 | "es5-ext": { 1451 | "version": "0.10.61", 1452 | "resolved": "https://registry.npmjs.org/es5-ext/-/es5-ext-0.10.61.tgz", 1453 | "integrity": "sha512-yFhIqQAzu2Ca2I4SE2Au3rxVfmohU9Y7wqGR+s7+H7krk26NXhIRAZDgqd6xqjCEFUomDEA3/Bo/7fKmIkW1kA==", 1454 | "requires": { 1455 | "es6-iterator": "^2.0.3", 1456 | "es6-symbol": "^3.1.3", 1457 | "next-tick": "^1.1.0" 1458 | } 1459 | }, 1460 | "es6-iterator": { 1461 | "version": "2.0.3", 1462 | "resolved": "https://registry.npmjs.org/es6-iterator/-/es6-iterator-2.0.3.tgz", 1463 | "integrity": "sha512-zw4SRzoUkd+cl+ZoE15A9o1oQd920Bb0iOJMQkQhl3jNc03YqVjAhG7scf9C5KWRU/R13Orf588uCC6525o02g==", 1464 | "requires": { 1465 | "d": "1", 1466 | "es5-ext": "^0.10.35", 1467 | "es6-symbol": "^3.1.1" 1468 | } 1469 | }, 1470 | "es6-symbol": { 1471 | "version": "3.1.3", 1472 | "resolved": "https://registry.npmjs.org/es6-symbol/-/es6-symbol-3.1.3.tgz", 1473 | "integrity": "sha512-NJ6Yn3FuDinBaBRWl/q5X/s4koRHBrgKAu+yGI6JCBeiu3qrcbJhwT2GeR/EXVfylRk8dpQVJoLEFhK+Mu31NA==", 1474 | "requires": { 1475 | "d": "^1.0.1", 1476 | "ext": "^1.1.2" 1477 | } 1478 | }, 1479 | "es6-weak-map": { 1480 | "version": "2.0.3", 1481 | "resolved": "https://registry.npmjs.org/es6-weak-map/-/es6-weak-map-2.0.3.tgz", 1482 | "integrity": "sha512-p5um32HOTO1kP+w7PRnB+5lQ43Z6muuMuIMffvDN8ZB4GcnjLBV6zGStpbASIMk4DCAvEaamhe2zhyCb/QXXsA==", 1483 | "requires": { 1484 | "d": "1", 1485 | "es5-ext": "^0.10.46", 1486 | "es6-iterator": "^2.0.3", 1487 | "es6-symbol": "^3.1.1" 1488 | } 1489 | }, 1490 | "escalade": { 1491 | "version": "3.1.1", 1492 | "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz", 1493 | "integrity": "sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==" 1494 | }, 1495 | "event-emitter": { 1496 | "version": "0.3.5", 1497 | "resolved": "https://registry.npmjs.org/event-emitter/-/event-emitter-0.3.5.tgz", 1498 | "integrity": "sha512-D9rRn9y7kLPnJ+hMq7S/nhvoKwwvVJahBi2BPmx3bvbsEdK3W9ii8cBSGjP+72/LnM4n6fo3+dkCX5FeTQruXA==", 1499 | "requires": { 1500 | "d": "1", 1501 | "es5-ext": "~0.10.14" 1502 | } 1503 | }, 1504 | "ext": { 1505 | "version": "1.6.0", 1506 | "resolved": "https://registry.npmjs.org/ext/-/ext-1.6.0.tgz", 1507 | "integrity": "sha512-sdBImtzkq2HpkdRLtlLWDa6w4DX22ijZLKx8BMPUuKe1c5lbN6xwQDQCxSfxBQnHZ13ls/FH0MQZx/q/gr6FQg==", 1508 | "requires": { 1509 | "type": "^2.5.0" 1510 | }, 1511 | "dependencies": { 1512 | "type": { 1513 | "version": "2.6.0", 1514 | "resolved": "https://registry.npmjs.org/type/-/type-2.6.0.tgz", 1515 | "integrity": "sha512-eiDBDOmkih5pMbo9OqsqPRGMljLodLcwd5XD5JbtNB0o89xZAwynY9EdCDsJU7LtcVCClu9DvM7/0Ep1hYX3EQ==" 1516 | } 1517 | } 1518 | }, 1519 | "fs-extra": { 1520 | "version": "9.1.0", 1521 | "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-9.1.0.tgz", 1522 | "integrity": "sha512-hcg3ZmepS30/7BSFqRvoo3DOMQu7IjqxO5nCDt+zM9XWjb33Wg7ziNT+Qvqbuc3+gWpzO02JubVyk2G4Zvo1OQ==", 1523 | "requires": { 1524 | "at-least-node": "^1.0.0", 1525 | "graceful-fs": "^4.2.0", 1526 | "jsonfile": "^6.0.1", 1527 | "universalify": "^2.0.0" 1528 | } 1529 | }, 1530 | "fs.realpath": { 1531 | "version": "1.0.0", 1532 | "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", 1533 | "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==" 1534 | }, 1535 | "function-bind": { 1536 | "version": "1.1.1", 1537 | "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", 1538 | "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==" 1539 | }, 1540 | "get-caller-file": { 1541 | "version": "2.0.5", 1542 | "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", 1543 | "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==" 1544 | }, 1545 | "glob": { 1546 | "version": "8.0.3", 1547 | "resolved": "https://registry.npmjs.org/glob/-/glob-8.0.3.tgz", 1548 | "integrity": "sha512-ull455NHSHI/Y1FqGaaYFaLGkNMMJbavMrEGFXG/PGrg6y7sutWHUHrz6gy6WEBH6akM1M414dWKCNs+IhKdiQ==", 1549 | "requires": { 1550 | "fs.realpath": "^1.0.0", 1551 | "inflight": "^1.0.4", 1552 | "inherits": "2", 1553 | "minimatch": "^5.0.1", 1554 | "once": "^1.3.0" 1555 | }, 1556 | "dependencies": { 1557 | "brace-expansion": { 1558 | "version": "2.0.1", 1559 | "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", 1560 | "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", 1561 | "requires": { 1562 | "balanced-match": "^1.0.0" 1563 | } 1564 | }, 1565 | "minimatch": { 1566 | "version": "5.1.0", 1567 | "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.1.0.tgz", 1568 | "integrity": "sha512-9TPBGGak4nHfGZsPBohm9AWg6NoT7QTCehS3BIJABslyZbzxfV78QM2Y6+i741OPZIafFAaiiEMh5OyIrJPgtg==", 1569 | "requires": { 1570 | "brace-expansion": "^2.0.1" 1571 | } 1572 | } 1573 | } 1574 | }, 1575 | "graceful-fs": { 1576 | "version": "4.2.10", 1577 | "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.10.tgz", 1578 | "integrity": "sha512-9ByhssR2fPVsNZj478qUUbKfmL0+t5BDVyjShtyZZLiK7ZDAArFFfopyOTj0M05wE2tJPisA4iTnnXl2YoPvOA==" 1579 | }, 1580 | "has": { 1581 | "version": "1.0.3", 1582 | "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", 1583 | "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", 1584 | "requires": { 1585 | "function-bind": "^1.1.1" 1586 | } 1587 | }, 1588 | "inflection": { 1589 | "version": "1.13.2", 1590 | "resolved": "https://registry.npmjs.org/inflection/-/inflection-1.13.2.tgz", 1591 | "integrity": "sha512-cmZlljCRTBFouT8UzMzrGcVEvkv6D/wBdcdKG7J1QH5cXjtU75Dm+P27v9EKu/Y43UYyCJd1WC4zLebRrC8NBw==" 1592 | }, 1593 | "inflight": { 1594 | "version": "1.0.6", 1595 | "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", 1596 | "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==", 1597 | "requires": { 1598 | "once": "^1.3.0", 1599 | "wrappy": "1" 1600 | } 1601 | }, 1602 | "inherits": { 1603 | "version": "2.0.4", 1604 | "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", 1605 | "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" 1606 | }, 1607 | "ini": { 1608 | "version": "1.3.8", 1609 | "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.8.tgz", 1610 | "integrity": "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==" 1611 | }, 1612 | "is-core-module": { 1613 | "version": "2.9.0", 1614 | "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.9.0.tgz", 1615 | "integrity": "sha512-+5FPy5PnwmO3lvfMb0AsoPaBG+5KHUI0wYFXOtYPnVVVspTFUuMZNfNaNVRt3FZadstu2c8x23vykRW/NBoU6A==", 1616 | "requires": { 1617 | "has": "^1.0.3" 1618 | } 1619 | }, 1620 | "is-fullwidth-code-point": { 1621 | "version": "3.0.0", 1622 | "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", 1623 | "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==" 1624 | }, 1625 | "is-promise": { 1626 | "version": "2.2.2", 1627 | "resolved": "https://registry.npmjs.org/is-promise/-/is-promise-2.2.2.tgz", 1628 | "integrity": "sha512-+lP4/6lKUBfQjZ2pdxThZvLUAafmZb8OAxFb8XXtiQmS35INgr85hdOGoEs124ez1FCnZJt6jau/T+alh58QFQ==" 1629 | }, 1630 | "js-beautify": { 1631 | "version": "1.14.6", 1632 | "resolved": "https://registry.npmjs.org/js-beautify/-/js-beautify-1.14.6.tgz", 1633 | "integrity": "sha512-GfofQY5zDp+cuHc+gsEXKPpNw2KbPddreEo35O6jT6i0RVK6LhsoYBhq5TvK4/n74wnA0QbK8gGd+jUZwTMKJw==", 1634 | "requires": { 1635 | "config-chain": "^1.1.13", 1636 | "editorconfig": "^0.15.3", 1637 | "glob": "^8.0.3", 1638 | "nopt": "^6.0.0" 1639 | } 1640 | }, 1641 | "jsonfile": { 1642 | "version": "6.1.0", 1643 | "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz", 1644 | "integrity": "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==", 1645 | "requires": { 1646 | "graceful-fs": "^4.1.6", 1647 | "universalify": "^2.0.0" 1648 | } 1649 | }, 1650 | "lodash": { 1651 | "version": "4.17.21", 1652 | "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", 1653 | "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==" 1654 | }, 1655 | "lru-cache": { 1656 | "version": "6.0.0", 1657 | "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", 1658 | "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", 1659 | "requires": { 1660 | "yallist": "^4.0.0" 1661 | } 1662 | }, 1663 | "lru-queue": { 1664 | "version": "0.1.0", 1665 | "resolved": "https://registry.npmjs.org/lru-queue/-/lru-queue-0.1.0.tgz", 1666 | "integrity": "sha512-BpdYkt9EvGl8OfWHDQPISVpcl5xZthb+XPsbELj5AQXxIC8IriDZIQYjBJPEm5rS420sjZ0TLEzRcq5KdBhYrQ==", 1667 | "requires": { 1668 | "es5-ext": "~0.10.2" 1669 | } 1670 | }, 1671 | "make-error": { 1672 | "version": "1.3.6", 1673 | "resolved": "https://registry.npmjs.org/make-error/-/make-error-1.3.6.tgz", 1674 | "integrity": "sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw==", 1675 | "dev": true 1676 | }, 1677 | "memoizee": { 1678 | "version": "0.4.15", 1679 | "resolved": "https://registry.npmjs.org/memoizee/-/memoizee-0.4.15.tgz", 1680 | "integrity": "sha512-UBWmJpLZd5STPm7PMUlOw/TSy972M+z8gcyQ5veOnSDRREz/0bmpyTfKt3/51DhEBqCZQn1udM/5flcSPYhkdQ==", 1681 | "requires": { 1682 | "d": "^1.0.1", 1683 | "es5-ext": "^0.10.53", 1684 | "es6-weak-map": "^2.0.3", 1685 | "event-emitter": "^0.3.5", 1686 | "is-promise": "^2.2.2", 1687 | "lru-queue": "^0.1.0", 1688 | "next-tick": "^1.1.0", 1689 | "timers-ext": "^0.1.7" 1690 | } 1691 | }, 1692 | "minimatch": { 1693 | "version": "3.1.2", 1694 | "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", 1695 | "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", 1696 | "requires": { 1697 | "brace-expansion": "^1.1.7" 1698 | } 1699 | }, 1700 | "moment": { 1701 | "version": "2.29.4", 1702 | "resolved": "https://registry.npmjs.org/moment/-/moment-2.29.4.tgz", 1703 | "integrity": "sha512-5LC9SOxjSc2HF6vO2CyuTDNivEdoz2IvyJJGj6X8DJ0eFyfszE0QiEd+iXmBvUP3WHxSjFH/vIsA0EN00cgr8w==" 1704 | }, 1705 | "moment-timezone": { 1706 | "version": "0.5.37", 1707 | "resolved": "https://registry.npmjs.org/moment-timezone/-/moment-timezone-0.5.37.tgz", 1708 | "integrity": "sha512-uEDzDNFhfaywRl+vwXxffjjq1q0Vzr+fcQpQ1bU0kbzorfS7zVtZnCnGc8mhWmF39d4g4YriF6kwA75mJKE/Zg==", 1709 | "requires": { 1710 | "moment": ">= 2.9.0" 1711 | } 1712 | }, 1713 | "ms": { 1714 | "version": "2.1.2", 1715 | "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", 1716 | "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" 1717 | }, 1718 | "next-tick": { 1719 | "version": "1.1.0", 1720 | "resolved": "https://registry.npmjs.org/next-tick/-/next-tick-1.1.0.tgz", 1721 | "integrity": "sha512-CXdUiJembsNjuToQvxayPZF9Vqht7hewsvy2sOWafLvi2awflj9mOC6bHIg50orX8IJvWKY9wYQ/zB2kogPslQ==" 1722 | }, 1723 | "nopt": { 1724 | "version": "6.0.0", 1725 | "resolved": "https://registry.npmjs.org/nopt/-/nopt-6.0.0.tgz", 1726 | "integrity": "sha512-ZwLpbTgdhuZUnZzjd7nb1ZV+4DoiC6/sfiVKok72ym/4Tlf+DFdlHYmT2JPmcNNWV6Pi3SDf1kT+A4r9RTuT9g==", 1727 | "requires": { 1728 | "abbrev": "^1.0.0" 1729 | } 1730 | }, 1731 | "once": { 1732 | "version": "1.4.0", 1733 | "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", 1734 | "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", 1735 | "requires": { 1736 | "wrappy": "1" 1737 | } 1738 | }, 1739 | "packet-reader": { 1740 | "version": "1.0.0", 1741 | "resolved": "https://registry.npmjs.org/packet-reader/-/packet-reader-1.0.0.tgz", 1742 | "integrity": "sha512-HAKu/fG3HpHFO0AA8WE8q2g+gBJaZ9MG7fcKk+IJPLTGAD6Psw4443l+9DGRbOIh3/aXr7Phy0TjilYivJo5XQ==" 1743 | }, 1744 | "path-is-absolute": { 1745 | "version": "1.0.1", 1746 | "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", 1747 | "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==" 1748 | }, 1749 | "path-parse": { 1750 | "version": "1.0.7", 1751 | "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", 1752 | "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==" 1753 | }, 1754 | "pg": { 1755 | "version": "8.7.3", 1756 | "resolved": "https://registry.npmjs.org/pg/-/pg-8.7.3.tgz", 1757 | "integrity": "sha512-HPmH4GH4H3AOprDJOazoIcpI49XFsHCe8xlrjHkWiapdbHK+HLtbm/GQzXYAZwmPju/kzKhjaSfMACG+8cgJcw==", 1758 | "requires": { 1759 | "buffer-writer": "2.0.0", 1760 | "packet-reader": "1.0.0", 1761 | "pg-connection-string": "^2.5.0", 1762 | "pg-pool": "^3.5.1", 1763 | "pg-protocol": "^1.5.0", 1764 | "pg-types": "^2.1.0", 1765 | "pgpass": "1.x" 1766 | } 1767 | }, 1768 | "pg-connection-string": { 1769 | "version": "2.5.0", 1770 | "resolved": "https://registry.npmjs.org/pg-connection-string/-/pg-connection-string-2.5.0.tgz", 1771 | "integrity": "sha512-r5o/V/ORTA6TmUnyWZR9nCj1klXCO2CEKNRlVuJptZe85QuhFayC7WeMic7ndayT5IRIR0S0xFxFi2ousartlQ==" 1772 | }, 1773 | "pg-int8": { 1774 | "version": "1.0.1", 1775 | "resolved": "https://registry.npmjs.org/pg-int8/-/pg-int8-1.0.1.tgz", 1776 | "integrity": "sha512-WCtabS6t3c8SkpDBUlb1kjOs7l66xsGdKpIPZsg4wR+B3+u9UAum2odSsF9tnvxg80h4ZxLWMy4pRjOsFIqQpw==" 1777 | }, 1778 | "pg-pool": { 1779 | "version": "3.5.1", 1780 | "resolved": "https://registry.npmjs.org/pg-pool/-/pg-pool-3.5.1.tgz", 1781 | "integrity": "sha512-6iCR0wVrro6OOHFsyavV+i6KYL4lVNyYAB9RD18w66xSzN+d8b66HiwuP30Gp1SH5O9T82fckkzsRjlrhD0ioQ==", 1782 | "requires": {} 1783 | }, 1784 | "pg-protocol": { 1785 | "version": "1.5.0", 1786 | "resolved": "https://registry.npmjs.org/pg-protocol/-/pg-protocol-1.5.0.tgz", 1787 | "integrity": "sha512-muRttij7H8TqRNu/DxrAJQITO4Ac7RmX3Klyr/9mJEOBeIpgnF8f9jAfRz5d3XwQZl5qBjF9gLsUtMPJE0vezQ==" 1788 | }, 1789 | "pg-types": { 1790 | "version": "2.2.0", 1791 | "resolved": "https://registry.npmjs.org/pg-types/-/pg-types-2.2.0.tgz", 1792 | "integrity": "sha512-qTAAlrEsl8s4OiEQY69wDvcMIdQN6wdz5ojQiOy6YRMuynxenON0O5oCpJI6lshc6scgAY8qvJ2On/p+CXY0GA==", 1793 | "requires": { 1794 | "pg-int8": "1.0.1", 1795 | "postgres-array": "~2.0.0", 1796 | "postgres-bytea": "~1.0.0", 1797 | "postgres-date": "~1.0.4", 1798 | "postgres-interval": "^1.1.0" 1799 | } 1800 | }, 1801 | "pgpass": { 1802 | "version": "1.0.5", 1803 | "resolved": "https://registry.npmjs.org/pgpass/-/pgpass-1.0.5.tgz", 1804 | "integrity": "sha512-FdW9r/jQZhSeohs1Z3sI1yxFQNFvMcnmfuj4WBMUTxOrAyLMaTcE1aAMBiTlbMNaXvBCQuVi0R7hd8udDSP7ug==", 1805 | "requires": { 1806 | "split2": "^4.1.0" 1807 | } 1808 | }, 1809 | "postgres-array": { 1810 | "version": "2.0.0", 1811 | "resolved": "https://registry.npmjs.org/postgres-array/-/postgres-array-2.0.0.tgz", 1812 | "integrity": "sha512-VpZrUqU5A69eQyW2c5CA1jtLecCsN2U/bD6VilrFDWq5+5UIEVO7nazS3TEcHf1zuPYO/sqGvUvW62g86RXZuA==" 1813 | }, 1814 | "postgres-bytea": { 1815 | "version": "1.0.0", 1816 | "resolved": "https://registry.npmjs.org/postgres-bytea/-/postgres-bytea-1.0.0.tgz", 1817 | "integrity": "sha512-xy3pmLuQqRBZBXDULy7KbaitYqLcmxigw14Q5sj8QBVLqEwXfeybIKVWiqAXTlcvdvb0+xkOtDbfQMOf4lST1w==" 1818 | }, 1819 | "postgres-date": { 1820 | "version": "1.0.7", 1821 | "resolved": "https://registry.npmjs.org/postgres-date/-/postgres-date-1.0.7.tgz", 1822 | "integrity": "sha512-suDmjLVQg78nMK2UZ454hAG+OAW+HQPZ6n++TNDUX+L0+uUlLywnoxJKDou51Zm+zTCjrCl0Nq6J9C5hP9vK/Q==" 1823 | }, 1824 | "postgres-interval": { 1825 | "version": "1.2.0", 1826 | "resolved": "https://registry.npmjs.org/postgres-interval/-/postgres-interval-1.2.0.tgz", 1827 | "integrity": "sha512-9ZhXKM/rw350N1ovuWHbGxnGh/SNJ4cnxHiM0rxE4VN41wsg8P8zWn9hv/buK00RP4WvlOyr/RBDiptyxVbkZQ==", 1828 | "requires": { 1829 | "xtend": "^4.0.0" 1830 | } 1831 | }, 1832 | "proto-list": { 1833 | "version": "1.2.4", 1834 | "resolved": "https://registry.npmjs.org/proto-list/-/proto-list-1.2.4.tgz", 1835 | "integrity": "sha512-vtK/94akxsTMhe0/cbfpR+syPuszcuwhqVjJq26CuNDgFGj682oRBXOP5MJpv2r7JtE8MsiepGIqvvOTBwn2vA==" 1836 | }, 1837 | "pseudomap": { 1838 | "version": "1.0.2", 1839 | "resolved": "https://registry.npmjs.org/pseudomap/-/pseudomap-1.0.2.tgz", 1840 | "integrity": "sha512-b/YwNhb8lk1Zz2+bXXpS/LK9OisiZZ1SNsSLxN1x2OXVEhW2Ckr/7mWE5vrC1ZTiJlD9g19jWszTmJsB+oEpFQ==" 1841 | }, 1842 | "reflect-metadata": { 1843 | "version": "0.1.13", 1844 | "resolved": "https://registry.npmjs.org/reflect-metadata/-/reflect-metadata-0.1.13.tgz", 1845 | "integrity": "sha512-Ts1Y/anZELhSsjMcU605fU9RE4Oi3p5ORujwbIKXfWa+0Zxs510Qrmrce5/Jowq3cHSZSJqBjypxmHarc+vEWg==", 1846 | "peer": true 1847 | }, 1848 | "require-directory": { 1849 | "version": "2.1.1", 1850 | "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", 1851 | "integrity": "sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==" 1852 | }, 1853 | "resolve": { 1854 | "version": "1.22.1", 1855 | "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.1.tgz", 1856 | "integrity": "sha512-nBpuuYuY5jFsli/JIs1oldw6fOQCBioohqWZg/2hiaOybXOft4lonv85uDOKXdf8rhyK159cxU5cDcK/NKk8zw==", 1857 | "requires": { 1858 | "is-core-module": "^2.9.0", 1859 | "path-parse": "^1.0.7", 1860 | "supports-preserve-symlinks-flag": "^1.0.0" 1861 | } 1862 | }, 1863 | "retry-as-promised": { 1864 | "version": "6.1.0", 1865 | "resolved": "https://registry.npmjs.org/retry-as-promised/-/retry-as-promised-6.1.0.tgz", 1866 | "integrity": "sha512-Hj/jY+wFC+SB9SDlIIFWiGOHnNG0swYbGYsOj2BJ8u2HKUaobNKab0OIC0zOLYzDy0mb7A4xA5BMo4LMz5YtEA==" 1867 | }, 1868 | "semver": { 1869 | "version": "7.3.7", 1870 | "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.7.tgz", 1871 | "integrity": "sha512-QlYTucUYOews+WeEujDoEGziz4K6c47V/Bd+LjSSYcA94p+DmINdf7ncaUinThfvZyu13lN9OY1XDxt8C0Tw0g==", 1872 | "requires": { 1873 | "lru-cache": "^6.0.0" 1874 | } 1875 | }, 1876 | "sequelize": { 1877 | "version": "6.23.2", 1878 | "resolved": "https://registry.npmjs.org/sequelize/-/sequelize-6.23.2.tgz", 1879 | "integrity": "sha512-0jy5pkRV7LZlBArIrYKfpKa+DowC+fIcI6LrWDfvdqFmuXZfmS4qq8gzFmIu0C210ts2Mmw/dghzRhX73xPoMg==", 1880 | "requires": { 1881 | "@types/debug": "^4.1.7", 1882 | "@types/validator": "^13.7.1", 1883 | "debug": "^4.3.3", 1884 | "dottie": "^2.0.2", 1885 | "inflection": "^1.13.2", 1886 | "lodash": "^4.17.21", 1887 | "moment": "^2.29.1", 1888 | "moment-timezone": "^0.5.34", 1889 | "pg-connection-string": "^2.5.0", 1890 | "retry-as-promised": "^6.1.0", 1891 | "semver": "^7.3.5", 1892 | "sequelize-pool": "^7.1.0", 1893 | "toposort-class": "^1.0.1", 1894 | "uuid": "^8.3.2", 1895 | "validator": "^13.7.0", 1896 | "wkx": "^0.5.0" 1897 | } 1898 | }, 1899 | "sequelize-cli": { 1900 | "version": "6.5.1", 1901 | "resolved": "https://registry.npmjs.org/sequelize-cli/-/sequelize-cli-6.5.1.tgz", 1902 | "integrity": "sha512-36hfZKNeZkIshp6L0jPVQ27xNLzgDPpiZokQsvo0M882AtAm+KhGOIViR0BecWb0Xz8+uSq03xxcl7RfMgyIRA==", 1903 | "requires": { 1904 | "cli-color": "^2.0.3", 1905 | "fs-extra": "^9.1.0", 1906 | "js-beautify": "^1.14.5", 1907 | "lodash": "^4.17.21", 1908 | "resolve": "^1.22.1", 1909 | "umzug": "^2.3.0", 1910 | "yargs": "^16.2.0" 1911 | } 1912 | }, 1913 | "sequelize-pool": { 1914 | "version": "7.1.0", 1915 | "resolved": "https://registry.npmjs.org/sequelize-pool/-/sequelize-pool-7.1.0.tgz", 1916 | "integrity": "sha512-G9c0qlIWQSK29pR/5U2JF5dDQeqqHRragoyahj/Nx4KOOQ3CPPfzxnfqFPCSB7x5UgjOgnZ61nSxz+fjDpRlJg==" 1917 | }, 1918 | "sequelize-typescript": { 1919 | "version": "2.1.3", 1920 | "resolved": "https://registry.npmjs.org/sequelize-typescript/-/sequelize-typescript-2.1.3.tgz", 1921 | "integrity": "sha512-0mejGAaLywuCoOOLSXCQs2sMBNudU/QtWZkGY5VT2dfTHToXZi5bOxCa3/CukNNk7wJwXnLuIdeHdlqjvVoj1g==", 1922 | "requires": { 1923 | "glob": "7.2.0" 1924 | }, 1925 | "dependencies": { 1926 | "glob": { 1927 | "version": "7.2.0", 1928 | "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.0.tgz", 1929 | "integrity": "sha512-lmLf6gtyrPq8tTjSmrO94wBeQbFR3HbLHbuyD69wuyQkImp2hWqMGB47OX65FBkPffO641IP9jWa1z4ivqG26Q==", 1930 | "requires": { 1931 | "fs.realpath": "^1.0.0", 1932 | "inflight": "^1.0.4", 1933 | "inherits": "2", 1934 | "minimatch": "^3.0.4", 1935 | "once": "^1.3.0", 1936 | "path-is-absolute": "^1.0.0" 1937 | } 1938 | } 1939 | } 1940 | }, 1941 | "sigmund": { 1942 | "version": "1.0.1", 1943 | "resolved": "https://registry.npmjs.org/sigmund/-/sigmund-1.0.1.tgz", 1944 | "integrity": "sha512-fCvEXfh6NWpm+YSuY2bpXb/VIihqWA6hLsgboC+0nl71Q7N7o2eaCW8mJa/NLvQhs6jpd3VZV4UiUQlV6+lc8g==" 1945 | }, 1946 | "source-map": { 1947 | "version": "0.6.1", 1948 | "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", 1949 | "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", 1950 | "dev": true 1951 | }, 1952 | "source-map-support": { 1953 | "version": "0.5.19", 1954 | "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.19.tgz", 1955 | "integrity": "sha512-Wonm7zOCIJzBGQdB+thsPar0kYuCIzYvxZwlBa87yi/Mdjv7Tip2cyVbLj5o0cFPN4EVkuTwb3GDDyUx2DGnGw==", 1956 | "dev": true, 1957 | "requires": { 1958 | "buffer-from": "^1.0.0", 1959 | "source-map": "^0.6.0" 1960 | } 1961 | }, 1962 | "split2": { 1963 | "version": "4.1.0", 1964 | "resolved": "https://registry.npmjs.org/split2/-/split2-4.1.0.tgz", 1965 | "integrity": "sha512-VBiJxFkxiXRlUIeyMQi8s4hgvKCSjtknJv/LVYbrgALPwf5zSKmEwV9Lst25AkvMDnvxODugjdl6KZgwKM1WYQ==" 1966 | }, 1967 | "string-width": { 1968 | "version": "4.2.3", 1969 | "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", 1970 | "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", 1971 | "requires": { 1972 | "emoji-regex": "^8.0.0", 1973 | "is-fullwidth-code-point": "^3.0.0", 1974 | "strip-ansi": "^6.0.1" 1975 | } 1976 | }, 1977 | "strip-ansi": { 1978 | "version": "6.0.1", 1979 | "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", 1980 | "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", 1981 | "requires": { 1982 | "ansi-regex": "^5.0.1" 1983 | } 1984 | }, 1985 | "supports-preserve-symlinks-flag": { 1986 | "version": "1.0.0", 1987 | "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz", 1988 | "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==" 1989 | }, 1990 | "timers-ext": { 1991 | "version": "0.1.7", 1992 | "resolved": "https://registry.npmjs.org/timers-ext/-/timers-ext-0.1.7.tgz", 1993 | "integrity": "sha512-b85NUNzTSdodShTIbky6ZF02e8STtVVfD+fu4aXXShEELpozH+bCpJLYMPZbsABN2wDH7fJpqIoXxJpzbf0NqQ==", 1994 | "requires": { 1995 | "es5-ext": "~0.10.46", 1996 | "next-tick": "1" 1997 | } 1998 | }, 1999 | "toposort-class": { 2000 | "version": "1.0.1", 2001 | "resolved": "https://registry.npmjs.org/toposort-class/-/toposort-class-1.0.1.tgz", 2002 | "integrity": "sha512-OsLcGGbYF3rMjPUf8oKktyvCiUxSbqMMS39m33MAjLTC1DVIH6x3WSt63/M77ihI09+Sdfk1AXvfhCEeUmC7mg==" 2003 | }, 2004 | "ts-node": { 2005 | "version": "10.0.0", 2006 | "resolved": "https://registry.npmjs.org/ts-node/-/ts-node-10.0.0.tgz", 2007 | "integrity": "sha512-ROWeOIUvfFbPZkoDis0L/55Fk+6gFQNZwwKPLinacRl6tsxstTF1DbAcLKkovwnpKMVvOMHP1TIbnwXwtLg1gg==", 2008 | "dev": true, 2009 | "requires": { 2010 | "@tsconfig/node10": "^1.0.7", 2011 | "@tsconfig/node12": "^1.0.7", 2012 | "@tsconfig/node14": "^1.0.0", 2013 | "@tsconfig/node16": "^1.0.1", 2014 | "arg": "^4.1.0", 2015 | "create-require": "^1.1.0", 2016 | "diff": "^4.0.1", 2017 | "make-error": "^1.1.1", 2018 | "source-map-support": "^0.5.17", 2019 | "yn": "3.1.1" 2020 | } 2021 | }, 2022 | "type": { 2023 | "version": "1.2.0", 2024 | "resolved": "https://registry.npmjs.org/type/-/type-1.2.0.tgz", 2025 | "integrity": "sha512-+5nt5AAniqsCnu2cEQQdpzCAh33kVx8n0VoFidKpB1dVVLAN/F+bgVOqOJqOnEnrhp222clB5p3vUlD+1QAnfg==" 2026 | }, 2027 | "typescript": { 2028 | "version": "4.7.4", 2029 | "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.7.4.tgz", 2030 | "integrity": "sha512-C0WQT0gezHuw6AdY1M2jxUO83Rjf0HP7Sk1DtXj6j1EwkQNZrHAg2XPWlq62oqEhYvONq5pkC2Y9oPljWToLmQ==" 2031 | }, 2032 | "umzug": { 2033 | "version": "2.3.0", 2034 | "resolved": "https://registry.npmjs.org/umzug/-/umzug-2.3.0.tgz", 2035 | "integrity": "sha512-Z274K+e8goZK8QJxmbRPhl89HPO1K+ORFtm6rySPhFKfKc5GHhqdzD0SGhSWHkzoXasqJuItdhorSvY7/Cgflw==", 2036 | "requires": { 2037 | "bluebird": "^3.7.2" 2038 | } 2039 | }, 2040 | "universalify": { 2041 | "version": "2.0.0", 2042 | "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.0.tgz", 2043 | "integrity": "sha512-hAZsKq7Yy11Zu1DE0OzWjw7nnLZmJZYTDZZyEFHZdUhV8FkH5MCfoU1XMaxXovpyW5nq5scPqq0ZDP9Zyl04oQ==" 2044 | }, 2045 | "uuid": { 2046 | "version": "8.3.2", 2047 | "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz", 2048 | "integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==" 2049 | }, 2050 | "validator": { 2051 | "version": "13.7.0", 2052 | "resolved": "https://registry.npmjs.org/validator/-/validator-13.7.0.tgz", 2053 | "integrity": "sha512-nYXQLCBkpJ8X6ltALua9dRrZDHVYxjJ1wgskNt1lH9fzGjs3tgojGSCBjmEPwkWS1y29+DrizMTW19Pr9uB2nw==" 2054 | }, 2055 | "wkx": { 2056 | "version": "0.5.0", 2057 | "resolved": "https://registry.npmjs.org/wkx/-/wkx-0.5.0.tgz", 2058 | "integrity": "sha512-Xng/d4Ichh8uN4l0FToV/258EjMGU9MGcA0HV2d9B/ZpZB3lqQm7nkOdZdm5GhKtLLhAE7PiVQwN4eN+2YJJUg==", 2059 | "requires": { 2060 | "@types/node": "*" 2061 | } 2062 | }, 2063 | "wrap-ansi": { 2064 | "version": "7.0.0", 2065 | "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", 2066 | "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", 2067 | "requires": { 2068 | "ansi-styles": "^4.0.0", 2069 | "string-width": "^4.1.0", 2070 | "strip-ansi": "^6.0.0" 2071 | } 2072 | }, 2073 | "wrappy": { 2074 | "version": "1.0.2", 2075 | "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", 2076 | "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==" 2077 | }, 2078 | "xtend": { 2079 | "version": "4.0.2", 2080 | "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz", 2081 | "integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==" 2082 | }, 2083 | "y18n": { 2084 | "version": "5.0.8", 2085 | "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", 2086 | "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==" 2087 | }, 2088 | "yallist": { 2089 | "version": "4.0.0", 2090 | "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", 2091 | "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" 2092 | }, 2093 | "yargs": { 2094 | "version": "16.2.0", 2095 | "resolved": "https://registry.npmjs.org/yargs/-/yargs-16.2.0.tgz", 2096 | "integrity": "sha512-D1mvvtDG0L5ft/jGWkLpG1+m0eQxOfaBvTNELraWj22wSVUMWxZUvYgJYcKh6jGGIkJFhH4IZPQhR4TKpc8mBw==", 2097 | "requires": { 2098 | "cliui": "^7.0.2", 2099 | "escalade": "^3.1.1", 2100 | "get-caller-file": "^2.0.5", 2101 | "require-directory": "^2.1.1", 2102 | "string-width": "^4.2.0", 2103 | "y18n": "^5.0.5", 2104 | "yargs-parser": "^20.2.2" 2105 | } 2106 | }, 2107 | "yargs-parser": { 2108 | "version": "20.2.9", 2109 | "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-20.2.9.tgz", 2110 | "integrity": "sha512-y11nGElTIV+CT3Zv9t7VKl+Q3hTQoT9a1Qzezhhl6Rp21gJ/IVTW7Z3y9EWXhuUBC2Shnf+DX0antecpAwSP8w==" 2111 | }, 2112 | "yn": { 2113 | "version": "3.1.1", 2114 | "resolved": "https://registry.npmjs.org/yn/-/yn-3.1.1.tgz", 2115 | "integrity": "sha512-Ux4ygGWsu2c7isFWe8Yu1YluJmqVhxqK2cLXNQA5AcC3QfbGNpM7fu0Y8b/z16pXLnFxZYvWhd3fhBY9DLmC6Q==", 2116 | "dev": true 2117 | } 2118 | } 2119 | } 2120 | -------------------------------------------------------------------------------- /example/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "scripts": { 3 | "build": "tsc", 4 | "practice": "ts-node -T -r tsconfig-paths/register practice.ts", 5 | "configure": "cp db/config.example.json db/config.json", 6 | "db:init": "sequelize init", 7 | "db:create": "sequelize db:create", 8 | "db:drop": "sequelize db:drop", 9 | "db:migrate": "sequelize db:migrate", 10 | "db:migrate:create": "ts-node -T -r tsconfig-paths/register practice.ts", 11 | "db:migrate:undo": "sequelize db:migrate:undo", 12 | "db:migrate:undo:all": "sequelize db:migrate:undo:all" 13 | }, 14 | "dependencies": { 15 | "dotenv": "^16.0.1", 16 | "pg": "^8.7.3", 17 | "sequelize": "^6.23.2", 18 | "sequelize-cli": "^6.5.1", 19 | "sequelize-typescript": "^2.1.3", 20 | "typescript": "^4.3.5" 21 | }, 22 | "devDependencies": { 23 | "ts-node": "^10.0.0" 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /example/practice.ts: -------------------------------------------------------------------------------- 1 | import { SequelizeTypescriptMigration } from "../src"; 2 | import { Sequelize } from "sequelize-typescript"; 3 | import { join } from "path"; 4 | import dotenv from "dotenv"; 5 | 6 | import { Car } from "models/car.model"; 7 | import { CarBrand } from "models/car_brand.model"; 8 | import { Dialect } from "sequelize"; 9 | 10 | dotenv.config(); 11 | 12 | const bootstrap = async () => { 13 | const sequelize: Sequelize = new Sequelize({ 14 | username: process.env.DATABASE_USER, 15 | password: process.env.DATABASE_PASS, 16 | database: process.env.DATABASE_NAME, 17 | host: process.env.DATABASE_HOST, 18 | dialect: process.env.DATABASE_DIALECT as Dialect, 19 | models: [CarBrand, Car], 20 | timezone: process.env.DATABASE_TIMEZONE, 21 | logging: false, 22 | }); 23 | try { 24 | const result = await SequelizeTypescriptMigration.makeMigration(sequelize, { 25 | outDir: join(__dirname, "./db/migrations"), 26 | migrationName: "init", 27 | useSnakeCase: false, 28 | }); 29 | console.log(result); 30 | } catch (e) { 31 | console.log(e); 32 | } 33 | }; 34 | 35 | bootstrap(); 36 | -------------------------------------------------------------------------------- /example/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target": "esnext", 4 | "lib": ["esnext", "dom"], 5 | "allowJs": true, 6 | "checkJs": false, 7 | "skipLibCheck": true, 8 | "esModuleInterop": true, 9 | "allowSyntheticDefaultImports": true, 10 | "strict": true, 11 | "forceConsistentCasingInFileNames": true, 12 | "noFallthroughCasesInSwitch": true, 13 | "module": "commonjs", 14 | "moduleResolution": "node", 15 | "resolveJsonModule": true, 16 | "isolatedModules": true, 17 | "noEmit": true, 18 | "noImplicitAny": false, 19 | "sourceMap": true, 20 | "experimentalDecorators": true, 21 | "emitDecoratorMetadata": true, 22 | "baseUrl": "./", 23 | "paths": { 24 | "@src/*": ["src/*"] 25 | }, 26 | "outDir": "dist", 27 | "charset": "utf8" 28 | }, 29 | "exclude": ["node_modules", "dist"] 30 | } 31 | -------------------------------------------------------------------------------- /jest.config.js: -------------------------------------------------------------------------------- 1 | // eslint-disable-next-line no-undef 2 | module.exports = { 3 | preset: 'ts-jest', 4 | testEnvironment: 'node', 5 | }; 6 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "sequelize-typescript-migration-lts", 3 | "version": "3.2.5", 4 | "description": "migration tool for sequelize & typescript users", 5 | "keywords": [ 6 | "sequelize", 7 | "typescript", 8 | "migrate", 9 | "migration", 10 | "makemigration", 11 | "diff", 12 | "compare", 13 | "detect", 14 | "changes" 15 | ], 16 | "homepage": "https://github.com/mmRoshani/sequelize-typescript-migration", 17 | "bugs": { 18 | "url": "https://github.com/mmRoshani/sequelize-typescript-migration/issues", 19 | "email": "mohammadmojtabaroshani@outlook.com" 20 | }, 21 | "main": "dist/index.js", 22 | "scripts": { 23 | "release": "npm publish --access public", 24 | "build": "tsc", 25 | "start": "node dist/index.js", 26 | "packlist": "npx npm-packlist", 27 | "lint": "eslint --ext .ts .", 28 | "test": "jest --detectOpenHandles" 29 | }, 30 | "bin": { 31 | "sequelize-typescript-migration": "dist/index.js" 32 | }, 33 | "repository": { 34 | "type": "git", 35 | "url": "https://github.com/mmRoshani/sequelize-typescript-migration.git" 36 | }, 37 | "author": "mohammadmojtabaroshani@outlook.com", 38 | "license": "MIT", 39 | "dependencies": { 40 | "deep-diff": "^1.0.2", 41 | "inflection": "^1.13.2", 42 | "js-beautify": "^1.14.0", 43 | "mysql2": "^2.3.3", 44 | "reflect-metadata": "^0.1.13", 45 | "sequelize": "^6.23.2", 46 | "sequelize-typescript": "^2.1.3" 47 | }, 48 | "devDependencies": { 49 | "@types/bluebird": "^3.5.36", 50 | "@types/deep-diff": "^1.0.1", 51 | "@types/inflection": "^1.13.0", 52 | "@types/jest": "^29.4.0", 53 | "@types/js-beautify": "^1.13.3", 54 | "@types/node": "^17.0.23", 55 | "@types/validator": "^13.7.2", 56 | "@typescript-eslint/eslint-plugin": "^5.38.1", 57 | "@typescript-eslint/parser": "^5.38.1", 58 | "dotenv": "^16.0.1", 59 | "eslint": "^8.24.0", 60 | "eslint-config-prettier": "^8.5.0", 61 | "eslint-config-standard": "^17.0.0", 62 | "eslint-plugin-import": "^2.26.0", 63 | "eslint-plugin-n": "^15.2.4", 64 | "eslint-plugin-prettier": "^4.2.1", 65 | "eslint-plugin-promise": "^6.0.0", 66 | "jest": "^29.4.0", 67 | "prettier": "^2.7.1", 68 | "ts-jest": "^29.0.5", 69 | "ts-node": "^10.7.0", 70 | "tsconfig-paths": "^3.14.1", 71 | "typescript": "^4.8.4" 72 | }, 73 | "engines": { 74 | "node": ">=12" 75 | }, 76 | "directories": { 77 | "example": "example" 78 | } 79 | } 80 | -------------------------------------------------------------------------------- /src/constants.ts: -------------------------------------------------------------------------------- 1 | export interface Json { 2 | [key: string]: any; 3 | } 4 | 5 | export interface MigrationState { 6 | revision?: number; 7 | version?: number; 8 | tables: Json; 9 | } 10 | 11 | export interface SequelizeMigrations { 12 | name: string; 13 | date: Date; 14 | } 15 | 16 | export interface SequelizeMigrationsMeta { 17 | revision: number; 18 | name: string; 19 | state: MigrationState; 20 | date: Date; 21 | } 22 | -------------------------------------------------------------------------------- /src/index.ts: -------------------------------------------------------------------------------- 1 | import { existsSync } from "fs"; 2 | import beautify from "js-beautify"; 3 | import type { Model, ModelCtor } from "sequelize/types"; 4 | import type { Sequelize } from "sequelize-typescript"; 5 | 6 | import type { MigrationState } from "./constants"; 7 | import createMigrationTable from "./utils/createMigrationTable"; 8 | import getDiffActionsFromTables from "./utils/getDiffActionsFromTables"; 9 | import getLastMigrationState from "./utils/getLastMigrationState"; 10 | import getMigration from "./utils/getMigration"; 11 | import getTablesFromModels, { ReverseModelsOptions } from "./utils/getTablesFromModels"; 12 | import writeMigration from "./utils/writeMigration"; 13 | 14 | export type IMigrationOptions = { 15 | /** 16 | * directory where migration file saved. We recommend that you specify this path to sequelize migration path. 17 | */ 18 | outDir: string; 19 | 20 | /** 21 | * if true, it doesn't generate files but just prints result action. 22 | */ 23 | preview?: boolean; 24 | 25 | /** 26 | * migration file name, default is "noname" 27 | */ 28 | migrationName?: string; 29 | 30 | /** 31 | * comment of migration. 32 | */ 33 | comment?: string; 34 | 35 | debug?: boolean; 36 | } & ReverseModelsOptions 37 | 38 | export class SequelizeTypescriptMigration { 39 | /** 40 | * generates migration file including up, down code 41 | * after this, run 'npx sequelize-cli db:migrate'. 42 | * @param sequelize sequelize-typescript instance 43 | * @param options options 44 | */ 45 | public static makeMigration = async ( 46 | sequelize: Sequelize, 47 | options: IMigrationOptions 48 | ) => { 49 | options.preview = options.preview || false; 50 | 51 | if (!existsSync(options.outDir)) 52 | return Promise.reject( 53 | new Error( 54 | `${options.outDir} not exists. check path and if you did 'npx sequelize init' you must use path used in sequelize migration path` 55 | ) 56 | ); 57 | 58 | await sequelize.authenticate(); 59 | 60 | const models: { 61 | [key: string]: ModelCtor; 62 | } = sequelize.models; 63 | 64 | const queryInterface = sequelize.getQueryInterface(); 65 | 66 | await createMigrationTable(sequelize); 67 | 68 | const lastMigrationState = await getLastMigrationState(sequelize); 69 | const previousState: MigrationState = { 70 | revision: lastMigrationState?.revision ?? 0, 71 | version: lastMigrationState?.version ?? 1, 72 | tables: lastMigrationState?.tables ?? {}, 73 | }; 74 | const currentState: MigrationState = { 75 | revision: (previousState.revision || 0) + 1, 76 | tables: getTablesFromModels(sequelize, models, options), 77 | }; 78 | 79 | const upActions = getDiffActionsFromTables( 80 | previousState.tables, 81 | currentState.tables 82 | ); 83 | const downActions = getDiffActionsFromTables( 84 | currentState.tables, 85 | previousState.tables 86 | ); 87 | 88 | const migration = getMigration(upActions); 89 | const tmp = getMigration(downActions); 90 | 91 | migration.commandsDown = tmp.commandsUp; 92 | 93 | if (migration.commandsUp.length === 0) 94 | return Promise.resolve({ msg: "success: no changes found" }); 95 | 96 | // log 97 | migration.consoleOut.forEach((v) => { 98 | console.log(`[Actions] ${v}`); 99 | }); 100 | 101 | if (options.preview) { 102 | console.log("Migration result:"); 103 | console.log(beautify(`[ \n${migration.commandsUp.join(", \n")} \n];\n`)); 104 | console.log("Undo commands:"); 105 | console.log( 106 | beautify(`[ \n${migration.commandsDown.join(", \n")} \n];\n`) 107 | ); 108 | 109 | return Promise.resolve({ msg: "success without save" }); 110 | } 111 | 112 | const info = await writeMigration(currentState, migration, options); 113 | 114 | console.log( 115 | `New migration to revision ${currentState.revision} has been saved to file '${info.filename}'` 116 | ); 117 | 118 | // save current state, Ugly hack, see https://github.com/sequelize/sequelize/issues/8310 119 | const rows = [ 120 | { 121 | revision: currentState.revision, 122 | name: info.info.name, 123 | state: JSON.stringify(currentState), 124 | }, 125 | ]; 126 | 127 | try { 128 | await queryInterface.bulkDelete("SequelizeMigrationsMeta", { 129 | revision: currentState.revision, 130 | }); 131 | await queryInterface.bulkInsert("SequelizeMigrationsMeta", rows); 132 | 133 | console.log(`Use sequelize CLI: 134 | npx sequelize db:migrate --to ${info.revisionNumber}-${ 135 | info.info.name 136 | }.js ${`--migrations-path=${options.outDir}`} `); 137 | 138 | return await Promise.resolve({ msg: "success" }); 139 | } catch (err) { 140 | if (options.debug) console.error(err); 141 | } 142 | 143 | return Promise.resolve({ msg: "success anyway..." }); 144 | }; 145 | } 146 | -------------------------------------------------------------------------------- /src/utils/createMigrationTable.ts: -------------------------------------------------------------------------------- 1 | import { 2 | DataType as SequelizeTypescriptDataType, 3 | Sequelize, 4 | } from "sequelize-typescript"; 5 | 6 | export default async function createMigrationTable(sequelize: Sequelize) { 7 | const queryInterface = sequelize.getQueryInterface(); 8 | 9 | await queryInterface.createTable("SequelizeMeta", { 10 | name: { 11 | type: SequelizeTypescriptDataType.STRING, 12 | allowNull: false, 13 | unique: true, 14 | primaryKey: true, 15 | }, 16 | date: { 17 | type: SequelizeTypescriptDataType.DATE, 18 | defaultValue: Sequelize.fn("now"), 19 | }, 20 | }); 21 | await queryInterface.createTable("SequelizeMigrationsMeta", { 22 | revision: { 23 | type: SequelizeTypescriptDataType.INTEGER, 24 | allowNull: false, 25 | unique: true, 26 | primaryKey: true, 27 | }, 28 | name: { 29 | type: SequelizeTypescriptDataType.STRING, 30 | allowNull: false, 31 | }, 32 | state: { 33 | type: SequelizeTypescriptDataType.JSON, 34 | allowNull: false, 35 | }, 36 | date: { 37 | type: SequelizeTypescriptDataType.DATE, 38 | defaultValue: Sequelize.fn("now"), 39 | }, 40 | }); 41 | } 42 | -------------------------------------------------------------------------------- /src/utils/getDiffActionsFromTables.ts: -------------------------------------------------------------------------------- 1 | import { diff } from "deep-diff"; 2 | 3 | import type { Json } from "../constants"; 4 | import sortActions from "./sortActions"; 5 | 6 | export interface IAction { 7 | actionType: 8 | | "addColumn" 9 | | "addIndex" 10 | | "changeColumn" 11 | | "createTable" 12 | | "dropTable" 13 | | "removeColumn" 14 | | "removeIndex"; 15 | tableName: string; 16 | attributes?: any; 17 | attributeName?: any; 18 | options?: any; 19 | columnName?: any; 20 | fields?: any[]; 21 | depends: string[]; 22 | } 23 | 24 | export default function getDiffActionsFromTables( 25 | previousStateTables: Json, 26 | currentStateTables: Json 27 | ) { 28 | const actions: IAction[] = []; 29 | const differences = diff(previousStateTables, currentStateTables); 30 | 31 | if (!differences) return actions; 32 | 33 | console.log(differences); 34 | 35 | differences.forEach((df) => { 36 | if (!df.path) throw new Error("Missing path"); 37 | 38 | switch (df.kind) { 39 | // add new 40 | case "N": 41 | { 42 | // new table created 43 | if (df.path.length === 1) { 44 | const depends: string[] = []; 45 | const tableName = df.rhs.tableName as string; 46 | 47 | Object.values(df.rhs.schema).forEach((v: any) => { 48 | if (v.references) depends.push(v.references.model as string); 49 | }); 50 | 51 | actions.push({ 52 | actionType: "createTable", 53 | tableName, 54 | attributes: df.rhs.schema, 55 | options: {}, 56 | depends, 57 | }); 58 | 59 | // create indexes 60 | if (df.rhs.indexes) 61 | for (const i in df.rhs.indexes) { 62 | const copied = JSON.parse(JSON.stringify(df.rhs.indexes[i])); 63 | 64 | actions.push({ 65 | actionType: "addIndex", 66 | tableName, 67 | depends: [tableName], 68 | ...copied, 69 | }); 70 | } 71 | 72 | break; 73 | } 74 | 75 | const tableName = df.path[0]; 76 | const depends = [tableName]; 77 | 78 | if (df.path[1] === "schema") { 79 | // if (df.path.length === 3) - new field 80 | if (df.path.length === 3) { 81 | // new field 82 | if (df.rhs && df.rhs.references) 83 | depends.push(df.rhs.references.model); 84 | 85 | actions.push({ 86 | actionType: "addColumn", 87 | tableName, 88 | attributeName: df.path[2], 89 | options: df.rhs, 90 | depends, 91 | }); 92 | break; 93 | } 94 | 95 | // if (df.path.length > 3) - add new attribute to column (change col) 96 | if (df.path.length > 3) 97 | if (df.path[1] === "schema") { 98 | // new field attributes 99 | const options = 100 | currentStateTables[tableName].schema[df.path[2]]; 101 | 102 | if (options.references) depends.push(options.references.nodel); 103 | 104 | actions.push({ 105 | actionType: "changeColumn", 106 | tableName, 107 | attributeName: df.path[2], 108 | options, 109 | depends, 110 | }); 111 | break; 112 | } 113 | } 114 | 115 | // new index 116 | if (df.path[1] === "indexes" && df.rhs) { 117 | const tableName = df.path[0]; 118 | const copied = df.rhs 119 | ? JSON.parse(JSON.stringify(df.rhs)) 120 | : undefined; 121 | const index = copied; 122 | 123 | index.actionType = "addIndex"; 124 | index.tableName = tableName; 125 | index.depends = [tableName]; 126 | actions.push(index); 127 | break; 128 | } 129 | } 130 | break; 131 | 132 | // drop 133 | case "D": 134 | { 135 | const tableName = df.path[0]; 136 | 137 | if (df.path.length === 1) { 138 | // drop table 139 | const depends: string[] = []; 140 | Object.values(df.lhs.schema).forEach((v: any) => { 141 | if (v.references) depends.push(v.references.model); 142 | }); 143 | 144 | actions.push({ 145 | actionType: "dropTable", 146 | tableName, 147 | depends, 148 | }); 149 | break; 150 | } 151 | 152 | if (df.path[1] === "schema") { 153 | // if (df.path.length === 3) - drop field 154 | if (df.path.length === 3) { 155 | // drop column 156 | actions.push({ 157 | actionType: "removeColumn", 158 | tableName, 159 | columnName: df.path[2], 160 | depends: [tableName], 161 | }); 162 | break; 163 | } 164 | 165 | // if (df.path.length > 3) - drop attribute from column (change col) 166 | if (df.path.length > 3) { 167 | const depends = [tableName]; 168 | // new field attributes 169 | const options = currentStateTables[tableName].schema[df.path[2]]; 170 | if (options.references) depends.push(options.references.model); 171 | 172 | actions.push({ 173 | actionType: "changeColumn", 174 | tableName, 175 | attributeName: df.path[2], 176 | options, 177 | depends, 178 | }); 179 | break; 180 | } 181 | } 182 | 183 | if (df.path[1] === "indexes" && df.lhs) { 184 | actions.push({ 185 | actionType: "removeIndex", 186 | tableName, 187 | fields: df.lhs.fields, 188 | options: df.lhs.options, 189 | depends: [tableName], 190 | }); 191 | break; 192 | } 193 | } 194 | break; 195 | 196 | // edit 197 | case "E": 198 | { 199 | const tableName = df.path[0]; 200 | const depends = [tableName]; 201 | 202 | if (df.path[1] === "schema") { 203 | // new field attributes 204 | const options = currentStateTables[tableName].schema[df.path[2]]; 205 | if (options.references) depends.push(options.references.nodel); 206 | 207 | actions.push({ 208 | actionType: "changeColumn", 209 | tableName, 210 | attributeName: df.path[2], 211 | options, 212 | depends, 213 | }); 214 | } 215 | } 216 | break; 217 | 218 | // array change indexes 219 | case "A": 220 | console.log( 221 | "[Not supported] Array model changes! Problems are possible. Please, check result more carefully!" 222 | ); 223 | console.log("[Not supported] Difference: "); 224 | console.log(JSON.stringify(df, null, 4)); 225 | break; 226 | 227 | default: 228 | // code 229 | break; 230 | } 231 | }); 232 | 233 | const result = sortActions(actions); 234 | 235 | return result; 236 | } 237 | -------------------------------------------------------------------------------- /src/utils/getLastMigrationState.ts: -------------------------------------------------------------------------------- 1 | import { QueryTypes } from "sequelize"; 2 | import type { Sequelize } from "sequelize-typescript"; 3 | 4 | import type { 5 | MigrationState, 6 | SequelizeMigrations, 7 | SequelizeMigrationsMeta, 8 | } from "../constants"; 9 | 10 | export default async function getLastMigrationState(sequelize: Sequelize) { 11 | const [lastExecutedMigration] = await sequelize.query( 12 | 'SELECT name FROM "SequelizeMeta" ORDER BY name desc limit 1', 13 | { type: QueryTypes.SELECT } 14 | ); 15 | 16 | // eslint-disable-next-line @typescript-eslint/no-unused-vars 17 | const lastRevision: number = 18 | lastExecutedMigration !== undefined 19 | ? parseInt(lastExecutedMigration.name.split("-")[0]) 20 | : -1; 21 | 22 | const [lastMigration] = await sequelize.query( 23 | `SELECT state FROM "SequelizeMigrationsMeta" where revision = '${lastRevision}'`, 24 | { type: QueryTypes.SELECT } 25 | ); 26 | 27 | if (lastMigration) 28 | return typeof lastMigration.state === "string" 29 | ? (JSON.parse(lastMigration.state) as MigrationState) 30 | : lastMigration.state; 31 | } 32 | -------------------------------------------------------------------------------- /src/utils/getMigration.ts: -------------------------------------------------------------------------------- 1 | export default function getMigration(actions) { 2 | const commandsUp: string[] = []; 3 | const commandsDown: string[] = []; 4 | const consoleOut: string[] = []; 5 | 6 | for (const i in actions) { 7 | const action = actions[i]; 8 | 9 | switch (action.actionType) { 10 | case "createTable": 11 | { 12 | const resUp = ` 13 | { fn: "createTable", params: [ 14 | "${action.tableName}", 15 | ${getAttributes(action.attributes)}, 16 | ${JSON.stringify(action.options)} 17 | ] }`; 18 | commandsUp.push(resUp); 19 | consoleOut.push( 20 | `createTable "${action.tableName}", deps: [${action.depends.join( 21 | ", " 22 | )}]` 23 | ); 24 | } 25 | break; 26 | 27 | case "dropTable": 28 | { 29 | const res = `{ fn: "dropTable", params: ["${action.tableName}"] }`; 30 | 31 | commandsUp.push(res); 32 | consoleOut.push(`dropTable "${action.tableName}"`); 33 | } 34 | break; 35 | 36 | case "addColumn": 37 | { 38 | const resUp = `{ fn: "addColumn", params: [ 39 | "${action.tableName}", 40 | "${action.attributeName}", 41 | ${propertyToStr(action.options)} 42 | ] }`; 43 | 44 | commandsUp.push(resUp); 45 | consoleOut.push( 46 | `addColumn "${action.attributeName}" to table "${action.tableName}"` 47 | ); 48 | } 49 | break; 50 | 51 | case "removeColumn": 52 | { 53 | const res = `{ fn: "removeColumn", params: ["${action.tableName}", "${action.columnName}"] }`; 54 | 55 | commandsUp.push(res); 56 | consoleOut.push( 57 | `removeColumn "${action.columnName}" from table "${action.tableName}"` 58 | ); 59 | } 60 | break; 61 | 62 | case "changeColumn": 63 | { 64 | const res = `{ fn: "changeColumn", params: [ 65 | "${action.tableName}", 66 | "${action.attributeName}", 67 | ${propertyToStr(action.options)} 68 | ] }`; 69 | commandsUp.push(res); 70 | consoleOut.push( 71 | `changeColumn "${action.attributeName}" on table "${action.tableName}"` 72 | ); 73 | } 74 | break; 75 | 76 | case "addIndex": 77 | { 78 | const res = `{ fn: "addIndex", params: [ 79 | "${action.tableName}", 80 | ${JSON.stringify(action.fields)}, 81 | ${JSON.stringify(action.options)} 82 | ] }`; 83 | commandsUp.push(res); 84 | 85 | const nameOrAttrs = 86 | action.options && 87 | action.options.indexName && 88 | action.options.indexName !== "" 89 | ? `"${action.options.indexName}"` 90 | : JSON.stringify(action.fields); 91 | 92 | consoleOut.push( 93 | `addIndex ${nameOrAttrs} to table "${action.tableName}"` 94 | ); 95 | } 96 | break; 97 | 98 | case "removeIndex": { 99 | const nameOrAttrs = 100 | action.options && 101 | action.options.indexName && 102 | action.options.indexName !== "" 103 | ? `"${action.options.indexName}"` 104 | : JSON.stringify(action.fields); 105 | const res = `{ fn: "removeIndex", params: [ 106 | "${action.tableName}", 107 | ${nameOrAttrs} 108 | ] }`; 109 | 110 | commandsUp.push(res); 111 | consoleOut.push( 112 | `removeIndex ${nameOrAttrs} from table "${action.tableName}"` 113 | ); 114 | break; 115 | } 116 | 117 | default: 118 | // code 119 | } 120 | } 121 | 122 | return { commandsUp, commandsDown, consoleOut }; 123 | } 124 | 125 | const propertyToStr = (obj) => { 126 | const values: string[] = []; 127 | 128 | for (const k in obj) { 129 | if (k === "seqType") { 130 | values.push(`"type": ${obj[k]}`); 131 | 132 | continue; 133 | } 134 | 135 | if (k === "defaultValue") { 136 | if (obj[k].internal) { 137 | values.push(`"defaultValue": ${obj[k].value}`); 138 | 139 | continue; 140 | } 141 | 142 | if (obj[k].notSupported) continue; 143 | 144 | const x = {}; 145 | 146 | x[k] = obj[k].value; 147 | values.push(JSON.stringify(x).slice(1, -1)); 148 | 149 | continue; 150 | } 151 | 152 | const x = {}; 153 | 154 | x[k] = obj[k]; 155 | values.push(JSON.stringify(x).slice(1, -1)); 156 | } 157 | 158 | return `{ ${values 159 | .filter((v) => v !== "") 160 | .reverse() 161 | .join(", ")} }`; 162 | }; 163 | 164 | const getAttributes = (attrs) => { 165 | const ret: string[] = []; 166 | 167 | for (const attrName in attrs) 168 | ret.push(` "${attrName}": ${propertyToStr(attrs[attrName])}`); 169 | 170 | return ` { \n${ret.join(", \n")}\n }`; 171 | }; 172 | -------------------------------------------------------------------------------- /src/utils/getTablesFromModels.ts: -------------------------------------------------------------------------------- 1 | import type { 2 | Model, 3 | ModelAttributeColumnOptions, 4 | ModelStatic 5 | } from "sequelize/types"; 6 | import type { Sequelize } from "sequelize-typescript"; 7 | import { makeColumnName } from "./makeColumnName"; 8 | import parseIndex from "./parseIndex"; 9 | import reverseSequelizeColType from "./reverseSequelizeColType"; 10 | import reverseSequelizeDefValueType from "./reverseSequelizeDefValueType"; 11 | 12 | export type ReverseModelsOptions = { 13 | useSnakeCase?: boolean; 14 | } 15 | 16 | export default function reverseModels( 17 | sequelize: Sequelize, 18 | models: Record>, 19 | options: ReverseModelsOptions = {}, 20 | ) { 21 | const tables = {}; 22 | for (const [, model] of Object.entries(models)) { 23 | const attributes: { 24 | [key: string]: ModelAttributeColumnOptions; 25 | } = model.rawAttributes; 26 | 27 | const resultAttributes = {}; 28 | 29 | for (const [column, attribute] of Object.entries(attributes)) { 30 | let rowAttribute: { [x: string]: unknown } = {}; 31 | 32 | if (attribute.defaultValue) { 33 | const _val = reverseSequelizeDefValueType(attribute.defaultValue); 34 | if (_val.notSupported) { 35 | console.log( 36 | `[Not supported] Skip defaultValue column of attribute ${model}:${column}` 37 | ); 38 | } 39 | rowAttribute.defaultValue = _val; 40 | } 41 | 42 | if (attribute.type === undefined) { 43 | console.log( 44 | `[Not supported] Skip column with undefined type ${model}:${column}` 45 | ); 46 | continue; 47 | } 48 | 49 | const seqType: string = reverseSequelizeColType( 50 | sequelize, 51 | attribute.type 52 | ); 53 | if (seqType === "Sequelize.VIRTUAL") { 54 | console.log( 55 | `[SKIP] Skip Sequelize.VIRTUAL column "${column}"", defined in model "${model}"` 56 | ); 57 | continue; 58 | } 59 | 60 | rowAttribute = { 61 | seqType, 62 | }; 63 | [ 64 | "allowNull", 65 | "unique", 66 | "primaryKey", 67 | "autoIncrement", 68 | "autoIncrementIdentity", 69 | "comment", 70 | "references", 71 | "onUpdate", 72 | "onDelete", 73 | // "validate", 74 | ].forEach((key) => { 75 | if (attribute[key] !== undefined) rowAttribute[key] = attribute[key]; 76 | }); 77 | 78 | resultAttributes[makeColumnName(column, options.useSnakeCase)] = rowAttribute; 79 | } // attributes in model 80 | 81 | tables[model.tableName] = { 82 | tableName: model.tableName, 83 | schema: resultAttributes, 84 | }; 85 | 86 | const indexOut: { [x: string]: unknown } = {}; 87 | if ( 88 | model.options && 89 | model.options.indexes && 90 | model.options.indexes.length > 0 91 | ) 92 | for (const _i in model.options.indexes) { 93 | const index = parseIndex(model.options.indexes[_i]); 94 | indexOut[`${index.hash}`] = index; 95 | delete index.hash; 96 | } 97 | 98 | tables[model.tableName].indexes = indexOut; 99 | } // model in models 100 | 101 | return tables; 102 | } 103 | -------------------------------------------------------------------------------- /src/utils/makeColumnName.ts: -------------------------------------------------------------------------------- 1 | import { snakeCase } from "./snakeCase"; 2 | 3 | export const makeColumnName = (classPropertyName: string, useSnakeCase?: boolean): string => { 4 | return useSnakeCase ? snakeCase(classPropertyName) : classPropertyName; 5 | }; 6 | -------------------------------------------------------------------------------- /src/utils/parseIndex.ts: -------------------------------------------------------------------------------- 1 | import * as crypto from "crypto"; 2 | import type { IndexesOptions } from "sequelize/types"; 3 | 4 | export default function parseIndex(idx: IndexesOptions) { 5 | const result: { [x: string]: unknown } = {}; 6 | 7 | [ 8 | "name", 9 | "type", 10 | "unique", 11 | "concurrently", 12 | "fields", 13 | "using", 14 | "operator", 15 | "where", 16 | ].forEach((key) => { 17 | if (idx[key] !== undefined) result[key] = idx[key]; 18 | }); 19 | 20 | const options: { [x: string]: unknown } = {}; 21 | 22 | if (idx.name) options.indexName = idx.name; 23 | // The name of the index. Default is __ 24 | 25 | // @todo: UNIQUE|FULLTEXT|SPATIAL 26 | if (idx.unique) options.type = "UNIQUE"; 27 | 28 | // Set a type for the index, e.g. BTREE. See the documentation of the used dialect 29 | // if (idx.method) { 30 | // options["indexType"] = idx.type; 31 | // } 32 | 33 | if (idx.parser && idx.parser !== "") options.parser = idx.parser; 34 | // For FULLTEXT columns set your parser 35 | 36 | result.options = options; 37 | 38 | // result["hash"] = hash(idx); 39 | result.hash = crypto 40 | .createHash("sha1") 41 | .update(JSON.stringify(idx)) 42 | .digest("hex"); 43 | 44 | return result; 45 | } 46 | -------------------------------------------------------------------------------- /src/utils/removeCurrentRevisionMigrations.ts: -------------------------------------------------------------------------------- 1 | import * as fs from "fs"; 2 | 3 | export default function removeCurrentRevisionMigrations( 4 | revision, 5 | migrationsPath, 6 | options 7 | ): Promise { 8 | // if old files can't be deleted, we won't stop the execution 9 | 10 | // eslint-disable-next-line @typescript-eslint/no-unused-vars 11 | return new Promise((resolve, reject) => { 12 | if (options.keepFiles) resolve(false); 13 | 14 | try { 15 | const files: string[] = fs.readdirSync(migrationsPath); 16 | if (files.length === 0) resolve(false); 17 | 18 | let i = 0; 19 | files.forEach((file) => { 20 | i += 1; 21 | if (file.split("-")[0] === revision.toString()) { 22 | fs.unlinkSync(`${migrationsPath}/${file}`); 23 | if (options.verbose) { 24 | console.log(`Successfully deleted ${file}`); 25 | resolve(true); 26 | } 27 | } 28 | if (i === files.length) resolve(false); 29 | }); 30 | } catch (err) { 31 | // if (options.debug) console.error(`Can't read dir: ${err}`); 32 | // console.log(`Failed to delete mig file: ${error}`); 33 | if (options.debug) console.error(`Error Occurred: ${err}`); 34 | resolve(false); 35 | } 36 | }); 37 | } 38 | -------------------------------------------------------------------------------- /src/utils/reverseSequelizeColType.ts: -------------------------------------------------------------------------------- 1 | import type { Sequelize } from "sequelize-typescript"; 2 | 3 | export default function reverseSequelizeColType( 4 | sequelize: Sequelize, 5 | attrType: any | never, 6 | prefix = "Sequelize." 7 | ) { 8 | if (attrType.constructor.name === "VIRTUAL") return `${prefix}VIRTUAL`; 9 | 10 | if (attrType.constructor.name === "CHAR") { 11 | if (!attrType.options) return `${prefix}CHAR`; 12 | 13 | const postfix = attrType.options.binary ? ".BINARY" : ""; 14 | 15 | return `${prefix}CHAR${postfix}`; 16 | } 17 | 18 | if (attrType.constructor.name === "STRING") { 19 | if (attrType.options === undefined) return `${prefix}STRING`; 20 | 21 | if (attrType.options.binary !== undefined) return `${prefix}STRING.BINARY`; 22 | 23 | const length = 24 | attrType.options.length !== undefined 25 | ? `(${attrType.options.length})` 26 | : ""; 27 | 28 | return `${prefix}STRING${length}`; 29 | } 30 | 31 | if (attrType.constructor.name === "TEXT") { 32 | if (!attrType.options.length) return `${prefix}TEXT`; 33 | 34 | const postfix = `('${attrType.options.length.toLowerCase()}')`; 35 | 36 | return `${prefix}TEXT(${postfix})`; 37 | } 38 | 39 | if (attrType.constructor.name === "DECIMAL") { 40 | const params: unknown[] = []; 41 | 42 | if (attrType.options.precision) params.push(attrType.options.precision); 43 | 44 | if (attrType.options.scale) params.push(attrType.options.scale); 45 | 46 | const postfix = params.length > 0 ? `(${params.join(",")})` : ""; 47 | 48 | return `${prefix}DECIMAL${postfix}`; 49 | } 50 | 51 | if ( 52 | ["TINYINT", "SMALLINT", "MEDIUMINT", "INTEGER", "BIGINT"].includes( 53 | attrType.constructor.name 54 | ) 55 | ) { 56 | const params: unknown[] = []; 57 | 58 | if (attrType.options.length) params.push(attrType.options.length); 59 | 60 | if (attrType.options.decimals) params.push(attrType.options.decimals); 61 | 62 | let postfix = params.length > 0 ? `(${params.join(",")})` : ""; 63 | 64 | if (attrType.options.zerofill) postfix += ".ZEROFILL"; 65 | 66 | if (attrType.options.unsigned) postfix += ".UNSIGNED"; 67 | 68 | return `${prefix}${attrType.key}${postfix}`; 69 | } 70 | 71 | if (attrType.constructor.name === "DATE") { 72 | const length = attrType.options.length 73 | ? `(${attrType.options.length})` 74 | : ""; 75 | 76 | return `${prefix}DATE${length}`; 77 | } 78 | 79 | if (attrType.constructor.name === "DATEONLY") return `${prefix}DATEONLY`; 80 | 81 | if (attrType.constructor.name === "JSONTYPE") return `${prefix}JSON`; 82 | 83 | if (attrType.constructor.name === "BLOB") { 84 | const postfix = `'${attrType.options.length.toLowerCase()}'`; 85 | 86 | return `${prefix}BLOB(${postfix})`; 87 | } 88 | 89 | if (attrType.constructor.name === "ENUM") 90 | return `${prefix}ENUM('${attrType.options.values.join("', '")}')`; 91 | 92 | if (attrType.constructor.name === "GEOMETRY") { 93 | // eslint-disable-next-line eqeqeq 94 | if (attrType.options.type == undefined) return `${prefix}GEOMETRY`; 95 | 96 | const type = attrType.options.type.toUpperCase(); 97 | const srid = attrType.options.srid; 98 | const postfixItems = [`'${type}'`]; 99 | 100 | if (srid !== undefined) postfixItems.push(attrType.options.srid.toString()); 101 | 102 | return `${prefix}GEOMETRY(${postfixItems.join(",")})`; 103 | } 104 | 105 | if (attrType.constructor.name === "GEOGRAPHY") { 106 | // eslint-disable-next-line eqeqeq 107 | if (attrType.options.type == undefined) return `${prefix}GEOGRAPHY`; 108 | 109 | const type = attrType.options.type.toUpperCase(); 110 | const srid = attrType.options.srid; 111 | const postfixItems = [`'${type}'`]; 112 | 113 | if (srid !== undefined) postfixItems.push(attrType.options.srid.toString()); 114 | 115 | return `${prefix}GEOGRAPHY(${postfixItems.join(",")})`; 116 | } 117 | 118 | // ARRAY ( PostgreSQL only ) 119 | if (attrType.constructor.name === "ARRAY") { 120 | const innerType = reverseSequelizeColType(sequelize, attrType.type); 121 | 122 | return `${prefix}ARRAY(${innerType})`; 123 | } 124 | 125 | // RANGE ( PostgreSQL only ) 126 | if (attrType.constructor.name === "RANGE") { 127 | const innerType = reverseSequelizeColType(sequelize, attrType.type); 128 | 129 | return `${prefix}RANGE(${innerType})`; 130 | } 131 | 132 | let seqType; 133 | [ 134 | "BOOLEAN", 135 | "TIME", 136 | "HSTORE", 137 | "JSON", 138 | "JSONB", 139 | "NOW", 140 | "UUID", 141 | "UUIDV1", 142 | "UUIDV4", 143 | "JSONTYPE", 144 | "DOUBLE", 145 | "CIDR", 146 | "INET", 147 | "MACADDR", 148 | "CITEXT", 149 | ].forEach((typeName) => { 150 | if (attrType.constructor.name === typeName) 151 | seqType = `${prefix}${typeName}`; 152 | }); 153 | 154 | if (seqType) return seqType; 155 | 156 | // not supported 157 | console.log(`not supported ...${attrType.constructor.name}`); 158 | 159 | return `${prefix}VIRTUAL`; 160 | } 161 | -------------------------------------------------------------------------------- /src/utils/reverseSequelizeDefValueType.ts: -------------------------------------------------------------------------------- 1 | export default function reverseSequelizeDefValueType( 2 | defaultValue, 3 | prefix = "Sequelize." 4 | ) { 5 | if (typeof defaultValue.fn !== "undefined") 6 | return { 7 | internal: true, 8 | value: `${prefix}fn('${defaultValue.fn}')`, 9 | }; 10 | 11 | if (defaultValue.constructor.name === "NOW") 12 | return { 13 | internal: true, 14 | value: `${prefix}NOW`, 15 | }; 16 | 17 | if (defaultValue.constructor.name === "UUIDV1") 18 | return { 19 | internal: true, 20 | value: `${prefix}UUIDV1`, 21 | }; 22 | 23 | if (defaultValue.constructor.name === "UUIDV4") 24 | return { 25 | internal: true, 26 | value: `${prefix}UUIDV4`, 27 | }; 28 | 29 | if (typeof defaultValue === "function") 30 | return { notSupported: true, value: "" }; 31 | 32 | return { value: defaultValue }; 33 | } 34 | -------------------------------------------------------------------------------- /src/utils/snakeCase.spec.ts: -------------------------------------------------------------------------------- 1 | import { snakeCase } from "./snakeCase"; 2 | 3 | type Case = { input: string, expected: string } 4 | 5 | const cases: Case[] = [ 6 | { 7 | input: "camelCase", 8 | expected: "camel_case", 9 | }, 10 | { 11 | input: "CamelCase123", 12 | expected: "camel_case_123", 13 | }, 14 | { 15 | input: "__FOO-BAR__123.2CamelCase_", 16 | expected: "foo_bar_123_2_camel_case", 17 | }, 18 | ]; 19 | 20 | it.each(cases)("snakeCase($input) should return $expected", ({ input, expected }) => { 21 | expect(snakeCase(input)).toEqual(expected); 22 | }); 23 | -------------------------------------------------------------------------------- /src/utils/snakeCase.ts: -------------------------------------------------------------------------------- 1 | export const snakeCase = (camelCase: string): string => { 2 | // TODO: maybe we can simplify it 3 | return camelCase 4 | // split words by capital letters 5 | .replace(/([A-Z]+)/g, (match) => `_${match.toLowerCase()}`) 6 | // split multi-digit numbers 7 | .replace(/(\d+)/g, (match) => `_${match}`) 8 | // split replace punctuation 9 | .replace(/[._-]+/g, "_") 10 | // rm leading/trailing underscores 11 | .replace(/^_+/g, "") 12 | .replace(/_+$/g, ""); 13 | }; 14 | -------------------------------------------------------------------------------- /src/utils/sortActions.ts: -------------------------------------------------------------------------------- 1 | import type { IAction } from "./getDiffActionsFromTables"; 2 | 3 | const sortByLengthExists = (left: unknown[], right: unknown[]) => { 4 | if (left.length === 0 && right.length > 0) return -1; 5 | // left < right 6 | if (right.length === 0 && left.length > 0) return 1; 7 | // right < left 8 | 9 | return 0; 10 | }; 11 | 12 | export default function sortActions(actions: IAction[]) { 13 | const orderedActionTypes: string[] = [ 14 | "removeIndex", 15 | "removeColumn", 16 | "dropTable", 17 | "createTable", 18 | "addColumn", 19 | "changeColumn", 20 | "addIndex", 21 | ]; 22 | 23 | actions.sort((left: IAction, right: IAction) => { 24 | if ( 25 | orderedActionTypes.indexOf(left.actionType) < 26 | orderedActionTypes.indexOf(right.actionType) 27 | ) 28 | return -1; 29 | 30 | if ( 31 | orderedActionTypes.indexOf(left.actionType) > 32 | orderedActionTypes.indexOf(right.actionType) 33 | ) 34 | return 1; 35 | 36 | if (left.actionType === "dropTable" && right.actionType === "dropTable") 37 | return sortByLengthExists(right.depends, left.depends); 38 | 39 | return sortByLengthExists(left.depends, right.depends); 40 | }); 41 | 42 | for (let i = 0; i < actions.length; i++) { 43 | const leftAction: IAction = actions[i]; 44 | 45 | if (leftAction.depends.length === 0) continue; 46 | 47 | for (let j = 0; j < actions.length; j++) { 48 | const rightAction: IAction = actions[j]; 49 | 50 | if (rightAction.depends.length === 0) continue; 51 | 52 | if (leftAction.actionType !== rightAction.actionType) continue; 53 | 54 | if (rightAction.depends.includes(leftAction.tableName)) 55 | if (i > j) { 56 | const c = actions[i]; 57 | 58 | actions[i] = actions[j]; 59 | actions[j] = c; 60 | } 61 | } 62 | } 63 | 64 | return actions; 65 | } 66 | -------------------------------------------------------------------------------- /src/utils/writeMigration.ts: -------------------------------------------------------------------------------- 1 | import * as fs from "fs"; 2 | import beautify from "js-beautify"; 3 | import * as path from "path"; 4 | 5 | import removeCurrentRevisionMigrations from "./removeCurrentRevisionMigrations"; 6 | 7 | export default async function writeMigration(currentState, migration, options) { 8 | await removeCurrentRevisionMigrations( 9 | currentState.revision, 10 | options.outDir, 11 | options 12 | ); 13 | 14 | const name = options.migrationName || "noname"; 15 | const comment = options.comment || ""; 16 | 17 | let myState = JSON.stringify(currentState); 18 | const searchRegExp = /'/g; 19 | const replaceWith = "\\'"; 20 | 21 | myState = myState.replace(searchRegExp, replaceWith); 22 | 23 | const versionCommands = ` 24 | { 25 | fn: "createTable", 26 | params: [ 27 | "SequelizeMigrationsMeta", 28 | { 29 | "revision": { 30 | "primaryKey": true, 31 | "type": Sequelize.INTEGER 32 | }, 33 | "name": { 34 | "allowNull": false, 35 | "type": Sequelize.STRING 36 | }, 37 | "state": { 38 | "allowNull": false, 39 | "type": Sequelize.JSON 40 | }, 41 | }, 42 | {} 43 | ] 44 | }, 45 | { 46 | fn: "bulkDelete", 47 | params: [ 48 | "SequelizeMigrationsMeta", 49 | [{ 50 | revision: info.revision 51 | }], 52 | {} 53 | ] 54 | }, 55 | { 56 | fn: "bulkInsert", 57 | params: [ 58 | "SequelizeMigrationsMeta", 59 | [{ 60 | revision: info.revision, 61 | name: info.name, 62 | state: '${myState}' 63 | }], 64 | {} 65 | ] 66 | }, 67 | `; 68 | 69 | const versionDownCommands = ` 70 | { 71 | fn: "bulkDelete", 72 | params: [ 73 | "SequelizeMigrationsMeta", 74 | [{ 75 | revision: info.revision, 76 | }], 77 | {} 78 | ] 79 | }, 80 | `; 81 | 82 | let commands = `const migrationCommands = [\n${versionCommands}\n\n \n${migration.commandsUp.join( 83 | ", \n" 84 | )} \n];\n`; 85 | let commandsDown = `const rollbackCommands = [\n${versionDownCommands}\n\n \n${migration.commandsDown.join( 86 | ", \n" 87 | )} \n];\n`; 88 | 89 | const actions = ` * ${migration.consoleOut.join("\n * ")}`; 90 | 91 | commands = beautify(commands); 92 | commandsDown = beautify(commandsDown); 93 | 94 | const info = { 95 | revision: currentState.revision, 96 | name, 97 | created: new Date(), 98 | comment, 99 | }; 100 | 101 | const template = `'use strict'; 102 | 103 | const Sequelize = require('sequelize'); 104 | 105 | /** 106 | * Actions summary: 107 | * 108 | ${actions} 109 | * 110 | **/ 111 | 112 | const info = ${JSON.stringify(info, null, 4)}; 113 | 114 | ${commands} 115 | 116 | ${commandsDown} 117 | 118 | module.exports = { 119 | pos: 0, 120 | up: function(queryInterface, Sequelize) { 121 | let index = this.pos; 122 | 123 | return new Promise(function(resolve, reject) { 124 | function next() { 125 | if (index < migrationCommands.length) { 126 | let command = migrationCommands[index]; 127 | console.log("[#"+index+"] execute: " + command.fn); 128 | index++; 129 | queryInterface[command.fn].apply(queryInterface, command.params).then(next, reject); 130 | } else resolve(); 131 | } 132 | 133 | next(); 134 | }); 135 | }, 136 | down: function(queryInterface, Sequelize) { 137 | let index = this.pos; 138 | 139 | return new Promise(function(resolve, reject) { 140 | function next() { 141 | if (index < rollbackCommands.length) { 142 | let command = rollbackCommands[index]; 143 | console.log("[#"+index+"] execute: " + command.fn); 144 | index++; 145 | queryInterface[command.fn].apply(queryInterface, command.params).then(next, reject); 146 | } 147 | else resolve(); 148 | } 149 | 150 | next(); 151 | }); 152 | }, 153 | info 154 | }; 155 | `; 156 | 157 | const revisionNumber = currentState.revision.toString().padStart(8, "0"); 158 | 159 | const filename = path.join( 160 | options.outDir, 161 | `${ 162 | revisionNumber + (name !== "" ? `-${name.replace(/[\s-]/g, "_")}` : "") 163 | }.js` 164 | ); 165 | 166 | fs.writeFileSync(filename, template); 167 | 168 | return { filename, info, revisionNumber }; 169 | } 170 | -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://json.schemastore.org/tsconfig", 3 | "display": "Node 16", 4 | 5 | "compilerOptions": { 6 | "rootDir": "src", 7 | "outDir": "dist", 8 | "target": "es2021", 9 | "module": "commonjs", 10 | "moduleResolution": "node", 11 | "lib": ["es2021", "dom"], 12 | "declaration": true, 13 | "allowJs": true, 14 | "checkJs": false, 15 | "skipLibCheck": true, 16 | "esModuleInterop": true, 17 | "allowSyntheticDefaultImports": true, 18 | "strict": true, 19 | "forceConsistentCasingInFileNames": true, 20 | "noFallthroughCasesInSwitch": true, 21 | "resolveJsonModule": true, 22 | "isolatedModules": true, 23 | "noImplicitAny": false, 24 | "sourceMap": true, 25 | "experimentalDecorators": true, 26 | "emitDecoratorMetadata": true, 27 | "charset": "utf8" 28 | }, 29 | "include": [ 30 | "./src/**/*.ts" 31 | ], 32 | "exclude": [ 33 | "./node_modules", 34 | "./dist", 35 | "./example" 36 | ] 37 | } --------------------------------------------------------------------------------