added prettier
This commit is contained in:
parent
76339ddf18
commit
14d064e631
3
.prettierrc
Normal file
3
.prettierrc
Normal file
@ -0,0 +1,3 @@
|
||||
{
|
||||
"parser":"typescript"
|
||||
}
|
714
package-lock.json
generated
714
package-lock.json
generated
@ -214,6 +214,12 @@
|
||||
"integrity": "sha1-qCJQ3bABXponyoLoLqYDu/pF768=",
|
||||
"dev": true
|
||||
},
|
||||
"any-observable": {
|
||||
"version": "0.2.0",
|
||||
"resolved": "https://registry.npmjs.org/any-observable/-/any-observable-0.2.0.tgz",
|
||||
"integrity": "sha1-xnhwBYADV5AJCD9UrAq6+1wz0kI=",
|
||||
"dev": true
|
||||
},
|
||||
"any-promise": {
|
||||
"version": "1.3.0",
|
||||
"resolved": "https://registry.npmjs.org/any-promise/-/any-promise-1.3.0.tgz",
|
||||
@ -531,6 +537,12 @@
|
||||
"integrity": "sha1-V00xLt2Iu13YkS6Sht1sCu1KrII=",
|
||||
"dev": true
|
||||
},
|
||||
"ci-info": {
|
||||
"version": "1.1.2",
|
||||
"resolved": "https://registry.npmjs.org/ci-info/-/ci-info-1.1.2.tgz",
|
||||
"integrity": "sha512-uTGIPNx/nSpBdsF6xnseRXLLtfr9VLqkz8ZqHXr3Y7b6SftyRxBGjwMtJj1OhNbmlc1wZzLNAlAcvyIiE8a6ZA==",
|
||||
"dev": true
|
||||
},
|
||||
"cli-boxes": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/cli-boxes/-/cli-boxes-1.0.0.tgz",
|
||||
@ -602,6 +614,12 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"cli-spinners": {
|
||||
"version": "0.1.2",
|
||||
"resolved": "https://registry.npmjs.org/cli-spinners/-/cli-spinners-0.1.2.tgz",
|
||||
"integrity": "sha1-u3ZNiOGF+54eaiofGXcjGPYF4xw=",
|
||||
"dev": true
|
||||
},
|
||||
"cli-truncate": {
|
||||
"version": "1.1.0",
|
||||
"resolved": "https://registry.npmjs.org/cli-truncate/-/cli-truncate-1.1.0.tgz",
|
||||
@ -763,6 +781,30 @@
|
||||
"resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz",
|
||||
"integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac="
|
||||
},
|
||||
"cosmiconfig": {
|
||||
"version": "4.0.0",
|
||||
"resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-4.0.0.tgz",
|
||||
"integrity": "sha512-6e5vDdrXZD+t5v0L8CrurPeybg4Fmf+FCSYxXKYVAqLUtyCSbuyqE059d0kDthTNRzKVjL7QMgNpEUlsoYH3iQ==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"is-directory": "0.3.1",
|
||||
"js-yaml": "3.10.0",
|
||||
"parse-json": "4.0.0",
|
||||
"require-from-string": "2.0.1"
|
||||
},
|
||||
"dependencies": {
|
||||
"parse-json": {
|
||||
"version": "4.0.0",
|
||||
"resolved": "https://registry.npmjs.org/parse-json/-/parse-json-4.0.0.tgz",
|
||||
"integrity": "sha1-vjX1Qlvh9/bHRxhPmKeIy5lHfuA=",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"error-ex": "1.3.1",
|
||||
"json-parse-better-errors": "1.0.1"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"create-error-class": {
|
||||
"version": "3.0.2",
|
||||
"resolved": "https://registry.npmjs.org/create-error-class/-/create-error-class-3.0.2.tgz",
|
||||
@ -814,6 +856,12 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"date-fns": {
|
||||
"version": "1.29.0",
|
||||
"resolved": "https://registry.npmjs.org/date-fns/-/date-fns-1.29.0.tgz",
|
||||
"integrity": "sha512-lbTXWZ6M20cWH8N9S6afb0SBm6tMk+uUg6z3MqHPKE9atmsY3kJkTm8vKe93izJ2B2+q5MV990sM2CHgtAZaOw==",
|
||||
"dev": true
|
||||
},
|
||||
"debug": {
|
||||
"version": "2.6.9",
|
||||
"resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz",
|
||||
@ -827,6 +875,12 @@
|
||||
"resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz",
|
||||
"integrity": "sha1-9lNNFRSCabIDUue+4m9QH5oZEpA="
|
||||
},
|
||||
"dedent": {
|
||||
"version": "0.7.0",
|
||||
"resolved": "https://registry.npmjs.org/dedent/-/dedent-0.7.0.tgz",
|
||||
"integrity": "sha1-JJXduvbrh0q7Dhvp3yLS5aVEMmw=",
|
||||
"dev": true
|
||||
},
|
||||
"deep-eql": {
|
||||
"version": "3.0.1",
|
||||
"resolved": "https://registry.npmjs.org/deep-eql/-/deep-eql-3.0.1.tgz",
|
||||
@ -1041,6 +1095,22 @@
|
||||
"resolved": "https://registry.npmjs.org/figlet/-/figlet-1.2.0.tgz",
|
||||
"integrity": "sha1-bEZTc3j6tkkUa1phQ92gGbQwtBA="
|
||||
},
|
||||
"figures": {
|
||||
"version": "1.7.0",
|
||||
"resolved": "https://registry.npmjs.org/figures/-/figures-1.7.0.tgz",
|
||||
"integrity": "sha1-y+Hjr/zxzUS4DK3+0o3Hk6lwHS4=",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"escape-string-regexp": "1.0.5",
|
||||
"object-assign": "4.1.1"
|
||||
}
|
||||
},
|
||||
"find-parent-dir": {
|
||||
"version": "0.3.0",
|
||||
"resolved": "https://registry.npmjs.org/find-parent-dir/-/find-parent-dir-0.3.0.tgz",
|
||||
"integrity": "sha1-M8RLQpqysvBkYpnF+fcY83b/jVQ=",
|
||||
"dev": true
|
||||
},
|
||||
"find-up": {
|
||||
"version": "2.1.0",
|
||||
"resolved": "https://registry.npmjs.org/find-up/-/find-up-2.1.0.tgz",
|
||||
@ -1113,6 +1183,12 @@
|
||||
"integrity": "sha1-6td0q+5y4gQJQzoGY2YCPdaIekE=",
|
||||
"dev": true
|
||||
},
|
||||
"get-own-enumerable-property-symbols": {
|
||||
"version": "2.0.1",
|
||||
"resolved": "https://registry.npmjs.org/get-own-enumerable-property-symbols/-/get-own-enumerable-property-symbols-2.0.1.tgz",
|
||||
"integrity": "sha512-TtY/sbOemiMKPRUDDanGCSgBYe7Mf0vbRsWnBZ+9yghpZ1MvcpSpuZFjHdEeY/LZjZy0vdLjS77L6HosisFiug==",
|
||||
"dev": true
|
||||
},
|
||||
"get-stream": {
|
||||
"version": "3.0.0",
|
||||
"resolved": "https://registry.npmjs.org/get-stream/-/get-stream-3.0.0.tgz",
|
||||
@ -1325,6 +1401,17 @@
|
||||
"extend": "3.0.1"
|
||||
}
|
||||
},
|
||||
"husky": {
|
||||
"version": "0.14.3",
|
||||
"resolved": "https://registry.npmjs.org/husky/-/husky-0.14.3.tgz",
|
||||
"integrity": "sha512-e21wivqHpstpoiWA/Yi8eFti8E+sQDSS53cpJsPptPs295QTOQR0ZwnHo2TXy1XOpZFD9rPOd3NpmqTK6uMLJA==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"is-ci": "1.1.0",
|
||||
"normalize-path": "1.0.0",
|
||||
"strip-indent": "2.0.0"
|
||||
}
|
||||
},
|
||||
"iconv-lite": {
|
||||
"version": "0.4.19",
|
||||
"resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.19.tgz",
|
||||
@ -1342,6 +1429,15 @@
|
||||
"integrity": "sha1-khi5srkoojixPcT7a21XbyMUU+o=",
|
||||
"dev": true
|
||||
},
|
||||
"indent-string": {
|
||||
"version": "2.1.0",
|
||||
"resolved": "https://registry.npmjs.org/indent-string/-/indent-string-2.1.0.tgz",
|
||||
"integrity": "sha1-ji1INIdCEhtKghi3oTfppSBJ3IA=",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"repeating": "2.0.1"
|
||||
}
|
||||
},
|
||||
"inflight": {
|
||||
"version": "1.0.6",
|
||||
"resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz",
|
||||
@ -1404,11 +1500,50 @@
|
||||
"builtin-modules": "1.1.1"
|
||||
}
|
||||
},
|
||||
"is-ci": {
|
||||
"version": "1.1.0",
|
||||
"resolved": "https://registry.npmjs.org/is-ci/-/is-ci-1.1.0.tgz",
|
||||
"integrity": "sha512-c7TnwxLePuqIlxHgr7xtxzycJPegNHFuIrBkwbf8hc58//+Op1CqFkyS+xnIMkwn9UsJIwc174BIjkyBmSpjKg==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"ci-info": "1.1.2"
|
||||
}
|
||||
},
|
||||
"is-directory": {
|
||||
"version": "0.3.1",
|
||||
"resolved": "https://registry.npmjs.org/is-directory/-/is-directory-0.3.1.tgz",
|
||||
"integrity": "sha1-YTObbyR1/Hcv2cnYP1yFddwVSuE=",
|
||||
"dev": true
|
||||
},
|
||||
"is-extglob": {
|
||||
"version": "2.1.1",
|
||||
"resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz",
|
||||
"integrity": "sha1-qIwCU1eR8C7TfHahueqXc8gz+MI=",
|
||||
"dev": true
|
||||
},
|
||||
"is-finite": {
|
||||
"version": "1.0.2",
|
||||
"resolved": "https://registry.npmjs.org/is-finite/-/is-finite-1.0.2.tgz",
|
||||
"integrity": "sha1-zGZ3aVYCvlUO8R6LSqYwU0K20Ko=",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"number-is-nan": "1.0.1"
|
||||
}
|
||||
},
|
||||
"is-fullwidth-code-point": {
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz",
|
||||
"integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8="
|
||||
},
|
||||
"is-glob": {
|
||||
"version": "4.0.0",
|
||||
"resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.0.tgz",
|
||||
"integrity": "sha1-lSHHaEXMJhCoUgPd8ICpWML/q8A=",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"is-extglob": "2.1.1"
|
||||
}
|
||||
},
|
||||
"is-installed-globally": {
|
||||
"version": "0.1.0",
|
||||
"resolved": "https://registry.npmjs.org/is-installed-globally/-/is-installed-globally-0.1.0.tgz",
|
||||
@ -1439,6 +1574,15 @@
|
||||
"integrity": "sha1-PkcprB9f3gJc19g6iW2rn09n2w8=",
|
||||
"dev": true
|
||||
},
|
||||
"is-observable": {
|
||||
"version": "0.2.0",
|
||||
"resolved": "https://registry.npmjs.org/is-observable/-/is-observable-0.2.0.tgz",
|
||||
"integrity": "sha1-s2ExHYPG5dcmyr9eJQsCNxBvWuI=",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"symbol-observable": "0.2.4"
|
||||
}
|
||||
},
|
||||
"is-path-inside": {
|
||||
"version": "1.0.1",
|
||||
"resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-1.0.1.tgz",
|
||||
@ -1454,12 +1598,24 @@
|
||||
"integrity": "sha1-caUMhCnfync8kqOQpKA7OfzVHT4=",
|
||||
"dev": true
|
||||
},
|
||||
"is-promise": {
|
||||
"version": "2.1.0",
|
||||
"resolved": "https://registry.npmjs.org/is-promise/-/is-promise-2.1.0.tgz",
|
||||
"integrity": "sha1-eaKp7OfwlugPNtKy87wWwf9L8/o=",
|
||||
"dev": true
|
||||
},
|
||||
"is-redirect": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/is-redirect/-/is-redirect-1.0.0.tgz",
|
||||
"integrity": "sha1-HQPd7VO9jbDzDCbk+V02/HyH3CQ=",
|
||||
"dev": true
|
||||
},
|
||||
"is-regexp": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/is-regexp/-/is-regexp-1.0.0.tgz",
|
||||
"integrity": "sha1-/S2INUXEa6xaYz57mgnof6LLUGk=",
|
||||
"dev": true
|
||||
},
|
||||
"is-relative": {
|
||||
"version": "0.2.1",
|
||||
"resolved": "https://registry.npmjs.org/is-relative/-/is-relative-0.2.1.tgz",
|
||||
@ -1595,6 +1751,24 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"jest-get-type": {
|
||||
"version": "21.2.0",
|
||||
"resolved": "https://registry.npmjs.org/jest-get-type/-/jest-get-type-21.2.0.tgz",
|
||||
"integrity": "sha512-y2fFw3C+D0yjNSDp7ab1kcd6NUYfy3waPTlD8yWkAtiocJdBRQqNoRqVfMNxgj+IjT0V5cBIHJO0z9vuSSZ43Q==",
|
||||
"dev": true
|
||||
},
|
||||
"jest-validate": {
|
||||
"version": "21.2.1",
|
||||
"resolved": "https://registry.npmjs.org/jest-validate/-/jest-validate-21.2.1.tgz",
|
||||
"integrity": "sha512-k4HLI1rZQjlU+EC682RlQ6oZvLrE5SCh3brseQc24vbZTxzT/k/3urar5QMCVgjadmSO7lECeGdc6YxnM3yEGg==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"chalk": "2.3.0",
|
||||
"jest-get-type": "21.2.0",
|
||||
"leven": "2.1.0",
|
||||
"pretty-format": "21.2.1"
|
||||
}
|
||||
},
|
||||
"js-string-escape": {
|
||||
"version": "1.0.1",
|
||||
"resolved": "https://registry.npmjs.org/js-string-escape/-/js-string-escape-1.0.1.tgz",
|
||||
@ -1622,6 +1796,12 @@
|
||||
"dev": true,
|
||||
"optional": true
|
||||
},
|
||||
"json-parse-better-errors": {
|
||||
"version": "1.0.1",
|
||||
"resolved": "https://registry.npmjs.org/json-parse-better-errors/-/json-parse-better-errors-1.0.1.tgz",
|
||||
"integrity": "sha512-xyQpxeWWMKyJps9CuGJYeng6ssI5bpqS9ltQpdVQ90t4ql6NdnxFKh95JcRt2cun/DjMVNrdjniLPuMA69xmCw==",
|
||||
"dev": true
|
||||
},
|
||||
"json-schema": {
|
||||
"version": "0.2.3",
|
||||
"resolved": "https://registry.npmjs.org/json-schema/-/json-schema-0.2.3.tgz",
|
||||
@ -1732,6 +1912,12 @@
|
||||
"invert-kv": "1.0.0"
|
||||
}
|
||||
},
|
||||
"leven": {
|
||||
"version": "2.1.0",
|
||||
"resolved": "https://registry.npmjs.org/leven/-/leven-2.1.0.tgz",
|
||||
"integrity": "sha1-wuep93IJTe6dNCAq6KzORoeHVYA=",
|
||||
"dev": true
|
||||
},
|
||||
"levn": {
|
||||
"version": "0.3.0",
|
||||
"resolved": "https://registry.npmjs.org/levn/-/levn-0.3.0.tgz",
|
||||
@ -1742,12 +1928,353 @@
|
||||
"type-check": "0.3.2"
|
||||
}
|
||||
},
|
||||
"lint-staged": {
|
||||
"version": "6.1.0",
|
||||
"resolved": "https://registry.npmjs.org/lint-staged/-/lint-staged-6.1.0.tgz",
|
||||
"integrity": "sha512-RMB6BUd2bEKaPnj06F7j8RRB8OHM+UP4fQS2LT8lF+X9BjSaezw1oVB5hc4elLhYvzlFCkhAaatzYz+x53YHgw==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"app-root-path": "2.0.1",
|
||||
"chalk": "2.3.0",
|
||||
"commander": "2.11.0",
|
||||
"cosmiconfig": "4.0.0",
|
||||
"debug": "3.1.0",
|
||||
"dedent": "0.7.0",
|
||||
"execa": "0.8.0",
|
||||
"find-parent-dir": "0.3.0",
|
||||
"is-glob": "4.0.0",
|
||||
"jest-validate": "21.2.1",
|
||||
"listr": "0.13.0",
|
||||
"lodash": "4.17.4",
|
||||
"log-symbols": "2.2.0",
|
||||
"minimatch": "3.0.4",
|
||||
"npm-which": "3.0.1",
|
||||
"p-map": "1.2.0",
|
||||
"path-is-inside": "1.0.2",
|
||||
"pify": "3.0.0",
|
||||
"staged-git-files": "0.0.4",
|
||||
"stringify-object": "3.2.1"
|
||||
},
|
||||
"dependencies": {
|
||||
"debug": {
|
||||
"version": "3.1.0",
|
||||
"resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz",
|
||||
"integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"ms": "2.0.0"
|
||||
}
|
||||
},
|
||||
"execa": {
|
||||
"version": "0.8.0",
|
||||
"resolved": "https://registry.npmjs.org/execa/-/execa-0.8.0.tgz",
|
||||
"integrity": "sha1-2NdrvBtVIX7RkP1t1J08d07PyNo=",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"cross-spawn": "5.1.0",
|
||||
"get-stream": "3.0.0",
|
||||
"is-stream": "1.1.0",
|
||||
"npm-run-path": "2.0.2",
|
||||
"p-finally": "1.0.0",
|
||||
"signal-exit": "3.0.2",
|
||||
"strip-eof": "1.0.0"
|
||||
}
|
||||
},
|
||||
"pify": {
|
||||
"version": "3.0.0",
|
||||
"resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz",
|
||||
"integrity": "sha1-5aSs0sEB/fPZpNB/DbxNtJ3SgXY=",
|
||||
"dev": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"listify": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/listify/-/listify-1.0.0.tgz",
|
||||
"integrity": "sha1-A8p7otFQ1CZ3c/dOV1WNEFPSvuM=",
|
||||
"dev": true
|
||||
},
|
||||
"listr": {
|
||||
"version": "0.13.0",
|
||||
"resolved": "https://registry.npmjs.org/listr/-/listr-0.13.0.tgz",
|
||||
"integrity": "sha1-ILsLowuuZg7oTMBQPfS+PVYjiH0=",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"chalk": "1.1.3",
|
||||
"cli-truncate": "0.2.1",
|
||||
"figures": "1.7.0",
|
||||
"indent-string": "2.1.0",
|
||||
"is-observable": "0.2.0",
|
||||
"is-promise": "2.1.0",
|
||||
"is-stream": "1.1.0",
|
||||
"listr-silent-renderer": "1.1.1",
|
||||
"listr-update-renderer": "0.4.0",
|
||||
"listr-verbose-renderer": "0.4.1",
|
||||
"log-symbols": "1.0.2",
|
||||
"log-update": "1.0.2",
|
||||
"ora": "0.2.3",
|
||||
"p-map": "1.2.0",
|
||||
"rxjs": "5.5.6",
|
||||
"stream-to-observable": "0.2.0",
|
||||
"strip-ansi": "3.0.1"
|
||||
},
|
||||
"dependencies": {
|
||||
"ansi-regex": {
|
||||
"version": "2.1.1",
|
||||
"resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz",
|
||||
"integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=",
|
||||
"dev": true
|
||||
},
|
||||
"ansi-styles": {
|
||||
"version": "2.2.1",
|
||||
"resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz",
|
||||
"integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=",
|
||||
"dev": true
|
||||
},
|
||||
"chalk": {
|
||||
"version": "1.1.3",
|
||||
"resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz",
|
||||
"integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"ansi-styles": "2.2.1",
|
||||
"escape-string-regexp": "1.0.5",
|
||||
"has-ansi": "2.0.0",
|
||||
"strip-ansi": "3.0.1",
|
||||
"supports-color": "2.0.0"
|
||||
}
|
||||
},
|
||||
"cli-truncate": {
|
||||
"version": "0.2.1",
|
||||
"resolved": "https://registry.npmjs.org/cli-truncate/-/cli-truncate-0.2.1.tgz",
|
||||
"integrity": "sha1-nxXPuwcFAFNpIWxiasfQWrkN1XQ=",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"slice-ansi": "0.0.4",
|
||||
"string-width": "1.0.2"
|
||||
}
|
||||
},
|
||||
"is-fullwidth-code-point": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz",
|
||||
"integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"number-is-nan": "1.0.1"
|
||||
}
|
||||
},
|
||||
"log-symbols": {
|
||||
"version": "1.0.2",
|
||||
"resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-1.0.2.tgz",
|
||||
"integrity": "sha1-N2/3tY6jCGoPCfrMdGF+ylAeGhg=",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"chalk": "1.1.3"
|
||||
}
|
||||
},
|
||||
"slice-ansi": {
|
||||
"version": "0.0.4",
|
||||
"resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-0.0.4.tgz",
|
||||
"integrity": "sha1-7b+JA/ZvfOL46v1s7tZeJkyDGzU=",
|
||||
"dev": true
|
||||
},
|
||||
"string-width": {
|
||||
"version": "1.0.2",
|
||||
"resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz",
|
||||
"integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"code-point-at": "1.1.0",
|
||||
"is-fullwidth-code-point": "1.0.0",
|
||||
"strip-ansi": "3.0.1"
|
||||
}
|
||||
},
|
||||
"strip-ansi": {
|
||||
"version": "3.0.1",
|
||||
"resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz",
|
||||
"integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"ansi-regex": "2.1.1"
|
||||
}
|
||||
},
|
||||
"supports-color": {
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz",
|
||||
"integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=",
|
||||
"dev": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"listr-silent-renderer": {
|
||||
"version": "1.1.1",
|
||||
"resolved": "https://registry.npmjs.org/listr-silent-renderer/-/listr-silent-renderer-1.1.1.tgz",
|
||||
"integrity": "sha1-kktaN1cVN3C/Go4/v3S4u/P5JC4=",
|
||||
"dev": true
|
||||
},
|
||||
"listr-update-renderer": {
|
||||
"version": "0.4.0",
|
||||
"resolved": "https://registry.npmjs.org/listr-update-renderer/-/listr-update-renderer-0.4.0.tgz",
|
||||
"integrity": "sha1-NE2YDaLKLosUW6MFkI8yrj9MyKc=",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"chalk": "1.1.3",
|
||||
"cli-truncate": "0.2.1",
|
||||
"elegant-spinner": "1.0.1",
|
||||
"figures": "1.7.0",
|
||||
"indent-string": "3.2.0",
|
||||
"log-symbols": "1.0.2",
|
||||
"log-update": "1.0.2",
|
||||
"strip-ansi": "3.0.1"
|
||||
},
|
||||
"dependencies": {
|
||||
"ansi-regex": {
|
||||
"version": "2.1.1",
|
||||
"resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz",
|
||||
"integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=",
|
||||
"dev": true
|
||||
},
|
||||
"ansi-styles": {
|
||||
"version": "2.2.1",
|
||||
"resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz",
|
||||
"integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=",
|
||||
"dev": true
|
||||
},
|
||||
"chalk": {
|
||||
"version": "1.1.3",
|
||||
"resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz",
|
||||
"integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"ansi-styles": "2.2.1",
|
||||
"escape-string-regexp": "1.0.5",
|
||||
"has-ansi": "2.0.0",
|
||||
"strip-ansi": "3.0.1",
|
||||
"supports-color": "2.0.0"
|
||||
}
|
||||
},
|
||||
"cli-truncate": {
|
||||
"version": "0.2.1",
|
||||
"resolved": "https://registry.npmjs.org/cli-truncate/-/cli-truncate-0.2.1.tgz",
|
||||
"integrity": "sha1-nxXPuwcFAFNpIWxiasfQWrkN1XQ=",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"slice-ansi": "0.0.4",
|
||||
"string-width": "1.0.2"
|
||||
}
|
||||
},
|
||||
"indent-string": {
|
||||
"version": "3.2.0",
|
||||
"resolved": "https://registry.npmjs.org/indent-string/-/indent-string-3.2.0.tgz",
|
||||
"integrity": "sha1-Sl/W0nzDMvN+VBmlBNu4NxBckok=",
|
||||
"dev": true
|
||||
},
|
||||
"is-fullwidth-code-point": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz",
|
||||
"integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"number-is-nan": "1.0.1"
|
||||
}
|
||||
},
|
||||
"log-symbols": {
|
||||
"version": "1.0.2",
|
||||
"resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-1.0.2.tgz",
|
||||
"integrity": "sha1-N2/3tY6jCGoPCfrMdGF+ylAeGhg=",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"chalk": "1.1.3"
|
||||
}
|
||||
},
|
||||
"slice-ansi": {
|
||||
"version": "0.0.4",
|
||||
"resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-0.0.4.tgz",
|
||||
"integrity": "sha1-7b+JA/ZvfOL46v1s7tZeJkyDGzU=",
|
||||
"dev": true
|
||||
},
|
||||
"string-width": {
|
||||
"version": "1.0.2",
|
||||
"resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz",
|
||||
"integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"code-point-at": "1.1.0",
|
||||
"is-fullwidth-code-point": "1.0.0",
|
||||
"strip-ansi": "3.0.1"
|
||||
}
|
||||
},
|
||||
"strip-ansi": {
|
||||
"version": "3.0.1",
|
||||
"resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz",
|
||||
"integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"ansi-regex": "2.1.1"
|
||||
}
|
||||
},
|
||||
"supports-color": {
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz",
|
||||
"integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=",
|
||||
"dev": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"listr-verbose-renderer": {
|
||||
"version": "0.4.1",
|
||||
"resolved": "https://registry.npmjs.org/listr-verbose-renderer/-/listr-verbose-renderer-0.4.1.tgz",
|
||||
"integrity": "sha1-ggb0z21S3cWCfl/RSYng6WWTOjU=",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"chalk": "1.1.3",
|
||||
"cli-cursor": "1.0.2",
|
||||
"date-fns": "1.29.0",
|
||||
"figures": "1.7.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"ansi-regex": {
|
||||
"version": "2.1.1",
|
||||
"resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz",
|
||||
"integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=",
|
||||
"dev": true
|
||||
},
|
||||
"ansi-styles": {
|
||||
"version": "2.2.1",
|
||||
"resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz",
|
||||
"integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=",
|
||||
"dev": true
|
||||
},
|
||||
"chalk": {
|
||||
"version": "1.1.3",
|
||||
"resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz",
|
||||
"integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"ansi-styles": "2.2.1",
|
||||
"escape-string-regexp": "1.0.5",
|
||||
"has-ansi": "2.0.0",
|
||||
"strip-ansi": "3.0.1",
|
||||
"supports-color": "2.0.0"
|
||||
}
|
||||
},
|
||||
"strip-ansi": {
|
||||
"version": "3.0.1",
|
||||
"resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz",
|
||||
"integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"ansi-regex": "2.1.1"
|
||||
}
|
||||
},
|
||||
"supports-color": {
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz",
|
||||
"integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=",
|
||||
"dev": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"load-json-file": {
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-2.0.0.tgz",
|
||||
@ -1774,12 +2301,27 @@
|
||||
"integrity": "sha1-Jjj8OaAzHpysGgS3F5mTHJxQ33k=",
|
||||
"dev": true
|
||||
},
|
||||
"lodash": {
|
||||
"version": "4.17.4",
|
||||
"resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.4.tgz",
|
||||
"integrity": "sha1-eCA6TRwyiuHYbcpkYONptX9AVa4=",
|
||||
"dev": true
|
||||
},
|
||||
"lodash.get": {
|
||||
"version": "4.4.2",
|
||||
"resolved": "https://registry.npmjs.org/lodash.get/-/lodash.get-4.4.2.tgz",
|
||||
"integrity": "sha1-LRd/ZS+jHpObRDjVNBSZ36OCXpk=",
|
||||
"dev": true
|
||||
},
|
||||
"log-symbols": {
|
||||
"version": "2.2.0",
|
||||
"resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-2.2.0.tgz",
|
||||
"integrity": "sha512-VeIAFslyIerEJLXHziedo2basKbMKtTw3vfn5IzG0XTjhAVEJyNHnL2p7vc+wBDSdQuUpNw3M2u6xb9QsAY5Eg==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"chalk": "2.3.0"
|
||||
}
|
||||
},
|
||||
"log-update": {
|
||||
"version": "1.0.2",
|
||||
"resolved": "https://registry.npmjs.org/log-update/-/log-update-1.0.2.tgz",
|
||||
@ -2055,6 +2597,21 @@
|
||||
"validate-npm-package-license": "3.0.1"
|
||||
}
|
||||
},
|
||||
"normalize-path": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-1.0.0.tgz",
|
||||
"integrity": "sha1-MtDkcvkf80VwHBWoMRAY07CpA3k=",
|
||||
"dev": true
|
||||
},
|
||||
"npm-path": {
|
||||
"version": "2.0.4",
|
||||
"resolved": "https://registry.npmjs.org/npm-path/-/npm-path-2.0.4.tgz",
|
||||
"integrity": "sha512-IFsj0R9C7ZdR5cP+ET342q77uSRdtWOlWpih5eC+lu29tIDbNEgDbzgVJ5UFvYHWhxDZ5TFkJafFioO0pPQjCw==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"which": "1.3.0"
|
||||
}
|
||||
},
|
||||
"npm-run-path": {
|
||||
"version": "2.0.2",
|
||||
"resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-2.0.2.tgz",
|
||||
@ -2063,6 +2620,17 @@
|
||||
"path-key": "2.0.1"
|
||||
}
|
||||
},
|
||||
"npm-which": {
|
||||
"version": "3.0.1",
|
||||
"resolved": "https://registry.npmjs.org/npm-which/-/npm-which-3.0.1.tgz",
|
||||
"integrity": "sha1-kiXybsOihcIJyuZ8OxGmtKtxQKo=",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"commander": "2.11.0",
|
||||
"npm-path": "2.0.4",
|
||||
"which": "1.3.0"
|
||||
}
|
||||
},
|
||||
"number-is-nan": {
|
||||
"version": "1.0.1",
|
||||
"resolved": "https://registry.npmjs.org/number-is-nan/-/number-is-nan-1.0.1.tgz",
|
||||
@ -2133,6 +2701,60 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"ora": {
|
||||
"version": "0.2.3",
|
||||
"resolved": "https://registry.npmjs.org/ora/-/ora-0.2.3.tgz",
|
||||
"integrity": "sha1-N1J9Igrc1Tw5tzVx11QVbV22V6Q=",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"chalk": "1.1.3",
|
||||
"cli-cursor": "1.0.2",
|
||||
"cli-spinners": "0.1.2",
|
||||
"object-assign": "4.1.1"
|
||||
},
|
||||
"dependencies": {
|
||||
"ansi-regex": {
|
||||
"version": "2.1.1",
|
||||
"resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz",
|
||||
"integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=",
|
||||
"dev": true
|
||||
},
|
||||
"ansi-styles": {
|
||||
"version": "2.2.1",
|
||||
"resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz",
|
||||
"integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=",
|
||||
"dev": true
|
||||
},
|
||||
"chalk": {
|
||||
"version": "1.1.3",
|
||||
"resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz",
|
||||
"integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"ansi-styles": "2.2.1",
|
||||
"escape-string-regexp": "1.0.5",
|
||||
"has-ansi": "2.0.0",
|
||||
"strip-ansi": "3.0.1",
|
||||
"supports-color": "2.0.0"
|
||||
}
|
||||
},
|
||||
"strip-ansi": {
|
||||
"version": "3.0.1",
|
||||
"resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz",
|
||||
"integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"ansi-regex": "2.1.1"
|
||||
}
|
||||
},
|
||||
"supports-color": {
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz",
|
||||
"integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=",
|
||||
"dev": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"oracledb": {
|
||||
"version": "2.0.15",
|
||||
"resolved": "https://registry.npmjs.org/oracledb/-/oracledb-2.0.15.tgz",
|
||||
@ -2169,6 +2791,12 @@
|
||||
"p-limit": "1.2.0"
|
||||
}
|
||||
},
|
||||
"p-map": {
|
||||
"version": "1.2.0",
|
||||
"resolved": "https://registry.npmjs.org/p-map/-/p-map-1.2.0.tgz",
|
||||
"integrity": "sha512-r6zKACMNhjPJMTl8KcFH4li//gkrXWfbD6feV8l6doRHlzljFWGJ2AP6iKaCJXyZmAUMOPtvbW7EXkbWO/pLEA==",
|
||||
"dev": true
|
||||
},
|
||||
"p-try": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/p-try/-/p-try-1.0.0.tgz",
|
||||
@ -2444,6 +3072,22 @@
|
||||
"integrity": "sha1-1PRWKwzjaW5BrFLQ4ALlemNdxtw=",
|
||||
"dev": true
|
||||
},
|
||||
"prettier": {
|
||||
"version": "1.10.2",
|
||||
"resolved": "https://registry.npmjs.org/prettier/-/prettier-1.10.2.tgz",
|
||||
"integrity": "sha512-TcdNoQIWFoHblurqqU6d1ysopjq7UX0oRcT/hJ8qvBAELiYWn+Ugf0AXdnzISEJ7vuhNnQ98N8jR8Sh53x4IZg==",
|
||||
"dev": true
|
||||
},
|
||||
"pretty-format": {
|
||||
"version": "21.2.1",
|
||||
"resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-21.2.1.tgz",
|
||||
"integrity": "sha512-ZdWPGYAnYfcVP8yKA3zFjCn8s4/17TeYH28MXuC8vTp0o21eXjbFGcOAXZEaDaOFJjc3h2qa7HQNHNshhvoh2A==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"ansi-regex": "3.0.0",
|
||||
"ansi-styles": "3.2.0"
|
||||
}
|
||||
},
|
||||
"process-nextick-args": {
|
||||
"version": "1.0.7",
|
||||
"resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-1.0.7.tgz",
|
||||
@ -2581,6 +3225,15 @@
|
||||
"resolved": "https://registry.npmjs.org/repeat-string/-/repeat-string-1.6.1.tgz",
|
||||
"integrity": "sha1-jcrkcOHIirwtYA//Sndihtp15jc="
|
||||
},
|
||||
"repeating": {
|
||||
"version": "2.0.1",
|
||||
"resolved": "https://registry.npmjs.org/repeating/-/repeating-2.0.1.tgz",
|
||||
"integrity": "sha1-UhTFOpJtNVJwdSf7q0FdvAjQbdo=",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"is-finite": "1.0.2"
|
||||
}
|
||||
},
|
||||
"request": {
|
||||
"version": "2.81.0",
|
||||
"resolved": "https://registry.npmjs.org/request/-/request-2.81.0.tgz",
|
||||
@ -2616,6 +3269,12 @@
|
||||
"resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz",
|
||||
"integrity": "sha1-jGStX9MNqxyXbiNE/+f3kqam30I="
|
||||
},
|
||||
"require-from-string": {
|
||||
"version": "2.0.1",
|
||||
"resolved": "https://registry.npmjs.org/require-from-string/-/require-from-string-2.0.1.tgz",
|
||||
"integrity": "sha1-xUUjPp19pmFunVmt+zn8n1iGdv8=",
|
||||
"dev": true
|
||||
},
|
||||
"require-main-filename": {
|
||||
"version": "1.0.1",
|
||||
"resolved": "https://registry.npmjs.org/require-main-filename/-/require-main-filename-1.0.1.tgz",
|
||||
@ -2655,6 +3314,23 @@
|
||||
"glob": "7.1.2"
|
||||
}
|
||||
},
|
||||
"rxjs": {
|
||||
"version": "5.5.6",
|
||||
"resolved": "https://registry.npmjs.org/rxjs/-/rxjs-5.5.6.tgz",
|
||||
"integrity": "sha512-v4Q5HDC0FHAQ7zcBX7T2IL6O5ltl1a2GX4ENjPXg6SjDY69Cmx9v4113C99a4wGF16ClPv5Z8mghuYorVkg/kg==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"symbol-observable": "1.0.1"
|
||||
},
|
||||
"dependencies": {
|
||||
"symbol-observable": {
|
||||
"version": "1.0.1",
|
||||
"resolved": "https://registry.npmjs.org/symbol-observable/-/symbol-observable-1.0.1.tgz",
|
||||
"integrity": "sha1-g0D8RwLDEi310iKI+IKD9RPT/dQ=",
|
||||
"dev": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"safe-buffer": {
|
||||
"version": "5.1.1",
|
||||
"resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.1.tgz",
|
||||
@ -2865,6 +3541,21 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"staged-git-files": {
|
||||
"version": "0.0.4",
|
||||
"resolved": "https://registry.npmjs.org/staged-git-files/-/staged-git-files-0.0.4.tgz",
|
||||
"integrity": "sha1-15fhtVHKemOd7AI33G60u5vhfTU=",
|
||||
"dev": true
|
||||
},
|
||||
"stream-to-observable": {
|
||||
"version": "0.2.0",
|
||||
"resolved": "https://registry.npmjs.org/stream-to-observable/-/stream-to-observable-0.2.0.tgz",
|
||||
"integrity": "sha1-WdbqOT2HwsDdrBCqDVYbxrpvDhA=",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"any-observable": "0.2.0"
|
||||
}
|
||||
},
|
||||
"string-template": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/string-template/-/string-template-1.0.0.tgz",
|
||||
@ -2888,6 +3579,17 @@
|
||||
"safe-buffer": "5.1.1"
|
||||
}
|
||||
},
|
||||
"stringify-object": {
|
||||
"version": "3.2.1",
|
||||
"resolved": "https://registry.npmjs.org/stringify-object/-/stringify-object-3.2.1.tgz",
|
||||
"integrity": "sha512-jPcQYw/52HUPP8uOE4kkjxl5bB9LfHkKCTptIk3qw7ozP5XMIMlHMLjt00GGSwW6DJAf/njY5EU6Vpwl4LlBKQ==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"get-own-enumerable-property-symbols": "2.0.1",
|
||||
"is-obj": "1.0.1",
|
||||
"is-regexp": "1.0.0"
|
||||
}
|
||||
},
|
||||
"stringstream": {
|
||||
"version": "0.0.5",
|
||||
"resolved": "https://registry.npmjs.org/stringstream/-/stringstream-0.0.5.tgz",
|
||||
@ -2912,6 +3614,12 @@
|
||||
"resolved": "https://registry.npmjs.org/strip-eof/-/strip-eof-1.0.0.tgz",
|
||||
"integrity": "sha1-u0P/VZim6wXYm1n80SnJgzE2Br8="
|
||||
},
|
||||
"strip-indent": {
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/strip-indent/-/strip-indent-2.0.0.tgz",
|
||||
"integrity": "sha1-XvjbKV0B5u1sv3qrlpmNeCJSe2g=",
|
||||
"dev": true
|
||||
},
|
||||
"strip-json-comments": {
|
||||
"version": "2.0.1",
|
||||
"resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz",
|
||||
@ -2935,6 +3643,12 @@
|
||||
"upper-case": "1.1.3"
|
||||
}
|
||||
},
|
||||
"symbol-observable": {
|
||||
"version": "0.2.4",
|
||||
"resolved": "https://registry.npmjs.org/symbol-observable/-/symbol-observable-0.2.4.tgz",
|
||||
"integrity": "sha1-lag9smGG1q9+ehjb2XYKL4bQj0A=",
|
||||
"dev": true
|
||||
},
|
||||
"tedious": {
|
||||
"version": "2.1.5",
|
||||
"resolved": "https://registry.npmjs.org/tedious/-/tedious-2.1.5.tgz",
|
||||
|
140
package.json
140
package.json
@ -1,65 +1,79 @@
|
||||
{
|
||||
"name": "typeorm-model-generator",
|
||||
"version": "0.2.6",
|
||||
"description": "Generates models for TypeORM from existing databases.",
|
||||
"bin": "bin/typeorm-model-generator",
|
||||
"scripts": {
|
||||
"tsc:w": "tsc -w",
|
||||
"tsc": "tsc",
|
||||
"typings-install": "typings install",
|
||||
"setup": "npm install && npm run typings-install",
|
||||
"prestart": "tsc",
|
||||
"start": " node ./dist/src/index.js",
|
||||
"test": "istanbul cover ./node_modules/mocha/bin/_mocha dist/test/**/*.test.js -- -R spec",
|
||||
"posttest": "remap-istanbul -i ./coverage/coverage.json -o ./coverage/coverage-remapped.json && codecov --file=./coverage/coverage-remapped.json "
|
||||
},
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "git+https://github.com/Kononnable/typeorm-model-generator.git"
|
||||
},
|
||||
"author": "Kononnable",
|
||||
"license": "MIT",
|
||||
"bugs": {
|
||||
"url": "https://github.com/Kononnable/typeorm-model-generator/issues"
|
||||
},
|
||||
"homepage": "https://github.com/Kononnable/typeorm-model-generator#readme",
|
||||
"dependencies": {
|
||||
"handlebars": "^4.0.11",
|
||||
"mssql": "^4.0.4",
|
||||
"mysql": "^2.15.0",
|
||||
"oracledb": "^2.0.15",
|
||||
"pg": "^7.4.0",
|
||||
"reflect-metadata": "^0.1.10",
|
||||
"typeorm": "^0.2.0-alpha.13",
|
||||
"change-case": "^3.0.1",
|
||||
"typescript": "^2.6.1",
|
||||
"yargs": "^11.0.0",
|
||||
"yn": "^2.0.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/chai": "^4.0.5",
|
||||
"@types/chai-as-promised": "7.1.0",
|
||||
"@types/chai-subset": "^1.3.1",
|
||||
"@types/fs-extra": "^5.0.0",
|
||||
"@types/handlebars": "^4.0.36",
|
||||
"@types/mocha": "^2.2.44",
|
||||
"@types/mssql": "^4.0.4",
|
||||
"@types/mysql": "2.15.2",
|
||||
"@types/oracledb": "^1.11.34",
|
||||
"@types/node": "^9.3.0",
|
||||
"@types/pg": "^7.4.1",
|
||||
"@types/sinon": "^4.1.2",
|
||||
"chai": "^4.1.2",
|
||||
"chai-as-promised": "^7.1.1",
|
||||
"chai-subset": "^1.6.0",
|
||||
"codecov": "^3.0.0",
|
||||
"dotenv": "^5.0.0",
|
||||
"fs-extra": "^5.0.0",
|
||||
"istanbul": "^0.4.5",
|
||||
"mocha": "^5.0.0",
|
||||
"remap-istanbul": "^0.10.0",
|
||||
"sinon": "^4.1.2",
|
||||
"sinon-chai": "^2.14.0",
|
||||
"typings": "^2.1.1"
|
||||
}
|
||||
"name": "typeorm-model-generator",
|
||||
"version": "0.2.6",
|
||||
"description": "Generates models for TypeORM from existing databases.",
|
||||
"bin": "bin/typeorm-model-generator",
|
||||
"scripts": {
|
||||
"tsc:w": "tsc -w",
|
||||
"tsc": "tsc",
|
||||
"typings-install": "typings install",
|
||||
"setup": "npm install && npm run typings-install",
|
||||
"prestart": "tsc",
|
||||
"start": " node ./dist/src/index.js",
|
||||
"test": "istanbul cover ./node_modules/mocha/bin/_mocha dist/test/**/*.test.js -- -R spec",
|
||||
"posttest": "remap-istanbul -i ./coverage/coverage.json -o ./coverage/coverage-remapped.json && codecov --file=./coverage/coverage-remapped.json "
|
||||
},
|
||||
"husky": {
|
||||
"hooks": {
|
||||
"pre-commit": "lint-staged"
|
||||
}
|
||||
},
|
||||
"lint-staged": {
|
||||
"*.{ts,json,md}": [
|
||||
"prettier --write",
|
||||
"git add"
|
||||
]
|
||||
},
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "git+https://github.com/Kononnable/typeorm-model-generator.git"
|
||||
},
|
||||
"author": "Kononnable",
|
||||
"license": "MIT",
|
||||
"bugs": {
|
||||
"url": "https://github.com/Kononnable/typeorm-model-generator/issues"
|
||||
},
|
||||
"homepage": "https://github.com/Kononnable/typeorm-model-generator#readme",
|
||||
"dependencies": {
|
||||
"handlebars": "^4.0.11",
|
||||
"mssql": "^4.0.4",
|
||||
"mysql": "^2.15.0",
|
||||
"oracledb": "^2.0.15",
|
||||
"pg": "^7.4.0",
|
||||
"reflect-metadata": "^0.1.10",
|
||||
"typeorm": "^0.2.0-alpha.13",
|
||||
"change-case": "^3.0.1",
|
||||
"typescript": "^2.6.1",
|
||||
"yargs": "^11.0.0",
|
||||
"yn": "^2.0.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/chai": "^4.0.5",
|
||||
"@types/chai-as-promised": "7.1.0",
|
||||
"@types/chai-subset": "^1.3.1",
|
||||
"@types/fs-extra": "^5.0.0",
|
||||
"@types/handlebars": "^4.0.36",
|
||||
"@types/mocha": "^2.2.44",
|
||||
"@types/mssql": "^4.0.4",
|
||||
"@types/mysql": "2.15.2",
|
||||
"@types/node": "^9.3.0",
|
||||
"@types/oracledb": "^1.11.34",
|
||||
"@types/pg": "^7.4.1",
|
||||
"@types/sinon": "^4.1.2",
|
||||
"chai": "^4.1.2",
|
||||
"chai-as-promised": "^7.1.1",
|
||||
"chai-subset": "^1.6.0",
|
||||
"codecov": "^3.0.0",
|
||||
"dotenv": "^5.0.0",
|
||||
"fs-extra": "^5.0.0",
|
||||
"husky": "^0.14.3",
|
||||
"istanbul": "^0.4.5",
|
||||
"lint-staged": "^6.1.0",
|
||||
"mocha": "^5.0.0",
|
||||
"prettier": "^1.10.2",
|
||||
"remap-istanbul": "^0.10.0",
|
||||
"sinon": "^4.1.2",
|
||||
"sinon-chai": "^2.14.0",
|
||||
"typings": "^2.1.1"
|
||||
}
|
||||
}
|
||||
|
197
src/Engine.ts
197
src/Engine.ts
@ -1,136 +1,172 @@
|
||||
import { AbstractDriver } from "./drivers/AbstractDriver";
|
||||
import { DatabaseModel } from './models/DatabaseModel'
|
||||
import * as Handlebars from 'handlebars'
|
||||
import fs = require('fs');
|
||||
import path = require('path')
|
||||
import * as TomgUtils from './Utils'
|
||||
import { DatabaseModel } from "./models/DatabaseModel";
|
||||
import * as Handlebars from "handlebars";
|
||||
import fs = require("fs");
|
||||
import path = require("path");
|
||||
import * as TomgUtils from "./Utils";
|
||||
import changeCase = require("change-case");
|
||||
/**
|
||||
* Engine
|
||||
*/
|
||||
export class Engine {
|
||||
constructor(private driver: AbstractDriver, public Options: EngineOptions) {
|
||||
}
|
||||
constructor(
|
||||
private driver: AbstractDriver,
|
||||
public Options: EngineOptions
|
||||
) {}
|
||||
|
||||
public async createModelFromDatabase(): Promise<boolean> {
|
||||
let dbModel = await this.getEntitiesInfo(this.Options.databaseName, this.Options.host, this.Options.port, this.Options.user, this.Options.password, this.Options.schemaName, this.Options.ssl);
|
||||
let dbModel = await this.getEntitiesInfo(
|
||||
this.Options.databaseName,
|
||||
this.Options.host,
|
||||
this.Options.port,
|
||||
this.Options.user,
|
||||
this.Options.password,
|
||||
this.Options.schemaName,
|
||||
this.Options.ssl
|
||||
);
|
||||
if (dbModel.entities.length > 0) {
|
||||
this.createModelFromMetadata(dbModel);
|
||||
} else {
|
||||
TomgUtils.LogFatalError('Tables not found in selected database. Skipping creation of typeorm model.', false);
|
||||
TomgUtils.LogFatalError(
|
||||
"Tables not found in selected database. Skipping creation of typeorm model.",
|
||||
false
|
||||
);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
private async getEntitiesInfo(database: string, server: string, port: number, user: string, password: string, schemaName: string, ssl: boolean): Promise<DatabaseModel> {
|
||||
return await this.driver.GetDataFromServer(database, server, port, user, password, schemaName, ssl)
|
||||
|
||||
private async getEntitiesInfo(
|
||||
database: string,
|
||||
server: string,
|
||||
port: number,
|
||||
user: string,
|
||||
password: string,
|
||||
schemaName: string,
|
||||
ssl: boolean
|
||||
): Promise<DatabaseModel> {
|
||||
return await this.driver.GetDataFromServer(
|
||||
database,
|
||||
server,
|
||||
port,
|
||||
user,
|
||||
password,
|
||||
schemaName,
|
||||
ssl
|
||||
);
|
||||
}
|
||||
private createModelFromMetadata(databaseModel: DatabaseModel) {
|
||||
this.createHandlebarsHelpers();
|
||||
let templatePath = path.resolve(__dirname, '../../src/entity.mst')
|
||||
let template = fs.readFileSync(templatePath, 'UTF-8');
|
||||
let resultPath = this.Options.resultsPath
|
||||
if (!fs.existsSync(resultPath))
|
||||
fs.mkdirSync(resultPath);
|
||||
let entitesPath = resultPath
|
||||
let templatePath = path.resolve(__dirname, "../../src/entity.mst");
|
||||
let template = fs.readFileSync(templatePath, "UTF-8");
|
||||
let resultPath = this.Options.resultsPath;
|
||||
if (!fs.existsSync(resultPath)) fs.mkdirSync(resultPath);
|
||||
let entitesPath = resultPath;
|
||||
if (!this.Options.noConfigs) {
|
||||
this.createTsConfigFile(resultPath)
|
||||
this.createTypeOrmConfig(resultPath)
|
||||
entitesPath = path.resolve(resultPath, './entities')
|
||||
if (!fs.existsSync(entitesPath))
|
||||
fs.mkdirSync(entitesPath);
|
||||
this.createTsConfigFile(resultPath);
|
||||
this.createTypeOrmConfig(resultPath);
|
||||
entitesPath = path.resolve(resultPath, "./entities");
|
||||
if (!fs.existsSync(entitesPath)) fs.mkdirSync(entitesPath);
|
||||
}
|
||||
let compliedTemplate = Handlebars.compile(template, { noEscape: true })
|
||||
let compliedTemplate = Handlebars.compile(template, { noEscape: true });
|
||||
databaseModel.entities.forEach(element => {
|
||||
element.Imports = [];
|
||||
element.Columns.forEach((column) => {
|
||||
column.relations.forEach(
|
||||
(relation) => {
|
||||
if (element.EntityName !== relation.relatedTable) { element.Imports.push(relation.relatedTable); }
|
||||
element.Columns.forEach(column => {
|
||||
column.relations.forEach(relation => {
|
||||
if (element.EntityName !== relation.relatedTable) {
|
||||
element.Imports.push(relation.relatedTable);
|
||||
}
|
||||
);
|
||||
});
|
||||
});
|
||||
element.Imports.filter(function (elem, index, self) {
|
||||
element.Imports.filter(function(elem, index, self) {
|
||||
return index === self.indexOf(elem);
|
||||
});
|
||||
let casedFileName = ''
|
||||
let casedFileName = "";
|
||||
switch (this.Options.convertCaseFile) {
|
||||
case 'camel':
|
||||
case "camel":
|
||||
casedFileName = changeCase.camelCase(element.EntityName);
|
||||
break;
|
||||
case 'param':
|
||||
case "param":
|
||||
casedFileName = changeCase.paramCase(element.EntityName);
|
||||
break;
|
||||
case 'pascal':
|
||||
case "pascal":
|
||||
casedFileName = changeCase.pascalCase(element.EntityName);
|
||||
break;
|
||||
case 'none':
|
||||
case "none":
|
||||
casedFileName = element.EntityName;
|
||||
break;
|
||||
}
|
||||
let resultFilePath = path.resolve(entitesPath, (casedFileName) + '.ts');
|
||||
let rendered = compliedTemplate(element)
|
||||
fs.writeFileSync(resultFilePath, rendered, { encoding: 'UTF-8', flag: 'w' })
|
||||
let resultFilePath = path.resolve(
|
||||
entitesPath,
|
||||
casedFileName + ".ts"
|
||||
);
|
||||
let rendered = compliedTemplate(element);
|
||||
fs.writeFileSync(resultFilePath, rendered, {
|
||||
encoding: "UTF-8",
|
||||
flag: "w"
|
||||
});
|
||||
});
|
||||
}
|
||||
private createHandlebarsHelpers() {
|
||||
Handlebars.registerHelper("curly", (open) => { return open ? "{" : "}"; });
|
||||
Handlebars.registerHelper("curly", open => {
|
||||
return open ? "{" : "}";
|
||||
});
|
||||
Handlebars.registerHelper("toEntityName", str => {
|
||||
let retStr = ''
|
||||
let retStr = "";
|
||||
switch (this.Options.convertCaseEntity) {
|
||||
case 'camel':
|
||||
case "camel":
|
||||
retStr = changeCase.camelCase(str);
|
||||
break;
|
||||
case 'pascal':
|
||||
case "pascal":
|
||||
retStr = changeCase.pascalCase(str);
|
||||
break;
|
||||
case 'none':
|
||||
case "none":
|
||||
retStr = str;
|
||||
break;
|
||||
}
|
||||
return retStr;
|
||||
});
|
||||
Handlebars.registerHelper("toFileName", str => {
|
||||
let retStr = ''
|
||||
let retStr = "";
|
||||
switch (this.Options.convertCaseFile) {
|
||||
case 'camel':
|
||||
case "camel":
|
||||
retStr = changeCase.camelCase(str);
|
||||
break;
|
||||
case 'param':
|
||||
case "param":
|
||||
retStr = changeCase.paramCase(str);
|
||||
break;
|
||||
case 'pascal':
|
||||
case "pascal":
|
||||
retStr = changeCase.pascalCase(str);
|
||||
break;
|
||||
case 'none':
|
||||
case "none":
|
||||
retStr = str;
|
||||
break;
|
||||
}
|
||||
return retStr;
|
||||
});
|
||||
Handlebars.registerHelper("toPropertyName", str => {
|
||||
let retStr = ''
|
||||
let retStr = "";
|
||||
switch (this.Options.convertCaseProperty) {
|
||||
case 'camel':
|
||||
case "camel":
|
||||
retStr = changeCase.camelCase(str);
|
||||
break;
|
||||
case 'pascal':
|
||||
case "pascal":
|
||||
retStr = changeCase.pascalCase(str);
|
||||
break;
|
||||
case 'none':
|
||||
case "none":
|
||||
retStr = str;
|
||||
break;
|
||||
}
|
||||
return retStr;
|
||||
});
|
||||
Handlebars.registerHelper('toLowerCase', str => {
|
||||
Handlebars.registerHelper("toLowerCase", str => {
|
||||
return str.toLowerCase();
|
||||
});
|
||||
}
|
||||
|
||||
//TODO:Move to mustache template file
|
||||
private createTsConfigFile(resultPath) {
|
||||
fs.writeFileSync(path.resolve(resultPath, 'tsconfig.json'), `{"compilerOptions": {
|
||||
fs.writeFileSync(
|
||||
path.resolve(resultPath, "tsconfig.json"),
|
||||
`{"compilerOptions": {
|
||||
"lib": ["es5", "es6"],
|
||||
"target": "es6",
|
||||
"module": "commonjs",
|
||||
@ -138,11 +174,15 @@ export class Engine {
|
||||
"emitDecoratorMetadata": true,
|
||||
"experimentalDecorators": true,
|
||||
"sourceMap": true
|
||||
}}`, { encoding: 'UTF-8', flag: 'w' });
|
||||
}}`,
|
||||
{ encoding: "UTF-8", flag: "w" }
|
||||
);
|
||||
}
|
||||
private createTypeOrmConfig(resultPath) {
|
||||
if (this.Options.schemaName == '') {
|
||||
fs.writeFileSync(path.resolve(resultPath, 'ormconfig.json'), `[
|
||||
if (this.Options.schemaName == "") {
|
||||
fs.writeFileSync(
|
||||
path.resolve(resultPath, "ormconfig.json"),
|
||||
`[
|
||||
{
|
||||
"name": "default",
|
||||
"type": "${this.Options.databaseType}",
|
||||
@ -156,10 +196,13 @@ export class Engine {
|
||||
"entities/*.js"
|
||||
]
|
||||
}
|
||||
]`, { encoding: 'UTF-8', flag: 'w' });
|
||||
}
|
||||
else {
|
||||
fs.writeFileSync(path.resolve(resultPath, 'ormconfig.json'), `[
|
||||
]`,
|
||||
{ encoding: "UTF-8", flag: "w" }
|
||||
);
|
||||
} else {
|
||||
fs.writeFileSync(
|
||||
path.resolve(resultPath, "ormconfig.json"),
|
||||
`[
|
||||
{
|
||||
"name": "default",
|
||||
"type": "${this.Options.databaseType}",
|
||||
@ -174,24 +217,24 @@ export class Engine {
|
||||
"entities/*.js"
|
||||
]
|
||||
}
|
||||
]`, { encoding: 'UTF-8', flag: 'w' });
|
||||
]`,
|
||||
{ encoding: "UTF-8", flag: "w" }
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
export interface EngineOptions {
|
||||
host: string,
|
||||
port: number,
|
||||
databaseName: string,
|
||||
user: string,
|
||||
password: string,
|
||||
resultsPath: string,
|
||||
databaseType: string,
|
||||
schemaName: string,
|
||||
ssl: boolean,
|
||||
noConfigs: boolean,
|
||||
convertCaseFile: 'pascal' | 'param' | 'camel' | 'none',
|
||||
convertCaseEntity: 'pascal' | 'camel' | 'none',
|
||||
convertCaseProperty: 'pascal' | 'camel' | 'none',
|
||||
host: string;
|
||||
port: number;
|
||||
databaseName: string;
|
||||
user: string;
|
||||
password: string;
|
||||
resultsPath: string;
|
||||
databaseType: string;
|
||||
schemaName: string;
|
||||
ssl: boolean;
|
||||
noConfigs: boolean;
|
||||
convertCaseFile: "pascal" | "param" | "camel" | "none";
|
||||
convertCaseEntity: "pascal" | "camel" | "none";
|
||||
convertCaseProperty: "pascal" | "camel" | "none";
|
||||
}
|
||||
|
||||
|
29
src/Utils.ts
29
src/Utils.ts
@ -1,13 +1,20 @@
|
||||
|
||||
import * as data from './../../package.json'
|
||||
export function LogFatalError(errText: string, isABug: boolean = true, errObject?: any) {
|
||||
import * as data from "./../../package.json";
|
||||
export function LogFatalError(
|
||||
errText: string,
|
||||
isABug: boolean = true,
|
||||
errObject?: any
|
||||
) {
|
||||
let x = <any>data;
|
||||
console.error(errText)
|
||||
console.error(`Fatal error occured.`)
|
||||
console.error(`${x.name}@${x.version} node@${process.version}`)
|
||||
console.error(`Fatal error occured in typeorm-model-generator.`)
|
||||
console.error(`If this is a bug please open an issue including this log on ${x.bugs.url}`)
|
||||
if (isABug && !errObject) errObject = new Error().stack
|
||||
if (!!errObject) console.error(errObject)
|
||||
process.abort()
|
||||
console.error(errText);
|
||||
console.error(`Fatal error occured.`);
|
||||
console.error(`${x.name}@${x.version} node@${process.version}`);
|
||||
console.error(`Fatal error occured in typeorm-model-generator.`);
|
||||
console.error(
|
||||
`If this is a bug please open an issue including this log on ${
|
||||
x.bugs.url
|
||||
}`
|
||||
);
|
||||
if (isABug && !errObject) errObject = new Error().stack;
|
||||
if (!!errObject) console.error(errObject);
|
||||
process.abort();
|
||||
}
|
||||
|
@ -1,10 +1,18 @@
|
||||
import { EntityInfo } from './../models/EntityInfo'
|
||||
import { DatabaseModel } from './../models/DatabaseModel'
|
||||
import { EntityInfo } from "./../models/EntityInfo";
|
||||
import { DatabaseModel } from "./../models/DatabaseModel";
|
||||
/**
|
||||
* AbstractDriver
|
||||
*/
|
||||
export abstract class AbstractDriver {
|
||||
async GetDataFromServer(database: string, server: string, port: number, user: string, password: string, schema: string, ssl: boolean): Promise<DatabaseModel> {
|
||||
async GetDataFromServer(
|
||||
database: string,
|
||||
server: string,
|
||||
port: number,
|
||||
user: string,
|
||||
password: string,
|
||||
schema: string,
|
||||
ssl: boolean
|
||||
): Promise<DatabaseModel> {
|
||||
let dbModel = <DatabaseModel>{};
|
||||
await this.ConnectToServer(database, server, port, user, password, ssl);
|
||||
dbModel.entities = await this.GetAllTables(schema);
|
||||
@ -12,14 +20,30 @@ export abstract class AbstractDriver {
|
||||
await this.GetIndexesFromEntity(dbModel.entities, schema);
|
||||
dbModel.entities = await this.GetRelations(dbModel.entities, schema);
|
||||
await this.DisconnectFromServer();
|
||||
this.FindPrimaryColumnsFromIndexes(dbModel)
|
||||
this.FindPrimaryColumnsFromIndexes(dbModel);
|
||||
return dbModel;
|
||||
}
|
||||
abstract async ConnectToServer(database: string, server: string, port: number, user: string, password: string, ssl: boolean);
|
||||
abstract async GetAllTables(schema: string): Promise<EntityInfo[]>
|
||||
abstract async GetCoulmnsFromEntity(entities: EntityInfo[], schema: string): Promise<EntityInfo[]>;
|
||||
abstract async GetIndexesFromEntity(entities: EntityInfo[], schema: string): Promise<EntityInfo[]>;
|
||||
abstract async GetRelations(entities: EntityInfo[], schema: string): Promise<EntityInfo[]>;
|
||||
abstract async ConnectToServer(
|
||||
database: string,
|
||||
server: string,
|
||||
port: number,
|
||||
user: string,
|
||||
password: string,
|
||||
ssl: boolean
|
||||
);
|
||||
abstract async GetAllTables(schema: string): Promise<EntityInfo[]>;
|
||||
abstract async GetCoulmnsFromEntity(
|
||||
entities: EntityInfo[],
|
||||
schema: string
|
||||
): Promise<EntityInfo[]>;
|
||||
abstract async GetIndexesFromEntity(
|
||||
entities: EntityInfo[],
|
||||
schema: string
|
||||
): Promise<EntityInfo[]>;
|
||||
abstract async GetRelations(
|
||||
entities: EntityInfo[],
|
||||
schema: string
|
||||
): Promise<EntityInfo[]>;
|
||||
abstract async FindPrimaryColumnsFromIndexes(dbModel: DatabaseModel);
|
||||
abstract async DisconnectFromServer();
|
||||
|
||||
|
@ -1,14 +1,13 @@
|
||||
import { AbstractDriver } from './AbstractDriver'
|
||||
import * as MariaDb from 'mysql'
|
||||
import { ColumnInfo } from './../models/ColumnInfo'
|
||||
import { EntityInfo } from './../models/EntityInfo'
|
||||
import { RelationInfo } from './../models/RelationInfo'
|
||||
import { DatabaseModel } from './../models/DatabaseModel'
|
||||
import { MysqlDriver } from './MysqlDriver';
|
||||
import { AbstractDriver } from "./AbstractDriver";
|
||||
import * as MariaDb from "mysql";
|
||||
import { ColumnInfo } from "./../models/ColumnInfo";
|
||||
import { EntityInfo } from "./../models/EntityInfo";
|
||||
import { RelationInfo } from "./../models/RelationInfo";
|
||||
import { DatabaseModel } from "./../models/DatabaseModel";
|
||||
import { MysqlDriver } from "./MysqlDriver";
|
||||
/**
|
||||
* MariaDb
|
||||
*/
|
||||
export class MariaDbDriver extends MysqlDriver {
|
||||
readonly EngineName: string = 'MariaDb'
|
||||
|
||||
readonly EngineName: string = "MariaDb";
|
||||
}
|
||||
|
@ -1,10 +1,10 @@
|
||||
import { AbstractDriver } from './AbstractDriver'
|
||||
import * as MSSQL from 'mssql'
|
||||
import { ColumnInfo } from './../models/ColumnInfo'
|
||||
import { EntityInfo } from './../models/EntityInfo'
|
||||
import { RelationInfo } from './../models/RelationInfo'
|
||||
import { DatabaseModel } from './../models/DatabaseModel'
|
||||
import * as TomgUtils from './../Utils'
|
||||
import { AbstractDriver } from "./AbstractDriver";
|
||||
import * as MSSQL from "mssql";
|
||||
import { ColumnInfo } from "./../models/ColumnInfo";
|
||||
import { EntityInfo } from "./../models/EntityInfo";
|
||||
import { RelationInfo } from "./../models/RelationInfo";
|
||||
import { DatabaseModel } from "./../models/DatabaseModel";
|
||||
import * as TomgUtils from "./../Utils";
|
||||
|
||||
/**
|
||||
* MssqlDriver
|
||||
@ -14,204 +14,277 @@ export class MssqlDriver extends AbstractDriver {
|
||||
dbModel.entities.forEach(entity => {
|
||||
let primaryIndex = entity.Indexes.find(v => v.isPrimaryKey);
|
||||
if (!primaryIndex) {
|
||||
TomgUtils.LogFatalError(`Table ${entity.EntityName} has no PK.`, false)
|
||||
TomgUtils.LogFatalError(
|
||||
`Table ${entity.EntityName} has no PK.`,
|
||||
false
|
||||
);
|
||||
return;
|
||||
}
|
||||
entity.Columns.forEach(col => {
|
||||
if (primaryIndex!.columns.some(cIndex => cIndex.name == col.name)) col.isPrimary = true
|
||||
})
|
||||
if (
|
||||
primaryIndex!.columns.some(
|
||||
cIndex => cIndex.name == col.name
|
||||
)
|
||||
)
|
||||
col.isPrimary = true;
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
async GetAllTables(schema: string): Promise<EntityInfo[]> {
|
||||
let request = new MSSQL.Request(this.Connection)
|
||||
let response: { TABLE_SCHEMA: string, TABLE_NAME: string }[]
|
||||
= (await request.query(`SELECT TABLE_SCHEMA,TABLE_NAME FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_TYPE='BASE TABLE' and TABLE_SCHEMA='${schema}'`)).recordset;
|
||||
let request = new MSSQL.Request(this.Connection);
|
||||
let response: {
|
||||
TABLE_SCHEMA: string;
|
||||
TABLE_NAME: string;
|
||||
}[] = (await request.query(
|
||||
`SELECT TABLE_SCHEMA,TABLE_NAME FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_TYPE='BASE TABLE' and TABLE_SCHEMA='${schema}'`
|
||||
)).recordset;
|
||||
let ret: EntityInfo[] = <EntityInfo[]>[];
|
||||
response.forEach((val) => {
|
||||
response.forEach(val => {
|
||||
let ent: EntityInfo = new EntityInfo();
|
||||
ent.EntityName = val.TABLE_NAME;
|
||||
ent.Columns = <ColumnInfo[]>[];
|
||||
ent.Indexes = <IndexInfo[]>[];
|
||||
ret.push(ent);
|
||||
})
|
||||
});
|
||||
return ret;
|
||||
}
|
||||
async GetCoulmnsFromEntity(entities: EntityInfo[], schema: string): Promise<EntityInfo[]> {
|
||||
let request = new MSSQL.Request(this.Connection)
|
||||
async GetCoulmnsFromEntity(
|
||||
entities: EntityInfo[],
|
||||
schema: string
|
||||
): Promise<EntityInfo[]> {
|
||||
let request = new MSSQL.Request(this.Connection);
|
||||
let response: {
|
||||
TABLE_NAME: string, COLUMN_NAME: string, COLUMN_DEFAULT: string,
|
||||
IS_NULLABLE: string, DATA_TYPE: string, CHARACTER_MAXIMUM_LENGTH: number,
|
||||
NUMERIC_PRECISION: number, NUMERIC_SCALE: number, IsIdentity: number
|
||||
}[]
|
||||
= (await request.query(`SELECT TABLE_NAME,COLUMN_NAME,COLUMN_DEFAULT,IS_NULLABLE,
|
||||
TABLE_NAME: string;
|
||||
COLUMN_NAME: string;
|
||||
COLUMN_DEFAULT: string;
|
||||
IS_NULLABLE: string;
|
||||
DATA_TYPE: string;
|
||||
CHARACTER_MAXIMUM_LENGTH: number;
|
||||
NUMERIC_PRECISION: number;
|
||||
NUMERIC_SCALE: number;
|
||||
IsIdentity: number;
|
||||
}[] = (await request.query(`SELECT TABLE_NAME,COLUMN_NAME,COLUMN_DEFAULT,IS_NULLABLE,
|
||||
DATA_TYPE,CHARACTER_MAXIMUM_LENGTH,NUMERIC_PRECISION,NUMERIC_SCALE,
|
||||
COLUMNPROPERTY(object_id(TABLE_NAME), COLUMN_NAME, 'IsIdentity') IsIdentity FROM INFORMATION_SCHEMA.COLUMNS where TABLE_SCHEMA='${schema}'`)).recordset;
|
||||
entities.forEach((ent) => {
|
||||
response.filter((filterVal) => {
|
||||
return filterVal.TABLE_NAME == ent.EntityName;
|
||||
}).forEach((resp) => {
|
||||
let colInfo: ColumnInfo = new ColumnInfo();
|
||||
colInfo.name = resp.COLUMN_NAME;
|
||||
colInfo.is_nullable = resp.IS_NULLABLE == 'YES' ? true : false;
|
||||
colInfo.is_generated = resp.IsIdentity == 1 ? true : false;
|
||||
colInfo.default = resp.COLUMN_DEFAULT;
|
||||
switch (resp.DATA_TYPE) {
|
||||
case "int":
|
||||
colInfo.ts_type = "number"
|
||||
colInfo.sql_type = "int"
|
||||
colInfo.char_max_lenght = resp.CHARACTER_MAXIMUM_LENGTH > 0 ? resp.CHARACTER_MAXIMUM_LENGTH : null;
|
||||
break;
|
||||
case "tinyint":
|
||||
colInfo.ts_type = "number"
|
||||
colInfo.sql_type = "smallint"
|
||||
colInfo.char_max_lenght = resp.CHARACTER_MAXIMUM_LENGTH > 0 ? resp.CHARACTER_MAXIMUM_LENGTH : null;
|
||||
break;
|
||||
case "smallint":
|
||||
colInfo.ts_type = "number"
|
||||
colInfo.sql_type = "smallint"
|
||||
colInfo.char_max_lenght = resp.CHARACTER_MAXIMUM_LENGTH > 0 ? resp.CHARACTER_MAXIMUM_LENGTH : null;
|
||||
break;
|
||||
case "bit":
|
||||
colInfo.ts_type = "boolean"
|
||||
colInfo.sql_type = "boolean"
|
||||
break;
|
||||
case "float":
|
||||
colInfo.ts_type = "number"
|
||||
colInfo.sql_type = "float"
|
||||
colInfo.char_max_lenght = resp.CHARACTER_MAXIMUM_LENGTH > 0 ? resp.CHARACTER_MAXIMUM_LENGTH : null;
|
||||
colInfo.numericPrecision = resp.NUMERIC_PRECISION
|
||||
break;
|
||||
case "bigint":
|
||||
colInfo.ts_type = "string"
|
||||
colInfo.sql_type = "bigint"
|
||||
colInfo.char_max_lenght = resp.CHARACTER_MAXIMUM_LENGTH > 0 ? resp.CHARACTER_MAXIMUM_LENGTH : null;
|
||||
break;
|
||||
case "date":
|
||||
colInfo.ts_type = "Date"
|
||||
colInfo.sql_type = "date"
|
||||
break;
|
||||
case "time":
|
||||
colInfo.ts_type = "Date"
|
||||
colInfo.sql_type = "time"
|
||||
break;
|
||||
case "datetime":
|
||||
colInfo.ts_type = "Date";
|
||||
colInfo.sql_type = "datetime"
|
||||
break;
|
||||
case "char":
|
||||
colInfo.ts_type = "string"
|
||||
colInfo.sql_type = "char"
|
||||
colInfo.char_max_lenght = resp.CHARACTER_MAXIMUM_LENGTH > 0 ? resp.CHARACTER_MAXIMUM_LENGTH : null;
|
||||
break;
|
||||
case "nchar":
|
||||
colInfo.ts_type = "string"
|
||||
colInfo.sql_type = "nchar"
|
||||
colInfo.char_max_lenght = resp.CHARACTER_MAXIMUM_LENGTH > 0 ? resp.CHARACTER_MAXIMUM_LENGTH : null;
|
||||
break;
|
||||
case "text":
|
||||
colInfo.ts_type = "string"
|
||||
colInfo.sql_type = "text"
|
||||
break;
|
||||
case "ntext":
|
||||
colInfo.ts_type = "string"
|
||||
colInfo.sql_type = "ntext"
|
||||
break;
|
||||
case "uniqueidentifier":
|
||||
colInfo.ts_type = "string"
|
||||
colInfo.sql_type = "uniqueidentifier"
|
||||
break;
|
||||
case "varchar":
|
||||
colInfo.ts_type = "string"
|
||||
colInfo.sql_type = "varchar"
|
||||
colInfo.char_max_lenght = resp.CHARACTER_MAXIMUM_LENGTH > 0 ? resp.CHARACTER_MAXIMUM_LENGTH : null;
|
||||
break;
|
||||
case "binary":
|
||||
colInfo.ts_type = "Buffer"
|
||||
colInfo.sql_type = "binary"
|
||||
colInfo.char_max_lenght = resp.CHARACTER_MAXIMUM_LENGTH > 0 ? resp.CHARACTER_MAXIMUM_LENGTH : null;
|
||||
break;
|
||||
case "varbinary":
|
||||
colInfo.ts_type = "Buffer"
|
||||
colInfo.sql_type = "varbinary"
|
||||
colInfo.char_max_lenght = resp.CHARACTER_MAXIMUM_LENGTH > 0 ? resp.CHARACTER_MAXIMUM_LENGTH : null;
|
||||
break;
|
||||
case "image":
|
||||
colInfo.ts_type = "Buffer"
|
||||
colInfo.sql_type = "image"
|
||||
break;
|
||||
case "nvarchar":
|
||||
colInfo.ts_type = "string"
|
||||
colInfo.sql_type = "nvarchar"
|
||||
colInfo.char_max_lenght = resp.CHARACTER_MAXIMUM_LENGTH > 0 ? resp.CHARACTER_MAXIMUM_LENGTH : null;
|
||||
break;
|
||||
case "money":
|
||||
colInfo.ts_type = "number"
|
||||
colInfo.sql_type = "decimal"
|
||||
break;
|
||||
case "smallmoney":
|
||||
colInfo.ts_type = "number"
|
||||
colInfo.sql_type = "smallmoney"
|
||||
break;
|
||||
case "real":
|
||||
colInfo.ts_type = "number"
|
||||
colInfo.sql_type = "double"
|
||||
colInfo.char_max_lenght = resp.CHARACTER_MAXIMUM_LENGTH > 0 ? resp.CHARACTER_MAXIMUM_LENGTH : null;
|
||||
break;
|
||||
case "decimal":
|
||||
colInfo.ts_type = "number"
|
||||
colInfo.sql_type = "decimal"
|
||||
colInfo.numericPrecision = resp.NUMERIC_PRECISION
|
||||
colInfo.numericScale = resp.NUMERIC_SCALE
|
||||
colInfo.char_max_lenght = resp.CHARACTER_MAXIMUM_LENGTH > 0 ? resp.CHARACTER_MAXIMUM_LENGTH : null;
|
||||
break;
|
||||
case "numeric":
|
||||
colInfo.ts_type = "number"
|
||||
colInfo.sql_type = "numeric"
|
||||
colInfo.numericPrecision = resp.NUMERIC_PRECISION
|
||||
colInfo.numericScale = resp.NUMERIC_SCALE
|
||||
colInfo.char_max_lenght = resp.CHARACTER_MAXIMUM_LENGTH > 0 ? resp.CHARACTER_MAXIMUM_LENGTH : null;
|
||||
break;
|
||||
case "datetime2":
|
||||
colInfo.ts_type = "Date"
|
||||
colInfo.sql_type = "datetime2"
|
||||
colInfo.numericPrecision = resp.NUMERIC_PRECISION
|
||||
break;
|
||||
case "time":
|
||||
colInfo.ts_type = "Date"
|
||||
colInfo.sql_type = "time"
|
||||
colInfo.numericPrecision = resp.NUMERIC_PRECISION
|
||||
break;
|
||||
case "datetimeoffset":
|
||||
colInfo.ts_type = "Date"
|
||||
colInfo.sql_type = "datetimeoffset"
|
||||
colInfo.numericPrecision = resp.NUMERIC_PRECISION
|
||||
break;
|
||||
case "smalldatetime":
|
||||
colInfo.ts_type = "Date"
|
||||
colInfo.sql_type = "smalldatetime"
|
||||
break;
|
||||
case "xml":
|
||||
colInfo.ts_type = "string"
|
||||
colInfo.sql_type = "text"
|
||||
break;
|
||||
default:
|
||||
TomgUtils.LogFatalError("Unknown column type:" + resp.DATA_TYPE);
|
||||
break;
|
||||
}
|
||||
COLUMNPROPERTY(object_id(TABLE_NAME), COLUMN_NAME, 'IsIdentity') IsIdentity FROM INFORMATION_SCHEMA.COLUMNS where TABLE_SCHEMA='${schema}'`))
|
||||
.recordset;
|
||||
entities.forEach(ent => {
|
||||
response
|
||||
.filter(filterVal => {
|
||||
return filterVal.TABLE_NAME == ent.EntityName;
|
||||
})
|
||||
.forEach(resp => {
|
||||
let colInfo: ColumnInfo = new ColumnInfo();
|
||||
colInfo.name = resp.COLUMN_NAME;
|
||||
colInfo.is_nullable =
|
||||
resp.IS_NULLABLE == "YES" ? true : false;
|
||||
colInfo.is_generated = resp.IsIdentity == 1 ? true : false;
|
||||
colInfo.default = resp.COLUMN_DEFAULT;
|
||||
switch (resp.DATA_TYPE) {
|
||||
case "int":
|
||||
colInfo.ts_type = "number";
|
||||
colInfo.sql_type = "int";
|
||||
colInfo.char_max_lenght =
|
||||
resp.CHARACTER_MAXIMUM_LENGTH > 0
|
||||
? resp.CHARACTER_MAXIMUM_LENGTH
|
||||
: null;
|
||||
break;
|
||||
case "tinyint":
|
||||
colInfo.ts_type = "number";
|
||||
colInfo.sql_type = "smallint";
|
||||
colInfo.char_max_lenght =
|
||||
resp.CHARACTER_MAXIMUM_LENGTH > 0
|
||||
? resp.CHARACTER_MAXIMUM_LENGTH
|
||||
: null;
|
||||
break;
|
||||
case "smallint":
|
||||
colInfo.ts_type = "number";
|
||||
colInfo.sql_type = "smallint";
|
||||
colInfo.char_max_lenght =
|
||||
resp.CHARACTER_MAXIMUM_LENGTH > 0
|
||||
? resp.CHARACTER_MAXIMUM_LENGTH
|
||||
: null;
|
||||
break;
|
||||
case "bit":
|
||||
colInfo.ts_type = "boolean";
|
||||
colInfo.sql_type = "boolean";
|
||||
break;
|
||||
case "float":
|
||||
colInfo.ts_type = "number";
|
||||
colInfo.sql_type = "float";
|
||||
colInfo.char_max_lenght =
|
||||
resp.CHARACTER_MAXIMUM_LENGTH > 0
|
||||
? resp.CHARACTER_MAXIMUM_LENGTH
|
||||
: null;
|
||||
colInfo.numericPrecision = resp.NUMERIC_PRECISION;
|
||||
break;
|
||||
case "bigint":
|
||||
colInfo.ts_type = "string";
|
||||
colInfo.sql_type = "bigint";
|
||||
colInfo.char_max_lenght =
|
||||
resp.CHARACTER_MAXIMUM_LENGTH > 0
|
||||
? resp.CHARACTER_MAXIMUM_LENGTH
|
||||
: null;
|
||||
break;
|
||||
case "date":
|
||||
colInfo.ts_type = "Date";
|
||||
colInfo.sql_type = "date";
|
||||
break;
|
||||
case "time":
|
||||
colInfo.ts_type = "Date";
|
||||
colInfo.sql_type = "time";
|
||||
break;
|
||||
case "datetime":
|
||||
colInfo.ts_type = "Date";
|
||||
colInfo.sql_type = "datetime";
|
||||
break;
|
||||
case "char":
|
||||
colInfo.ts_type = "string";
|
||||
colInfo.sql_type = "char";
|
||||
colInfo.char_max_lenght =
|
||||
resp.CHARACTER_MAXIMUM_LENGTH > 0
|
||||
? resp.CHARACTER_MAXIMUM_LENGTH
|
||||
: null;
|
||||
break;
|
||||
case "nchar":
|
||||
colInfo.ts_type = "string";
|
||||
colInfo.sql_type = "nchar";
|
||||
colInfo.char_max_lenght =
|
||||
resp.CHARACTER_MAXIMUM_LENGTH > 0
|
||||
? resp.CHARACTER_MAXIMUM_LENGTH
|
||||
: null;
|
||||
break;
|
||||
case "text":
|
||||
colInfo.ts_type = "string";
|
||||
colInfo.sql_type = "text";
|
||||
break;
|
||||
case "ntext":
|
||||
colInfo.ts_type = "string";
|
||||
colInfo.sql_type = "ntext";
|
||||
break;
|
||||
case "uniqueidentifier":
|
||||
colInfo.ts_type = "string";
|
||||
colInfo.sql_type = "uniqueidentifier";
|
||||
break;
|
||||
case "varchar":
|
||||
colInfo.ts_type = "string";
|
||||
colInfo.sql_type = "varchar";
|
||||
colInfo.char_max_lenght =
|
||||
resp.CHARACTER_MAXIMUM_LENGTH > 0
|
||||
? resp.CHARACTER_MAXIMUM_LENGTH
|
||||
: null;
|
||||
break;
|
||||
case "binary":
|
||||
colInfo.ts_type = "Buffer";
|
||||
colInfo.sql_type = "binary";
|
||||
colInfo.char_max_lenght =
|
||||
resp.CHARACTER_MAXIMUM_LENGTH > 0
|
||||
? resp.CHARACTER_MAXIMUM_LENGTH
|
||||
: null;
|
||||
break;
|
||||
case "varbinary":
|
||||
colInfo.ts_type = "Buffer";
|
||||
colInfo.sql_type = "varbinary";
|
||||
colInfo.char_max_lenght =
|
||||
resp.CHARACTER_MAXIMUM_LENGTH > 0
|
||||
? resp.CHARACTER_MAXIMUM_LENGTH
|
||||
: null;
|
||||
break;
|
||||
case "image":
|
||||
colInfo.ts_type = "Buffer";
|
||||
colInfo.sql_type = "image";
|
||||
break;
|
||||
case "nvarchar":
|
||||
colInfo.ts_type = "string";
|
||||
colInfo.sql_type = "nvarchar";
|
||||
colInfo.char_max_lenght =
|
||||
resp.CHARACTER_MAXIMUM_LENGTH > 0
|
||||
? resp.CHARACTER_MAXIMUM_LENGTH
|
||||
: null;
|
||||
break;
|
||||
case "money":
|
||||
colInfo.ts_type = "number";
|
||||
colInfo.sql_type = "decimal";
|
||||
break;
|
||||
case "smallmoney":
|
||||
colInfo.ts_type = "number";
|
||||
colInfo.sql_type = "smallmoney";
|
||||
break;
|
||||
case "real":
|
||||
colInfo.ts_type = "number";
|
||||
colInfo.sql_type = "double";
|
||||
colInfo.char_max_lenght =
|
||||
resp.CHARACTER_MAXIMUM_LENGTH > 0
|
||||
? resp.CHARACTER_MAXIMUM_LENGTH
|
||||
: null;
|
||||
break;
|
||||
case "decimal":
|
||||
colInfo.ts_type = "number";
|
||||
colInfo.sql_type = "decimal";
|
||||
colInfo.numericPrecision = resp.NUMERIC_PRECISION;
|
||||
colInfo.numericScale = resp.NUMERIC_SCALE;
|
||||
colInfo.char_max_lenght =
|
||||
resp.CHARACTER_MAXIMUM_LENGTH > 0
|
||||
? resp.CHARACTER_MAXIMUM_LENGTH
|
||||
: null;
|
||||
break;
|
||||
case "numeric":
|
||||
colInfo.ts_type = "number";
|
||||
colInfo.sql_type = "numeric";
|
||||
colInfo.numericPrecision = resp.NUMERIC_PRECISION;
|
||||
colInfo.numericScale = resp.NUMERIC_SCALE;
|
||||
colInfo.char_max_lenght =
|
||||
resp.CHARACTER_MAXIMUM_LENGTH > 0
|
||||
? resp.CHARACTER_MAXIMUM_LENGTH
|
||||
: null;
|
||||
break;
|
||||
case "datetime2":
|
||||
colInfo.ts_type = "Date";
|
||||
colInfo.sql_type = "datetime2";
|
||||
colInfo.numericPrecision = resp.NUMERIC_PRECISION;
|
||||
break;
|
||||
case "time":
|
||||
colInfo.ts_type = "Date";
|
||||
colInfo.sql_type = "time";
|
||||
colInfo.numericPrecision = resp.NUMERIC_PRECISION;
|
||||
break;
|
||||
case "datetimeoffset":
|
||||
colInfo.ts_type = "Date";
|
||||
colInfo.sql_type = "datetimeoffset";
|
||||
colInfo.numericPrecision = resp.NUMERIC_PRECISION;
|
||||
break;
|
||||
case "smalldatetime":
|
||||
colInfo.ts_type = "Date";
|
||||
colInfo.sql_type = "smalldatetime";
|
||||
break;
|
||||
case "xml":
|
||||
colInfo.ts_type = "string";
|
||||
colInfo.sql_type = "text";
|
||||
break;
|
||||
default:
|
||||
TomgUtils.LogFatalError(
|
||||
"Unknown column type:" + resp.DATA_TYPE
|
||||
);
|
||||
break;
|
||||
}
|
||||
|
||||
if (colInfo.sql_type) ent.Columns.push(colInfo);
|
||||
})
|
||||
})
|
||||
if (colInfo.sql_type) ent.Columns.push(colInfo);
|
||||
});
|
||||
});
|
||||
return entities;
|
||||
}
|
||||
async GetIndexesFromEntity(entities: EntityInfo[], schema: string): Promise<EntityInfo[]> {
|
||||
let request = new MSSQL.Request(this.Connection)
|
||||
async GetIndexesFromEntity(
|
||||
entities: EntityInfo[],
|
||||
schema: string
|
||||
): Promise<EntityInfo[]> {
|
||||
let request = new MSSQL.Request(this.Connection);
|
||||
let response: {
|
||||
TableName: string, IndexName: string, ColumnName: string, is_unique: number,
|
||||
is_primary_key: number//, is_descending_key: number//, is_included_column: number
|
||||
}[]
|
||||
= (await request.query(`SELECT
|
||||
TableName: string;
|
||||
IndexName: string;
|
||||
ColumnName: string;
|
||||
is_unique: number;
|
||||
is_primary_key: number; //, is_descending_key: number//, is_included_column: number
|
||||
}[] = (await request.query(`SELECT
|
||||
TableName = t.name,
|
||||
IndexName = ind.name,
|
||||
ColumnName = col.name,
|
||||
@ -233,44 +306,54 @@ WHERE
|
||||
t.is_ms_shipped = 0 and s.name='${schema}'
|
||||
ORDER BY
|
||||
t.name, ind.name, ind.index_id, ic.key_ordinal;`)).recordset;
|
||||
entities.forEach((ent) => {
|
||||
response.filter((filterVal) => {
|
||||
return filterVal.TableName == ent.EntityName;
|
||||
}).forEach((resp) => {
|
||||
let indexInfo: IndexInfo = <IndexInfo>{};
|
||||
let indexColumnInfo: IndexColumnInfo = <IndexColumnInfo>{};
|
||||
if (ent.Indexes.filter((filterVal) => {
|
||||
return filterVal.name == resp.IndexName
|
||||
}).length > 0) {
|
||||
indexInfo = ent.Indexes.filter((filterVal) => {
|
||||
return filterVal.name == resp.IndexName
|
||||
})[0];
|
||||
} else {
|
||||
indexInfo.columns = <IndexColumnInfo[]>[];
|
||||
indexInfo.name = resp.IndexName;
|
||||
indexInfo.isUnique = resp.is_unique == 1 ? true : false;
|
||||
indexInfo.isPrimaryKey = resp.is_primary_key == 1 ? true : false;
|
||||
ent.Indexes.push(indexInfo);
|
||||
}
|
||||
indexColumnInfo.name = resp.ColumnName;
|
||||
// indexColumnInfo.isIncludedColumn = resp.is_included_column == 1 ? true : false;
|
||||
// indexColumnInfo.isDescending = resp.is_descending_key == 1 ? true : false;
|
||||
indexInfo.columns.push(indexColumnInfo);
|
||||
|
||||
})
|
||||
})
|
||||
entities.forEach(ent => {
|
||||
response
|
||||
.filter(filterVal => {
|
||||
return filterVal.TableName == ent.EntityName;
|
||||
})
|
||||
.forEach(resp => {
|
||||
let indexInfo: IndexInfo = <IndexInfo>{};
|
||||
let indexColumnInfo: IndexColumnInfo = <IndexColumnInfo>{};
|
||||
if (
|
||||
ent.Indexes.filter(filterVal => {
|
||||
return filterVal.name == resp.IndexName;
|
||||
}).length > 0
|
||||
) {
|
||||
indexInfo = ent.Indexes.filter(filterVal => {
|
||||
return filterVal.name == resp.IndexName;
|
||||
})[0];
|
||||
} else {
|
||||
indexInfo.columns = <IndexColumnInfo[]>[];
|
||||
indexInfo.name = resp.IndexName;
|
||||
indexInfo.isUnique = resp.is_unique == 1 ? true : false;
|
||||
indexInfo.isPrimaryKey =
|
||||
resp.is_primary_key == 1 ? true : false;
|
||||
ent.Indexes.push(indexInfo);
|
||||
}
|
||||
indexColumnInfo.name = resp.ColumnName;
|
||||
// indexColumnInfo.isIncludedColumn = resp.is_included_column == 1 ? true : false;
|
||||
// indexColumnInfo.isDescending = resp.is_descending_key == 1 ? true : false;
|
||||
indexInfo.columns.push(indexColumnInfo);
|
||||
});
|
||||
});
|
||||
|
||||
return entities;
|
||||
}
|
||||
async GetRelations(entities: EntityInfo[], schema: string): Promise<EntityInfo[]> {
|
||||
let request = new MSSQL.Request(this.Connection)
|
||||
async GetRelations(
|
||||
entities: EntityInfo[],
|
||||
schema: string
|
||||
): Promise<EntityInfo[]> {
|
||||
let request = new MSSQL.Request(this.Connection);
|
||||
let response: {
|
||||
TableWithForeignKey: string, FK_PartNo: number, ForeignKeyColumn: string,
|
||||
TableReferenced: string, ForeignKeyColumnReferenced: string,
|
||||
onDelete: "RESTRICT" | "CASCADE" | "SET NULL",
|
||||
onUpdate: "RESTRICT" | "CASCADE" | "SET NULL", object_id: number
|
||||
}[]
|
||||
= (await request.query(`select
|
||||
TableWithForeignKey: string;
|
||||
FK_PartNo: number;
|
||||
ForeignKeyColumn: string;
|
||||
TableReferenced: string;
|
||||
ForeignKeyColumnReferenced: string;
|
||||
onDelete: "RESTRICT" | "CASCADE" | "SET NULL";
|
||||
onUpdate: "RESTRICT" | "CASCADE" | "SET NULL";
|
||||
object_id: number;
|
||||
}[] = (await request.query(`select
|
||||
parentTable.name as TableWithForeignKey,
|
||||
fkc.constraint_column_id as FK_PartNo,
|
||||
parentColumn.name as ForeignKeyColumn,
|
||||
@ -298,10 +381,10 @@ where
|
||||
order by
|
||||
TableWithForeignKey, FK_PartNo`)).recordset;
|
||||
let relationsTemp: RelationTempInfo[] = <RelationTempInfo[]>[];
|
||||
response.forEach((resp) => {
|
||||
let rels = relationsTemp.find((val) => {
|
||||
response.forEach(resp => {
|
||||
let rels = relationsTemp.find(val => {
|
||||
return val.object_id == resp.object_id;
|
||||
})
|
||||
});
|
||||
if (rels == undefined) {
|
||||
rels = <RelationTempInfo>{};
|
||||
rels.ownerColumnsNames = [];
|
||||
@ -315,112 +398,148 @@ order by
|
||||
}
|
||||
rels.ownerColumnsNames.push(resp.ForeignKeyColumn);
|
||||
rels.referencedColumnsNames.push(resp.ForeignKeyColumnReferenced);
|
||||
})
|
||||
relationsTemp.forEach((relationTmp) => {
|
||||
let ownerEntity = entities.find((entitity) => {
|
||||
});
|
||||
relationsTemp.forEach(relationTmp => {
|
||||
let ownerEntity = entities.find(entitity => {
|
||||
return entitity.EntityName == relationTmp.ownerTable;
|
||||
})
|
||||
});
|
||||
if (!ownerEntity) {
|
||||
TomgUtils.LogFatalError(`Relation between tables ${relationTmp.ownerTable} and ${relationTmp.referencedTable} didn't found entity model ${relationTmp.ownerTable}.`)
|
||||
TomgUtils.LogFatalError(
|
||||
`Relation between tables ${relationTmp.ownerTable} and ${
|
||||
relationTmp.referencedTable
|
||||
} didn't found entity model ${relationTmp.ownerTable}.`
|
||||
);
|
||||
return;
|
||||
}
|
||||
let referencedEntity = entities.find((entitity) => {
|
||||
let referencedEntity = entities.find(entitity => {
|
||||
return entitity.EntityName == relationTmp.referencedTable;
|
||||
})
|
||||
});
|
||||
if (!referencedEntity) {
|
||||
TomgUtils.LogFatalError(`Relation between tables ${relationTmp.ownerTable} and ${relationTmp.referencedTable} didn't found entity model ${relationTmp.referencedTable}.`)
|
||||
TomgUtils.LogFatalError(
|
||||
`Relation between tables ${relationTmp.ownerTable} and ${
|
||||
relationTmp.referencedTable
|
||||
} didn't found entity model ${relationTmp.referencedTable}.`
|
||||
);
|
||||
return;
|
||||
}
|
||||
let ownerColumn = ownerEntity.Columns.find((column) => {
|
||||
let ownerColumn = ownerEntity.Columns.find(column => {
|
||||
return column.name == relationTmp.ownerColumnsNames[0];
|
||||
})
|
||||
});
|
||||
if (!ownerColumn) {
|
||||
TomgUtils.LogFatalError(`Relation between tables ${relationTmp.ownerTable} and ${relationTmp.referencedTable} didn't found entity column ${relationTmp.ownerTable}.${ownerColumn}.`)
|
||||
TomgUtils.LogFatalError(
|
||||
`Relation between tables ${relationTmp.ownerTable} and ${
|
||||
relationTmp.referencedTable
|
||||
} didn't found entity column ${
|
||||
relationTmp.ownerTable
|
||||
}.${ownerColumn}.`
|
||||
);
|
||||
return;
|
||||
}
|
||||
let relatedColumn = referencedEntity.Columns.find((column) => {
|
||||
let relatedColumn = referencedEntity.Columns.find(column => {
|
||||
return column.name == relationTmp.referencedColumnsNames[0];
|
||||
})
|
||||
});
|
||||
if (!relatedColumn) {
|
||||
TomgUtils.LogFatalError(`Relation between tables ${relationTmp.ownerTable} and ${relationTmp.referencedTable} didn't found entity column ${relationTmp.referencedTable}.${relatedColumn}.`)
|
||||
TomgUtils.LogFatalError(
|
||||
`Relation between tables ${relationTmp.ownerTable} and ${
|
||||
relationTmp.referencedTable
|
||||
} didn't found entity column ${
|
||||
relationTmp.referencedTable
|
||||
}.${relatedColumn}.`
|
||||
);
|
||||
return;
|
||||
}
|
||||
let ownColumn: ColumnInfo = ownerColumn;
|
||||
let isOneToMany: boolean;
|
||||
isOneToMany = false;
|
||||
let index = ownerEntity.Indexes.find(
|
||||
(index) => {
|
||||
return index.isUnique && index.columns.some(col => {
|
||||
return col.name == ownerColumn!.name
|
||||
let index = ownerEntity.Indexes.find(index => {
|
||||
return (
|
||||
index.isUnique &&
|
||||
index.columns.some(col => {
|
||||
return col.name == ownerColumn!.name;
|
||||
})
|
||||
}
|
||||
)
|
||||
);
|
||||
});
|
||||
if (!index) {
|
||||
isOneToMany = true;
|
||||
} else {
|
||||
isOneToMany = false;
|
||||
}
|
||||
let ownerRelation = new RelationInfo()
|
||||
let columnName = ownerEntity.EntityName.toLowerCase() + (isOneToMany ? 's' : '')
|
||||
if (referencedEntity.Columns.filter((filterVal) => {
|
||||
return filterVal.name == columnName;
|
||||
}).length > 0) {
|
||||
let ownerRelation = new RelationInfo();
|
||||
let columnName =
|
||||
ownerEntity.EntityName.toLowerCase() + (isOneToMany ? "s" : "");
|
||||
if (
|
||||
referencedEntity.Columns.filter(filterVal => {
|
||||
return filterVal.name == columnName;
|
||||
}).length > 0
|
||||
) {
|
||||
for (let i = 2; i <= ownerEntity.Columns.length; i++) {
|
||||
columnName = ownerEntity.EntityName.toLowerCase() + (isOneToMany ? 's' : '') + i.toString();
|
||||
if (referencedEntity.Columns.filter((filterVal) => {
|
||||
return filterVal.name == columnName;
|
||||
}).length == 0) break;
|
||||
columnName =
|
||||
ownerEntity.EntityName.toLowerCase() +
|
||||
(isOneToMany ? "s" : "") +
|
||||
i.toString();
|
||||
if (
|
||||
referencedEntity.Columns.filter(filterVal => {
|
||||
return filterVal.name == columnName;
|
||||
}).length == 0
|
||||
)
|
||||
break;
|
||||
}
|
||||
}
|
||||
ownerRelation.actionOnDelete = relationTmp.actionOnDelete
|
||||
ownerRelation.actionOnUpdate = relationTmp.actionOnUpdate
|
||||
ownerRelation.isOwner = true
|
||||
ownerRelation.relatedColumn = relatedColumn.name.toLowerCase()
|
||||
ownerRelation.relatedTable = relationTmp.referencedTable
|
||||
ownerRelation.ownerTable = relationTmp.ownerTable
|
||||
ownerRelation.ownerColumn = columnName
|
||||
ownerRelation.relationType = isOneToMany ? "ManyToOne" : "OneToOne"
|
||||
ownerColumn.relations.push(ownerRelation)
|
||||
ownerRelation.actionOnDelete = relationTmp.actionOnDelete;
|
||||
ownerRelation.actionOnUpdate = relationTmp.actionOnUpdate;
|
||||
ownerRelation.isOwner = true;
|
||||
ownerRelation.relatedColumn = relatedColumn.name.toLowerCase();
|
||||
ownerRelation.relatedTable = relationTmp.referencedTable;
|
||||
ownerRelation.ownerTable = relationTmp.ownerTable;
|
||||
ownerRelation.ownerColumn = columnName;
|
||||
ownerRelation.relationType = isOneToMany ? "ManyToOne" : "OneToOne";
|
||||
ownerColumn.relations.push(ownerRelation);
|
||||
if (isOneToMany) {
|
||||
let col = new ColumnInfo()
|
||||
col.name = columnName
|
||||
let col = new ColumnInfo();
|
||||
col.name = columnName;
|
||||
let referencedRelation = new RelationInfo();
|
||||
col.relations.push(referencedRelation)
|
||||
referencedRelation.actionOnDelete = relationTmp.actionOnDelete
|
||||
referencedRelation.actionOnUpdate = relationTmp.actionOnUpdate
|
||||
referencedRelation.isOwner = false
|
||||
referencedRelation.relatedColumn = ownerColumn.name
|
||||
referencedRelation.relatedTable = relationTmp.ownerTable
|
||||
referencedRelation.ownerTable = relationTmp.referencedTable
|
||||
referencedRelation.ownerColumn = relatedColumn.name.toLowerCase()
|
||||
referencedRelation.relationType = "OneToMany"
|
||||
referencedEntity.Columns.push(col)
|
||||
col.relations.push(referencedRelation);
|
||||
referencedRelation.actionOnDelete = relationTmp.actionOnDelete;
|
||||
referencedRelation.actionOnUpdate = relationTmp.actionOnUpdate;
|
||||
referencedRelation.isOwner = false;
|
||||
referencedRelation.relatedColumn = ownerColumn.name;
|
||||
referencedRelation.relatedTable = relationTmp.ownerTable;
|
||||
referencedRelation.ownerTable = relationTmp.referencedTable;
|
||||
referencedRelation.ownerColumn = relatedColumn.name.toLowerCase();
|
||||
referencedRelation.relationType = "OneToMany";
|
||||
referencedEntity.Columns.push(col);
|
||||
} else {
|
||||
let col = new ColumnInfo()
|
||||
col.name = columnName
|
||||
let col = new ColumnInfo();
|
||||
col.name = columnName;
|
||||
let referencedRelation = new RelationInfo();
|
||||
col.relations.push(referencedRelation)
|
||||
referencedRelation.actionOnDelete = relationTmp.actionOnDelete
|
||||
referencedRelation.actionOnUpdate = relationTmp.actionOnUpdate
|
||||
referencedRelation.isOwner = false
|
||||
referencedRelation.relatedColumn = ownerColumn.name
|
||||
referencedRelation.relatedTable = relationTmp.ownerTable
|
||||
referencedRelation.ownerTable = relationTmp.referencedTable
|
||||
referencedRelation.ownerColumn = relatedColumn.name.toLowerCase()
|
||||
referencedRelation.relationType = "OneToOne"
|
||||
col.relations.push(referencedRelation);
|
||||
referencedRelation.actionOnDelete = relationTmp.actionOnDelete;
|
||||
referencedRelation.actionOnUpdate = relationTmp.actionOnUpdate;
|
||||
referencedRelation.isOwner = false;
|
||||
referencedRelation.relatedColumn = ownerColumn.name;
|
||||
referencedRelation.relatedTable = relationTmp.ownerTable;
|
||||
referencedRelation.ownerTable = relationTmp.referencedTable;
|
||||
referencedRelation.ownerColumn = relatedColumn.name.toLowerCase();
|
||||
referencedRelation.relationType = "OneToOne";
|
||||
|
||||
referencedEntity.Columns.push(col)
|
||||
referencedEntity.Columns.push(col);
|
||||
}
|
||||
})
|
||||
});
|
||||
return entities;
|
||||
}
|
||||
async DisconnectFromServer() {
|
||||
if (this.Connection)
|
||||
await this.Connection.close();
|
||||
if (this.Connection) await this.Connection.close();
|
||||
}
|
||||
|
||||
private Connection: MSSQL.ConnectionPool;
|
||||
async ConnectToServer(database: string, server: string, port: number, user: string, password: string, ssl: boolean) {
|
||||
async ConnectToServer(
|
||||
database: string,
|
||||
server: string,
|
||||
port: number,
|
||||
user: string,
|
||||
password: string,
|
||||
ssl: boolean
|
||||
) {
|
||||
let config: MSSQL.config = {
|
||||
database: database,
|
||||
server: server,
|
||||
@ -429,43 +548,45 @@ order by
|
||||
password: password,
|
||||
options: {
|
||||
encrypt: ssl, // Use this if you're on Windows Azure
|
||||
appName: 'typeorm-model-generator'
|
||||
appName: "typeorm-model-generator"
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
let promise = new Promise<boolean>(
|
||||
(resolve, reject) => {
|
||||
this.Connection = new MSSQL.ConnectionPool(config, (err) => {
|
||||
if (!err) {
|
||||
//Connection successfull
|
||||
resolve(true)
|
||||
}
|
||||
else {
|
||||
TomgUtils.LogFatalError('Error connecting to MSSQL Server.', false, err.message)
|
||||
reject(err)
|
||||
}
|
||||
});
|
||||
}
|
||||
)
|
||||
let promise = new Promise<boolean>((resolve, reject) => {
|
||||
this.Connection = new MSSQL.ConnectionPool(config, err => {
|
||||
if (!err) {
|
||||
//Connection successfull
|
||||
resolve(true);
|
||||
} else {
|
||||
TomgUtils.LogFatalError(
|
||||
"Error connecting to MSSQL Server.",
|
||||
false,
|
||||
err.message
|
||||
);
|
||||
reject(err);
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
await promise;
|
||||
}
|
||||
async CreateDB(dbName: string) {
|
||||
let request = new MSSQL.Request(this.Connection);
|
||||
let resp = await request.query(`CREATE DATABASE ${dbName}; `)
|
||||
let resp = await request.query(`CREATE DATABASE ${dbName}; `);
|
||||
}
|
||||
async UseDB(dbName: string) {
|
||||
let request = new MSSQL.Request(this.Connection);
|
||||
let resp = await request.query(`USE ${dbName}; `)
|
||||
let resp = await request.query(`USE ${dbName}; `);
|
||||
}
|
||||
async DropDB(dbName: string) {
|
||||
let request = new MSSQL.Request(this.Connection);
|
||||
let resp = await request.query(`DROP DATABASE ${dbName}; `)
|
||||
let resp = await request.query(`DROP DATABASE ${dbName}; `);
|
||||
}
|
||||
async CheckIfDBExists(dbName: string): Promise<boolean> {
|
||||
let request = new MSSQL.Request(this.Connection);
|
||||
let resp = await request.query(`SELECT name FROM master.sys.databases WHERE name = N'${dbName}' `)
|
||||
let resp = await request.query(
|
||||
`SELECT name FROM master.sys.databases WHERE name = N'${dbName}' `
|
||||
);
|
||||
return resp.recordset.length > 0;
|
||||
}
|
||||
}
|
||||
|
@ -1,259 +1,330 @@
|
||||
import { AbstractDriver } from './AbstractDriver'
|
||||
import * as MYSQL from 'mysql'
|
||||
import { ColumnInfo } from './../models/ColumnInfo'
|
||||
import { EntityInfo } from './../models/EntityInfo'
|
||||
import { RelationInfo } from './../models/RelationInfo'
|
||||
import { DatabaseModel } from './../models/DatabaseModel'
|
||||
import * as TomgUtils from './../Utils'
|
||||
import { AbstractDriver } from "./AbstractDriver";
|
||||
import * as MYSQL from "mysql";
|
||||
import { ColumnInfo } from "./../models/ColumnInfo";
|
||||
import { EntityInfo } from "./../models/EntityInfo";
|
||||
import { RelationInfo } from "./../models/RelationInfo";
|
||||
import { DatabaseModel } from "./../models/DatabaseModel";
|
||||
import * as TomgUtils from "./../Utils";
|
||||
/**
|
||||
* MysqlDriver
|
||||
*/
|
||||
export class MysqlDriver extends AbstractDriver {
|
||||
readonly EngineName: string = 'MySQL'
|
||||
readonly EngineName: string = "MySQL";
|
||||
|
||||
FindPrimaryColumnsFromIndexes(dbModel: DatabaseModel) {
|
||||
dbModel.entities.forEach(entity => {
|
||||
let primaryIndex = entity.Indexes.find(v => v.isPrimaryKey);
|
||||
if (!primaryIndex) {
|
||||
TomgUtils.LogFatalError(`Table ${entity.EntityName} has no PK.`, false)
|
||||
TomgUtils.LogFatalError(
|
||||
`Table ${entity.EntityName} has no PK.`,
|
||||
false
|
||||
);
|
||||
return;
|
||||
}
|
||||
entity.Columns.forEach(col => {
|
||||
if (primaryIndex!.columns.some(cIndex => cIndex.name == col.name)) col.isPrimary = true
|
||||
})
|
||||
if (
|
||||
primaryIndex!.columns.some(
|
||||
cIndex => cIndex.name == col.name
|
||||
)
|
||||
)
|
||||
col.isPrimary = true;
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
async GetAllTables(schema: string): Promise<EntityInfo[]> {
|
||||
|
||||
let response = await this.ExecQuery<{ TABLE_SCHEMA: string, TABLE_NAME: string }>(`SELECT TABLE_SCHEMA, TABLE_NAME
|
||||
let response = await this.ExecQuery<{
|
||||
TABLE_SCHEMA: string;
|
||||
TABLE_NAME: string;
|
||||
}>(`SELECT TABLE_SCHEMA, TABLE_NAME
|
||||
FROM information_schema.tables
|
||||
WHERE table_type='BASE TABLE'
|
||||
AND table_schema like DATABASE()`);
|
||||
let ret: EntityInfo[] = <EntityInfo[]>[];
|
||||
response.forEach((val) => {
|
||||
response.forEach(val => {
|
||||
let ent: EntityInfo = new EntityInfo();
|
||||
ent.EntityName = val.TABLE_NAME;
|
||||
ent.Columns = <ColumnInfo[]>[];
|
||||
ent.Indexes = <IndexInfo[]>[];
|
||||
ret.push(ent);
|
||||
})
|
||||
});
|
||||
return ret;
|
||||
}
|
||||
async GetCoulmnsFromEntity(entities: EntityInfo[], schema: string): Promise<EntityInfo[]> {
|
||||
async GetCoulmnsFromEntity(
|
||||
entities: EntityInfo[],
|
||||
schema: string
|
||||
): Promise<EntityInfo[]> {
|
||||
let response = await this.ExecQuery<{
|
||||
TABLE_NAME: string, COLUMN_NAME: string, COLUMN_DEFAULT: string,
|
||||
IS_NULLABLE: string, DATA_TYPE: string, CHARACTER_MAXIMUM_LENGTH: number,
|
||||
NUMERIC_PRECISION: number, NUMERIC_SCALE: number, IsIdentity: number, column_type:string
|
||||
TABLE_NAME: string;
|
||||
COLUMN_NAME: string;
|
||||
COLUMN_DEFAULT: string;
|
||||
IS_NULLABLE: string;
|
||||
DATA_TYPE: string;
|
||||
CHARACTER_MAXIMUM_LENGTH: number;
|
||||
NUMERIC_PRECISION: number;
|
||||
NUMERIC_SCALE: number;
|
||||
IsIdentity: number;
|
||||
column_type: string;
|
||||
}>(`SELECT TABLE_NAME,COLUMN_NAME,COLUMN_DEFAULT,IS_NULLABLE,
|
||||
DATA_TYPE,CHARACTER_MAXIMUM_LENGTH,NUMERIC_PRECISION,NUMERIC_SCALE,
|
||||
CASE WHEN EXTRA like '%auto_increment%' THEN 1 ELSE 0 END IsIdentity, column_type FROM INFORMATION_SCHEMA.COLUMNS
|
||||
where TABLE_SCHEMA like DATABASE()`);
|
||||
entities.forEach((ent) => {
|
||||
response.filter((filterVal) => {
|
||||
return filterVal.TABLE_NAME == ent.EntityName;
|
||||
}).forEach((resp) => {
|
||||
let colInfo: ColumnInfo = new ColumnInfo();
|
||||
colInfo.name = resp.COLUMN_NAME;
|
||||
colInfo.is_nullable = resp.IS_NULLABLE == 'YES' ? true : false;
|
||||
colInfo.is_generated = resp.IsIdentity == 1 ? true : false;
|
||||
colInfo.default = resp.COLUMN_DEFAULT;
|
||||
switch (resp.DATA_TYPE) {
|
||||
case "int":
|
||||
colInfo.ts_type = "number"
|
||||
colInfo.sql_type = "int"
|
||||
colInfo.char_max_lenght = resp.CHARACTER_MAXIMUM_LENGTH > 0 ? resp.CHARACTER_MAXIMUM_LENGTH : null;
|
||||
break;
|
||||
case "tinyint":
|
||||
colInfo.ts_type = "number"
|
||||
colInfo.sql_type = "tinyint"
|
||||
break;
|
||||
case "smallint":
|
||||
colInfo.ts_type = "number"
|
||||
colInfo.sql_type = "smallint"
|
||||
colInfo.char_max_lenght = resp.CHARACTER_MAXIMUM_LENGTH > 0 ? resp.CHARACTER_MAXIMUM_LENGTH : null;
|
||||
break;
|
||||
case "bit":
|
||||
colInfo.ts_type = "boolean"
|
||||
colInfo.sql_type = "boolean"
|
||||
break;
|
||||
case "float":
|
||||
colInfo.ts_type = "number"
|
||||
colInfo.sql_type = "float"
|
||||
colInfo.char_max_lenght = resp.CHARACTER_MAXIMUM_LENGTH > 0 ? resp.CHARACTER_MAXIMUM_LENGTH : null;
|
||||
break;
|
||||
case "bigint":
|
||||
colInfo.ts_type = "number"
|
||||
colInfo.sql_type = "bigint"
|
||||
colInfo.char_max_lenght = resp.CHARACTER_MAXIMUM_LENGTH > 0 ? resp.CHARACTER_MAXIMUM_LENGTH : null;
|
||||
break;
|
||||
case "date":
|
||||
colInfo.ts_type = "string"
|
||||
colInfo.sql_type = "date"
|
||||
break;
|
||||
case "time":
|
||||
colInfo.ts_type = "string"
|
||||
colInfo.sql_type = "time"
|
||||
break;
|
||||
case "datetime":
|
||||
colInfo.ts_type = "Date";
|
||||
colInfo.sql_type = "datetime"
|
||||
break;
|
||||
case "char":
|
||||
colInfo.ts_type = "string"
|
||||
colInfo.sql_type = "text"
|
||||
break;
|
||||
case "nchar":
|
||||
colInfo.ts_type = "string"
|
||||
colInfo.sql_type = "text"
|
||||
break;
|
||||
case "text":
|
||||
colInfo.ts_type = "string"
|
||||
colInfo.sql_type = "text"
|
||||
break;
|
||||
case "ntext":
|
||||
colInfo.ts_type = "string"
|
||||
colInfo.sql_type = "text"
|
||||
break;
|
||||
entities.forEach(ent => {
|
||||
response
|
||||
.filter(filterVal => {
|
||||
return filterVal.TABLE_NAME == ent.EntityName;
|
||||
})
|
||||
.forEach(resp => {
|
||||
let colInfo: ColumnInfo = new ColumnInfo();
|
||||
colInfo.name = resp.COLUMN_NAME;
|
||||
colInfo.is_nullable =
|
||||
resp.IS_NULLABLE == "YES" ? true : false;
|
||||
colInfo.is_generated = resp.IsIdentity == 1 ? true : false;
|
||||
colInfo.default = resp.COLUMN_DEFAULT;
|
||||
switch (resp.DATA_TYPE) {
|
||||
case "int":
|
||||
colInfo.ts_type = "number";
|
||||
colInfo.sql_type = "int";
|
||||
colInfo.char_max_lenght =
|
||||
resp.CHARACTER_MAXIMUM_LENGTH > 0
|
||||
? resp.CHARACTER_MAXIMUM_LENGTH
|
||||
: null;
|
||||
break;
|
||||
case "tinyint":
|
||||
colInfo.ts_type = "number";
|
||||
colInfo.sql_type = "tinyint";
|
||||
break;
|
||||
case "smallint":
|
||||
colInfo.ts_type = "number";
|
||||
colInfo.sql_type = "smallint";
|
||||
colInfo.char_max_lenght =
|
||||
resp.CHARACTER_MAXIMUM_LENGTH > 0
|
||||
? resp.CHARACTER_MAXIMUM_LENGTH
|
||||
: null;
|
||||
break;
|
||||
case "bit":
|
||||
colInfo.ts_type = "boolean";
|
||||
colInfo.sql_type = "boolean";
|
||||
break;
|
||||
case "float":
|
||||
colInfo.ts_type = "number";
|
||||
colInfo.sql_type = "float";
|
||||
colInfo.char_max_lenght =
|
||||
resp.CHARACTER_MAXIMUM_LENGTH > 0
|
||||
? resp.CHARACTER_MAXIMUM_LENGTH
|
||||
: null;
|
||||
break;
|
||||
case "bigint":
|
||||
colInfo.ts_type = "number";
|
||||
colInfo.sql_type = "bigint";
|
||||
colInfo.char_max_lenght =
|
||||
resp.CHARACTER_MAXIMUM_LENGTH > 0
|
||||
? resp.CHARACTER_MAXIMUM_LENGTH
|
||||
: null;
|
||||
break;
|
||||
case "date":
|
||||
colInfo.ts_type = "string";
|
||||
colInfo.sql_type = "date";
|
||||
break;
|
||||
case "time":
|
||||
colInfo.ts_type = "string";
|
||||
colInfo.sql_type = "time";
|
||||
break;
|
||||
case "datetime":
|
||||
colInfo.ts_type = "Date";
|
||||
colInfo.sql_type = "datetime";
|
||||
break;
|
||||
case "char":
|
||||
colInfo.ts_type = "string";
|
||||
colInfo.sql_type = "text";
|
||||
break;
|
||||
case "nchar":
|
||||
colInfo.ts_type = "string";
|
||||
colInfo.sql_type = "text";
|
||||
break;
|
||||
case "text":
|
||||
colInfo.ts_type = "string";
|
||||
colInfo.sql_type = "text";
|
||||
break;
|
||||
case "ntext":
|
||||
colInfo.ts_type = "string";
|
||||
colInfo.sql_type = "text";
|
||||
break;
|
||||
|
||||
case "mediumint":
|
||||
colInfo.ts_type = "number"
|
||||
colInfo.sql_type = "mediumint"
|
||||
break;
|
||||
case "timestamp":
|
||||
colInfo.ts_type = "Date"
|
||||
colInfo.sql_type = "timestamp"
|
||||
break;
|
||||
case "year":
|
||||
colInfo.ts_type = "number"
|
||||
colInfo.sql_type = "year"
|
||||
break;
|
||||
case "blob":
|
||||
colInfo.ts_type = "Buffer"
|
||||
colInfo.sql_type = "blob"
|
||||
break;
|
||||
case "tinyblob":
|
||||
colInfo.ts_type = "Buffer"
|
||||
colInfo.sql_type = "tinyblob"
|
||||
break;
|
||||
case "tinytext":
|
||||
colInfo.ts_type = "string"
|
||||
colInfo.sql_type = "tinytext"
|
||||
break;
|
||||
case "mediumblob":
|
||||
colInfo.ts_type = "Buffer"
|
||||
colInfo.sql_type = "mediumblob"
|
||||
break;
|
||||
case "mediumtext":
|
||||
colInfo.ts_type = "string"
|
||||
colInfo.sql_type = "mediumtext"
|
||||
break;
|
||||
case "longblob":
|
||||
colInfo.ts_type = "Buffer"
|
||||
colInfo.sql_type = "longblob"
|
||||
break;
|
||||
case "longtext":
|
||||
colInfo.ts_type = "string"
|
||||
colInfo.sql_type = "longtext"
|
||||
break;
|
||||
case "mediumint":
|
||||
colInfo.ts_type = "number";
|
||||
colInfo.sql_type = "mediumint";
|
||||
break;
|
||||
case "timestamp":
|
||||
colInfo.ts_type = "Date";
|
||||
colInfo.sql_type = "timestamp";
|
||||
break;
|
||||
case "year":
|
||||
colInfo.ts_type = "number";
|
||||
colInfo.sql_type = "year";
|
||||
break;
|
||||
case "blob":
|
||||
colInfo.ts_type = "Buffer";
|
||||
colInfo.sql_type = "blob";
|
||||
break;
|
||||
case "tinyblob":
|
||||
colInfo.ts_type = "Buffer";
|
||||
colInfo.sql_type = "tinyblob";
|
||||
break;
|
||||
case "tinytext":
|
||||
colInfo.ts_type = "string";
|
||||
colInfo.sql_type = "tinytext";
|
||||
break;
|
||||
case "mediumblob":
|
||||
colInfo.ts_type = "Buffer";
|
||||
colInfo.sql_type = "mediumblob";
|
||||
break;
|
||||
case "mediumtext":
|
||||
colInfo.ts_type = "string";
|
||||
colInfo.sql_type = "mediumtext";
|
||||
break;
|
||||
case "longblob":
|
||||
colInfo.ts_type = "Buffer";
|
||||
colInfo.sql_type = "longblob";
|
||||
break;
|
||||
case "longtext":
|
||||
colInfo.ts_type = "string";
|
||||
colInfo.sql_type = "longtext";
|
||||
break;
|
||||
|
||||
case "varchar":
|
||||
colInfo.ts_type = "string"
|
||||
colInfo.sql_type = "varchar"
|
||||
colInfo.char_max_lenght = resp.CHARACTER_MAXIMUM_LENGTH > 0 ? resp.CHARACTER_MAXIMUM_LENGTH : null;
|
||||
break;
|
||||
case "nvarchar":
|
||||
colInfo.ts_type = "string"
|
||||
colInfo.sql_type = "nvarchar"
|
||||
colInfo.char_max_lenght = resp.CHARACTER_MAXIMUM_LENGTH > 0 ? resp.CHARACTER_MAXIMUM_LENGTH : null;
|
||||
break;
|
||||
case "money":
|
||||
colInfo.ts_type = "number"
|
||||
colInfo.sql_type = "decimal"
|
||||
break;
|
||||
case "real":
|
||||
colInfo.ts_type = "number"
|
||||
colInfo.sql_type = "double"
|
||||
colInfo.char_max_lenght = resp.CHARACTER_MAXIMUM_LENGTH > 0 ? resp.CHARACTER_MAXIMUM_LENGTH : null;
|
||||
break;
|
||||
case "double":
|
||||
colInfo.ts_type = "number"
|
||||
colInfo.sql_type = "double"
|
||||
colInfo.char_max_lenght = resp.CHARACTER_MAXIMUM_LENGTH > 0 ? resp.CHARACTER_MAXIMUM_LENGTH : null;
|
||||
break;
|
||||
case "decimal":
|
||||
colInfo.ts_type = "number"
|
||||
colInfo.sql_type = "decimal"
|
||||
colInfo.numericPrecision = resp.NUMERIC_PRECISION
|
||||
colInfo.numericScale = resp.NUMERIC_SCALE
|
||||
colInfo.char_max_lenght = resp.CHARACTER_MAXIMUM_LENGTH > 0 ? resp.CHARACTER_MAXIMUM_LENGTH : null;
|
||||
break;
|
||||
case "xml":
|
||||
colInfo.ts_type = "string"
|
||||
colInfo.sql_type = "text"
|
||||
break;
|
||||
case "json":
|
||||
colInfo.ts_type = "Object"
|
||||
colInfo.sql_type = "json"
|
||||
break;
|
||||
case "enum":
|
||||
colInfo.ts_type = "string"
|
||||
colInfo.sql_type = "enum"
|
||||
colInfo.enumOptions = resp.column_type.substring(5, resp.column_type.length - 1).replace(/\'/gi,'"')
|
||||
break;
|
||||
default:
|
||||
TomgUtils.LogFatalError("Unknown column type:" + resp.DATA_TYPE);
|
||||
break;
|
||||
}
|
||||
if (colInfo.sql_type) ent.Columns.push(colInfo);
|
||||
})
|
||||
})
|
||||
case "varchar":
|
||||
colInfo.ts_type = "string";
|
||||
colInfo.sql_type = "varchar";
|
||||
colInfo.char_max_lenght =
|
||||
resp.CHARACTER_MAXIMUM_LENGTH > 0
|
||||
? resp.CHARACTER_MAXIMUM_LENGTH
|
||||
: null;
|
||||
break;
|
||||
case "nvarchar":
|
||||
colInfo.ts_type = "string";
|
||||
colInfo.sql_type = "nvarchar";
|
||||
colInfo.char_max_lenght =
|
||||
resp.CHARACTER_MAXIMUM_LENGTH > 0
|
||||
? resp.CHARACTER_MAXIMUM_LENGTH
|
||||
: null;
|
||||
break;
|
||||
case "money":
|
||||
colInfo.ts_type = "number";
|
||||
colInfo.sql_type = "decimal";
|
||||
break;
|
||||
case "real":
|
||||
colInfo.ts_type = "number";
|
||||
colInfo.sql_type = "double";
|
||||
colInfo.char_max_lenght =
|
||||
resp.CHARACTER_MAXIMUM_LENGTH > 0
|
||||
? resp.CHARACTER_MAXIMUM_LENGTH
|
||||
: null;
|
||||
break;
|
||||
case "double":
|
||||
colInfo.ts_type = "number";
|
||||
colInfo.sql_type = "double";
|
||||
colInfo.char_max_lenght =
|
||||
resp.CHARACTER_MAXIMUM_LENGTH > 0
|
||||
? resp.CHARACTER_MAXIMUM_LENGTH
|
||||
: null;
|
||||
break;
|
||||
case "decimal":
|
||||
colInfo.ts_type = "number";
|
||||
colInfo.sql_type = "decimal";
|
||||
colInfo.numericPrecision = resp.NUMERIC_PRECISION;
|
||||
colInfo.numericScale = resp.NUMERIC_SCALE;
|
||||
colInfo.char_max_lenght =
|
||||
resp.CHARACTER_MAXIMUM_LENGTH > 0
|
||||
? resp.CHARACTER_MAXIMUM_LENGTH
|
||||
: null;
|
||||
break;
|
||||
case "xml":
|
||||
colInfo.ts_type = "string";
|
||||
colInfo.sql_type = "text";
|
||||
break;
|
||||
case "json":
|
||||
colInfo.ts_type = "Object";
|
||||
colInfo.sql_type = "json";
|
||||
break;
|
||||
case "enum":
|
||||
colInfo.ts_type = "string";
|
||||
colInfo.sql_type = "enum";
|
||||
colInfo.enumOptions = resp.column_type
|
||||
.substring(5, resp.column_type.length - 1)
|
||||
.replace(/\'/gi, '"');
|
||||
break;
|
||||
default:
|
||||
TomgUtils.LogFatalError(
|
||||
"Unknown column type:" + resp.DATA_TYPE
|
||||
);
|
||||
break;
|
||||
}
|
||||
if (colInfo.sql_type) ent.Columns.push(colInfo);
|
||||
});
|
||||
});
|
||||
return entities;
|
||||
}
|
||||
async GetIndexesFromEntity(entities: EntityInfo[], schema: string): Promise<EntityInfo[]> {
|
||||
async GetIndexesFromEntity(
|
||||
entities: EntityInfo[],
|
||||
schema: string
|
||||
): Promise<EntityInfo[]> {
|
||||
let response = await this.ExecQuery<{
|
||||
TableName: string, IndexName: string, ColumnName: string, is_unique: number,
|
||||
is_primary_key: number//, is_descending_key: number//, is_included_column: number
|
||||
TableName: string;
|
||||
IndexName: string;
|
||||
ColumnName: string;
|
||||
is_unique: number;
|
||||
is_primary_key: number; //, is_descending_key: number//, is_included_column: number
|
||||
}>(`SELECT TABLE_NAME TableName,INDEX_NAME IndexName,COLUMN_NAME ColumnName,CASE WHEN NON_UNIQUE=0 THEN 1 ELSE 0 END is_unique,
|
||||
CASE WHEN INDEX_NAME='PRIMARY' THEN 1 ELSE 0 END is_primary_key
|
||||
FROM information_schema.statistics sta
|
||||
WHERE table_schema like DATABASE();
|
||||
`);
|
||||
entities.forEach((ent) => {
|
||||
response.filter((filterVal) => {
|
||||
return filterVal.TableName == ent.EntityName;
|
||||
}).forEach((resp) => {
|
||||
let indexInfo: IndexInfo = <IndexInfo>{};
|
||||
let indexColumnInfo: IndexColumnInfo = <IndexColumnInfo>{};
|
||||
if (ent.Indexes.filter((filterVal) => {
|
||||
return filterVal.name == resp.IndexName
|
||||
}).length > 0) {
|
||||
indexInfo = ent.Indexes.filter((filterVal) => {
|
||||
return filterVal.name == resp.IndexName
|
||||
})[0];
|
||||
} else {
|
||||
indexInfo.columns = <IndexColumnInfo[]>[];
|
||||
indexInfo.name = resp.IndexName;
|
||||
indexInfo.isUnique = resp.is_unique == 1 ? true : false;
|
||||
indexInfo.isPrimaryKey = resp.is_primary_key == 1 ? true : false;
|
||||
ent.Indexes.push(indexInfo);
|
||||
}
|
||||
indexColumnInfo.name = resp.ColumnName;
|
||||
// indexColumnInfo.isIncludedColumn = resp.is_included_column == 1 ? true : false;
|
||||
// indexColumnInfo.isDescending = resp.is_descending_key == 1 ? true : false;
|
||||
indexInfo.columns.push(indexColumnInfo);
|
||||
|
||||
})
|
||||
})
|
||||
entities.forEach(ent => {
|
||||
response
|
||||
.filter(filterVal => {
|
||||
return filterVal.TableName == ent.EntityName;
|
||||
})
|
||||
.forEach(resp => {
|
||||
let indexInfo: IndexInfo = <IndexInfo>{};
|
||||
let indexColumnInfo: IndexColumnInfo = <IndexColumnInfo>{};
|
||||
if (
|
||||
ent.Indexes.filter(filterVal => {
|
||||
return filterVal.name == resp.IndexName;
|
||||
}).length > 0
|
||||
) {
|
||||
indexInfo = ent.Indexes.filter(filterVal => {
|
||||
return filterVal.name == resp.IndexName;
|
||||
})[0];
|
||||
} else {
|
||||
indexInfo.columns = <IndexColumnInfo[]>[];
|
||||
indexInfo.name = resp.IndexName;
|
||||
indexInfo.isUnique = resp.is_unique == 1 ? true : false;
|
||||
indexInfo.isPrimaryKey =
|
||||
resp.is_primary_key == 1 ? true : false;
|
||||
ent.Indexes.push(indexInfo);
|
||||
}
|
||||
indexColumnInfo.name = resp.ColumnName;
|
||||
// indexColumnInfo.isIncludedColumn = resp.is_included_column == 1 ? true : false;
|
||||
// indexColumnInfo.isDescending = resp.is_descending_key == 1 ? true : false;
|
||||
indexInfo.columns.push(indexColumnInfo);
|
||||
});
|
||||
});
|
||||
|
||||
return entities;
|
||||
}
|
||||
async GetRelations(entities: EntityInfo[], schema: string): Promise<EntityInfo[]> {
|
||||
async GetRelations(
|
||||
entities: EntityInfo[],
|
||||
schema: string
|
||||
): Promise<EntityInfo[]> {
|
||||
let response = await this.ExecQuery<{
|
||||
TableWithForeignKey: string, FK_PartNo: number, ForeignKeyColumn: string,
|
||||
TableReferenced: string, ForeignKeyColumnReferenced: string,
|
||||
onDelete: "RESTRICT" | "CASCADE" | "SET NULL",
|
||||
onUpdate: "RESTRICT" | "CASCADE" | "SET NULL", object_id: string
|
||||
TableWithForeignKey: string;
|
||||
FK_PartNo: number;
|
||||
ForeignKeyColumn: string;
|
||||
TableReferenced: string;
|
||||
ForeignKeyColumnReferenced: string;
|
||||
onDelete: "RESTRICT" | "CASCADE" | "SET NULL";
|
||||
onUpdate: "RESTRICT" | "CASCADE" | "SET NULL";
|
||||
object_id: string;
|
||||
}>(`SELECT
|
||||
CU.TABLE_NAME TableWithForeignKey,
|
||||
CU.ORDINAL_POSITION FK_PartNo,
|
||||
@ -272,10 +343,10 @@ export class MysqlDriver extends AbstractDriver {
|
||||
AND CU.REFERENCED_TABLE_NAME IS NOT NULL;
|
||||
`);
|
||||
let relationsTemp: RelationTempInfo[] = <RelationTempInfo[]>[];
|
||||
response.forEach((resp) => {
|
||||
let rels = relationsTemp.find((val) => {
|
||||
response.forEach(resp => {
|
||||
let rels = relationsTemp.find(val => {
|
||||
return val.object_id == resp.object_id;
|
||||
})
|
||||
});
|
||||
if (rels == undefined) {
|
||||
rels = <RelationTempInfo>{};
|
||||
rels.ownerColumnsNames = [];
|
||||
@ -289,129 +360,165 @@ export class MysqlDriver extends AbstractDriver {
|
||||
}
|
||||
rels.ownerColumnsNames.push(resp.ForeignKeyColumn);
|
||||
rels.referencedColumnsNames.push(resp.ForeignKeyColumnReferenced);
|
||||
})
|
||||
relationsTemp.forEach((relationTmp) => {
|
||||
let ownerEntity = entities.find((entitity) => {
|
||||
});
|
||||
relationsTemp.forEach(relationTmp => {
|
||||
let ownerEntity = entities.find(entitity => {
|
||||
return entitity.EntityName == relationTmp.ownerTable;
|
||||
})
|
||||
});
|
||||
if (!ownerEntity) {
|
||||
TomgUtils.LogFatalError(`Relation between tables ${relationTmp.ownerTable} and ${relationTmp.referencedTable} didn't found entity model ${relationTmp.ownerTable}.`)
|
||||
TomgUtils.LogFatalError(
|
||||
`Relation between tables ${relationTmp.ownerTable} and ${
|
||||
relationTmp.referencedTable
|
||||
} didn't found entity model ${relationTmp.ownerTable}.`
|
||||
);
|
||||
return;
|
||||
}
|
||||
let referencedEntity = entities.find((entitity) => {
|
||||
let referencedEntity = entities.find(entitity => {
|
||||
return entitity.EntityName == relationTmp.referencedTable;
|
||||
})
|
||||
});
|
||||
if (!referencedEntity) {
|
||||
TomgUtils.LogFatalError(`Relation between tables ${relationTmp.ownerTable} and ${relationTmp.referencedTable} didn't found entity model ${relationTmp.referencedTable}.`)
|
||||
TomgUtils.LogFatalError(
|
||||
`Relation between tables ${relationTmp.ownerTable} and ${
|
||||
relationTmp.referencedTable
|
||||
} didn't found entity model ${relationTmp.referencedTable}.`
|
||||
);
|
||||
return;
|
||||
}
|
||||
let ownerColumn = ownerEntity.Columns.find((column) => {
|
||||
let ownerColumn = ownerEntity.Columns.find(column => {
|
||||
return column.name == relationTmp.ownerColumnsNames[0];
|
||||
})
|
||||
});
|
||||
if (!ownerColumn) {
|
||||
TomgUtils.LogFatalError(`Relation between tables ${relationTmp.ownerTable} and ${relationTmp.referencedTable} didn't found entity column ${relationTmp.ownerTable}.${ownerColumn}.`)
|
||||
TomgUtils.LogFatalError(
|
||||
`Relation between tables ${relationTmp.ownerTable} and ${
|
||||
relationTmp.referencedTable
|
||||
} didn't found entity column ${
|
||||
relationTmp.ownerTable
|
||||
}.${ownerColumn}.`
|
||||
);
|
||||
return;
|
||||
}
|
||||
let relatedColumn = referencedEntity.Columns.find((column) => {
|
||||
let relatedColumn = referencedEntity.Columns.find(column => {
|
||||
return column.name == relationTmp.referencedColumnsNames[0];
|
||||
})
|
||||
});
|
||||
if (!relatedColumn) {
|
||||
TomgUtils.LogFatalError(`Relation between tables ${relationTmp.ownerTable} and ${relationTmp.referencedTable} didn't found entity column ${relationTmp.referencedTable}.${relatedColumn}.`)
|
||||
TomgUtils.LogFatalError(
|
||||
`Relation between tables ${relationTmp.ownerTable} and ${
|
||||
relationTmp.referencedTable
|
||||
} didn't found entity column ${
|
||||
relationTmp.referencedTable
|
||||
}.${relatedColumn}.`
|
||||
);
|
||||
return;
|
||||
}
|
||||
let ownColumn: ColumnInfo = ownerColumn;
|
||||
let isOneToMany: boolean;
|
||||
isOneToMany = false;
|
||||
let index = ownerEntity.Indexes.find(
|
||||
(index) => {
|
||||
return index.isUnique && index.columns.some(col => {
|
||||
return col.name == ownerColumn!.name
|
||||
let index = ownerEntity.Indexes.find(index => {
|
||||
return (
|
||||
index.isUnique &&
|
||||
index.columns.some(col => {
|
||||
return col.name == ownerColumn!.name;
|
||||
})
|
||||
}
|
||||
)
|
||||
);
|
||||
});
|
||||
if (!index) {
|
||||
isOneToMany = true;
|
||||
} else {
|
||||
isOneToMany = false;
|
||||
}
|
||||
let ownerRelation = new RelationInfo()
|
||||
let columnName = ownerEntity.EntityName.toLowerCase() + (isOneToMany ? 's' : '')
|
||||
if (referencedEntity.Columns.filter((filterVal) => {
|
||||
return filterVal.name == columnName;
|
||||
}).length > 0) {
|
||||
let ownerRelation = new RelationInfo();
|
||||
let columnName =
|
||||
ownerEntity.EntityName.toLowerCase() + (isOneToMany ? "s" : "");
|
||||
if (
|
||||
referencedEntity.Columns.filter(filterVal => {
|
||||
return filterVal.name == columnName;
|
||||
}).length > 0
|
||||
) {
|
||||
for (let i = 2; i <= ownerEntity.Columns.length; i++) {
|
||||
columnName = ownerEntity.EntityName.toLowerCase() + (isOneToMany ? 's' : '') + i.toString();
|
||||
if (referencedEntity.Columns.filter((filterVal) => {
|
||||
return filterVal.name == columnName;
|
||||
}).length == 0) break;
|
||||
columnName =
|
||||
ownerEntity.EntityName.toLowerCase() +
|
||||
(isOneToMany ? "s" : "") +
|
||||
i.toString();
|
||||
if (
|
||||
referencedEntity.Columns.filter(filterVal => {
|
||||
return filterVal.name == columnName;
|
||||
}).length == 0
|
||||
)
|
||||
break;
|
||||
}
|
||||
}
|
||||
ownerRelation.actionOnDelete = relationTmp.actionOnDelete
|
||||
ownerRelation.actionOnUpdate = relationTmp.actionOnUpdate
|
||||
ownerRelation.isOwner = true
|
||||
ownerRelation.relatedColumn = relatedColumn.name.toLowerCase()
|
||||
ownerRelation.relatedTable = relationTmp.referencedTable
|
||||
ownerRelation.ownerTable = relationTmp.ownerTable
|
||||
ownerRelation.ownerColumn = columnName
|
||||
ownerRelation.relationType = isOneToMany ? "ManyToOne" : "OneToOne"
|
||||
ownerColumn.relations.push(ownerRelation)
|
||||
ownerRelation.actionOnDelete = relationTmp.actionOnDelete;
|
||||
ownerRelation.actionOnUpdate = relationTmp.actionOnUpdate;
|
||||
ownerRelation.isOwner = true;
|
||||
ownerRelation.relatedColumn = relatedColumn.name.toLowerCase();
|
||||
ownerRelation.relatedTable = relationTmp.referencedTable;
|
||||
ownerRelation.ownerTable = relationTmp.ownerTable;
|
||||
ownerRelation.ownerColumn = columnName;
|
||||
ownerRelation.relationType = isOneToMany ? "ManyToOne" : "OneToOne";
|
||||
ownerColumn.relations.push(ownerRelation);
|
||||
if (isOneToMany) {
|
||||
let col = new ColumnInfo()
|
||||
col.name = columnName
|
||||
let col = new ColumnInfo();
|
||||
col.name = columnName;
|
||||
let referencedRelation = new RelationInfo();
|
||||
col.relations.push(referencedRelation)
|
||||
referencedRelation.actionOnDelete = relationTmp.actionOnDelete
|
||||
referencedRelation.actionOnUpdate = relationTmp.actionOnUpdate
|
||||
referencedRelation.isOwner = false
|
||||
referencedRelation.relatedColumn = ownerColumn.name
|
||||
referencedRelation.relatedTable = relationTmp.ownerTable
|
||||
referencedRelation.ownerTable = relationTmp.referencedTable
|
||||
referencedRelation.ownerColumn = relatedColumn.name.toLowerCase()
|
||||
referencedRelation.relationType = "OneToMany"
|
||||
referencedEntity.Columns.push(col)
|
||||
col.relations.push(referencedRelation);
|
||||
referencedRelation.actionOnDelete = relationTmp.actionOnDelete;
|
||||
referencedRelation.actionOnUpdate = relationTmp.actionOnUpdate;
|
||||
referencedRelation.isOwner = false;
|
||||
referencedRelation.relatedColumn = ownerColumn.name;
|
||||
referencedRelation.relatedTable = relationTmp.ownerTable;
|
||||
referencedRelation.ownerTable = relationTmp.referencedTable;
|
||||
referencedRelation.ownerColumn = relatedColumn.name.toLowerCase();
|
||||
referencedRelation.relationType = "OneToMany";
|
||||
referencedEntity.Columns.push(col);
|
||||
} else {
|
||||
let col = new ColumnInfo()
|
||||
col.name = columnName
|
||||
let col = new ColumnInfo();
|
||||
col.name = columnName;
|
||||
let referencedRelation = new RelationInfo();
|
||||
col.relations.push(referencedRelation)
|
||||
referencedRelation.actionOnDelete = relationTmp.actionOnDelete
|
||||
referencedRelation.actionOnUpdate = relationTmp.actionOnUpdate
|
||||
referencedRelation.isOwner = false
|
||||
referencedRelation.relatedColumn = ownerColumn.name
|
||||
referencedRelation.relatedTable = relationTmp.ownerTable
|
||||
referencedRelation.ownerTable = relationTmp.referencedTable
|
||||
referencedRelation.ownerColumn = relatedColumn.name.toLowerCase()
|
||||
referencedRelation.relationType = "OneToOne"
|
||||
col.relations.push(referencedRelation);
|
||||
referencedRelation.actionOnDelete = relationTmp.actionOnDelete;
|
||||
referencedRelation.actionOnUpdate = relationTmp.actionOnUpdate;
|
||||
referencedRelation.isOwner = false;
|
||||
referencedRelation.relatedColumn = ownerColumn.name;
|
||||
referencedRelation.relatedTable = relationTmp.ownerTable;
|
||||
referencedRelation.ownerTable = relationTmp.referencedTable;
|
||||
referencedRelation.ownerColumn = relatedColumn.name.toLowerCase();
|
||||
referencedRelation.relationType = "OneToOne";
|
||||
|
||||
referencedEntity.Columns.push(col)
|
||||
referencedEntity.Columns.push(col);
|
||||
}
|
||||
})
|
||||
});
|
||||
return entities;
|
||||
}
|
||||
async DisconnectFromServer() {
|
||||
let promise = new Promise<boolean>(
|
||||
(resolve, reject) => {
|
||||
this.Connection.end((err) => {
|
||||
if (!err) {
|
||||
//Connection successfull
|
||||
resolve(true)
|
||||
}
|
||||
else {
|
||||
TomgUtils.LogFatalError(`Error disconnecting to ${this.EngineName} Server.`, false, err.message)
|
||||
reject(err)
|
||||
}
|
||||
});
|
||||
}
|
||||
)
|
||||
|
||||
if (this.Connection)
|
||||
await promise;
|
||||
let promise = new Promise<boolean>((resolve, reject) => {
|
||||
this.Connection.end(err => {
|
||||
if (!err) {
|
||||
//Connection successfull
|
||||
resolve(true);
|
||||
} else {
|
||||
TomgUtils.LogFatalError(
|
||||
`Error disconnecting to ${this.EngineName} Server.`,
|
||||
false,
|
||||
err.message
|
||||
);
|
||||
reject(err);
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
if (this.Connection) await promise;
|
||||
}
|
||||
|
||||
private Connection: MYSQL.Connection;
|
||||
async ConnectToServer(database: string, server: string, port: number, user: string, password: string, ssl: boolean) {
|
||||
let config: MYSQL.ConnectionConfig
|
||||
async ConnectToServer(
|
||||
database: string,
|
||||
server: string,
|
||||
port: number,
|
||||
user: string,
|
||||
password: string,
|
||||
ssl: boolean
|
||||
) {
|
||||
let config: MYSQL.ConnectionConfig;
|
||||
if (ssl) {
|
||||
config = {
|
||||
database: database,
|
||||
@ -422,7 +529,7 @@ export class MysqlDriver extends AbstractDriver {
|
||||
ssl: {
|
||||
rejectUnauthorized: false
|
||||
}
|
||||
}
|
||||
};
|
||||
} else {
|
||||
config = {
|
||||
database: database,
|
||||
@ -430,55 +537,55 @@ export class MysqlDriver extends AbstractDriver {
|
||||
port: port,
|
||||
user: user,
|
||||
password: password
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
let promise = new Promise<boolean>((resolve, reject) => {
|
||||
this.Connection = MYSQL.createConnection(config);
|
||||
|
||||
let promise = new Promise<boolean>(
|
||||
(resolve, reject) => {
|
||||
this.Connection = MYSQL.createConnection(config)
|
||||
|
||||
this.Connection.connect((err) => {
|
||||
if (!err) {
|
||||
//Connection successfull
|
||||
resolve(true)
|
||||
}
|
||||
else {
|
||||
TomgUtils.LogFatalError(`Error connecting to ${this.EngineName} Server.`, false, err.message)
|
||||
reject(err)
|
||||
}
|
||||
});
|
||||
}
|
||||
)
|
||||
this.Connection.connect(err => {
|
||||
if (!err) {
|
||||
//Connection successfull
|
||||
resolve(true);
|
||||
} else {
|
||||
TomgUtils.LogFatalError(
|
||||
`Error connecting to ${this.EngineName} Server.`,
|
||||
false,
|
||||
err.message
|
||||
);
|
||||
reject(err);
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
await promise;
|
||||
}
|
||||
async CreateDB(dbName: string) {
|
||||
let resp = await this.ExecQuery<any>(`CREATE DATABASE ${dbName}; `)
|
||||
let resp = await this.ExecQuery<any>(`CREATE DATABASE ${dbName}; `);
|
||||
}
|
||||
async UseDB(dbName: string) {
|
||||
let resp = await this.ExecQuery<any>(`USE ${dbName}; `)
|
||||
let resp = await this.ExecQuery<any>(`USE ${dbName}; `);
|
||||
}
|
||||
async DropDB(dbName: string) {
|
||||
let resp = await this.ExecQuery<any>(`DROP DATABASE ${dbName}; `)
|
||||
let resp = await this.ExecQuery<any>(`DROP DATABASE ${dbName}; `);
|
||||
}
|
||||
async CheckIfDBExists(dbName: string): Promise<boolean> {
|
||||
let resp = await this.ExecQuery<any>(`SHOW DATABASES LIKE '${dbName}' `)
|
||||
let resp = await this.ExecQuery<any>(
|
||||
`SHOW DATABASES LIKE '${dbName}' `
|
||||
);
|
||||
return resp.length > 0;
|
||||
}
|
||||
async ExecQuery<T>(sql: string): Promise<Array<T>> {
|
||||
let ret: Array<T> = [];
|
||||
let that = this;
|
||||
let query = this.Connection.query(sql)
|
||||
let query = this.Connection.query(sql);
|
||||
let stream = query.stream({});
|
||||
let promise = new Promise<boolean>(
|
||||
(resolve, reject) => {
|
||||
stream.on('data',
|
||||
chunk => {
|
||||
ret.push(<T><any>chunk)
|
||||
});
|
||||
stream.on('end', () => resolve(true));
|
||||
})
|
||||
let promise = new Promise<boolean>((resolve, reject) => {
|
||||
stream.on("data", chunk => {
|
||||
ret.push(<T>(<any>chunk));
|
||||
});
|
||||
stream.on("end", () => resolve(true));
|
||||
});
|
||||
await promise;
|
||||
return ret;
|
||||
}
|
||||
|
@ -1,12 +1,11 @@
|
||||
import { AbstractDriver } from './AbstractDriver'
|
||||
import { ColumnInfo } from './../models/ColumnInfo'
|
||||
import { EntityInfo } from './../models/EntityInfo'
|
||||
import { RelationInfo } from './../models/RelationInfo'
|
||||
import { DatabaseModel } from './../models/DatabaseModel'
|
||||
import { promisify } from 'util'
|
||||
import { request } from 'https';
|
||||
import * as TomgUtils from './../Utils'
|
||||
|
||||
import { AbstractDriver } from "./AbstractDriver";
|
||||
import { ColumnInfo } from "./../models/ColumnInfo";
|
||||
import { EntityInfo } from "./../models/EntityInfo";
|
||||
import { RelationInfo } from "./../models/RelationInfo";
|
||||
import { DatabaseModel } from "./../models/DatabaseModel";
|
||||
import { promisify } from "util";
|
||||
import { request } from "https";
|
||||
import * as TomgUtils from "./../Utils";
|
||||
|
||||
/**
|
||||
* OracleDriver
|
||||
@ -16,117 +15,142 @@ export class OracleDriver extends AbstractDriver {
|
||||
constructor() {
|
||||
super();
|
||||
try {
|
||||
this.Oracle = require('oracledb')
|
||||
this.Oracle = require("oracledb");
|
||||
} catch (error) {
|
||||
TomgUtils.LogFatalError('', false, error);
|
||||
TomgUtils.LogFatalError("", false, error);
|
||||
throw error;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
FindPrimaryColumnsFromIndexes(dbModel: DatabaseModel) {
|
||||
dbModel.entities.forEach(entity => {
|
||||
let primaryIndex = entity.Indexes.find(v => v.isPrimaryKey);
|
||||
if (!primaryIndex) {
|
||||
TomgUtils.LogFatalError(`Table ${entity.EntityName} has no PK.`, false)
|
||||
TomgUtils.LogFatalError(
|
||||
`Table ${entity.EntityName} has no PK.`,
|
||||
false
|
||||
);
|
||||
return;
|
||||
}
|
||||
entity.Columns.forEach(col => {
|
||||
if (primaryIndex!.columns.some(cIndex => cIndex.name == col.name)) col.isPrimary = true
|
||||
})
|
||||
if (
|
||||
primaryIndex!.columns.some(
|
||||
cIndex => cIndex.name == col.name
|
||||
)
|
||||
)
|
||||
col.isPrimary = true;
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
async GetAllTables(schema: string): Promise<EntityInfo[]> {
|
||||
|
||||
let response: any[][] = (await this.Connection.execute(` SELECT TABLE_NAME FROM all_tables WHERE owner = (select user from dual)`)).rows!;
|
||||
let response: any[][] = (await this.Connection.execute(
|
||||
` SELECT TABLE_NAME FROM all_tables WHERE owner = (select user from dual)`
|
||||
)).rows!;
|
||||
let ret: EntityInfo[] = <EntityInfo[]>[];
|
||||
response.forEach((val) => {
|
||||
response.forEach(val => {
|
||||
let ent: EntityInfo = new EntityInfo();
|
||||
ent.EntityName = val[0];
|
||||
ent.Columns = <ColumnInfo[]>[];
|
||||
ent.Indexes = <IndexInfo[]>[];
|
||||
ret.push(ent);
|
||||
})
|
||||
});
|
||||
return ret;
|
||||
}
|
||||
async GetCoulmnsFromEntity(entities: EntityInfo[], schema: string): Promise<EntityInfo[]> {
|
||||
let response: any[][] = (await this.Connection.execute(`SELECT TABLE_NAME, COLUMN_NAME, DATA_DEFAULT, NULLABLE, DATA_TYPE, DATA_LENGTH,
|
||||
async GetCoulmnsFromEntity(
|
||||
entities: EntityInfo[],
|
||||
schema: string
|
||||
): Promise<EntityInfo[]> {
|
||||
let response: any[][] = (await this.Connection
|
||||
.execute(`SELECT TABLE_NAME, COLUMN_NAME, DATA_DEFAULT, NULLABLE, DATA_TYPE, DATA_LENGTH,
|
||||
DATA_PRECISION, DATA_SCALE, IDENTITY_COLUMN
|
||||
FROM USER_TAB_COLUMNS`)).rows!;
|
||||
|
||||
entities.forEach((ent) => {
|
||||
response.filter((filterVal) => {
|
||||
return filterVal[0] == ent.EntityName;
|
||||
}).forEach((resp) => {
|
||||
let colInfo: ColumnInfo = new ColumnInfo();
|
||||
colInfo.name = resp[1];
|
||||
colInfo.is_nullable = resp[3] == 'Y' ? true : false;
|
||||
colInfo.is_generated = resp[8] == 'YES' ? true : false;
|
||||
colInfo.default = resp[2];
|
||||
switch (resp[4].toLowerCase()) {
|
||||
case "number":
|
||||
colInfo.ts_type = "number"
|
||||
colInfo.sql_type = "int"
|
||||
colInfo.char_max_lenght = resp[5] > 0 ? resp[5] : null;
|
||||
break;
|
||||
case "varchar2":
|
||||
colInfo.ts_type = "number"
|
||||
colInfo.sql_type = "smallint"
|
||||
colInfo.char_max_lenght = resp[5] > 0 ? resp[5] : null;
|
||||
break;
|
||||
default:
|
||||
TomgUtils.LogFatalError("Unknown column type:" + resp[4]);
|
||||
break;
|
||||
}
|
||||
entities.forEach(ent => {
|
||||
response
|
||||
.filter(filterVal => {
|
||||
return filterVal[0] == ent.EntityName;
|
||||
})
|
||||
.forEach(resp => {
|
||||
let colInfo: ColumnInfo = new ColumnInfo();
|
||||
colInfo.name = resp[1];
|
||||
colInfo.is_nullable = resp[3] == "Y" ? true : false;
|
||||
colInfo.is_generated = resp[8] == "YES" ? true : false;
|
||||
colInfo.default = resp[2];
|
||||
switch (resp[4].toLowerCase()) {
|
||||
case "number":
|
||||
colInfo.ts_type = "number";
|
||||
colInfo.sql_type = "int";
|
||||
colInfo.char_max_lenght =
|
||||
resp[5] > 0 ? resp[5] : null;
|
||||
break;
|
||||
case "varchar2":
|
||||
colInfo.ts_type = "number";
|
||||
colInfo.sql_type = "smallint";
|
||||
colInfo.char_max_lenght =
|
||||
resp[5] > 0 ? resp[5] : null;
|
||||
break;
|
||||
default:
|
||||
TomgUtils.LogFatalError(
|
||||
"Unknown column type:" + resp[4]
|
||||
);
|
||||
break;
|
||||
}
|
||||
|
||||
if (colInfo.sql_type) ent.Columns.push(colInfo);
|
||||
})
|
||||
})
|
||||
if (colInfo.sql_type) ent.Columns.push(colInfo);
|
||||
});
|
||||
});
|
||||
return entities;
|
||||
}
|
||||
async GetIndexesFromEntity(entities: EntityInfo[], schema: string): Promise<EntityInfo[]> {
|
||||
let response: any[][] = (await this.Connection.execute(`SELECT ind.TABLE_NAME, ind.INDEX_NAME, col.COLUMN_NAME,ind.UNIQUENESS, CASE WHEN uc.CONSTRAINT_NAME IS NULL THEN 0 ELSE 1 END
|
||||
async GetIndexesFromEntity(
|
||||
entities: EntityInfo[],
|
||||
schema: string
|
||||
): Promise<EntityInfo[]> {
|
||||
let response: any[][] = (await this.Connection
|
||||
.execute(`SELECT ind.TABLE_NAME, ind.INDEX_NAME, col.COLUMN_NAME,ind.UNIQUENESS, CASE WHEN uc.CONSTRAINT_NAME IS NULL THEN 0 ELSE 1 END
|
||||
FROM USER_INDEXES ind
|
||||
JOIN USER_IND_COLUMNS col ON ind.INDEX_NAME=col.INDEX_NAME
|
||||
LEFT JOIN USER_CONSTRAINTS uc ON uc.INDEX_NAME = ind.INDEX_NAME
|
||||
ORDER BY col.INDEX_NAME ASC ,col.COLUMN_POSITION ASC`)).rows!;
|
||||
|
||||
entities.forEach((ent) => {
|
||||
response.filter((filterVal) => {
|
||||
return filterVal[0] == ent.EntityName;
|
||||
}).forEach((resp) => {
|
||||
let indexInfo: IndexInfo = <IndexInfo>{};
|
||||
let indexColumnInfo: IndexColumnInfo = <IndexColumnInfo>{};
|
||||
if (ent.Indexes.filter((filterVal) => {
|
||||
return filterVal.name == resp[1]
|
||||
}).length > 0) {
|
||||
indexInfo = ent.Indexes.filter((filterVal) => {
|
||||
return filterVal.name == resp[1]
|
||||
})[0];
|
||||
} else {
|
||||
indexInfo.columns = <IndexColumnInfo[]>[];
|
||||
indexInfo.name = resp[1];
|
||||
indexInfo.isUnique = resp[3] == 'UNIQUE' ? true : false;
|
||||
indexInfo.isPrimaryKey = resp[4] == 1 ? true : false;
|
||||
ent.Indexes.push(indexInfo);
|
||||
}
|
||||
indexColumnInfo.name = resp[2];
|
||||
// indexColumnInfo.isIncludedColumn = resp.is_included_column == 1 ? true : false;
|
||||
// indexColumnInfo.isDescending = resp.is_descending_key == 1 ? true : false;
|
||||
indexInfo.columns.push(indexColumnInfo);
|
||||
|
||||
})
|
||||
})
|
||||
entities.forEach(ent => {
|
||||
response
|
||||
.filter(filterVal => {
|
||||
return filterVal[0] == ent.EntityName;
|
||||
})
|
||||
.forEach(resp => {
|
||||
let indexInfo: IndexInfo = <IndexInfo>{};
|
||||
let indexColumnInfo: IndexColumnInfo = <IndexColumnInfo>{};
|
||||
if (
|
||||
ent.Indexes.filter(filterVal => {
|
||||
return filterVal.name == resp[1];
|
||||
}).length > 0
|
||||
) {
|
||||
indexInfo = ent.Indexes.filter(filterVal => {
|
||||
return filterVal.name == resp[1];
|
||||
})[0];
|
||||
} else {
|
||||
indexInfo.columns = <IndexColumnInfo[]>[];
|
||||
indexInfo.name = resp[1];
|
||||
indexInfo.isUnique = resp[3] == "UNIQUE" ? true : false;
|
||||
indexInfo.isPrimaryKey = resp[4] == 1 ? true : false;
|
||||
ent.Indexes.push(indexInfo);
|
||||
}
|
||||
indexColumnInfo.name = resp[2];
|
||||
// indexColumnInfo.isIncludedColumn = resp.is_included_column == 1 ? true : false;
|
||||
// indexColumnInfo.isDescending = resp.is_descending_key == 1 ? true : false;
|
||||
indexInfo.columns.push(indexColumnInfo);
|
||||
});
|
||||
});
|
||||
|
||||
return entities;
|
||||
}
|
||||
async GetRelations(entities: EntityInfo[], schema: string): Promise<EntityInfo[]> {
|
||||
let response: any[][] = (await this.Connection.execute(`select owner.TABLE_NAME ownTbl,ownCol.POSITION,ownCol.COLUMN_NAME,
|
||||
async GetRelations(
|
||||
entities: EntityInfo[],
|
||||
schema: string
|
||||
): Promise<EntityInfo[]> {
|
||||
let response: any[][] = (await this.Connection
|
||||
.execute(`select owner.TABLE_NAME ownTbl,ownCol.POSITION,ownCol.COLUMN_NAME,
|
||||
child.TABLE_NAME,childCol.COLUMN_NAME,
|
||||
owner.DELETE_RULE,
|
||||
4,owner.CONSTRAINT_NAME
|
||||
@ -134,14 +158,14 @@ export class OracleDriver extends AbstractDriver {
|
||||
join user_constraints child on owner.r_constraint_name=child.CONSTRAINT_NAME and child.constraint_type in ('P','U')
|
||||
JOIN USER_CONS_COLUMNS ownCol ON owner.CONSTRAINT_NAME = ownCol.CONSTRAINT_NAME
|
||||
JOIN USER_CONS_COLUMNS childCol ON child.CONSTRAINT_NAME = childCol.CONSTRAINT_NAME AND ownCol.POSITION=childCol.POSITION
|
||||
ORDER BY ownTbl ASC, owner.CONSTRAINT_NAME ASC, ownCol.POSITION ASC`)).rows!;
|
||||
|
||||
ORDER BY ownTbl ASC, owner.CONSTRAINT_NAME ASC, ownCol.POSITION ASC`))
|
||||
.rows!;
|
||||
|
||||
let relationsTemp: RelationTempInfo[] = <RelationTempInfo[]>[];
|
||||
response.forEach((resp) => {
|
||||
let rels = relationsTemp.find((val) => {
|
||||
response.forEach(resp => {
|
||||
let rels = relationsTemp.find(val => {
|
||||
return val.object_id == resp[6];
|
||||
})
|
||||
});
|
||||
if (rels == undefined) {
|
||||
rels = <RelationTempInfo>{};
|
||||
rels.ownerColumnsNames = [];
|
||||
@ -155,151 +179,180 @@ export class OracleDriver extends AbstractDriver {
|
||||
}
|
||||
rels.ownerColumnsNames.push(resp[2]);
|
||||
rels.referencedColumnsNames.push(resp[4]);
|
||||
})
|
||||
relationsTemp.forEach((relationTmp) => {
|
||||
let ownerEntity = entities.find((entitity) => {
|
||||
});
|
||||
relationsTemp.forEach(relationTmp => {
|
||||
let ownerEntity = entities.find(entitity => {
|
||||
return entitity.EntityName == relationTmp.ownerTable;
|
||||
})
|
||||
});
|
||||
if (!ownerEntity) {
|
||||
TomgUtils.LogFatalError(`Relation between tables ${relationTmp.ownerTable} and ${relationTmp.referencedTable} didn't found entity model ${relationTmp.ownerTable}.`)
|
||||
TomgUtils.LogFatalError(
|
||||
`Relation between tables ${relationTmp.ownerTable} and ${
|
||||
relationTmp.referencedTable
|
||||
} didn't found entity model ${relationTmp.ownerTable}.`
|
||||
);
|
||||
return;
|
||||
}
|
||||
let referencedEntity = entities.find((entitity) => {
|
||||
let referencedEntity = entities.find(entitity => {
|
||||
return entitity.EntityName == relationTmp.referencedTable;
|
||||
})
|
||||
});
|
||||
if (!referencedEntity) {
|
||||
TomgUtils.LogFatalError(`Relation between tables ${relationTmp.ownerTable} and ${relationTmp.referencedTable} didn't found entity model ${relationTmp.referencedTable}.`)
|
||||
TomgUtils.LogFatalError(
|
||||
`Relation between tables ${relationTmp.ownerTable} and ${
|
||||
relationTmp.referencedTable
|
||||
} didn't found entity model ${relationTmp.referencedTable}.`
|
||||
);
|
||||
return;
|
||||
}
|
||||
let ownerColumn = ownerEntity.Columns.find((column) => {
|
||||
let ownerColumn = ownerEntity.Columns.find(column => {
|
||||
return column.name == relationTmp.ownerColumnsNames[0];
|
||||
})
|
||||
});
|
||||
if (!ownerColumn) {
|
||||
TomgUtils.LogFatalError(`Relation between tables ${relationTmp.ownerTable} and ${relationTmp.referencedTable} didn't found entity column ${relationTmp.ownerTable}.${ownerColumn}.`)
|
||||
TomgUtils.LogFatalError(
|
||||
`Relation between tables ${relationTmp.ownerTable} and ${
|
||||
relationTmp.referencedTable
|
||||
} didn't found entity column ${
|
||||
relationTmp.ownerTable
|
||||
}.${ownerColumn}.`
|
||||
);
|
||||
return;
|
||||
}
|
||||
let relatedColumn = referencedEntity.Columns.find((column) => {
|
||||
let relatedColumn = referencedEntity.Columns.find(column => {
|
||||
return column.name == relationTmp.referencedColumnsNames[0];
|
||||
})
|
||||
});
|
||||
if (!relatedColumn) {
|
||||
TomgUtils.LogFatalError(`Relation between tables ${relationTmp.ownerTable} and ${relationTmp.referencedTable} didn't found entity column ${relationTmp.referencedTable}.${relatedColumn}.`)
|
||||
TomgUtils.LogFatalError(
|
||||
`Relation between tables ${relationTmp.ownerTable} and ${
|
||||
relationTmp.referencedTable
|
||||
} didn't found entity column ${
|
||||
relationTmp.referencedTable
|
||||
}.${relatedColumn}.`
|
||||
);
|
||||
return;
|
||||
}
|
||||
let ownColumn: ColumnInfo = ownerColumn;
|
||||
let isOneToMany: boolean;
|
||||
isOneToMany = false;
|
||||
let index = ownerEntity.Indexes.find(
|
||||
(index) => {
|
||||
return index.isUnique && index.columns.some(col => {
|
||||
return col.name == ownerColumn!.name
|
||||
let index = ownerEntity.Indexes.find(index => {
|
||||
return (
|
||||
index.isUnique &&
|
||||
index.columns.some(col => {
|
||||
return col.name == ownerColumn!.name;
|
||||
})
|
||||
}
|
||||
)
|
||||
);
|
||||
});
|
||||
if (!index) {
|
||||
isOneToMany = true;
|
||||
} else {
|
||||
isOneToMany = false;
|
||||
}
|
||||
let ownerRelation = new RelationInfo()
|
||||
let columnName = ownerEntity.EntityName.toLowerCase() + (isOneToMany ? 's' : '')
|
||||
if (referencedEntity.Columns.filter((filterVal) => {
|
||||
return filterVal.name == columnName;
|
||||
}).length > 0) {
|
||||
let ownerRelation = new RelationInfo();
|
||||
let columnName =
|
||||
ownerEntity.EntityName.toLowerCase() + (isOneToMany ? "s" : "");
|
||||
if (
|
||||
referencedEntity.Columns.filter(filterVal => {
|
||||
return filterVal.name == columnName;
|
||||
}).length > 0
|
||||
) {
|
||||
for (let i = 2; i <= ownerEntity.Columns.length; i++) {
|
||||
columnName = ownerEntity.EntityName.toLowerCase() + (isOneToMany ? 's' : '') + i.toString();
|
||||
if (referencedEntity.Columns.filter((filterVal) => {
|
||||
return filterVal.name == columnName;
|
||||
}).length == 0) break;
|
||||
columnName =
|
||||
ownerEntity.EntityName.toLowerCase() +
|
||||
(isOneToMany ? "s" : "") +
|
||||
i.toString();
|
||||
if (
|
||||
referencedEntity.Columns.filter(filterVal => {
|
||||
return filterVal.name == columnName;
|
||||
}).length == 0
|
||||
)
|
||||
break;
|
||||
}
|
||||
}
|
||||
ownerRelation.actionOnDelete = relationTmp.actionOnDelete
|
||||
ownerRelation.actionOnUpdate = relationTmp.actionOnUpdate
|
||||
ownerRelation.isOwner = true
|
||||
ownerRelation.relatedColumn = relatedColumn.name.toLowerCase()
|
||||
ownerRelation.relatedTable = relationTmp.referencedTable
|
||||
ownerRelation.ownerTable = relationTmp.ownerTable
|
||||
ownerRelation.ownerColumn = columnName
|
||||
ownerRelation.relationType = isOneToMany ? "ManyToOne" : "OneToOne"
|
||||
ownerColumn.relations.push(ownerRelation)
|
||||
ownerRelation.actionOnDelete = relationTmp.actionOnDelete;
|
||||
ownerRelation.actionOnUpdate = relationTmp.actionOnUpdate;
|
||||
ownerRelation.isOwner = true;
|
||||
ownerRelation.relatedColumn = relatedColumn.name.toLowerCase();
|
||||
ownerRelation.relatedTable = relationTmp.referencedTable;
|
||||
ownerRelation.ownerTable = relationTmp.ownerTable;
|
||||
ownerRelation.ownerColumn = columnName;
|
||||
ownerRelation.relationType = isOneToMany ? "ManyToOne" : "OneToOne";
|
||||
ownerColumn.relations.push(ownerRelation);
|
||||
if (isOneToMany) {
|
||||
let col = new ColumnInfo()
|
||||
col.name = columnName
|
||||
let col = new ColumnInfo();
|
||||
col.name = columnName;
|
||||
let referencedRelation = new RelationInfo();
|
||||
col.relations.push(referencedRelation)
|
||||
referencedRelation.actionOnDelete = relationTmp.actionOnDelete
|
||||
referencedRelation.actionOnUpdate = relationTmp.actionOnUpdate
|
||||
referencedRelation.isOwner = false
|
||||
referencedRelation.relatedColumn = ownerColumn.name
|
||||
referencedRelation.relatedTable = relationTmp.ownerTable
|
||||
referencedRelation.ownerTable = relationTmp.referencedTable
|
||||
referencedRelation.ownerColumn = relatedColumn.name.toLowerCase()
|
||||
referencedRelation.relationType = "OneToMany"
|
||||
referencedEntity.Columns.push(col)
|
||||
col.relations.push(referencedRelation);
|
||||
referencedRelation.actionOnDelete = relationTmp.actionOnDelete;
|
||||
referencedRelation.actionOnUpdate = relationTmp.actionOnUpdate;
|
||||
referencedRelation.isOwner = false;
|
||||
referencedRelation.relatedColumn = ownerColumn.name;
|
||||
referencedRelation.relatedTable = relationTmp.ownerTable;
|
||||
referencedRelation.ownerTable = relationTmp.referencedTable;
|
||||
referencedRelation.ownerColumn = relatedColumn.name.toLowerCase();
|
||||
referencedRelation.relationType = "OneToMany";
|
||||
referencedEntity.Columns.push(col);
|
||||
} else {
|
||||
let col = new ColumnInfo()
|
||||
col.name = columnName
|
||||
let col = new ColumnInfo();
|
||||
col.name = columnName;
|
||||
let referencedRelation = new RelationInfo();
|
||||
col.relations.push(referencedRelation)
|
||||
referencedRelation.actionOnDelete = relationTmp.actionOnDelete
|
||||
referencedRelation.actionOnUpdate = relationTmp.actionOnUpdate
|
||||
referencedRelation.isOwner = false
|
||||
referencedRelation.relatedColumn = ownerColumn.name
|
||||
referencedRelation.relatedTable = relationTmp.ownerTable
|
||||
referencedRelation.ownerTable = relationTmp.referencedTable
|
||||
referencedRelation.ownerColumn = relatedColumn.name.toLowerCase()
|
||||
referencedRelation.relationType = "OneToOne"
|
||||
col.relations.push(referencedRelation);
|
||||
referencedRelation.actionOnDelete = relationTmp.actionOnDelete;
|
||||
referencedRelation.actionOnUpdate = relationTmp.actionOnUpdate;
|
||||
referencedRelation.isOwner = false;
|
||||
referencedRelation.relatedColumn = ownerColumn.name;
|
||||
referencedRelation.relatedTable = relationTmp.ownerTable;
|
||||
referencedRelation.ownerTable = relationTmp.referencedTable;
|
||||
referencedRelation.ownerColumn = relatedColumn.name.toLowerCase();
|
||||
referencedRelation.relationType = "OneToOne";
|
||||
|
||||
referencedEntity.Columns.push(col)
|
||||
referencedEntity.Columns.push(col);
|
||||
}
|
||||
})
|
||||
});
|
||||
return entities;
|
||||
}
|
||||
async DisconnectFromServer() {
|
||||
if (this.Connection)
|
||||
await this.Connection.close();
|
||||
if (this.Connection) await this.Connection.close();
|
||||
}
|
||||
|
||||
private Connection: any/*Oracle.IConnection*/;
|
||||
async ConnectToServer(database: string, server: string, port: number, user: string, password: string, ssl: boolean) {
|
||||
let config: any/*Oracle.IConnectionAttributes*/ = {
|
||||
private Connection: any /*Oracle.IConnection*/;
|
||||
async ConnectToServer(
|
||||
database: string,
|
||||
server: string,
|
||||
port: number,
|
||||
user: string,
|
||||
password: string,
|
||||
ssl: boolean
|
||||
) {
|
||||
let config: any /*Oracle.IConnectionAttributes*/ = {
|
||||
user: user,
|
||||
password: password,
|
||||
// connectString: `${server}:${port}/ORCLCDB.localdomain/${database}`,
|
||||
connectString: `${server}:${port}/${database}`,
|
||||
externalAuth: ssl
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
let that = this;
|
||||
let promise = new Promise<boolean>(
|
||||
(resolve, reject) => {
|
||||
this.Oracle.getConnection(
|
||||
config,
|
||||
function (err, connection) {
|
||||
if (!err) {
|
||||
//Connection successfull
|
||||
that.Connection = connection
|
||||
resolve(true)
|
||||
}
|
||||
else {
|
||||
TomgUtils.LogFatalError('Error connecting to Oracle Server.', false, err.message)
|
||||
reject(err)
|
||||
}
|
||||
|
||||
});
|
||||
}
|
||||
)
|
||||
let promise = new Promise<boolean>((resolve, reject) => {
|
||||
this.Oracle.getConnection(config, function(err, connection) {
|
||||
if (!err) {
|
||||
//Connection successfull
|
||||
that.Connection = connection;
|
||||
resolve(true);
|
||||
} else {
|
||||
TomgUtils.LogFatalError(
|
||||
"Error connecting to Oracle Server.",
|
||||
false,
|
||||
err.message
|
||||
);
|
||||
reject(err);
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
await promise;
|
||||
}
|
||||
|
||||
|
||||
async CreateDB(dbName: string) {
|
||||
}
|
||||
async UseDB(dbName: string) {
|
||||
}
|
||||
async DropDB(dbName: string) {
|
||||
}
|
||||
async CreateDB(dbName: string) {}
|
||||
async UseDB(dbName: string) {}
|
||||
async DropDB(dbName: string) {}
|
||||
async CheckIfDBExists(dbName: string): Promise<boolean> {
|
||||
return true;
|
||||
}
|
||||
|
@ -1,10 +1,10 @@
|
||||
import { AbstractDriver } from './AbstractDriver'
|
||||
import * as PG from 'pg'
|
||||
import { ColumnInfo } from './../models/ColumnInfo'
|
||||
import { EntityInfo } from './../models/EntityInfo'
|
||||
import { RelationInfo } from './../models/RelationInfo'
|
||||
import { DatabaseModel } from './../models/DatabaseModel'
|
||||
import * as TomgUtils from './../Utils'
|
||||
import { AbstractDriver } from "./AbstractDriver";
|
||||
import * as PG from "pg";
|
||||
import { ColumnInfo } from "./../models/ColumnInfo";
|
||||
import { EntityInfo } from "./../models/EntityInfo";
|
||||
import { RelationInfo } from "./../models/RelationInfo";
|
||||
import { DatabaseModel } from "./../models/DatabaseModel";
|
||||
import * as TomgUtils from "./../Utils";
|
||||
/**
|
||||
* PostgresDriver
|
||||
*/
|
||||
@ -15,215 +15,255 @@ export class PostgresDriver extends AbstractDriver {
|
||||
dbModel.entities.forEach(entity => {
|
||||
let primaryIndex = entity.Indexes.find(v => v.isPrimaryKey);
|
||||
if (!primaryIndex) {
|
||||
TomgUtils.LogFatalError(`Table ${entity.EntityName} has no PK.`, false)
|
||||
TomgUtils.LogFatalError(
|
||||
`Table ${entity.EntityName} has no PK.`,
|
||||
false
|
||||
);
|
||||
return;
|
||||
}
|
||||
entity.Columns.forEach(col => {
|
||||
if (primaryIndex!.columns.some(cIndex => cIndex.name == col.name)) col.isPrimary = true
|
||||
})
|
||||
if (
|
||||
primaryIndex!.columns.some(
|
||||
cIndex => cIndex.name == col.name
|
||||
)
|
||||
)
|
||||
col.isPrimary = true;
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
async GetAllTables(schema: string): Promise<EntityInfo[]> {
|
||||
|
||||
let response: { table_schema: string, table_name: string }[]
|
||||
= (await this.Connection.query(`SELECT table_schema,table_name FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_TYPE='BASE TABLE' AND table_schema = '${schema}' `)).rows;
|
||||
let response: {
|
||||
table_schema: string;
|
||||
table_name: string;
|
||||
}[] = (await this.Connection.query(
|
||||
`SELECT table_schema,table_name FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_TYPE='BASE TABLE' AND table_schema = '${schema}' `
|
||||
)).rows;
|
||||
|
||||
let ret: EntityInfo[] = <EntityInfo[]>[];
|
||||
response.forEach((val) => {
|
||||
response.forEach(val => {
|
||||
let ent: EntityInfo = new EntityInfo();
|
||||
ent.EntityName = val.table_name;
|
||||
ent.Columns = <ColumnInfo[]>[];
|
||||
ent.Indexes = <IndexInfo[]>[];
|
||||
ret.push(ent);
|
||||
})
|
||||
});
|
||||
return ret;
|
||||
}
|
||||
async GetCoulmnsFromEntity(entities: EntityInfo[], schema: string): Promise<EntityInfo[]> {
|
||||
async GetCoulmnsFromEntity(
|
||||
entities: EntityInfo[],
|
||||
schema: string
|
||||
): Promise<EntityInfo[]> {
|
||||
let response: {
|
||||
table_name: string, column_name: string, column_default: string,
|
||||
is_nullable: string, data_type: string, character_maximum_length: number,
|
||||
numeric_precision: number, numeric_scale: number, isidentity: string
|
||||
}[]
|
||||
= (await this.Connection.query(`SELECT table_name,column_name,column_default,is_nullable,
|
||||
table_name: string;
|
||||
column_name: string;
|
||||
column_default: string;
|
||||
is_nullable: string;
|
||||
data_type: string;
|
||||
character_maximum_length: number;
|
||||
numeric_precision: number;
|
||||
numeric_scale: number;
|
||||
isidentity: string;
|
||||
}[] = (await this.Connection
|
||||
.query(`SELECT table_name,column_name,column_default,is_nullable,
|
||||
data_type,character_maximum_length,numeric_precision,numeric_scale
|
||||
--,COLUMNPROPERTY(object_id(table_name), column_name, 'isidentity') isidentity
|
||||
, case when column_default LIKE 'nextval%' then 'YES' else 'NO' end isidentity
|
||||
FROM INFORMATION_SCHEMA.COLUMNS where table_schema ='${schema}'`)).rows;
|
||||
entities.forEach((ent) => {
|
||||
response.filter((filterVal) => {
|
||||
return filterVal.table_name == ent.EntityName;
|
||||
}).forEach((resp) => {
|
||||
let colInfo: ColumnInfo = new ColumnInfo();
|
||||
colInfo.name = resp.column_name;
|
||||
colInfo.is_nullable = resp.is_nullable == 'YES' ? true : false;
|
||||
colInfo.is_generated = resp.isidentity == 'YES' ? true : false;
|
||||
colInfo.default = colInfo.is_generated ? '' : resp.column_default;
|
||||
switch (resp.data_type) {
|
||||
case "integer":
|
||||
colInfo.ts_type = "number"
|
||||
colInfo.sql_type = "int"
|
||||
break;
|
||||
case "character varying":
|
||||
colInfo.ts_type = "string"
|
||||
colInfo.sql_type = "varchar"
|
||||
colInfo.char_max_lenght = resp.character_maximum_length > 0 ? resp.character_maximum_length : null;
|
||||
break;
|
||||
case "text":
|
||||
colInfo.ts_type = "string"
|
||||
colInfo.sql_type = "text"
|
||||
break;
|
||||
case "uuid":
|
||||
colInfo.ts_type = "string"
|
||||
colInfo.sql_type = "uuid"
|
||||
break;
|
||||
case "smallint":
|
||||
colInfo.ts_type = "number"
|
||||
colInfo.sql_type = "smallint"
|
||||
break;
|
||||
case "bigint":
|
||||
colInfo.ts_type = "string"
|
||||
colInfo.sql_type = "bigint"
|
||||
break;
|
||||
case "date":
|
||||
colInfo.ts_type = "string"
|
||||
colInfo.sql_type = "date"
|
||||
break;
|
||||
case "boolean":
|
||||
colInfo.ts_type = "boolean"
|
||||
colInfo.sql_type = "boolean"
|
||||
break;
|
||||
case "double precision":
|
||||
colInfo.ts_type = "number"
|
||||
colInfo.sql_type = "double"
|
||||
colInfo.numericPrecision = resp.numeric_precision
|
||||
colInfo.numericScale = resp.numeric_scale
|
||||
break;
|
||||
case "real":
|
||||
colInfo.ts_type = "number"
|
||||
colInfo.sql_type = "float"
|
||||
colInfo.numericPrecision = resp.numeric_precision
|
||||
colInfo.numericScale = resp.numeric_scale
|
||||
break;
|
||||
case "numeric":
|
||||
colInfo.ts_type = "string"
|
||||
colInfo.sql_type = "numeric"
|
||||
colInfo.numericPrecision = resp.numeric_precision
|
||||
colInfo.numericScale = resp.numeric_scale
|
||||
break;
|
||||
case "time without time zone":
|
||||
colInfo.ts_type = "string"
|
||||
colInfo.sql_type = "time without time zone"
|
||||
break;
|
||||
case "timestamp without time zone":
|
||||
colInfo.ts_type = "Date"
|
||||
colInfo.sql_type = "timestamp"
|
||||
break;
|
||||
case "timestamp with time zone":
|
||||
colInfo.ts_type = "Date"
|
||||
colInfo.sql_type = "timestamp"
|
||||
break;
|
||||
case "timestamp with time zone":
|
||||
colInfo.ts_type = "Date"
|
||||
colInfo.sql_type = "timestamp"
|
||||
break;
|
||||
case "json":
|
||||
colInfo.ts_type = "Object"
|
||||
colInfo.sql_type = "json"
|
||||
break;
|
||||
case "jsonb":
|
||||
colInfo.ts_type = "Object"
|
||||
colInfo.sql_type = "jsonb"
|
||||
break;
|
||||
case "money":
|
||||
colInfo.ts_type = "string"
|
||||
colInfo.sql_type = "money"
|
||||
break;
|
||||
case "character":
|
||||
colInfo.ts_type = "string"
|
||||
colInfo.sql_type = "character"
|
||||
colInfo.char_max_lenght = resp.character_maximum_length > 0 ? resp.character_maximum_length : null;
|
||||
break;
|
||||
case "bytea":
|
||||
colInfo.ts_type = "Buffer"
|
||||
colInfo.sql_type = "bytea"
|
||||
break;
|
||||
case "interval":
|
||||
colInfo.ts_type = "any"
|
||||
colInfo.sql_type = "interval"
|
||||
break;
|
||||
case "time with time zone":
|
||||
colInfo.ts_type = "string"
|
||||
colInfo.sql_type = "time with time zone"
|
||||
break;
|
||||
case "point":
|
||||
colInfo.ts_type = "string | Object"
|
||||
colInfo.sql_type = "point"
|
||||
break;
|
||||
case "line":
|
||||
colInfo.ts_type = "string"
|
||||
colInfo.sql_type = "line"
|
||||
break;
|
||||
case "lseg":
|
||||
colInfo.ts_type = "string | string[]"
|
||||
colInfo.sql_type = "lseg"
|
||||
break;
|
||||
case "box":
|
||||
colInfo.ts_type = "string | Object"
|
||||
colInfo.sql_type = "box"
|
||||
break;
|
||||
case "path":
|
||||
colInfo.ts_type = "string"
|
||||
colInfo.sql_type = "path"
|
||||
break;
|
||||
case "polygon":
|
||||
colInfo.ts_type = "string"
|
||||
colInfo.sql_type = "polygon"
|
||||
break;
|
||||
case "circle":
|
||||
colInfo.ts_type = "string | Object"
|
||||
colInfo.sql_type = "circle"
|
||||
break;
|
||||
case "cidr":
|
||||
colInfo.ts_type = "string"
|
||||
colInfo.sql_type = "cidr"
|
||||
break;
|
||||
case "inet":
|
||||
colInfo.ts_type = "string"
|
||||
colInfo.sql_type = "inet"
|
||||
break;
|
||||
case "macaddr":
|
||||
colInfo.ts_type = "string"
|
||||
colInfo.sql_type = "macaddr"
|
||||
break;
|
||||
case "bit":
|
||||
colInfo.ts_type = "string"
|
||||
colInfo.sql_type = "bit"
|
||||
break;
|
||||
case "bit varying":
|
||||
colInfo.ts_type = "string"
|
||||
colInfo.sql_type = "bit varying"
|
||||
break;
|
||||
case "xml":
|
||||
colInfo.ts_type = "string"
|
||||
colInfo.sql_type = "xml"
|
||||
break;
|
||||
default:
|
||||
TomgUtils.LogFatalError("Unknown column type:" + resp.data_type);
|
||||
break;
|
||||
}
|
||||
FROM INFORMATION_SCHEMA.COLUMNS where table_schema ='${schema}'`))
|
||||
.rows;
|
||||
entities.forEach(ent => {
|
||||
response
|
||||
.filter(filterVal => {
|
||||
return filterVal.table_name == ent.EntityName;
|
||||
})
|
||||
.forEach(resp => {
|
||||
let colInfo: ColumnInfo = new ColumnInfo();
|
||||
colInfo.name = resp.column_name;
|
||||
colInfo.is_nullable =
|
||||
resp.is_nullable == "YES" ? true : false;
|
||||
colInfo.is_generated =
|
||||
resp.isidentity == "YES" ? true : false;
|
||||
colInfo.default = colInfo.is_generated
|
||||
? ""
|
||||
: resp.column_default;
|
||||
switch (resp.data_type) {
|
||||
case "integer":
|
||||
colInfo.ts_type = "number";
|
||||
colInfo.sql_type = "int";
|
||||
break;
|
||||
case "character varying":
|
||||
colInfo.ts_type = "string";
|
||||
colInfo.sql_type = "varchar";
|
||||
colInfo.char_max_lenght =
|
||||
resp.character_maximum_length > 0
|
||||
? resp.character_maximum_length
|
||||
: null;
|
||||
break;
|
||||
case "text":
|
||||
colInfo.ts_type = "string";
|
||||
colInfo.sql_type = "text";
|
||||
break;
|
||||
case "uuid":
|
||||
colInfo.ts_type = "string";
|
||||
colInfo.sql_type = "uuid";
|
||||
break;
|
||||
case "smallint":
|
||||
colInfo.ts_type = "number";
|
||||
colInfo.sql_type = "smallint";
|
||||
break;
|
||||
case "bigint":
|
||||
colInfo.ts_type = "string";
|
||||
colInfo.sql_type = "bigint";
|
||||
break;
|
||||
case "date":
|
||||
colInfo.ts_type = "string";
|
||||
colInfo.sql_type = "date";
|
||||
break;
|
||||
case "boolean":
|
||||
colInfo.ts_type = "boolean";
|
||||
colInfo.sql_type = "boolean";
|
||||
break;
|
||||
case "double precision":
|
||||
colInfo.ts_type = "number";
|
||||
colInfo.sql_type = "double";
|
||||
colInfo.numericPrecision = resp.numeric_precision;
|
||||
colInfo.numericScale = resp.numeric_scale;
|
||||
break;
|
||||
case "real":
|
||||
colInfo.ts_type = "number";
|
||||
colInfo.sql_type = "float";
|
||||
colInfo.numericPrecision = resp.numeric_precision;
|
||||
colInfo.numericScale = resp.numeric_scale;
|
||||
break;
|
||||
case "numeric":
|
||||
colInfo.ts_type = "string";
|
||||
colInfo.sql_type = "numeric";
|
||||
colInfo.numericPrecision = resp.numeric_precision;
|
||||
colInfo.numericScale = resp.numeric_scale;
|
||||
break;
|
||||
case "time without time zone":
|
||||
colInfo.ts_type = "string";
|
||||
colInfo.sql_type = "time without time zone";
|
||||
break;
|
||||
case "timestamp without time zone":
|
||||
colInfo.ts_type = "Date";
|
||||
colInfo.sql_type = "timestamp";
|
||||
break;
|
||||
case "timestamp with time zone":
|
||||
colInfo.ts_type = "Date";
|
||||
colInfo.sql_type = "timestamp";
|
||||
break;
|
||||
case "timestamp with time zone":
|
||||
colInfo.ts_type = "Date";
|
||||
colInfo.sql_type = "timestamp";
|
||||
break;
|
||||
case "json":
|
||||
colInfo.ts_type = "Object";
|
||||
colInfo.sql_type = "json";
|
||||
break;
|
||||
case "jsonb":
|
||||
colInfo.ts_type = "Object";
|
||||
colInfo.sql_type = "jsonb";
|
||||
break;
|
||||
case "money":
|
||||
colInfo.ts_type = "string";
|
||||
colInfo.sql_type = "money";
|
||||
break;
|
||||
case "character":
|
||||
colInfo.ts_type = "string";
|
||||
colInfo.sql_type = "character";
|
||||
colInfo.char_max_lenght =
|
||||
resp.character_maximum_length > 0
|
||||
? resp.character_maximum_length
|
||||
: null;
|
||||
break;
|
||||
case "bytea":
|
||||
colInfo.ts_type = "Buffer";
|
||||
colInfo.sql_type = "bytea";
|
||||
break;
|
||||
case "interval":
|
||||
colInfo.ts_type = "any";
|
||||
colInfo.sql_type = "interval";
|
||||
break;
|
||||
case "time with time zone":
|
||||
colInfo.ts_type = "string";
|
||||
colInfo.sql_type = "time with time zone";
|
||||
break;
|
||||
case "point":
|
||||
colInfo.ts_type = "string | Object";
|
||||
colInfo.sql_type = "point";
|
||||
break;
|
||||
case "line":
|
||||
colInfo.ts_type = "string";
|
||||
colInfo.sql_type = "line";
|
||||
break;
|
||||
case "lseg":
|
||||
colInfo.ts_type = "string | string[]";
|
||||
colInfo.sql_type = "lseg";
|
||||
break;
|
||||
case "box":
|
||||
colInfo.ts_type = "string | Object";
|
||||
colInfo.sql_type = "box";
|
||||
break;
|
||||
case "path":
|
||||
colInfo.ts_type = "string";
|
||||
colInfo.sql_type = "path";
|
||||
break;
|
||||
case "polygon":
|
||||
colInfo.ts_type = "string";
|
||||
colInfo.sql_type = "polygon";
|
||||
break;
|
||||
case "circle":
|
||||
colInfo.ts_type = "string | Object";
|
||||
colInfo.sql_type = "circle";
|
||||
break;
|
||||
case "cidr":
|
||||
colInfo.ts_type = "string";
|
||||
colInfo.sql_type = "cidr";
|
||||
break;
|
||||
case "inet":
|
||||
colInfo.ts_type = "string";
|
||||
colInfo.sql_type = "inet";
|
||||
break;
|
||||
case "macaddr":
|
||||
colInfo.ts_type = "string";
|
||||
colInfo.sql_type = "macaddr";
|
||||
break;
|
||||
case "bit":
|
||||
colInfo.ts_type = "string";
|
||||
colInfo.sql_type = "bit";
|
||||
break;
|
||||
case "bit varying":
|
||||
colInfo.ts_type = "string";
|
||||
colInfo.sql_type = "bit varying";
|
||||
break;
|
||||
case "xml":
|
||||
colInfo.ts_type = "string";
|
||||
colInfo.sql_type = "xml";
|
||||
break;
|
||||
default:
|
||||
TomgUtils.LogFatalError(
|
||||
"Unknown column type:" + resp.data_type
|
||||
);
|
||||
break;
|
||||
}
|
||||
|
||||
if (colInfo.sql_type) ent.Columns.push(colInfo);
|
||||
})
|
||||
})
|
||||
if (colInfo.sql_type) ent.Columns.push(colInfo);
|
||||
});
|
||||
});
|
||||
return entities;
|
||||
}
|
||||
async GetIndexesFromEntity(entities: EntityInfo[], schema: string): Promise<EntityInfo[]> {
|
||||
async GetIndexesFromEntity(
|
||||
entities: EntityInfo[],
|
||||
schema: string
|
||||
): Promise<EntityInfo[]> {
|
||||
let response: {
|
||||
tablename: string, indexname: string, columnname: string, is_unique: number,
|
||||
is_primary_key: number//, is_descending_key: number//, is_included_column: number
|
||||
}[]
|
||||
= (await this.Connection.query(`SELECT
|
||||
tablename: string;
|
||||
indexname: string;
|
||||
columnname: string;
|
||||
is_unique: number;
|
||||
is_primary_key: number; //, is_descending_key: number//, is_included_column: number
|
||||
}[] = (await this.Connection.query(`SELECT
|
||||
c.relname AS tablename,
|
||||
i.relname as indexname,
|
||||
f.attname AS columnname,
|
||||
@ -251,46 +291,56 @@ export class PostgresDriver extends AbstractDriver {
|
||||
AND f.attnum > 0
|
||||
AND i.oid<>0
|
||||
ORDER BY c.relname,f.attname;`)).rows;
|
||||
entities.forEach((ent) => {
|
||||
response.filter((filterVal) => {
|
||||
return filterVal.tablename == ent.EntityName;
|
||||
}).forEach((resp) => {
|
||||
let indexInfo: IndexInfo = <IndexInfo>{};
|
||||
let indexColumnInfo: IndexColumnInfo = <IndexColumnInfo>{};
|
||||
if (ent.Indexes.filter((filterVal) => {
|
||||
return filterVal.name == resp.indexname
|
||||
}).length > 0) {
|
||||
indexInfo = ent.Indexes.filter((filterVal) => {
|
||||
return filterVal.name == resp.indexname
|
||||
})[0];
|
||||
} else {
|
||||
indexInfo.columns = <IndexColumnInfo[]>[];
|
||||
indexInfo.name = resp.indexname;
|
||||
indexInfo.isUnique = resp.is_unique == 1 ? true : false;
|
||||
indexInfo.isPrimaryKey = resp.is_primary_key == 1 ? true : false;
|
||||
ent.Indexes.push(indexInfo);
|
||||
}
|
||||
indexColumnInfo.name = resp.columnname;
|
||||
if (resp.is_primary_key == 0) {
|
||||
indexInfo.isPrimaryKey = false;
|
||||
}
|
||||
// indexColumnInfo.isIncludedColumn = resp.is_included_column == 1 ? true : false;
|
||||
//indexColumnInfo.isDescending = resp.is_descending_key == 1 ? true : false;
|
||||
indexInfo.columns.push(indexColumnInfo);
|
||||
|
||||
})
|
||||
})
|
||||
entities.forEach(ent => {
|
||||
response
|
||||
.filter(filterVal => {
|
||||
return filterVal.tablename == ent.EntityName;
|
||||
})
|
||||
.forEach(resp => {
|
||||
let indexInfo: IndexInfo = <IndexInfo>{};
|
||||
let indexColumnInfo: IndexColumnInfo = <IndexColumnInfo>{};
|
||||
if (
|
||||
ent.Indexes.filter(filterVal => {
|
||||
return filterVal.name == resp.indexname;
|
||||
}).length > 0
|
||||
) {
|
||||
indexInfo = ent.Indexes.filter(filterVal => {
|
||||
return filterVal.name == resp.indexname;
|
||||
})[0];
|
||||
} else {
|
||||
indexInfo.columns = <IndexColumnInfo[]>[];
|
||||
indexInfo.name = resp.indexname;
|
||||
indexInfo.isUnique = resp.is_unique == 1 ? true : false;
|
||||
indexInfo.isPrimaryKey =
|
||||
resp.is_primary_key == 1 ? true : false;
|
||||
ent.Indexes.push(indexInfo);
|
||||
}
|
||||
indexColumnInfo.name = resp.columnname;
|
||||
if (resp.is_primary_key == 0) {
|
||||
indexInfo.isPrimaryKey = false;
|
||||
}
|
||||
// indexColumnInfo.isIncludedColumn = resp.is_included_column == 1 ? true : false;
|
||||
//indexColumnInfo.isDescending = resp.is_descending_key == 1 ? true : false;
|
||||
indexInfo.columns.push(indexColumnInfo);
|
||||
});
|
||||
});
|
||||
|
||||
return entities;
|
||||
}
|
||||
async GetRelations(entities: EntityInfo[], schema: string): Promise<EntityInfo[]> {
|
||||
async GetRelations(
|
||||
entities: EntityInfo[],
|
||||
schema: string
|
||||
): Promise<EntityInfo[]> {
|
||||
let response: {
|
||||
tablewithforeignkey: string, fk_partno: number, foreignkeycolumn: string,
|
||||
tablereferenced: string, foreignkeycolumnreferenced: string,
|
||||
ondelete: "RESTRICT" | "CASCADE" | "SET NULL" | "NO ACTION",
|
||||
onupdate: "RESTRICT" | "CASCADE" | "SET NULL" | "NO ACTION", object_id: string
|
||||
}[]
|
||||
= (await this.Connection.query(`SELECT
|
||||
tablewithforeignkey: string;
|
||||
fk_partno: number;
|
||||
foreignkeycolumn: string;
|
||||
tablereferenced: string;
|
||||
foreignkeycolumnreferenced: string;
|
||||
ondelete: "RESTRICT" | "CASCADE" | "SET NULL" | "NO ACTION";
|
||||
onupdate: "RESTRICT" | "CASCADE" | "SET NULL" | "NO ACTION";
|
||||
object_id: string;
|
||||
}[] = (await this.Connection.query(`SELECT
|
||||
con.relname AS tablewithforeignkey,
|
||||
att.attnum as fk_partno,
|
||||
att2.attname AS foreignkeycolumn,
|
||||
@ -329,10 +379,10 @@ export class PostgresDriver extends AbstractDriver {
|
||||
AND att2.attnum = con.parent
|
||||
and rc.constraint_name= con.conname`)).rows;
|
||||
let relationsTemp: RelationTempInfo[] = <RelationTempInfo[]>[];
|
||||
response.forEach((resp) => {
|
||||
let rels = relationsTemp.find((val) => {
|
||||
response.forEach(resp => {
|
||||
let rels = relationsTemp.find(val => {
|
||||
return val.object_id == resp.object_id;
|
||||
})
|
||||
});
|
||||
if (rels == undefined) {
|
||||
rels = <RelationTempInfo>{};
|
||||
rels.ownerColumnsNames = [];
|
||||
@ -346,125 +396,164 @@ export class PostgresDriver extends AbstractDriver {
|
||||
}
|
||||
rels.ownerColumnsNames.push(resp.foreignkeycolumn);
|
||||
rels.referencedColumnsNames.push(resp.foreignkeycolumnreferenced);
|
||||
})
|
||||
relationsTemp.forEach((relationTmp) => {
|
||||
let ownerEntity = entities.find((entitity) => {
|
||||
});
|
||||
relationsTemp.forEach(relationTmp => {
|
||||
let ownerEntity = entities.find(entitity => {
|
||||
return entitity.EntityName == relationTmp.ownerTable;
|
||||
})
|
||||
});
|
||||
if (!ownerEntity) {
|
||||
TomgUtils.LogFatalError(`Relation between tables ${relationTmp.ownerTable} and ${relationTmp.referencedTable} didn't found entity model ${relationTmp.ownerTable}.`)
|
||||
TomgUtils.LogFatalError(
|
||||
`Relation between tables ${relationTmp.ownerTable} and ${
|
||||
relationTmp.referencedTable
|
||||
} didn't found entity model ${relationTmp.ownerTable}.`
|
||||
);
|
||||
return;
|
||||
}
|
||||
let referencedEntity = entities.find((entitity) => {
|
||||
let referencedEntity = entities.find(entitity => {
|
||||
return entitity.EntityName == relationTmp.referencedTable;
|
||||
})
|
||||
});
|
||||
if (!referencedEntity) {
|
||||
TomgUtils.LogFatalError(`Relation between tables ${relationTmp.ownerTable} and ${relationTmp.referencedTable} didn't found entity model ${relationTmp.referencedTable}.`)
|
||||
TomgUtils.LogFatalError(
|
||||
`Relation between tables ${relationTmp.ownerTable} and ${
|
||||
relationTmp.referencedTable
|
||||
} didn't found entity model ${relationTmp.referencedTable}.`
|
||||
);
|
||||
return;
|
||||
}
|
||||
let ownerColumn = ownerEntity.Columns.find((column) => {
|
||||
let ownerColumn = ownerEntity.Columns.find(column => {
|
||||
return column.name == relationTmp.ownerColumnsNames[0];
|
||||
})
|
||||
});
|
||||
if (!ownerColumn) {
|
||||
TomgUtils.LogFatalError(`Relation between tables ${relationTmp.ownerTable} and ${relationTmp.referencedTable} didn't found entity column ${relationTmp.ownerTable}.${ownerColumn}.`)
|
||||
TomgUtils.LogFatalError(
|
||||
`Relation between tables ${relationTmp.ownerTable} and ${
|
||||
relationTmp.referencedTable
|
||||
} didn't found entity column ${
|
||||
relationTmp.ownerTable
|
||||
}.${ownerColumn}.`
|
||||
);
|
||||
return;
|
||||
}
|
||||
let relatedColumn = referencedEntity.Columns.find((column) => {
|
||||
let relatedColumn = referencedEntity.Columns.find(column => {
|
||||
return column.name == relationTmp.referencedColumnsNames[0];
|
||||
})
|
||||
});
|
||||
if (!relatedColumn) {
|
||||
TomgUtils.LogFatalError(`Relation between tables ${relationTmp.ownerTable} and ${relationTmp.referencedTable} didn't found entity column ${relationTmp.referencedTable}.${relatedColumn}.`)
|
||||
TomgUtils.LogFatalError(
|
||||
`Relation between tables ${relationTmp.ownerTable} and ${
|
||||
relationTmp.referencedTable
|
||||
} didn't found entity column ${
|
||||
relationTmp.referencedTable
|
||||
}.${relatedColumn}.`
|
||||
);
|
||||
return;
|
||||
}
|
||||
let ownColumn: ColumnInfo = ownerColumn;
|
||||
let isOneToMany: boolean;
|
||||
isOneToMany = false;
|
||||
let index = ownerEntity.Indexes.find(
|
||||
(index) => {
|
||||
return index.isUnique && index.columns.some(col => {
|
||||
return col.name == ownerColumn!.name
|
||||
let index = ownerEntity.Indexes.find(index => {
|
||||
return (
|
||||
index.isUnique &&
|
||||
index.columns.some(col => {
|
||||
return col.name == ownerColumn!.name;
|
||||
})
|
||||
}
|
||||
)
|
||||
);
|
||||
});
|
||||
if (!index) {
|
||||
isOneToMany = true;
|
||||
} else {
|
||||
isOneToMany = false;
|
||||
}
|
||||
let ownerRelation = new RelationInfo()
|
||||
let columnName = ownerEntity.EntityName.toLowerCase() + (isOneToMany ? 's' : '')
|
||||
if (referencedEntity.Columns.filter((filterVal) => {
|
||||
return filterVal.name == columnName;
|
||||
}).length > 0) {
|
||||
let ownerRelation = new RelationInfo();
|
||||
let columnName =
|
||||
ownerEntity.EntityName.toLowerCase() + (isOneToMany ? "s" : "");
|
||||
if (
|
||||
referencedEntity.Columns.filter(filterVal => {
|
||||
return filterVal.name == columnName;
|
||||
}).length > 0
|
||||
) {
|
||||
for (let i = 2; i <= ownerEntity.Columns.length; i++) {
|
||||
columnName = ownerEntity.EntityName.toLowerCase() + (isOneToMany ? 's' : '') + i.toString();
|
||||
if (referencedEntity.Columns.filter((filterVal) => {
|
||||
return filterVal.name == columnName;
|
||||
}).length == 0) break;
|
||||
columnName =
|
||||
ownerEntity.EntityName.toLowerCase() +
|
||||
(isOneToMany ? "s" : "") +
|
||||
i.toString();
|
||||
if (
|
||||
referencedEntity.Columns.filter(filterVal => {
|
||||
return filterVal.name == columnName;
|
||||
}).length == 0
|
||||
)
|
||||
break;
|
||||
}
|
||||
}
|
||||
ownerRelation.actionOnDelete = relationTmp.actionOnDelete
|
||||
ownerRelation.actionOnUpdate = relationTmp.actionOnUpdate
|
||||
ownerRelation.isOwner = true
|
||||
ownerRelation.relatedColumn = relatedColumn.name.toLowerCase()
|
||||
ownerRelation.relatedTable = relationTmp.referencedTable
|
||||
ownerRelation.ownerTable = relationTmp.ownerTable
|
||||
ownerRelation.ownerColumn = columnName
|
||||
ownerRelation.relationType = isOneToMany ? "ManyToOne" : "OneToOne"
|
||||
ownerColumn.relations.push(ownerRelation)
|
||||
ownerRelation.actionOnDelete = relationTmp.actionOnDelete;
|
||||
ownerRelation.actionOnUpdate = relationTmp.actionOnUpdate;
|
||||
ownerRelation.isOwner = true;
|
||||
ownerRelation.relatedColumn = relatedColumn.name.toLowerCase();
|
||||
ownerRelation.relatedTable = relationTmp.referencedTable;
|
||||
ownerRelation.ownerTable = relationTmp.ownerTable;
|
||||
ownerRelation.ownerColumn = columnName;
|
||||
ownerRelation.relationType = isOneToMany ? "ManyToOne" : "OneToOne";
|
||||
ownerColumn.relations.push(ownerRelation);
|
||||
if (isOneToMany) {
|
||||
let col = new ColumnInfo()
|
||||
col.name = columnName
|
||||
let col = new ColumnInfo();
|
||||
col.name = columnName;
|
||||
let referencedRelation = new RelationInfo();
|
||||
col.relations.push(referencedRelation)
|
||||
referencedRelation.actionondelete = relationTmp.actionOnDelete
|
||||
referencedRelation.actiononupdate = relationTmp.actionOnUpdate
|
||||
referencedRelation.isOwner = false
|
||||
referencedRelation.relatedColumn = ownerColumn.name
|
||||
referencedRelation.relatedTable = relationTmp.ownerTable
|
||||
referencedRelation.ownerTable = relationTmp.referencedTable
|
||||
referencedRelation.ownerColumn = relatedColumn.name.toLowerCase()
|
||||
referencedRelation.relationType = "OneToMany"
|
||||
referencedEntity.Columns.push(col)
|
||||
col.relations.push(referencedRelation);
|
||||
referencedRelation.actionondelete = relationTmp.actionOnDelete;
|
||||
referencedRelation.actiononupdate = relationTmp.actionOnUpdate;
|
||||
referencedRelation.isOwner = false;
|
||||
referencedRelation.relatedColumn = ownerColumn.name;
|
||||
referencedRelation.relatedTable = relationTmp.ownerTable;
|
||||
referencedRelation.ownerTable = relationTmp.referencedTable;
|
||||
referencedRelation.ownerColumn = relatedColumn.name.toLowerCase();
|
||||
referencedRelation.relationType = "OneToMany";
|
||||
referencedEntity.Columns.push(col);
|
||||
} else {
|
||||
let col = new ColumnInfo()
|
||||
col.name = columnName
|
||||
let col = new ColumnInfo();
|
||||
col.name = columnName;
|
||||
let referencedRelation = new RelationInfo();
|
||||
col.relations.push(referencedRelation)
|
||||
referencedRelation.actionondelete = relationTmp.actionOnDelete
|
||||
referencedRelation.actiononupdate = relationTmp.actionOnUpdate
|
||||
referencedRelation.isOwner = false
|
||||
referencedRelation.relatedColumn = ownerColumn.name
|
||||
referencedRelation.relatedTable = relationTmp.ownerTable
|
||||
referencedRelation.ownerTable = relationTmp.referencedTable
|
||||
referencedRelation.ownerColumn = relatedColumn.name.toLowerCase()
|
||||
referencedRelation.relationType = "OneToOne"
|
||||
col.relations.push(referencedRelation);
|
||||
referencedRelation.actionondelete = relationTmp.actionOnDelete;
|
||||
referencedRelation.actiononupdate = relationTmp.actionOnUpdate;
|
||||
referencedRelation.isOwner = false;
|
||||
referencedRelation.relatedColumn = ownerColumn.name;
|
||||
referencedRelation.relatedTable = relationTmp.ownerTable;
|
||||
referencedRelation.ownerTable = relationTmp.referencedTable;
|
||||
referencedRelation.ownerColumn = relatedColumn.name.toLowerCase();
|
||||
referencedRelation.relationType = "OneToOne";
|
||||
|
||||
referencedEntity.Columns.push(col)
|
||||
referencedEntity.Columns.push(col);
|
||||
}
|
||||
})
|
||||
});
|
||||
return entities;
|
||||
}
|
||||
async DisconnectFromServer() {
|
||||
if (this.Connection) {
|
||||
let promise = new Promise<boolean>(
|
||||
(resolve, reject) => {
|
||||
this.Connection.end((err) => {
|
||||
if (!err) {
|
||||
//Connection successfull
|
||||
resolve(true)
|
||||
}
|
||||
else {
|
||||
TomgUtils.LogFatalError('Error connecting to Postgres Server.', false, err.message)
|
||||
reject(err)
|
||||
}
|
||||
});
|
||||
})
|
||||
let promise = new Promise<boolean>((resolve, reject) => {
|
||||
this.Connection.end(err => {
|
||||
if (!err) {
|
||||
//Connection successfull
|
||||
resolve(true);
|
||||
} else {
|
||||
TomgUtils.LogFatalError(
|
||||
"Error connecting to Postgres Server.",
|
||||
false,
|
||||
err.message
|
||||
);
|
||||
reject(err);
|
||||
}
|
||||
});
|
||||
});
|
||||
await promise;
|
||||
}
|
||||
}
|
||||
|
||||
async ConnectToServer(database: string, server: string, port: number, user: string, password: string, ssl: boolean) {
|
||||
async ConnectToServer(
|
||||
database: string,
|
||||
server: string,
|
||||
port: number,
|
||||
user: string,
|
||||
password: string,
|
||||
ssl: boolean
|
||||
) {
|
||||
this.Connection = new PG.Client({
|
||||
database: database,
|
||||
host: server,
|
||||
@ -472,39 +561,40 @@ export class PostgresDriver extends AbstractDriver {
|
||||
user: user,
|
||||
password: password,
|
||||
ssl: ssl
|
||||
})
|
||||
});
|
||||
|
||||
|
||||
let promise = new Promise<boolean>(
|
||||
(resolve, reject) => {
|
||||
this.Connection.connect((err) => {
|
||||
if (!err) {
|
||||
//Connection successfull
|
||||
resolve(true)
|
||||
}
|
||||
else {
|
||||
TomgUtils.LogFatalError('Error connecting to Postgres Server.', false, err.message)
|
||||
reject(err)
|
||||
}
|
||||
});
|
||||
}
|
||||
)
|
||||
let promise = new Promise<boolean>((resolve, reject) => {
|
||||
this.Connection.connect(err => {
|
||||
if (!err) {
|
||||
//Connection successfull
|
||||
resolve(true);
|
||||
} else {
|
||||
TomgUtils.LogFatalError(
|
||||
"Error connecting to Postgres Server.",
|
||||
false,
|
||||
err.message
|
||||
);
|
||||
reject(err);
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
await promise;
|
||||
}
|
||||
|
||||
async CreateDB(dbName: string) {
|
||||
|
||||
let resp = await this.Connection.query(`CREATE DATABASE ${dbName}; `)
|
||||
let resp = await this.Connection.query(`CREATE DATABASE ${dbName}; `);
|
||||
}
|
||||
async UseDB(dbName: string) {
|
||||
let resp = await this.Connection.query(`USE ${dbName}; `)
|
||||
let resp = await this.Connection.query(`USE ${dbName}; `);
|
||||
}
|
||||
async DropDB(dbName: string) {
|
||||
let resp = await this.Connection.query(`DROP DATABASE ${dbName}; `)
|
||||
let resp = await this.Connection.query(`DROP DATABASE ${dbName}; `);
|
||||
}
|
||||
async CheckIfDBExists(dbName: string): Promise<boolean> {
|
||||
let resp = await this.Connection.query(`SELECT datname FROM pg_database WHERE datname ='${dbName}' `)
|
||||
let resp = await this.Connection.query(
|
||||
`SELECT datname FROM pg_database WHERE datname ='${dbName}' `
|
||||
);
|
||||
return resp.rowCount > 0;
|
||||
}
|
||||
}
|
||||
|
173
src/index.ts
173
src/index.ts
@ -1,136 +1,137 @@
|
||||
import { AbstractDriver } from "./drivers/AbstractDriver";
|
||||
import { MssqlDriver } from './drivers/MssqlDriver';
|
||||
import { MssqlDriver } from "./drivers/MssqlDriver";
|
||||
import { PostgresDriver } from "./drivers/PostgresDriver";
|
||||
import { MysqlDriver } from "./drivers/MysqlDriver";
|
||||
import { MariaDbDriver } from "./drivers/MariaDbDriver";
|
||||
import { OracleDriver } from "./drivers/OracleDriver";
|
||||
import { Engine } from './Engine'
|
||||
import * as Yargs from 'yargs'
|
||||
import * as TomgUtils from './Utils'
|
||||
import path = require('path')
|
||||
import { Engine } from "./Engine";
|
||||
import * as Yargs from "yargs";
|
||||
import * as TomgUtils from "./Utils";
|
||||
import path = require("path");
|
||||
|
||||
|
||||
|
||||
var argv = Yargs
|
||||
.usage('Usage: typeorm-model-generator -h <host> -d <database> -p [port] -u <user> -x [password] -e [engine]')
|
||||
.option('h', {
|
||||
alias: 'host',
|
||||
describe: 'IP adress/Hostname for database server.',
|
||||
var argv = Yargs.usage(
|
||||
"Usage: typeorm-model-generator -h <host> -d <database> -p [port] -u <user> -x [password] -e [engine]"
|
||||
)
|
||||
.option("h", {
|
||||
alias: "host",
|
||||
describe: "IP adress/Hostname for database server.",
|
||||
demand: true
|
||||
})
|
||||
.option('d', {
|
||||
alias: 'database',
|
||||
describe: 'Database name.',
|
||||
.option("d", {
|
||||
alias: "database",
|
||||
describe: "Database name.",
|
||||
demand: true
|
||||
})
|
||||
.option('u', {
|
||||
alias: 'user',
|
||||
describe: 'Username for database server.',
|
||||
.option("u", {
|
||||
alias: "user",
|
||||
describe: "Username for database server.",
|
||||
demand: true
|
||||
})
|
||||
.option('x', {
|
||||
alias: 'pass',
|
||||
describe: 'Password for database server.',
|
||||
default: ''
|
||||
.option("x", {
|
||||
alias: "pass",
|
||||
describe: "Password for database server.",
|
||||
default: ""
|
||||
})
|
||||
.option('p', {
|
||||
alias: 'port',
|
||||
describe: 'Port number for database server.',
|
||||
.option("p", {
|
||||
alias: "port",
|
||||
describe: "Port number for database server."
|
||||
})
|
||||
.option('e', {
|
||||
alias: 'engine',
|
||||
describe: 'Database engine.',
|
||||
choices: ['mssql', 'postgres', 'mysql', 'mariadb'],
|
||||
default: 'mssql'
|
||||
.option("e", {
|
||||
alias: "engine",
|
||||
describe: "Database engine.",
|
||||
choices: ["mssql", "postgres", "mysql", "mariadb"],
|
||||
default: "mssql"
|
||||
})
|
||||
.option('o', {
|
||||
alias: 'output',
|
||||
describe: 'Where to place generated models.',
|
||||
default: path.resolve(process.cwd(), 'output')
|
||||
.option("o", {
|
||||
alias: "output",
|
||||
describe: "Where to place generated models.",
|
||||
default: path.resolve(process.cwd(), "output")
|
||||
})
|
||||
.option('s', {
|
||||
alias: 'schema',
|
||||
describe: 'Schema name to create model from. Only for mssql and postgres.'
|
||||
.option("s", {
|
||||
alias: "schema",
|
||||
describe:
|
||||
"Schema name to create model from. Only for mssql and postgres."
|
||||
})
|
||||
.option('ssl', {
|
||||
.option("ssl", {
|
||||
boolean: true,
|
||||
default: false
|
||||
})
|
||||
.option('noConfig', {
|
||||
.option("noConfig", {
|
||||
boolean: true,
|
||||
describe: `Doesn't create tsconfig.json and ormconfig.json`,
|
||||
default: false
|
||||
})
|
||||
.option('cf', {
|
||||
alias: 'case-file',
|
||||
describe: 'Convert file names to specified case',
|
||||
choices: ['pascal', 'param', 'camel', 'none'],
|
||||
default: 'none'
|
||||
.option("cf", {
|
||||
alias: "case-file",
|
||||
describe: "Convert file names to specified case",
|
||||
choices: ["pascal", "param", "camel", "none"],
|
||||
default: "none"
|
||||
})
|
||||
.option('ce', {
|
||||
alias: 'case-entity',
|
||||
describe: 'Convert class names to specified case',
|
||||
choices: ['pascal', 'camel', 'none'],
|
||||
default: 'none'
|
||||
.option("ce", {
|
||||
alias: "case-entity",
|
||||
describe: "Convert class names to specified case",
|
||||
choices: ["pascal", "camel", "none"],
|
||||
default: "none"
|
||||
})
|
||||
.option('cp', {
|
||||
alias: 'case-property',
|
||||
describe: 'Convert property names to specified case',
|
||||
choices: ['pascal', 'camel', 'none'],
|
||||
default: 'none'
|
||||
})
|
||||
.argv;
|
||||
|
||||
.option("cp", {
|
||||
alias: "case-property",
|
||||
describe: "Convert property names to specified case",
|
||||
choices: ["pascal", "camel", "none"],
|
||||
default: "none"
|
||||
}).argv;
|
||||
|
||||
var driver: AbstractDriver;
|
||||
var standardPort: number;
|
||||
var standardSchema: string = '';
|
||||
var standardSchema: string = "";
|
||||
switch (argv.e) {
|
||||
case 'mssql':
|
||||
case "mssql":
|
||||
driver = new MssqlDriver();
|
||||
standardPort = 1433;
|
||||
standardSchema = 'dbo';
|
||||
standardSchema = "dbo";
|
||||
break;
|
||||
case 'postgres':
|
||||
case "postgres":
|
||||
driver = new PostgresDriver();
|
||||
standardPort = 5432;
|
||||
standardSchema = 'public';
|
||||
standardSchema = "public";
|
||||
break;
|
||||
case 'mysql':
|
||||
case "mysql":
|
||||
driver = new MysqlDriver();
|
||||
standardPort = 3306;
|
||||
break;
|
||||
case 'mariadb':
|
||||
case "mariadb":
|
||||
driver = new MysqlDriver();
|
||||
standardPort = 3306;
|
||||
break;
|
||||
case 'oracle':
|
||||
case "oracle":
|
||||
driver = new OracleDriver();
|
||||
standardPort = 1521;
|
||||
break;
|
||||
default:
|
||||
TomgUtils.LogFatalError('Database engine not recognized.', false)
|
||||
throw new Error('Database engine not recognized.');
|
||||
TomgUtils.LogFatalError("Database engine not recognized.", false);
|
||||
throw new Error("Database engine not recognized.");
|
||||
}
|
||||
|
||||
let engine = new Engine(
|
||||
driver, {
|
||||
host: argv.h,
|
||||
port: parseInt(argv.p) || standardPort,
|
||||
databaseName: argv.d,
|
||||
user: argv.u,
|
||||
password: argv.x,
|
||||
databaseType: argv.e,
|
||||
resultsPath: argv.o,
|
||||
schemaName: argv.s || standardSchema,
|
||||
ssl: argv.ssl,
|
||||
noConfigs: argv.noConfig,
|
||||
convertCaseFile: argv.cf,
|
||||
convertCaseEntity: argv.ce,
|
||||
convertCaseProperty: argv.cp,
|
||||
});
|
||||
let engine = new Engine(driver, {
|
||||
host: argv.h,
|
||||
port: parseInt(argv.p) || standardPort,
|
||||
databaseName: argv.d,
|
||||
user: argv.u,
|
||||
password: argv.x,
|
||||
databaseType: argv.e,
|
||||
resultsPath: argv.o,
|
||||
schemaName: argv.s || standardSchema,
|
||||
ssl: argv.ssl,
|
||||
noConfigs: argv.noConfig,
|
||||
convertCaseFile: argv.cf,
|
||||
convertCaseEntity: argv.ce,
|
||||
convertCaseProperty: argv.cp
|
||||
});
|
||||
|
||||
console.log(`[${new Date().toLocaleTimeString()}] Starting creation of model classes.`);
|
||||
console.log(
|
||||
`[${new Date().toLocaleTimeString()}] Starting creation of model classes.`
|
||||
);
|
||||
engine.createModelFromDatabase().then(() => {
|
||||
console.info(`[${new Date().toLocaleTimeString()}] Typeorm model classes created.`)
|
||||
})
|
||||
console.info(
|
||||
`[${new Date().toLocaleTimeString()}] Typeorm model classes created.`
|
||||
);
|
||||
});
|
||||
|
@ -1,13 +1,22 @@
|
||||
import { RelationInfo } from './RelationInfo'
|
||||
import { ColumnType } from 'typeorm';
|
||||
import { RelationInfo } from "./RelationInfo";
|
||||
import { ColumnType } from "typeorm";
|
||||
/**
|
||||
* ColumnInfo
|
||||
*/
|
||||
export class ColumnInfo {
|
||||
name: string = '';
|
||||
name: string = "";
|
||||
default: string | null = null;
|
||||
is_nullable: boolean = false;
|
||||
ts_type: 'number' | 'string' | 'boolean' | 'Date' | 'Buffer' | 'Object' | 'string | Object' | 'string | string[]' | 'any';
|
||||
ts_type:
|
||||
| "number"
|
||||
| "string"
|
||||
| "boolean"
|
||||
| "Date"
|
||||
| "Buffer"
|
||||
| "Object"
|
||||
| "string | Object"
|
||||
| "string | string[]"
|
||||
| "any";
|
||||
sql_type: ColumnType;
|
||||
char_max_lenght: number | null = null;
|
||||
isPrimary: boolean = false;
|
||||
@ -17,9 +26,7 @@ export class ColumnInfo {
|
||||
enumOptions: string | null = null;
|
||||
relations: RelationInfo[];
|
||||
|
||||
|
||||
constructor() {
|
||||
this.relations = [];
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -1,18 +1,23 @@
|
||||
import { EntityInfo } from './EntityInfo'
|
||||
import { EntityInfo } from "./EntityInfo";
|
||||
export class DatabaseModel {
|
||||
entities: EntityInfo[];
|
||||
config: {
|
||||
cascadeInsert: boolean,
|
||||
cascadeUpdate: boolean,
|
||||
cascadeRemove: boolean,
|
||||
}
|
||||
cascadeInsert: boolean;
|
||||
cascadeUpdate: boolean;
|
||||
cascadeRemove: boolean;
|
||||
};
|
||||
|
||||
//TODO:check if unused
|
||||
//TODO:check if unused
|
||||
relationImports(): any {
|
||||
let that = this;
|
||||
return function (text, render) {
|
||||
if ('l' != render(text)) return `import {{curly true}}{{toEntityName ${render(text)}}}{{curly false}} from "./{{ ${render( "toFileName"+ text)}}}`
|
||||
else return '';
|
||||
}
|
||||
return function(text, render) {
|
||||
if ("l" != render(text))
|
||||
return `import {{curly true}}{{toEntityName ${render(
|
||||
text
|
||||
)}}}{{curly false}} from "./{{ ${render(
|
||||
"toFileName" + text
|
||||
)}}}`;
|
||||
else return "";
|
||||
};
|
||||
}
|
||||
}
|
||||
|
@ -1,5 +1,5 @@
|
||||
import { ColumnInfo } from './ColumnInfo'
|
||||
import * as Handlebars from 'handlebars'
|
||||
import { ColumnInfo } from "./ColumnInfo";
|
||||
import * as Handlebars from "handlebars";
|
||||
|
||||
/**
|
||||
* EntityInfo
|
||||
@ -14,17 +14,14 @@ export class EntityInfo {
|
||||
relationImports(): any {
|
||||
var returnString = "";
|
||||
var imports: string[] = [];
|
||||
this.Columns.forEach((column) => {
|
||||
column.relations.forEach(
|
||||
(relation) => {
|
||||
if (this.EntityName != relation.relatedTable)
|
||||
imports.push(relation.relatedTable);
|
||||
}
|
||||
)
|
||||
this.Columns.forEach(column => {
|
||||
column.relations.forEach(relation => {
|
||||
if (this.EntityName != relation.relatedTable)
|
||||
imports.push(relation.relatedTable);
|
||||
});
|
||||
});
|
||||
this.UniqueImports=imports.filter(function (elem, index, self) {
|
||||
this.UniqueImports = imports.filter(function(elem, index, self) {
|
||||
return index == self.indexOf(elem);
|
||||
})
|
||||
});
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -1,5 +1,5 @@
|
||||
interface IndexColumnInfo {
|
||||
name: string,
|
||||
name: string;
|
||||
//isDescending:boolean,
|
||||
// isIncludedColumn:boolean
|
||||
}
|
||||
|
@ -2,8 +2,8 @@
|
||||
* IndexInfo
|
||||
*/
|
||||
interface IndexInfo {
|
||||
name: string,
|
||||
columns: IndexColumnInfo[],
|
||||
isUnique: boolean,
|
||||
isPrimaryKey: boolean,
|
||||
name: string;
|
||||
columns: IndexColumnInfo[];
|
||||
isUnique: boolean;
|
||||
isPrimaryKey: boolean;
|
||||
}
|
||||
|
@ -1,17 +1,16 @@
|
||||
export class RelationInfo {
|
||||
[x: string]: any;
|
||||
|
||||
isOwner: boolean
|
||||
relationType: "OneToOne" | "OneToMany" | "ManyToOne"
|
||||
relatedTable: string
|
||||
relatedColumn: string
|
||||
ownerTable: string
|
||||
ownerColumn: string
|
||||
actionOnDelete: "RESTRICT" | "CASCADE" | "SET NULL" | "NO ACTION"
|
||||
actionOnUpdate: "RESTRICT" | "CASCADE" | "SET NULL" | "NO ACTION"
|
||||
isOwner: boolean;
|
||||
relationType: "OneToOne" | "OneToMany" | "ManyToOne";
|
||||
relatedTable: string;
|
||||
relatedColumn: string;
|
||||
ownerTable: string;
|
||||
ownerColumn: string;
|
||||
actionOnDelete: "RESTRICT" | "CASCADE" | "SET NULL" | "NO ACTION";
|
||||
actionOnUpdate: "RESTRICT" | "CASCADE" | "SET NULL" | "NO ACTION";
|
||||
|
||||
get isOneToMany(): boolean {
|
||||
return this.relationType == "OneToMany"
|
||||
return this.relationType == "OneToMany";
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -1,9 +1,9 @@
|
||||
interface RelationTempInfo {
|
||||
ownerTable: string,
|
||||
ownerColumnsNames: string[],
|
||||
referencedTable: string,
|
||||
referencedColumnsNames: string[],
|
||||
actionOnDelete: "RESTRICT" | "CASCADE" | "SET NULL" | "NO ACTION",
|
||||
actionOnUpdate: "RESTRICT" | "CASCADE" | "SET NULL" | "NO ACTION",
|
||||
object_id: number | string
|
||||
ownerTable: string;
|
||||
ownerColumnsNames: string[];
|
||||
referencedTable: string;
|
||||
referencedColumnsNames: string[];
|
||||
actionOnDelete: "RESTRICT" | "CASCADE" | "SET NULL" | "NO ACTION";
|
||||
actionOnUpdate: "RESTRICT" | "CASCADE" | "SET NULL" | "NO ACTION";
|
||||
object_id: number | string;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user