UNPKG

8.43 kBTypeScriptView Raw
1import {
2 Schema,
3 InferSchemaType,
4 SchemaType,
5 SchemaTypeOptions,
6 TypeKeyBaseType,
7 Types,
8 NumberSchemaDefinition,
9 StringSchemaDefinition,
10 BooleanSchemaDefinition,
11 DateSchemaDefinition,
12 ObtainDocumentType,
13 DefaultTypeKey,
14 ObjectIdSchemaDefinition,
15 IfEquals
16} from 'mongoose';
17
18declare module 'mongoose' {
19 /**
20 * @summary Obtains document schema type.
21 * @description Obtains document schema type from document Definition OR returns enforced schema type if it's provided.
22 * @param {DocDefinition} DocDefinition A generic equals to the type of document definition "provided in as first parameter in Schema constructor".
23 * @param {EnforcedDocType} EnforcedDocType A generic type enforced by user "provided before schema constructor".
24 * @param {TypeKey} TypeKey A generic of literal string type."Refers to the property used for path type definition".
25 */
26 type ObtainDocumentType<DocDefinition, EnforcedDocType = any, TypeKey extends TypeKeyBaseType = DefaultTypeKey> =
27 IsItRecordAndNotAny<EnforcedDocType> extends true ? EnforcedDocType : {
28 [K in keyof (RequiredPaths<DocDefinition, TypeKey> &
29 OptionalPaths<DocDefinition, TypeKey>)]: ObtainDocumentPathType<DocDefinition[K], TypeKey>;
30 };
31
32 /**
33 * @summary Obtains document schema type from Schema instance.
34 * @param {SchemaType} SchemaType A generic of schema type instance.
35 * @example
36 * const userSchema = new Schema({userName:String});
37 * type UserType = InferSchemaType<typeof userSchema>;
38 * // result
39 * type UserType = {userName?: string}
40 */
41 type InferSchemaType<SchemaType> = ObtainSchemaGeneric<SchemaType, 'DocType'>;
42
43 /**
44 * @summary Obtains schema Generic type by using generic alias.
45 * @param {TSchema} TSchema A generic of schema type instance.
46 * @param {alias} alias Targeted generic alias.
47 */
48 type ObtainSchemaGeneric<TSchema, alias extends 'EnforcedDocType' | 'M' | 'TInstanceMethods' | 'TQueryHelpers' | 'TVirtuals' | 'TStaticMethods' | 'TPathTypeKey' | 'DocType'> =
49 TSchema extends Schema<infer EnforcedDocType, infer M, infer TInstanceMethods, infer TQueryHelpers, infer TVirtuals, infer TStaticMethods, infer TPathTypeKey, infer DocType>
50 ? {
51 EnforcedDocType: EnforcedDocType;
52 M: M;
53 TInstanceMethods: TInstanceMethods;
54 TQueryHelpers: TQueryHelpers;
55 TVirtuals: TVirtuals;
56 TStaticMethods: TStaticMethods;
57 TPathTypeKey: TPathTypeKey;
58 DocType: DocType;
59 }[alias]
60 : unknown;
61}
62
63/**
64 * @summary Checks if a document path is required or optional.
65 * @param {P} P Document path.
66 * @param {TypeKey} TypeKey A generic of literal string type."Refers to the property used for path type definition".
67 */
68type IsPathRequired<P, TypeKey extends TypeKeyBaseType> =
69 P extends { required: true | [true, string | undefined] } | ArrayConstructor | any[]
70 ? true
71 : P extends (Record<TypeKey, ArrayConstructor | any[]>)
72 ? P extends { default: undefined }
73 ? false
74 : true
75 : P extends (Record<TypeKey, any>)
76 ? P extends { default: any }
77 ? IfEquals<P['default'], undefined, false, true>
78 : false
79 : false;
80
81/**
82 * @summary Path base type defined by using TypeKey
83 * @description It helps to check if a path is defined by TypeKey OR not.
84 * @param {TypeKey} TypeKey A literal string refers to path type property key.
85 */
86type PathWithTypePropertyBaseType<TypeKey extends TypeKeyBaseType> = { [k in TypeKey]: any };
87
88/**
89 * @summary A Utility to obtain schema's required path keys.
90 * @param {T} T A generic refers to document definition.
91 * @param {TypeKey} TypeKey A generic of literal string type."Refers to the property used for path type definition".
92 * @returns required paths keys of document definition.
93 */
94type RequiredPathKeys<T, TypeKey extends TypeKeyBaseType> = {
95 [K in keyof T]: IsPathRequired<T[K], TypeKey> extends true ? IfEquals<T[K], any, never, K> : never;
96}[keyof T];
97
98/**
99 * @summary A Utility to obtain schema's required paths.
100 * @param {T} T A generic refers to document definition.
101 * @param {TypeKey} TypeKey A generic of literal string type."Refers to the property used for path type definition".
102 * @returns a record contains required paths with the corresponding type.
103 */
104type RequiredPaths<T, TypeKey extends TypeKeyBaseType> = {
105 [K in RequiredPathKeys<T, TypeKey>]: T[K];
106};
107
108/**
109 * @summary A Utility to obtain schema's optional path keys.
110 * @param {T} T A generic refers to document definition.
111 * @param {TypeKey} TypeKey A generic of literal string type."Refers to the property used for path type definition".
112 * @returns optional paths keys of document definition.
113 */
114type OptionalPathKeys<T, TypeKey extends TypeKeyBaseType> = {
115 [K in keyof T]: IsPathRequired<T[K], TypeKey> extends true ? never : K;
116}[keyof T];
117
118/**
119 * @summary A Utility to obtain schema's optional paths.
120 * @param {T} T A generic refers to document definition.
121 * @param {TypeKey} TypeKey A generic of literal string type."Refers to the property used for path type definition".
122 * @returns a record contains optional paths with the corresponding type.
123 */
124type OptionalPaths<T, TypeKey extends TypeKeyBaseType> = {
125 [K in OptionalPathKeys<T, TypeKey>]?: T[K];
126};
127
128/**
129 * @summary Obtains schema Path type.
130 * @description Obtains Path type by calling {@link ResolvePathType} OR by calling {@link InferSchemaType} if path of schema type.
131 * @param {PathValueType} PathValueType Document definition path type.
132 * @param {TypeKey} TypeKey A generic refers to document definition.
133 */
134type ObtainDocumentPathType<PathValueType, TypeKey extends TypeKeyBaseType> = PathValueType extends Schema<any>
135 ? InferSchemaType<PathValueType>
136 : ResolvePathType<
137 PathValueType extends PathWithTypePropertyBaseType<TypeKey> ? PathValueType[TypeKey] : PathValueType,
138 PathValueType extends PathWithTypePropertyBaseType<TypeKey> ? Omit<PathValueType, TypeKey> : {},
139 TypeKey
140 >;
141
142/**
143 * @param {T} T A generic refers to string path enums.
144 * @returns Path enum values type as literal strings or string.
145 */
146type PathEnumOrString<T extends SchemaTypeOptions<string>['enum']> = T extends (infer E)[] ? E : T extends { values: any } ? PathEnumOrString<T['values']> : string;
147
148/**
149 * @summary Resolve path type by returning the corresponding type.
150 * @param {PathValueType} PathValueType Document definition path type.
151 * @param {Options} Options Document definition path options except path type.
152 * @param {TypeKey} TypeKey A generic of literal string type."Refers to the property used for path type definition".
153 * @returns Number, "Number" or "number" will be resolved to number type.
154 */
155type ResolvePathType<PathValueType, Options extends SchemaTypeOptions<PathValueType> = {}, TypeKey extends TypeKeyBaseType = DefaultTypeKey> =
156 PathValueType extends Schema ? InferSchemaType<PathValueType> :
157 PathValueType extends (infer Item)[] ? IfEquals<Item, never, any[], Item extends Schema ? Types.DocumentArray<ResolvePathType<Item>> : ResolvePathType<Item>[]> :
158 PathValueType extends StringSchemaDefinition ? PathEnumOrString<Options['enum']> :
159 PathValueType extends NumberSchemaDefinition ? Options['enum'] extends ReadonlyArray<any> ? Options['enum'][number] : number :
160 PathValueType extends DateSchemaDefinition ? Date :
161 PathValueType extends typeof Buffer | 'buffer' | 'Buffer' | typeof Schema.Types.Buffer ? Buffer :
162 PathValueType extends BooleanSchemaDefinition ? boolean :
163 PathValueType extends ObjectIdSchemaDefinition ? Types.ObjectId :
164 PathValueType extends 'decimal128' | 'Decimal128' | typeof Schema.Types.Decimal128 ? Types.Decimal128 :
165 PathValueType extends MapConstructor ? Map<string, ResolvePathType<Options['of']>> :
166 PathValueType extends ArrayConstructor ? any[] :
167 PathValueType extends typeof Schema.Types.Mixed ? any:
168 IfEquals<PathValueType, ObjectConstructor> extends true ? any:
169 IfEquals<PathValueType, {}> extends true ? any:
170 PathValueType extends typeof SchemaType ? PathValueType['prototype'] :
171 PathValueType extends Record<string, any> ? ObtainDocumentType<PathValueType, any, TypeKey> :
172 unknown;