From 4b7391ad7de42f4f060f5629d99d689e5c1bf553 Mon Sep 17 00:00:00 2001 From: Dotan Simha Date: Mon, 31 Oct 2016 12:22:34 +0200 Subject: [PATCH] feat(jsdoc): Document ObservableCollection and ObservableCursor --- src/ObservableCollection.ts | 157 +++++++++++++++++++++++++++++++++++- src/ObservableCursor.ts | 51 ++++++++++++ 2 files changed, 204 insertions(+), 4 deletions(-) diff --git a/src/ObservableCollection.ts b/src/ObservableCollection.ts index e579efb8..4e8e642a 100644 --- a/src/ObservableCollection.ts +++ b/src/ObservableCollection.ts @@ -1,7 +1,5 @@ import {Observable, Subscriber} from 'rxjs'; - import {ObservableCursor} from './ObservableCursor'; - import {removeObserver} from './utils'; import Selector = Mongo.Selector; @@ -27,42 +25,104 @@ export module MongoObservable { transform ? : Function; } - export function fromExisting(collection: Mongo.Collection) { + /** + * Creates a new MongoObservable.Collection from an existing of predefined Mongo.Collection. + * Use this feature to wrap existing collections such as Meteor.users. + * @param {Mongo.Collection} collection - The collection. + * @returns {MongoObservable.Collection} - Wrapped collection. + * @static + */ + export function fromExisting(collection: Mongo.Collection): MongoObservable.Collection { return new MongoObservable.Collection(collection); } + /** + * A class represents a MongoDB collection in the client side, wrapped with RxJS + * Observables, so you can use it with your Angular 2 easier. + * The wrapper has the same API as Mongo.Collection, only the "find" method returns + * an ObservableCursor instead of regular Mongo.Cursor. + * + * T is a generic type - should be used with the type of the objects inside the collection. + */ export class Collection { private _collection: Mongo.Collection; + /** + * Creates a new Mongo.Collection instance wrapped with Observable features. + * @param {String | Mongo.Collection} nameOrExisting - The name of the collection. If null, creates an + * unmanaged (unsynchronized) local collection. If provided an instance of existing collection, will + * create a wrapper for the existing Mongo.Collection. + * @param {ConstructorOptions} options - Creation options. + * @constructor + */ constructor(nameOrExisting: string | Mongo.Collection, options?: ConstructorOptions) { if (nameOrExisting instanceof Mongo.Collection) { this._collection = nameOrExisting; } else { - this._collection = new Mongo.Collection(nameOrExisting, options); + this._collection = new Mongo.Collection(nameOrExisting, options); } } + /** + * Returns the Mongo.Collection object that wrapped with the MongoObservable.Collection. + * @returns {Mongo.Collection} The Collection instance + */ get collection(): Mongo.Collection { return this._collection; } + /** + * Allow users to write directly to this collection from client code, subject to limitations you define. + * + * @returns {Boolean} + */ allow(options: AllowDenyOptionsObject): boolean { return this._collection.allow(options); } + /** + * Override allow rules. + * + * @returns {Boolean} + */ deny(options: AllowDenyOptionsObject): boolean { return this._collection.deny(options); } + /** + * Returns the Collection object corresponding to this collection from the npm + * mongodb driver module which is wrapped by Mongo.Collection. + * + * @returns {Mongo.Collection} The Collection instance + * + * @see {@link https://docs.meteor.com/api/collections.html#Mongo-Collection-rawCollection|rawCollection on Meteor documentation} + */ rawCollection(): any { return this._collection.rawCollection(); } + /** + * Returns the Db object corresponding to this collection's database connection from the + * npm mongodb driver module which is wrapped by Mongo.Collection. + * + * @returns {Mongo.Db} The Db instance + * + * @see {@link https://docs.meteor.com/api/collections.html#Mongo-Collection-rawDatabase|rawDatabase on Meteor documentation} + */ rawDatabase(): any { return this._collection.rawDatabase(); } + /** + * Insert a document in the collection. + * + * @param {T} doc - The document to insert. May not yet have an _id + * attribute, in which case Meteor will generate one for you. + * @returns {Observable} Observable which completes with the inserted ObjectId + * + * @see {@link https://docs.meteor.com/api/collections.html#Mongo-Collection-insert|insert on Meteor documentation} + */ insert(doc: T): Observable { let observers: Subscriber[] = []; let obs = this._createObservable(observers); @@ -78,6 +138,14 @@ export module MongoObservable { return obs; } + /** + * Remove documents from the collection. + * + * @param {Collection~MongoQuerySelector} selector - Specifies which documents to modify + * @returns {Observable} Observable which completes with the number of affected rows + * + * @see {@link https://docs.meteor.com/api/collections.html#Mongo-Collection-remove|remove on Meteor documentation} + */ remove(selector: Selector | ObjectID | string): Observable { let observers: Subscriber[] = []; let obs = this._createObservable(observers); @@ -94,6 +162,17 @@ export module MongoObservable { return obs; } + /** + * Modify one or more documents in the collection. + * + * @param {Collection~MongoQuerySelector} selector - Specifies which documents to modify + * @param {Modifier} modifier - Specifies how to modify the documents + * @param {MongoUpdateOptions} options - Update options + * first argument and, if no error, the number of affected documents as the second + * @returns {Observable} Observable which completes with the number of affected rows + * + * @see {@link https://docs.meteor.com/api/collections.html#Mongo-Collection-update|update on Meteor documentation} + */ update( selector: Selector | ObjectID | string, modifier: Modifier, @@ -113,6 +192,18 @@ export module MongoObservable { return obs; } + /** + * Finds the first document that matches the selector, as ordered by sort and skip options. + * + * @param {Collection~MongoQuerySelector} selector - Specifies which documents to modify + * @param {Modifier} modifier - Specifies how to modify the documents + * @param {MongoUpsertOptions} options - Upsert options + * first argument and, if no error, the number of affected documents as the second. + * @returns {Observable<{numberAffected, insertedId}>} Observable which completes with an + * Object that contain the keys numberAffected and insertedId. + * + * @see {@link https://docs.meteor.com/api/collections.html#Mongo-Collection-upsert|upsert on Meteor documentation} + */ upsert( selector: Selector | ObjectID | string, modifier: Modifier, @@ -132,6 +223,25 @@ export module MongoObservable { return obs; } + /** + * Method has the same notation as Mongo.Collection.find, only returns Observable. + * + * @param {Collection~MongoQuerySelector} selector - A query describing the documents to find + * @param {Collection~MongoQueryOptions} options - Query options, such as sort, limit, etc. + * @returns {ObservableCursor} RxJS Observable wrapped with Meteor features. + * @example Using Angular2 Component + * const MyCollection = MongoObservable.Collection("myCollection"); + * + * class MyComponent { + * private myData: ObservableCursor; + * + * constructor() { + * this.myData = MyCollection.find({}, {limit: 10}); + * } + * } + * + * @see {@link https://docs.meteor.com/api/collections.html#Mongo-Collection-find|find on Meteor documentation} + */ find(selector?: Selector | ObjectID | string, options?: { sort?: SortSpecifier; skip?: number; @@ -145,6 +255,15 @@ export module MongoObservable { return ObservableCursor.create(cursor); } + /** + * Finds the first document that matches the selector, as ordered by sort and skip options. + * + * @param {Collection~MongoQuerySelector} selector - A query describing the documents to find + * @param {Collection~MongoQueryOptions} options - Query options, such as sort, limit, etc. + * @returns {any} The first object, or `undefined` in case of non-existing object. + * + * @see {@link https://docs.meteor.com/api/collections.html#Mongo-Collection-findOne|findOne on Meteor documentation} + */ findOne(selector?: Selector | ObjectID | string, options?: { sort?: SortSpecifier; skip?: number; @@ -166,3 +285,33 @@ export module MongoObservable { } } } + + +/** + * An options object for MongoDB queries. + * @typedef {Object} Collection~MongoQueryOptions + * @property {Object} sort - Sort order (default: natural order) + * @property {Number} skip - Number of results to skip at the beginning + * @property {Object} fields - Dictionary of fields to return or exclude. + * @property {Boolean} reactive - (Client only) Default true; pass false to disable reactivity + * @property {Function} transform - Overrides transform on the Collection for this cursor. Pass null to disable transformation. + */ + +/** + * A MongoDB query selector representation. + * @typedef {(Mongo.Selector|Mongo.ObjectID|string)} Collection~MongoQuerySelector + */ + +/** + * A MongoDB query options for upsert action + * @typedef {Object} Collection~MongoUpsertOptions + * @property {Boolean} multi - True to modify all matching documents; + * false to only modify one of the matching documents (the default). + */ + +/** + * A MongoDB query options for update action + * @typedef {Object} Collection~MongoUpdateOptions + * @property {Boolean} multi - True to modify all matching documents; + * @property {Boolean} upsert - True to use upsert logic. + */ diff --git a/src/ObservableCursor.ts b/src/ObservableCursor.ts index d079f1c9..6dcaf915 100644 --- a/src/ObservableCursor.ts +++ b/src/ObservableCursor.ts @@ -3,6 +3,10 @@ import {Observable, Subscriber, Subject} from 'rxjs'; import {gZone, forkZone, removeObserver} from './utils'; +/** + * A class represents a Monog.Cursor wrapped with RxJS features. + * @extends Observable + */ export class ObservableCursor extends Observable { private _zone: Zone; private _data: Array = []; @@ -11,10 +15,23 @@ export class ObservableCursor extends Observable { private _observers: Subscriber[] = []; private _countObserver: Subject = new Subject(); + /** + * Static method which creates an ObservableCursor from Mongo.Cursor. + * Use this to create an ObservableCursor object from an existing Mongo.Cursor. + * Prefer to create an Cursors from the ObservableCollection instance instead. + * + * @param {Mongo.Cursor} cursor - The Mongo.Cursor to wrap. + * @returns {ObservableCursor} Wrapped Cursor. + */ static create(cursor: Mongo.Cursor): ObservableCursor { return new ObservableCursor(cursor); } + /** + * @constructor + * @extends Observable + * @param {Mongo.Cursor} cursor - The Mongo.Cursor to wrap. + */ constructor(cursor: Mongo.Cursor) { super((observer: Subscriber) => { this._observers.push(observer); @@ -35,14 +52,28 @@ export class ObservableCursor extends Observable { this._zone = forkZone(); } + /** + * Returns the actual Mongo.Cursor that wrapped by current ObservableCursor instance. + * @return {Mongo.Cursor} The actual MongoDB Cursor. + */ get cursor(): Mongo.Cursor { return this._cursor; } + /** + * A wrapper for Mongo.Cursor.count() method - returns an Observable of number, which + * triggers each time there is a change in the collection, and exposes the number of + * objects in the collection. + * @returns {Observable} Observable which trigger the callback when the + * count of the object changes. + */ collectionCount(): Observable { return this._countObserver.asObservable(); } + /** + * Stops the observation on the cursor. + */ stop() { this._zone.run(() => { this._runComplete(); @@ -56,19 +87,39 @@ export class ObservableCursor extends Observable { this._hCursor = null; } + /** + * Clears the Observable definition. + * Use this method only when the Observable is still cold, and there are no active subscriptions yet. + */ dispose() { this._observers = null; this._cursor = null; } + /** + * Return all matching documents as an Array. + * + * @return {Array} The array with the matching documents. + */ fetch(): Array { return this._cursor.fetch(); } + /** + * Watch a query. Receive callbacks as the result set changes. + * @param {Mongo.ObserveCallbacks} callbacks - The callbacks object. + * @return {Meteor.LiveQueryHandle} The array with the matching documents. + */ observe(callbacks: Mongo.ObserveCallbacks): Meteor.LiveQueryHandle { return this._cursor.observe(callbacks); } + /** + * Watch a query. Receive callbacks as the result set changes. + * Only the differences between the old and new documents are passed to the callbacks. + * @param {Mongo.ObserveChangesCallbacks} callbacks - The callbacks object. + * @return {Meteor.LiveQueryHandle} The array with the matching documents. + */ observeChanges(callbacks: Mongo.ObserveChangesCallbacks): Meteor.LiveQueryHandle { return this._cursor.observeChanges(callbacks); }