Creating a Meteorite Package

Sidebar 9.5

Percentage Translated

In this chapter, you will:

  • Write a local in-app package.
  • Write some tests for your package.
  • Release your package on Atmosphere.
  • ////

    ////

    ////

    Package.describe({
      summary: "A pattern to display application errors to the user"
    });
    
    Package.on_use(function (api, where) {
      api.use(['minimongo', 'mongo-livedata', 'templating'], 'client');
    
      api.add_files(['errors.js', 'errors_list.html', 'errors_list.js'], 'client');
    
      if (api.export) 
        api.export('Errors');
    });
    
    packages/errors/package.js

    ////

    Errors = {
      // Local (client-only) collection
      collection: new Meteor.Collection(null),
    
      throw: function(message) {
        Errors.collection.insert({message: message, seen: false})
      },
      clearSeen: function() {
        Errors.collection.remove({seen: true});
      }
    };
    
    
    packages/errors/errors.js
    <template name="meteorErrors">
      {{#each errors}}
        {{> meteorError}}
      {{/each}}
    </template>
    
    <template name="meteorError">
      <div class="alert alert-error">
        <button type="button" class="close" data-dismiss="alert">&times;</button>
        {{message}}
      </div>
    </template>
    
    packages/errors/errors_list.html
    Template.meteorErrors.helpers({
      errors: function() {
        return Errors.collection.find();
      }
    });
    
    Template.meteorError.rendered = function() {
      var error = this.data;
      Meteor.defer(function() {
        Errors.collection.update(error._id, {$set: {seen: true}});
      });
    };
    
    packages/errors/errors_list.js

    Testing the package out with Microscope

    ////

    $ rm client/helpers/errors.js
    $ rm client/views/includes/errors.html
    $ rm client/views/includes/errors.js
    
    removing old files on the bash console

    ////

    Router.before(function() { Errors.clearSeen(); });
    
    lib/router.js
      {{> header}}
      {{> meteorErrors}}
    
    client/views/application/layout.html
    Meteor.call('post', post, function(error, id) {
      if (error) {
        // display the error to the user
        Errors.throw(error.reason);
    
    
    client/views/posts/post_submit.js
    Posts.update(currentPostId, {$set: postProperties}, function(error) {
      if (error) {
        // display the error to the user
        Errors.throw(error.reason);
    
    client/views/posts/post_edit.js

    Commit 9-5-1

    Created basic errors package and linked it in.

    ////

    Writing tests

    ////

    ////

    Tinytest.add("Errors collection works", function(test) {
      test.equal(Errors.collection.find({}).count(), 0);
    
      Errors.throw('A new error!');
      test.equal(Errors.collection.find({}).count(), 1);
    
      Errors.collection.remove({});
    });
    
    Tinytest.addAsync("Errors template works", function(test, done) {  
      Errors.throw('A new error!');
      test.equal(Errors.collection.find({seen: false}).count(), 1);
    
      // render the template
      OnscreenDiv(Spark.render(function() {
        return Template.meteorErrors();
      }));
    
      // wait a few milliseconds
      Meteor.setTimeout(function() {
        test.equal(Errors.collection.find({seen: false}).count(), 0);
        test.equal(Errors.collection.find({}).count(), 1);
        Errors.clearSeen();
    
        test.equal(Errors.collection.find({seen: true}).count(), 0);
        done();
      }, 500);
    });
    
    packages/errors/errors_tests.js

    ////

    ////

    ////

    Package.on_test(function(api) {
      api.use('errors', 'client');
      api.use(['tinytest', 'test-helpers'], 'client');  
    
      api.add_files('errors_tests.js', 'client');
    });
    
    packages/errors/package.js

    Commit 9-5-2

    Added tests to the package.

    ////

    $ meteor test-packages errors
    
    Terminal
    Passing all tests
    Passing all tests

    Releasing the package

    ////

    ////

    {
      "name": "errors",
      "description": "A pattern to display application errors to the user",
      "homepage": "https://github.com/tmeasday/meteor-errors",
      "author": "Tom Coleman <tom@thesnail.org>",
      "version": "0.1.0",
      "git": "https://github.com/tmeasday/meteor-errors.git",
      "packages": {
      }
    }
    
    packages/errors/smart.json

    Commit 9-5-3

    Added a smart.json

    ////

    ////

    ////

    $ git init
    $ git add -A
    $ git commit -m "Created Errors Package"
    $ git remote add origin https://github.com/tmeasday/meteor-errors.git
    $ git push origin master
    $ mrt release .
    Done!
    
    Terminal (run from within `packages/errors`)

    ////

    ////

    ////

    $ rm -r packages/errors
    $ mrt add errors
    
    Terminal (run from the top level of the app)

    Commit 9-5-4

    Removed package from development tree.

    ////