diff --git a/.prettierrc b/.prettierrc new file mode 100644 index 0000000..f85bffb --- /dev/null +++ b/.prettierrc @@ -0,0 +1,3 @@ +{ + "parser":"typescript" +} diff --git a/package-lock.json b/package-lock.json index e003f67..5c6aa78 100644 --- a/package-lock.json +++ b/package-lock.json @@ -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", diff --git a/package.json b/package.json index cd5d2ed..f8f75cb 100644 --- a/package.json +++ b/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" + } } diff --git a/src/Engine.ts b/src/Engine.ts index 930efbd..ee6d21d 100644 --- a/src/Engine.ts +++ b/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 { - 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 { - 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 { + 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"; } - diff --git a/src/Utils.ts b/src/Utils.ts index ce7f0f6..2835553 100644 --- a/src/Utils.ts +++ b/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 = 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(); } diff --git a/src/drivers/AbstractDriver.ts b/src/drivers/AbstractDriver.ts index a63850c..b07eb01 100644 --- a/src/drivers/AbstractDriver.ts +++ b/src/drivers/AbstractDriver.ts @@ -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 { + async GetDataFromServer( + database: string, + server: string, + port: number, + user: string, + password: string, + schema: string, + ssl: boolean + ): Promise { let dbModel = {}; 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 - abstract async GetCoulmnsFromEntity(entities: EntityInfo[], schema: string): Promise; - abstract async GetIndexesFromEntity(entities: EntityInfo[], schema: string): Promise; - abstract async GetRelations(entities: EntityInfo[], schema: string): Promise; + abstract async ConnectToServer( + database: string, + server: string, + port: number, + user: string, + password: string, + ssl: boolean + ); + abstract async GetAllTables(schema: string): Promise; + abstract async GetCoulmnsFromEntity( + entities: EntityInfo[], + schema: string + ): Promise; + abstract async GetIndexesFromEntity( + entities: EntityInfo[], + schema: string + ): Promise; + abstract async GetRelations( + entities: EntityInfo[], + schema: string + ): Promise; abstract async FindPrimaryColumnsFromIndexes(dbModel: DatabaseModel); abstract async DisconnectFromServer(); diff --git a/src/drivers/MariaDbDriver.ts b/src/drivers/MariaDbDriver.ts index db75c97..52309f8 100644 --- a/src/drivers/MariaDbDriver.ts +++ b/src/drivers/MariaDbDriver.ts @@ -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"; } diff --git a/src/drivers/MssqlDriver.ts b/src/drivers/MssqlDriver.ts index 488beaf..b59ad36 100644 --- a/src/drivers/MssqlDriver.ts +++ b/src/drivers/MssqlDriver.ts @@ -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 { - 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[] = []; - response.forEach((val) => { + response.forEach(val => { let ent: EntityInfo = new EntityInfo(); ent.EntityName = val.TABLE_NAME; ent.Columns = []; ent.Indexes = []; ret.push(ent); - }) + }); return ret; } - async GetCoulmnsFromEntity(entities: EntityInfo[], schema: string): Promise { - let request = new MSSQL.Request(this.Connection) + async GetCoulmnsFromEntity( + entities: EntityInfo[], + schema: string + ): Promise { + 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 { - let request = new MSSQL.Request(this.Connection) + async GetIndexesFromEntity( + entities: EntityInfo[], + schema: string + ): Promise { + 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 = {}; - let 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 = []; - 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 = {}; + let 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 = []; + 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 { - let request = new MSSQL.Request(this.Connection) + async GetRelations( + entities: EntityInfo[], + schema: string + ): Promise { + 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[] = []; - 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 = {}; 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( - (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((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 { 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; } } diff --git a/src/drivers/MysqlDriver.ts b/src/drivers/MysqlDriver.ts index 023507d..74a3087 100644 --- a/src/drivers/MysqlDriver.ts +++ b/src/drivers/MysqlDriver.ts @@ -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 { - - 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[] = []; - response.forEach((val) => { + response.forEach(val => { let ent: EntityInfo = new EntityInfo(); ent.EntityName = val.TABLE_NAME; ent.Columns = []; ent.Indexes = []; ret.push(ent); - }) + }); return ret; } - async GetCoulmnsFromEntity(entities: EntityInfo[], schema: string): Promise { + async GetCoulmnsFromEntity( + entities: EntityInfo[], + schema: string + ): Promise { 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 { + async GetIndexesFromEntity( + entities: EntityInfo[], + schema: string + ): Promise { 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 = {}; - let 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 = []; - 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 = {}; + let 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 = []; + 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 { + async GetRelations( + entities: EntityInfo[], + schema: string + ): Promise { 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[] = []; - 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 = {}; 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( - (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((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((resolve, reject) => { + this.Connection = MYSQL.createConnection(config); - let promise = new Promise( - (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(`CREATE DATABASE ${dbName}; `) + let resp = await this.ExecQuery(`CREATE DATABASE ${dbName}; `); } async UseDB(dbName: string) { - let resp = await this.ExecQuery(`USE ${dbName}; `) + let resp = await this.ExecQuery(`USE ${dbName}; `); } async DropDB(dbName: string) { - let resp = await this.ExecQuery(`DROP DATABASE ${dbName}; `) + let resp = await this.ExecQuery(`DROP DATABASE ${dbName}; `); } async CheckIfDBExists(dbName: string): Promise { - let resp = await this.ExecQuery(`SHOW DATABASES LIKE '${dbName}' `) + let resp = await this.ExecQuery( + `SHOW DATABASES LIKE '${dbName}' ` + ); return resp.length > 0; } async ExecQuery(sql: string): Promise> { let ret: Array = []; let that = this; - let query = this.Connection.query(sql) + let query = this.Connection.query(sql); let stream = query.stream({}); - let promise = new Promise( - (resolve, reject) => { - stream.on('data', - chunk => { - ret.push(chunk) - }); - stream.on('end', () => resolve(true)); - }) + let promise = new Promise((resolve, reject) => { + stream.on("data", chunk => { + ret.push((chunk)); + }); + stream.on("end", () => resolve(true)); + }); await promise; return ret; } diff --git a/src/drivers/OracleDriver.ts b/src/drivers/OracleDriver.ts index b0f8d34..8a1d3f5 100644 --- a/src/drivers/OracleDriver.ts +++ b/src/drivers/OracleDriver.ts @@ -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 { - - 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[] = []; - response.forEach((val) => { + response.forEach(val => { let ent: EntityInfo = new EntityInfo(); ent.EntityName = val[0]; ent.Columns = []; ent.Indexes = []; ret.push(ent); - }) + }); return ret; } - async GetCoulmnsFromEntity(entities: EntityInfo[], schema: string): Promise { - 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 { + 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 { - 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 { + 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 = {}; - let 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 = []; - 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 = {}; + let 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 = []; + 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 { - let response: any[][] = (await this.Connection.execute(`select owner.TABLE_NAME ownTbl,ownCol.POSITION,ownCol.COLUMN_NAME, + async GetRelations( + entities: EntityInfo[], + schema: string + ): Promise { + 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[] = []; - 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 = {}; 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( - (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((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 { return true; } diff --git a/src/drivers/PostgresDriver.ts b/src/drivers/PostgresDriver.ts index d853016..59edc5b 100644 --- a/src/drivers/PostgresDriver.ts +++ b/src/drivers/PostgresDriver.ts @@ -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 { - - 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[] = []; - response.forEach((val) => { + response.forEach(val => { let ent: EntityInfo = new EntityInfo(); ent.EntityName = val.table_name; ent.Columns = []; ent.Indexes = []; ret.push(ent); - }) + }); return ret; } - async GetCoulmnsFromEntity(entities: EntityInfo[], schema: string): Promise { + async GetCoulmnsFromEntity( + entities: EntityInfo[], + schema: string + ): Promise { 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 { + async GetIndexesFromEntity( + entities: EntityInfo[], + schema: string + ): Promise { 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 = {}; - let 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 = []; - 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 = {}; + let 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 = []; + 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 { + async GetRelations( + entities: EntityInfo[], + schema: string + ): Promise { 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[] = []; - 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 = {}; 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( - (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((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( - (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((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 { - 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; } } diff --git a/src/index.ts b/src/index.ts index 52ca469..f10e48f 100644 --- a/src/index.ts +++ b/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 -d -p [port] -u -x [password] -e [engine]') - .option('h', { - alias: 'host', - describe: 'IP adress/Hostname for database server.', +var argv = Yargs.usage( + "Usage: typeorm-model-generator -h -d -p [port] -u -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.` + ); +}); diff --git a/src/models/ColumnInfo.ts b/src/models/ColumnInfo.ts index 2449bc6..fed4491 100644 --- a/src/models/ColumnInfo.ts +++ b/src/models/ColumnInfo.ts @@ -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 = []; } - } diff --git a/src/models/DatabaseModel.ts b/src/models/DatabaseModel.ts index d151d63..e3d409e 100644 --- a/src/models/DatabaseModel.ts +++ b/src/models/DatabaseModel.ts @@ -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 ""; + }; } } diff --git a/src/models/EntityInfo.ts b/src/models/EntityInfo.ts index 12d638b..265ec62 100644 --- a/src/models/EntityInfo.ts +++ b/src/models/EntityInfo.ts @@ -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); - }) + }); } - } diff --git a/src/models/IndexColumnInfo.ts b/src/models/IndexColumnInfo.ts index 5513189..7e21e55 100644 --- a/src/models/IndexColumnInfo.ts +++ b/src/models/IndexColumnInfo.ts @@ -1,5 +1,5 @@ interface IndexColumnInfo { - name: string, + name: string; //isDescending:boolean, // isIncludedColumn:boolean } diff --git a/src/models/IndexInfo.ts b/src/models/IndexInfo.ts index 3fc7540..53d13a4 100644 --- a/src/models/IndexInfo.ts +++ b/src/models/IndexInfo.ts @@ -2,8 +2,8 @@ * IndexInfo */ interface IndexInfo { - name: string, - columns: IndexColumnInfo[], - isUnique: boolean, - isPrimaryKey: boolean, + name: string; + columns: IndexColumnInfo[]; + isUnique: boolean; + isPrimaryKey: boolean; } diff --git a/src/models/RelationInfo.ts b/src/models/RelationInfo.ts index f68ffce..88dd40a 100644 --- a/src/models/RelationInfo.ts +++ b/src/models/RelationInfo.ts @@ -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"; } - } diff --git a/src/models/RelationTempInfo.ts b/src/models/RelationTempInfo.ts index 94a82ec..ecf657f 100644 --- a/src/models/RelationTempInfo.ts +++ b/src/models/RelationTempInfo.ts @@ -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; }