From 828fd52302e6967b904794ef24d7fcf6774482b6 Mon Sep 17 00:00:00 2001 From: NorbiPeti Date: Wed, 10 Nov 2021 17:10:20 +0100 Subject: [PATCH] Add production database, user model and controller --- backend/docker.sh | 1 + backend/package-lock.json | 289 +++++++++++++++++- backend/package.json | 1 + backend/src/controllers/index.ts | 1 + backend/src/controllers/user.controller.ts | 150 +++++++++ .../src/datasources/database.datasource.ts | 31 ++ backend/src/datasources/index.ts | 1 + backend/src/models/index.ts | 1 + backend/src/models/user.model.ts | 46 +++ backend/src/repositories/index.ts | 1 + backend/src/repositories/user.repository.ts | 16 + docker-compose.yml | 1 + 12 files changed, 535 insertions(+), 4 deletions(-) create mode 100644 backend/src/controllers/user.controller.ts create mode 100644 backend/src/datasources/database.datasource.ts create mode 100644 backend/src/datasources/index.ts create mode 100644 backend/src/models/index.ts create mode 100644 backend/src/models/user.model.ts create mode 100644 backend/src/repositories/index.ts create mode 100644 backend/src/repositories/user.repository.ts diff --git a/backend/docker.sh b/backend/docker.sh index 1f3d82d..825be9e 100644 --- a/backend/docker.sh +++ b/backend/docker.sh @@ -8,4 +8,5 @@ fi echo "Installing packages" npm install echo "Running application" +npm run rebuild npm run start:watch diff --git a/backend/package-lock.json b/backend/package-lock.json index d9b0cdf..49ec7d3 100644 --- a/backend/package-lock.json +++ b/backend/package-lock.json @@ -14,6 +14,7 @@ "@loopback/rest": "^10.1.0", "@loopback/rest-explorer": "^3.3.4", "@loopback/service-proxy": "^3.2.4", + "loopback-connector-mysql": "^5.4.4", "tslib": "^2.0.0" }, "devDependencies": { @@ -1662,6 +1663,14 @@ "node": ">=0.10" } }, + "node_modules/bignumber.js": { + "version": "9.0.0", + "resolved": "https://registry.npmjs.org/bignumber.js/-/bignumber.js-9.0.0.tgz", + "integrity": "sha512-t/OYhhJ2SD+YGBQcjY8GzzDHEk9f3nerxjtfa6tlMXfe7frs/WozhvCNoGvpM0P3bNf3Gq5ZRMlGr5f3r4/N8A==", + "engines": { + "node": "*" + } + }, "node_modules/binary-extensions": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.2.0.tgz", @@ -4092,6 +4101,128 @@ "node": ">=10" } }, + "node_modules/loopback-connector-mysql": { + "version": "5.4.4", + "resolved": "https://registry.npmjs.org/loopback-connector-mysql/-/loopback-connector-mysql-5.4.4.tgz", + "integrity": "sha512-6y+eXbP1YJWfEqBsuaNoK6zGSTurN1h0X67qpRj/pf0U9qWphjuJGYbU4Z8DnutY3J1OTeSycQgvt1qLJNHj/w==", + "dependencies": { + "async": "^2.6.1", + "debug": "^3.1.0", + "lodash": "^4.17.11", + "loopback-connector": "^4.0.0", + "mysql": "^2.11.1", + "strong-globalize": "^5.0.5" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/loopback-connector-mysql/node_modules/async": { + "version": "2.6.3", + "resolved": "https://registry.npmjs.org/async/-/async-2.6.3.tgz", + "integrity": "sha512-zflvls11DCy+dQWzTW2dzuilv8Z5X/pjfmZOWba6TNIVDm+2UDaJmXSOXlasHKfNBs8oo3M0aT50fDEWfKZjXg==", + "dependencies": { + "lodash": "^4.17.14" + } + }, + "node_modules/loopback-connector-mysql/node_modules/debug": { + "version": "3.2.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", + "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", + "dependencies": { + "ms": "^2.1.1" + } + }, + "node_modules/loopback-connector-mysql/node_modules/loopback-connector": { + "version": "4.11.1", + "resolved": "https://registry.npmjs.org/loopback-connector/-/loopback-connector-4.11.1.tgz", + "integrity": "sha512-EA31zur3xIhP4UW+P2rWEcSbqpk4jPddpTBZSSw8KCszM7T0/Pe4HvEmG0MndAWJctRPtrwKDEu/8rWuMDLf+A==", + "dependencies": { + "async": "^3.2.0", + "bluebird": "^3.7.2", + "debug": "^4.1.1", + "msgpack5": "^4.2.0", + "strong-globalize": "^5.1.0", + "uuid": "^7.0.3" + }, + "engines": { + "node": ">=8.9" + } + }, + "node_modules/loopback-connector-mysql/node_modules/loopback-connector/node_modules/async": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/async/-/async-3.2.2.tgz", + "integrity": "sha512-H0E+qZaDEfx/FY4t7iLRv1W2fFI6+pyCeTw1uN20AQPiwqwM6ojPxHxdLv4z8hi2DtnW9BOckSspLucW7pIE5g==" + }, + "node_modules/loopback-connector-mysql/node_modules/loopback-connector/node_modules/debug": { + "version": "4.3.2", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.2.tgz", + "integrity": "sha512-mOp8wKcvj7XxC78zLgw/ZA+6TSgkoE2C/ienthhRD298T7UNwAg9diBpLRxC0mOezLl4B0xV7M0cCO6P/O0Xhw==", + "dependencies": { + "ms": "2.1.2" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/loopback-connector-mysql/node_modules/mkdirp": { + "version": "0.5.5", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.5.tgz", + "integrity": "sha512-NKmAlESf6jMGym1++R0Ra7wvhV+wFW63FaSOFPwRahvea0gMUcGUhVeAg/0BC0wiv9ih5NYPB1Wn1UEI1/L+xQ==", + "dependencies": { + "minimist": "^1.2.5" + }, + "bin": { + "mkdirp": "bin/cmd.js" + } + }, + "node_modules/loopback-connector-mysql/node_modules/strong-globalize": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/strong-globalize/-/strong-globalize-5.1.0.tgz", + "integrity": "sha512-9cooAb6kNMDFmTDybkkch1x7b+LuzZNva8oIr+MxXnvx9jcvw4/4DTSXPc53mG68G0Q9YOTYZkhDkWe/DiJ1Qg==", + "dependencies": { + "accept-language": "^3.0.18", + "debug": "^4.1.1", + "globalize": "^1.5.0", + "lodash": "^4.17.15", + "md5": "^2.2.1", + "mkdirp": "^0.5.5", + "os-locale": "^5.0.0", + "yamljs": "^0.3.0" + }, + "engines": { + "node": ">=8.9" + } + }, + "node_modules/loopback-connector-mysql/node_modules/strong-globalize/node_modules/debug": { + "version": "4.3.2", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.2.tgz", + "integrity": "sha512-mOp8wKcvj7XxC78zLgw/ZA+6TSgkoE2C/ienthhRD298T7UNwAg9diBpLRxC0mOezLl4B0xV7M0cCO6P/O0Xhw==", + "dependencies": { + "ms": "2.1.2" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/loopback-connector-mysql/node_modules/uuid": { + "version": "7.0.3", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-7.0.3.tgz", + "integrity": "sha512-DPSke0pXhTZgoF/d+WSt2QaKMCFSfx7QegxEWT+JOuHF5aWrKEn0G+ztjuJg/gG8/ItK+rbPCD/yNv8yyih6Cg==", + "bin": { + "uuid": "dist/bin/uuid" + } + }, "node_modules/loopback-datasource-juggler": { "version": "4.26.0", "resolved": "https://registry.npmjs.org/loopback-datasource-juggler/-/loopback-datasource-juggler-4.26.0.tgz", @@ -4299,8 +4430,7 @@ "node_modules/minimist": { "version": "1.2.5", "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.5.tgz", - "integrity": "sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw==", - "dev": true + "integrity": "sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw==" }, "node_modules/mkdirp": { "version": "1.0.4", @@ -4446,6 +4576,25 @@ "safe-buffer": "^5.1.2" } }, + "node_modules/mysql": { + "version": "2.18.1", + "resolved": "https://registry.npmjs.org/mysql/-/mysql-2.18.1.tgz", + "integrity": "sha512-Bca+gk2YWmqp2Uf6k5NFEurwY/0td0cpebAucFpY/3jhrwrVGuxU2uQFCHjU19SJfje0yQvi+rVWdq78hR5lig==", + "dependencies": { + "bignumber.js": "9.0.0", + "readable-stream": "2.3.7", + "safe-buffer": "5.1.2", + "sqlstring": "2.3.1" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/mysql/node_modules/safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" + }, "node_modules/nanoid": { "version": "2.1.11", "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-2.1.11.tgz", @@ -6001,6 +6150,14 @@ "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", "integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw=" }, + "node_modules/sqlstring": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/sqlstring/-/sqlstring-2.3.1.tgz", + "integrity": "sha1-R1OT/56RR5rqYtyvDKPRSYOn+0A=", + "engines": { + "node": ">= 0.6" + } + }, "node_modules/stable": { "version": "0.1.8", "resolved": "https://registry.npmjs.org/stable/-/stable-0.1.8.tgz", @@ -7993,6 +8150,11 @@ "resolved": "https://registry.npmjs.org/bcp47/-/bcp47-1.1.2.tgz", "integrity": "sha1-NUvjMH/9CEM6ePXh4glYRfifx/4=" }, + "bignumber.js": { + "version": "9.0.0", + "resolved": "https://registry.npmjs.org/bignumber.js/-/bignumber.js-9.0.0.tgz", + "integrity": "sha512-t/OYhhJ2SD+YGBQcjY8GzzDHEk9f3nerxjtfa6tlMXfe7frs/WozhvCNoGvpM0P3bNf3Gq5ZRMlGr5f3r4/N8A==" + }, "binary-extensions": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.2.0.tgz", @@ -9870,6 +10032,103 @@ "uuid": "^8.3.0" } }, + "loopback-connector-mysql": { + "version": "5.4.4", + "resolved": "https://registry.npmjs.org/loopback-connector-mysql/-/loopback-connector-mysql-5.4.4.tgz", + "integrity": "sha512-6y+eXbP1YJWfEqBsuaNoK6zGSTurN1h0X67qpRj/pf0U9qWphjuJGYbU4Z8DnutY3J1OTeSycQgvt1qLJNHj/w==", + "requires": { + "async": "^2.6.1", + "debug": "^3.1.0", + "lodash": "^4.17.11", + "loopback-connector": "^4.0.0", + "mysql": "^2.11.1", + "strong-globalize": "^5.0.5" + }, + "dependencies": { + "async": { + "version": "2.6.3", + "resolved": "https://registry.npmjs.org/async/-/async-2.6.3.tgz", + "integrity": "sha512-zflvls11DCy+dQWzTW2dzuilv8Z5X/pjfmZOWba6TNIVDm+2UDaJmXSOXlasHKfNBs8oo3M0aT50fDEWfKZjXg==", + "requires": { + "lodash": "^4.17.14" + } + }, + "debug": { + "version": "3.2.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", + "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", + "requires": { + "ms": "^2.1.1" + } + }, + "loopback-connector": { + "version": "4.11.1", + "resolved": "https://registry.npmjs.org/loopback-connector/-/loopback-connector-4.11.1.tgz", + "integrity": "sha512-EA31zur3xIhP4UW+P2rWEcSbqpk4jPddpTBZSSw8KCszM7T0/Pe4HvEmG0MndAWJctRPtrwKDEu/8rWuMDLf+A==", + "requires": { + "async": "^3.2.0", + "bluebird": "^3.7.2", + "debug": "^4.1.1", + "msgpack5": "^4.2.0", + "strong-globalize": "^5.1.0", + "uuid": "^7.0.3" + }, + "dependencies": { + "async": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/async/-/async-3.2.2.tgz", + "integrity": "sha512-H0E+qZaDEfx/FY4t7iLRv1W2fFI6+pyCeTw1uN20AQPiwqwM6ojPxHxdLv4z8hi2DtnW9BOckSspLucW7pIE5g==" + }, + "debug": { + "version": "4.3.2", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.2.tgz", + "integrity": "sha512-mOp8wKcvj7XxC78zLgw/ZA+6TSgkoE2C/ienthhRD298T7UNwAg9diBpLRxC0mOezLl4B0xV7M0cCO6P/O0Xhw==", + "requires": { + "ms": "2.1.2" + } + } + } + }, + "mkdirp": { + "version": "0.5.5", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.5.tgz", + "integrity": "sha512-NKmAlESf6jMGym1++R0Ra7wvhV+wFW63FaSOFPwRahvea0gMUcGUhVeAg/0BC0wiv9ih5NYPB1Wn1UEI1/L+xQ==", + "requires": { + "minimist": "^1.2.5" + } + }, + "strong-globalize": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/strong-globalize/-/strong-globalize-5.1.0.tgz", + "integrity": "sha512-9cooAb6kNMDFmTDybkkch1x7b+LuzZNva8oIr+MxXnvx9jcvw4/4DTSXPc53mG68G0Q9YOTYZkhDkWe/DiJ1Qg==", + "requires": { + "accept-language": "^3.0.18", + "debug": "^4.1.1", + "globalize": "^1.5.0", + "lodash": "^4.17.15", + "md5": "^2.2.1", + "mkdirp": "^0.5.5", + "os-locale": "^5.0.0", + "yamljs": "^0.3.0" + }, + "dependencies": { + "debug": { + "version": "4.3.2", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.2.tgz", + "integrity": "sha512-mOp8wKcvj7XxC78zLgw/ZA+6TSgkoE2C/ienthhRD298T7UNwAg9diBpLRxC0mOezLl4B0xV7M0cCO6P/O0Xhw==", + "requires": { + "ms": "2.1.2" + } + } + } + }, + "uuid": { + "version": "7.0.3", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-7.0.3.tgz", + "integrity": "sha512-DPSke0pXhTZgoF/d+WSt2QaKMCFSfx7QegxEWT+JOuHF5aWrKEn0G+ztjuJg/gG8/ItK+rbPCD/yNv8yyih6Cg==" + } + } + }, "loopback-datasource-juggler": { "version": "4.26.0", "resolved": "https://registry.npmjs.org/loopback-datasource-juggler/-/loopback-datasource-juggler-4.26.0.tgz", @@ -10028,8 +10287,7 @@ "minimist": { "version": "1.2.5", "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.5.tgz", - "integrity": "sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw==", - "dev": true + "integrity": "sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw==" }, "mkdirp": { "version": "1.0.4", @@ -10133,6 +10391,24 @@ "safe-buffer": "^5.1.2" } }, + "mysql": { + "version": "2.18.1", + "resolved": "https://registry.npmjs.org/mysql/-/mysql-2.18.1.tgz", + "integrity": "sha512-Bca+gk2YWmqp2Uf6k5NFEurwY/0td0cpebAucFpY/3jhrwrVGuxU2uQFCHjU19SJfje0yQvi+rVWdq78hR5lig==", + "requires": { + "bignumber.js": "9.0.0", + "readable-stream": "2.3.7", + "safe-buffer": "5.1.2", + "sqlstring": "2.3.1" + }, + "dependencies": { + "safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" + } + } + }, "nanoid": { "version": "2.1.11", "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-2.1.11.tgz", @@ -11336,6 +11612,11 @@ "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", "integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw=" }, + "sqlstring": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/sqlstring/-/sqlstring-2.3.1.tgz", + "integrity": "sha1-R1OT/56RR5rqYtyvDKPRSYOn+0A=" + }, "stable": { "version": "0.1.8", "resolved": "https://registry.npmjs.org/stable/-/stable-0.1.8.tgz", diff --git a/backend/package.json b/backend/package.json index 2e8252a..e8cee38 100644 --- a/backend/package.json +++ b/backend/package.json @@ -56,6 +56,7 @@ "@loopback/rest": "^10.1.0", "@loopback/rest-explorer": "^3.3.4", "@loopback/service-proxy": "^3.2.4", + "loopback-connector-mysql": "^5.4.4", "tslib": "^2.0.0" }, "devDependencies": { diff --git a/backend/src/controllers/index.ts b/backend/src/controllers/index.ts index e4c8eb5..88f9fd6 100644 --- a/backend/src/controllers/index.ts +++ b/backend/src/controllers/index.ts @@ -1 +1,2 @@ export * from './ping.controller'; +export * from './user.controller'; diff --git a/backend/src/controllers/user.controller.ts b/backend/src/controllers/user.controller.ts new file mode 100644 index 0000000..9b4bbea --- /dev/null +++ b/backend/src/controllers/user.controller.ts @@ -0,0 +1,150 @@ +import { + Count, + CountSchema, + Filter, + FilterExcludingWhere, + repository, + Where, +} from '@loopback/repository'; +import { + post, + param, + get, + getModelSchemaRef, + patch, + put, + del, + requestBody, + response, +} from '@loopback/rest'; +import {User} from '../models'; +import {UserRepository} from '../repositories'; + +export class UserController { + constructor( + @repository(UserRepository) + public userRepository : UserRepository, + ) {} + + @post('/users') + @response(200, { + description: 'User model instance', + content: {'application/json': {schema: getModelSchemaRef(User)}}, + }) + async create( + @requestBody({ + content: { + 'application/json': { + schema: getModelSchemaRef(User, { + title: 'NewUser', + exclude: ['id'], + }), + }, + }, + }) + user: Omit, + ): Promise { + return this.userRepository.create(user); + } + + @get('/users/count') + @response(200, { + description: 'User model count', + content: {'application/json': {schema: CountSchema}}, + }) + async count( + @param.where(User) where?: Where, + ): Promise { + return this.userRepository.count(where); + } + + @get('/users') + @response(200, { + description: 'Array of User model instances', + content: { + 'application/json': { + schema: { + type: 'array', + items: getModelSchemaRef(User, {includeRelations: true}), + }, + }, + }, + }) + async find( + @param.filter(User) filter?: Filter, + ): Promise { + return this.userRepository.find(filter); + } + + @patch('/users') + @response(200, { + description: 'User PATCH success count', + content: {'application/json': {schema: CountSchema}}, + }) + async updateAll( + @requestBody({ + content: { + 'application/json': { + schema: getModelSchemaRef(User, {partial: true}), + }, + }, + }) + user: User, + @param.where(User) where?: Where, + ): Promise { + return this.userRepository.updateAll(user, where); + } + + @get('/users/{id}') + @response(200, { + description: 'User model instance', + content: { + 'application/json': { + schema: getModelSchemaRef(User, {includeRelations: true}), + }, + }, + }) + async findById( + @param.path.number('id') id: number, + @param.filter(User, {exclude: 'where'}) filter?: FilterExcludingWhere + ): Promise { + return this.userRepository.findById(id, filter); + } + + @patch('/users/{id}') + @response(204, { + description: 'User PATCH success', + }) + async updateById( + @param.path.number('id') id: number, + @requestBody({ + content: { + 'application/json': { + schema: getModelSchemaRef(User, {partial: true}), + }, + }, + }) + user: User, + ): Promise { + await this.userRepository.updateById(id, user); + } + + @put('/users/{id}') + @response(204, { + description: 'User PUT success', + }) + async replaceById( + @param.path.number('id') id: number, + @requestBody() user: User, + ): Promise { + await this.userRepository.replaceById(id, user); + } + + @del('/users/{id}') + @response(204, { + description: 'User DELETE success', + }) + async deleteById(@param.path.number('id') id: number): Promise { + await this.userRepository.deleteById(id); + } +} diff --git a/backend/src/datasources/database.datasource.ts b/backend/src/datasources/database.datasource.ts new file mode 100644 index 0000000..c691450 --- /dev/null +++ b/backend/src/datasources/database.datasource.ts @@ -0,0 +1,31 @@ +import {inject, lifeCycleObserver, LifeCycleObserver} from '@loopback/core'; +import {juggler} from '@loopback/repository'; + +const config = { + name: 'database', + connector: 'mysql', + url: process.env.DATABASE_URL, + host: '', + port: 0, + user: '', + password: '', + database: '' +}; + +// Observe application's life cycle to disconnect the datasource when +// application is stopped. This allows the application to be shut down +// gracefully. The `stop()` method is inherited from `juggler.DataSource`. +// Learn more at https://loopback.io/doc/en/lb4/Life-cycle.html +@lifeCycleObserver('datasource') +export class DatabaseDataSource extends juggler.DataSource + implements LifeCycleObserver { + static dataSourceName = 'database'; + static readonly defaultConfig = config; + + constructor( + @inject('datasources.config.database', {optional: true}) + dsConfig: object = config, + ) { + super(dsConfig); + } +} diff --git a/backend/src/datasources/index.ts b/backend/src/datasources/index.ts new file mode 100644 index 0000000..0962c7c --- /dev/null +++ b/backend/src/datasources/index.ts @@ -0,0 +1 @@ +export * from './database.datasource'; diff --git a/backend/src/models/index.ts b/backend/src/models/index.ts new file mode 100644 index 0000000..5a670ce --- /dev/null +++ b/backend/src/models/index.ts @@ -0,0 +1 @@ +export * from './user.model'; diff --git a/backend/src/models/user.model.ts b/backend/src/models/user.model.ts new file mode 100644 index 0000000..012d4dc --- /dev/null +++ b/backend/src/models/user.model.ts @@ -0,0 +1,46 @@ +import {Entity, model, property} from '@loopback/repository'; + +@model() +export class User extends Entity { + @property({ + type: 'number', + id: true, + generated: true, + }) + id?: number; + + @property({ + type: 'string', + required: true, + }) + email: string; + + @property({ + type: 'string', + required: true, + }) + name: string; + + @property({ + type: 'string', + required: true, + }) + password: string; + + @property({ + type: 'object', + required: true, + }) + role: object; + + + constructor(data?: Partial) { + super(data); + } +} + +export interface UserRelations { + // describe navigational properties here +} + +export type UserWithRelations = User & UserRelations; diff --git a/backend/src/repositories/index.ts b/backend/src/repositories/index.ts new file mode 100644 index 0000000..9fb5d34 --- /dev/null +++ b/backend/src/repositories/index.ts @@ -0,0 +1 @@ +export * from './user.repository'; diff --git a/backend/src/repositories/user.repository.ts b/backend/src/repositories/user.repository.ts new file mode 100644 index 0000000..8c9ce2f --- /dev/null +++ b/backend/src/repositories/user.repository.ts @@ -0,0 +1,16 @@ +import {inject} from '@loopback/core'; +import {DefaultCrudRepository} from '@loopback/repository'; +import {DatabaseDataSource} from '../datasources'; +import {User, UserRelations} from '../models'; + +export class UserRepository extends DefaultCrudRepository< + User, + typeof User.prototype.id, + UserRelations +> { + constructor( + @inject('datasources.database') dataSource: DatabaseDataSource, + ) { + super(User, dataSource); + } +} diff --git a/docker-compose.yml b/docker-compose.yml index 4707950..2df9786 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -15,6 +15,7 @@ services: - ./backend:/home/node/app environment: - COMMAND=run + - DATABASE_URL=${CLEARDB_DATABASE_URL} networks: default: