mongoose-tsgen
Version:
A Typescript interface generator for Mongoose that works out of the box.
170 lines (162 loc) • 6.79 kB
JavaScript
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.getSubdocumentDocs = exports.getLeanDocs = exports.getSchemaDocs = exports.getDocumentDocs = exports.getModelDocs = exports.getQueryHelpersDocs = exports.getQueryDocs = exports.getObjectDocs = exports.QUERY_POPULATE = exports.POPULATE_HELPERS = exports.MONGOOSE_IMPORT = exports.MAIN_HEADER = void 0;
exports.MAIN_HEADER = `/* tslint:disable */\n/* eslint-disable */\n\n// ######################################## THIS FILE WAS GENERATED BY MONGOOSE-TSGEN ######################################## //\n\n// NOTE: ANY CHANGES MADE WILL BE OVERWRITTEN ON SUBSEQUENT EXECUTIONS OF MONGOOSE-TSGEN.`;
exports.MONGOOSE_IMPORT = `import mongoose from "mongoose";`;
exports.POPULATE_HELPERS = `/**
* Check if a property on a document is populated:
* \`\`\`
* import { IsPopulated } from "../interfaces/mongoose.gen.ts"
*
* if (IsPopulated<UserDocument["bestFriend"]>) { ... }
* \`\`\`
*/
export function IsPopulated<T>(doc: T | mongoose.Types.ObjectId): doc is T {
return doc instanceof mongoose.Document;
}
/**
* Helper type used by \`PopulatedDocument\`. Returns the parent property of a string
* representing a nested property (i.e. \`friend.user\` -> \`friend\`)
*/
type ParentProperty<T> = T extends \`\${infer P}.\${string}\` ? P : never;
/**
* Helper type used by \`PopulatedDocument\`. Returns the child property of a string
* representing a nested property (i.e. \`friend.user\` -> \`user\`).
*/
type ChildProperty<T> = T extends \`\${string}.\${infer C}\` ? C : never;
/**
* Helper type used by \`PopulatedDocument\`. Removes the \`ObjectId\` from the general union type generated
* for ref documents (i.e. \`mongoose.Types.ObjectId | UserDocument\` -> \`UserDocument\`)
*/
type PopulatedProperty<Root, T extends keyof Root> = Omit<Root, T> & {
[ref in T]: Root[T] extends mongoose.Types.Array<infer U> ?
mongoose.Types.Array<Exclude<U, mongoose.Types.ObjectId>> :
Exclude<Root[T], mongoose.Types.ObjectId>
}
/**
* Populate properties on a document type:
* \`\`\`
* import { PopulatedDocument } from "../interfaces/mongoose.gen.ts"
*
* function example(user: PopulatedDocument<UserDocument, "bestFriend">) {
* console.log(user.bestFriend._id) // typescript knows this is populated
* }
* \`\`\`
*/
export type PopulatedDocument<
DocType,
T
> = T extends keyof DocType
? PopulatedProperty<DocType, T>
: (
ParentProperty<T> extends keyof DocType
? Omit<DocType, ParentProperty<T>> &
{
[ref in ParentProperty<T>]: (
DocType[ParentProperty<T>] extends mongoose.Types.Array<infer U> ? (
mongoose.Types.Array<
ChildProperty<T> extends keyof U
? PopulatedProperty<U, ChildProperty<T>>
: PopulatedDocument<U, ChildProperty<T>>
>
) : (
ChildProperty<T> extends keyof DocType[ParentProperty<T>]
? PopulatedProperty<DocType[ParentProperty<T>], ChildProperty<T>>
: PopulatedDocument<DocType[ParentProperty<T>], ChildProperty<T>>
)
)
}
: DocType
)
`;
exports.QUERY_POPULATE = `/**
* Helper types used by the populate overloads
*/
type Unarray<T> = T extends Array<infer U> ? U : T;
type Modify<T, R> = Omit<T, keyof R> & R;
/**
* Augment mongoose with Query.populate overloads
*/
declare module "mongoose" {
interface Query<ResultType, DocType, THelpers = {}> {
populate<T extends string>(path: T, select?: string | any, model?: string | Model<any, THelpers>, match?: any): Query<
ResultType extends Array<DocType> ? Array<PopulatedDocument<Unarray<ResultType>, T>> : (ResultType extends DocType ? PopulatedDocument<Unarray<ResultType>, T> : ResultType),
DocType,
THelpers
> & THelpers;
populate<T extends string>(options: Modify<PopulateOptions, { path: T }> | Array<PopulateOptions>): Query<
ResultType extends Array<DocType> ? Array<PopulatedDocument<Unarray<ResultType>, T>> : (ResultType extends DocType ? PopulatedDocument<Unarray<ResultType>, T> : ResultType),
DocType,
THelpers
> & THelpers;
}
}`;
const getObjectDocs = (modelName) => `/**
* Lean version of ${modelName}Document (type alias of \`${modelName}\`)
*
* Use this type alias to avoid conflicts with model names:
* \`\`\`
* import { ${modelName} } from "../models"
* import { ${modelName}Object } from "../interfaces/mongoose.gen.ts"
*
* const ${modelName.toLowerCase()}Object: ${modelName}Object = ${modelName.toLowerCase()}.toObject();
* \`\`\`
*/`;
exports.getObjectDocs = getObjectDocs;
const getQueryDocs = () => `/**
* Mongoose Query type
*
* This type is returned from query functions. For most use cases, you should not need to use this type explicitly.
*/`;
exports.getQueryDocs = getQueryDocs;
const getQueryHelpersDocs = (modelName) => `/**
* Mongoose Query helper types
*
* This type represents \`${modelName}Schema.query\`. For most use cases, you should not need to use this type explicitly.
*/`;
exports.getQueryHelpersDocs = getQueryHelpersDocs;
const getModelDocs = (modelName) => `/**
* Mongoose Model type
*
* Pass this type to the Mongoose Model constructor:
* \`\`\`
* const ${modelName} = mongoose.model<${modelName}Document, ${modelName}Model>("${modelName}", ${modelName}Schema);
* \`\`\`
*/`;
exports.getModelDocs = getModelDocs;
const getDocumentDocs = (modelName) => `/**
* Mongoose Document type
*
* Pass this type to the Mongoose Model constructor:
* \`\`\`
* const ${modelName} = mongoose.model<${modelName}Document, ${modelName}Model>("${modelName}", ${modelName}Schema);
* \`\`\`
*/`;
exports.getDocumentDocs = getDocumentDocs;
const getSchemaDocs = (modelName) => `/**
* Mongoose Schema type
*
* Assign this type to new ${modelName} schema instances:
* \`\`\`
* const ${modelName}Schema: ${modelName}Schema = new mongoose.Schema({ ... })
* \`\`\`
*/`;
exports.getSchemaDocs = getSchemaDocs;
// If model is a subdoc, pass `fullName`
const getLeanDocs = (modelName, fullName) => `/**
* Lean version of ${fullName !== null && fullName !== void 0 ? fullName : modelName}Document
*
* This has all Mongoose getters & functions removed. This type will be returned from \`${modelName}Document.toObject()\`.${!fullName || modelName === fullName ?
` To avoid conflicts with model names, use the type alias \`${modelName}Object\`.` :
""}
* \`\`\`
* const ${modelName.toLowerCase()}Object = ${modelName.toLowerCase()}.toObject();
* \`\`\`
*/`;
exports.getLeanDocs = getLeanDocs;
const getSubdocumentDocs = (modelName, path) => `/**
* Mongoose Subdocument type
*
* Type of \`${modelName}Document["${path}"]\` element.
*/`;
exports.getSubdocumentDocs = getSubdocumentDocs;