Meteor package only approach, calling namespace function from a different package - meteor

I am using the structure design shown at Meteor Meetup Antwerp by Pieter Soudan
I have had success by having different namespace names (UserAuth,AppRoute) depending on the functionality of my module. I however want to have an app specific namespace UP (UserPortal) and have namespaces like UP.UserAuth, UP.AppRoutes.
I can't seem to call a function in UP.UserAuth that checks for login.
My up-app package package.js looks like this
Package.describe({
name: 'up-app',
version: '0.0.1',
summary: 'User Portal Application',
});
var both=['server','client'];
var server ='server';
var client ='client';
Package.onUse(function(api) {
api.versionsFrom('1.0.3.2');
api.use('templating',client);
api.use('iron:router#1.0.7',both);
api.use('tracker',both);
api.use('underscore',both);
api.use('blaze',both);
api.use(['up-user-auth'],both);
api.addFiles(['lib/namespace.js','lib/routes.js'],both);
api.addFiles(['views/dashboard.html','views/loading.html'],client);
api.export('UP');
});
Package.onTest(function(api) {
api.use('tinytest');
api.use('up-app');
api.addFiles('tests/up-app-tests.js');
});
I intend to use up-app to declare all my app dependencies within a single package.
My up-app/lib/routes.js file looks like this:
Router.configure({
layoutTemplate: 'upDashBoard',
loadingTemplate: 'upLoading'
});
Router.onBeforeAction(UP.UserAuth.loginRequired, {
except: ['login','install']
});
Router.route('/', {
name: 'home'
});
My up-user-auth package has this in its package.js
Package.describe({
name: 'up-user-auth',
version: '0.0.1',
// Brief, one-line summary of the package.
summary: 'User Authentication and Roles Management',
});
Package.onUse(function(api) {
var both = ['server', 'client'];
var server = 'server';
var client = 'client';
api.versionsFrom('1.0.3.2');
api.use([
'tracker',
'service-configuration',
'accounts-base',
'underscore',
'templating',
'blaze',
'session',
'sha',
]
,client);
api.use([
'tracker',
'service-configuration',
'accounts-password',
'accounts-base',
'underscore',]
,server);
api.use(['iron:router#1.0.1','copleykj:mesosphere'], both);
api.imply(['accounts-base','accounts-password'], both);
api.addFiles(['lib/namespace.js','lib/loginValidation.js','lib/loginMethods.js'],both);
api.export('UP', both);
});
Package.onTest(function(api) {
api.use('tinytest');
api.use('up-user-auth');
api.addFiles('tests/server/up-user-auth-tests.js');
});
My up/lib/namespace.js looks like this:
UP={};
UP.UserAuth={
loginRequired: function() {
return console.log("loginControllers");
}
}
If I remove the second reference to UP={}; then I get an error saying
Cannot set property 'UserAuth' of undefined but when I add it all I get is Cannot read property 'loginRequired' of undefined
What am I doing wrong?

your forgot to declare the dependency on your main package 'up-app'.
Every package using the namespace UP, should declare dependency on the package exporting the namespace.
So, just add
api.use('up-app', ['client', 'server']);
in up-user-auth/package.js
Kr,
Pieter

Related

TypeError: Cannot read property <template name> of undefined when creating package

I am trying to create a package for Meteor, unsuccessfully unfortunately. I'm on Meteor 1.8.1. My goal is to make a template for a button that I can use in my application like this {{> testButton}} (I am just trying it out atm).
package.js
Package.describe({
name: 'button-test',
version: '0.0.1',
summary: '',
git: '',
documentation: 'README.md'
});
Package.onUse(function (api) {
api.use(['ecmascript']);
api.use(['session', 'templating'], ['client', 'server']);
api.mainModule('button-test.js');
});
Package.onTest(function (api) {
api.use('ecmascript');
api.use('tinytest');
api.use('button-test');
api.mainModule('button-test-tests.js');
});
button-test.js
// Variables exported by this module can be imported by other packages and
// applications. See button-test-tests.js for an example of importing.
import './testButton.js';
testButton.js
import { Template } from 'meteor/templating';
Template.testButton.events({
'click #buttonT': () =>
console.log('Clicked the button')
});
testButton.html
<template name="testButton"><button id="buttonT">TEST</button></template>
I have some problems with this;
Running the code like this returns the error TypeError: Cannot read property 'testButton' of undefined. So there is a problem with Template, but I don't know what it is, since I have added it with api.use
When I try to add import ./testButton.html to testButton.js I get the error Error: Cannot find module './testButton.html'
I looked at the source code for accounts-ui-unstyled, but this is written on an older meteor version.
Does anybody have an idea as to what I am doing wrong?
The problem was with the api.mainModule, I solved it by having my Package.onUse like this:
Package.onUse(function (api) {
api.use(['templating', 'blaze'], 'client');
api.use('ecmascript');
api.addFiles(['button-test.js'], 'client');
});
After using the addFiles instead of mainModule, I could import the html and the Template problem disappeared. I have no idea why this works and mainModule does not, but hey, it does.

Meteor.js: Using server.call when testing with Chimp

