diff --git a/.env.example b/.env.example index 4dc7854..d71fb73 100644 --- a/.env.example +++ b/.env.example @@ -1,10 +1,22 @@ -DB_TYPE = (mysql|sqlite|...) -DB_PORT = number +DB_TYPE = (mysql|sqlite|postgres) + +## BSP für mysql +DB_PORT = 3306 DB_HOST = database_host DB_NAME = database_name DB_USERNAME = database_username DB_PASSWORD = database_password +## BSP für postgres +DB_PORT = 5432 +DB_HOST = database_host +DB_NAME = database_name +DB_USERNAME = database_username +DB_PASSWORD = database_password + +## BSP für sqlite +DB_HOST = filename.db + SERVER_PORT = portnumber JWT_SECRET = ABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890 diff --git a/.gitignore b/.gitignore index 7efd6b5..7410d05 100644 --- a/.gitignore +++ b/.gitignore @@ -132,4 +132,5 @@ dist files -.idea \ No newline at end of file +.idea +*.db \ No newline at end of file diff --git a/README.md b/README.md index 93add1a..432cc37 100644 --- a/README.md +++ b/README.md @@ -25,7 +25,7 @@ services: container_name: ff_member_administration_server restart: unless-stopped environment: - - DB_TYPE= # default ist auf mysql gesetzt + - DB_TYPE= # default ist auf mysql gesetzt - DB_HOST=ff-db - DB_PORT= # default ist auf 3306 gesetzt - DB_NAME=ffadmin @@ -44,7 +44,7 @@ services: - CLUB_WEBSITE= - BACKUP_INTERVAL= # alle x Tage, sonst keine - BACKUP_COPIES= # Anzahl parallel bestehender Backups - - BACKUP_AUTO_RESTORE= # default ist auf false gesetzt + - BACKUP_AUTO_RESTORE= # default ist auf true gesetzt volumes: - :/app/files networks: @@ -65,11 +65,27 @@ services: - :/var/lib/mysql networks: - ff_internal + # OR + image: postgres:16 + container_name: ff_db + restart: unless-stopped + environment: + - POSTGRES_DB=ffadmin + - POSTGRES_USER=administration_backend + - POSTGRES_PASSWORD= + volumes: + - :/var/lib/postgresql/data + networks: + - ff_internal networks: ff_internal: ``` +Die Verwendung von postgres wird aufgrund des Verhaltens bei Struktur-Update-Fehlern und genauerer Datum-Berechnungen empfohlen. + +Die Verwendung von SQLite wird nur für die Entwicklung oder lokale Tests empfohlen. + Führen Sie dann den folgenden Befehl im Verzeichnis der compose-Datei aus, um den Container zu starten: ```sh diff --git a/package-lock.json b/package-lock.json index 39f6b73..75ebbc6 100644 --- a/package-lock.json +++ b/package-lock.json @@ -28,6 +28,7 @@ "rss-parser": "^3.13.0", "socket.io": "^4.7.5", "speakeasy": "^2.0.0", + "sqlite3": "^5.1.7", "typeorm": "^0.3.20", "uuid": "^10.0.0" }, @@ -92,6 +93,13 @@ "node": ">=12" } }, + "node_modules/@gar/promisify": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/@gar/promisify/-/promisify-1.1.3.tgz", + "integrity": "sha512-k2Ty1JcVojjJFwrg/ThKi2ujJ7XNLYaFGNB/bWT9wGR+oSMJHMa5w+CUq6p/pVrKeNNgA7pCqEcjSnHVoqJQFw==", + "license": "MIT", + "optional": true + }, "node_modules/@isaacs/cliui": { "version": "8.0.2", "resolved": "https://registry.npmjs.org/@isaacs/cliui/-/cliui-8.0.2.tgz", @@ -181,6 +189,45 @@ "url": "https://github.com/chalk/wrap-ansi?sponsor=1" } }, + "node_modules/@npmcli/fs": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@npmcli/fs/-/fs-1.1.1.tgz", + "integrity": "sha512-8KG5RD0GVP4ydEzRn/I4BNDuxDtqVbOdm8675T49OIG/NGhaK0pjPX7ZcDlvKYbA+ulvVK3ztfcF4uBdOxuJbQ==", + "license": "ISC", + "optional": true, + "dependencies": { + "@gar/promisify": "^1.0.1", + "semver": "^7.3.5" + } + }, + "node_modules/@npmcli/move-file": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@npmcli/move-file/-/move-file-1.1.2.tgz", + "integrity": "sha512-1SUf/Cg2GzGDyaf15aR9St9TWlb+XvbZXWpDx8YKs7MLzMH/BCeopv+y9vzrzgkfykCGuWOlSu3mZhj2+FQcrg==", + "deprecated": "This functionality has been moved to @npmcli/fs", + "license": "MIT", + "optional": true, + "dependencies": { + "mkdirp": "^1.0.4", + "rimraf": "^3.0.2" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/@npmcli/move-file/node_modules/mkdirp": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz", + "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==", + "license": "MIT", + "optional": true, + "bin": { + "mkdirp": "bin/cmd.js" + }, + "engines": { + "node": ">=10" + } + }, "node_modules/@pdf-lib/standard-fonts": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/@pdf-lib/standard-fonts/-/standard-fonts-1.0.0.tgz", @@ -378,6 +425,16 @@ "resolved": "https://registry.npmjs.org/@sqltools/formatter/-/formatter-1.2.5.tgz", "integrity": "sha512-Uy0+khmZqUrUGm5dmMqVlnvufZRSK0FbYzVgp0UMstm+F5+W2/jnEEQyc9vo1ZR/E5ZI/B1WjjoTqBqwJL6Krw==" }, + "node_modules/@tootallnate/once": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@tootallnate/once/-/once-1.1.2.tgz", + "integrity": "sha512-RbzJvlNzmRq5c3O09UipeuXno4tA1FE6ikOjxZK0tuxVv3412l64l5t1W5pj4+rJq9vpkm/kwiR07aZXnsKPxw==", + "license": "MIT", + "optional": true, + "engines": { + "node": ">= 6" + } + }, "node_modules/@tootallnate/quickjs-emscripten": { "version": "0.23.0", "resolved": "https://registry.npmjs.org/@tootallnate/quickjs-emscripten/-/quickjs-emscripten-0.23.0.tgz", @@ -610,6 +667,13 @@ "@types/node": "*" } }, + "node_modules/abbrev": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.1.1.tgz", + "integrity": "sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==", + "license": "ISC", + "optional": true + }, "node_modules/accepts": { "version": "1.3.8", "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.8.tgz", @@ -655,6 +719,33 @@ "node": ">= 14" } }, + "node_modules/agentkeepalive": { + "version": "4.6.0", + "resolved": "https://registry.npmjs.org/agentkeepalive/-/agentkeepalive-4.6.0.tgz", + "integrity": "sha512-kja8j7PjmncONqaTsB8fQ+wE2mSU2DJ9D4XKoJ5PFWIdRMa6SLSN1ff4mOr4jCbfRSsxR4keIiySJU0N9T5hIQ==", + "license": "MIT", + "optional": true, + "dependencies": { + "humanize-ms": "^1.2.1" + }, + "engines": { + "node": ">= 8.0.0" + } + }, + "node_modules/aggregate-error": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/aggregate-error/-/aggregate-error-3.1.0.tgz", + "integrity": "sha512-4I7Td01quW/RpocfNayFdFVk1qSuoh0E7JrbRJ16nH01HhKFQ88INq9Sd+nd72zqRySlr9BmDA8xlEJ6vJMrYA==", + "license": "MIT", + "optional": true, + "dependencies": { + "clean-stack": "^2.0.0", + "indent-string": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, "node_modules/ansi-regex": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", @@ -690,6 +781,43 @@ "node": ">= 6.0.0" } }, + "node_modules/aproba": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/aproba/-/aproba-2.0.0.tgz", + "integrity": "sha512-lYe4Gx7QT+MKGbDsA+Z+he/Wtef0BiwDOlK/XkBrdfsh9J/jPPXbX0tE9x9cl27Tmu5gg3QUbUrQYa/y+KOHPQ==", + "license": "ISC", + "optional": true + }, + "node_modules/are-we-there-yet": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/are-we-there-yet/-/are-we-there-yet-3.0.1.tgz", + "integrity": "sha512-QZW4EDmGwlYur0Yyf/b2uGucHQMa8aFUP7eu9ddR73vvhFyt4V0Vl3QHPcTNJ8l6qYOBdxgXdnBXQrHilfRQBg==", + "deprecated": "This package is no longer supported.", + "license": "ISC", + "optional": true, + "dependencies": { + "delegates": "^1.0.0", + "readable-stream": "^3.6.0" + }, + "engines": { + "node": "^12.13.0 || ^14.15.0 || >=16.0.0" + } + }, + "node_modules/are-we-there-yet/node_modules/readable-stream": { + "version": "3.6.2", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", + "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", + "license": "MIT", + "optional": true, + "dependencies": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + }, + "engines": { + "node": ">= 6" + } + }, "node_modules/arg": { "version": "4.1.3", "resolved": "https://registry.npmjs.org/arg/-/arg-4.1.3.tgz", @@ -842,8 +970,6 @@ "version": "1.5.0", "resolved": "https://registry.npmjs.org/bindings/-/bindings-1.5.0.tgz", "integrity": "sha512-p2q/t/mhvuOj/UeLlV6566GD/guowlr0hHxClI0W9m7MWYkL1F0hLo+0Aexs9HSPCtR1SXQ0TD3MMKrXZajbiQ==", - "optional": true, - "peer": true, "dependencies": { "file-uri-to-path": "1.0.0" } @@ -852,8 +978,6 @@ "version": "4.1.0", "resolved": "https://registry.npmjs.org/bl/-/bl-4.1.0.tgz", "integrity": "sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w==", - "optional": true, - "peer": true, "dependencies": { "buffer": "^5.5.0", "inherits": "^2.0.4", @@ -878,8 +1002,6 @@ "url": "https://feross.org/support" } ], - "optional": true, - "peer": true, "dependencies": { "base64-js": "^1.3.1", "ieee754": "^1.1.13" @@ -889,8 +1011,6 @@ "version": "3.6.2", "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", - "optional": true, - "peer": true, "dependencies": { "inherits": "^2.0.3", "string_decoder": "^1.1.1", @@ -989,6 +1109,131 @@ "node": ">= 0.8" } }, + "node_modules/cacache": { + "version": "15.3.0", + "resolved": "https://registry.npmjs.org/cacache/-/cacache-15.3.0.tgz", + "integrity": "sha512-VVdYzXEn+cnbXpFgWs5hTT7OScegHVmLhJIR8Ufqk3iFD6A6j5iSX1KuBTfNEv4tdJWE2PzA6IVFtcLC7fN9wQ==", + "license": "ISC", + "optional": true, + "dependencies": { + "@npmcli/fs": "^1.0.0", + "@npmcli/move-file": "^1.0.1", + "chownr": "^2.0.0", + "fs-minipass": "^2.0.0", + "glob": "^7.1.4", + "infer-owner": "^1.0.4", + "lru-cache": "^6.0.0", + "minipass": "^3.1.1", + "minipass-collect": "^1.0.2", + "minipass-flush": "^1.0.5", + "minipass-pipeline": "^1.2.2", + "mkdirp": "^1.0.3", + "p-map": "^4.0.0", + "promise-inflight": "^1.0.1", + "rimraf": "^3.0.2", + "ssri": "^8.0.1", + "tar": "^6.0.2", + "unique-filename": "^1.1.1" + }, + "engines": { + "node": ">= 10" + } + }, + "node_modules/cacache/node_modules/brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "license": "MIT", + "optional": true, + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/cacache/node_modules/chownr": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/chownr/-/chownr-2.0.0.tgz", + "integrity": "sha512-bIomtDF5KGpdogkLd9VspvFzk9KfpyyGlS8YFVZl7TGPBHL5snIOnxeshwVgPteQ9b4Eydl+pVbIyE1DcvCWgQ==", + "license": "ISC", + "optional": true, + "engines": { + "node": ">=10" + } + }, + "node_modules/cacache/node_modules/glob": { + "version": "7.2.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", + "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", + "deprecated": "Glob versions prior to v9 are no longer supported", + "license": "ISC", + "optional": true, + "dependencies": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.1.1", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + }, + "engines": { + "node": "*" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/cacache/node_modules/lru-cache": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", + "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", + "license": "ISC", + "optional": true, + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/cacache/node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "license": "ISC", + "optional": true, + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/cacache/node_modules/minipass": { + "version": "3.3.6", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz", + "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", + "license": "ISC", + "optional": true, + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/cacache/node_modules/mkdirp": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz", + "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==", + "license": "MIT", + "optional": true, + "bin": { + "mkdirp": "bin/cmd.js" + }, + "engines": { + "node": ">=10" + } + }, "node_modules/call-bind": { "version": "1.0.7", "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.7.tgz", @@ -1042,9 +1287,7 @@ "node_modules/chownr": { "version": "1.1.4", "resolved": "https://registry.npmjs.org/chownr/-/chownr-1.1.4.tgz", - "integrity": "sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg==", - "optional": true, - "peer": true + "integrity": "sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg==" }, "node_modules/chromium-bidi": { "version": "0.11.0", @@ -1059,6 +1302,16 @@ "devtools-protocol": "*" } }, + "node_modules/clean-stack": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/clean-stack/-/clean-stack-2.2.0.tgz", + "integrity": "sha512-4diC9HaTE+KRAMWhDhrGOECgWZxoevMc5TlkObMqNSsVU62PYzXZ/SMTjzyGAFF1YusgxGcSWTEXBhp0CPwQ1A==", + "license": "MIT", + "optional": true, + "engines": { + "node": ">=6" + } + }, "node_modules/cli-highlight": { "version": "2.1.11", "resolved": "https://registry.npmjs.org/cli-highlight/-/cli-highlight-2.1.11.tgz", @@ -1164,6 +1417,30 @@ "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==" }, + "node_modules/color-support": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-support/-/color-support-1.1.3.tgz", + "integrity": "sha512-qiBjkpbMLO/HL68y+lh4q0/O1MZFj2RX6X/KmMa3+gJD3z+WwI1ZzDHysvqHGS3mP6mznPckpXmw1nI9cJjyRg==", + "license": "ISC", + "optional": true, + "bin": { + "color-support": "bin.js" + } + }, + "node_modules/concat-map": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==", + "license": "MIT", + "optional": true + }, + "node_modules/console-control-strings": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/console-control-strings/-/console-control-strings-1.1.0.tgz", + "integrity": "sha512-ty/fTekppD2fIwRvnZAVdeOiGd1c7YXEixbgJTNzqcxJWKQnjJ/V1bNEEE6hygpM3WjwHFUVK6HTjWSzV4a8sQ==", + "license": "ISC", + "optional": true + }, "node_modules/content-disposition": { "version": "0.5.4", "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.4.tgz", @@ -1309,8 +1586,6 @@ "version": "6.0.0", "resolved": "https://registry.npmjs.org/decompress-response/-/decompress-response-6.0.0.tgz", "integrity": "sha512-aW35yZM6Bb/4oJlZncMH2LCoZtJXTRxES17vE3hoRiowU2kWHaJKFkSBDnDR+cm9J+9QhXmREyIfv0pji9ejCQ==", - "optional": true, - "peer": true, "dependencies": { "mimic-response": "^3.1.0" }, @@ -1325,8 +1600,6 @@ "version": "0.6.0", "resolved": "https://registry.npmjs.org/deep-extend/-/deep-extend-0.6.0.tgz", "integrity": "sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA==", - "optional": true, - "peer": true, "engines": { "node": ">=4.0.0" } @@ -1361,6 +1634,13 @@ "node": ">= 14" } }, + "node_modules/delegates": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delegates/-/delegates-1.0.0.tgz", + "integrity": "sha512-bd2L678uiWATM6m5Z1VzNCErI3jiGzt6HGY8OVICs40JQq/HALfbyNJmp0UDakEY4pMMaN0Ly5om/B1VI/+xfQ==", + "license": "MIT", + "optional": true + }, "node_modules/depd": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz", @@ -1382,8 +1662,6 @@ "version": "2.0.3", "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.0.3.tgz", "integrity": "sha512-bwy0MGW55bG41VqxxypOsdSdGqLwXPI/focwgTYCFMbdUiBAxLg9CFzG08sz2aqzknwiX7Hkl0bQENjg8iLByw==", - "optional": true, - "peer": true, "engines": { "node": ">=8" } @@ -1451,6 +1729,29 @@ "node": ">= 0.8" } }, + "node_modules/encoding": { + "version": "0.1.13", + "resolved": "https://registry.npmjs.org/encoding/-/encoding-0.1.13.tgz", + "integrity": "sha512-ETBauow1T35Y/WZMkio9jiM0Z5xjHHmJ4XmjZOq1l/dXz3lr2sRn87nJy20RupqSh1F2m3HHPSp8ShIPQJrJ3A==", + "license": "MIT", + "optional": true, + "dependencies": { + "iconv-lite": "^0.6.2" + } + }, + "node_modules/encoding/node_modules/iconv-lite": { + "version": "0.6.3", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.3.tgz", + "integrity": "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==", + "license": "MIT", + "optional": true, + "dependencies": { + "safer-buffer": ">= 2.1.2 < 3.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/end-of-stream": { "version": "1.4.4", "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.4.tgz", @@ -1534,6 +1835,13 @@ "node": ">=6" } }, + "node_modules/err-code": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/err-code/-/err-code-2.0.3.tgz", + "integrity": "sha512-2bmlRpNKBxT/CRmPOlyISQpNj+qSeYvcym/uT0Jx2bMOlKLtSy1ZmLuVxSEKKyor/N5yhvp/ZiG1oE3DEYMSFA==", + "license": "MIT", + "optional": true + }, "node_modules/error-ex": { "version": "1.3.2", "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz", @@ -1639,8 +1947,6 @@ "version": "2.0.3", "resolved": "https://registry.npmjs.org/expand-template/-/expand-template-2.0.3.tgz", "integrity": "sha512-XYfuKMvj4O35f/pOXLObndIRvyQ+/+6AhODh+OKWj9S9498pHHn/IMszH+gt0fBCRWMNfk1ZSp5x3AifmnI2vg==", - "optional": true, - "peer": true, "engines": { "node": ">=6" } @@ -1720,9 +2026,7 @@ "node_modules/file-uri-to-path": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/file-uri-to-path/-/file-uri-to-path-1.0.0.tgz", - "integrity": "sha512-0Zt+s3L7Vf1biwWZ29aARiVYLx7iMGnEUl9x33fbB/j3jR81u/O2LbqK+Bm1CDSNDKVtJ/YjwY7TUd5SkeLQLw==", - "optional": true, - "peer": true + "integrity": "sha512-0Zt+s3L7Vf1biwWZ29aARiVYLx7iMGnEUl9x33fbB/j3jR81u/O2LbqK+Bm1CDSNDKVtJ/YjwY7TUd5SkeLQLw==" }, "node_modules/finalhandler": { "version": "1.2.0", @@ -1787,9 +2091,38 @@ "node_modules/fs-constants": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/fs-constants/-/fs-constants-1.0.0.tgz", - "integrity": "sha512-y6OAwoSIf7FyjMIv94u+b5rdheZEjzR63GTyZJm5qh4Bi+2YgwLCcI/fPFZkL5PSixOt6ZNKm+w+Hfp/Bciwow==", - "optional": true, - "peer": true + "integrity": "sha512-y6OAwoSIf7FyjMIv94u+b5rdheZEjzR63GTyZJm5qh4Bi+2YgwLCcI/fPFZkL5PSixOt6ZNKm+w+Hfp/Bciwow==" + }, + "node_modules/fs-minipass": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/fs-minipass/-/fs-minipass-2.1.0.tgz", + "integrity": "sha512-V/JgOLFCS+R6Vcq0slCuaeWEdNC3ouDlJMNIsacH2VtALiu9mV4LPrHc5cDl8k5aw6J8jwgWWpiTo5RYhmIzvg==", + "license": "ISC", + "dependencies": { + "minipass": "^3.0.0" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/fs-minipass/node_modules/minipass": { + "version": "3.3.6", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz", + "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", + "license": "ISC", + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/fs.realpath": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", + "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==", + "license": "ISC", + "optional": true }, "node_modules/function-bind": { "version": "1.1.2", @@ -1799,6 +2132,34 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/gauge": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/gauge/-/gauge-4.0.4.tgz", + "integrity": "sha512-f9m+BEN5jkg6a0fZjleidjN51VE1X+mPFQ2DJ0uv1V39oCLCbsGe6yjbBnp7eK7z/+GAon99a3nHuqbuuthyPg==", + "deprecated": "This package is no longer supported.", + "license": "ISC", + "optional": true, + "dependencies": { + "aproba": "^1.0.3 || ^2.0.0", + "color-support": "^1.1.3", + "console-control-strings": "^1.1.0", + "has-unicode": "^2.0.1", + "signal-exit": "^3.0.7", + "string-width": "^4.2.3", + "strip-ansi": "^6.0.1", + "wide-align": "^1.1.5" + }, + "engines": { + "node": "^12.13.0 || ^14.15.0 || >=16.0.0" + } + }, + "node_modules/gauge/node_modules/signal-exit": { + "version": "3.0.7", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", + "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==", + "license": "ISC", + "optional": true + }, "node_modules/get-caller-file": { "version": "2.0.5", "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", @@ -1874,9 +2235,7 @@ "node_modules/github-from-package": { "version": "0.0.0", "resolved": "https://registry.npmjs.org/github-from-package/-/github-from-package-0.0.0.tgz", - "integrity": "sha512-SyHy3T1v2NUXn29OsWdxmK6RwHD+vkj3v8en8AOBZ1wBQ/hCAQ5bAQTD02kW4W9tUp/3Qh6J8r9EvntiyCmOOw==", - "optional": true, - "peer": true + "integrity": "sha512-SyHy3T1v2NUXn29OsWdxmK6RwHD+vkj3v8en8AOBZ1wBQ/hCAQ5bAQTD02kW4W9tUp/3Qh6J8r9EvntiyCmOOw==" }, "node_modules/glob": { "version": "10.4.5", @@ -1908,6 +2267,13 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/graceful-fs": { + "version": "4.2.11", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz", + "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==", + "license": "ISC", + "optional": true + }, "node_modules/handlebars": { "version": "4.7.8", "resolved": "https://registry.npmjs.org/handlebars/-/handlebars-4.7.8.tgz", @@ -1970,6 +2336,13 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/has-unicode": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/has-unicode/-/has-unicode-2.0.1.tgz", + "integrity": "sha512-8Rf9Y83NBReMnx0gFzA8JImQACstCYWUplepDa9xprwwtmgEZUF0h/i5xSA625zB/I37EtrswSST6OXxwaaIJQ==", + "license": "ISC", + "optional": true + }, "node_modules/hasown": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz", @@ -1989,6 +2362,13 @@ "node": "*" } }, + "node_modules/http-cache-semantics": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/http-cache-semantics/-/http-cache-semantics-4.1.1.tgz", + "integrity": "sha512-er295DKPVsV82j5kw1Gjt+ADA/XYHsajl82cGNQG2eyoPkvgUhX+nDIyelzhIWbbsXP39EHcI6l5tYs2FYqYXQ==", + "license": "BSD-2-Clause", + "optional": true + }, "node_modules/http-errors": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.0.tgz", @@ -2064,6 +2444,16 @@ } } }, + "node_modules/humanize-ms": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/humanize-ms/-/humanize-ms-1.2.1.tgz", + "integrity": "sha512-Fl70vYtsAFb/C06PTS9dZBo7ihau+Tu/DNCk/OyHhea07S+aeMWpFFkUaXRa8fI+ScZbEI8dfSxwY7gxZ9SAVQ==", + "license": "MIT", + "optional": true, + "dependencies": { + "ms": "^2.0.0" + } + }, "node_modules/iconv-lite": { "version": "0.5.2", "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.5.2.tgz", @@ -2121,6 +2511,45 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/imurmurhash": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", + "integrity": "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==", + "license": "MIT", + "optional": true, + "engines": { + "node": ">=0.8.19" + } + }, + "node_modules/indent-string": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-4.0.0.tgz", + "integrity": "sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg==", + "license": "MIT", + "optional": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/infer-owner": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/infer-owner/-/infer-owner-1.0.4.tgz", + "integrity": "sha512-IClj+Xz94+d7irH5qRyfJonOdfTzuDaifE6ZPWfx0N0+/ATZCbuTPq2prFl526urkQd90WyUKIh1DfBQ2hMz9A==", + "license": "ISC", + "optional": true + }, + "node_modules/inflight": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", + "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==", + "deprecated": "This module is not supported, and leaks memory. Do not use it. Check out lru-cache if you want a good and tested way to coalesce async requests by a key value, which is much more comprehensive and powerful.", + "license": "ISC", + "optional": true, + "dependencies": { + "once": "^1.3.0", + "wrappy": "1" + } + }, "node_modules/inherits": { "version": "2.0.4", "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", @@ -2129,9 +2558,7 @@ "node_modules/ini": { "version": "1.3.8", "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.8.tgz", - "integrity": "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==", - "optional": true, - "peer": true + "integrity": "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==" }, "node_modules/ip-address": { "version": "9.0.5", @@ -2174,6 +2601,13 @@ "node": ">=8" } }, + "node_modules/is-lambda": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-lambda/-/is-lambda-1.0.1.tgz", + "integrity": "sha512-z7CMFGNrENq5iFB9Bqo64Xk6Y9sg+epq1myIcdHaGnbMTYOxvzsEtdYqQUylB7LxfkvgrrjP32T6Ywciio9UIQ==", + "license": "MIT", + "optional": true + }, "node_modules/is-promise": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/is-promise/-/is-promise-4.0.0.tgz", @@ -2359,6 +2793,135 @@ "integrity": "sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw==", "devOptional": true }, + "node_modules/make-fetch-happen": { + "version": "9.1.0", + "resolved": "https://registry.npmjs.org/make-fetch-happen/-/make-fetch-happen-9.1.0.tgz", + "integrity": "sha512-+zopwDy7DNknmwPQplem5lAZX/eCOzSvSNNcSKm5eVwTkOBzoktEfXsa9L23J/GIRhxRsaxzkPEhrJEpE2F4Gg==", + "license": "ISC", + "optional": true, + "dependencies": { + "agentkeepalive": "^4.1.3", + "cacache": "^15.2.0", + "http-cache-semantics": "^4.1.0", + "http-proxy-agent": "^4.0.1", + "https-proxy-agent": "^5.0.0", + "is-lambda": "^1.0.1", + "lru-cache": "^6.0.0", + "minipass": "^3.1.3", + "minipass-collect": "^1.0.2", + "minipass-fetch": "^1.3.2", + "minipass-flush": "^1.0.5", + "minipass-pipeline": "^1.2.4", + "negotiator": "^0.6.2", + "promise-retry": "^2.0.1", + "socks-proxy-agent": "^6.0.0", + "ssri": "^8.0.0" + }, + "engines": { + "node": ">= 10" + } + }, + "node_modules/make-fetch-happen/node_modules/agent-base": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz", + "integrity": "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==", + "license": "MIT", + "optional": true, + "dependencies": { + "debug": "4" + }, + "engines": { + "node": ">= 6.0.0" + } + }, + "node_modules/make-fetch-happen/node_modules/debug": { + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.0.tgz", + "integrity": "sha512-6WTZ/IxCY/T6BALoZHaE4ctp9xm+Z5kY/pzYaCHRFeyVhojxlrm+46y68HA6hr0TcwEssoxNiDEUJQjfPZ/RYA==", + "license": "MIT", + "optional": true, + "dependencies": { + "ms": "^2.1.3" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/make-fetch-happen/node_modules/http-proxy-agent": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-4.0.1.tgz", + "integrity": "sha512-k0zdNgqWTGA6aeIRVpvfVob4fL52dTfaehylg0Y4UvSySvOq/Y+BOyPrgpUrA7HylqvU8vIZGsRuXmspskV0Tg==", + "license": "MIT", + "optional": true, + "dependencies": { + "@tootallnate/once": "1", + "agent-base": "6", + "debug": "4" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/make-fetch-happen/node_modules/https-proxy-agent": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.1.tgz", + "integrity": "sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA==", + "license": "MIT", + "optional": true, + "dependencies": { + "agent-base": "6", + "debug": "4" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/make-fetch-happen/node_modules/lru-cache": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", + "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", + "license": "ISC", + "optional": true, + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/make-fetch-happen/node_modules/minipass": { + "version": "3.3.6", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz", + "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", + "license": "ISC", + "optional": true, + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/make-fetch-happen/node_modules/socks-proxy-agent": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/socks-proxy-agent/-/socks-proxy-agent-6.2.1.tgz", + "integrity": "sha512-a6KW9G+6B3nWZ1yB8G7pJwL3ggLy1uTzKAgCb7ttblwqdz9fMGJUuTy3uFzEP48FAs9FLILlmzDlE2JJhVQaXQ==", + "license": "MIT", + "optional": true, + "dependencies": { + "agent-base": "^6.0.2", + "debug": "^4.3.3", + "socks": "^2.6.2" + }, + "engines": { + "node": ">= 10" + } + }, "node_modules/media-typer": { "version": "0.3.0", "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", @@ -2403,8 +2966,6 @@ "version": "3.1.0", "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-3.1.0.tgz", "integrity": "sha512-z0yWI+4FDrrweS8Zmt4Ej5HdJmky15+L2e6Wgn3+iK5fWzb6T3fhNFq2+MeTRb064c6Wr4N/wv0DzQTjNzHNGQ==", - "optional": true, - "peer": true, "engines": { "node": ">=10" }, @@ -2442,6 +3003,166 @@ "node": ">=16 || 14 >=14.17" } }, + "node_modules/minipass-collect": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/minipass-collect/-/minipass-collect-1.0.2.tgz", + "integrity": "sha512-6T6lH0H8OG9kITm/Jm6tdooIbogG9e0tLgpY6mphXSm/A9u8Nq1ryBG+Qspiub9LjWlBPsPS3tWQ/Botq4FdxA==", + "license": "ISC", + "optional": true, + "dependencies": { + "minipass": "^3.0.0" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/minipass-collect/node_modules/minipass": { + "version": "3.3.6", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz", + "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", + "license": "ISC", + "optional": true, + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/minipass-fetch": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/minipass-fetch/-/minipass-fetch-1.4.1.tgz", + "integrity": "sha512-CGH1eblLq26Y15+Azk7ey4xh0J/XfJfrCox5LDJiKqI2Q2iwOLOKrlmIaODiSQS8d18jalF6y2K2ePUm0CmShw==", + "license": "MIT", + "optional": true, + "dependencies": { + "minipass": "^3.1.0", + "minipass-sized": "^1.0.3", + "minizlib": "^2.0.0" + }, + "engines": { + "node": ">=8" + }, + "optionalDependencies": { + "encoding": "^0.1.12" + } + }, + "node_modules/minipass-fetch/node_modules/minipass": { + "version": "3.3.6", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz", + "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", + "license": "ISC", + "optional": true, + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/minipass-flush": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/minipass-flush/-/minipass-flush-1.0.5.tgz", + "integrity": "sha512-JmQSYYpPUqX5Jyn1mXaRwOda1uQ8HP5KAT/oDSLCzt1BYRhQU0/hDtsB1ufZfEEzMZ9aAVmsBw8+FWsIXlClWw==", + "license": "ISC", + "optional": true, + "dependencies": { + "minipass": "^3.0.0" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/minipass-flush/node_modules/minipass": { + "version": "3.3.6", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz", + "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", + "license": "ISC", + "optional": true, + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/minipass-pipeline": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/minipass-pipeline/-/minipass-pipeline-1.2.4.tgz", + "integrity": "sha512-xuIq7cIOt09RPRJ19gdi4b+RiNvDFYe5JH+ggNvBqGqpQXcru3PcRmOZuHBKWK1Txf9+cQ+HMVN4d6z46LZP7A==", + "license": "ISC", + "optional": true, + "dependencies": { + "minipass": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/minipass-pipeline/node_modules/minipass": { + "version": "3.3.6", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz", + "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", + "license": "ISC", + "optional": true, + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/minipass-sized": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/minipass-sized/-/minipass-sized-1.0.3.tgz", + "integrity": "sha512-MbkQQ2CTiBMlA2Dm/5cY+9SWFEN8pzzOXi6rlM5Xxq0Yqbda5ZQy9sU75a673FE9ZK0Zsbr6Y5iP6u9nktfg2g==", + "license": "ISC", + "optional": true, + "dependencies": { + "minipass": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/minipass-sized/node_modules/minipass": { + "version": "3.3.6", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz", + "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", + "license": "ISC", + "optional": true, + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/minizlib": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/minizlib/-/minizlib-2.1.2.tgz", + "integrity": "sha512-bAxsR8BVfj60DWXHE3u30oHzfl4G7khkSuPW+qvpd7jFRHm7dLxOjUk1EHACJ/hxLY8phGJ0YhYHZo7jil7Qdg==", + "license": "MIT", + "dependencies": { + "minipass": "^3.0.0", + "yallist": "^4.0.0" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/minizlib/node_modules/minipass": { + "version": "3.3.6", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz", + "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", + "license": "ISC", + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, "node_modules/mitt": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/mitt/-/mitt-3.0.1.tgz", @@ -2465,9 +3186,7 @@ "node_modules/mkdirp-classic": { "version": "0.5.3", "resolved": "https://registry.npmjs.org/mkdirp-classic/-/mkdirp-classic-0.5.3.tgz", - "integrity": "sha512-gKLcREMhtuZRwRAfqP3RFW+TK4JqApVBtOIftVgjuABpAtpxhPGaDcfvbhNvD0B8iD1oUr/txX35NjcaY6Ns/A==", - "optional": true, - "peer": true + "integrity": "sha512-gKLcREMhtuZRwRAfqP3RFW+TK4JqApVBtOIftVgjuABpAtpxhPGaDcfvbhNvD0B8iD1oUr/txX35NjcaY6Ns/A==" }, "node_modules/moment": { "version": "2.30.1", @@ -2534,9 +3253,7 @@ "node_modules/napi-build-utils": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/napi-build-utils/-/napi-build-utils-1.0.2.tgz", - "integrity": "sha512-ONmRUqK7zj7DWX0D9ADe03wbwOBZxNAfF20PlGfCWQcD3+/MakShIHrMqx9YwPTfxDdF1zLeL+RGZiR9kGMLdg==", - "optional": true, - "peer": true + "integrity": "sha512-ONmRUqK7zj7DWX0D9ADe03wbwOBZxNAfF20PlGfCWQcD3+/MakShIHrMqx9YwPTfxDdF1zLeL+RGZiR9kGMLdg==" }, "node_modules/negotiator": { "version": "0.6.3", @@ -2565,8 +3282,6 @@ "version": "3.65.0", "resolved": "https://registry.npmjs.org/node-abi/-/node-abi-3.65.0.tgz", "integrity": "sha512-ThjYBfoDNr08AWx6hGaRbfPwxKV9kVzAzOzlLKbk2CuqXE2xnCh+cbAGnwM3t8Lq4v9rUB7VfondlkBckcJrVA==", - "optional": true, - "peer": true, "dependencies": { "semver": "^7.3.5" }, @@ -2574,6 +3289,83 @@ "node": ">=10" } }, + "node_modules/node-addon-api": { + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-7.1.1.tgz", + "integrity": "sha512-5m3bsyrjFWE1xf7nz7YXdN4udnVtXK6/Yfgn5qnahL6bCkf2yKt4k3nuTKAtT4r3IG8JNR2ncsIMdZuAzJjHQQ==", + "license": "MIT" + }, + "node_modules/node-gyp": { + "version": "8.4.1", + "resolved": "https://registry.npmjs.org/node-gyp/-/node-gyp-8.4.1.tgz", + "integrity": "sha512-olTJRgUtAb/hOXG0E93wZDs5YiJlgbXxTwQAFHyNlRsXQnYzUaF2aGgujZbw+hR8aF4ZG/rST57bWMWD16jr9w==", + "license": "MIT", + "optional": true, + "dependencies": { + "env-paths": "^2.2.0", + "glob": "^7.1.4", + "graceful-fs": "^4.2.6", + "make-fetch-happen": "^9.1.0", + "nopt": "^5.0.0", + "npmlog": "^6.0.0", + "rimraf": "^3.0.2", + "semver": "^7.3.5", + "tar": "^6.1.2", + "which": "^2.0.2" + }, + "bin": { + "node-gyp": "bin/node-gyp.js" + }, + "engines": { + "node": ">= 10.12.0" + } + }, + "node_modules/node-gyp/node_modules/brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "license": "MIT", + "optional": true, + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/node-gyp/node_modules/glob": { + "version": "7.2.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", + "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", + "deprecated": "Glob versions prior to v9 are no longer supported", + "license": "ISC", + "optional": true, + "dependencies": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.1.1", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + }, + "engines": { + "node": "*" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/node-gyp/node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "license": "ISC", + "optional": true, + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, "node_modules/node-schedule": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/node-schedule/-/node-schedule-2.1.1.tgz", @@ -2595,6 +3387,39 @@ "node": ">=6.0.0" } }, + "node_modules/nopt": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/nopt/-/nopt-5.0.0.tgz", + "integrity": "sha512-Tbj67rffqceeLpcRXrT7vKAN8CwfPeIBgM7E6iBkmKLV7bEMwpGgYLGv0jACUsECaa/vuxP0IjEont6umdMgtQ==", + "license": "ISC", + "optional": true, + "dependencies": { + "abbrev": "1" + }, + "bin": { + "nopt": "bin/nopt.js" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/npmlog": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/npmlog/-/npmlog-6.0.2.tgz", + "integrity": "sha512-/vBvz5Jfr9dT/aFWd0FIRf+T/Q2WBsLENygUaFUqstqsycmZAP/t5BvFJTK0viFmSUxiUKTUplWy5vt+rvKIxg==", + "deprecated": "This package is no longer supported.", + "license": "ISC", + "optional": true, + "dependencies": { + "are-we-there-yet": "^3.0.0", + "console-control-strings": "^1.1.0", + "gauge": "^4.0.3", + "set-blocking": "^2.0.0" + }, + "engines": { + "node": "^12.13.0 || ^14.15.0 || >=16.0.0" + } + }, "node_modules/object-assign": { "version": "4.1.1", "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", @@ -2658,6 +3483,22 @@ "node": ">=8" } }, + "node_modules/p-map": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/p-map/-/p-map-4.0.0.tgz", + "integrity": "sha512-/bjOqmgETBYB5BoEeGVea8dmvHb2m9GLy1E9W43yeyfP6QQCZGFNa+XRceJEuDB6zqr+gKpIAmlLebMpykw/MQ==", + "license": "MIT", + "optional": true, + "dependencies": { + "aggregate-error": "^3.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/p-try": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", @@ -2868,8 +3709,6 @@ "version": "7.1.2", "resolved": "https://registry.npmjs.org/prebuild-install/-/prebuild-install-7.1.2.tgz", "integrity": "sha512-UnNke3IQb6sgarcZIDU3gbMeTp/9SSU1DAIkil7PrqG1vZlBtY5msYccSKSHDqa3hNg436IXK+SNImReuA1wEQ==", - "optional": true, - "peer": true, "dependencies": { "detect-libc": "^2.0.0", "expand-template": "^2.0.3", @@ -2896,6 +3735,27 @@ "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==" }, + "node_modules/promise-inflight": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/promise-inflight/-/promise-inflight-1.0.1.tgz", + "integrity": "sha512-6zWPyEOFaQBJYcGMHBKTKJ3u6TBsnMFOIZSa6ce1e/ZrrsOlnHRHbabMjLiBYKp+n44X9eUI6VUPaukCXHuG4g==", + "license": "ISC", + "optional": true + }, + "node_modules/promise-retry": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/promise-retry/-/promise-retry-2.0.1.tgz", + "integrity": "sha512-y+WKFlBR8BGXnsNlIHFGPZmyDf3DFMoLhaflAnyZgV6rG6xu+JwesTo2Q9R6XwYmtmwAFCkAk3e35jEdoeh/3g==", + "license": "MIT", + "optional": true, + "dependencies": { + "err-code": "^2.0.2", + "retry": "^0.12.0" + }, + "engines": { + "node": ">=10" + } + }, "node_modules/property-expr": { "version": "2.0.6", "resolved": "https://registry.npmjs.org/property-expr/-/property-expr-2.0.6.tgz", @@ -3112,8 +3972,6 @@ "version": "1.2.8", "resolved": "https://registry.npmjs.org/rc/-/rc-1.2.8.tgz", "integrity": "sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw==", - "optional": true, - "peer": true, "dependencies": { "deep-extend": "^0.6.0", "ini": "~1.3.0", @@ -3170,6 +4028,79 @@ "node": ">=4" } }, + "node_modules/retry": { + "version": "0.12.0", + "resolved": "https://registry.npmjs.org/retry/-/retry-0.12.0.tgz", + "integrity": "sha512-9LkiTwjUh6rT555DtE9rTX+BKByPfrMzEAtnlEtdEwr3Nkffwiihqe2bWADg+OQRjt9gl6ICdmB/ZFDCGAtSow==", + "license": "MIT", + "optional": true, + "engines": { + "node": ">= 4" + } + }, + "node_modules/rimraf": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", + "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", + "deprecated": "Rimraf versions prior to v4 are no longer supported", + "license": "ISC", + "optional": true, + "dependencies": { + "glob": "^7.1.3" + }, + "bin": { + "rimraf": "bin.js" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/rimraf/node_modules/brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "license": "MIT", + "optional": true, + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/rimraf/node_modules/glob": { + "version": "7.2.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", + "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", + "deprecated": "Glob versions prior to v9 are no longer supported", + "license": "ISC", + "optional": true, + "dependencies": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.1.1", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + }, + "engines": { + "node": "*" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/rimraf/node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "license": "ISC", + "optional": true, + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, "node_modules/router": { "version": "2.0.0-beta.2", "resolved": "https://registry.npmjs.org/router/-/router-2.0.0-beta.2.tgz", @@ -3395,9 +4326,7 @@ "type": "consulting", "url": "https://feross.org/support" } - ], - "optional": true, - "peer": true + ] }, "node_modules/simple-get": { "version": "4.0.1", @@ -3417,8 +4346,6 @@ "url": "https://feross.org/support" } ], - "optional": true, - "peer": true, "dependencies": { "decompress-response": "^6.0.0", "once": "^1.3.1", @@ -3613,6 +4540,30 @@ "integrity": "sha512-Oo+0REFV59/rz3gfJNKQiBlwfHaSESl1pcGyABQsnnIfWOFt6JNj5gCog2U6MLZ//IGYD+nA8nI+mTShREReaA==", "license": "BSD-3-Clause" }, + "node_modules/sqlite3": { + "version": "5.1.7", + "resolved": "https://registry.npmjs.org/sqlite3/-/sqlite3-5.1.7.tgz", + "integrity": "sha512-GGIyOiFaG+TUra3JIfkI/zGP8yZYLPQ0pl1bH+ODjiX57sPhrLU5sQJn1y9bDKZUFYkX1crlrPfSYt0BKKdkog==", + "hasInstallScript": true, + "license": "BSD-3-Clause", + "dependencies": { + "bindings": "^1.5.0", + "node-addon-api": "^7.0.0", + "prebuild-install": "^7.1.1", + "tar": "^6.1.11" + }, + "optionalDependencies": { + "node-gyp": "8.x" + }, + "peerDependencies": { + "node-gyp": "8.x" + }, + "peerDependenciesMeta": { + "node-gyp": { + "optional": true + } + } + }, "node_modules/sqlstring": { "version": "2.3.1", "resolved": "https://registry.npmjs.org/sqlstring/-/sqlstring-2.3.1.tgz", @@ -3621,6 +4572,32 @@ "node": ">= 0.6" } }, + "node_modules/ssri": { + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/ssri/-/ssri-8.0.1.tgz", + "integrity": "sha512-97qShzy1AiyxvPNIkLWoGua7xoQzzPjQ0HAH4B0rWKo7SZ6USuPcrUiAFrws0UH8RrbWmgq3LMTObhPIHbbBeQ==", + "license": "ISC", + "optional": true, + "dependencies": { + "minipass": "^3.1.1" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/ssri/node_modules/minipass": { + "version": "3.3.6", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz", + "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", + "license": "ISC", + "optional": true, + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, "node_modules/statuses": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.1.tgz", @@ -3710,8 +4687,6 @@ "version": "2.0.1", "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz", "integrity": "sha512-4gB8na07fecVVkOI6Rs4e7T6NOTki5EmL7TUduTs6bu3EdnSycntVJ4re8kgZA+wx9IueI2Y11bfbgwtzuE0KQ==", - "optional": true, - "peer": true, "engines": { "node": ">=0.10.0" } @@ -3727,12 +4702,27 @@ "node": ">=8" } }, + "node_modules/tar": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/tar/-/tar-6.2.1.tgz", + "integrity": "sha512-DZ4yORTwrbTj/7MZYq2w+/ZFdI6OZ/f9SFHR+71gIVUZhOQPHzVCLpvRnPgyaMpfWxxk/4ONva3GQSyNIKRv6A==", + "license": "ISC", + "dependencies": { + "chownr": "^2.0.0", + "fs-minipass": "^2.0.0", + "minipass": "^5.0.0", + "minizlib": "^2.1.1", + "mkdirp": "^1.0.3", + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=10" + } + }, "node_modules/tar-fs": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/tar-fs/-/tar-fs-2.1.1.tgz", "integrity": "sha512-V0r2Y9scmbDRLCNex/+hYzvp/zyYjvFbHPNgVTKfQvVrb6guiE/fxP+XblDNR011utopbkex2nM4dHNV6GDsng==", - "optional": true, - "peer": true, "dependencies": { "chownr": "^1.1.1", "mkdirp-classic": "^0.5.2", @@ -3744,8 +4734,6 @@ "version": "2.2.0", "resolved": "https://registry.npmjs.org/tar-stream/-/tar-stream-2.2.0.tgz", "integrity": "sha512-ujeqbceABgwMZxEJnk2HDY2DlnUZ+9oEcb1KzTVfYHio0UE6dG71n60d8D2I4qNvleWrrXpmjpt7vZeF1LnMZQ==", - "optional": true, - "peer": true, "dependencies": { "bl": "^4.0.3", "end-of-stream": "^1.4.1", @@ -3761,8 +4749,6 @@ "version": "3.6.2", "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", - "optional": true, - "peer": true, "dependencies": { "inherits": "^2.0.3", "string_decoder": "^1.1.1", @@ -3772,6 +4758,36 @@ "node": ">= 6" } }, + "node_modules/tar/node_modules/chownr": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/chownr/-/chownr-2.0.0.tgz", + "integrity": "sha512-bIomtDF5KGpdogkLd9VspvFzk9KfpyyGlS8YFVZl7TGPBHL5snIOnxeshwVgPteQ9b4Eydl+pVbIyE1DcvCWgQ==", + "license": "ISC", + "engines": { + "node": ">=10" + } + }, + "node_modules/tar/node_modules/minipass": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-5.0.0.tgz", + "integrity": "sha512-3FnjYuehv9k6ovOEbyOswadCDPX1piCfhV8ncmYtHOjuPwylVWsghTLo7rabjC3Rx5xD4HDx8Wm1xnMF7S5qFQ==", + "license": "ISC", + "engines": { + "node": ">=8" + } + }, + "node_modules/tar/node_modules/mkdirp": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz", + "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==", + "license": "MIT", + "bin": { + "mkdirp": "bin/cmd.js" + }, + "engines": { + "node": ">=10" + } + }, "node_modules/text-decoder": { "version": "1.2.3", "resolved": "https://registry.npmjs.org/text-decoder/-/text-decoder-1.2.3.tgz", @@ -3878,8 +4894,6 @@ "version": "0.6.0", "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz", "integrity": "sha512-McnNiV1l8RYeY8tBgEpuodCC1mLUdbSN+CYBL7kJsJNInOP8UjDDEwdk6Mw60vdLLrr5NHKZhMAOSrR2NZuQ+w==", - "optional": true, - "peer": true, "dependencies": { "safe-buffer": "^5.0.1" }, @@ -4177,6 +5191,26 @@ "ieee754": "^1.1.13" } }, + "node_modules/unique-filename": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/unique-filename/-/unique-filename-1.1.1.tgz", + "integrity": "sha512-Vmp0jIp2ln35UTXuryvjzkjGdRyf9b2lTXuSYUiPmzRcl3FDtYqAwOnTJkAngD9SWhnoJzDbTKwaOrZ+STtxNQ==", + "license": "ISC", + "optional": true, + "dependencies": { + "unique-slug": "^2.0.0" + } + }, + "node_modules/unique-slug": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/unique-slug/-/unique-slug-2.0.2.tgz", + "integrity": "sha512-zoWr9ObaxALD3DOPfjPSqxt4fnZiWblxHIgeWqW8x7UqDzEtHEQLzji2cuJYQFCU6KmoJikOYAZlrTHHebjx2w==", + "license": "ISC", + "optional": true, + "dependencies": { + "imurmurhash": "^0.1.4" + } + }, "node_modules/unpipe": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", @@ -4243,6 +5277,16 @@ "resolved": "https://registry.npmjs.org/which-module/-/which-module-2.0.1.tgz", "integrity": "sha512-iBdZ57RDvnOR9AGBhML2vFZf7h8vmBjhoaZqODJBFWHVtKkDmKuHai3cx5PgVMrX5YDNp27AofYbAwctSS+vhQ==" }, + "node_modules/wide-align": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/wide-align/-/wide-align-1.1.5.tgz", + "integrity": "sha512-eDMORYaPNZ4sQIuuYPDHdQvf4gyCF9rEEV/yPxGfwPkRodwEgiMUUXTx/dex+Me0wxx53S+NgUHaP7y3MGlDmg==", + "license": "ISC", + "optional": true, + "dependencies": { + "string-width": "^1.0.2 || 2 || 3 || 4" + } + }, "node_modules/wordwrap": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-1.0.0.tgz", @@ -4331,6 +5375,12 @@ "resolved": "https://registry.npmjs.org/y18n/-/y18n-4.0.3.tgz", "integrity": "sha512-JKhqTOwSrqNA1NY5lSztJ1GrBiUodLMmIZuLiDaMRJ+itFd+ABVE8XBjOvIWL+rSqNDC74LCSFmlb/U4UZ4hJQ==" }, + "node_modules/yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "license": "ISC" + }, "node_modules/yargs": { "version": "15.4.1", "resolved": "https://registry.npmjs.org/yargs/-/yargs-15.4.1.tgz", diff --git a/package.json b/package.json index 3eace88..7c289f7 100644 --- a/package.json +++ b/package.json @@ -43,6 +43,7 @@ "rss-parser": "^3.13.0", "socket.io": "^4.7.5", "speakeasy": "^2.0.0", + "sqlite3": "^5.1.7", "typeorm": "^0.3.20", "uuid": "^10.0.0" }, diff --git a/src/data-source.ts b/src/data-source.ts index 51d6659..e775503 100644 --- a/src/data-source.ts +++ b/src/data-source.ts @@ -50,7 +50,7 @@ import { CreateSchema1738166167472 } from "./migrations/1738166167472-CreateSche const dataSource = new DataSource({ type: DB_TYPE as any, - host: process.env.NODE_ENV || process.env.DBMODE ? "localhost" : DB_HOST, + host: DB_HOST, port: DB_PORT, username: DB_USERNAME, password: DB_PASSWORD, diff --git a/src/entity/club/calendar.ts b/src/entity/club/calendar.ts index a91fc5a..e6488f6 100644 --- a/src/entity/club/calendar.ts +++ b/src/entity/club/calendar.ts @@ -8,18 +8,20 @@ import { UpdateDateColumn, AfterUpdate, BeforeUpdate, + ColumnType, } from "typeorm"; import { calendarType } from "../settings/calendarType"; +import { getTypeByORM } from "../../migrations/ormHelper"; @Entity() export class calendar { @PrimaryGeneratedColumn("uuid") id: string; - @Column({ type: "datetime", nullable: false }) + @Column({ type: getTypeByORM("datetime").type as ColumnType }) starttime: Date; - @Column({ type: "datetime", nullable: false }) + @Column({ type: getTypeByORM("datetime").type as ColumnType }) endtime: Date; @Column({ type: "varchar", length: 255, nullable: false }) diff --git a/src/entity/club/member/member.ts b/src/entity/club/member/member.ts index 228eebb..d387469 100644 --- a/src/entity/club/member/member.ts +++ b/src/entity/club/member/member.ts @@ -1,10 +1,11 @@ -import { Column, Entity, JoinColumn, ManyToOne, OneToMany, OneToOne, PrimaryColumn } from "typeorm"; +import { Column, ColumnType, Entity, JoinColumn, ManyToOne, OneToMany, OneToOne, PrimaryColumn } from "typeorm"; import { membership } from "./membership"; import { memberAwards } from "./memberAwards"; import { memberQualifications } from "./memberQualifications"; import { memberExecutivePositions } from "./memberExecutivePositions"; import { communication } from "./communication"; import { salutation } from "../../settings/salutation"; +import { getTypeByORM } from "../../../migrations/ormHelper"; @Entity() export class member { @@ -20,7 +21,7 @@ export class member { @Column({ type: "varchar", length: 255 }) nameaffix: string; - @Column({ type: "date" }) + @Column({ type: getTypeByORM("date").type as ColumnType }) birthdate: Date; @Column({ type: "varchar", length: 255, unique: true, nullable: true }) diff --git a/src/entity/club/member/memberAwards.ts b/src/entity/club/member/memberAwards.ts index 1a453a2..3559024 100644 --- a/src/entity/club/member/memberAwards.ts +++ b/src/entity/club/member/memberAwards.ts @@ -1,6 +1,7 @@ -import { Column, Entity, ManyToOne, PrimaryColumn } from "typeorm"; +import { Column, ColumnType, Entity, ManyToOne, PrimaryColumn } from "typeorm"; import { member } from "./member"; import { award } from "../../settings/award"; +import { getTypeByORM } from "../../../migrations/ormHelper"; @Entity() export class memberAwards { @@ -13,7 +14,7 @@ export class memberAwards { @Column({ type: "varchar", length: 255, nullable: true }) note?: string; - @Column({ type: "date" }) + @Column({ type: getTypeByORM("date").type as ColumnType }) date: Date; @Column() diff --git a/src/entity/club/member/memberExecutivePositions.ts b/src/entity/club/member/memberExecutivePositions.ts index f09e9a8..c972d85 100644 --- a/src/entity/club/member/memberExecutivePositions.ts +++ b/src/entity/club/member/memberExecutivePositions.ts @@ -1,6 +1,7 @@ -import { Column, Entity, ManyToOne, PrimaryColumn } from "typeorm"; +import { Column, ColumnType, Entity, ManyToOne, PrimaryColumn } from "typeorm"; import { member } from "./member"; import { executivePosition } from "../../settings/executivePosition"; +import { getTypeByORM } from "../../../migrations/ormHelper"; @Entity() export class memberExecutivePositions { @@ -10,10 +11,10 @@ export class memberExecutivePositions { @Column({ type: "varchar", length: 255, nullable: true }) note?: string; - @Column({ type: "date" }) + @Column({ type: getTypeByORM("date").type as ColumnType }) start: Date; - @Column({ type: "date", nullable: true }) + @Column({ type: getTypeByORM("date").type as ColumnType, nullable: true }) end?: Date; @Column() diff --git a/src/entity/club/member/memberQualifications.ts b/src/entity/club/member/memberQualifications.ts index fe97ba5..c4e5a46 100644 --- a/src/entity/club/member/memberQualifications.ts +++ b/src/entity/club/member/memberQualifications.ts @@ -1,6 +1,7 @@ -import { Column, Entity, ManyToOne, PrimaryColumn } from "typeorm"; +import { Column, ColumnType, Entity, ManyToOne, PrimaryColumn } from "typeorm"; import { member } from "./member"; import { qualification } from "../../settings/qualification"; +import { getTypeByORM } from "../../../migrations/ormHelper"; @Entity() export class memberQualifications { @@ -10,10 +11,10 @@ export class memberQualifications { @Column({ type: "varchar", length: 255, nullable: true }) note?: string; - @Column({ type: "date" }) + @Column({ type: getTypeByORM("date").type as ColumnType }) start: Date; - @Column({ type: "date", nullable: true }) + @Column({ type: getTypeByORM("date").type as ColumnType, nullable: true }) end?: Date; @Column({ type: "varchar", length: 255, nullable: true }) diff --git a/src/entity/club/member/membership.ts b/src/entity/club/member/membership.ts index 63d2d52..1186f9c 100644 --- a/src/entity/club/member/membership.ts +++ b/src/entity/club/member/membership.ts @@ -1,16 +1,17 @@ -import { Column, Entity, JoinColumn, ManyToOne, PrimaryColumn } from "typeorm"; +import { Column, ColumnType, Entity, JoinColumn, ManyToOne, PrimaryColumn } from "typeorm"; import { member } from "./member"; import { membershipStatus } from "../../settings/membershipStatus"; +import { getTypeByORM } from "../../../migrations/ormHelper"; @Entity() export class membership { @PrimaryColumn({ generated: "increment", type: "int" }) id: number; - @Column({ type: "date" }) + @Column({ type: getTypeByORM("date").type as ColumnType }) start: Date; - @Column({ type: "date", nullable: true }) + @Column({ type: getTypeByORM("date").type as ColumnType, nullable: true }) end?: Date; @Column({ type: "varchar", length: 255, nullable: true }) diff --git a/src/entity/club/protocol/protocol.ts b/src/entity/club/protocol/protocol.ts index feaa4d9..18f672a 100644 --- a/src/entity/club/protocol/protocol.ts +++ b/src/entity/club/protocol/protocol.ts @@ -1,9 +1,10 @@ -import { Column, Entity, OneToMany, PrimaryColumn } from "typeorm"; +import { Column, ColumnType, Entity, OneToMany, PrimaryColumn } from "typeorm"; import { protocolAgenda } from "./protocolAgenda"; import { protocolDecision } from "./protocolDecision"; import { protocolPresence } from "./protocolPresence"; import { protocolPrintout } from "./protocolPrintout"; import { protocolVoting } from "./protocolVoting"; +import { getTypeByORM } from "../../../migrations/ormHelper"; @Entity() export class protocol { @@ -13,13 +14,13 @@ export class protocol { @Column({ type: "varchar", length: 255, unique: true }) title: string; - @Column({ type: "date" }) + @Column({ type: getTypeByORM("date").type as ColumnType }) date: Date; - @Column({ type: "time", nullable: true }) + @Column({ type: getTypeByORM("time").type as ColumnType, nullable: true }) starttime: Date; - @Column({ type: "time", nullable: true }) + @Column({ type: getTypeByORM("time").type as ColumnType, nullable: true }) endtime: Date; @Column({ type: "text", nullable: true }) diff --git a/src/entity/refresh.ts b/src/entity/refresh.ts index 646b3bd..c9a82e0 100644 --- a/src/entity/refresh.ts +++ b/src/entity/refresh.ts @@ -1,5 +1,6 @@ -import { Column, Entity, ManyToOne, PrimaryColumn } from "typeorm"; +import { Column, ColumnType, Entity, ManyToOne, PrimaryColumn } from "typeorm"; import { user } from "./user/user"; +import { getTypeByORM } from "../migrations/ormHelper"; @Entity() export class refresh { @@ -9,7 +10,7 @@ export class refresh { @PrimaryColumn() userId: string; - @Column({ type: "datetime" }) + @Column({ type: getTypeByORM("datetime").type as ColumnType }) expiry: Date; @ManyToOne(() => user, { diff --git a/src/entity/user/webapi.ts b/src/entity/user/webapi.ts index 2e8292c..c7aad4b 100644 --- a/src/entity/user/webapi.ts +++ b/src/entity/user/webapi.ts @@ -1,5 +1,6 @@ -import { Column, CreateDateColumn, Entity, OneToMany, PrimaryColumn } from "typeorm"; +import { Column, ColumnType, CreateDateColumn, Entity, OneToMany, PrimaryColumn } from "typeorm"; import { webapiPermission } from "./webapi_permission"; +import { getTypeByORM } from "../../migrations/ormHelper"; @Entity() export class webapi { @@ -15,10 +16,10 @@ export class webapi { @CreateDateColumn() createdAt: Date; - @Column({ type: "datetime", nullable: true }) + @Column({ type: getTypeByORM("datetime").type as ColumnType, nullable: true }) lastUsage?: Date; - @Column({ type: "date", nullable: true }) + @Column({ type: getTypeByORM("date").type as ColumnType, nullable: true }) expiry?: Date; @OneToMany(() => webapiPermission, (apiPermission) => apiPermission.webapi, { cascade: ["insert"] }) diff --git a/src/env.defaults.ts b/src/env.defaults.ts index 96968cb..61562b5 100644 --- a/src/env.defaults.ts +++ b/src/env.defaults.ts @@ -26,14 +26,18 @@ export const CLUB_WEBSITE = process.env.CLUB_WEBSITE ?? ""; export const BACKUP_INTERVAL = Number(process.env.BACKUP_INTERVAL ?? "0"); export const BACKUP_COPIES = Number(process.env.BACKUP_COPIES ?? "0"); -export const BACKUP_AUTO_RESTORE = process.env.BACKUP_AUTO_RESTORE ?? "false"; +export const BACKUP_AUTO_RESTORE = process.env.BACKUP_AUTO_RESTORE ?? "true"; export function configCheck() { - if (DB_TYPE != "mysql" && DB_TYPE != "sqlite") throw new Error("set valid value to DB_TYPE (mysql|sqlite)"); - if (DB_HOST == "" || typeof DB_HOST != "string") throw new Error("set valid value to DB_HOST"); + if (DB_TYPE != "mysql" && DB_TYPE != "sqlite" && DB_TYPE != "postgres") + throw new Error("set valid value to DB_TYPE (mysql|sqlite|postgres)"); + if ((DB_HOST == "" || typeof DB_HOST != "string") && DB_TYPE != "sqlite") + throw new Error("set valid value to DB_HOST"); if (DB_NAME == "" || typeof DB_NAME != "string") throw new Error("set valid value to DB_NAME"); - if (DB_USERNAME == "" || typeof DB_USERNAME != "string") throw new Error("set valid value to DB_USERNAME"); - if (DB_PASSWORD == "" || typeof DB_PASSWORD != "string") throw new Error("set valid value to DB_PASSWORD"); + if ((DB_USERNAME == "" || typeof DB_USERNAME != "string") && DB_TYPE != "sqlite") + throw new Error("set valid value to DB_USERNAME"); + if ((DB_PASSWORD == "" || typeof DB_PASSWORD != "string") && DB_TYPE != "sqlite") + throw new Error("set valid value to DB_PASSWORD"); if (typeof SERVER_PORT != "number") throw new Error("set valid numeric value to SERVER_PORT"); diff --git a/src/migrations/1738166124200-BackupAndResetDatabase.ts b/src/migrations/1738166124200-BackupAndResetDatabase.ts index 4a190c5..f0656ba 100644 --- a/src/migrations/1738166124200-BackupAndResetDatabase.ts +++ b/src/migrations/1738166124200-BackupAndResetDatabase.ts @@ -1,13 +1,15 @@ import { MigrationInterface, QueryRunner, Table } from "typeorm"; import BackupHelper from "../helpers/backupHelper"; -import { getTypeByORM } from "./ormHelper"; +import { getDefaultByORM, getTypeByORM, isIncrementPrimary } from "./ormHelper"; import InternalException from "../exceptions/internalException"; +import { DB_TYPE } from "../env.defaults"; export class BackupAndResetDatabase1738166124200 implements MigrationInterface { name = "BackupAndResetDatabase1738166124200"; public async up(queryRunner: QueryRunner): Promise { - let migrations = await queryRunner.query("SELECT `name` FROM `migrations`"); + let query = DB_TYPE == "postgres" ? "SELECT name FROM migrations" : "SELECT `name` FROM `migrations`"; + let migrations = await queryRunner.query(query); if ( (await queryRunner.hasTable("user")) && migrations.findIndex((m: any) => m.name == "MoveSendNewsletterFlag1737816852011") == -1 @@ -26,15 +28,9 @@ export class BackupAndResetDatabase1738166124200 implements MigrationInterface { new Table({ name: "migrations", columns: [ - { - name: "id", - type: getTypeByORM("int"), - isPrimary: true, - isGenerated: true, - generationStrategy: "increment", - }, - { name: "timestamp", type: getTypeByORM("bigint"), isNullable: false }, - { name: "name", type: getTypeByORM("varchar"), length: "255", isNullable: false }, + { name: "id", ...getTypeByORM("int"), ...isIncrementPrimary }, + { name: "timestamp", ...getTypeByORM("bigint") }, + { name: "name", ...getTypeByORM("varchar") }, ], }), true @@ -44,12 +40,12 @@ export class BackupAndResetDatabase1738166124200 implements MigrationInterface { new Table({ name: "typeorm_metadata", columns: [ - { name: "type", type: getTypeByORM("varchar"), length: "255", isNullable: false }, - { name: "database", type: getTypeByORM("varchar"), length: "255", isNullable: true, default: null }, - { name: "schema", type: getTypeByORM("varchar"), length: "255", isNullable: true, default: null }, - { name: "table", type: getTypeByORM("varchar"), length: "255", isNullable: true, default: null }, - { name: "name", type: getTypeByORM("varchar"), length: "255", isNullable: true, default: null }, - { name: "value", type: getTypeByORM("text"), length: "255", isNullable: true, default: null }, + { name: "type", ...getTypeByORM("varchar") }, + { name: "database", ...getTypeByORM("varchar", true), default: getDefaultByORM("null") }, + { name: "schema", ...getTypeByORM("varchar", true), default: getDefaultByORM("null") }, + { name: "table", ...getTypeByORM("varchar", true), default: getDefaultByORM("null") }, + { name: "name", ...getTypeByORM("varchar", true), default: getDefaultByORM("null") }, + { name: "value", ...getTypeByORM("text", true), default: getDefaultByORM("null") }, ], }), true diff --git a/src/migrations/1738166167472-CreateSchema.ts b/src/migrations/1738166167472-CreateSchema.ts index 0eafa18..f5995b7 100644 --- a/src/migrations/1738166167472-CreateSchema.ts +++ b/src/migrations/1738166167472-CreateSchema.ts @@ -20,13 +20,17 @@ import { member_communication_table, member_executive_positions_table, member_executive_positions_view, + member_executive_positions_view_postgres, member_qualifications_table, member_qualifications_view, + member_qualifications_view_postgres, member_table, member_view, + member_view_postgres, membership_status_table, membership_table, membership_view, + membership_view_postgres, qualification_table, salutation_table, } from "./baseSchemaTables/member"; @@ -46,6 +50,7 @@ import { newsletter_recipients_table, newsletter_table, } from "./baseSchemaTables/newsletter"; +import { DB_TYPE } from "../env.defaults"; export class CreateSchema1738166167472 implements MigrationInterface { name = "CreateSchema1738166167472"; @@ -75,10 +80,14 @@ export class CreateSchema1738166167472 implements MigrationInterface { await queryRunner.createTable(member_executive_positions_table, true, true, true); await queryRunner.createTable(member_qualifications_table, true, true, true); - await queryRunner.createView(member_view, true); - await queryRunner.createView(membership_view, true); - await queryRunner.createView(member_qualifications_view, true); - await queryRunner.createView(member_executive_positions_view, true); + if (DB_TYPE == "postgres") await queryRunner.createView(member_view_postgres, true); + else await queryRunner.createView(member_view, true); + if (DB_TYPE == "postgres") await queryRunner.createView(membership_view_postgres, true); + else await queryRunner.createView(membership_view, true); + if (DB_TYPE == "postgres") await queryRunner.createView(member_qualifications_view_postgres, true); + else await queryRunner.createView(member_qualifications_view, true); + if (DB_TYPE == "postgres") await queryRunner.createView(member_executive_positions_view_postgres, true); + else await queryRunner.createView(member_executive_positions_view, true); await queryRunner.createTable(query_table, true, true, true); await queryRunner.createTable(template_table, true, true, true); diff --git a/src/migrations/baseSchemaTables/admin.ts b/src/migrations/baseSchemaTables/admin.ts index 9ad6437..c3eb94b 100644 --- a/src/migrations/baseSchemaTables/admin.ts +++ b/src/migrations/baseSchemaTables/admin.ts @@ -1,36 +1,30 @@ import { Table, TableForeignKey } from "typeorm"; -import { getTypeByORM } from "../ormHelper"; +import { getDefaultByORM, getTypeByORM, isIncrementPrimary, isUUIDPrimary } from "../ormHelper"; export const invite_table = new Table({ name: "invite", columns: [ - { name: "mail", type: getTypeByORM("varchar"), length: "255", isPrimary: true }, - { name: "token", type: getTypeByORM("varchar"), length: "255", isNullable: false }, - { name: "username", type: getTypeByORM("varchar"), length: "255", isNullable: false }, - { name: "firstname", type: getTypeByORM("varchar"), length: "255", isNullable: false }, - { name: "lastname", type: getTypeByORM("varchar"), length: "255", isNullable: false }, - { name: "secret", type: getTypeByORM("varchar"), length: "255", isNullable: false }, + { name: "mail", ...getTypeByORM("varchar"), isPrimary: true }, + { name: "token", ...getTypeByORM("varchar") }, + { name: "username", ...getTypeByORM("varchar") }, + { name: "firstname", ...getTypeByORM("varchar") }, + { name: "lastname", ...getTypeByORM("varchar") }, + { name: "secret", ...getTypeByORM("varchar") }, ], }); export const role_table = new Table({ name: "role", columns: [ - { - name: "id", - type: getTypeByORM("int"), - isPrimary: true, - isGenerated: true, - generationStrategy: "increment", - }, - { name: "role", type: getTypeByORM("varchar"), length: "255", isNullable: false, isUnique: true }, + { name: "id", ...getTypeByORM("int"), ...isIncrementPrimary }, + { name: "role", ...getTypeByORM("varchar"), isUnique: true }, ], }); export const role_permission_table = new Table({ name: "role_permission", columns: [ - { name: "roleId", type: getTypeByORM("int"), isPrimary: true }, - { name: "permission", type: getTypeByORM("varchar"), length: "255", isPrimary: true }, + { name: "roleId", ...getTypeByORM("int"), isPrimary: true }, + { name: "permission", ...getTypeByORM("varchar"), isPrimary: true }, ], foreignKeys: [ new TableForeignKey({ @@ -46,29 +40,22 @@ export const role_permission_table = new Table({ export const user_table = new Table({ name: "user", columns: [ - { - name: "id", - type: getTypeByORM("varchar"), - length: "36", - isPrimary: true, - isGenerated: true, - generationStrategy: "uuid", - }, - { name: "mail", type: getTypeByORM("varchar"), length: "255", isNullable: false, isUnique: true }, - { name: "username", type: getTypeByORM("varchar"), length: "255", isNullable: false, isUnique: true }, - { name: "firstname", type: getTypeByORM("varchar"), length: "255", isNullable: false }, - { name: "lastname", type: getTypeByORM("varchar"), length: "255", isNullable: false }, - { name: "secret", type: getTypeByORM("varchar"), length: "255", isNullable: false }, - { name: "static", type: getTypeByORM("boolean"), isNullable: false, default: false }, - { name: "isOwner", type: getTypeByORM("boolean"), isNullable: false, default: false }, + { name: "id", ...getTypeByORM("uuid"), ...isUUIDPrimary }, + { name: "mail", ...getTypeByORM("varchar"), isUnique: true }, + { name: "username", ...getTypeByORM("varchar"), isUnique: true }, + { name: "firstname", ...getTypeByORM("varchar") }, + { name: "lastname", ...getTypeByORM("varchar") }, + { name: "secret", ...getTypeByORM("varchar") }, + { name: "static", ...getTypeByORM("boolean"), default: getDefaultByORM("boolean", false) }, + { name: "isOwner", ...getTypeByORM("boolean"), default: getDefaultByORM("boolean", false) }, ], }); export const user_roles_table = new Table({ name: "user_roles", columns: [ - { name: "userId", type: getTypeByORM("varchar"), isPrimary: true }, - { name: "roleId", type: getTypeByORM("int"), isPrimary: true }, + { name: "userId", ...getTypeByORM("uuid"), isPrimary: true }, + { name: "roleId", ...getTypeByORM("int"), isPrimary: true }, ], foreignKeys: [ new TableForeignKey({ @@ -91,8 +78,8 @@ export const user_roles_table = new Table({ export const user_permission_table = new Table({ name: "user_permission", columns: [ - { name: "userId", type: getTypeByORM("varchar"), isPrimary: true }, - { name: "permission", type: getTypeByORM("varchar"), length: "255", isPrimary: true }, + { name: "userId", ...getTypeByORM("uuid"), isPrimary: true }, + { name: "permission", ...getTypeByORM("varchar"), isPrimary: true }, ], foreignKeys: [ new TableForeignKey({ @@ -108,9 +95,9 @@ export const user_permission_table = new Table({ export const refresh_table = new Table({ name: "refresh", columns: [ - { name: "token", type: getTypeByORM("varchar"), length: "255", isPrimary: true, isNullable: false }, - { name: "expiry", type: getTypeByORM("datetime"), isNullable: false }, - { name: "userId", type: getTypeByORM("varchar"), isPrimary: true, isNullable: false }, + { name: "token", ...getTypeByORM("varchar"), isPrimary: true }, + { name: "expiry", ...getTypeByORM("datetime", false, 6) }, + { name: "userId", ...getTypeByORM("uuid"), isPrimary: true }, ], foreignKeys: [ new TableForeignKey({ @@ -126,26 +113,20 @@ export const refresh_table = new Table({ export const webapi_table = new Table({ name: "webapi", columns: [ - { - name: "id", - type: getTypeByORM("int"), - isPrimary: true, - isGenerated: true, - generationStrategy: "increment", - }, - { name: "token", type: getTypeByORM("varchar"), length: "255", isNullable: false, isUnique: true }, - { name: "title", type: getTypeByORM("varchar"), length: "255", isNullable: false, isUnique: true }, - { name: "createdAt", type: getTypeByORM("datetime"), isNullable: false, default: "CURRENT_TIMESTAMP(6)" }, - { name: "lastUsage", type: getTypeByORM("datetime"), isNullable: true, default: null }, - { name: "expiry", type: getTypeByORM("date"), isNullable: true, default: null }, + { name: "id", ...getTypeByORM("int"), ...isIncrementPrimary }, + { name: "token", ...getTypeByORM("varchar"), isUnique: true }, + { name: "title", ...getTypeByORM("varchar"), isUnique: true }, + { name: "createdAt", ...getTypeByORM("datetime", false, 6), default: getDefaultByORM("currentTimestamp", 6) }, + { name: "lastUsage", ...getTypeByORM("datetime", true, 6), default: getDefaultByORM("null") }, + { name: "expiry", ...getTypeByORM("date", true), default: getDefaultByORM("null") }, ], }); export const webapi_permission_table = new Table({ name: "webapi_permission", columns: [ - { name: "webapiId", type: getTypeByORM("int"), isPrimary: true }, - { name: "permission", type: getTypeByORM("varchar"), length: "255", isPrimary: true }, + { name: "webapiId", ...getTypeByORM("int"), isPrimary: true }, + { name: "permission", ...getTypeByORM("varchar"), isPrimary: true }, ], foreignKeys: [ new TableForeignKey({ @@ -161,9 +142,9 @@ export const webapi_permission_table = new Table({ export const reset_table = new Table({ name: "reset", columns: [ - { name: "mail", type: getTypeByORM("varchar"), length: "255", isPrimary: true }, - { name: "token", type: getTypeByORM("varchar"), length: "255", isNullable: false }, - { name: "username", type: getTypeByORM("varchar"), length: "255", isNullable: false }, - { name: "secret", type: getTypeByORM("varchar"), length: "255", isNullable: false }, + { name: "mail", ...getTypeByORM("varchar"), isPrimary: true }, + { name: "token", ...getTypeByORM("varchar") }, + { name: "username", ...getTypeByORM("varchar") }, + { name: "secret", ...getTypeByORM("varchar") }, ], }); diff --git a/src/migrations/baseSchemaTables/calendar.ts b/src/migrations/baseSchemaTables/calendar.ts index 793b2cc..155dc46 100644 --- a/src/migrations/baseSchemaTables/calendar.ts +++ b/src/migrations/baseSchemaTables/calendar.ts @@ -1,61 +1,39 @@ import { Table, TableForeignKey } from "typeorm"; -import { getTypeByORM } from "../ormHelper"; +import { getDefaultByORM, getTypeByORM, isIncrementPrimary, isUUIDPrimary } from "../ormHelper"; export const calendar_type_table = new Table({ name: "calendar_type", columns: [ - { name: "id", type: getTypeByORM("int"), isPrimary: true, isGenerated: true, generationStrategy: "increment" }, - { name: "type", type: getTypeByORM("varchar"), length: "255", isUnique: true, isNullable: false }, - { name: "nscdr", type: getTypeByORM("boolean"), isNullable: false, default: false }, - { name: "color", type: getTypeByORM("varchar"), length: "255", isNullable: false }, - { name: "passphrase", type: getTypeByORM("varchar"), length: "255", isNullable: true }, - { name: "externalPrefix", type: getTypeByORM("varchar"), length: "255", isNullable: false, default: "''" }, - { name: "sendToWebpage", type: getTypeByORM("boolean"), isNullable: false, default: false }, + { name: "id", ...getTypeByORM("int"), ...isIncrementPrimary }, + { name: "type", ...getTypeByORM("varchar"), isUnique: true }, + { name: "nscdr", ...getTypeByORM("boolean"), default: getDefaultByORM("boolean", false) }, + { name: "color", ...getTypeByORM("varchar") }, + { name: "passphrase", ...getTypeByORM("varchar", true) }, + { name: "externalPrefix", ...getTypeByORM("varchar"), default: getDefaultByORM("string") }, + { name: "sendToWebpage", ...getTypeByORM("boolean"), default: getDefaultByORM("boolean", false) }, ], }); export const calendar_table = new Table({ name: "calendar", columns: [ - { - name: "id", - type: getTypeByORM("varchar"), - length: "36", - isPrimary: true, - isGenerated: true, - generationStrategy: "uuid", - }, - { name: "starttime", type: getTypeByORM("datetime"), isNullable: false }, - { name: "endtime", type: getTypeByORM("datetime"), isNullable: false }, - { name: "title", type: getTypeByORM("varchar"), length: "255", isNullable: false }, - { name: "content", type: getTypeByORM("text"), isNullable: true }, - { name: "allDay", type: getTypeByORM("boolean"), isNullable: false, default: false }, - { name: "location", type: getTypeByORM("text"), isNullable: true }, - { name: "sequence", type: getTypeByORM("int"), default: 1 }, - { - name: "createdAt", - type: getTypeByORM("datetime"), - precision: 6, - isNullable: false, - default: "CURRENT_TIMESTAMP(6)", - }, + { name: "id", ...getTypeByORM("uuid"), ...isUUIDPrimary }, + { name: "starttime", ...getTypeByORM("datetime", false, 6) }, + { name: "endtime", ...getTypeByORM("datetime", false, 6) }, + { name: "title", ...getTypeByORM("varchar") }, + { name: "content", ...getTypeByORM("text", true) }, + { name: "allDay", ...getTypeByORM("boolean"), default: getDefaultByORM("boolean", false) }, + { name: "location", ...getTypeByORM("text", true) }, + { name: "sequence", ...getTypeByORM("int"), default: getDefaultByORM("number", 1) }, + { name: "createdAt", ...getTypeByORM("datetime", false, 6), default: getDefaultByORM("currentTimestamp", 6) }, { name: "updatedAt", - type: getTypeByORM("datetime"), - precision: 6, - isNullable: false, - default: "CURRENT_TIMESTAMP(6)", - onUpdate: "CURRENT_TIMESTAMP(6)", + ...getTypeByORM("datetime", false, 6), + default: getDefaultByORM("currentTimestamp", 6), + onUpdate: getDefaultByORM("currentTimestamp", 6), }, - { - name: "webpageId", - type: getTypeByORM("varchar"), - length: "255", - isNullable: true, - default: null, - isUnique: true, - }, - { name: "typeId", type: getTypeByORM("int"), isNullable: false }, + { name: "webpageId", ...getTypeByORM("varchar", true), default: getDefaultByORM("null"), isUnique: true }, + { name: "typeId", ...getTypeByORM("int") }, ], foreignKeys: [ new TableForeignKey({ diff --git a/src/migrations/baseSchemaTables/member.ts b/src/migrations/baseSchemaTables/member.ts index ead90b5..c2657cb 100644 --- a/src/migrations/baseSchemaTables/member.ts +++ b/src/migrations/baseSchemaTables/member.ts @@ -1,53 +1,53 @@ import { Table, TableForeignKey, View } from "typeorm"; -import { getTypeByORM } from "../ormHelper"; +import { getDefaultByORM, getTypeByORM, isIncrementPrimary, isUUIDPrimary } from "../ormHelper"; export const salutation_table = new Table({ name: "salutation", columns: [ - { name: "id", type: getTypeByORM("int"), isPrimary: true, isGenerated: true, generationStrategy: "increment" }, - { name: "salutation", type: getTypeByORM("varchar"), length: "255", isUnique: true, isNullable: false }, + { name: "id", ...getTypeByORM("int"), ...isIncrementPrimary }, + { name: "salutation", ...getTypeByORM("varchar"), isUnique: true }, ], }); export const award_table = new Table({ name: "award", columns: [ - { name: "id", type: getTypeByORM("int"), isPrimary: true, isGenerated: true, generationStrategy: "increment" }, - { name: "award", type: getTypeByORM("varchar"), length: "255", isUnique: true, isNullable: false }, + { name: "id", ...getTypeByORM("int"), ...isIncrementPrimary }, + { name: "award", ...getTypeByORM("varchar"), isUnique: true }, ], }); export const communication_type_table = new Table({ name: "communication_type", columns: [ - { name: "id", type: getTypeByORM("int"), isPrimary: true, isGenerated: true, generationStrategy: "increment" }, - { name: "type", type: getTypeByORM("varchar"), length: "255", isUnique: true, isNullable: false }, - { name: "useColumns", type: getTypeByORM("varchar"), length: "255", isNullable: false, default: "''" }, + { name: "id", ...getTypeByORM("int"), ...isIncrementPrimary }, + { name: "type", ...getTypeByORM("varchar"), isUnique: true }, + { name: "useColumns", ...getTypeByORM("varchar"), default: getDefaultByORM("string") }, ], }); export const executive_position_table = new Table({ name: "executive_position", columns: [ - { name: "id", type: getTypeByORM("int"), isPrimary: true, isGenerated: true, generationStrategy: "increment" }, - { name: "position", type: getTypeByORM("varchar"), length: "255", isUnique: true, isNullable: false }, + { name: "id", ...getTypeByORM("int"), ...isIncrementPrimary }, + { name: "position", ...getTypeByORM("varchar"), isUnique: true }, ], }); export const membership_status_table = new Table({ name: "membership_status", columns: [ - { name: "id", type: getTypeByORM("int"), isPrimary: true, isGenerated: true, generationStrategy: "increment" }, - { name: "status", type: getTypeByORM("varchar"), length: "255", isUnique: true, isNullable: false }, + { name: "id", ...getTypeByORM("int"), ...isIncrementPrimary }, + { name: "status", ...getTypeByORM("varchar"), isUnique: true }, ], }); export const qualification_table = new Table({ name: "qualification", columns: [ - { name: "id", type: getTypeByORM("int"), isPrimary: true, isGenerated: true, generationStrategy: "increment" }, - { name: "qualification", type: getTypeByORM("varchar"), length: "255", isUnique: true, isNullable: false }, - { name: "description", type: getTypeByORM("varchar"), length: "255", isNullable: true }, + { name: "id", ...getTypeByORM("int"), ...isIncrementPrimary }, + { name: "qualification", ...getTypeByORM("varchar"), isUnique: true }, + { name: "description", ...getTypeByORM("varchar"), isNullable: true }, ], }); @@ -55,27 +55,13 @@ export const qualification_table = new Table({ export const member_table = new Table({ name: "member", columns: [ - { - name: "id", - type: getTypeByORM("varchar"), - length: "36", - isPrimary: true, - isGenerated: true, - generationStrategy: "uuid", - }, - { name: "salutationId", type: getTypeByORM("int"), isNullable: false }, - { - name: "internalId", - type: getTypeByORM("varchar"), - length: "255", - default: null, - isNullable: true, - isUnique: true, - }, - { name: "firstname", type: getTypeByORM("varchar"), length: "255", isNullable: false }, - { name: "lastname", type: getTypeByORM("varchar"), length: "255", isNullable: false }, - { name: "nameaffix", type: getTypeByORM("varchar"), length: "255", isNullable: false }, - { name: "birthdate", type: getTypeByORM("date"), isNullable: false }, + { name: "id", ...getTypeByORM("uuid"), ...isUUIDPrimary }, + { name: "salutationId", ...getTypeByORM("int") }, + { name: "internalId", ...getTypeByORM("varchar", true), default: getDefaultByORM("null"), isUnique: true }, + { name: "firstname", ...getTypeByORM("varchar") }, + { name: "lastname", ...getTypeByORM("varchar") }, + { name: "nameaffix", ...getTypeByORM("varchar") }, + { name: "birthdate", ...getTypeByORM("date") }, ], foreignKeys: [ new TableForeignKey({ @@ -91,12 +77,12 @@ export const member_table = new Table({ export const membership_table = new Table({ name: "membership", columns: [ - { name: "id", type: getTypeByORM("int"), isPrimary: true, isGenerated: true, generationStrategy: "increment" }, - { name: "start", type: getTypeByORM("date"), isNullable: false }, - { name: "end", type: getTypeByORM("date"), isNullable: true }, - { name: "terminationReason", type: getTypeByORM("varchar"), length: "255", isNullable: true }, - { name: "memberId", type: getTypeByORM("varchar"), isNullable: false }, - { name: "statusId", type: getTypeByORM("int"), isNullable: false }, + { name: "id", ...getTypeByORM("int"), ...isIncrementPrimary }, + { name: "start", ...getTypeByORM("date") }, + { name: "end", ...getTypeByORM("date", true) }, + { name: "terminationReason", ...getTypeByORM("varchar"), isNullable: true }, + { name: "memberId", ...getTypeByORM("uuid") }, + { name: "statusId", ...getTypeByORM("int") }, ], foreignKeys: [ new TableForeignKey({ @@ -119,13 +105,13 @@ export const membership_table = new Table({ export const member_qualifications_table = new Table({ name: "member_qualifications", columns: [ - { name: "id", type: getTypeByORM("int"), isPrimary: true, isGenerated: true, generationStrategy: "increment" }, - { name: "note", type: getTypeByORM("varchar"), length: "255", isNullable: true }, - { name: "start", type: getTypeByORM("date"), isNullable: false }, - { name: "end", type: getTypeByORM("date"), isNullable: true }, - { name: "terminationReason", type: getTypeByORM("varchar"), length: "255", isNullable: true }, - { name: "memberId", type: getTypeByORM("varchar"), isNullable: false }, - { name: "qualificationId", type: getTypeByORM("int"), isNullable: false }, + { name: "id", ...getTypeByORM("int"), ...isIncrementPrimary }, + { name: "note", ...getTypeByORM("varchar"), isNullable: true }, + { name: "start", ...getTypeByORM("date") }, + { name: "end", ...getTypeByORM("date", true) }, + { name: "terminationReason", ...getTypeByORM("varchar"), isNullable: true }, + { name: "memberId", ...getTypeByORM("uuid") }, + { name: "qualificationId", ...getTypeByORM("int") }, ], foreignKeys: [ new TableForeignKey({ @@ -148,12 +134,12 @@ export const member_qualifications_table = new Table({ export const member_executive_positions_table = new Table({ name: "member_executive_positions", columns: [ - { name: "id", type: getTypeByORM("int"), isPrimary: true, isGenerated: true, generationStrategy: "increment" }, - { name: "note", type: getTypeByORM("varchar"), length: "255", isNullable: true }, - { name: "start", type: getTypeByORM("date"), isNullable: false }, - { name: "end", type: getTypeByORM("date"), isNullable: true }, - { name: "memberId", type: getTypeByORM("varchar"), isNullable: false }, - { name: "executivePositionId", type: getTypeByORM("int"), isNullable: false }, + { name: "id", ...getTypeByORM("int"), ...isIncrementPrimary }, + { name: "note", ...getTypeByORM("varchar"), isNullable: true }, + { name: "start", ...getTypeByORM("date") }, + { name: "end", ...getTypeByORM("date", true) }, + { name: "memberId", ...getTypeByORM("uuid") }, + { name: "executivePositionId", ...getTypeByORM("int") }, ], foreignKeys: [ new TableForeignKey({ @@ -176,12 +162,12 @@ export const member_executive_positions_table = new Table({ export const member_awards_table = new Table({ name: "member_awards", columns: [ - { name: "id", type: getTypeByORM("int"), isPrimary: true, isGenerated: true, generationStrategy: "increment" }, - { name: "given", type: getTypeByORM("boolean"), default: false, isNullable: false }, - { name: "note", type: getTypeByORM("varchar"), length: "255", isNullable: true }, - { name: "date", type: getTypeByORM("date"), isNullable: false }, - { name: "memberId", type: getTypeByORM("varchar"), isNullable: false }, - { name: "awardId", type: getTypeByORM("int"), isNullable: false }, + { name: "id", ...getTypeByORM("int"), ...isIncrementPrimary }, + { name: "given", ...getTypeByORM("boolean"), default: getDefaultByORM("boolean", false) }, + { name: "note", ...getTypeByORM("varchar"), isNullable: true }, + { name: "date", ...getTypeByORM("date") }, + { name: "memberId", ...getTypeByORM("uuid") }, + { name: "awardId", ...getTypeByORM("int") }, ], foreignKeys: [ new TableForeignKey({ @@ -204,19 +190,19 @@ export const member_awards_table = new Table({ export const member_communication_table = new Table({ name: "communication", columns: [ - { name: "id", type: getTypeByORM("int"), isPrimary: true, isGenerated: true, generationStrategy: "increment" }, - { name: "preferred", type: getTypeByORM("boolean"), isNullable: false, default: false }, - { name: "isSendNewsletter", type: getTypeByORM("boolean"), isNullable: false, default: false }, - { name: "isSMSAlarming", type: getTypeByORM("boolean"), isNullable: false, default: false }, - { name: "mobile", type: getTypeByORM("varchar"), length: "255", isNullable: true }, - { name: "email", type: getTypeByORM("varchar"), length: "255", isNullable: true }, - { name: "postalCode", type: getTypeByORM("varchar"), length: "255", default: null, isNullable: true }, - { name: "city", type: getTypeByORM("varchar"), length: "255", isNullable: true }, - { name: "street", type: getTypeByORM("varchar"), length: "255", isNullable: true }, - { name: "streetNumber", type: getTypeByORM("int"), isNullable: true }, - { name: "streetNumberAddition", type: getTypeByORM("varchar"), length: "255", isNullable: true }, - { name: "memberId", type: getTypeByORM("varchar"), isNullable: false }, - { name: "typeId", type: getTypeByORM("int"), isNullable: false }, + { name: "id", ...getTypeByORM("int"), ...isIncrementPrimary }, + { name: "preferred", ...getTypeByORM("boolean"), default: getDefaultByORM("boolean", false) }, + { name: "isSendNewsletter", ...getTypeByORM("boolean"), default: getDefaultByORM("boolean", false) }, + { name: "isSMSAlarming", ...getTypeByORM("boolean"), default: getDefaultByORM("boolean", false) }, + { name: "mobile", ...getTypeByORM("varchar"), isNullable: true }, + { name: "email", ...getTypeByORM("varchar"), isNullable: true }, + { name: "postalCode", ...getTypeByORM("varchar"), default: getDefaultByORM("null"), isNullable: true }, + { name: "city", ...getTypeByORM("varchar"), isNullable: true }, + { name: "street", ...getTypeByORM("varchar"), isNullable: true }, + { name: "streetNumber", ...getTypeByORM("int", true) }, + { name: "streetNumberAddition", ...getTypeByORM("varchar"), isNullable: true }, + { name: "memberId", ...getTypeByORM("uuid") }, + { name: "typeId", ...getTypeByORM("int") }, ], foreignKeys: [ new TableForeignKey({ @@ -247,13 +233,32 @@ export const member_view = new View({ \`member\`.\`nameaffix\` AS \`nameaffix\`, \`member\`.\`birthdate\` AS \`birthdate\`, \`salutation\`.\`salutation\` AS \`salutation\`, - TIMESTAMPDIFF(YEAR, \`member\`.\`birthdate\`, CURDATE()) AS \`todayAge\`, YEAR(CURDATE()) - YEAR(\`member\`.\`birthdate\`) AS \`ageThisYear\`, + TIMESTAMPDIFF(YEAR, \`member\`.\`birthdate\`, CURDATE()) AS \`todayAge\`, + YEAR(CURDATE()) - YEAR(\`member\`.\`birthdate\`) AS \`ageThisYear\`, CONCAT('_', FROM_DAYS(TIMESTAMPDIFF(DAY, \`member\`.\`birthdate\`, CURDATE()))) AS \`exactAge\` FROM \`member\` \`member\` LEFT JOIN \`salutation\` \`salutation\` ON \`salutation\`.\`id\`=\`member\`.\`salutationId\` `, }); +export const member_view_postgres = new View({ + name: "member_view", + expression: ` + SELECT + "member"."id" AS "id", + "member"."firstname" AS "firstname", + "member"."lastname" AS "lastname", + "member"."nameaffix" AS "nameaffix", + "member"."birthdate" AS "birthdate", + "salutation"."salutation" AS "salutation", + DATE_PART('year', AGE(CURRENT_DATE, member.birthdate)) AS "todayAge", + EXTRACT(YEAR FROM CURRENT_DATE) - EXTRACT(YEAR FROM member.birthdate) AS "ageThisYear", + AGE(CURRENT_DATE, member.birthdate) AS "exactAge" + FROM "member" "member" + LEFT JOIN "salutation" "salutation" ON "salutation"."id"="member"."salutationId" + `, +}); + export const member_executive_positions_view = new View({ name: "member_executive_positions_view", expression: ` @@ -266,13 +271,35 @@ export const member_executive_positions_view = new View({ \`member\`.\`nameaffix\` AS \`memberNameaffix\`, \`member\`.\`birthdate\` AS \`memberBirthdate\`, \`salutation\`.\`salutation\` AS \`memberSalutation\`, - SUM(TIMESTAMPDIFF(DAY, \`memberExecutivePositions\`.\`start\`, - COALESCE(\`memberExecutivePositions\`.\`end\`, CURRENT_DATE))) AS \`durationInDays\` + SUM(TIMESTAMPDIFF(DAY, \`memberExecutivePositions\`.\`start\`, COALESCE(\`memberExecutivePositions\`.\`end\`, CURRENT_DATE))) AS \`durationInDays\`, + CONCAT('_', FROM_DAYS(SUM(TIMESTAMPDIFF(DAY, \`memberExecutivePositions\`.\`start\`, COALESCE(\`memberExecutivePositions\`.\`end\`, CURRENT_DATE))))) AS \`durationInYears\` FROM \`member_executive_positions\` \`memberExecutivePositions\` LEFT JOIN \`executive_position\` \`executivePosition\` ON \`executivePosition\`.\`id\`=\`memberExecutivePositions\`.\`executivePositionId\` LEFT JOIN \`member\` \`member\` ON \`member\`.\`id\`=\`memberExecutivePositions\`.\`memberId\` LEFT JOIN \`salutation\` \`salutation\` ON \`salutation\`.\`id\`=\`member\`.\`salutationId\` - GROUP BY \`executivePosition\`.\`id\`, \`member\`.\`id\` + GROUP BY \`executivePosition\`.\`id\`, \`member\`.\`id\`, \`salutation\`.\`id\` + `, +}); + +export const member_executive_positions_view_postgres = new View({ + name: "member_executive_positions_view", + expression: ` + SELECT + "executivePosition"."id" AS "positionId", + "executivePosition"."position" AS "position", + "member"."id" AS "memberId", + "member"."firstname" AS "memberFirstname", + "member"."lastname" AS "memberLastname", + "member"."nameaffix" AS "memberNameaffix", + "member"."birthdate" AS "memberBirthdate", + "salutation"."salutation" AS "memberSalutation", + SUM(COALESCE("memberExecutivePositions"."end", CURRENT_DATE) - "memberExecutivePositions"."start") AS "durationInDays", + SUM(AGE(COALESCE("memberExecutivePositions"."end", CURRENT_DATE), "memberExecutivePositions"."start")) AS "durationInYears" + FROM "member_executive_positions" "memberExecutivePositions" + LEFT JOIN "executive_position" "executivePosition" ON "executivePosition"."id"="memberExecutivePositions"."executivePositionId" + LEFT JOIN "member" "member" ON "member"."id"="memberExecutivePositions"."memberId" + LEFT JOIN "salutation" "salutation" ON "salutation"."id"="member"."salutationId" + GROUP BY "executivePosition"."id", "member"."id", "salutation"."id" `, }); @@ -288,13 +315,35 @@ export const member_qualifications_view = new View({ \`member\`.\`nameaffix\` AS \`memberNameaffix\`, \`member\`.\`birthdate\` AS \`memberBirthdate\`, \`salutation\`.\`salutation\` AS \`memberSalutation\`, - SUM(TIMESTAMPDIFF(DAY, \`memberQualifications\`.\`start\`, - COALESCE(\`memberQualifications\`.\`end\`, CURRENT_DATE))) AS \`durationInDays\` + SUM(TIMESTAMPDIFF(DAY, \`memberQualifications\`.\`start\`, COALESCE(\`memberQualifications\`.\`end\`, CURRENT_DATE))) AS \`durationInDays\`, + CONCAT('_', FROM_DAYS(SUM(TIMESTAMPDIFF(DAY, \`memberQualifications\`.\`start\`, COALESCE(\`memberQualifications\`.\`end\`, CURRENT_DATE))))) AS \`durationInYears\` FROM \`member_qualifications\` \`memberQualifications\` LEFT JOIN \`qualification\` \`qualification\` ON \`qualification\`.\`id\`=\`memberQualifications\`.\`qualificationId\` LEFT JOIN \`member\` \`member\` ON \`member\`.\`id\`=\`memberQualifications\`.\`memberId\` LEFT JOIN \`salutation\` \`salutation\` ON \`salutation\`.\`id\`=\`member\`.\`salutationId\` - GROUP BY \`qualification\`.\`id\`, \`member\`.\`id\` + GROUP BY \`qualification\`.\`id\`, \`member\`.\`id\`, \`salutation\`.\`id\` + `, +}); + +export const member_qualifications_view_postgres = new View({ + name: "member_qualifications_view", + expression: ` + SELECT + "qualification"."id" AS "qualificationId", + "qualification"."qualification" AS "qualification", + "member"."id" AS "memberId", + "member"."firstname" AS "memberFirstname", + "member"."lastname" AS "memberLastname", + "member"."nameaffix" AS "memberNameaffix", + "member"."birthdate" AS "memberBirthdate", + "salutation"."salutation" AS "memberSalutation", + SUM(COALESCE("memberQualifications"."end", CURRENT_DATE) - "memberQualifications"."start") AS "durationInDays", + SUM(AGE(COALESCE("memberQualifications"."end", CURRENT_DATE), "memberQualifications"."start")) AS "durationInYears" + FROM "member_qualifications" "memberQualifications" + LEFT JOIN "qualification" "qualification" ON "qualification"."id"="memberQualifications"."qualificationId" + LEFT JOIN "member" "member" ON "member"."id"="memberQualifications"."memberId" + LEFT JOIN "salutation" "salutation" ON "salutation"."id"="member"."salutationId" + GROUP BY "qualification"."id", "member"."id", "salutation"."id" `, }); @@ -310,13 +359,34 @@ export const membership_view = new View({ \`member\`.\`nameaffix\` AS \`memberNameaffix\`, \`member\`.\`birthdate\` AS \`memberBirthdate\`, \`salutation\`.\`salutation\` AS \`memberSalutation\`, - SUM(TIMESTAMPDIFF(DAY, \`membership\`.\`start\`, - COALESCE(\`membership\`.\`end\`, CURRENT_DATE))) AS \`durationInDays\`, + SUM(TIMESTAMPDIFF(DAY, \`membership\`.\`start\`, COALESCE(\`membership\`.\`end\`, CURRENT_DATE))) AS \`durationInDays\`, CONCAT('_', FROM_DAYS(SUM(TIMESTAMPDIFF(DAY, \`membership\`.\`start\`, COALESCE(\`membership\`.\`end\`, CURRENT_DATE))))) AS \`durationInYears\` FROM \`membership\` \`membership\` LEFT JOIN \`membership_status\` \`status\` ON \`status\`.\`id\`=\`membership\`.\`statusId\` LEFT JOIN \`member\` \`member\` ON \`member\`.\`id\`=\`membership\`.\`memberId\` LEFT JOIN \`salutation\` \`salutation\` ON \`salutation\`.\`id\`=\`member\`.\`salutationId\` - GROUP BY \`status\`.\`id\`, \`member\`.\`id\` + GROUP BY \`status\`.\`id\`, \`member\`.\`id\`, \`salutation\`.\`id\` + `, +}); + +export const membership_view_postgres = new View({ + name: "membership_view", + expression: ` + SELECT + "status"."id" AS "statusId", + "status"."status" AS "status", + "member"."id" AS "memberId", + "member"."firstname" AS "memberFirstname", + "member"."lastname" AS "memberLastname", + "member"."nameaffix" AS "memberNameaffix", + "member"."birthdate" AS "memberBirthdate", + "salutation"."salutation" AS "memberSalutation", + SUM(COALESCE("membership"."end", CURRENT_DATE) - "membership"."start") AS "durationInDays", + SUM(AGE(COALESCE("membership"."end", CURRENT_DATE), "membership"."start")) AS "durationInYears" + FROM "membership" "membership" + LEFT JOIN "membership_status" "status" ON "status"."id"="membership"."statusId" + LEFT JOIN "member" "member" ON "member"."id"="membership"."memberId" + LEFT JOIN "salutation" "salutation" ON "salutation"."id"="member"."salutationId" + GROUP BY "status"."id","member"."id", "salutation"."id" `, }); diff --git a/src/migrations/baseSchemaTables/newsletter.ts b/src/migrations/baseSchemaTables/newsletter.ts index 5e39fcc..537428f 100644 --- a/src/migrations/baseSchemaTables/newsletter.ts +++ b/src/migrations/baseSchemaTables/newsletter.ts @@ -1,17 +1,17 @@ import { Table, TableForeignKey } from "typeorm"; -import { getTypeByORM } from "../ormHelper"; +import { getDefaultByORM, getTypeByORM, isIncrementPrimary } from "../ormHelper"; export const newsletter_table = new Table({ name: "newsletter", columns: [ - { name: "id", type: getTypeByORM("int"), isPrimary: true, isGenerated: true, generationStrategy: "increment" }, - { name: "title", type: getTypeByORM("varchar"), length: "255" }, - { name: "description", type: getTypeByORM("varchar"), length: "255", default: "''" }, - { name: "newsletterTitle", type: getTypeByORM("varchar"), length: "255", default: "''" }, - { name: "newsletterText", type: getTypeByORM("text"), default: "''" }, - { name: "newsletterSignatur", type: getTypeByORM("varchar"), length: "255", default: "''" }, - { name: "isSent", type: getTypeByORM("boolean"), default: false }, - { name: "recipientsByQueryId", type: getTypeByORM("int"), isNullable: true }, + { name: "id", ...getTypeByORM("int"), ...isIncrementPrimary }, + { name: "title", ...getTypeByORM("varchar") }, + { name: "description", ...getTypeByORM("varchar"), default: getDefaultByORM("string") }, + { name: "newsletterTitle", ...getTypeByORM("varchar"), default: getDefaultByORM("string") }, + { name: "newsletterText", ...getTypeByORM("text"), default: getDefaultByORM("string") }, + { name: "newsletterSignatur", ...getTypeByORM("varchar"), default: getDefaultByORM("string") }, + { name: "isSent", ...getTypeByORM("boolean"), default: getDefaultByORM("boolean", false) }, + { name: "recipientsByQueryId", ...getTypeByORM("int", true) }, ], foreignKeys: [ new TableForeignKey({ @@ -27,10 +27,10 @@ export const newsletter_table = new Table({ export const newsletter_dates_table = new Table({ name: "newsletter_dates", columns: [ - { name: "newsletterId", type: getTypeByORM("int"), isPrimary: true }, - { name: "calendarId", type: getTypeByORM("varchar"), length: "255", isPrimary: true }, - { name: "diffTitle", type: getTypeByORM("varchar"), length: "255", isNullable: true }, - { name: "diffDescription", type: getTypeByORM("text"), isNullable: true }, + { name: "newsletterId", ...getTypeByORM("int"), isPrimary: true }, + { name: "calendarId", ...getTypeByORM("uuid"), isPrimary: true }, + { name: "diffTitle", ...getTypeByORM("varchar"), isNullable: true }, + { name: "diffDescription", ...getTypeByORM("text", true) }, ], foreignKeys: [ new TableForeignKey({ @@ -53,8 +53,8 @@ export const newsletter_dates_table = new Table({ export const newsletter_recipients_table = new Table({ name: "newsletter_recipients", columns: [ - { name: "newsletterId", type: getTypeByORM("int"), isPrimary: true }, - { name: "memberId", type: getTypeByORM("varchar"), isPrimary: true }, + { name: "newsletterId", ...getTypeByORM("int"), isPrimary: true }, + { name: "memberId", ...getTypeByORM("uuid"), isPrimary: true }, ], foreignKeys: [ new TableForeignKey({ @@ -77,8 +77,8 @@ export const newsletter_recipients_table = new Table({ export const newsletter_config_table = new Table({ name: "newsletter_config", columns: [ - { name: "comTypeId", type: getTypeByORM("int"), isPrimary: true, isNullable: false }, - { name: "config", type: getTypeByORM("varchar"), length: "255", isNullable: false }, + { name: "comTypeId", ...getTypeByORM("int"), isPrimary: true }, + { name: "config", ...getTypeByORM("varchar") }, ], foreignKeys: [ new TableForeignKey({ diff --git a/src/migrations/baseSchemaTables/protocol.ts b/src/migrations/baseSchemaTables/protocol.ts index 2dee098..fd1cc89 100644 --- a/src/migrations/baseSchemaTables/protocol.ts +++ b/src/migrations/baseSchemaTables/protocol.ts @@ -1,25 +1,25 @@ import { Table, TableForeignKey } from "typeorm"; -import { getTypeByORM } from "../ormHelper"; +import { getDefaultByORM, getTypeByORM, isIncrementPrimary } from "../ormHelper"; export const protocol_table = new Table({ name: "protocol", columns: [ - { name: "id", type: getTypeByORM("int"), isPrimary: true, isGenerated: true, generationStrategy: "increment" }, - { name: "title", type: getTypeByORM("varchar"), length: "255", isNullable: false }, - { name: "date", type: getTypeByORM("date"), isNullable: false }, - { name: "starttime", type: getTypeByORM("time"), isNullable: true }, - { name: "endtime", type: getTypeByORM("time"), isNullable: true }, - { name: "summary", type: getTypeByORM("text"), isNullable: true }, + { name: "id", ...getTypeByORM("int"), ...isIncrementPrimary }, + { name: "title", ...getTypeByORM("varchar") }, + { name: "date", ...getTypeByORM("date") }, + { name: "starttime", ...getTypeByORM("time", true) }, + { name: "endtime", ...getTypeByORM("time", true) }, + { name: "summary", ...getTypeByORM("text", true) }, ], }); export const protocol_agenda_table = new Table({ name: "protocol_agenda", columns: [ - { name: "id", type: getTypeByORM("int"), isPrimary: true, isGenerated: true, generationStrategy: "increment" }, - { name: "topic", type: getTypeByORM("varchar"), length: "255", isNullable: false }, - { name: "context", type: getTypeByORM("text"), default: "''", isNullable: false }, - { name: "protocolId", type: getTypeByORM("int"), isNullable: false }, + { name: "id", ...getTypeByORM("int"), ...isIncrementPrimary }, + { name: "topic", ...getTypeByORM("varchar") }, + { name: "context", ...getTypeByORM("text"), default: getDefaultByORM("string") }, + { name: "protocolId", ...getTypeByORM("int") }, ], foreignKeys: [ new TableForeignKey({ @@ -35,10 +35,10 @@ export const protocol_agenda_table = new Table({ export const protocol_decision_table = new Table({ name: "protocol_decision", columns: [ - { name: "id", type: getTypeByORM("int"), isPrimary: true, isGenerated: true, generationStrategy: "increment" }, - { name: "topic", type: getTypeByORM("varchar"), length: "255", isNullable: false }, - { name: "context", type: getTypeByORM("text"), default: "''", isNullable: false }, - { name: "protocolId", type: getTypeByORM("int"), isNullable: false }, + { name: "id", ...getTypeByORM("int"), ...isIncrementPrimary }, + { name: "topic", ...getTypeByORM("varchar") }, + { name: "context", ...getTypeByORM("text"), default: getDefaultByORM("string") }, + { name: "protocolId", ...getTypeByORM("int") }, ], foreignKeys: [ new TableForeignKey({ @@ -54,10 +54,10 @@ export const protocol_decision_table = new Table({ export const protocol_presence_table = new Table({ name: "protocol_presence", columns: [ - { name: "memberId", type: getTypeByORM("varchar"), isPrimary: true }, - { name: "protocolId", type: getTypeByORM("int"), isPrimary: true }, - { name: "absent", type: getTypeByORM("boolean"), default: false, isNullable: false }, - { name: "excused", type: getTypeByORM("boolean"), default: false, isNullable: false }, + { name: "memberId", ...getTypeByORM("uuid"), isPrimary: true }, + { name: "protocolId", ...getTypeByORM("int"), isPrimary: true }, + { name: "absent", ...getTypeByORM("boolean"), default: getDefaultByORM("boolean", false) }, + { name: "excused", ...getTypeByORM("boolean"), default: getDefaultByORM("boolean", true) }, ], foreignKeys: [ new TableForeignKey({ @@ -80,13 +80,13 @@ export const protocol_presence_table = new Table({ export const protocol_voting_table = new Table({ name: "protocol_voting", columns: [ - { name: "id", type: getTypeByORM("int"), isPrimary: true, isGenerated: true, generationStrategy: "increment" }, - { name: "topic", type: getTypeByORM("varchar"), length: "255", isNullable: false }, - { name: "context", type: getTypeByORM("text"), default: "''", isNullable: false }, - { name: "favour", type: getTypeByORM("int"), default: 0, isNullable: false }, - { name: "abstain", type: getTypeByORM("int"), default: 0, isNullable: false }, - { name: "against", type: getTypeByORM("int"), default: 0, isNullable: false }, - { name: "protocolId", type: getTypeByORM("int"), isNullable: false }, + { name: "id", ...getTypeByORM("int"), ...isIncrementPrimary }, + { name: "topic", ...getTypeByORM("varchar") }, + { name: "context", ...getTypeByORM("text"), default: getDefaultByORM("string") }, + { name: "favour", ...getTypeByORM("int"), default: getDefaultByORM("number", 0) }, + { name: "abstain", ...getTypeByORM("int"), default: getDefaultByORM("number", 0) }, + { name: "against", ...getTypeByORM("int"), default: getDefaultByORM("number", 0) }, + { name: "protocolId", ...getTypeByORM("int") }, ], foreignKeys: [ new TableForeignKey({ @@ -102,12 +102,12 @@ export const protocol_voting_table = new Table({ export const protocol_printout_table = new Table({ name: "protocol_printout", columns: [ - { name: "id", type: getTypeByORM("int"), isPrimary: true, isGenerated: true, generationStrategy: "increment" }, - { name: "title", type: getTypeByORM("varchar"), length: "255", isNullable: false }, - { name: "iteration", type: getTypeByORM("int"), default: 1, isNullable: false }, - { name: "filename", type: getTypeByORM("varchar"), length: "255", isNullable: false }, - { name: "createdAt", type: getTypeByORM("datetime"), isNullable: false, default: "CURRENT_TIMESTAMP(6)" }, - { name: "protocolId", type: getTypeByORM("int"), isNullable: false }, + { name: "id", ...getTypeByORM("int"), ...isIncrementPrimary }, + { name: "title", ...getTypeByORM("varchar") }, + { name: "iteration", ...getTypeByORM("int"), default: getDefaultByORM("number", 1) }, + { name: "filename", ...getTypeByORM("varchar") }, + { name: "createdAt", ...getTypeByORM("datetime", false, 6), default: getDefaultByORM("currentTimestamp", 6) }, + { name: "protocolId", ...getTypeByORM("int") }, ], foreignKeys: [ new TableForeignKey({ diff --git a/src/migrations/baseSchemaTables/query_template.ts b/src/migrations/baseSchemaTables/query_template.ts index 399b34b..da4eb44 100644 --- a/src/migrations/baseSchemaTables/query_template.ts +++ b/src/migrations/baseSchemaTables/query_template.ts @@ -1,35 +1,35 @@ import { Table, TableForeignKey } from "typeorm"; -import { getTypeByORM } from "../ormHelper"; +import { getDefaultByORM, getTypeByORM, isIncrementPrimary } from "../ormHelper"; export const query_table = new Table({ name: "query", columns: [ - { name: "id", type: getTypeByORM("int"), isPrimary: true, isGenerated: true, generationStrategy: "increment" }, - { name: "title", type: getTypeByORM("varchar"), length: "255", isNullable: false, isUnique: true }, - { name: "query", type: getTypeByORM("text"), isNullable: false, default: "''" }, + { name: "id", ...getTypeByORM("int"), ...isIncrementPrimary }, + { name: "title", ...getTypeByORM("varchar"), isUnique: true }, + { name: "query", ...getTypeByORM("text"), default: getDefaultByORM("string") }, ], }); export const template_table = new Table({ name: "template", columns: [ - { name: "id", type: getTypeByORM("int"), isPrimary: true, isGenerated: true, generationStrategy: "increment" }, - { name: "template", type: getTypeByORM("varchar"), length: "255", isNullable: false, isUnique: true }, - { name: "description", type: getTypeByORM("varchar"), length: "255", isNullable: true }, - { name: "design", type: getTypeByORM("text"), isNullable: false, default: "'{}'" }, - { name: "html", type: getTypeByORM("text"), isNullable: false, default: "''" }, + { name: "id", ...getTypeByORM("int"), ...isIncrementPrimary }, + { name: "template", ...getTypeByORM("varchar"), isUnique: true }, + { name: "description", ...getTypeByORM("varchar", true) }, + { name: "design", ...getTypeByORM("text"), default: getDefaultByORM("string", "{}") }, + { name: "html", ...getTypeByORM("text"), default: getDefaultByORM("string") }, ], }); export const template_usage_table = new Table({ name: "template_usage", columns: [ - { name: "scope", type: getTypeByORM("varchar"), length: "255", isPrimary: true }, - { name: "headerId", type: getTypeByORM("int"), isNullable: true }, - { name: "bodyId", type: getTypeByORM("int"), isNullable: true }, - { name: "footerId", type: getTypeByORM("int"), isNullable: true }, - { name: "headerHeight", type: getTypeByORM("int"), default: null, isNullable: true }, - { name: "footerHeight", type: getTypeByORM("int"), default: null, isNullable: true }, + { name: "scope", ...getTypeByORM("varchar"), isPrimary: true }, + { name: "headerId", ...getTypeByORM("int", true), default: getDefaultByORM("null") }, + { name: "bodyId", ...getTypeByORM("int", true), default: getDefaultByORM("null") }, + { name: "footerId", ...getTypeByORM("int", true), default: getDefaultByORM("null") }, + { name: "headerHeight", ...getTypeByORM("int", true), default: getDefaultByORM("null") }, + { name: "footerHeight", ...getTypeByORM("int", true), default: getDefaultByORM("null") }, ], foreignKeys: [ new TableForeignKey({ diff --git a/src/migrations/ormHelper.ts b/src/migrations/ormHelper.ts index d4c7f43..20a57ad 100644 --- a/src/migrations/ormHelper.ts +++ b/src/migrations/ormHelper.ts @@ -1,6 +1,18 @@ -export type ORMType = "int" | "bigint" | "boolean" | "date" | "datetime" | "time" | "text" | "varchar"; +export type ORMType = "int" | "bigint" | "boolean" | "date" | "datetime" | "time" | "text" | "varchar" | "uuid"; +export type ORMDefault = "currentTimestamp" | "string" | "boolean" | "number" | "null"; +export type ColumnConfig = { + type: string; + length?: string; + precision?: number; + isNullable: boolean; +}; +export type Primary = { + isPrimary: boolean; + isGenerated: boolean; + generationStrategy: "increment" | "uuid" | "rowid" | "identity"; +}; -export function getTypeByORM(type: ORMType): string { +export function getTypeByORM(type: ORMType, nullable: boolean = false, length: number = 255): ColumnConfig { const dbType = process.env.DB_TYPE; const typeMap: Record> = { @@ -13,6 +25,7 @@ export function getTypeByORM(type: ORMType): string { time: "time", text: "text", varchar: "varchar", + uuid: "varchar", }, postgres: { int: "integer", @@ -22,19 +35,71 @@ export function getTypeByORM(type: ORMType): string { datetime: "timestamp", time: "time", text: "text", - varchar: "varchar", + varchar: "character varying", + uuid: "uuid", }, sqlite: { int: "integer", bigint: "integer", boolean: "integer", - date: "text", - datetime: "text", + date: "date", + datetime: "datetime", time: "text", text: "text", - varchar: "text", + varchar: "varchar", + uuid: "varchar", }, }; - return typeMap[dbType]?.[type] || type; + let obj: ColumnConfig = { + type: typeMap[dbType]?.[type] || type, + isNullable: nullable, + }; + if (type == "datetime") obj.precision = length; + else if (dbType != "sqlite" && (obj.type == "varchar" || type == "varchar")) obj.length = `${length}`; + else if (dbType != "postgres" && type == "uuid") obj.length = "36"; + + return obj; } + +export function getDefaultByORM(type: ORMDefault, data?: string | number | boolean): T { + const dbType = process.env.DB_TYPE; + + const typeMap: Record> = { + mysql: { + currentTimestamp: `CURRENT_TIMESTAMP(${data ?? 6})`, + string: `'${data ?? ""}'`, + boolean: Boolean(data).toString(), + number: Number(data).toString(), + null: null, + }, + postgres: { + currentTimestamp: `now()`, + string: `'${data ?? ""}'`, + boolean: Boolean(data) == true ? "true" : "false", + number: Number(data).toString(), + null: null, + }, + sqlite: { + currentTimestamp: `datetime('now')`, + string: `'${data ?? ""}'`, + boolean: Boolean(data) == true ? "1" : "0", + number: Number(data).toString(), + null: null, + }, + }; + + return (typeMap[dbType]?.[type] || type) as T; +} + +export const isIncrementPrimary: Primary = { + isPrimary: true, + isGenerated: true, + generationStrategy: "increment", +}; + +export const isUUIDPrimary: Primary = { + isPrimary: true, + isGenerated: true, + generationStrategy: "uuid", +}; diff --git a/src/views/memberExecutivePositionView.ts b/src/views/memberExecutivePositionView.ts index 6bac173..610fe34 100644 --- a/src/views/memberExecutivePositionView.ts +++ b/src/views/memberExecutivePositionView.ts @@ -1,5 +1,6 @@ import { DataSource, ViewColumn, ViewEntity } from "typeorm"; import { memberExecutivePositions } from "../entity/club/member/memberExecutivePositions"; +import { DB_TYPE } from "../env.defaults"; @ViewEntity({ expression: (datasource: DataSource) => @@ -15,19 +16,31 @@ import { memberExecutivePositions } from "../entity/club/member/memberExecutiveP .addSelect("member.birthdate", "memberBirthdate") .addSelect("salutation.salutation", "memberSalutation") .addSelect( - "SUM(TIMESTAMPDIFF(DAY, memberExecutivePositions.start, COALESCE(memberExecutivePositions.end, CURRENT_DATE)))", + DB_TYPE == "postgres" + ? `SUM(COALESCE("memberExecutivePositions"."end", CURRENT_DATE) - "memberExecutivePositions"."start")` + : "SUM(TIMESTAMPDIFF(DAY, memberExecutivePositions.start, COALESCE(memberExecutivePositions.end, CURRENT_DATE)))", "durationInDays" ) + .addSelect( + DB_TYPE == "postgres" + ? `SUM(AGE(COALESCE("memberExecutivePositions"."end", CURRENT_DATE), "memberExecutivePositions"."start"))` + : "CONCAT('_', FROM_DAYS(SUM(TIMESTAMPDIFF(DAY, memberExecutivePositions.start, COALESCE(memberExecutivePositions.end, CURRENT_DATE)))))", + "durationInYears" + ) .leftJoin("memberExecutivePositions.executivePosition", "executivePosition") .leftJoin("memberExecutivePositions.member", "member") .leftJoin("member.salutation", "salutation") .groupBy("executivePosition.id") - .addGroupBy("member.id"), + .addGroupBy("member.id") + .addGroupBy("salutation.id"), }) export class memberExecutivePositionsView { @ViewColumn() durationInDays: number; + @ViewColumn() + durationInYears: string; + @ViewColumn() position: string; diff --git a/src/views/memberQualificationsView.ts b/src/views/memberQualificationsView.ts index 9db700c..1e6dd55 100644 --- a/src/views/memberQualificationsView.ts +++ b/src/views/memberQualificationsView.ts @@ -1,5 +1,6 @@ import { DataSource, ViewColumn, ViewEntity } from "typeorm"; import { memberQualifications } from "../entity/club/member/memberQualifications"; +import { DB_TYPE } from "../env.defaults"; @ViewEntity({ expression: (datasource: DataSource) => @@ -15,19 +16,31 @@ import { memberQualifications } from "../entity/club/member/memberQualifications .addSelect("member.birthdate", "memberBirthdate") .addSelect("salutation.salutation", "memberSalutation") .addSelect( - "SUM(TIMESTAMPDIFF(DAY, memberQualifications.start, COALESCE(memberQualifications.end, CURRENT_DATE)))", + DB_TYPE == "postgres" + ? `SUM(COALESCE("memberQualifications"."end", CURRENT_DATE) - "memberQualifications"."start")` + : "SUM(TIMESTAMPDIFF(DAY, memberQualifications.start, COALESCE(memberQualifications.end, CURRENT_DATE)))", "durationInDays" ) + .addSelect( + DB_TYPE == "postgres" + ? `SUM(AGE(COALESCE("memberQualifications"."end", CURRENT_DATE), "memberQualifications"."start"))` + : "CONCAT('_', FROM_DAYS(SUM(TIMESTAMPDIFF(DAY, memberQualifications.start, COALESCE(memberQualifications.end, CURRENT_DATE)))))", + "durationInYears" + ) .leftJoin("memberQualifications.qualification", "qualification") .leftJoin("memberQualifications.member", "member") .leftJoin("member.salutation", "salutation") .groupBy("qualification.id") - .addGroupBy("member.id"), + .addGroupBy("member.id") + .addGroupBy("salutation.id"), }) export class memberQualificationsView { @ViewColumn() durationInDays: number; + @ViewColumn() + durationInYears: string; + @ViewColumn() qualification: string; diff --git a/src/views/memberView.ts b/src/views/memberView.ts index 74be622..11de1e8 100644 --- a/src/views/memberView.ts +++ b/src/views/memberView.ts @@ -1,5 +1,6 @@ import { DataSource, ViewColumn, ViewEntity } from "typeorm"; import { member } from "../entity/club/member/member"; +import { DB_TYPE } from "../env.defaults"; @ViewEntity({ expression: (datasource: DataSource) => @@ -12,9 +13,24 @@ import { member } from "../entity/club/member/member"; .addSelect("member.nameaffix", "nameaffix") .addSelect("member.birthdate", "birthdate") .addSelect("salutation.salutation", "salutation") - .addSelect("TIMESTAMPDIFF(YEAR, member.birthdate, CURDATE())", "todayAge") - .addSelect("YEAR(CURDATE()) - YEAR(member.birthdate)", "ageThisYear") - .addSelect("CONCAT('_', FROM_DAYS(TIMESTAMPDIFF(DAY, member.birthdate, CURDATE())))", "exactAge") + .addSelect( + DB_TYPE == "postgres" + ? `DATE_PART('year', AGE(CURRENT_DATE, member.birthdate))` + : "TIMESTAMPDIFF(YEAR, member.birthdate, CURDATE())", + "todayAge" + ) + .addSelect( + DB_TYPE == "postgres" + ? `EXTRACT(YEAR FROM CURRENT_DATE) - EXTRACT(YEAR FROM member.birthdate)` + : "YEAR(CURDATE()) - YEAR(member.birthdate)", + "ageThisYear" + ) + .addSelect( + DB_TYPE == "postgres" + ? `AGE(CURRENT_DATE, member.birthdate)` + : "CONCAT('_', FROM_DAYS(TIMESTAMPDIFF(DAY, member.birthdate, CURDATE())))", + "exactAge" + ) .leftJoin("member.salutation", "salutation"), }) export class memberView { diff --git a/src/views/membershipsView.ts b/src/views/membershipsView.ts index 52ebcc7..5a614de 100644 --- a/src/views/membershipsView.ts +++ b/src/views/membershipsView.ts @@ -1,5 +1,6 @@ import { DataSource, ViewColumn, ViewEntity } from "typeorm"; import { membership } from "../entity/club/member/membership"; +import { DB_TYPE } from "../env.defaults"; @ViewEntity({ expression: (datasource: DataSource) => @@ -14,16 +15,24 @@ import { membership } from "../entity/club/member/membership"; .addSelect("member.nameaffix", "memberNameaffix") .addSelect("member.birthdate", "memberBirthdate") .addSelect("salutation.salutation", "memberSalutation") - .addSelect("SUM(TIMESTAMPDIFF(DAY, membership.start, COALESCE(membership.end, CURRENT_DATE)))", "durationInDays") .addSelect( - "CONCAT('_', FROM_DAYS(SUM(TIMESTAMPDIFF(DAY, membership.start, COALESCE(membership.end, CURRENT_DATE)))))", + DB_TYPE == "postgres" + ? `SUM(COALESCE("membership"."end", CURRENT_DATE) - "membership"."start") ` + : "SUM(TIMESTAMPDIFF(DAY, membership.start, COALESCE(membership.end, CURRENT_DATE)))", + "durationInDays" + ) + .addSelect( + DB_TYPE == "postgres" + ? `SUM(AGE(COALESCE("membership"."end", CURRENT_DATE), "membership"."start"))` + : "CONCAT('_', FROM_DAYS(SUM(TIMESTAMPDIFF(DAY, membership.start, COALESCE(membership.end, CURRENT_DATE)))))", "durationInYears" ) .leftJoin("membership.status", "status") .leftJoin("membership.member", "member") .leftJoin("member.salutation", "salutation") .groupBy("status.id") - .addGroupBy("member.id"), + .addGroupBy("member.id") + .addGroupBy("salutation.id"), }) export class membershipView { @ViewColumn()