@slango/mangusta 1.1.8 → 2.0.1
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/.turbo/turbo-build.log +1 -1
- package/.turbo/turbo-lint.log +1 -1
- package/.turbo/turbo-test.log +14 -14
- package/CHANGELOG.md +12 -0
- package/dist/middleware/password.d.ts.map +1 -1
- package/dist/middleware/password.js +3 -11
- package/dist/middleware/password.js.map +1 -1
- package/dist/middleware/reactions.d.ts.map +1 -1
- package/dist/middleware/reactions.js +23 -34
- package/dist/middleware/reactions.js.map +1 -1
- package/dist/middleware/tags.d.ts.map +1 -1
- package/dist/middleware/tags.js +1 -2
- package/dist/middleware/tags.js.map +1 -1
- package/dist/middleware/timestamps.d.ts.map +1 -1
- package/dist/middleware/timestamps.js +10 -18
- package/dist/middleware/timestamps.js.map +1 -1
- package/package.json +8 -8
- package/src/middleware/compactId.spec.ts +21 -31
- package/src/middleware/owner.spec.ts +16 -27
- package/src/middleware/password.ts +4 -11
- package/src/middleware/reactions.spec.ts +22 -31
- package/src/middleware/reactions.ts +28 -40
- package/src/middleware/tags.spec.ts +19 -27
- package/src/middleware/tags.ts +1 -3
- package/src/middleware/timestamps.spec.ts +11 -23
- package/src/middleware/timestamps.ts +11 -19
- package/src/test-utils/model.ts +29 -0
- package/tsconfig.build.json +1 -1
- package/tsconfig.build.tsbuildinfo +1 -1
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
import { setupMongoTestEnvironment } from '@slango.configs/vitest/helpers/mongooseTestEnvironment';
|
|
2
|
-
import
|
|
2
|
+
import { Document, Schema, Types } from 'mongoose';
|
|
3
3
|
import { describe, expect, it } from 'vitest';
|
|
4
4
|
|
|
5
5
|
import type { PluginFunction } from '../types.js';
|
|
6
6
|
|
|
7
|
+
import { createModelWithPlugin } from '../test-utils/model.js';
|
|
7
8
|
import reactionsMiddleware, {
|
|
8
9
|
defaultReactionTypes,
|
|
9
10
|
ReactionCountSummary,
|
|
@@ -32,32 +33,22 @@ const createTestModel = <
|
|
|
32
33
|
TimestampField extends string = 'createdAt',
|
|
33
34
|
>(
|
|
34
35
|
options?: ReactionsMiddlewareOptions<Field, UserField, TypeField, TimestampField>,
|
|
35
|
-
) =>
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
ReactionsMiddlewareOptions<Field, UserField, TypeField, TimestampField>
|
|
48
|
-
>,
|
|
49
|
-
options,
|
|
50
|
-
);
|
|
51
|
-
} else {
|
|
52
|
-
TestSchema.plugin(reactionsMiddleware);
|
|
53
|
-
}
|
|
54
|
-
|
|
55
|
-
return model<TestDoc<Field, UserField, TypeField, TimestampField>>(modelName, TestSchema);
|
|
56
|
-
};
|
|
36
|
+
) =>
|
|
37
|
+
createModelWithPlugin<
|
|
38
|
+
TestDoc<Field, UserField, TypeField, TimestampField>,
|
|
39
|
+
ReactionsMiddlewareOptions<Field, UserField, TypeField, TimestampField>
|
|
40
|
+
>({
|
|
41
|
+
modelName: 'ReactionsTestDoc',
|
|
42
|
+
plugin: reactionsMiddleware as PluginFunction<
|
|
43
|
+
ReactionsMiddlewareOptions<Field, UserField, TypeField, TimestampField>
|
|
44
|
+
>,
|
|
45
|
+
pluginOptions: options,
|
|
46
|
+
buildSchema: () => new Schema<TestDoc<Field, UserField, TypeField, TimestampField>>({}),
|
|
47
|
+
});
|
|
57
48
|
|
|
58
49
|
describe('reactionsMiddleware', () => {
|
|
59
50
|
it('should add reactions field and persist entries with defaults', async () => {
|
|
60
|
-
const TestModel = createTestModel();
|
|
51
|
+
const { model: TestModel } = createTestModel();
|
|
61
52
|
const userId = new Types.ObjectId();
|
|
62
53
|
|
|
63
54
|
const doc = new TestModel();
|
|
@@ -74,7 +65,7 @@ describe('reactionsMiddleware', () => {
|
|
|
74
65
|
});
|
|
75
66
|
|
|
76
67
|
it('should deduplicate reactions for the same user when multiple reactions are disabled', async () => {
|
|
77
|
-
const TestModel = createTestModel();
|
|
68
|
+
const { model: TestModel } = createTestModel();
|
|
78
69
|
const userId = new Types.ObjectId();
|
|
79
70
|
|
|
80
71
|
const doc = new TestModel({
|
|
@@ -93,7 +84,7 @@ describe('reactionsMiddleware', () => {
|
|
|
93
84
|
});
|
|
94
85
|
|
|
95
86
|
it('should allow multiple reactions for the same user when enabled', async () => {
|
|
96
|
-
const TestModel = createTestModel({ allowMultiplePerUser: true });
|
|
87
|
+
const { model: TestModel } = createTestModel({ allowMultiplePerUser: true });
|
|
97
88
|
const userId = new Types.ObjectId();
|
|
98
89
|
|
|
99
90
|
const doc = new TestModel();
|
|
@@ -109,7 +100,7 @@ describe('reactionsMiddleware', () => {
|
|
|
109
100
|
});
|
|
110
101
|
|
|
111
102
|
it('should expose helper methods for managing reactions', async () => {
|
|
112
|
-
const TestModel = createTestModel();
|
|
103
|
+
const { model: TestModel } = createTestModel();
|
|
113
104
|
const userId = new Types.ObjectId();
|
|
114
105
|
|
|
115
106
|
const doc = new TestModel();
|
|
@@ -135,7 +126,7 @@ describe('reactionsMiddleware', () => {
|
|
|
135
126
|
});
|
|
136
127
|
|
|
137
128
|
it('should reject unsupported reaction types', async () => {
|
|
138
|
-
const TestModel = createTestModel();
|
|
129
|
+
const { model: TestModel } = createTestModel();
|
|
139
130
|
const userId = new Types.ObjectId();
|
|
140
131
|
const doc = new TestModel();
|
|
141
132
|
|
|
@@ -150,7 +141,7 @@ describe('reactionsMiddleware', () => {
|
|
|
150
141
|
});
|
|
151
142
|
|
|
152
143
|
it('should allow custom configuration for field and helper schema options', async () => {
|
|
153
|
-
const TestModel = createTestModel<'feedback', 'member', 'category', 'time'>({
|
|
144
|
+
const { model: TestModel, schema } = createTestModel<'feedback', 'member', 'category', 'time'>({
|
|
154
145
|
field: 'feedback',
|
|
155
146
|
userField: 'member',
|
|
156
147
|
typeField: 'category',
|
|
@@ -176,7 +167,7 @@ describe('reactionsMiddleware', () => {
|
|
|
176
167
|
|
|
177
168
|
await expect(doc.save()).resolves.not.toThrow();
|
|
178
169
|
|
|
179
|
-
const indexes =
|
|
170
|
+
const indexes = schema.indexes();
|
|
180
171
|
const categoryIndex = indexes.find(([fields]) =>
|
|
181
172
|
Object.prototype.hasOwnProperty.call(fields, 'feedback.category'),
|
|
182
173
|
);
|
|
@@ -194,7 +185,7 @@ describe('reactionsMiddleware', () => {
|
|
|
194
185
|
});
|
|
195
186
|
|
|
196
187
|
it('should support disabling timestamps', async () => {
|
|
197
|
-
const TestModel = createTestModel({ timestamp: false });
|
|
188
|
+
const { model: TestModel } = createTestModel({ timestamp: false });
|
|
198
189
|
const userId = new Types.ObjectId();
|
|
199
190
|
|
|
200
191
|
const doc = new TestModel();
|
|
@@ -185,55 +185,43 @@ const reactionsMiddleware: PluginFunction<ReactionsMiddlewareOptions> = <
|
|
|
185
185
|
return normalized;
|
|
186
186
|
};
|
|
187
187
|
|
|
188
|
-
schema.pre<DocType>('save', function reactionsPreSave(
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
188
|
+
schema.pre<DocType>('save', function reactionsPreSave(this: DocType) {
|
|
189
|
+
const existing =
|
|
190
|
+
(this.get(field) as ReactionEntry<UserField, TypeField, TimestampField>[] | undefined) ?? [];
|
|
191
|
+
|
|
192
|
+
if (!existing.length) {
|
|
193
|
+
return;
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
const normalizedEntries: ReactionEntry<UserField, TypeField, TimestampField>[] = [];
|
|
197
|
+
const seenUsers = new Map<string, number>();
|
|
198
|
+
let modified = false;
|
|
199
|
+
|
|
200
|
+
for (const entry of existing) {
|
|
201
|
+
const normalized = normalizeEntry(entry);
|
|
202
|
+
if (!normalized) {
|
|
203
|
+
modified = true;
|
|
204
|
+
continue;
|
|
196
205
|
}
|
|
197
206
|
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
207
|
+
if (!allowMultiplePerUser) {
|
|
208
|
+
const userKey = normalized[userField].toString();
|
|
209
|
+
const idx = seenUsers.get(userKey);
|
|
201
210
|
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
if (!normalized) {
|
|
211
|
+
if (idx !== undefined) {
|
|
212
|
+
normalizedEntries[idx] = normalized;
|
|
205
213
|
modified = true;
|
|
206
|
-
continue;
|
|
207
|
-
}
|
|
208
|
-
|
|
209
|
-
if (!allowMultiplePerUser) {
|
|
210
|
-
const userKey = normalized[userField].toString();
|
|
211
|
-
const idx = seenUsers.get(userKey);
|
|
212
|
-
|
|
213
|
-
if (idx !== undefined) {
|
|
214
|
-
normalizedEntries[idx] = normalized;
|
|
215
|
-
modified = true;
|
|
216
|
-
} else {
|
|
217
|
-
seenUsers.set(userKey, normalizedEntries.length);
|
|
218
|
-
normalizedEntries.push(normalized);
|
|
219
|
-
}
|
|
220
214
|
} else {
|
|
215
|
+
seenUsers.set(userKey, normalizedEntries.length);
|
|
221
216
|
normalizedEntries.push(normalized);
|
|
222
217
|
}
|
|
218
|
+
} else {
|
|
219
|
+
normalizedEntries.push(normalized);
|
|
223
220
|
}
|
|
221
|
+
}
|
|
224
222
|
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
}
|
|
228
|
-
|
|
229
|
-
next();
|
|
230
|
-
} catch (err) {
|
|
231
|
-
if (err instanceof Error) {
|
|
232
|
-
next(err);
|
|
233
|
-
return;
|
|
234
|
-
}
|
|
235
|
-
|
|
236
|
-
next(new Error('Unknown error while normalizing reactions.'));
|
|
223
|
+
if (normalizedEntries.length !== existing.length || modified) {
|
|
224
|
+
this.set(field, normalizedEntries);
|
|
237
225
|
}
|
|
238
226
|
});
|
|
239
227
|
|
|
@@ -1,33 +1,25 @@
|
|
|
1
1
|
import { setupMongoTestEnvironment } from '@slango.configs/vitest/helpers/mongooseTestEnvironment';
|
|
2
|
-
import mongoose, { Document
|
|
2
|
+
import mongoose, { Document } from 'mongoose';
|
|
3
3
|
import { describe, expect, it } from 'vitest';
|
|
4
4
|
|
|
5
|
+
import { createModelWithPlugin } from '../test-utils/model.js';
|
|
6
|
+
import { PluginFunction } from '../types.js';
|
|
5
7
|
import tagsMiddleware, { TagsMiddlewareOptions, WithTags } from './tags.js';
|
|
6
8
|
|
|
7
9
|
setupMongoTestEnvironment();
|
|
8
10
|
|
|
9
11
|
type TestDoc<Field extends string = 'tags'> = Document & WithTags<Field>;
|
|
10
12
|
|
|
11
|
-
const createTestModel = <Field extends string = 'tags'>(options?: TagsMiddlewareOptions<Field>) =>
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
}
|
|
17
|
-
|
|
18
|
-
const TestSchema = new Schema<TestDoc<Field>>({});
|
|
19
|
-
if (options) {
|
|
20
|
-
TestSchema.plugin(tagsMiddleware, options as TagsMiddlewareOptions);
|
|
21
|
-
} else {
|
|
22
|
-
TestSchema.plugin(tagsMiddleware);
|
|
23
|
-
}
|
|
24
|
-
|
|
25
|
-
return model<TestDoc<Field>>(modelName, TestSchema);
|
|
26
|
-
};
|
|
13
|
+
const createTestModel = <Field extends string = 'tags'>(options?: TagsMiddlewareOptions<Field>) =>
|
|
14
|
+
createModelWithPlugin<TestDoc<Field>, TagsMiddlewareOptions<Field>>({
|
|
15
|
+
modelName: 'TestDoc',
|
|
16
|
+
plugin: tagsMiddleware as PluginFunction<TagsMiddlewareOptions<Field>>,
|
|
17
|
+
pluginOptions: options,
|
|
18
|
+
});
|
|
27
19
|
|
|
28
20
|
describe('tagsMiddleware', () => {
|
|
29
21
|
it('should add a "tags" field with correct content if tags are provided', async () => {
|
|
30
|
-
const TestModel = createTestModel();
|
|
22
|
+
const { model: TestModel } = createTestModel();
|
|
31
23
|
const doc = new TestModel({ tags: ['tag1', 'tag2'] });
|
|
32
24
|
|
|
33
25
|
await expect(doc.save()).resolves.not.toThrow();
|
|
@@ -38,7 +30,7 @@ describe('tagsMiddleware', () => {
|
|
|
38
30
|
});
|
|
39
31
|
|
|
40
32
|
it('should add a "tags" field with empty array if no tag is provided', async () => {
|
|
41
|
-
const TestModel = createTestModel();
|
|
33
|
+
const { model: TestModel } = createTestModel();
|
|
42
34
|
const doc = new TestModel({});
|
|
43
35
|
|
|
44
36
|
await expect(doc.save()).resolves.not.toThrow();
|
|
@@ -49,7 +41,7 @@ describe('tagsMiddleware', () => {
|
|
|
49
41
|
});
|
|
50
42
|
|
|
51
43
|
it('should ensure uniqueness of tags if "unique" is set to true', async () => {
|
|
52
|
-
const TestModel = createTestModel({ unique: true });
|
|
44
|
+
const { model: TestModel } = createTestModel({ unique: true });
|
|
53
45
|
const doc = new TestModel({ tags: ['tag1', 'tag2', 'tag1'] });
|
|
54
46
|
|
|
55
47
|
await expect(doc.save()).resolves.not.toThrow();
|
|
@@ -60,7 +52,7 @@ describe('tagsMiddleware', () => {
|
|
|
60
52
|
});
|
|
61
53
|
|
|
62
54
|
it('should not enforce uniqueness if "unique" is set to false', async () => {
|
|
63
|
-
const TestModel = createTestModel({ unique: false });
|
|
55
|
+
const { model: TestModel } = createTestModel({ unique: false });
|
|
64
56
|
const doc = new TestModel({ tags: ['tag1', 'tag2', 'tag1'] });
|
|
65
57
|
|
|
66
58
|
await expect(doc.save()).resolves.not.toThrow();
|
|
@@ -71,7 +63,7 @@ describe('tagsMiddleware', () => {
|
|
|
71
63
|
});
|
|
72
64
|
|
|
73
65
|
it('should validate tags with custom validation function', async () => {
|
|
74
|
-
const TestModel = createTestModel({
|
|
66
|
+
const { model: TestModel } = createTestModel({
|
|
75
67
|
validate: (tags) => tags.every((tag) => tag.startsWith('valid')),
|
|
76
68
|
});
|
|
77
69
|
|
|
@@ -83,7 +75,7 @@ describe('tagsMiddleware', () => {
|
|
|
83
75
|
});
|
|
84
76
|
|
|
85
77
|
it('should allow configuring the field name', async () => {
|
|
86
|
-
const TestModel = createTestModel<'customTags'>({ field: 'customTags' });
|
|
78
|
+
const { model: TestModel } = createTestModel<'customTags'>({ field: 'customTags' });
|
|
87
79
|
const doc = new TestModel({ customTags: ['tag1', 'tag2'] });
|
|
88
80
|
|
|
89
81
|
await expect(doc.save()).resolves.not.toThrow();
|
|
@@ -94,16 +86,16 @@ describe('tagsMiddleware', () => {
|
|
|
94
86
|
});
|
|
95
87
|
|
|
96
88
|
it('should add a text index when index is set to "text"', () => {
|
|
97
|
-
const
|
|
98
|
-
const indexes =
|
|
89
|
+
const { schema } = createTestModel({ index: 'text' });
|
|
90
|
+
const indexes = schema.indexes();
|
|
99
91
|
|
|
100
92
|
const textIndex = indexes.find(([fields]) => fields.tags === 'text');
|
|
101
93
|
expect(textIndex).toBeDefined();
|
|
102
94
|
});
|
|
103
95
|
|
|
104
96
|
it('should add a hashed index when index is set to "hashed"', () => {
|
|
105
|
-
const
|
|
106
|
-
const indexes =
|
|
97
|
+
const { schema } = createTestModel({ index: 'hashed' });
|
|
98
|
+
const indexes = schema.indexes();
|
|
107
99
|
|
|
108
100
|
const textIndex = indexes.find(([fields]) => fields.tags === 'hashed');
|
|
109
101
|
expect(textIndex).toBeDefined();
|
package/src/middleware/tags.ts
CHANGED
|
@@ -43,13 +43,11 @@ const tagsMiddleware: PluginFunction<TagsMiddlewareOptions> = <
|
|
|
43
43
|
schema.index({ [field]: index });
|
|
44
44
|
}
|
|
45
45
|
|
|
46
|
-
schema.pre<DocType>('save', function schemaWithTagsPreSave(
|
|
46
|
+
schema.pre<DocType>('save', function schemaWithTagsPreSave(this: DocType) {
|
|
47
47
|
const tags = this.get(field) as DocType[Field];
|
|
48
48
|
if (unique && tags) {
|
|
49
49
|
this.set(field, Array.from(new Set(tags)));
|
|
50
50
|
}
|
|
51
|
-
|
|
52
|
-
next();
|
|
53
51
|
});
|
|
54
52
|
};
|
|
55
53
|
|
|
@@ -1,37 +1,25 @@
|
|
|
1
1
|
import { setupMongoTestEnvironment } from '@slango.configs/vitest/helpers/mongooseTestEnvironment';
|
|
2
|
-
import
|
|
2
|
+
import { Document } from 'mongoose';
|
|
3
3
|
import { setTimeout as delay } from 'node:timers/promises';
|
|
4
4
|
import { describe, expect, it } from 'vitest';
|
|
5
5
|
|
|
6
|
+
import { createModelWithPlugin } from '../test-utils/model.js';
|
|
6
7
|
import timestampsMiddleware, { TimestampsMiddlewareOptions, WithTimestamps } from './timestamps.js';
|
|
7
8
|
|
|
8
9
|
setupMongoTestEnvironment();
|
|
9
10
|
|
|
10
11
|
type TestDoc = Document & WithTimestamps & { name: string };
|
|
11
12
|
|
|
12
|
-
const createTestModel = (options?: TimestampsMiddlewareOptions) =>
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
}
|
|
18
|
-
|
|
19
|
-
const TestSchema = new Schema<TestDoc>({
|
|
20
|
-
name: String,
|
|
13
|
+
const createTestModel = (options?: TimestampsMiddlewareOptions) =>
|
|
14
|
+
createModelWithPlugin<TestDoc, TimestampsMiddlewareOptions>({
|
|
15
|
+
modelName: 'TestDoc',
|
|
16
|
+
plugin: timestampsMiddleware,
|
|
17
|
+
pluginOptions: options,
|
|
21
18
|
});
|
|
22
19
|
|
|
23
|
-
if (options) {
|
|
24
|
-
TestSchema.plugin(timestampsMiddleware, options);
|
|
25
|
-
} else {
|
|
26
|
-
TestSchema.plugin(timestampsMiddleware);
|
|
27
|
-
}
|
|
28
|
-
|
|
29
|
-
return model<TestDoc>(modelName, TestSchema);
|
|
30
|
-
};
|
|
31
|
-
|
|
32
20
|
describe('timestampsMiddleware', () => {
|
|
33
21
|
it('should store creation and update timestamps correctly on save', async () => {
|
|
34
|
-
const TestModel = createTestModel();
|
|
22
|
+
const { model: TestModel } = createTestModel();
|
|
35
23
|
const doc = new TestModel({ name: 'initial' });
|
|
36
24
|
|
|
37
25
|
await expect(doc.save()).resolves.not.toThrow();
|
|
@@ -56,7 +44,7 @@ describe('timestampsMiddleware', () => {
|
|
|
56
44
|
});
|
|
57
45
|
|
|
58
46
|
it('should update timestamp when using updateOne operations', async () => {
|
|
59
|
-
const TestModel = createTestModel();
|
|
47
|
+
const { model: TestModel } = createTestModel();
|
|
60
48
|
const doc = new TestModel({ name: 'initial' });
|
|
61
49
|
await doc.save();
|
|
62
50
|
|
|
@@ -72,8 +60,8 @@ describe('timestampsMiddleware', () => {
|
|
|
72
60
|
});
|
|
73
61
|
|
|
74
62
|
it('should add an index on the update field when indexUpdate is true', () => {
|
|
75
|
-
const
|
|
76
|
-
const indexes =
|
|
63
|
+
const { schema } = createTestModel({ indexUpdate: true });
|
|
64
|
+
const indexes = schema.indexes();
|
|
77
65
|
|
|
78
66
|
const index = indexes.find(([fields]) => fields.updated === 1);
|
|
79
67
|
expect(index).toBeDefined();
|
|
@@ -54,29 +54,21 @@ const timestampsMiddleware: PluginFunction<TimestampsMiddlewareOptions> = <
|
|
|
54
54
|
);
|
|
55
55
|
}
|
|
56
56
|
|
|
57
|
-
schema.pre('save', function schemaWithTimestampsPreSave(
|
|
58
|
-
|
|
59
|
-
const now = new Date();
|
|
57
|
+
schema.pre<DocType>('save', function schemaWithTimestampsPreSave(this: DocType) {
|
|
58
|
+
const now = new Date();
|
|
60
59
|
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
60
|
+
if (creation && this.isNew && !this.get(creationField)) {
|
|
61
|
+
this.set(creationField, now);
|
|
62
|
+
}
|
|
64
63
|
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
this.set(updateField, now);
|
|
69
|
-
}
|
|
70
|
-
// else: do nothing so it's undefined
|
|
71
|
-
} else {
|
|
64
|
+
if (update) {
|
|
65
|
+
if (this.isNew) {
|
|
66
|
+
if (updateTimestampOnCreation) {
|
|
72
67
|
this.set(updateField, now);
|
|
73
68
|
}
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
} catch (err) {
|
|
78
|
-
if (err instanceof Error) {
|
|
79
|
-
next(err);
|
|
69
|
+
// else: do nothing so it's undefined
|
|
70
|
+
} else {
|
|
71
|
+
this.set(updateField, now);
|
|
80
72
|
}
|
|
81
73
|
}
|
|
82
74
|
});
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import mongoose, { Document, Model, Schema } from 'mongoose';
|
|
2
|
+
|
|
3
|
+
import { PluginFunction } from '../types.js';
|
|
4
|
+
|
|
5
|
+
export interface CreateModelWithPluginParams<Doc extends Document, Options> {
|
|
6
|
+
buildSchema?: () => Schema<Doc>;
|
|
7
|
+
modelName: string;
|
|
8
|
+
plugin: PluginFunction<Options>;
|
|
9
|
+
pluginOptions?: Options;
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
export const createModelWithPlugin = <Doc extends Document, Options>({
|
|
13
|
+
buildSchema,
|
|
14
|
+
modelName,
|
|
15
|
+
plugin,
|
|
16
|
+
pluginOptions,
|
|
17
|
+
}: CreateModelWithPluginParams<Doc, Options>): { model: Model<Doc>; schema: Schema<Doc> } => {
|
|
18
|
+
if (mongoose.models[modelName]) {
|
|
19
|
+
delete mongoose.models[modelName];
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
const schema = buildSchema ? buildSchema() : new Schema<Doc>({});
|
|
23
|
+
|
|
24
|
+
schema.plugin(plugin, pluginOptions);
|
|
25
|
+
|
|
26
|
+
const modelInstance = mongoose.model<Doc>(modelName, schema);
|
|
27
|
+
|
|
28
|
+
return { model: modelInstance, schema };
|
|
29
|
+
};
|
package/tsconfig.build.json
CHANGED