diff --git a/api/.dockerignore b/api/.dockerignore
index 36f06c9..74a312d 100644
--- a/api/.dockerignore
+++ b/api/.dockerignore
@@ -145,7 +145,7 @@ bower_components
build/Release
# Dependency directories
-test-backend/api/node_modules/
+foodapp/api/node_modules/
jspm_packages/
# TypeScript v1 declaration files
diff --git a/api/assets/foodapp.drawio b/api/assets/foodapp.drawio
new file mode 100644
index 0000000..acf7958
--- /dev/null
+++ b/api/assets/foodapp.drawio
@@ -0,0 +1 @@
+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
\ No newline at end of file
diff --git a/api/package-lock.json b/api/package-lock.json
index 5ece812..be12f79 100644
--- a/api/package-lock.json
+++ b/api/package-lock.json
@@ -1303,6 +1303,19 @@
"xlsx": "^0.17.2"
}
},
+ "@recursyve/nestjs-rosetta-core": {
+ "version": "9.0.0-beta.19",
+ "resolved": "https://registry.npmjs.org/@recursyve/nestjs-rosetta-core/-/nestjs-rosetta-core-9.0.0-beta.19.tgz",
+ "integrity": "sha512-vHLzZg25aZAFXiskUaiI4KRZYLKjTL58tdP27VuvdKePg4/aL1DWfoTR4KV211szsQGgIDmaKBfL6MNevBXS7g==",
+ "requires": {
+ "accept-language-parser": "^1.5.0"
+ }
+ },
+ "@recursyve/nestjs-rosetta-sequelize": {
+ "version": "9.0.0-beta.19",
+ "resolved": "https://registry.npmjs.org/@recursyve/nestjs-rosetta-sequelize/-/nestjs-rosetta-sequelize-9.0.0-beta.19.tgz",
+ "integrity": "sha512-G5w+sPhDRC3A5YALR6RdAaqPhKTDBKJmhu6ITrfEhoJAHD6zpt8rODtcYAxUl5NeGHLoz3SzG42JrYf+DhOeZA=="
+ },
"@recursyve/nestjs-sequelize-utils": {
"version": "8.0.4",
"resolved": "https://registry.npmjs.org/@recursyve/nestjs-sequelize-utils/-/nestjs-sequelize-utils-8.0.4.tgz",
@@ -1968,6 +1981,11 @@
"integrity": "sha512-NuHqBY1PB/D8xU6s/thBgOAiAP7HOYDQ32+BFZILJ8ivkUkAHQnWfn6WhL79Owj1qmUnoN/YPhktdIoucipkAQ==",
"dev": true
},
+ "accept-language-parser": {
+ "version": "1.5.0",
+ "resolved": "https://registry.npmjs.org/accept-language-parser/-/accept-language-parser-1.5.0.tgz",
+ "integrity": "sha512-QhyTbMLYo0BBGg1aWbeMG4ekWtds/31BrEU+DONOg/7ax23vxpL03Pb7/zBmha2v7vdD3AyzZVWBVGEZxKOXWw=="
+ },
"accepts": {
"version": "1.3.8",
"resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.8.tgz",
@@ -2116,7 +2134,7 @@
"array-flatten": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz",
- "integrity": "sha512-PCVAQswWemu6UdxsDFFX/+gVeYqKAod3D3UVm91jHwynguOwAvYPhx8nNlM++NqRcK6CxxpUafjmhIdKiHibqg=="
+ "integrity": "sha1-ml9pkFGx5wczKPKgCJaLZOopVdI="
},
"array-union": {
"version": "2.1.0",
@@ -2489,12 +2507,20 @@
"integrity": "sha512-SQa1Ws6hUbfC98vKGxZH3KFY0Y1lm5Zm0SY8XX9zbK7FJCyVEac3ATW0RIpwzW+oOfmHE5PMPufDG9hCfoEOMw=="
},
"class-validator": {
- "version": "0.13.2",
- "resolved": "https://registry.npmjs.org/class-validator/-/class-validator-0.13.2.tgz",
- "integrity": "sha512-yBUcQy07FPlGzUjoLuUfIOXzgynnQPPruyK1Ge2B74k9ROwnle1E+NxLWnUv5OLU8hA/qL5leAE9XnXq3byaBw==",
+ "version": "0.14.0",
+ "resolved": "https://registry.npmjs.org/class-validator/-/class-validator-0.14.0.tgz",
+ "integrity": "sha512-ct3ltplN8I9fOwUd8GrP8UQixwff129BkEtuWDKL5W45cQuLd19xqmTLu5ge78YDm/fdje6FMt0hGOhl0lii3A==",
"requires": {
- "libphonenumber-js": "^1.9.43",
+ "@types/validator": "^13.7.10",
+ "libphonenumber-js": "^1.10.14",
"validator": "^13.7.0"
+ },
+ "dependencies": {
+ "@types/validator": {
+ "version": "13.7.12",
+ "resolved": "https://registry.npmjs.org/@types/validator/-/validator-13.7.12.tgz",
+ "integrity": "sha512-YVtyAPqpefU+Mm/qqnOANW6IkqKpCSrarcyV269C8MA8Ux0dbkEuQwM/4CjL47kVEM2LgBef/ETfkH+c6+moFA=="
+ }
}
},
"cli-cursor": {
@@ -2627,7 +2653,7 @@
"concat-map": {
"version": "0.0.1",
"resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz",
- "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s="
+ "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg=="
},
"concat-stream": {
"version": "1.6.2",
@@ -2682,7 +2708,7 @@
"cookie-signature": {
"version": "1.0.6",
"resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz",
- "integrity": "sha512-QADzlaHc8icV8I7vbaJXJwod9HWYp8uCqf1xa4OfNu1T7JVxQIrUgOWtHdNDtPiywmFbiS12VjotIXLrKM3orQ=="
+ "integrity": "sha1-4wOogrNCzD7oylE6eZmXNNqzriw="
},
"cookiejar": {
"version": "2.1.3",
@@ -2881,7 +2907,7 @@
"encodeurl": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz",
- "integrity": "sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w=="
+ "integrity": "sha1-rT/0yG7C0CkyL1oCw6mmBslbP1k="
},
"end-of-stream": {
"version": "1.4.4",
@@ -2926,7 +2952,7 @@
"escape-html": {
"version": "1.0.3",
"resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz",
- "integrity": "sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow=="
+ "integrity": "sha1-Aljq5NPQwJdN4cFpGI7wBR0dGYg="
},
"escape-string-regexp": {
"version": "1.0.5",
@@ -3148,7 +3174,7 @@
"etag": {
"version": "1.8.1",
"resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz",
- "integrity": "sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg=="
+ "integrity": "sha1-Qa4u62XvpiJorr/qg6x9eSmbCIc="
},
"events": {
"version": "3.3.0",
@@ -3471,7 +3497,7 @@
"fresh": {
"version": "0.5.2",
"resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz",
- "integrity": "sha512-zJ2mQYM18rEFOudeV4GShTGIQ7RbzA7ozbU9I/XBpm7kqgMywgmylMwXHxZJmkVoYkna9d2pVXVXPdYTP9ej8Q=="
+ "integrity": "sha1-PYyt2Q2XZWn6g1qx+OSyOhBWBac="
},
"fs-extra": {
"version": "10.1.0",
@@ -3493,7 +3519,7 @@
"fs.realpath": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz",
- "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8="
+ "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw=="
},
"fsevents": {
"version": "2.3.2",
@@ -3730,7 +3756,7 @@
"inflight": {
"version": "1.0.6",
"resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz",
- "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=",
+ "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==",
"requires": {
"once": "^1.3.0",
"wrappy": "1"
@@ -3856,7 +3882,7 @@
"is-property": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/is-property/-/is-property-1.0.2.tgz",
- "integrity": "sha1-V/4cTkhHTt1lsJkR8msc1Ald2oQ="
+ "integrity": "sha512-Ks/IoX00TtClbGQr4TWXemAnktAQvYB7HzcCxDGqEZU6oCmb2INHuOoKxbtR+HFkmYWBKv/dOZtGRiAjDhj92g=="
},
"is-stream": {
"version": "2.0.1",
@@ -4610,9 +4636,9 @@
}
},
"libphonenumber-js": {
- "version": "1.10.7",
- "resolved": "https://registry.npmjs.org/libphonenumber-js/-/libphonenumber-js-1.10.7.tgz",
- "integrity": "sha512-jZXLCCWMe1b/HXkjiLeYt2JsytZMcqH26jLFIdzFDFF0xvSUWrYKyvPlyPG+XJzEyKUFbcZxLdWGMwQsWaHDxQ=="
+ "version": "1.10.20",
+ "resolved": "https://registry.npmjs.org/libphonenumber-js/-/libphonenumber-js-1.10.20.tgz",
+ "integrity": "sha512-kQovlKNdLcVzerbTPmJ+Fx4R+7/pYXmPDIllHjg7IxL4X6MsMG7jaT5opfYrBok0uqkByVif//JUR8e11l/V7w=="
},
"lines-and-columns": {
"version": "1.2.4",
@@ -4725,7 +4751,7 @@
"media-typer": {
"version": "0.3.0",
"resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz",
- "integrity": "sha512-dq+qelQ9akHpcOl/gUVRTxVIOkAJ1wR3QAvb4RsVjS8oVoFjDGTc679wJYmUmknUF5HwMLOgb5O+a3KxfWapPQ=="
+ "integrity": "sha1-hxDXrwqmJvj/+hzgAWhUUmMlV0g="
},
"memfs": {
"version": "3.4.7",
@@ -4739,7 +4765,7 @@
"merge-descriptors": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.1.tgz",
- "integrity": "sha512-cCi6g3/Zr1iqQi6ySbseM1Xvooa98N0w31jzUYrXPX2xqObmFGHJ0tQ5u74H3mVh7wLouTseZyYIq39g8cNp1w=="
+ "integrity": "sha1-sAqqVW3YtEVoFQ7J0blT8/kMu2E="
},
"merge-stream": {
"version": "2.0.0",
@@ -4756,7 +4782,7 @@
"methods": {
"version": "1.1.2",
"resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz",
- "integrity": "sha512-iclAHeNqNm68zFtnZ0e+1L2yUIdvzNoauKU4WBA3VvH/vPFieF7qfRlwUZU+DA9P9bPXIS90ulxoUoCH23sV2w=="
+ "integrity": "sha1-VSmk1nZUE07cxSZmVoNbD4Ua/O4="
},
"micromatch": {
"version": "4.0.5",
@@ -4915,7 +4941,7 @@
"yallist": {
"version": "2.1.2",
"resolved": "https://registry.npmjs.org/yallist/-/yallist-2.1.2.tgz",
- "integrity": "sha1-HBH5IY8HYImkfdUS+TxmmaaoHVI="
+ "integrity": "sha512-ncTzHV7NvsQZkYe1DW7cbDLm0YpzHmZF5r/iyP3ZnQtMiJ+pjzisCiMNI+Sj+xQF5pXhSHxSB3uDbsBTzY/c2A=="
}
}
},
@@ -5032,7 +5058,7 @@
"once": {
"version": "1.4.0",
"resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz",
- "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=",
+ "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==",
"requires": {
"wrappy": "1"
}
@@ -5152,7 +5178,7 @@
"path-is-absolute": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz",
- "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18="
+ "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg=="
},
"path-key": {
"version": "3.1.1",
@@ -5288,7 +5314,7 @@
"pseudomap": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/pseudomap/-/pseudomap-1.0.2.tgz",
- "integrity": "sha1-8FKijacOYYkX7wqKw0wa5aaChrM="
+ "integrity": "sha512-b/YwNhb8lk1Zz2+bXXpS/LK9OisiZZ1SNsSLxN1x2OXVEhW2Ckr/7mWE5vrC1ZTiJlD9g19jWszTmJsB+oEpFQ=="
},
"pump": {
"version": "3.0.0",
@@ -5565,7 +5591,7 @@
"seq-queue": {
"version": "0.0.5",
"resolved": "https://registry.npmjs.org/seq-queue/-/seq-queue-0.0.5.tgz",
- "integrity": "sha1-1WgS4cAXpuTnw+Ojeh2m143TyT4="
+ "integrity": "sha512-hr3Wtp/GZIc/6DAGPDcV4/9WoZhjrkXsi5B/07QgX8tsdc6ilr7BFM6PM6rbdAX1kFSDYeZGLipIZZKyQP0O5Q=="
},
"sequelize": {
"version": "6.21.2",
@@ -6234,7 +6260,7 @@
"unpipe": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz",
- "integrity": "sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ=="
+ "integrity": "sha1-sr9O6FFKrmFltIF4KdIbLvSZBOw="
},
"update-browserslist-db": {
"version": "1.0.4",
@@ -6263,7 +6289,7 @@
"utils-merge": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz",
- "integrity": "sha512-pMZTvIkT1d+TFGvDOqodOclx0QWkkgi6Tdoa8gC8ffGAAqz9pzPTZWAybbsHHoED/ztMtkv/VoYTYyShUn81hA=="
+ "integrity": "sha1-n5VxD1CiZ5R7LMwSR0HBAoQn5xM="
},
"uuid": {
"version": "8.3.2",
@@ -6431,7 +6457,7 @@
"wrappy": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz",
- "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8="
+ "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ=="
},
"write-file-atomic": {
"version": "4.0.1",
diff --git a/api/package.json b/api/package.json
index f16148b..efb0cac 100644
--- a/api/package.json
+++ b/api/package.json
@@ -5,21 +5,21 @@
"author": "",
"license": "MIT",
"scripts": {
- "prebuild": "test-backend/api/node_modules/.bin/rimraf dist",
- "build": "test-backend/api/node_modules/.bin/nest build",
- "build:data-migrations": "test-backend/api/node_modules/.bin/rimraf data-migrations-dist && tsc --build tsconfig.migrations.json",
- "format": "test-backend/api/node_modules/.bin/prettier --write \\\"src/**/*.ts\\\" \\\"test/**/*.ts\\\"",
- "start": "test-backend/api/node_modules/.bin/nest start",
- "start:dev": "test-backend/api/node_modules/.bin/nest start --watch",
- "start:debug": "test-backend/api/node_modules/.bin/nest start --debug --watch",
+ "prebuild": "rimraf dist",
+ "build": "nest build",
+ "build:data-migrations": "rimraf data-migrations-dist && tsc --build tsconfig.migrations.json",
+ "format": "prettier --write \\\"src/**/*.ts\\\" \\\"test/**/*.ts\\\"",
+ "start": "nest start",
+ "start:dev": "nest start --watch",
+ "start:debug": "nest start --debug --watch",
"start:prod": "node dist/main",
- "lint": "test-backend/api/node_modules/.bin/eslint . --fix --ext .ts",
- "test": "test-backend/api/node_modules/.bin/jest",
- "test:watch": "test-backend/api/node_modules/.bin/jest --watch",
- "test:cov": "test-backend/api/node_modules/.bin/jest --coverage",
- "test:debug": "node --inspect-brk -r tsconfig-paths/register -r ts-node/register test-backend/api/node_modules/.bin/jest --runInBand",
- "test:e2e": "test-backend/api/node_modules/.bin/jest --config ./test/jest-e2e.json",
- "install": "(ls test-backend/pre-commit-setup.sh >> /dev/null 2>&1 && echo 'pre-commit setup' && chmod +x ../pre-commit-setup.sh && bash -c ../pre-commit-setup.sh) || echo 'pre-commit setup skipped'",
+ "lint": "eslint . --fix --ext .ts",
+ "test": "jest",
+ "test:watch": "jest --watch",
+ "test:cov": "jest --coverage",
+ "test:debug": "node --inspect-brk -r tsconfig-paths/register -r ts-node/register jest --runInBand",
+ "test:e2e": "jest --config ./test/jest-e2e.json",
+ "install": "(ls foodapp/pre-commit-setup.sh >> /dev/null 2>&1 && echo 'pre-commit setup' && chmod +x ../pre-commit-setup.sh && bash -c ../pre-commit-setup.sh) || echo 'pre-commit setup skipped'",
"data-migrations": "node data-migrations-dist/data-migrations/index.js"
},
"dependencies": {
@@ -34,8 +34,10 @@
"@recursyve/nestjs-config": "^8.0.1",
"@recursyve/nestjs-data-filter": "^8.4.4",
"@recursyve/nestjs-sequelize-utils": "^8.0.4",
+ "@recursyve/nestjs-rosetta-core": "^9.0.0-beta.19",
+ "@recursyve/nestjs-rosetta-sequelize": "^9.0.0-beta.19",
"class-transformer": "^0.5.1",
- "class-validator": "^0.13.2",
+ "class-validator": "^0.14.0",
"compression": "^1.7.4",
"dotenv": "^16.0.1",
"helmet": "^5.1.0",
diff --git a/api/src/modules/app.module.ts b/api/src/modules/app.module.ts
index fcea8a5..1237a35 100644
--- a/api/src/modules/app.module.ts
+++ b/api/src/modules/app.module.ts
@@ -3,8 +3,22 @@ import { GlobalConfigModule } from "./config/config.module";
import { RootModule } from "./root/root.module";
import { DatabaseModule } from "./database/database.module";
import { HealthModule } from "./health/health.module";
+import { NestjsRosettaModule } from "@recursyve/nestjs-rosetta-core";
+import { NestjsRosettaSequelizeModule, SequelizeTranslationObjectProcessor } from "@recursyve/nestjs-rosetta-sequelize";
+import { languagesValues, Languages } from "./translations/languages.enum";
@Module({
- imports: [GlobalConfigModule, RootModule, DatabaseModule, HealthModule]
+ imports: [
+ GlobalConfigModule,
+ RootModule,
+ DatabaseModule,
+ HealthModule,
+ NestjsRosettaModule.forRoot({
+ processors: [new SequelizeTranslationObjectProcessor()],
+ supportedLanguages: languagesValues,
+ fallbackLanguage: Languages.EN
+ }),
+ NestjsRosettaSequelizeModule
+ ]
})
export class ApplicationModule {}
diff --git a/api/src/modules/database/accounts/models/home.model.ts b/api/src/modules/database/accounts/models/home.model.ts
index a38f807..8d72e7f 100644
--- a/api/src/modules/database/accounts/models/home.model.ts
+++ b/api/src/modules/database/accounts/models/home.model.ts
@@ -1,8 +1,9 @@
import { DatabaseEntities } from "../../common/models/database-entities.model";
import { AllowNull, BelongsTo, Column, ForeignKey, Table } from "sequelize-typescript";
import { Accounts } from "./accounts.model";
-import { Translation } from "../../../translations/models/translation.model";
import { DataTypes } from "sequelize";
+import { TranslationObject } from "@recursyve/nestjs-rosetta-core";
+import { TranslationColumn } from "@recursyve/nestjs-rosetta-sequelize";
@Table
export class Homes extends DatabaseEntities {
@@ -12,7 +13,9 @@ export class Homes extends DatabaseEntities {
@AllowNull(false)
@Column(DataTypes.JSON)
- public name: Translation;
+ @TranslationColumn()
+ // TODO should be a string
+ public name: TranslationObject;
@BelongsTo(() => Accounts)
public ownerAccount: Accounts;
diff --git a/api/src/modules/database/grocery_products/models/grocery-products.model.ts b/api/src/modules/database/grocery_products/models/grocery-products.model.ts
index 7add403..9b040ee 100644
--- a/api/src/modules/database/grocery_products/models/grocery-products.model.ts
+++ b/api/src/modules/database/grocery_products/models/grocery-products.model.ts
@@ -1,8 +1,9 @@
import { DatabaseEntities } from "../../common/models/database-entities.model";
import { AllowNull, BelongsTo, Column, ForeignKey, Table } from "sequelize-typescript";
import { Ingredients } from "../../ingredients/models/ingredients.model";
-import { Translation } from "../../../translations/models/translation.model";
import { DataTypes } from "sequelize";
+import { TranslationColumn } from "@recursyve/nestjs-rosetta-sequelize";
+import { TranslationObject } from "@recursyve/nestjs-rosetta-core";
@Table
export class GroceryProducts extends DatabaseEntities {
@@ -16,10 +17,12 @@ export class GroceryProducts extends DatabaseEntities {
@AllowNull(false)
@Column(DataTypes.JSON)
- public name: Translation;
+ @TranslationColumn()
+ public name: TranslationObject;
@Column(DataTypes.JSON)
- public description: Translation;
+ @TranslationColumn()
+ public description: TranslationObject;
@Column
public skuCode: string;
diff --git a/api/src/modules/database/ingredients/models/ingredient-categories.model.ts b/api/src/modules/database/ingredients/models/ingredient-categories.model.ts
index 7e54ef2..c83978f 100644
--- a/api/src/modules/database/ingredients/models/ingredient-categories.model.ts
+++ b/api/src/modules/database/ingredients/models/ingredient-categories.model.ts
@@ -1,13 +1,16 @@
import { DatabaseEntities } from "../../common/models/database-entities.model";
import { Column, Table } from "sequelize-typescript";
-import { Translation } from "../../../translations/models/translation.model";
import { DataTypes } from "sequelize";
+import { TranslationObject } from "@recursyve/nestjs-rosetta-core";
+import { TranslationColumn } from "@recursyve/nestjs-rosetta-sequelize";
@Table
export class IngredientCategories extends DatabaseEntities {
- @Column(DataTypes.JSON)
- public name: Translation;
+ @Column(DataTypes.JSON)
+ @TranslationColumn()
+ public name: TranslationObject;
- @Column(DataTypes.JSON)
- public description: Translation;
+ @Column(DataTypes.JSON)
+ @TranslationColumn()
+ public description: TranslationObject;
}
diff --git a/api/src/modules/database/ingredients/models/ingredients.model.ts b/api/src/modules/database/ingredients/models/ingredients.model.ts
index d849dd6..1253109 100644
--- a/api/src/modules/database/ingredients/models/ingredients.model.ts
+++ b/api/src/modules/database/ingredients/models/ingredients.model.ts
@@ -1,24 +1,27 @@
import { DatabaseEntities } from "../../common/models/database-entities.model";
import { AllowNull, BelongsTo, Column, ForeignKey, Table } from "sequelize-typescript";
-import { Translation } from "../../../translations/models/translation.model";
import { DataTypes } from "sequelize";
+import { TranslationObject } from "@recursyve/nestjs-rosetta-core";
+import { TranslationColumn } from "@recursyve/nestjs-rosetta-sequelize";
@Table
export class Ingredients extends DatabaseEntities {
- @Column
- @ForeignKey(() => Ingredients)
- public variationOfIngredientId: number;
+ @Column
+ @ForeignKey(() => Ingredients)
+ public variationOfIngredientId: number;
- @AllowNull(false)
- @Column(DataTypes.JSON)
- public name: Translation;
+ @AllowNull(false)
+ @Column(DataTypes.JSON)
+ @TranslationColumn()
+ public name: TranslationObject;
- @Column(DataTypes.JSON)
- public description: Translation;
+ @Column(DataTypes.JSON)
+ @TranslationColumn()
+ public description: TranslationObject;
- @Column
- public imagePath: string;
+ @Column
+ public imagePath: string;
- @BelongsTo(() => Ingredients)
- public variationOfIngredient: Ingredients;
+ @BelongsTo(() => Ingredients)
+ public variationOfIngredient: Ingredients;
}
diff --git a/api/src/modules/database/ingredients/services/ingredients.service.ts b/api/src/modules/database/ingredients/services/ingredients.service.ts
index 51ce1b5..3c412f7 100644
--- a/api/src/modules/database/ingredients/services/ingredients.service.ts
+++ b/api/src/modules/database/ingredients/services/ingredients.service.ts
@@ -2,7 +2,7 @@ import { DatabaseRepository } from "../../common/repositories/database.repositor
import { Ingredients } from "../models/ingredients.model";
export class IngredientsService extends DatabaseRepository {
- constructor() {
- super(Ingredients);
- }
+ constructor() {
+ super(Ingredients);
+ }
}
diff --git a/api/src/modules/database/pantry/controllers/pantry.controller.ts b/api/src/modules/database/pantry/controllers/pantry.controller.ts
index 36a1631..76bd7f7 100644
--- a/api/src/modules/database/pantry/controllers/pantry.controller.ts
+++ b/api/src/modules/database/pantry/controllers/pantry.controller.ts
@@ -4,10 +4,10 @@ import { PantryItems } from "../models/pantry-items.model";
@Controller("pantry")
export class PantryController {
- constructor(private service: PantryService) {}
+ constructor(private service: PantryService) {}
- @Get()
- public async getPantryItems(): Promise {
- return this.service.getAllItems();
- }
+ @Get()
+ public async getPantryItems(): Promise {
+ return this.service.findAllItems();
+ }
}
diff --git a/api/src/modules/database/pantry/models/pantry-items.model.ts b/api/src/modules/database/pantry/models/pantry-items.model.ts
index 4520d19..471955a 100644
--- a/api/src/modules/database/pantry/models/pantry-items.model.ts
+++ b/api/src/modules/database/pantry/models/pantry-items.model.ts
@@ -5,30 +5,30 @@ import { GroceryProducts } from "../../grocery_products/models/grocery-products.
@Table
export class PantryItems extends DatabaseEntities {
- @Column
- @ForeignKey(() => GroceryProducts)
- public groceryProductId: number;
+ @Column
+ @ForeignKey(() => GroceryProducts)
+ public groceryProductId: number;
- @Column
- @ForeignKey(() => Homes)
- public homeId: number;
+ @Column
+ @ForeignKey(() => Homes)
+ public homeId: number;
- @Column
- public itemCount: number;
+ @Column
+ public itemCount: number;
- @Default(false)
- @Column
- public isLow: boolean;
+ @Default(false)
+ @Column
+ public isLow: boolean;
- // @Column
- // public oldestEntry: Date;
- //
- // @Column
- // public newestEntry: Date;
+ // @Column
+ // public oldestEntry: Date;
+ //
+ // @Column
+ // public newestEntry: Date;
- @BelongsTo(() => GroceryProducts)
- public groceryProduct: GroceryProducts;
+ @BelongsTo(() => GroceryProducts)
+ public groceryProduct: GroceryProducts;
- @BelongsTo(() => Homes)
- public home: Homes;
+ @BelongsTo(() => Homes)
+ public home: Homes;
}
diff --git a/api/src/modules/database/pantry/services/pantry.service.ts b/api/src/modules/database/pantry/services/pantry.service.ts
index b5fd692..ee6217d 100644
--- a/api/src/modules/database/pantry/services/pantry.service.ts
+++ b/api/src/modules/database/pantry/services/pantry.service.ts
@@ -4,11 +4,16 @@ import { Injectable } from "@nestjs/common";
@Injectable()
export class PantryService extends DatabaseRepository {
- constructor() {
- super(PantryItems);
- }
+ constructor() {
+ super(PantryItems);
+ }
- public async getAllItems(): Promise {
- return this.findAll();
- }
+ public async findAllItems(): Promise {
+ const pantryItems = await this.findAll({
+ include: ["groceryProduct", "home"]
+ });
+
+ pantryItems.forEach((p) => console.log(p.toJSON()));
+ return pantryItems;
+ }
}
diff --git a/api/src/modules/translations/languages.enum.ts b/api/src/modules/translations/languages.enum.ts
index 7b9cdb2..ad40883 100644
--- a/api/src/modules/translations/languages.enum.ts
+++ b/api/src/modules/translations/languages.enum.ts
@@ -1,4 +1,6 @@
export enum Languages {
FR = "fr",
EN = "en"
-}
\ No newline at end of file
+}
+
+export const languagesValues = Object.values(Languages);
diff --git a/api/src/modules/translations/models/translation.model.ts b/api/src/modules/translations/models/translation.model.ts
deleted file mode 100644
index f7c8a00..0000000
--- a/api/src/modules/translations/models/translation.model.ts
+++ /dev/null
@@ -1,5 +0,0 @@
-import { Languages } from "../languages.enum";
-
-export type Translation = {
- [key in Languages]?: string;
-}
\ No newline at end of file
diff --git a/api/tsconfig.build.json b/api/tsconfig.build.json
index 9054e73..5e705a7 100644
--- a/api/tsconfig.build.json
+++ b/api/tsconfig.build.json
@@ -1,10 +1,11 @@
{
"extends": "./tsconfig.json",
"exclude": [
- "test-backend/api/node_modules",
+ "foodapp/api/node_modules",
"test",
- "dist",
+ "dist",
+ "ceto",
"data-migrations",
- "**/*spec.ts"
+ "**/*spec.ts"
]
}
diff --git a/api/tsconfig.json b/api/tsconfig.json
index 4e111cb..3ec0b7d 100644
--- a/api/tsconfig.json
+++ b/api/tsconfig.json
@@ -7,12 +7,13 @@
"experimentalDecorators": true,
"target": "es2017",
"sourceMap": true,
- "outDir": "./test-backend/api/dist",
+ "outDir": "./dist",
"baseUrl": "./",
"incremental": true
},
"exclude": [
- "test-backend/api/node_modules",
+ "foodapp/api/node_modules",
+ "ceto",
"dist"
]
}
diff --git a/api/tsconfig.migrations.json b/api/tsconfig.migrations.json
index 5f103a6..0b07309 100644
--- a/api/tsconfig.migrations.json
+++ b/api/tsconfig.migrations.json
@@ -18,5 +18,5 @@
"src"
],
"exclude": [
- "test-backend/api/node_modules", "dist"]
+ "foodapp/api/node_modules", "dist"]
}
diff --git a/app/analysis_options.yaml b/app/analysis_options.yaml
index 61b6c4d..0c9e8a3 100644
--- a/app/analysis_options.yaml
+++ b/app/analysis_options.yaml
@@ -24,6 +24,10 @@ linter:
rules:
# avoid_print: false # Uncomment to disable the `avoid_print` rule
# prefer_single_quotes: true # Uncomment to enable the `prefer_single_quotes` rule
+ always_declare_return_types: true
+ always_use_package_imports: true
+ eol_at_end_of_file: true
+ require_trailing_commas: true
# Additional information about this file can be found at
# https://dart.dev/guides/language/analysis-options
diff --git a/app/android/app/build.gradle b/app/android/app/build.gradle
index 2e3901b..4bc2741 100644
--- a/app/android/app/build.gradle
+++ b/app/android/app/build.gradle
@@ -26,7 +26,7 @@ apply plugin: 'kotlin-android'
apply from: "$flutterRoot/packages/flutter_tools/gradle/flutter.gradle"
android {
- compileSdkVersion flutter.compileSdkVersion
+ compileSdkVersion 33
ndkVersion flutter.ndkVersion
compileOptions {
@@ -47,7 +47,7 @@ android {
applicationId "com.example.foodapp"
// You can update the following values to match your application needs.
// For more information, see: https://docs.flutter.dev/deployment/android#reviewing-the-build-configuration.
- minSdkVersion flutter.minSdkVersion
+ minSdkVersion 21
targetSdkVersion flutter.targetSdkVersion
versionCode flutterVersionCode.toInteger()
versionName flutterVersionName
diff --git a/app/lib/api/base_api.dart b/app/lib/api/base_api.dart
index fef2adb..7646708 100644
--- a/app/lib/api/base_api.dart
+++ b/app/lib/api/base_api.dart
@@ -2,13 +2,12 @@ import 'package:dio/dio.dart';
import 'package:foodapp/environment.dart';
class BaseApi {
- late Dio http;
- late String baseUrl;
+ final Dio http;
+ late final String baseUrl;
BaseApi(this.http, String path) {
String apiUrl = Environment.apiUrl;
baseUrl = "$apiUrl/$path";
- http = Dio();
}
String url([String? path]) {
diff --git a/app/lib/api/common/models/database-entity.model.dart b/app/lib/api/common/models/database-entity.model.dart
index d3437d1..82a57f4 100644
--- a/app/lib/api/common/models/database-entity.model.dart
+++ b/app/lib/api/common/models/database-entity.model.dart
@@ -1,39 +1,30 @@
-import 'dart:collection';
+import 'package:foodapp/api/common/types/json.type.dart';
+import 'package:foodapp/utils/json.utils.dart';
class DatabaseEntityModel {
- int? id;
- DateTime? createdAt;
- DateTime? updatedAt;
- DateTime? deletedAt;
+ final int id;
+ final DateTime? createdAt;
+ final DateTime? updatedAt;
+ final DateTime? deletedAt;
- DatabaseEntityModel(this.id, this.createdAt, this.updatedAt, this.deletedAt);
+ DatabaseEntityModel({required this.id, this.createdAt, this.updatedAt, this.deletedAt});
- DatabaseEntityModel.fromJson(LinkedHashMap? json) {
- if (json == null) return;
+ DatabaseEntityModel.fromJson(Json json)
+ : id = json["id"],
+ createdAt = JsonUtils.parseIfNotNull(json["createdAt"], DateTime.parse)?.toLocal(),
+ updatedAt = JsonUtils.parseIfNotNull(json["updatedAt"], DateTime.parse)?.toLocal(),
+ deletedAt = JsonUtils.parseIfNotNull(json["deletedAt"], DateTime.parse)?.toLocal();
- id = json["id"];
- if (json["createdAt"] != null) {
- createdAt = DateTime.tryParse(json["createdAt"])?.toLocal();
- }
- if (json["updatedAt"] != null) {
- updatedAt = DateTime.tryParse(json["updatedAt"])?.toLocal();
- }
- if (json["deletedAt"] != null) {
- deletedAt = DateTime.tryParse(json["deletedAt"])?.toLocal();
- }
- }
-
- DatabaseEntityModel.merge(DatabaseEntityModel target, DatabaseEntityModel source) {
- id = source.id ?? target.id;
- createdAt = source.createdAt ?? target.createdAt;
- updatedAt = source.updatedAt ?? target.updatedAt;
- deletedAt = source.deletedAt ?? target.deletedAt;
- }
+ DatabaseEntityModel.merge(DatabaseEntityModel target, DatabaseEntityModel source)
+ : id = source.id,
+ createdAt = source.createdAt ?? target.createdAt,
+ updatedAt = source.updatedAt ?? target.updatedAt,
+ deletedAt = source.deletedAt ?? target.deletedAt;
Map toJson() => {
- if (id != null) "id": id,
- if (createdAt != null) "createdAt": createdAt?.toIso8601String(),
- if (updatedAt != null) "updatedAt": updatedAt?.toIso8601String(),
- if (deletedAt != null) "deletedAt": deletedAt?.toIso8601String(),
- };
-}
\ No newline at end of file
+ "id": id,
+ if (createdAt != null) "createdAt": createdAt?.toIso8601String(),
+ if (updatedAt != null) "updatedAt": updatedAt?.toIso8601String(),
+ if (deletedAt != null) "deletedAt": deletedAt?.toIso8601String(),
+ };
+}
diff --git a/app/lib/api/grocery-products/apis/grocery-product.api.dart b/app/lib/api/grocery-products/apis/grocery-product.api.dart
index 9be99fe..ab821f9 100644
--- a/app/lib/api/grocery-products/apis/grocery-product.api.dart
+++ b/app/lib/api/grocery-products/apis/grocery-product.api.dart
@@ -1,21 +1,19 @@
-import 'dart:collection';
-
import 'package:dio/dio.dart';
import 'package:foodapp/api/base_api.dart';
import 'package:foodapp/api/common/types/json.type.dart';
import 'package:foodapp/api/grocery-products/models/grocery-products.model.dart';
class GroceryProductApi extends BaseApi {
- GroceryProductApi(Dio http): super(http, "grocery-product");
+ GroceryProductApi(Dio http) : super(http, "grocery-product");
Future getGroceryProductBySku(String skuCode) async {
try {
- final Response response = await http.get(url(), queryParameters: { "sku": skuCode });
+ final Response response = await http.get(url(), queryParameters: {"sku": skuCode});
return GroceryProductsModel.fromJson(Json.from(response.data));
- } catch(e) {
+ } catch (e) {
if (e is DioError && e.response?.statusCode == 400) return null;
print(e);
return null;
}
}
-}
\ No newline at end of file
+}
diff --git a/app/lib/api/grocery-products/models/grocery-products.model.dart b/app/lib/api/grocery-products/models/grocery-products.model.dart
index ac56746..1386ed0 100644
--- a/app/lib/api/grocery-products/models/grocery-products.model.dart
+++ b/app/lib/api/grocery-products/models/grocery-products.model.dart
@@ -1,21 +1,19 @@
-import 'dart:collection';
-
-import 'package:equatable/equatable.dart';
import 'package:foodapp/api/common/models/database-entity.model.dart';
+import 'package:foodapp/api/common/types/json.type.dart';
-class GroceryProductsModel extends DatabaseEntityModel with EquatableMixin {
- int? ingredientId;
- int? duplicateOfGroceryProductId;
- String? name;
- String? description;
- String? skuCode;
- double? averagePrice;
- int? averageLifeSpanDays;
- String? imagePath;
+class GroceryProductsModel extends DatabaseEntityModel {
+ final int? ingredientId;
+ final int? duplicateOfGroceryProductId;
+ final String? name;
+ final String? description;
+ final String? skuCode;
+ final double? averagePrice;
+ final int? averageLifeSpanDays;
+ final String? imagePath;
dynamic productMetadata;
GroceryProductsModel({
- int? id,
+ required super.id,
this.ingredientId,
this.duplicateOfGroceryProductId,
this.name,
@@ -25,44 +23,22 @@ class GroceryProductsModel extends DatabaseEntityModel with EquatableMixin {
this.averageLifeSpanDays,
this.imagePath,
this.productMetadata,
- DateTime? createdAt,
- DateTime? updatedAt,
- DateTime? deletedAt
-}) : super(id, createdAt, updatedAt, deletedAt);
-
- GroceryProductsModel.fromJson(LinkedHashMap? json) : super.fromJson(json) {
- if (json == null) return;
-
- name = json["name"];
-
- if (json["ingredientId"] != null) {
- ingredientId = json["ingredientId"];
- }
-
- if (json["duplicateOfGroceryProductId"] != null) {
- duplicateOfGroceryProductId = json["duplicateOfGroceryProductId"];
- }
-
- if (json["description"] != null) {
- description = json["description"];
- }
+ super.createdAt,
+ super.updatedAt,
+ super.deletedAt,
+ });
- if (json["skuCode"] != null) {
- skuCode = json["skuCode"];
- }
-
- if (json["averagePrice"] != null) {
- averagePrice = json["averagePrice"];
- }
-
- if (json["averageLifeSpanDays"] != null) {
- averageLifeSpanDays = json["averageLifeSpanDays"];
- }
-
- if (json["productMetadata"] != null) {
- productMetadata = json["productMetadata"];
- }
- }
+ GroceryProductsModel.fromJson(Json json)
+ : name = json["name"],
+ ingredientId = json["ingredientId"],
+ duplicateOfGroceryProductId = json["duplicateOfGroceryProductId"],
+ description = json["description"],
+ skuCode = json["skuCode"],
+ averagePrice = json["averagePrice"],
+ averageLifeSpanDays = json["averageLifeSpanDays"],
+ productMetadata = json["productMetadata"],
+ imagePath = json["imagePath"],
+ super.fromJson(json);
GroceryProductsModel copyWith({
int? ingredientId,
@@ -74,7 +50,7 @@ class GroceryProductsModel extends DatabaseEntityModel with EquatableMixin {
int? averageLifeSpanDays,
String? imagePath,
dynamic productMetadata,
-}) {
+ }) {
return GroceryProductsModel(
id: id,
ingredientId: ingredientId ?? this.ingredientId,
@@ -91,22 +67,4 @@ class GroceryProductsModel extends DatabaseEntityModel with EquatableMixin {
deletedAt: deletedAt,
);
}
-
- @override
- List