GithubHelp home page GithubHelp logo

scottmcpherson / meteor-io Goto Github PK

View Code? Open in Web Editor NEW
59.0 5.0 5.0 83 KB

A Command-line Tool for Meteor to Create Custom Commands, Generators, and Scaffolding

JavaScript 98.26% HTML 1.18% Shell 0.56%

meteor-io's Introduction

io (for Meteor)

io is a pluggable and extendable, command-line scaffolding tool written entirely in es6.

It gives you the ability to create custom commands, generators, and templates to facilitate your Meteor workflow.

Windows has not yet been thoroughly tested.

Table of Contents

Getting Started

io leverage es6 and required node v4.2.1 or later.

To install the meteor-io npm package:

npm install -g meteor-io

And then run io from anywhere:

io

io will ask you to specify a directory to set up a couple sample generators, templates, and a config file.

After you specify a directory, io will create a director that looks similar to this:

io/
  .io/
    config.json
  generators/
    route.js
    template.js
  templates/
    package.js
    route.js
    template.html
    template.js

To create a new io project:

io create project-name

This will set up a boiler plate io project for you.

If you're not happy with the structure of the project that io creates, you can always override the create command by generating one of your own:

io g:cmd create

This will create a command for at: path/to/your/io/commands/create.js

(If you forget where io is installed, run io --help)

Once your project is created, you can then cd into your project and run the io command to start the server:

io

Config Files

The first time you run the io command, it will create a global config for you: path/to/your/io/.io/config.json You can modify this file to control which packages will be installed and removed when you run io create project-name. By default, it will install: kadira:flow-router and kadira:blaze-layout, and remove: autopublish and insecure.

io will also create a local config file for you in your project when you run io create project-name. Local config settings will trump globals.

Generators

io automatically creates a couple of sample generators for you. One to generate routes—io uses FlowRouter by default, but you can set it up to use any router, and one to generate templates. You'll be able to see and modify these generators in your local io/generators folder, and run them with the following commands:

io g:route route-name
io g:template template-name

To create a new pluggable generator:

io g:generator generator-name

Commands

Command and generators both extend the Command class, and both have access to the same functionality. They're just two separate means to organize actions. And command are called without the g: prefix.

To run a command:

io command-name args

To generate a new pluggable command:

io g:cmd command-name

Templating

io uses handlebars to generate templates. Templates can be used to dynamically create files and resources for you app. Take for example the template that's used to generate helpers, events, and life-cycle callbacks when you run io g:template template-name. The template that's used to generate those resources can be found at path/to/your/io/templates/template.js, and looks like this:

Template.{{name}}.events({
});

Template.{{name}}.helpers({
});

Template.{{name}}.onCreated(function () {
});

Template.{{name}}.onRendered(function () {
});

Template.{{name}}.onDestroyed(function () {
});

