UNPKG

ottoman

Version:
388 lines (387 loc) 12 kB
import { ApplyStrategy, CastOptions } from '../utils/cast-strategy'; import { ModelMetadata } from './interfaces/model-metadata.interface'; import { removeOptions, saveOptions } from './model.types'; import { PopulateFieldsType, PopulateOptionsType } from './populate.types'; type CleanDocument = Omit<Document, '$' | '$isNew'>; export type IDocument<T = any> = CleanDocument & T; /** * Document class represents a database document and provides useful methods to work with. * * @example * ```javascript * import { connect, model } from "ottoman"; * connect("couchbase://localhost/travel-sample@admin:password"); * * // Create an `User` model * const User = model('User', { name: String }); * * // Create a document from the `User` Model * const jane = new User({ name: "Jane Doe" }) * ``` */ export declare abstract class Document { #private; /** * @ignore */ [key: string]: any; /** * @ignore */ protected constructor(data: any, options?: CastOptions); /** * @ignore */ get $(): ModelMetadata; /** * Returns id value, useful when working with dynamic ID_KEY. * * @example * ```javascript * console.log(user._getId()); // 'userId' * console.log(user.id); // 'userId' * ``` */ _getId(): string; /** * Returns id key. */ _getIdField(): string; /** * Saves or Updates the document. * * @example * ```javascript * const user = new User({ name: "John Doe" }); //user document created, it's not saved yet * * await user.save(); // user saved into the DB * * // You also can force save function to only create new Documents by passing true as argument * await user.save(true); // ensure to execute a insert operation * ``` */ save(onlyCreate?: boolean, options?: saveOptions): Promise<any>; /** * Removes the document from the database. * * @example * ```javascript * const user = User.findById('userId') * * await user.remove(); * ``` */ remove(options?: removeOptions): Promise<any>; /** * Allows to load document references. * * * @example * Getting context to explain populate. * ```typescript * // Defining the schemas * const addressSchema = new Schema({ * address: String, * }); * const personSchema = new Schema({ * name: String, * age: Number, * address: { type: addressSchema, ref: 'Address' }, * }); * const companySchema = new Schema({ * president: { type: personSchema, ref: 'Person' }, * ceo: { type: personSchema, ref: 'Person' }, * name: String, * workers: [{ type: personSchema, ref: 'Person' }], * }); * * // Initializing the models * const Address = model('Address', addressSchema); * const Person = model('Person', personSchema); * const Company = model('Company', companySchema); * * // Adding some data * const johnAddress = await Address.create({ address: '13 Washington Square S, New York, NY 10012, USA' }); * const john = await Person.create({ name: 'John Smith', age: 52, address: johnAddress }); * * const janeAddress = await Address.create({ address: '55 Clark St, Brooklyn, NY 11201, USA' }); * const jane = await Person.create({ name: 'Jane Doe', age: 45, address: janeAddress }); * * const company = await Company.create({ name: 'Space X', president: john, ceo: jane }); * * * // Getting saved company data * const spaceX = await Company.findById(company.id); * console.log(`Company: `, company); * ``` * * Will get: * ``` * Company: { * name: 'Space X', * president: '50e85ac9-5b4f-4587-aeb6-b287527794c9', * ceo: '32c2e85a-cc91-4db2-935f-f7d2768168de', * id: 'd59efbdf-4b7e-4d2f-a986-6e8451f22822', * _type: 'Company' * } * ``` * * Now we will see how the _populate methods works. * ```typescript * const result = await spaceX._populate('ceo'); * console.log(`Result: `, result); * ``` * ``` * Result: { * name: 'Space X', * president: '50e85ac9-5b4f-4587-aeb6-b287527794c9', * ceo: { * name: 'Jane Doe', * age: 45, * address: '235dd441-b445-4b88-b6aa-2ce35a958a32', * id: '32c2e85a-cc91-4db2-935f-f7d2768168de', * _type: 'Person' * }, * id: 'd59efbdf-4b7e-4d2f-a986-6e8451f22822', * _type: 'Company' * } * ``` * * Can also pass an array or a string separated by a comma * ```typescript * const result = await spaceX._populate('ceo,president'); * // or * const result = await spaceX._populate(['ceo', 'president']); * console.log(`Result: `, result); * ``` * ``` * Result: { * name: 'Space X', * president: { * name: 'John Smith', * age: 52, * address: 'bc7ea8a8-8d1c-4ab6-990c-d3a0163f7e10', * id: '50e85ac9-5b4f-4587-aeb6-b287527794c9', * _type: 'Person' * }, * ceo: { * name: 'Jane Doe', * age: 45, * address: '235dd441-b445-4b88-b6aa-2ce35a958a32', * id: '32c2e85a-cc91-4db2-935f-f7d2768168de', * _type: 'Person' * }, * id: 'd59efbdf-4b7e-4d2f-a986-6e8451f22822', * _type: 'Company' * } * ``` * * If you want to get only a portion of the object * ```typescript * const result = await spaceX._populate({ * ceo: ['age', 'address'], // or 'age,addres' * president: 'name', * }); * console.log(`Result: `, result); * ``` * ``` * Result: { * name: 'Space X', * president: { name: 'John Smith' }, * ceo: { age: 45, address: '235dd441-b445-4b88-b6aa-2ce35a958a32' }, * id: 'd59efbdf-4b7e-4d2f-a986-6e8451f22822', * _type: 'Company' * } * ``` * * Now let's to go deeper * ```typescript * const result = await spaceX._populate( * { * ceo: { * select: 'age,id', // remember you can use ['age','address'] * populate: 'address', // will populate all the fields * }, * president: { * select: 'name', * populate: { * address: 'address', // will populate address field only * }, * }, * }, * 2, // for populate up to the second level * ); * console.log(`Result: `, result); * ``` * ``` * Result: { * name: 'Space X', * president: { * name: 'John Smith', * address: { address: '13 Washington Square S, New York, NY 10012, USA' } * }, * ceo: { * age: 45, * id: '32c2e85a-cc91-4db2-935f-f7d2768168de', * address: { * address: '55 Clark St, Brooklyn, NY 11201, USA', * id: '235dd441-b445-4b88-b6aa-2ce35a958a32', * _type: 'Address' * } * }, * id: 'd59efbdf-4b7e-4d2f-a986-6e8451f22822', * _type: 'Company' * } *``` * Below is another way through the find functions * ```typescript * const result = await Company.findOne( * { name: 'Space X' }, * { * select: 'president,ceo', * populate: { * president: { select: 'address,id', populate: 'address' }, * ceo: { select: ['age', 'name'], populate: { address: { select: 'id' } } }, * }, * populateMaxDeep: 2, * }, * ); * console.log(`Result: `, result); * ``` * ``` * Result: { * ceo: { * age: 45, * name: 'Jane Doe', * address: { id: '235dd441-b445-4b88-b6aa-2ce35a958a32' } * }, * president: { * address: { * address: '13 Washington Square S, New York, NY 10012, USA', * id: 'bc7ea8a8-8d1c-4ab6-990c-d3a0163f7e10', * _type: 'Address' * }, * id: '50e85ac9-5b4f-4587-aeb6-b287527794c9' * } * } * ``` */ _populate(fieldsName?: PopulateFieldsType, options?: PopulateOptionsType): Promise<this>; /** * Reverts population. Switches back document reference. * * @example * To get in context about the Card and Issue Models [see the populate example.](/docs/api/classes/document.html). * ```javascript * const card = await Card.findById(cardId); * console.log(card.issues); // ['issueId'] * * await card._populate('issues') * console.log(card.issues); // [{ id: 'issueId', title: 'Broken card' }] * * card._depopulate('issues') * console.log(card.issues); // ['issueId'] * ``` */ _depopulate(fieldsName: string | string[]): this; /** * Allows to know if a document field is populated. * * @example * To get in context about the Card and Issue Models [see the populate example.](/docs/api/classes/document.html). * ```javascript * const card = await Card.findById(cardId); * console.log(card.issues); // ['issueId'] * console.log(card._populated('issues')); // false * * await card._populate('issues') * console.log(card.issues); // [{ id: 'issueId', title: 'Broken card' }] * console.log(card._populated('issues')); // true * ``` */ _populated(fieldName: string): boolean; /** * Allows to easily apply data from an object to current document. * * @example * ```typescript * const user = new User({ name: "John Doe" }); * * user._applyData({ name: "Jane Doe" }); * console.log(user) // { name: "Jane Doe" } * ``` * * @example With strategies on immutable properties * ```typescript * const User = model('Card', { name: { type: String, immutable: true } }); * const user = new User({ name: 'John Doe' }); * * // with strategy:false is like above example * user._applyData({ name: 'Jane Doe' }, false); * console.log(user); // { name: "Jane Doe" } * * // with strategy:true remains immutable * user._applyData({ name: 'Jane Doe' }, true); * console.log(user); // { name: "John Doe" } * * // trying to update it directly * user.name = 'Jane Doe'; * console.log(user); // { name: "John Doe" } * * // with strategy:CAST_STRATEGY.THROW * user._applyData({ name: 'Jane Doe' }, CAST_STRATEGY.THROW); * // ImmutableError: Field 'name' is immutable and current cast strategy is set to 'throw' * ``` */ _applyData(data: any, strategy?: ApplyStrategy): this; /** * Runs schema validations over current document. * @example * ```javascript * const user = new User( { name: "John Doe" } ); * * try { * await user._validate() * } catch(errors) { * console.log(errors) * } * ``` */ _validate(): any; /** * Returns a Javascript object with data */ toObject(): this; /** * Returns a Javascript object to be serialized to JSON */ toJSON(): this; /** * Encapsulate logic for toObject and toJson * @ignore */ $toObject(): this; /** * Boolean flag specifying if the document is new. * @example * ```typescript * const CardSchema = new Schema({ * cardNumber: { type: String, immutable: true }, * zipCode: String, * }); * * // Create model * const Card = model('Card', CardSchema); * * // Create document * const myCard = new Card({ cardNumber: '4321 4321 4321 4321', zipCode: '43210' }); * myCard.$isNew; // true * * // Save document * const myCardSaved = await myCard.save(); * myCardSaved.$isNew; // false * ``` */ get $isNew(): boolean; } export {};