Coding With Fun
Home Docker Django Node.js Articles Python pip guide FAQ Policy

Meteor creates the Meteor Package


May 10, 2021 Meteor


Table of contents


Create a Meteor Package

We've created a reusable pattern in our reporting of errors, so why not package it for others in the Meteor community to use?

To get started, we need a Meteor developer account. Y ou can apply meteor.com, but chances are you'll get it by the time you sign up for the book. In either case, you should find out what your userna name is, as we'll use it extensively in this chapter.

In this chapter we use the username tmeasday of course you can change it to your own.

First we need to create a structure to hold the new package. U se the meteor create --package tmeasday:errors to complete. I t is important to note that Meteor has created a folder and some files packages/tmeasday:errors/ Let's package.js which tells Meteor what objects or functions to export if you use the package.

Package.describe({
  name: "tmeasday:errors",
  summary: "A pattern to display application errors to the user",
  version: "1.0.0"
});

Package.onUse(function (api, where) {
  api.versionsFrom('0.9.0');

  api.use(['minimongo', 'mongo-livedata', 'templating'], 'client');

  api.addFiles(['errors.js', 'errors_list.html', 'errors_list.js'], 'client');

  if (api.export) 
    api.export('Errors');
});

When developing a real-world package, it's a great git URL of your code base (for example, in the Package.describe block of https://github.com/tmeasday/meteor-errors.git the git https://github.com/tmeasday/meteor-errors.git That way, users can browse the source code, and (assuming you use GitHub) your package's readme appears on Atomsphere.

Let's add 3 files to the package. (We can remove the templates that Meteor automatically adds) We can pull these files from Microscope without much modification, except for some suitable naming and slightly clearer APIs:

Errors = {
  // Local (client-only) collection
  collection: new Mongo.Collection(null),

  throw: function(message) {
    Errors.collection.insert({message: message, seen: false})
  }
};
<template name="meteorErrors">
  <div class="errors">
    {{#each errors}}
      {{> meteorError}}
    {{/each}}
  </div>
</template>

<template name="meteorError">
  <div class="alert alert-danger" role="alert">
    <button type="button" class="close" data-dismiss="alert">&times;</button>
    {{message}}
  </div>
</template>
Template.meteorErrors.helpers({
  errors: function() {
    return Errors.collection.find();
  }
});

Template.meteorError.rendered = function() {
  var error = this.data;
  Meteor.setTimeout(function () {
    Errors.collection.remove(error._id);
  }, 3000);
};

Test the package in Microscope

Now we need to do local testing on Microscope to make sure the code is working correctly. I n order to link the package to the project, we meteor add tmeasday:errors Then, you need to delete existing files that have become redundant:

rm client/helpers/errors.js
rm client/templates/includes/errors.html
rm client/templates/includes/errors.js

Another thing we need to do is do some small updates using the correct API:

  {{> header}}
  {{> meteorErrors}}
Meteor.call('postInsert', post, function(error, result) {
  if (error) {
    // display the error to the user
    Errors.throw(error.reason);
Posts.update(currentPostId, {$set: postProperties}, function(error) {
  if (error) {
    // display the error to the user
    Errors.throw(error.reason);

Once these modifications are complete, we can resume our pre-subcontracted behavior.

Write a test

The first step in a development package is to test it in an application, but the next step is to write a test suite that corrects the behavior of the test package. Meteor itself comes with Tinytest ( the built-in package tester) that makes it easy to run the test suite to make sure the package is correct when sharing it with others.

Let's create a test file and use Tinytest to run some tests on the new package:

Tinytest.add("Errors - collection", 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", function(test, done) {  
  Errors.throw('A new error!');
  test.equal(Errors.collection.find({}).count(), 1);

  // render the template
  UI.insert(UI.render(Template.meteorErrors), document.body);

  Meteor.setTimeout(function() {
    test.equal(Errors.collection.find({}).count(), 0);
    done();
  }, 3500);
});

In these tests, we check to see if Meteor.Errors functionality works, and to confirm again that rendered is still working.

We won't write all the details of the Meteor package test here (and the API hasn't been finalized yet, and it's likely to change), but hopefully it's a way to explain itself to some extent.

Use the following code to tell Meteor how to run .js in the package.js

Package.onTest(function(api) {
  api.use('tmeasday:errors', 'client');
  api.use(['tinytest', 'test-helpers'], 'client');  

  api.addFiles('errors_tests.js', 'client');
});

Then we can run the test:

meteor test-packages tmeasday:errors

Publish the package

Now we're going to release this package, push it to the Meteor package server, and show it in Atmopshere for people all over the world to use.

Fortunately, it's easy. We're just cd-to-package directories, meteor publish --create cd

cd packages/tmeasday:errors
meteor publish --create

Now that the package has been published, we can remove it from the project and add it directly from Atmopshere:

rm -r packages/tmeasday:errors
meteor add tmeasday:errors

Now we should see Meteor download our package for the first time. It's great!

As in the usual appendix sections, make sure to restore your changes before moving on to the next chapter (or consider your changes as you read other chapters of the book).