npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

meteor-publications

v1.2.0

Published

A custom publication class for Meteor

Downloads

2

Readme

Meteor Publications

A library to make creating powerful publications in Meteor easier to write and understand. This library also enables basic "relational" publications.

Installation

npm install --save @webantic/meteor-publications

Since there is no way to require meteor/meteor or meteor/mongo from npm, you must pass this in to the module at startup:

// publication.config.js
import { Meteor } from 'meteor/meteor'
import { Mongo } from 'meteor/mongo'
import init from '@webantic/meteor-publications'

const { Publication, RelationalPublication } = init(Meteor, Mongo)

export {
  Publication,
  RelationalPublication
}

Usage

All publications require:

  • a name which can be any string or null
  • an action which is a function that defines what data will be sent to the client.

A publication can also control access by setting one or more authenticate hooks. Access can be further controlled by setting one or more authorize hooks. Finally, publications have built-in support for the simple:rest package - options set on the rest object will be processed and passed to the simple:rest package.

Examples

A basic publication can be set up by supplying only a name and action:

const inkPub = new Publication({
  name: 'inks',
  action () {
    return Inks.find()
  }
})

The action handlers' contexts are equivalent to that of a standard Meteor publication handler's, but with the addition of two publication helpers; this.publish and this.relationalPublish:

const inkPub = new Publication({
  name: 'inks',
  action () {
    // All the standard properties and methods are available:
    this.userId
    this.added(/* collectionName, documentId, documentFields */)
    // etc...

    // Two additional methods are also available:
    this.publish(/* publicationConfig */) // a helper to publish a cursor to a client
    this.relationalPublish(/* publicationConfig */) // a helper to publish a cursor and related data to a client
  }
})

The Publish helper

Why?

One of the great things about Meteor publications is being able to return a cursor and have the associated documents be published to the client. When you need to publish more than one cursor from a single publication, things can get complicated quite quickly. The publish helper abstracts away a lot of this complexity, leaving you with more expressive publications.

How?

The publish helper takes a single object argument which contains the following properties:

  • {Mongo.Collection} collection The collection to query
  • {Object} selector The selector to query the collection with
  • {Object} [options] An optional set of query options (limit, sort, etc..)

N.B. You must manually call this.ready() once you have set up all your observers.

const inkPub = new Publication({
  name: 'inks',
  action () {
    this.publish({
      collection: BlueInks,
      selector: {},
      options: { limit: 5 }
    })

    this.publish({
      collection: BlackInks,
      selector: {},
      options: { limit: 5 }
    })

    this.ready()
  }
})

The RelationalPublish helper

Why?

Meteor's implementation of Mongo (currently) lacks support for aggregation pipelines, making it challenging to publish related data across multiple collections. This helper abstracts away the implementation, leaving more expressive publications.

How?

The relationalPublish helper takes a single object argument which contains the same properties as the publish helper, but with an additional one:

  • {Object[]} relations An array of objects with the following keys:
    • {Mongo.Collection} collection The collection where the related data resides
    • {string} foreignKeyName The name of the key on the main collection which contains the identifier for the related data
    • {string} [identifier] An optional identifier name on the related collection. Defaults to '_id'
    • {boolean} [reactive] An optional flag to specify whether to update which related data is published when changes occur in the main collection. Defaults to true
const penPub = new Publication({
  name: 'pens',
  action () {
    this.relationalPublish({
      collection: Pens,
      selector: { inkColor: 'blue' },
      relations: [{
        collection: Inks, // publish related data about inks
        foreignKeyName: 'inkColor', // use "inkColor" as the foreign key name on the Pens collection (always "blue" in this example)
        identifier: 'color' // The field to look for on the "Inks" collection
      }]
    })

    // This acomplishes the following:
    // we publish collection.find(selector) --- Pens.find({inkColor: 'blue'})
    // we take all the unique values found in the foreignKeyName ("inkColor") field of the resulting documents and publish relation.collection.find({[identifier]: {$in: <those values>}}) --- Inks.find({color: {$in: ['blue']}})

    this.ready()
  }
})

Authentication and Authorization

You can ensure that users are allowed access to the data a publication provides by setting authenticate and/or authorize hook(s):

const protectedPub = new Publication({
  name: 'protected',
  authenticate () {
    // context is the same as `action` handler
    return !!this.userId
  },
  // values can be either functions or arrays of functions
  authorize: [authHandler, otherAuthHandler],
  action () {
    
  }
})

The context is the same in these hooks as it is in the action handler. They also receive the same parameters. You may either return false or throw an error in an auth hook to prevent the execution of the action handler.