arashsheyda / nuxt-mongoose

A Nuxt module for simplifying the use of Mongoose in your project.
https://docs.arashsheyda.me/nuxt-mongoose
69 stars 11 forks source link

Difficulty with typeScript model definitions and generic declarations in mongoose #12

Open tarkantoan opened 11 months ago

tarkantoan commented 11 months ago

Hello, I'm having difficulty defining models with TypeScript. Even though I've added Mongoose as a devDependency, I'm noticing some shortcomings in the generic declarations. If you'd like, I can do a little work and submit a pull request, or if you have a specific roadmap, could you please share it?

arashsheyda commented 11 months ago

@tarkantoan Sure! PR is welcome. Thanks

xarenas107 commented 6 months ago

You can try with something like this. Is not the prettiest solution but it should work .

import { model, Schema } from 'mongoose'
import type {
    SchemaDefinition, SchemaOptions, Model, SchemaDefinitionType,
    DefaultSchemaOptions, ApplySchemaOptions, ObtainDocumentType,
    ResolveSchemaOptions, FlatRecord, InferSchemaType, ObtainSchemaGeneric, HydratedDocument
} from 'mongoose'

type Options<D,I,Q,S,V,H,O> = SchemaOptions<FlatRecord<D>, I, Q, S, V, H> | ResolveSchemaOptions<O>
type ApplyOptions<T,D,O> = ApplySchemaOptions<ObtainDocumentType<D, T, ResolveSchemaOptions<O>>,ResolveSchemaOptions<O>>
export function defineMongooseModel<T, I={}, Q={}, V={}, S={},
    M = Model<T,Q,I,V>,
    O = DefaultSchemaOptions,
    D extends ApplyOptions<T,D,O> = ApplyOptions<T,any,O>,
    H = HydratedDocument<FlatRecord<D>, V & I>,
    TSchema = Schema<T, M, I, Q, V, S, O, D, H>
    >(
    document: string | {
        name: string,
        collection?: string
    },
    schema?: SchemaDefinition<SchemaDefinitionType<T>, T> | D,
    options?: Options<D,I,Q,S,V,H,O>,
    hooks?: (schema: Schema<T, M, I, Q, V, S, O, D, H>) => void,
): Model<
  InferSchemaType<TSchema>,
  ObtainSchemaGeneric<TSchema, 'TQueryHelpers'>,
  ObtainSchemaGeneric<TSchema, 'TInstanceMethods'>,
  ObtainSchemaGeneric<TSchema, 'TVirtuals'>,
  HydratedDocument<
  InferSchemaType<TSchema>,
  ObtainSchemaGeneric<TSchema, 'TVirtuals'> & ObtainSchemaGeneric<TSchema, 'TInstanceMethods'>,
  ObtainSchemaGeneric<TSchema, 'TQueryHelpers'>
  >,
  TSchema
  > & ObtainSchemaGeneric<TSchema, 'TStaticMethods'>
export function defineMongooseModel<T,
    O = DefaultSchemaOptions,
    D extends ApplyOptions<T,D,O> = ApplyOptions<T,any,O>,
    H = HydratedDocument<FlatRecord<D>>
    >(
    document: string | {
        name: string,
        collection?: string
    },
    definition?: SchemaDefinition<T>,
    options?: Options<D,{},{},{},{},H,O>,
    hooks?: (schema: Schema<T>) => void,
): Model<T>
export function defineMongooseModel(...args:any[]) {
    const [document,schema,options,hooks] = args

  const name = typeof document === 'string' ? document : document?.name
  const collection = typeof document !== 'string' ? document?.collection : undefined

    const $schema = new Schema(schema, options)
    if (hooks) hooks($schema)

    const $model = model(name, $schema, collection)
    return $model
}