@mocking-bird/mongoose
Version:
Generates fixtures for `mongoose`. Simply provide the schema or model, and it will generate mock data based on the types and constraints of the schema.
324 lines (323 loc) • 12.5 kB
TypeScript
/// <reference types="mongoose/types/aggregate" />
/// <reference types="mongoose/types/callback" />
/// <reference types="mongoose/types/collection" />
/// <reference types="mongoose/types/connection" />
/// <reference types="mongoose/types/cursor" />
/// <reference types="mongoose/types/document" />
/// <reference types="mongoose/types/error" />
/// <reference types="mongoose/types/expressions" />
/// <reference types="mongoose/types/helpers" />
/// <reference types="mongoose/types/middlewares" />
/// <reference types="mongoose/types/indexes" />
/// <reference types="mongoose/types/models" />
/// <reference types="mongoose/types/mongooseoptions" />
/// <reference types="mongoose/types/pipelinestage" />
/// <reference types="mongoose/types/populate" />
/// <reference types="mongoose/types/query" />
/// <reference types="mongoose/types/schemaoptions" />
/// <reference types="mongoose/types/schematypes" />
/// <reference types="mongoose/types/session" />
/// <reference types="mongoose/types/types" />
/// <reference types="mongoose/types/utility" />
/// <reference types="mongoose/types/validation" />
/// <reference types="mongoose/types/virtuals" />
/// <reference types="mongoose/types/inferschematype" />
import { Model, Schema } from 'mongoose';
import { CoreFixture, FieldPath, FixtureOptions, Value } from '@mocking-bird/core';
/**
* ### Overview
*
* MongooseFixture class extending abstract CoreFixture class for generating mock data based on Mongoose models
* or schemas.
*
* @see CoreFixture
*
* @typeParam T The type of the document corresponding to the Mongoose model or schema.
*
* @example
* const Model = mongoose.model<IDocumentType>('ModelName', schema);
* const Schema = new mongoose.Schema({ name: String, age: Number });
*
* const modelFixture = new MongooseFixture(Model);
* const schemaFixture = new MongooseFixture(Schema);
*
* const data = modelFixture.generate();
* const multiple = schemaFixture.bulkGenerate(10);
*/
export declare class MongooseFixture<T> extends CoreFixture<T> {
private static readonly globalOptions;
private static readonly MONGOOSE_SPECIAL_CHARS_REGEX;
private static readonly NESTED_SCHEMA_INSTANCE;
private static readonly ARRAY_SCHEMA_INSTANCE;
private static readonly MAP_SCHEMA_INSTANCE;
private static readonly VERSION_KEY;
private readonly schema;
private readonly mongooseValidator;
/**
* Constructs a MongooseFixture instance.
*
* @param target The Mongoose model or schema to generate fixtures for. If a model is provided, the schema is
* extracted from it. If a schema is provided, it is used directly.
*/
constructor(target: Model<T> | Schema<T>);
/**
* Sets global options for the fixture generation.
*
* @param options Fixture options to be set globally. If an option is provided per function call, options
* provided via the parameter will override the global options.
*/
static setGlobalOptions(options: FixtureOptions): void;
/**
* Generates an array of mock data based on the schema.
*
* @inheritDoc
* @override
*
* @typeParam T The type of the document corresponding to the Mongoose model or schema.
*
* @throws {Error} same as {@link MongooseFixture#generate}
*
* @public
*/
bulkGenerate(size: number, overrideValues?: Record<FieldPath, Value>, options?: FixtureOptions): T[];
/**
* Generates a single mock data based on the schema.
*
* @inheritDoc
* @override
*
* @typeParam T The type of the document corresponding to the Mongoose model or schema.
*
* @throws {Error}
* For the following reasons:
*
* - If multiple override values are found for the same path. For example, { 'address.*.buildingNo': 42,
* 'address.street.buildingNo': 43 }.
* - If override value breaks the schema rule.
* - If a required field is excluded.
* - If a custom rule has conflict with the schema rule.
* - If the value generated does not match the custom rule or the schema rule.
*
* @public
*/
generate(overrideValues?: Record<FieldPath, Value>, options?: FixtureOptions): T;
/**
* Recursively generates values for nested schema.
* First, it iterates through each field in the schema and generates a value for each field.
* If a field is a nested schema, it will recursively generate values for the nested schema.
* During each iteration, it builds a sub path, e.g., 'address.street', 'address.street.city', etc.
*
* @example
* const schema = new Schema({
* name: String,
* address: {
* street: String,
* city: String,
* country: {
* name: String,
* code: String,
* }
* },
* phone: String,
* });
*
* For such a nested schema above, data will be generated for each child field in the schema.
*
* @param schemaNode The current level of the schema being processed.
* @param rootPath The root path for the current schema node. If undefined, the current schema node is the root.
* @param overrideValues Values to override in the schema.
* @param options Fixture generation options.
*
* @returns The generated mock data for the current schema node.
*
* @private
*/
private recursivelyGenerateValue;
/**
* Generates a value based on the schema type.
*
* We check if a field is nested by checking if it has a `schema` property.
* If a field has basic types such as String, Number, etc., it will not have a schema property.
* Whereas, if a field is an array or an embedded schema, it will have a schema property and will be recursively
* processed.
* Map types are also supported and processed in a special way, as they can be little more complex.
*
* @param path The path to the field.
* @param schemaType The schema type of the field.
* @param overrideValues Values to override in the schema.
* @param options Fixture generation options.
*
* @returns A mock value for the field or `undefined` if the field is either excluded or explicitly set to
* `undefined` in the override values.
*
* @private
*/
private generateValueForSchemaType;
/**
* Generates a value for a nested schema.
* Nested schema is a schema that either has an embedded schema or an array schema.
* Values are generated recursively.
*
* @param path The path to the field.
* @param schemaType The mongoose schema type of the field.
* @param overrideValues Values to override in the schema.
* @param options Fixture generation options.
*
* @returns A mock value for the field in the nested schema; `undefined` if the schema type is not a nested schema.
*
* @private
*/
private generateValueForNestedSchema;
/**
* Generates a value for an array schema.
* The process is similar to generating a value for a nested schema, except that it returns an array of values.
* If a size is provided in the `rule`, the array will be generated with the specified size.
*
* @param path The path to the field.
* @param schemaType The mongoose schema type of the field.
* @param overrideValues Values to override in the schema.
* @param options Fixture generation options.
*
* @returns An array of mock values
*
* @private
*/
private generateValueForSchemaArray;
/**
* Generates a value for a map schema.
* The types used in the map is separated into three main categories: array, schema and basic types.
*
* There are four special cases for processing a map:
* 1. A map is of an array of schema -> { type: Map, of: [new Schema({ name: String, age: Number })] }
* 2. A map is of an array of basic types -> { type: Map, of: [String] }
* 3. A map is of a schema type -> { type: Map, of: new Schema({ name: String, age: Number }) }
* 4. A map is of a basic type -> { type: Map, of: String }
*
* @param path The path to the field.
* @param schemaType The mongoose schema type of the field.
* @param overrideValues Values to override in the schema.
* @param options Fixture generation options.
*
* @returns A key-value pair of mock values. Returns `undefined` if the map type is not defined.
*
* @private
*/
private generateValueForMapType;
/**
* Generates a value for an array map type.
*
* @example
* {
* basicArray: [1, 2, 3],
* schemaArray: [{ name: 'John', age: 30 }, { name: 'Jane', age: 25 }],
* }
*
* @param mapDefinition Either based on schema or basic type. If based on basic type, we access the `name` property.
* @param path The path to the field.
* @param overrideValues Values to override in the schema.
* @param options Fixture generation options.
*
* @returns An array of mock values, either an object of values or primitive values.
*
* @private
*/
private generateArrayMapValues;
/**
* Generates a map value based on the basic type -> { type: Map, of: String }
*
* @param basicFieldType The basic type of the map value. String, Number, etc.
*
* @returns A mock value for the map value.
*
* @private
*/
private generateBasicMapValue;
/**
* Generates a random map value which will be used for the map key.
*
* @returns A random map key.
*
* @private
*/
private generateMapKey;
/**
* Generates a value for a field based on the schema type.
* If a value is provided in the `overrideValues`, it will be used instead of generating a new value.
* If a `rule` is provided, a value will be generated based on it.
*
* @param path The path to the field.
* @param schemaType The mongoose schema type of the field.
* @param overrideValues Values to override in the schema.
* @param options Fixture generation options.
*
* @returns A mock value for the field or a value in the `overrideValues` if it exists.
*
* @throws {Error} If the value generated does not match the custom rule or the schema rule.
*
* @private
*/
private generateValue;
/**
* Generates a mock value for a field based on the schema rule and the custom rule.
*
* @param path The path to the field.
* @param schemaType The mongoose schema type of the field.
* @param rule The custom rule to apply for the field.
* @param isAccurate If set to `true`, the value will be generated based on the field name. {@link FakerFinder#search}
*
* @returns A mock value for the field or `undefined`.
*
* @throws {Error} If the schema rules and custom rules conflict each other
*
* @private
*/
private generateMockValue;
/**
* Pre-generation routine to validate and extract paths and to set global options.
*
* @param overrideValues Values to override in the schema.in the schema
* @param options Fixture generation options.
*
* @returns Merged fixture options.
*
* @throws {Error} If paths defined both in the `overrideValues` and the `options` are invalid.
*
* @private
*/
private preGeneration;
/**
* Checks if a given field (path) is excluded from the fixture generation.
*
* @param path The path to the field.
* @param schemaType The mongoose schema type of the field.
* @param options Fixture generation options.
*
* @returns `true` if the field is excluded, `false` otherwise.
*
* @throws {Error} If a required field is excluded.
*
* @private
*/
private isExcluded;
/**
* Checks if the path contains special characters.
*
* @param path The path to the field.
*
* @returns `true` if the path contains special characters, `false` otherwise.
*
* @private
*/
private containsSpecialChars;
/**
* Checks if the target is a Mongoose model.
* Model instances have a `schema` property, by which we can distinguish between a model and a schema.
*
* @param target Either a Mongoose model or a schema.
*
* @returns `true` if the target is a Mongoose model, `false` otherwise.
*
* @private
*/
private isModel;
}