initial data structures

This commit is contained in:
Evert Prants 2022-12-06 14:26:39 +02:00
parent 30cf12148d
commit c4d2cba4cb
24 changed files with 668 additions and 134 deletions

3
.vscode/settings.json vendored Normal file
View File

@ -0,0 +1,3 @@
{
"editor.formatOnSave": true
}

View File

@ -1,73 +1,6 @@
<p align="center">
<a href="http://nestjs.com/" target="blank"><img src="https://nestjs.com/img/logo-small.svg" width="120" alt="Nest Logo" /></a>
</p>
# Exercise
[circleci-image]: https://img.shields.io/circleci/build/github/nestjs/nest/master?token=abc123def456
[circleci-url]: https://circleci.com/gh/nestjs/nest
<p align="center">A progressive <a href="http://nodejs.org" target="_blank">Node.js</a> framework for building efficient and scalable server-side applications.</p>
<p align="center">
<a href="https://www.npmjs.com/~nestjscore" target="_blank"><img src="https://img.shields.io/npm/v/@nestjs/core.svg" alt="NPM Version" /></a>
<a href="https://www.npmjs.com/~nestjscore" target="_blank"><img src="https://img.shields.io/npm/l/@nestjs/core.svg" alt="Package License" /></a>
<a href="https://www.npmjs.com/~nestjscore" target="_blank"><img src="https://img.shields.io/npm/dm/@nestjs/common.svg" alt="NPM Downloads" /></a>
<a href="https://circleci.com/gh/nestjs/nest" target="_blank"><img src="https://img.shields.io/circleci/build/github/nestjs/nest/master" alt="CircleCI" /></a>
<a href="https://coveralls.io/github/nestjs/nest?branch=master" target="_blank"><img src="https://coveralls.io/repos/github/nestjs/nest/badge.svg?branch=master#9" alt="Coverage" /></a>
<a href="https://discord.gg/G7Qnnhy" target="_blank"><img src="https://img.shields.io/badge/discord-online-brightgreen.svg" alt="Discord"/></a>
<a href="https://opencollective.com/nest#backer" target="_blank"><img src="https://opencollective.com/nest/backers/badge.svg" alt="Backers on Open Collective" /></a>
<a href="https://opencollective.com/nest#sponsor" target="_blank"><img src="https://opencollective.com/nest/sponsors/badge.svg" alt="Sponsors on Open Collective" /></a>
<a href="https://paypal.me/kamilmysliwiec" target="_blank"><img src="https://img.shields.io/badge/Donate-PayPal-ff3f59.svg" alt="Donate us"/></a>
<a href="https://opencollective.com/nest#sponsor" target="_blank"><img src="https://img.shields.io/badge/Support%20us-Open%20Collective-41B883.svg" alt="Support us"></a>
<a href="https://twitter.com/nestframework" target="_blank"><img src="https://img.shields.io/twitter/follow/nestframework.svg?style=social&label=Follow" alt="Follow us on Twitter"></a>
</p>
<!--[![Backers on Open Collective](https://opencollective.com/nest/backers/badge.svg)](https://opencollective.com/nest#backer)
[![Sponsors on Open Collective](https://opencollective.com/nest/sponsors/badge.svg)](https://opencollective.com/nest#sponsor)-->
## Description
[Nest](https://github.com/nestjs/nest) framework TypeScript starter repository.
## Installation
```bash
$ npm install
```
## Running the app
```bash
# development
$ npm run start
# watch mode
$ npm run start:dev
# production mode
$ npm run start:prod
```
## Test
```bash
# unit tests
$ npm run test
# e2e tests
$ npm run test:e2e
# test coverage
$ npm run test:cov
```
## Support
Nest is an MIT-licensed open source project. It can grow thanks to the sponsors and support by the amazing backers. If you'd like to join them, please [read more here](https://docs.nestjs.com/support).
## Stay in touch
- Author - [Kamil Myśliwiec](https://twitter.com/kammysliwiec)
- Website - [https://nestjs.com](https://nestjs.com/)
- Twitter - [@nestframework](https://twitter.com/nestframework)
## License
Nest is [MIT licensed](https://github.com/nestjs/nest/blob/master/LICENSE).
1. Run MongoDB `docker-compose up`
2. Create initial resident `npx nestjs-command create:resident`
3. Run the application `npm run start:dev`
4. API is at http://localhost:3000

View File

@ -9,6 +9,7 @@ services:
environment:
MONGO_INITDB_ROOT_USERNAME: root
MONGO_INITDB_ROOT_PASSWORD: eprosperatest
MONGO_INITDB_DATABASE: nest
volumes:
- ./database:/data/db
- ./mongo-init.js:/docker-entrypoint-initdb.d/mongo-init.js:ro

10
mongo-init.js Normal file
View File

@ -0,0 +1,10 @@
db.createUser({
user: 'root',
pwd: 'eprosperatest',
roles: [
{
role: 'readWrite',
db: 'nest',
},
],
});

154
package-lock.json generated
View File

@ -17,8 +17,10 @@
"class-transformer": "^0.5.1",
"class-validator": "^0.13.2",
"mongoose": "^6.8.0",
"nestjs-command": "^3.1.2",
"reflect-metadata": "^0.1.13",
"rxjs": "^7.5.5"
"rxjs": "^7.5.5",
"yargs": "^17.6.2"
},
"devDependencies": {
"@nestjs/cli": "^9.0.0",
@ -3711,7 +3713,6 @@
"version": "5.0.1",
"resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz",
"integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==",
"dev": true,
"engines": {
"node": ">=8"
}
@ -3720,7 +3721,6 @@
"version": "4.3.0",
"resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz",
"integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==",
"dev": true,
"dependencies": {
"color-convert": "^2.0.1"
},
@ -4302,14 +4302,16 @@
}
},
"node_modules/cliui": {
"version": "7.0.4",
"resolved": "https://registry.npmjs.org/cliui/-/cliui-7.0.4.tgz",
"integrity": "sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ==",
"dev": true,
"version": "8.0.1",
"resolved": "https://registry.npmjs.org/cliui/-/cliui-8.0.1.tgz",
"integrity": "sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==",
"dependencies": {
"string-width": "^4.2.0",
"strip-ansi": "^6.0.0",
"strip-ansi": "^6.0.1",
"wrap-ansi": "^7.0.0"
},
"engines": {
"node": ">=12"
}
},
"node_modules/clone": {
@ -4341,7 +4343,6 @@
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz",
"integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==",
"dev": true,
"dependencies": {
"color-name": "~1.1.4"
},
@ -4352,8 +4353,7 @@
"node_modules/color-name": {
"version": "1.1.4",
"resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz",
"integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==",
"dev": true
"integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA=="
},
"node_modules/combined-stream": {
"version": "1.0.8",
@ -4680,8 +4680,7 @@
"node_modules/emoji-regex": {
"version": "8.0.0",
"resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz",
"integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==",
"dev": true
"integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A=="
},
"node_modules/encodeurl": {
"version": "1.0.2",
@ -4732,7 +4731,6 @@
"version": "3.1.1",
"resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz",
"integrity": "sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==",
"dev": true,
"engines": {
"node": ">=6"
}
@ -5553,7 +5551,6 @@
"version": "2.0.5",
"resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz",
"integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==",
"dev": true,
"engines": {
"node": "6.* || 8.* || >= 10.*"
}
@ -5982,7 +5979,6 @@
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz",
"integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==",
"dev": true,
"engines": {
"node": ">=8"
}
@ -7283,6 +7279,16 @@
"resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz",
"integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg=="
},
"node_modules/lodash.compact": {
"version": "3.0.1",
"resolved": "https://registry.npmjs.org/lodash.compact/-/lodash.compact-3.0.1.tgz",
"integrity": "sha512-2ozeiPi+5eBXW1CLtzjk8XQFhQOEMwwfxblqeq6EGyTxZJ1bPATqilY0e6g2SLQpP4KuMeuioBhEnWz5Pr7ICQ=="
},
"node_modules/lodash.flattendeep": {
"version": "4.4.0",
"resolved": "https://registry.npmjs.org/lodash.flattendeep/-/lodash.flattendeep-4.4.0.tgz",
"integrity": "sha512-uHaJFihxmJcEX3kT4I23ABqKKalJ/zDrDg0lsFtc1h+3uw49SIJ5beyhx5ExVRti3AvKoOJngIj7xz3oylPdWQ=="
},
"node_modules/lodash.memoize": {
"version": "4.1.2",
"resolved": "https://registry.npmjs.org/lodash.memoize/-/lodash.memoize-4.1.2.tgz",
@ -7676,6 +7682,23 @@
"integrity": "sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==",
"dev": true
},
"node_modules/nestjs-command": {
"version": "3.1.2",
"resolved": "https://registry.npmjs.org/nestjs-command/-/nestjs-command-3.1.2.tgz",
"integrity": "sha512-9PG4cEqx2OME+YSO7uzLg6YBzGwP7rv9ULZqa+Uitu7KR5S/FEWj1BrmET9vdWG61H/jy9mJdYro4ml4je02cg==",
"dependencies": {
"lodash.compact": "^3.0.1",
"lodash.flattendeep": "^4.4.0"
},
"bin": {
"nestjs-command": "bin/cli"
},
"peerDependencies": {
"@nestjs/common": "^6.0.0 || ^7.0.0 || ^8.0.0 || ^9.0.0",
"@nestjs/core": "^6.0.0 || ^7.0.0 || ^8.0.0 || ^9.0.0",
"yargs": "^16.0.0 || ^17.0.0"
}
},
"node_modules/node-emoji": {
"version": "1.11.0",
"resolved": "https://registry.npmjs.org/node-emoji/-/node-emoji-1.11.0.tgz",
@ -8311,7 +8334,6 @@
"version": "2.1.1",
"resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz",
"integrity": "sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==",
"dev": true,
"engines": {
"node": ">=0.10.0"
}
@ -8822,7 +8844,6 @@
"version": "4.2.3",
"resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz",
"integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==",
"dev": true,
"dependencies": {
"emoji-regex": "^8.0.0",
"is-fullwidth-code-point": "^3.0.0",
@ -8836,7 +8857,6 @@
"version": "6.0.1",
"resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz",
"integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==",
"dev": true,
"dependencies": {
"ansi-regex": "^5.0.1"
},
@ -9746,7 +9766,6 @@
"version": "7.0.0",
"resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz",
"integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==",
"dev": true,
"dependencies": {
"ansi-styles": "^4.0.0",
"string-width": "^4.1.0",
@ -9790,7 +9809,6 @@
"version": "5.0.8",
"resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz",
"integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==",
"dev": true,
"engines": {
"node": ">=10"
}
@ -9811,18 +9829,17 @@
}
},
"node_modules/yargs": {
"version": "17.5.1",
"resolved": "https://registry.npmjs.org/yargs/-/yargs-17.5.1.tgz",
"integrity": "sha512-t6YAJcxDkNX7NFYiVtKvWUz8l+PaKTLiL63mJYWR2GnHq2gjEWISzsLp9wg3aY36dY1j+gfIEL3pIF+XlJJfbA==",
"dev": true,
"version": "17.6.2",
"resolved": "https://registry.npmjs.org/yargs/-/yargs-17.6.2.tgz",
"integrity": "sha512-1/9UrdHjDZc0eOU0HxOHoS78C69UD3JRMvzlJ7S79S2nTaWRA/whGCTV8o9e/N/1Va9YIV7Q4sOxD8VV4pCWOw==",
"dependencies": {
"cliui": "^7.0.2",
"cliui": "^8.0.1",
"escalade": "^3.1.1",
"get-caller-file": "^2.0.5",
"require-directory": "^2.1.1",
"string-width": "^4.2.3",
"y18n": "^5.0.5",
"yargs-parser": "^21.0.0"
"yargs-parser": "^21.1.1"
},
"engines": {
"node": ">=12"
@ -9837,6 +9854,14 @@
"node": ">=12"
}
},
"node_modules/yargs/node_modules/yargs-parser": {
"version": "21.1.1",
"resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.1.1.tgz",
"integrity": "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==",
"engines": {
"node": ">=12"
}
},
"node_modules/yn": {
"version": "3.1.1",
"resolved": "https://registry.npmjs.org/yn/-/yn-3.1.1.tgz",
@ -12755,14 +12780,12 @@
"ansi-regex": {
"version": "5.0.1",
"resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz",
"integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==",
"dev": true
"integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ=="
},
"ansi-styles": {
"version": "4.3.0",
"resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz",
"integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==",
"dev": true,
"requires": {
"color-convert": "^2.0.1"
}
@ -13184,13 +13207,12 @@
"dev": true
},
"cliui": {
"version": "7.0.4",
"resolved": "https://registry.npmjs.org/cliui/-/cliui-7.0.4.tgz",
"integrity": "sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ==",
"dev": true,
"version": "8.0.1",
"resolved": "https://registry.npmjs.org/cliui/-/cliui-8.0.1.tgz",
"integrity": "sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==",
"requires": {
"string-width": "^4.2.0",
"strip-ansi": "^6.0.0",
"strip-ansi": "^6.0.1",
"wrap-ansi": "^7.0.0"
}
},
@ -13216,7 +13238,6 @@
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz",
"integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==",
"dev": true,
"requires": {
"color-name": "~1.1.4"
}
@ -13224,8 +13245,7 @@
"color-name": {
"version": "1.1.4",
"resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz",
"integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==",
"dev": true
"integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA=="
},
"combined-stream": {
"version": "1.0.8",
@ -13487,8 +13507,7 @@
"emoji-regex": {
"version": "8.0.0",
"resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz",
"integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==",
"dev": true
"integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A=="
},
"encodeurl": {
"version": "1.0.2",
@ -13532,8 +13551,7 @@
"escalade": {
"version": "3.1.1",
"resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz",
"integrity": "sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==",
"dev": true
"integrity": "sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw=="
},
"escape-html": {
"version": "1.0.3",
@ -14147,8 +14165,7 @@
"get-caller-file": {
"version": "2.0.5",
"resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz",
"integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==",
"dev": true
"integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg=="
},
"get-intrinsic": {
"version": "1.1.2",
@ -14454,8 +14471,7 @@
"is-fullwidth-code-point": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz",
"integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==",
"dev": true
"integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg=="
},
"is-generator-fn": {
"version": "2.1.0",
@ -15434,6 +15450,16 @@
"resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz",
"integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg=="
},
"lodash.compact": {
"version": "3.0.1",
"resolved": "https://registry.npmjs.org/lodash.compact/-/lodash.compact-3.0.1.tgz",
"integrity": "sha512-2ozeiPi+5eBXW1CLtzjk8XQFhQOEMwwfxblqeq6EGyTxZJ1bPATqilY0e6g2SLQpP4KuMeuioBhEnWz5Pr7ICQ=="
},
"lodash.flattendeep": {
"version": "4.4.0",
"resolved": "https://registry.npmjs.org/lodash.flattendeep/-/lodash.flattendeep-4.4.0.tgz",
"integrity": "sha512-uHaJFihxmJcEX3kT4I23ABqKKalJ/zDrDg0lsFtc1h+3uw49SIJ5beyhx5ExVRti3AvKoOJngIj7xz3oylPdWQ=="
},
"lodash.memoize": {
"version": "4.1.2",
"resolved": "https://registry.npmjs.org/lodash.memoize/-/lodash.memoize-4.1.2.tgz",
@ -15734,6 +15760,15 @@
"integrity": "sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==",
"dev": true
},
"nestjs-command": {
"version": "3.1.2",
"resolved": "https://registry.npmjs.org/nestjs-command/-/nestjs-command-3.1.2.tgz",
"integrity": "sha512-9PG4cEqx2OME+YSO7uzLg6YBzGwP7rv9ULZqa+Uitu7KR5S/FEWj1BrmET9vdWG61H/jy9mJdYro4ml4je02cg==",
"requires": {
"lodash.compact": "^3.0.1",
"lodash.flattendeep": "^4.4.0"
}
},
"node-emoji": {
"version": "1.11.0",
"resolved": "https://registry.npmjs.org/node-emoji/-/node-emoji-1.11.0.tgz",
@ -16195,8 +16230,7 @@
"require-directory": {
"version": "2.1.1",
"resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz",
"integrity": "sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==",
"dev": true
"integrity": "sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q=="
},
"require-from-string": {
"version": "2.0.2",
@ -16577,7 +16611,6 @@
"version": "4.2.3",
"resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz",
"integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==",
"dev": true,
"requires": {
"emoji-regex": "^8.0.0",
"is-fullwidth-code-point": "^3.0.0",
@ -16588,7 +16621,6 @@
"version": "6.0.1",
"resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz",
"integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==",
"dev": true,
"requires": {
"ansi-regex": "^5.0.1"
}
@ -17216,7 +17248,6 @@
"version": "7.0.0",
"resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz",
"integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==",
"dev": true,
"requires": {
"ansi-styles": "^4.0.0",
"string-width": "^4.1.0",
@ -17247,8 +17278,7 @@
"y18n": {
"version": "5.0.8",
"resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz",
"integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==",
"dev": true
"integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA=="
},
"yallist": {
"version": "4.0.0",
@ -17263,18 +17293,24 @@
"dev": true
},
"yargs": {
"version": "17.5.1",
"resolved": "https://registry.npmjs.org/yargs/-/yargs-17.5.1.tgz",
"integrity": "sha512-t6YAJcxDkNX7NFYiVtKvWUz8l+PaKTLiL63mJYWR2GnHq2gjEWISzsLp9wg3aY36dY1j+gfIEL3pIF+XlJJfbA==",
"dev": true,
"version": "17.6.2",
"resolved": "https://registry.npmjs.org/yargs/-/yargs-17.6.2.tgz",
"integrity": "sha512-1/9UrdHjDZc0eOU0HxOHoS78C69UD3JRMvzlJ7S79S2nTaWRA/whGCTV8o9e/N/1Va9YIV7Q4sOxD8VV4pCWOw==",
"requires": {
"cliui": "^7.0.2",
"cliui": "^8.0.1",
"escalade": "^3.1.1",
"get-caller-file": "^2.0.5",
"require-directory": "^2.1.1",
"string-width": "^4.2.3",
"y18n": "^5.0.5",
"yargs-parser": "^21.0.0"
"yargs-parser": "^21.1.1"
},
"dependencies": {
"yargs-parser": {
"version": "21.1.1",
"resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.1.1.tgz",
"integrity": "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw=="
}
}
},
"yargs-parser": {

View File

@ -27,8 +27,10 @@
"class-transformer": "^0.5.1",
"class-validator": "^0.13.2",
"mongoose": "^6.8.0",
"nestjs-command": "^3.1.2",
"reflect-metadata": "^0.1.13",
"rxjs": "^7.5.5"
"rxjs": "^7.5.5",
"yargs": "^17.6.2"
},
"devDependencies": {
"@nestjs/cli": "^9.0.0",

View File

@ -1,9 +1,26 @@
import { Module } from '@nestjs/common';
import { ConfigModule, ConfigService } from '@nestjs/config';
import { MongooseModule } from '@nestjs/mongoose';
import { AppController } from './app.controller';
import { AppService } from './app.service';
import { IndustryChangeApplicationModule } from './industry-change-application/industry-change-application.module';
import { ResidentModule } from './resident/resident.module';
import { CommandModule } from 'nestjs-command';
@Module({
imports: [],
imports: [
CommandModule,
ConfigModule.forRoot({}),
MongooseModule.forRootAsync({
imports: [ConfigModule],
useFactory: async (configService: ConfigService) => ({
uri: configService.get<string>('MONGODB_URI'),
}),
inject: [ConfigService],
}),
ResidentModule,
IndustryChangeApplicationModule,
],
controllers: [AppController],
providers: [AppService],
})

20
src/cli.ts Normal file
View File

@ -0,0 +1,20 @@
import { NestFactory } from '@nestjs/core';
import { CommandModule, CommandService } from 'nestjs-command';
import { AppModule } from './app.module';
async function bootstrap() {
const app = await NestFactory.createApplicationContext(AppModule, {
logger: false,
});
try {
await app.select(CommandModule).get(CommandService).exec();
await app.close();
} catch (error) {
console.error(error);
await app.close();
process.exit(1);
}
}
bootstrap();

View File

@ -0,0 +1,12 @@
export enum Industry {
AGRICULTURAL = 'AGRICULTURAL',
CONSTRUCTION = 'CONSTRUCTION',
ENERGY = 'ENERGY',
FINANCE_AND_INSURANCE = 'FINANCE_AND_INSURANCE',
FOOD = 'FOOD',
HEALTH = 'HEALTH',
MANUFACTURING = 'MANUFACTURING',
MINING_AND_SUBSURFACE = 'MINING_AND_SUBSURFACE',
PRIVATE_SECURITY = 'PRIVATE_SECURITY',
WASTE_MANAGEMENT = 'WASTE_MANAGEMENT',
}

View File

@ -0,0 +1,37 @@
export enum RegulatoryElection {
AUSTRALIA = 'AUSTRALIA',
AUSTRIA = 'AUSTRIA',
BELGIUM = 'BELGIUM',
CANADA = 'CANADA',
CHILE = 'CHILE',
ROATAN_COMMON_LAW_CODE = 'ROATAN_COMMON_LAW_CODE',
DENMARK = 'DENMARK',
DUBAI = 'DUBAI',
ESTONIA = 'ESTONIA',
FINLAND = 'FINLAND',
FRANCE = 'FRANCE',
GERMANY = 'GERMANY',
HONDURAS = 'HONDURAS',
HONG_KONG = 'HONG_KONG',
ICELAND = 'ICELAND',
IRELAND = 'IRELAND',
ISRAEL = 'ISRAEL',
ITALY = 'ITALY',
JAPAN = 'JAPAN',
LUXEMBOURG = 'LUXEMBOURG',
MEXICO = 'MEXICO',
NETHERLANDS = 'NETHERLANDS',
NEW_ZEALAND = 'NEW_ZEALAND',
null = 'null',
NORWAY = 'NORWAY',
PETITION_FOR_TAILORED_REGULATION_GRANTED = 'PETITION_FOR_TAILORED_REGULATION_GRANTED',
PETITION_FOR_TAILORED_REGULATION_PENDING = 'PETITION_FOR_TAILORED_REGULATION_PENDING',
POLAND = 'POLAND',
SINGAPORE = 'SINGAPORE',
SOUTH_KOREA = 'SOUTH_KOREA',
SPAIN = 'SPAIN',
SWEDEN = 'SWEDEN',
SWITZERLAND = 'SWITZERLAND',
UK = 'UK',
USA = 'USA',
}

15
src/enums/status.enum.ts Normal file
View File

@ -0,0 +1,15 @@
export enum ApplicationStatus {
IN_REVIEW = 'IN_REVIEW',
APPROVED = 'APPROVED',
REJECTED = 'REJECTED',
}
export enum ObjectStatus {
CURRENT = 'CURRENT',
DELETED = 'DELETED',
}
export enum ResidentStatus {
ACTIVE = 'ACTIVE',
INACTIVE = 'INACTIVE',
}

View File

@ -0,0 +1,10 @@
export enum TypeOfRegistration {
E_RESIDENCY = 'E_RESIDENCY',
RESIDENCY = 'RESIDENCY',
LIMITED_E_RESIDENCY = 'LIMITED_E_RESIDENCY',
}
export enum TypeOfRegistrationSub {
HONDURAN = 'HONDURAN',
INTERNATIONAL = 'INTERNATIONAL',
}

View File

@ -0,0 +1,43 @@
import { Exclude, Expose } from 'class-transformer';
import { Industry } from 'src/enums/industry.enum';
import { RegulatoryElection } from 'src/enums/regulatory-election.enums';
import { ApplicationStatus, ObjectStatus } from 'src/enums/status.enum';
import { Resident } from 'src/resident/schemas/Resident.schema';
export class ApplicationInformationDto {
@Exclude()
_id: string;
willWorkInPhysicalJuristiction: string;
industry: Industry;
regulatoryElection: RegulatoryElection;
regulatoryElectionSub: string;
}
export class DecisionDto {
@Exclude()
_id: string;
decidedAt: Date;
rejctionReason: string;
}
export class GetRegisterIndustryChangeApplicationDto {
@Expose({ name: 'id' })
_id: string;
@Exclude()
resident: Resident;
@Expose({ name: 'residentSub' })
getResidentSub() {
return this.resident.sub;
}
current: ApplicationInformationDto;
requested: ApplicationInformationDto;
status: ApplicationStatus;
submittedAt: Date;
decision: DecisionDto;
objectStatus: ObjectStatus;
}

View File

@ -0,0 +1,24 @@
import { Controller, Get } from '@nestjs/common';
import { plainToInstance } from 'class-transformer';
import { GetRegisterIndustryChangeApplicationDto } from './dtos/register-industry-change-application.dto';
import { IndustryChangeApplicationService } from './industry-change-application.service';
@Controller({
path: '/resident-register/industry-change-applications',
})
export class IndustryChangeApplicationController {
constructor(
private readonly applicationsSerivce: IndustryChangeApplicationService,
) {}
@Get()
async getList() {
const allApplications = await this.applicationsSerivce.getAll();
const transformed = plainToInstance(
GetRegisterIndustryChangeApplicationDto,
allApplications,
{ excludeExtraneousValues: true },
);
return transformed;
}
}

View File

@ -0,0 +1,35 @@
import { Module } from '@nestjs/common';
import { MongooseModule } from '@nestjs/mongoose';
import { IndustryChangeApplicationController } from './industry-change-application.controller';
import { IndustryChangeApplicationService } from './industry-change-application.service';
import { Decision, DecisionSchema } from './schemas/Decision.schema';
import {
ICAInformation,
ICAInformationSchema,
} from './schemas/ICAInformation.schema';
import {
IndustryChangeApplication,
IndustryChangeApplicationSchema,
} from './schemas/IndustryChangeApplication.schema';
@Module({
imports: [
MongooseModule.forFeature([
{
name: Decision.name,
schema: DecisionSchema,
},
{
name: ICAInformation.name,
schema: ICAInformationSchema,
},
{
name: IndustryChangeApplication.name,
schema: IndustryChangeApplicationSchema,
},
]),
],
controllers: [IndustryChangeApplicationController],
providers: [IndustryChangeApplicationService],
})
export class IndustryChangeApplicationModule {}

View File

@ -0,0 +1,19 @@
import { Injectable } from '@nestjs/common';
import { InjectModel } from '@nestjs/mongoose';
import { Model } from 'mongoose';
import {
IndustryChangeApplication,
IndustryChangeApplicationDocument,
} from './schemas/IndustryChangeApplication.schema';
@Injectable()
export class IndustryChangeApplicationService {
constructor(
@InjectModel(IndustryChangeApplication.name)
private applicationModel: Model<IndustryChangeApplicationDocument>,
) {}
async getAll() {
return this.applicationModel.find();
}
}

View File

@ -0,0 +1,15 @@
import { Prop, Schema, SchemaFactory } from '@nestjs/mongoose';
@Schema({ _id: false })
export class Decision {
@Prop()
decidedAt: Date;
@Prop()
decidedBy: string;
@Prop()
rejectionReason: string;
}
export const DecisionSchema = SchemaFactory.createForClass(Decision);

View File

@ -0,0 +1,21 @@
import { Prop, Schema, SchemaFactory } from '@nestjs/mongoose';
import { Industry } from 'src/enums/industry.enum';
import { RegulatoryElection } from 'src/enums/regulatory-election.enums';
@Schema({ _id: false })
export class ICAInformation {
@Prop({ type: String, enum: Industry })
industry: Industry;
@Prop({ required: true })
willWorkInPhysicalJurisdiction: boolean;
@Prop({ type: String, enum: RegulatoryElection })
regulatoryElection: RegulatoryElection;
@Prop()
regulatoryElectionSub: string;
}
export const ICAInformationSchema =
SchemaFactory.createForClass(ICAInformation);

View File

@ -0,0 +1,65 @@
import { Prop, Schema, SchemaFactory } from '@nestjs/mongoose';
import mongoose, { HydratedDocument } from 'mongoose';
import { Resident } from 'src/resident/schemas/Resident.schema';
import { Decision } from './Decision.schema';
import { ApplicationStatus, ObjectStatus } from 'src/enums/status.enum';
import { ICAInformation } from './ICAInformation.schema';
export type IndustryChangeApplicationDocument =
HydratedDocument<IndustryChangeApplication>;
@Schema({
timestamps: true,
})
export class IndustryChangeApplication {
@Prop({
required: true,
ref: 'Resident',
type: mongoose.Schema.Types.ObjectId,
})
resident: Resident;
@Prop({
required: true,
type: ICAInformation,
})
current: ICAInformation;
@Prop({
required: true,
type: ICAInformation,
})
requested: ICAInformation;
@Prop({
type: String,
enum: ApplicationStatus,
default: ApplicationStatus.IN_REVIEW,
required: true,
})
status: ApplicationStatus;
@Prop()
submittedAt: Date;
@Prop({ type: Decision })
decision: Decision;
@Prop()
createdBy: string;
@Prop()
updatedBy: string;
@Prop({
type: String,
enum: ObjectStatus,
default: ObjectStatus.CURRENT,
required: true,
})
objectStatus: ObjectStatus;
}
export const IndustryChangeApplicationSchema = SchemaFactory.createForClass(
IndustryChangeApplication,
);

View File

@ -0,0 +1,27 @@
import { Module } from '@nestjs/common';
import { MongooseModule } from '@nestjs/mongoose';
import { ResidentSeed } from './resident.seed';
import { ResidentService } from './resident.service';
import { Resident, ResidentSchema } from './schemas/Resident.schema';
import {
ResidentAddress,
ResidentAddressSchema,
} from './schemas/ResidentAddress.schema';
@Module({
imports: [
MongooseModule.forFeature([
{
name: ResidentAddress.name,
schema: ResidentAddressSchema,
},
{
name: Resident.name,
schema: ResidentSchema,
},
]),
],
providers: [ResidentService, ResidentSeed],
exports: [ResidentService],
})
export class ResidentModule {}

View File

@ -0,0 +1,55 @@
import { Injectable } from '@nestjs/common';
import { ResidentService } from './resident.service';
import { Command } from 'nestjs-command';
import {
TypeOfRegistration,
TypeOfRegistrationSub,
} from 'src/enums/type-of-registration.enums';
import { Industry } from 'src/enums/industry.enum';
import { RegulatoryElection } from 'src/enums/regulatory-election.enums';
import { ResidentStatus } from 'src/enums/status.enum';
@Injectable()
export class ResidentSeed {
constructor(private readonly residentService: ResidentService) {}
@Command({
command: 'create:resident',
describe: 'Create initial resident',
})
async create() {
const resident = await this.residentService.createResident({
sub: 'f26d49bd-73aa-4e9c-b793-a367e1315b7d',
firstName: 'Someone',
lastName: 'Special',
fullName: 'Someone Special',
permitNumber: 1234,
permitNumberQrCode: '<qr code in base 64>',
dateOfBirth: new Date('1998-12-13'),
countryOfBirth: 'Estonia',
email: 'someone.special@world-news.local',
citizenship: 'Estonia',
gender: 'm',
address: {
country: 'Estonia',
city: 'Tallinn',
streetAddress: '9 Lambi Tee',
zipCode: '34211',
isVerifiedAddress: true,
},
phoneNumber: '+372 5454 1010',
typeOfRegistration: TypeOfRegistration.E_RESIDENCY,
typeOfRegistrationSub: TypeOfRegistrationSub.INTERNATIONAL,
industry: Industry.WASTE_MANAGEMENT,
willWorkInPhysicalJurisdiction: false,
regulatoryElection: RegulatoryElection.ESTONIA,
regulatoryElectionSub: 'sub info',
firstRegistrationDate: new Date('2006-06-12'),
profilePicture: '<profile picture base64>',
status: ResidentStatus.ACTIVE,
nextSubscriptionPaymentDate: new Date(Date.now() + 31 * 24 * 60 * 60000),
});
console.log(resident);
}
}

View File

@ -0,0 +1,17 @@
import { Injectable } from '@nestjs/common';
import { InjectModel } from '@nestjs/mongoose';
import { Model } from 'mongoose';
import { Resident, ResidentDocument } from './schemas/Resident.schema';
import { ResidentAddress } from './schemas/ResidentAddress.schema';
@Injectable()
export class ResidentService {
constructor(
@InjectModel(Resident.name) private residentModel: Model<ResidentDocument>,
) {}
public async createResident(resident: Partial<Resident>): Promise<Resident> {
const createdResident = new this.residentModel(resident);
return createdResident.save();
}
}

View File

@ -0,0 +1,92 @@
import { Prop, Schema, SchemaFactory } from '@nestjs/mongoose';
import { HydratedDocument } from 'mongoose';
import { Industry } from 'src/enums/industry.enum';
import { RegulatoryElection } from 'src/enums/regulatory-election.enums';
import { ResidentStatus } from 'src/enums/status.enum';
import {
TypeOfRegistration,
TypeOfRegistrationSub,
} from 'src/enums/type-of-registration.enums';
import { ResidentAddress } from './ResidentAddress.schema';
export type ResidentDocument = HydratedDocument<Resident>;
@Schema()
export class Resident {
@Prop({ required: true, unique: true })
sub: string;
@Prop({ required: true })
firstName: string;
@Prop({ required: true })
lastName: string;
@Prop({ required: true })
fullName: string;
@Prop({ required: true })
permitNumber: number;
@Prop()
permitNumberQrCode: string;
@Prop({ required: true })
dateOfBirth: Date;
@Prop({ required: true })
countryOfBirth: string;
@Prop({ required: true })
email: string;
@Prop({ required: true })
citizenship: string;
@Prop({ required: true })
gender: string;
@Prop({
type: ResidentAddress,
required: true,
})
address: ResidentAddress;
@Prop({ required: true })
phoneNumber: string;
@Prop({ required: true, type: String, enum: TypeOfRegistration })
typeOfRegistration: TypeOfRegistration;
@Prop({ type: String, enum: TypeOfRegistrationSub })
typeOfRegistrationSub: TypeOfRegistrationSub;
@Prop({ type: String, enum: Industry })
industry: Industry;
@Prop({ required: true })
willWorkInPhysicalJurisdiction: boolean;
@Prop({ type: String, enum: RegulatoryElection })
regulatoryElection: RegulatoryElection;
@Prop()
regulatoryElectionSub: string;
@Prop({ required: true })
firstRegistrationDate: Date;
@Prop({ required: true })
nextSubscriptionPaymentDate: Date;
@Prop({ required: true })
profilePicture: string;
@Prop({ required: true, type: String, enum: ResidentStatus })
status: ResidentStatus;
@Prop()
residencyEndDate: Date;
}
export const ResidentSchema = SchemaFactory.createForClass(Resident);

View File

@ -0,0 +1,25 @@
import { Prop, Schema, SchemaFactory } from '@nestjs/mongoose';
@Schema({ _id: false })
export class ResidentAddress {
@Prop({ required: true })
country: string;
@Prop({ required: true })
city: string;
@Prop()
state?: string;
@Prop({ required: true })
streetAddress: string;
@Prop({ required: true })
zipCode: string;
@Prop({ required: true })
isVerifiedAddress: boolean;
}
export const ResidentAddressSchema =
SchemaFactory.createForClass(ResidentAddress);