Transitioning to Modules With Global Imports


#1

Hey all,

I’ve been upgrading several Meteor applications to 1.3 and I’ve been using a quick trick to help ease some of the pain. Check out my most recent post on transitioning to modules with global imports.

Importing modules and then exposing them as globals may seem like a backwards move at first, but it can definitely help ease some of the awkwardness of moving from a 1.2-style application over to 1.3 without the (minor) potential dangers and extra work of explicitly importing your module in every file it’s used.

Hopefully this helps some people out there who are tackling larger upgrades and want to keep their sanity.


#2

You’re brilliant! Thank you so much! This is exactly what we’ve been talking about re: autoimport package. Add this into a package, and we have the perfect upgrade path for Blaze users, people with existing large apps, or beginners who aren’t yet comfortable with imports. Fantastic stuff! :slight_smile:


#3

Good solution for apps, but…

What if I’m writing package, and some people may have collections in global scope and other will not?

I mean before 1.3, in package I could have:

function foo (collection_name) {
   var collection = global[collection_name]
   ...
}

And now such package will force anyone to use your described pattern even if they are writing new Meteor app :confused: Have you any ideas how to solve it?


#4

Why not have the function take the actual collection object, and not the name?


#5

That was my first idea, but… it will not work when you have to pass collection from client into server using methods.

// /server/methods.js
import { Meteor } from 'meteor/meteor';

Meteor.methods({
    foo: function (collection) {
        let results = collection.find().fetch()
        ...
    }
})
// /client/main.js
import { Meteor } from 'meteor/meteor'
import CoolCollection from '../lib/collections.js'

Template.someTemplate.events({
  'click button': function() {
     Meteor.call('foo', CoolCollection)
  }
})

I’m getting strange error in chrome console:
underscore.js:113 Uncaught RangeError: Maximum call stack size exceeded


#6

I feel like for this you should use: https://github.com/dburles/mongo-collection-instances

Are you building some kind of development/debugging tool?


#7

Big thank you, that was very good advice. Actually finally I just used meteor/lai:collection-extensions which is used by mongo-collection-instances.

I’m creating simple search solution nous:searchIn for my autoform widget nous:autoform-picker and a few more packages.

@pcorey, sorry for offtopic


#8

Thanks all! I don’t know about brilliant… Usually the simplest solutions are the best solutions.

@chompomonim - Glad you figured out your problem. Honestly, I’m not sure how 1.3 packages will deal with collections moving forward. @sashko’s idea of passing in collection references is probably the most bullet-proof.


#9

Su, @sashko’s idea is good in almost all cases, but I think we should be also be able to do the same with methods. I mean to pass collection as a method parameter Meteor.call('my_method', AwesomeCollection, (err, res) => {}).

Going to create feature request on github for that.


#10

It’s probably possible by making Mongo.Collection a serializable EJSON type. Check out how Astronomy does it for ideas.

If you go down that road, definitely make sure you’re securing yourself. Don’t perform arbitrary transformations on any collection that a user gives you - that’ll open the door for worlds of trouble.