universe:buckets

v1.3.5Published 8 years ago

This package has not had recent updates. Please investigate it's current state before committing to using it in your project.

Universe Buckets

This package provides possibility of publishing documents from various collections to bucket (sandbox). The biggest benefit of using this package is that you don't need to search in collection of documents second time on client. Additionally api of buckets brings many improvements and syntactic sugars.

Installation

    $ meteor add universe:buckets

Single bucket

This package offers you two way of working with bucket. First one is as a single bucket instance and second gives you dictionary of buckets. In this section we will explain how to use single instance of bucket.

Creation of new bucket

  • both sides
1import {Bucket} from 'meteor/universe:buckets';
2var MyBucket = new Bucket('uniqueName');

new Bucket(name, options = {})

  • On server side
1MyBucket.publish(function () {
2   //you can return cursor, array of cursors or even array of plain objects
3    return ([
4        //cursor:
5        Meteor.users.find(),
6        //plain objects:
7        [{someData: 1}, {someData: 2}]
8    ]);
9})

As you can see on example you can publish array of cursors and even array of objects

MyBucket.publish(publishHandler, options = {condition})

Publish api in publishHandler is fully compatible with Meteor.publish, but the return can accept not only cursor or array of cursors but also array of objects, which gives more flexible and freedom in what can be published to the clients.

Additionally in options you can pass a condition function that will checks if publication can be processed for current user.

  • On Client side
1MyBucket.subscribe().then(handler => {
2    console.log('Ready');
3    console.log('users:', handler.getDocs('users'));
4    console.log('custom docs:', handler.getDocs(null));
5    console.log('all in buckets:', handler.getDocs());
6    console.log('admins in users:', handler.getDocs('users', {is_admin: true}, {limit:2}));
7});

Using with async functions

1async function example () {
2    const {
3        getDocs,
4        getCount,
5        getDoc,
6        ready,
7        stop
8    } = await MyBucket.subscribe();
9    console.log('users:', getDocs('users'));
10    console.log('custom docs count:', getCount(null));
11    console.log('one doc:', getDoc());
12    console.log('reade:', ready());
13    stop().onStop(() => console.log('stopped'));
14}

The name of subscription is omitted because we are working on bucket instance. Of course you can pass some arguments to subscriptions as on Meteor.subscribe/Meteor.publish.

MyBucket.subscribe(...params) returns an handler object, which has:

Standard api:

  • .ready()
  • .stop()
  • .subscriptionId

Extra api:

  • .then(function(handler){})
  • .catch(function(error){})
  • .onStop(callback)
  • .autorun(function(computation){})
  • .getDocs(collectionName = ALL, selector = {}, options = {})
  • .getDoc(collectionName = ALL, selector = {}, options = {})
  • .getCount(collectionName = ALL, selector = {}, options = {})
  • .subscriptionHash

MyBucket.load(...params) works as subscribe method but without tracking of changes (non-reactive).

This is good option for long listings where performance is more important than reactivity of items.

Of course you can ask why not use just a meteor call (rpc method) instead of that. The answer is simple, Bucket api give you possibility of:

  • Searching in those data (using mongo selectors)
  • You can write just one publish method for both functionalities (subscribe / load)
  • Refreshing data by calling simple refresh() from handler
  • 'load` method gives you possibility of adding reactivity for selected documents in bucket. It means that some of items in your listing still can be reactive.
load method returns the handle, which is pretty much same like this one returned by subscribe:

Standard api:

  • .ready()
  • .stop()
  • .subscriptionId

Extra api:

  • .then(function(handler){})
  • .catch(function(error){})
  • .onStop(callback)
  • .autorun(function(computation){})
  • .getDocs(collectionName = ALL, selector = {}, options = {})
  • .getDoc(collectionName = ALL, selector = {}, options = {})
  • .getCount(collectionName = ALL, selector = {}, options = {})
  • .subscriptionHash
  • .isStatic: true
  • .observeCursor(cursor)
  • .refresh(silentStart = true)

Adding reactivity for some documents in bucket

1//both sides:
2const usersBucket = new Bucket('usersBucket');
3if (Meteor.isServer) {
4    usersBucket.publish(function() {
5        return Meteor.users.find();
6    });
7}
8// client:
9(async function () {
10        const {getDoc, getDocs, observeCursor} = await usersBucket.load();
11        const loggedInId = Meteor.userId();
12        observeCursor(Meteor.users.find(loggedInId));
13        //will be reactive
14        const user1 = getDoc('users', loggedInId);
15        // will be nonreactive
16        const user2 = getDoc('users', 'otherId');
17
18        // Will be reactive only for one user
19        const allDocs = getDocs();
20})

Extra stuff in handler

As you can see bucket handlers have additional stuff. So, any time when you call bucket.subscribe or bucket.load, you will get a handler which contains standard api but also handler can be treat as a promise (it mean, there are available then/catch methods on it)

additionally you can find methods like autorun which is bound with life cycle of subscription (subscribe - stop).

Of course there are methods to gets data from buckets like getDocs/getDoc/getCount.

besides methods, there are few properties like subscriptionHash witch is same for subscription of buckets with the same parameters.

Creation of collections of buckets

to be continued soon

License MIT