diff --git a/apps/teloalapi/config/custom-environment-variables.js b/apps/teloalapi/config/custom-environment-variables.js index 528511c..b8acb41 100644 --- a/apps/teloalapi/config/custom-environment-variables.js +++ b/apps/teloalapi/config/custom-environment-variables.js @@ -3,4 +3,10 @@ module.exports = { al: { token: "AL_TOKEN", }, + mongo: { + host: "MONGO_HOST", + user: "MONGO_USER", + password: "MONGO_PASSWORD", + database: "MONGO_DATABASE", + }, }; diff --git a/apps/teloalapi/config/default.js b/apps/teloalapi/config/default.js index 36ae1d7..21c62b7 100644 --- a/apps/teloalapi/config/default.js +++ b/apps/teloalapi/config/default.js @@ -25,4 +25,8 @@ module.exports = { al: { url: urlDefault(process.env.AL_URL, "https://adventure.land"), }, + mongo: { + port: parseIntDefault(process.env.MONGO_PORT, 10, 27027), + database: "teloal", + }, }; diff --git a/apps/teloalapi/config/development.js b/apps/teloalapi/config/development.js index a91fa4d..2bf4b68 100644 --- a/apps/teloalapi/config/development.js +++ b/apps/teloalapi/config/development.js @@ -1,3 +1,8 @@ module.exports = { host: "127.0.0.1", + mongo: { + host: "localhost", + user: "teloal", + password: "teloal", + }, }; diff --git a/apps/teloalapi/config/production.js b/apps/teloalapi/config/production.js index cd9974f..20f69e6 100644 --- a/apps/teloalapi/config/production.js +++ b/apps/teloalapi/config/production.js @@ -1,5 +1,6 @@ const boolVal = (val, def) => (val ? val === "true" : def); +// `undefined` means the default value is ignored and an environment variable is required module.exports = { host: undefined, }; diff --git a/apps/teloalapi/src/controllers/adventure-land.controller.ts b/apps/teloalapi/src/controllers/adventure-land.controller.ts index c18b544..626d520 100644 --- a/apps/teloalapi/src/controllers/adventure-land.controller.ts +++ b/apps/teloalapi/src/controllers/adventure-land.controller.ts @@ -6,12 +6,17 @@ import { cache } from "@teloal/lb4-cache"; import { parseCharacters, AlCharacter } from "@teloal/parse-character"; import { AlMerchants } from "../types/AlMerchants"; import { AlMerchant } from "../models"; +import { repository } from "@loopback/repository"; +import { AlCharacterRepository } from "../repositories"; @api({ basePath: "/v1/al" }) export class AdventureLandController { @inject("services.AdventureLand") protected alService: AdventureLandService; + @repository(AlCharacterRepository) + protected alCharRepo: AlCharacterRepository; + @cache({ ttl: 5 }) @get("/character/{name}") @response(200, { @@ -35,6 +40,10 @@ export class AdventureLandController { throw new HttpErrors.NotFound(`The character "${name}" doesn't exist.`); } + const res = await this.alCharRepo.upsert(char); + + console.log(res); + return char; } diff --git a/apps/teloalapi/src/datasources/index.ts b/apps/teloalapi/src/datasources/index.ts index d80064c..af1b319 100644 --- a/apps/teloalapi/src/datasources/index.ts +++ b/apps/teloalapi/src/datasources/index.ts @@ -1 +1,2 @@ -export * from './adventure-land.datasource'; +export * from "./adventure-land.datasource"; +export * from "./mongo.datasource"; diff --git a/apps/teloalapi/src/datasources/mongo.datasource.ts b/apps/teloalapi/src/datasources/mongo.datasource.ts new file mode 100644 index 0000000..c63a6c9 --- /dev/null +++ b/apps/teloalapi/src/datasources/mongo.datasource.ts @@ -0,0 +1,31 @@ +import { inject, lifeCycleObserver, LifeCycleObserver } from "@loopback/core"; +import { juggler } from "@loopback/repository"; +import config from "config"; + +const connectorConfig = { + name: "mongo", + connector: "mongodb", + host: config.mongo.host, + port: config.mongo.port, + user: config.mongo.user, + password: config.mongo.password, + database: config.mongo.database, + useNewUrlParser: true, +}; + +// 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 MongoDataSource extends juggler.DataSource implements LifeCycleObserver { + static dataSourceName = "mongo"; + static readonly defaultConfig = connectorConfig; + + constructor( + @inject("datasources.config.mongo", { optional: true }) + dsConfig: object = connectorConfig, + ) { + super(dsConfig); + } +} diff --git a/apps/teloalapi/src/repositories/al-character.repository.ts b/apps/teloalapi/src/repositories/al-character.repository.ts new file mode 100644 index 0000000..575edc3 --- /dev/null +++ b/apps/teloalapi/src/repositories/al-character.repository.ts @@ -0,0 +1,91 @@ +import { inject } from "@loopback/core"; +import { + Count, + DefaultCrudRepository, + Entity, + Options, + Where, + model, + property, +} from "@loopback/repository"; +import { MongoDataSource } from "../datasources"; +import { AlCharacter } from "@teloal/parse-character"; + +type Timestamps = { + createdAt?: Date; + updatedAt?: Date; +}; + +type GConstructor = new (...args: any[]) => T; + +function extendClassWithTimestamps>(Base: T) { + @model({ + name: "AlCharacter", + }) + class Extended extends Base { + constructor(...args: any[]) { + super(...args); + } + + @property({ + type: "date", + }) + createdAt?: Date; + + @property({ + type: "date", + }) + updatedAt?: Date; + } + + return Extended; +} + +type TimestampedAlCharacter = AlCharacter & Timestamps; + +export class AlCharacterRepository extends DefaultCrudRepository< + TimestampedAlCharacter, + typeof AlCharacter.prototype.name +> { + constructor(@inject("datasources.mongo") dataSource: MongoDataSource) { + super(extendClassWithTimestamps(AlCharacter), dataSource); + } + + async create(entity: TimestampedAlCharacter, options?: Options): Promise { + entity.createdAt = new Date(); + entity.updatedAt = new Date(); + return super.create(entity, options); + } + + async update(data: TimestampedAlCharacter, options?: Options): Promise { + data.updatedAt = new Date(); + return super.update(data, options); + } + + async updateAll( + data: TimestampedAlCharacter, + where?: Where, + options?: Options, + ): Promise { + data.updatedAt = new Date(); + return super.updateAll(data, where, options); + } + + async replaceById(id: string, data: TimestampedAlCharacter, options?: Options): Promise { + data.updatedAt = new Date(); + return super.replaceById(id, data, options); + } + + async updateById(id: string, data: TimestampedAlCharacter, options?: Options): Promise { + data.updatedAt = new Date(); + return super.updateById(id, data, options); + } + + async upsert(char: AlCharacter) { + if (await this.exists(char.name)) { + return await this.updateById(char.name, char); + } + + return await this.create(char); + } +} diff --git a/apps/teloalapi/src/repositories/index.ts b/apps/teloalapi/src/repositories/index.ts new file mode 100644 index 0000000..6c7ef9f --- /dev/null +++ b/apps/teloalapi/src/repositories/index.ts @@ -0,0 +1 @@ +export * from "./al-character.repository"; diff --git a/apps/teloalapi/src/types/config.d.ts b/apps/teloalapi/src/types/config.d.ts index 0976da5..beec0a3 100644 --- a/apps/teloalapi/src/types/config.d.ts +++ b/apps/teloalapi/src/types/config.d.ts @@ -7,4 +7,12 @@ declare module "config" { url: string; token: string | undefined; }; + + export const mongo: { + host: string; + port: number; + user: string; + password: string; + database: string; + }; } diff --git a/docker-compose.yml b/docker-compose.yml new file mode 100644 index 0000000..fba2238 --- /dev/null +++ b/docker-compose.yml @@ -0,0 +1,32 @@ +# This docker-compose is meant for local development. +# It should not be used in production. + +version: "3" +services: + teloal-mongo: + image: mongo + container_name: teloal-mongo + restart: unless-stopped + environment: + MONGO_INITDB_ROOT_USERNAME: mongo-user + MONGO_INITDB_ROOT_PASSWORD: mongo-password + command: --port 27027 + ports: + - "27027:27027" + volumes: + - ./scripts/init-mongo.js:/docker-entrypoint-initdb.d/mongo-init.js:ro + + teloal-mongo-express: + image: mongo-express + container_name: teloal-mongo-express + restart: unless-stopped + environment: + ME_CONFIG_BASICAUTH_USERNAME: "" + ME_CONFIG_MONGODB_ADMINUSERNAME: mongo-user + ME_CONFIG_MONGODB_ADMINPASSWORD: mongo-password + ME_CONFIG_SITE_COOKIESECRET: teloal-cookie-secret + ME_CONFIG_SITE_SESSIONSECRET: teloal-session-secret + ME_CONFIG_MONGODB_URL: mongodb://mongo-user:mongo-password@teloal-mongo:27027/ + ME_CONFIG_OPTIONS_EDITORTHEME: dracula + ports: + - "127.0.0.1:7937:8081" diff --git a/libs/parse-character/src/lib/models/al-character.model.ts b/libs/parse-character/src/lib/models/al-character.model.ts index 2f30b2d..aa82480 100644 --- a/libs/parse-character/src/lib/models/al-character.model.ts +++ b/libs/parse-character/src/lib/models/al-character.model.ts @@ -1,4 +1,4 @@ -import { Model, model, property } from "@loopback/repository"; +import { Entity, Model, model, property } from "@loopback/repository"; import type { ClassKey, SlotType } from "typed-adventureland"; import { ALCharacterCleanSlot, AlCharacterItem } from "./al-character-item.model"; @@ -72,8 +72,9 @@ export class AlCharacterItemSlots extends Model { required: ["name", "level", "ctype", "slots"], }, }) -export class AlCharacter extends Model implements ALCharacterDefinition { +export class AlCharacter extends Entity implements ALCharacterDefinition { @property({ + id: true, description: "Name of the character.", }) name: string; diff --git a/package-lock.json b/package-lock.json index a6c546f..0fa67ab 100644 --- a/package-lock.json +++ b/package-lock.json @@ -11,9 +11,10 @@ "dependencies": { "@loopback/boot": "^6.1.2", "@loopback/core": "^5.1.2", + "@loopback/cron": "^0.11.3", "@loopback/health": "^0.13.2", "@loopback/metrics": "^0.13.2", - "@loopback/repository": "^6.1.2", + "@loopback/repository": "^6.1.3", "@loopback/rest": "^13.1.2", "@loopback/rest-explorer": "^6.1.2", "@loopback/service-proxy": "^6.1.2", @@ -22,6 +23,7 @@ "config": "^3.3.9", "dotenv": "^16.3.1", "lodash": "^4.17.21", + "loopback-connector-mongodb": "^5.6.0", "loopback-connector-rest": "^3.7.0", "tslib": "^2.3.0", "yargs": "14.2.2" @@ -3049,6 +3051,24 @@ "node": "16 || 18 || 20" } }, + "node_modules/@loopback/cron": { + "version": "0.11.3", + "resolved": "https://registry.npmjs.org/@loopback/cron/-/cron-0.11.3.tgz", + "integrity": "sha512-G7JvwjHAllY/W/c/ZrnPZvVAMX90Bi1hUfM+E082EOo1/aHt6tmyZmvdWiZtHbhOEVT8E/FAx89drl9cBuLsyw==", + "dependencies": { + "@types/cron": "^2.0.1", + "@types/debug": "^4.1.8", + "cron": "^2.4.3", + "debug": "^4.3.4", + "tslib": "^2.6.2" + }, + "engines": { + "node": "16 || 18 || 20" + }, + "peerDependencies": { + "@loopback/core": "^5.0.0" + } + }, "node_modules/@loopback/eslint-config": { "version": "14.0.4", "resolved": "https://registry.npmjs.org/@loopback/eslint-config/-/eslint-config-14.0.4.tgz", @@ -6476,6 +6496,15 @@ "@types/node": "*" } }, + "node_modules/@types/cron": { + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/@types/cron/-/cron-2.4.0.tgz", + "integrity": "sha512-5bBaAkqvSFBX8JMi/xCofNzG5E594TNsApMz68dLd/sQYz/HGQqgcxGHTRjOvD4G3Y+YF1Oo3S7QdCvKt1KAJQ==", + "deprecated": "This is a stub types definition. cron provides its own type definitions, so you do not need this installed.", + "dependencies": { + "cron": "*" + } + }, "node_modules/@types/debug": { "version": "4.1.8", "resolved": "https://registry.npmjs.org/@types/debug/-/debug-4.1.8.tgz", @@ -6595,6 +6624,11 @@ "integrity": "sha512-trNJ/vtMZYMLhfN45uLq4ShQSw0/S7xCTLLVM+WM1rmFpba/VS42jVUgaO3w/NOLiWR/09lnYk0yMaA/atdIsg==", "dev": true }, + "node_modules/@types/luxon": { + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/@types/luxon/-/luxon-3.3.2.tgz", + "integrity": "sha512-l5cpE57br4BIjK+9BSkFBOsWtwv6J9bJpC7gdXIzZyI0vuKvNTk0wZZrkQxMGsUAuGW9+WMNWF2IJMD7br2yeQ==" + }, "node_modules/@types/mime": { "version": "1.3.2", "resolved": "https://registry.npmjs.org/@types/mime/-/mime-1.3.2.tgz", @@ -8081,6 +8115,14 @@ "node-int64": "^0.4.0" } }, + "node_modules/bson": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/bson/-/bson-1.1.6.tgz", + "integrity": "sha512-EvVNVeGo4tHxwi8L6bPj3y3itEvStdwvvlojVxxbyYfoaxJ6keLgrTuKdyfEAszFK+H3olzBuafE0yoh0D1gdg==", + "engines": { + "node": ">=0.6.19" + } + }, "node_modules/buffer": { "version": "5.7.1", "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.7.1.tgz", @@ -9027,6 +9069,15 @@ "integrity": "sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ==", "dev": true }, + "node_modules/cron": { + "version": "2.4.3", + "resolved": "https://registry.npmjs.org/cron/-/cron-2.4.3.tgz", + "integrity": "sha512-YBvExkQYF7w0PxyeFLRyr817YVDhGxaCi5/uRRMqa4aWD3IFKRd+uNbpW1VWMdqQy8PZ7CElc+accXJcauPKzQ==", + "dependencies": { + "@types/luxon": "~3.3.0", + "luxon": "~3.3.0" + } + }, "node_modules/cross-spawn": { "version": "7.0.3", "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", @@ -9238,6 +9289,14 @@ "integrity": "sha512-bd2L678uiWATM6m5Z1VzNCErI3jiGzt6HGY8OVICs40JQq/HALfbyNJmp0UDakEY4pMMaN0Ly5om/B1VI/+xfQ==", "dev": true }, + "node_modules/denque": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/denque/-/denque-1.5.1.tgz", + "integrity": "sha512-XwE+iZ4D6ZUB7mfYRMb5wByE8L74HCn30FBN7sWnXksWc1LO1bPDl67pBR9o/kC4z/xSNAwkMYcGgqDV3BE3Hw==", + "engines": { + "node": ">=0.10" + } + }, "node_modules/depd": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz", @@ -13172,6 +13231,51 @@ "node": ">=10" } }, + "node_modules/loopback-connector-mongodb": { + "version": "5.6.0", + "resolved": "https://registry.npmjs.org/loopback-connector-mongodb/-/loopback-connector-mongodb-5.6.0.tgz", + "integrity": "sha512-mhuOUknJkmZhr9BhJCUz3ggRuFKNZuU1tkZrwqUxwosAUPWeZMIdrj7XP9Vr6OCP6+RfZoSRMITj3keAOPTKrg==", + "dependencies": { + "async": "^3.1.0", + "bson": "^1.0.6", + "debug": "^4.1.0", + "loopback-connector": "^5.0.0", + "mongodb": "^3.2.4", + "strong-globalize": "^6.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/loopback-connector-mongodb/node_modules/mkdirp": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz", + "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==", + "bin": { + "mkdirp": "bin/cmd.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/loopback-connector-mongodb/node_modules/strong-globalize": { + "version": "6.0.6", + "resolved": "https://registry.npmjs.org/strong-globalize/-/strong-globalize-6.0.6.tgz", + "integrity": "sha512-+mN0wTXBg9rLiKBk7jsyfXFWsg08q160XQcmJ3gNxSQ8wrC668dzR8JUp/wcK3NZ2eQ5h5tvc8O6Y+FC0D61lw==", + "dependencies": { + "accept-language": "^3.0.18", + "debug": "^4.2.0", + "globalize": "^1.6.0", + "lodash": "^4.17.20", + "md5": "^2.3.0", + "mkdirp": "^1.0.4", + "os-locale": "^5.0.0", + "yamljs": "^0.3.0" + }, + "engines": { + "node": ">=10" + } + }, "node_modules/loopback-connector-rest": { "version": "3.7.0", "resolved": "https://registry.npmjs.org/loopback-connector-rest/-/loopback-connector-rest-3.7.0.tgz", @@ -13317,6 +13421,14 @@ "yallist": "^3.0.2" } }, + "node_modules/luxon": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/luxon/-/luxon-3.3.0.tgz", + "integrity": "sha512-An0UCfG/rSiqtAIiBPO0Y9/zAnHUZxAMiCpTd5h2smgsj7GGmcenvrvww2cqNA8/4A5ZrD1gJpHN2mIHZQF+Mg==", + "engines": { + "node": ">=12" + } + }, "node_modules/make-dir": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-4.0.0.tgz", @@ -13584,6 +13696,12 @@ "integrity": "sha512-qjd88DrCxupx/kJD5yQgZdcYKZKSIGBVDIBE1/LTGcNm3d2Np/jxojkdePDdfnBHJc5W7vSMpbJ1aB7p/Py69A==", "dev": true }, + "node_modules/memory-pager": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/memory-pager/-/memory-pager-1.5.0.tgz", + "integrity": "sha512-ZS4Bp4r/Zoeq6+NLJpP+0Zzm0pR8whtGPf1XExKLJBAczGMnSi3It14OiNCStjQjM6NU1okjQGSxgEZN8eBYKg==", + "optional": true + }, "node_modules/merge-descriptors": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.1.tgz", @@ -14169,6 +14287,44 @@ "node": ">=10" } }, + "node_modules/mongodb": { + "version": "3.7.4", + "resolved": "https://registry.npmjs.org/mongodb/-/mongodb-3.7.4.tgz", + "integrity": "sha512-K5q8aBqEXMwWdVNh94UQTwZ6BejVbFhh1uB6c5FKtPE9eUMZPUO3sRZdgIEcHSrAWmxzpG/FeODDKL388sqRmw==", + "dependencies": { + "bl": "^2.2.1", + "bson": "^1.1.4", + "denque": "^1.4.1", + "optional-require": "^1.1.8", + "safe-buffer": "^5.1.2" + }, + "engines": { + "node": ">=4" + }, + "optionalDependencies": { + "saslprep": "^1.0.0" + }, + "peerDependenciesMeta": { + "aws4": { + "optional": true + }, + "bson-ext": { + "optional": true + }, + "kerberos": { + "optional": true + }, + "mongodb-client-encryption": { + "optional": true + }, + "mongodb-extjson": { + "optional": true + }, + "snappy": { + "optional": true + } + } + }, "node_modules/ms": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", @@ -15335,6 +15491,17 @@ "yaml": "^1.10.2" } }, + "node_modules/optional-require": { + "version": "1.1.8", + "resolved": "https://registry.npmjs.org/optional-require/-/optional-require-1.1.8.tgz", + "integrity": "sha512-jq83qaUb0wNg9Krv1c5OQ+58EK+vHde6aBPzLvPPqJm89UQWsvSuFy9X/OSNJnFeSOKo7btE0n8Nl2+nE+z5nA==", + "dependencies": { + "require-at": "^1.0.6" + }, + "engines": { + "node": ">=4" + } + }, "node_modules/optionator": { "version": "0.9.3", "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.3.tgz", @@ -16693,6 +16860,14 @@ "uuid": "bin/uuid" } }, + "node_modules/require-at": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/require-at/-/require-at-1.0.6.tgz", + "integrity": "sha512-7i1auJbMUrXEAZCOQ0VNJgmcT2VOKPRl2YGJwgpHpC9CE91Mv4/4UYIUm4chGJaI381ZDq1JUicFii64Hapd8g==", + "engines": { + "node": ">=4" + } + }, "node_modules/require-directory": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", @@ -16879,6 +17054,18 @@ "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==" }, + "node_modules/saslprep": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/saslprep/-/saslprep-1.0.3.tgz", + "integrity": "sha512-/MY/PEMbk2SuY5sScONwhUDsV2p77Znkb/q3nSVstq/yQzYJOH/Azh29p9oJLsl3LnQwSvZDKagDGBsBwSooag==", + "optional": true, + "dependencies": { + "sparse-bitfield": "^3.0.3" + }, + "engines": { + "node": ">=6" + } + }, "node_modules/scoped-regex": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/scoped-regex/-/scoped-regex-2.1.0.tgz", @@ -17315,6 +17502,15 @@ "source-map": "^0.6.0" } }, + "node_modules/sparse-bitfield": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/sparse-bitfield/-/sparse-bitfield-3.0.3.tgz", + "integrity": "sha512-kvzhi7vqKTfkh0PZU+2D2PIllw2ymqJKujUcyPMd9Y75Nv4nPbGJZXNhxsgdQab2BmlDct1YnfQCguEvHr7VsQ==", + "optional": true, + "dependencies": { + "memory-pager": "^1.0.2" + } + }, "node_modules/spawn-wrap": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/spawn-wrap/-/spawn-wrap-2.0.0.tgz", diff --git a/package.json b/package.json index d5ce323..053f96b 100644 --- a/package.json +++ b/package.json @@ -6,9 +6,10 @@ "dependencies": { "@loopback/boot": "^6.1.2", "@loopback/core": "^5.1.2", + "@loopback/cron": "^0.11.3", "@loopback/health": "^0.13.2", "@loopback/metrics": "^0.13.2", - "@loopback/repository": "^6.1.2", + "@loopback/repository": "^6.1.3", "@loopback/rest": "^13.1.2", "@loopback/rest-explorer": "^6.1.2", "@loopback/service-proxy": "^6.1.2", @@ -17,6 +18,7 @@ "config": "^3.3.9", "dotenv": "^16.3.1", "lodash": "^4.17.21", + "loopback-connector-mongodb": "^5.6.0", "loopback-connector-rest": "^3.7.0", "tslib": "^2.3.0", "yargs": "14.2.2" diff --git a/scripts/init-mongo.js b/scripts/init-mongo.js new file mode 100644 index 0000000..aec642b --- /dev/null +++ b/scripts/init-mongo.js @@ -0,0 +1,18 @@ +// This script will initialize a default database to then work with. +// Do not use in production. + +db = db.getSiblingDB("admin"); +db.auth(process.env.MONGO_INITDB_ROOT_USERNAME, process.env.MONGO_INITDB_ROOT_PASSWORD); + +db = db.getSiblingDB("teloal"); + +db.createUser({ + user: "teloal", + pwd: "teloal", + roles: [ + { + role: "readWrite", + db: "teloal", + }, + ], +});