And we can use this template and interpolate the data by calling writeTemplateWithData or writeTemplatesWithData. For example, given the command io g:template template-name:

  run(args, argv) {

    var fileBaseName = self.getBaseName(args[1]);
    // template-name

    var camelCaseName = self.camelize(fileBaseName);
    // templateName

    this.writeTemplateWithData({
      src: [this.ioTemplatesPath, 'template.js'],
      dest: [this.config.dest, fileBaseName + '.js'],
      data: { name: camelCaseName }
    });

API

io provides you with a high-level API for creating custom commands and generators. All of which can be accessed and called from within the run() methods of your generators and commands.

this.ioTemplatesPath;

Gets the path to your io templates.

this.projectPath;

Gets the path to your io project.

this.appPath;

Gets the path to your meteor app inside the io project.

this.settingsPath;

Gets the path to your app's local setting.json file.

this.envPath;

Gets the path to your app's local env.sh file.

this.globalConfig;

Gets the global config in a JSON format.

this.localConfig;

Gets the project's local config in a JSON format.

this.configFile;

Gets the global config in a JSON format.

this.configFile;

Gets both the local and global config, merges them, and returns the JSON.

this.mkdir([path]);

Creates a directory with a given path String, or an Array of path parts.

Examples:

run(args, argv) {
  this.mkdir([this.appPath, 'client', templates]);
  // Creates a directory at: path/to/project/app/client/templates
run(args, argv) {
  this.mkdir('path/to/project/app/client/templates');
  // creates a directory at: path/to/project/app/client/templates

this.mkdirs([path], [path]);

Creates x number of directories with given path Strings, or Arrays of path parts.

Example:

run(args, argv) {
  var templatesPath = this.join(this.appPath, 'client', templates);
  this.mkdirs([templatesPath, 'public'],
              [templatesPath, 'admin']);
  // Creates directories at:
  // path/to/project/app/client/templates/public
  // path/to/project/app/client/templates/admin

this.copy([srcPath], [destPath]);

Copies a file from the given source path to the destination path.

Both paths can be either a String, or an array of path parts.

Examples:

run(args, argv) {
  var src = this.join(this.ioTemplatesPath, 'sample.js');
  var dest = this.join(this.appPath, 'client', 'templates', 'sample.js');
  this.copy(src, dest);
  // Copies the file from: path/to/your/io/templates/sample.js
  // to: path/to/your/project/app/client/templates/sample.js

this.copyAll({ src: src, dest: dest }, { src: src, dest: dest });

Copies x number of files from given source paths to destination paths.

Example:

run(args, argv) {
  var appTemplatesPath = this.join(this.appPath, 'client', 'templates');
  this.copy({
    src: [this.ioTemplatesPath, 'sample-one.js'],
    dest: [appTemplatesPath, 'sample-one.js']
  }, {
    src: [this.ioTemplatesPath, 'sample-two.js'],
    dest: [appTemplatesPath, 'sample-two.js']
  });
  // from: path/to/your/io/templates/sample-one.js
  // to: path/to/your/project/app/client/templates/sample-one.js
  // from: path/to/your/io/templates/sample-two.js
  // to: path/to/your/project/app/client/templates/sample-two.js

this.remove([srcPath]);

This will remove the file at the given source path.

this.removeAll([srcPath], [srcPath]);

This will remove x number of files at the given source paths.

this.writeTemplateWithData({ src: [path], dest: [path], data: data });

Grabs a template, interpolates the data, and writes the template to the specified dest path.

Example:

run(args, argv) {
  var appTemplatesPath = this.join(this.appPath, 'client', 'templates');
  this.copy({
    src: [this.ioTemplatesPath, 'sample.js'],
    dest: [appTemplatesPath, 'sample.js'],
    data: { name: 'demo' }
  });
  // This will get the template from `path/to/your/io/templates/sample.js`,
  // interpolate the data, and write the file to `path/to/your/project/app/client/templates/sample.js`

this.writeTemplatesWithData({args}, {args});

Same as writeTemplateWithData, but allows you to write multiple templates with data.

Example:

run(args, argv) {
  var appTemplatesPath = this.join(this.appPath, 'client', 'templates');
  this.copy({
    src: [this.ioTemplatesPath, 'sample.js'],
    dest: [appTemplatesPath, 'sample.js'],
    data: { name: 'demo' }
  }, {
    src: [this.ioTemplatesPath, 'sample-two.js'],
    dest: [appTemplatesPath, 'sample-two.js'],
    data: { name: 'demo' }
  });
  // This will get the template from `path/to/your/io/templates/sample.js`,
  // interpolate the data, and write the file to `path/to/your/project/app/client/templates/sample.js`
  // And the template from `path/to/your/io/templates/sample-two.js`,
  // interpolate the data, and write the file to `path/to/your/project/app/client/templates/sample-two.js`

this.writeFile(filePath);

Write a blank file to the specified filePath. filePath must be a String.

Example:

run(args, argv) {
  this.writeFile('path/to/your/project/app/client/templates/sample.js');
  // Creates a blank file at path/to/your/project/app/client/templates/sample.js

meteor-io's People

Contributors

scottmcpherson avatar stanlindsey avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar

meteor-io's Issues

Fails on create

Can't seem to be able to create a new project, here's the output:

C:\Users\leonardoc
λ io create io-test
fs.js:856
  return binding.readdir(pathModule._makeLong(path));
                 ^

Error: ENOENT: no such file or directory, scandir 'C:\Users\leonardoc\AppData\Roaming\npm\node_modules\meteor-io\bin\lib\generators'
    at Error (native)
    at Object.fs.readdirSync (fs.js:856:18)
    at requireDir (C:\Users\leonardoc\AppData\Roaming\npm\node_modules\meteor-io\node_modules\require-dir\index.js:25:20)
    at Command.loadUserGenerators (C:\Users\leonardoc\AppData\Roaming\npm\node_modules\meteor-io\lib\command.js:69:29)
    at Command.run (C:\Users\leonardoc\AppData\Roaming\npm\node_modules\meteor-io\lib\command.js:34:10)
    at Object.<anonymous> (C:\Users\leonardoc\AppData\Roaming\npm\node_modules\meteor-io\bin\io:7:13)
    at Module._compile (module.js:425:26)
    at Object.Module._extensions..js (module.js:432:10)
    at Module.load (module.js:356:32)
    at Function.Module._load (module.js:311:12)

Using nodejs 5.0.0 on win7 x64

Add default react component

It might be nice to have a default react component:

ComponentName = React.createClass({

  mixins: [ReactMeteorData],

  getMeteorData(params) {
    return {};
  },

  render() {
    return (

    );
  }
});

Issue during Create for the latest version in mac

io create test
Error: unrecognized flag --harmony-rest-parameters
Try --help for options

/usr/local/lib/node_modules/meteor-io/lib/command.js:9
class Command extends Utils {
^^^^^
SyntaxError: Unexpected reserved word
at Module._compile (module.js:439:25)
at Object.Module._extensions..js (module.js:474:10)
at Module.load (module.js:356:32)
at Function.Module._load (module.js:312:12)
at Module.require (module.js:364:17)
at require (module.js:380:17)
at Object. (/usr/local/lib/node_modules/meteor-io/lib/io.js:1:77)
at Module._compile (module.js:456:26)
at Object.Module._extensions..js (module.js:474:10)
at Module.load (module.js:356:32)

how would you go about generating a variable number of, say, helper methods?

I see how you can interpolate data, but that seems to rely on the base template being pretty static. Imagine you want to build a modal popup that lets developers specify the names of helper methods (or events, etc) to add, and then generate empty function definitions in the helpers and events map--how would I go about that? What is the best practices way you would recommend? What about a an api method to generate a map of methods/properties?

Here's how I'd imagine doing that now:

Template.{{name}}.helpers({
{{helpers}}
});

this.writeTemplateWithData({
      src: [this.ioTemplatesPath, 'template.js'],
      dest: [this.config.dest, fileBaseName + '.js'],
      data: { name: templateName, helpers: formattedStringOfHelpers }
});

It just seems that formatting the helpers string might get annoying, and being able to provide an array of helper names could be something that makes sense as a core api feature. Here's an example of how it could look :

Template.{{name}}.helpers({
    {{io.helpers helperNames}}
});

this.writeTemplateWithData({
      src: [this.ioTemplatesPath, 'template.js'],
      dest: [this.config.dest, fileBaseName + '.js'],
      data: { name: templateName, helperNames: ['selected', 'posts', 'etc'] }
});

The next step would be being able to provide a value for the function as well, so in this example helperNames could be an array of arrays, where each child array has 2 items: the name and then the function string. It would also be nice if there was a way to generate an ES6 class

Unexpected reserved word

Running on windows:

D:\Documents\GitHub>npm install -g meteor-io
D:\AppData\Roaming\npm\io -> D:\AppData\Roaming\npm\node_modules\meteor-io\bin\i
o
[email protected] D:\AppData\Roaming\npm\node_modules\meteor-io
├── [email protected]
├── [email protected]
├── [email protected]
├── [email protected]
├── [email protected]
├── [email protected]
├── [email protected] ([email protected])
├── [email protected] ([email protected], [email protected], [email protected])
├── [email protected] ([email protected], [email protected], [email protected])
├── [email protected]
└── [email protected] ([email protected], [email protected], [email protected], es6-iterator@0
.1.3, [email protected], [email protected])

D:\Documents\GitHub>io
Error: unrecognized flag --harmony-rest-parameters
Try --help for options

D:\AppData\Roaming\npm\node_modules\meteor-io\lib\command.js:9
class Command extends Utils {
^^^^^
SyntaxError: Unexpected reserved word
    at Module._compile (module.js:439:25)
    at Object.Module._extensions..js (module.js:474:10)
    at Module.load (module.js:356:32)
    at Function.Module._load (module.js:312:12)
    at Module.require (module.js:364:17)
    at require (module.js:380:17)
    at Object.<anonymous> (D:\AppData\Roaming\npm\node_modules\meteor-io\lib\io.
js:1:77)
    at Module._compile (module.js:456:26)
    at Object.Module._extensions..js (module.js:474:10)
    at Module.load (module.js:356:32)

Let me know if you need any diagnostic steps.

Create project fail.

i follow your tutorial here but i'm getting error everytime..

npm install -g meteor-io
ok passed.

io
*ok passed
*

After you specify a directory, io will create a director that looks similar to this:
yes, io created for me some directory.

io create project-name
*and ....
*

mac$ io create project-name
fs.js:856
  return binding.readdir(pathModule._makeLong(path));
                 ^

Error: ENOENT: no such file or directory, scandir '/usr/local/lib/node_modules/meteor-io/lib/Desktop/meteormain/io/generators'
    at Error (native)
    at Object.fs.readdirSync (fs.js:856:18)
    at requireDir (/usr/local/lib/node_modules/meteor-io/node_modules/require-dir/index.js:25:20)
    at Command.loadUserGenerators (/usr/local/lib/node_modules/meteor-io/lib/command.js:83:29)
    at Command.run (/usr/local/lib/node_modules/meteor-io/lib/command.js:35:10)
    at Object.<anonymous> (/usr/local/lib/node_modules/meteor-io/bin/io:7:13)
    at Module._compile (module.js:398:26)
    at Object.Module._extensions..js (module.js:405:10)
    at Module.load (module.js:344:32)
    at Function.Module._load (module.js:301:12)


ENOENT: config.json' on Windows

Node.js latest stable 5.0.0

First we need to set up an io directory.

Specify a directory where you would like to store your generators, templates, an
d config.

Directory: ./

Created dir:  io
Created dir:  io\templates
Created dir:  io\generators
Created dir:  io\.io

{ [Error: ENOENT: no such file or directory, stat 'D:\AppData\Roaming\npm\node_m
odules\meteor-io\bin\lib\templates\templates\config.json']
  errno: -4058,
  code: 'ENOENT',
  syscall: 'stat',
  path: 'D:\\AppData\\Roaming\\npm\\node_modules\\meteor-io\\bin\\lib\\templates
\\templates\\config.json' }

Let me know if you need anything doing to figure this out :D

if (self.isDir(ioDest)) always returns false

o/

Looks like the isDir method is always returning false and triggering the 'not valid directory error':

Directory: test
/usr/local/lib/node_modules/meteor-io/lib/commands/setup.js:93
    throw new Error('Not a valid directory');

I replaced "if (self.isDir(ioDest))" with "if (ioDest)" and it creates the directory fine. Though obviously there is no validation.

I still appear to get errors down the line. When attempting to create a project etc.
I have updated Node to v5.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.