@tsed/mongoose 8.0.1 → 8.0.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (78) hide show
  1. package/package.json +15 -14
  2. package/readme.md +5 -5
  3. package/src/MongooseModule.ts +32 -0
  4. package/src/constants/constants.ts +20 -0
  5. package/src/decorators/auto.spec.ts +30 -0
  6. package/src/decorators/auto.ts +24 -0
  7. package/src/decorators/discriminatorKey.ts +1 -0
  8. package/src/decorators/dynamicRef.spec.ts +46 -0
  9. package/src/decorators/dynamicRef.ts +76 -0
  10. package/src/decorators/excludeIndexes.spec.ts +30 -0
  11. package/src/decorators/excludeIndexes.ts +24 -0
  12. package/src/decorators/expires.spec.ts +18 -0
  13. package/src/decorators/expires.ts +24 -0
  14. package/src/decorators/immutable.spec.ts +30 -0
  15. package/src/decorators/immutable.ts +26 -0
  16. package/src/decorators/indexed.spec.ts +19 -0
  17. package/src/decorators/indexed.ts +24 -0
  18. package/src/decorators/lowercase.spec.ts +30 -0
  19. package/src/decorators/lowercase.ts +24 -0
  20. package/src/decorators/model.ts +69 -0
  21. package/src/decorators/mongooseIndex.spec.ts +26 -0
  22. package/src/decorators/mongooseIndex.ts +35 -0
  23. package/src/decorators/mongooseIndexes.spec.ts +35 -0
  24. package/src/decorators/mongooseIndexes.ts +35 -0
  25. package/src/decorators/mongoosePlugin.spec.ts +25 -0
  26. package/src/decorators/mongoosePlugin.ts +20 -0
  27. package/src/decorators/numberDecimal.spec.ts +266 -0
  28. package/src/decorators/numberDecimal.ts +84 -0
  29. package/src/decorators/objectID.spec.ts +24 -0
  30. package/src/decorators/objectID.ts +39 -0
  31. package/src/decorators/postHook.spec.ts +44 -0
  32. package/src/decorators/postHook.ts +72 -0
  33. package/src/decorators/preHook.spec.ts +75 -0
  34. package/src/decorators/preHook.ts +70 -0
  35. package/src/decorators/ref.spec.ts +361 -0
  36. package/src/decorators/ref.ts +111 -0
  37. package/src/decorators/schema.ts +79 -0
  38. package/src/decorators/schemaIgnore.spec.ts +18 -0
  39. package/src/decorators/schemaIgnore.ts +24 -0
  40. package/src/decorators/select.spec.ts +18 -0
  41. package/src/decorators/select.ts +24 -0
  42. package/src/decorators/sparse.spec.ts +30 -0
  43. package/src/decorators/sparse.ts +26 -0
  44. package/src/decorators/text.spec.ts +30 -0
  45. package/src/decorators/text.ts +25 -0
  46. package/src/decorators/trim.spec.ts +18 -0
  47. package/src/decorators/trim.ts +23 -0
  48. package/src/decorators/unique.spec.ts +18 -0
  49. package/src/decorators/unique.ts +23 -0
  50. package/src/decorators/uppercase.spec.ts +30 -0
  51. package/src/decorators/uppercase.ts +24 -0
  52. package/src/decorators/versionKey.spec.ts +19 -0
  53. package/src/decorators/versionKey.ts +9 -0
  54. package/src/decorators/virtualRef.spec.ts +383 -0
  55. package/src/decorators/virtualRef.ts +73 -0
  56. package/src/index.ts +47 -0
  57. package/src/interfaces/MongooseConnectionOptions.ts +10 -0
  58. package/src/interfaces/MongooseDocument.ts +3 -0
  59. package/src/interfaces/MongooseModel.ts +10 -0
  60. package/src/interfaces/MongooseModelOptions.ts +8 -0
  61. package/src/interfaces/MongooseSchemaOptions.ts +51 -0
  62. package/src/interfaces/MongooseSchemaTypes.ts +5 -0
  63. package/src/interfaces/MongooseVirtualRefOptions.ts +10 -0
  64. package/src/interfaces/interfaces.ts +9 -0
  65. package/src/registries/MongooseModels.ts +3 -0
  66. package/src/services/MongooseConnection.spec.ts +70 -0
  67. package/src/services/MongooseConnections.ts +58 -0
  68. package/src/services/MongooseService.spec.ts +73 -0
  69. package/src/services/MongooseService.ts +77 -0
  70. package/src/utils/buildMongooseSchema.spec.ts +67 -0
  71. package/src/utils/createModel.spec.ts +49 -0
  72. package/src/utils/createModel.ts +54 -0
  73. package/src/utils/createSchema.spec.ts +771 -0
  74. package/src/utils/createSchema.ts +198 -0
  75. package/src/utils/resolveRefType.spec.ts +30 -0
  76. package/src/utils/resolveRefType.ts +18 -0
  77. package/src/utils/schemaOptions.spec.ts +68 -0
  78. package/src/utils/schemaOptions.ts +74 -0
