@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.
- package/package.json +15 -14
- package/readme.md +5 -5
- package/src/MongooseModule.ts +32 -0
- package/src/constants/constants.ts +20 -0
- package/src/decorators/auto.spec.ts +30 -0
- package/src/decorators/auto.ts +24 -0
- package/src/decorators/discriminatorKey.ts +1 -0
- package/src/decorators/dynamicRef.spec.ts +46 -0
- package/src/decorators/dynamicRef.ts +76 -0
- package/src/decorators/excludeIndexes.spec.ts +30 -0
- package/src/decorators/excludeIndexes.ts +24 -0
- package/src/decorators/expires.spec.ts +18 -0
- package/src/decorators/expires.ts +24 -0
- package/src/decorators/immutable.spec.ts +30 -0
- package/src/decorators/immutable.ts +26 -0
- package/src/decorators/indexed.spec.ts +19 -0
- package/src/decorators/indexed.ts +24 -0
- package/src/decorators/lowercase.spec.ts +30 -0
- package/src/decorators/lowercase.ts +24 -0
- package/src/decorators/model.ts +69 -0
- package/src/decorators/mongooseIndex.spec.ts +26 -0
- package/src/decorators/mongooseIndex.ts +35 -0
- package/src/decorators/mongooseIndexes.spec.ts +35 -0
- package/src/decorators/mongooseIndexes.ts +35 -0
- package/src/decorators/mongoosePlugin.spec.ts +25 -0
- package/src/decorators/mongoosePlugin.ts +20 -0
- package/src/decorators/numberDecimal.spec.ts +266 -0
- package/src/decorators/numberDecimal.ts +84 -0
- package/src/decorators/objectID.spec.ts +24 -0
- package/src/decorators/objectID.ts +39 -0
- package/src/decorators/postHook.spec.ts +44 -0
- package/src/decorators/postHook.ts +72 -0
- package/src/decorators/preHook.spec.ts +75 -0
- package/src/decorators/preHook.ts +70 -0
- package/src/decorators/ref.spec.ts +361 -0
- package/src/decorators/ref.ts +111 -0
- package/src/decorators/schema.ts +79 -0
- package/src/decorators/schemaIgnore.spec.ts +18 -0
- package/src/decorators/schemaIgnore.ts +24 -0
- package/src/decorators/select.spec.ts +18 -0
- package/src/decorators/select.ts +24 -0
- package/src/decorators/sparse.spec.ts +30 -0
- package/src/decorators/sparse.ts +26 -0
- package/src/decorators/text.spec.ts +30 -0
- package/src/decorators/text.ts +25 -0
- package/src/decorators/trim.spec.ts +18 -0
- package/src/decorators/trim.ts +23 -0
- package/src/decorators/unique.spec.ts +18 -0
- package/src/decorators/unique.ts +23 -0
- package/src/decorators/uppercase.spec.ts +30 -0
- package/src/decorators/uppercase.ts +24 -0
- package/src/decorators/versionKey.spec.ts +19 -0
- package/src/decorators/versionKey.ts +9 -0
- package/src/decorators/virtualRef.spec.ts +383 -0
- package/src/decorators/virtualRef.ts +73 -0
- package/src/index.ts +47 -0
- package/src/interfaces/MongooseConnectionOptions.ts +10 -0
- package/src/interfaces/MongooseDocument.ts +3 -0
- package/src/interfaces/MongooseModel.ts +10 -0
- package/src/interfaces/MongooseModelOptions.ts +8 -0
- package/src/interfaces/MongooseSchemaOptions.ts +51 -0
- package/src/interfaces/MongooseSchemaTypes.ts +5 -0
- package/src/interfaces/MongooseVirtualRefOptions.ts +10 -0
- package/src/interfaces/interfaces.ts +9 -0
- package/src/registries/MongooseModels.ts +3 -0
- package/src/services/MongooseConnection.spec.ts +70 -0
- package/src/services/MongooseConnections.ts +58 -0
- package/src/services/MongooseService.spec.ts +73 -0
- package/src/services/MongooseService.ts +77 -0
- package/src/utils/buildMongooseSchema.spec.ts +67 -0
- package/src/utils/createModel.spec.ts +49 -0
- package/src/utils/createModel.ts +54 -0
- package/src/utils/createSchema.spec.ts +771 -0
- package/src/utils/createSchema.ts +198 -0
- package/src/utils/resolveRefType.spec.ts +30 -0
- package/src/utils/resolveRefType.ts +18 -0
- package/src/utils/schemaOptions.spec.ts +68 -0
- 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.
|
|
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.
|
|
37
|
-
"@tsed/barrels": "8.0.
|
|
38
|
-
"@tsed/core": "8.0.
|
|
39
|
-
"@tsed/di": "8.0.
|
|
40
|
-
"@tsed/json-mapper": "8.0.
|
|
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.
|
|
43
|
-
"@tsed/testcontainers-mongo": "8.0.
|
|
44
|
-
"@tsed/typescript": "8.0.
|
|
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.
|
|
52
|
-
"@tsed/core": "8.0.
|
|
53
|
-
"@tsed/di": "8.0.
|
|
54
|
-
"@tsed/json-mapper": "8.0.
|
|
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.
|
|
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.
|
|
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.
|
|
19
|
+
<a href="https://tsed.dev/">Website</a>
|
|
20
20
|
<span> • </span>
|
|
21
|
-
<a href="https://tsed.
|
|
21
|
+
<a href="https://tsed.dev/getting-started/">Getting started</a>
|
|
22
22
|
<span> • </span>
|
|
23
23
|
<a href="https://api.tsed.io/rest/slack/tsedio/tsed">Slack</a>
|
|
24
24
|
<span> • </span>
|
|
@@ -27,7 +27,7 @@
|
|
|
27
27
|
|
|
28
28
|
<hr />
|
|
29
29
|
|
|
30
|
-
A package of Ts.ED framework. See website: https://tsed.
|
|
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.
|
|
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
|
+
}
|