kindagoose
65 строк · 2.6 Кб
1import { DiscoveryService, MetadataScanner, Reflector } from '@nestjs/core';
2import { InstanceWrapper } from '@nestjs/core/injector/instance-wrapper';
3import { addModelToTypegoose, buildSchema, getName } from '@typegoose/typegoose';
4import { ModelType } from '@typegoose/typegoose/lib/types';
5import { Connection } from 'mongoose';
6
7import { EVENT_TRACKER_FOR_KEY, POST_METADATA_KEY, PRE_METADATA_KEY } from '../constants/kindagoose.constants';
8import { AnyClass } from '../interfaces/any-class.interface';
9import { getModelToken } from './get-model-token';
10
11export const discriminatorFactory = (discriminator: AnyClass, connectionName?: string) => {
12return (
13connection: Connection,
14model: ModelType<any>,
15discoveryService: DiscoveryService,
16reflector: Reflector,
17metadataScanner: MetadataScanner,
18) => {
19const existingDiscriminator = discoveryService
20.getProviders()
21.find(provider => provider.token === getModelToken(discriminator.name, connectionName))?.instance;
22
23if (existingDiscriminator) {
24return existingDiscriminator;
25}
26
27const providers = discoveryService.getProviders().filter(provider => provider.instance);
28let tracker: InstanceWrapper | null = null;
29
30for (const provider of providers) {
31const trackerMetadata = reflector.get(EVENT_TRACKER_FOR_KEY, provider.instance.constructor);
32
33if (trackerMetadata === discriminator.name) {
34tracker = provider;
35break;
36}
37}
38
39const mongooseDiscriminatorSchema = buildSchema(discriminator);
40
41if (tracker) {
42const { instance } = tracker;
43
44const methodNames = metadataScanner.getAllMethodNames(Object.getPrototypeOf(instance));
45
46for (const methodName of methodNames) {
47const propertyPreMetadata = reflector.get(PRE_METADATA_KEY, instance[methodName]) || [];
48const propertyPostMetadata = reflector.get(POST_METADATA_KEY, instance[methodName]) || [];
49
50for (const preEventName of propertyPreMetadata) {
51mongooseDiscriminatorSchema.pre(preEventName, instance[methodName].bind(instance));
52}
53
54for (const postEventName of propertyPostMetadata) {
55mongooseDiscriminatorSchema.post(postEventName, instance[methodName].bind(instance));
56}
57}
58}
59
60return addModelToTypegoose(
61model.discriminator(getName(discriminator), mongooseDiscriminatorSchema),
62discriminator,
63);
64};
65};
66