I'm having an issue triggering method calls while writing feature tests. I'm not actually given an error in the chimp terminal log, but the server.call line is where the failure is highlighted. I believe this might be related to the folder structure of the app (which I've loosely based on Letterpress) or the order in which the call is defined and then triggered. When I move the method call out to my main.js file (in the root folder of the app), it works without a problem.
hooks.js path: /app/tests/cucumber/features/support/hooks.js
(function(){
module.exports = function() {
this.Before(function() {
console.log("server calling");
server.call("fixtures/resetUsers"); //test stops here
});
};
})();
fixtures.js /app/packages/fixtures/fixtures.js
(function(){
'use strict';
Meteor.methods({
"fixtures/resetUsers": function() {
Meteor.users.remove({});
}
});
})();
package.js /app/packages/fixtures/packages.js
Package.describe({
name: 'forum:fixtures',
version: '0.0.1',
summary: '',
debugOnly: true
});
Package.onUse(function(api) {
api.versionsFrom('1.2.1');
api.use('ecmascript');
api.addFiles('fixtures.js', 'server');
});
Note: I originally didn't have the fixtures folder wrapped in the packages folder (it still didn't work then) but came across this post by #Xolv.io, the developers of Chimp.js who advised to do so.
with the new chimp, you can just use:
server.execute(function() {
// code you put here will run on the server
});
Check this repository for examples:
https://github.com/xolvio/automated-testing-best-practices/
In your sample repo, if you define a meteor method, 'something', you can call as server.call('something').
If you have a standard method definition (not even a meteor method), say something2=function(){}, with xolvio:backdoor, you can server.execute('something2'). ( calling chimp with --ddp switch)

Meteor's iron:router loadingTemplate not rendered

I have the following code:
Router.configure({
layoutTemplate: 'commonTemplate',
loadingTemplate: 'loadingApp'
});
Router.route('/configuration', {
name:'configuration',
template:'configuration',
onBeforeAction: function(){
this.layout(null);
if (Session.get('appReady')){
this.next();
} else {
console.log("loading app...");
this.render('loadingApp');
}
}
});
"loading app..." is correctly shown on console.
However during that time (waiting for session variable), no loading template (neither from Router.configure; nor from this.render) is displayed.
Also when the session variable is true, the configuration template is rendered correctly.
Is this an iron:router bug or I'm doing something wrong?
Your code is working for me, maybe the problem is that your loading template isn't showing the loading content properly. I tested the code with the loading template from the https://atmospherejs.com/sacha/spin package and worked fine.
You could install from atmospherejs the package sacha:spin and configure Iron Router to use the loading template, this package is easy to use, you have to use the template 'loading' where you want the loading animation.
1) meteor add sacha:spin
2) In your router file :
Router.configure({
loadingTemplate: 'loading'
});
Router.route('/test', {
name: 'test',
template: 'test',
onBeforeAction : function()
{
this.layout(null);
if (Session.get('appReady')){
this.next();
} else {
console.log("loading app...");
this.render('loading');
}
}
}
);

Template helpers in Telescope Package when using Telescope.modules.add

I have been able to insert this template titled lightBox using Telescope.modules.add
The file structure seems to be working fine except I cannot make a template helper to interact with the template thats inserted using Telescope.modules.add function. The following code produces a client side error of "Uncaught TypeError: Cannot read property 'helpers' of undefined". Without this helper method the template is visible and does exist in the browser view.
lightBox.js
if (Meteor.isClient) {
Telescope.modules.add("top", {
template: "lightBox",
order: 0
});
Template.layout.events({
'click .post-content': function (e) {
Session.set('lightBoxPageViewCounter', 1 );
}
});
Template.lightBox.helpers({
lightBoxOn: function() {
return true;
}
});
}
Package.js
Package.describe({
name: "admithub:admithub-lightbox",
summary: "popup lightbox for admit hub forum to college email leads",
version: "0.0.1"
});
Package.onUse(function(api) {
api.use([
'accounts-base',
'stylus',
'telescope:core#0.24.0',
'aldeed:simple-schema',
'aldeed:collection2',
'aldeed:autoform'
]);
api.addFiles('lib/client/lightBox.js', 'client');
api.addFiles('lib/client/lightbox.html', 'client');
api.addFiles('lib/client/lightbox.styl', 'client');
});
Template is named lightBox and exists in the same package within the same directory. I have worked around this by using a global helper methods but this is an inefficient fix.
Your package load order is wrong, you must load the template declaration (html) before the template helpers declaration (js), you just need to swap your api.addFiles calls.
api.addFiles('lib/client/lightbox.html', 'client');
api.addFiles('lib/client/lightBox.js', 'client');

Iron-router set notFoundTemplate when no data found in database

How can I set a layout when my data function returns null.
For example, in the route below, when chefs is null, I would like to render my 'notFound' template.
Router.route('/vendors/chefs/:_url', {
template: 'chefs',
data: function() {
var chefs = Chef_db.findOne({url: this.params._url});
return chefs;
}
});
Take a look at the notFoundTemplate in the documentation: https://github.com/iron-meteor/iron-router/blob/devel/Guide.md
You can apply it globally:
Router.plugin('dataNotFound', {notFoundTemplate: 'notFound'});
Or you can apply it to specific routes using the except/only options:
Router.plugin('dataNotFound', {
notFoundTemplate: 'NotFound',
except: ['server.route']
// or only: ['routeOne', 'routeTwo']
});
There's a built-in plugin for that. It's called dataNotFound. It's mentioned in the iron:router guide.

Resources