diff --git a/.env.example b/.env.example index 511dbe2..cadcd6d 100644 --- a/.env.example +++ b/.env.example @@ -1,8 +1,8 @@ KC_URL=http://192.168.1.20:8080 KC_REALM=dev -KC_SERVICE_ACCOUNT_CLIENT_ID=dev-service -KC_SERVICE_ACCOUNT_SECRET= +KC_ADMIN_USERNAME=admin +KC_ADMIN_PASSWORD= APP_HOST=0.0.0.0 APP_PORT=3000 diff --git a/.gitignore b/.gitignore index 395a731..e90ad5b 100644 --- a/.gitignore +++ b/.gitignore @@ -1,5 +1,6 @@ .DS_S node_modules +/src/generated .env .env.* diff --git a/Dockerfile b/Dockerfile index c8d8da5..85f8ccd 100644 --- a/Dockerfile +++ b/Dockerfile @@ -5,7 +5,7 @@ ENV PATH="$PNPM_HOME:$PATH" RUN corepack enable RUN apt-get update && apt-get install -y openssl -RUN pnpm i -g prisma +RUN pnpm i -g prisma prisma-kysely WORKDIR /app diff --git a/package.json b/package.json index b2e63ea..2502949 100644 --- a/package.json +++ b/package.json @@ -22,21 +22,24 @@ "@types/express": "^4.17.21", "@types/node": "^20.12.2", "@types/swagger-ui-express": "^4.1.6", - "nodemon": "^3.1.0", + "nodemon": "^3.1.3", "prettier": "^3.2.5", - "prisma": "^5.12.1", + "prisma": "^5.16.0", + "prisma-kysely": "^1.8.0", "ts-node": "^10.9.2", "typescript": "^5.4.3" }, "dependencies": { "@elastic/elasticsearch": "^8.13.0", - "@prisma/client": "5.12.1", + "@prisma/client": "^5.16.0", "@tsoa/runtime": "^6.2.0", "cors": "^2.8.5", "dotenv": "^16.4.5", "express": "^4.19.2", "fast-jwt": "^4.0.0", + "kysely": "^0.27.3", "minio": "^7.1.3", + "prisma-extension-kysely": "^2.1.0", "promise.any": "^2.0.6", "swagger-ui-express": "^5.0.0", "tsoa": "^6.2.0" diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 244f837..08a3c9d 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -1,95 +1,2169 @@ -lockfileVersion: '6.0' +lockfileVersion: '9.0' settings: autoInstallPeers: true excludeLinksFromLockfile: false -dependencies: - '@elastic/elasticsearch': - specifier: ^8.13.0 - version: 8.13.0 - '@prisma/client': - specifier: 5.12.1 - version: 5.12.1(prisma@5.12.1) - '@tsoa/runtime': - specifier: ^6.2.0 - version: 6.2.0 - cors: - specifier: ^2.8.5 - version: 2.8.5 - dotenv: - specifier: ^16.4.5 - version: 16.4.5 - express: - specifier: ^4.19.2 - version: 4.19.2 - fast-jwt: - specifier: ^4.0.0 - version: 4.0.0 - minio: - specifier: ^7.1.3 - version: 7.1.3 - promise.any: - specifier: ^2.0.6 - version: 2.0.6 - swagger-ui-express: - specifier: ^5.0.0 - version: 5.0.0(express@4.19.2) - tsoa: - specifier: ^6.2.0 - version: 6.2.0 +importers: -devDependencies: - '@types/cors': - specifier: ^2.8.17 - version: 2.8.17 - '@types/express': - specifier: ^4.17.21 - version: 4.17.21 - '@types/node': - specifier: ^20.12.2 - version: 20.12.2 - '@types/swagger-ui-express': - specifier: ^4.1.6 - version: 4.1.6 - nodemon: - specifier: ^3.1.0 - version: 3.1.0 - prettier: - specifier: ^3.2.5 - version: 3.2.5 - prisma: - specifier: ^5.12.1 - version: 5.12.1 - ts-node: - specifier: ^10.9.2 - version: 10.9.2(@types/node@20.12.2)(typescript@5.4.3) - typescript: - specifier: ^5.4.3 - version: 5.4.3 + .: + dependencies: + '@elastic/elasticsearch': + specifier: ^8.13.0 + version: 8.13.0 + '@prisma/client': + specifier: ^5.16.0 + version: 5.16.0(prisma@5.16.0) + '@tsoa/runtime': + specifier: ^6.2.0 + version: 6.2.0 + cors: + specifier: ^2.8.5 + version: 2.8.5 + dotenv: + specifier: ^16.4.5 + version: 16.4.5 + express: + specifier: ^4.19.2 + version: 4.19.2 + fast-jwt: + specifier: ^4.0.0 + version: 4.0.0 + kysely: + specifier: ^0.27.3 + version: 0.27.3 + minio: + specifier: ^7.1.3 + version: 7.1.3 + prisma-extension-kysely: + specifier: ^2.1.0 + version: 2.1.0(@prisma/client@5.16.0(prisma@5.16.0)) + promise.any: + specifier: ^2.0.6 + version: 2.0.6 + swagger-ui-express: + specifier: ^5.0.0 + version: 5.0.0(express@4.19.2) + tsoa: + specifier: ^6.2.0 + version: 6.2.0 + devDependencies: + '@types/cors': + specifier: ^2.8.17 + version: 2.8.17 + '@types/express': + specifier: ^4.17.21 + version: 4.17.21 + '@types/node': + specifier: ^20.12.2 + version: 20.12.2 + '@types/swagger-ui-express': + specifier: ^4.1.6 + version: 4.1.6 + nodemon: + specifier: ^3.1.3 + version: 3.1.3 + prettier: + specifier: ^3.2.5 + version: 3.2.5 + prisma: + specifier: ^5.16.0 + version: 5.16.0 + prisma-kysely: + specifier: ^1.8.0 + version: 1.8.0 + ts-node: + specifier: ^10.9.2 + version: 10.9.2(@types/node@20.12.2)(typescript@5.4.3) + typescript: + specifier: ^5.4.3 + version: 5.4.3 packages: - /@cspotcode/source-map-support@0.8.1: + '@antfu/ni@0.21.8': + resolution: {integrity: sha512-90X8pU2szlvw0AJo9EZMbYc2eQKkmO7mAdC4tD4r5co2Mm56MT37MIG8EyB7p4WRheuzGxuLDxJ63mF6+Zajiw==} + hasBin: true + + '@babel/code-frame@7.24.7': + resolution: {integrity: sha512-BcYH1CVJBO9tvyIZ2jVeXgSIMvGZ2FDRvDdOIVQyuklNKSsx+eppDEBq/g47Ayw+RqNFE+URvOShmf+f/qwAlA==} + engines: {node: '>=6.9.0'} + + '@babel/helper-validator-identifier@7.24.7': + resolution: {integrity: sha512-rR+PBcQ1SMQDDyF6X0wxtG8QyLCgUB0eRAGguqRLfkCA87l7yAP7ehq8SNj96OOGTO8OBV70KhuFYcIkHXOg0w==} + engines: {node: '>=6.9.0'} + + '@babel/highlight@7.24.7': + resolution: {integrity: sha512-EStJpq4OuY8xYfhGVXngigBJRWxftKX9ksiGDnmlY3o7B/V7KIAc9X4oiK87uPJSc/vs5L869bem5fhZa8caZw==} + engines: {node: '>=6.9.0'} + + '@chevrotain/cst-dts-gen@10.5.0': + resolution: {integrity: sha512-lhmC/FyqQ2o7pGK4Om+hzuDrm9rhFYIJ/AXoQBeongmn870Xeb0L6oGEiuR8nohFNL5sMaQEJWCxr1oIVIVXrw==} + + '@chevrotain/gast@10.5.0': + resolution: {integrity: sha512-pXdMJ9XeDAbgOWKuD1Fldz4ieCs6+nLNmyVhe2gZVqoO7v8HXuHYs5OV2EzUtbuai37TlOAQHrTDvxMnvMJz3A==} + + '@chevrotain/types@10.5.0': + resolution: {integrity: sha512-f1MAia0x/pAVPWH/T73BJVyO2XU5tI4/iE7cnxb7tqdNTNhQI3Uq3XkqcoteTmD4t1aM0LbHCJOhgIDn07kl2A==} + + '@chevrotain/utils@10.5.0': + resolution: {integrity: sha512-hBzuU5+JjB2cqNZyszkDHZgOSrUUT8V3dhgRl8Q9Gp6dAj/H5+KILGjbhDpc3Iy9qmqlm/akuOI2ut9VUtzJxQ==} + + '@cspotcode/source-map-support@0.8.1': resolution: {integrity: sha512-IchNf6dN4tHoMFIn/7OE8LWZ19Y6q/67Bmf6vnGREv8RSbBVb9LPJxEcnwrcwX6ixSvaiGoomAUvu4YSxXrVgw==} engines: {node: '>=12'} - dependencies: - '@jridgewell/trace-mapping': 0.3.9 - dev: true - /@elastic/elasticsearch@8.13.0: + '@elastic/elasticsearch@8.13.0': resolution: {integrity: sha512-OAYgzqArPqgDaIJ1yT0RX31YCgr1lleo53zL+36i23PFjHu08CA6Uq+BmBzEV05yEidl+ILPdeSfF3G8hPG/JQ==} engines: {node: '>=18'} + + '@elastic/transport@8.5.0': + resolution: {integrity: sha512-T+zSUHXBfrqlj/E9pJiaEgKoTdGykBCohzNBt6omDfI6EQtaNT240oMO03oXo35T8rwrCVonSMSoedbmToncVA==} + engines: {node: '>=18'} + + '@hapi/accept@6.0.3': + resolution: {integrity: sha512-p72f9k56EuF0n3MwlBNThyVE5PXX40g+aQh+C/xbKrfzahM2Oispv3AXmOIU51t3j77zay1qrX7IIziZXspMlw==} + + '@hapi/ammo@6.0.1': + resolution: {integrity: sha512-pmL+nPod4g58kXrMcsGLp05O2jF4P2Q3GiL8qYV7nKYEh3cGf+rV4P5Jyi2Uq0agGhVU63GtaSAfBEZOlrJn9w==} + + '@hapi/b64@6.0.1': + resolution: {integrity: sha512-ZvjX4JQReUmBheeCq+S9YavcnMMHWqx3S0jHNXWIM1kQDxB9cyfSycpVvjfrKcIS8Mh5N3hmu/YKo4Iag9g2Kw==} + + '@hapi/boom@10.0.1': + resolution: {integrity: sha512-ERcCZaEjdH3OgSJlyjVk8pHIFeus91CjKP3v+MpgBNp5IvGzP2l/bRiD78nqYcKPaZdbKkK5vDBVPd2ohHBlsA==} + + '@hapi/bounce@3.0.1': + resolution: {integrity: sha512-G+/Pp9c1Ha4FDP+3Sy/Xwg2O4Ahaw3lIZFSX+BL4uWi64CmiETuZPxhKDUD4xBMOUZbBlzvO8HjiK8ePnhBadA==} + + '@hapi/bourne@3.0.0': + resolution: {integrity: sha512-Waj1cwPXJDucOib4a3bAISsKJVb15MKi9IvmTI/7ssVEm6sywXGjVJDhl6/umt1pK1ZS7PacXU3A1PmFKHEZ2w==} + + '@hapi/call@9.0.1': + resolution: {integrity: sha512-uPojQRqEL1GRZR4xXPqcLMujQGaEpyVPRyBlD8Pp5rqgIwLhtveF9PkixiKru2THXvuN8mUrLeet5fqxKAAMGg==} + + '@hapi/catbox-memory@6.0.1': + resolution: {integrity: sha512-sVb+/ZxbZIvaMtJfAbdyY+QJUQg9oKTwamXpEg/5xnfG5WbJLTjvEn4kIGKz9pN3ENNbIL/bIdctmHmqi/AdGA==} + + '@hapi/catbox@12.1.1': + resolution: {integrity: sha512-hDqYB1J+R0HtZg4iPH3LEnldoaBsar6bYp0EonBmNQ9t5CO+1CqgCul2ZtFveW1ReA5SQuze9GPSU7/aecERhw==} + + '@hapi/content@6.0.0': + resolution: {integrity: sha512-CEhs7j+H0iQffKfe5Htdak5LBOz/Qc8TRh51cF+BFv0qnuph3Em4pjGVzJMkI2gfTDdlJKWJISGWS1rK34POGA==} + + '@hapi/cryptiles@6.0.1': + resolution: {integrity: sha512-9GM9ECEHfR8lk5ASOKG4+4ZsEzFqLfhiryIJ2ISePVB92OHLp/yne4m+zn7z9dgvM98TLpiFebjDFQ0UHcqxXQ==} + engines: {node: '>=14.0.0'} + + '@hapi/file@3.0.0': + resolution: {integrity: sha512-w+lKW+yRrLhJu620jT3y+5g2mHqnKfepreykvdOcl9/6up8GrQQn+l3FRTsjHTKbkbfQFkuksHpdv2EcpKcJ4Q==} + + '@hapi/hapi@21.3.7': + resolution: {integrity: sha512-33J0nreMfqkhY7wwRAZRy+9J+7J4QOH1JtICMjIUmxfaOYSJL/d8JJCtg57SX60944bhlCeu7isb7qyr2jT2oA==} + engines: {node: '>=14.15.0'} + + '@hapi/heavy@8.0.1': + resolution: {integrity: sha512-gBD/NANosNCOp6RsYTsjo2vhr5eYA3BEuogk6cxY0QdhllkkTaJFYtTXv46xd6qhBVMbMMqcSdtqey+UQU3//w==} + + '@hapi/hoek@11.0.4': + resolution: {integrity: sha512-PnsP5d4q7289pS2T2EgGz147BFJ2Jpb4yrEdkpz2IhgEUzos1S7HTl7ezWh1yfYzYlj89KzLdCRkqsP6SIryeQ==} + + '@hapi/iron@7.0.1': + resolution: {integrity: sha512-tEZnrOujKpS6jLKliyWBl3A9PaE+ppuL/+gkbyPPDb/l2KSKQyH4lhMkVb+sBhwN+qaxxlig01JRqB8dk/mPxQ==} + + '@hapi/mimos@7.0.1': + resolution: {integrity: sha512-b79V+BrG0gJ9zcRx1VGcCI6r6GEzzZUgiGEJVoq5gwzuB2Ig9Cax8dUuBauQCFKvl2YWSWyOc8mZ8HDaJOtkew==} + + '@hapi/nigel@5.0.1': + resolution: {integrity: sha512-uv3dtYuB4IsNaha+tigWmN8mQw/O9Qzl5U26Gm4ZcJVtDdB1AVJOwX3X5wOX+A07qzpEZnOMBAm8jjSqGsU6Nw==} + engines: {node: '>=14.0.0'} + + '@hapi/pez@6.1.0': + resolution: {integrity: sha512-+FE3sFPYuXCpuVeHQ/Qag1b45clR2o54QoonE/gKHv9gukxQ8oJJZPR7o3/ydDTK6racnCJXxOyT1T93FCJMIg==} + + '@hapi/podium@5.0.1': + resolution: {integrity: sha512-eznFTw6rdBhAijXFIlBOMJJd+lXTvqbrBIS4Iu80r2KTVIo4g+7fLy4NKp/8+UnSt5Ox6mJtAlKBU/Sf5080TQ==} + + '@hapi/shot@6.0.1': + resolution: {integrity: sha512-s5ynMKZXYoDd3dqPw5YTvOR/vjHvMTxc388+0qL0jZZP1+uwXuUD32o9DuuuLsmTlyXCWi02BJl1pBpwRuUrNA==} + + '@hapi/somever@4.1.1': + resolution: {integrity: sha512-lt3QQiDDOVRatS0ionFDNrDIv4eXz58IibQaZQDOg4DqqdNme8oa0iPWcE0+hkq/KTeBCPtEOjDOBKBKwDumVg==} + + '@hapi/statehood@8.1.1': + resolution: {integrity: sha512-YbK7PSVUA59NArAW5Np0tKRoIZ5VNYUicOk7uJmWZF6XyH5gGL+k62w77SIJb0AoAJ0QdGQMCQ/WOGL1S3Ydow==} + + '@hapi/subtext@8.1.0': + resolution: {integrity: sha512-PyaN4oSMtqPjjVxLny1k0iYg4+fwGusIhaom9B2StinBclHs7v46mIW706Y+Wo21lcgulGyXbQrmT/w4dus6ww==} + + '@hapi/teamwork@6.0.0': + resolution: {integrity: sha512-05HumSy3LWfXpmJ9cr6HzwhAavrHkJ1ZRCmNE2qJMihdM5YcWreWPfyN0yKT2ZjCM92au3ZkuodjBxOibxM67A==} + engines: {node: '>=14.0.0'} + + '@hapi/topo@6.0.2': + resolution: {integrity: sha512-KR3rD5inZbGMrHmgPxsJ9dbi6zEK+C3ZwUwTa+eMwWLz7oijWUTWD2pMSNNYJAU6Qq+65NkxXjqHr/7LM2Xkqg==} + + '@hapi/validate@2.0.1': + resolution: {integrity: sha512-NZmXRnrSLK8MQ9y/CMqE9WSspgB9xA41/LlYR0k967aSZebWr4yNrpxIbov12ICwKy4APSlWXZga9jN5p6puPA==} + + '@hapi/vise@5.0.1': + resolution: {integrity: sha512-XZYWzzRtINQLedPYlIkSkUr7m5Ddwlu99V9elh8CSygXstfv3UnWIXT0QD+wmR0VAG34d2Vx3olqcEhRRoTu9A==} + + '@hapi/wreck@18.0.1': + resolution: {integrity: sha512-OLHER70+rZxvDl75xq3xXOfd3e8XIvz8fWY0dqg92UvhZ29zo24vQgfqgHSYhB5ZiuFpSLeriOisAlxAo/1jWg==} + + '@isaacs/cliui@8.0.2': + resolution: {integrity: sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==} + engines: {node: '>=12'} + + '@jridgewell/resolve-uri@3.1.2': + resolution: {integrity: sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==} + engines: {node: '>=6.0.0'} + + '@jridgewell/sourcemap-codec@1.4.15': + resolution: {integrity: sha512-eF2rxCRulEKXHTRiDrDy6erMYWqNw4LPdQ8UQA4huuxaQsVeRPFl2oM8oDGxMFhJUWZf9McpLtJasDDZb/Bpeg==} + + '@jridgewell/trace-mapping@0.3.9': + resolution: {integrity: sha512-3Belt6tdc8bPgAtbcmdtNJlirVoTmEb5e2gC94PnkwEW9jI6CAHUeoG85tjWP5WquqfavoMtMwiG4P926ZKKuQ==} + + '@lukeed/ms@2.0.2': + resolution: {integrity: sha512-9I2Zn6+NJLfaGoz9jN3lpwDgAYvfGeNYdbAIjJOqzs4Tpc+VU3Jqq4IofSUBKajiDS8k9fZIg18/z13mpk1bsA==} + engines: {node: '>=8'} + + '@mrleebo/prisma-ast@0.7.0': + resolution: {integrity: sha512-GTPkYf1meO2UXXIrz/SIDFWz+P4kXo2PTt36LYh/oNxV1PieYi7ZgenQk4IV0ut71Je3Z8ZoNZ8Tr7v2c1X1pg==} + engines: {node: '>=16'} + + '@nodelib/fs.scandir@2.1.5': + resolution: {integrity: sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==} + engines: {node: '>= 8'} + + '@nodelib/fs.stat@2.0.5': + resolution: {integrity: sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==} + engines: {node: '>= 8'} + + '@nodelib/fs.walk@1.2.8': + resolution: {integrity: sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==} + engines: {node: '>= 8'} + + '@opentelemetry/api@1.4.1': + resolution: {integrity: sha512-O2yRJce1GOc6PAy3QxFM4NzFiWzvScDC1/5ihYBL6BUEVdq0XMWN01sppE+H6bBXbaFYipjwFLEWLg5PaSOThA==} + engines: {node: '>=8.0.0'} + + '@pkgjs/parseargs@0.11.0': + resolution: {integrity: sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==} + engines: {node: '>=14'} + + '@prisma/client@5.16.0': + resolution: {integrity: sha512-8NOQSzgrSgpU2YcNm4MsPR4/vNvZdUBPuyX89PwWlClSKZeDjPSZ8+eds/ffu1Ttrjnm8V8D0hjgqpyc6wyqDg==} + engines: {node: '>=16.13'} + peerDependencies: + prisma: '*' + peerDependenciesMeta: + prisma: + optional: true + + '@prisma/debug@5.16.0': + resolution: {integrity: sha512-pfdOGxMShqZKkNNskYB0yXICsqL6rOkQUKNktouUZ9Y9ASd5736+ae2fpzif7onwJiIyEpu/yvOO3rFUbliKTA==} + + '@prisma/debug@5.3.1': + resolution: {integrity: sha512-eYrxqslEKf+wpMFIIHgbcNYuZBXUdiJLA85Or3TwOhgPIN1ZoXT9CwJph3ynW8H1Xg0LkdYLwVmuULCwiMoU5A==} + + '@prisma/engines-version@5.16.0-24.34ace0eb2704183d2c05b60b52fba5c43c13f303': + resolution: {integrity: sha512-HkT2WbfmFZ9WUPyuJHhkiADxazHg8Y4gByrTSVeb3OikP6tjQ7txtSUGu9OBOBH0C13dPKN2qqH12xKtHu/Hiw==} + + '@prisma/engines@5.16.0': + resolution: {integrity: sha512-OGvi/GvLX3XwTWQ+k/57kLyHGidQ8rC8zB+Zq9nEE7gegjazyzgLYN9qzfdcCfyI8ilc6IMxOyX4sspwkv98hg==} + + '@prisma/engines@5.3.1': + resolution: {integrity: sha512-6QkILNyfeeN67BNEPEtkgh3Xo2tm6D7V+UhrkBbRHqKw9CTaz/vvTP/ROwYSP/3JT2MtIutZm/EnhxUiuOPVDA==} + + '@prisma/fetch-engine@5.16.0': + resolution: {integrity: sha512-8C8y6J9eWRl+R/aO3vQ2HlmM9IbjAmrZaaEAdC0OJfG3CHvbTOcL7VRY6CEUKo8RwZ8bdATOePaSMS634fHWgw==} + + '@prisma/fetch-engine@5.3.1': + resolution: {integrity: sha512-w1yk1YiK8N82Pobdq58b85l6e8akyrkxuzwV9DoiUTRf3gpsuhJJesHc4Yi0WzUC9/3znizl1UfCsI6dhkj3Vw==} + + '@prisma/generator-helper@5.3.1': + resolution: {integrity: sha512-zrYS0iHLgPlOJjYnd5KvVMMvSS+ktOL39EwooS5EnyvfzwfzxlKCeOUgxTfiKYs0WUWqzEvyNAYtramYgSknsQ==} + + '@prisma/get-platform@5.16.0': + resolution: {integrity: sha512-ynp2jAYfYdd7OObX+uWaFRpvhPVmpF0nsRMhbrWdVVUj39q3Zr8dGz5WDj2g+BTUE++u1T1Am3RyM3PBQdDZXA==} + + '@prisma/get-platform@5.3.1': + resolution: {integrity: sha512-3IiZY2BUjKnAuZ0569zppZE6/rZbVAM09//c2nvPbbkGG9MqrirA8fbhhF7tfVmhyVfdmVCHnf/ujWPHJ8B46Q==} + + '@prisma/internals@5.3.1': + resolution: {integrity: sha512-zkW73hPHHNrMD21PeYgCTBfMu71vzJf+WtfydtJbS0JVJKyLfOel0iWSQg7wjNeQfccKp+NdHJ/5rTJ4NEUzgA==} + + '@prisma/prisma-schema-wasm@5.3.1-2.61e140623197a131c2a6189271ffee05a7aa9a59': + resolution: {integrity: sha512-+zUI7NQDXfcNnU8HgrAj4jRMv8yRfITLzcfv0Urf0adKimM+hkkVG4rX38i9zWMlxekkEBw7NLFx3Gxxy8d3iQ==} + + '@tsconfig/node10@1.0.11': + resolution: {integrity: sha512-DcRjDCujK/kCk/cUe8Xz8ZSpm8mS3mNNpta+jGCA6USEDfktlNvm1+IuZ9eTcDbNk41BHwpHHeW+N1lKCz4zOw==} + + '@tsconfig/node12@1.0.11': + resolution: {integrity: sha512-cqefuRsh12pWyGsIoBKJA9luFu3mRxCA+ORZvA4ktLSzIuCUtWVxGIuXigEwO5/ywWFMZ2QEGKWvkZG1zDMTag==} + + '@tsconfig/node14@1.0.3': + resolution: {integrity: sha512-ysT8mhdixWK6Hw3i1V2AeRqZ5WfXg1G43mqoYlM2nc6388Fq5jcXyr5mRsqViLx/GJYdoL0bfXD8nmF+Zn/Iow==} + + '@tsconfig/node16@1.0.4': + resolution: {integrity: sha512-vxhUy4J8lyeyinH7Azl1pdd43GJhZH/tP2weN8TntQblOY+A0XbT8DJk1/oCPuOOyg/Ja757rG0CgHcWC8OfMA==} + + '@tsoa/cli@6.2.0': + resolution: {integrity: sha512-kzr10MsARpuivJl59XD33+sdMA18Rx9KBu7NCp18nV6kPQ1LDrVBwVgLL96w7lBgUGsCgVJ1/cUePW313uTZCw==} + engines: {node: '>=18.0.0', yarn: '>=1.9.4'} + hasBin: true + + '@tsoa/runtime@6.2.0': + resolution: {integrity: sha512-iXSi5rDZWcPRcLKa9WaMBUdh4SdDN+9Cmy+R7i/DSCtFtbtUqE+ui+IMV9o6+759N6J3FqGBaPWa9kAtOrL4sA==} + engines: {node: '>=18.0.0', yarn: '>=1.9.4'} + + '@types/accepts@1.3.7': + resolution: {integrity: sha512-Pay9fq2lM2wXPWbteBsRAGiWH2hig4ZE2asK+mm7kUzlxRTfL961rj89I6zV/E3PcIkDqyuBEcMxFT7rccugeQ==} + + '@types/body-parser@1.19.5': + resolution: {integrity: sha512-fB3Zu92ucau0iQ0JMCFQE7b/dv8Ot07NI3KaZIkIUNXq82k4eBAqUaneXfleGY9JWskeS9y+u0nXMyspcuQrCg==} + + '@types/connect@3.4.38': + resolution: {integrity: sha512-K6uROf1LD88uDQqJCktA4yzL1YYAK6NgfsI0v/mTgyPKWsX1CnJ0XPSDhViejru1GcRkLWb8RlzFYJRqGUbaug==} + + '@types/content-disposition@0.5.8': + resolution: {integrity: sha512-QVSSvno3dE0MgO76pJhmv4Qyi/j0Yk9pBp0Y7TJ2Tlj+KCgJWY6qX7nnxCOLkZ3VYRSIk1WTxCvwUSdx6CCLdg==} + + '@types/cookies@0.9.0': + resolution: {integrity: sha512-40Zk8qR147RABiQ7NQnBzWzDcjKzNrntB5BAmeGCb2p/MIyOE+4BVvc17wumsUqUw00bJYqoXFHYygQnEFh4/Q==} + + '@types/cors@2.8.17': + resolution: {integrity: sha512-8CGDvrBj1zgo2qE+oS3pOCyYNqCPryMWY2bGfwA0dcfopWGgxs+78df0Rs3rc9THP4JkOhLsAa+15VdpAqkcUA==} + + '@types/cross-spawn@6.0.2': + resolution: {integrity: sha512-KuwNhp3eza+Rhu8IFI5HUXRP0LIhqH5cAjubUvGXXthh4YYBuP2ntwEX+Cz8GJoZUHlKo247wPWOfA9LYEq4cw==} + + '@types/debug@4.1.8': + resolution: {integrity: sha512-/vPO1EPOs306Cvhwv7KfVfYvOJqA/S/AXjaHQiJboCZzcNDb+TIJFN9/2C9DZ//ijSKWioNyUxD792QmDJ+HKQ==} + + '@types/express-serve-static-core@4.17.43': + resolution: {integrity: sha512-oaYtiBirUOPQGSWNGPWnzyAFJ0BP3cwvN4oWZQY+zUBwpVIGsKUkpBpSztp74drYcjavs7SKFZ4DX1V2QeN8rg==} + + '@types/express@4.17.21': + resolution: {integrity: sha512-ejlPM315qwLpaQlQDTjPdsUFSc6ZsP4AN6AlWnogPjQ7CVi7PYF3YVz+CY3jE2pwYf7E/7HlDAN0rV2GxTG0HQ==} + + '@types/http-assert@1.5.5': + resolution: {integrity: sha512-4+tE/lwdAahgZT1g30Jkdm9PzFRde0xwxBNUyRsCitRvCQB90iuA2uJYdUnhnANRcqGXaWOGY4FEoxeElNAK2g==} + + '@types/http-errors@2.0.4': + resolution: {integrity: sha512-D0CFMMtydbJAegzOyHjtiKPLlvnm3iTZyZRSZoLq2mRhDdmLfIWOCYPfQJ4cu2erKghU++QvjcUjp/5h7hESpA==} + + '@types/keygrip@1.0.6': + resolution: {integrity: sha512-lZuNAY9xeJt7Bx4t4dx0rYCDqGPW8RXhQZK1td7d4H6E9zYbLoOtjBvfwdTKpsyxQI/2jv+armjX/RW+ZNpXOQ==} + + '@types/koa-compose@3.2.8': + resolution: {integrity: sha512-4Olc63RY+MKvxMwVknCUDhRQX1pFQoBZ/lXcRLP69PQkEpze/0cr8LNqJQe5NFb/b19DWi2a5bTi2VAlQzhJuA==} + + '@types/koa@2.15.0': + resolution: {integrity: sha512-7QFsywoE5URbuVnG3loe03QXuGajrnotr3gQkXcEBShORai23MePfFYdhz90FEtBBpkyIYQbVD+evKtloCgX3g==} + + '@types/mime@1.3.5': + resolution: {integrity: sha512-/pyBZWSLD2n0dcHE3hq8s8ZvcETHtEuF+3E7XVt0Ig2nvsVQXdghHVcEkIWjy9A0wKfTn97a/PSDYohKIlnP/w==} + + '@types/mime@4.0.0': + resolution: {integrity: sha512-5eEkJZ/BLvTE3vXGKkWlyTSUVZuzj23Wj8PoyOq2lt5I3CYbiLBOPb3XmCW6QcuOibIUE6emHXHt9E/F/rCa6w==} + deprecated: This is a stub types definition. mime provides its own type definitions, so you do not need this installed. + + '@types/ms@0.7.34': + resolution: {integrity: sha512-nG96G3Wp6acyAgJqGasjODb+acrI7KltPiRxzHPXnP3NgI28bpQDRv53olbqGXbfcgF5aiiHmO3xpwEpS5Ld9g==} + + '@types/multer@1.4.11': + resolution: {integrity: sha512-svK240gr6LVWvv3YGyhLlA+6LRRWA4mnGIU7RcNmgjBYFl6665wcXrRfxGp5tEPVHUNm5FMcmq7too9bxCwX/w==} + + '@types/node@20.12.2': + resolution: {integrity: sha512-zQ0NYO87hyN6Xrclcqp7f8ZbXNbRfoGWNcMvHTPQp9UUrwI0mI7XBz+cu7/W6/VClYo2g63B0cjull/srU7LgQ==} + + '@types/normalize-package-data@2.4.4': + resolution: {integrity: sha512-37i+OaWTh9qeK4LSHPsyRC7NahnGotNuZvjLSgcPzblpHB3rrCJxAOgI5gCdKm7coonsaX1Of0ILiTcnZjbfxA==} + + '@types/qs@6.9.14': + resolution: {integrity: sha512-5khscbd3SwWMhFqylJBLQ0zIu7c1K6Vz0uBIt915BI3zV0q1nfjRQD3RqSBcPaO6PHEF4ov/t9y89fSiyThlPA==} + + '@types/range-parser@1.2.7': + resolution: {integrity: sha512-hKormJbkJqzQGhziax5PItDUTMAM9uE2XXQmM37dyd4hVM+5aVl7oVxMVUiVQn2oCQFN/LKCZdvSM0pFRqbSmQ==} + + '@types/retry@0.12.0': + resolution: {integrity: sha512-wWKOClTTiizcZhXnPY4wikVAwmdYHp8q6DmC+EJUzAMsycb7HB32Kh9RN4+0gExjmPmZSAQjgURXIGATPegAvA==} + + '@types/send@0.17.4': + resolution: {integrity: sha512-x2EM6TJOybec7c52BX0ZspPodMsQUd5L6PRwOunVyVUhXiBSKf3AezDL8Dgvgt5o0UfKNfuA0eMLr2wLT4AiBA==} + + '@types/serve-static@1.15.5': + resolution: {integrity: sha512-PDRk21MnK70hja/YF8AHfC7yIsiQHn1rcXx7ijCFBX/k+XQJhQT/gw3xekXKJvx+5SXaMMS8oqQy09Mzvz2TuQ==} + + '@types/swagger-ui-express@4.1.6': + resolution: {integrity: sha512-UVSiGYXa5IzdJJG3hrc86e8KdZWLYxyEsVoUI4iPXc7CO4VZ3AfNP8d/8+hrDRIqz+HAaSMtZSqAsF3Nq2X/Dg==} + + '@zxing/text-encoding@0.9.0': + resolution: {integrity: sha512-U/4aVJ2mxI0aDNI8Uq0wEhMgY+u4CNtEb0om3+y3+niDAsoTCOB33UF0sxpzqzdqXLqmvc+vZyAt4O8pPdfkwA==} + + abbrev@1.1.1: + resolution: {integrity: sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==} + + accepts@1.3.8: + resolution: {integrity: sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw==} + engines: {node: '>= 0.6'} + + acorn-walk@8.3.2: + resolution: {integrity: sha512-cjkyv4OtNCIeqhHrfS81QWXoCBPExR/J62oyEqepVw8WaQeSqpW2uhuLPh1m9eWhDuOo/jUXVTlifvesOWp/4A==} + engines: {node: '>=0.4.0'} + + acorn@8.11.3: + resolution: {integrity: sha512-Y9rRfJG5jcKOE0CLisYbojUjIrIEE7AGMzA/Sm4BslANhbS+cDMpgBdcPT91oJ7OuJ9hYJBx59RjbhxVnrF8Xg==} + engines: {node: '>=0.4.0'} + hasBin: true + + agent-base@7.1.1: + resolution: {integrity: sha512-H0TSyFNDMomMNJQBn8wFV5YC/2eJ+VXECwOadZJT554xP6cODZHPX3H9QMQECxvrgiSOP1pHjy1sMWQVYJOUOA==} + engines: {node: '>= 14'} + + aggregate-error@3.1.0: + resolution: {integrity: sha512-4I7Td01quW/RpocfNayFdFVk1qSuoh0E7JrbRJ16nH01HhKFQ88INq9Sd+nd72zqRySlr9BmDA8xlEJ6vJMrYA==} + engines: {node: '>=8'} + + ansi-escapes@4.3.2: + resolution: {integrity: sha512-gKXj5ALrKWQLsYG9jlTRmR/xKluxHV+Z9QEwNIgCfM1/uwPMCuzVVnh5mwTd+OuBZcwSIMbqssNWRm1lE51QaQ==} + engines: {node: '>=8'} + + ansi-regex@5.0.1: + resolution: {integrity: sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==} + engines: {node: '>=8'} + + ansi-regex@6.0.1: + resolution: {integrity: sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA==} + engines: {node: '>=12'} + + ansi-styles@3.2.1: + resolution: {integrity: sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==} + engines: {node: '>=4'} + + ansi-styles@4.3.0: + resolution: {integrity: sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==} + engines: {node: '>=8'} + + ansi-styles@6.2.1: + resolution: {integrity: sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==} + engines: {node: '>=12'} + + anymatch@3.1.3: + resolution: {integrity: sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==} + engines: {node: '>= 8'} + + archiver-utils@2.1.0: + resolution: {integrity: sha512-bEL/yUb/fNNiNTuUz979Z0Yg5L+LzLxGJz8x79lYmR54fmTIb6ob/hNQgkQnIUDWIFjZVQwl9Xs356I6BAMHfw==} + engines: {node: '>= 6'} + + archiver-utils@3.0.4: + resolution: {integrity: sha512-KVgf4XQVrTjhyWmx6cte4RxonPLR9onExufI1jhvw/MQ4BB6IsZD5gT8Lq+u/+pRkWna/6JoHpiQioaqFP5Rzw==} + engines: {node: '>= 10'} + + archiver@5.3.2: + resolution: {integrity: sha512-+25nxyyznAXF7Nef3y0EbBeqmGZgeN/BxHX29Rs39djAfaFalmQ89SE6CWyDCHzGL0yt/ycBtNOmGTW0FyGWNw==} + engines: {node: '>= 10'} + + arg@4.1.3: + resolution: {integrity: sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA==} + + arg@5.0.2: + resolution: {integrity: sha512-PYjyFOLKQ9y57JvQ6QLo8dAgNqswh8M1RMJYdQduT6xbWSgK36P/Z/v+p888pM69jMMfS8Xd8F6I1kQ/I9HUGg==} + + array-buffer-byte-length@1.0.1: + resolution: {integrity: sha512-ahC5W1xgou+KTXix4sAO8Ki12Q+jf4i0+tmk3sC+zgcynshkHxzpXdImBehiUYKKKDwvfFiJl1tZt6ewscS1Mg==} + engines: {node: '>= 0.4'} + + array-flatten@1.1.1: + resolution: {integrity: sha512-PCVAQswWemu6UdxsDFFX/+gVeYqKAod3D3UVm91jHwynguOwAvYPhx8nNlM++NqRcK6CxxpUafjmhIdKiHibqg==} + + array-union@2.1.0: + resolution: {integrity: sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==} + engines: {node: '>=8'} + + array.prototype.map@1.0.7: + resolution: {integrity: sha512-XpcFfLoBEAhezrrNw1V+yLXkE7M6uR7xJEsxbG6c/V9v043qurwVJB9r9UTnoSioFDoz1i1VOydpWGmJpfVZbg==} + engines: {node: '>= 0.4'} + + arraybuffer.prototype.slice@1.0.3: + resolution: {integrity: sha512-bMxMKAjg13EBSVscxTaYA4mRc5t1UAXa2kXiGTNfZ079HIWXEkKmkgFrh/nJqamaLSrXO5H4WFFkPEaLJWbs3A==} + engines: {node: '>= 0.4'} + + asn1.js@5.4.1: + resolution: {integrity: sha512-+I//4cYPccV8LdmBLiX8CYvf9Sp3vQsrqu2QNXRcrbiWvcx/UdlFiqUJJzxRQxgsZmvhXhn4cSKeSmoFjVdupA==} + + astral-regex@2.0.0: + resolution: {integrity: sha512-Z7tMw1ytTXt5jqMcOP+OQteU1VuNK9Y02uuJtKQ1Sv69jXQKKg5cibLwGJow8yzZP+eAc18EmLGPal0bp36rvQ==} + engines: {node: '>=8'} + + async@3.2.5: + resolution: {integrity: sha512-baNZyqaaLhyLVKm/DlvdW051MSgO6b8eVfIezl9E5PqWxFgzLm/wQntEW4zOytVburDEr0JlALEpdOFwvErLsg==} + + available-typed-arrays@1.0.7: + resolution: {integrity: sha512-wvUjBtSGN7+7SjNpq/9M2Tg350UZD3q62IFZLbRAR1bSMlCo1ZaeW+BJ+D090e4hIIZLBcTDWe4Mh4jvUDajzQ==} + engines: {node: '>= 0.4'} + + balanced-match@1.0.2: + resolution: {integrity: sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==} + + base64-js@1.5.1: + resolution: {integrity: sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==} + + binary-extensions@2.3.0: + resolution: {integrity: sha512-Ceh+7ox5qe7LJuLHoY0feh3pHuUDHAcRUeyL2VYghZwfpkNIy/+8Ocg0a3UuSoYzavmylwuLWQOf3hl0jjMMIw==} + engines: {node: '>=8'} + + bl@4.1.0: + resolution: {integrity: sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w==} + + block-stream2@2.1.0: + resolution: {integrity: sha512-suhjmLI57Ewpmq00qaygS8UgEq2ly2PCItenIyhMqVjo4t4pGzqMvfgJuX8iWTeSDdfSSqS6j38fL4ToNL7Pfg==} + + bn.js@4.12.0: + resolution: {integrity: sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA==} + + body-parser@1.20.2: + resolution: {integrity: sha512-ml9pReCu3M61kGlqoTm2umSXTlRTuGTx0bfYj+uIUKKYycG5NtSbeetV3faSU6R7ajOPw0g/J1PvK4qNy7s5bA==} + engines: {node: '>= 0.8', npm: 1.2.8000 || >= 1.4.16} + + brace-expansion@1.1.11: + resolution: {integrity: sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==} + + brace-expansion@2.0.1: + resolution: {integrity: sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==} + + braces@3.0.2: + resolution: {integrity: sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==} + engines: {node: '>=8'} + + braces@3.0.3: + resolution: {integrity: sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==} + engines: {node: '>=8'} + + browser-or-node@2.1.1: + resolution: {integrity: sha512-8CVjaLJGuSKMVTxJ2DpBl5XnlNDiT4cQFeuCJJrvJmts9YrTZDizTX7PjC2s6W4x+MBGZeEY6dGMrF04/6Hgqg==} + + buffer-crc32@0.2.13: + resolution: {integrity: sha512-VO9Ht/+p3SN7SKWqcrgEzjGbRSJYTx+Q1pTQC0wrWqHx0vpJraQ6GtHx8tvcg1rlK1byhU5gccxgOgj7B0TDkQ==} + + buffer@5.7.1: + resolution: {integrity: sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==} + + bytes@3.1.2: + resolution: {integrity: sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==} + engines: {node: '>= 0.8'} + + call-bind@1.0.7: + resolution: {integrity: sha512-GHTSNSYICQ7scH7sZ+M2rFopRoLh8t2bLSW6BbgrtLsahOIB5iyAVJf9GjWK3cYTDaMj4XdBpM1cA6pIS0Kv2w==} + engines: {node: '>= 0.4'} + + chalk@2.4.2: + resolution: {integrity: sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==} + engines: {node: '>=4'} + + checkpoint-client@1.1.27: + resolution: {integrity: sha512-xstymfUalJOv6ZvTtmkwP4ORJN36ikT4PvrIoLe3wstbYf87XIXCcZrSmbFQOjyB0v1qbBnCsAscDpfdZlCkFA==} + + chevrotain@10.5.0: + resolution: {integrity: sha512-Pkv5rBY3+CsHOYfV5g/Vs5JY9WTHHDEKOlohI2XeygaZhUeqhAlldZ8Hz9cRmxu709bvS08YzxHdTPHhffc13A==} + + chokidar@3.6.0: + resolution: {integrity: sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw==} + engines: {node: '>= 8.10.0'} + + ci-info@3.8.0: + resolution: {integrity: sha512-eXTggHWSooYhq49F2opQhuHWgzucfF2YgODK4e1566GQs5BIfP30B0oenwBJHfWxAs2fyPB1s7Mg949zLf61Yw==} + engines: {node: '>=8'} + + clean-stack@2.2.0: + resolution: {integrity: sha512-4diC9HaTE+KRAMWhDhrGOECgWZxoevMc5TlkObMqNSsVU62PYzXZ/SMTjzyGAFF1YusgxGcSWTEXBhp0CPwQ1A==} + engines: {node: '>=6'} + + cli-truncate@2.1.0: + resolution: {integrity: sha512-n8fOixwDD6b/ObinzTrp1ZKFzbgvKZvuz/TvejnLn1aQfC6r52XEx85FmuC+3HI+JM7coBRXUvNqEU2PHVrHpg==} + engines: {node: '>=8'} + + cliui@8.0.1: + resolution: {integrity: sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==} + engines: {node: '>=12'} + + color-convert@1.9.3: + resolution: {integrity: sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==} + + color-convert@2.0.1: + resolution: {integrity: sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==} + engines: {node: '>=7.0.0'} + + color-name@1.1.3: + resolution: {integrity: sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==} + + color-name@1.1.4: + resolution: {integrity: sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==} + + commondir@1.0.1: + resolution: {integrity: sha512-W9pAhw0ja1Edb5GVdIF1mjZw/ASI0AlShXM83UUGe2DVr5TdAPEA1OA8m/g8zWp9x6On7gqufY+FatDbC3MDQg==} + + compress-commons@4.1.2: + resolution: {integrity: sha512-D3uMHtGc/fcO1Gt1/L7i1e33VOvD4A9hfQLP+6ewd+BvG/gQ84Yh4oftEhAdjSMgBgwGL+jsppT7JYNpo6MHHg==} + engines: {node: '>= 10'} + + concat-map@0.0.1: + resolution: {integrity: sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==} + + content-disposition@0.5.4: + resolution: {integrity: sha512-FveZTNuGw04cxlAiWbzi6zTAL/lhehaWbTtgluJh4/E95DqMwTmha3KZN1aAWA8cFIhHzMZUvLevkw5Rqk+tSQ==} + engines: {node: '>= 0.6'} + + content-type@1.0.5: + resolution: {integrity: sha512-nTjqfcBFEipKdXCv4YDQWCfmcLZKm81ldF0pAopTvyrFGVbcR6P/VAAd5G7N+0tTr8QqiU0tFadD6FK4NtJwOA==} + engines: {node: '>= 0.6'} + + cookie-signature@1.0.6: + resolution: {integrity: sha512-QADzlaHc8icV8I7vbaJXJwod9HWYp8uCqf1xa4OfNu1T7JVxQIrUgOWtHdNDtPiywmFbiS12VjotIXLrKM3orQ==} + + cookie@0.6.0: + resolution: {integrity: sha512-U71cyTamuh1CRNCfpGY6to28lxvNwPG4Guz/EVjgf3Jmzv0vlDp1atT9eS5dDjMYHucpHbWns6Lwf3BKz6svdw==} + engines: {node: '>= 0.6'} + + core-util-is@1.0.3: + resolution: {integrity: sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==} + + cors@2.8.5: + resolution: {integrity: sha512-KIHbLJqu73RGr/hnbrO9uBeixNGuvSQjul/jdFvS/KFSIH1hWVd1ng7zOHx+YrEfInLG7q4n6GHQ9cDtxv/P6g==} + engines: {node: '>= 0.10'} + + crc-32@1.2.2: + resolution: {integrity: sha512-ROmzCKrTnOwybPcJApAA6WBWij23HVfGVNKqqrZpuyZOHqK2CwHSvpGuyt/UNNvaIjEd8X5IFGp4Mh+Ie1IHJQ==} + engines: {node: '>=0.8'} + hasBin: true + + crc32-stream@4.0.3: + resolution: {integrity: sha512-NT7w2JVU7DFroFdYkeq8cywxrgjPHWkdX1wjpRQXPX5Asews3tA+Ght6lddQO5Mkumffp3X7GEqku3epj2toIw==} + engines: {node: '>= 10'} + + create-require@1.1.1: + resolution: {integrity: sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ==} + + cross-spawn@7.0.3: + resolution: {integrity: sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==} + engines: {node: '>= 8'} + + crypto-random-string@2.0.0: + resolution: {integrity: sha512-v1plID3y9r/lPhviJ1wrXpLeyUIGAZ2SHNYTEapm7/8A9nLPoyvVp3RK/EPFqn5kEznyWgYZNsRtYYIWbuG8KA==} + engines: {node: '>=8'} + + data-view-buffer@1.0.1: + resolution: {integrity: sha512-0lht7OugA5x3iJLOWFhWK/5ehONdprk0ISXqVFn/NFrDu+cuc8iADFrGQz5BnRK7LLU3JmkbXSxaqX+/mXYtUA==} + engines: {node: '>= 0.4'} + + data-view-byte-length@1.0.1: + resolution: {integrity: sha512-4J7wRJD3ABAzr8wP+OcIcqq2dlUKp4DVflx++hs5h5ZKydWMI6/D/fAot+yh6g2tHh8fLFTvNOaVN357NvSrOQ==} + engines: {node: '>= 0.4'} + + data-view-byte-offset@1.0.0: + resolution: {integrity: sha512-t/Ygsytq+R995EJ5PZlD4Cu56sWa8InXySaViRzw9apusqsOO2bQP+SbYzAhR0pFKoB+43lYy8rWban9JSuXnA==} + engines: {node: '>= 0.4'} + + debug@2.6.9: + resolution: {integrity: sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==} + peerDependencies: + supports-color: '*' + peerDependenciesMeta: + supports-color: + optional: true + + debug@4.3.4: + resolution: {integrity: sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==} + engines: {node: '>=6.0'} + peerDependencies: + supports-color: '*' + peerDependenciesMeta: + supports-color: + optional: true + + decode-uri-component@0.2.2: + resolution: {integrity: sha512-FqUYQ+8o158GyGTrMFJms9qh3CqTKvAqgqsTnkLI8sKu0028orqBhxNMFkFen0zGyg6epACD32pjVk58ngIErQ==} + engines: {node: '>=0.10'} + + define-data-property@1.1.4: + resolution: {integrity: sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A==} + engines: {node: '>= 0.4'} + + define-properties@1.2.1: + resolution: {integrity: sha512-8QmQKqEASLd5nx0U1B1okLElbUuuttJ/AnYmRXbbbGDWh6uS208EjD4Xqq/I9wK7u0v6O08XhTWnt5XtEbR6Dg==} + engines: {node: '>= 0.4'} + + del@6.1.1: + resolution: {integrity: sha512-ua8BhapfP0JUJKC/zV9yHHDW/rDoDxP4Zhn3AkA6/xT6gY7jYXJiaeyBZznYVujhZZET+UgcbZiQ7sN3WqcImg==} + engines: {node: '>=10'} + + depd@2.0.0: + resolution: {integrity: sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==} + engines: {node: '>= 0.8'} + + destroy@1.2.0: + resolution: {integrity: sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg==} + engines: {node: '>= 0.8', npm: 1.2.8000 || >= 1.4.16} + + diff@4.0.2: + resolution: {integrity: sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==} + engines: {node: '>=0.3.1'} + + dir-glob@3.0.1: + resolution: {integrity: sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==} + engines: {node: '>=8'} + + dotenv@16.0.3: + resolution: {integrity: sha512-7GO6HghkA5fYG9TYnNxi14/7K9f5occMlp3zXAuSxn7CKCxt9xbNWG7yF8hTCSUchlfWSe3uLmlPfigevRItzQ==} + engines: {node: '>=12'} + + dotenv@16.4.5: + resolution: {integrity: sha512-ZmdL2rui+eB2YwhsWzjInR8LldtZHGDoQ1ugH85ppHKwpUHL7j7rN0Ti9NCnGiQbhaZ11FpR+7ao1dNsmduNUg==} + engines: {node: '>=12'} + + eastasianwidth@0.2.0: + resolution: {integrity: sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==} + + ecdsa-sig-formatter@1.0.11: + resolution: {integrity: sha512-nagl3RYrbNv6kQkeJIpt6NJZy8twLB/2vtz6yN9Z4vRKHN4/QZJIEbqohALSgwKdnksuY3k5Addp5lg8sVoVcQ==} + + ee-first@1.1.1: + resolution: {integrity: sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==} + + emoji-regex@8.0.0: + resolution: {integrity: sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==} + + emoji-regex@9.2.2: + resolution: {integrity: sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==} + + encodeurl@1.0.2: + resolution: {integrity: sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w==} + engines: {node: '>= 0.8'} + + end-of-stream@1.4.4: + resolution: {integrity: sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==} + + env-paths@2.2.1: + resolution: {integrity: sha512-+h1lkLKhZMTYjog1VEpJNG7NZJWcuc2DDk/qsqSTRRCOXiLjeQ1d1/udrUGhqMxUgAlwKNZ0cf2uqan5GLuS2A==} + engines: {node: '>=6'} + + error-ex@1.3.2: + resolution: {integrity: sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==} + + es-abstract@1.23.3: + resolution: {integrity: sha512-e+HfNH61Bj1X9/jLc5v1owaLYuHdeHHSQlkhCBiTK8rBvKaULl/beGMxwrMXjpYrv4pz22BlY570vVePA2ho4A==} + engines: {node: '>= 0.4'} + + es-aggregate-error@1.0.13: + resolution: {integrity: sha512-KkzhUUuD2CUMqEc8JEqsXEMDHzDPE8RCjZeUBitsnB1eNcAJWQPiciKsMXe3Yytj4Flw1XLl46Qcf9OxvZha7A==} + engines: {node: '>= 0.4'} + + es-array-method-boxes-properly@1.0.0: + resolution: {integrity: sha512-wd6JXUmyHmt8T5a2xreUwKcGPq6f1f+WwIJkijUqiGcJz1qqnZgP6XIK+QyIWU5lT7imeNxUll48bziG+TSYcA==} + + es-define-property@1.0.0: + resolution: {integrity: sha512-jxayLKShrEqqzJ0eumQbVhTYQM27CfT1T35+gCgDFoL82JLsXqTJ76zv6A0YLOgEnLUMvLzsDsGIrl8NFpT2gQ==} + engines: {node: '>= 0.4'} + + es-errors@1.3.0: + resolution: {integrity: sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==} + engines: {node: '>= 0.4'} + + es-get-iterator@1.1.3: + resolution: {integrity: sha512-sPZmqHBe6JIiTfN5q2pEi//TwxmAFHwj/XEuYjTuse78i8KxaqMTTzxPoFKuzRpDpTJ+0NAbpfenkmH2rePtuw==} + + es-object-atoms@1.0.0: + resolution: {integrity: sha512-MZ4iQ6JwHOBQjahnjwaC1ZtIBH+2ohjamzAO3oaHcXYup7qxjF2fixyH+Q71voWHeOkI2q/TnJao/KfXYIZWbw==} + engines: {node: '>= 0.4'} + + es-set-tostringtag@2.0.3: + resolution: {integrity: sha512-3T8uNMC3OQTHkFUsFq8r/BwAXLHvU/9O9mE0fBc/MY5iq/8H7ncvO947LmYA6ldWw9Uh8Yhf25zu6n7nML5QWQ==} + engines: {node: '>= 0.4'} + + es-to-primitive@1.2.1: + resolution: {integrity: sha512-QCOllgZJtaUo9miYBcLChTUaHNjJF3PYs1VidD7AwiEj1kYxKeQTctLAezAOH5ZKRH0g2IgPn6KwB4IT8iRpvA==} + engines: {node: '>= 0.4'} + + escalade@3.1.2: + resolution: {integrity: sha512-ErCHMCae19vR8vQGe50xIsVomy19rg6gFu3+r3jkEO46suLMWBksvVyoGgQV+jOfl84ZSOSlmv6Gxa89PmTGmA==} + engines: {node: '>=6'} + + escape-html@1.0.3: + resolution: {integrity: sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==} + + escape-string-regexp@1.0.5: + resolution: {integrity: sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==} + engines: {node: '>=0.8.0'} + + escape-string-regexp@4.0.0: + resolution: {integrity: sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==} + engines: {node: '>=10'} + + etag@1.8.1: + resolution: {integrity: sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg==} + engines: {node: '>= 0.6'} + + execa@5.1.1: + resolution: {integrity: sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg==} + engines: {node: '>=10'} + + express@4.19.2: + resolution: {integrity: sha512-5T6nhjsT+EOMzuck8JjBHARTHfMht0POzlA60WV2pMD3gyXw2LZnZ+ueGdNxG+0calOJcWKbpFcuzLZ91YWq9Q==} + engines: {node: '>= 0.10.0'} + + fast-glob@3.3.2: + resolution: {integrity: sha512-oX2ruAFQwf/Orj8m737Y5adxDQO0LAB7/S5MnxCdTNDd4p6BsyIVsv9JQsATbTSq8KHRpLwIHbVlUNatxd+1Ow==} + engines: {node: '>=8.6.0'} + + fast-jwt@4.0.0: + resolution: {integrity: sha512-CnI93Tmk7eSzfw4e0Jlc5ZcWiN+/zK7xAKAhtXS8PAcKmYqfcXqxJl1hMyhk3iEt0M9JLo7DCYRDV2XcIacWAw==} + engines: {node: '>=16 <22'} + + fast-xml-parser@4.3.6: + resolution: {integrity: sha512-M2SovcRxD4+vC493Uc2GZVcZaj66CCJhWurC4viynVSTvrpErCShNcDz1lAho6n9REQKvL/ll4A4/fw6Y9z8nw==} + hasBin: true + + fastq@1.17.1: + resolution: {integrity: sha512-sRVD3lWVIXWg6By68ZN7vho9a1pQcN/WBFaAAsDDFzlJjvoGx0P8z7V1t72grFJfJhu3YPZBuu25f7Kaw2jN1w==} + + fill-range@7.0.1: + resolution: {integrity: sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==} + engines: {node: '>=8'} + + fill-range@7.1.1: + resolution: {integrity: sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==} + engines: {node: '>=8'} + + filter-obj@1.1.0: + resolution: {integrity: sha512-8rXg1ZnX7xzy2NGDVkBVaAy+lSlPNwad13BtgSlLuxfIslyt5Vg64U7tFcCt4WS1R0hvtnQybT/IyCkGZ3DpXQ==} + engines: {node: '>=0.10.0'} + + finalhandler@1.2.0: + resolution: {integrity: sha512-5uXcUVftlQMFnWC9qu/svkWv3GTd2PfUhK/3PLkYNAe7FbqJMt3515HaxE6eRL74GdsriiwujiawdaB1BpEISg==} + engines: {node: '>= 0.8'} + + find-cache-dir@3.3.2: + resolution: {integrity: sha512-wXZV5emFEjrridIgED11OoUKLxiYjAcqot/NJdAkOhlJ+vGzwhOAfcG5OX1jP+S0PcjEn8bdMJv+g2jwQ3Onig==} + engines: {node: '>=8'} + + find-up@4.1.0: + resolution: {integrity: sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==} + engines: {node: '>=8'} + + find-up@5.0.0: + resolution: {integrity: sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==} + engines: {node: '>=10'} + + for-each@0.3.3: + resolution: {integrity: sha512-jqYfLp7mo9vIyQf8ykW2v7A+2N4QjeCeI5+Dz9XraiO1ign81wjiH7Fb9vSOWvQfNtmSa4H2RoQTrrXivdUZmw==} + + foreground-child@3.1.1: + resolution: {integrity: sha512-TMKDUnIte6bfb5nWv7V/caI169OHgvwjb7V4WkeUvbQQdjr5rWKqHFiKWb/fcOwB+CzBT+qbWjvj+DVwRskpIg==} + engines: {node: '>=14'} + + forwarded@0.2.0: + resolution: {integrity: sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow==} + engines: {node: '>= 0.6'} + + fp-ts@2.16.1: + resolution: {integrity: sha512-by7U5W8dkIzcvDofUcO42yl9JbnHTEDBrzu3pt5fKT+Z4Oy85I21K80EYJYdjQGC2qum4Vo55Ag57iiIK4FYuA==} + + fresh@0.5.2: + resolution: {integrity: sha512-zJ2mQYM18rEFOudeV4GShTGIQ7RbzA7ozbU9I/XBpm7kqgMywgmylMwXHxZJmkVoYkna9d2pVXVXPdYTP9ej8Q==} + engines: {node: '>= 0.6'} + + fs-constants@1.0.0: + resolution: {integrity: sha512-y6OAwoSIf7FyjMIv94u+b5rdheZEjzR63GTyZJm5qh4Bi+2YgwLCcI/fPFZkL5PSixOt6ZNKm+w+Hfp/Bciwow==} + + fs-extra@11.1.1: + resolution: {integrity: sha512-MGIE4HOvQCeUCzmlHs0vXpih4ysz4wg9qiSAu6cd42lVwPbTM1TjV7RusoyQqMmk/95gdQZX72u+YW+c3eEpFQ==} + engines: {node: '>=14.14'} + + fs-extra@11.2.0: + resolution: {integrity: sha512-PmDi3uwK5nFuXh7XDTlVnS17xJS7vW36is2+w3xcv8SVxiB4NyATf4ctkVY5bkSjX0Y4nbvZCq1/EjtEyr9ktw==} + engines: {node: '>=14.14'} + + fs-jetpack@5.1.0: + resolution: {integrity: sha512-Xn4fDhLydXkuzepZVsr02jakLlmoARPy+YWIclo4kh0GyNGUHnTqeH/w/qIsVn50dFxtp8otPL2t/HcPJBbxUA==} + + fs.realpath@1.0.0: + resolution: {integrity: sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==} + + fsevents@2.3.3: + resolution: {integrity: sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==} + engines: {node: ^8.16.0 || ^10.6.0 || >=11.0.0} + os: [darwin] + + function-bind@1.1.2: + resolution: {integrity: sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==} + + function.prototype.name@1.1.6: + resolution: {integrity: sha512-Z5kx79swU5P27WEayXM1tBi5Ze/lbIyiNgU3qyXUOf9b2rgXYyF9Dy9Cx+IQv/Lc8WCG6L82zwUPpSS9hGehIg==} + engines: {node: '>= 0.4'} + + functions-have-names@1.2.3: + resolution: {integrity: sha512-xckBUXyTIqT97tq2x2AMb+g163b5JFysYk0x4qxNFwbfQkmNZoiRHb6sPzI9/QV33WeuvVYBUIiD4NzNIyqaRQ==} + + get-caller-file@2.0.5: + resolution: {integrity: sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==} + engines: {node: 6.* || 8.* || >= 10.*} + + get-intrinsic@1.2.4: + resolution: {integrity: sha512-5uYhsJH8VJBTv7oslg4BznJYhDoRI6waYCxMmCdnTrcCrHA/fCFKoTFz2JKKE0HdDFUF7/oQuhzumXJK7paBRQ==} + engines: {node: '>= 0.4'} + + get-stream@6.0.1: + resolution: {integrity: sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==} + engines: {node: '>=10'} + + get-symbol-description@1.0.2: + resolution: {integrity: sha512-g0QYk1dZBxGwk+Ngc+ltRH2IBp2f7zBkBMBJZCDerh6EhlhSR6+9irMCuT/09zD6qkarHUSn529sK/yL4S27mg==} + engines: {node: '>= 0.4'} + + glob-parent@5.1.2: + resolution: {integrity: sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==} + engines: {node: '>= 6'} + + glob@10.3.12: + resolution: {integrity: sha512-TCNv8vJ+xz4QiqTpfOJA7HvYv+tNIRHKfUWw/q+v2jdgN4ebz+KY9tGx5J4rHP0o84mNP+ApH66HRX8us3Khqg==} + engines: {node: '>=16 || 14 >=14.17'} + hasBin: true + + glob@7.2.3: + resolution: {integrity: sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==} + deprecated: Glob versions prior to v9 are no longer supported + + glob@8.1.0: + resolution: {integrity: sha512-r8hpEjiQEYlF2QU0df3dS+nxxSIreXQS1qRhMJM0Q5NDdR386C7jb7Hwwod8Fgiuex+k0GFjgft18yvxm5XoCQ==} + engines: {node: '>=12'} + deprecated: Glob versions prior to v9 are no longer supported + + global-dirs@3.0.1: + resolution: {integrity: sha512-NBcGGFbBA9s1VzD41QXDG+3++t9Mn5t1FpLdhESY6oKY4gYTFpX4wO3sqGUa0Srjtbfj3szX0RnemmrVRUdULA==} + engines: {node: '>=10'} + + globalthis@1.0.3: + resolution: {integrity: sha512-sFdI5LyBiNTHjRd7cGPWapiHWMOXKyuBNX/cWJ3NfzrZQVa8GI/8cofCl74AOVqq9W5kNmguTIzJ/1s2gyI9wA==} + engines: {node: '>= 0.4'} + + globby@11.1.0: + resolution: {integrity: sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g==} + engines: {node: '>=10'} + + gopd@1.0.1: + resolution: {integrity: sha512-d65bNlIadxvpb/A2abVdlqKqV563juRnZ1Wtk6s1sIR8uNsXR70xqIzVqxVf1eTqDunwT2MkczEeaezCKTZhwA==} + + graceful-fs@4.2.11: + resolution: {integrity: sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==} + + handlebars@4.7.8: + resolution: {integrity: sha512-vafaFqs8MZkRrSX7sFVUdo3ap/eNiLnb4IakshzvP56X5Nr1iGKAIqdX6tMlm6HcNRIkr6AxO5jFEoJzzpT8aQ==} + engines: {node: '>=0.4.7'} + hasBin: true + + has-bigints@1.0.2: + resolution: {integrity: sha512-tSvCKtBr9lkF0Ex0aQiP9N+OpV4zi2r/Nee5VkRDbaqv35RLYMzbwQfFSZZH0kR+Rd6302UJZ2p/bJCEoR3VoQ==} + + has-flag@3.0.0: + resolution: {integrity: sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==} + engines: {node: '>=4'} + + has-flag@4.0.0: + resolution: {integrity: sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==} + engines: {node: '>=8'} + + has-property-descriptors@1.0.2: + resolution: {integrity: sha512-55JNKuIW+vq4Ke1BjOTjM2YctQIvCT7GFzHwmfZPGo5wnrgkid0YQtnAleFSqumZm4az3n2BS+erby5ipJdgrg==} + + has-proto@1.0.3: + resolution: {integrity: sha512-SJ1amZAJUiZS+PhsVLf5tGydlaVB8EdFpaSO4gmiUKUOxk8qzn5AIy4ZeJUmh22znIdk/uMAUT2pl3FxzVUH+Q==} + engines: {node: '>= 0.4'} + + has-symbols@1.0.3: + resolution: {integrity: sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==} + engines: {node: '>= 0.4'} + + has-tostringtag@1.0.2: + resolution: {integrity: sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw==} + engines: {node: '>= 0.4'} + + hasha@5.2.2: + resolution: {integrity: sha512-Hrp5vIK/xr5SkeN2onO32H0MgNZ0f17HRNH39WfL0SYUNOTZ5Lz1TJ8Pajo/87dYGEFlLMm7mIc/k/s6Bvz9HQ==} + engines: {node: '>=8'} + + hasown@2.0.2: + resolution: {integrity: sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==} + engines: {node: '>= 0.4'} + + hosted-git-info@2.8.9: + resolution: {integrity: sha512-mxIDAb9Lsm6DoOJ7xH+5+X4y1LU/4Hi50L9C5sIswK3JzULS4bwk1FvjdBgvYR4bzT4tuUQiC15FE2f5HbLvYw==} + + hpagent@1.2.0: + resolution: {integrity: sha512-A91dYTeIB6NoXG+PxTQpCCDDnfHsW9kc06Lvpu1TEe9gnd6ZFeiBoRO9JvzEv6xK7EX97/dUE8g/vBMTqTS3CA==} + engines: {node: '>=14'} + + http-errors@2.0.0: + resolution: {integrity: sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ==} + engines: {node: '>= 0.8'} + + http-proxy-agent@7.0.0: + resolution: {integrity: sha512-+ZT+iBxVUQ1asugqnD6oWoRiS25AkjNfG085dKJGtGxkdwLQrMKU5wJr2bOOFAXzKcTuqq+7fZlTMgG3SRfIYQ==} + engines: {node: '>= 14'} + + https-proxy-agent@7.0.2: + resolution: {integrity: sha512-NmLNjm6ucYwtcUmL7JQC1ZQ57LmHP4lT15FQ8D61nak1rO6DH+fz5qNK2Ap5UN4ZapYICE3/0KodcLYSPsPbaA==} + engines: {node: '>= 14'} + + human-signals@2.1.0: + resolution: {integrity: sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw==} + engines: {node: '>=10.17.0'} + + iconv-lite@0.4.24: + resolution: {integrity: sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==} + engines: {node: '>=0.10.0'} + + ieee754@1.2.1: + resolution: {integrity: sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==} + + ignore-by-default@1.0.1: + resolution: {integrity: sha512-Ius2VYcGNk7T90CppJqcIkS5ooHUZyIQK+ClZfMfMNFEF9VSE73Fq+906u/CWu92x4gzZMWOwfFYckPObzdEbA==} + + ignore-walk@5.0.1: + resolution: {integrity: sha512-yemi4pMf51WKT7khInJqAvsIGzoqYXblnsz0ql8tM+yi1EKYTY1evX4NAbJrLL/Aanr2HyZeluqU+Oi7MGHokw==} + engines: {node: ^12.13.0 || ^14.15.0 || >=16.0.0} + + ignore@5.3.1: + resolution: {integrity: sha512-5Fytz/IraMjqpwfd34ke28PTVMjZjJG2MPn5t7OE4eUCUNf8BAa7b5WUS9/Qvr6mwOQS7Mk6vdsMno5he+T8Xw==} + engines: {node: '>= 4'} + + indent-string@4.0.0: + resolution: {integrity: sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg==} + engines: {node: '>=8'} + + inflight@1.0.6: + resolution: {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. + + inherits@2.0.4: + resolution: {integrity: sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==} + + ini@2.0.0: + resolution: {integrity: sha512-7PnF4oN3CvZF23ADhA5wRaYEQpJ8qygSkbtTXWBeXWXmEVRXK+1ITciHWwHhsjv1TmW0MgacIv6hEi5pX5NQdA==} + engines: {node: '>=10'} + + internal-slot@1.0.7: + resolution: {integrity: sha512-NGnrKwXzSms2qUUih/ILZ5JBqNTSa1+ZmP6flaIp6KmSElgE9qdndzS3cqjrDovwFdmwsGsLdeFgB6suw+1e9g==} + engines: {node: '>= 0.4'} + + ipaddr.js@1.9.1: + resolution: {integrity: sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==} + engines: {node: '>= 0.10'} + + ipaddr.js@2.1.0: + resolution: {integrity: sha512-LlbxQ7xKzfBusov6UMi4MFpEg0m+mAm9xyNGEduwXMEDuf4WfzB/RZwMVYEd7IKGvh4IUkEXYxtAVu9T3OelJQ==} + engines: {node: '>= 10'} + + is-arguments@1.1.1: + resolution: {integrity: sha512-8Q7EARjzEnKpt/PCD7e1cgUS0a6X8u5tdSiMqXhojOdoV9TsMsiO+9VLC5vAmO8N7/GmXn7yjR8qnA6bVAEzfA==} + engines: {node: '>= 0.4'} + + is-array-buffer@3.0.4: + resolution: {integrity: sha512-wcjaerHw0ydZwfhiKbXJWLDY8A7yV7KhjQOpb83hGgGfId/aQa4TOvwyzn2PuswW2gPCYEL/nEAiSVpdOj1lXw==} + engines: {node: '>= 0.4'} + + is-arrayish@0.2.1: + resolution: {integrity: sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg==} + + is-bigint@1.0.4: + resolution: {integrity: sha512-zB9CruMamjym81i2JZ3UMn54PKGsQzsJeo6xvN3HJJ4CAsQNB6iRutp2To77OfCNuoxspsIhzaPoO1zyCEhFOg==} + + is-binary-path@2.1.0: + resolution: {integrity: sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==} + engines: {node: '>=8'} + + is-boolean-object@1.1.2: + resolution: {integrity: sha512-gDYaKHJmnj4aWxyj6YHyXVpdQawtVLHU5cb+eztPGczf6cjuTdwve5ZIEfgXqH4e57An1D1AKf8CZ3kYrQRqYA==} + engines: {node: '>= 0.4'} + + is-callable@1.2.7: + resolution: {integrity: sha512-1BC0BVFhS/p0qtw6enp8e+8OD0UrK0oFLztSjNzhcKA3WDuJxxAPXzPuPtKkjEY9UUoEWlX/8fgKeu2S8i9JTA==} + engines: {node: '>= 0.4'} + + is-core-module@2.14.0: + resolution: {integrity: sha512-a5dFJih5ZLYlRtDc0dZWP7RiKr6xIKzmn/oAYCDvdLThadVgyJwlaoQPmRtMSpz+rk0OGAgIu+TcM9HUF0fk1A==} + engines: {node: '>= 0.4'} + + is-data-view@1.0.1: + resolution: {integrity: sha512-AHkaJrsUVW6wq6JS8y3JnM/GJF/9cf+k20+iDzlSaJrinEo5+7vRiteOSwBhHRiAyQATN1AmY4hwzxJKPmYf+w==} + engines: {node: '>= 0.4'} + + is-date-object@1.0.5: + resolution: {integrity: sha512-9YQaSxsAiSwcvS33MBk3wTCVnWK+HhF8VZR2jRxehM16QcVOdHqPn4VPHmRK4lSr38n9JriurInLcP90xsYNfQ==} + engines: {node: '>= 0.4'} + + is-docker@2.2.1: + resolution: {integrity: sha512-F+i2BKsFrH66iaUFc0woD8sLy8getkwTwtOBjvs56Cx4CgJDeKQeqfz8wAYiSb8JOprWhHH5p77PbmYCvvUuXQ==} + engines: {node: '>=8'} + hasBin: true + + is-extglob@2.1.1: + resolution: {integrity: sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==} + engines: {node: '>=0.10.0'} + + is-fullwidth-code-point@3.0.0: + resolution: {integrity: sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==} + engines: {node: '>=8'} + + is-generator-function@1.0.10: + resolution: {integrity: sha512-jsEjy9l3yiXEQ+PsXdmBwEPcOxaXWLspKdplFUVI9vq1iZgIekeC0L167qeu86czQaxed3q/Uzuw0swL0irL8A==} + engines: {node: '>= 0.4'} + + is-glob@4.0.3: + resolution: {integrity: sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==} + engines: {node: '>=0.10.0'} + + is-map@2.0.3: + resolution: {integrity: sha512-1Qed0/Hr2m+YqxnM09CjA2d/i6YZNfF6R2oRAOj36eUdS6qIV/huPJNSEpKbupewFs+ZsJlxsjjPbc0/afW6Lw==} + engines: {node: '>= 0.4'} + + is-negative-zero@2.0.3: + resolution: {integrity: sha512-5KoIu2Ngpyek75jXodFvnafB6DJgr3u8uuK0LEZJjrU19DrMD3EVERaR8sjz8CCGgpZvxPl9SuE1GMVPFHx1mw==} + engines: {node: '>= 0.4'} + + is-number-object@1.0.7: + resolution: {integrity: sha512-k1U0IRzLMo7ZlYIfzRu23Oh6MiIFasgpb9X76eqfFZAqwH44UI4KTBvBYIZ1dSL9ZzChTB9ShHfLkR4pdW5krQ==} + engines: {node: '>= 0.4'} + + is-number@7.0.0: + resolution: {integrity: sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==} + engines: {node: '>=0.12.0'} + + is-path-cwd@2.2.0: + resolution: {integrity: sha512-w942bTcih8fdJPJmQHFzkS76NEP8Kzzvmw92cXsazb8intwLqPibPPdXf4ANdKV3rYMuuQYGIWtvz9JilB3NFQ==} + engines: {node: '>=6'} + + is-path-inside@3.0.3: + resolution: {integrity: sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ==} + engines: {node: '>=8'} + + is-regex@1.1.4: + resolution: {integrity: sha512-kvRdxDsxZjhzUX07ZnLydzS1TU/TJlTUHHY4YLL87e37oUA49DfkLqgy+VjFocowy29cKvcSiu+kIv728jTTVg==} + engines: {node: '>= 0.4'} + + is-set@2.0.3: + resolution: {integrity: sha512-iPAjerrse27/ygGLxw+EBR9agv9Y6uLeYVJMu+QNCoouJ1/1ri0mGrcWpfCqFZuzzx3WjtwxG098X+n4OuRkPg==} + engines: {node: '>= 0.4'} + + is-shared-array-buffer@1.0.3: + resolution: {integrity: sha512-nA2hv5XIhLR3uVzDDfCIknerhx8XUKnstuOERPNNIinXG7v9u+ohXF67vxm4TPTEPU6lm61ZkwP3c9PCB97rhg==} + engines: {node: '>= 0.4'} + + is-stream@2.0.1: + resolution: {integrity: sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==} + engines: {node: '>=8'} + + is-string@1.0.7: + resolution: {integrity: sha512-tE2UXzivje6ofPW7l23cjDOMa09gb7xlAqG6jG5ej6uPV32TlWP3NKPigtaGeHNu9fohccRYvIiZMfOOnOYUtg==} + engines: {node: '>= 0.4'} + + is-symbol@1.0.4: + resolution: {integrity: sha512-C/CPBqKWnvdcxqIARxyOh4v1UUEOCHpgDa0WYgpKDFMszcrPcffg5uhwSgPCLD2WWxmq6isisz87tzT01tuGhg==} + engines: {node: '>= 0.4'} + + is-typed-array@1.1.13: + resolution: {integrity: sha512-uZ25/bUAlUY5fR4OKT4rZQEBrzQWYV9ZJYGGsUmEJ6thodVJ1HX64ePQ6Z0qPWP+m+Uq6e9UugrE38jeYsDSMw==} + engines: {node: '>= 0.4'} + + is-weakref@1.0.2: + resolution: {integrity: sha512-qctsuLZmIQ0+vSSMfoVvyFe2+GSEvnmZ2ezTup1SBse9+twCCeial6EEi3Nc2KFcf6+qz2FBPnjXsk8xhKSaPQ==} + + is-what@4.1.16: + resolution: {integrity: sha512-ZhMwEosbFJkA0YhFnNDgTM4ZxDRsS6HqTo7qsZM08fehyRYIYa0yHu5R6mgo1n/8MgaPBXiPimPD77baVFYg+A==} + engines: {node: '>=12.13'} + + is-windows@1.0.2: + resolution: {integrity: sha512-eXK1UInq2bPmjyX6e3VHIzMLobc4J94i4AWn+Hpq3OU5KkrRC96OAcR3PRJ/pGu6m8TRnBHP9dkXQVsT/COVIA==} + engines: {node: '>=0.10.0'} + + is-wsl@2.2.0: + resolution: {integrity: sha512-fKzAra0rGJUUBwGBgNkHZuToZcn+TtXHpeCgmkMJMMYx1sQDYaCSyjJBSCa2nH1DGm7s3n1oBnohoVTBaN7Lww==} + engines: {node: '>=8'} + + isarray@1.0.0: + resolution: {integrity: sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==} + + isarray@2.0.5: + resolution: {integrity: sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==} + + isexe@2.0.0: + resolution: {integrity: sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==} + + iterate-iterator@1.0.2: + resolution: {integrity: sha512-t91HubM4ZDQ70M9wqp+pcNpu8OyJ9UAtXntT/Bcsvp5tZMnz9vRa+IunKXeI8AnfZMTv0jNuVEmGeLSMjVvfPw==} + + iterate-value@1.0.2: + resolution: {integrity: sha512-A6fMAio4D2ot2r/TYzr4yUWrmwNdsN5xL7+HUiyACE4DXm+q8HtPcnFTp+NnW3k4N05tZ7FVYFFb2CR13NxyHQ==} + + jackspeak@2.3.6: + resolution: {integrity: sha512-N3yCS/NegsOBokc8GAdM8UcmfsKiSS8cipheD/nivzr700H+nsMOxJjQnvwOcRYVuFkdH0wGUvW2WbXGmrZGbQ==} + engines: {node: '>=14'} + + js-tokens@4.0.0: + resolution: {integrity: sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==} + + json-parse-even-better-errors@2.3.1: + resolution: {integrity: sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==} + + json-stream@1.0.0: + resolution: {integrity: sha512-H/ZGY0nIAg3QcOwE1QN/rK/Fa7gJn7Ii5obwp6zyPO4xiPNwpIMjqy2gwjBEGqzkF/vSWEIBQCBuN19hYiL6Qg==} + + jsonfile@6.1.0: + resolution: {integrity: sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==} + + kleur@3.0.3: + resolution: {integrity: sha512-eTIzlVOSUR+JxdDFepEYcBMtZ9Qqdef+rnzWdRZuMbOywu5tO2w2N7rqjoANZ5k9vywhL6Br1VRjUIgTQx4E8w==} + engines: {node: '>=6'} + + kleur@4.1.5: + resolution: {integrity: sha512-o+NO+8WrRiQEE4/7nwRJhN1HWpVmJm511pBHUxPLtp0BUISzlBplORYSmTclCnJvQq2tKu/sgl3xVpkc7ZWuQQ==} + engines: {node: '>=6'} + + kysely@0.27.3: + resolution: {integrity: sha512-lG03Ru+XyOJFsjH3OMY6R/9U38IjDPfnOfDgO3ynhbDr+Dz8fak+X6L62vqu3iybQnj+lG84OttBuU9KY3L9kA==} + engines: {node: '>=14.0.0'} + + lazystream@1.0.1: + resolution: {integrity: sha512-b94GiNHQNy6JNTrt5w6zNyffMrNkXZb3KTkCZJb2V1xaEGCk093vkZ2jk3tpaeP33/OiXC+WvK9AxUebnf5nbw==} + engines: {node: '>= 0.6.3'} + + lilconfig@2.1.0: + resolution: {integrity: sha512-utWOt/GHzuUxnLKxB6dk81RoOeoNeHgbrXiuGk4yyF5qlRz+iIVWu56E2fqGHFrXz0QNUhLB/8nKqvRH66JKGQ==} + engines: {node: '>=10'} + + lines-and-columns@1.2.4: + resolution: {integrity: sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==} + + locate-path@5.0.0: + resolution: {integrity: sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==} + engines: {node: '>=8'} + + locate-path@6.0.0: + resolution: {integrity: sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==} + engines: {node: '>=10'} + + lodash.defaults@4.2.0: + resolution: {integrity: sha512-qjxPLHd3r5DnsdGacqOMU6pb/avJzdh9tFX2ymgoZE27BmjXrNy/y4LoaiTeAb+O3gL8AfpJGtqfX/ae2leYYQ==} + + lodash.difference@4.5.0: + resolution: {integrity: sha512-dS2j+W26TQ7taQBGN8Lbbq04ssV3emRw4NY58WErlTO29pIqS0HmoT5aJ9+TUQ1N3G+JOZSji4eugsWwGp9yPA==} + + lodash.flatten@4.4.0: + resolution: {integrity: sha512-C5N2Z3DgnnKr0LOpv/hKCgKdb7ZZwafIrsesve6lmzvZIRZRGaZ/l6Q8+2W7NaT+ZwO3fFlSCzCzrDCFdJfZ4g==} + + lodash.isplainobject@4.0.6: + resolution: {integrity: sha512-oSXzaWypCMHkPC3NvBEaPHf0KsA5mvPrOPgQWDsbg8n7orZ290M0BmC/jgRZ4vcJ6DTAhjrsSYgdsW/F+MFOBA==} + + lodash.union@4.6.0: + resolution: {integrity: sha512-c4pB2CdGrGdjMKYLA+XiRDO7Y0PRQbm/Gzg8qMj+QH+pFVAoTp5sBpO0odL3FjoPCGjK96p6qsP+yQoiLoOBcw==} + + lodash@4.17.21: + resolution: {integrity: sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==} + + lru-cache@10.2.0: + resolution: {integrity: sha512-2bIM8x+VAf6JT4bKAljS1qUWgMsqZRPGJS6FSahIMPVvctcNhyVp7AJu7quxOW9jwkryBReKZY5tY5JYv2n/7Q==} + engines: {node: 14 || >=16.14} + + lru-cache@6.0.0: + resolution: {integrity: sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==} + engines: {node: '>=10'} + + make-dir@3.1.0: + resolution: {integrity: sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw==} + engines: {node: '>=8'} + + make-dir@4.0.0: + resolution: {integrity: sha512-hXdUTZYIVOt1Ex//jAQi+wTZZpUpwBj/0QsOzqegb3rGMMeJiSEu5xLHnYfBrRV4RH2+OCSOO95Is/7x1WJ4bw==} + engines: {node: '>=10'} + + make-error@1.3.6: + resolution: {integrity: sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw==} + + media-typer@0.3.0: + resolution: {integrity: sha512-dq+qelQ9akHpcOl/gUVRTxVIOkAJ1wR3QAvb4RsVjS8oVoFjDGTc679wJYmUmknUF5HwMLOgb5O+a3KxfWapPQ==} + engines: {node: '>= 0.6'} + + merge-anything@5.1.7: + resolution: {integrity: sha512-eRtbOb1N5iyH0tkQDAoQ4Ipsp/5qSR79Dzrz8hEPxRX10RWWR/iQXdoKmBSRCThY1Fh5EhISDtpSc93fpxUniQ==} + engines: {node: '>=12.13'} + + merge-descriptors@1.0.1: + resolution: {integrity: sha512-cCi6g3/Zr1iqQi6ySbseM1Xvooa98N0w31jzUYrXPX2xqObmFGHJ0tQ5u74H3mVh7wLouTseZyYIq39g8cNp1w==} + + merge-stream@2.0.0: + resolution: {integrity: sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==} + + merge2@1.4.1: + resolution: {integrity: sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==} + engines: {node: '>= 8'} + + methods@1.1.2: + resolution: {integrity: sha512-iclAHeNqNm68zFtnZ0e+1L2yUIdvzNoauKU4WBA3VvH/vPFieF7qfRlwUZU+DA9P9bPXIS90ulxoUoCH23sV2w==} + engines: {node: '>= 0.6'} + + micromatch@4.0.7: + resolution: {integrity: sha512-LPP/3KorzCwBxfeUuZmaR6bG2kdeHSbe0P2tY3FLRU4vYrjYz5hI4QZwV0njUx3jeuKe67YukQ1LSPZBKDqO/Q==} + engines: {node: '>=8.6'} + + mime-db@1.52.0: + resolution: {integrity: sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==} + engines: {node: '>= 0.6'} + + mime-types@2.1.35: + resolution: {integrity: sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==} + engines: {node: '>= 0.6'} + + mime@1.6.0: + resolution: {integrity: sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==} + engines: {node: '>=4'} + hasBin: true + + mime@4.0.1: + resolution: {integrity: sha512-5lZ5tyrIfliMXzFtkYyekWbtRXObT9OWa8IwQ5uxTBDHucNNwniRqo0yInflj+iYi5CBa6qxadGzGarDfuEOxA==} + engines: {node: '>=16'} + hasBin: true + + mimic-fn@2.1.0: + resolution: {integrity: sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==} + engines: {node: '>=6'} + + min-indent@1.0.1: + resolution: {integrity: sha512-I9jwMn07Sy/IwOj3zVkVik2JTvgpaykDZEigL6Rx6N9LbMywwUSMtxET+7lVoDLLd3O3IXwJwvuuns8UB/HeAg==} + engines: {node: '>=4'} + + minimalistic-assert@1.0.1: + resolution: {integrity: sha512-UtJcAD4yEaGtjPezWuO9wC4nwUnVH/8/Im3yEHQP4b67cXlD/Qr9hdITCU1xDbSEXg2XKNaP8jsReV7vQd00/A==} + + minimatch@3.1.2: + resolution: {integrity: sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==} + + minimatch@5.1.6: + resolution: {integrity: sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g==} + engines: {node: '>=10'} + + minimatch@9.0.4: + resolution: {integrity: sha512-KqWh+VchfxcMNRAJjj2tnsSJdNbHsVgnkBhTNrW7AjVo6OvLtxw8zfT9oLw1JSohlFzJ8jCoTgaoXvJ+kHt6fw==} + engines: {node: '>=16 || 14 >=14.17'} + + minimist@1.2.8: + resolution: {integrity: sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==} + + minio@7.1.3: + resolution: {integrity: sha512-xPrLjWkTT5E7H7VnzOjF//xBp9I40jYB4aWhb2xTFopXXfw+Wo82DDWngdUju7Doy3Wk7R8C4LAgwhLHHnf0wA==} + engines: {node: ^16 || ^18 || >=20} + + minipass@7.0.4: + resolution: {integrity: sha512-jYofLM5Dam9279rdkWzqHozUo4ybjdZmCsDHePy5V/PbBcVMiSZR97gmAy45aqi8CK1lG2ECd356FU86avfwUQ==} + engines: {node: '>=16 || 14 >=14.17'} + + mnemonist@0.39.8: + resolution: {integrity: sha512-vyWo2K3fjrUw8YeeZ1zF0fy6Mu59RHokURlld8ymdUPjMlD9EC9ov1/YPqTgqRvUN9nTr3Gqfz29LYAmu0PHPQ==} + + ms@2.0.0: + resolution: {integrity: sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==} + + ms@2.1.2: + resolution: {integrity: sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==} + + ms@2.1.3: + resolution: {integrity: sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==} + + negotiator@0.6.3: + resolution: {integrity: sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg==} + engines: {node: '>= 0.6'} + + neo-async@2.6.2: + resolution: {integrity: sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==} + + new-github-issue-url@0.2.1: + resolution: {integrity: sha512-md4cGoxuT4T4d/HDOXbrUHkTKrp/vp+m3aOA7XXVYwNsUNMK49g3SQicTSeV5GIz/5QVGAeYRAOlyp9OvlgsYA==} + engines: {node: '>=10'} + + node-fetch@2.6.12: + resolution: {integrity: sha512-C/fGU2E8ToujUivIO0H+tpQ6HWo4eEmchoPIoXtxCrVghxdKq+QOHqEZW7tuP3KlV3bC8FRMO5nMCC7Zm1VP6g==} + engines: {node: 4.x || >=6.0.0} + peerDependencies: + encoding: ^0.1.0 + peerDependenciesMeta: + encoding: + optional: true + + node-fetch@2.7.0: + resolution: {integrity: sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A==} + engines: {node: 4.x || >=6.0.0} + peerDependencies: + encoding: ^0.1.0 + peerDependenciesMeta: + encoding: + optional: true + + nodemon@3.1.3: + resolution: {integrity: sha512-m4Vqs+APdKzDFpuaL9F9EVOF85+h070FnkHVEoU4+rmT6Vw0bmNl7s61VEkY/cJkL7RCv1p4urnUDUMrS5rk2w==} + engines: {node: '>=10'} + hasBin: true + + nopt@1.0.10: + resolution: {integrity: sha512-NWmpvLSqUrgrAC9HCuxEvb+PSloHpqVu+FqcO4eeF2h5qYRhA7ev6KvelyQAKtegUbC6RypJnlEOhd8vloNKYg==} + hasBin: true + + normalize-package-data@2.5.0: + resolution: {integrity: sha512-/5CMN3T0R4XTj4DcGaexo+roZSdSFW/0AOOTROrjxzCG1wrWXEsGbRKevjlIL+ZDE4sZlJr5ED4YW0yqmkK+eA==} + + normalize-path@3.0.0: + resolution: {integrity: sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==} + engines: {node: '>=0.10.0'} + + npm-bundled@2.0.1: + resolution: {integrity: sha512-gZLxXdjEzE/+mOstGDqR6b0EkhJ+kM6fxM6vUuckuctuVPh80Q6pw/rSZj9s4Gex9GxWtIicO1pc8DB9KZWudw==} + engines: {node: ^12.13.0 || ^14.15.0 || >=16.0.0} + + npm-normalize-package-bin@2.0.0: + resolution: {integrity: sha512-awzfKUO7v0FscrSpRoogyNm0sajikhBWpU0QMrW09AMi9n1PoKU6WaIqUzuJSQnpciZZmJ/jMZ2Egfmb/9LiWQ==} + engines: {node: ^12.13.0 || ^14.15.0 || >=16.0.0} + + npm-packlist@5.1.3: + resolution: {integrity: sha512-263/0NGrn32YFYi4J533qzrQ/krmmrWwhKkzwTuM4f/07ug51odoaNjUexxO4vxlzURHcmYMH1QjvHjsNDKLVg==} + engines: {node: ^12.13.0 || ^14.15.0 || >=16.0.0} + hasBin: true + + npm-run-path@4.0.1: + resolution: {integrity: sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw==} + engines: {node: '>=8'} + + object-assign@4.1.1: + resolution: {integrity: sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==} + engines: {node: '>=0.10.0'} + + object-inspect@1.13.1: + resolution: {integrity: sha512-5qoj1RUiKOMsCCNLV1CBiPYE10sziTsnmNxkAI/rZhiD63CF7IqdFGC/XzjWjpSgLf0LxXX3bDFIh0E18f6UhQ==} + + object-keys@1.1.1: + resolution: {integrity: sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==} + engines: {node: '>= 0.4'} + + object.assign@4.1.5: + resolution: {integrity: sha512-byy+U7gp+FVwmyzKPYhW2h5l3crpmGsxl7X2s8y43IgxvG4g3QZ6CffDtsNQy1WsmZpQbO+ybo0AlW7TY6DcBQ==} + engines: {node: '>= 0.4'} + + obliterator@2.0.4: + resolution: {integrity: sha512-lgHwxlxV1qIg1Eap7LgIeoBWIMFibOjbrYPIPJZcI1mmGAI2m3lNYpK12Y+GBdPQ0U1hRwSord7GIaawz962qQ==} + + on-finished@2.4.1: + resolution: {integrity: sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg==} + engines: {node: '>= 0.8'} + + once@1.4.0: + resolution: {integrity: sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==} + + onetime@5.1.2: + resolution: {integrity: sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==} + engines: {node: '>=6'} + + open@7.4.2: + resolution: {integrity: sha512-MVHddDVweXZF3awtlAS+6pgKLlm/JgxZ90+/NBurBoQctVOOB/zDdVjcyPzQ+0laDGbsWgrRkflI65sQeOgT9Q==} + engines: {node: '>=8'} + + p-filter@2.1.0: + resolution: {integrity: sha512-ZBxxZ5sL2HghephhpGAQdoskxplTwr7ICaehZwLIlfL6acuVgZPm8yBNuRAFBGEqtD/hmUeq9eqLg2ys9Xr/yw==} + engines: {node: '>=8'} + + p-limit@2.3.0: + resolution: {integrity: sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==} + engines: {node: '>=6'} + + p-limit@3.1.0: + resolution: {integrity: sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==} + engines: {node: '>=10'} + + p-locate@4.1.0: + resolution: {integrity: sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==} + engines: {node: '>=8'} + + p-locate@5.0.0: + resolution: {integrity: sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==} + engines: {node: '>=10'} + + p-map@2.1.0: + resolution: {integrity: sha512-y3b8Kpd8OAN444hxfBbFfj1FY/RjtTd8tzYwhUqNYXx0fXx2iX4maP4Qr6qhIKbQXI02wTLAda4fYUbDagTUFw==} + engines: {node: '>=6'} + + p-map@4.0.0: + resolution: {integrity: sha512-/bjOqmgETBYB5BoEeGVea8dmvHb2m9GLy1E9W43yeyfP6QQCZGFNa+XRceJEuDB6zqr+gKpIAmlLebMpykw/MQ==} + engines: {node: '>=10'} + + p-retry@4.6.2: + resolution: {integrity: sha512-312Id396EbJdvRONlngUx0NydfrIQ5lsYu0znKVUzVvArzEIt08V1qhtyESbGVd1FGX7UKtiFp5uwKZdM8wIuQ==} + engines: {node: '>=8'} + + p-try@2.2.0: + resolution: {integrity: sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==} + engines: {node: '>=6'} + + parse-json@5.2.0: + resolution: {integrity: sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==} + engines: {node: '>=8'} + + parseurl@1.3.3: + resolution: {integrity: sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==} + engines: {node: '>= 0.8'} + + path-exists@4.0.0: + resolution: {integrity: sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==} + engines: {node: '>=8'} + + path-is-absolute@1.0.1: + resolution: {integrity: sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==} + engines: {node: '>=0.10.0'} + + path-key@3.1.1: + resolution: {integrity: sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==} + engines: {node: '>=8'} + + path-parse@1.0.7: + resolution: {integrity: sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==} + + path-scurry@1.10.2: + resolution: {integrity: sha512-7xTavNy5RQXnsjANvVvMkEjvloOinkAjv/Z6Ildz9v2RinZ4SBKTWFOVRbaF8p0vpHnyjV/UwNDdKuUv6M5qcA==} + engines: {node: '>=16 || 14 >=14.17'} + + path-to-regexp@0.1.7: + resolution: {integrity: sha512-5DFkuoqlv1uYQKxy8omFBeJPQcdoE07Kv2sferDCrAq1ohOU+MSDswDIbnx3YAM60qIOnYa53wBhXW0EbMonrQ==} + + path-type@4.0.0: + resolution: {integrity: sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==} + engines: {node: '>=8'} + + picocolors@1.0.1: + resolution: {integrity: sha512-anP1Z8qwhkbmu7MFP5iTt+wQKXgwzf7zTyGlcdzabySa9vd0Xt392U0rVmz9poOaBj0uHJKyyo9/upk0HrEQew==} + + picomatch@2.3.1: + resolution: {integrity: sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==} + engines: {node: '>=8.6'} + + pkg-dir@4.2.0: + resolution: {integrity: sha512-HRDzbaKjC+AOWVXxAU/x54COGeIv9eb+6CkDSQoNTt4XyWoIJvuPsXizxu/Fr23EiekbtZwmh1IcIG/l/a10GQ==} + engines: {node: '>=8'} + + possible-typed-array-names@1.0.0: + resolution: {integrity: sha512-d7Uw+eZoloe0EHDIYoe+bQ5WXnGMOpmiZFTuMWCwpjzzkL2nTjcKiAk4hh8TjnGye2TwWOk3UXucZ+3rbmBa8Q==} + engines: {node: '>= 0.4'} + + prettier@3.2.5: + resolution: {integrity: sha512-3/GWa9aOC0YeD7LUfvOG2NiDyhOWRvt1k+rcKhOuYnMY24iiCphgneUfJDyFXd6rZCAnuLBv6UeAULtrhT/F4A==} + engines: {node: '>=14'} + hasBin: true + + prisma-extension-kysely@2.1.0: + resolution: {integrity: sha512-s1hujYjrNzfQc9Z79s93464mkTkkt9ZPqPELDRFe9jEmiIlM/JRXZtqIyyN3FM0GDkN/BDPVtpPtdC52XnjAcQ==} + peerDependencies: + '@prisma/client': latest + + prisma-kysely@1.8.0: + resolution: {integrity: sha512-VpNpolZ8RXRgfU+j4R+fPZmX8EE95w3vJ2tt7+FwuiQc0leNTfLK5QLf3KbbPDes2rfjh3g20AjDxefQIo5GIA==} + hasBin: true + + prisma@5.16.0: + resolution: {integrity: sha512-T1ZWJT/vgzp3rtRmd1iCSnPPsgOItXnnny+/cfpHraowiBEvUMD2pEI6yEOL6CP2EelTmq4wKDbXbYucy4Fd+A==} + engines: {node: '>=16.13'} + hasBin: true + + process-nextick-args@2.0.1: + resolution: {integrity: sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==} + + progress@2.0.3: + resolution: {integrity: sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA==} + engines: {node: '>=0.4.0'} + + promise.any@2.0.6: + resolution: {integrity: sha512-Ew/MrPtTjiHnnki0AA2hS2o65JaZ5n+5pp08JSyWWUdeOGF4F41P+Dn+rdqnaOV/FTxhR6eBDX412luwn3th9g==} + engines: {node: '>= 0.4'} + + prompts@2.4.2: + resolution: {integrity: sha512-NxNv/kLguCA7p3jE8oL2aEBsrJWgAakBpgmgK6lpPWV+WuOmY6r2/zbAVnP+T8bQlA0nzHXSJSJW0Hq7ylaD2Q==} + engines: {node: '>= 6'} + + proxy-addr@2.0.7: + resolution: {integrity: sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg==} + engines: {node: '>= 0.10'} + + pstree.remy@1.1.8: + resolution: {integrity: sha512-77DZwxQmxKnu3aR542U+X8FypNzbfJ+C5XQDk3uWjWxn6151aIMGthWYRXTqT1E5oJvg+ljaa2OJi+VfvCOQ8w==} + + qs@6.11.0: + resolution: {integrity: sha512-MvjoMCJwEarSbUYk5O+nmoSzSutSsTwF85zcHPQ9OrlFoZOYIjaqBAJIqIXjptyD5vThxGq52Xu/MaJzRkIk4Q==} + engines: {node: '>=0.6'} + + query-string@7.1.3: + resolution: {integrity: sha512-hh2WYhq4fi8+b+/2Kg9CEge4fDPvHS534aOOvOZeQ3+Vf2mCFsaFBYj0i+iXcAq6I9Vzp5fjMFBlONvayDC1qg==} + engines: {node: '>=6'} + + queue-microtask@1.2.3: + resolution: {integrity: sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==} + + range-parser@1.2.1: + resolution: {integrity: sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==} + engines: {node: '>= 0.6'} + + raw-body@2.5.2: + resolution: {integrity: sha512-8zGqypfENjCIqGhgXToC8aB2r7YrBX+AQAfIPs/Mlk+BtPTztOvTS01NRW/3Eh60J+a48lt8qsCzirQ6loCVfA==} + engines: {node: '>= 0.8'} + + read-pkg-up@7.0.1: + resolution: {integrity: sha512-zK0TB7Xd6JpCLmlLmufqykGE+/TlOePD6qKClNW7hHDKFh/J7/7gCWGR7joEQEW1bKq3a3yUZSObOoWLFQ4ohg==} + engines: {node: '>=8'} + + read-pkg@5.2.0: + resolution: {integrity: sha512-Ug69mNOpfvKDAc2Q8DRpMjjzdtrnv9HcSMX+4VsZxD1aZ6ZzrIE7rlzXBtWTyhULSMKg076AW6WR5iZpD0JiOg==} + engines: {node: '>=8'} + + readable-stream@2.3.8: + resolution: {integrity: sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==} + + readable-stream@3.6.2: + resolution: {integrity: sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==} + engines: {node: '>= 6'} + + readdir-glob@1.1.3: + resolution: {integrity: sha512-v05I2k7xN8zXvPD9N+z/uhXPaj0sUFCe2rcWZIpBsqxfP7xXFQ0tipAd/wjj1YxWyWtUS5IDJpOG82JKt2EAVA==} + + readdirp@3.6.0: + resolution: {integrity: sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==} + engines: {node: '>=8.10.0'} + + reflect-metadata@0.2.2: + resolution: {integrity: sha512-urBwgfrvVP/eAyXx4hluJivBKzuEbSQs9rKWCrCkbSxNv8mxPcUZKeuoF3Uy4mJl3Lwprp6yy5/39VWigZ4K6Q==} + + regexp-to-ast@0.5.0: + resolution: {integrity: sha512-tlbJqcMHnPKI9zSrystikWKwHkBqu2a/Sgw01h3zFjvYrMxEDYHzzoMZnUrbIfpTFEsoRnnviOXNCzFiSc54Qw==} + + regexp.prototype.flags@1.5.2: + resolution: {integrity: sha512-NcDiDkTLuPR+++OCKB0nWafEmhg/Da8aUPLPMQbK+bxKKCm1/S5he+AqYa4PlMCVBalb4/yxIRub6qkEx5yJbw==} + engines: {node: '>= 0.4'} + + replace-string@3.1.0: + resolution: {integrity: sha512-yPpxc4ZR2makceA9hy/jHNqc7QVkd4Je/N0WRHm6bs3PtivPuPynxE5ejU/mp5EhnCv8+uZL7vhz8rkluSlx+Q==} + engines: {node: '>=8'} + + require-directory@2.1.1: + resolution: {integrity: sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==} + engines: {node: '>=0.10.0'} + + resolve@1.22.4: + resolution: {integrity: sha512-PXNdCiPqDqeUou+w1C2eTQbNfxKSuMxqTCuvlmmMsk1NWHL5fRrhY6Pl0qEYYc6+QqGClco1Qj8XnjPego4wfg==} + hasBin: true + + retry@0.13.1: + resolution: {integrity: sha512-XQBQ3I8W1Cge0Seh+6gjj03LbmRFWuoszgK9ooCpwYIrhhoO80pfq4cUkU5DkknwfOfFteRwlZ56PYOGYyFWdg==} + engines: {node: '>= 4'} + + reusify@1.0.4: + resolution: {integrity: sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==} + engines: {iojs: '>=1.0.0', node: '>=0.10.0'} + + rimraf@3.0.2: + resolution: {integrity: sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==} + deprecated: Rimraf versions prior to v4 are no longer supported + hasBin: true + + run-parallel@1.2.0: + resolution: {integrity: sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==} + + safe-array-concat@1.1.2: + resolution: {integrity: sha512-vj6RsCsWBCf19jIeHEfkRMw8DPiBb+DMXklQ/1SGDHOMlHdPUkZXFQ2YdplS23zESTijAcurb1aSgJA3AgMu1Q==} + engines: {node: '>=0.4'} + + safe-buffer@5.1.2: + resolution: {integrity: sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==} + + safe-buffer@5.2.1: + resolution: {integrity: sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==} + + safe-regex-test@1.0.3: + resolution: {integrity: sha512-CdASjNJPvRa7roO6Ra/gLYBTzYzzPyyBXxIMdGW3USQLyjWEls2RgW5UBTXaQVp+OrpeCK3bLem8smtmheoRuw==} + engines: {node: '>= 0.4'} + + safer-buffer@2.1.2: + resolution: {integrity: sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==} + + sax@1.3.0: + resolution: {integrity: sha512-0s+oAmw9zLl1V1cS9BtZN7JAd0cW5e0QH4W3LWEK6a4LaLEA2OTpGYWDY+6XasBLtz6wkm3u1xRw95mRuJ59WA==} + + secure-json-parse@2.7.0: + resolution: {integrity: sha512-6aU+Rwsezw7VR8/nyvKTx8QpWH9FrcYiXXlqC4z5d5XQBDRqtbfsRjnwGyqbi3gddNtWHuEk9OANUotL26qKUw==} + + semver@5.7.2: + resolution: {integrity: sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==} + hasBin: true + + semver@6.3.1: + resolution: {integrity: sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==} + hasBin: true + + semver@7.6.0: + resolution: {integrity: sha512-EnwXhrlwXMk9gKu5/flx5sv/an57AkRplG3hTK68W7FRDN+k+OWBj65M7719OkA82XLBxrcX0KSHj+X5COhOVg==} + engines: {node: '>=10'} + hasBin: true + + send@0.18.0: + resolution: {integrity: sha512-qqWzuOjSFOuqPjFe4NOsMLafToQQwBSOEpS+FwEt3A2V3vKubTquT3vmLTQpFgMXp8AlFWFuP1qKaJZOtPpVXg==} + engines: {node: '>= 0.8.0'} + + serve-static@1.15.0: + resolution: {integrity: sha512-XGuRDNjXUijsUL0vl6nSD7cwURuzEgglbOaFuZM9g3kwDXOWVTck0jLzjPzGD+TazWbboZYu52/9/XPdUgne9g==} + engines: {node: '>= 0.8.0'} + + set-function-length@1.2.2: + resolution: {integrity: sha512-pgRc4hJ4/sNjWCSS9AmnS40x3bNMDTknHgL5UaMBTMyJnU90EgWh1Rz+MC9eFu4BuN/UwZjKQuY/1v3rM7HMfg==} + engines: {node: '>= 0.4'} + + set-function-name@2.0.2: + resolution: {integrity: sha512-7PGFlmtwsEADb0WYyvCMa1t+yke6daIG4Wirafur5kcf+MhUnPms1UeR0CKQdTZD81yESwMHbtn+TR+dMviakQ==} + engines: {node: '>= 0.4'} + + setprototypeof@1.2.0: + resolution: {integrity: sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==} + + shebang-command@2.0.0: + resolution: {integrity: sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==} + engines: {node: '>=8'} + + shebang-regex@3.0.0: + resolution: {integrity: sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==} + engines: {node: '>=8'} + + side-channel@1.0.6: + resolution: {integrity: sha512-fDW/EZ6Q9RiO8eFG8Hj+7u/oW+XrPTIChwCOM2+th2A6OblDtYYIpve9m+KvI9Z4C9qSEXlaGR6bTEYHReuglA==} + engines: {node: '>= 0.4'} + + signal-exit@3.0.7: + resolution: {integrity: sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==} + + signal-exit@4.1.0: + resolution: {integrity: sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==} + engines: {node: '>=14'} + + simple-update-notifier@2.0.0: + resolution: {integrity: sha512-a2B9Y0KlNXl9u/vsW6sTIu9vGEpfKu2wRV6l1H3XEas/0gUIzGzBoP/IouTcUQbm9JWZLH3COxyn03TYlFax6w==} + engines: {node: '>=10'} + + sisteransi@1.0.5: + resolution: {integrity: sha512-bLGGlR1QxBcynn2d5YmDX4MGjlZvy2MRBDRNHLJ8VI6l6+9FUiyTFNJ0IveOSP0bcXgVDPRcfGqA0pjaqUpfVg==} + + slash@3.0.0: + resolution: {integrity: sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==} + engines: {node: '>=8'} + + slice-ansi@3.0.0: + resolution: {integrity: sha512-pSyv7bSTC7ig9Dcgbw9AuRNUb5k5V6oDudjZoMBSr13qpLBG7tB+zgCkARjq7xIUgdz5P1Qe8u+rSGdouOOIyQ==} + engines: {node: '>=8'} + + source-map@0.6.1: + resolution: {integrity: sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==} + engines: {node: '>=0.10.0'} + + spdx-correct@3.2.0: + resolution: {integrity: sha512-kN9dJbvnySHULIluDHy32WHRUu3Og7B9sbY7tsFLctQkIqnMh3hErYgdMjTYuqmcXX+lK5T1lnUt3G7zNswmZA==} + + spdx-exceptions@2.5.0: + resolution: {integrity: sha512-PiU42r+xO4UbUS1buo3LPJkjlO7430Xn5SVAhdpzzsPHsjbYVflnnFdATgabnLude+Cqu25p6N+g2lw/PFsa4w==} + + spdx-expression-parse@3.0.1: + resolution: {integrity: sha512-cbqHunsQWnJNE6KhVSMsMeH5H/L9EpymbzqTQ3uLwNCLZ1Q481oWaofqH7nO6V07xlXwY6PhQdQ2IedWx/ZK4Q==} + + spdx-license-ids@3.0.18: + resolution: {integrity: sha512-xxRs31BqRYHwiMzudOrpSiHtZ8i/GeionCBDSilhYRj+9gIcI8wCZTlXZKu9vZIVqViP3dcp9qE5G6AlIaD+TQ==} + + split-on-first@1.1.0: + resolution: {integrity: sha512-43ZssAJaMusuKWL8sKUBQXHWOpq8d6CfN/u1p4gUzfJkM05C8rxTmYrkIPTXapZpORA6LkkzcUulJ8FqA7Uudw==} + engines: {node: '>=6'} + + statuses@2.0.1: + resolution: {integrity: sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==} + engines: {node: '>= 0.8'} + + stop-iteration-iterator@1.0.0: + resolution: {integrity: sha512-iCGQj+0l0HOdZ2AEeBADlsRC+vsnDsZsbdSiH1yNSjcfKM7fdpCMfqAL/dwF5BLiw/XhRft/Wax6zQbhq2BcjQ==} + engines: {node: '>= 0.4'} + + strict-uri-encode@2.0.0: + resolution: {integrity: sha512-QwiXZgpRcKkhTj2Scnn++4PKtWsH0kpzZ62L2R6c/LUVYv7hVnZqcg2+sMuT6R7Jusu1vviK/MFsu6kNJfWlEQ==} + engines: {node: '>=4'} + + string-width@4.2.3: + resolution: {integrity: sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==} + engines: {node: '>=8'} + + string-width@5.1.2: + resolution: {integrity: sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==} + engines: {node: '>=12'} + + string.prototype.trim@1.2.9: + resolution: {integrity: sha512-klHuCNxiMZ8MlsOihJhJEBJAiMVqU3Z2nEXWfWnIqjN0gEFS9J9+IxKozWWtQGcgoa1WUZzLjKPTr4ZHNFTFxw==} + engines: {node: '>= 0.4'} + + string.prototype.trimend@1.0.8: + resolution: {integrity: sha512-p73uL5VCHCO2BZZ6krwwQE3kCzM7NKmis8S//xEC6fQonchbum4eP6kR4DLEjQFO3Wnj3Fuo8NM0kOSjVdHjZQ==} + + string.prototype.trimstart@1.0.8: + resolution: {integrity: sha512-UXSH262CSZY1tfu3G3Secr6uGLCFVPMhIqHjlgCUtCCcgihYc/xKs9djMTMUOb2j1mVSeU8EU6NWc/iQKU6Gfg==} + engines: {node: '>= 0.4'} + + string_decoder@1.1.1: + resolution: {integrity: sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==} + + string_decoder@1.3.0: + resolution: {integrity: sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==} + + strip-ansi@6.0.1: + resolution: {integrity: sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==} + engines: {node: '>=8'} + + strip-ansi@7.1.0: + resolution: {integrity: sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==} + engines: {node: '>=12'} + + strip-final-newline@2.0.0: + resolution: {integrity: sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA==} + engines: {node: '>=6'} + + strip-indent@3.0.0: + resolution: {integrity: sha512-laJTa3Jb+VQpaC6DseHhF7dXVqHTfJPCRDaEbid/drOhgitgYku/letMUqOXFoWV0zIIUbjpdH2t+tYj4bQMRQ==} + engines: {node: '>=8'} + + strnum@1.0.5: + resolution: {integrity: sha512-J8bbNyKKXl5qYcR36TIO8W3mVGVHrmmxsd5PAItGkmyzwJvybiw2IVq5nqd0i4LSNSkB/sx9VHllbfFdr9k1JA==} + + supports-color@5.5.0: + resolution: {integrity: sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==} + engines: {node: '>=4'} + + supports-color@7.2.0: + resolution: {integrity: sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==} + engines: {node: '>=8'} + + supports-hyperlinks@2.3.0: + resolution: {integrity: sha512-RpsAZlpWcDwOPQA22aCH4J0t7L8JmAvsCxfOSEwm7cQs3LshN36QaTkwd70DnBOXDWGssw2eUoc8CaRWT0XunA==} + engines: {node: '>=8'} + + supports-preserve-symlinks-flag@1.0.0: + resolution: {integrity: sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==} + engines: {node: '>= 0.4'} + + swagger-ui-dist@5.13.0: + resolution: {integrity: sha512-uaWhh6j18IIs5tOX0arvIBnVINAzpTXaQXkr7qAk8zoupegJVg0UU/5+S/FgsgVCnzVsJ9d7QLjIxkswEeTg0Q==} + + swagger-ui-express@5.0.0: + resolution: {integrity: sha512-tsU9tODVvhyfkNSvf03E6FAk+z+5cU3lXAzMy6Pv4av2Gt2xA0++fogwC4qo19XuFf6hdxevPuVCSKFuMHJhFA==} + engines: {node: '>= v0.10.32'} + peerDependencies: + express: '>=4.0.0 || >=5.0.0-beta' + + tar-stream@2.2.0: + resolution: {integrity: sha512-ujeqbceABgwMZxEJnk2HDY2DlnUZ+9oEcb1KzTVfYHio0UE6dG71n60d8D2I4qNvleWrrXpmjpt7vZeF1LnMZQ==} + engines: {node: '>=6'} + + temp-dir@2.0.0: + resolution: {integrity: sha512-aoBAniQmmwtcKp/7BzsH8Cxzv8OL736p7v1ihGb5e9DJ9kTwGWHrQrVB5+lfVDzfGrdRzXch+ig7LHaY1JTOrg==} + engines: {node: '>=8'} + + tempy@1.0.1: + resolution: {integrity: sha512-biM9brNqxSc04Ee71hzFbryD11nX7VPhQQY32AdDmjFvodsRFz/3ufeoTZ6uYkRFfGo188tENcASNs3vTdsM0w==} + engines: {node: '>=10'} + + terminal-link@2.1.1: + resolution: {integrity: sha512-un0FmiRUQNr5PJqy9kP7c40F5BOfpGlYTrxonDChEZB7pzZxRNp/bt+ymiy9/npwXya9KH99nJ/GXFIiUkYGFQ==} + engines: {node: '>=8'} + + through2@4.0.2: + resolution: {integrity: sha512-iOqSav00cVxEEICeD7TjLB1sueEL+81Wpzp2bY17uZjZN0pWZPuo4suZ/61VujxmqSGFfgOcNuTZ85QJwNZQpw==} + + tmp@0.2.1: + resolution: {integrity: sha512-76SUhtfqR2Ijn+xllcI5P1oyannHNHByD80W1q447gU3mp9G9PSpGdWmjUOHRDPiHYacIk66W7ubDTuPF3BEtQ==} + engines: {node: '>=8.17.0'} + + to-regex-range@5.0.1: + resolution: {integrity: sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==} + engines: {node: '>=8.0'} + + toidentifier@1.0.1: + resolution: {integrity: sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==} + engines: {node: '>=0.6'} + + touch@3.1.0: + resolution: {integrity: sha512-WBx8Uy5TLtOSRtIq+M03/sKDrXCLHxwDcquSP2c43Le03/9serjQBIztjRz6FkJez9D/hleyAXTBGLwwZUw9lA==} + hasBin: true + + tr46@0.0.3: + resolution: {integrity: sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==} + + ts-deepmerge@7.0.0: + resolution: {integrity: sha512-WZ/iAJrKDhdINv1WG6KZIGHrZDar6VfhftG1QJFpVbOYZMYJLJOvZOo1amictRXVdBXZIgBHKswMTXzElngprA==} + engines: {node: '>=14.13.1'} + + ts-node@10.9.2: + resolution: {integrity: sha512-f0FFpIdcHgn8zcPSbf1dRevwt047YMnaiJM3u2w2RewrB+fob/zePZcrOyQoLMMO7aBIddLcQIEK5dYjkLnGrQ==} + hasBin: true + peerDependencies: + '@swc/core': '>=1.2.50' + '@swc/wasm': '>=1.2.50' + '@types/node': '*' + typescript: '>=2.7' + peerDependenciesMeta: + '@swc/core': + optional: true + '@swc/wasm': + optional: true + + ts-pattern@4.3.0: + resolution: {integrity: sha512-pefrkcd4lmIVR0LA49Imjf9DYLK8vtWhqBPA3Ya1ir8xCW0O2yjL9dsCVvI7pCodLC5q7smNpEtDR2yVulQxOg==} + + tslib@2.6.2: + resolution: {integrity: sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==} + + tsoa@6.2.0: + resolution: {integrity: sha512-EX/RyoU+4hD1rLM5NjYG+I7lEhqx1yuLgcHs/gyWQpkX/RL9cVR9hFA9LKQrK6PE+WTg1SEahn1MK3l/+6pVKw==} + engines: {node: '>=18.0.0', yarn: '>=1.9.4'} + hasBin: true + + type-fest@0.16.0: + resolution: {integrity: sha512-eaBzG6MxNzEn9kiwvtre90cXaNLkmadMWa1zQMs3XORCXNbsH/OewwbxC5ia9dCxIxnTAsSxXJaa/p5y8DlvJg==} + engines: {node: '>=10'} + + type-fest@0.21.3: + resolution: {integrity: sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w==} + engines: {node: '>=10'} + + type-fest@0.6.0: + resolution: {integrity: sha512-q+MB8nYR1KDLrgr4G5yemftpMC7/QLqVndBmEEdqzmNj5dcFOO4Oo8qlwZE3ULT3+Zim1F8Kq4cBnikNhlCMlg==} + engines: {node: '>=8'} + + type-fest@0.8.1: + resolution: {integrity: sha512-4dbzIzqvjtgiM5rw1k5rEHtBANKmdudhGyBEajN01fEyhaAIhsoKNy6y7+IN93IfpFtwY9iqi7kD+xwKhQsNJA==} + engines: {node: '>=8'} + + type-is@1.6.18: + resolution: {integrity: sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==} + engines: {node: '>= 0.6'} + + typed-array-buffer@1.0.2: + resolution: {integrity: sha512-gEymJYKZtKXzzBzM4jqa9w6Q1Jjm7x2d+sh19AdsD4wqnMPDYyvwpsIc2Q/835kHuo3BEQ7CjelGhfTsoBb2MQ==} + engines: {node: '>= 0.4'} + + typed-array-byte-length@1.0.1: + resolution: {integrity: sha512-3iMJ9q0ao7WE9tWcaYKIptkNBuOIcZCCT0d4MRvuuH88fEoEH62IuQe0OtraD3ebQEoTRk8XCBoknUNc1Y67pw==} + engines: {node: '>= 0.4'} + + typed-array-byte-offset@1.0.2: + resolution: {integrity: sha512-Ous0vodHa56FviZucS2E63zkgtgrACj7omjwd/8lTEMEPFFyjfixMZ1ZXenpgCFBBt4EC1J2XsyVS2gkG0eTFA==} + engines: {node: '>= 0.4'} + + typed-array-length@1.0.6: + resolution: {integrity: sha512-/OxDN6OtAk5KBpGb28T+HZc2M+ADtvRxXrKKbUwtsLgdoxgX13hyy7ek6bFRl5+aBs2yZzB0c4CnQfAtVypW/g==} + engines: {node: '>= 0.4'} + + typescript@5.4.3: + resolution: {integrity: sha512-KrPd3PKaCLr78MalgiwJnA25Nm8HAmdwN3mYUYZgG/wizIo9EainNVQI9/yDavtVFRN2h3k8uf3GLHuhDMgEHg==} + engines: {node: '>=14.17'} + hasBin: true + + uglify-js@3.17.4: + resolution: {integrity: sha512-T9q82TJI9e/C1TAxYvfb16xO120tMVFZrGA3f9/P4424DNu6ypK103y0GPFVa17yotwSyZW5iYXgjYHkGrJW/g==} + engines: {node: '>=0.8.0'} + hasBin: true + + unbox-primitive@1.0.2: + resolution: {integrity: sha512-61pPlCD9h51VoreyJ0BReideM3MDKMKnh6+V9L08331ipq6Q8OFXZYiqP6n/tbHx4s5I9uRhcye6BrbkizkBDw==} + + undefsafe@2.0.5: + resolution: {integrity: sha512-WxONCrssBM8TSPRqN5EmsjVrsv4A8X12J4ArBiiayv3DyyG3ZlIg6yysuuSYdZsVz3TKcTg2fd//Ujd4CHV1iA==} + + undici-types@5.26.5: + resolution: {integrity: sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==} + + undici@6.11.1: + resolution: {integrity: sha512-KyhzaLJnV1qa3BSHdj4AZ2ndqI0QWPxYzaIOio0WzcEJB9gvuysprJSLtpvc2D9mhR9jPDUk7xlJlZbH2KR5iw==} + engines: {node: '>=18.0'} + + unique-string@2.0.0: + resolution: {integrity: sha512-uNaeirEPvpZWSgzwsPGtU2zVSTrn/8L5q/IexZmH0eH6SA73CmAA5U4GwORTxQAZs95TAXLNqeLoPPNO5gZfWg==} + engines: {node: '>=8'} + + universalify@2.0.1: + resolution: {integrity: sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==} + engines: {node: '>= 10.0.0'} + + unpipe@1.0.0: + resolution: {integrity: sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==} + engines: {node: '>= 0.8'} + + util-deprecate@1.0.2: + resolution: {integrity: sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==} + + util@0.12.5: + resolution: {integrity: sha512-kZf/K6hEIrWHI6XqOFUiiMa+79wE/D8Q+NCNAWclkyg3b4d2k7s0QGepNjiABc+aR3N1PAyHL7p6UcLY6LmrnA==} + + utils-merge@1.0.1: + resolution: {integrity: sha512-pMZTvIkT1d+TFGvDOqodOclx0QWkkgi6Tdoa8gC8ffGAAqz9pzPTZWAybbsHHoED/ztMtkv/VoYTYyShUn81hA==} + engines: {node: '>= 0.4.0'} + + uuid@9.0.0: + resolution: {integrity: sha512-MXcSTerfPa4uqyzStbRoTgt5XIe3x5+42+q1sDuy3R5MDk66URdLMOZe5aPX/SQd+kuYAh0FdP/pO28IkQyTeg==} + hasBin: true + + v8-compile-cache-lib@3.0.1: + resolution: {integrity: sha512-wa7YjyUGfNZngI/vtK0UHAN+lgDCxBPCylVXGp0zu59Fz5aiGtNXaq3DhIov063MorB+VfufLh3JlF2KdTK3xg==} + + validate-npm-package-license@3.0.4: + resolution: {integrity: sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew==} + + validator@13.11.0: + resolution: {integrity: sha512-Ii+sehpSfZy+At5nPdnyMhx78fEoPDkR2XW/zimHEL3MyGJQOCQ7WeP20jPYRz7ZCpcKLB21NxuXHF3bxjStBQ==} + engines: {node: '>= 0.10'} + + vary@1.1.2: + resolution: {integrity: sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==} + engines: {node: '>= 0.8'} + + web-encoding@1.1.5: + resolution: {integrity: sha512-HYLeVCdJ0+lBYV2FvNZmv3HJ2Nt0QYXqZojk3d9FJOLkwnuhzM9tmamh8d7HPM8QqjKH8DeHkFTx+CFlWpZZDA==} + + webidl-conversions@3.0.1: + resolution: {integrity: sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==} + + whatwg-url@5.0.0: + resolution: {integrity: sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==} + + which-boxed-primitive@1.0.2: + resolution: {integrity: sha512-bwZdv0AKLpplFY2KZRX6TvyuN7ojjr7lwkg6ml0roIy9YeuSr7JS372qlNW18UQYzgYK9ziGcerWqZOmEn9VNg==} + + which-typed-array@1.1.15: + resolution: {integrity: sha512-oV0jmFtUky6CXfkqehVvBP/LSWJ2sy4vWMioiENyJLePrBO/yKyV9OyJySfAKosh+RYkIl5zJCNZ8/4JncrpdA==} + engines: {node: '>= 0.4'} + + which@2.0.2: + resolution: {integrity: sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==} + engines: {node: '>= 8'} + hasBin: true + + wordwrap@1.0.0: + resolution: {integrity: sha512-gvVzJFlPycKc5dZN4yPkP8w7Dc37BtP1yczEneOb4uq34pXZcvrtRTmWV8W+Ume+XCxKgbjM+nevkyFPMybd4Q==} + + wrap-ansi@7.0.0: + resolution: {integrity: sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==} + engines: {node: '>=10'} + + wrap-ansi@8.1.0: + resolution: {integrity: sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ==} + engines: {node: '>=12'} + + wrappy@1.0.2: + resolution: {integrity: sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==} + + xml2js@0.5.0: + resolution: {integrity: sha512-drPFnkQJik/O+uPKpqSgr22mpuFHqKdbS835iAQrUC73L2F5WkboIRd63ai/2Yg6I1jzifPFKH2NTK+cfglkIA==} + engines: {node: '>=4.0.0'} + + xml@1.0.1: + resolution: {integrity: sha512-huCv9IH9Tcf95zuYCsQraZtWnJvBtLVE0QHMOs8bWyZAFZNDcYjsPq1nEx8jKA9y+Beo9v+7OBPRisQTjinQMw==} + + xmlbuilder@11.0.1: + resolution: {integrity: sha512-fDlsI/kFEx7gLvbecc0/ohLG50fugQp8ryHzMTuW9vSa1GJ0XYWKnhsUx7oie3G98+r56aTQIUB4kht42R3JvA==} + engines: {node: '>=4.0'} + + y18n@5.0.8: + resolution: {integrity: sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==} + engines: {node: '>=10'} + + yallist@4.0.0: + resolution: {integrity: sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==} + + yaml@2.4.1: + resolution: {integrity: sha512-pIXzoImaqmfOrL7teGUBt/T7ZDnyeGBWyXQBvOVhLkWLN37GXv8NMLK406UY6dS51JfcQHsmcW5cJ441bHg6Lg==} + engines: {node: '>= 14'} + hasBin: true + + yargs-parser@21.1.1: + resolution: {integrity: sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==} + engines: {node: '>=12'} + + yargs@17.7.2: + resolution: {integrity: sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==} + engines: {node: '>=12'} + + yn@3.1.1: + resolution: {integrity: sha512-Ux4ygGWsu2c7isFWe8Yu1YluJmqVhxqK2cLXNQA5AcC3QfbGNpM7fu0Y8b/z16pXLnFxZYvWhd3fhBY9DLmC6Q==} + engines: {node: '>=6'} + + yocto-queue@0.1.0: + resolution: {integrity: sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==} + engines: {node: '>=10'} + + zip-stream@4.1.1: + resolution: {integrity: sha512-9qv4rlDiopXg4E69k+vMHjNN63YFMe9sZMrdlvKnCjlCRWeCBswPPMPUfx+ipsAWq1LXHe70RcbaHdJJpS6hyQ==} + engines: {node: '>= 10'} + + zod@3.23.8: + resolution: {integrity: sha512-XBx9AXhXktjUqnepgTiE5flcKIYWi/rme0Eaj+5Y0lftuGBq+jyRu/md4WnuxqgP1ubdpNCsYEYPxrzVHD8d6g==} + +snapshots: + + '@antfu/ni@0.21.8': {} + + '@babel/code-frame@7.24.7': + dependencies: + '@babel/highlight': 7.24.7 + picocolors: 1.0.1 + + '@babel/helper-validator-identifier@7.24.7': {} + + '@babel/highlight@7.24.7': + dependencies: + '@babel/helper-validator-identifier': 7.24.7 + chalk: 2.4.2 + js-tokens: 4.0.0 + picocolors: 1.0.1 + + '@chevrotain/cst-dts-gen@10.5.0': + dependencies: + '@chevrotain/gast': 10.5.0 + '@chevrotain/types': 10.5.0 + lodash: 4.17.21 + + '@chevrotain/gast@10.5.0': + dependencies: + '@chevrotain/types': 10.5.0 + lodash: 4.17.21 + + '@chevrotain/types@10.5.0': {} + + '@chevrotain/utils@10.5.0': {} + + '@cspotcode/source-map-support@0.8.1': + dependencies: + '@jridgewell/trace-mapping': 0.3.9 + + '@elastic/elasticsearch@8.13.0': dependencies: '@elastic/transport': 8.5.0 tslib: 2.6.2 transitivePeerDependencies: - supports-color - dev: false - /@elastic/transport@8.5.0: - resolution: {integrity: sha512-T+zSUHXBfrqlj/E9pJiaEgKoTdGykBCohzNBt6omDfI6EQtaNT240oMO03oXo35T8rwrCVonSMSoedbmToncVA==} - engines: {node: '>=18'} + '@elastic/transport@8.5.0': dependencies: debug: 4.3.4(supports-color@5.5.0) hpagent: 1.2.0 @@ -99,87 +2173,59 @@ packages: undici: 6.11.1 transitivePeerDependencies: - supports-color - dev: false - /@hapi/accept@6.0.3: - resolution: {integrity: sha512-p72f9k56EuF0n3MwlBNThyVE5PXX40g+aQh+C/xbKrfzahM2Oispv3AXmOIU51t3j77zay1qrX7IIziZXspMlw==} + '@hapi/accept@6.0.3': dependencies: '@hapi/boom': 10.0.1 '@hapi/hoek': 11.0.4 - dev: false - /@hapi/ammo@6.0.1: - resolution: {integrity: sha512-pmL+nPod4g58kXrMcsGLp05O2jF4P2Q3GiL8qYV7nKYEh3cGf+rV4P5Jyi2Uq0agGhVU63GtaSAfBEZOlrJn9w==} + '@hapi/ammo@6.0.1': dependencies: '@hapi/hoek': 11.0.4 - dev: false - /@hapi/b64@6.0.1: - resolution: {integrity: sha512-ZvjX4JQReUmBheeCq+S9YavcnMMHWqx3S0jHNXWIM1kQDxB9cyfSycpVvjfrKcIS8Mh5N3hmu/YKo4Iag9g2Kw==} + '@hapi/b64@6.0.1': dependencies: '@hapi/hoek': 11.0.4 - dev: false - /@hapi/boom@10.0.1: - resolution: {integrity: sha512-ERcCZaEjdH3OgSJlyjVk8pHIFeus91CjKP3v+MpgBNp5IvGzP2l/bRiD78nqYcKPaZdbKkK5vDBVPd2ohHBlsA==} + '@hapi/boom@10.0.1': dependencies: '@hapi/hoek': 11.0.4 - dev: false - /@hapi/bounce@3.0.1: - resolution: {integrity: sha512-G+/Pp9c1Ha4FDP+3Sy/Xwg2O4Ahaw3lIZFSX+BL4uWi64CmiETuZPxhKDUD4xBMOUZbBlzvO8HjiK8ePnhBadA==} + '@hapi/bounce@3.0.1': dependencies: '@hapi/boom': 10.0.1 '@hapi/hoek': 11.0.4 - dev: false - /@hapi/bourne@3.0.0: - resolution: {integrity: sha512-Waj1cwPXJDucOib4a3bAISsKJVb15MKi9IvmTI/7ssVEm6sywXGjVJDhl6/umt1pK1ZS7PacXU3A1PmFKHEZ2w==} - dev: false + '@hapi/bourne@3.0.0': {} - /@hapi/call@9.0.1: - resolution: {integrity: sha512-uPojQRqEL1GRZR4xXPqcLMujQGaEpyVPRyBlD8Pp5rqgIwLhtveF9PkixiKru2THXvuN8mUrLeet5fqxKAAMGg==} + '@hapi/call@9.0.1': dependencies: '@hapi/boom': 10.0.1 '@hapi/hoek': 11.0.4 - dev: false - /@hapi/catbox-memory@6.0.1: - resolution: {integrity: sha512-sVb+/ZxbZIvaMtJfAbdyY+QJUQg9oKTwamXpEg/5xnfG5WbJLTjvEn4kIGKz9pN3ENNbIL/bIdctmHmqi/AdGA==} + '@hapi/catbox-memory@6.0.1': dependencies: '@hapi/boom': 10.0.1 '@hapi/hoek': 11.0.4 - dev: false - /@hapi/catbox@12.1.1: - resolution: {integrity: sha512-hDqYB1J+R0HtZg4iPH3LEnldoaBsar6bYp0EonBmNQ9t5CO+1CqgCul2ZtFveW1ReA5SQuze9GPSU7/aecERhw==} + '@hapi/catbox@12.1.1': dependencies: '@hapi/boom': 10.0.1 '@hapi/hoek': 11.0.4 '@hapi/podium': 5.0.1 '@hapi/validate': 2.0.1 - dev: false - /@hapi/content@6.0.0: - resolution: {integrity: sha512-CEhs7j+H0iQffKfe5Htdak5LBOz/Qc8TRh51cF+BFv0qnuph3Em4pjGVzJMkI2gfTDdlJKWJISGWS1rK34POGA==} + '@hapi/content@6.0.0': dependencies: '@hapi/boom': 10.0.1 - dev: false - /@hapi/cryptiles@6.0.1: - resolution: {integrity: sha512-9GM9ECEHfR8lk5ASOKG4+4ZsEzFqLfhiryIJ2ISePVB92OHLp/yne4m+zn7z9dgvM98TLpiFebjDFQ0UHcqxXQ==} - engines: {node: '>=14.0.0'} + '@hapi/cryptiles@6.0.1': dependencies: '@hapi/boom': 10.0.1 - dev: false - /@hapi/file@3.0.0: - resolution: {integrity: sha512-w+lKW+yRrLhJu620jT3y+5g2mHqnKfepreykvdOcl9/6up8GrQQn+l3FRTsjHTKbkbfQFkuksHpdv2EcpKcJ4Q==} - dev: false + '@hapi/file@3.0.0': {} - /@hapi/hapi@21.3.7: - resolution: {integrity: sha512-33J0nreMfqkhY7wwRAZRy+9J+7J4QOH1JtICMjIUmxfaOYSJL/d8JJCtg57SX60944bhlCeu7isb7qyr2jT2oA==} - engines: {node: '>=14.15.0'} + '@hapi/hapi@21.3.7': dependencies: '@hapi/accept': 6.0.3 '@hapi/ammo': 6.0.1 @@ -199,79 +2245,58 @@ packages: '@hapi/teamwork': 6.0.0 '@hapi/topo': 6.0.2 '@hapi/validate': 2.0.1 - dev: false - /@hapi/heavy@8.0.1: - resolution: {integrity: sha512-gBD/NANosNCOp6RsYTsjo2vhr5eYA3BEuogk6cxY0QdhllkkTaJFYtTXv46xd6qhBVMbMMqcSdtqey+UQU3//w==} + '@hapi/heavy@8.0.1': dependencies: '@hapi/boom': 10.0.1 '@hapi/hoek': 11.0.4 '@hapi/validate': 2.0.1 - dev: false - /@hapi/hoek@11.0.4: - resolution: {integrity: sha512-PnsP5d4q7289pS2T2EgGz147BFJ2Jpb4yrEdkpz2IhgEUzos1S7HTl7ezWh1yfYzYlj89KzLdCRkqsP6SIryeQ==} - dev: false + '@hapi/hoek@11.0.4': {} - /@hapi/iron@7.0.1: - resolution: {integrity: sha512-tEZnrOujKpS6jLKliyWBl3A9PaE+ppuL/+gkbyPPDb/l2KSKQyH4lhMkVb+sBhwN+qaxxlig01JRqB8dk/mPxQ==} + '@hapi/iron@7.0.1': dependencies: '@hapi/b64': 6.0.1 '@hapi/boom': 10.0.1 '@hapi/bourne': 3.0.0 '@hapi/cryptiles': 6.0.1 '@hapi/hoek': 11.0.4 - dev: false - /@hapi/mimos@7.0.1: - resolution: {integrity: sha512-b79V+BrG0gJ9zcRx1VGcCI6r6GEzzZUgiGEJVoq5gwzuB2Ig9Cax8dUuBauQCFKvl2YWSWyOc8mZ8HDaJOtkew==} + '@hapi/mimos@7.0.1': dependencies: '@hapi/hoek': 11.0.4 mime-db: 1.52.0 - dev: false - /@hapi/nigel@5.0.1: - resolution: {integrity: sha512-uv3dtYuB4IsNaha+tigWmN8mQw/O9Qzl5U26Gm4ZcJVtDdB1AVJOwX3X5wOX+A07qzpEZnOMBAm8jjSqGsU6Nw==} - engines: {node: '>=14.0.0'} + '@hapi/nigel@5.0.1': dependencies: '@hapi/hoek': 11.0.4 '@hapi/vise': 5.0.1 - dev: false - /@hapi/pez@6.1.0: - resolution: {integrity: sha512-+FE3sFPYuXCpuVeHQ/Qag1b45clR2o54QoonE/gKHv9gukxQ8oJJZPR7o3/ydDTK6racnCJXxOyT1T93FCJMIg==} + '@hapi/pez@6.1.0': dependencies: '@hapi/b64': 6.0.1 '@hapi/boom': 10.0.1 '@hapi/content': 6.0.0 '@hapi/hoek': 11.0.4 '@hapi/nigel': 5.0.1 - dev: false - /@hapi/podium@5.0.1: - resolution: {integrity: sha512-eznFTw6rdBhAijXFIlBOMJJd+lXTvqbrBIS4Iu80r2KTVIo4g+7fLy4NKp/8+UnSt5Ox6mJtAlKBU/Sf5080TQ==} + '@hapi/podium@5.0.1': dependencies: '@hapi/hoek': 11.0.4 '@hapi/teamwork': 6.0.0 '@hapi/validate': 2.0.1 - dev: false - /@hapi/shot@6.0.1: - resolution: {integrity: sha512-s5ynMKZXYoDd3dqPw5YTvOR/vjHvMTxc388+0qL0jZZP1+uwXuUD32o9DuuuLsmTlyXCWi02BJl1pBpwRuUrNA==} + '@hapi/shot@6.0.1': dependencies: '@hapi/hoek': 11.0.4 '@hapi/validate': 2.0.1 - dev: false - /@hapi/somever@4.1.1: - resolution: {integrity: sha512-lt3QQiDDOVRatS0ionFDNrDIv4eXz58IibQaZQDOg4DqqdNme8oa0iPWcE0+hkq/KTeBCPtEOjDOBKBKwDumVg==} + '@hapi/somever@4.1.1': dependencies: '@hapi/bounce': 3.0.1 '@hapi/hoek': 11.0.4 - dev: false - /@hapi/statehood@8.1.1: - resolution: {integrity: sha512-YbK7PSVUA59NArAW5Np0tKRoIZ5VNYUicOk7uJmWZF6XyH5gGL+k62w77SIJb0AoAJ0QdGQMCQ/WOGL1S3Ydow==} + '@hapi/statehood@8.1.1': dependencies: '@hapi/boom': 10.0.1 '@hapi/bounce': 3.0.1 @@ -280,10 +2305,8 @@ packages: '@hapi/hoek': 11.0.4 '@hapi/iron': 7.0.1 '@hapi/validate': 2.0.1 - dev: false - /@hapi/subtext@8.1.0: - resolution: {integrity: sha512-PyaN4oSMtqPjjVxLny1k0iYg4+fwGusIhaom9B2StinBclHs7v46mIW706Y+Wo21lcgulGyXbQrmT/w4dus6ww==} + '@hapi/subtext@8.1.0': dependencies: '@hapi/boom': 10.0.1 '@hapi/bourne': 3.0.0 @@ -292,140 +2315,211 @@ packages: '@hapi/hoek': 11.0.4 '@hapi/pez': 6.1.0 '@hapi/wreck': 18.0.1 - dev: false - /@hapi/teamwork@6.0.0: - resolution: {integrity: sha512-05HumSy3LWfXpmJ9cr6HzwhAavrHkJ1ZRCmNE2qJMihdM5YcWreWPfyN0yKT2ZjCM92au3ZkuodjBxOibxM67A==} - engines: {node: '>=14.0.0'} - dev: false + '@hapi/teamwork@6.0.0': {} - /@hapi/topo@6.0.2: - resolution: {integrity: sha512-KR3rD5inZbGMrHmgPxsJ9dbi6zEK+C3ZwUwTa+eMwWLz7oijWUTWD2pMSNNYJAU6Qq+65NkxXjqHr/7LM2Xkqg==} + '@hapi/topo@6.0.2': dependencies: '@hapi/hoek': 11.0.4 - dev: false - /@hapi/validate@2.0.1: - resolution: {integrity: sha512-NZmXRnrSLK8MQ9y/CMqE9WSspgB9xA41/LlYR0k967aSZebWr4yNrpxIbov12ICwKy4APSlWXZga9jN5p6puPA==} + '@hapi/validate@2.0.1': dependencies: '@hapi/hoek': 11.0.4 '@hapi/topo': 6.0.2 - dev: false - /@hapi/vise@5.0.1: - resolution: {integrity: sha512-XZYWzzRtINQLedPYlIkSkUr7m5Ddwlu99V9elh8CSygXstfv3UnWIXT0QD+wmR0VAG34d2Vx3olqcEhRRoTu9A==} + '@hapi/vise@5.0.1': dependencies: '@hapi/hoek': 11.0.4 - dev: false - /@hapi/wreck@18.0.1: - resolution: {integrity: sha512-OLHER70+rZxvDl75xq3xXOfd3e8XIvz8fWY0dqg92UvhZ29zo24vQgfqgHSYhB5ZiuFpSLeriOisAlxAo/1jWg==} + '@hapi/wreck@18.0.1': dependencies: '@hapi/boom': 10.0.1 '@hapi/bourne': 3.0.0 '@hapi/hoek': 11.0.4 - dev: false - /@isaacs/cliui@8.0.2: - resolution: {integrity: sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==} - engines: {node: '>=12'} + '@isaacs/cliui@8.0.2': dependencies: string-width: 5.1.2 - string-width-cjs: /string-width@4.2.3 + string-width-cjs: string-width@4.2.3 strip-ansi: 7.1.0 - strip-ansi-cjs: /strip-ansi@6.0.1 + strip-ansi-cjs: strip-ansi@6.0.1 wrap-ansi: 8.1.0 - wrap-ansi-cjs: /wrap-ansi@7.0.0 - dev: false + wrap-ansi-cjs: wrap-ansi@7.0.0 - /@jridgewell/resolve-uri@3.1.2: - resolution: {integrity: sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==} - engines: {node: '>=6.0.0'} - dev: true + '@jridgewell/resolve-uri@3.1.2': {} - /@jridgewell/sourcemap-codec@1.4.15: - resolution: {integrity: sha512-eF2rxCRulEKXHTRiDrDy6erMYWqNw4LPdQ8UQA4huuxaQsVeRPFl2oM8oDGxMFhJUWZf9McpLtJasDDZb/Bpeg==} - dev: true + '@jridgewell/sourcemap-codec@1.4.15': {} - /@jridgewell/trace-mapping@0.3.9: - resolution: {integrity: sha512-3Belt6tdc8bPgAtbcmdtNJlirVoTmEb5e2gC94PnkwEW9jI6CAHUeoG85tjWP5WquqfavoMtMwiG4P926ZKKuQ==} + '@jridgewell/trace-mapping@0.3.9': dependencies: '@jridgewell/resolve-uri': 3.1.2 '@jridgewell/sourcemap-codec': 1.4.15 - dev: true - /@lukeed/ms@2.0.2: - resolution: {integrity: sha512-9I2Zn6+NJLfaGoz9jN3lpwDgAYvfGeNYdbAIjJOqzs4Tpc+VU3Jqq4IofSUBKajiDS8k9fZIg18/z13mpk1bsA==} - engines: {node: '>=8'} - dev: false + '@lukeed/ms@2.0.2': {} - /@pkgjs/parseargs@0.11.0: - resolution: {integrity: sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==} - engines: {node: '>=14'} - requiresBuild: true - dev: false + '@mrleebo/prisma-ast@0.7.0': + dependencies: + chevrotain: 10.5.0 + lilconfig: 2.1.0 + + '@nodelib/fs.scandir@2.1.5': + dependencies: + '@nodelib/fs.stat': 2.0.5 + run-parallel: 1.2.0 + + '@nodelib/fs.stat@2.0.5': {} + + '@nodelib/fs.walk@1.2.8': + dependencies: + '@nodelib/fs.scandir': 2.1.5 + fastq: 1.17.1 + + '@opentelemetry/api@1.4.1': {} + + '@pkgjs/parseargs@0.11.0': optional: true - /@prisma/client@5.12.1(prisma@5.12.1): - resolution: {integrity: sha512-6/JnizEdlSBxDIdiLbrBdMW5NqDxOmhXAJaNXiPpgzAPr/nLZResT6MMpbOHLo5yAbQ1Vv5UU8PTPRzb0WIxdA==} - engines: {node: '>=16.13'} - requiresBuild: true - peerDependencies: - prisma: '*' - peerDependenciesMeta: - prisma: - optional: true + '@prisma/client@5.16.0(prisma@5.16.0)': + optionalDependencies: + prisma: 5.16.0 + + '@prisma/debug@5.16.0': {} + + '@prisma/debug@5.3.1': dependencies: - prisma: 5.12.1 - dev: false + '@types/debug': 4.1.8 + debug: 4.3.4(supports-color@5.5.0) + strip-ansi: 6.0.1 + transitivePeerDependencies: + - supports-color - /@prisma/debug@5.12.1: - resolution: {integrity: sha512-kd/wNsR0klrv79o1ITsbWxYyh4QWuBidvxsXSParPsYSu0ircUmNk3q4ojsgNc3/81b0ozg76iastOG43tbf8A==} + '@prisma/engines-version@5.16.0-24.34ace0eb2704183d2c05b60b52fba5c43c13f303': {} - /@prisma/engines-version@5.12.0-21.473ed3124229e22d881cb7addf559799debae1ab: - resolution: {integrity: sha512-6yvO8s80Tym61aB4QNtYZfWVmE3pwqe807jEtzm8C5VDe7nw8O1FGX3TXUaXmWV0fQTIAfRbeL2Gwrndabp/0g==} - - /@prisma/engines@5.12.1: - resolution: {integrity: sha512-HQDdglLw2bZR/TXD2Y+YfDMvi5Q8H+acbswqOsWyq9pPjBLYJ6gzM+ptlTU/AV6tl0XSZLU1/7F4qaWa8bqpJA==} - requiresBuild: true + '@prisma/engines@5.16.0': dependencies: - '@prisma/debug': 5.12.1 - '@prisma/engines-version': 5.12.0-21.473ed3124229e22d881cb7addf559799debae1ab - '@prisma/fetch-engine': 5.12.1 - '@prisma/get-platform': 5.12.1 + '@prisma/debug': 5.16.0 + '@prisma/engines-version': 5.16.0-24.34ace0eb2704183d2c05b60b52fba5c43c13f303 + '@prisma/fetch-engine': 5.16.0 + '@prisma/get-platform': 5.16.0 - /@prisma/fetch-engine@5.12.1: - resolution: {integrity: sha512-qSs3KcX1HKcea1A+hlJVK/ljj0PNIUHDxAayGMvgJBqmaN32P9tCidlKz1EGv6WoRFICYnk3Dd/YFLBwnFIozA==} + '@prisma/engines@5.3.1': {} + + '@prisma/fetch-engine@5.16.0': dependencies: - '@prisma/debug': 5.12.1 - '@prisma/engines-version': 5.12.0-21.473ed3124229e22d881cb7addf559799debae1ab - '@prisma/get-platform': 5.12.1 + '@prisma/debug': 5.16.0 + '@prisma/engines-version': 5.16.0-24.34ace0eb2704183d2c05b60b52fba5c43c13f303 + '@prisma/get-platform': 5.16.0 - /@prisma/get-platform@5.12.1: - resolution: {integrity: sha512-pgIR+pSvhYHiUcqXVEZS31NrFOTENC9yFUdEAcx7cdQBoZPmHVjtjN4Ss6NzVDMYPrKJJ51U14EhEoeuBlMioQ==} + '@prisma/fetch-engine@5.3.1': dependencies: - '@prisma/debug': 5.12.1 + '@prisma/debug': 5.3.1 + '@prisma/get-platform': 5.3.1 + execa: 5.1.1 + find-cache-dir: 3.3.2 + fs-extra: 11.1.1 + hasha: 5.2.2 + http-proxy-agent: 7.0.0 + https-proxy-agent: 7.0.2 + kleur: 4.1.5 + node-fetch: 2.7.0 + p-filter: 2.1.0 + p-map: 4.0.0 + p-retry: 4.6.2 + progress: 2.0.3 + rimraf: 3.0.2 + temp-dir: 2.0.0 + tempy: 1.0.1 + transitivePeerDependencies: + - encoding + - supports-color - /@tsconfig/node10@1.0.11: - resolution: {integrity: sha512-DcRjDCujK/kCk/cUe8Xz8ZSpm8mS3mNNpta+jGCA6USEDfktlNvm1+IuZ9eTcDbNk41BHwpHHeW+N1lKCz4zOw==} - dev: true + '@prisma/generator-helper@5.3.1': + dependencies: + '@prisma/debug': 5.3.1 + '@types/cross-spawn': 6.0.2 + cross-spawn: 7.0.3 + kleur: 4.1.5 + transitivePeerDependencies: + - supports-color - /@tsconfig/node12@1.0.11: - resolution: {integrity: sha512-cqefuRsh12pWyGsIoBKJA9luFu3mRxCA+ORZvA4ktLSzIuCUtWVxGIuXigEwO5/ywWFMZ2QEGKWvkZG1zDMTag==} - dev: true + '@prisma/get-platform@5.16.0': + dependencies: + '@prisma/debug': 5.16.0 - /@tsconfig/node14@1.0.3: - resolution: {integrity: sha512-ysT8mhdixWK6Hw3i1V2AeRqZ5WfXg1G43mqoYlM2nc6388Fq5jcXyr5mRsqViLx/GJYdoL0bfXD8nmF+Zn/Iow==} - dev: true + '@prisma/get-platform@5.3.1': + dependencies: + '@prisma/debug': 5.3.1 + escape-string-regexp: 4.0.0 + execa: 5.1.1 + fs-jetpack: 5.1.0 + kleur: 4.1.5 + replace-string: 3.1.0 + strip-ansi: 6.0.1 + tempy: 1.0.1 + terminal-link: 2.1.1 + ts-pattern: 4.3.0 + transitivePeerDependencies: + - supports-color - /@tsconfig/node16@1.0.4: - resolution: {integrity: sha512-vxhUy4J8lyeyinH7Azl1pdd43GJhZH/tP2weN8TntQblOY+A0XbT8DJk1/oCPuOOyg/Ja757rG0CgHcWC8OfMA==} - dev: true + '@prisma/internals@5.3.1': + dependencies: + '@antfu/ni': 0.21.8 + '@opentelemetry/api': 1.4.1 + '@prisma/debug': 5.3.1 + '@prisma/engines': 5.3.1 + '@prisma/fetch-engine': 5.3.1 + '@prisma/generator-helper': 5.3.1 + '@prisma/get-platform': 5.3.1 + '@prisma/prisma-schema-wasm': 5.3.1-2.61e140623197a131c2a6189271ffee05a7aa9a59 + archiver: 5.3.2 + arg: 5.0.2 + checkpoint-client: 1.1.27 + cli-truncate: 2.1.0 + dotenv: 16.0.3 + escape-string-regexp: 4.0.0 + execa: 5.1.1 + find-up: 5.0.0 + fp-ts: 2.16.1 + fs-extra: 11.1.1 + fs-jetpack: 5.1.0 + global-dirs: 3.0.1 + globby: 11.1.0 + indent-string: 4.0.0 + is-windows: 1.0.2 + is-wsl: 2.2.0 + kleur: 4.1.5 + new-github-issue-url: 0.2.1 + node-fetch: 2.7.0 + npm-packlist: 5.1.3 + open: 7.4.2 + p-map: 4.0.0 + prompts: 2.4.2 + read-pkg-up: 7.0.1 + replace-string: 3.1.0 + resolve: 1.22.4 + string-width: 4.2.3 + strip-ansi: 6.0.1 + strip-indent: 3.0.0 + temp-dir: 2.0.0 + tempy: 1.0.1 + terminal-link: 2.1.1 + tmp: 0.2.1 + ts-pattern: 4.3.0 + transitivePeerDependencies: + - encoding + - supports-color - /@tsoa/cli@6.2.0: - resolution: {integrity: sha512-kzr10MsARpuivJl59XD33+sdMA18Rx9KBu7NCp18nV6kPQ1LDrVBwVgLL96w7lBgUGsCgVJ1/cUePW313uTZCw==} - engines: {node: '>=18.0.0', yarn: '>=1.9.4'} - hasBin: true + '@prisma/prisma-schema-wasm@5.3.1-2.61e140623197a131c2a6189271ffee05a7aa9a59': {} + + '@tsconfig/node10@1.0.11': {} + + '@tsconfig/node12@1.0.11': {} + + '@tsconfig/node14@1.0.3': {} + + '@tsconfig/node16@1.0.4': {} + + '@tsoa/cli@6.2.0': dependencies: '@tsoa/runtime': 6.2.0 '@types/multer': 1.4.11 @@ -441,11 +2535,8 @@ packages: yargs: 17.7.2 transitivePeerDependencies: - supports-color - dev: false - /@tsoa/runtime@6.2.0: - resolution: {integrity: sha512-iXSi5rDZWcPRcLKa9WaMBUdh4SdDN+9Cmy+R7i/DSCtFtbtUqE+ui+IMV9o6+759N6J3FqGBaPWa9kAtOrL4sA==} - engines: {node: '>=18.0.0', yarn: '>=1.9.4'} + '@tsoa/runtime@6.2.0': dependencies: '@hapi/boom': 10.0.1 '@hapi/hapi': 21.3.7 @@ -456,79 +2547,66 @@ packages: validator: 13.11.0 transitivePeerDependencies: - supports-color - dev: false - /@types/accepts@1.3.7: - resolution: {integrity: sha512-Pay9fq2lM2wXPWbteBsRAGiWH2hig4ZE2asK+mm7kUzlxRTfL961rj89I6zV/E3PcIkDqyuBEcMxFT7rccugeQ==} + '@types/accepts@1.3.7': dependencies: '@types/node': 20.12.2 - dev: false - /@types/body-parser@1.19.5: - resolution: {integrity: sha512-fB3Zu92ucau0iQ0JMCFQE7b/dv8Ot07NI3KaZIkIUNXq82k4eBAqUaneXfleGY9JWskeS9y+u0nXMyspcuQrCg==} + '@types/body-parser@1.19.5': dependencies: '@types/connect': 3.4.38 '@types/node': 20.12.2 - /@types/connect@3.4.38: - resolution: {integrity: sha512-K6uROf1LD88uDQqJCktA4yzL1YYAK6NgfsI0v/mTgyPKWsX1CnJ0XPSDhViejru1GcRkLWb8RlzFYJRqGUbaug==} + '@types/connect@3.4.38': dependencies: '@types/node': 20.12.2 - /@types/content-disposition@0.5.8: - resolution: {integrity: sha512-QVSSvno3dE0MgO76pJhmv4Qyi/j0Yk9pBp0Y7TJ2Tlj+KCgJWY6qX7nnxCOLkZ3VYRSIk1WTxCvwUSdx6CCLdg==} - dev: false + '@types/content-disposition@0.5.8': {} - /@types/cookies@0.9.0: - resolution: {integrity: sha512-40Zk8qR147RABiQ7NQnBzWzDcjKzNrntB5BAmeGCb2p/MIyOE+4BVvc17wumsUqUw00bJYqoXFHYygQnEFh4/Q==} + '@types/cookies@0.9.0': dependencies: '@types/connect': 3.4.38 '@types/express': 4.17.21 '@types/keygrip': 1.0.6 '@types/node': 20.12.2 - dev: false - /@types/cors@2.8.17: - resolution: {integrity: sha512-8CGDvrBj1zgo2qE+oS3pOCyYNqCPryMWY2bGfwA0dcfopWGgxs+78df0Rs3rc9THP4JkOhLsAa+15VdpAqkcUA==} + '@types/cors@2.8.17': dependencies: '@types/node': 20.12.2 - dev: true - /@types/express-serve-static-core@4.17.43: - resolution: {integrity: sha512-oaYtiBirUOPQGSWNGPWnzyAFJ0BP3cwvN4oWZQY+zUBwpVIGsKUkpBpSztp74drYcjavs7SKFZ4DX1V2QeN8rg==} + '@types/cross-spawn@6.0.2': + dependencies: + '@types/node': 20.12.2 + + '@types/debug@4.1.8': + dependencies: + '@types/ms': 0.7.34 + + '@types/express-serve-static-core@4.17.43': dependencies: '@types/node': 20.12.2 '@types/qs': 6.9.14 '@types/range-parser': 1.2.7 '@types/send': 0.17.4 - /@types/express@4.17.21: - resolution: {integrity: sha512-ejlPM315qwLpaQlQDTjPdsUFSc6ZsP4AN6AlWnogPjQ7CVi7PYF3YVz+CY3jE2pwYf7E/7HlDAN0rV2GxTG0HQ==} + '@types/express@4.17.21': dependencies: '@types/body-parser': 1.19.5 '@types/express-serve-static-core': 4.17.43 '@types/qs': 6.9.14 '@types/serve-static': 1.15.5 - /@types/http-assert@1.5.5: - resolution: {integrity: sha512-4+tE/lwdAahgZT1g30Jkdm9PzFRde0xwxBNUyRsCitRvCQB90iuA2uJYdUnhnANRcqGXaWOGY4FEoxeElNAK2g==} - dev: false + '@types/http-assert@1.5.5': {} - /@types/http-errors@2.0.4: - resolution: {integrity: sha512-D0CFMMtydbJAegzOyHjtiKPLlvnm3iTZyZRSZoLq2mRhDdmLfIWOCYPfQJ4cu2erKghU++QvjcUjp/5h7hESpA==} + '@types/http-errors@2.0.4': {} - /@types/keygrip@1.0.6: - resolution: {integrity: sha512-lZuNAY9xeJt7Bx4t4dx0rYCDqGPW8RXhQZK1td7d4H6E9zYbLoOtjBvfwdTKpsyxQI/2jv+armjX/RW+ZNpXOQ==} - dev: false + '@types/keygrip@1.0.6': {} - /@types/koa-compose@3.2.8: - resolution: {integrity: sha512-4Olc63RY+MKvxMwVknCUDhRQX1pFQoBZ/lXcRLP69PQkEpze/0cr8LNqJQe5NFb/b19DWi2a5bTi2VAlQzhJuA==} + '@types/koa-compose@3.2.8': dependencies: '@types/koa': 2.15.0 - dev: false - /@types/koa@2.15.0: - resolution: {integrity: sha512-7QFsywoE5URbuVnG3loe03QXuGajrnotr3gQkXcEBShORai23MePfFYdhz90FEtBBpkyIYQbVD+evKtloCgX3g==} + '@types/koa@2.15.0': dependencies: '@types/accepts': 1.3.7 '@types/content-disposition': 0.5.8 @@ -538,132 +2616,145 @@ packages: '@types/keygrip': 1.0.6 '@types/koa-compose': 3.2.8 '@types/node': 20.12.2 - dev: false - /@types/mime@1.3.5: - resolution: {integrity: sha512-/pyBZWSLD2n0dcHE3hq8s8ZvcETHtEuF+3E7XVt0Ig2nvsVQXdghHVcEkIWjy9A0wKfTn97a/PSDYohKIlnP/w==} + '@types/mime@1.3.5': {} - /@types/mime@4.0.0: - resolution: {integrity: sha512-5eEkJZ/BLvTE3vXGKkWlyTSUVZuzj23Wj8PoyOq2lt5I3CYbiLBOPb3XmCW6QcuOibIUE6emHXHt9E/F/rCa6w==} - deprecated: This is a stub types definition. mime provides its own type definitions, so you do not need this installed. + '@types/mime@4.0.0': dependencies: mime: 4.0.1 - /@types/multer@1.4.11: - resolution: {integrity: sha512-svK240gr6LVWvv3YGyhLlA+6LRRWA4mnGIU7RcNmgjBYFl6665wcXrRfxGp5tEPVHUNm5FMcmq7too9bxCwX/w==} + '@types/ms@0.7.34': {} + + '@types/multer@1.4.11': dependencies: '@types/express': 4.17.21 - dev: false - /@types/node@20.12.2: - resolution: {integrity: sha512-zQ0NYO87hyN6Xrclcqp7f8ZbXNbRfoGWNcMvHTPQp9UUrwI0mI7XBz+cu7/W6/VClYo2g63B0cjull/srU7LgQ==} + '@types/node@20.12.2': dependencies: undici-types: 5.26.5 - /@types/qs@6.9.14: - resolution: {integrity: sha512-5khscbd3SwWMhFqylJBLQ0zIu7c1K6Vz0uBIt915BI3zV0q1nfjRQD3RqSBcPaO6PHEF4ov/t9y89fSiyThlPA==} + '@types/normalize-package-data@2.4.4': {} - /@types/range-parser@1.2.7: - resolution: {integrity: sha512-hKormJbkJqzQGhziax5PItDUTMAM9uE2XXQmM37dyd4hVM+5aVl7oVxMVUiVQn2oCQFN/LKCZdvSM0pFRqbSmQ==} + '@types/qs@6.9.14': {} - /@types/send@0.17.4: - resolution: {integrity: sha512-x2EM6TJOybec7c52BX0ZspPodMsQUd5L6PRwOunVyVUhXiBSKf3AezDL8Dgvgt5o0UfKNfuA0eMLr2wLT4AiBA==} + '@types/range-parser@1.2.7': {} + + '@types/retry@0.12.0': {} + + '@types/send@0.17.4': dependencies: '@types/mime': 1.3.5 '@types/node': 20.12.2 - /@types/serve-static@1.15.5: - resolution: {integrity: sha512-PDRk21MnK70hja/YF8AHfC7yIsiQHn1rcXx7ijCFBX/k+XQJhQT/gw3xekXKJvx+5SXaMMS8oqQy09Mzvz2TuQ==} + '@types/serve-static@1.15.5': dependencies: '@types/http-errors': 2.0.4 '@types/mime': 4.0.0 '@types/node': 20.12.2 - /@types/swagger-ui-express@4.1.6: - resolution: {integrity: sha512-UVSiGYXa5IzdJJG3hrc86e8KdZWLYxyEsVoUI4iPXc7CO4VZ3AfNP8d/8+hrDRIqz+HAaSMtZSqAsF3Nq2X/Dg==} + '@types/swagger-ui-express@4.1.6': dependencies: '@types/express': 4.17.21 '@types/serve-static': 1.15.5 - dev: true - /@zxing/text-encoding@0.9.0: - resolution: {integrity: sha512-U/4aVJ2mxI0aDNI8Uq0wEhMgY+u4CNtEb0om3+y3+niDAsoTCOB33UF0sxpzqzdqXLqmvc+vZyAt4O8pPdfkwA==} - requiresBuild: true - dev: false + '@zxing/text-encoding@0.9.0': optional: true - /abbrev@1.1.1: - resolution: {integrity: sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==} - dev: true + abbrev@1.1.1: {} - /accepts@1.3.8: - resolution: {integrity: sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw==} - engines: {node: '>= 0.6'} + accepts@1.3.8: dependencies: mime-types: 2.1.35 negotiator: 0.6.3 - dev: false - /acorn-walk@8.3.2: - resolution: {integrity: sha512-cjkyv4OtNCIeqhHrfS81QWXoCBPExR/J62oyEqepVw8WaQeSqpW2uhuLPh1m9eWhDuOo/jUXVTlifvesOWp/4A==} - engines: {node: '>=0.4.0'} - dev: true + acorn-walk@8.3.2: {} - /acorn@8.11.3: - resolution: {integrity: sha512-Y9rRfJG5jcKOE0CLisYbojUjIrIEE7AGMzA/Sm4BslANhbS+cDMpgBdcPT91oJ7OuJ9hYJBx59RjbhxVnrF8Xg==} - engines: {node: '>=0.4.0'} - hasBin: true - dev: true + acorn@8.11.3: {} - /ansi-regex@5.0.1: - resolution: {integrity: sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==} - engines: {node: '>=8'} - dev: false + agent-base@7.1.1: + dependencies: + debug: 4.3.4(supports-color@5.5.0) + transitivePeerDependencies: + - supports-color - /ansi-regex@6.0.1: - resolution: {integrity: sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA==} - engines: {node: '>=12'} - dev: false + aggregate-error@3.1.0: + dependencies: + clean-stack: 2.2.0 + indent-string: 4.0.0 - /ansi-styles@4.3.0: - resolution: {integrity: sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==} - engines: {node: '>=8'} + ansi-escapes@4.3.2: + dependencies: + type-fest: 0.21.3 + + ansi-regex@5.0.1: {} + + ansi-regex@6.0.1: {} + + ansi-styles@3.2.1: + dependencies: + color-convert: 1.9.3 + + ansi-styles@4.3.0: dependencies: color-convert: 2.0.1 - dev: false - /ansi-styles@6.2.1: - resolution: {integrity: sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==} - engines: {node: '>=12'} - dev: false + ansi-styles@6.2.1: {} - /anymatch@3.1.3: - resolution: {integrity: sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==} - engines: {node: '>= 8'} + anymatch@3.1.3: dependencies: normalize-path: 3.0.0 picomatch: 2.3.1 - dev: true - /arg@4.1.3: - resolution: {integrity: sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA==} - dev: true + archiver-utils@2.1.0: + dependencies: + glob: 7.2.3 + graceful-fs: 4.2.11 + lazystream: 1.0.1 + lodash.defaults: 4.2.0 + lodash.difference: 4.5.0 + lodash.flatten: 4.4.0 + lodash.isplainobject: 4.0.6 + lodash.union: 4.6.0 + normalize-path: 3.0.0 + readable-stream: 2.3.8 - /array-buffer-byte-length@1.0.1: - resolution: {integrity: sha512-ahC5W1xgou+KTXix4sAO8Ki12Q+jf4i0+tmk3sC+zgcynshkHxzpXdImBehiUYKKKDwvfFiJl1tZt6ewscS1Mg==} - engines: {node: '>= 0.4'} + archiver-utils@3.0.4: + dependencies: + glob: 7.2.3 + graceful-fs: 4.2.11 + lazystream: 1.0.1 + lodash.defaults: 4.2.0 + lodash.difference: 4.5.0 + lodash.flatten: 4.4.0 + lodash.isplainobject: 4.0.6 + lodash.union: 4.6.0 + normalize-path: 3.0.0 + readable-stream: 3.6.2 + + archiver@5.3.2: + dependencies: + archiver-utils: 2.1.0 + async: 3.2.5 + buffer-crc32: 0.2.13 + readable-stream: 3.6.2 + readdir-glob: 1.1.3 + tar-stream: 2.2.0 + zip-stream: 4.1.1 + + arg@4.1.3: {} + + arg@5.0.2: {} + + array-buffer-byte-length@1.0.1: dependencies: call-bind: 1.0.7 is-array-buffer: 3.0.4 - dev: false - /array-flatten@1.1.1: - resolution: {integrity: sha512-PCVAQswWemu6UdxsDFFX/+gVeYqKAod3D3UVm91jHwynguOwAvYPhx8nNlM++NqRcK6CxxpUafjmhIdKiHibqg==} - dev: false + array-flatten@1.1.1: {} - /array.prototype.map@1.0.7: - resolution: {integrity: sha512-XpcFfLoBEAhezrrNw1V+yLXkE7M6uR7xJEsxbG6c/V9v043qurwVJB9r9UTnoSioFDoz1i1VOydpWGmJpfVZbg==} - engines: {node: '>= 0.4'} + array-union@2.1.0: {} + + array.prototype.map@1.0.7: dependencies: call-bind: 1.0.7 define-properties: 1.2.1 @@ -671,11 +2762,8 @@ packages: es-array-method-boxes-properly: 1.0.0 es-object-atoms: 1.0.0 is-string: 1.0.7 - dev: false - /arraybuffer.prototype.slice@1.0.3: - resolution: {integrity: sha512-bMxMKAjg13EBSVscxTaYA4mRc5t1UAXa2kXiGTNfZ079HIWXEkKmkgFrh/nJqamaLSrXO5H4WFFkPEaLJWbs3A==} - engines: {node: '>= 0.4'} + arraybuffer.prototype.slice@1.0.3: dependencies: array-buffer-byte-length: 1.0.1 call-bind: 1.0.7 @@ -685,49 +2773,41 @@ packages: get-intrinsic: 1.2.4 is-array-buffer: 3.0.4 is-shared-array-buffer: 1.0.3 - dev: false - /asn1.js@5.4.1: - resolution: {integrity: sha512-+I//4cYPccV8LdmBLiX8CYvf9Sp3vQsrqu2QNXRcrbiWvcx/UdlFiqUJJzxRQxgsZmvhXhn4cSKeSmoFjVdupA==} + asn1.js@5.4.1: dependencies: bn.js: 4.12.0 inherits: 2.0.4 minimalistic-assert: 1.0.1 safer-buffer: 2.1.2 - dev: false - /async@3.2.5: - resolution: {integrity: sha512-baNZyqaaLhyLVKm/DlvdW051MSgO6b8eVfIezl9E5PqWxFgzLm/wQntEW4zOytVburDEr0JlALEpdOFwvErLsg==} - dev: false + astral-regex@2.0.0: {} - /available-typed-arrays@1.0.7: - resolution: {integrity: sha512-wvUjBtSGN7+7SjNpq/9M2Tg350UZD3q62IFZLbRAR1bSMlCo1ZaeW+BJ+D090e4hIIZLBcTDWe4Mh4jvUDajzQ==} - engines: {node: '>= 0.4'} + async@3.2.5: {} + + available-typed-arrays@1.0.7: dependencies: possible-typed-array-names: 1.0.0 - dev: false - /balanced-match@1.0.2: - resolution: {integrity: sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==} + balanced-match@1.0.2: {} - /binary-extensions@2.3.0: - resolution: {integrity: sha512-Ceh+7ox5qe7LJuLHoY0feh3pHuUDHAcRUeyL2VYghZwfpkNIy/+8Ocg0a3UuSoYzavmylwuLWQOf3hl0jjMMIw==} - engines: {node: '>=8'} - dev: true + base64-js@1.5.1: {} - /block-stream2@2.1.0: - resolution: {integrity: sha512-suhjmLI57Ewpmq00qaygS8UgEq2ly2PCItenIyhMqVjo4t4pGzqMvfgJuX8iWTeSDdfSSqS6j38fL4ToNL7Pfg==} + binary-extensions@2.3.0: {} + + bl@4.1.0: + dependencies: + buffer: 5.7.1 + inherits: 2.0.4 + readable-stream: 3.6.2 + + block-stream2@2.1.0: dependencies: readable-stream: 3.6.2 - dev: false - /bn.js@4.12.0: - resolution: {integrity: sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA==} - dev: false + bn.js@4.12.0: {} - /body-parser@1.20.2: - resolution: {integrity: sha512-ml9pReCu3M61kGlqoTm2umSXTlRTuGTx0bfYj+uIUKKYycG5NtSbeetV3faSU6R7ajOPw0g/J1PvK4qNy7s5bA==} - engines: {node: '>= 0.8', npm: 1.2.8000 || >= 1.4.16} + body-parser@1.20.2: dependencies: bytes: 3.1.2 content-type: 1.0.5 @@ -743,55 +2823,70 @@ packages: unpipe: 1.0.0 transitivePeerDependencies: - supports-color - dev: false - /brace-expansion@1.1.11: - resolution: {integrity: sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==} + brace-expansion@1.1.11: dependencies: balanced-match: 1.0.2 concat-map: 0.0.1 - dev: true - /brace-expansion@2.0.1: - resolution: {integrity: sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==} + brace-expansion@2.0.1: dependencies: balanced-match: 1.0.2 - dev: false - /braces@3.0.2: - resolution: {integrity: sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==} - engines: {node: '>=8'} + braces@3.0.2: dependencies: fill-range: 7.0.1 - dev: true - /browser-or-node@2.1.1: - resolution: {integrity: sha512-8CVjaLJGuSKMVTxJ2DpBl5XnlNDiT4cQFeuCJJrvJmts9YrTZDizTX7PjC2s6W4x+MBGZeEY6dGMrF04/6Hgqg==} - dev: false + braces@3.0.3: + dependencies: + fill-range: 7.1.1 - /buffer-crc32@0.2.13: - resolution: {integrity: sha512-VO9Ht/+p3SN7SKWqcrgEzjGbRSJYTx+Q1pTQC0wrWqHx0vpJraQ6GtHx8tvcg1rlK1byhU5gccxgOgj7B0TDkQ==} - dev: false + browser-or-node@2.1.1: {} - /bytes@3.1.2: - resolution: {integrity: sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==} - engines: {node: '>= 0.8'} - dev: false + buffer-crc32@0.2.13: {} - /call-bind@1.0.7: - resolution: {integrity: sha512-GHTSNSYICQ7scH7sZ+M2rFopRoLh8t2bLSW6BbgrtLsahOIB5iyAVJf9GjWK3cYTDaMj4XdBpM1cA6pIS0Kv2w==} - engines: {node: '>= 0.4'} + buffer@5.7.1: + dependencies: + base64-js: 1.5.1 + ieee754: 1.2.1 + + bytes@3.1.2: {} + + call-bind@1.0.7: dependencies: es-define-property: 1.0.0 es-errors: 1.3.0 function-bind: 1.1.2 get-intrinsic: 1.2.4 set-function-length: 1.2.2 - dev: false - /chokidar@3.6.0: - resolution: {integrity: sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw==} - engines: {node: '>= 8.10.0'} + chalk@2.4.2: + dependencies: + ansi-styles: 3.2.1 + escape-string-regexp: 1.0.5 + supports-color: 5.5.0 + + checkpoint-client@1.1.27: + dependencies: + ci-info: 3.8.0 + env-paths: 2.2.1 + make-dir: 4.0.0 + ms: 2.1.3 + node-fetch: 2.6.12 + uuid: 9.0.0 + transitivePeerDependencies: + - encoding + + chevrotain@10.5.0: + dependencies: + '@chevrotain/cst-dts-gen': 10.5.0 + '@chevrotain/gast': 10.5.0 + '@chevrotain/types': 10.5.0 + '@chevrotain/utils': 10.5.0 + lodash: 4.17.21 + regexp-to-ast: 0.5.0 + + chokidar@3.6.0: dependencies: anymatch: 3.1.3 braces: 3.0.2 @@ -802,197 +2897,171 @@ packages: readdirp: 3.6.0 optionalDependencies: fsevents: 2.3.3 - dev: true - /cliui@8.0.1: - resolution: {integrity: sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==} - engines: {node: '>=12'} + ci-info@3.8.0: {} + + clean-stack@2.2.0: {} + + cli-truncate@2.1.0: + dependencies: + slice-ansi: 3.0.0 + string-width: 4.2.3 + + cliui@8.0.1: dependencies: string-width: 4.2.3 strip-ansi: 6.0.1 wrap-ansi: 7.0.0 - dev: false - /color-convert@2.0.1: - resolution: {integrity: sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==} - engines: {node: '>=7.0.0'} + color-convert@1.9.3: + dependencies: + color-name: 1.1.3 + + color-convert@2.0.1: dependencies: color-name: 1.1.4 - dev: false - /color-name@1.1.4: - resolution: {integrity: sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==} - dev: false + color-name@1.1.3: {} - /concat-map@0.0.1: - resolution: {integrity: sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==} - dev: true + color-name@1.1.4: {} - /content-disposition@0.5.4: - resolution: {integrity: sha512-FveZTNuGw04cxlAiWbzi6zTAL/lhehaWbTtgluJh4/E95DqMwTmha3KZN1aAWA8cFIhHzMZUvLevkw5Rqk+tSQ==} - engines: {node: '>= 0.6'} + commondir@1.0.1: {} + + compress-commons@4.1.2: + dependencies: + buffer-crc32: 0.2.13 + crc32-stream: 4.0.3 + normalize-path: 3.0.0 + readable-stream: 3.6.2 + + concat-map@0.0.1: {} + + content-disposition@0.5.4: dependencies: safe-buffer: 5.2.1 - dev: false - /content-type@1.0.5: - resolution: {integrity: sha512-nTjqfcBFEipKdXCv4YDQWCfmcLZKm81ldF0pAopTvyrFGVbcR6P/VAAd5G7N+0tTr8QqiU0tFadD6FK4NtJwOA==} - engines: {node: '>= 0.6'} - dev: false + content-type@1.0.5: {} - /cookie-signature@1.0.6: - resolution: {integrity: sha512-QADzlaHc8icV8I7vbaJXJwod9HWYp8uCqf1xa4OfNu1T7JVxQIrUgOWtHdNDtPiywmFbiS12VjotIXLrKM3orQ==} - dev: false + cookie-signature@1.0.6: {} - /cookie@0.6.0: - resolution: {integrity: sha512-U71cyTamuh1CRNCfpGY6to28lxvNwPG4Guz/EVjgf3Jmzv0vlDp1atT9eS5dDjMYHucpHbWns6Lwf3BKz6svdw==} - engines: {node: '>= 0.6'} - dev: false + cookie@0.6.0: {} - /cors@2.8.5: - resolution: {integrity: sha512-KIHbLJqu73RGr/hnbrO9uBeixNGuvSQjul/jdFvS/KFSIH1hWVd1ng7zOHx+YrEfInLG7q4n6GHQ9cDtxv/P6g==} - engines: {node: '>= 0.10'} + core-util-is@1.0.3: {} + + cors@2.8.5: dependencies: object-assign: 4.1.1 vary: 1.1.2 - dev: false - /create-require@1.1.1: - resolution: {integrity: sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ==} - dev: true + crc-32@1.2.2: {} - /cross-spawn@7.0.3: - resolution: {integrity: sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==} - engines: {node: '>= 8'} + crc32-stream@4.0.3: + dependencies: + crc-32: 1.2.2 + readable-stream: 3.6.2 + + create-require@1.1.1: {} + + cross-spawn@7.0.3: dependencies: path-key: 3.1.1 shebang-command: 2.0.0 which: 2.0.2 - dev: false - /data-view-buffer@1.0.1: - resolution: {integrity: sha512-0lht7OugA5x3iJLOWFhWK/5ehONdprk0ISXqVFn/NFrDu+cuc8iADFrGQz5BnRK7LLU3JmkbXSxaqX+/mXYtUA==} - engines: {node: '>= 0.4'} + crypto-random-string@2.0.0: {} + + data-view-buffer@1.0.1: dependencies: call-bind: 1.0.7 es-errors: 1.3.0 is-data-view: 1.0.1 - dev: false - /data-view-byte-length@1.0.1: - resolution: {integrity: sha512-4J7wRJD3ABAzr8wP+OcIcqq2dlUKp4DVflx++hs5h5ZKydWMI6/D/fAot+yh6g2tHh8fLFTvNOaVN357NvSrOQ==} - engines: {node: '>= 0.4'} + data-view-byte-length@1.0.1: dependencies: call-bind: 1.0.7 es-errors: 1.3.0 is-data-view: 1.0.1 - dev: false - /data-view-byte-offset@1.0.0: - resolution: {integrity: sha512-t/Ygsytq+R995EJ5PZlD4Cu56sWa8InXySaViRzw9apusqsOO2bQP+SbYzAhR0pFKoB+43lYy8rWban9JSuXnA==} - engines: {node: '>= 0.4'} + data-view-byte-offset@1.0.0: dependencies: call-bind: 1.0.7 es-errors: 1.3.0 is-data-view: 1.0.1 - dev: false - /debug@2.6.9: - resolution: {integrity: sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==} - peerDependencies: - supports-color: '*' - peerDependenciesMeta: - supports-color: - optional: true + debug@2.6.9: dependencies: ms: 2.0.0 - dev: false - /debug@4.3.4(supports-color@5.5.0): - resolution: {integrity: sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==} - engines: {node: '>=6.0'} - peerDependencies: - supports-color: '*' - peerDependenciesMeta: - supports-color: - optional: true + debug@4.3.4(supports-color@5.5.0): dependencies: ms: 2.1.2 + optionalDependencies: supports-color: 5.5.0 - /decode-uri-component@0.2.2: - resolution: {integrity: sha512-FqUYQ+8o158GyGTrMFJms9qh3CqTKvAqgqsTnkLI8sKu0028orqBhxNMFkFen0zGyg6epACD32pjVk58ngIErQ==} - engines: {node: '>=0.10'} - dev: false + decode-uri-component@0.2.2: {} - /define-data-property@1.1.4: - resolution: {integrity: sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A==} - engines: {node: '>= 0.4'} + define-data-property@1.1.4: dependencies: es-define-property: 1.0.0 es-errors: 1.3.0 gopd: 1.0.1 - dev: false - /define-properties@1.2.1: - resolution: {integrity: sha512-8QmQKqEASLd5nx0U1B1okLElbUuuttJ/AnYmRXbbbGDWh6uS208EjD4Xqq/I9wK7u0v6O08XhTWnt5XtEbR6Dg==} - engines: {node: '>= 0.4'} + define-properties@1.2.1: dependencies: define-data-property: 1.1.4 has-property-descriptors: 1.0.2 object-keys: 1.1.1 - dev: false - /depd@2.0.0: - resolution: {integrity: sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==} - engines: {node: '>= 0.8'} - dev: false + del@6.1.1: + dependencies: + globby: 11.1.0 + graceful-fs: 4.2.11 + is-glob: 4.0.3 + is-path-cwd: 2.2.0 + is-path-inside: 3.0.3 + p-map: 4.0.0 + rimraf: 3.0.2 + slash: 3.0.0 - /destroy@1.2.0: - resolution: {integrity: sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg==} - engines: {node: '>= 0.8', npm: 1.2.8000 || >= 1.4.16} - dev: false + depd@2.0.0: {} - /diff@4.0.2: - resolution: {integrity: sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==} - engines: {node: '>=0.3.1'} - dev: true + destroy@1.2.0: {} - /dotenv@16.4.5: - resolution: {integrity: sha512-ZmdL2rui+eB2YwhsWzjInR8LldtZHGDoQ1ugH85ppHKwpUHL7j7rN0Ti9NCnGiQbhaZ11FpR+7ao1dNsmduNUg==} - engines: {node: '>=12'} - dev: false + diff@4.0.2: {} - /eastasianwidth@0.2.0: - resolution: {integrity: sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==} - dev: false + dir-glob@3.0.1: + dependencies: + path-type: 4.0.0 - /ecdsa-sig-formatter@1.0.11: - resolution: {integrity: sha512-nagl3RYrbNv6kQkeJIpt6NJZy8twLB/2vtz6yN9Z4vRKHN4/QZJIEbqohALSgwKdnksuY3k5Addp5lg8sVoVcQ==} + dotenv@16.0.3: {} + + dotenv@16.4.5: {} + + eastasianwidth@0.2.0: {} + + ecdsa-sig-formatter@1.0.11: dependencies: safe-buffer: 5.2.1 - dev: false - /ee-first@1.1.1: - resolution: {integrity: sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==} - dev: false + ee-first@1.1.1: {} - /emoji-regex@8.0.0: - resolution: {integrity: sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==} - dev: false + emoji-regex@8.0.0: {} - /emoji-regex@9.2.2: - resolution: {integrity: sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==} - dev: false + emoji-regex@9.2.2: {} - /encodeurl@1.0.2: - resolution: {integrity: sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w==} - engines: {node: '>= 0.8'} - dev: false + encodeurl@1.0.2: {} - /es-abstract@1.23.3: - resolution: {integrity: sha512-e+HfNH61Bj1X9/jLc5v1owaLYuHdeHHSQlkhCBiTK8rBvKaULl/beGMxwrMXjpYrv4pz22BlY570vVePA2ho4A==} - engines: {node: '>= 0.4'} + end-of-stream@1.4.4: + dependencies: + once: 1.4.0 + + env-paths@2.2.1: {} + + error-ex@1.3.2: + dependencies: + is-arrayish: 0.2.1 + + es-abstract@1.23.3: dependencies: array-buffer-byte-length: 1.0.1 arraybuffer.prototype.slice: 1.0.3 @@ -1040,11 +3109,8 @@ packages: typed-array-length: 1.0.6 unbox-primitive: 1.0.2 which-typed-array: 1.1.15 - dev: false - /es-aggregate-error@1.0.13: - resolution: {integrity: sha512-KkzhUUuD2CUMqEc8JEqsXEMDHzDPE8RCjZeUBitsnB1eNcAJWQPiciKsMXe3Yytj4Flw1XLl46Qcf9OxvZha7A==} - engines: {node: '>= 0.4'} + es-aggregate-error@1.0.13: dependencies: define-data-property: 1.1.4 define-properties: 1.2.1 @@ -1054,26 +3120,16 @@ packages: globalthis: 1.0.3 has-property-descriptors: 1.0.2 set-function-name: 2.0.2 - dev: false - /es-array-method-boxes-properly@1.0.0: - resolution: {integrity: sha512-wd6JXUmyHmt8T5a2xreUwKcGPq6f1f+WwIJkijUqiGcJz1qqnZgP6XIK+QyIWU5lT7imeNxUll48bziG+TSYcA==} - dev: false + es-array-method-boxes-properly@1.0.0: {} - /es-define-property@1.0.0: - resolution: {integrity: sha512-jxayLKShrEqqzJ0eumQbVhTYQM27CfT1T35+gCgDFoL82JLsXqTJ76zv6A0YLOgEnLUMvLzsDsGIrl8NFpT2gQ==} - engines: {node: '>= 0.4'} + es-define-property@1.0.0: dependencies: get-intrinsic: 1.2.4 - dev: false - /es-errors@1.3.0: - resolution: {integrity: sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==} - engines: {node: '>= 0.4'} - dev: false + es-errors@1.3.0: {} - /es-get-iterator@1.1.3: - resolution: {integrity: sha512-sPZmqHBe6JIiTfN5q2pEi//TwxmAFHwj/XEuYjTuse78i8KxaqMTTzxPoFKuzRpDpTJ+0NAbpfenkmH2rePtuw==} + es-get-iterator@1.1.3: dependencies: call-bind: 1.0.7 get-intrinsic: 1.2.4 @@ -1084,50 +3140,46 @@ packages: is-string: 1.0.7 isarray: 2.0.5 stop-iteration-iterator: 1.0.0 - dev: false - /es-object-atoms@1.0.0: - resolution: {integrity: sha512-MZ4iQ6JwHOBQjahnjwaC1ZtIBH+2ohjamzAO3oaHcXYup7qxjF2fixyH+Q71voWHeOkI2q/TnJao/KfXYIZWbw==} - engines: {node: '>= 0.4'} + es-object-atoms@1.0.0: dependencies: es-errors: 1.3.0 - dev: false - /es-set-tostringtag@2.0.3: - resolution: {integrity: sha512-3T8uNMC3OQTHkFUsFq8r/BwAXLHvU/9O9mE0fBc/MY5iq/8H7ncvO947LmYA6ldWw9Uh8Yhf25zu6n7nML5QWQ==} - engines: {node: '>= 0.4'} + es-set-tostringtag@2.0.3: dependencies: get-intrinsic: 1.2.4 has-tostringtag: 1.0.2 hasown: 2.0.2 - dev: false - /es-to-primitive@1.2.1: - resolution: {integrity: sha512-QCOllgZJtaUo9miYBcLChTUaHNjJF3PYs1VidD7AwiEj1kYxKeQTctLAezAOH5ZKRH0g2IgPn6KwB4IT8iRpvA==} - engines: {node: '>= 0.4'} + es-to-primitive@1.2.1: dependencies: is-callable: 1.2.7 is-date-object: 1.0.5 is-symbol: 1.0.4 - dev: false - /escalade@3.1.2: - resolution: {integrity: sha512-ErCHMCae19vR8vQGe50xIsVomy19rg6gFu3+r3jkEO46suLMWBksvVyoGgQV+jOfl84ZSOSlmv6Gxa89PmTGmA==} - engines: {node: '>=6'} - dev: false + escalade@3.1.2: {} - /escape-html@1.0.3: - resolution: {integrity: sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==} - dev: false + escape-html@1.0.3: {} - /etag@1.8.1: - resolution: {integrity: sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg==} - engines: {node: '>= 0.6'} - dev: false + escape-string-regexp@1.0.5: {} - /express@4.19.2: - resolution: {integrity: sha512-5T6nhjsT+EOMzuck8JjBHARTHfMht0POzlA60WV2pMD3gyXw2LZnZ+ueGdNxG+0calOJcWKbpFcuzLZ91YWq9Q==} - engines: {node: '>= 0.10.0'} + escape-string-regexp@4.0.0: {} + + etag@1.8.1: {} + + execa@5.1.1: + dependencies: + cross-spawn: 7.0.3 + get-stream: 6.0.1 + human-signals: 2.1.0 + is-stream: 2.0.1 + merge-stream: 2.0.0 + npm-run-path: 4.0.1 + onetime: 5.1.2 + signal-exit: 3.0.7 + strip-final-newline: 2.0.0 + + express@4.19.2: dependencies: accepts: 1.3.8 array-flatten: 1.1.1 @@ -1162,40 +3214,41 @@ packages: vary: 1.1.2 transitivePeerDependencies: - supports-color - dev: false - /fast-jwt@4.0.0: - resolution: {integrity: sha512-CnI93Tmk7eSzfw4e0Jlc5ZcWiN+/zK7xAKAhtXS8PAcKmYqfcXqxJl1hMyhk3iEt0M9JLo7DCYRDV2XcIacWAw==} - engines: {node: '>=16 <22'} + fast-glob@3.3.2: + dependencies: + '@nodelib/fs.stat': 2.0.5 + '@nodelib/fs.walk': 1.2.8 + glob-parent: 5.1.2 + merge2: 1.4.1 + micromatch: 4.0.7 + + fast-jwt@4.0.0: dependencies: '@lukeed/ms': 2.0.2 asn1.js: 5.4.1 ecdsa-sig-formatter: 1.0.11 mnemonist: 0.39.8 - dev: false - /fast-xml-parser@4.3.6: - resolution: {integrity: sha512-M2SovcRxD4+vC493Uc2GZVcZaj66CCJhWurC4viynVSTvrpErCShNcDz1lAho6n9REQKvL/ll4A4/fw6Y9z8nw==} - hasBin: true + fast-xml-parser@4.3.6: dependencies: strnum: 1.0.5 - dev: false - /fill-range@7.0.1: - resolution: {integrity: sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==} - engines: {node: '>=8'} + fastq@1.17.1: + dependencies: + reusify: 1.0.4 + + fill-range@7.0.1: dependencies: to-regex-range: 5.0.1 - dev: true - /filter-obj@1.1.0: - resolution: {integrity: sha512-8rXg1ZnX7xzy2NGDVkBVaAy+lSlPNwad13BtgSlLuxfIslyt5Vg64U7tFcCt4WS1R0hvtnQybT/IyCkGZ3DpXQ==} - engines: {node: '>=0.10.0'} - dev: false + fill-range@7.1.1: + dependencies: + to-regex-range: 5.0.1 - /finalhandler@1.2.0: - resolution: {integrity: sha512-5uXcUVftlQMFnWC9qu/svkWv3GTd2PfUhK/3PLkYNAe7FbqJMt3515HaxE6eRL74GdsriiwujiawdaB1BpEISg==} - engines: {node: '>= 0.8'} + filter-obj@1.1.0: {} + + finalhandler@1.2.0: dependencies: debug: 2.6.9 encodeurl: 1.0.2 @@ -1206,132 +3259,143 @@ packages: unpipe: 1.0.0 transitivePeerDependencies: - supports-color - dev: false - /for-each@0.3.3: - resolution: {integrity: sha512-jqYfLp7mo9vIyQf8ykW2v7A+2N4QjeCeI5+Dz9XraiO1ign81wjiH7Fb9vSOWvQfNtmSa4H2RoQTrrXivdUZmw==} + find-cache-dir@3.3.2: + dependencies: + commondir: 1.0.1 + make-dir: 3.1.0 + pkg-dir: 4.2.0 + + find-up@4.1.0: + dependencies: + locate-path: 5.0.0 + path-exists: 4.0.0 + + find-up@5.0.0: + dependencies: + locate-path: 6.0.0 + path-exists: 4.0.0 + + for-each@0.3.3: dependencies: is-callable: 1.2.7 - dev: false - /foreground-child@3.1.1: - resolution: {integrity: sha512-TMKDUnIte6bfb5nWv7V/caI169OHgvwjb7V4WkeUvbQQdjr5rWKqHFiKWb/fcOwB+CzBT+qbWjvj+DVwRskpIg==} - engines: {node: '>=14'} + foreground-child@3.1.1: dependencies: cross-spawn: 7.0.3 signal-exit: 4.1.0 - dev: false - /forwarded@0.2.0: - resolution: {integrity: sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow==} - engines: {node: '>= 0.6'} - dev: false + forwarded@0.2.0: {} - /fresh@0.5.2: - resolution: {integrity: sha512-zJ2mQYM18rEFOudeV4GShTGIQ7RbzA7ozbU9I/XBpm7kqgMywgmylMwXHxZJmkVoYkna9d2pVXVXPdYTP9ej8Q==} - engines: {node: '>= 0.6'} - dev: false + fp-ts@2.16.1: {} - /fs-extra@11.2.0: - resolution: {integrity: sha512-PmDi3uwK5nFuXh7XDTlVnS17xJS7vW36is2+w3xcv8SVxiB4NyATf4ctkVY5bkSjX0Y4nbvZCq1/EjtEyr9ktw==} - engines: {node: '>=14.14'} + fresh@0.5.2: {} + + fs-constants@1.0.0: {} + + fs-extra@11.1.1: dependencies: graceful-fs: 4.2.11 jsonfile: 6.1.0 universalify: 2.0.1 - dev: false - /fsevents@2.3.3: - resolution: {integrity: sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==} - engines: {node: ^8.16.0 || ^10.6.0 || >=11.0.0} - os: [darwin] - requiresBuild: true - dev: true + fs-extra@11.2.0: + dependencies: + graceful-fs: 4.2.11 + jsonfile: 6.1.0 + universalify: 2.0.1 + + fs-jetpack@5.1.0: + dependencies: + minimatch: 5.1.6 + + fs.realpath@1.0.0: {} + + fsevents@2.3.3: optional: true - /function-bind@1.1.2: - resolution: {integrity: sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==} - dev: false + function-bind@1.1.2: {} - /function.prototype.name@1.1.6: - resolution: {integrity: sha512-Z5kx79swU5P27WEayXM1tBi5Ze/lbIyiNgU3qyXUOf9b2rgXYyF9Dy9Cx+IQv/Lc8WCG6L82zwUPpSS9hGehIg==} - engines: {node: '>= 0.4'} + function.prototype.name@1.1.6: dependencies: call-bind: 1.0.7 define-properties: 1.2.1 es-abstract: 1.23.3 functions-have-names: 1.2.3 - dev: false - /functions-have-names@1.2.3: - resolution: {integrity: sha512-xckBUXyTIqT97tq2x2AMb+g163b5JFysYk0x4qxNFwbfQkmNZoiRHb6sPzI9/QV33WeuvVYBUIiD4NzNIyqaRQ==} - dev: false + functions-have-names@1.2.3: {} - /get-caller-file@2.0.5: - resolution: {integrity: sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==} - engines: {node: 6.* || 8.* || >= 10.*} - dev: false + get-caller-file@2.0.5: {} - /get-intrinsic@1.2.4: - resolution: {integrity: sha512-5uYhsJH8VJBTv7oslg4BznJYhDoRI6waYCxMmCdnTrcCrHA/fCFKoTFz2JKKE0HdDFUF7/oQuhzumXJK7paBRQ==} - engines: {node: '>= 0.4'} + get-intrinsic@1.2.4: dependencies: es-errors: 1.3.0 function-bind: 1.1.2 has-proto: 1.0.3 has-symbols: 1.0.3 hasown: 2.0.2 - dev: false - /get-symbol-description@1.0.2: - resolution: {integrity: sha512-g0QYk1dZBxGwk+Ngc+ltRH2IBp2f7zBkBMBJZCDerh6EhlhSR6+9irMCuT/09zD6qkarHUSn529sK/yL4S27mg==} - engines: {node: '>= 0.4'} + get-stream@6.0.1: {} + + get-symbol-description@1.0.2: dependencies: call-bind: 1.0.7 es-errors: 1.3.0 get-intrinsic: 1.2.4 - dev: false - /glob-parent@5.1.2: - resolution: {integrity: sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==} - engines: {node: '>= 6'} + glob-parent@5.1.2: dependencies: is-glob: 4.0.3 - dev: true - /glob@10.3.12: - resolution: {integrity: sha512-TCNv8vJ+xz4QiqTpfOJA7HvYv+tNIRHKfUWw/q+v2jdgN4ebz+KY9tGx5J4rHP0o84mNP+ApH66HRX8us3Khqg==} - engines: {node: '>=16 || 14 >=14.17'} - hasBin: true + glob@10.3.12: dependencies: foreground-child: 3.1.1 jackspeak: 2.3.6 minimatch: 9.0.4 minipass: 7.0.4 path-scurry: 1.10.2 - dev: false - /globalthis@1.0.3: - resolution: {integrity: sha512-sFdI5LyBiNTHjRd7cGPWapiHWMOXKyuBNX/cWJ3NfzrZQVa8GI/8cofCl74AOVqq9W5kNmguTIzJ/1s2gyI9wA==} - engines: {node: '>= 0.4'} + glob@7.2.3: + dependencies: + fs.realpath: 1.0.0 + inflight: 1.0.6 + inherits: 2.0.4 + minimatch: 3.1.2 + once: 1.4.0 + path-is-absolute: 1.0.1 + + glob@8.1.0: + dependencies: + fs.realpath: 1.0.0 + inflight: 1.0.6 + inherits: 2.0.4 + minimatch: 5.1.6 + once: 1.4.0 + + global-dirs@3.0.1: + dependencies: + ini: 2.0.0 + + globalthis@1.0.3: dependencies: define-properties: 1.2.1 - dev: false - /gopd@1.0.1: - resolution: {integrity: sha512-d65bNlIadxvpb/A2abVdlqKqV563juRnZ1Wtk6s1sIR8uNsXR70xqIzVqxVf1eTqDunwT2MkczEeaezCKTZhwA==} + globby@11.1.0: + dependencies: + array-union: 2.1.0 + dir-glob: 3.0.1 + fast-glob: 3.3.2 + ignore: 5.3.1 + merge2: 1.4.1 + slash: 3.0.0 + + gopd@1.0.1: dependencies: get-intrinsic: 1.2.4 - dev: false - /graceful-fs@4.2.11: - resolution: {integrity: sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==} - dev: false + graceful-fs@4.2.11: {} - /handlebars@4.7.8: - resolution: {integrity: sha512-vafaFqs8MZkRrSX7sFVUdo3ap/eNiLnb4IakshzvP56X5Nr1iGKAIqdX6tMlm6HcNRIkr6AxO5jFEoJzzpT8aQ==} - engines: {node: '>=0.4.7'} - hasBin: true + handlebars@4.7.8: dependencies: minimist: 1.2.8 neo-async: 2.6.2 @@ -1339,378 +3403,332 @@ packages: wordwrap: 1.0.0 optionalDependencies: uglify-js: 3.17.4 - dev: false - /has-bigints@1.0.2: - resolution: {integrity: sha512-tSvCKtBr9lkF0Ex0aQiP9N+OpV4zi2r/Nee5VkRDbaqv35RLYMzbwQfFSZZH0kR+Rd6302UJZ2p/bJCEoR3VoQ==} - dev: false + has-bigints@1.0.2: {} - /has-flag@3.0.0: - resolution: {integrity: sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==} - engines: {node: '>=4'} + has-flag@3.0.0: {} - /has-property-descriptors@1.0.2: - resolution: {integrity: sha512-55JNKuIW+vq4Ke1BjOTjM2YctQIvCT7GFzHwmfZPGo5wnrgkid0YQtnAleFSqumZm4az3n2BS+erby5ipJdgrg==} + has-flag@4.0.0: {} + + has-property-descriptors@1.0.2: dependencies: es-define-property: 1.0.0 - dev: false - /has-proto@1.0.3: - resolution: {integrity: sha512-SJ1amZAJUiZS+PhsVLf5tGydlaVB8EdFpaSO4gmiUKUOxk8qzn5AIy4ZeJUmh22znIdk/uMAUT2pl3FxzVUH+Q==} - engines: {node: '>= 0.4'} - dev: false + has-proto@1.0.3: {} - /has-symbols@1.0.3: - resolution: {integrity: sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==} - engines: {node: '>= 0.4'} - dev: false + has-symbols@1.0.3: {} - /has-tostringtag@1.0.2: - resolution: {integrity: sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw==} - engines: {node: '>= 0.4'} + has-tostringtag@1.0.2: dependencies: has-symbols: 1.0.3 - dev: false - /hasown@2.0.2: - resolution: {integrity: sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==} - engines: {node: '>= 0.4'} + hasha@5.2.2: + dependencies: + is-stream: 2.0.1 + type-fest: 0.8.1 + + hasown@2.0.2: dependencies: function-bind: 1.1.2 - dev: false - /hpagent@1.2.0: - resolution: {integrity: sha512-A91dYTeIB6NoXG+PxTQpCCDDnfHsW9kc06Lvpu1TEe9gnd6ZFeiBoRO9JvzEv6xK7EX97/dUE8g/vBMTqTS3CA==} - engines: {node: '>=14'} - dev: false + hosted-git-info@2.8.9: {} - /http-errors@2.0.0: - resolution: {integrity: sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ==} - engines: {node: '>= 0.8'} + hpagent@1.2.0: {} + + http-errors@2.0.0: dependencies: depd: 2.0.0 inherits: 2.0.4 setprototypeof: 1.2.0 statuses: 2.0.1 toidentifier: 1.0.1 - dev: false - /iconv-lite@0.4.24: - resolution: {integrity: sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==} - engines: {node: '>=0.10.0'} + http-proxy-agent@7.0.0: + dependencies: + agent-base: 7.1.1 + debug: 4.3.4(supports-color@5.5.0) + transitivePeerDependencies: + - supports-color + + https-proxy-agent@7.0.2: + dependencies: + agent-base: 7.1.1 + debug: 4.3.4(supports-color@5.5.0) + transitivePeerDependencies: + - supports-color + + human-signals@2.1.0: {} + + iconv-lite@0.4.24: dependencies: safer-buffer: 2.1.2 - dev: false - /ignore-by-default@1.0.1: - resolution: {integrity: sha512-Ius2VYcGNk7T90CppJqcIkS5ooHUZyIQK+ClZfMfMNFEF9VSE73Fq+906u/CWu92x4gzZMWOwfFYckPObzdEbA==} - dev: true + ieee754@1.2.1: {} - /inherits@2.0.4: - resolution: {integrity: sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==} - dev: false + ignore-by-default@1.0.1: {} - /internal-slot@1.0.7: - resolution: {integrity: sha512-NGnrKwXzSms2qUUih/ILZ5JBqNTSa1+ZmP6flaIp6KmSElgE9qdndzS3cqjrDovwFdmwsGsLdeFgB6suw+1e9g==} - engines: {node: '>= 0.4'} + ignore-walk@5.0.1: + dependencies: + minimatch: 5.1.6 + + ignore@5.3.1: {} + + indent-string@4.0.0: {} + + inflight@1.0.6: + dependencies: + once: 1.4.0 + wrappy: 1.0.2 + + inherits@2.0.4: {} + + ini@2.0.0: {} + + internal-slot@1.0.7: dependencies: es-errors: 1.3.0 hasown: 2.0.2 side-channel: 1.0.6 - dev: false - /ipaddr.js@1.9.1: - resolution: {integrity: sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==} - engines: {node: '>= 0.10'} - dev: false + ipaddr.js@1.9.1: {} - /ipaddr.js@2.1.0: - resolution: {integrity: sha512-LlbxQ7xKzfBusov6UMi4MFpEg0m+mAm9xyNGEduwXMEDuf4WfzB/RZwMVYEd7IKGvh4IUkEXYxtAVu9T3OelJQ==} - engines: {node: '>= 10'} - dev: false + ipaddr.js@2.1.0: {} - /is-arguments@1.1.1: - resolution: {integrity: sha512-8Q7EARjzEnKpt/PCD7e1cgUS0a6X8u5tdSiMqXhojOdoV9TsMsiO+9VLC5vAmO8N7/GmXn7yjR8qnA6bVAEzfA==} - engines: {node: '>= 0.4'} + is-arguments@1.1.1: dependencies: call-bind: 1.0.7 has-tostringtag: 1.0.2 - dev: false - /is-array-buffer@3.0.4: - resolution: {integrity: sha512-wcjaerHw0ydZwfhiKbXJWLDY8A7yV7KhjQOpb83hGgGfId/aQa4TOvwyzn2PuswW2gPCYEL/nEAiSVpdOj1lXw==} - engines: {node: '>= 0.4'} + is-array-buffer@3.0.4: dependencies: call-bind: 1.0.7 get-intrinsic: 1.2.4 - dev: false - /is-bigint@1.0.4: - resolution: {integrity: sha512-zB9CruMamjym81i2JZ3UMn54PKGsQzsJeo6xvN3HJJ4CAsQNB6iRutp2To77OfCNuoxspsIhzaPoO1zyCEhFOg==} + is-arrayish@0.2.1: {} + + is-bigint@1.0.4: dependencies: has-bigints: 1.0.2 - dev: false - /is-binary-path@2.1.0: - resolution: {integrity: sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==} - engines: {node: '>=8'} + is-binary-path@2.1.0: dependencies: binary-extensions: 2.3.0 - dev: true - /is-boolean-object@1.1.2: - resolution: {integrity: sha512-gDYaKHJmnj4aWxyj6YHyXVpdQawtVLHU5cb+eztPGczf6cjuTdwve5ZIEfgXqH4e57An1D1AKf8CZ3kYrQRqYA==} - engines: {node: '>= 0.4'} + is-boolean-object@1.1.2: dependencies: call-bind: 1.0.7 has-tostringtag: 1.0.2 - dev: false - /is-callable@1.2.7: - resolution: {integrity: sha512-1BC0BVFhS/p0qtw6enp8e+8OD0UrK0oFLztSjNzhcKA3WDuJxxAPXzPuPtKkjEY9UUoEWlX/8fgKeu2S8i9JTA==} - engines: {node: '>= 0.4'} - dev: false + is-callable@1.2.7: {} - /is-data-view@1.0.1: - resolution: {integrity: sha512-AHkaJrsUVW6wq6JS8y3JnM/GJF/9cf+k20+iDzlSaJrinEo5+7vRiteOSwBhHRiAyQATN1AmY4hwzxJKPmYf+w==} - engines: {node: '>= 0.4'} + is-core-module@2.14.0: + dependencies: + hasown: 2.0.2 + + is-data-view@1.0.1: dependencies: is-typed-array: 1.1.13 - dev: false - /is-date-object@1.0.5: - resolution: {integrity: sha512-9YQaSxsAiSwcvS33MBk3wTCVnWK+HhF8VZR2jRxehM16QcVOdHqPn4VPHmRK4lSr38n9JriurInLcP90xsYNfQ==} - engines: {node: '>= 0.4'} + is-date-object@1.0.5: dependencies: has-tostringtag: 1.0.2 - dev: false - /is-extglob@2.1.1: - resolution: {integrity: sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==} - engines: {node: '>=0.10.0'} - dev: true + is-docker@2.2.1: {} - /is-fullwidth-code-point@3.0.0: - resolution: {integrity: sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==} - engines: {node: '>=8'} - dev: false + is-extglob@2.1.1: {} - /is-generator-function@1.0.10: - resolution: {integrity: sha512-jsEjy9l3yiXEQ+PsXdmBwEPcOxaXWLspKdplFUVI9vq1iZgIekeC0L167qeu86czQaxed3q/Uzuw0swL0irL8A==} - engines: {node: '>= 0.4'} + is-fullwidth-code-point@3.0.0: {} + + is-generator-function@1.0.10: dependencies: has-tostringtag: 1.0.2 - dev: false - /is-glob@4.0.3: - resolution: {integrity: sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==} - engines: {node: '>=0.10.0'} + is-glob@4.0.3: dependencies: is-extglob: 2.1.1 - dev: true - /is-map@2.0.3: - resolution: {integrity: sha512-1Qed0/Hr2m+YqxnM09CjA2d/i6YZNfF6R2oRAOj36eUdS6qIV/huPJNSEpKbupewFs+ZsJlxsjjPbc0/afW6Lw==} - engines: {node: '>= 0.4'} - dev: false + is-map@2.0.3: {} - /is-negative-zero@2.0.3: - resolution: {integrity: sha512-5KoIu2Ngpyek75jXodFvnafB6DJgr3u8uuK0LEZJjrU19DrMD3EVERaR8sjz8CCGgpZvxPl9SuE1GMVPFHx1mw==} - engines: {node: '>= 0.4'} - dev: false + is-negative-zero@2.0.3: {} - /is-number-object@1.0.7: - resolution: {integrity: sha512-k1U0IRzLMo7ZlYIfzRu23Oh6MiIFasgpb9X76eqfFZAqwH44UI4KTBvBYIZ1dSL9ZzChTB9ShHfLkR4pdW5krQ==} - engines: {node: '>= 0.4'} + is-number-object@1.0.7: dependencies: has-tostringtag: 1.0.2 - dev: false - /is-number@7.0.0: - resolution: {integrity: sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==} - engines: {node: '>=0.12.0'} - dev: true + is-number@7.0.0: {} - /is-regex@1.1.4: - resolution: {integrity: sha512-kvRdxDsxZjhzUX07ZnLydzS1TU/TJlTUHHY4YLL87e37oUA49DfkLqgy+VjFocowy29cKvcSiu+kIv728jTTVg==} - engines: {node: '>= 0.4'} + is-path-cwd@2.2.0: {} + + is-path-inside@3.0.3: {} + + is-regex@1.1.4: dependencies: call-bind: 1.0.7 has-tostringtag: 1.0.2 - dev: false - /is-set@2.0.3: - resolution: {integrity: sha512-iPAjerrse27/ygGLxw+EBR9agv9Y6uLeYVJMu+QNCoouJ1/1ri0mGrcWpfCqFZuzzx3WjtwxG098X+n4OuRkPg==} - engines: {node: '>= 0.4'} - dev: false + is-set@2.0.3: {} - /is-shared-array-buffer@1.0.3: - resolution: {integrity: sha512-nA2hv5XIhLR3uVzDDfCIknerhx8XUKnstuOERPNNIinXG7v9u+ohXF67vxm4TPTEPU6lm61ZkwP3c9PCB97rhg==} - engines: {node: '>= 0.4'} + is-shared-array-buffer@1.0.3: dependencies: call-bind: 1.0.7 - dev: false - /is-string@1.0.7: - resolution: {integrity: sha512-tE2UXzivje6ofPW7l23cjDOMa09gb7xlAqG6jG5ej6uPV32TlWP3NKPigtaGeHNu9fohccRYvIiZMfOOnOYUtg==} - engines: {node: '>= 0.4'} + is-stream@2.0.1: {} + + is-string@1.0.7: dependencies: has-tostringtag: 1.0.2 - dev: false - /is-symbol@1.0.4: - resolution: {integrity: sha512-C/CPBqKWnvdcxqIARxyOh4v1UUEOCHpgDa0WYgpKDFMszcrPcffg5uhwSgPCLD2WWxmq6isisz87tzT01tuGhg==} - engines: {node: '>= 0.4'} + is-symbol@1.0.4: dependencies: has-symbols: 1.0.3 - dev: false - /is-typed-array@1.1.13: - resolution: {integrity: sha512-uZ25/bUAlUY5fR4OKT4rZQEBrzQWYV9ZJYGGsUmEJ6thodVJ1HX64ePQ6Z0qPWP+m+Uq6e9UugrE38jeYsDSMw==} - engines: {node: '>= 0.4'} + is-typed-array@1.1.13: dependencies: which-typed-array: 1.1.15 - dev: false - /is-weakref@1.0.2: - resolution: {integrity: sha512-qctsuLZmIQ0+vSSMfoVvyFe2+GSEvnmZ2ezTup1SBse9+twCCeial6EEi3Nc2KFcf6+qz2FBPnjXsk8xhKSaPQ==} + is-weakref@1.0.2: dependencies: call-bind: 1.0.7 - dev: false - /is-what@4.1.16: - resolution: {integrity: sha512-ZhMwEosbFJkA0YhFnNDgTM4ZxDRsS6HqTo7qsZM08fehyRYIYa0yHu5R6mgo1n/8MgaPBXiPimPD77baVFYg+A==} - engines: {node: '>=12.13'} - dev: false + is-what@4.1.16: {} - /isarray@2.0.5: - resolution: {integrity: sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==} - dev: false + is-windows@1.0.2: {} - /isexe@2.0.0: - resolution: {integrity: sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==} - dev: false + is-wsl@2.2.0: + dependencies: + is-docker: 2.2.1 - /iterate-iterator@1.0.2: - resolution: {integrity: sha512-t91HubM4ZDQ70M9wqp+pcNpu8OyJ9UAtXntT/Bcsvp5tZMnz9vRa+IunKXeI8AnfZMTv0jNuVEmGeLSMjVvfPw==} - dev: false + isarray@1.0.0: {} - /iterate-value@1.0.2: - resolution: {integrity: sha512-A6fMAio4D2ot2r/TYzr4yUWrmwNdsN5xL7+HUiyACE4DXm+q8HtPcnFTp+NnW3k4N05tZ7FVYFFb2CR13NxyHQ==} + isarray@2.0.5: {} + + isexe@2.0.0: {} + + iterate-iterator@1.0.2: {} + + iterate-value@1.0.2: dependencies: es-get-iterator: 1.1.3 iterate-iterator: 1.0.2 - dev: false - /jackspeak@2.3.6: - resolution: {integrity: sha512-N3yCS/NegsOBokc8GAdM8UcmfsKiSS8cipheD/nivzr700H+nsMOxJjQnvwOcRYVuFkdH0wGUvW2WbXGmrZGbQ==} - engines: {node: '>=14'} + jackspeak@2.3.6: dependencies: '@isaacs/cliui': 8.0.2 optionalDependencies: '@pkgjs/parseargs': 0.11.0 - dev: false - /json-stream@1.0.0: - resolution: {integrity: sha512-H/ZGY0nIAg3QcOwE1QN/rK/Fa7gJn7Ii5obwp6zyPO4xiPNwpIMjqy2gwjBEGqzkF/vSWEIBQCBuN19hYiL6Qg==} - dev: false + js-tokens@4.0.0: {} - /jsonfile@6.1.0: - resolution: {integrity: sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==} + json-parse-even-better-errors@2.3.1: {} + + json-stream@1.0.0: {} + + jsonfile@6.1.0: dependencies: universalify: 2.0.1 optionalDependencies: graceful-fs: 4.2.11 - dev: false - /lodash@4.17.21: - resolution: {integrity: sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==} - dev: false + kleur@3.0.3: {} - /lru-cache@10.2.0: - resolution: {integrity: sha512-2bIM8x+VAf6JT4bKAljS1qUWgMsqZRPGJS6FSahIMPVvctcNhyVp7AJu7quxOW9jwkryBReKZY5tY5JYv2n/7Q==} - engines: {node: 14 || >=16.14} - dev: false + kleur@4.1.5: {} - /lru-cache@6.0.0: - resolution: {integrity: sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==} - engines: {node: '>=10'} + kysely@0.27.3: {} + + lazystream@1.0.1: + dependencies: + readable-stream: 2.3.8 + + lilconfig@2.1.0: {} + + lines-and-columns@1.2.4: {} + + locate-path@5.0.0: + dependencies: + p-locate: 4.1.0 + + locate-path@6.0.0: + dependencies: + p-locate: 5.0.0 + + lodash.defaults@4.2.0: {} + + lodash.difference@4.5.0: {} + + lodash.flatten@4.4.0: {} + + lodash.isplainobject@4.0.6: {} + + lodash.union@4.6.0: {} + + lodash@4.17.21: {} + + lru-cache@10.2.0: {} + + lru-cache@6.0.0: dependencies: yallist: 4.0.0 - dev: true - /make-error@1.3.6: - resolution: {integrity: sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw==} - dev: true + make-dir@3.1.0: + dependencies: + semver: 6.3.1 - /media-typer@0.3.0: - resolution: {integrity: sha512-dq+qelQ9akHpcOl/gUVRTxVIOkAJ1wR3QAvb4RsVjS8oVoFjDGTc679wJYmUmknUF5HwMLOgb5O+a3KxfWapPQ==} - engines: {node: '>= 0.6'} - dev: false + make-dir@4.0.0: + dependencies: + semver: 7.6.0 - /merge-anything@5.1.7: - resolution: {integrity: sha512-eRtbOb1N5iyH0tkQDAoQ4Ipsp/5qSR79Dzrz8hEPxRX10RWWR/iQXdoKmBSRCThY1Fh5EhISDtpSc93fpxUniQ==} - engines: {node: '>=12.13'} + make-error@1.3.6: {} + + media-typer@0.3.0: {} + + merge-anything@5.1.7: dependencies: is-what: 4.1.16 - dev: false - /merge-descriptors@1.0.1: - resolution: {integrity: sha512-cCi6g3/Zr1iqQi6ySbseM1Xvooa98N0w31jzUYrXPX2xqObmFGHJ0tQ5u74H3mVh7wLouTseZyYIq39g8cNp1w==} - dev: false + merge-descriptors@1.0.1: {} - /methods@1.1.2: - resolution: {integrity: sha512-iclAHeNqNm68zFtnZ0e+1L2yUIdvzNoauKU4WBA3VvH/vPFieF7qfRlwUZU+DA9P9bPXIS90ulxoUoCH23sV2w==} - engines: {node: '>= 0.6'} - dev: false + merge-stream@2.0.0: {} - /mime-db@1.52.0: - resolution: {integrity: sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==} - engines: {node: '>= 0.6'} - dev: false + merge2@1.4.1: {} - /mime-types@2.1.35: - resolution: {integrity: sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==} - engines: {node: '>= 0.6'} + methods@1.1.2: {} + + micromatch@4.0.7: + dependencies: + braces: 3.0.3 + picomatch: 2.3.1 + + mime-db@1.52.0: {} + + mime-types@2.1.35: dependencies: mime-db: 1.52.0 - dev: false - /mime@1.6.0: - resolution: {integrity: sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==} - engines: {node: '>=4'} - hasBin: true - dev: false + mime@1.6.0: {} - /mime@4.0.1: - resolution: {integrity: sha512-5lZ5tyrIfliMXzFtkYyekWbtRXObT9OWa8IwQ5uxTBDHucNNwniRqo0yInflj+iYi5CBa6qxadGzGarDfuEOxA==} - engines: {node: '>=16'} - hasBin: true + mime@4.0.1: {} - /minimalistic-assert@1.0.1: - resolution: {integrity: sha512-UtJcAD4yEaGtjPezWuO9wC4nwUnVH/8/Im3yEHQP4b67cXlD/Qr9hdITCU1xDbSEXg2XKNaP8jsReV7vQd00/A==} - dev: false + mimic-fn@2.1.0: {} - /minimatch@3.1.2: - resolution: {integrity: sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==} + min-indent@1.0.1: {} + + minimalistic-assert@1.0.1: {} + + minimatch@3.1.2: dependencies: brace-expansion: 1.1.11 - dev: true - /minimatch@9.0.4: - resolution: {integrity: sha512-KqWh+VchfxcMNRAJjj2tnsSJdNbHsVgnkBhTNrW7AjVo6OvLtxw8zfT9oLw1JSohlFzJ8jCoTgaoXvJ+kHt6fw==} - engines: {node: '>=16 || 14 >=14.17'} + minimatch@5.1.6: dependencies: brace-expansion: 2.0.1 - dev: false - /minimist@1.2.8: - resolution: {integrity: sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==} - dev: false + minimatch@9.0.4: + dependencies: + brace-expansion: 2.0.1 - /minio@7.1.3: - resolution: {integrity: sha512-xPrLjWkTT5E7H7VnzOjF//xBp9I40jYB4aWhb2xTFopXXfw+Wo82DDWngdUju7Doy3Wk7R8C4LAgwhLHHnf0wA==} - engines: {node: ^16 || ^18 || >=20} + minimist@1.2.8: {} + + minio@7.1.3: dependencies: async: 3.2.5 block-stream2: 2.1.0 @@ -1726,43 +3744,34 @@ packages: web-encoding: 1.1.5 xml: 1.0.1 xml2js: 0.5.0 - dev: false - /minipass@7.0.4: - resolution: {integrity: sha512-jYofLM5Dam9279rdkWzqHozUo4ybjdZmCsDHePy5V/PbBcVMiSZR97gmAy45aqi8CK1lG2ECd356FU86avfwUQ==} - engines: {node: '>=16 || 14 >=14.17'} - dev: false + minipass@7.0.4: {} - /mnemonist@0.39.8: - resolution: {integrity: sha512-vyWo2K3fjrUw8YeeZ1zF0fy6Mu59RHokURlld8ymdUPjMlD9EC9ov1/YPqTgqRvUN9nTr3Gqfz29LYAmu0PHPQ==} + mnemonist@0.39.8: dependencies: obliterator: 2.0.4 - dev: false - /ms@2.0.0: - resolution: {integrity: sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==} - dev: false + ms@2.0.0: {} - /ms@2.1.2: - resolution: {integrity: sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==} + ms@2.1.2: {} - /ms@2.1.3: - resolution: {integrity: sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==} - dev: false + ms@2.1.3: {} - /negotiator@0.6.3: - resolution: {integrity: sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg==} - engines: {node: '>= 0.6'} - dev: false + negotiator@0.6.3: {} - /neo-async@2.6.2: - resolution: {integrity: sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==} - dev: false + neo-async@2.6.2: {} - /nodemon@3.1.0: - resolution: {integrity: sha512-xqlktYlDMCepBJd43ZQhjWwMw2obW/JRvkrLxq5RCNcuDDX1DbcPT+qT1IlIIdf+DhnWs90JpTMe+Y5KxOchvA==} - engines: {node: '>=10'} - hasBin: true + new-github-issue-url@0.2.1: {} + + node-fetch@2.6.12: + dependencies: + whatwg-url: 5.0.0 + + node-fetch@2.7.0: + dependencies: + whatwg-url: 5.0.0 + + nodemon@3.1.3: dependencies: chokidar: 3.6.0 debug: 4.3.4(supports-color@5.5.0) @@ -1774,104 +3783,164 @@ packages: supports-color: 5.5.0 touch: 3.1.0 undefsafe: 2.0.5 - dev: true - /nopt@1.0.10: - resolution: {integrity: sha512-NWmpvLSqUrgrAC9HCuxEvb+PSloHpqVu+FqcO4eeF2h5qYRhA7ev6KvelyQAKtegUbC6RypJnlEOhd8vloNKYg==} - hasBin: true + nopt@1.0.10: dependencies: abbrev: 1.1.1 - dev: true - /normalize-path@3.0.0: - resolution: {integrity: sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==} - engines: {node: '>=0.10.0'} - dev: true + normalize-package-data@2.5.0: + dependencies: + hosted-git-info: 2.8.9 + resolve: 1.22.4 + semver: 5.7.2 + validate-npm-package-license: 3.0.4 - /object-assign@4.1.1: - resolution: {integrity: sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==} - engines: {node: '>=0.10.0'} - dev: false + normalize-path@3.0.0: {} - /object-inspect@1.13.1: - resolution: {integrity: sha512-5qoj1RUiKOMsCCNLV1CBiPYE10sziTsnmNxkAI/rZhiD63CF7IqdFGC/XzjWjpSgLf0LxXX3bDFIh0E18f6UhQ==} - dev: false + npm-bundled@2.0.1: + dependencies: + npm-normalize-package-bin: 2.0.0 - /object-keys@1.1.1: - resolution: {integrity: sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==} - engines: {node: '>= 0.4'} - dev: false + npm-normalize-package-bin@2.0.0: {} - /object.assign@4.1.5: - resolution: {integrity: sha512-byy+U7gp+FVwmyzKPYhW2h5l3crpmGsxl7X2s8y43IgxvG4g3QZ6CffDtsNQy1WsmZpQbO+ybo0AlW7TY6DcBQ==} - engines: {node: '>= 0.4'} + npm-packlist@5.1.3: + dependencies: + glob: 8.1.0 + ignore-walk: 5.0.1 + npm-bundled: 2.0.1 + npm-normalize-package-bin: 2.0.0 + + npm-run-path@4.0.1: + dependencies: + path-key: 3.1.1 + + object-assign@4.1.1: {} + + object-inspect@1.13.1: {} + + object-keys@1.1.1: {} + + object.assign@4.1.5: dependencies: call-bind: 1.0.7 define-properties: 1.2.1 has-symbols: 1.0.3 object-keys: 1.1.1 - dev: false - /obliterator@2.0.4: - resolution: {integrity: sha512-lgHwxlxV1qIg1Eap7LgIeoBWIMFibOjbrYPIPJZcI1mmGAI2m3lNYpK12Y+GBdPQ0U1hRwSord7GIaawz962qQ==} - dev: false + obliterator@2.0.4: {} - /on-finished@2.4.1: - resolution: {integrity: sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg==} - engines: {node: '>= 0.8'} + on-finished@2.4.1: dependencies: ee-first: 1.1.1 - dev: false - /parseurl@1.3.3: - resolution: {integrity: sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==} - engines: {node: '>= 0.8'} - dev: false + once@1.4.0: + dependencies: + wrappy: 1.0.2 - /path-key@3.1.1: - resolution: {integrity: sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==} - engines: {node: '>=8'} - dev: false + onetime@5.1.2: + dependencies: + mimic-fn: 2.1.0 - /path-scurry@1.10.2: - resolution: {integrity: sha512-7xTavNy5RQXnsjANvVvMkEjvloOinkAjv/Z6Ildz9v2RinZ4SBKTWFOVRbaF8p0vpHnyjV/UwNDdKuUv6M5qcA==} - engines: {node: '>=16 || 14 >=14.17'} + open@7.4.2: + dependencies: + is-docker: 2.2.1 + is-wsl: 2.2.0 + + p-filter@2.1.0: + dependencies: + p-map: 2.1.0 + + p-limit@2.3.0: + dependencies: + p-try: 2.2.0 + + p-limit@3.1.0: + dependencies: + yocto-queue: 0.1.0 + + p-locate@4.1.0: + dependencies: + p-limit: 2.3.0 + + p-locate@5.0.0: + dependencies: + p-limit: 3.1.0 + + p-map@2.1.0: {} + + p-map@4.0.0: + dependencies: + aggregate-error: 3.1.0 + + p-retry@4.6.2: + dependencies: + '@types/retry': 0.12.0 + retry: 0.13.1 + + p-try@2.2.0: {} + + parse-json@5.2.0: + dependencies: + '@babel/code-frame': 7.24.7 + error-ex: 1.3.2 + json-parse-even-better-errors: 2.3.1 + lines-and-columns: 1.2.4 + + parseurl@1.3.3: {} + + path-exists@4.0.0: {} + + path-is-absolute@1.0.1: {} + + path-key@3.1.1: {} + + path-parse@1.0.7: {} + + path-scurry@1.10.2: dependencies: lru-cache: 10.2.0 minipass: 7.0.4 - dev: false - /path-to-regexp@0.1.7: - resolution: {integrity: sha512-5DFkuoqlv1uYQKxy8omFBeJPQcdoE07Kv2sferDCrAq1ohOU+MSDswDIbnx3YAM60qIOnYa53wBhXW0EbMonrQ==} - dev: false + path-to-regexp@0.1.7: {} - /picomatch@2.3.1: - resolution: {integrity: sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==} - engines: {node: '>=8.6'} - dev: true + path-type@4.0.0: {} - /possible-typed-array-names@1.0.0: - resolution: {integrity: sha512-d7Uw+eZoloe0EHDIYoe+bQ5WXnGMOpmiZFTuMWCwpjzzkL2nTjcKiAk4hh8TjnGye2TwWOk3UXucZ+3rbmBa8Q==} - engines: {node: '>= 0.4'} - dev: false + picocolors@1.0.1: {} - /prettier@3.2.5: - resolution: {integrity: sha512-3/GWa9aOC0YeD7LUfvOG2NiDyhOWRvt1k+rcKhOuYnMY24iiCphgneUfJDyFXd6rZCAnuLBv6UeAULtrhT/F4A==} - engines: {node: '>=14'} - hasBin: true - dev: true + picomatch@2.3.1: {} - /prisma@5.12.1: - resolution: {integrity: sha512-SkMnb6wyIxTv9ACqiHBI2u9gD6y98qXRoCoLEnZsF6yee5Qg828G+ARrESN+lQHdw4maSZFFSBPPDpvSiVTo0Q==} - engines: {node: '>=16.13'} - hasBin: true - requiresBuild: true + pkg-dir@4.2.0: dependencies: - '@prisma/engines': 5.12.1 + find-up: 4.1.0 - /promise.any@2.0.6: - resolution: {integrity: sha512-Ew/MrPtTjiHnnki0AA2hS2o65JaZ5n+5pp08JSyWWUdeOGF4F41P+Dn+rdqnaOV/FTxhR6eBDX412luwn3th9g==} - engines: {node: '>= 0.4'} + possible-typed-array-names@1.0.0: {} + + prettier@3.2.5: {} + + prisma-extension-kysely@2.1.0(@prisma/client@5.16.0(prisma@5.16.0)): + dependencies: + '@prisma/client': 5.16.0(prisma@5.16.0) + + prisma-kysely@1.8.0: + dependencies: + '@mrleebo/prisma-ast': 0.7.0 + '@prisma/generator-helper': 5.3.1 + '@prisma/internals': 5.3.1 + typescript: 5.4.3 + zod: 3.23.8 + transitivePeerDependencies: + - encoding + - supports-color + + prisma@5.16.0: + dependencies: + '@prisma/engines': 5.16.0 + + process-nextick-args@2.0.1: {} + + progress@2.0.3: {} + + promise.any@2.0.6: dependencies: array.prototype.map: 1.0.7 call-bind: 1.0.7 @@ -1880,133 +3949,143 @@ packages: es-aggregate-error: 1.0.13 get-intrinsic: 1.2.4 iterate-value: 1.0.2 - dev: false - /proxy-addr@2.0.7: - resolution: {integrity: sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg==} - engines: {node: '>= 0.10'} + prompts@2.4.2: + dependencies: + kleur: 3.0.3 + sisteransi: 1.0.5 + + proxy-addr@2.0.7: dependencies: forwarded: 0.2.0 ipaddr.js: 1.9.1 - dev: false - /pstree.remy@1.1.8: - resolution: {integrity: sha512-77DZwxQmxKnu3aR542U+X8FypNzbfJ+C5XQDk3uWjWxn6151aIMGthWYRXTqT1E5oJvg+ljaa2OJi+VfvCOQ8w==} - dev: true + pstree.remy@1.1.8: {} - /qs@6.11.0: - resolution: {integrity: sha512-MvjoMCJwEarSbUYk5O+nmoSzSutSsTwF85zcHPQ9OrlFoZOYIjaqBAJIqIXjptyD5vThxGq52Xu/MaJzRkIk4Q==} - engines: {node: '>=0.6'} + qs@6.11.0: dependencies: side-channel: 1.0.6 - dev: false - /query-string@7.1.3: - resolution: {integrity: sha512-hh2WYhq4fi8+b+/2Kg9CEge4fDPvHS534aOOvOZeQ3+Vf2mCFsaFBYj0i+iXcAq6I9Vzp5fjMFBlONvayDC1qg==} - engines: {node: '>=6'} + query-string@7.1.3: dependencies: decode-uri-component: 0.2.2 filter-obj: 1.1.0 split-on-first: 1.1.0 strict-uri-encode: 2.0.0 - dev: false - /range-parser@1.2.1: - resolution: {integrity: sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==} - engines: {node: '>= 0.6'} - dev: false + queue-microtask@1.2.3: {} - /raw-body@2.5.2: - resolution: {integrity: sha512-8zGqypfENjCIqGhgXToC8aB2r7YrBX+AQAfIPs/Mlk+BtPTztOvTS01NRW/3Eh60J+a48lt8qsCzirQ6loCVfA==} - engines: {node: '>= 0.8'} + range-parser@1.2.1: {} + + raw-body@2.5.2: dependencies: bytes: 3.1.2 http-errors: 2.0.0 iconv-lite: 0.4.24 unpipe: 1.0.0 - dev: false - /readable-stream@3.6.2: - resolution: {integrity: sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==} - engines: {node: '>= 6'} + read-pkg-up@7.0.1: + dependencies: + find-up: 4.1.0 + read-pkg: 5.2.0 + type-fest: 0.8.1 + + read-pkg@5.2.0: + dependencies: + '@types/normalize-package-data': 2.4.4 + normalize-package-data: 2.5.0 + parse-json: 5.2.0 + type-fest: 0.6.0 + + readable-stream@2.3.8: + dependencies: + core-util-is: 1.0.3 + inherits: 2.0.4 + isarray: 1.0.0 + process-nextick-args: 2.0.1 + safe-buffer: 5.1.2 + string_decoder: 1.1.1 + util-deprecate: 1.0.2 + + readable-stream@3.6.2: dependencies: inherits: 2.0.4 string_decoder: 1.3.0 util-deprecate: 1.0.2 - dev: false - /readdirp@3.6.0: - resolution: {integrity: sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==} - engines: {node: '>=8.10.0'} + readdir-glob@1.1.3: + dependencies: + minimatch: 5.1.6 + + readdirp@3.6.0: dependencies: picomatch: 2.3.1 - dev: true - /reflect-metadata@0.2.2: - resolution: {integrity: sha512-urBwgfrvVP/eAyXx4hluJivBKzuEbSQs9rKWCrCkbSxNv8mxPcUZKeuoF3Uy4mJl3Lwprp6yy5/39VWigZ4K6Q==} - dev: false + reflect-metadata@0.2.2: {} - /regexp.prototype.flags@1.5.2: - resolution: {integrity: sha512-NcDiDkTLuPR+++OCKB0nWafEmhg/Da8aUPLPMQbK+bxKKCm1/S5he+AqYa4PlMCVBalb4/yxIRub6qkEx5yJbw==} - engines: {node: '>= 0.4'} + regexp-to-ast@0.5.0: {} + + regexp.prototype.flags@1.5.2: dependencies: call-bind: 1.0.7 define-properties: 1.2.1 es-errors: 1.3.0 set-function-name: 2.0.2 - dev: false - /require-directory@2.1.1: - resolution: {integrity: sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==} - engines: {node: '>=0.10.0'} - dev: false + replace-string@3.1.0: {} - /safe-array-concat@1.1.2: - resolution: {integrity: sha512-vj6RsCsWBCf19jIeHEfkRMw8DPiBb+DMXklQ/1SGDHOMlHdPUkZXFQ2YdplS23zESTijAcurb1aSgJA3AgMu1Q==} - engines: {node: '>=0.4'} + require-directory@2.1.1: {} + + resolve@1.22.4: + dependencies: + is-core-module: 2.14.0 + path-parse: 1.0.7 + supports-preserve-symlinks-flag: 1.0.0 + + retry@0.13.1: {} + + reusify@1.0.4: {} + + rimraf@3.0.2: + dependencies: + glob: 7.2.3 + + run-parallel@1.2.0: + dependencies: + queue-microtask: 1.2.3 + + safe-array-concat@1.1.2: dependencies: call-bind: 1.0.7 get-intrinsic: 1.2.4 has-symbols: 1.0.3 isarray: 2.0.5 - dev: false - /safe-buffer@5.2.1: - resolution: {integrity: sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==} - dev: false + safe-buffer@5.1.2: {} - /safe-regex-test@1.0.3: - resolution: {integrity: sha512-CdASjNJPvRa7roO6Ra/gLYBTzYzzPyyBXxIMdGW3USQLyjWEls2RgW5UBTXaQVp+OrpeCK3bLem8smtmheoRuw==} - engines: {node: '>= 0.4'} + safe-buffer@5.2.1: {} + + safe-regex-test@1.0.3: dependencies: call-bind: 1.0.7 es-errors: 1.3.0 is-regex: 1.1.4 - dev: false - /safer-buffer@2.1.2: - resolution: {integrity: sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==} - dev: false + safer-buffer@2.1.2: {} - /sax@1.3.0: - resolution: {integrity: sha512-0s+oAmw9zLl1V1cS9BtZN7JAd0cW5e0QH4W3LWEK6a4LaLEA2OTpGYWDY+6XasBLtz6wkm3u1xRw95mRuJ59WA==} - dev: false + sax@1.3.0: {} - /secure-json-parse@2.7.0: - resolution: {integrity: sha512-6aU+Rwsezw7VR8/nyvKTx8QpWH9FrcYiXXlqC4z5d5XQBDRqtbfsRjnwGyqbi3gddNtWHuEk9OANUotL26qKUw==} - dev: false + secure-json-parse@2.7.0: {} - /semver@7.6.0: - resolution: {integrity: sha512-EnwXhrlwXMk9gKu5/flx5sv/an57AkRplG3hTK68W7FRDN+k+OWBj65M7719OkA82XLBxrcX0KSHj+X5COhOVg==} - engines: {node: '>=10'} - hasBin: true + semver@5.7.2: {} + + semver@6.3.1: {} + + semver@7.6.0: dependencies: lru-cache: 6.0.0 - dev: true - /send@0.18.0: - resolution: {integrity: sha512-qqWzuOjSFOuqPjFe4NOsMLafToQQwBSOEpS+FwEt3A2V3vKubTquT3vmLTQpFgMXp8AlFWFuP1qKaJZOtPpVXg==} - engines: {node: '>= 0.8.0'} + send@0.18.0: dependencies: debug: 2.6.9 depd: 2.0.0 @@ -2023,11 +4102,8 @@ packages: statuses: 2.0.1 transitivePeerDependencies: - supports-color - dev: false - /serve-static@1.15.0: - resolution: {integrity: sha512-XGuRDNjXUijsUL0vl6nSD7cwURuzEgglbOaFuZM9g3kwDXOWVTck0jLzjPzGD+TazWbboZYu52/9/XPdUgne9g==} - engines: {node: '>= 0.8.0'} + serve-static@1.15.0: dependencies: encodeurl: 1.0.2 escape-html: 1.0.3 @@ -2035,11 +4111,8 @@ packages: send: 0.18.0 transitivePeerDependencies: - supports-color - dev: false - /set-function-length@1.2.2: - resolution: {integrity: sha512-pgRc4hJ4/sNjWCSS9AmnS40x3bNMDTknHgL5UaMBTMyJnU90EgWh1Rz+MC9eFu4BuN/UwZjKQuY/1v3rM7HMfg==} - engines: {node: '>= 0.4'} + set-function-length@1.2.2: dependencies: define-data-property: 1.1.4 es-errors: 1.3.0 @@ -2047,215 +4120,196 @@ packages: get-intrinsic: 1.2.4 gopd: 1.0.1 has-property-descriptors: 1.0.2 - dev: false - /set-function-name@2.0.2: - resolution: {integrity: sha512-7PGFlmtwsEADb0WYyvCMa1t+yke6daIG4Wirafur5kcf+MhUnPms1UeR0CKQdTZD81yESwMHbtn+TR+dMviakQ==} - engines: {node: '>= 0.4'} + set-function-name@2.0.2: dependencies: define-data-property: 1.1.4 es-errors: 1.3.0 functions-have-names: 1.2.3 has-property-descriptors: 1.0.2 - dev: false - /setprototypeof@1.2.0: - resolution: {integrity: sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==} - dev: false + setprototypeof@1.2.0: {} - /shebang-command@2.0.0: - resolution: {integrity: sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==} - engines: {node: '>=8'} + shebang-command@2.0.0: dependencies: shebang-regex: 3.0.0 - dev: false - /shebang-regex@3.0.0: - resolution: {integrity: sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==} - engines: {node: '>=8'} - dev: false + shebang-regex@3.0.0: {} - /side-channel@1.0.6: - resolution: {integrity: sha512-fDW/EZ6Q9RiO8eFG8Hj+7u/oW+XrPTIChwCOM2+th2A6OblDtYYIpve9m+KvI9Z4C9qSEXlaGR6bTEYHReuglA==} - engines: {node: '>= 0.4'} + side-channel@1.0.6: dependencies: call-bind: 1.0.7 es-errors: 1.3.0 get-intrinsic: 1.2.4 object-inspect: 1.13.1 - dev: false - /signal-exit@4.1.0: - resolution: {integrity: sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==} - engines: {node: '>=14'} - dev: false + signal-exit@3.0.7: {} - /simple-update-notifier@2.0.0: - resolution: {integrity: sha512-a2B9Y0KlNXl9u/vsW6sTIu9vGEpfKu2wRV6l1H3XEas/0gUIzGzBoP/IouTcUQbm9JWZLH3COxyn03TYlFax6w==} - engines: {node: '>=10'} + signal-exit@4.1.0: {} + + simple-update-notifier@2.0.0: dependencies: semver: 7.6.0 - dev: true - /source-map@0.6.1: - resolution: {integrity: sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==} - engines: {node: '>=0.10.0'} - dev: false + sisteransi@1.0.5: {} - /split-on-first@1.1.0: - resolution: {integrity: sha512-43ZssAJaMusuKWL8sKUBQXHWOpq8d6CfN/u1p4gUzfJkM05C8rxTmYrkIPTXapZpORA6LkkzcUulJ8FqA7Uudw==} - engines: {node: '>=6'} - dev: false + slash@3.0.0: {} - /statuses@2.0.1: - resolution: {integrity: sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==} - engines: {node: '>= 0.8'} - dev: false + slice-ansi@3.0.0: + dependencies: + ansi-styles: 4.3.0 + astral-regex: 2.0.0 + is-fullwidth-code-point: 3.0.0 - /stop-iteration-iterator@1.0.0: - resolution: {integrity: sha512-iCGQj+0l0HOdZ2AEeBADlsRC+vsnDsZsbdSiH1yNSjcfKM7fdpCMfqAL/dwF5BLiw/XhRft/Wax6zQbhq2BcjQ==} - engines: {node: '>= 0.4'} + source-map@0.6.1: {} + + spdx-correct@3.2.0: + dependencies: + spdx-expression-parse: 3.0.1 + spdx-license-ids: 3.0.18 + + spdx-exceptions@2.5.0: {} + + spdx-expression-parse@3.0.1: + dependencies: + spdx-exceptions: 2.5.0 + spdx-license-ids: 3.0.18 + + spdx-license-ids@3.0.18: {} + + split-on-first@1.1.0: {} + + statuses@2.0.1: {} + + stop-iteration-iterator@1.0.0: dependencies: internal-slot: 1.0.7 - dev: false - /strict-uri-encode@2.0.0: - resolution: {integrity: sha512-QwiXZgpRcKkhTj2Scnn++4PKtWsH0kpzZ62L2R6c/LUVYv7hVnZqcg2+sMuT6R7Jusu1vviK/MFsu6kNJfWlEQ==} - engines: {node: '>=4'} - dev: false + strict-uri-encode@2.0.0: {} - /string-width@4.2.3: - resolution: {integrity: sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==} - engines: {node: '>=8'} + string-width@4.2.3: dependencies: emoji-regex: 8.0.0 is-fullwidth-code-point: 3.0.0 strip-ansi: 6.0.1 - dev: false - /string-width@5.1.2: - resolution: {integrity: sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==} - engines: {node: '>=12'} + string-width@5.1.2: dependencies: eastasianwidth: 0.2.0 emoji-regex: 9.2.2 strip-ansi: 7.1.0 - dev: false - /string.prototype.trim@1.2.9: - resolution: {integrity: sha512-klHuCNxiMZ8MlsOihJhJEBJAiMVqU3Z2nEXWfWnIqjN0gEFS9J9+IxKozWWtQGcgoa1WUZzLjKPTr4ZHNFTFxw==} - engines: {node: '>= 0.4'} + string.prototype.trim@1.2.9: dependencies: call-bind: 1.0.7 define-properties: 1.2.1 es-abstract: 1.23.3 es-object-atoms: 1.0.0 - dev: false - /string.prototype.trimend@1.0.8: - resolution: {integrity: sha512-p73uL5VCHCO2BZZ6krwwQE3kCzM7NKmis8S//xEC6fQonchbum4eP6kR4DLEjQFO3Wnj3Fuo8NM0kOSjVdHjZQ==} + string.prototype.trimend@1.0.8: dependencies: call-bind: 1.0.7 define-properties: 1.2.1 es-object-atoms: 1.0.0 - dev: false - /string.prototype.trimstart@1.0.8: - resolution: {integrity: sha512-UXSH262CSZY1tfu3G3Secr6uGLCFVPMhIqHjlgCUtCCcgihYc/xKs9djMTMUOb2j1mVSeU8EU6NWc/iQKU6Gfg==} - engines: {node: '>= 0.4'} + string.prototype.trimstart@1.0.8: dependencies: call-bind: 1.0.7 define-properties: 1.2.1 es-object-atoms: 1.0.0 - dev: false - /string_decoder@1.3.0: - resolution: {integrity: sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==} + string_decoder@1.1.1: + dependencies: + safe-buffer: 5.1.2 + + string_decoder@1.3.0: dependencies: safe-buffer: 5.2.1 - dev: false - /strip-ansi@6.0.1: - resolution: {integrity: sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==} - engines: {node: '>=8'} + strip-ansi@6.0.1: dependencies: ansi-regex: 5.0.1 - dev: false - /strip-ansi@7.1.0: - resolution: {integrity: sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==} - engines: {node: '>=12'} + strip-ansi@7.1.0: dependencies: ansi-regex: 6.0.1 - dev: false - /strnum@1.0.5: - resolution: {integrity: sha512-J8bbNyKKXl5qYcR36TIO8W3mVGVHrmmxsd5PAItGkmyzwJvybiw2IVq5nqd0i4LSNSkB/sx9VHllbfFdr9k1JA==} - dev: false + strip-final-newline@2.0.0: {} - /supports-color@5.5.0: - resolution: {integrity: sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==} - engines: {node: '>=4'} + strip-indent@3.0.0: + dependencies: + min-indent: 1.0.1 + + strnum@1.0.5: {} + + supports-color@5.5.0: dependencies: has-flag: 3.0.0 - /swagger-ui-dist@5.13.0: - resolution: {integrity: sha512-uaWhh6j18IIs5tOX0arvIBnVINAzpTXaQXkr7qAk8zoupegJVg0UU/5+S/FgsgVCnzVsJ9d7QLjIxkswEeTg0Q==} - dev: false + supports-color@7.2.0: + dependencies: + has-flag: 4.0.0 - /swagger-ui-express@5.0.0(express@4.19.2): - resolution: {integrity: sha512-tsU9tODVvhyfkNSvf03E6FAk+z+5cU3lXAzMy6Pv4av2Gt2xA0++fogwC4qo19XuFf6hdxevPuVCSKFuMHJhFA==} - engines: {node: '>= v0.10.32'} - peerDependencies: - express: '>=4.0.0 || >=5.0.0-beta' + supports-hyperlinks@2.3.0: + dependencies: + has-flag: 4.0.0 + supports-color: 7.2.0 + + supports-preserve-symlinks-flag@1.0.0: {} + + swagger-ui-dist@5.13.0: {} + + swagger-ui-express@5.0.0(express@4.19.2): dependencies: express: 4.19.2 swagger-ui-dist: 5.13.0 - dev: false - /through2@4.0.2: - resolution: {integrity: sha512-iOqSav00cVxEEICeD7TjLB1sueEL+81Wpzp2bY17uZjZN0pWZPuo4suZ/61VujxmqSGFfgOcNuTZ85QJwNZQpw==} + tar-stream@2.2.0: + dependencies: + bl: 4.1.0 + end-of-stream: 1.4.4 + fs-constants: 1.0.0 + inherits: 2.0.4 + readable-stream: 3.6.2 + + temp-dir@2.0.0: {} + + tempy@1.0.1: + dependencies: + del: 6.1.1 + is-stream: 2.0.1 + temp-dir: 2.0.0 + type-fest: 0.16.0 + unique-string: 2.0.0 + + terminal-link@2.1.1: + dependencies: + ansi-escapes: 4.3.2 + supports-hyperlinks: 2.3.0 + + through2@4.0.2: dependencies: readable-stream: 3.6.2 - dev: false - /to-regex-range@5.0.1: - resolution: {integrity: sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==} - engines: {node: '>=8.0'} + tmp@0.2.1: + dependencies: + rimraf: 3.0.2 + + to-regex-range@5.0.1: dependencies: is-number: 7.0.0 - dev: true - /toidentifier@1.0.1: - resolution: {integrity: sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==} - engines: {node: '>=0.6'} - dev: false + toidentifier@1.0.1: {} - /touch@3.1.0: - resolution: {integrity: sha512-WBx8Uy5TLtOSRtIq+M03/sKDrXCLHxwDcquSP2c43Le03/9serjQBIztjRz6FkJez9D/hleyAXTBGLwwZUw9lA==} - hasBin: true + touch@3.1.0: dependencies: nopt: 1.0.10 - dev: true - /ts-deepmerge@7.0.0: - resolution: {integrity: sha512-WZ/iAJrKDhdINv1WG6KZIGHrZDar6VfhftG1QJFpVbOYZMYJLJOvZOo1amictRXVdBXZIgBHKswMTXzElngprA==} - engines: {node: '>=14.13.1'} - dev: false + tr46@0.0.3: {} - /ts-node@10.9.2(@types/node@20.12.2)(typescript@5.4.3): - resolution: {integrity: sha512-f0FFpIdcHgn8zcPSbf1dRevwt047YMnaiJM3u2w2RewrB+fob/zePZcrOyQoLMMO7aBIddLcQIEK5dYjkLnGrQ==} - hasBin: true - peerDependencies: - '@swc/core': '>=1.2.50' - '@swc/wasm': '>=1.2.50' - '@types/node': '*' - typescript: '>=2.7' - peerDependenciesMeta: - '@swc/core': - optional: true - '@swc/wasm': - optional: true + ts-deepmerge@7.0.0: {} + + ts-node@10.9.2(@types/node@20.12.2)(typescript@5.4.3): dependencies: '@cspotcode/source-map-support': 0.8.1 '@tsconfig/node10': 1.0.11 @@ -2272,54 +4326,46 @@ packages: typescript: 5.4.3 v8-compile-cache-lib: 3.0.1 yn: 3.1.1 - dev: true - /tslib@2.6.2: - resolution: {integrity: sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==} - dev: false + ts-pattern@4.3.0: {} - /tsoa@6.2.0: - resolution: {integrity: sha512-EX/RyoU+4hD1rLM5NjYG+I7lEhqx1yuLgcHs/gyWQpkX/RL9cVR9hFA9LKQrK6PE+WTg1SEahn1MK3l/+6pVKw==} - engines: {node: '>=18.0.0', yarn: '>=1.9.4'} - hasBin: true + tslib@2.6.2: {} + + tsoa@6.2.0: dependencies: '@tsoa/cli': 6.2.0 '@tsoa/runtime': 6.2.0 transitivePeerDependencies: - supports-color - dev: false - /type-is@1.6.18: - resolution: {integrity: sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==} - engines: {node: '>= 0.6'} + type-fest@0.16.0: {} + + type-fest@0.21.3: {} + + type-fest@0.6.0: {} + + type-fest@0.8.1: {} + + type-is@1.6.18: dependencies: media-typer: 0.3.0 mime-types: 2.1.35 - dev: false - /typed-array-buffer@1.0.2: - resolution: {integrity: sha512-gEymJYKZtKXzzBzM4jqa9w6Q1Jjm7x2d+sh19AdsD4wqnMPDYyvwpsIc2Q/835kHuo3BEQ7CjelGhfTsoBb2MQ==} - engines: {node: '>= 0.4'} + typed-array-buffer@1.0.2: dependencies: call-bind: 1.0.7 es-errors: 1.3.0 is-typed-array: 1.1.13 - dev: false - /typed-array-byte-length@1.0.1: - resolution: {integrity: sha512-3iMJ9q0ao7WE9tWcaYKIptkNBuOIcZCCT0d4MRvuuH88fEoEH62IuQe0OtraD3ebQEoTRk8XCBoknUNc1Y67pw==} - engines: {node: '>= 0.4'} + typed-array-byte-length@1.0.1: dependencies: call-bind: 1.0.7 for-each: 0.3.3 gopd: 1.0.1 has-proto: 1.0.3 is-typed-array: 1.1.13 - dev: false - /typed-array-byte-offset@1.0.2: - resolution: {integrity: sha512-Ous0vodHa56FviZucS2E63zkgtgrACj7omjwd/8lTEMEPFFyjfixMZ1ZXenpgCFBBt4EC1J2XsyVS2gkG0eTFA==} - engines: {node: '>= 0.4'} + typed-array-byte-offset@1.0.2: dependencies: available-typed-arrays: 1.0.7 call-bind: 1.0.7 @@ -2327,11 +4373,8 @@ packages: gopd: 1.0.1 has-proto: 1.0.3 is-typed-array: 1.1.13 - dev: false - /typed-array-length@1.0.6: - resolution: {integrity: sha512-/OxDN6OtAk5KBpGb28T+HZc2M+ADtvRxXrKKbUwtsLgdoxgX13hyy7ek6bFRl5+aBs2yZzB0c4CnQfAtVypW/g==} - engines: {node: '>= 0.4'} + typed-array-length@1.0.6: dependencies: call-bind: 1.0.7 for-each: 0.3.3 @@ -2339,184 +4382,125 @@ packages: has-proto: 1.0.3 is-typed-array: 1.1.13 possible-typed-array-names: 1.0.0 - dev: false - /typescript@5.4.3: - resolution: {integrity: sha512-KrPd3PKaCLr78MalgiwJnA25Nm8HAmdwN3mYUYZgG/wizIo9EainNVQI9/yDavtVFRN2h3k8uf3GLHuhDMgEHg==} - engines: {node: '>=14.17'} - hasBin: true + typescript@5.4.3: {} - /uglify-js@3.17.4: - resolution: {integrity: sha512-T9q82TJI9e/C1TAxYvfb16xO120tMVFZrGA3f9/P4424DNu6ypK103y0GPFVa17yotwSyZW5iYXgjYHkGrJW/g==} - engines: {node: '>=0.8.0'} - hasBin: true - requiresBuild: true - dev: false + uglify-js@3.17.4: optional: true - /unbox-primitive@1.0.2: - resolution: {integrity: sha512-61pPlCD9h51VoreyJ0BReideM3MDKMKnh6+V9L08331ipq6Q8OFXZYiqP6n/tbHx4s5I9uRhcye6BrbkizkBDw==} + unbox-primitive@1.0.2: dependencies: call-bind: 1.0.7 has-bigints: 1.0.2 has-symbols: 1.0.3 which-boxed-primitive: 1.0.2 - dev: false - /undefsafe@2.0.5: - resolution: {integrity: sha512-WxONCrssBM8TSPRqN5EmsjVrsv4A8X12J4ArBiiayv3DyyG3ZlIg6yysuuSYdZsVz3TKcTg2fd//Ujd4CHV1iA==} - dev: true + undefsafe@2.0.5: {} - /undici-types@5.26.5: - resolution: {integrity: sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==} + undici-types@5.26.5: {} - /undici@6.11.1: - resolution: {integrity: sha512-KyhzaLJnV1qa3BSHdj4AZ2ndqI0QWPxYzaIOio0WzcEJB9gvuysprJSLtpvc2D9mhR9jPDUk7xlJlZbH2KR5iw==} - engines: {node: '>=18.0'} - dev: false + undici@6.11.1: {} - /universalify@2.0.1: - resolution: {integrity: sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==} - engines: {node: '>= 10.0.0'} - dev: false + unique-string@2.0.0: + dependencies: + crypto-random-string: 2.0.0 - /unpipe@1.0.0: - resolution: {integrity: sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==} - engines: {node: '>= 0.8'} - dev: false + universalify@2.0.1: {} - /util-deprecate@1.0.2: - resolution: {integrity: sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==} - dev: false + unpipe@1.0.0: {} - /util@0.12.5: - resolution: {integrity: sha512-kZf/K6hEIrWHI6XqOFUiiMa+79wE/D8Q+NCNAWclkyg3b4d2k7s0QGepNjiABc+aR3N1PAyHL7p6UcLY6LmrnA==} + util-deprecate@1.0.2: {} + + util@0.12.5: dependencies: inherits: 2.0.4 is-arguments: 1.1.1 is-generator-function: 1.0.10 is-typed-array: 1.1.13 which-typed-array: 1.1.15 - dev: false - /utils-merge@1.0.1: - resolution: {integrity: sha512-pMZTvIkT1d+TFGvDOqodOclx0QWkkgi6Tdoa8gC8ffGAAqz9pzPTZWAybbsHHoED/ztMtkv/VoYTYyShUn81hA==} - engines: {node: '>= 0.4.0'} - dev: false + utils-merge@1.0.1: {} - /v8-compile-cache-lib@3.0.1: - resolution: {integrity: sha512-wa7YjyUGfNZngI/vtK0UHAN+lgDCxBPCylVXGp0zu59Fz5aiGtNXaq3DhIov063MorB+VfufLh3JlF2KdTK3xg==} - dev: true + uuid@9.0.0: {} - /validator@13.11.0: - resolution: {integrity: sha512-Ii+sehpSfZy+At5nPdnyMhx78fEoPDkR2XW/zimHEL3MyGJQOCQ7WeP20jPYRz7ZCpcKLB21NxuXHF3bxjStBQ==} - engines: {node: '>= 0.10'} - dev: false + v8-compile-cache-lib@3.0.1: {} - /vary@1.1.2: - resolution: {integrity: sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==} - engines: {node: '>= 0.8'} - dev: false + validate-npm-package-license@3.0.4: + dependencies: + spdx-correct: 3.2.0 + spdx-expression-parse: 3.0.1 - /web-encoding@1.1.5: - resolution: {integrity: sha512-HYLeVCdJ0+lBYV2FvNZmv3HJ2Nt0QYXqZojk3d9FJOLkwnuhzM9tmamh8d7HPM8QqjKH8DeHkFTx+CFlWpZZDA==} + validator@13.11.0: {} + + vary@1.1.2: {} + + web-encoding@1.1.5: dependencies: util: 0.12.5 optionalDependencies: '@zxing/text-encoding': 0.9.0 - dev: false - /which-boxed-primitive@1.0.2: - resolution: {integrity: sha512-bwZdv0AKLpplFY2KZRX6TvyuN7ojjr7lwkg6ml0roIy9YeuSr7JS372qlNW18UQYzgYK9ziGcerWqZOmEn9VNg==} + webidl-conversions@3.0.1: {} + + whatwg-url@5.0.0: + dependencies: + tr46: 0.0.3 + webidl-conversions: 3.0.1 + + which-boxed-primitive@1.0.2: dependencies: is-bigint: 1.0.4 is-boolean-object: 1.1.2 is-number-object: 1.0.7 is-string: 1.0.7 is-symbol: 1.0.4 - dev: false - /which-typed-array@1.1.15: - resolution: {integrity: sha512-oV0jmFtUky6CXfkqehVvBP/LSWJ2sy4vWMioiENyJLePrBO/yKyV9OyJySfAKosh+RYkIl5zJCNZ8/4JncrpdA==} - engines: {node: '>= 0.4'} + which-typed-array@1.1.15: dependencies: available-typed-arrays: 1.0.7 call-bind: 1.0.7 for-each: 0.3.3 gopd: 1.0.1 has-tostringtag: 1.0.2 - dev: false - /which@2.0.2: - resolution: {integrity: sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==} - engines: {node: '>= 8'} - hasBin: true + which@2.0.2: dependencies: isexe: 2.0.0 - dev: false - /wordwrap@1.0.0: - resolution: {integrity: sha512-gvVzJFlPycKc5dZN4yPkP8w7Dc37BtP1yczEneOb4uq34pXZcvrtRTmWV8W+Ume+XCxKgbjM+nevkyFPMybd4Q==} - dev: false + wordwrap@1.0.0: {} - /wrap-ansi@7.0.0: - resolution: {integrity: sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==} - engines: {node: '>=10'} + wrap-ansi@7.0.0: dependencies: ansi-styles: 4.3.0 string-width: 4.2.3 strip-ansi: 6.0.1 - dev: false - /wrap-ansi@8.1.0: - resolution: {integrity: sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ==} - engines: {node: '>=12'} + wrap-ansi@8.1.0: dependencies: ansi-styles: 6.2.1 string-width: 5.1.2 strip-ansi: 7.1.0 - dev: false - /xml2js@0.5.0: - resolution: {integrity: sha512-drPFnkQJik/O+uPKpqSgr22mpuFHqKdbS835iAQrUC73L2F5WkboIRd63ai/2Yg6I1jzifPFKH2NTK+cfglkIA==} - engines: {node: '>=4.0.0'} + wrappy@1.0.2: {} + + xml2js@0.5.0: dependencies: sax: 1.3.0 xmlbuilder: 11.0.1 - dev: false - /xml@1.0.1: - resolution: {integrity: sha512-huCv9IH9Tcf95zuYCsQraZtWnJvBtLVE0QHMOs8bWyZAFZNDcYjsPq1nEx8jKA9y+Beo9v+7OBPRisQTjinQMw==} - dev: false + xml@1.0.1: {} - /xmlbuilder@11.0.1: - resolution: {integrity: sha512-fDlsI/kFEx7gLvbecc0/ohLG50fugQp8ryHzMTuW9vSa1GJ0XYWKnhsUx7oie3G98+r56aTQIUB4kht42R3JvA==} - engines: {node: '>=4.0'} - dev: false + xmlbuilder@11.0.1: {} - /y18n@5.0.8: - resolution: {integrity: sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==} - engines: {node: '>=10'} - dev: false + y18n@5.0.8: {} - /yallist@4.0.0: - resolution: {integrity: sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==} - dev: true + yallist@4.0.0: {} - /yaml@2.4.1: - resolution: {integrity: sha512-pIXzoImaqmfOrL7teGUBt/T7ZDnyeGBWyXQBvOVhLkWLN37GXv8NMLK406UY6dS51JfcQHsmcW5cJ441bHg6Lg==} - engines: {node: '>= 14'} - hasBin: true - dev: false + yaml@2.4.1: {} - /yargs-parser@21.1.1: - resolution: {integrity: sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==} - engines: {node: '>=12'} - dev: false + yargs-parser@21.1.1: {} - /yargs@17.7.2: - resolution: {integrity: sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==} - engines: {node: '>=12'} + yargs@17.7.2: dependencies: cliui: 8.0.1 escalade: 3.1.2 @@ -2525,9 +4509,15 @@ packages: string-width: 4.2.3 y18n: 5.0.8 yargs-parser: 21.1.1 - dev: false - /yn@3.1.1: - resolution: {integrity: sha512-Ux4ygGWsu2c7isFWe8Yu1YluJmqVhxqK2cLXNQA5AcC3QfbGNpM7fu0Y8b/z16pXLnFxZYvWhd3fhBY9DLmC6Q==} - engines: {node: '>=6'} - dev: true + yn@3.1.1: {} + + yocto-queue@0.1.0: {} + + zip-stream@4.1.1: + dependencies: + archiver-utils: 3.0.4 + compress-commons: 4.1.2 + readable-stream: 3.6.2 + + zod@3.23.8: {} diff --git a/prisma/migrations/20240409065557_update_customer/migration.sql b/prisma/migrations/20240409065557_update_customer/migration.sql deleted file mode 100644 index f5291b9..0000000 --- a/prisma/migrations/20240409065557_update_customer/migration.sql +++ /dev/null @@ -1,14 +0,0 @@ -/* - Warnings: - - - You are about to drop the column `imageUrl` on the `Customer` table. All the data in the column will be lost. - - Changed the type of `customerType` on the `Customer` table. No cast exists, the column would be dropped and recreated, which cannot be done if there is data, since the column is required. - -*/ --- CreateEnum -CREATE TYPE "CustomerType" AS ENUM ('CORP', 'PERS'); - --- AlterTable -ALTER TABLE "Customer" DROP COLUMN "imageUrl", -DROP COLUMN "customerType", -ADD COLUMN "customerType" "CustomerType" NOT NULL; diff --git a/prisma/migrations/20240410043453_add_missing_user_field/migration.sql b/prisma/migrations/20240410043453_add_missing_user_field/migration.sql deleted file mode 100644 index a32f678..0000000 --- a/prisma/migrations/20240410043453_add_missing_user_field/migration.sql +++ /dev/null @@ -1,3 +0,0 @@ --- AlterTable -ALTER TABLE "User" ADD COLUMN "birtDate" TIMESTAMP(3), -ADD COLUMN "responsibleArea" TEXT; diff --git a/prisma/migrations/20240410053228_fix_typo/migration.sql b/prisma/migrations/20240410053228_fix_typo/migration.sql deleted file mode 100644 index 59c29dd..0000000 --- a/prisma/migrations/20240410053228_fix_typo/migration.sql +++ /dev/null @@ -1,9 +0,0 @@ -/* - Warnings: - - - You are about to drop the column `birtDate` on the `User` table. All the data in the column will be lost. - -*/ --- AlterTable -ALTER TABLE "User" DROP COLUMN "birtDate", -ADD COLUMN "birthDate" TIMESTAMP(3); diff --git a/prisma/migrations/20240417020614_remove_field/migration.sql b/prisma/migrations/20240417020614_remove_field/migration.sql deleted file mode 100644 index 3cb801f..0000000 --- a/prisma/migrations/20240417020614_remove_field/migration.sql +++ /dev/null @@ -1,8 +0,0 @@ -/* - Warnings: - - - You are about to drop the column `keycloakId` on the `User` table. All the data in the column will be lost. - -*/ --- AlterTable -ALTER TABLE "User" DROP COLUMN "keycloakId"; diff --git a/prisma/migrations/20240417041541_move_field/migration.sql b/prisma/migrations/20240417041541_move_field/migration.sql deleted file mode 100644 index 3b720dc..0000000 --- a/prisma/migrations/20240417041541_move_field/migration.sql +++ /dev/null @@ -1,11 +0,0 @@ -/* - Warnings: - - - You are about to drop the column `lineId` on the `BranchContact` table. All the data in the column will be lost. - -*/ --- AlterTable -ALTER TABLE "Branch" ADD COLUMN "lineId" TEXT; - --- AlterTable -ALTER TABLE "BranchContact" DROP COLUMN "lineId"; diff --git a/prisma/migrations/20240417063829_update_table/migration.sql b/prisma/migrations/20240417063829_update_table/migration.sql deleted file mode 100644 index 8b7bd17..0000000 --- a/prisma/migrations/20240417063829_update_table/migration.sql +++ /dev/null @@ -1,119 +0,0 @@ -/* - Warnings: - - - You are about to drop the column `telephoneNo` on the `Branch` table. All the data in the column will be lost. - -*/ --- AlterTable -ALTER TABLE "Branch" DROP COLUMN "telephoneNo"; - --- CreateTable -CREATE TABLE "Menu" ( - "id" TEXT NOT NULL, - "caption" TEXT NOT NULL, - "captionEN" TEXT NOT NULL, - "menuType" TEXT NOT NULL, - "url" TEXT NOT NULL, - "createdBy" TEXT, - "createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, - "updateBy" TEXT, - "updatedAt" TIMESTAMP(3) NOT NULL, - "parentId" TEXT, - - CONSTRAINT "Menu_pkey" PRIMARY KEY ("id") -); - --- CreateTable -CREATE TABLE "RoleMenuPermission" ( - "id" TEXT NOT NULL, - "userRole" TEXT NOT NULL, - "permission" TEXT NOT NULL, - "menuId" TEXT NOT NULL, - "createdBy" TEXT, - "createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, - "updateBy" TEXT, - "updatedAt" TIMESTAMP(3) NOT NULL, - - CONSTRAINT "RoleMenuPermission_pkey" PRIMARY KEY ("id") -); - --- CreateTable -CREATE TABLE "UserMenuPermission" ( - "id" TEXT NOT NULL, - "permission" TEXT NOT NULL, - "menuId" TEXT NOT NULL, - "userId" TEXT NOT NULL, - "createdBy" TEXT, - "createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, - "updateBy" TEXT, - "updatedAt" TIMESTAMP(3) NOT NULL, - - CONSTRAINT "UserMenuPermission_pkey" PRIMARY KEY ("id") -); - --- CreateTable -CREATE TABLE "MenuComponent" ( - "id" TEXT NOT NULL, - "componentId" TEXT NOT NULL, - "componentTag" TEXT NOT NULL, - "menuId" TEXT NOT NULL, - "createdBy" TEXT, - "createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, - "updateBy" TEXT, - "updatedAt" TIMESTAMP(3) NOT NULL, - - CONSTRAINT "MenuComponent_pkey" PRIMARY KEY ("id") -); - --- CreateTable -CREATE TABLE "RoleMenuComponentPermission" ( - "id" TEXT NOT NULL, - "componentId" TEXT NOT NULL, - "componentTag" TEXT NOT NULL, - "menuComponentId" TEXT NOT NULL, - "permission" TEXT NOT NULL, - "createdBy" TEXT, - "createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, - "updateBy" TEXT, - "updatedAt" TIMESTAMP(3) NOT NULL, - - CONSTRAINT "RoleMenuComponentPermission_pkey" PRIMARY KEY ("id") -); - --- CreateTable -CREATE TABLE "UserMenuComponentPermission" ( - "id" TEXT NOT NULL, - "userId" TEXT NOT NULL, - "menuComponentId" TEXT NOT NULL, - "permission" TEXT NOT NULL, - "createdBy" TEXT, - "createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, - "updateBy" TEXT, - "updatedAt" TIMESTAMP(3) NOT NULL, - - CONSTRAINT "UserMenuComponentPermission_pkey" PRIMARY KEY ("id") -); - --- AddForeignKey -ALTER TABLE "Menu" ADD CONSTRAINT "Menu_parentId_fkey" FOREIGN KEY ("parentId") REFERENCES "Menu"("id") ON DELETE SET NULL ON UPDATE CASCADE; - --- AddForeignKey -ALTER TABLE "RoleMenuPermission" ADD CONSTRAINT "RoleMenuPermission_menuId_fkey" FOREIGN KEY ("menuId") REFERENCES "Menu"("id") ON DELETE RESTRICT ON UPDATE CASCADE; - --- AddForeignKey -ALTER TABLE "UserMenuPermission" ADD CONSTRAINT "UserMenuPermission_menuId_fkey" FOREIGN KEY ("menuId") REFERENCES "Menu"("id") ON DELETE RESTRICT ON UPDATE CASCADE; - --- AddForeignKey -ALTER TABLE "UserMenuPermission" ADD CONSTRAINT "UserMenuPermission_userId_fkey" FOREIGN KEY ("userId") REFERENCES "User"("id") ON DELETE RESTRICT ON UPDATE CASCADE; - --- AddForeignKey -ALTER TABLE "MenuComponent" ADD CONSTRAINT "MenuComponent_menuId_fkey" FOREIGN KEY ("menuId") REFERENCES "Menu"("id") ON DELETE RESTRICT ON UPDATE CASCADE; - --- AddForeignKey -ALTER TABLE "RoleMenuComponentPermission" ADD CONSTRAINT "RoleMenuComponentPermission_menuComponentId_fkey" FOREIGN KEY ("menuComponentId") REFERENCES "MenuComponent"("id") ON DELETE RESTRICT ON UPDATE CASCADE; - --- AddForeignKey -ALTER TABLE "UserMenuComponentPermission" ADD CONSTRAINT "UserMenuComponentPermission_userId_fkey" FOREIGN KEY ("userId") REFERENCES "User"("id") ON DELETE RESTRICT ON UPDATE CASCADE; - --- AddForeignKey -ALTER TABLE "UserMenuComponentPermission" ADD CONSTRAINT "UserMenuComponentPermission_menuComponentId_fkey" FOREIGN KEY ("menuComponentId") REFERENCES "MenuComponent"("id") ON DELETE RESTRICT ON UPDATE CASCADE; diff --git a/prisma/migrations/20240417064127_add_missing_user_field/migration.sql b/prisma/migrations/20240417064127_add_missing_user_field/migration.sql deleted file mode 100644 index b0b8442..0000000 --- a/prisma/migrations/20240417064127_add_missing_user_field/migration.sql +++ /dev/null @@ -1,2 +0,0 @@ --- AlterTable -ALTER TABLE "Branch" ADD COLUMN "contactName" TEXT; diff --git a/prisma/migrations/20240417091605_add_missing_user_field_checkpoint/migration.sql b/prisma/migrations/20240417091605_add_missing_user_field_checkpoint/migration.sql deleted file mode 100644 index 30b641e..0000000 --- a/prisma/migrations/20240417091605_add_missing_user_field_checkpoint/migration.sql +++ /dev/null @@ -1,3 +0,0 @@ --- AlterTable -ALTER TABLE "User" ADD COLUMN "checkpoint" TEXT, -ADD COLUMN "checkpointEN" TEXT; diff --git a/prisma/migrations/20240417094807_add_username_field/migration.sql b/prisma/migrations/20240417094807_add_username_field/migration.sql deleted file mode 100644 index 2d730b3..0000000 --- a/prisma/migrations/20240417094807_add_username_field/migration.sql +++ /dev/null @@ -1,8 +0,0 @@ -/* - Warnings: - - - Added the required column `username` to the `User` table without a default value. This is not possible if the table is not empty. - -*/ --- AlterTable -ALTER TABLE "User" ADD COLUMN "username" TEXT NOT NULL; diff --git a/prisma/migrations/20240418042147_fix_missing_field/migration.sql b/prisma/migrations/20240418042147_fix_missing_field/migration.sql deleted file mode 100644 index c22f622..0000000 --- a/prisma/migrations/20240418042147_fix_missing_field/migration.sql +++ /dev/null @@ -1,12 +0,0 @@ -/* - Warnings: - - - You are about to drop the column `componentId` on the `RoleMenuComponentPermission` table. All the data in the column will be lost. - - You are about to drop the column `componentTag` on the `RoleMenuComponentPermission` table. All the data in the column will be lost. - - Added the required column `userRole` to the `RoleMenuComponentPermission` table without a default value. This is not possible if the table is not empty. - -*/ --- AlterTable -ALTER TABLE "RoleMenuComponentPermission" DROP COLUMN "componentId", -DROP COLUMN "componentTag", -ADD COLUMN "userRole" TEXT NOT NULL; diff --git a/prisma/migrations/20240418060611_add_hq_tel_field/migration.sql b/prisma/migrations/20240418060611_add_hq_tel_field/migration.sql deleted file mode 100644 index ae17c14..0000000 --- a/prisma/migrations/20240418060611_add_hq_tel_field/migration.sql +++ /dev/null @@ -1,2 +0,0 @@ --- AlterTable -ALTER TABLE "Branch" ADD COLUMN "telephoneHq" TEXT; diff --git a/prisma/migrations/20240418060739_remove_optional_hq_tel/migration.sql b/prisma/migrations/20240418060739_remove_optional_hq_tel/migration.sql deleted file mode 100644 index 922dfa6..0000000 --- a/prisma/migrations/20240418060739_remove_optional_hq_tel/migration.sql +++ /dev/null @@ -1,8 +0,0 @@ -/* - Warnings: - - - Made the column `telephoneHq` on table `Branch` required. This step will fail if there are existing NULL values in that column. - -*/ --- AlterTable -ALTER TABLE "Branch" ALTER COLUMN "telephoneHq" SET NOT NULL; diff --git a/prisma/migrations/20240418061959_rename_field/migration.sql b/prisma/migrations/20240418061959_rename_field/migration.sql deleted file mode 100644 index 6233aa1..0000000 --- a/prisma/migrations/20240418061959_rename_field/migration.sql +++ /dev/null @@ -1,9 +0,0 @@ -/* - Warnings: - - - You are about to drop the column `telephoneHq` on the `Branch` table. All the data in the column will be lost. - -*/ --- AlterTable -ALTER TABLE "Branch" DROP COLUMN "telephoneHq", -ADD COLUMN "telephoneNo" TEXT; diff --git a/prisma/migrations/20240418062042_remove_optional/migration.sql b/prisma/migrations/20240418062042_remove_optional/migration.sql deleted file mode 100644 index ca8ae37..0000000 --- a/prisma/migrations/20240418062042_remove_optional/migration.sql +++ /dev/null @@ -1,8 +0,0 @@ -/* - Warnings: - - - Made the column `telephoneNo` on table `Branch` required. This step will fail if there are existing NULL values in that column. - -*/ --- AlterTable -ALTER TABLE "Branch" ALTER COLUMN "telephoneNo" SET NOT NULL; diff --git a/prisma/migrations/20240409061231_init/migration.sql b/prisma/migrations/20240628023502_init/migration.sql similarity index 60% rename from prisma/migrations/20240409061231_init/migration.sql rename to prisma/migrations/20240628023502_init/migration.sql index 9c0ad32..c8b655b 100644 --- a/prisma/migrations/20240409061231_init/migration.sql +++ b/prisma/migrations/20240628023502_init/migration.sql @@ -4,6 +4,103 @@ CREATE TYPE "Status" AS ENUM ('CREATED', 'ACTIVE', 'INACTIVE'); -- CreateEnum CREATE TYPE "UserType" AS ENUM ('USER', 'MESSENGER', 'DELEGATE', 'AGENCY'); +-- CreateEnum +CREATE TYPE "CustomerType" AS ENUM ('CORP', 'PERS'); + +-- CreateTable +CREATE TABLE "Menu" ( + "id" TEXT NOT NULL, + "caption" TEXT NOT NULL, + "captionEN" TEXT NOT NULL, + "menuType" TEXT NOT NULL, + "url" TEXT NOT NULL, + "createdBy" TEXT, + "createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, + "updatedBy" TEXT, + "updatedAt" TIMESTAMP(3) NOT NULL, + "parentId" TEXT, + + CONSTRAINT "Menu_pkey" PRIMARY KEY ("id") +); + +-- CreateTable +CREATE TABLE "RoleMenuPermission" ( + "id" TEXT NOT NULL, + "userRole" TEXT NOT NULL, + "permission" TEXT NOT NULL, + "menuId" TEXT NOT NULL, + "createdBy" TEXT, + "createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, + "updatedBy" TEXT, + "updatedAt" TIMESTAMP(3) NOT NULL, + + CONSTRAINT "RoleMenuPermission_pkey" PRIMARY KEY ("id") +); + +-- CreateTable +CREATE TABLE "UserMenuPermission" ( + "id" TEXT NOT NULL, + "permission" TEXT NOT NULL, + "menuId" TEXT NOT NULL, + "userId" TEXT NOT NULL, + "createdBy" TEXT, + "createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, + "updatedBy" TEXT, + "updatedAt" TIMESTAMP(3) NOT NULL, + + CONSTRAINT "UserMenuPermission_pkey" PRIMARY KEY ("id") +); + +-- CreateTable +CREATE TABLE "MenuComponent" ( + "id" TEXT NOT NULL, + "componentId" TEXT NOT NULL, + "componentTag" TEXT NOT NULL, + "menuId" TEXT NOT NULL, + "createdBy" TEXT, + "createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, + "updatedBy" TEXT, + "updatedAt" TIMESTAMP(3) NOT NULL, + + CONSTRAINT "MenuComponent_pkey" PRIMARY KEY ("id") +); + +-- CreateTable +CREATE TABLE "RoleMenuComponentPermission" ( + "id" TEXT NOT NULL, + "userRole" TEXT NOT NULL, + "permission" TEXT NOT NULL, + "menuComponentId" TEXT NOT NULL, + "createdBy" TEXT, + "createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, + "updatedBy" TEXT, + "updatedAt" TIMESTAMP(3) NOT NULL, + + CONSTRAINT "RoleMenuComponentPermission_pkey" PRIMARY KEY ("id") +); + +-- CreateTable +CREATE TABLE "RunningNo" ( + "key" TEXT NOT NULL, + "value" INTEGER NOT NULL, + + CONSTRAINT "RunningNo_pkey" PRIMARY KEY ("key") +); + +-- CreateTable +CREATE TABLE "UserMenuComponentPermission" ( + "id" TEXT NOT NULL, + "userId" TEXT NOT NULL, + "menuComponentId" TEXT NOT NULL, + "permission" TEXT NOT NULL, + "createdBy" TEXT, + "createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, + "updatedBy" TEXT, + "updatedAt" TIMESTAMP(3) NOT NULL, + + CONSTRAINT "UserMenuComponentPermission_pkey" PRIMARY KEY ("id") +); + -- CreateTable CREATE TABLE "Province" ( "id" TEXT NOT NULL, @@ -11,7 +108,7 @@ CREATE TABLE "Province" ( "nameEN" TEXT NOT NULL, "createdBy" TEXT, "createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, - "updateBy" TEXT, + "updatedBy" TEXT, "updatedAt" TIMESTAMP(3) NOT NULL, CONSTRAINT "Province_pkey" PRIMARY KEY ("id") @@ -25,7 +122,7 @@ CREATE TABLE "District" ( "provinceId" TEXT NOT NULL, "createdBy" TEXT, "createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, - "updateBy" TEXT, + "updatedBy" TEXT, "updatedAt" TIMESTAMP(3) NOT NULL, CONSTRAINT "District_pkey" PRIMARY KEY ("id") @@ -40,7 +137,7 @@ CREATE TABLE "SubDistrict" ( "districtId" TEXT NOT NULL, "createdBy" TEXT, "createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, - "updateBy" TEXT, + "updatedBy" TEXT, "updatedAt" TIMESTAMP(3) NOT NULL, CONSTRAINT "SubDistrict_pkey" PRIMARY KEY ("id") @@ -55,20 +152,23 @@ CREATE TABLE "Branch" ( "nameEN" TEXT NOT NULL, "address" TEXT NOT NULL, "addressEN" TEXT NOT NULL, + "telephoneNo" TEXT NOT NULL, "provinceId" TEXT, "districtId" TEXT, "subDistrictId" TEXT, "zipCode" TEXT NOT NULL, "email" TEXT NOT NULL, - "telephoneNo" TEXT NOT NULL, + "contactName" TEXT, + "lineId" TEXT, "latitude" TEXT NOT NULL, "longitude" TEXT NOT NULL, "isHeadOffice" BOOLEAN NOT NULL DEFAULT false, "headOfficeId" TEXT, "status" "Status" NOT NULL DEFAULT 'CREATED', + "statusOrder" INTEGER NOT NULL DEFAULT 0, "createdBy" TEXT, "createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, - "updateBy" TEXT, + "updatedBy" TEXT, "updatedAt" TIMESTAMP(3) NOT NULL, CONSTRAINT "Branch_pkey" PRIMARY KEY ("id") @@ -78,11 +178,10 @@ CREATE TABLE "Branch" ( CREATE TABLE "BranchContact" ( "id" TEXT NOT NULL, "telephoneNo" TEXT NOT NULL, - "lineId" TEXT NOT NULL, "branchId" TEXT NOT NULL, "createdBy" TEXT, "createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, - "updateBy" TEXT, + "updatedBy" TEXT, "updatedAt" TIMESTAMP(3) NOT NULL, CONSTRAINT "BranchContact_pkey" PRIMARY KEY ("id") @@ -95,7 +194,7 @@ CREATE TABLE "BranchUser" ( "userId" TEXT NOT NULL, "createdBy" TEXT, "createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, - "updateBy" TEXT, + "updatedBy" TEXT, "updatedAt" TIMESTAMP(3) NOT NULL, CONSTRAINT "BranchUser_pkey" PRIMARY KEY ("id") @@ -104,12 +203,12 @@ CREATE TABLE "BranchUser" ( -- CreateTable CREATE TABLE "User" ( "id" TEXT NOT NULL, - "keycloakId" TEXT NOT NULL, "code" TEXT, "firstName" TEXT NOT NULL, "firstNameEN" TEXT NOT NULL, "lastName" TEXT NOT NULL, "lastNameEN" TEXT NOT NULL, + "username" TEXT NOT NULL, "gender" TEXT NOT NULL, "address" TEXT NOT NULL, "addressEN" TEXT NOT NULL, @@ -122,6 +221,8 @@ CREATE TABLE "User" ( "registrationNo" TEXT, "startDate" TIMESTAMP(3), "retireDate" TIMESTAMP(3), + "checkpoint" TEXT, + "checkpointEN" TEXT, "userType" "UserType" NOT NULL, "userRole" TEXT NOT NULL, "discountCondition" TEXT, @@ -131,10 +232,13 @@ CREATE TABLE "User" ( "sourceNationality" TEXT, "importNationality" TEXT, "trainingPlace" TEXT, + "responsibleArea" TEXT, + "birthDate" TIMESTAMP(3), "status" "Status" NOT NULL DEFAULT 'CREATED', + "statusOrder" INTEGER NOT NULL DEFAULT 0, "createdBy" TEXT, "createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, - "updateBy" TEXT, + "updatedBy" TEXT, "updatedAt" TIMESTAMP(3) NOT NULL, CONSTRAINT "User_pkey" PRIMARY KEY ("id") @@ -144,14 +248,17 @@ CREATE TABLE "User" ( CREATE TABLE "Customer" ( "id" TEXT NOT NULL, "code" TEXT NOT NULL, - "customerType" TEXT NOT NULL, + "personName" TEXT NOT NULL, + "personNameEN" TEXT, + "customerType" "CustomerType" NOT NULL, "customerName" TEXT NOT NULL, "customerNameEN" TEXT NOT NULL, - "imageUrl" TEXT, + "taxNo" TEXT, "status" "Status" NOT NULL DEFAULT 'CREATED', + "statusOrder" INTEGER NOT NULL DEFAULT 0, "createdBy" TEXT, "createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, - "updateBy" TEXT, + "updatedBy" TEXT, "updatedAt" TIMESTAMP(3) NOT NULL, CONSTRAINT "Customer_pkey" PRIMARY KEY ("id") @@ -160,12 +267,13 @@ CREATE TABLE "Customer" ( -- CreateTable CREATE TABLE "CustomerBranch" ( "id" TEXT NOT NULL, - "branchNo" TEXT NOT NULL, + "branchNo" INTEGER NOT NULL, + "code" TEXT NOT NULL, "legalPersonNo" TEXT NOT NULL, "name" TEXT NOT NULL, "nameEN" TEXT NOT NULL, "customerId" TEXT NOT NULL, - "taxNo" TEXT NOT NULL, + "taxNo" TEXT, "registerName" TEXT NOT NULL, "registerDate" TIMESTAMP(3) NOT NULL, "authorizedCapital" TEXT NOT NULL, @@ -177,12 +285,20 @@ CREATE TABLE "CustomerBranch" ( "zipCode" TEXT NOT NULL, "email" TEXT NOT NULL, "telephoneNo" TEXT NOT NULL, - "latitude" TEXT NOT NULL, - "longitude" TEXT NOT NULL, + "employmentOffice" TEXT NOT NULL, + "bussinessType" TEXT NOT NULL, + "bussinessTypeEN" TEXT NOT NULL, + "jobPosition" TEXT NOT NULL, + "jobPositionEN" TEXT NOT NULL, + "jobDescription" TEXT NOT NULL, + "saleEmployee" TEXT NOT NULL, + "payDate" TIMESTAMP(3) NOT NULL, + "wageRate" INTEGER NOT NULL, "status" "Status" NOT NULL DEFAULT 'CREATED', + "statusOrder" INTEGER NOT NULL DEFAULT 0, "createdBy" TEXT, "createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, - "updateBy" TEXT, + "updatedBy" TEXT, "updatedAt" TIMESTAMP(3) NOT NULL, CONSTRAINT "CustomerBranch_pkey" PRIMARY KEY ("id") @@ -200,42 +316,70 @@ CREATE TABLE "Employee" ( "dateOfBirth" TIMESTAMP(3) NOT NULL, "gender" TEXT NOT NULL, "nationality" TEXT NOT NULL, - "address" TEXT NOT NULL, - "addressEN" TEXT NOT NULL, + "address" TEXT, + "addressEN" TEXT, "provinceId" TEXT, "districtId" TEXT, "subDistrictId" TEXT, "zipCode" TEXT NOT NULL, - "email" TEXT NOT NULL, - "telephoneNo" TEXT NOT NULL, - "arrivalBarricade" TEXT NOT NULL, - "arrivalCardNo" TEXT NOT NULL, + "passportType" TEXT NOT NULL, + "passportNumber" TEXT NOT NULL, + "passportIssueDate" TIMESTAMP(3) NOT NULL, + "passportExpiryDate" TIMESTAMP(3) NOT NULL, + "passportIssuingCountry" TEXT NOT NULL, + "passportIssuingPlace" TEXT NOT NULL, + "previousPassportReference" TEXT, + "visaType" TEXT, + "visaNumber" TEXT, + "visaIssueDate" TIMESTAMP(3), + "visaExpiryDate" TIMESTAMP(3), + "visaIssuingPlace" TEXT, + "visaStayUntilDate" TIMESTAMP(3), + "tm6Number" TEXT, + "entryDate" TIMESTAMP(3), + "workerStatus" TEXT, "customerBranchId" TEXT, "status" "Status" NOT NULL DEFAULT 'CREATED', + "statusOrder" INTEGER NOT NULL DEFAULT 0, "createdBy" TEXT, "createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, - "updateBy" TEXT, + "updatedBy" TEXT, "updatedAt" TIMESTAMP(3) NOT NULL, CONSTRAINT "Employee_pkey" PRIMARY KEY ("id") ); +-- CreateTable +CREATE TABLE "EmployeeHistory" ( + "id" TEXT NOT NULL, + "field" TEXT NOT NULL, + "valueBefore" JSONB NOT NULL, + "valueAfter" JSONB NOT NULL, + "timestamp" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, + "updatedByUserId" TEXT, + "updatedBy" TEXT, + "updatedAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, + "masterId" TEXT NOT NULL, + + CONSTRAINT "EmployeeHistory_pkey" PRIMARY KEY ("id") +); + -- CreateTable CREATE TABLE "EmployeeCheckup" ( "id" TEXT NOT NULL, "employeeId" TEXT NOT NULL, - "checkupResult" TEXT NOT NULL, - "checkupType" TEXT NOT NULL, + "checkupResult" TEXT, + "checkupType" TEXT, "provinceId" TEXT, - "hospitalName" TEXT NOT NULL, - "remark" TEXT NOT NULL, - "medicalBenefitScheme" TEXT NOT NULL, - "insuranceCompany" TEXT NOT NULL, - "coverageStartDate" TIMESTAMP(3) NOT NULL, - "coverageExpireDate" TIMESTAMP(3) NOT NULL, + "hospitalName" TEXT, + "remark" TEXT, + "medicalBenefitScheme" TEXT, + "insuranceCompany" TEXT, + "coverageStartDate" TIMESTAMP(3), + "coverageExpireDate" TIMESTAMP(3), "createdBy" TEXT, "createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, - "updateBy" TEXT, + "updatedBy" TEXT, "updatedAt" TIMESTAMP(3) NOT NULL, CONSTRAINT "EmployeeCheckup_pkey" PRIMARY KEY ("id") @@ -245,17 +389,18 @@ CREATE TABLE "EmployeeCheckup" ( CREATE TABLE "EmployeeWork" ( "id" TEXT NOT NULL, "employeeId" TEXT NOT NULL, - "ownerName" TEXT NOT NULL, - "positionName" TEXT NOT NULL, - "jobType" TEXT NOT NULL, - "workplace" TEXT NOT NULL, - "workPermitNo" TEXT NOT NULL, - "workPermitIssuDate" TIMESTAMP(3) NOT NULL, - "workPermitExpireDate" TIMESTAMP(3) NOT NULL, - "workEndDate" TIMESTAMP(3) NOT NULL, + "ownerName" TEXT, + "positionName" TEXT, + "jobType" TEXT, + "workplace" TEXT, + "workPermitNo" TEXT, + "workPermitIssuDate" TIMESTAMP(3), + "workPermitExpireDate" TIMESTAMP(3), + "workEndDate" TIMESTAMP(3), + "remark" TEXT, "createdBy" TEXT, "createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, - "updateBy" TEXT, + "updatedBy" TEXT, "updatedAt" TIMESTAMP(3) NOT NULL, CONSTRAINT "EmployeeWork_pkey" PRIMARY KEY ("id") @@ -265,13 +410,20 @@ CREATE TABLE "EmployeeWork" ( CREATE TABLE "EmployeeOtherInfo" ( "id" TEXT NOT NULL, "employeeId" TEXT NOT NULL, - "citizenId" TEXT NOT NULL, - "fatherFullName" TEXT NOT NULL, - "motherFullName" TEXT NOT NULL, - "birthPlace" TEXT NOT NULL, + "citizenId" TEXT, + "fatherBirthPlace" TEXT, + "fatherFirstName" TEXT, + "fatherLastName" TEXT, + "motherBirthPlace" TEXT, + "motherFirstName" TEXT, + "motherLastName" TEXT, + "fatherFirstNameEN" TEXT, + "fatherLastNameEN" TEXT, + "motherFirstNameEN" TEXT, + "motherLastNameEN" TEXT, "createdBy" TEXT, "createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, - "updateBy" TEXT, + "updatedBy" TEXT, "updatedAt" TIMESTAMP(3) NOT NULL, CONSTRAINT "EmployeeOtherInfo_pkey" PRIMARY KEY ("id") @@ -283,10 +435,12 @@ CREATE TABLE "Service" ( "code" TEXT NOT NULL, "name" TEXT NOT NULL, "detail" TEXT NOT NULL, + "attributes" JSONB, "status" "Status" NOT NULL DEFAULT 'CREATED', + "statusOrder" INTEGER NOT NULL DEFAULT 0, "createdBy" TEXT, "createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, - "updateBy" TEXT, + "updatedBy" TEXT, "updatedAt" TIMESTAMP(3) NOT NULL, CONSTRAINT "Service_pkey" PRIMARY KEY ("id") @@ -297,11 +451,13 @@ CREATE TABLE "Work" ( "id" TEXT NOT NULL, "order" INTEGER NOT NULL, "name" TEXT NOT NULL, - "serviceId" TEXT NOT NULL, + "attributes" JSONB, "status" "Status" NOT NULL DEFAULT 'CREATED', + "statusOrder" INTEGER NOT NULL DEFAULT 0, + "serviceId" TEXT, "createdBy" TEXT, "createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, - "updateBy" TEXT, + "updatedBy" TEXT, "updatedAt" TIMESTAMP(3) NOT NULL, CONSTRAINT "Work_pkey" PRIMARY KEY ("id") @@ -309,14 +465,15 @@ CREATE TABLE "Work" ( -- CreateTable CREATE TABLE "WorkProduct" ( - "id" TEXT NOT NULL, + "order" INTEGER NOT NULL, "workId" TEXT NOT NULL, + "productId" TEXT NOT NULL, "createdBy" TEXT, "createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, - "updateBy" TEXT, + "updatedBy" TEXT, "updatedAt" TIMESTAMP(3) NOT NULL, - CONSTRAINT "WorkProduct_pkey" PRIMARY KEY ("id") + CONSTRAINT "WorkProduct_pkey" PRIMARY KEY ("workId","productId") ); -- CreateTable @@ -327,9 +484,10 @@ CREATE TABLE "ProductGroup" ( "detail" TEXT NOT NULL, "remark" TEXT NOT NULL, "status" "Status" NOT NULL DEFAULT 'CREATED', + "statusOrder" INTEGER NOT NULL DEFAULT 0, "createdBy" TEXT, "createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, - "updateBy" TEXT, + "updatedBy" TEXT, "updatedAt" TIMESTAMP(3) NOT NULL, CONSTRAINT "ProductGroup_pkey" PRIMARY KEY ("id") @@ -343,10 +501,12 @@ CREATE TABLE "ProductType" ( "detail" TEXT NOT NULL, "remark" TEXT NOT NULL, "status" "Status" NOT NULL DEFAULT 'CREATED', + "statusOrder" INTEGER NOT NULL DEFAULT 0, "createdBy" TEXT, "createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, - "updateBy" TEXT, + "updatedBy" TEXT, "updatedAt" TIMESTAMP(3) NOT NULL, + "productGroupId" TEXT NOT NULL, CONSTRAINT "ProductType_pkey" PRIMARY KEY ("id") ); @@ -357,22 +517,49 @@ CREATE TABLE "Product" ( "code" TEXT NOT NULL, "name" TEXT NOT NULL, "detail" TEXT NOT NULL, - "process" TEXT NOT NULL, - "price" INTEGER NOT NULL, - "agentPrice" INTEGER NOT NULL, - "serviceCharge" INTEGER NOT NULL, - "imageUrl" TEXT NOT NULL, + "process" INTEGER NOT NULL, + "price" DOUBLE PRECISION NOT NULL, + "agentPrice" DOUBLE PRECISION NOT NULL, + "serviceCharge" DOUBLE PRECISION NOT NULL, "status" "Status" NOT NULL DEFAULT 'CREATED', + "statusOrder" INTEGER NOT NULL DEFAULT 0, + "remark" TEXT, "productTypeId" TEXT, - "productGroupId" TEXT, "createdBy" TEXT, "createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, - "updateBy" TEXT, + "updatedBy" TEXT, "updatedAt" TIMESTAMP(3) NOT NULL, CONSTRAINT "Product_pkey" PRIMARY KEY ("id") ); +-- CreateIndex +CREATE UNIQUE INDEX "RunningNo_key_key" ON "RunningNo"("key"); + +-- AddForeignKey +ALTER TABLE "Menu" ADD CONSTRAINT "Menu_parentId_fkey" FOREIGN KEY ("parentId") REFERENCES "Menu"("id") ON DELETE SET NULL ON UPDATE CASCADE; + +-- AddForeignKey +ALTER TABLE "RoleMenuPermission" ADD CONSTRAINT "RoleMenuPermission_menuId_fkey" FOREIGN KEY ("menuId") REFERENCES "Menu"("id") ON DELETE RESTRICT ON UPDATE CASCADE; + +-- AddForeignKey +ALTER TABLE "UserMenuPermission" ADD CONSTRAINT "UserMenuPermission_menuId_fkey" FOREIGN KEY ("menuId") REFERENCES "Menu"("id") ON DELETE RESTRICT ON UPDATE CASCADE; + +-- AddForeignKey +ALTER TABLE "UserMenuPermission" ADD CONSTRAINT "UserMenuPermission_userId_fkey" FOREIGN KEY ("userId") REFERENCES "User"("id") ON DELETE RESTRICT ON UPDATE CASCADE; + +-- AddForeignKey +ALTER TABLE "MenuComponent" ADD CONSTRAINT "MenuComponent_menuId_fkey" FOREIGN KEY ("menuId") REFERENCES "Menu"("id") ON DELETE RESTRICT ON UPDATE CASCADE; + +-- AddForeignKey +ALTER TABLE "RoleMenuComponentPermission" ADD CONSTRAINT "RoleMenuComponentPermission_menuComponentId_fkey" FOREIGN KEY ("menuComponentId") REFERENCES "MenuComponent"("id") ON DELETE RESTRICT ON UPDATE CASCADE; + +-- AddForeignKey +ALTER TABLE "UserMenuComponentPermission" ADD CONSTRAINT "UserMenuComponentPermission_userId_fkey" FOREIGN KEY ("userId") REFERENCES "User"("id") ON DELETE RESTRICT ON UPDATE CASCADE; + +-- AddForeignKey +ALTER TABLE "UserMenuComponentPermission" ADD CONSTRAINT "UserMenuComponentPermission_menuComponentId_fkey" FOREIGN KEY ("menuComponentId") REFERENCES "MenuComponent"("id") ON DELETE RESTRICT ON UPDATE CASCADE; + -- AddForeignKey ALTER TABLE "District" ADD CONSTRAINT "District_provinceId_fkey" FOREIGN KEY ("provinceId") REFERENCES "Province"("id") ON DELETE CASCADE ON UPDATE CASCADE; @@ -433,6 +620,12 @@ ALTER TABLE "Employee" ADD CONSTRAINT "Employee_subDistrictId_fkey" FOREIGN KEY -- AddForeignKey ALTER TABLE "Employee" ADD CONSTRAINT "Employee_customerBranchId_fkey" FOREIGN KEY ("customerBranchId") REFERENCES "CustomerBranch"("id") ON DELETE SET NULL ON UPDATE CASCADE; +-- AddForeignKey +ALTER TABLE "EmployeeHistory" ADD CONSTRAINT "EmployeeHistory_updatedByUserId_fkey" FOREIGN KEY ("updatedByUserId") REFERENCES "User"("id") ON DELETE SET NULL ON UPDATE CASCADE; + +-- AddForeignKey +ALTER TABLE "EmployeeHistory" ADD CONSTRAINT "EmployeeHistory_masterId_fkey" FOREIGN KEY ("masterId") REFERENCES "Employee"("id") ON DELETE CASCADE ON UPDATE CASCADE; + -- AddForeignKey ALTER TABLE "EmployeeCheckup" ADD CONSTRAINT "EmployeeCheckup_employeeId_fkey" FOREIGN KEY ("employeeId") REFERENCES "Employee"("id") ON DELETE CASCADE ON UPDATE CASCADE; @@ -452,7 +645,10 @@ ALTER TABLE "Work" ADD CONSTRAINT "Work_serviceId_fkey" FOREIGN KEY ("serviceId" ALTER TABLE "WorkProduct" ADD CONSTRAINT "WorkProduct_workId_fkey" FOREIGN KEY ("workId") REFERENCES "Work"("id") ON DELETE CASCADE ON UPDATE CASCADE; -- AddForeignKey -ALTER TABLE "Product" ADD CONSTRAINT "Product_productTypeId_fkey" FOREIGN KEY ("productTypeId") REFERENCES "ProductType"("id") ON DELETE SET NULL ON UPDATE CASCADE; +ALTER TABLE "WorkProduct" ADD CONSTRAINT "WorkProduct_productId_fkey" FOREIGN KEY ("productId") REFERENCES "Product"("id") ON DELETE CASCADE ON UPDATE CASCADE; -- AddForeignKey -ALTER TABLE "Product" ADD CONSTRAINT "Product_productGroupId_fkey" FOREIGN KEY ("productGroupId") REFERENCES "ProductGroup"("id") ON DELETE SET NULL ON UPDATE CASCADE; +ALTER TABLE "ProductType" ADD CONSTRAINT "ProductType_productGroupId_fkey" FOREIGN KEY ("productGroupId") REFERENCES "ProductGroup"("id") ON DELETE CASCADE ON UPDATE CASCADE; + +-- AddForeignKey +ALTER TABLE "Product" ADD CONSTRAINT "Product_productTypeId_fkey" FOREIGN KEY ("productTypeId") REFERENCES "ProductType"("id") ON DELETE SET NULL ON UPDATE CASCADE; diff --git a/prisma/schema.prisma b/prisma/schema.prisma index 1652ee2..3912749 100644 --- a/prisma/schema.prisma +++ b/prisma/schema.prisma @@ -2,6 +2,11 @@ generator client { provider = "prisma-client-js" } +generator kysely { + provider = "prisma-kysely" + output = "../src/generated/kysely" +} + datasource db { provider = "postgresql" url = env("DATABASE_URL") @@ -17,7 +22,7 @@ model Menu { createdBy String? createdAt DateTime @default(now()) - updateBy String? + updatedBy String? updatedAt DateTime @updatedAt parent Menu? @relation(name: "MenuRelation", fields: [parentId], references: [id]) @@ -40,7 +45,7 @@ model RoleMenuPermission { createdBy String? createdAt DateTime @default(now()) - updateBy String? + updatedBy String? updatedAt DateTime @updatedAt } @@ -57,7 +62,7 @@ model UserMenuPermission { createdBy String? createdAt DateTime @default(now()) - updateBy String? + updatedBy String? updatedAt DateTime @updatedAt } @@ -72,7 +77,7 @@ model MenuComponent { createdBy String? createdAt DateTime @default(now()) - updateBy String? + updatedBy String? updatedAt DateTime @updatedAt roleMenuComponentPermission RoleMenuComponentPermission[] userMennuComponentPermission UserMenuComponentPermission[] @@ -89,10 +94,15 @@ model RoleMenuComponentPermission { createdBy String? createdAt DateTime @default(now()) - updateBy String? + updatedBy String? updatedAt DateTime @updatedAt } +model RunningNo { + key String @id @unique + value Int +} + model UserMenuComponentPermission { id String @id @default(uuid()) @@ -106,7 +116,7 @@ model UserMenuComponentPermission { createdBy String? createdAt DateTime @default(now()) - updateBy String? + updatedBy String? updatedAt DateTime @updatedAt } @@ -117,7 +127,7 @@ model Province { createdBy String? createdAt DateTime @default(now()) - updateBy String? + updatedBy String? updatedAt DateTime @updatedAt district District[] @@ -138,7 +148,7 @@ model District { createdBy String? createdAt DateTime @default(now()) - updateBy String? + updatedBy String? updatedAt DateTime @updatedAt subDistrict SubDistrict[] @@ -159,7 +169,7 @@ model SubDistrict { createdBy String? createdAt DateTime @default(now()) - updateBy String? + updatedBy String? updatedAt DateTime @updatedAt branch Branch[] @@ -207,11 +217,12 @@ model Branch { headOffice Branch? @relation(name: "HeadOfficeRelation", fields: [headOfficeId], references: [id]) headOfficeId String? - status Status @default(CREATED) + status Status @default(CREATED) + statusOrder Int @default(0) createdBy String? createdAt DateTime @default(now()) - updateBy String? + updatedBy String? updatedAt DateTime @updatedAt branch Branch[] @relation(name: "HeadOfficeRelation") @@ -228,7 +239,7 @@ model BranchContact { createdBy String? createdAt DateTime @default(now()) - updateBy String? + updatedBy String? updatedAt DateTime @updatedAt } @@ -243,7 +254,7 @@ model BranchUser { createdBy String? createdAt DateTime @default(now()) - updateBy String? + updatedBy String? updatedAt DateTime @updatedAt } @@ -307,16 +318,18 @@ model User { birthDate DateTime? - status Status @default(CREATED) + status Status @default(CREATED) + statusOrder Int @default(0) createdBy String? createdAt DateTime @default(now()) - updateBy String? + updatedBy String? updatedAt DateTime @updatedAt branch BranchUser[] userMenuPermission UserMenuPermission[] userMenuComponentPermission UserMenuComponentPermission[] + employeeHistory EmployeeHistory[] } enum CustomerType { @@ -327,15 +340,19 @@ enum CustomerType { model Customer { id String @id @default(uuid()) code String + personName String + personNameEN String? customerType CustomerType customerName String customerNameEN String + taxNo String? - status Status @default(CREATED) + status Status @default(CREATED) + statusOrder Int @default(0) createdBy String? createdAt DateTime @default(now()) - updateBy String? + updatedBy String? updatedAt DateTime @updatedAt branch CustomerBranch[] @@ -343,7 +360,8 @@ model Customer { model CustomerBranch { id String @id @default(uuid()) - branchNo String + branchNo Int + code String legalPersonNo String name String @@ -352,7 +370,7 @@ model CustomerBranch { customer Customer @relation(fields: [customerId], references: [id], onDelete: Cascade) customerId String - taxNo String + taxNo String? registerName String registerDate DateTime authorizedCapital String @@ -374,14 +392,22 @@ model CustomerBranch { email String telephoneNo String - latitude String - longitude String + employmentOffice String + bussinessType String + bussinessTypeEN String + jobPosition String + jobPositionEN String + jobDescription String + saleEmployee String + payDate DateTime + wageRate Int - status Status @default(CREATED) + status Status @default(CREATED) + statusOrder Int @default(0) createdBy String? createdAt DateTime @default(now()) - updateBy String? + updatedBy String? updatedAt DateTime @updatedAt employee Employee[] @@ -401,8 +427,8 @@ model Employee { gender String nationality String - address String - addressEN String + address String? + addressEN String? province Province? @relation(fields: [provinceId], references: [id], onDelete: SetNull) provinceId String? @@ -415,25 +441,57 @@ model Employee { zipCode String - email String - telephoneNo String + passportType String + passportNumber String + passportIssueDate DateTime + passportExpiryDate DateTime + passportIssuingCountry String + passportIssuingPlace String + previousPassportReference String? - arrivalBarricade String - arrivalCardNo String + visaType String? + visaNumber String? + visaIssueDate DateTime? + visaExpiryDate DateTime? + visaIssuingPlace String? + visaStayUntilDate DateTime? + tm6Number String? + entryDate DateTime? + workerStatus String? customerBranch CustomerBranch? @relation(fields: [customerBranchId], references: [id], onDelete: SetNull) customerBranchId String? - status Status @default(CREATED) + status Status @default(CREATED) + statusOrder Int @default(0) createdBy String? createdAt DateTime @default(now()) - updateBy String? + updatedBy String? updatedAt DateTime @updatedAt employeeCheckup EmployeeCheckup[] employeeWork EmployeeWork[] employeeOtherInfo EmployeeOtherInfo[] + + editHistory EmployeeHistory[] +} + +model EmployeeHistory { + id String @id @default(uuid()) + field String + valueBefore Json + valueAfter Json + + timestamp DateTime @default(now()) + + updatedByUserId String? + updatedByUser User? @relation(fields: [updatedByUserId], references: [id]) + updatedBy String? + updatedAt DateTime @default(now()) + + masterId String + master Employee @relation(fields: [masterId], references: [id], onDelete: Cascade) } model EmployeeCheckup { @@ -442,22 +500,22 @@ model EmployeeCheckup { employee Employee @relation(fields: [employeeId], references: [id], onDelete: Cascade) employeeId String - checkupResult String - checkupType String + checkupResult String? + checkupType String? province Province? @relation(fields: [provinceId], references: [id], onDelete: SetNull) provinceId String? - hospitalName String - remark String - medicalBenefitScheme String - insuranceCompany String - coverageStartDate DateTime - coverageExpireDate DateTime + hospitalName String? + remark String? + medicalBenefitScheme String? + insuranceCompany String? + coverageStartDate DateTime? + coverageExpireDate DateTime? createdBy String? createdAt DateTime @default(now()) - updateBy String? + updatedBy String? updatedAt DateTime @updatedAt } @@ -467,18 +525,19 @@ model EmployeeWork { employee Employee @relation(fields: [employeeId], references: [id], onDelete: Cascade) employeeId String - ownerName String - positionName String - jobType String - workplace String - workPermitNo String - workPermitIssuDate DateTime - workPermitExpireDate DateTime - workEndDate DateTime + ownerName String? + positionName String? + jobType String? + workplace String? + workPermitNo String? + workPermitIssuDate DateTime? + workPermitExpireDate DateTime? + workEndDate DateTime? + remark String? createdBy String? createdAt DateTime @default(now()) - updateBy String? + updatedBy String? updatedAt DateTime @updatedAt } @@ -488,61 +547,78 @@ model EmployeeOtherInfo { employee Employee @relation(fields: [employeeId], references: [id], onDelete: Cascade) employeeId String - citizenId String - fatherFullName String - motherFullName String - birthPlace String + citizenId String? + fatherBirthPlace String? + fatherFirstName String? + fatherLastName String? + motherBirthPlace String? + motherFirstName String? + motherLastName String? + + fatherFirstNameEN String? + fatherLastNameEN String? + motherFirstNameEN String? + motherLastNameEN String? createdBy String? createdAt DateTime @default(now()) - updateBy String? + updatedBy String? updatedAt DateTime @updatedAt } model Service { id String @id @default(uuid()) - code String - name String - detail String + code String + name String + detail String + attributes Json? - status Status @default(CREATED) + status Status @default(CREATED) + statusOrder Int @default(0) + + work Work[] createdBy String? createdAt DateTime @default(now()) - updateBy String? + updatedBy String? updatedAt DateTime @updatedAt - work Work[] } model Work { id String @id @default(uuid()) - order Int - name String + order Int + name String + attributes Json? - service Service @relation(fields: [serviceId], references: [id], onDelete: Cascade) - serviceId String + status Status @default(CREATED) + statusOrder Int @default(0) - status Status @default(CREATED) - - createdBy String? - createdAt DateTime @default(now()) - updateBy String? - updatedAt DateTime @updatedAt - WorkProduct WorkProduct[] -} - -model WorkProduct { - id String @id @default(uuid()) - - work Work @relation(fields: [workId], references: [id], onDelete: Cascade) - workId String + service Service? @relation(fields: [serviceId], references: [id], onDelete: Cascade) + serviceId String? createdBy String? createdAt DateTime @default(now()) - updateBy String? + updatedBy String? updatedAt DateTime @updatedAt + + productOnWork WorkProduct[] +} + +model WorkProduct { + order Int + work Work @relation(fields: [workId], references: [id], onDelete: Cascade) + workId String + product Product @relation(fields: [productId], references: [id], onDelete: Cascade) + productId String + + createdBy String? + createdAt DateTime @default(now()) + updatedBy String? + updatedAt DateTime @updatedAt + + @@id([workId, productId]) } model ProductGroup { @@ -553,13 +629,15 @@ model ProductGroup { detail String remark String - status Status @default(CREATED) + status Status @default(CREATED) + statusOrder Int @default(0) createdBy String? - createdAt DateTime @default(now()) - updateBy String? - updatedAt DateTime @updatedAt - Product Product[] + createdAt DateTime @default(now()) + updatedBy String? + updatedAt DateTime @updatedAt + + type ProductType[] } model ProductType { @@ -570,13 +648,17 @@ model ProductType { detail String remark String - status Status @default(CREATED) + status Status @default(CREATED) + statusOrder Int @default(0) createdBy String? createdAt DateTime @default(now()) - updateBy String? + updatedBy String? updatedAt DateTime @updatedAt + productGroup ProductGroup @relation(fields: [productGroupId], references: [id], onDelete: Cascade) + productGroupId String + product Product[] } @@ -586,22 +668,23 @@ model Product { code String name String detail String - process String - price Int - agentPrice Int - serviceCharge Int - imageUrl String + process Int + price Float + agentPrice Float + serviceCharge Float - status Status @default(CREATED) + status Status @default(CREATED) + statusOrder Int @default(0) + + remark String? productType ProductType? @relation(fields: [productTypeId], references: [id], onDelete: SetNull) productTypeId String? - productGroup ProductGroup? @relation(fields: [productGroupId], references: [id], onDelete: SetNull) - productGroupId String? + workProduct WorkProduct[] createdBy String? createdAt DateTime @default(now()) - updateBy String? + updatedBy String? updatedAt DateTime @updatedAt } diff --git a/src/controllers/address-controller.ts b/src/controllers/address-controller.ts index c836829..ba123bf 100644 --- a/src/controllers/address-controller.ts +++ b/src/controllers/address-controller.ts @@ -1,7 +1,7 @@ import { Controller, Get, Path, Route, Tags } from "tsoa"; import prisma from "../db"; -@Route("api/address") +@Route("api/v1/address") @Tags("Address") export class AddressController extends Controller { @Get("province") diff --git a/src/controllers/branch-contact-controller.ts b/src/controllers/branch-contact-controller.ts index b71aea5..d98c966 100644 --- a/src/controllers/branch-contact-controller.ts +++ b/src/controllers/branch-contact-controller.ts @@ -26,7 +26,7 @@ type BranchContactUpdate = { telephoneNo?: string; }; -@Route("api/branch/{branchId}/contact") +@Route("api/v1/branch/{branchId}/contact") @Tags("Branch Contact") @Security("keycloak") export class BranchContactController extends Controller { @@ -62,7 +62,7 @@ export class BranchContactController extends Controller { throw new HttpError( HttpStatus.NOT_FOUND, "Branch contact cannot be found.", - "data_not_found", + "branchContactNotFound", ); } @@ -76,14 +76,10 @@ export class BranchContactController extends Controller { @Body() body: BranchContactCreate, ) { if (!(await prisma.branch.findFirst({ where: { id: branchId } }))) { - throw new HttpError( - HttpStatus.BAD_REQUEST, - "Branch not found.", - "missing_or_invalid_parameter", - ); + throw new HttpError(HttpStatus.BAD_REQUEST, "Branch cannot be found.", "branchBadReq"); } const record = await prisma.branchContact.create({ - data: { ...body, branchId, createdBy: req.user.name, updateBy: req.user.name }, + data: { ...body, branchId, createdBy: req.user.name, updatedBy: req.user.name }, }); this.setStatus(HttpStatus.CREATED); @@ -106,12 +102,12 @@ export class BranchContactController extends Controller { throw new HttpError( HttpStatus.NOT_FOUND, "Branch contact cannot be found.", - "data_not_found", + "branchContactNotFound", ); } const record = await prisma.branchContact.update({ - data: { ...body, updateBy: req.user.name }, + data: { ...body, updatedBy: req.user.name }, where: { id: contactId, branchId }, }); @@ -125,7 +121,7 @@ export class BranchContactController extends Controller { throw new HttpError( HttpStatus.NOT_FOUND, "Branch contact cannot be found.", - "data_not_found", + "branchContactNotFound", ); } } diff --git a/src/controllers/branch-controller.ts b/src/controllers/branch-controller.ts index 9aa12a3..50bce01 100644 --- a/src/controllers/branch-controller.ts +++ b/src/controllers/branch-controller.ts @@ -57,7 +57,7 @@ type BranchUpdate = { address?: string; zipCode?: string; email?: string; - telephoneNo: string; + telephoneNo?: string; contactName?: string; contact?: string | string[] | null; lineId?: string; @@ -78,7 +78,7 @@ function branchImageLoc(id: string) { return `branch/branch-img-${id}`; } -@Route("api/branch") +@Route("api/v1/branch") @Tags("Branch") @Security("keycloak") export class BranchController extends Controller { @@ -109,13 +109,26 @@ export class BranchController extends Controller { const record = await prisma.branch.findMany({ select: { id: true, + headOfficeId: true, + isHeadOffice: true, nameEN: true, name: true, - isHeadOffice: true, }, + orderBy: [{ isHeadOffice: "desc" }, { createdAt: "asc" }], }); - return record.map((a) => + const sort = record.reduce<(typeof record)[]>((acc, curr) => { + for (const i of acc) { + if (i[0].id === curr.headOfficeId) { + i.push(curr); + return acc; + } + } + acc.push([curr]); + return acc; + }, []); + + return sort.flat().map((a) => Object.assign(a, { count: list.find((b) => b.branchId === a.id)?._count ?? 0, }), @@ -195,7 +208,7 @@ export class BranchController extends Controller { }); if (!record) { - throw new HttpError(HttpStatus.NOT_FOUND, "Branch cannot be found.", "data_not_found"); + throw new HttpError(HttpStatus.NOT_FOUND, "Branch cannot be found.", "branchNotFound"); } return Object.assign(record, { @@ -216,58 +229,70 @@ export class BranchController extends Controller { throw new HttpError( HttpStatus.BAD_REQUEST, "Province cannot be found.", - "missing_or_invalid_parameter", + "relationProvinceNotFound", ); if (body.districtId && !district) throw new HttpError( HttpStatus.BAD_REQUEST, "District cannot be found.", - "missing_or_invalid_parameter", + "relationDistrictNotFound", ); if (body.subDistrictId && !subDistrict) throw new HttpError( HttpStatus.BAD_REQUEST, "Sub-district cannot be found.", - "missing_or_invalid_parameter", + "relationSubDistrictNotFound", ); if (body.headOfficeId && !head) throw new HttpError( HttpStatus.BAD_REQUEST, - "Head branch cannot be found.", - "missing_or_invalid_parameter", + "Headquaters cannot be found.", + "relationHQNotFound", ); const { provinceId, districtId, subDistrictId, headOfficeId, contact, ...rest } = body; const year = new Date().getFullYear(); - const last = await prisma.branch.findFirst({ - orderBy: { createdAt: "desc" }, - where: { headOfficeId: headOfficeId ?? null }, - }); + const record = await prisma.$transaction( + async (tx) => { + const last = await tx.runningNo.upsert({ + where: { + key: !headOfficeId ? `HQ${year.toString().slice(2)}` : `BR${head?.code.slice(2, 5)}`, + }, + create: { + key: !headOfficeId ? `HQ${year.toString().slice(2)}` : `BR${head?.code.slice(2, 5)}`, + value: 1, + }, + update: { value: { increment: 1 } }, + }); - const code = !headOfficeId - ? `HQ${year.toString().slice(2)}${+(last?.code.slice(-1) || 0) + 1}` - : `BR${head?.code.slice(2, 5)}${(+(last?.code.slice(-2) || 0) + 1).toString().padStart(2, "0")}`; + const code = !headOfficeId + ? `HQ${year.toString().slice(2)}${last.value}` + : `BR${head?.code.slice(2, 5)}${last.value.toString().padStart(2, "0")}`; - const record = await prisma.branch.create({ - include: { - province: true, - district: true, - subDistrict: true, + return await tx.branch.create({ + include: { + province: true, + district: true, + subDistrict: true, + }, + data: { + ...rest, + statusOrder: +(rest.status === "INACTIVE"), + code, + isHeadOffice: !headOfficeId, + province: { connect: provinceId ? { id: provinceId } : undefined }, + district: { connect: districtId ? { id: districtId } : undefined }, + subDistrict: { connect: subDistrictId ? { id: subDistrictId } : undefined }, + headOffice: { connect: headOfficeId ? { id: headOfficeId } : undefined }, + createdBy: req.user.name, + updatedBy: req.user.name, + }, + }); }, - data: { - ...rest, - code, - isHeadOffice: !headOfficeId, - province: { connect: provinceId ? { id: provinceId } : undefined }, - district: { connect: districtId ? { id: districtId } : undefined }, - subDistrict: { connect: subDistrictId ? { id: subDistrictId } : undefined }, - headOffice: { connect: headOfficeId ? { id: headOfficeId } : undefined }, - createdBy: req.user.name, - updateBy: req.user.name, - }, - }); + { isolationLevel: Prisma.TransactionIsolationLevel.Serializable }, + ); if (headOfficeId) { await prisma.branch.updateMany({ @@ -313,8 +338,8 @@ export class BranchController extends Controller { if (body.headOfficeId === branchId) throw new HttpError( HttpStatus.BAD_REQUEST, - "Cannot make this as head office and branch at the same time.", - "missing_or_invalid_parameter", + "Cannot make this as headquaters and branch at the same time.", + "cantMakeHQAndBranchSameTime", ); if (body.subDistrictId || body.districtId || body.provinceId || body.headOfficeId) { @@ -328,38 +353,39 @@ export class BranchController extends Controller { throw new HttpError( HttpStatus.BAD_REQUEST, "Province cannot be found.", - "missing_or_invalid_parameter", + "relationProvinceNotFound", ); if (body.districtId && !district) throw new HttpError( HttpStatus.BAD_REQUEST, "District cannot be found.", - "missing_or_invalid_parameter", + "relationDistrictNotFound", ); if (body.subDistrictId && !subDistrict) throw new HttpError( HttpStatus.BAD_REQUEST, "Sub-district cannot be found.", - "missing_or_invalid_parameter", + "relationSubDistrictNotFound", ); if (body.headOfficeId && !branch) throw new HttpError( HttpStatus.BAD_REQUEST, - "Head branch cannot be found.", - "missing_or_invalid_parameter", + "Headquaters cannot be found.", + "relationHQNotFound", ); } const { provinceId, districtId, subDistrictId, headOfficeId, contact, ...rest } = body; if (!(await prisma.branch.findUnique({ where: { id: branchId } }))) { - throw new HttpError(HttpStatus.NOT_FOUND, "Branch cannot be found.", "data_not_found"); + throw new HttpError(HttpStatus.NOT_FOUND, "Branch cannot be found.", "branchNotFound"); } const record = await prisma.branch.update({ include: { province: true, district: true, subDistrict: true }, data: { ...rest, + statusOrder: +(rest.status === "INACTIVE"), isHeadOffice: headOfficeId !== undefined ? headOfficeId === null : undefined, province: { connect: provinceId ? { id: provinceId } : undefined, @@ -377,7 +403,7 @@ export class BranchController extends Controller { connect: headOfficeId ? { id: headOfficeId } : undefined, disconnect: headOfficeId === null || undefined, }, - updateBy: req.user.name, + updatedBy: req.user.name, }, where: { id: branchId }, }); @@ -421,11 +447,11 @@ export class BranchController extends Controller { }); if (!record) { - throw new HttpError(HttpStatus.NOT_FOUND, "Branch cannot be found.", "data_not_found"); + throw new HttpError(HttpStatus.NOT_FOUND, "Branch cannot be found.", "branchNotFound"); } if (record.status !== Status.CREATED) { - throw new HttpError(HttpStatus.FORBIDDEN, "Branch is in used.", "data_in_used"); + throw new HttpError(HttpStatus.FORBIDDEN, "Branch is in used.", "branchInUsed"); } await minio.removeObject(MINIO_BUCKET, lineImageLoc(branchId), { diff --git a/src/controllers/branch-user-controller.ts b/src/controllers/branch-user-controller.ts index d33b307..7dfed95 100644 --- a/src/controllers/branch-user-controller.ts +++ b/src/controllers/branch-user-controller.ts @@ -1,4 +1,4 @@ -import { Prisma, Status, UserType } from "@prisma/client"; +import { Branch, Prisma, Status, User, UserType } from "@prisma/client"; import { Body, Controller, @@ -20,7 +20,38 @@ import { RequestWithUser } from "../interfaces/user"; type BranchUserBody = { user: string[] }; -@Route("api/branch/{branchId}/user") +async function userBranchCodeGen(branch: Branch, user: User[]) { + await prisma.$transaction( + async (tx) => { + for (const usr of user) { + if (usr.code !== null) continue; + + const typ = usr.userType; + + const last = await tx.runningNo.upsert({ + where: { + key: `BR_USR_${branch.code.slice(4).padEnd(3, "0")}${typ !== "USER" ? typ.charAt(0).toLocaleUpperCase() : ""}`, + }, + create: { + key: `BR_USR_${branch.code.slice(4).padEnd(3, "0")}${typ !== "USER" ? typ.charAt(0).toLocaleUpperCase() : ""}`, + value: 1, + }, + update: { value: { increment: 1 } }, + }); + + await prisma.user.update({ + where: { id: usr.id }, + data: { + code: `${last.key.slice(7)}${last.value.toString().padStart(4, "0")}`, + }, + }); + } + }, + { isolationLevel: Prisma.TransactionIsolationLevel.Serializable }, + ); +} + +@Route("api/v1/branch/{branchId}/user") @Tags("Branch User") @Security("keycloak") export class BranchUserController extends Controller { @@ -85,7 +116,7 @@ export class BranchUserController extends Controller { throw new HttpError( HttpStatus.BAD_REQUEST, "Branch cannot be found.", - "missing_or_invalid_parameter", + "branchBadReq", ); } @@ -93,7 +124,7 @@ export class BranchUserController extends Controller { throw new HttpError( HttpStatus.BAD_REQUEST, "One or more user cannot be found.", - "missing_or_invalid_parameter", + "oneOrMoreUserBadReq", ); } @@ -109,47 +140,12 @@ export class BranchUserController extends Controller { branchId, userId: v.id, createdBy: req.user.name, - updateBy: req.user.name, + updatedBy: req.user.name, })), }), ]); - const group: Record = { - USER: [], - AGENCY: [], - DELEGATE: [], - MESSENGER: [], - }; - - for (const u of user) group[u.userType].push(u.id); - - for (const g of Object.values(UserType)) { - if (group[g].length === 0) continue; - - const last = await prisma.branchUser.findFirst({ - orderBy: { createdAt: "desc" }, - include: { user: true }, - where: { - branchId, - user: { - userType: g, - code: { startsWith: `${branch.code.slice(4).padEnd(3, "0")}` }, - }, - }, - }); - - const code = (idx: number) => - `${branch.code.slice(4).padEnd(3, "0")}${g !== "USER" ? g.charAt(0) : ""}${(+(last?.user.code?.slice(-4) || 0) + idx + 1).toString().padStart(4, "0")}`; - - await prisma.$transaction( - group[g].map((v, i) => - prisma.user.updateMany({ - where: { id: v, code: null }, - data: { code: code(i) }, - }), - ), - ); - } + await userBranchCodeGen(branch, user); } @Delete() @@ -182,7 +178,7 @@ export class BranchUserController extends Controller { type UserBranchBody = { branch: string[] }; -@Route("api/user/{userId}/branch") +@Route("api/v1/user/{userId}/branch") @Tags("Branch User") @Security("keycloak") export class UserBranchController extends Controller { @@ -238,7 +234,7 @@ export class UserBranchController extends Controller { throw new HttpError( HttpStatus.BAD_REQUEST, "One or more branch cannot be found.", - "missing_or_invalid_parameter", + "oneOrMoreBranchBadReq", ); } @@ -254,7 +250,7 @@ export class UserBranchController extends Controller { branchId: v.id, userId, createdBy: req.user.name, - updateBy: req.user.name, + updatedBy: req.user.name, })), }); diff --git a/src/controllers/customer-branch-controller.ts b/src/controllers/customer-branch-controller.ts index c2220cc..d07d7b4 100644 --- a/src/controllers/customer-branch-controller.ts +++ b/src/controllers/customer-branch-controller.ts @@ -29,14 +29,18 @@ function imageLocation(id: string) { return `employee/profile-img-${id}`; } -type CustomerBranchCreate = { +function attachmentLocation(customerId: string, branchId: string) { + return `customer/${customerId}/branch/${branchId}`; +} + +export type CustomerBranchCreate = { customerId: string; status?: Status; legalPersonNo: string; - taxNo: string; + taxNo: string | null; name: string; nameEN: string; addressEN: string; @@ -44,26 +48,34 @@ type CustomerBranchCreate = { zipCode: string; email: string; telephoneNo: string; - longitude: string; - latitude: string; registerName: string; registerDate: Date; authorizedCapital: string; + employmentOffice: string; + bussinessType: string; + bussinessTypeEN: string; + jobPosition: string; + jobPositionEN: string; + jobDescription: string; + saleEmployee: string; + payDate: Date; + wageRate: number; + subDistrictId?: string | null; districtId?: string | null; provinceId?: string | null; }; -type CustomerBranchUpdate = { +export type CustomerBranchUpdate = { customerId?: string; status?: "ACTIVE" | "INACTIVE"; legalPersonNo?: string; - taxNo?: string; + taxNo?: string | null; name?: string; nameEN?: string; addressEN?: string; @@ -71,44 +83,82 @@ type CustomerBranchUpdate = { zipCode?: string; email?: string; telephoneNo?: string; - longitude?: string; - latitude?: string; registerName?: string; registerDate?: Date; authorizedCapital?: string; + employmentOffice?: string; + bussinessType?: string; + bussinessTypeEN?: string; + jobPosition?: string; + jobPositionEN?: string; + jobDescription?: string; + saleEmployee?: string; + payDate?: Date; + wageRate?: number; + subDistrictId?: string | null; districtId?: string | null; provinceId?: string | null; }; -@Route("api/customer-branch") +@Route("api/v1/customer-branch") @Tags("Customer Branch") @Security("keycloak") export class CustomerBranchController extends Controller { @Get() async list( @Query() zipCode?: string, + @Query() customerId?: string, + @Query() status?: Status, + @Query() includeCustomer?: boolean, @Query() query: string = "", @Query() page: number = 1, @Query() pageSize: number = 30, ) { + const filterStatus = (val?: Status) => { + if (!val) return {}; + + return val !== Status.CREATED && val !== Status.ACTIVE + ? { status: val } + : { OR: [{ status: Status.CREATED }, { status: Status.ACTIVE }] }; + }; + const where = { OR: [ - { nameEN: { contains: query }, zipCode }, - { name: { contains: query }, zipCode }, - { email: { contains: query }, zipCode }, + { nameEN: { contains: query }, zipCode, ...filterStatus(status) }, + { name: { contains: query }, zipCode, ...filterStatus(status) }, + { email: { contains: query }, zipCode, ...filterStatus(status) }, + { code: { contains: query }, zipCode, ...filterStatus(status) }, + { address: { contains: query }, zipCode, ...filterStatus(status) }, + { addressEN: { contains: query }, zipCode, ...filterStatus(status) }, + { province: { name: { contains: query } }, zipCode, ...filterStatus(status) }, + { province: { nameEN: { contains: query } }, zipCode, ...filterStatus(status) }, + { district: { name: { contains: query } }, zipCode, ...filterStatus(status) }, + { district: { nameEN: { contains: query } }, zipCode, ...filterStatus(status) }, + { subDistrict: { name: { contains: query } }, zipCode, ...filterStatus(status) }, + { subDistrict: { nameEN: { contains: query } }, zipCode, ...filterStatus(status) }, + { + customer: { + OR: [{ customerName: { contains: query } }, { customerNameEN: { contains: query } }], + }, + zipCode, + status, + }, ], - } satisfies Prisma.BranchWhereInput; + AND: { customerId }, + } satisfies Prisma.CustomerBranchWhereInput; const [result, total] = await prisma.$transaction([ prisma.customerBranch.findMany({ - orderBy: { createdAt: "asc" }, + orderBy: [{ statusOrder: "asc" }, { createdAt: "asc" }], include: { + customer: includeCustomer, province: true, district: true, subDistrict: true, + _count: true, }, where, take: pageSize, @@ -132,7 +182,7 @@ export class CustomerBranchController extends Controller { }); if (!record) { - throw new HttpError(HttpStatus.NOT_FOUND, "Branch cannot be found.", "data_not_found"); + throw new HttpError(HttpStatus.NOT_FOUND, "Branch cannot be found.", "branchNotFound"); } return record; @@ -153,7 +203,6 @@ export class CustomerBranchController extends Controller { { firstNameEN: { contains: query }, zipCode }, { lastName: { contains: query }, zipCode }, { lastNameEN: { contains: query }, zipCode }, - { email: { contains: query }, zipCode }, ], } satisfies Prisma.EmployeeWhereInput; @@ -191,62 +240,67 @@ export class CustomerBranchController extends Controller { @Post() async create(@Request() req: RequestWithUser, @Body() body: CustomerBranchCreate) { - if (body.provinceId || body.districtId || body.subDistrictId || body.customerId) { - const [province, district, subDistrict, customer] = await prisma.$transaction([ - prisma.province.findFirst({ where: { id: body.provinceId || undefined } }), - prisma.district.findFirst({ where: { id: body.districtId || undefined } }), - prisma.subDistrict.findFirst({ where: { id: body.subDistrictId || undefined } }), - prisma.customer.findFirst({ where: { id: body.customerId || undefined } }), - ]); - if (body.provinceId && !province) - throw new HttpError( - HttpStatus.BAD_REQUEST, - "Province cannot be found.", - "missing_or_invalid_parameter", - ); - if (body.districtId && !district) - throw new HttpError( - HttpStatus.BAD_REQUEST, - "District cannot be found.", - "missing_or_invalid_parameter", - ); - if (body.subDistrictId && !subDistrict) - throw new HttpError( - HttpStatus.BAD_REQUEST, - "Sub-district cannot be found.", - "missing_or_invalid_parameter", - ); - if (body.customerId && !customer) - throw new HttpError( - HttpStatus.BAD_REQUEST, - "Customer cannot be found.", - "missing_or_invalid_parameter", - ); - } + const [province, district, subDistrict, customer] = await prisma.$transaction([ + prisma.province.findFirst({ where: { id: body.provinceId || undefined } }), + prisma.district.findFirst({ where: { id: body.districtId || undefined } }), + prisma.subDistrict.findFirst({ where: { id: body.subDistrictId || undefined } }), + prisma.customer.findFirst({ where: { id: body.customerId || undefined } }), + ]); + if (body.provinceId && !province) + throw new HttpError( + HttpStatus.BAD_REQUEST, + "Province cannot be found.", + "relationProvinceNotFound", + ); + if (body.districtId && !district) + throw new HttpError( + HttpStatus.BAD_REQUEST, + "District cannot be found.", + "relationDistrictNotFound", + ); + if (body.subDistrictId && !subDistrict) + throw new HttpError( + HttpStatus.BAD_REQUEST, + "Sub-district cannot be found.", + "relationSubDistrictNotFound", + ); + if (!customer) + throw new HttpError( + HttpStatus.BAD_REQUEST, + "Customer cannot be found.", + "relationCustomerNotFound", + ); const { provinceId, districtId, subDistrictId, customerId, ...rest } = body; - const count = await prisma.customerBranch.count({ - where: { customerId }, - }); + const record = await prisma.$transaction( + async (tx) => { + const count = await tx.customerBranch.count({ + where: { customerId }, + }); - const record = await prisma.customerBranch.create({ - include: { - province: true, - district: true, - subDistrict: true, + return await tx.customerBranch.create({ + include: { + province: true, + district: true, + subDistrict: true, + }, + data: { + ...rest, + statusOrder: +(rest.status === "INACTIVE"), + branchNo: count + 1, + code: `${customer.code}-${(count + 1).toString().padStart(2, "0")}`, + customer: { connect: { id: customerId } }, + province: { connect: provinceId ? { id: provinceId } : undefined }, + district: { connect: districtId ? { id: districtId } : undefined }, + subDistrict: { connect: subDistrictId ? { id: subDistrictId } : undefined }, + createdBy: req.user.name, + updatedBy: req.user.name, + }, + }); }, - data: { - ...rest, - branchNo: `${count + 1}`, - customer: { connect: { id: customerId } }, - province: { connect: provinceId ? { id: provinceId } : undefined }, - district: { connect: districtId ? { id: districtId } : undefined }, - subDistrict: { connect: subDistrictId ? { id: subDistrictId } : undefined }, - createdBy: req.user.name, - updateBy: req.user.name, - }, - }); + { isolationLevel: Prisma.TransactionIsolationLevel.Serializable }, + ); await prisma.customer.updateMany({ where: { id: customerId, status: Status.CREATED }, @@ -275,32 +329,32 @@ export class CustomerBranchController extends Controller { throw new HttpError( HttpStatus.BAD_REQUEST, "Province cannot be found.", - "missing_or_invalid_parameter", + "relationProvinceNotFound", ); if (body.districtId && !district) throw new HttpError( HttpStatus.BAD_REQUEST, "District cannot be found.", - "missing_or_invalid_parameter", + "relationDistrictNotFound", ); if (body.subDistrictId && !subDistrict) throw new HttpError( HttpStatus.BAD_REQUEST, "Sub-district cannot be found.", - "missing_or_invalid_parameter", + "relationSubDistrictNotFound", ); if (body.customerId && !customer) throw new HttpError( HttpStatus.BAD_REQUEST, "Customer cannot be found.", - "missing_or_invalid_parameter", + "relationCustomerNotFound", ); } const { provinceId, districtId, subDistrictId, customerId, ...rest } = body; if (!(await prisma.customerBranch.findUnique({ where: { id: branchId } }))) { - throw new HttpError(HttpStatus.NOT_FOUND, "Branch cannot be found.", "data_not_found"); + throw new HttpError(HttpStatus.NOT_FOUND, "Branch cannot be found.", "branchNotFound"); } const record = await prisma.customerBranch.update({ @@ -312,6 +366,7 @@ export class CustomerBranchController extends Controller { }, data: { ...rest, + statusOrder: +(rest.status === "INACTIVE"), customer: { connect: customerId ? { id: customerId } : undefined }, province: { connect: provinceId ? { id: provinceId } : undefined, @@ -326,7 +381,7 @@ export class CustomerBranchController extends Controller { disconnect: subDistrictId === null || undefined, }, createdBy: req.user.name, - updateBy: req.user.name, + updatedBy: req.user.name, }, }); @@ -337,20 +392,143 @@ export class CustomerBranchController extends Controller { @Delete("{branchId}") async delete(@Path() branchId: string) { - const record = await prisma.customerBranch.findFirst({ where: { id: branchId } }); + const record = await prisma.customerBranch.findFirst({ + where: { id: branchId }, + }); if (!record) { throw new HttpError( HttpStatus.NOT_FOUND, "Customer branch cannot be found.", - "data_not_found", + "customerBranchNotFound", ); } if (record.status !== Status.CREATED) { - throw new HttpError(HttpStatus.FORBIDDEN, "Customer branch is in used.", "data_in_used"); + throw new HttpError( + HttpStatus.FORBIDDEN, + "Customer branch is in used.", + "customerBranchInUsed", + ); } - return await prisma.customerBranch.delete({ where: { id: branchId } }); + return await prisma.customerBranch.delete({ where: { id: branchId } }).then((v) => { + new Promise((resolve, reject) => { + const item: string[] = []; + + const stream = minio.listObjectsV2( + MINIO_BUCKET, + `${attachmentLocation(record.customerId, branchId)}/`, + ); + + stream.on("data", (v) => v && v.name && item.push(v.name)); + stream.on("end", () => resolve(item)); + stream.on("error", () => reject(new Error("MinIO error."))); + }).then((list) => { + list.map(async (v) => { + await minio.removeObject(MINIO_BUCKET, v, { + forceDelete: true, + }); + }); + }); + return v; + }); + } +} + +@Route("api/v1/customer-branch/{branchId}/attachment") +@Tags("Customer Branch") +@Security("keycloak") +export class CustomerAttachmentController extends Controller { + @Get() + async listAttachment(@Path() branchId: string) { + const record = await prisma.customerBranch.findFirst({ + where: { id: branchId }, + }); + + if (!record) { + throw new HttpError( + HttpStatus.NOT_FOUND, + "Customer branch cannot be found.", + "customerBranchNotFound", + ); + } + + const list = await new Promise((resolve, reject) => { + const item: string[] = []; + + const stream = minio.listObjectsV2( + MINIO_BUCKET, + `${attachmentLocation(record.customerId, branchId)}/`, + ); + + stream.on("data", (v) => v && v.name && item.push(v.name)); + stream.on("end", () => resolve(item)); + stream.on("error", () => reject(new Error("MinIO error."))); + }); + + return await Promise.all( + list.map(async (v) => ({ + name: v.split("/").at(-1) as string, + url: await minio.presignedGetObject(MINIO_BUCKET, v, 12 * 60 * 60), + })), + ); + } + + @Post() + async addAttachment(@Path() branchId: string, @Body() payload: { file: string[] }) { + const record = await prisma.customerBranch.findFirst({ + where: { id: branchId }, + }); + + if (!record) { + throw new HttpError( + HttpStatus.NOT_FOUND, + "Customer branch cannot be found.", + "customerBranchNotFound", + ); + } + + return await Promise.all( + payload.file.map(async (v) => ({ + name: v, + url: await minio.presignedGetObject( + MINIO_BUCKET, + `${attachmentLocation(record.customerId, branchId)}/${v}`, + ), + uploadUrl: await minio.presignedPutObject( + MINIO_BUCKET, + `${attachmentLocation(record.customerId, branchId)}/${v}`, + 12 * 60 * 60, + ), + })), + ); + } + + @Delete() + async deleteAttachment(@Path() branchId: string, @Body() payload: { file: string[] }) { + const record = await prisma.customerBranch.findFirst({ + where: { id: branchId }, + }); + + if (!record) { + throw new HttpError( + HttpStatus.NOT_FOUND, + "Customer branch cannot be found.", + "customerBranchNotFound", + ); + } + + await Promise.all( + payload.file.map(async (v) => { + await minio.removeObject( + MINIO_BUCKET, + `${attachmentLocation(record.customerId, branchId)}/${v}`, + { + forceDelete: true, + }, + ); + }), + ); } } diff --git a/src/controllers/customer-controller.ts b/src/controllers/customer-controller.ts index 4be81cf..23b1e8d 100644 --- a/src/controllers/customer-controller.ts +++ b/src/controllers/customer-controller.ts @@ -15,7 +15,7 @@ import { } from "tsoa"; import { RequestWithUser } from "../interfaces/user"; import prisma from "../db"; -import minio from "../services/minio"; +import minio, { presignedGetObjectIfExist } from "../services/minio"; import HttpStatus from "../interfaces/http-status"; import HttpError from "../interfaces/http-error"; @@ -27,39 +27,155 @@ const MINIO_BUCKET = process.env.MINIO_BUCKET; export type CustomerCreate = { status?: Status; + personName: string; + personNameEN?: string; customerType: CustomerType; customerName: string; customerNameEN: string; + taxNo?: string | null; + customerBranch?: { + status?: Status; + + legalPersonNo: string; + + taxNo: string | null; + name: string; + nameEN: string; + addressEN: string; + address: string; + zipCode: string; + email: string; + telephoneNo: string; + + registerName: string; + registerDate: Date; + authorizedCapital: string; + + employmentOffice: string; + bussinessType: string; + bussinessTypeEN: string; + jobPosition: string; + jobPositionEN: string; + jobDescription: string; + saleEmployee: string; + payDate: Date; + wageRate: number; + + subDistrictId?: string | null; + districtId?: string | null; + provinceId?: string | null; + }[]; }; export type CustomerUpdate = { status?: "ACTIVE" | "INACTIVE"; + personName?: string; + personNameEN?: string; customerType?: CustomerType; customerName?: string; customerNameEN?: string; + taxNo?: string | null; + customerBranch?: { + id?: string; + + status?: Status; + + legalPersonNo: string; + + taxNo: string | null; + name: string; + nameEN: string; + addressEN: string; + address: string; + zipCode: string; + email: string; + telephoneNo: string; + + registerName: string; + registerDate: Date; + authorizedCapital: string; + + employmentOffice: string; + bussinessType: string; + bussinessTypeEN: string; + jobPosition: string; + jobPositionEN: string; + jobDescription: string; + saleEmployee: string; + payDate: Date; + wageRate: number; + + subDistrictId?: string | null; + districtId?: string | null; + provinceId?: string | null; + }[]; }; function imageLocation(id: string) { - return `customer/img-${id}`; + return `customer/${id}/profile-image`; } -@Route("api/customer") +@Route("api/v1/customer") @Tags("Customer") @Security("keycloak") export class CustomerController extends Controller { + @Get("type-stats") + async stat() { + const list = await prisma.customer.groupBy({ + by: "customerType", + _count: true, + }); + + return list.reduce>( + (a, c) => { + a[c.customerType] = c._count; + return a; + }, + { + CORP: 0, + PERS: 0, + }, + ); + } + @Get() async list( + @Query() customerType?: CustomerType, @Query() query: string = "", + @Query() status?: Status, @Query() page: number = 1, @Query() pageSize: number = 30, + @Query() includeBranch: boolean = false, ) { + const filterStatus = (val?: Status) => { + if (!val) return {}; + + return val !== Status.CREATED && val !== Status.ACTIVE + ? { status: val } + : { OR: [{ status: Status.CREATED }, { status: Status.ACTIVE }] }; + }; const where = { - OR: [{ customerName: { contains: query } }, { customerNameEN: { contains: query } }], + OR: [ + { customerName: { contains: query }, customerType, ...filterStatus(status) }, + { customerNameEN: { contains: query }, customerType, ...filterStatus(status) }, + ], } satisfies Prisma.CustomerWhereInput; const [result, total] = await prisma.$transaction([ prisma.customer.findMany({ - orderBy: { createdAt: "asc" }, + include: { + _count: true, + branch: includeBranch + ? { + include: { + province: true, + district: true, + subDistrict: true, + }, + } + : undefined, + }, + orderBy: [{ statusOrder: "asc" }, { createdAt: "asc" }], where, take: pageSize, skip: (page - 1) * pageSize, @@ -71,7 +187,11 @@ export class CustomerController extends Controller { result: await Promise.all( result.map(async (v) => ({ ...v, - imageUrl: await minio.presignedGetObject(MINIO_BUCKET, imageLocation(v.id), 12 * 60 * 60), + imageUrl: await presignedGetObjectIfExist( + MINIO_BUCKET, + imageLocation(v.id), + 12 * 60 * 60, + ), })), ), page, @@ -82,11 +202,22 @@ export class CustomerController extends Controller { @Get("{customerId}") async getById(@Path() customerId: string) { - const record = await prisma.customer.findFirst({ where: { id: customerId } }); + const record = await prisma.customer.findFirst({ + include: { + branch: { + include: { + province: true, + district: true, + subDistrict: true, + }, + }, + }, + where: { id: customerId }, + }); if (!record) - throw new HttpError(HttpStatus.NOT_FOUND, "Customer cannot be found.", "data_not_found"); + throw new HttpError(HttpStatus.NOT_FOUND, "Customer cannot be found.", "customerNotFound"); return Object.assign(record, { - imageUrl: await minio.presignedGetObject( + imageUrl: await presignedGetObjectIfExist( MINIO_BUCKET, imageLocation(record.id), 12 * 60 * 60, @@ -96,26 +227,101 @@ export class CustomerController extends Controller { @Post() async create(@Request() req: RequestWithUser, @Body() body: CustomerCreate) { - const last = await prisma.customer.findFirst({ - orderBy: { createdAt: "desc" }, - where: { customerType: body.customerType }, - }); + const { customerBranch, ...payload } = body; - const code = `${body.customerType}${(+(last?.code.slice(-6) || 0) + 1).toString().padStart(6, "0")}`; + const provinceId = body.customerBranch?.reduce((acc, cur) => { + if (cur.provinceId && !acc.includes(cur.provinceId)) return acc.concat(cur.provinceId); + return acc; + }, []); + const districtId = body.customerBranch?.reduce((acc, cur) => { + if (cur.districtId && !acc.includes(cur.districtId)) return acc.concat(cur.districtId); + return acc; + }, []); + const subDistrictId = body.customerBranch?.reduce((acc, cur) => { + if (cur.subDistrictId && !acc.includes(cur.subDistrictId)) + return acc.concat(cur.subDistrictId); + return acc; + }, []); - const record = await prisma.customer.create({ - data: { - ...body, - code, - createdBy: req.user.name, - updateBy: req.user.name, + const [province, district, subDistrict] = await prisma.$transaction([ + prisma.province.findMany({ where: { id: { in: provinceId } } }), + prisma.district.findMany({ where: { id: { in: districtId } } }), + prisma.subDistrict.findMany({ where: { id: { in: subDistrictId } } }), + ]); + + if (provinceId && province.length !== provinceId?.length) { + throw new HttpError( + HttpStatus.BAD_REQUEST, + "Some province cannot be found.", + "relationProvinceNotFound", + ); + } + if (districtId && district.length !== districtId?.length) { + throw new HttpError( + HttpStatus.BAD_REQUEST, + "Some district cannot be found.", + "relationDistrictNotFound", + ); + } + if (subDistrictId && subDistrict.length !== subDistrictId?.length) { + throw new HttpError( + HttpStatus.BAD_REQUEST, + "Some sub district cannot be found.", + "relationSubDistrictNotFound", + ); + } + + const record = await prisma.$transaction( + async (tx) => { + const last = await tx.runningNo.upsert({ + where: { + key: `CUSTOMER_${body.customerType}`, + }, + create: { + key: `CUSTOMER_${body.customerType}`, + value: 1, + }, + update: { value: { increment: 1 } }, + }); + + return await prisma.customer.create({ + include: { + branch: { + include: { + province: true, + district: true, + subDistrict: true, + }, + }, + }, + data: { + ...payload, + statusOrder: +(payload.status === "INACTIVE"), + code: `${last.key.slice(9)}${last.value.toString().padStart(6, "0")}`, + branch: { + createMany: { + data: + customerBranch?.map((v, i) => ({ + ...v, + branchNo: i + 1, + code: `${last.key.slice(9)}${last.value.toString().padStart(6, "0")}-${(i + 1).toString().padStart(2, "0")}`, + createdBy: req.user.name, + updatedBy: req.user.name, + })) || [], + }, + }, + createdBy: req.user.name, + updatedBy: req.user.name, + }, + }); }, - }); + { isolationLevel: Prisma.TransactionIsolationLevel.Serializable }, + ); this.setStatus(HttpStatus.CREATED); return Object.assign(record, { - imageUrl: await minio.presignedGetObject( + imageUrl: await presignedGetObjectIfExist( MINIO_BUCKET, imageLocation(record.id), 12 * 60 * 60, @@ -134,21 +340,145 @@ export class CustomerController extends Controller { @Request() req: RequestWithUser, @Body() body: CustomerUpdate, ) { - if (!(await prisma.customer.findUnique({ where: { id: customerId } }))) { - throw new HttpError(HttpStatus.NOT_FOUND, "Customer cannot be found.", "data_not_found"); + const customer = await prisma.customer.findUnique({ where: { id: customerId } }); + + if (!customer) { + throw new HttpError(HttpStatus.NOT_FOUND, "Customer cannot be found.", "customerNotFound"); } - const record = await prisma.customer.update({ - where: { id: customerId }, - data: { - ...body, - createdBy: req.user.name, - updateBy: req.user.name, + const provinceId = body.customerBranch?.reduce((acc, cur) => { + if (cur.provinceId && !acc.includes(cur.provinceId)) return acc.concat(cur.provinceId); + return acc; + }, []); + const districtId = body.customerBranch?.reduce((acc, cur) => { + if (cur.districtId && !acc.includes(cur.districtId)) return acc.concat(cur.districtId); + return acc; + }, []); + const subDistrictId = body.customerBranch?.reduce((acc, cur) => { + if (cur.subDistrictId && !acc.includes(cur.subDistrictId)) + return acc.concat(cur.subDistrictId); + return acc; + }, []); + + const [province, district, subDistrict] = await prisma.$transaction([ + prisma.province.findMany({ where: { id: { in: provinceId } } }), + prisma.district.findMany({ where: { id: { in: districtId } } }), + prisma.subDistrict.findMany({ where: { id: { in: subDistrictId } } }), + ]); + + if (provinceId && province.length !== provinceId?.length) { + throw new HttpError( + HttpStatus.BAD_REQUEST, + "Some province cannot be found.", + "relationProvinceNotFound", + ); + } + if (districtId && district.length !== districtId?.length) { + throw new HttpError( + HttpStatus.BAD_REQUEST, + "Some district cannot be found.", + "relationDistrictNotFound", + ); + } + if (subDistrictId && subDistrict.length !== subDistrictId?.length) { + throw new HttpError( + HttpStatus.BAD_REQUEST, + "Some sub district cannot be found.", + "relationSubDistrictNotFound", + ); + } + + const { customerBranch, ...payload } = body; + + const relation = await prisma.customerBranch.findMany({ + where: { + customerId, }, }); + if ( + customerBranch && + relation.find((a) => !customerBranch.find((b) => a.id === b.id) && a.status !== "CREATED") + ) { + throw new HttpError( + HttpStatus.BAD_REQUEST, + "One or more branch cannot be delete and is missing.", + "oneOrMoreBranchMissing", + ); + } + + const record = await prisma.customer + .update({ + include: { + branch: { + include: { + province: true, + district: true, + subDistrict: true, + }, + }, + }, + where: { id: customerId }, + data: { + ...payload, + statusOrder: +(payload.status === "INACTIVE"), + branch: + (customerBranch && { + deleteMany: { + id: { + notIn: customerBranch.map((v) => v.id).filter((v): v is string => !!v) || [], + }, + status: Status.CREATED, + }, + upsert: customerBranch.map((v, i) => ({ + where: { id: v.id || "" }, + create: { + ...v, + branchNo: i + 1, + code: `${customer.code}-${(i + 1).toString().padStart(2, "0")}`, + createdBy: req.user.name, + updatedBy: req.user.name, + id: undefined, + }, + update: { + ...v, + branchNo: i + 1, + code: `${customer.code}-${(i + 1).toString().padStart(2, "0")}`, + updatedBy: req.user.name, + }, + })), + }) || + undefined, + updatedBy: req.user.name, + }, + }) + .then((v) => { + if (customerBranch) { + relation + .filter((a) => !customerBranch.find((b) => b.id === a.id)) + .forEach((deleted) => { + new Promise((resolve, reject) => { + const item: string[] = []; + + const stream = minio.listObjectsV2(MINIO_BUCKET, `customer/${deleted.id}`); + + stream.on("data", (v) => v && v.name && item.push(v.name)); + stream.on("end", () => resolve(item)); + stream.on("error", () => reject(new Error("MinIO error."))); + }).then((list) => { + list.map(async (v) => { + await minio.removeObject(MINIO_BUCKET, v, { + forceDelete: true, + }); + }); + }); + }); + } + return v; + }); + return Object.assign(record, { - imageUrl: await minio.presignedGetObject( + imageUrl: await presignedGetObjectIfExist( MINIO_BUCKET, imageLocation(record.id), 12 * 60 * 60, @@ -166,13 +496,30 @@ export class CustomerController extends Controller { const record = await prisma.customer.findFirst({ where: { id: customerId } }); if (!record) { - throw new HttpError(HttpStatus.NOT_FOUND, "Customer cannot be found.", "data_not_found"); + throw new HttpError(HttpStatus.NOT_FOUND, "Customer cannot be found.", "customerNotFound"); } if (record.status !== Status.CREATED) { - throw new HttpError(HttpStatus.FORBIDDEN, "Customer is in used.", "data_in_used"); + throw new HttpError(HttpStatus.FORBIDDEN, "Customer is in used.", "customerInUsed"); } - return await prisma.customer.delete({ where: { id: customerId } }); + return await prisma.customer.delete({ where: { id: customerId } }).then((v) => { + new Promise((resolve, reject) => { + const item: string[] = []; + + const stream = minio.listObjectsV2(MINIO_BUCKET, `customer/${customerId}`); + + stream.on("data", (v) => v && v.name && item.push(v.name)); + stream.on("end", () => resolve(item)); + stream.on("error", () => reject(new Error("MinIO error."))); + }).then((list) => { + list.map(async (v) => { + await minio.removeObject(MINIO_BUCKET, v, { + forceDelete: true, + }); + }); + }); + return v; + }); } } diff --git a/src/controllers/employee-checkup-controller.ts b/src/controllers/employee-checkup-controller.ts index de683d8..21fb896 100644 --- a/src/controllers/employee-checkup-controller.ts +++ b/src/controllers/employee-checkup-controller.ts @@ -16,35 +16,21 @@ import prisma from "../db"; import HttpStatus from "../interfaces/http-status"; import HttpError from "../interfaces/http-error"; -type EmployeeCheckupCreate = { - checkupType: string; - checkupResult: string; +type EmployeeCheckupPayload = { + checkupType?: string | null; + checkupResult?: string | null; provinceId?: string | null; - hospitalName: string; - remark: string; - medicalBenefitScheme: string; - insuranceCompany: string; - coverageStartDate: Date; - coverageExpireDate: Date; + hospitalName?: string | null; + remark?: string | null; + medicalBenefitScheme?: string | null; + insuranceCompany?: string | null; + coverageStartDate?: Date | null; + coverageExpireDate?: Date | null; }; -type EmployeeCheckupEdit = { - checkupType?: string; - checkupResult?: string; - - provinceId?: string | null; - - hospitalName?: string; - remark?: string; - medicalBenefitScheme?: string; - insuranceCompany?: string; - coverageStartDate?: Date; - coverageExpireDate?: Date; -}; - -@Route("api/employee/{employeeId}/checkup") +@Route("api/v1/employee/{employeeId}/checkup") @Tags("Employee Checkup") @Security("keycloak") export class EmployeeCheckupController extends Controller { @@ -65,7 +51,7 @@ export class EmployeeCheckupController extends Controller { throw new HttpError( HttpStatus.NOT_FOUND, "Employee checkup cannot be found.", - "data_not_found", + "employeeCheckupNotFound", ); } return record; @@ -75,7 +61,7 @@ export class EmployeeCheckupController extends Controller { async create( @Request() req: RequestWithUser, @Path() employeeId: string, - @Body() body: EmployeeCheckupCreate, + @Body() body: EmployeeCheckupPayload, ) { if (body.provinceId || employeeId) { const [province, employee] = await prisma.$transaction([ @@ -86,13 +72,13 @@ export class EmployeeCheckupController extends Controller { throw new HttpError( HttpStatus.BAD_REQUEST, "Province cannot be found.", - "missing_or_invalid_parameter", + "provinceNotFound", ); if (!employee) throw new HttpError( HttpStatus.BAD_REQUEST, "Employee cannot be found.", - "missing_or_invalid_parameter", + "employeeNotFound", ); } @@ -105,7 +91,7 @@ export class EmployeeCheckupController extends Controller { province: { connect: provinceId ? { id: provinceId } : undefined }, employee: { connect: { id: employeeId } }, createdBy: req.user.name, - updateBy: req.user.name, + updatedBy: req.user.name, }, }); @@ -119,7 +105,7 @@ export class EmployeeCheckupController extends Controller { @Request() req: RequestWithUser, @Path() employeeId: string, @Path() checkupId: string, - @Body() body: EmployeeCheckupEdit, + @Body() body: EmployeeCheckupPayload, ) { if (body.provinceId || employeeId) { const [province, employee] = await prisma.$transaction([ @@ -130,13 +116,13 @@ export class EmployeeCheckupController extends Controller { throw new HttpError( HttpStatus.BAD_REQUEST, "Province cannot be found.", - "missing_or_invalid_parameter", + "provinceNotFound", ); if (!employee) throw new HttpError( HttpStatus.BAD_REQUEST, "Employee cannot be found.", - "missing_or_invalid_parameter", + "employeeNotFound", ); } @@ -146,7 +132,7 @@ export class EmployeeCheckupController extends Controller { throw new HttpError( HttpStatus.NOT_FOUND, "Employee checkup cannot be found.", - "data_not_found", + "employeeCheckupNotFound", ); } @@ -157,7 +143,7 @@ export class EmployeeCheckupController extends Controller { ...rest, province: { connect: provinceId ? { id: provinceId } : undefined }, createdBy: req.user.name, - updateBy: req.user.name, + updatedBy: req.user.name, }, }); @@ -174,7 +160,7 @@ export class EmployeeCheckupController extends Controller { throw new HttpError( HttpStatus.NOT_FOUND, "Employee checkup cannot be found.", - "data_not_found", + "employeeCheckupNotFound", ); } diff --git a/src/controllers/employee-controller.ts b/src/controllers/employee-controller.ts index aeff13e..c366aa2 100644 --- a/src/controllers/employee-controller.ts +++ b/src/controllers/employee-controller.ts @@ -17,7 +17,7 @@ import { RequestWithUser } from "../interfaces/user"; import prisma from "../db"; import HttpStatus from "../interfaces/http-status"; import HttpError from "../interfaces/http-error"; -import minio from "../services/minio"; +import minio, { presignedGetObjectIfExist } from "../services/minio"; if (!process.env.MINIO_BUCKET) { throw Error("Require MinIO bucket."); @@ -26,7 +26,7 @@ if (!process.env.MINIO_BUCKET) { const MINIO_BUCKET = process.env.MINIO_BUCKET; function imageLocation(id: string) { - return `employee/profile-img-${id}`; + return `employee/${id}/profile-image`; } type EmployeeCreate = { @@ -34,7 +34,6 @@ type EmployeeCreate = { status?: Status; - code: string; nrcNo: string; dateOfBirth: Date; @@ -49,22 +48,75 @@ type EmployeeCreate = { addressEN: string; address: string; zipCode: string; - email: string; - telephoneNo: string; - arrivalBarricade: string; - arrivalCardNo: string; + passportType: string; + passportNumber: string; + passportIssueDate: Date; + passportExpiryDate: Date; + passportIssuingCountry: string; + passportIssuingPlace: string; + previousPassportReference?: string; + + visaType?: string | null; + visaNumber?: string | null; + visaIssueDate?: Date | null; + visaExpiryDate?: Date | null; + visaIssuingPlace?: string | null; + visaStayUntilDate?: Date | null; + tm6Number?: string | null; + entryDate?: Date | null; + workerStatus?: string | null; subDistrictId?: string | null; districtId?: string | null; provinceId?: string | null; + + employeeWork?: { + ownerName?: string | null; + positionName?: string | null; + jobType?: string | null; + workplace?: string | null; + workPermitNo?: string | null; + workPermitIssuDate?: Date | null; + workPermitExpireDate?: Date | null; + workEndDate?: Date | null; + remark?: string | null; + }[]; + + employeeCheckup?: { + checkupType?: string | null; + checkupResult?: string | null; + + provinceId?: string | null; + + hospitalName?: string | null; + remark?: string | null; + medicalBenefitScheme?: string | null; + insuranceCompany?: string | null; + coverageStartDate?: Date | null; + coverageExpireDate?: Date | null; + }[]; + + employeeOtherInfo?: { + citizenId?: string | null; + fatherFirstName?: string | null; + fatherLastName?: string | null; + fatherBirthPlace?: string | null; + motherFirstName?: string | null; + motherLastName?: string | null; + motherBirthPlace?: string | null; + + fatherFirstNameEN?: string | null; + fatherLastNameEN?: string | null; + motherFirstNameEN?: string | null; + motherLastNameEN?: string | null; + }; }; type EmployeeUpdate = { customerBranchId?: string; status?: "ACTIVE" | "INACTIVE"; - code?: string; nrcNo?: string; dateOfBirth?: Date; @@ -79,41 +131,129 @@ type EmployeeUpdate = { addressEN?: string; address?: string; zipCode?: string; - email?: string; - telephoneNo?: string; - arrivalBarricade?: string; - arrivalCardNo?: string; + passportType?: string; + passportNumber?: string; + passportIssueDate?: Date; + passportExpiryDate?: Date; + passportIssuingCountry?: string; + passportIssuingPlace?: string; + previousPassportReference?: string; + + visaType?: string | null; + visaNumber?: string | null; + visaIssueDate?: Date | null; + visaExpiryDate?: Date | null; + visaIssuingPlace?: string | null; + visaStayUntilDate?: Date | null; + tm6Number?: string | null; + entryDate?: Date | null; + workerStatus?: string | null; subDistrictId?: string | null; districtId?: string | null; provinceId?: string | null; + + employeeWork?: { + id?: string; + ownerName?: string | null; + positionName?: string | null; + jobType?: string | null; + workplace?: string | null; + workPermitNo?: string | null; + workPermitIssuDate?: Date | null; + workPermitExpireDate?: Date | null; + workEndDate?: Date | null; + remark?: string | null; + }[]; + + employeeCheckup?: { + id?: string; + checkupType?: string | null; + checkupResult?: string | null; + + provinceId?: string | null; + + hospitalName?: string | null; + remark?: string | null; + medicalBenefitScheme?: string | null; + insuranceCompany?: string | null; + coverageStartDate?: Date | null; + coverageExpireDate?: Date | null; + }[]; + + employeeOtherInfo?: { + citizenId?: string | null; + fatherFirstName?: string | null; + fatherLastName?: string | null; + fatherBirthPlace?: string | null; + motherFirstName?: string | null; + motherLastName?: string | null; + motherBirthPlace?: string | null; + + fatherFirstNameEN?: string | null; + fatherLastNameEN?: string | null; + motherFirstNameEN?: string | null; + motherLastNameEN?: string | null; + }; }; -@Route("api/employee") +@Route("api/v1/employee") @Tags("Employee") @Security("keycloak") export class EmployeeController extends Controller { + @Get("stats") + async getEmployeeStats(@Query() customerBranchId?: string) { + return await prisma.employee.count({ + where: { customerBranchId }, + }); + } + + @Get("stats/gender") + async getEmployeeStatsGender(@Query() customerBranchId?: string) { + return await prisma.employee + .groupBy({ + _count: true, + by: ["gender"], + where: { customerBranchId }, + }) + .then((res) => + res.reduce>((a, c) => { + a[c.gender] = c._count; + return a; + }, {}), + ); + } + @Get() async list( @Query() zipCode?: string, + @Query() gender?: string, + @Query() status?: Status, @Query() query: string = "", @Query() page: number = 1, @Query() pageSize: number = 30, ) { + const filterStatus = (val?: Status) => { + if (!val) return {}; + + return val !== Status.CREATED && val !== Status.ACTIVE + ? { status: val } + : { OR: [{ status: Status.CREATED }, { status: Status.ACTIVE }] }; + }; + const where = { OR: [ - { firstName: { contains: query }, zipCode }, - { firstNameEN: { contains: query }, zipCode }, - { lastName: { contains: query }, zipCode }, - { lastNameEN: { contains: query }, zipCode }, - { email: { contains: query }, zipCode }, + { firstName: { contains: query }, zipCode, gender, ...filterStatus(status) }, + { firstNameEN: { contains: query }, zipCode, gender, ...filterStatus(status) }, + { lastName: { contains: query }, zipCode, gender, ...filterStatus(status) }, + { lastNameEN: { contains: query }, zipCode, gender, ...filterStatus(status) }, ], } satisfies Prisma.EmployeeWhereInput; const [result, total] = await prisma.$transaction([ prisma.employee.findMany({ - orderBy: { createdAt: "asc" }, + orderBy: [{ statusOrder: "asc" }, { createdAt: "asc" }], include: { province: true, district: true, @@ -130,7 +270,7 @@ export class EmployeeController extends Controller { result: await Promise.all( result.map(async (v) => ({ ...v, - profileImageUrl: await minio.presignedGetObject( + profileImageUrl: await presignedGetObjectIfExist( MINIO_BUCKET, imageLocation(v.id), 12 * 60 * 60, @@ -155,7 +295,7 @@ export class EmployeeController extends Controller { }); if (!record) { - throw new HttpError(HttpStatus.NOT_FOUND, "Employee cannot be found.", "data_not_found"); + throw new HttpError(HttpStatus.NOT_FOUND, "Employee cannot be found.", "employeeNotFound"); } return record; @@ -163,67 +303,148 @@ export class EmployeeController extends Controller { @Post() async create(@Request() req: RequestWithUser, @Body() body: EmployeeCreate) { - if (body.provinceId || body.districtId || body.subDistrictId || body.customerBranchId) { - const [province, district, subDistrict, customerBranch] = await prisma.$transaction([ - prisma.province.findFirst({ where: { id: body.provinceId || undefined } }), - prisma.district.findFirst({ where: { id: body.districtId || undefined } }), - prisma.subDistrict.findFirst({ where: { id: body.subDistrictId || undefined } }), - prisma.customerBranch.findFirst({ where: { id: body.customerBranchId || undefined } }), + const [province, district, subDistrict, customerBranch] = await prisma.$transaction([ + prisma.province.findFirst({ where: { id: body.provinceId || undefined } }), + prisma.district.findFirst({ where: { id: body.districtId || undefined } }), + prisma.subDistrict.findFirst({ where: { id: body.subDistrictId || undefined } }), + prisma.customerBranch.findFirst({ + where: { id: body.customerBranchId }, + include: { customer: true }, + }), + ]); + if (body.provinceId !== province?.id) + throw new HttpError( + HttpStatus.BAD_REQUEST, + "Province cannot be found.", + "relationProvinceNotFound", + ); + if (body.districtId !== district?.id) + throw new HttpError( + HttpStatus.BAD_REQUEST, + "District cannot be found.", + "relationDistrictNotFound", + ); + if (body.subDistrictId !== subDistrict?.id) + throw new HttpError( + HttpStatus.BAD_REQUEST, + "Sub-district cannot be found.", + "relationSubDistrictNotFound", + ); + if (!customerBranch) + throw new HttpError( + HttpStatus.BAD_REQUEST, + "Customer Branch cannot be found.", + "relationCustomerBranchNotFound", + ); + + const { + provinceId, + districtId, + subDistrictId, + customerBranchId, + employeeWork, + employeeCheckup, + employeeOtherInfo, + ...rest + } = body; + + const listProvinceId = employeeCheckup?.reduce((acc, cur) => { + if (cur.provinceId && !acc.includes(cur.provinceId)) return acc.concat(cur.provinceId); + if (!cur.provinceId) cur.provinceId = null; + return acc; + }, []); + + if (listProvinceId) { + const [listProvince] = await prisma.$transaction([ + prisma.province.findMany({ where: { id: { in: listProvinceId } } }), ]); - if (body.provinceId && !province) + if (listProvince.length !== listProvinceId.length) { throw new HttpError( HttpStatus.BAD_REQUEST, - "Province cannot be found.", - "missing_or_invalid_parameter", - ); - if (body.districtId && !district) - throw new HttpError( - HttpStatus.BAD_REQUEST, - "District cannot be found.", - "missing_or_invalid_parameter", - ); - if (body.subDistrictId && !subDistrict) - throw new HttpError( - HttpStatus.BAD_REQUEST, - "Sub-district cannot be found.", - "missing_or_invalid_parameter", - ); - if (body.customerBranchId && !customerBranch) - throw new HttpError( - HttpStatus.BAD_REQUEST, - "Customer Branch cannot be found.", - "missing_or_invalid_parameter", + "Some province cannot be found.", + "someProvinceNotFound", ); + } } - const { provinceId, districtId, subDistrictId, customerBranchId, ...rest } = body; + const record = await prisma.$transaction( + async (tx) => { + const last = await tx.runningNo.upsert({ + where: { + key: `EMPLOYEE_${customerBranch.customer.code}-${customerBranch.branchNo.toString().padStart(2, "0")}-${new Date().getFullYear().toString().slice(-2).padStart(2, "0")}`, + }, + create: { + key: `EMPLOYEE_${customerBranch.customer.code}-${customerBranch.branchNo.toString().padStart(2, "0")}-${new Date().getFullYear().toString().slice(-2).padStart(2, "0")}`, + value: 1, + }, + update: { value: { increment: 1 } }, + }); - const record = await prisma.employee.create({ - include: { - province: true, - district: true, - subDistrict: true, + return await prisma.employee.create({ + include: { + province: true, + district: true, + subDistrict: true, + employeeOtherInfo: true, + employeeCheckup: { + include: { + province: true, + }, + }, + employeeWork: true, + }, + data: { + ...rest, + statusOrder: +(rest.status === "INACTIVE"), + code: `${customerBranch.customer.code}-${customerBranch.branchNo.toString().padStart(2, "0")}-${new Date().getFullYear().toString().slice(-2).padStart(2, "0")}${last.value.toString().padStart(4, "0")}`, + employeeWork: { + createMany: { + data: employeeWork || [], + }, + }, + employeeCheckup: { + createMany: { + data: + employeeCheckup?.map((v) => ({ + ...v, + provinceId: !!v.provinceId ? null : v.provinceId, + })) || [], + }, + }, + employeeOtherInfo: { + create: employeeOtherInfo, + }, + province: { connect: provinceId ? { id: provinceId } : undefined }, + district: { connect: districtId ? { id: districtId } : undefined }, + subDistrict: { connect: subDistrictId ? { id: subDistrictId } : undefined }, + customerBranch: { connect: { id: customerBranchId } }, + createdBy: req.user.name, + updatedBy: req.user.name, + }, + }); }, - data: { - ...rest, - province: { connect: provinceId ? { id: provinceId } : undefined }, - district: { connect: districtId ? { id: districtId } : undefined }, - subDistrict: { connect: subDistrictId ? { id: subDistrictId } : undefined }, - customerBranch: { connect: { id: customerBranchId } }, - createdBy: req.user.name, - updateBy: req.user.name, - }, - }); + { isolationLevel: Prisma.TransactionIsolationLevel.Serializable }, + ); await prisma.customerBranch.updateMany({ where: { id: customerBranchId, status: Status.CREATED }, data: { status: Status.ACTIVE }, }); + await prisma.customer.updateMany({ + where: { + branch: { + some: { id: customerBranchId }, + }, + status: Status.CREATED, + }, + data: { status: Status.ACTIVE }, + }); + this.setStatus(HttpStatus.CREATED); return Object.assign(record, { - profileImageUrl: await minio.presignedPutObject( + profileImageUrl: await presignedGetObjectIfExist( MINIO_BUCKET, imageLocation(record.id), 12 * 60 * 60, @@ -242,71 +463,223 @@ export class EmployeeController extends Controller { @Body() body: EmployeeUpdate, @Path() employeeId: string, ) { - if (body.provinceId || body.districtId || body.subDistrictId || body.customerBranchId) { - const [province, district, subDistrict, customerBranch] = await prisma.$transaction([ - prisma.province.findFirst({ where: { id: body.provinceId || undefined } }), - prisma.district.findFirst({ where: { id: body.districtId || undefined } }), - prisma.subDistrict.findFirst({ where: { id: body.subDistrictId || undefined } }), - prisma.customerBranch.findFirst({ where: { id: body.customerBranchId || undefined } }), - ]); - if (body.provinceId && !province) - throw new HttpError( - HttpStatus.BAD_REQUEST, - "Province cannot be found.", - "missing_or_invalid_parameter", - ); - if (body.districtId && !district) - throw new HttpError( - HttpStatus.BAD_REQUEST, - "District cannot be found.", - "missing_or_invalid_parameter", - ); - if (body.subDistrictId && !subDistrict) - throw new HttpError( - HttpStatus.BAD_REQUEST, - "Sub-district cannot be found.", - "missing_or_invalid_parameter", - ); - if (body.customerBranchId && !customerBranch) - throw new HttpError( - HttpStatus.BAD_REQUEST, - "Customer cannot be found.", - "missing_or_invalid_parameter", - ); + const [province, district, subDistrict, customerBranch, employee] = await prisma.$transaction([ + prisma.province.findFirst({ where: { id: body.provinceId || undefined } }), + prisma.district.findFirst({ where: { id: body.districtId || undefined } }), + prisma.subDistrict.findFirst({ where: { id: body.subDistrictId || undefined } }), + prisma.customerBranch.findFirst({ + where: { id: body.customerBranchId || undefined }, + include: { customer: true }, + }), + prisma.employee.findFirst({ where: { id: employeeId } }), + ]); + if (body.provinceId && !province) + throw new HttpError( + HttpStatus.BAD_REQUEST, + "Province cannot be found.", + "relationProvinceNotFound", + ); + if (body.districtId && !district) + throw new HttpError( + HttpStatus.BAD_REQUEST, + "District cannot be found.", + "relationDistrictNotFound", + ); + if (body.subDistrictId && !subDistrict) + throw new HttpError( + HttpStatus.BAD_REQUEST, + "Sub-district cannot be found.", + "relationSubDistrictNotFound", + ); + if (body.customerBranchId && !customerBranch) + throw new HttpError( + HttpStatus.BAD_REQUEST, + "Customer cannot be found.", + "relationCustomerNotFound", + ); + if (!employee) { + throw new HttpError(HttpStatus.NOT_FOUND, "Employee cannot be found.", "employeeNotFound"); } - const { provinceId, districtId, subDistrictId, customerBranchId, ...rest } = body; + const { + provinceId, + districtId, + subDistrictId, + customerBranchId, + employeeWork, + employeeCheckup, + employeeOtherInfo, + ...rest + } = body; - const record = await prisma.employee.update({ - where: { id: employeeId }, - include: { - province: true, - district: true, - subDistrict: true, - }, - data: { - ...rest, - customerBranch: { connect: customerBranchId ? { id: customerBranchId } : undefined }, - province: { - connect: provinceId ? { id: provinceId } : undefined, - disconnect: provinceId === null || undefined, + const listProvinceId = employeeCheckup?.reduce((acc, cur) => { + if (cur.provinceId && !acc.includes(cur.provinceId)) return acc.concat(cur.provinceId); + if (!cur.provinceId) cur.provinceId = null; + return acc; + }, []); + + if (listProvinceId) { + const [listProvince] = await prisma.$transaction([ + prisma.province.findMany({ where: { id: { in: listProvinceId } } }), + ]); + if (listProvince.length !== listProvinceId.length) { + throw new HttpError( + HttpStatus.BAD_REQUEST, + "Some province cannot be found.", + "someProvinceNotFound", + ); + } + } + + const record = await prisma.$transaction(async (tx) => { + let code: string | undefined; + + if (customerBranch && customerBranch.id !== employee.customerBranchId) { + const last = await tx.runningNo.upsert({ + where: { + key: `EMPLOYEE_${customerBranch.customer.code}-${customerBranch.branchNo.toString().padStart(2, "0")}-${new Date().getFullYear().toString().slice(-2).padStart(2, "0")}`, + }, + create: { + key: `EMPLOYEE_${customerBranch.customer.code}-${customerBranch.branchNo.toString().padStart(2, "0")}-${new Date().getFullYear().toString().slice(-2).padStart(2, "0")}`, + value: 1, + }, + update: { value: { increment: 1 } }, + }); + code = `${customerBranch.customer.code}-${customerBranch.branchNo.toString().padStart(2, "0")}-${new Date().getFullYear().toString().slice(-2).padStart(2, "0")}${last.value.toString().padStart(4, "0")}`; + } + + return await prisma.employee.update({ + where: { id: employeeId }, + include: { + province: true, + district: true, + subDistrict: true, + employeeOtherInfo: true, + employeeCheckup: { + include: { + province: true, + }, + }, + employeeWork: true, }, - district: { - connect: districtId ? { id: districtId } : undefined, - disconnect: districtId === null || undefined, + data: { + ...rest, + statusOrder: +(rest.status === "INACTIVE"), + code, + customerBranch: { connect: customerBranchId ? { id: customerBranchId } : undefined }, + employeeWork: employeeWork + ? { + deleteMany: { + id: { + notIn: employeeWork.map((v) => v.id).filter((v): v is string => !!v) || [], + }, + }, + upsert: employeeWork.map((v) => ({ + where: { id: v.id || "" }, + create: { + ...v, + createdBy: req.user.name, + updatedBy: req.user.name, + id: undefined, + }, + update: { + ...v, + updatedBy: req.user.name, + }, + })), + } + : undefined, + + employeeCheckup: employeeCheckup + ? { + deleteMany: { + id: { + notIn: employeeCheckup.map((v) => v.id).filter((v): v is string => !!v) || [], + }, + }, + upsert: employeeCheckup.map((v) => ({ + where: { id: v.id || "" }, + create: { + ...v, + provinceId: !v.provinceId ? undefined : v.provinceId, + createdBy: req.user.name, + updatedBy: req.user.name, + id: undefined, + }, + update: { + ...v, + updatedBy: req.user.name, + }, + })), + } + : undefined, + employeeOtherInfo: employeeOtherInfo + ? { + deleteMany: {}, + create: employeeOtherInfo, + } + : undefined, + province: { + connect: provinceId ? { id: provinceId } : undefined, + disconnect: provinceId === null || undefined, + }, + district: { + connect: districtId ? { id: districtId } : undefined, + disconnect: districtId === null || undefined, + }, + subDistrict: { + connect: subDistrictId ? { id: subDistrictId } : undefined, + disconnect: subDistrictId === null || undefined, + }, + createdBy: req.user.name, + updatedBy: req.user.name, }, - subDistrict: { - connect: subDistrictId ? { id: subDistrictId } : undefined, - disconnect: subDistrictId === null || undefined, - }, - createdBy: req.user.name, - updateBy: req.user.name, - }, + }); }); - this.setStatus(HttpStatus.CREATED); + const historyEntries: { field: string; valueBefore: string; valueAfter: string }[] = []; - return record; + for (const k of Object.keys(body)) { + const field = k as keyof typeof body; + + if (field === "employeeCheckup") continue; + if (field === "employeeOtherInfo") continue; + if (field === "employeeWork") continue; + + let valueBefore = employee[field]; + let valueAfter = body[field]; + + if (valueBefore === undefined && valueAfter === undefined) continue; + + if (valueBefore instanceof Date) valueBefore = valueBefore.toISOString(); + if (valueBefore === null || valueBefore === undefined) valueBefore = ""; + if (valueAfter instanceof Date) valueAfter = valueAfter.toISOString(); + if (valueAfter === null || valueAfter === undefined) valueAfter = ""; + + if (valueBefore !== valueAfter) historyEntries.push({ field, valueBefore, valueAfter }); + } + + await prisma.employeeHistory.createMany({ + data: historyEntries.map((v) => ({ + ...v, + updatedByUserId: req.user.sub, + updatedBy: req.user.preferred_username, + masterId: employee.id, + })), + }); + + return Object.assign(record, { + profileImageUrl: await presignedGetObjectIfExist( + MINIO_BUCKET, + imageLocation(record.id), + 12 * 60 * 60, + ), + profileImageUploadUrl: await minio.presignedPutObject( + MINIO_BUCKET, + imageLocation(record.id), + 12 * 60 * 60, + ), + }); } @Delete("{employeeId}") @@ -314,17 +687,20 @@ export class EmployeeController extends Controller { const record = await prisma.employee.findFirst({ where: { id: employeeId } }); if (!record) { - throw new HttpError(HttpStatus.NOT_FOUND, "Employee cannot be found.", "data_not_found"); + throw new HttpError(HttpStatus.NOT_FOUND, "Employee cannot be found.", "employeeNotFound"); } if (record.status !== Status.CREATED) { - throw new HttpError( - HttpStatus.FORBIDDEN, - "Emplyee is in used.", - "missing_or_invalid_parameter", - ); + throw new HttpError(HttpStatus.FORBIDDEN, "Employee is in used.", "employeeInUsed"); } return await prisma.employee.delete({ where: { id: employeeId } }); } + + @Get("{employeeId}/edit-history") + async editHistory(@Path() employeeId: string) { + return await prisma.employeeHistory.findMany({ + where: { masterId: employeeId }, + }); + } } diff --git a/src/controllers/employee-other-info-controller.ts b/src/controllers/employee-other-info-controller.ts index 4445c17..a479de7 100644 --- a/src/controllers/employee-other-info-controller.ts +++ b/src/controllers/employee-other-info-controller.ts @@ -1,4 +1,3 @@ -import { Prisma, Status } from "@prisma/client"; import { Body, Controller, @@ -7,7 +6,6 @@ import { Put, Path, Post, - Query, Request, Route, Security, @@ -19,54 +17,44 @@ import HttpError from "../interfaces/http-error"; import HttpStatus from "../interfaces/http-status"; import { RequestWithUser } from "../interfaces/user"; -type EmployeeOtherInfoCreate = { - citizenId: string; - fatherFullName: string; - motherFullName: string; - birthPlace: string; +type EmployeeOtherInfoPayload = { + citizenId?: string | null; + fatherFirstName?: string | null; + fatherLastName?: string | null; + fatherBirthPlace?: string | null; + motherFirstName?: string | null; + motherLastName?: string | null; + motherBirthPlace?: string | null; + + fatherFirstNameEN?: string | null; + fatherLastNameEN?: string | null; + motherFirstNameEN?: string | null; + motherLastNameEN?: string | null; }; -type EmployeeOtherInfoUpdate = { - citizenId: string; - fatherFullName: string; - motherFullName: string; - birthPlace: string; -}; - -@Route("api/employee/{employeeId}/other-info") +@Route("api/v1/employee/{employeeId}/other-info") @Tags("Employee Other Info") @Security("keycloak") export class EmployeeOtherInfo extends Controller { @Get() async list(@Path() employeeId: string) { - return prisma.employeeOtherInfo.findMany({ + return prisma.employeeOtherInfo.findFirst({ orderBy: { createdAt: "asc" }, where: { employeeId }, }); } - @Get("{otherInfoId}") - async getById(@Path() employeeId: string, @Path() otherInfoId: string) { - const record = await prisma.employeeOtherInfo.findFirst({ - where: { id: otherInfoId, employeeId }, - }); - if (!record) { - throw new HttpError(HttpStatus.NOT_FOUND, "Employee info cannot be found.", "data_not_found"); - } - return record; - } - @Post() async create( @Request() req: RequestWithUser, @Path() employeeId: string, - @Body() body: EmployeeOtherInfoCreate, + @Body() body: EmployeeOtherInfoPayload, ) { if (!(await prisma.employee.findUnique({ where: { id: employeeId } }))) throw new HttpError( HttpStatus.BAD_REQUEST, "Employee cannot be found.", - "missing_or_invalid_parameter", + "employeeBadReq", ); const record = await prisma.employeeOtherInfo.create({ @@ -74,7 +62,7 @@ export class EmployeeOtherInfo extends Controller { ...body, employee: { connect: { id: employeeId } }, createdBy: req.user.name, - updateBy: req.user.name, + updatedBy: req.user.name, }, }); @@ -88,19 +76,19 @@ export class EmployeeOtherInfo extends Controller { @Request() req: RequestWithUser, @Path() employeeId: string, @Path() otherInfoId: string, - @Body() body: EmployeeOtherInfoUpdate, + @Body() body: EmployeeOtherInfoPayload, ) { if (!(await prisma.employeeOtherInfo.findUnique({ where: { id: otherInfoId, employeeId } }))) { throw new HttpError( HttpStatus.NOT_FOUND, "Employee other info cannot be found.", - "data_not_found", + "employeeOtherNotFound", ); } const record = await prisma.employeeOtherInfo.update({ where: { id: otherInfoId, employeeId }, - data: { ...body, createdBy: req.user.name, updateBy: req.user.name }, + data: { ...body, createdBy: req.user.name, updatedBy: req.user.name }, }); this.setStatus(HttpStatus.CREATED); @@ -118,7 +106,7 @@ export class EmployeeOtherInfo extends Controller { throw new HttpError( HttpStatus.NOT_FOUND, "Employee other info cannot be found.", - "data_not_found", + "employeeOtherNotFound", ); } diff --git a/src/controllers/employee-work-controller.ts b/src/controllers/employee-work-controller.ts new file mode 100644 index 0000000..85c12f4 --- /dev/null +++ b/src/controllers/employee-work-controller.ts @@ -0,0 +1,112 @@ +import { + Body, + Controller, + Delete, + Get, + Path, + Post, + Put, + Request, + Route, + Security, + Tags, +} from "tsoa"; +import { RequestWithUser } from "../interfaces/user"; +import prisma from "../db"; +import HttpStatus from "../interfaces/http-status"; +import HttpError from "../interfaces/http-error"; + +type EmployeeWorkPayload = { + ownerName?: string | null; + positionName?: string | null; + jobType?: string | null; + workplace?: string | null; + workPermitNo?: string | null; + workPermitIssuDate?: Date | null; + workPermitExpireDate?: Date | null; + workEndDate?: Date | null; + remark?: string | null; +}; + +@Route("api/v1/employee/{employeeId}/work") +@Tags("Employee Work") +@Security("keycloak") +export class EmployeeWorkController extends Controller { + @Get() + async list(@Path() employeeId: string) { + return prisma.employeeWork.findMany({ + orderBy: { createdAt: "asc" }, + where: { employeeId }, + }); + } + + @Get("{workId}") + async getById(@Path() employeeId: string, @Path() workId: string) { + const record = await prisma.employeeWork.findFirst({ + where: { id: workId, employeeId }, + }); + if (!record) { + throw new HttpError(HttpStatus.NOT_FOUND, "Employee work cannot be found.", "employeeWorkNotFound"); + } + return record; + } + + @Post() + async create( + @Request() req: RequestWithUser, + @Path() employeeId: string, + @Body() body: EmployeeWorkPayload, + ) { + if (!(await prisma.employee.findUnique({ where: { id: employeeId } }))) + throw new HttpError( + HttpStatus.BAD_REQUEST, + "Employee cannot be found.", + "employeeBadReq", + ); + + const record = await prisma.employeeWork.create({ + data: { + ...body, + employee: { connect: { id: employeeId } }, + createdBy: req.user.name, + updatedBy: req.user.name, + }, + }); + + this.setStatus(HttpStatus.CREATED); + + return record; + } + + @Put("{workId}") + async editById( + @Request() req: RequestWithUser, + @Path() employeeId: string, + @Path() workId: string, + @Body() body: EmployeeWorkPayload, + ) { + if (!(await prisma.employeeWork.findUnique({ where: { id: workId, employeeId } }))) { + throw new HttpError(HttpStatus.NOT_FOUND, "Employee work cannot be found.", "employeeWorkNotFound"); + } + + const record = await prisma.employeeWork.update({ + where: { id: workId, employeeId }, + data: { ...body, createdBy: req.user.name, updatedBy: req.user.name }, + }); + + this.setStatus(HttpStatus.CREATED); + + return record; + } + + @Delete("{workId}") + async deleteById(@Path() employeeId: string, @Path() workId: string) { + const record = await prisma.employeeWork.findFirst({ where: { id: workId, employeeId } }); + + if (!record) { + throw new HttpError(HttpStatus.NOT_FOUND, "Employee work cannot be found.", "employeeWorkNotFound"); + } + + return await prisma.employeeWork.delete({ where: { id: workId, employeeId } }); + } +} diff --git a/src/controllers/keycloak-controller.ts b/src/controllers/keycloak-controller.ts index 5ebb09f..69ed2de 100644 --- a/src/controllers/keycloak-controller.ts +++ b/src/controllers/keycloak-controller.ts @@ -8,7 +8,7 @@ import { removeUserRoles, } from "../services/keycloak"; -@Route("api/keycloak") +@Route("api/v1/keycloak") @Tags("Single-Sign On") @Security("keycloak") export class KeycloakController extends Controller { diff --git a/src/controllers/permission-controller.ts b/src/controllers/permission-controller.ts index 8d9b17c..d10c649 100644 --- a/src/controllers/permission-controller.ts +++ b/src/controllers/permission-controller.ts @@ -19,7 +19,7 @@ type MenuEdit = { url: string; }; -@Route("v1/permission/menu") +@Route("api/v1/permission/menu") @Tags("Permission") @Security("keycloak") export class MenuController extends Controller { @@ -41,7 +41,7 @@ export class MenuController extends Controller { throw new HttpError( HttpStatus.BAD_REQUEST, "Parent menu not found.", - "missing_or_invalid_parameter", + "parentMenuBadReq", ); } } @@ -66,7 +66,7 @@ export class MenuController extends Controller { }) .catch((e) => { if (e instanceof PrismaClientKnownRequestError && e.code === "P2025") { - throw new HttpError(HttpStatus.NOT_FOUND, "Menu cannot be found.", "data_not_found"); + throw new HttpError(HttpStatus.NOT_FOUND, "Menu cannot be found.", "menuNotFound"); } throw new Error(e); }); @@ -78,7 +78,83 @@ export class MenuController extends Controller { async deleteMenu(@Path("menuId") id: string) { const record = await prisma.menu.deleteMany({ where: { id } }); if (record.count <= 0) { - throw new HttpError(HttpStatus.NOT_FOUND, "Menu cannot be found.", "data_not_found"); + throw new HttpError(HttpStatus.NOT_FOUND, "Menu cannot be found.", "menuNotFound"); + } + } +} + +type RoleMenuPermissionCreate = { + userRole: string; + permission: string; +}; + +type RoleMenuPermissionEdit = { + userRole?: string; + permission?: string; +}; + +@Route("api/v1/permission/menu/{menuId}/role") +@Tags("Permission") +@Security("keycloak") +export class RoleMenuController extends Controller { + @Get() + async listRoleMenu(@Path() menuId: string) { + const record = await prisma.roleMenuPermission.findMany({ + where: { menuId }, + orderBy: [{ userRole: "asc" }, { createdAt: "asc" }], + }); + return record; + } + + @Post() + async createRoleMenu(@Path() menuId: string, @Body() body: RoleMenuPermissionCreate) { + const menu = await prisma.menu.findFirst({ where: { id: menuId } }); + + if (!menu) { + throw new HttpError( + HttpStatus.BAD_REQUEST, + "Menu not found.", + "menuBadReq", + ); + } + + const record = await prisma.roleMenuPermission.create({ + data: Object.assign(body, { menuId }), + }); + + this.setStatus(HttpStatus.CREATED); + + return record; + } + + @Put("{roleMenuId}") + async editRoleMenu( + @Path("roleMenuId") id: string, + @Path() menuId: string, + @Body() body: RoleMenuPermissionEdit, + ) { + const record = await prisma.roleMenuPermission + .update({ + where: { id, menuId }, + data: body, + }) + .catch((e) => { + if (e instanceof PrismaClientKnownRequestError && e.code === "P2025") { + throw new HttpError(HttpStatus.NOT_FOUND, "Role menu cannot be found.", "roleMenuNotFound"); + } + throw new Error(e); + }); + + return record; + } + + @Delete("{roleMenuId}") + async deleteRoleMenu(@Path("roleMenuId") id: string, @Path() menuId: string) { + const record = await prisma.roleMenuPermission.deleteMany({ + where: { id, menuId }, + }); + if (record.count <= 0) { + throw new HttpError(HttpStatus.NOT_FOUND, "Role menu cannot be found.", "roleMenuNotFound"); } } } @@ -95,7 +171,7 @@ type MenuComponentEdit = { menuId?: string; }; -@Route("v1/permission/menu-component") +@Route("api/v1/permission/menu-component") @Tags("Permission") @Security("keycloak") export class MenuComponentController extends Controller { @@ -117,7 +193,7 @@ export class MenuComponentController extends Controller { throw new HttpError( HttpStatus.BAD_REQUEST, "Menu not found.", - "missing_or_invalid_parameter", + "menuBadReq", ); } @@ -139,7 +215,7 @@ export class MenuComponentController extends Controller { throw new HttpError( HttpStatus.BAD_REQUEST, "Menu not found.", - "missing_or_invalid_parameter", + "menuBadReq", ); } } @@ -155,7 +231,7 @@ export class MenuComponentController extends Controller { throw new HttpError( HttpStatus.NOT_FOUND, "Menu component cannot be found.", - "data_not_found", + "menuComponentNotFound", ); } throw new Error(e); @@ -171,7 +247,97 @@ export class MenuComponentController extends Controller { throw new HttpError( HttpStatus.NOT_FOUND, "Menu component cannot be found.", - "data_not_found", + "menuComponentNotFound", + ); + } + } +} + +type RoleMenuComponentPermissionCreate = { + userRole: string; + permission: string; +}; + +type RoleMenuComponentPermissionEdit = { + userRole?: string; + permission?: string; +}; + +@Route("api/v1/permission/menu-component/{menuComponentId}/role") +@Tags("Permission") +@Security("keycloak") +export class RoleMenuComponentController extends Controller { + @Get() + async listRoleMenuComponent(@Path() menuComponentId: string) { + const record = await prisma.roleMenuComponentPermission.findMany({ + where: { menuComponentId }, + orderBy: [{ userRole: "asc" }, { createdAt: "asc" }], + }); + return record; + } + + @Post() + async createRoleMenuComponent( + @Path() menuComponentId: string, + @Body() body: RoleMenuComponentPermissionCreate, + ) { + const menu = await prisma.menuComponent.findFirst({ where: { id: menuComponentId } }); + + if (!menu) { + throw new HttpError( + HttpStatus.BAD_REQUEST, + "Menu not found.", + "menuBadReq", + ); + } + + const record = await prisma.roleMenuComponentPermission.create({ + data: Object.assign(body, { menuComponentId }), + }); + + this.setStatus(HttpStatus.CREATED); + + return record; + } + + @Put("{roleMenuComponentId}") + async editRoleMenuComponent( + @Path("roleMenuComponentId") id: string, + @Path() menuComponentId: string, + @Body() body: RoleMenuComponentPermissionEdit, + ) { + const record = await prisma.roleMenuComponentPermission + .update({ + where: { id, menuComponentId }, + data: body, + }) + .catch((e) => { + if (e instanceof PrismaClientKnownRequestError && e.code === "P2025") { + throw new HttpError( + HttpStatus.NOT_FOUND, + "Role menu component cannot be found.", + "roleMenuNotFound", + ); + } + throw new Error(e); + }); + + return record; + } + + @Delete("{roleMenuComponentId}") + async deleteRoleMenuComponent( + @Path("roleMenuComponentId") id: string, + @Path() menuComponentId: string, + ) { + const record = await prisma.roleMenuComponentPermission.deleteMany({ + where: { id, menuComponentId }, + }); + if (record.count <= 0) { + throw new HttpError( + HttpStatus.NOT_FOUND, + "Role menu component cannot be found.", + "roleMenuNotFound", ); } } diff --git a/src/controllers/product-service-controller.ts b/src/controllers/product-service-controller.ts new file mode 100644 index 0000000..8671c3d --- /dev/null +++ b/src/controllers/product-service-controller.ts @@ -0,0 +1,100 @@ +import { Controller, Get, Query, Route, Security } from "tsoa"; +import prisma from "../db"; +import { Prisma, Product, Service } from "@prisma/client"; + +@Route("/api/v1/product-service") +export class ProductServiceController extends Controller { + @Get() + @Security("keycloak") + async getProductService( + @Query() status?: "ACTIVE" | "INACTIVE", + @Query() query = "", + @Query() productTypeId?: string, + @Query() page: number = 1, + @Query() pageSize: number = 30, + ) { + const union = Prisma.sql` + SELECT + "id", + "code", + "name", + "detail", + "price", + "agentPrice", + "serviceCharge", + "process", + "remark", + "status", + "statusOrder", + "productTypeId", + "createdBy", + "createdAt", + "updatedBy", + "updatedAt", + 'product' as "type" + FROM "Product" + UNION ALL + SELECT + "id", + "code", + "name", + "detail", + null as "price", + null as "agentPrice", + null as "serviceCharge", + null as "process", + null as "remark", + "status", + "statusOrder", + null as "productTypeId", + "createdBy", + "createdAt", + "updatedBy", + "updatedAt", + 'service' as "type" + FROM "Service" + `; + + const or: Prisma.Sql[] = []; + const and: Prisma.Sql[] = []; + + if (query) or.push(Prisma.sql`"name" LIKE ${`%${query}%`}`); + if (status) and.push(Prisma.sql`"status" = ${status}::"Status"`); + if (productTypeId) { + and.push(Prisma.sql`("productTypeId" = ${productTypeId} OR ("type" = 'service'))`); + } + + const where = Prisma.sql` + ${or.length > 0 || and.length > 0 ? Prisma.sql`WHERE ` : Prisma.empty} + ${or.length > 0 ? Prisma.join(or, " OR ", "(", ")") : Prisma.empty} + ${or.length > 0 && and.length > 0 ? Prisma.sql` AND ` : Prisma.empty} + ${and.length > 0 ? Prisma.join(and, " AND ", "(", ")") : Prisma.empty} + `; + + const [result, [{ total }]] = await prisma.$transaction([ + prisma.$queryRaw<((Product & { type: "product" }) | (Service & { type: "service" }))[]>` + SELECT * FROM (${union}) AS "ProductService" + ${where} + ORDER BY "ProductService"."statusOrder" ASC, "ProductService"."createdAt" ASC + LIMIT ${pageSize} OFFSET ${(page - 1) * pageSize} + `, + prisma.$queryRaw<[{ total: number }]>` + SELECT COUNT(*) AS "total" FROM (${union}) as "ProductService" + ${where} + `, + ]); + + const work = await prisma.work.findMany({ + where: { serviceId: { in: result.flatMap((v) => (v.type === "service" ? v.id : [])) } }, + }); + + return { + result: result.map((v) => + v.type === "service" ? { ...v, work: work.filter((w) => w.serviceId === v.id) || [] } : v, + ), + page, + pageSize, + total: +String(total), + }; + } +} diff --git a/src/controllers/product/group-controller.ts b/src/controllers/product/group-controller.ts new file mode 100644 index 0000000..2d676c4 --- /dev/null +++ b/src/controllers/product/group-controller.ts @@ -0,0 +1,199 @@ +import { + Body, + Controller, + Delete, + Get, + Put, + Path, + Post, + Query, + Request, + Route, + Security, + Tags, +} from "tsoa"; +import { Prisma, Status } from "@prisma/client"; + +import prisma from "../../db"; +import { RequestWithUser } from "../../interfaces/user"; +import HttpError from "../../interfaces/http-error"; +import HttpStatus from "../../interfaces/http-status"; + +type ProductGroupCreate = { + name: string; + detail: string; + remark: string; + status?: Status; +}; + +type ProductGroupUpdate = { + name?: string; + detail?: string; + remark?: string; + status?: "ACTIVE" | "INACTIVE"; +}; + +@Route("api/v1/product-group") +@Tags("Product Group") +@Security("keycloak") +export class ProductGroup extends Controller { + @Get("stats") + async getProductGroupStats() { + return await prisma.productGroup.count(); + } + + @Get() + async getProductGroup( + @Query() query: string = "", + @Query() status?: Status, + @Query() page: number = 1, + @Query() pageSize: number = 30, + ) { + const filterStatus = (val?: Status) => { + if (!val) return {}; + + return val !== Status.CREATED && val !== Status.ACTIVE + ? { status: val } + : { OR: [{ status: Status.CREATED }, { status: Status.ACTIVE }] }; + }; + + const where = { + OR: [ + { name: { contains: query }, ...filterStatus(status) }, + { detail: { contains: query }, ...filterStatus(status) }, + ], + } satisfies Prisma.ProductGroupWhereInput; + + const [result, total] = await prisma.$transaction([ + prisma.productGroup.findMany({ + include: { + _count: { + select: { + type: true, + }, + }, + }, + orderBy: [{ statusOrder: "asc" }, { createdAt: "asc" }], + where, + take: pageSize, + skip: (page - 1) * pageSize, + }), + prisma.productGroup.count({ where }), + ]); + + const statsProduct = await prisma.productType.findMany({ + include: { + _count: { select: { product: true } }, + }, + where: { + productGroupId: { in: result.map((v) => v.id) }, + }, + }); + + return { + result: result.map((v) => ({ + ...v, + _count: { + ...v._count, + product: statsProduct.reduce( + (a, c) => (c.productGroupId === v.id ? a + c._count.product : a), + 0, + ), + }, + })), + page, + pageSize, + total, + }; + } + + @Get("{groupId}") + async getProductGroupById(@Path() groupId: string) { + const record = await prisma.productGroup.findFirst({ + where: { id: groupId }, + }); + + if (!record) + throw new HttpError( + HttpStatus.NOT_FOUND, + "Product group cannot be found.", + "productGroupNotFound", + ); + + return record; + } + + @Post() + async createProductGroup(@Request() req: RequestWithUser, @Body() body: ProductGroupCreate) { + const record = await prisma.$transaction( + async (tx) => { + const last = await tx.runningNo.upsert({ + where: { + key: `PRODGRP`, + }, + create: { + key: `PRODGRP`, + value: 1, + }, + update: { value: { increment: 1 } }, + }); + + return await tx.productGroup.create({ + data: { + ...body, + statusOrder: +(body.status === "INACTIVE"), + code: `G${last.value.toString().padStart(2, "0")}`, + createdBy: req.user.name, + updatedBy: req.user.name, + }, + }); + }, + { isolationLevel: Prisma.TransactionIsolationLevel.Serializable }, + ); + + this.setStatus(HttpStatus.CREATED); + + return record; + } + + @Put("{groupId}") + async editProductGroup( + @Request() req: RequestWithUser, + @Body() body: ProductGroupUpdate, + @Path() groupId: string, + ) { + if (!(await prisma.productGroup.findUnique({ where: { id: groupId } }))) { + throw new HttpError( + HttpStatus.NOT_FOUND, + "Product group cannot be found.", + "productGroupNotFound", + ); + } + + const record = await prisma.productGroup.update({ + data: { ...body, statusOrder: +(body.status === "INACTIVE"), updatedBy: req.user.name }, + where: { id: groupId }, + }); + + return record; + } + + @Delete("{groupId}") + async deleteProductGroup(@Path() groupId: string) { + const record = await prisma.productGroup.findFirst({ where: { id: groupId } }); + + if (!record) { + throw new HttpError( + HttpStatus.NOT_FOUND, + "Product group cannot be found.", + "productGroupNotFound", + ); + } + + if (record.status !== Status.CREATED) { + throw new HttpError(HttpStatus.FORBIDDEN, "Product group is in used.", "productGroupInUsed"); + } + + return await prisma.productGroup.delete({ where: { id: groupId } }); + } +} diff --git a/src/controllers/product/product-controller.ts b/src/controllers/product/product-controller.ts new file mode 100644 index 0000000..340ab9f --- /dev/null +++ b/src/controllers/product/product-controller.ts @@ -0,0 +1,273 @@ +import { + Body, + Controller, + Delete, + Get, + Put, + Path, + Post, + Request, + Route, + Security, + Tags, + Query, +} from "tsoa"; +import { Prisma, Status } from "@prisma/client"; + +import prisma from "../../db"; +import minio, { presignedGetObjectIfExist } from "../../services/minio"; +import { RequestWithUser } from "../../interfaces/user"; +import HttpError from "../../interfaces/http-error"; +import HttpStatus from "../../interfaces/http-status"; + +if (!process.env.MINIO_BUCKET) { + throw Error("Require MinIO bucket."); +} + +const MINIO_BUCKET = process.env.MINIO_BUCKET; + +type ProductCreate = { + status?: Status; + code: "AC" | "DO" | "ac" | "do"; + name: string; + detail: string; + process: number; + price: number; + agentPrice: number; + serviceCharge: number; + productTypeId: string; + remark?: string; +}; + +type ProductUpdate = { + status?: "ACTIVE" | "INACTIVE"; + name?: string; + detail?: string; + process?: number; + price?: number; + agentPrice?: number; + serviceCharge?: number; + remark?: string; + productTypeId?: string; +}; + +function imageLocation(id: string) { + return `product/${id}/image`; +} + +@Route("api/v1/product") +@Tags("Product") +export class ProductController extends Controller { + @Get("stats") + async getProductStats(@Query() productTypeId?: string) { + return await prisma.product.count({ where: { productTypeId } }); + } + + @Get() + @Security("keycloak") + async getProduct( + @Query() status?: Status, + @Query() productTypeId?: string, + @Query() query: string = "", + @Query() page: number = 1, + @Query() pageSize: number = 30, + ) { + const filterStatus = (val?: Status) => { + if (!val) return {}; + + return val !== Status.CREATED && val !== Status.ACTIVE + ? { status: val } + : { OR: [{ status: Status.CREATED }, { status: Status.ACTIVE }] }; + }; + + const where = { + OR: [ + { name: { contains: query }, productTypeId, ...filterStatus(status) }, + { detail: { contains: query }, productTypeId, ...filterStatus(status) }, + ], + } satisfies Prisma.ProductWhereInput; + + const [result, total] = await prisma.$transaction([ + prisma.product.findMany({ + orderBy: [{ statusOrder: "asc" }, { createdAt: "asc" }], + where, + take: pageSize, + skip: (page - 1) * pageSize, + }), + prisma.product.count({ where }), + ]); + + return { + result: await Promise.all( + result.map(async (v) => ({ + ...v, + imageUrl: await presignedGetObjectIfExist( + MINIO_BUCKET, + imageLocation(v.id), + 12 * 60 * 60, + ), + })), + ), + page, + pageSize, + total, + }; + } + + @Get("{productId}") + @Security("keycloak") + async getProductById(@Path() productId: string) { + const record = await prisma.product.findFirst({ + where: { id: productId }, + }); + + if (!record) { + throw new HttpError(HttpStatus.NOT_FOUND, "Product cannot be found.", "productNotFound"); + } + + return Object.assign(record, { + imageUrl: await presignedGetObjectIfExist(MINIO_BUCKET, imageLocation(record.id), 60 * 60), + }); + } + + @Get("{productId}/image") + async getProductImageById(@Request() req: RequestWithUser, @Path() productId: string) { + const url = await presignedGetObjectIfExist(MINIO_BUCKET, imageLocation(productId), 60 * 60); + + if (!url) { + throw new HttpError(HttpStatus.NOT_FOUND, "Image cannot be found", "imageNotFound"); + } + + return req.res?.redirect(url); + } + + @Post() + @Security("keycloak") + async createProduct(@Request() req: RequestWithUser, @Body() body: ProductCreate) { + const productType = await prisma.productType.findFirst({ + where: { id: body.productTypeId }, + }); + + if (!productType) { + throw new HttpError( + HttpStatus.BAD_REQUEST, + "Product Type cannot be found.", + "relationProductTypeNotFound", + ); + } + + const record = await prisma.$transaction( + async (tx) => { + const last = await tx.runningNo.upsert({ + where: { + key: `PRODUCT_${body.code.toLocaleUpperCase()}`, + }, + create: { + key: `PRODUCT_${body.code.toLocaleUpperCase()}`, + value: 1, + }, + update: { value: { increment: 1 } }, + }); + return await prisma.product.create({ + data: { + ...body, + statusOrder: +(body.status === "INACTIVE"), + code: `${body.code.toLocaleUpperCase()}${last.value.toString().padStart(3, "0")}`, + createdBy: req.user.name, + updatedBy: req.user.name, + }, + }); + }, + { + isolationLevel: Prisma.TransactionIsolationLevel.Serializable, + }, + ); + + if (productType.status === "CREATED") { + await prisma.productType.update({ + where: { id: body.productTypeId }, + data: { status: Status.ACTIVE }, + }); + } + + this.setStatus(HttpStatus.CREATED); + + return Object.assign(record, { + imageUrl: await presignedGetObjectIfExist( + MINIO_BUCKET, + imageLocation(record.id), + 12 * 60 * 60, + ), + imageUploadUrl: await minio.presignedPutObject( + MINIO_BUCKET, + imageLocation(record.id), + 12 * 60 * 60, + ), + }); + } + + @Put("{productId}") + @Security("keycloak") + async editProduct( + @Request() req: RequestWithUser, + @Body() body: ProductUpdate, + @Path() productId: string, + ) { + if (!(await prisma.product.findUnique({ where: { id: productId } }))) { + throw new HttpError(HttpStatus.NOT_FOUND, "Product cannot be found.", "productNotFound"); + } + + const productType = await prisma.productType.findFirst({ + where: { id: body.productTypeId }, + }); + + if (!productType) { + throw new HttpError( + HttpStatus.BAD_REQUEST, + "Product Type cannot be found.", + "relationProductTypeNotFound", + ); + } + + const record = await prisma.product.update({ + data: { ...body, statusOrder: +(body.status === "INACTIVE"), updatedBy: req.user.name }, + where: { id: productId }, + }); + + if (productType.status === "CREATED") { + await prisma.productType.updateMany({ + where: { id: body.productTypeId, status: Status.CREATED }, + data: { status: Status.ACTIVE }, + }); + } + + return Object.assign(record, { + imageUrl: await presignedGetObjectIfExist( + MINIO_BUCKET, + imageLocation(record.id), + 12 * 60 * 60, + ), + imageUploadUrl: await minio.presignedPutObject( + MINIO_BUCKET, + imageLocation(record.id), + 12 * 60 * 60, + ), + }); + } + + @Delete("{productId}") + @Security("keycloak") + async deleteProduct(@Path() productId: string) { + const record = await prisma.product.findFirst({ where: { id: productId } }); + + if (!record) { + throw new HttpError(HttpStatus.NOT_FOUND, "Product cannot be found.", "productNotFound"); + } + + if (record.status !== Status.CREATED) { + throw new HttpError(HttpStatus.FORBIDDEN, "Product is in used.", "productInUsed"); + } + + return await prisma.product.delete({ where: { id: productId } }); + } +} diff --git a/src/controllers/product/type-controller.ts b/src/controllers/product/type-controller.ts new file mode 100644 index 0000000..786c1da --- /dev/null +++ b/src/controllers/product/type-controller.ts @@ -0,0 +1,213 @@ +import { + Body, + Controller, + Delete, + Get, + Put, + Path, + Post, + Query, + Request, + Route, + Security, + Tags, +} from "tsoa"; +import { Prisma, Status } from "@prisma/client"; + +import prisma from "../../db"; +import { RequestWithUser } from "../../interfaces/user"; +import HttpError from "../../interfaces/http-error"; +import HttpStatus from "../../interfaces/http-status"; + +type ProductTypeCreate = { + productGroupId: string; + name: string; + detail: string; + remark: string; + status?: Status; +}; + +type ProductTypeUpdate = { + productGroupId?: string; + name?: string; + detail?: string; + remark?: string; + status?: "ACTIVE" | "INACTIVE"; +}; + +@Route("api/v1/product-type") +@Tags("Product Type") +@Security("keycloak") +export class ProductType extends Controller { + @Get("stats") + async getProductTypeStats() { + return await prisma.productType.count(); + } + + @Get() + async getProductType( + @Query() query: string = "", + @Query() productGroupId?: string, + @Query() status?: Status, + @Query() page: number = 1, + @Query() pageSize: number = 30, + ) { + const filterStatus = (val?: Status) => { + if (!val) return {}; + + return val !== Status.CREATED && val !== Status.ACTIVE + ? { status: val } + : { OR: [{ status: Status.CREATED }, { status: Status.ACTIVE }] }; + }; + const where = { + AND: { productGroupId }, + OR: [ + { name: { contains: query }, ...filterStatus(status) }, + { detail: { contains: query }, ...filterStatus(status) }, + ], + } satisfies Prisma.ProductTypeWhereInput; + const [result, total] = await prisma.$transaction([ + prisma.productType.findMany({ + include: { + _count: { + select: { product: true }, + }, + }, + orderBy: [{ statusOrder: "asc" }, { createdAt: "asc" }], + where, + take: pageSize, + skip: (page - 1) * pageSize, + }), + prisma.productType.count({ where }), + ]); + + return { result, page, pageSize, total }; + } + + @Get("{typeId}") + async getProductTypeById(@Path() typeId: string) { + const record = await prisma.productType.findFirst({ + where: { id: typeId }, + }); + + if (!record) + throw new HttpError( + HttpStatus.NOT_FOUND, + "Product type cannot be found.", + "productTypeNotFound", + ); + + return record; + } + + @Post() + async createProductType(@Request() req: RequestWithUser, @Body() body: ProductTypeCreate) { + const productGroup = await prisma.productGroup.findFirst({ + where: { id: body.productGroupId }, + }); + + if (!productGroup) { + throw new HttpError( + HttpStatus.BAD_REQUEST, + "Product group associated cannot be found.", + "productGroupAssociatedBadReq", + ); + } + + const record = await prisma.$transaction( + async (tx) => { + const last = await tx.runningNo.upsert({ + where: { + key: `PRODTYP_T${productGroup.code}`, + }, + create: { + key: `PRODTYP_T${productGroup.code}`, + value: 1, + }, + update: { value: { increment: 1 } }, + }); + + return await tx.productType.create({ + data: { + ...body, + statusOrder: +(body.status === "INACTIVE"), + code: `T${productGroup.code}${last.value.toString().padStart(2, "0")}`, + createdBy: req.user.name, + updatedBy: req.user.name, + }, + }); + }, + { isolationLevel: Prisma.TransactionIsolationLevel.Serializable }, + ); + + if (productGroup.status === "CREATED") { + await prisma.productGroup.update({ + where: { id: body.productGroupId }, + data: { status: Status.ACTIVE }, + }); + } + + this.setStatus(HttpStatus.CREATED); + + return record; + } + + @Put("{typeId}") + async editProductType( + @Request() req: RequestWithUser, + @Body() body: ProductTypeUpdate, + @Path() typeId: string, + ) { + const productGroup = await prisma.productGroup.findFirst({ + where: { id: body.productGroupId }, + }); + if (body.productGroupId && !productGroup) { + throw new HttpError( + HttpStatus.BAD_REQUEST, + "Product group cannot be found.", + "productGroupBadReq", + ); + } + + if (!(await prisma.productType.findUnique({ where: { id: typeId } }))) { + throw new HttpError( + HttpStatus.NOT_FOUND, + "Product type cannot be found.", + "productTypeNotFound", + ); + } + + const record = await prisma.productType.update({ + data: { ...body, statusOrder: +(body.status === "INACTIVE"), updatedBy: req.user.name }, + where: { id: typeId }, + }); + + if (productGroup?.status === "CREATED") { + await prisma.productGroup.update({ + where: { id: body.productGroupId, status: Status.CREATED }, + data: { status: Status.ACTIVE }, + }); + } + + return record; + } + + @Delete("{typeId}") + async deleteProductType(@Path() typeId: string) { + const record = await prisma.productType.findFirst({ where: { id: typeId } }); + + if (!record) { + throw new HttpError( + HttpStatus.NOT_FOUND, + "Product type cannot be found.", + "productTypeNotFound", + ); + } + + if (record.status !== Status.CREATED) { + throw new HttpError(HttpStatus.FORBIDDEN, "Product type is in used.", "productTypeInUsed"); + } + + return await prisma.productType.delete({ where: { id: typeId } }); + } +} diff --git a/src/controllers/service/service-controller.ts b/src/controllers/service/service-controller.ts new file mode 100644 index 0000000..a565620 --- /dev/null +++ b/src/controllers/service/service-controller.ts @@ -0,0 +1,346 @@ +import { + Body, + Controller, + Delete, + Get, + Put, + Path, + Post, + Query, + Request, + Route, + Security, + Tags, +} from "tsoa"; +import { Prisma, Status } from "@prisma/client"; + +import prisma from "../../db"; +import minio, { presignedGetObjectIfExist } from "../../services/minio"; +import { RequestWithUser } from "../../interfaces/user"; +import HttpError from "../../interfaces/http-error"; +import HttpStatus from "../../interfaces/http-status"; + +if (!process.env.MINIO_BUCKET) { + throw Error("Require MinIO bucket."); +} + +const MINIO_BUCKET = process.env.MINIO_BUCKET; + +type ServiceCreate = { + code: "MOU" | "mou"; + name: string; + detail: string; + attributes?: { + [key: string]: any; + }; + status?: Status; + work?: { + name: string; + productId: string[]; + attributes?: { [key: string]: any }; + }[]; +}; + +type ServiceUpdate = { + name?: string; + detail?: string; + attributes?: { + [key: string]: any; + }; + status?: "ACTIVE" | "INACTIVE"; + work?: { + name: string; + productId: string[]; + attributes?: { [key: string]: any }; + }[]; +}; + +function imageLocation(id: string) { + return `service/${id}/service-image`; +} + +@Route("api/v1/service") +@Tags("Service") +export class ServiceController extends Controller { + @Get("stats") + @Security("keycloak") + async getServiceStats() { + return await prisma.service.count(); + } + + @Get() + @Security("keycloak") + async getService( + @Query() query: string = "", + @Query() page: number = 1, + @Query() pageSize: number = 30, + @Query() status?: Status, + ) { + const filterStatus = (val?: Status) => { + if (!val) return {}; + + return val !== Status.CREATED && val !== Status.ACTIVE + ? { status: val } + : { OR: [{ status: Status.CREATED }, { status: Status.ACTIVE }] }; + }; + + const where = { + OR: [ + { name: { contains: query }, ...filterStatus(status) }, + { detail: { contains: query }, ...filterStatus(status) }, + ], + } satisfies Prisma.ServiceWhereInput; + + const [result, total] = await prisma.$transaction([ + prisma.service.findMany({ + include: { + work: true, + }, + orderBy: [{ statusOrder: "asc" }, { createdAt: "asc" }], + where, + take: pageSize, + skip: (page - 1) * pageSize, + }), + prisma.service.count({ where }), + ]); + + return { + result: await Promise.all( + result.map(async (v) => ({ + ...v, + imageUrl: await presignedGetObjectIfExist( + MINIO_BUCKET, + imageLocation(v.id), + 12 * 60 * 60, + ), + })), + ), + page, + pageSize, + total, + }; + } + + @Get("{serviceId}") + @Security("keycloak") + async getServiceById(@Path() serviceId: string) { + const record = await prisma.service.findFirst({ + include: { + work: { + orderBy: { order: "asc" }, + include: { + productOnWork: { + include: { product: true }, + orderBy: { order: "asc" }, + }, + }, + }, + }, + where: { id: serviceId }, + }); + + if (!record) { + throw new HttpError(HttpStatus.NOT_FOUND, "Service cannot be found.", "serviceNotFound"); + } + + return Object.assign(record, { + imageUrl: await presignedGetObjectIfExist(MINIO_BUCKET, imageLocation(record.id), 60 * 60), + }); + } + + @Get("{serviceId}/work") + @Security("keycloak") + async getWorkOfService( + @Path() serviceId: string, + @Query() page: number = 1, + @Query() pageSize: number = 30, + ) { + const where = { + serviceId, + } satisfies Prisma.WorkWhereInput; + + const [result, total] = await prisma.$transaction([ + prisma.work.findMany({ + include: { + productOnWork: { + include: { + product: true, + }, + orderBy: { order: "asc" }, + }, + }, + where, + take: pageSize, + skip: (page - 1) * pageSize, + }), + prisma.work.count({ where }), + ]); + return { result, page, pageSize, total }; + } + + @Get("{serviceId}/image") + async getServiceImageById(@Request() req: RequestWithUser, @Path() serviceId: string) { + const url = await presignedGetObjectIfExist(MINIO_BUCKET, imageLocation(serviceId), 60 * 60); + + if (!url) { + throw new HttpError(HttpStatus.NOT_FOUND, "Image cannot be found", "imageNotFound"); + } + + return req.res?.redirect(url); + } + + @Post() + @Security("keycloak") + async createService(@Request() req: RequestWithUser, @Body() body: ServiceCreate) { + const { work, ...payload } = body; + + const record = await prisma.$transaction( + async (tx) => { + const last = await tx.runningNo.upsert({ + where: { + key: `SERVICE_${body.code.toLocaleUpperCase()}`, + }, + create: { + key: `SERVICE_${body.code.toLocaleUpperCase()}`, + value: 1, + }, + update: { value: { increment: 1 } }, + }); + + const workList = await Promise.all( + (work || []).map(async (w, wIdx) => + tx.work.create({ + data: { + name: w.name, + order: wIdx + 1, + attributes: w.attributes, + productOnWork: { + createMany: { + data: w.productId.map((p, pIdx) => ({ + productId: p, + order: pIdx + 1, + })), + }, + }, + }, + }), + ), + ); + + return tx.service.create({ + include: { + work: { + include: { + productOnWork: { + include: { + product: true, + }, + orderBy: { order: "asc" }, + }, + }, + }, + }, + data: { + ...payload, + statusOrder: +(body.status === "INACTIVE"), + code: `${body.code.toLocaleUpperCase()}${last.value.toString().padStart(3, "0")}`, + work: { connect: workList.map((v) => ({ id: v.id })) }, + createdBy: req.user.name, + updatedBy: req.user.name, + }, + }); + }, + { isolationLevel: Prisma.TransactionIsolationLevel.Serializable }, + ); + this.setStatus(HttpStatus.CREATED); + + return Object.assign(record, { + imageUrl: await presignedGetObjectIfExist( + MINIO_BUCKET, + imageLocation(record.id), + 12 * 60 * 60, + ), + imageUploadUrl: await minio.presignedPutObject( + MINIO_BUCKET, + imageLocation(record.id), + 12 * 60 * 60, + ), + }); + } + + @Put("{serviceId}") + @Security("keycloak") + async editService( + @Request() req: RequestWithUser, + @Body() body: ServiceUpdate, + @Path() serviceId: string, + ) { + if (!(await prisma.service.findUnique({ where: { id: serviceId } }))) { + throw new HttpError(HttpStatus.NOT_FOUND, "Service cannot be found.", "serviceNotFound"); + } + const { work, ...payload } = body; + const record = await prisma.$transaction(async (tx) => { + const workList = await Promise.all( + (work || []).map(async (w, wIdx) => + tx.work.create({ + data: { + name: w.name, + order: wIdx + 1, + attributes: w.attributes, + productOnWork: { + createMany: { + data: w.productId.map((p, pIdx) => ({ + productId: p, + order: pIdx + 1, + })), + }, + }, + }, + }), + ), + ); + + return await tx.service.update({ + data: { + ...payload, + statusOrder: +(payload.status === "INACTIVE"), + work: { + deleteMany: {}, + connect: workList.map((v) => ({ id: v.id })), + }, + updatedBy: req.user.name, + }, + where: { id: serviceId }, + }); + }); + + return Object.assign(record, { + imageUrl: await presignedGetObjectIfExist( + MINIO_BUCKET, + imageLocation(record.id), + 12 * 60 * 60, + ), + imageUploadUrl: await minio.presignedPutObject( + MINIO_BUCKET, + imageLocation(record.id), + 12 * 60 * 60, + ), + }); + } + + @Delete("{serviceId}") + @Security("keycloak") + async deleteService(@Path() serviceId: string) { + const record = await prisma.service.findFirst({ where: { id: serviceId } }); + + if (!record) { + throw new HttpError(HttpStatus.NOT_FOUND, "Service cannot be found.", "serviceNotFound"); + } + + if (record.status !== Status.CREATED) { + throw new HttpError(HttpStatus.FORBIDDEN, "Service is in used.", "serviceInUsed"); + } + + return await prisma.service.delete({ where: { id: serviceId } }); + } +} diff --git a/src/controllers/user-controller.ts b/src/controllers/user-controller.ts index a31b0a8..9f88d73 100644 --- a/src/controllers/user-controller.ts +++ b/src/controllers/user-controller.ts @@ -15,7 +15,7 @@ import { import { Prisma, Status, UserType } from "@prisma/client"; import prisma from "../db"; -import minio from "../services/minio"; +import minio, { presignedGetObjectIfExist } from "../services/minio"; import { RequestWithUser } from "../interfaces/user"; import HttpError from "../interfaces/http-error"; import HttpStatus from "../interfaces/http-status"; @@ -119,11 +119,11 @@ function imageLocation(id: string) { return `user/profile-img-${id}`; } -@Route("api/user") +@Route("api/v1/user") @Tags("User") -@Security("keycloak") export class UserController extends Controller { @Get("type-stats") + @Security("keycloak") async getUserTypeStats() { const list = await prisma.user.groupBy({ by: "userType", @@ -145,6 +145,7 @@ export class UserController extends Controller { } @Get() + @Security("keycloak") async getUser( @Query() userType?: UserType, @Query() zipCode?: string, @@ -166,7 +167,7 @@ export class UserController extends Controller { const [result, total] = await prisma.$transaction([ prisma.user.findMany({ - orderBy: { createdAt: "asc" }, + orderBy: [{ statusOrder: "asc" }, { createdAt: "asc" }], include: { province: true, district: true, @@ -185,7 +186,7 @@ export class UserController extends Controller { result.map(async (v) => ({ ...v, branch: includeBranch ? v.branch.map((a) => a.branch) : undefined, - profileImageUrl: await minio.presignedGetObject( + profileImageUrl: await presignedGetObjectIfExist( MINIO_BUCKET, imageLocation(v.id), 12 * 60 * 60, @@ -199,6 +200,7 @@ export class UserController extends Controller { } @Get("{userId}") + @Security("keycloak") async getUserById(@Path() userId: string) { const record = await prisma.user.findFirst({ include: { @@ -209,8 +211,7 @@ export class UserController extends Controller { where: { id: userId }, }); - if (!record) - throw new HttpError(HttpStatus.NOT_FOUND, "User cannot be found.", "data_not_found"); + if (!record) throw new HttpError(HttpStatus.NOT_FOUND, "User cannot be found.", "userNotFound"); return Object.assign(record, { profileImageUrl: await minio.presignedGetObject( @@ -222,6 +223,7 @@ export class UserController extends Controller { } @Post() + @Security("keycloak") async createUser(@Request() req: RequestWithUser, @Body() body: UserCreate) { if (body.provinceId || body.districtId || body.subDistrictId) { const [province, district, subDistrict] = await prisma.$transaction([ @@ -233,21 +235,21 @@ export class UserController extends Controller { throw new HttpError( HttpStatus.BAD_REQUEST, "Province cannot be found.", - "missing_or_invalid_parameter", + "relationProvinceNotFound", ); } if (body.districtId && !district) { throw new HttpError( HttpStatus.BAD_REQUEST, "District cannot be found.", - "missing_or_invalid_parameter", + "relationDistrictNotFound", ); } if (body.subDistrictId && !subDistrict) { throw new HttpError( HttpStatus.BAD_REQUEST, "Sub-district cannot be found.", - "missing_or_invalid_parameter", + "relationSubDistrictNotFound", ); } } @@ -268,6 +270,7 @@ export class UserController extends Controller { firstName: body.firstName, lastName: body.lastName, requiredActions: ["UPDATE_PASSWORD"], + enabled: rest.status !== "INACTIVE", }); if (!userId || typeof userId !== "string") { @@ -288,13 +291,14 @@ export class UserController extends Controller { data: { id: userId, ...rest, + statusOrder: +(rest.status === "INACTIVE"), username, userRole: role.name, province: { connect: provinceId ? { id: provinceId } : undefined }, district: { connect: districtId ? { id: districtId } : undefined }, subDistrict: { connect: subDistrictId ? { id: subDistrictId } : undefined }, createdBy: req.user.name, - updateBy: req.user.name, + updatedBy: req.user.name, }, }); @@ -315,6 +319,7 @@ export class UserController extends Controller { } @Put("{userId}") + @Security("keycloak") async editUser( @Request() req: RequestWithUser, @Body() body: UserUpdate, @@ -370,14 +375,23 @@ export class UserController extends Controller { if (!resultAddRole) { throw new Error("Failed. Cannot set user's role."); } else { - if (Array.isArray(currentRole)) await removeUserRoles(userId, currentRole); + if (Array.isArray(currentRole)) + await removeUserRoles( + userId, + currentRole.filter( + (a) => + !["uma_authorization", "offline_access", "default-roles"].some((b) => + a.name.includes(b), + ), + ), + ); } userRole = role.name; } if (body.username) { - await editUser(userId, { username: body.username }); + await editUser(userId, { username: body.username, enabled: body.status !== "INACTIVE" }); } const { provinceId, districtId, subDistrictId, ...rest } = body; @@ -387,7 +401,7 @@ export class UserController extends Controller { }); if (!user) { - throw new HttpError(HttpStatus.NOT_FOUND, "Branch cannot be found.", "data_not_found"); + throw new HttpError(HttpStatus.NOT_FOUND, "Branch cannot be found.", "branchNotFound"); } const lastUserOfType = @@ -406,6 +420,7 @@ export class UserController extends Controller { include: { province: true, district: true, subDistrict: true }, data: { ...rest, + statusOrder: +(rest.status === "INACTIVE"), userRole, code: (lastUserOfType && @@ -423,7 +438,7 @@ export class UserController extends Controller { connect: subDistrictId ? { id: subDistrictId } : undefined, disconnect: subDistrictId === null || undefined, }, - updateBy: req.user.name, + updatedBy: req.user.name, }, where: { id: userId }, }); @@ -443,6 +458,7 @@ export class UserController extends Controller { } @Delete("{userId}") + @Security("keycloak") async deleteUser(@Path() userId: string) { const record = await prisma.user.findFirst({ include: { @@ -454,11 +470,11 @@ export class UserController extends Controller { }); if (!record) { - throw new HttpError(HttpStatus.NOT_FOUND, "User cannot be found.", "data_not_found"); + throw new HttpError(HttpStatus.NOT_FOUND, "User cannot be found.", "userNotFound"); } if (record.status !== Status.CREATED) { - throw new HttpError(HttpStatus.FORBIDDEN, "User is in used.", "data_in_used"); + throw new HttpError(HttpStatus.FORBIDDEN, "User is in used.", "userInUsed"); } await minio.removeObject(MINIO_BUCKET, imageLocation(userId), { @@ -475,9 +491,7 @@ export class UserController extends Controller { stream.on("error", () => reject(new Error("MinIO error."))); }).then((list) => { list.map(async (v) => { - await minio.removeObject(MINIO_BUCKET, `${attachmentLocation(userId)}/${v}`, { - forceDelete: true, - }); + await minio.removeObject(MINIO_BUCKET, v, { forceDelete: true }); }); }); @@ -498,7 +512,7 @@ function attachmentLocation(uid: string) { return `user-attachment/${uid}`; } -@Route("api/user/{userId}/attachment") +@Route("api/v1/user/{userId}/attachment") @Tags("User") @Security("keycloak") export class UserAttachmentController extends Controller { @@ -514,7 +528,7 @@ export class UserAttachmentController extends Controller { }); if (!record) { - throw new HttpError(HttpStatus.NOT_FOUND, "User cannot be found.", "data_not_found"); + throw new HttpError(HttpStatus.NOT_FOUND, "User cannot be found.", "userNotFound"); } const list = await new Promise((resolve, reject) => { @@ -547,7 +561,7 @@ export class UserAttachmentController extends Controller { }); if (!record) { - throw new HttpError(HttpStatus.NOT_FOUND, "User cannot be found.", "data_not_found"); + throw new HttpError(HttpStatus.NOT_FOUND, "User cannot be found.", "userNotFound"); } return await Promise.all( diff --git a/src/controllers/work/work-controller.ts b/src/controllers/work/work-controller.ts new file mode 100644 index 0000000..24577b7 --- /dev/null +++ b/src/controllers/work/work-controller.ts @@ -0,0 +1,311 @@ +import { + Body, + Controller, + Delete, + Get, + Put, + Path, + Post, + Query, + Request, + Route, + Security, + Tags, +} from "tsoa"; +import { Prisma, Status } from "@prisma/client"; + +import prisma from "../../db"; +import { RequestWithUser } from "../../interfaces/user"; +import HttpError from "../../interfaces/http-error"; +import HttpStatus from "../../interfaces/http-status"; + +type WorkCreate = { + order: number; + name: string; + productId: string[]; + attributes?: { + [key: string]: any; + }; +}; + +type WorkUpdate = { + order?: number; + name?: string; + productId?: string[]; + attributes?: { + [key: string]: any; + }; +}; + +@Route("api/v1/work") +@Tags("Work") +@Security("keycloak") +export class WorkController extends Controller { + @Get() + async getWork( + @Query() baseOnly?: boolean, + @Query() query: string = "", + @Query() page: number = 1, + @Query() pageSize: number = 30, + ) { + const where = { + OR: [{ name: { contains: query }, serviceId: baseOnly ? null : undefined }], + } satisfies Prisma.WorkWhereInput; + + const [result, total] = await prisma.$transaction([ + prisma.work.findMany({ + include: { + productOnWork: { + include: { + product: true, + }, + orderBy: { + order: "asc", + }, + }, + }, + orderBy: { createdAt: "asc" }, + where, + take: pageSize, + skip: (page - 1) * pageSize, + }), + prisma.work.count({ where }), + ]); + + return { result, page, pageSize, total }; + } + + @Get("{workId}") + async getWorkById(@Path() workId: string) { + const record = await prisma.work.findFirst({ + where: { id: workId }, + }); + + if (!record) throw new HttpError(HttpStatus.NOT_FOUND, "Work cannot be found.", "workNotFound"); + + return record; + } + + @Get("{workId}/product") + async getProductOfWork( + @Path() workId: string, + @Query() query: string = "", + @Query() page: number = 1, + @Query() pageSize: number = 30, + ) { + const where = { + AND: [ + { + workProduct: { some: { workId } }, + }, + { + OR: [{ name: { contains: query } }], + }, + ], + } satisfies Prisma.ProductWhereInput; + + const [result, total] = await prisma.$transaction([ + prisma.product.findMany({ + where, + take: pageSize, + skip: (page - 1) * pageSize, + }), + prisma.product.count({ + where, + }), + ]); + + return { result, page, pageSize, total }; + } + + @Post() + async createWork(@Request() req: RequestWithUser, @Body() body: WorkCreate) { + const { productId, ...payload } = body; + + const exist = await prisma.work.findFirst({ + include: { + productOnWork: { + include: { + product: true, + }, + }, + }, + where: { + productOnWork: { + every: { + productId: { in: productId }, + }, + }, + NOT: { + OR: [ + { + productOnWork: { + some: { + productId: { notIn: productId }, + }, + }, + }, + { + productOnWork: { + none: {}, + }, + }, + ], + }, + }, + }); + + if (exist) return exist; + + const productList = await prisma.product.findMany({ + where: { id: { in: productId } }, + }); + + if (productList.length !== productId.length) { + throw new HttpError(HttpStatus.BAD_REQUEST, "Some product not found.", "someProductBadReq"); + } + + const record = await prisma.work.create({ + include: { + productOnWork: { + include: { + product: true, + }, + orderBy: { + order: "asc", + }, + }, + }, + data: { + ...payload, + productOnWork: { + createMany: { + data: productId.map((v, i) => ({ + order: i + 1, + productId: v, + createdBy: req.user.name, + updatedBy: req.user.name, + })), + }, + }, + createdBy: req.user.name, + updatedBy: req.user.name, + }, + }); + + await prisma.product.updateMany({ + where: { id: { in: body.productId }, status: Status.CREATED }, + data: { status: Status.ACTIVE }, + }); + + this.setStatus(HttpStatus.CREATED); + + return record; + } + + @Put("{workId}") + async editWork( + @Request() req: RequestWithUser, + @Body() body: WorkUpdate, + @Path() workId: string, + ) { + const { productId, ...payload } = body; + + if (!(await prisma.work.findUnique({ where: { id: workId } }))) { + throw new HttpError(HttpStatus.NOT_FOUND, "Work cannot be found.", "workNotFound"); + } + + const exist = await prisma.work.findFirst({ + include: { + productOnWork: { + include: { + product: true, + }, + }, + }, + where: { + productOnWork: { + every: { + productId: { in: productId }, + }, + }, + NOT: { + OR: [ + { id: workId }, + { + productOnWork: { + some: { + productId: { notIn: productId }, + }, + }, + }, + { + productOnWork: { + none: {}, + }, + }, + ], + }, + }, + }); + + if (exist) return exist; + + const record = await prisma.work.update({ + include: { + productOnWork: { + include: { + product: true, + }, + orderBy: { + order: "asc", + }, + }, + }, + where: { id: workId }, + data: { + ...payload, + productOnWork: productId + ? { + deleteMany: { + productId: { notIn: productId }, + }, + upsert: productId.map((v, i) => ({ + where: { + workId_productId: { + workId, + productId: v, + }, + }, + update: { order: i + 1 }, + create: { + order: i + 1, + productId: v, + createdBy: req.user.name, + updatedBy: req.user.name, + }, + })), + } + : undefined, + updatedBy: req.user.name, + }, + }); + + return record; + } + + @Delete("{workId}") + async deleteWork(@Path() workId: string) { + const record = await prisma.work.findFirst({ where: { id: workId } }); + + if (!record) { + throw new HttpError(HttpStatus.NOT_FOUND, "Work cannot be found.", "workNotFound"); + } + + if (record.status !== Status.CREATED) { + throw new HttpError(HttpStatus.FORBIDDEN, "Work is in used.", "workInUsed"); + } + + return await prisma.work.delete({ where: { id: workId } }); + } +} diff --git a/src/db.ts b/src/db.ts index 7298c40..1e2206b 100644 --- a/src/db.ts +++ b/src/db.ts @@ -1,7 +1,23 @@ import { PrismaClient } from "@prisma/client"; +import { Kysely, PostgresAdapter, PostgresIntrospector, PostgresQueryCompiler } from "kysely"; +import kyselyExtension from "prisma-extension-kysely"; +import type { DB } from "./generated/kysely/types"; const prisma = new PrismaClient({ errorFormat: process.env.NODE_ENV === "production" ? "minimal" : "pretty", -}); +}).$extends( + kyselyExtension({ + kysely: (driver) => + new Kysely({ + dialect: { + createDriver: () => driver, + createAdapter: () => new PostgresAdapter(), + createIntrospector: (db: Kysely) => new PostgresIntrospector(db), + createQueryCompiler: () => new PostgresQueryCompiler(), + }, + plugins: [], + }), + }), +); export default prisma; diff --git a/src/interfaces/http-error.ts b/src/interfaces/http-error.ts index e9f34fd..e4820bc 100644 --- a/src/interfaces/http-error.ts +++ b/src/interfaces/http-error.ts @@ -1,29 +1,20 @@ import HttpStatus from "./http-status"; -type DevMessage = - | "missing_or_invalid_parameter" - | "data_exists" - | "data_in_used" - | "no_permission" - | "unknown_url" - | "data_not_found" - | "unauthorized"; - class HttpError extends Error { /** * HTTP Status Code */ status: HttpStatus; message: string; - devMessage?: DevMessage; + code?: string; - constructor(status: HttpStatus, message: string, devMessage?: DevMessage) { + constructor(status: HttpStatus, message: string, code?: string) { super(message); this.name = "HttpError"; this.status = status; this.message = message; - this.devMessage = devMessage; + this.code = code; } } diff --git a/src/interfaces/user.ts b/src/interfaces/user.ts index 12c5d59..a35cdc4 100644 --- a/src/interfaces/user.ts +++ b/src/interfaces/user.ts @@ -2,6 +2,7 @@ import type { Request } from "express"; export type RequestWithUser = Request & { user: { + sub: string; name: string; given_name: string; familiy_name: string; diff --git a/src/middlewares/auth.ts b/src/middlewares/auth.ts index ad0bb1e..1809e73 100644 --- a/src/middlewares/auth.ts +++ b/src/middlewares/auth.ts @@ -10,8 +10,15 @@ export async function expressAuthentication( ) { switch (securityName) { case "keycloak": - return keycloakAuth(request, scopes); + const authData = await keycloakAuth(request, scopes); + request.app.locals.logData.sessionId = authData.session_state; + request.app.locals.logData.user = authData.preffered_username; + return authData; default: - throw new HttpError(HttpStatus.NOT_IMPLEMENTED, "ไม่ทราบวิธียืนยันตัวตน"); + throw new HttpError( + HttpStatus.NOT_IMPLEMENTED, + "Unknown how to verify identity.", + "unknowHowToVerify", + ); } } diff --git a/src/middlewares/error.ts b/src/middlewares/error.ts index d80ceb3..177e363 100644 --- a/src/middlewares/error.ts +++ b/src/middlewares/error.ts @@ -8,7 +8,7 @@ function error(error: Error, _req: Request, res: Response, _next: NextFunction) return res.status(error.status).json({ status: error.status, message: error.message, - devMessage: error.devMessage, + code: error.code, }); } @@ -17,7 +17,7 @@ function error(error: Error, _req: Request, res: Response, _next: NextFunction) status: HttpStatus.UNPROCESSABLE_ENTITY, message: "Validation error(s).", detail: error.fields, - devMessage: "missing_or_invalid_parameter", + code: "validateError", }); } @@ -26,7 +26,7 @@ function error(error: Error, _req: Request, res: Response, _next: NextFunction) return res.status(HttpStatus.INTERNAL_SERVER_ERROR).json({ status: HttpStatus.INTERNAL_SERVER_ERROR, message: error.message, - devMessage: "system_error", + code: "system_error", }); } diff --git a/src/middlewares/log.ts b/src/middlewares/log.ts index 3cd45f5..d7ab8db 100644 --- a/src/middlewares/log.ts +++ b/src/middlewares/log.ts @@ -1,5 +1,6 @@ import { NextFunction, Request, Response } from "express"; import elasticsearch from "../services/elasticsearch"; +import { randomUUID } from "crypto"; if (!process.env.ELASTICSEARCH_INDEX) { throw new Error("Require ELASTICSEARCH_INDEX to store log."); @@ -50,16 +51,11 @@ async function logMiddleware(req: Request, res: Response, next: NextFunction) { host: req.hostname, sessionId: req.headers["x-session-id"], rtId: req.headers["x-rtid"], - tId: req.headers["x-tid"], + tId: randomUUID(), method: req.method, endpoint: req.url, responseCode: res.statusCode, - responseDescription: - data?.devMessage !== undefined - ? data.devMessage - : { 200: "success", 201: "created_success", 204: "no_content", 304: "success" }[ - res.statusCode - ], + responseDescription: data?.code, input: (level === 4 && JSON.stringify(req.body, null, 2)) || undefined, output: (level === 4 && JSON.stringify(data, null, 2)) || undefined, ...req.app.locals.logData, diff --git a/src/middlewares/role.ts b/src/middlewares/role.ts index d02d316..dd2ec2f 100644 --- a/src/middlewares/role.ts +++ b/src/middlewares/role.ts @@ -5,14 +5,14 @@ import HttpStatus from "../interfaces/http-status"; export function role( role: string | string[], - errorMessage: string = "คุณไม่มีสิทธิในการเข้าถึงทรัพยากรดังกล่าว", + errorMessage: string = "You do not have permission to access this resource.", ) { return (req: RequestWithUser, _res: Response, next: NextFunction) => { if (!Array.isArray(role) && !req.user.role.includes(role) && !req.user.role.includes("*")) { - throw new HttpError(HttpStatus.FORBIDDEN, errorMessage); + throw new HttpError(HttpStatus.FORBIDDEN, errorMessage, "noPermissionToAccess"); } if (role !== "*" && !req.user.role.some((v) => role.includes(v))) { - throw new HttpError(HttpStatus.FORBIDDEN, errorMessage); + throw new HttpError(HttpStatus.FORBIDDEN, errorMessage, "noPermissionToAccess"); } return next(); }; diff --git a/src/services/keycloak.ts b/src/services/keycloak.ts index db7b4b5..984817f 100644 --- a/src/services/keycloak.ts +++ b/src/services/keycloak.ts @@ -2,8 +2,8 @@ import { DecodedJwt, createDecoder } from "fast-jwt"; const KC_URL = process.env.KC_URL; const KC_REALM = process.env.KC_REALM; -const KC_CLIENT_ID = process.env.KC_SERVICE_ACCOUNT_CLIENT_ID; -const KC_SECRET = process.env.KC_SERVICE_ACCOUNT_SECRET; +const KC_ADMIN_USERNAME = process.env.KC_ADMIN_USERNAME; +const KC_ADMIN_PASSWORD = process.env.KC_ADMIN_PASSWORD; let token: string | null = null; let decoded: DecodedJwt | null = null; @@ -14,7 +14,7 @@ const jwtDecode = createDecoder({ complete: true }); * Check if token is expired or will expire in 30 seconds * @returns true if expire or can't get exp, false otherwise */ -export function isTokenExpired(token: string, beforeExpire: number = 30) { +export function isTokenExpired(token: string, beforeExpire: number = 10) { decoded = jwtDecode(token); if (decoded && decoded.payload.exp) { @@ -28,19 +28,20 @@ export function isTokenExpired(token: string, beforeExpire: number = 30) { * Get token from keycloak if needed */ export async function getToken() { - if (!KC_CLIENT_ID || !KC_SECRET) { - throw new Error("KC_CLIENT_ID and KC_SECRET are required to used this feature."); + if (!KC_ADMIN_PASSWORD || !KC_ADMIN_USERNAME) { + throw new Error("KC_ADMIN_USERNAME and KC_ADMIN_PASSWORD are required to used this feature."); } if (token && !isTokenExpired(token)) return token; const body = new URLSearchParams(); - body.append("client_id", KC_CLIENT_ID); - body.append("client_secret", KC_SECRET); - body.append("grant_type", "client_credentials"); + body.append("client_id", "admin-cli"); + body.append("grant_type", "password"); + body.append("username", KC_ADMIN_USERNAME); + body.append("password", KC_ADMIN_PASSWORD); - const res = await fetch(`${KC_URL}/realms/${KC_REALM}/protocol/openid-connect/token`, { + const res = await fetch(`${KC_URL}/realms/master/protocol/openid-connect/token`, { method: "POST", body: body, }).catch((e) => console.error(e)); @@ -74,7 +75,7 @@ export async function createUser(username: string, password: string, opts?: Reco }, method: "POST", body: JSON.stringify({ - enabled: true, + enabled: opts?.enabled !== undefined ? opts.enabled : true, credentials: [{ type: "password", value: password }], username, ...opts, @@ -109,7 +110,7 @@ export async function editUser(userId: string, opts: Record) { }, method: "PUT", body: JSON.stringify({ - enabled: true, + enabled: opts?.enabled !== undefined ? opts.enabled : true, credentials: (password && [{ type: "password", value: opts?.password }]) || undefined, ...rest, }), diff --git a/src/services/minio.ts b/src/services/minio.ts index 5f68d91..1204c72 100644 --- a/src/services/minio.ts +++ b/src/services/minio.ts @@ -9,3 +9,52 @@ const minio = new Client({ }); export default minio; + +// minio typescript does not support include version +type BucketItemWithVersion = { + name: string; + lastModified: string; + etag: string; + size: number; + versionId: string; + isLatest: boolean; + isDeleteMarker: boolean; +}; + +export async function listObjectVersion(bucket: string, obj: string) { + return await new Promise((resolve, reject) => { + const data: BucketItemWithVersion[] = []; + // @ts-ignore + let stream = minio.listObjects(bucket, obj, true, { + IncludeVersion: true, // type error (ts not support) - expected 3 args but got 4 + }); + stream.on("data", (obj) => data.push(obj as unknown as BucketItemWithVersion)); + stream.on("error", (err) => reject(err)); + stream.on("end", () => resolve(data)); + }); +} + +export async function deleteObjectAllVersion(bucket: string, obj: string) { + const item = await listObjectVersion(bucket, obj); + + return await new Promise((resolve, reject) => { + minio.removeObjects( + bucket, + // @ts-ignore + item.map(({ name, versionId }) => ({ name, versionId })), // type error (ts not support) - expected "string[]" + (e) => (e && reject(e)) || resolve(true), + ); + }); +} + +export async function presignedGetObjectIfExist(bucket: string, obj: string, exp?: number) { + if ( + await minio.statObject(bucket, obj).catch((e) => { + if (e.code === "NotFound") return false; + throw new Error("Object storage error."); + }) + ) { + return await minio.presignedGetObject(bucket, obj, exp); + } + return null; +} diff --git a/tsoa.json b/tsoa.json index 694176c..b6acbc9 100644 --- a/tsoa.json +++ b/tsoa.json @@ -29,10 +29,11 @@ { "name": "Employee Checkup" }, { "name": "Employee Work" }, { "name": "Employee Other Info" }, - { "name": "Service" }, - { "name": "Work" }, + { "name": "Product Group" }, { "name": "Product Type" }, - { "name": "Product Group" } + { "name": "Product" }, + { "name": "Work" }, + { "name": "Service" } ] } },