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