From 5af9825bd8bf69539dc3a9198a30484be8bbce5a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gustavo=20Mendon=C3=A7a?= Date: Tue, 18 Jun 2019 10:33:53 -0300 Subject: [PATCH 1/4] feat(mongoose): Added DynamicRef decorator to support mongoose dynamic refs. Issue #567 --- .../mongoose/src/decorators/dynamicRef.ts | 54 +++++++++++++++++++ packages/mongoose/src/decorators/index.ts | 1 + 2 files changed, 55 insertions(+) create mode 100644 packages/mongoose/src/decorators/dynamicRef.ts diff --git a/packages/mongoose/src/decorators/dynamicRef.ts b/packages/mongoose/src/decorators/dynamicRef.ts new file mode 100644 index 00000000000..4dc0c490169 --- /dev/null +++ b/packages/mongoose/src/decorators/dynamicRef.ts @@ -0,0 +1,54 @@ +import {Property, Schema} from "@tsed/common"; +import {applyDecorators, Store, StoreFn, StoreMerge} from "@tsed/core"; +import {Schema as MongooseSchema} from "mongoose"; +import {MONGOOSE_SCHEMA} from "../constants"; + +/** + * Define a property as mongoose reference to other Model (decorated with @Model). + * + * ### Example + * + * ```typescript + * + * @Model() + * class FooModel { + * + * @DynamicRef('type') + * field: Ref + * + * @Enum(['OtherFooModel', 'OtherModel']) + * type: string + * } + * + * @Model() + * class OtherFooModel { + * } + * + * @Model() + * class OtherModel { + * } + * ``` + * + * @param type + * @returns {Function} + * @decorator + * @mongoose + * @property + */ +export function DynamicRef(refPath: string) { + return applyDecorators( + Property({use: String}), + Schema({ + type: String, + example: "5ce7ad3028890bd71749d477", + description: "Mongoose Ref ObjectId" + }), + StoreFn((store: Store) => { + delete store.get("schema").$ref; + }), + StoreMerge(MONGOOSE_SCHEMA, { + type: MongooseSchema.Types.ObjectId, + refPath + }) + ); +} diff --git a/packages/mongoose/src/decorators/index.ts b/packages/mongoose/src/decorators/index.ts index c40223fd9e3..ef1a9581808 100644 --- a/packages/mongoose/src/decorators/index.ts +++ b/packages/mongoose/src/decorators/index.ts @@ -10,3 +10,4 @@ export * from "./select"; export * from "./unique"; export * from "./virtualRef"; export * from "./objectID"; +export * from "./dynamicRef"; From 4bf5daa6d41d7f9ab749280eb2c433bf7ab9d2f3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gustavo=20Mendon=C3=A7a?= Date: Thu, 11 Jul 2019 16:31:21 -0300 Subject: [PATCH 2/4] docs: Added dynamic reference documentation --- docs/tutorials/mongoose.md | 8 ++++++++ .../tutorials/snippets/mongoose/dynamic-references.ts | 11 +++++++++++ 2 files changed, 19 insertions(+) create mode 100644 docs/tutorials/snippets/mongoose/dynamic-references.ts diff --git a/docs/tutorials/mongoose.md b/docs/tutorials/mongoose.md index f73345fa408..c667de61002 100644 --- a/docs/tutorials/mongoose.md +++ b/docs/tutorials/mongoose.md @@ -127,6 +127,14 @@ Be wary of circular dependencies. Direct references must be declared after the r <<< @/docs/tutorials/snippets/mongoose/virtual-references.ts +### Dynamic References + +`@tsed/mongoose` supports `mongoose` dynamic references between defined models. + +This works by having a field with the referenced object model's name and a field with the referenced field. + +<<< @/docs/tutorials/snippets/mongoose/dynamic-references.ts + ## Register hook Mongoose allows the developer to add pre and post [hooks / middlewares](http://mongoosejs.com/docs/middleware.html) to the schema. diff --git a/docs/tutorials/snippets/mongoose/dynamic-references.ts b/docs/tutorials/snippets/mongoose/dynamic-references.ts new file mode 100644 index 00000000000..d9274ef4d8c --- /dev/null +++ b/docs/tutorials/snippets/mongoose/dynamic-references.ts @@ -0,0 +1,11 @@ +import {Model, Ref, DynamicRef} from "@tsed/mongoose"; +import {Enum, Required} from "@tsed/common" + +@Model() +export class DynamicRef { + @DynamicRef('type') + dynamicRef: Ref + + @Enum(['Mode lA', 'ModelB']) + type: string // This field has to match the referenced model's name +} \ No newline at end of file From 5b9205f917a9353243ae26ad1178e3b639a98cd1 Mon Sep 17 00:00:00 2001 From: "romain.lenzotti" Date: Sat, 20 Jul 2019 09:05:40 +0200 Subject: [PATCH 3/4] fix(mongoose): Add unit test for DynamicRef --- .../mongoose/src/decorators/dynamicRef.ts | 6 ++-- .../test/decorators/dynamicRef.spec.ts | 30 +++++++++++++++++++ 2 files changed, 33 insertions(+), 3 deletions(-) create mode 100644 packages/mongoose/test/decorators/dynamicRef.spec.ts diff --git a/packages/mongoose/src/decorators/dynamicRef.ts b/packages/mongoose/src/decorators/dynamicRef.ts index 4dc0c490169..2e20f851ab5 100644 --- a/packages/mongoose/src/decorators/dynamicRef.ts +++ b/packages/mongoose/src/decorators/dynamicRef.ts @@ -3,18 +3,18 @@ import {applyDecorators, Store, StoreFn, StoreMerge} from "@tsed/core"; import {Schema as MongooseSchema} from "mongoose"; import {MONGOOSE_SCHEMA} from "../constants"; +export type DynamicRef = T | string; /** * Define a property as mongoose reference to other Model (decorated with @Model). * * ### Example * * ```typescript - * * @Model() * class FooModel { * * @DynamicRef('type') - * field: Ref + * field: DynamicRef * * @Enum(['OtherFooModel', 'OtherModel']) * type: string @@ -29,7 +29,7 @@ import {MONGOOSE_SCHEMA} from "../constants"; * } * ``` * - * @param type + * @param refPath * @returns {Function} * @decorator * @mongoose diff --git a/packages/mongoose/test/decorators/dynamicRef.spec.ts b/packages/mongoose/test/decorators/dynamicRef.spec.ts new file mode 100644 index 00000000000..9519402f183 --- /dev/null +++ b/packages/mongoose/test/decorators/dynamicRef.spec.ts @@ -0,0 +1,30 @@ +import {descriptorOf, Store} from "@tsed/core"; +import {expect} from "chai"; +import {Schema} from "mongoose"; +import {MONGOOSE_MODEL_NAME, MONGOOSE_SCHEMA} from "../../src/constants"; +import {DynamicRef} from "../../src/decorators"; + +describe("@Ref()", () => { + it("should set metadata", () => { + // GIVEN + + class RefTest { + } + + Store.from(RefTest).set(MONGOOSE_MODEL_NAME, "RefTest"); + + // WHEN + class Test { + @DynamicRef("RefTest") + test: DynamicRef; + } + + // THEN + const store = Store.from(Test, "test", descriptorOf(Test, "test")); + + expect(store.get(MONGOOSE_SCHEMA)).to.deep.eq({ + type: Schema.Types.ObjectId, + refPath: "RefTest" + }); + }); +}); From e5b9f9075056ab464b0f62661be7892af835de8d Mon Sep 17 00:00:00 2001 From: "romain.lenzotti" Date: Sat, 20 Jul 2019 09:05:54 +0200 Subject: [PATCH 4/4] chore: Edit contributing file --- CONTRIBUTING.md | 35 +++++++++++++++++++++++------------ docs/contributing.md | 33 ++++++++++++++++++++++----------- 2 files changed, 45 insertions(+), 23 deletions(-) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 3c3a2aed643..040b4e4f587 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -43,7 +43,7 @@ Install npm dependencies with yarn (not with NPM!): ```bash yarn ``` -> After installing dependencies, yarn run the `postinstall` hook and mounted all packages with `npm link` (e.g. `yarn run repo:bootstrap`). +> After installing dependencies, yarn/npm run the `postinstall` hook and mounted all packages with `npm link` (e.g. `yarn run repo:bootstrap`). Compile TypeScript: ```bash @@ -54,10 +54,6 @@ yarn tsc npm run tsc ``` -Build project: -``` -``` - ### Test ```bash @@ -66,9 +62,9 @@ yarn test npm run test ``` -### Gflow +### Gflow (optional) -[Gflow](https://www.npmjs.com/package/gflow) is a command line tool to help developer with the Git Flow process used in Ts.ED. +[Gflow](https://www.npmjs.com/package/gflow) is a command line tool to help developer with the Git process used in Ts.ED. Gflow help you to create a branch from production, rebase and run the test before pushing your branch on your remote repository. @@ -76,25 +72,40 @@ Gflow help you to create a branch from production, rebase and run the test befor npm install -g gflow ``` -#### Start a feature branch +### Start a feature branch ```bash +git fetch +git branch --no-track -b feat-branch-name origin/production # !IMPORTANT +yarn + +## OR gflow new feat name_of_feat ``` -#### Commit & Push a feature +### Commit & Push a feature This command rebase your branch feature from the production branch, run the test and push your branch. ```bash git commit -m "feat(domain): Your message" +``` +> To write your commit message see [convention page](https://www.conventionalcommits.org/en/v1.0.0-beta.4/) + +Then: +```bash +npm run test +git fetch +git rebase origin/production +git push -f + +# OR using gflow (run fetch, rebase and push for you) gflow push ``` -> To write your commit message see [convention page](https://docs.google.com/document/d/1QrDFcIiPjSLDn3EL15IJygNPiHORgU1_OOAqWjiDU5Y/edit) When your feature is ready to review, you can open a PR on Ts.ED github. -#### Finish a feature +### Finish a feature (repo owner and maintainers) After the PR has been accepted, the feature will be automatically merge on the master branch, but your feature isn't merge with the production branch. @@ -102,7 +113,7 @@ your feature isn't merge with the production branch. To publish your feature on the production branch you need to run a this command: ```bash -gflow finish +gflow finish ``` > Note: This action works only on the Ts.ED repository (not on your fork). diff --git a/docs/contributing.md b/docs/contributing.md index 6b20c0fc19e..7399222d418 100644 --- a/docs/contributing.md +++ b/docs/contributing.md @@ -68,7 +68,7 @@ Install npm dependencies with yarn (not with NPM!): ```bash yarn ``` -> After installing dependencies, yarn run the `postinstall` hook and mounted all packages with `npm link` (e.g. `yarn run repo:bootstrap`). +> After installing dependencies, yarn/npm run the `postinstall` hook and mounted all packages with `npm link` (e.g. `yarn run repo:bootstrap`). Compile TypeScript: ```bash @@ -79,10 +79,6 @@ yarn tsc npm run tsc ``` -Build project: -``` -``` - ### Test ```bash @@ -91,9 +87,9 @@ yarn test npm run test ``` -### Gflow +### Gflow (optional) -[Gflow](https://www.npmjs.com/package/gflow) is a command line tool to help developer with the Git Flow process used in Ts.ED. +[Gflow](https://www.npmjs.com/package/gflow) is a command line tool to help developer with the Git process used in Ts.ED. Gflow help you to create a branch from production, rebase and run the test before pushing your branch on your remote repository. @@ -101,25 +97,40 @@ Gflow help you to create a branch from production, rebase and run the test befor npm install -g gflow ``` -#### Start a feature branch +### Start a feature branch ```bash +git fetch +git branch --no-track -b feat-branch-name origin/production # !IMPORTANT +yarn + +## OR gflow new feat name_of_feat ``` -#### Commit & Push a feature +### Commit & Push a feature This command rebase your branch feature from the production branch, run the test and push your branch. ```bash git commit -m "feat(domain): Your message" +``` +> To write your commit message see [convention page](https://www.conventionalcommits.org/en/v1.0.0-beta.4/) + +Then: +```bash +npm run test +git fetch +git rebase origin/production +git push -f + +# OR using gflow (run fetch, rebase and push for you) gflow push ``` -> To write your commit message see [convention page](https://docs.google.com/document/d/1QrDFcIiPjSLDn3EL15IJygNPiHORgU1_OOAqWjiDU5Y/edit) When your feature is ready to review, you can open a PR on Ts.ED github. -#### Finish a feature +### Finish a feature (repo owner and maintainers) After the PR has been accepted, the feature will be automatically merge on the master branch, but your feature isn't merge with the production branch.