package/package.json CHANGED
@@ -2,7 +2,7 @@
2
2
  "name": "@tsed/mongoose",
3
3
  "description": "Mongoose package for Ts.ED framework",
4
4
  "type": "module",
5
- "version": "8.0.1",
5
+ "version": "8.0.3",
6
6
  "keywords": [
7
7
  "tsed",
8
8
  "mongoose",
@@ -16,6 +16,7 @@
16
16
  "typings": "./lib/types/index.d.ts",
17
17
  "exports": {
18
18
  ".": {
19
+ "@tsed/source": "./src/index.ts",
19
20
  "types": "./lib/types/index.d.ts",
20
21
  "import": "./lib/esm/index.js",
21
22
  "default": "./lib/esm/index.js"
@@ -33,27 +34,27 @@
33
34
  "tslib": "2.7.0"
34
35
  },
35
36
  "devDependencies": {
36
- "@tsed/ajv": "8.0.1",
37
- "@tsed/barrels": "8.0.1",
38
- "@tsed/core": "8.0.1",
39
- "@tsed/di": "8.0.1",
40
- "@tsed/json-mapper": "8.0.1",
37
+ "@tsed/ajv": "8.0.3",
38
+ "@tsed/barrels": "8.0.3",
39
+ "@tsed/core": "8.0.3",
40
+ "@tsed/di": "8.0.3",
41
+ "@tsed/json-mapper": "8.0.3",
41
42
  "@tsed/logger": "^6.7.8",
42
- "@tsed/schema": "8.0.1",
43
- "@tsed/testcontainers-mongo": "8.0.1",
44
- "@tsed/typescript": "8.0.1",
43
+ "@tsed/schema": "8.0.3",
44
+ "@tsed/testcontainers-mongo": "8.0.3",
45
+ "@tsed/typescript": "8.0.3",
45
46
  "eslint": "9.12.0",
46
47
  "mongoose": "8.7.0",
47
48
  "typescript": "5.4.5",
48
49
  "vitest": "2.1.2"
49
50
  },
50
51
  "peerDependencies": {
51
- "@tsed/ajv": "8.0.1",
52
- "@tsed/core": "8.0.1",
53
- "@tsed/di": "8.0.1",
54
- "@tsed/json-mapper": "8.0.1",
52
+ "@tsed/ajv": "8.0.3",
53
+ "@tsed/core": "8.0.3",
54
+ "@tsed/di": "8.0.3",
55
+ "@tsed/json-mapper": "8.0.3",
55
56
  "@tsed/logger": ">=6.7.5",
56
- "@tsed/schema": "8.0.1",
57
+ "@tsed/schema": "8.0.3",
57
58
  "mongoose": ">=6.0.0"
58
59
  },
59
60
  "repository": "https://github.com/tsedio/tsed",
package/readme.md CHANGED
@@ -1,5 +1,5 @@
1
1
  <p style="text-align: center" align="center">
2
- <a href="https://tsed.io" target="_blank"><img src="https://tsed.io/tsed-og.png" width="200" alt="Ts.ED logo"/></a>
2
+ <a href="https://tsed.dev" target="_blank"><img src="https://tsed.dev/tsed-og.png" width="200" alt="Ts.ED logo"/></a>
3
3
  </p>
4
4
 
5
5
  <div align="center">
@@ -16,9 +16,9 @@
16
16
  </div>
17
17
 
18
18
  <div align="center">
19
- <a href="https://tsed.io/">Website</a>
19
+ <a href="https://tsed.dev/">Website</a>
20
20
  <span>&nbsp;&nbsp;•&nbsp;&nbsp;</span>
21
- <a href="https://tsed.io/getting-started/">Getting started</a>
21
+ <a href="https://tsed.dev/getting-started/">Getting started</a>
22
22
  <span>&nbsp;&nbsp;•&nbsp;&nbsp;</span>
23
23
  <a href="https://api.tsed.io/rest/slack/tsedio/tsed">Slack</a>
24
24
  <span>&nbsp;&nbsp;•&nbsp;&nbsp;</span>
@@ -27,7 +27,7 @@
27
27
 
28
28
  <hr />
29
29
 
30
- A package of Ts.ED framework. See website: https://tsed.io/tutorials/mongoose.html
30
+ A package of Ts.ED framework. See website: https://tsed.dev/tutorials/mongoose.html
31
31
 
32
32
  ## Features
33
33
 
@@ -345,7 +345,7 @@ For further information, please refer to the [mongoose documentation about discr
345
345
 
346
346
  ## Contributors
347
347
 
348
- Please read [contributing guidelines here](https://tsed.io/contributing.html)
348
+ Please read [contributing guidelines here](https://tsed.dev/contributing.html)
349
349
 
350
350
  <a href="https://github.com/tsedio/tsed/graphs/contributors"><img src="https://opencollective.com/tsed/contributors.svg?width=890" /></a>
351
351
 
@@ -0,0 +1,32 @@
1
+ import {Configuration, OnInit} from "@tsed/di";
2
+ import {Module, OnDestroy} from "@tsed/di";
3
+
4
+ import {MONGOOSE_CONNECTIONS} from "./services/MongooseConnections.js";
5
+ import {MongooseService} from "./services/MongooseService.js";
6
+
7
+ /**
8
+ * @ignore
9
+ */
10
+ @Module({
11
+ imports: [MONGOOSE_CONNECTIONS]
12
+ })
13
+ export class MongooseModule implements OnDestroy, OnInit {
14
+ constructor(
15
+ private mongooseService: MongooseService,
16
+ @Configuration() private settings: Configuration
17
+ ) {
18
+ // auto configure the cache manager when mongoose is used with @tsed/mongoose
19
+ const cache = this.settings.get<any>("cache");
20
+
21
+ // istanbul ignore next
22
+ if (cache?.mongoose) {
23
+ cache.connection = this.mongooseService.get();
24
+ }
25
+ }
26
+
27
+ $onInit(): void | Promise<any> {}
28
+
29
+ $onDestroy(): Promise<any> | void {
30
+ return this.mongooseService.closeConnections();
31
+ }
32
+ }
@@ -0,0 +1,20 @@
1
+ /**
2
+ *
3
+ * @type {string}
4
+ */
5
+ export const MONGOOSE_SCHEMA = "tsed:mongoose:schema";
6
+ /**
7
+ *
8
+ * @type {string}
9
+ */
10
+ export const MONGOOSE_SCHEMA_OPTIONS = "tsed:mongoose:schema:options";
11
+ /**
12
+ *
13
+ * @type {string}
14
+ */
15
+ export const MONGOOSE_MODEL = "tsed:mongoose:model";
16
+ /**
17
+ *
18
+ * @type {string}
19
+ */
20
+ export const MONGOOSE_MODEL_NAME = "tsed:mongoose:model:name";
@@ -0,0 +1,30 @@
1
+ import {descriptorOf, Store} from "@tsed/core";
2
+
3
+ import {MONGOOSE_SCHEMA} from "../constants/constants.js";
4
+ import {Auto} from "./auto.js";
5
+
6
+ describe("@Auto()", () => {
7
+ it("should set metadata (default)", () => {
8
+ class Test {
9
+ @Auto()
10
+ test: string;
11
+ }
12
+
13
+ const store = Store.from(Test, "test", descriptorOf(Test, "test"));
14
+ expect(store.get(MONGOOSE_SCHEMA)).toEqual({
15
+ auto: true
16
+ });
17
+ });
18
+
19
+ it("should set metadata (true)", () => {
20
+ class Test {
21
+ @Auto(true)
22
+ test: string;
23
+ }
24
+
25
+ const store = Store.from(Test, "test", descriptorOf(Test, "test"));
26
+ expect(store.get(MONGOOSE_SCHEMA)).toEqual({
27
+ auto: true
28
+ });
29
+ });
30
+ });
@@ -0,0 +1,24 @@
1
+ import {MongooseSchema} from "./schema.js";
2
+
3
+ /**
4
+ * If true, uses Mongoose's default _id settings. Only allowed for ObjectIds
5
+ *
6
+ * ### Example
7
+ *
8
+ * ```typescript
9
+ * @Model()
10
+ * export class EventModel {
11
+ * @ExcludeIndexes()
12
+ * field: string;
13
+ * }
14
+ * ```
15
+ *
16
+ * @param {boolean} auto
17
+ * @returns {Function}
18
+ * @decorator
19
+ * @mongoose
20
+ * @property
21
+ */
22
+ export function Auto(auto: boolean = true): PropertyDecorator {
23
+ return MongooseSchema({auto} as any);
24
+ }
@@ -0,0 +1 @@
1
+ export {DiscriminatorKey} from "@tsed/schema";
@@ -0,0 +1,46 @@
1
+ import {descriptorOf, Store} from "@tsed/core";
2
+ import {getJsonSchema} from "@tsed/schema";
3
+ import {Schema} from "mongoose";
4
+
5
+ import {DynamicRef} from "../../src/index.js";
6
+ import {MONGOOSE_MODEL_NAME, MONGOOSE_SCHEMA} from "../constants/constants.js";
7
+
8
+ describe("@DynamicRef()", () => {
9
+ it("should set metadata", () => {
10
+ // GIVEN
11
+ class RefTest {}
12
+
13
+ Store.from(RefTest).set(MONGOOSE_MODEL_NAME, "RefTest");
14
+
15
+ // WHEN
16
+ class Test {
17
+ @DynamicRef("RefTest")
18
+ test: DynamicRef<RefTest>;
19
+ }
20
+
21
+ // THEN
22
+ expect(getJsonSchema(Test)).toEqual({
23
+ properties: {
24
+ test: {
25
+ description: "A reference ObjectID",
26
+ examples: ["5ce7ad3028890bd71749d477"],
27
+ oneOf: [
28
+ {
29
+ description: "A reference ObjectID",
30
+ examples: ["5ce7ad3028890bd71749d477"],
31
+ type: "string"
32
+ }
33
+ ]
34
+ }
35
+ },
36
+ type: "object"
37
+ });
38
+
39
+ const store = Store.from(Test, "test", descriptorOf(Test, "test"));
40
+
41
+ expect(store.get(MONGOOSE_SCHEMA)).toEqual({
42
+ type: Schema.Types.ObjectId,
43
+ refPath: "RefTest"
44
+ });
45
+ });
46
+ });
@@ -0,0 +1,76 @@
1
+ import {classOf, isArrowFn, isString, StoreMerge, Type, useDecorators} from "@tsed/core";
2
+ import {deserialize, OnDeserialize, OnSerialize, serialize} from "@tsed/json-mapper";
3
+ import {Description, Example, JsonHookContext, OneOf, Property, string} from "@tsed/schema";
4
+ import {Schema as MongooseSchema} from "mongoose";
5
+
6
+ import {MONGOOSE_SCHEMA} from "../constants/constants.js";
7
+ import {MongooseModels} from "../registries/MongooseModels.js";
8
+
9
+ function isRef(value: undefined | string | any) {
10
+ return (value && value._bsontype) || isString(value);
11
+ }
12
+
13
+ function getType(refPath: string, ctx: JsonHookContext) {
14
+ return (ctx?.self[refPath] && MongooseModels.get(ctx.self[refPath] as string)) || Object;
15
+ }
16
+
17
+ /**
18
+ * Define a property as mongoose reference to other Model (decorated with @Model).
19
+ *
20
+ * ### Example
21
+ *
22
+ * ```typescript
23
+ * @Model()
24
+ * class FooModel {
25
+ *
26
+ * @DynamicRef('type')
27
+ * field: DynamicRef<OtherFooModel | OtherModel>
28
+ *
29
+ * @Enum(['OtherFooModel', 'OtherModel'])
30
+ * type: string
31
+ * }
32
+ *
33
+ * @Model()
34
+ * class OtherFooModel {
35
+ * }
36
+ *
37
+ * @Model()
38
+ * class OtherModel {
39
+ * }
40
+ * ```
41
+ *
42
+ * @param refPath {String} the path to apply the correct model
43
+ * @param types {Type} the classes to generate the correct json schema
44
+ * @returns {Function}
45
+ * @decorator
46
+ * @mongoose
47
+ * @property
48
+ */
49
+ export function DynamicRef(refPath: string, ...types: Type<any>[]): PropertyDecorator {
50
+ return useDecorators(
51
+ Property(Object),
52
+ Example("5ce7ad3028890bd71749d477"),
53
+ Description("A reference ObjectID"),
54
+ StoreMerge(MONGOOSE_SCHEMA, {
55
+ type: MongooseSchema.Types.ObjectId,
56
+ refPath
57
+ }),
58
+ OnDeserialize((value, ctx) => {
59
+ if (isRef(value)) {
60
+ return value.toString();
61
+ }
62
+
63
+ return deserialize(value, {...ctx, type: getType(refPath, ctx)});
64
+ }),
65
+ OnSerialize((value: any, ctx) => {
66
+ if (isRef(value)) {
67
+ return value.toString();
68
+ }
69
+
70
+ return serialize(value, {...ctx, type: getType(refPath, ctx)});
71
+ }),
72
+ OneOf(string().example("5ce7ad3028890bd71749d477").description("A reference ObjectID"), ...types)
73
+ ) as PropertyDecorator;
74
+ }
75
+
76
+ export type DynamicRef<T> = T | string;
@@ -0,0 +1,30 @@
1
+ import {descriptorOf, Store} from "@tsed/core";
2
+
3
+ import {MONGOOSE_SCHEMA} from "../constants/constants.js";
4
+ import {ExcludeIndexes} from "./excludeIndexes.js";
5
+
6
+ describe("@ExcludeIndexes()", () => {
7
+ it("should set metadata (default)", () => {
8
+ class Test {
9
+ @ExcludeIndexes()
10
+ test: string;
11
+ }
12
+
13
+ const store = Store.from(Test, "test", descriptorOf(Test, "test"));
14
+ expect(store.get(MONGOOSE_SCHEMA)).toEqual({
15
+ excludeIndexes: true
16
+ });
17
+ });
18
+
19
+ it("should set metadata (true)", () => {
20
+ class Test {
21
+ @ExcludeIndexes(true)
22
+ test: string;
23
+ }
24
+
25
+ const store = Store.from(Test, "test", descriptorOf(Test, "test"));
26
+ expect(store.get(MONGOOSE_SCHEMA)).toEqual({
27
+ excludeIndexes: true
28
+ });
29
+ });
30
+ });
@@ -0,0 +1,24 @@
1
+ import {MongooseSchema} from "./schema.js";
2
+
3
+ /**
4
+ * If true, Mongoose will skip gathering indexes on subpaths. Only allowed for subdocuments and subdocument arrays.
5
+ *
6
+ * ### Example
7
+ *
8
+ * ```typescript
9
+ * @Model()
10
+ * export class EventModel {
11
+ * @ExcludeIndexes()
12
+ * field: string;
13
+ * }
14
+ * ```
15
+ *
16
+ * @param {boolean} excludeIndexes
17
+ * @returns {Function}
18
+ * @decorator
19
+ * @mongoose
20
+ * @property
21
+ */
22
+ export function ExcludeIndexes(excludeIndexes: boolean = true): PropertyDecorator {
23
+ return MongooseSchema({excludeIndexes} as any);
24
+ }
@@ -0,0 +1,18 @@
1
+ import {descriptorOf, Store} from "@tsed/core";
2
+
3
+ import {MONGOOSE_SCHEMA} from "../constants/constants.js";
4
+ import {Expires} from "./expires.js";
5
+
6
+ describe("@Expires()", () => {
7
+ it("should set metadata", () => {
8
+ class Test {
9
+ @Expires("5d")
10
+ test: string;
11
+ }
12
+
13
+ const store = Store.from(Test, "test", descriptorOf(Test, "test"));
14
+ expect(store.get(MONGOOSE_SCHEMA)).toEqual({
15
+ expires: "5d"
16
+ });
17
+ });
18
+ });
@@ -0,0 +1,24 @@
1
+ import {MongooseSchema} from "./schema.js";
2
+
3
+ /**
4
+ * Defines a TTL index on this path. Only allowed for dates.
5
+ *
6
+ * ### Example
7
+ *
8
+ * ```typescript
9
+ * @Model()
10
+ * export class EventModel {
11
+ * @Expires('5d')
12
+ * field: string;
13
+ * }
14
+ * ```
15
+ *
16
+ * @param {boolean | any} expires
17
+ * @returns {Function}
18
+ * @decorator
19
+ * @mongoose
20
+ * @property
21
+ */
22
+ export function Expires(expires: number | string | Date): PropertyDecorator {
23
+ return MongooseSchema({expires} as any);
24
+ }
@@ -0,0 +1,30 @@
1
+ import {descriptorOf, Store} from "@tsed/core";
2
+
3
+ import {MONGOOSE_SCHEMA} from "../constants/constants.js";
4
+ import {Immutable} from "./immutable.js";
5
+
6
+ describe("@Immutable()", () => {
7
+ it("should set metadata (default)", () => {
8
+ class Test {
9
+ @Immutable()
10
+ test: string;
11
+ }
12
+
13
+ const store = Store.from(Test, "test", descriptorOf(Test, "test"));
14
+ expect(store.get(MONGOOSE_SCHEMA)).toEqual({
15
+ immutable: true
16
+ });
17
+ });
18
+
19
+ it("should set metadata (true)", () => {
20
+ class Test {
21
+ @Immutable(true)
22
+ test: string;
23
+ }
24
+
25
+ const store = Store.from(Test, "test", descriptorOf(Test, "test"));
26
+ expect(store.get(MONGOOSE_SCHEMA)).toEqual({
27
+ immutable: true
28
+ });
29
+ });
30
+ });
@@ -0,0 +1,26 @@
1
+ import {MongooseSchema} from "./schema.js";
2
+
3
+ /**
4
+ * If [truthy](https://masteringjs.io/tutorials/fundamentals/truthy), Mongoose will
5
+ * disallow changes to this path once the document is saved to the database for the first time. Read more
6
+ * about [immutability in Mongoose here](http://thecodebarbarian.com/whats-new-in-mongoose-5-6-immutable-properties.html).
7
+ *
8
+ * ### Example
9
+ *
10
+ * ```typescript
11
+ * @Model()
12
+ * export class EventModel {
13
+ * @Immutable()
14
+ * field: string;
15
+ * }
16
+ * ```
17
+ *
18
+ * @param {boolean | any} immutable
19
+ * @returns {Function}
20
+ * @decorator
21
+ * @mongoose
22
+ * @property
23
+ */
24
+ export function Immutable(immutable: boolean | ((this: any, doc: any) => boolean) = true): PropertyDecorator {
25
+ return MongooseSchema({immutable} as any);
26
+ }
@@ -0,0 +1,19 @@
1
+ import {Store} from "@tsed/core";
2
+
3
+ import {MONGOOSE_SCHEMA} from "../constants/constants.js";
4
+ import {Indexed} from "./indexed.js";
5
+
6
+ describe("@Indexed()", () => {
7
+ it("should set metadata", () => {
8
+ class Test {
9
+ @Indexed()
10
+ test: string;
11
+ }
12
+
13
+ const store = Store.from(Test, "test");
14
+
15
+ expect(store.get(MONGOOSE_SCHEMA)).toEqual({
16
+ index: true
17
+ });
18
+ });
19
+ });
@@ -0,0 +1,24 @@
1
+ import {IndexOptions} from "mongoose";
2
+
3
+ import {MongooseSchema} from "./schema.js";
4
+
5
+ /**
6
+ * Tell Mongoose whether to define an index for the property.
7
+ * ### Example
8
+ *
9
+ * ```typescript
10
+ * @Model()
11
+ * export class EventModel {
12
+ * @Indexed()
13
+ * field: string;
14
+ * }
15
+ * ```
16
+ *
17
+ * @returns {Function}
18
+ * @decorator
19
+ * @mongoose
20
+ * @property
21
+ */
22
+ export function Indexed(index: IndexOptions | boolean | string = true): PropertyDecorator {
23
+ return MongooseSchema({index} as any);
24
+ }
@@ -0,0 +1,30 @@
1
+ import {descriptorOf, Store} from "@tsed/core";
2
+
3
+ import {MONGOOSE_SCHEMA} from "../constants/constants.js";
4
+ import {Lowercase} from "./lowercase.js";
5
+
6
+ describe("@Lowercase()", () => {
7
+ it("should set metadata (default)", () => {
8
+ class Test {
9
+ @Lowercase()
10
+ test: string;
11
+ }
12
+
13
+ const store = Store.from(Test, "test", descriptorOf(Test, "test"));
14
+ expect(store.get(MONGOOSE_SCHEMA)).toEqual({
15
+ lowercase: true
16
+ });
17
+ });
18
+
19
+ it("should set metadata (true)", () => {
20
+ class Test {
21
+ @Lowercase(true)
22
+ test: string;
23
+ }
24
+
25
+ const store = Store.from(Test, "test", descriptorOf(Test, "test"));
26
+ expect(store.get(MONGOOSE_SCHEMA)).toEqual({
27
+ lowercase: true
28
+ });
29
+ });
30
+ });
@@ -0,0 +1,24 @@
1
+ import {MongooseSchema} from "./schema.js";
2
+
3
+ /**
4
+ * If truthy, Mongoose will add a custom setter that lowercases this string using JavaScript's built-in String#toLowerCase().
5
+ *
6
+ * ### Example
7
+ *
8
+ * ```typescript
9
+ * @Model()
10
+ * export class EventModel {
11
+ * @Lowercase()
12
+ * field: string;
13
+ * }
14
+ * ```
15
+ *
16
+ * @param {boolean} lowercase
17
+ * @returns {Function}
18
+ * @decorator
19
+ * @mongoose
20
+ * @property
21
+ */
22
+ export function Lowercase(lowercase: boolean = true): PropertyDecorator {
23
+ return MongooseSchema({lowercase} as any);
24
+ }
@@ -0,0 +1,69 @@
1
+ import {useDecorators} from "@tsed/core";
2
+ import {injectable} from "@tsed/di";
3
+ import {Schema} from "mongoose";
4
+
5
+ import {MongooseModelOptions} from "../interfaces/MongooseModelOptions.js";
6
+ import {MONGOOSE_CONNECTIONS} from "../services/MongooseConnections.js";
7
+ import {createModel, getModelToken} from "../utils/createModel.js";
8
+ import {getSchema} from "../utils/createSchema.js";
9
+ import {applySchemaOptions, schemaOptions} from "../utils/schemaOptions.js";
10
+
11
+ /**
12
+ * Define a class as a Mongoose Model. The model can be injected to the Service, Controller, Middleware, Converters or Filter with
13
+ * `@Inject` annotation.
14
+ *
15
+ * ### Example
16
+ *
17
+ * ```typescript
18
+ * @Model()
19
+ * export class EventModel {
20
+ * @Property()
21
+ * field: string;
22
+ * }
23
+ * ```
24
+ *
25
+ * Then inject the model into a service:
26
+ *
27
+ * ```typescript
28
+ * class MyService {
29
+ * constructor(@Inject(EventModel) eventModel: MongooseModel<EventModel>) {
30
+ * eventModel.findById().exec();
31
+ * }
32
+ * }
33
+ * ```
34
+ *
35
+ * ### Options
36
+ *
37
+ * - `schemaOptions` (mongoose.SchemaOptions): Option to configure the schema behavior.
38
+ * - `name` (String): model name.
39
+ * - `collection` (String): collection (optional, induced from model name).
40
+ * - `skipInit` (Boolean): skipInit whether to skip initialization (defaults to false).
41
+ *
42
+ * @param {MongooseModelOptions} options
43
+ * @returns {(target: any) => void}
44
+ * @decorator
45
+ * @mongoose
46
+ * @class
47
+ */
48
+ export function Model(options: MongooseModelOptions = {}) {
49
+ return useDecorators((target: any) => {
50
+ const {token, collectionName} = getModelToken(target, options);
51
+
52
+ injectable(token).factory(() => getSchema(target, options as any));
53
+
54
+ injectable(target)
55
+ .type("mongoose:model")
56
+ .deps([MONGOOSE_CONNECTIONS, token])
57
+ .factory((connections: MONGOOSE_CONNECTIONS, schema: Schema) => {
58
+ applySchemaOptions(schema, schemaOptions(target));
59
+ return createModel(
60
+ target,
61
+ schema,
62
+ collectionName,
63
+ options.collection,
64
+ options.overwriteModels,
65
+ connections.get(options.connection)
66
+ );
67
+ });
68
+ });
69
+ }