auth services implmented
This commit is contained in:
parent
8ca2d34dc6
commit
b4b752ca3a
23
README.md
23
README.md
|
|
@ -25,3 +25,26 @@ docker builder prune --all
|
|||
|
||||
npm install @prisma/client
|
||||
npm install -D prisma
|
||||
npm install class-validator class-transformer --legacy-peer-deps
|
||||
|
||||
npx prisma generate # generate client
|
||||
npx prisma db pull # update local schema
|
||||
|
||||
npx prisma db seed # seed database
|
||||
|
||||
nest generate module
|
||||
nest generate service
|
||||
nest generate controller
|
||||
|
||||
or / alias
|
||||
nest g module
|
||||
nest g service
|
||||
nest g controller
|
||||
|
||||
npm install @liaoliaots/nestjs-redis ioredis --legacy-peer-deps
|
||||
|
||||
npx prisma migrate dev --name "comment" # good for production creates step of migration
|
||||
npx prisma db push # update remote schema # not good for production creates no step of migration
|
||||
|
||||
npx prisma validate
|
||||
npx prisma format
|
||||
|
|
|
|||
|
|
@ -3,12 +3,12 @@ FROM node:20-alpine AS builder
|
|||
|
||||
WORKDIR /usr/src/app
|
||||
|
||||
COPY backend/package*.json ./
|
||||
COPY ServicesApi/package*.json ./
|
||||
|
||||
RUN npm install -g npm@latest
|
||||
RUN npm ci
|
||||
RUN npm ci --legacy-peer-deps
|
||||
|
||||
COPY backend .
|
||||
COPY ServicesApi .
|
||||
|
||||
RUN npm run build
|
||||
|
||||
|
|
|
|||
|
|
@ -9,12 +9,18 @@
|
|||
"version": "0.0.1",
|
||||
"license": "UNLICENSED",
|
||||
"dependencies": {
|
||||
"@liaoliaots/nestjs-redis": "^10.0.0",
|
||||
"@nestjs/common": "^11.0.1",
|
||||
"@nestjs/core": "^11.0.1",
|
||||
"@nestjs/platform-express": "^11.0.1",
|
||||
"@prisma/client": "^6.12.0",
|
||||
"class-transformer": "^0.5.1",
|
||||
"class-validator": "^0.14.2",
|
||||
"ioredis": "^5.6.1",
|
||||
"redis": "^5.6.1",
|
||||
"reflect-metadata": "^0.2.2",
|
||||
"rxjs": "^7.8.1"
|
||||
"rxjs": "^7.8.1",
|
||||
"uuid": "^11.1.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@eslint/eslintrc": "^3.2.0",
|
||||
|
|
@ -1292,6 +1298,12 @@
|
|||
}
|
||||
}
|
||||
},
|
||||
"node_modules/@ioredis/commands": {
|
||||
"version": "1.2.0",
|
||||
"resolved": "https://registry.npmjs.org/@ioredis/commands/-/commands-1.2.0.tgz",
|
||||
"integrity": "sha512-Sx1pU8EM64o2BrqNpEO1CNLtKQwyhuXuqyfH7oGKCk+1a33d2r5saW8zNwm3j6BTExtjrv2BxTgzzkMwts6vGg==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/@isaacs/balanced-match": {
|
||||
"version": "4.0.1",
|
||||
"resolved": "https://registry.npmjs.org/@isaacs/balanced-match/-/balanced-match-4.0.1.tgz",
|
||||
|
|
@ -1916,6 +1928,29 @@
|
|||
"@jridgewell/sourcemap-codec": "^1.4.14"
|
||||
}
|
||||
},
|
||||
"node_modules/@liaoliaots/nestjs-redis": {
|
||||
"version": "10.0.0",
|
||||
"resolved": "https://registry.npmjs.org/@liaoliaots/nestjs-redis/-/nestjs-redis-10.0.0.tgz",
|
||||
"integrity": "sha512-uCTmlzM4q+UYADwsJEQph0mbf4u0MrktFhByi50M5fNy/+fJoWlhSqrgvjtVKjHnqydxy1gyuU6vHJEOBp9cjg==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"tslib": "2.7.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=16.13.0"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@nestjs/common": "^10.0.0",
|
||||
"@nestjs/core": "^10.0.0",
|
||||
"ioredis": "^5.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@liaoliaots/nestjs-redis/node_modules/tslib": {
|
||||
"version": "2.7.0",
|
||||
"resolved": "https://registry.npmjs.org/tslib/-/tslib-2.7.0.tgz",
|
||||
"integrity": "sha512-gLXCKdN1/j47AiHiOkJN69hJmcbGTHI0ImLmbYLHykhgeN0jVGola9yVjFgzCUklsZQMW55o+dW7IXv3RCXDzA==",
|
||||
"license": "0BSD"
|
||||
},
|
||||
"node_modules/@lukeed/csprng": {
|
||||
"version": "1.1.0",
|
||||
"resolved": "https://registry.npmjs.org/@lukeed/csprng/-/csprng-1.1.0.tgz",
|
||||
|
|
@ -2780,7 +2815,7 @@
|
|||
"version": "6.12.0",
|
||||
"resolved": "https://registry.npmjs.org/@prisma/config/-/config-6.12.0.tgz",
|
||||
"integrity": "sha512-HovZWzhWEMedHxmjefQBRZa40P81N7/+74khKFz9e1AFjakcIQdXgMWKgt20HaACzY+d1LRBC+L4tiz71t9fkg==",
|
||||
"devOptional": true,
|
||||
"dev": true,
|
||||
"license": "Apache-2.0",
|
||||
"dependencies": {
|
||||
"jiti": "2.4.2"
|
||||
|
|
@ -2790,14 +2825,14 @@
|
|||
"version": "6.12.0",
|
||||
"resolved": "https://registry.npmjs.org/@prisma/debug/-/debug-6.12.0.tgz",
|
||||
"integrity": "sha512-plbz6z72orcqr0eeio7zgUrZj5EudZUpAeWkFTA/DDdXEj28YHDXuiakvR6S7sD6tZi+jiwQEJAPeV6J6m/tEQ==",
|
||||
"devOptional": true,
|
||||
"dev": true,
|
||||
"license": "Apache-2.0"
|
||||
},
|
||||
"node_modules/@prisma/engines": {
|
||||
"version": "6.12.0",
|
||||
"resolved": "https://registry.npmjs.org/@prisma/engines/-/engines-6.12.0.tgz",
|
||||
"integrity": "sha512-4BRZZUaAuB4p0XhTauxelvFs7IllhPmNLvmla0bO1nkECs8n/o1pUvAVbQ/VOrZR5DnF4HED0PrGai+rIOVePA==",
|
||||
"devOptional": true,
|
||||
"dev": true,
|
||||
"hasInstallScript": true,
|
||||
"license": "Apache-2.0",
|
||||
"dependencies": {
|
||||
|
|
@ -2811,14 +2846,14 @@
|
|||
"version": "6.12.0-15.8047c96bbd92db98a2abc7c9323ce77c02c89dbc",
|
||||
"resolved": "https://registry.npmjs.org/@prisma/engines-version/-/engines-version-6.12.0-15.8047c96bbd92db98a2abc7c9323ce77c02c89dbc.tgz",
|
||||
"integrity": "sha512-70vhecxBJlRr06VfahDzk9ow4k1HIaSfVUT3X0/kZoHCMl9zbabut4gEXAyzJZxaCGi5igAA7SyyfBI//mmkbQ==",
|
||||
"devOptional": true,
|
||||
"dev": true,
|
||||
"license": "Apache-2.0"
|
||||
},
|
||||
"node_modules/@prisma/fetch-engine": {
|
||||
"version": "6.12.0",
|
||||
"resolved": "https://registry.npmjs.org/@prisma/fetch-engine/-/fetch-engine-6.12.0.tgz",
|
||||
"integrity": "sha512-EamoiwrK46rpWaEbLX9aqKDPOd8IyLnZAkiYXFNuq0YsU0Z8K09/rH8S7feOWAVJ3xzeSgcEJtBlVDrajM9Sag==",
|
||||
"devOptional": true,
|
||||
"dev": true,
|
||||
"license": "Apache-2.0",
|
||||
"dependencies": {
|
||||
"@prisma/debug": "6.12.0",
|
||||
|
|
@ -2830,12 +2865,72 @@
|
|||
"version": "6.12.0",
|
||||
"resolved": "https://registry.npmjs.org/@prisma/get-platform/-/get-platform-6.12.0.tgz",
|
||||
"integrity": "sha512-nRerTGhTlgyvcBlyWgt8OLNIV7QgJS2XYXMJD1hysorMCuLAjuDDuoxmVt7C2nLxbuxbWPp7OuFRHC23HqD9dA==",
|
||||
"devOptional": true,
|
||||
"dev": true,
|
||||
"license": "Apache-2.0",
|
||||
"dependencies": {
|
||||
"@prisma/debug": "6.12.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@redis/bloom": {
|
||||
"version": "5.6.1",
|
||||
"resolved": "https://registry.npmjs.org/@redis/bloom/-/bloom-5.6.1.tgz",
|
||||
"integrity": "sha512-5/22U76IMEfn6TeZ+uvjXspHw+ykBF0kpBa8xouzeHaQMXs/auqBUOEYzU2VKYDvnd2RSpPTyIg82oB7PpUgLg==",
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">= 18"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@redis/client": "^5.6.1"
|
||||
}
|
||||
},
|
||||
"node_modules/@redis/client": {
|
||||
"version": "5.6.1",
|
||||
"resolved": "https://registry.npmjs.org/@redis/client/-/client-5.6.1.tgz",
|
||||
"integrity": "sha512-bWHmSFIJ5w1Y4aHsYs46XMDHKQsBHFRhNcllYaBxz2Zl+lu+gbm5yI9BqxvKh48bLTs/Wx1Kns0gN2WIasE8MA==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"cluster-key-slot": "1.1.2"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 18"
|
||||
}
|
||||
},
|
||||
"node_modules/@redis/json": {
|
||||
"version": "5.6.1",
|
||||
"resolved": "https://registry.npmjs.org/@redis/json/-/json-5.6.1.tgz",
|
||||
"integrity": "sha512-cTggVzPIVuiFeXcEcnTRiUzV7rmUvM9KUYxWiHyjsAVACTEUe4ifKkvzrij0H/z3ammU5tfGACffDB3olBwtVA==",
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">= 18"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@redis/client": "^5.6.1"
|
||||
}
|
||||
},
|
||||
"node_modules/@redis/search": {
|
||||
"version": "5.6.1",
|
||||
"resolved": "https://registry.npmjs.org/@redis/search/-/search-5.6.1.tgz",
|
||||
"integrity": "sha512-+eOjx8O2YoKygjqkLpTHqcAq0zKLjior+ee2tRBx/3RSf1+OHxiC9Y6NstshQpvB1XHqTw9n7+f0+MsRJZrp0g==",
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">= 18"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@redis/client": "^5.6.1"
|
||||
}
|
||||
},
|
||||
"node_modules/@redis/time-series": {
|
||||
"version": "5.6.1",
|
||||
"resolved": "https://registry.npmjs.org/@redis/time-series/-/time-series-5.6.1.tgz",
|
||||
"integrity": "sha512-sd3q4jMJdoSO2akw1L9NrdFI1JJ6zeMgMUoTh4a34p9sY3AnOI4aDLCecy8L2IcPAP1oNR3TbLFJiCJDQ35QTA==",
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">= 18"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@redis/client": "^5.6.1"
|
||||
}
|
||||
},
|
||||
"node_modules/@sinclair/typebox": {
|
||||
"version": "0.27.8",
|
||||
"resolved": "https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.27.8.tgz",
|
||||
|
|
@ -3526,6 +3621,12 @@
|
|||
"@types/superagent": "^8.1.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@types/validator": {
|
||||
"version": "13.15.2",
|
||||
"resolved": "https://registry.npmjs.org/@types/validator/-/validator-13.15.2.tgz",
|
||||
"integrity": "sha512-y7pa/oEJJ4iGYBxOpfAKn5b9+xuihvzDVnC/OSvlVnGxVg0pOqmjiMafiJ1KVNQEaPZf9HsEp5icEwGg8uIe5Q==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/@types/yargs": {
|
||||
"version": "17.0.33",
|
||||
"resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-17.0.33.tgz",
|
||||
|
|
@ -4274,20 +4375,6 @@
|
|||
"node": ">=0.4.0"
|
||||
}
|
||||
},
|
||||
"node_modules/acorn-import-phases": {
|
||||
"version": "1.0.4",
|
||||
"resolved": "https://registry.npmjs.org/acorn-import-phases/-/acorn-import-phases-1.0.4.tgz",
|
||||
"integrity": "sha512-wKmbr/DDiIXzEOiWrTTUcDm24kQ2vGfZQvM2fwg2vXqR5uW6aapr7ObPtj1th32b9u90/Pf4AItvdTh42fBmVQ==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"peer": true,
|
||||
"engines": {
|
||||
"node": ">=10.13.0"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"acorn": "^8.14.0"
|
||||
}
|
||||
},
|
||||
"node_modules/acorn-jsx": {
|
||||
"version": "5.3.2",
|
||||
"resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz",
|
||||
|
|
@ -5100,6 +5187,23 @@
|
|||
"dev": true,
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/class-transformer": {
|
||||
"version": "0.5.1",
|
||||
"resolved": "https://registry.npmjs.org/class-transformer/-/class-transformer-0.5.1.tgz",
|
||||
"integrity": "sha512-SQa1Ws6hUbfC98vKGxZH3KFY0Y1lm5Zm0SY8XX9zbK7FJCyVEac3ATW0RIpwzW+oOfmHE5PMPufDG9hCfoEOMw==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/class-validator": {
|
||||
"version": "0.14.2",
|
||||
"resolved": "https://registry.npmjs.org/class-validator/-/class-validator-0.14.2.tgz",
|
||||
"integrity": "sha512-3kMVRF2io8N8pY1IFIXlho9r8IPUUIfHe2hYVtiebvAzU2XeQFXTv+XI4WX+TnXmtwXMDcjngcpkiPM0O9PvLw==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@types/validator": "^13.11.8",
|
||||
"libphonenumber-js": "^1.11.1",
|
||||
"validator": "^13.9.0"
|
||||
}
|
||||
},
|
||||
"node_modules/cli-cursor": {
|
||||
"version": "3.1.0",
|
||||
"resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-3.1.0.tgz",
|
||||
|
|
@ -5218,6 +5322,15 @@
|
|||
"node": ">=0.8"
|
||||
}
|
||||
},
|
||||
"node_modules/cluster-key-slot": {
|
||||
"version": "1.1.2",
|
||||
"resolved": "https://registry.npmjs.org/cluster-key-slot/-/cluster-key-slot-1.1.2.tgz",
|
||||
"integrity": "sha512-RMr0FhtfXemyinomL4hrWcYJxmX6deFdCxpJzhDttxgO1+bcCnkk+9drydLVDmAMG7NE6aN/fl4F7ucU/90gAA==",
|
||||
"license": "Apache-2.0",
|
||||
"engines": {
|
||||
"node": ">=0.10.0"
|
||||
}
|
||||
},
|
||||
"node_modules/co": {
|
||||
"version": "4.6.0",
|
||||
"resolved": "https://registry.npmjs.org/co/-/co-4.6.0.tgz",
|
||||
|
|
@ -5593,6 +5706,15 @@
|
|||
"node": ">=0.4.0"
|
||||
}
|
||||
},
|
||||
"node_modules/denque": {
|
||||
"version": "2.1.0",
|
||||
"resolved": "https://registry.npmjs.org/denque/-/denque-2.1.0.tgz",
|
||||
"integrity": "sha512-HVQE3AAb/pxF8fQAoiqpvg9i3evqug3hoiwakOyZAwJm+6vZehbkYXZ0l4JxS+I3QxM97v5aaRNhj8v5oBhekw==",
|
||||
"license": "Apache-2.0",
|
||||
"engines": {
|
||||
"node": ">=0.10"
|
||||
}
|
||||
},
|
||||
"node_modules/depd": {
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz",
|
||||
|
|
@ -7149,6 +7271,30 @@
|
|||
"kind-of": "^6.0.2"
|
||||
}
|
||||
},
|
||||
"node_modules/ioredis": {
|
||||
"version": "5.6.1",
|
||||
"resolved": "https://registry.npmjs.org/ioredis/-/ioredis-5.6.1.tgz",
|
||||
"integrity": "sha512-UxC0Yv1Y4WRJiGQxQkP0hfdL0/5/6YvdfOOClRgJ0qppSarkhneSa6UvkMkms0AkdGimSH3Ikqm+6mkMmX7vGA==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@ioredis/commands": "^1.1.1",
|
||||
"cluster-key-slot": "^1.1.0",
|
||||
"debug": "^4.3.4",
|
||||
"denque": "^2.1.0",
|
||||
"lodash.defaults": "^4.2.0",
|
||||
"lodash.isarguments": "^3.1.0",
|
||||
"redis-errors": "^1.2.0",
|
||||
"redis-parser": "^3.0.0",
|
||||
"standard-as-callback": "^2.1.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=12.22.0"
|
||||
},
|
||||
"funding": {
|
||||
"type": "opencollective",
|
||||
"url": "https://opencollective.com/ioredis"
|
||||
}
|
||||
},
|
||||
"node_modules/ipaddr.js": {
|
||||
"version": "1.9.1",
|
||||
"resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz",
|
||||
|
|
@ -8083,7 +8229,7 @@
|
|||
"version": "2.4.2",
|
||||
"resolved": "https://registry.npmjs.org/jiti/-/jiti-2.4.2.tgz",
|
||||
"integrity": "sha512-rg9zJN+G4n2nfJl5MW3BMygZX56zKPNVEYYqq7adpmMh4Jn2QNEwhvQlFy6jPVdcod7txZtKHWnyZiA3a0zP7A==",
|
||||
"devOptional": true,
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"bin": {
|
||||
"jiti": "lib/jiti-cli.mjs"
|
||||
|
|
@ -8237,6 +8383,12 @@
|
|||
"node": ">= 0.8.0"
|
||||
}
|
||||
},
|
||||
"node_modules/libphonenumber-js": {
|
||||
"version": "1.12.10",
|
||||
"resolved": "https://registry.npmjs.org/libphonenumber-js/-/libphonenumber-js-1.12.10.tgz",
|
||||
"integrity": "sha512-E91vHJD61jekHHR/RF/E83T/CMoaLXT7cwYA75T4gim4FZjnM6hbJjVIGg7chqlSqRsSvQ3izGmOjHy1SQzcGQ==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/lines-and-columns": {
|
||||
"version": "1.2.4",
|
||||
"resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.2.4.tgz",
|
||||
|
|
@ -8296,6 +8448,18 @@
|
|||
"dev": true,
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/lodash.defaults": {
|
||||
"version": "4.2.0",
|
||||
"resolved": "https://registry.npmjs.org/lodash.defaults/-/lodash.defaults-4.2.0.tgz",
|
||||
"integrity": "sha512-qjxPLHd3r5DnsdGacqOMU6pb/avJzdh9tFX2ymgoZE27BmjXrNy/y4LoaiTeAb+O3gL8AfpJGtqfX/ae2leYYQ==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/lodash.isarguments": {
|
||||
"version": "3.1.0",
|
||||
"resolved": "https://registry.npmjs.org/lodash.isarguments/-/lodash.isarguments-3.1.0.tgz",
|
||||
"integrity": "sha512-chi4NHZlZqZD18a0imDHnZPrDeBbTtVN7GXMwuGdRH9qotxAjYs3aVLKc7zNOG9eddR5Ksd8rvFEBc9SsggPpg==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/lodash.memoize": {
|
||||
"version": "4.1.2",
|
||||
"resolved": "https://registry.npmjs.org/lodash.memoize/-/lodash.memoize-4.1.2.tgz",
|
||||
|
|
@ -9271,7 +9435,7 @@
|
|||
"version": "6.12.0",
|
||||
"resolved": "https://registry.npmjs.org/prisma/-/prisma-6.12.0.tgz",
|
||||
"integrity": "sha512-pmV7NEqQej9WjizN6RSNIwf7Y+jeh9mY1JEX2WjGxJi4YZWexClhde1yz/FuvAM+cTwzchcMytu2m4I6wPkIzg==",
|
||||
"devOptional": true,
|
||||
"dev": true,
|
||||
"hasInstallScript": true,
|
||||
"license": "Apache-2.0",
|
||||
"dependencies": {
|
||||
|
|
@ -9465,6 +9629,43 @@
|
|||
"url": "https://paulmillr.com/funding/"
|
||||
}
|
||||
},
|
||||
"node_modules/redis": {
|
||||
"version": "5.6.1",
|
||||
"resolved": "https://registry.npmjs.org/redis/-/redis-5.6.1.tgz",
|
||||
"integrity": "sha512-O9DwAvcBm/lrlkGE0A6gNBtUdA8J9oD9njeLYlLzmm+MGTR7nd7VkpspfXqeXFg3gm89zldDqckyaHhXfhY80g==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@redis/bloom": "5.6.1",
|
||||
"@redis/client": "5.6.1",
|
||||
"@redis/json": "5.6.1",
|
||||
"@redis/search": "5.6.1",
|
||||
"@redis/time-series": "5.6.1"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 18"
|
||||
}
|
||||
},
|
||||
"node_modules/redis-errors": {
|
||||
"version": "1.2.0",
|
||||
"resolved": "https://registry.npmjs.org/redis-errors/-/redis-errors-1.2.0.tgz",
|
||||
"integrity": "sha512-1qny3OExCf0UvUV/5wpYKf2YwPcOqXzkwKKSmKHiE6ZMQs5heeE/c8eXK+PNllPvmjgAbfnsbpkGZWy8cBpn9w==",
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=4"
|
||||
}
|
||||
},
|
||||
"node_modules/redis-parser": {
|
||||
"version": "3.0.0",
|
||||
"resolved": "https://registry.npmjs.org/redis-parser/-/redis-parser-3.0.0.tgz",
|
||||
"integrity": "sha512-DJnGAeenTdpMEH6uAJRK/uiyEIH9WVsUmoLwzudwGJUwZPp80PDBWPHXSAGNPwNvIXAbe7MSUB1zQFugFml66A==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"redis-errors": "^1.0.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=4"
|
||||
}
|
||||
},
|
||||
"node_modules/reflect-metadata": {
|
||||
"version": "0.2.2",
|
||||
"resolved": "https://registry.npmjs.org/reflect-metadata/-/reflect-metadata-0.2.2.tgz",
|
||||
|
|
@ -10045,6 +10246,12 @@
|
|||
"node": ">=8"
|
||||
}
|
||||
},
|
||||
"node_modules/standard-as-callback": {
|
||||
"version": "2.1.0",
|
||||
"resolved": "https://registry.npmjs.org/standard-as-callback/-/standard-as-callback-2.1.0.tgz",
|
||||
"integrity": "sha512-qoRRSyROncaz1z0mvYqIE4lCd9p2R90i6GxW3uZv5ucSu8tU7B5HXUP1gG8pVZsYNVaXjk8ClXHPttLyxAL48A==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/statuses": {
|
||||
"version": "2.0.2",
|
||||
"resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.2.tgz",
|
||||
|
|
@ -10949,7 +11156,7 @@
|
|||
"version": "5.8.3",
|
||||
"resolved": "https://registry.npmjs.org/typescript/-/typescript-5.8.3.tgz",
|
||||
"integrity": "sha512-p1diW6TqL9L07nNxvRMM7hMMw4c5XOo/1ibL4aAIGmSAt9slTE1Xgw5KWuof2uTOvCg9BY7ZRi+GaF+7sfgPeQ==",
|
||||
"devOptional": true,
|
||||
"dev": true,
|
||||
"license": "Apache-2.0",
|
||||
"bin": {
|
||||
"tsc": "bin/tsc",
|
||||
|
|
@ -11091,6 +11298,19 @@
|
|||
"integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/uuid": {
|
||||
"version": "11.1.0",
|
||||
"resolved": "https://registry.npmjs.org/uuid/-/uuid-11.1.0.tgz",
|
||||
"integrity": "sha512-0/A9rDy9P7cJ+8w1c9WD9V//9Wj15Ce2MPz8Ri6032usz+NfePxx5AcN3bN+r6ZL6jEo066/yNYB3tn4pQEx+A==",
|
||||
"funding": [
|
||||
"https://github.com/sponsors/broofa",
|
||||
"https://github.com/sponsors/ctavan"
|
||||
],
|
||||
"license": "MIT",
|
||||
"bin": {
|
||||
"uuid": "dist/esm/bin/uuid"
|
||||
}
|
||||
},
|
||||
"node_modules/v8-compile-cache-lib": {
|
||||
"version": "3.0.1",
|
||||
"resolved": "https://registry.npmjs.org/v8-compile-cache-lib/-/v8-compile-cache-lib-3.0.1.tgz",
|
||||
|
|
@ -11113,6 +11333,15 @@
|
|||
"node": ">=10.12.0"
|
||||
}
|
||||
},
|
||||
"node_modules/validator": {
|
||||
"version": "13.15.15",
|
||||
"resolved": "https://registry.npmjs.org/validator/-/validator-13.15.15.tgz",
|
||||
"integrity": "sha512-BgWVbCI72aIQy937xbawcs+hrVaN/CZ2UwutgaJ36hGqRrLNM+f5LUT/YPRbo8IV/ASeFzXszezV+y2+rq3l8A==",
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">= 0.10"
|
||||
}
|
||||
},
|
||||
"node_modules/vary": {
|
||||
"version": "1.1.2",
|
||||
"resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz",
|
||||
|
|
@ -11169,56 +11398,6 @@
|
|||
"url": "https://github.com/sponsors/sindresorhus"
|
||||
}
|
||||
},
|
||||
"node_modules/webpack": {
|
||||
"version": "5.100.2",
|
||||
"resolved": "https://registry.npmjs.org/webpack/-/webpack-5.100.2.tgz",
|
||||
"integrity": "sha512-QaNKAvGCDRh3wW1dsDjeMdDXwZm2vqq3zn6Pvq4rHOEOGSaUMgOOjG2Y9ZbIGzpfkJk9ZYTHpDqgDfeBDcnLaw==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"@types/eslint-scope": "^3.7.7",
|
||||
"@types/estree": "^1.0.8",
|
||||
"@types/json-schema": "^7.0.15",
|
||||
"@webassemblyjs/ast": "^1.14.1",
|
||||
"@webassemblyjs/wasm-edit": "^1.14.1",
|
||||
"@webassemblyjs/wasm-parser": "^1.14.1",
|
||||
"acorn": "^8.15.0",
|
||||
"acorn-import-phases": "^1.0.3",
|
||||
"browserslist": "^4.24.0",
|
||||
"chrome-trace-event": "^1.0.2",
|
||||
"enhanced-resolve": "^5.17.2",
|
||||
"es-module-lexer": "^1.2.1",
|
||||
"eslint-scope": "5.1.1",
|
||||
"events": "^3.2.0",
|
||||
"glob-to-regexp": "^0.4.1",
|
||||
"graceful-fs": "^4.2.11",
|
||||
"json-parse-even-better-errors": "^2.3.1",
|
||||
"loader-runner": "^4.2.0",
|
||||
"mime-types": "^2.1.27",
|
||||
"neo-async": "^2.6.2",
|
||||
"schema-utils": "^4.3.2",
|
||||
"tapable": "^2.1.1",
|
||||
"terser-webpack-plugin": "^5.3.11",
|
||||
"watchpack": "^2.4.1",
|
||||
"webpack-sources": "^3.3.3"
|
||||
},
|
||||
"bin": {
|
||||
"webpack": "bin/webpack.js"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=10.13.0"
|
||||
},
|
||||
"funding": {
|
||||
"type": "opencollective",
|
||||
"url": "https://opencollective.com/webpack"
|
||||
},
|
||||
"peerDependenciesMeta": {
|
||||
"webpack-cli": {
|
||||
"optional": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"node_modules/webpack-node-externals": {
|
||||
"version": "3.0.0",
|
||||
"resolved": "https://registry.npmjs.org/webpack-node-externals/-/webpack-node-externals-3.0.0.tgz",
|
||||
|
|
@ -11239,137 +11418,6 @@
|
|||
"node": ">=10.13.0"
|
||||
}
|
||||
},
|
||||
"node_modules/webpack/node_modules/ajv": {
|
||||
"version": "8.17.1",
|
||||
"resolved": "https://registry.npmjs.org/ajv/-/ajv-8.17.1.tgz",
|
||||
"integrity": "sha512-B/gBuNg5SiMTrPkC+A2+cW0RszwxYmn6VYxB/inlBStS5nx6xHIt/ehKRhIMhqusl7a8LjQoZnjCs5vhwxOQ1g==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"fast-deep-equal": "^3.1.3",
|
||||
"fast-uri": "^3.0.1",
|
||||
"json-schema-traverse": "^1.0.0",
|
||||
"require-from-string": "^2.0.2"
|
||||
},
|
||||
"funding": {
|
||||
"type": "github",
|
||||
"url": "https://github.com/sponsors/epoberezkin"
|
||||
}
|
||||
},
|
||||
"node_modules/webpack/node_modules/ajv-formats": {
|
||||
"version": "2.1.1",
|
||||
"resolved": "https://registry.npmjs.org/ajv-formats/-/ajv-formats-2.1.1.tgz",
|
||||
"integrity": "sha512-Wx0Kx52hxE7C18hkMEggYlEifqWZtYaRgouJor+WMdPnQyEK13vgEWyVNup7SoeeoLMsr4kf5h6dOW11I15MUA==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"ajv": "^8.0.0"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"ajv": "^8.0.0"
|
||||
},
|
||||
"peerDependenciesMeta": {
|
||||
"ajv": {
|
||||
"optional": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"node_modules/webpack/node_modules/ajv-keywords": {
|
||||
"version": "5.1.0",
|
||||
"resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-5.1.0.tgz",
|
||||
"integrity": "sha512-YCS/JNFAUyr5vAuhk1DWm1CBxRHW9LbJ2ozWeemrIqpbsqKjHVxYPyi5GC0rjZIT5JxJ3virVTS8wk4i/Z+krw==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"fast-deep-equal": "^3.1.3"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"ajv": "^8.8.2"
|
||||
}
|
||||
},
|
||||
"node_modules/webpack/node_modules/eslint-scope": {
|
||||
"version": "5.1.1",
|
||||
"resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.1.1.tgz",
|
||||
"integrity": "sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw==",
|
||||
"dev": true,
|
||||
"license": "BSD-2-Clause",
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"esrecurse": "^4.3.0",
|
||||
"estraverse": "^4.1.1"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=8.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/webpack/node_modules/estraverse": {
|
||||
"version": "4.3.0",
|
||||
"resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz",
|
||||
"integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==",
|
||||
"dev": true,
|
||||
"license": "BSD-2-Clause",
|
||||
"peer": true,
|
||||
"engines": {
|
||||
"node": ">=4.0"
|
||||
}
|
||||
},
|
||||
"node_modules/webpack/node_modules/json-schema-traverse": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz",
|
||||
"integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"peer": true
|
||||
},
|
||||
"node_modules/webpack/node_modules/mime-db": {
|
||||
"version": "1.52.0",
|
||||
"resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz",
|
||||
"integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"peer": true,
|
||||
"engines": {
|
||||
"node": ">= 0.6"
|
||||
}
|
||||
},
|
||||
"node_modules/webpack/node_modules/mime-types": {
|
||||
"version": "2.1.35",
|
||||
"resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz",
|
||||
"integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"mime-db": "1.52.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 0.6"
|
||||
}
|
||||
},
|
||||
"node_modules/webpack/node_modules/schema-utils": {
|
||||
"version": "4.3.2",
|
||||
"resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-4.3.2.tgz",
|
||||
"integrity": "sha512-Gn/JaSk/Mt9gYubxTtSn/QCV4em9mpAPiR1rqy/Ocu19u/G9J5WWdNoUT4SiV6mFC3y6cxyFcFwdzPM3FgxGAQ==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"@types/json-schema": "^7.0.9",
|
||||
"ajv": "^8.9.0",
|
||||
"ajv-formats": "^2.1.1",
|
||||
"ajv-keywords": "^5.1.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 10.13.0"
|
||||
},
|
||||
"funding": {
|
||||
"type": "opencollective",
|
||||
"url": "https://opencollective.com/webpack"
|
||||
}
|
||||
},
|
||||
"node_modules/which": {
|
||||
"version": "2.0.2",
|
||||
"resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz",
|
||||
|
|
|
|||
|
|
@ -20,12 +20,18 @@
|
|||
"test:e2e": "jest --config ./test/jest-e2e.json"
|
||||
},
|
||||
"dependencies": {
|
||||
"@liaoliaots/nestjs-redis": "^10.0.0",
|
||||
"@nestjs/common": "^11.0.1",
|
||||
"@nestjs/core": "^11.0.1",
|
||||
"@nestjs/platform-express": "^11.0.1",
|
||||
"@prisma/client": "^6.12.0",
|
||||
"class-transformer": "^0.5.1",
|
||||
"class-validator": "^0.14.2",
|
||||
"ioredis": "^5.6.1",
|
||||
"redis": "^5.6.1",
|
||||
"reflect-metadata": "^0.2.2",
|
||||
"rxjs": "^7.8.1"
|
||||
"rxjs": "^7.8.1",
|
||||
"uuid": "^11.1.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@eslint/eslintrc": "^3.2.0",
|
||||
|
|
|
|||
|
|
@ -1,11 +0,0 @@
|
|||
-- CreateTable
|
||||
CREATE TABLE "User" (
|
||||
"id" SERIAL NOT NULL,
|
||||
"name" TEXT NOT NULL,
|
||||
"email" TEXT NOT NULL,
|
||||
|
||||
CONSTRAINT "User_pkey" PRIMARY KEY ("id")
|
||||
);
|
||||
|
||||
-- CreateIndex
|
||||
CREATE UNIQUE INDEX "User_email_key" ON "User"("email");
|
||||
|
|
@ -1,3 +0,0 @@
|
|||
# Please do not edit this file manually
|
||||
# It should be added in your version-control system (e.g., Git)
|
||||
provider = "postgresql"
|
||||
|
|
@ -1,8 +1,8 @@
|
|||
import { Module } from '@nestjs/common';
|
||||
import { PrismaService } from '@/prisma.service';
|
||||
import { PrismaService } from '@/src/prisma.service';
|
||||
|
||||
@Module({
|
||||
providers: [PrismaService],
|
||||
exports: [PrismaService], // Dışarı açıyoruz ki başka modüller kullanabilsin
|
||||
exports: [PrismaService],
|
||||
})
|
||||
export class PrismaModule {}
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load Diff
|
|
@ -0,0 +1,18 @@
|
|||
import { Test, TestingModule } from '@nestjs/testing';
|
||||
import { AccountsController } from './accounts.controller';
|
||||
|
||||
describe('AccountsController', () => {
|
||||
let controller: AccountsController;
|
||||
|
||||
beforeEach(async () => {
|
||||
const module: TestingModule = await Test.createTestingModule({
|
||||
controllers: [AccountsController],
|
||||
}).compile();
|
||||
|
||||
controller = module.get<AccountsController>(AccountsController);
|
||||
});
|
||||
|
||||
it('should be defined', () => {
|
||||
expect(controller).toBeDefined();
|
||||
});
|
||||
});
|
||||
|
|
@ -0,0 +1,39 @@
|
|||
import {
|
||||
Controller,
|
||||
Get,
|
||||
Post,
|
||||
Put,
|
||||
Delete,
|
||||
Param,
|
||||
Body,
|
||||
HttpCode,
|
||||
} from '@nestjs/common';
|
||||
import { AccountsService } from './accounts.service';
|
||||
|
||||
@Controller('accounts')
|
||||
export class AccountsController {
|
||||
constructor(private accountsService: AccountsService) {}
|
||||
|
||||
@Post('filter')
|
||||
@HttpCode(200)
|
||||
async filterAccounts(@Body() query: any) {
|
||||
const result = await this.accountsService.findWithPagination(query);
|
||||
const { pagination, data } = result;
|
||||
|
||||
if (data.length === 0) {
|
||||
return { pagination, data: [] };
|
||||
}
|
||||
|
||||
const resultRefined = data.map((rec: any) => ({
|
||||
...rec,
|
||||
build_decision_book_payments: rec.build_decision_book_payments?.map(
|
||||
(pmt: any) => ({
|
||||
...pmt,
|
||||
ratePercent:
|
||||
((pmt.payment_amount / rec.currency_value) * 100).toFixed(2) + '%',
|
||||
}),
|
||||
),
|
||||
}));
|
||||
return { pagination, data: resultRefined };
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,13 @@
|
|||
import { Module } from '@nestjs/common';
|
||||
import { AccountsService } from './accounts.service';
|
||||
import { AccountsController } from './accounts.controller';
|
||||
import { PrismaModule } from '@/prisma/prisma.module';
|
||||
import { CacheService } from '../cache.service';
|
||||
import { UtilsModule } from '../utils/utils.module';
|
||||
|
||||
@Module({
|
||||
imports: [PrismaModule, UtilsModule],
|
||||
providers: [AccountsService, CacheService],
|
||||
controllers: [AccountsController],
|
||||
})
|
||||
export class AccountsModule {}
|
||||
|
|
@ -0,0 +1,18 @@
|
|||
import { Test, TestingModule } from '@nestjs/testing';
|
||||
import { AccountsService } from './accounts.service';
|
||||
|
||||
describe('AccountsService', () => {
|
||||
let service: AccountsService;
|
||||
|
||||
beforeEach(async () => {
|
||||
const module: TestingModule = await Test.createTestingModule({
|
||||
providers: [AccountsService],
|
||||
}).compile();
|
||||
|
||||
service = module.get<AccountsService>(AccountsService);
|
||||
});
|
||||
|
||||
it('should be defined', () => {
|
||||
expect(service).toBeDefined();
|
||||
});
|
||||
});
|
||||
|
|
@ -0,0 +1,42 @@
|
|||
import { Injectable } from '@nestjs/common';
|
||||
import { PrismaService } from '@/src/prisma.service';
|
||||
import { Prisma, account_records } from '@prisma/client';
|
||||
import { CacheService } from '../cache.service';
|
||||
import { PaginationHelper, PaginationInfo } from '../utils/pagination-helper';
|
||||
|
||||
@Injectable()
|
||||
export class AccountsService {
|
||||
constructor(
|
||||
private prisma: PrismaService,
|
||||
private cacheService: CacheService,
|
||||
private paginationHelper: PaginationHelper,
|
||||
) {}
|
||||
|
||||
async findAll(filter: any): Promise<Partial<account_records>[]> {
|
||||
return this.prisma.account_records.findMany({
|
||||
where: { ...filter },
|
||||
});
|
||||
}
|
||||
|
||||
async findDynamic(
|
||||
query: Prisma.account_recordsFindManyArgs,
|
||||
): Promise<{ totalCount: number; result: Partial<account_records>[] }> {
|
||||
const totalCount = await this.prisma.account_records.count({
|
||||
where: query.where,
|
||||
});
|
||||
const result = await this.prisma.account_records.findMany(query);
|
||||
return { totalCount, result };
|
||||
}
|
||||
|
||||
async findWithPagination(
|
||||
query: any & { page?: number; pageSize?: number },
|
||||
): Promise<{ data: any[]; pagination: PaginationInfo }> {
|
||||
return this.paginationHelper.paginate(this.prisma.account_records, query);
|
||||
}
|
||||
|
||||
async findOne(uuid: string): Promise<Partial<account_records> | null> {
|
||||
return this.prisma.account_records.findUnique({
|
||||
where: { uu_id: uuid },
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,36 @@
|
|||
http://localhost:3000/accounts/filter
|
||||
|
||||
{
|
||||
"where": {
|
||||
"build_parts": {
|
||||
"part_code": {
|
||||
"contains": "10",
|
||||
"mode": "insensitive"
|
||||
}
|
||||
}
|
||||
},
|
||||
"select": {
|
||||
"process_comment": true,
|
||||
"bank_date": true,
|
||||
"currency_value": true,
|
||||
"build_parts": {
|
||||
"select": {
|
||||
"part_code": true
|
||||
}
|
||||
},
|
||||
"build_decision_book_payments": {
|
||||
"select": {
|
||||
"payment_amount": true,
|
||||
"process_date": true,
|
||||
"build_decision_book_items": {
|
||||
"select": {
|
||||
"item_order": true,
|
||||
"item_comment": true
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"page": 2,
|
||||
"pageSize": 5
|
||||
}
|
||||
|
|
@ -1,12 +1,50 @@
|
|||
import { Module } from '@nestjs/common';
|
||||
import {
|
||||
MiddlewareConsumer,
|
||||
Module,
|
||||
NestModule,
|
||||
RequestMethod,
|
||||
} from '@nestjs/common';
|
||||
import { AppController } from './app.controller';
|
||||
import { AppService } from './app.service';
|
||||
import { UsersModule } from './users/users.module';
|
||||
import { PrismaModule } from '@/prisma/prisma.module';
|
||||
import { AccountsModule } from './accounts/accounts.module';
|
||||
import { AuthModule } from './auth/auth.module';
|
||||
import { RedisModule } from '@liaoliaots/nestjs-redis';
|
||||
import { CacheService } from './cache.service';
|
||||
import { LoggerMiddleware } from '@/src/middleware/logger.middleware';
|
||||
|
||||
const redisConfig = {
|
||||
host: '10.10.2.15',
|
||||
port: 6379,
|
||||
password: 'your_strong_password_here',
|
||||
};
|
||||
|
||||
const modulesList = [UsersModule, AccountsModule, AuthModule];
|
||||
const serviceModuleList = [
|
||||
PrismaModule,
|
||||
RedisModule.forRoot({
|
||||
config: redisConfig,
|
||||
}),
|
||||
];
|
||||
const controllersList = [AppController];
|
||||
const providersList = [AppService, CacheService];
|
||||
const exportsList = [CacheService];
|
||||
|
||||
@Module({
|
||||
imports: [PrismaModule, UsersModule],
|
||||
controllers: [AppController],
|
||||
providers: [AppService],
|
||||
imports: [...modulesList, ...serviceModuleList],
|
||||
controllers: controllersList,
|
||||
providers: providersList,
|
||||
exports: exportsList,
|
||||
})
|
||||
export class AppModule {}
|
||||
export class AppModule implements NestModule {
|
||||
configure(consumer: MiddlewareConsumer) {
|
||||
consumer
|
||||
.apply(LoggerMiddleware)
|
||||
.exclude(
|
||||
{ path: 'accounts', method: RequestMethod.ALL },
|
||||
{ path: 'users/*path', method: RequestMethod.ALL },
|
||||
)
|
||||
.forRoutes('*');
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,21 @@
|
|||
import { Module } from '@nestjs/common';
|
||||
import { LoginModule } from '@/src/auth/login/login.module';
|
||||
import { SelectModule } from '@/src/auth/select/select.module';
|
||||
import { PasswordService } from '@/src/auth/password/password.service';
|
||||
import { PasswordModule } from '@/src/auth/password/password.module';
|
||||
import { LogoutModule } from '@/src/auth/logout/logout.module';
|
||||
import { DisconnectModule } from '@/src/auth/disconnect/disconnect.module';
|
||||
import { TokenModule } from '@/src/auth/token/token.module';
|
||||
|
||||
@Module({
|
||||
imports: [
|
||||
LoginModule,
|
||||
LogoutModule,
|
||||
SelectModule,
|
||||
PasswordModule,
|
||||
DisconnectModule,
|
||||
TokenModule,
|
||||
],
|
||||
providers: [PasswordService],
|
||||
})
|
||||
export class AuthModule {}
|
||||
|
|
@ -0,0 +1,18 @@
|
|||
import { Test, TestingModule } from '@nestjs/testing';
|
||||
import { DisconnectController } from './disconnect.controller';
|
||||
|
||||
describe('DisconnectController', () => {
|
||||
let controller: DisconnectController;
|
||||
|
||||
beforeEach(async () => {
|
||||
const module: TestingModule = await Test.createTestingModule({
|
||||
controllers: [DisconnectController],
|
||||
}).compile();
|
||||
|
||||
controller = module.get<DisconnectController>(DisconnectController);
|
||||
});
|
||||
|
||||
it('should be defined', () => {
|
||||
expect(controller).toBeDefined();
|
||||
});
|
||||
});
|
||||
|
|
@ -0,0 +1,4 @@
|
|||
import { Controller } from '@nestjs/common';
|
||||
|
||||
@Controller('disconnect')
|
||||
export class DisconnectController {}
|
||||
|
|
@ -0,0 +1,9 @@
|
|||
import { Module } from '@nestjs/common';
|
||||
import { DisconnectService } from './disconnect.service';
|
||||
import { DisconnectController } from './disconnect.controller';
|
||||
|
||||
@Module({
|
||||
providers: [DisconnectService],
|
||||
controllers: [DisconnectController]
|
||||
})
|
||||
export class DisconnectModule {}
|
||||
|
|
@ -0,0 +1,18 @@
|
|||
import { Test, TestingModule } from '@nestjs/testing';
|
||||
import { DisconnectService } from './disconnect.service';
|
||||
|
||||
describe('DisconnectService', () => {
|
||||
let service: DisconnectService;
|
||||
|
||||
beforeEach(async () => {
|
||||
const module: TestingModule = await Test.createTestingModule({
|
||||
providers: [DisconnectService],
|
||||
}).compile();
|
||||
|
||||
service = module.get<DisconnectService>(DisconnectService);
|
||||
});
|
||||
|
||||
it('should be defined', () => {
|
||||
expect(service).toBeDefined();
|
||||
});
|
||||
});
|
||||
|
|
@ -0,0 +1,4 @@
|
|||
import { Injectable } from '@nestjs/common';
|
||||
|
||||
@Injectable()
|
||||
export class DisconnectService {}
|
||||
|
|
@ -0,0 +1,18 @@
|
|||
import { Test, TestingModule } from '@nestjs/testing';
|
||||
import { LoginController } from './login.controller';
|
||||
|
||||
describe('LoginController', () => {
|
||||
let controller: LoginController;
|
||||
|
||||
beforeEach(async () => {
|
||||
const module: TestingModule = await Test.createTestingModule({
|
||||
controllers: [LoginController],
|
||||
}).compile();
|
||||
|
||||
controller = module.get<LoginController>(LoginController);
|
||||
});
|
||||
|
||||
it('should be defined', () => {
|
||||
expect(controller).toBeDefined();
|
||||
});
|
||||
});
|
||||
|
|
@ -0,0 +1,4 @@
|
|||
import { Controller } from '@nestjs/common';
|
||||
|
||||
@Controller('login')
|
||||
export class LoginController {}
|
||||
|
|
@ -0,0 +1,9 @@
|
|||
import { Module } from '@nestjs/common';
|
||||
import { LoginController } from './login.controller';
|
||||
import { LoginService } from './login.service';
|
||||
|
||||
@Module({
|
||||
controllers: [LoginController],
|
||||
providers: [LoginService]
|
||||
})
|
||||
export class LoginModule {}
|
||||
|
|
@ -0,0 +1,18 @@
|
|||
import { Test, TestingModule } from '@nestjs/testing';
|
||||
import { LoginService } from './login.service';
|
||||
|
||||
describe('LoginService', () => {
|
||||
let service: LoginService;
|
||||
|
||||
beforeEach(async () => {
|
||||
const module: TestingModule = await Test.createTestingModule({
|
||||
providers: [LoginService],
|
||||
}).compile();
|
||||
|
||||
service = module.get<LoginService>(LoginService);
|
||||
});
|
||||
|
||||
it('should be defined', () => {
|
||||
expect(service).toBeDefined();
|
||||
});
|
||||
});
|
||||
|
|
@ -0,0 +1,4 @@
|
|||
import { Injectable } from '@nestjs/common';
|
||||
|
||||
@Injectable()
|
||||
export class LoginService {}
|
||||
|
|
@ -0,0 +1,18 @@
|
|||
import { Test, TestingModule } from '@nestjs/testing';
|
||||
import { LogoutController } from './logout.controller';
|
||||
|
||||
describe('LogoutController', () => {
|
||||
let controller: LogoutController;
|
||||
|
||||
beforeEach(async () => {
|
||||
const module: TestingModule = await Test.createTestingModule({
|
||||
controllers: [LogoutController],
|
||||
}).compile();
|
||||
|
||||
controller = module.get<LogoutController>(LogoutController);
|
||||
});
|
||||
|
||||
it('should be defined', () => {
|
||||
expect(controller).toBeDefined();
|
||||
});
|
||||
});
|
||||
|
|
@ -0,0 +1,4 @@
|
|||
import { Controller } from '@nestjs/common';
|
||||
|
||||
@Controller('logout')
|
||||
export class LogoutController {}
|
||||
|
|
@ -0,0 +1,9 @@
|
|||
import { Module } from '@nestjs/common';
|
||||
import { LogoutService } from './logout.service';
|
||||
import { LogoutController } from './logout.controller';
|
||||
|
||||
@Module({
|
||||
providers: [LogoutService],
|
||||
controllers: [LogoutController]
|
||||
})
|
||||
export class LogoutModule {}
|
||||
|
|
@ -0,0 +1,18 @@
|
|||
import { Test, TestingModule } from '@nestjs/testing';
|
||||
import { LogoutService } from './logout.service';
|
||||
|
||||
describe('LogoutService', () => {
|
||||
let service: LogoutService;
|
||||
|
||||
beforeEach(async () => {
|
||||
const module: TestingModule = await Test.createTestingModule({
|
||||
providers: [LogoutService],
|
||||
}).compile();
|
||||
|
||||
service = module.get<LogoutService>(LogoutService);
|
||||
});
|
||||
|
||||
it('should be defined', () => {
|
||||
expect(service).toBeDefined();
|
||||
});
|
||||
});
|
||||
|
|
@ -0,0 +1,4 @@
|
|||
import { Injectable } from '@nestjs/common';
|
||||
|
||||
@Injectable()
|
||||
export class LogoutService {}
|
||||
|
|
@ -0,0 +1,18 @@
|
|||
import { Test, TestingModule } from '@nestjs/testing';
|
||||
import { ChangeController } from './change.controller';
|
||||
|
||||
describe('ChangeController', () => {
|
||||
let controller: ChangeController;
|
||||
|
||||
beforeEach(async () => {
|
||||
const module: TestingModule = await Test.createTestingModule({
|
||||
controllers: [ChangeController],
|
||||
}).compile();
|
||||
|
||||
controller = module.get<ChangeController>(ChangeController);
|
||||
});
|
||||
|
||||
it('should be defined', () => {
|
||||
expect(controller).toBeDefined();
|
||||
});
|
||||
});
|
||||
|
|
@ -0,0 +1,4 @@
|
|||
import { Controller } from '@nestjs/common';
|
||||
|
||||
@Controller('change')
|
||||
export class ChangeController {}
|
||||
|
|
@ -0,0 +1,9 @@
|
|||
import { Module } from '@nestjs/common';
|
||||
import { ChangeService } from './change.service';
|
||||
import { ChangeController } from './change.controller';
|
||||
|
||||
@Module({
|
||||
providers: [ChangeService],
|
||||
controllers: [ChangeController]
|
||||
})
|
||||
export class ChangeModule {}
|
||||
|
|
@ -0,0 +1,18 @@
|
|||
import { Test, TestingModule } from '@nestjs/testing';
|
||||
import { ChangeService } from './change.service';
|
||||
|
||||
describe('ChangeService', () => {
|
||||
let service: ChangeService;
|
||||
|
||||
beforeEach(async () => {
|
||||
const module: TestingModule = await Test.createTestingModule({
|
||||
providers: [ChangeService],
|
||||
}).compile();
|
||||
|
||||
service = module.get<ChangeService>(ChangeService);
|
||||
});
|
||||
|
||||
it('should be defined', () => {
|
||||
expect(service).toBeDefined();
|
||||
});
|
||||
});
|
||||
|
|
@ -0,0 +1,4 @@
|
|||
import { Injectable } from '@nestjs/common';
|
||||
|
||||
@Injectable()
|
||||
export class ChangeService {}
|
||||
|
|
@ -0,0 +1,18 @@
|
|||
import { Test, TestingModule } from '@nestjs/testing';
|
||||
import { CreateController } from './create.controller';
|
||||
|
||||
describe('CreateController', () => {
|
||||
let controller: CreateController;
|
||||
|
||||
beforeEach(async () => {
|
||||
const module: TestingModule = await Test.createTestingModule({
|
||||
controllers: [CreateController],
|
||||
}).compile();
|
||||
|
||||
controller = module.get<CreateController>(CreateController);
|
||||
});
|
||||
|
||||
it('should be defined', () => {
|
||||
expect(controller).toBeDefined();
|
||||
});
|
||||
});
|
||||
|
|
@ -0,0 +1,4 @@
|
|||
import { Controller } from '@nestjs/common';
|
||||
|
||||
@Controller('create')
|
||||
export class CreateController {}
|
||||
|
|
@ -0,0 +1,9 @@
|
|||
import { Module } from '@nestjs/common';
|
||||
import { CreateService } from './create.service';
|
||||
import { CreateController } from './create.controller';
|
||||
|
||||
@Module({
|
||||
providers: [CreateService],
|
||||
controllers: [CreateController]
|
||||
})
|
||||
export class CreateModule {}
|
||||
|
|
@ -0,0 +1,18 @@
|
|||
import { Test, TestingModule } from '@nestjs/testing';
|
||||
import { CreateService } from './create.service';
|
||||
|
||||
describe('CreateService', () => {
|
||||
let service: CreateService;
|
||||
|
||||
beforeEach(async () => {
|
||||
const module: TestingModule = await Test.createTestingModule({
|
||||
providers: [CreateService],
|
||||
}).compile();
|
||||
|
||||
service = module.get<CreateService>(CreateService);
|
||||
});
|
||||
|
||||
it('should be defined', () => {
|
||||
expect(service).toBeDefined();
|
||||
});
|
||||
});
|
||||
|
|
@ -0,0 +1,4 @@
|
|||
import { Injectable } from '@nestjs/common';
|
||||
|
||||
@Injectable()
|
||||
export class CreateService {}
|
||||
|
|
@ -0,0 +1,18 @@
|
|||
import { Test, TestingModule } from '@nestjs/testing';
|
||||
import { PasswordController } from './password.controller';
|
||||
|
||||
describe('PasswordController', () => {
|
||||
let controller: PasswordController;
|
||||
|
||||
beforeEach(async () => {
|
||||
const module: TestingModule = await Test.createTestingModule({
|
||||
controllers: [PasswordController],
|
||||
}).compile();
|
||||
|
||||
controller = module.get<PasswordController>(PasswordController);
|
||||
});
|
||||
|
||||
it('should be defined', () => {
|
||||
expect(controller).toBeDefined();
|
||||
});
|
||||
});
|
||||
|
|
@ -0,0 +1,4 @@
|
|||
import { Controller } from '@nestjs/common';
|
||||
|
||||
@Controller('password')
|
||||
export class PasswordController {}
|
||||
|
|
@ -0,0 +1,12 @@
|
|||
import { Module } from '@nestjs/common';
|
||||
import { PasswordController } from './password.controller';
|
||||
import { CreateModule } from './create/create.module';
|
||||
import { ChangeModule } from './change/change.module';
|
||||
import { ResetModule } from './reset/reset.module';
|
||||
import { VerifyOtpModule } from './verify-otp/verify-otp.module';
|
||||
|
||||
@Module({
|
||||
controllers: [PasswordController],
|
||||
imports: [CreateModule, ChangeModule, ResetModule, VerifyOtpModule]
|
||||
})
|
||||
export class PasswordModule {}
|
||||
|
|
@ -0,0 +1,18 @@
|
|||
import { Test, TestingModule } from '@nestjs/testing';
|
||||
import { PasswordService } from './password.service';
|
||||
|
||||
describe('PasswordService', () => {
|
||||
let service: PasswordService;
|
||||
|
||||
beforeEach(async () => {
|
||||
const module: TestingModule = await Test.createTestingModule({
|
||||
providers: [PasswordService],
|
||||
}).compile();
|
||||
|
||||
service = module.get<PasswordService>(PasswordService);
|
||||
});
|
||||
|
||||
it('should be defined', () => {
|
||||
expect(service).toBeDefined();
|
||||
});
|
||||
});
|
||||
|
|
@ -0,0 +1,4 @@
|
|||
import { Injectable } from '@nestjs/common';
|
||||
|
||||
@Injectable()
|
||||
export class PasswordService {}
|
||||
|
|
@ -0,0 +1,18 @@
|
|||
import { Test, TestingModule } from '@nestjs/testing';
|
||||
import { ResetController } from './reset.controller';
|
||||
|
||||
describe('ResetController', () => {
|
||||
let controller: ResetController;
|
||||
|
||||
beforeEach(async () => {
|
||||
const module: TestingModule = await Test.createTestingModule({
|
||||
controllers: [ResetController],
|
||||
}).compile();
|
||||
|
||||
controller = module.get<ResetController>(ResetController);
|
||||
});
|
||||
|
||||
it('should be defined', () => {
|
||||
expect(controller).toBeDefined();
|
||||
});
|
||||
});
|
||||
|
|
@ -0,0 +1,4 @@
|
|||
import { Controller } from '@nestjs/common';
|
||||
|
||||
@Controller('reset')
|
||||
export class ResetController {}
|
||||
|
|
@ -0,0 +1,9 @@
|
|||
import { Module } from '@nestjs/common';
|
||||
import { ResetService } from './reset.service';
|
||||
import { ResetController } from './reset.controller';
|
||||
|
||||
@Module({
|
||||
providers: [ResetService],
|
||||
controllers: [ResetController]
|
||||
})
|
||||
export class ResetModule {}
|
||||
|
|
@ -0,0 +1,18 @@
|
|||
import { Test, TestingModule } from '@nestjs/testing';
|
||||
import { ResetService } from './reset.service';
|
||||
|
||||
describe('ResetService', () => {
|
||||
let service: ResetService;
|
||||
|
||||
beforeEach(async () => {
|
||||
const module: TestingModule = await Test.createTestingModule({
|
||||
providers: [ResetService],
|
||||
}).compile();
|
||||
|
||||
service = module.get<ResetService>(ResetService);
|
||||
});
|
||||
|
||||
it('should be defined', () => {
|
||||
expect(service).toBeDefined();
|
||||
});
|
||||
});
|
||||
|
|
@ -0,0 +1,4 @@
|
|||
import { Injectable } from '@nestjs/common';
|
||||
|
||||
@Injectable()
|
||||
export class ResetService {}
|
||||
|
|
@ -0,0 +1,18 @@
|
|||
import { Test, TestingModule } from '@nestjs/testing';
|
||||
import { VerifyOtpController } from './verify-otp.controller';
|
||||
|
||||
describe('VerifyOtpController', () => {
|
||||
let controller: VerifyOtpController;
|
||||
|
||||
beforeEach(async () => {
|
||||
const module: TestingModule = await Test.createTestingModule({
|
||||
controllers: [VerifyOtpController],
|
||||
}).compile();
|
||||
|
||||
controller = module.get<VerifyOtpController>(VerifyOtpController);
|
||||
});
|
||||
|
||||
it('should be defined', () => {
|
||||
expect(controller).toBeDefined();
|
||||
});
|
||||
});
|
||||
|
|
@ -0,0 +1,4 @@
|
|||
import { Controller } from '@nestjs/common';
|
||||
|
||||
@Controller('verify-otp')
|
||||
export class VerifyOtpController {}
|
||||
|
|
@ -0,0 +1,9 @@
|
|||
import { Module } from '@nestjs/common';
|
||||
import { VerifyOtpService } from './verify-otp.service';
|
||||
import { VerifyOtpController } from './verify-otp.controller';
|
||||
|
||||
@Module({
|
||||
providers: [VerifyOtpService],
|
||||
controllers: [VerifyOtpController]
|
||||
})
|
||||
export class VerifyOtpModule {}
|
||||
|
|
@ -0,0 +1,18 @@
|
|||
import { Test, TestingModule } from '@nestjs/testing';
|
||||
import { VerifyOtpService } from './verify-otp.service';
|
||||
|
||||
describe('VerifyOtpService', () => {
|
||||
let service: VerifyOtpService;
|
||||
|
||||
beforeEach(async () => {
|
||||
const module: TestingModule = await Test.createTestingModule({
|
||||
providers: [VerifyOtpService],
|
||||
}).compile();
|
||||
|
||||
service = module.get<VerifyOtpService>(VerifyOtpService);
|
||||
});
|
||||
|
||||
it('should be defined', () => {
|
||||
expect(service).toBeDefined();
|
||||
});
|
||||
});
|
||||
|
|
@ -0,0 +1,4 @@
|
|||
import { Injectable } from '@nestjs/common';
|
||||
|
||||
@Injectable()
|
||||
export class VerifyOtpService {}
|
||||
|
|
@ -0,0 +1,18 @@
|
|||
import { Test, TestingModule } from '@nestjs/testing';
|
||||
import { SelectController } from './select.controller';
|
||||
|
||||
describe('SelectController', () => {
|
||||
let controller: SelectController;
|
||||
|
||||
beforeEach(async () => {
|
||||
const module: TestingModule = await Test.createTestingModule({
|
||||
controllers: [SelectController],
|
||||
}).compile();
|
||||
|
||||
controller = module.get<SelectController>(SelectController);
|
||||
});
|
||||
|
||||
it('should be defined', () => {
|
||||
expect(controller).toBeDefined();
|
||||
});
|
||||
});
|
||||
|
|
@ -0,0 +1,4 @@
|
|||
import { Controller } from '@nestjs/common';
|
||||
|
||||
@Controller('select')
|
||||
export class SelectController {}
|
||||
|
|
@ -0,0 +1,9 @@
|
|||
import { Module } from '@nestjs/common';
|
||||
import { SelectController } from './select.controller';
|
||||
import { SelectService } from './select.service';
|
||||
|
||||
@Module({
|
||||
controllers: [SelectController],
|
||||
providers: [SelectService]
|
||||
})
|
||||
export class SelectModule {}
|
||||
|
|
@ -0,0 +1,18 @@
|
|||
import { Test, TestingModule } from '@nestjs/testing';
|
||||
import { SelectService } from './select.service';
|
||||
|
||||
describe('SelectService', () => {
|
||||
let service: SelectService;
|
||||
|
||||
beforeEach(async () => {
|
||||
const module: TestingModule = await Test.createTestingModule({
|
||||
providers: [SelectService],
|
||||
}).compile();
|
||||
|
||||
service = module.get<SelectService>(SelectService);
|
||||
});
|
||||
|
||||
it('should be defined', () => {
|
||||
expect(service).toBeDefined();
|
||||
});
|
||||
});
|
||||
|
|
@ -0,0 +1,4 @@
|
|||
import { Injectable } from '@nestjs/common';
|
||||
|
||||
@Injectable()
|
||||
export class SelectService {}
|
||||
|
|
@ -0,0 +1,18 @@
|
|||
import { Test, TestingModule } from '@nestjs/testing';
|
||||
import { CheckController } from './check.controller';
|
||||
|
||||
describe('CheckController', () => {
|
||||
let controller: CheckController;
|
||||
|
||||
beforeEach(async () => {
|
||||
const module: TestingModule = await Test.createTestingModule({
|
||||
controllers: [CheckController],
|
||||
}).compile();
|
||||
|
||||
controller = module.get<CheckController>(CheckController);
|
||||
});
|
||||
|
||||
it('should be defined', () => {
|
||||
expect(controller).toBeDefined();
|
||||
});
|
||||
});
|
||||
|
|
@ -0,0 +1,4 @@
|
|||
import { Controller } from '@nestjs/common';
|
||||
|
||||
@Controller('check')
|
||||
export class CheckController {}
|
||||
|
|
@ -0,0 +1,9 @@
|
|||
import { Module } from '@nestjs/common';
|
||||
import { CheckService } from './check.service';
|
||||
import { CheckController } from './check.controller';
|
||||
|
||||
@Module({
|
||||
providers: [CheckService],
|
||||
controllers: [CheckController]
|
||||
})
|
||||
export class CheckModule {}
|
||||
|
|
@ -0,0 +1,18 @@
|
|||
import { Test, TestingModule } from '@nestjs/testing';
|
||||
import { CheckService } from './check.service';
|
||||
|
||||
describe('CheckService', () => {
|
||||
let service: CheckService;
|
||||
|
||||
beforeEach(async () => {
|
||||
const module: TestingModule = await Test.createTestingModule({
|
||||
providers: [CheckService],
|
||||
}).compile();
|
||||
|
||||
service = module.get<CheckService>(CheckService);
|
||||
});
|
||||
|
||||
it('should be defined', () => {
|
||||
expect(service).toBeDefined();
|
||||
});
|
||||
});
|
||||
|
|
@ -0,0 +1,4 @@
|
|||
import { Injectable } from '@nestjs/common';
|
||||
|
||||
@Injectable()
|
||||
export class CheckService {}
|
||||
|
|
@ -0,0 +1,18 @@
|
|||
import { Test, TestingModule } from '@nestjs/testing';
|
||||
import { RefreshController } from './refresh.controller';
|
||||
|
||||
describe('RefreshController', () => {
|
||||
let controller: RefreshController;
|
||||
|
||||
beforeEach(async () => {
|
||||
const module: TestingModule = await Test.createTestingModule({
|
||||
controllers: [RefreshController],
|
||||
}).compile();
|
||||
|
||||
controller = module.get<RefreshController>(RefreshController);
|
||||
});
|
||||
|
||||
it('should be defined', () => {
|
||||
expect(controller).toBeDefined();
|
||||
});
|
||||
});
|
||||
|
|
@ -0,0 +1,4 @@
|
|||
import { Controller } from '@nestjs/common';
|
||||
|
||||
@Controller('refresh')
|
||||
export class RefreshController {}
|
||||
|
|
@ -0,0 +1,9 @@
|
|||
import { Module } from '@nestjs/common';
|
||||
import { RefreshService } from './refresh.service';
|
||||
import { RefreshController } from './refresh.controller';
|
||||
|
||||
@Module({
|
||||
providers: [RefreshService],
|
||||
controllers: [RefreshController]
|
||||
})
|
||||
export class RefreshModule {}
|
||||
|
|
@ -0,0 +1,18 @@
|
|||
import { Test, TestingModule } from '@nestjs/testing';
|
||||
import { RefreshService } from './refresh.service';
|
||||
|
||||
describe('RefreshService', () => {
|
||||
let service: RefreshService;
|
||||
|
||||
beforeEach(async () => {
|
||||
const module: TestingModule = await Test.createTestingModule({
|
||||
providers: [RefreshService],
|
||||
}).compile();
|
||||
|
||||
service = module.get<RefreshService>(RefreshService);
|
||||
});
|
||||
|
||||
it('should be defined', () => {
|
||||
expect(service).toBeDefined();
|
||||
});
|
||||
});
|
||||
|
|
@ -0,0 +1,4 @@
|
|||
import { Injectable } from '@nestjs/common';
|
||||
|
||||
@Injectable()
|
||||
export class RefreshService {}
|
||||
|
|
@ -0,0 +1,18 @@
|
|||
import { Test, TestingModule } from '@nestjs/testing';
|
||||
import { TokenController } from './token.controller';
|
||||
|
||||
describe('TokenController', () => {
|
||||
let controller: TokenController;
|
||||
|
||||
beforeEach(async () => {
|
||||
const module: TestingModule = await Test.createTestingModule({
|
||||
controllers: [TokenController],
|
||||
}).compile();
|
||||
|
||||
controller = module.get<TokenController>(TokenController);
|
||||
});
|
||||
|
||||
it('should be defined', () => {
|
||||
expect(controller).toBeDefined();
|
||||
});
|
||||
});
|
||||
|
|
@ -0,0 +1,4 @@
|
|||
import { Controller } from '@nestjs/common';
|
||||
|
||||
@Controller('token')
|
||||
export class TokenController {}
|
||||
|
|
@ -0,0 +1,12 @@
|
|||
import { Module } from '@nestjs/common';
|
||||
import { TokenService } from './token.service';
|
||||
import { TokenController } from './token.controller';
|
||||
import { CheckModule } from './check/check.module';
|
||||
import { RefreshModule } from './refresh/refresh.module';
|
||||
|
||||
@Module({
|
||||
providers: [TokenService],
|
||||
controllers: [TokenController],
|
||||
imports: [CheckModule, RefreshModule],
|
||||
})
|
||||
export class TokenModule {}
|
||||
|
|
@ -0,0 +1,18 @@
|
|||
import { Test, TestingModule } from '@nestjs/testing';
|
||||
import { TokenService } from './token.service';
|
||||
|
||||
describe('TokenService', () => {
|
||||
let service: TokenService;
|
||||
|
||||
beforeEach(async () => {
|
||||
const module: TestingModule = await Test.createTestingModule({
|
||||
providers: [TokenService],
|
||||
}).compile();
|
||||
|
||||
service = module.get<TokenService>(TokenService);
|
||||
});
|
||||
|
||||
it('should be defined', () => {
|
||||
expect(service).toBeDefined();
|
||||
});
|
||||
});
|
||||
|
|
@ -0,0 +1,4 @@
|
|||
import { Injectable } from '@nestjs/common';
|
||||
|
||||
@Injectable()
|
||||
export class TokenService {}
|
||||
|
|
@ -0,0 +1,102 @@
|
|||
import { Injectable } from '@nestjs/common';
|
||||
import { RedisService } from '@liaoliaots/nestjs-redis';
|
||||
import Redis from 'ioredis';
|
||||
|
||||
@Injectable()
|
||||
export class CacheService {
|
||||
private client: Redis;
|
||||
|
||||
constructor(private readonly redisService: RedisService) {
|
||||
this.client = this.redisService.getOrThrow();
|
||||
}
|
||||
|
||||
async set(key: string, value: any) {
|
||||
await this.client.set(key, JSON.stringify(value));
|
||||
}
|
||||
|
||||
async get(key: string): Promise<any | null> {
|
||||
const value = await this.client.get(key);
|
||||
if (!value) {
|
||||
return null;
|
||||
}
|
||||
return JSON.parse(value);
|
||||
}
|
||||
|
||||
async get_with_keys(listKeys: (string | null)[]): Promise<any | null> {
|
||||
const joinKeys = this.createRegexPattern(listKeys);
|
||||
const value = await this.client.get(joinKeys);
|
||||
if (!value) {
|
||||
return null;
|
||||
}
|
||||
return JSON.parse(value);
|
||||
}
|
||||
|
||||
async set_with_ttl(key: string, value: any, ttl: number) {
|
||||
await this.client.set(key, JSON.stringify(value), 'EX', ttl);
|
||||
}
|
||||
|
||||
async check_ttl(key: string): Promise<number> {
|
||||
return this.client.ttl(key);
|
||||
}
|
||||
|
||||
async delete(key: string): Promise<boolean> {
|
||||
const deleted = await this.client.del(key);
|
||||
if (deleted === 0) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete multiple keys matching a pattern.
|
||||
* Simplified version that just returns the count of deleted keys.
|
||||
*
|
||||
* @param listKeys - List of key components to form pattern for deletion.
|
||||
* @returns Number of deleted keys
|
||||
*/
|
||||
async deleteMultiple(listKeys: (string | null)[]): Promise<number> {
|
||||
const regex = this.createRegexPattern(listKeys);
|
||||
const keys: string[] = [];
|
||||
let cursor = '0';
|
||||
|
||||
do {
|
||||
const [nextCursor, matchedKeys] = await this.client.scan(
|
||||
cursor,
|
||||
'MATCH',
|
||||
regex,
|
||||
);
|
||||
cursor = nextCursor;
|
||||
keys.push(...matchedKeys);
|
||||
} while (cursor !== '0');
|
||||
|
||||
if (keys.length === 0) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
let deletedCount = 0;
|
||||
for (const key of keys) {
|
||||
const result = await this.client.del(key);
|
||||
deletedCount += result;
|
||||
}
|
||||
return deletedCount;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a regex pattern from list of keys
|
||||
* This is a simplified implementation - adjust according to your needs
|
||||
*/
|
||||
/**
|
||||
* Create a regex pattern from list of keys
|
||||
* Replaces null/undefined values with '*' wildcards
|
||||
* @param listKeys Array of key components, can contain null/undefined values
|
||||
* @returns Redis pattern string with wildcards
|
||||
*/
|
||||
createRegexPattern(listKeys: (string | null)[]): string {
|
||||
return listKeys.map((key) => (key === null ? '*' : key)).join(':') + '*';
|
||||
}
|
||||
|
||||
async check(key: string): Promise<boolean> {
|
||||
const exists = await this.client.exists(key);
|
||||
return exists === 1;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,10 @@
|
|||
import { Injectable, NestMiddleware } from '@nestjs/common';
|
||||
import { Request, Response, NextFunction } from 'express';
|
||||
|
||||
@Injectable()
|
||||
export class LoggerMiddleware implements NestMiddleware {
|
||||
use(req: Request, res: Response, next: NextFunction) {
|
||||
console.log(`[LoggerMiddleware] ${req.method} ${req.originalUrl}`);
|
||||
next();
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,90 @@
|
|||
// Token type redis base TOKEN object
|
||||
|
||||
enum UserType {
|
||||
employee = 1,
|
||||
occupant = 2,
|
||||
}
|
||||
|
||||
interface Credentials {
|
||||
person_id: number;
|
||||
person_name: string;
|
||||
}
|
||||
|
||||
interface ApplicationToken {
|
||||
// Application Token Object -> is the main object for the user
|
||||
user_type: number;
|
||||
credential_token: string;
|
||||
user_uu_id: string;
|
||||
user_id: number;
|
||||
person_id: number;
|
||||
person_uu_id: string;
|
||||
request?: Record<string, any>; // Request Info of Client
|
||||
expires_at?: number; // Expiry timestamp
|
||||
reachable_event_codes?: Record<string, any>; // ID list of reachable event codes as "endpoint_code": ["UUID", "UUID"]
|
||||
reachable_app_codes?: Record<string, any>; // ID list of reachable applications as "page_url": ["UUID", "UUID"]
|
||||
}
|
||||
|
||||
interface OccupantToken {
|
||||
// Selection of the occupant type for a build part is made by the user
|
||||
living_space_id: number; // Internal use
|
||||
living_space_uu_id: string; // Outer use
|
||||
occupant_type_id: number;
|
||||
occupant_type_uu_id: string;
|
||||
occupant_type: string;
|
||||
build_id: number;
|
||||
build_uuid: string;
|
||||
build_part_id: number;
|
||||
build_part_uuid: string;
|
||||
responsible_company_id?: number;
|
||||
responsible_company_uuid?: string;
|
||||
responsible_employee_id?: number;
|
||||
responsible_employee_uuid?: string;
|
||||
}
|
||||
|
||||
interface CompanyToken {
|
||||
// Selection of the company for an employee is made by the user
|
||||
company_id: number;
|
||||
company_uu_id: string;
|
||||
department_id: number; // ID list of departments
|
||||
department_uu_id: string; // UUID list of departments
|
||||
duty_id: number;
|
||||
duty_uu_id: string;
|
||||
staff_id: number;
|
||||
staff_uu_id: string;
|
||||
employee_id: number;
|
||||
employee_uu_id: string;
|
||||
bulk_duties_id: number;
|
||||
}
|
||||
|
||||
interface OccupantTokenObject extends ApplicationToken {
|
||||
// Occupant Token Object -> Requires selection of the occupant type for a specific build part
|
||||
available_occupants: Record<string, any> | null;
|
||||
selected?: Record<string, any>; // Selected Occupant Type
|
||||
is_employee: boolean; // Always false
|
||||
is_occupant: boolean; // Always true
|
||||
}
|
||||
|
||||
interface EmployeeTokenObject extends ApplicationToken {
|
||||
// Full hierarchy Employee[staff_id] -> Staff -> Duty -> Department -> Company
|
||||
companies_id_list: number[]; // List of company objects
|
||||
companies_uu_id_list: string[]; // UUID list of company objects
|
||||
duty_id_list: number[]; // List of duty objects
|
||||
duty_uu_id_list: string[]; // UUID list of duty objects
|
||||
selected?: Record<string, any>; // Selected Company Object
|
||||
is_employee: boolean; // Always true
|
||||
is_occupant: boolean; // Always false
|
||||
}
|
||||
|
||||
// Union type for token objects
|
||||
type TokenDictType = EmployeeTokenObject | OccupantTokenObject;
|
||||
|
||||
export {
|
||||
UserType,
|
||||
Credentials,
|
||||
ApplicationToken,
|
||||
OccupantToken,
|
||||
CompanyToken,
|
||||
OccupantTokenObject,
|
||||
EmployeeTokenObject,
|
||||
TokenDictType,
|
||||
};
|
||||
|
|
@ -0,0 +1,3 @@
|
|||
export function processUsers(): void {
|
||||
console.log('Processing users New...');
|
||||
}
|
||||
|
|
@ -6,39 +6,17 @@ import {
|
|||
Delete,
|
||||
Param,
|
||||
Body,
|
||||
HttpCode,
|
||||
} from '@nestjs/common';
|
||||
import { UsersService } from './users.service';
|
||||
import { User } from '@prisma/client';
|
||||
|
||||
@Controller('users')
|
||||
export class UsersController {
|
||||
constructor(private usersService: UsersService) {}
|
||||
|
||||
@Get()
|
||||
async findAll(): Promise<User[]> {
|
||||
return this.usersService.findAll();
|
||||
}
|
||||
|
||||
@Get(':id')
|
||||
async findOne(@Param('id') id: string): Promise<User | null> {
|
||||
return this.usersService.findOne(Number(id));
|
||||
}
|
||||
|
||||
@Post()
|
||||
async create(@Body() data: { name: string; email: string }): Promise<User> {
|
||||
return this.usersService.create(data);
|
||||
}
|
||||
|
||||
@Put(':id')
|
||||
async update(
|
||||
@Param('id') id: string,
|
||||
@Body() data: Partial<{ name: string; email: string }>,
|
||||
): Promise<User> {
|
||||
return this.usersService.update(Number(id), data);
|
||||
}
|
||||
|
||||
@Delete(':id')
|
||||
async remove(@Param('id') id: string): Promise<User> {
|
||||
return this.usersService.remove(Number(id));
|
||||
@Post('filter')
|
||||
@HttpCode(200)
|
||||
async filterUsers(@Body() query: any) {
|
||||
return this.usersService.findWithPagination(query);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2,10 +2,12 @@ import { Module } from '@nestjs/common';
|
|||
import { UsersService } from './users.service';
|
||||
import { UsersController } from './users.controller';
|
||||
import { PrismaModule } from '@/prisma/prisma.module';
|
||||
import { CacheService } from '../cache.service';
|
||||
import { UtilsModule } from '../utils/utils.module';
|
||||
|
||||
@Module({
|
||||
imports: [PrismaModule],
|
||||
providers: [UsersService],
|
||||
imports: [PrismaModule, UtilsModule],
|
||||
providers: [UsersService, CacheService],
|
||||
controllers: [UsersController],
|
||||
exports: [UsersService],
|
||||
})
|
||||
|
|
|
|||
|
|
@ -1,31 +1,28 @@
|
|||
import { Injectable } from '@nestjs/common';
|
||||
import { PrismaService } from '@/prisma.service';
|
||||
import { User } from '@prisma/client';
|
||||
import { PrismaService } from '@/src/prisma.service';
|
||||
import { users } from '@prisma/client';
|
||||
|
||||
@Injectable()
|
||||
export class UsersService {
|
||||
constructor(private prisma: PrismaService) {}
|
||||
|
||||
async findAll(): Promise<User[]> {
|
||||
return this.prisma.user.findMany();
|
||||
async findAll(): Promise<users[]> {
|
||||
return this.prisma.users.findMany();
|
||||
}
|
||||
|
||||
async findOne(id: number): Promise<User | null> {
|
||||
return this.prisma.user.findUnique({ where: { id } });
|
||||
async findOne(id: number): Promise<users | null> {
|
||||
return this.prisma.users.findUnique({ where: { id } });
|
||||
}
|
||||
|
||||
async create(data: { name: string; email: string }): Promise<User> {
|
||||
return this.prisma.user.create({ data });
|
||||
async create(data: any): Promise<users> {
|
||||
return this.prisma.users.create({ data });
|
||||
}
|
||||
|
||||
async update(
|
||||
id: number,
|
||||
data: Partial<{ name: string; email: string }>,
|
||||
): Promise<User> {
|
||||
return this.prisma.user.update({ where: { id }, data });
|
||||
async update(id: number, data: any): Promise<users> {
|
||||
return this.prisma.users.update({ where: { id }, data });
|
||||
}
|
||||
|
||||
async remove(id: number): Promise<User> {
|
||||
return this.prisma.user.delete({ where: { id } });
|
||||
async remove(id: number): Promise<users> {
|
||||
return this.prisma.users.delete({ where: { id } });
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,31 +1,42 @@
|
|||
import { Injectable } from '@nestjs/common';
|
||||
import { PrismaService } from '@/prisma.service';
|
||||
import { User } from '@prisma/client';
|
||||
import { PrismaService } from '@/src/prisma.service';
|
||||
import { Prisma, users } from '@prisma/client';
|
||||
import { CacheService } from '../cache.service';
|
||||
import { PaginationHelper, PaginationInfo } from '../utils/pagination-helper';
|
||||
|
||||
@Injectable()
|
||||
export class UsersService {
|
||||
constructor(private prisma: PrismaService) {}
|
||||
constructor(
|
||||
private prisma: PrismaService,
|
||||
private cacheService: CacheService,
|
||||
private paginationHelper: PaginationHelper,
|
||||
) {}
|
||||
|
||||
async findAll(): Promise<User[]> {
|
||||
return this.prisma.user.findMany();
|
||||
async findAll(filter: any): Promise<Partial<users>[]> {
|
||||
return this.prisma.users.findMany({
|
||||
where: { ...filter },
|
||||
});
|
||||
}
|
||||
|
||||
async findOne(id: number): Promise<User | null> {
|
||||
return this.prisma.user.findUnique({ where: { id } });
|
||||
async findDynamic(
|
||||
query: Prisma.usersFindManyArgs,
|
||||
): Promise<{ totalCount: number; result: Partial<users>[] }> {
|
||||
const totalCount = await this.prisma.users.count({
|
||||
where: query.where,
|
||||
});
|
||||
const result = await this.prisma.users.findMany(query);
|
||||
return { totalCount, result };
|
||||
}
|
||||
|
||||
async create(data: { name: string; email: string }): Promise<User> {
|
||||
return this.prisma.user.create({ data });
|
||||
async findWithPagination(
|
||||
query: any & { page?: number; pageSize?: number },
|
||||
): Promise<{ data: any[]; pagination: PaginationInfo }> {
|
||||
return this.paginationHelper.paginate(this.prisma.users, query);
|
||||
}
|
||||
|
||||
async update(
|
||||
id: number,
|
||||
data: Partial<{ name: string; email: string }>,
|
||||
): Promise<User> {
|
||||
return this.prisma.user.update({ where: { id }, data });
|
||||
}
|
||||
|
||||
async remove(id: number): Promise<User> {
|
||||
return this.prisma.user.delete({ where: { id } });
|
||||
async findOne(uuid: string): Promise<Partial<users> | null> {
|
||||
return this.prisma.users.findUnique({
|
||||
where: { uu_id: uuid },
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,65 @@
|
|||
import crypto from 'crypto';
|
||||
import { v4 as uuidv4 } from 'uuid';
|
||||
|
||||
interface TokenConfig {
|
||||
ACCESS_TOKEN_LENGTH: number;
|
||||
REFRESHER_TOKEN_LENGTH: number;
|
||||
}
|
||||
|
||||
const tokenConfig: TokenConfig = {
|
||||
ACCESS_TOKEN_LENGTH: 64,
|
||||
REFRESHER_TOKEN_LENGTH: 128,
|
||||
};
|
||||
|
||||
class PasswordHandlers {
|
||||
generate_random_uu_id(is_string: boolean = true): string {
|
||||
return is_string ? uuidv4().toString() : uuidv4();
|
||||
}
|
||||
|
||||
create_hashed_password(
|
||||
domain: string,
|
||||
uuid: string,
|
||||
password: string,
|
||||
): string {
|
||||
const data = `${domain}:${uuid}:${password}`;
|
||||
return crypto.createHash('sha256').update(data).digest('hex');
|
||||
}
|
||||
|
||||
check_password(
|
||||
domain: string,
|
||||
uuid: string,
|
||||
password: string,
|
||||
hashed_password: string,
|
||||
): boolean {
|
||||
return (
|
||||
this.create_hashed_password(domain, uuid, password) === hashed_password
|
||||
);
|
||||
}
|
||||
|
||||
generateAccessToken(): string {
|
||||
return this.generateToken(tokenConfig.ACCESS_TOKEN_LENGTH);
|
||||
}
|
||||
|
||||
generateRefreshToken(): string {
|
||||
return this.generateToken(tokenConfig.REFRESHER_TOKEN_LENGTH);
|
||||
}
|
||||
|
||||
generateToken(length: number): string {
|
||||
const letters = 'abcdefghijklmnopqrstuvwxyz';
|
||||
const mergedLetters = [...letters, ...letters.toUpperCase().split('')];
|
||||
let token = crypto.randomBytes(length).toString('base64url');
|
||||
|
||||
token = token
|
||||
.split('')
|
||||
.map((char) =>
|
||||
mergedLetters.includes(char)
|
||||
? char
|
||||
: mergedLetters[Math.floor(Math.random() * mergedLetters.length)],
|
||||
)
|
||||
.join('');
|
||||
|
||||
return token;
|
||||
}
|
||||
}
|
||||
|
||||
export { PasswordHandlers };
|
||||
|
|
@ -0,0 +1,124 @@
|
|||
import {
|
||||
TokenDictType,
|
||||
OccupantTokenObject,
|
||||
EmployeeTokenObject,
|
||||
UserType,
|
||||
} from '@/src/types/auth/token';
|
||||
import { CacheService } from '@/src/cache.service';
|
||||
import { users } from '@prisma/client';
|
||||
import { PasswordHandlers } from './login_handler';
|
||||
import { Injectable } from '@nestjs/common';
|
||||
|
||||
@Injectable()
|
||||
export class RedisHandlers {
|
||||
AUTH_TOKEN = 'AUTH_TOKEN';
|
||||
constructor(
|
||||
private readonly cacheService: CacheService,
|
||||
private readonly passwordService: PasswordHandlers,
|
||||
) {
|
||||
this.cacheService = cacheService;
|
||||
this.passwordService = passwordService;
|
||||
}
|
||||
|
||||
async process_redis_object(redis_object: any): Promise<TokenDictType> {
|
||||
if (!redis_object) {
|
||||
throw new Error('Invalid Redis object: Object is null or undefined');
|
||||
}
|
||||
if (redis_object.user_type === UserType.employee) {
|
||||
const validateEmployeeToken = (obj: any): obj is EmployeeTokenObject => {
|
||||
return (
|
||||
typeof obj === 'object' &&
|
||||
obj !== null &&
|
||||
typeof obj.user_type === 'number' &&
|
||||
typeof obj.user_uu_id === 'string' &&
|
||||
typeof obj.user_id === 'number' &&
|
||||
typeof obj.person_id === 'number' &&
|
||||
typeof obj.person_uu_id === 'string' &&
|
||||
Array.isArray(obj.companies_id_list) &&
|
||||
Array.isArray(obj.companies_uu_id_list) &&
|
||||
Array.isArray(obj.duty_id_list) &&
|
||||
Array.isArray(obj.duty_uu_id_list)
|
||||
);
|
||||
};
|
||||
const empToken: EmployeeTokenObject = {
|
||||
...redis_object,
|
||||
is_employee: true,
|
||||
is_occupant: false,
|
||||
user_type: UserType.employee,
|
||||
credential_token: redis_object.credential_token || '',
|
||||
};
|
||||
if (!validateEmployeeToken(empToken)) {
|
||||
throw new Error(
|
||||
'Invalid Redis object: Does not match EmployeeTokenObject interface',
|
||||
);
|
||||
}
|
||||
return empToken;
|
||||
}
|
||||
|
||||
if (redis_object.user_type === UserType.occupant) {
|
||||
const validateOccupantToken = (obj: any): obj is OccupantTokenObject => {
|
||||
return (
|
||||
typeof obj === 'object' &&
|
||||
obj !== null &&
|
||||
typeof obj.user_type === 'number' &&
|
||||
typeof obj.user_uu_id === 'string' &&
|
||||
typeof obj.user_id === 'number' &&
|
||||
typeof obj.person_id === 'number' &&
|
||||
typeof obj.person_uu_id === 'string'
|
||||
);
|
||||
};
|
||||
const occToken: OccupantTokenObject = {
|
||||
...redis_object,
|
||||
is_employee: false,
|
||||
is_occupant: true,
|
||||
user_type: UserType.occupant,
|
||||
credential_token: redis_object.credential_token || '',
|
||||
available_occupants: redis_object.available_occupants || null,
|
||||
};
|
||||
if (!validateOccupantToken(occToken)) {
|
||||
throw new Error(
|
||||
'Invalid Redis object: Does not match OccupantTokenObject interface',
|
||||
);
|
||||
}
|
||||
return occToken;
|
||||
}
|
||||
throw new Error(`Invalid user_type: ${redis_object.user_type}`);
|
||||
}
|
||||
|
||||
async get_object_from_redis(access_token: string): Promise<TokenDictType> {
|
||||
const token = await this.cacheService.get(access_token);
|
||||
return this.process_redis_object(token);
|
||||
}
|
||||
|
||||
async set_login_to_redis(user: users, token: TokenDictType): Promise<any> {
|
||||
const generated_token = this.passwordService.generateAccessToken();
|
||||
const listKeys = [this.AUTH_TOKEN, generated_token, user.uu_id];
|
||||
await this.cacheService.set_with_ttl(
|
||||
this.cacheService.createRegexPattern(listKeys),
|
||||
token,
|
||||
60 * 60 * 24,
|
||||
);
|
||||
return generated_token;
|
||||
}
|
||||
|
||||
async update_token_via_token(token: string, additional: any): Promise<any> {
|
||||
const listKeys = [this.AUTH_TOKEN, token, '*'];
|
||||
const accessObject = await this.cacheService.get_with_keys(listKeys);
|
||||
if (!accessObject) throw new Error('Token not found');
|
||||
const processedObject: TokenDictType =
|
||||
await this.process_redis_object(accessObject);
|
||||
if (processedObject.is_employee) {
|
||||
processedObject.selected = additional;
|
||||
}
|
||||
if (processedObject.is_occupant) {
|
||||
processedObject.selected = additional;
|
||||
}
|
||||
const listKeysNew = [this.AUTH_TOKEN, token, processedObject.user_uu_id];
|
||||
await this.cacheService.set_with_ttl(
|
||||
this.cacheService.createRegexPattern(listKeysNew),
|
||||
processedObject,
|
||||
60 * 60 * 24,
|
||||
);
|
||||
return token;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,58 @@
|
|||
import { Injectable } from '@nestjs/common';
|
||||
import { PrismaService } from '@/src/prisma.service';
|
||||
|
||||
export interface PaginationInfo {
|
||||
totalCount: number;
|
||||
page: number;
|
||||
pageSize: number;
|
||||
totalPages: number;
|
||||
hasNextPage: boolean;
|
||||
hasPreviousPage: boolean;
|
||||
pageCount: number;
|
||||
}
|
||||
|
||||
type ModelDelegate = {
|
||||
count: (args: any) => Promise<number>;
|
||||
findMany: (args: any) => Promise<any[]>;
|
||||
};
|
||||
|
||||
@Injectable()
|
||||
export class PaginationHelper {
|
||||
constructor(private prisma: PrismaService) {}
|
||||
|
||||
/**
|
||||
* Sayfalama destekli sorgu yapar
|
||||
*
|
||||
* @param modelDelegate Prisma model delegesi (ör. prisma.users)
|
||||
* @param query Prisma findMany argümanları + opsiyonel page, pageSize
|
||||
* @returns { data, pagination } sonuç ve sayfalama bilgisi
|
||||
*/
|
||||
async paginate(
|
||||
modelDelegate: ModelDelegate,
|
||||
query: any & { page?: number; pageSize?: number },
|
||||
): Promise<{ data: any[]; pagination: PaginationInfo }> {
|
||||
const { page = 1, pageSize = 10, ...prismaQuery } = query;
|
||||
const totalCount = await modelDelegate.count({ where: prismaQuery.where });
|
||||
const totalPages = Math.max(Math.ceil(totalCount / pageSize), 1);
|
||||
const pageNumber = page < 1 ? 1 : page > totalPages ? totalPages : page;
|
||||
const pageSizeNumber = pageSize > 0 ? pageSize : 10;
|
||||
const data = await modelDelegate.findMany({
|
||||
...prismaQuery,
|
||||
skip: (pageNumber - 1) * pageSizeNumber,
|
||||
take: pageSizeNumber,
|
||||
});
|
||||
const pageCount = data.length;
|
||||
return {
|
||||
data,
|
||||
pagination: {
|
||||
totalCount,
|
||||
page: pageNumber,
|
||||
pageSize: pageSizeNumber,
|
||||
totalPages,
|
||||
hasNextPage: pageNumber < totalPages,
|
||||
hasPreviousPage: pageNumber > 1,
|
||||
pageCount,
|
||||
},
|
||||
};
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,9 @@
|
|||
import { Module } from '@nestjs/common';
|
||||
import { PaginationHelper } from './pagination-helper';
|
||||
import { PrismaService } from '@/src/prisma.service';
|
||||
|
||||
@Module({
|
||||
providers: [PaginationHelper, PrismaService],
|
||||
exports: [PaginationHelper],
|
||||
})
|
||||
export class UtilsModule {}
|
||||
|
|
@ -1,6 +1,7 @@
|
|||
{
|
||||
"compilerOptions": {
|
||||
"types": ["node"],
|
||||
"typeRoots": ["./node_modules/@types"],
|
||||
"module": "commonjs",
|
||||
"declaration": true,
|
||||
"removeComments": true,
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@ services:
|
|||
container_name: backend_service
|
||||
build:
|
||||
context: .
|
||||
dockerfile: backend/Dockerfile
|
||||
dockerfile: ServicesApi/Dockerfile
|
||||
target: builder
|
||||
ports:
|
||||
- "3000:3000"
|
||||
|
|
@ -14,7 +14,7 @@ services:
|
|||
command: npm run start:dev
|
||||
restart: unless-stopped
|
||||
volumes:
|
||||
- ./backend:/usr/src/app
|
||||
- ./ServicesApi:/usr/src/app
|
||||
- node_modules:/usr/src/app/node_modules
|
||||
|
||||
volumes:
|
||||
|
|
|
|||
Loading…
Reference in New Issue