diff --git a/package-lock.json b/package-lock.json index e870b472..e1387396 100644 --- a/package-lock.json +++ b/package-lock.json @@ -56,6 +56,7 @@ "prettier": "^2.8.4", "prisma": "^4.9.0", "semantic-release": "^19.0.5", + "tsx": "^3.12.3", "typescript": "^4.9.4", "wait-on": "^7.0.1" }, @@ -1825,6 +1826,388 @@ "resolved": "https://registry.npmjs.org/@emotion/weak-memoize/-/weak-memoize-0.3.0.tgz", "integrity": "sha512-AHPmaAx+RYfZz0eYu6Gviiagpmiyw98ySSlQvCUhVGDRtDFe4DBS0x1bSjdF3gqUDYOczB+yYvBTtEylYSdRhg==" }, + "node_modules/@esbuild-kit/cjs-loader": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/@esbuild-kit/cjs-loader/-/cjs-loader-2.4.2.tgz", + "integrity": "sha512-BDXFbYOJzT/NBEtp71cvsrGPwGAMGRB/349rwKuoxNSiKjPraNNnlK6MIIabViCjqZugu6j+xeMDlEkWdHHJSg==", + "dev": true, + "dependencies": { + "@esbuild-kit/core-utils": "^3.0.0", + "get-tsconfig": "^4.4.0" + } + }, + "node_modules/@esbuild-kit/core-utils": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/@esbuild-kit/core-utils/-/core-utils-3.1.0.tgz", + "integrity": "sha512-Uuk8RpCg/7fdHSceR1M6XbSZFSuMrxcePFuGgyvsBn+u339dk5OeL4jv2EojwTN2st/unJGsVm4qHWjWNmJ/tw==", + "dev": true, + "dependencies": { + "esbuild": "~0.17.6", + "source-map-support": "^0.5.21" + } + }, + "node_modules/@esbuild-kit/esm-loader": { + "version": "2.5.5", + "resolved": "https://registry.npmjs.org/@esbuild-kit/esm-loader/-/esm-loader-2.5.5.tgz", + "integrity": "sha512-Qwfvj/qoPbClxCRNuac1Du01r9gvNOT+pMYtJDapfB1eoGN1YlJ1BixLyL9WVENRx5RXgNLdfYdx/CuswlGhMw==", + "dev": true, + "dependencies": { + "@esbuild-kit/core-utils": "^3.0.0", + "get-tsconfig": "^4.4.0" + } + }, + "node_modules/@esbuild/android-arm": { + "version": "0.17.8", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.17.8.tgz", + "integrity": "sha512-0/rb91GYKhrtbeglJXOhAv9RuYimgI8h623TplY2X+vA4EXnk3Zj1fXZreJ0J3OJJu1bwmb0W7g+2cT/d8/l/w==", + "cpu": [ + "arm" + ], + "dev": true, + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/android-arm64": { + "version": "0.17.8", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.17.8.tgz", + "integrity": "sha512-oa/N5j6v1svZQs7EIRPqR8f+Bf8g6HBDjD/xHC02radE/NjKHK7oQmtmLxPs1iVwYyvE+Kolo6lbpfEQ9xnhxQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/android-x64": { + "version": "0.17.8", + "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.17.8.tgz", + "integrity": "sha512-bTliMLqD7pTOoPg4zZkXqCDuzIUguEWLpeqkNfC41ODBHwoUgZ2w5JBeYimv4oP6TDVocoYmEhZrCLQTrH89bg==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/darwin-arm64": { + "version": "0.17.8", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.17.8.tgz", + "integrity": "sha512-ghAbV3ia2zybEefXRRm7+lx8J/rnupZT0gp9CaGy/3iolEXkJ6LYRq4IpQVI9zR97ID80KJVoUlo3LSeA/sMAg==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/darwin-x64": { + "version": "0.17.8", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.17.8.tgz", + "integrity": "sha512-n5WOpyvZ9TIdv2V1K3/iIkkJeKmUpKaCTdun9buhGRWfH//osmUjlv4Z5mmWdPWind/VGcVxTHtLfLCOohsOXw==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/freebsd-arm64": { + "version": "0.17.8", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.17.8.tgz", + "integrity": "sha512-a/SATTaOhPIPFWvHZDoZYgxaZRVHn0/LX1fHLGfZ6C13JqFUZ3K6SMD6/HCtwOQ8HnsNaEeokdiDSFLuizqv5A==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/freebsd-x64": { + "version": "0.17.8", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.17.8.tgz", + "integrity": "sha512-xpFJb08dfXr5+rZc4E+ooZmayBW6R3q59daCpKZ/cDU96/kvDM+vkYzNeTJCGd8rtO6fHWMq5Rcv/1cY6p6/0Q==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-arm": { + "version": "0.17.8", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.17.8.tgz", + "integrity": "sha512-6Ij8gfuGszcEwZpi5jQIJCVIACLS8Tz2chnEBfYjlmMzVsfqBP1iGmHQPp7JSnZg5xxK9tjCc+pJ2WtAmPRFVA==", + "cpu": [ + "arm" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-arm64": { + "version": "0.17.8", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.17.8.tgz", + "integrity": "sha512-v3iwDQuDljLTxpsqQDl3fl/yihjPAyOguxuloON9kFHYwopeJEf1BkDXODzYyXEI19gisEsQlG1bM65YqKSIww==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-ia32": { + "version": "0.17.8", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.17.8.tgz", + "integrity": "sha512-8svILYKhE5XetuFk/B6raFYIyIqydQi+GngEXJgdPdI7OMKUbSd7uzR02wSY4kb53xBrClLkhH4Xs8P61Q2BaA==", + "cpu": [ + "ia32" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-loong64": { + "version": "0.17.8", + "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.17.8.tgz", + "integrity": "sha512-B6FyMeRJeV0NpyEOYlm5qtQfxbdlgmiGdD+QsipzKfFky0K5HW5Td6dyK3L3ypu1eY4kOmo7wW0o94SBqlqBSA==", + "cpu": [ + "loong64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-mips64el": { + "version": "0.17.8", + "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.17.8.tgz", + "integrity": "sha512-CCb67RKahNobjm/eeEqeD/oJfJlrWyw29fgiyB6vcgyq97YAf3gCOuP6qMShYSPXgnlZe/i4a8WFHBw6N8bYAA==", + "cpu": [ + "mips64el" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-ppc64": { + "version": "0.17.8", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.17.8.tgz", + "integrity": "sha512-bytLJOi55y55+mGSdgwZ5qBm0K9WOCh0rx+vavVPx+gqLLhxtSFU0XbeYy/dsAAD6xECGEv4IQeFILaSS2auXw==", + "cpu": [ + "ppc64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-riscv64": { + "version": "0.17.8", + "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.17.8.tgz", + "integrity": "sha512-2YpRyQJmKVBEHSBLa8kBAtbhucaclb6ex4wchfY0Tj3Kg39kpjeJ9vhRU7x4mUpq8ISLXRXH1L0dBYjAeqzZAw==", + "cpu": [ + "riscv64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-s390x": { + "version": "0.17.8", + "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.17.8.tgz", + "integrity": "sha512-QgbNY/V3IFXvNf11SS6exkpVcX0LJcob+0RWCgV9OiDAmVElnxciHIisoSix9uzYzScPmS6dJFbZULdSAEkQVw==", + "cpu": [ + "s390x" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-x64": { + "version": "0.17.8", + "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.17.8.tgz", + "integrity": "sha512-mM/9S0SbAFDBc4OPoyP6SEOo5324LpUxdpeIUUSrSTOfhHU9hEfqRngmKgqILqwx/0DVJBzeNW7HmLEWp9vcOA==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/netbsd-x64": { + "version": "0.17.8", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.17.8.tgz", + "integrity": "sha512-eKUYcWaWTaYr9zbj8GertdVtlt1DTS1gNBWov+iQfWuWyuu59YN6gSEJvFzC5ESJ4kMcKR0uqWThKUn5o8We6Q==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "netbsd" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/openbsd-x64": { + "version": "0.17.8", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.17.8.tgz", + "integrity": "sha512-Vc9J4dXOboDyMXKD0eCeW0SIeEzr8K9oTHJU+Ci1mZc5njPfhKAqkRt3B/fUNU7dP+mRyralPu8QUkiaQn7iIg==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "openbsd" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/sunos-x64": { + "version": "0.17.8", + "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.17.8.tgz", + "integrity": "sha512-0xvOTNuPXI7ft1LYUgiaXtpCEjp90RuBBYovdd2lqAFxje4sEucurg30M1WIm03+3jxByd3mfo+VUmPtRSVuOw==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "sunos" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/win32-arm64": { + "version": "0.17.8", + "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.17.8.tgz", + "integrity": "sha512-G0JQwUI5WdEFEnYNKzklxtBheCPkuDdu1YrtRrjuQv30WsYbkkoixKxLLv8qhJmNI+ATEWquZe/N0d0rpr55Mg==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/win32-ia32": { + "version": "0.17.8", + "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.17.8.tgz", + "integrity": "sha512-Fqy63515xl20OHGFykjJsMnoIWS+38fqfg88ClvPXyDbLtgXal2DTlhb1TfTX34qWi3u4I7Cq563QcHpqgLx8w==", + "cpu": [ + "ia32" + ], + "dev": true, + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/win32-x64": { + "version": "0.17.8", + "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.17.8.tgz", + "integrity": "sha512-1iuezdyDNngPnz8rLRDO2C/ZZ/emJLb72OsZeqQ6gL6Avko/XCXZw+NuxBSNhBAP13Hie418V7VMt9et1FMvpg==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=12" + } + }, "node_modules/@eslint/eslintrc": { "version": "1.4.1", "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-1.4.1.tgz", @@ -3721,6 +4104,12 @@ "node": "^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7" } }, + "node_modules/buffer-from": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz", + "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==", + "dev": true + }, "node_modules/call-bind": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.2.tgz", @@ -4739,6 +5128,43 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/esbuild": { + "version": "0.17.8", + "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.17.8.tgz", + "integrity": "sha512-g24ybC3fWhZddZK6R3uD2iF/RIPnRpwJAqLov6ouX3hMbY4+tKolP0VMF3zuIYCaXun+yHwS5IPQ91N2BT191g==", + "dev": true, + "hasInstallScript": true, + "bin": { + "esbuild": "bin/esbuild" + }, + "engines": { + "node": ">=12" + }, + "optionalDependencies": { + "@esbuild/android-arm": "0.17.8", + "@esbuild/android-arm64": "0.17.8", + "@esbuild/android-x64": "0.17.8", + "@esbuild/darwin-arm64": "0.17.8", + "@esbuild/darwin-x64": "0.17.8", + "@esbuild/freebsd-arm64": "0.17.8", + "@esbuild/freebsd-x64": "0.17.8", + "@esbuild/linux-arm": "0.17.8", + "@esbuild/linux-arm64": "0.17.8", + "@esbuild/linux-ia32": "0.17.8", + "@esbuild/linux-loong64": "0.17.8", + "@esbuild/linux-mips64el": "0.17.8", + "@esbuild/linux-ppc64": "0.17.8", + "@esbuild/linux-riscv64": "0.17.8", + "@esbuild/linux-s390x": "0.17.8", + "@esbuild/linux-x64": "0.17.8", + "@esbuild/netbsd-x64": "0.17.8", + "@esbuild/openbsd-x64": "0.17.8", + "@esbuild/sunos-x64": "0.17.8", + "@esbuild/win32-arm64": "0.17.8", + "@esbuild/win32-ia32": "0.17.8", + "@esbuild/win32-x64": "0.17.8" + } + }, "node_modules/escalade": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz", @@ -5591,6 +6017,19 @@ "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==", "dev": true }, + "node_modules/fsevents": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz", + "integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==", + "hasInstallScript": true, + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": "^8.16.0 || ^10.6.0 || >=11.0.0" + } + }, "node_modules/function-bind": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", @@ -12092,6 +12531,25 @@ "node": ">=0.10.0" } }, + "node_modules/source-map-support": { + "version": "0.5.21", + "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.21.tgz", + "integrity": "sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==", + "dev": true, + "dependencies": { + "buffer-from": "^1.0.0", + "source-map": "^0.6.0" + } + }, + "node_modules/source-map-support/node_modules/source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/spawn-error-forwarder": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/spawn-error-forwarder/-/spawn-error-forwarder-1.0.0.tgz", @@ -12666,6 +13124,23 @@ "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==", "dev": true }, + "node_modules/tsx": { + "version": "3.12.3", + "resolved": "https://registry.npmjs.org/tsx/-/tsx-3.12.3.tgz", + "integrity": "sha512-Wc5BFH1xccYTXaQob+lEcimkcb/Pq+0en2s+ruiX0VEIC80nV7/0s7XRahx8NnsoCnpCVUPz8wrqVSPi760LkA==", + "dev": true, + "dependencies": { + "@esbuild-kit/cjs-loader": "^2.4.2", + "@esbuild-kit/core-utils": "^3.0.0", + "@esbuild-kit/esm-loader": "^2.5.5" + }, + "bin": { + "tsx": "dist/cli.js" + }, + "optionalDependencies": { + "fsevents": "~2.3.2" + } + }, "node_modules/type-check": { "version": "0.4.0", "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz", @@ -14509,6 +14984,190 @@ "resolved": "https://registry.npmjs.org/@emotion/weak-memoize/-/weak-memoize-0.3.0.tgz", "integrity": "sha512-AHPmaAx+RYfZz0eYu6Gviiagpmiyw98ySSlQvCUhVGDRtDFe4DBS0x1bSjdF3gqUDYOczB+yYvBTtEylYSdRhg==" }, + "@esbuild-kit/cjs-loader": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/@esbuild-kit/cjs-loader/-/cjs-loader-2.4.2.tgz", + "integrity": "sha512-BDXFbYOJzT/NBEtp71cvsrGPwGAMGRB/349rwKuoxNSiKjPraNNnlK6MIIabViCjqZugu6j+xeMDlEkWdHHJSg==", + "dev": true, + "requires": { + "@esbuild-kit/core-utils": "^3.0.0", + "get-tsconfig": "^4.4.0" + } + }, + "@esbuild-kit/core-utils": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/@esbuild-kit/core-utils/-/core-utils-3.1.0.tgz", + "integrity": "sha512-Uuk8RpCg/7fdHSceR1M6XbSZFSuMrxcePFuGgyvsBn+u339dk5OeL4jv2EojwTN2st/unJGsVm4qHWjWNmJ/tw==", + "dev": true, + "requires": { + "esbuild": "~0.17.6", + "source-map-support": "^0.5.21" + } + }, + "@esbuild-kit/esm-loader": { + "version": "2.5.5", + "resolved": "https://registry.npmjs.org/@esbuild-kit/esm-loader/-/esm-loader-2.5.5.tgz", + "integrity": "sha512-Qwfvj/qoPbClxCRNuac1Du01r9gvNOT+pMYtJDapfB1eoGN1YlJ1BixLyL9WVENRx5RXgNLdfYdx/CuswlGhMw==", + "dev": true, + "requires": { + "@esbuild-kit/core-utils": "^3.0.0", + "get-tsconfig": "^4.4.0" + } + }, + "@esbuild/android-arm": { + "version": "0.17.8", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.17.8.tgz", + "integrity": "sha512-0/rb91GYKhrtbeglJXOhAv9RuYimgI8h623TplY2X+vA4EXnk3Zj1fXZreJ0J3OJJu1bwmb0W7g+2cT/d8/l/w==", + "dev": true, + "optional": true + }, + "@esbuild/android-arm64": { + "version": "0.17.8", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.17.8.tgz", + "integrity": "sha512-oa/N5j6v1svZQs7EIRPqR8f+Bf8g6HBDjD/xHC02radE/NjKHK7oQmtmLxPs1iVwYyvE+Kolo6lbpfEQ9xnhxQ==", + "dev": true, + "optional": true + }, + "@esbuild/android-x64": { + "version": "0.17.8", + "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.17.8.tgz", + "integrity": "sha512-bTliMLqD7pTOoPg4zZkXqCDuzIUguEWLpeqkNfC41ODBHwoUgZ2w5JBeYimv4oP6TDVocoYmEhZrCLQTrH89bg==", + "dev": true, + "optional": true + }, + "@esbuild/darwin-arm64": { + "version": "0.17.8", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.17.8.tgz", + "integrity": "sha512-ghAbV3ia2zybEefXRRm7+lx8J/rnupZT0gp9CaGy/3iolEXkJ6LYRq4IpQVI9zR97ID80KJVoUlo3LSeA/sMAg==", + "dev": true, + "optional": true + }, + "@esbuild/darwin-x64": { + "version": "0.17.8", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.17.8.tgz", + "integrity": "sha512-n5WOpyvZ9TIdv2V1K3/iIkkJeKmUpKaCTdun9buhGRWfH//osmUjlv4Z5mmWdPWind/VGcVxTHtLfLCOohsOXw==", + "dev": true, + "optional": true + }, + "@esbuild/freebsd-arm64": { + "version": "0.17.8", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.17.8.tgz", + "integrity": "sha512-a/SATTaOhPIPFWvHZDoZYgxaZRVHn0/LX1fHLGfZ6C13JqFUZ3K6SMD6/HCtwOQ8HnsNaEeokdiDSFLuizqv5A==", + "dev": true, + "optional": true + }, + "@esbuild/freebsd-x64": { + "version": "0.17.8", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.17.8.tgz", + "integrity": "sha512-xpFJb08dfXr5+rZc4E+ooZmayBW6R3q59daCpKZ/cDU96/kvDM+vkYzNeTJCGd8rtO6fHWMq5Rcv/1cY6p6/0Q==", + "dev": true, + "optional": true + }, + "@esbuild/linux-arm": { + "version": "0.17.8", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.17.8.tgz", + "integrity": "sha512-6Ij8gfuGszcEwZpi5jQIJCVIACLS8Tz2chnEBfYjlmMzVsfqBP1iGmHQPp7JSnZg5xxK9tjCc+pJ2WtAmPRFVA==", + "dev": true, + "optional": true + }, + "@esbuild/linux-arm64": { + "version": "0.17.8", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.17.8.tgz", + "integrity": "sha512-v3iwDQuDljLTxpsqQDl3fl/yihjPAyOguxuloON9kFHYwopeJEf1BkDXODzYyXEI19gisEsQlG1bM65YqKSIww==", + "dev": true, + "optional": true + }, + "@esbuild/linux-ia32": { + "version": "0.17.8", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.17.8.tgz", + "integrity": "sha512-8svILYKhE5XetuFk/B6raFYIyIqydQi+GngEXJgdPdI7OMKUbSd7uzR02wSY4kb53xBrClLkhH4Xs8P61Q2BaA==", + "dev": true, + "optional": true + }, + "@esbuild/linux-loong64": { + "version": "0.17.8", + "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.17.8.tgz", + "integrity": "sha512-B6FyMeRJeV0NpyEOYlm5qtQfxbdlgmiGdD+QsipzKfFky0K5HW5Td6dyK3L3ypu1eY4kOmo7wW0o94SBqlqBSA==", + "dev": true, + "optional": true + }, + "@esbuild/linux-mips64el": { + "version": "0.17.8", + "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.17.8.tgz", + "integrity": "sha512-CCb67RKahNobjm/eeEqeD/oJfJlrWyw29fgiyB6vcgyq97YAf3gCOuP6qMShYSPXgnlZe/i4a8WFHBw6N8bYAA==", + "dev": true, + "optional": true + }, + "@esbuild/linux-ppc64": { + "version": "0.17.8", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.17.8.tgz", + "integrity": "sha512-bytLJOi55y55+mGSdgwZ5qBm0K9WOCh0rx+vavVPx+gqLLhxtSFU0XbeYy/dsAAD6xECGEv4IQeFILaSS2auXw==", + "dev": true, + "optional": true + }, + "@esbuild/linux-riscv64": { + "version": "0.17.8", + "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.17.8.tgz", + "integrity": "sha512-2YpRyQJmKVBEHSBLa8kBAtbhucaclb6ex4wchfY0Tj3Kg39kpjeJ9vhRU7x4mUpq8ISLXRXH1L0dBYjAeqzZAw==", + "dev": true, + "optional": true + }, + "@esbuild/linux-s390x": { + "version": "0.17.8", + "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.17.8.tgz", + "integrity": "sha512-QgbNY/V3IFXvNf11SS6exkpVcX0LJcob+0RWCgV9OiDAmVElnxciHIisoSix9uzYzScPmS6dJFbZULdSAEkQVw==", + "dev": true, + "optional": true + }, + "@esbuild/linux-x64": { + "version": "0.17.8", + "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.17.8.tgz", + "integrity": "sha512-mM/9S0SbAFDBc4OPoyP6SEOo5324LpUxdpeIUUSrSTOfhHU9hEfqRngmKgqILqwx/0DVJBzeNW7HmLEWp9vcOA==", + "dev": true, + "optional": true + }, + "@esbuild/netbsd-x64": { + "version": "0.17.8", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.17.8.tgz", + "integrity": "sha512-eKUYcWaWTaYr9zbj8GertdVtlt1DTS1gNBWov+iQfWuWyuu59YN6gSEJvFzC5ESJ4kMcKR0uqWThKUn5o8We6Q==", + "dev": true, + "optional": true + }, + "@esbuild/openbsd-x64": { + "version": "0.17.8", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.17.8.tgz", + "integrity": "sha512-Vc9J4dXOboDyMXKD0eCeW0SIeEzr8K9oTHJU+Ci1mZc5njPfhKAqkRt3B/fUNU7dP+mRyralPu8QUkiaQn7iIg==", + "dev": true, + "optional": true + }, + "@esbuild/sunos-x64": { + "version": "0.17.8", + "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.17.8.tgz", + "integrity": "sha512-0xvOTNuPXI7ft1LYUgiaXtpCEjp90RuBBYovdd2lqAFxje4sEucurg30M1WIm03+3jxByd3mfo+VUmPtRSVuOw==", + "dev": true, + "optional": true + }, + "@esbuild/win32-arm64": { + "version": "0.17.8", + "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.17.8.tgz", + "integrity": "sha512-G0JQwUI5WdEFEnYNKzklxtBheCPkuDdu1YrtRrjuQv30WsYbkkoixKxLLv8qhJmNI+ATEWquZe/N0d0rpr55Mg==", + "dev": true, + "optional": true + }, + "@esbuild/win32-ia32": { + "version": "0.17.8", + "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.17.8.tgz", + "integrity": "sha512-Fqy63515xl20OHGFykjJsMnoIWS+38fqfg88ClvPXyDbLtgXal2DTlhb1TfTX34qWi3u4I7Cq563QcHpqgLx8w==", + "dev": true, + "optional": true + }, + "@esbuild/win32-x64": { + "version": "0.17.8", + "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.17.8.tgz", + "integrity": "sha512-1iuezdyDNngPnz8rLRDO2C/ZZ/emJLb72OsZeqQ6gL6Avko/XCXZw+NuxBSNhBAP13Hie418V7VMt9et1FMvpg==", + "dev": true, + "optional": true + }, "@eslint/eslintrc": { "version": "1.4.1", "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-1.4.1.tgz", @@ -15821,6 +16480,12 @@ "update-browserslist-db": "^1.0.10" } }, + "buffer-from": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz", + "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==", + "dev": true + }, "call-bind": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.2.tgz", @@ -16597,6 +17262,36 @@ "is-symbol": "^1.0.2" } }, + "esbuild": { + "version": "0.17.8", + "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.17.8.tgz", + "integrity": "sha512-g24ybC3fWhZddZK6R3uD2iF/RIPnRpwJAqLov6ouX3hMbY4+tKolP0VMF3zuIYCaXun+yHwS5IPQ91N2BT191g==", + "dev": true, + "requires": { + "@esbuild/android-arm": "0.17.8", + "@esbuild/android-arm64": "0.17.8", + "@esbuild/android-x64": "0.17.8", + "@esbuild/darwin-arm64": "0.17.8", + "@esbuild/darwin-x64": "0.17.8", + "@esbuild/freebsd-arm64": "0.17.8", + "@esbuild/freebsd-x64": "0.17.8", + "@esbuild/linux-arm": "0.17.8", + "@esbuild/linux-arm64": "0.17.8", + "@esbuild/linux-ia32": "0.17.8", + "@esbuild/linux-loong64": "0.17.8", + "@esbuild/linux-mips64el": "0.17.8", + "@esbuild/linux-ppc64": "0.17.8", + "@esbuild/linux-riscv64": "0.17.8", + "@esbuild/linux-s390x": "0.17.8", + "@esbuild/linux-x64": "0.17.8", + "@esbuild/netbsd-x64": "0.17.8", + "@esbuild/openbsd-x64": "0.17.8", + "@esbuild/sunos-x64": "0.17.8", + "@esbuild/win32-arm64": "0.17.8", + "@esbuild/win32-ia32": "0.17.8", + "@esbuild/win32-x64": "0.17.8" + } + }, "escalade": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz", @@ -17240,6 +17935,12 @@ "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==", "dev": true }, + "fsevents": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz", + "integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==", + "optional": true + }, "function-bind": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", @@ -21813,6 +22514,24 @@ "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.0.2.tgz", "integrity": "sha512-R0XvVJ9WusLiqTCEiGCmICCMplcCkIwwR11mOSD9CR5u+IXYdiseeEuXCVAjS54zqwkLcPNnmU4OeJ6tUrWhDw==" }, + "source-map-support": { + "version": "0.5.21", + "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.21.tgz", + "integrity": "sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==", + "dev": true, + "requires": { + "buffer-from": "^1.0.0", + "source-map": "^0.6.0" + }, + "dependencies": { + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true + } + } + }, "spawn-error-forwarder": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/spawn-error-forwarder/-/spawn-error-forwarder-1.0.0.tgz", @@ -22248,6 +22967,18 @@ } } }, + "tsx": { + "version": "3.12.3", + "resolved": "https://registry.npmjs.org/tsx/-/tsx-3.12.3.tgz", + "integrity": "sha512-Wc5BFH1xccYTXaQob+lEcimkcb/Pq+0en2s+ruiX0VEIC80nV7/0s7XRahx8NnsoCnpCVUPz8wrqVSPi760LkA==", + "dev": true, + "requires": { + "@esbuild-kit/cjs-loader": "^2.4.2", + "@esbuild-kit/core-utils": "^3.0.0", + "@esbuild-kit/esm-loader": "^2.5.5", + "fsevents": "~2.3.2" + } + }, "type-check": { "version": "0.4.0", "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz", diff --git a/package.json b/package.json index 181c3b14..6d809848 100644 --- a/package.json +++ b/package.json @@ -7,6 +7,7 @@ "dev": "cross-env FORCE_COLOR=1 npm-run-all -l -p dev:*", "dev:app": "wait-on tcp:5432 && next dev", "dev:db": "docker compose -f docker-compose.dev.yml up --force-recreate -V ", + "db:seed": "prisma db seed", "postinstall": "prisma generate", "lint": "next lint", "format:check": "prettier --check src", @@ -14,6 +15,9 @@ "start": "next start", "prepare": "husky install" }, + "prisma": { + "seed": "tsx prisma/seed.ts" + }, "dependencies": { "@chakra-ui/icons": "^2.0.17", "@chakra-ui/react": "^2.4.9", @@ -62,6 +66,7 @@ "prettier": "^2.8.4", "prisma": "^4.9.0", "semantic-release": "^19.0.5", + "tsx": "^3.12.3", "typescript": "^4.9.4", "wait-on": "^7.0.1" }, diff --git a/prisma/migrations/20230214212125_add_tags_and_refactor_names/migration.sql b/prisma/migrations/20230214212125_add_tags_and_refactor_names/migration.sql new file mode 100644 index 00000000..d05b9a3e --- /dev/null +++ b/prisma/migrations/20230214212125_add_tags_and_refactor_names/migration.sql @@ -0,0 +1,117 @@ +/* + Warnings: + + - You are about to drop the column `contact_link` on the `ContactMethods` table. All the data in the column will be lost. + - You are about to drop the column `contact_type` on the `ContactMethods` table. All the data in the column will be lost. + - You are about to drop the column `organization_id` on the `ContactMethods` table. All the data in the column will be lost. + - You are about to drop the column `email_address` on the `Managers` table. All the data in the column will be lost. + - You are about to drop the column `organization_id` on the `Managers` table. All the data in the column will be lost. + - You are about to drop the column `foundation_date` on the `Organization` table. All the data in the column will be lost. + - You are about to drop the column `long_description` on the `Organization` table. All the data in the column will be lost. + - You are about to drop the column `number_of_users` on the `Organization` table. All the data in the column will be lost. + - You are about to drop the column `owner_id` on the `Organization` table. All the data in the column will be lost. + - You are about to drop the column `organization_id` on the `Projects` table. All the data in the column will be lost. + - A unique constraint covering the columns `[slug]` on the table `Organization` will be added. If there are existing duplicate values, this will fail. + - A unique constraint covering the columns `[ownerId]` on the table `Organization` will be added. If there are existing duplicate values, this will fail. + - Added the required column `contactLink` to the `ContactMethods` table without a default value. This is not possible if the table is not empty. + - Added the required column `contactType` to the `ContactMethods` table without a default value. This is not possible if the table is not empty. + - Added the required column `organizationId` to the `ContactMethods` table without a default value. This is not possible if the table is not empty. + - Added the required column `organizationId` to the `Managers` table without a default value. This is not possible if the table is not empty. + - Added the required column `foundationDate` to the `Organization` table without a default value. This is not possible if the table is not empty. + - Added the required column `longDescription` to the `Organization` table without a default value. This is not possible if the table is not empty. + - Added the required column `numberOfUsers` to the `Organization` table without a default value. This is not possible if the table is not empty. + - Added the required column `ownerId` to the `Organization` table without a default value. This is not possible if the table is not empty. + - Added the required column `slug` to the `Organization` table without a default value. This is not possible if the table is not empty. + - Added the required column `organizationId` to the `Projects` table without a default value. This is not possible if the table is not empty. + +*/ +-- DropForeignKey +ALTER TABLE "ContactMethods" DROP CONSTRAINT "ContactMethods_organization_id_fkey"; + +-- DropForeignKey +ALTER TABLE "Managers" DROP CONSTRAINT "Managers_organization_id_fkey"; + +-- DropForeignKey +ALTER TABLE "Organization" DROP CONSTRAINT "Organization_owner_id_fkey"; + +-- DropForeignKey +ALTER TABLE "Projects" DROP CONSTRAINT "Projects_organization_id_fkey"; + +-- DropIndex +DROP INDEX "Organization_owner_id_key"; + +-- AlterTable +ALTER TABLE "ContactMethods" DROP COLUMN "contact_link", +DROP COLUMN "contact_type", +DROP COLUMN "organization_id", +ADD COLUMN "contactLink" TEXT NOT NULL, +ADD COLUMN "contactType" TEXT NOT NULL, +ADD COLUMN "organizationId" TEXT NOT NULL; + +-- AlterTable +ALTER TABLE "Managers" DROP COLUMN "email_address", +DROP COLUMN "organization_id", +ADD COLUMN "email" TEXT, +ADD COLUMN "organizationId" TEXT NOT NULL; + +-- AlterTable +ALTER TABLE "Organization" DROP COLUMN "foundation_date", +DROP COLUMN "long_description", +DROP COLUMN "number_of_users", +DROP COLUMN "owner_id", +ADD COLUMN "foundationDate" TIMESTAMP(3) NOT NULL, +ADD COLUMN "longDescription" TEXT NOT NULL, +ADD COLUMN "numberOfUsers" INTEGER NOT NULL, +ADD COLUMN "ownerId" TEXT NOT NULL, +ADD COLUMN "slug" TEXT NOT NULL; + +-- AlterTable +ALTER TABLE "Projects" DROP COLUMN "organization_id", +ADD COLUMN "organizationId" TEXT NOT NULL; + +-- CreateTable +CREATE TABLE "Tag" ( + "id" TEXT NOT NULL, + "text" TEXT NOT NULL, + + CONSTRAINT "Tag_pkey" PRIMARY KEY ("id") +); + +-- CreateTable +CREATE TABLE "_OrganizationToTag" ( + "A" TEXT NOT NULL, + "B" TEXT NOT NULL +); + +-- CreateIndex +CREATE UNIQUE INDEX "Tag_text_key" ON "Tag"("text"); + +-- CreateIndex +CREATE UNIQUE INDEX "_OrganizationToTag_AB_unique" ON "_OrganizationToTag"("A", "B"); + +-- CreateIndex +CREATE INDEX "_OrganizationToTag_B_index" ON "_OrganizationToTag"("B"); + +-- CreateIndex +CREATE UNIQUE INDEX "Organization_slug_key" ON "Organization"("slug"); + +-- CreateIndex +CREATE UNIQUE INDEX "Organization_ownerId_key" ON "Organization"("ownerId"); + +-- AddForeignKey +ALTER TABLE "ContactMethods" ADD CONSTRAINT "ContactMethods_organizationId_fkey" FOREIGN KEY ("organizationId") REFERENCES "Organization"("id") ON DELETE CASCADE ON UPDATE CASCADE; + +-- AddForeignKey +ALTER TABLE "Projects" ADD CONSTRAINT "Projects_organizationId_fkey" FOREIGN KEY ("organizationId") REFERENCES "Organization"("id") ON DELETE CASCADE ON UPDATE CASCADE; + +-- AddForeignKey +ALTER TABLE "Managers" ADD CONSTRAINT "Managers_organizationId_fkey" FOREIGN KEY ("organizationId") REFERENCES "Organization"("id") ON DELETE RESTRICT ON UPDATE CASCADE; + +-- AddForeignKey +ALTER TABLE "Organization" ADD CONSTRAINT "Organization_ownerId_fkey" FOREIGN KEY ("ownerId") REFERENCES "User"("id") ON DELETE CASCADE ON UPDATE CASCADE; + +-- AddForeignKey +ALTER TABLE "_OrganizationToTag" ADD CONSTRAINT "_OrganizationToTag_A_fkey" FOREIGN KEY ("A") REFERENCES "Organization"("id") ON DELETE CASCADE ON UPDATE CASCADE; + +-- AddForeignKey +ALTER TABLE "_OrganizationToTag" ADD CONSTRAINT "_OrganizationToTag_B_fkey" FOREIGN KEY ("B") REFERENCES "Tag"("id") ON DELETE CASCADE ON UPDATE CASCADE; diff --git a/prisma/migrations/20230214212354_add_cascade_delete_to_managers/migration.sql b/prisma/migrations/20230214212354_add_cascade_delete_to_managers/migration.sql new file mode 100644 index 00000000..5f190b99 --- /dev/null +++ b/prisma/migrations/20230214212354_add_cascade_delete_to_managers/migration.sql @@ -0,0 +1,5 @@ +-- DropForeignKey +ALTER TABLE "Managers" DROP CONSTRAINT "Managers_organizationId_fkey"; + +-- AddForeignKey +ALTER TABLE "Managers" ADD CONSTRAINT "Managers_organizationId_fkey" FOREIGN KEY ("organizationId") REFERENCES "Organization"("id") ON DELETE CASCADE ON UPDATE CASCADE; diff --git a/prisma/models/contactMethod.factory.ts b/prisma/models/contactMethod.factory.ts new file mode 100644 index 00000000..1c16c066 --- /dev/null +++ b/prisma/models/contactMethod.factory.ts @@ -0,0 +1,14 @@ +import { faker } from "@faker-js/faker/locale/pl"; +import type { Prisma } from "@prisma/client"; + +const contactTypes = ["Facebook", "Instagram", "Website", "Email"]; + +export const contactMethodFactory = ( + props?: Partial +): Omit => { + return { + contactLink: faker.internet.url(), + contactType: faker.helpers.arrayElement(contactTypes), + ...props, + }; +}; diff --git a/prisma/models/manager.factory.ts b/prisma/models/manager.factory.ts new file mode 100644 index 00000000..85ecf77f --- /dev/null +++ b/prisma/models/manager.factory.ts @@ -0,0 +1,15 @@ +import { faker } from "@faker-js/faker/locale/pl"; +import type { Prisma } from "@prisma/client"; + +export const managerFactory = ( + props?: Partial +): Omit => { + const firstName = faker.name.firstName(); + const lastName = faker.name.lastName(); + + return { + name: firstName + " " + lastName, + email: faker.internet.email(firstName, lastName), + ...props, + }; +}; diff --git a/prisma/models/organization.factory.ts b/prisma/models/organization.factory.ts new file mode 100644 index 00000000..54aa089f --- /dev/null +++ b/prisma/models/organization.factory.ts @@ -0,0 +1,71 @@ +import { faker } from "@faker-js/faker/locale/pl"; +import type { Prisma } from "@prisma/client"; +import slugify from "slugify"; +import { contactMethodFactory } from "./contactMethod.factory"; +import { managerFactory } from "./manager.factory"; +import { projectFactory } from "./project.factory"; +import { tagFactory } from "./tag.factory"; +import { userFactory } from "./user.factory"; + +const departments = [ + "W1", + "W2", + "W3", + "W4", + "W5", + "W6", + "W7", + "W8", + "W9", + "W10", + "W11", + "W12", +]; + +export const organizationFactory = ( + props?: Partial +): Prisma.OrganizationCreateInput => { + const name = faker.company.name(); + + const tags = Array.from({ + length: faker.datatype.number({ min: 1, max: 6 }), + }).map(() => tagFactory()); + + return { + name, + description: faker.commerce.productDescription(), + longDescription: faker.lorem.paragraphs(9), + createdAt: faker.date.past(), + slug: slugify(name) + faker.random.numeric(4), + numberOfUsers: faker.datatype.number(100), + foundationDate: faker.date.past(), + residence: faker.helpers.arrayElement(departments), + owner: { + create: userFactory({ role: "OWNER" }), + }, + Tags: { + connectOrCreate: tags.map((tag) => ({ + where: { + text: tag.text, + }, + create: tag, + })), + }, + ContactMethods: { + create: Array.from({ length: 3 }).map(() => contactMethodFactory()), + }, + Managers: { + createMany: { + data: Array.from({ length: 3 }).map(() => managerFactory()), + }, + }, + Projects: { + createMany: { + data: Array.from({ + length: faker.datatype.number({ min: 0, max: 4 }), + }).map(() => projectFactory()), + }, + }, + ...props, + }; +}; diff --git a/prisma/models/project.factory.ts b/prisma/models/project.factory.ts new file mode 100644 index 00000000..6992cd72 --- /dev/null +++ b/prisma/models/project.factory.ts @@ -0,0 +1,12 @@ +import { faker } from "@faker-js/faker/locale/pl"; +import type { Prisma } from "@prisma/client"; + +export const projectFactory = ( + props?: Partial +): Omit => { + return { + name: faker.company.name(), + description: faker.commerce.productDescription(), + ...props, + }; +}; diff --git a/prisma/models/tag.factory.ts b/prisma/models/tag.factory.ts new file mode 100644 index 00000000..c6b607d9 --- /dev/null +++ b/prisma/models/tag.factory.ts @@ -0,0 +1,22 @@ +import { faker } from "@faker-js/faker/locale/pl"; +import type { Prisma } from "@prisma/client"; + +const tags = [ + "Druk3D", + "Piwo", + "Fotografia", + "Programowanie", + "Muzyka", + "Taniec", + "Kultura", + "Sport", +]; + +export const tagFactory = ( + props?: Partial +): Prisma.TagCreateInput => { + return { + text: faker.helpers.arrayElement(tags), + ...props, + }; +}; diff --git a/prisma/models/user.factory.ts b/prisma/models/user.factory.ts new file mode 100644 index 00000000..3a111485 --- /dev/null +++ b/prisma/models/user.factory.ts @@ -0,0 +1,16 @@ +import { faker } from "@faker-js/faker/locale/pl"; +import type { Prisma } from "@prisma/client"; + +export const userFactory = ( + props?: Partial +): Prisma.UserCreateInput => { + const firstName = faker.name.firstName(); + const lastName = faker.name.lastName(); + + return { + name: firstName + " " + lastName, + email: faker.internet.email(firstName, lastName), + role: "USER", + ...props, + }; +}; diff --git a/prisma/schema.prisma b/prisma/schema.prisma index ea295970..5ee70a38 100644 --- a/prisma/schema.prisma +++ b/prisma/schema.prisma @@ -23,51 +23,59 @@ enum Role { USER } +model Tag { + id String @id @default(cuid()) + text String @unique + organizations Organization[] +} + model ContactMethods { - id String @id @default(cuid()) - createdAt DateTime @default(now()) - updatedAt DateTime @updatedAt - contact_type String - contact_link String - organization_id String - organization Organization @relation(fields: [organization_id], references: [id], onDelete: Cascade) + id String @id @default(cuid()) + createdAt DateTime @default(now()) + updatedAt DateTime @updatedAt + contactType String + contactLink String + organizationId String + organization Organization @relation(fields: [organizationId], references: [id], onDelete: Cascade) } model Projects { - id String @id @default(cuid()) - createdAt DateTime @default(now()) - updatedAt DateTime @updatedAt - name String - description String - organization_id String - organization Organization @relation(fields: [organization_id], references: [id], onDelete: Cascade) + id String @id @default(cuid()) + createdAt DateTime @default(now()) + updatedAt DateTime @updatedAt + name String + description String + organizationId String + organization Organization @relation(fields: [organizationId], references: [id], onDelete: Cascade) } model Managers { - id String @id @default(cuid()) - createdAt DateTime @default(now()) - updatedAt DateTime @updatedAt - name String - organization_id String - email_address String - organization Organization @relation(fields: [organization_id], references: [id]) + id String @id @default(cuid()) + createdAt DateTime @default(now()) + updatedAt DateTime @updatedAt + name String + organizationId String + email String? + organization Organization @relation(fields: [organizationId], references: [id], onDelete: Cascade) } model Organization { - id String @id @default(cuid()) - name String - createdAt DateTime @default(now()) - updatedAt DateTime @updatedAt - residence String - description String - long_description String @db.Text - number_of_users Int - foundation_date DateTime - owner_id String @unique - owner User @relation(fields: [owner_id], references: [id], onDelete: Cascade) - ContactMethods ContactMethods[] - Projects Projects[] - Managers Managers[] + id String @id @default(cuid()) + name String + createdAt DateTime @default(now()) + updatedAt DateTime @updatedAt + residence String + description String + slug String @unique + longDescription String @db.Text + numberOfUsers Int + foundationDate DateTime + ownerId String @unique + owner User @relation(fields: [ownerId], references: [id], onDelete: Cascade) + ContactMethods ContactMethods[] + Projects Projects[] + Managers Managers[] + Tags Tag[] } // Necessary for Next auth diff --git a/prisma/seed.ts b/prisma/seed.ts new file mode 100644 index 00000000..799bd65a --- /dev/null +++ b/prisma/seed.ts @@ -0,0 +1,26 @@ +import { prisma } from "../src/server/db"; +import { organizationFactory } from "./models/organization.factory"; + +async function main() { + await prisma.organization.deleteMany(); + + const numberOfOrganizations = 100; + + for (let i = 0; i < numberOfOrganizations; i++) { + await prisma.organization.create({ + data: organizationFactory(), + }); + } + + console.log(`Created ${numberOfOrganizations} organizations`); +} + +main() + .then(async () => { + await prisma.$disconnect(); + }) + .catch(async (e) => { + console.error(e); + await prisma.$disconnect(); + process.exit(1); + }); diff --git a/src/features/admin/views/index.tsx b/src/features/admin/views/index.tsx index d35a9945..0a41b33d 100644 --- a/src/features/admin/views/index.tsx +++ b/src/features/admin/views/index.tsx @@ -25,10 +25,9 @@ import { useReactTable, } from "@tanstack/react-table"; import { useRouter } from "next/router"; -import slugify from "slugify"; const columnHelper = - createColumnHelper(); + createColumnHelper(); const columns = [ columnHelper.accessor("name", { @@ -38,21 +37,21 @@ const columns = [ cell: (info) => info.getValue().slice(0, 40) + "...", header: () => "Krótki opis", }), - columnHelper.accessor("department", { + columnHelper.accessor("residence", { header: () => "Wydział", }), - columnHelper.accessor("tags", { + columnHelper.accessor("Tags", { header: () => "Tagi", cell: (info) => info.getValue().join(", "), }), ]; export const HomePage = () => { - const { data, isLoading } = api.organizations.getAll.useQuery(); + const { data, isLoading } = api.organizations.list.useQuery(); const [sorting, setSorting] = useState([]); - const table = useReactTable({ + const table = useReactTable({ data: data ?? [], columns, state: { @@ -126,11 +125,10 @@ export const HomePage = () => { if (!row.original) { return; } - void router.push({ pathname: "/admin/organizacje/[slug]", query: { - slug: slugify(row.original.name), + slug: row.original.slug, }, }); }} diff --git a/src/features/search/components/List.tsx b/src/features/search/components/List.tsx index def99cb8..dc941808 100644 --- a/src/features/search/components/List.tsx +++ b/src/features/search/components/List.tsx @@ -11,7 +11,7 @@ export const List = ({ data, ...styles }: { - data?: RouterOutputs["organizations"]["getAll"]; + data?: RouterOutputs["organizations"]["list"]; } & BoxProps) => { return ( @@ -47,7 +47,7 @@ export const List = ({ {data?.slice(0, 10).map((org) => ( { const router = useRouter(); @@ -35,12 +36,12 @@ export const OrganisationCard = ({ align="start" > - {department} + {residence} {name} - {tags.map((tag) => ( + {Tags.map((tag) => ( @@ -56,7 +57,7 @@ export const OrganisationCard = ({ onClick={() => { void router.push({ pathname: "/organizacja/[slug]", - query: { slug: slugify(name) }, + query: { slug }, }); }} > diff --git a/src/features/search/components/OrganisationFull.tsx b/src/features/search/components/OrganisationFull.tsx index 06c5765a..f6f6de76 100644 --- a/src/features/search/components/OrganisationFull.tsx +++ b/src/features/search/components/OrganisationFull.tsx @@ -38,7 +38,7 @@ export const OrganisationFull = ({ {data.name} - {data.tags.map((tag) => ( + {data.Tags.map((tag) => ( @@ -46,9 +46,9 @@ export const OrganisationFull = ({ {data.description}
{data.longDescription} @@ -56,20 +56,26 @@ export const OrganisationFull = ({ Zarząd - {data.management.map((member) => ( - {member} + {data.Managers.map((member) => ( + {member.name} ))} Kontakt - {Object.entries(data.socials).map(([key, value]) => ( - + {data.ContactMethods.map((contactMethod) => ( + - {key}: - - {value} + + {contactMethod.contactType}: + + + {contactMethod.contactLink} diff --git a/src/features/search/components/Search.tsx b/src/features/search/components/Search.tsx index 263a63d0..44d27ab6 100644 --- a/src/features/search/components/Search.tsx +++ b/src/features/search/components/Search.tsx @@ -7,17 +7,7 @@ import { Input, InputGroup, InputRightElement, VStack } from "@chakra-ui/react"; import type { ComponentProps } from "react"; import React, { useEffect, useState } from "react"; import { Tag } from "./Tag"; - -const availableTags = [ - "Druk3D", - "Piwo", - "Fotografia", - "Programowanie", - "Muzyka", - "Taniec", - "Kultura", - "Sport", -]; +import { api } from "@/utils/api"; const SelectableTag = ( props: ComponentProps & { @@ -47,6 +37,7 @@ export const Search = ({ const [search, setSearch] = useState(value); const debouncedSearch = useDebounce(search, 200); const { toggleTag } = useSelectedTags(); + const { data: tags } = api.tags.list.useQuery(); useEffect(() => { setValue(debouncedSearch); @@ -69,7 +60,7 @@ export const Search = ({ - {availableTags.map((tag) => ( + {tags?.map((tag) => ( { const [search, setSearch] = useState(""); @@ -49,8 +49,8 @@ export const useSearch = (data?: Organizations) => { } return result.filter((item) => { - const { tags } = item; - return selectedTags.every((tag) => tags.includes(tag)); + const { Tags } = item; + return selectedTags.every((tag) => Tags.includes(tag)); }); }, [result, selectedTags]); diff --git a/src/features/search/views/index.tsx b/src/features/search/views/index.tsx index 6e7b0ece..4f3d1ba8 100644 --- a/src/features/search/views/index.tsx +++ b/src/features/search/views/index.tsx @@ -7,7 +7,7 @@ import { type NextPage } from "next"; import { Layout } from "../components/Layout"; const SearchPage: NextPage = () => { - const { data } = api.organizations.getAll.useQuery(); + const { data } = api.organizations.list.useQuery(); const { search, setSearch, results } = useSearch(data); diff --git a/src/server/api/root.ts b/src/server/api/root.ts index 3f1c2a73..2e962e3f 100644 --- a/src/server/api/root.ts +++ b/src/server/api/root.ts @@ -1,5 +1,6 @@ import { createTRPCRouter } from "./trpc"; import { organizations } from "./routers/organizations"; +import { tags } from "./routers/tags"; /** * This is the primary router for your server. @@ -8,6 +9,7 @@ import { organizations } from "./routers/organizations"; */ export const appRouter = createTRPCRouter({ organizations, + tags, }); // export type definition of API diff --git a/src/server/api/routers/organizations.ts b/src/server/api/routers/organizations.ts index f0900b3e..787944ea 100644 --- a/src/server/api/routers/organizations.ts +++ b/src/server/api/routers/organizations.ts @@ -1,79 +1,23 @@ import { createTRPCRouter, publicProcedure } from "../trpc"; -import { faker } from "@faker-js/faker/locale/pl"; import { z } from "zod"; -import slugify from "slugify"; - -const tags = [ - "Druk3D", - "Piwo", - "Fotografia", - "Programowanie", - "Muzyka", - "Taniec", - "Kultura", - "Sport", -]; - -const departments = [ - "W1", - "W2", - "W3", - "W4", - "W5", - "W6", - "W7", - "W8", - "W9", - "W10", - "W11", - "W12", -]; - -const generateFakeManagement = () => { - return Array.from({ length: 3 }).map(() => faker.name.fullName()); -}; - -const generateFakeSocialLinks = () => { - return { - facebook: faker.internet.url(), - instagram: faker.internet.url(), - website: faker.internet.url(), - }; -}; - -const generateFakeOrganization = () => { - return { - id: faker.datatype.uuid(), - name: faker.company.name(), - description: faker.commerce.productDescription(), - longDescription: faker.lorem.paragraphs(9), - management: generateFakeManagement(), - createdAt: faker.date.past(), - numberOfProjects: faker.datatype.number(10), - members: faker.datatype.number(100), - socials: generateFakeSocialLinks(), - logoUrl: faker.image.cats(150, 150, true), - tags: faker.helpers.arrayElements(tags, 3), - department: faker.helpers.arrayElement(departments), - }; -}; - -const globalMock = globalThis as unknown as { - mockData: ReturnType[]; -}; - -const getData = () => { - if (!globalMock.mockData) { - const mockData = Array.from({ length: 30 }).map(generateFakeOrganization); - globalMock.mockData = mockData; - } - - return globalMock.mockData; -}; +import { TRPCError } from "@trpc/server"; export const organizations = createTRPCRouter({ - getAll: publicProcedure.query(() => { - return getData(); + list: publicProcedure.query(async ({ ctx }) => { + const organizations = await ctx.prisma.organization.findMany({ + select: { + Tags: true, + name: true, + slug: true, + description: true, + residence: true, + }, + }); + + return organizations.map((organization) => ({ + ...organization, + Tags: organization.Tags.map((tag) => tag.text), + })); }), get: publicProcedure .input( @@ -81,11 +25,30 @@ export const organizations = createTRPCRouter({ slug: z.string().min(1).max(100), }) ) - .query(({ input }) => { - return ( - getData().find((org) => { - return slugify(org.name) === input.slug; - }) ?? getData()[0] - ); + .query(async ({ input, ctx }) => { + const organization = await ctx.prisma.organization.findUnique({ + where: { + slug: input.slug, + }, + include: { + ContactMethods: true, + Tags: true, + owner: true, + Managers: true, + Projects: true, + }, + }); + + if (!organization) { + throw new TRPCError({ + code: "NOT_FOUND", + message: "Organization not found", + }); + } + + return { + ...organization, + Tags: organization.Tags.map((tag) => tag.text), + }; }), }); diff --git a/src/server/api/routers/tags.ts b/src/server/api/routers/tags.ts new file mode 100644 index 00000000..0cd0f224 --- /dev/null +++ b/src/server/api/routers/tags.ts @@ -0,0 +1,7 @@ +import { createTRPCRouter, publicProcedure } from "../trpc"; + +export const tags = createTRPCRouter({ + list: publicProcedure.query(async ({ ctx }) => { + return (await ctx.prisma.tag.findMany()).map((tag) => tag.text); + }), +});