npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

generator-angular-xl

v0.6.1

Published

Custom yeoman generator for AngularJS

Downloads

49

Readme

generator-angular-xl logo

An opinionated kickstarter for your next large scale AngularJS application. Avoid boilerplate and improve productivity and consistency.

[Build Status](https://travis-ci.org/kennethlynne/generator-angular-xl) Code Climate

Roadmap:

  • Support ES6 transpilation
  • Support coffescript
  • Support Jade
  • Add demo application
  • Support associations, validation and basic ORM functionality (ngSymbiosis.Model)
  • Support caching to localStorage or similar of models and $http requests (offline, spotty connection, change tracking etc.) (ngSymbiosis.Repository)
  • Support build targets (Cordova/Phonegap (iOS, Android), Chrome app, Web-app, Firefox OS app, Chrome plugin)
  • Move generator templates into the project, so that the templates may be configured on a per project basis
  • Support Gulp for build instead, or in combination with, grunt
  • Add protractor tests
  • Better documentation

Maintainer: Kenneth Lynne

Based on angular-seed and generator-angular.


Quick start

Install Node.js with npm, then run:

npm install -g generator-angular-xl

Make a new directory, and cd into it:

mkdir my-new-project
cd my-new-project

Run yo angular-xl, with your application name:

yo angular-xl app-name

Run grunt server to start the local server.

Awesomeness ensues

Developing with the generator

Available Grunt tasks

grunt server    to run a test server with live reload.
grunt test      to run tests once (for continous integration)
karma start     to run tests coninously and rerun tests on file change
grunt changelog bumps version numbers in `bower.json` and `package.json` and creates a changelog based on your commit history using [these](https://docs.google.com/document/d/1QrDFcIiPjSLDn3EL15IJygNPiHORgU1_OOAqWjiDU5Y/edit) conventions

The following commands will build the application into the `/dist` folder.
grunt build     production profile, minified, concatinated and awesomified for production
grunt build:dev development profile, unminified code
grunt build:prototype same as dev profile, only stubbing out the API witch in turn makes this app a prototype :)

Deploy
grunt deploy    takes whatever lies in the `/dist` folder and pushes it to the `gh-states` branch, making whatever build you run before available to the world to see at `<your-username>.github.io/<your-repository>/`

Generators

Available generators:

Note: Generators are to be run from the root directory of your app.

Module

app/scripts/module.js contains the applications main module definition. All dependancies for your application needs to be specified here.

App

Sets up a new AngularJS app, generating all the boilerplate you need to get started. The app generator also installs Twitter Bootstrap and additional AngularJS modules.

Example:

yo angular-xl

CRUD-Mock

Prototype fast before the API is implemented, but implement like the API already exists.

yo angular-xl:crud-mock user

Creates the necessary code to stub out CRUD calls to example.com/api/users a CRUD API in the dev folder of your project. It will automatically intercept all calls done through $http to the API and reply with data after the given delay, when ever you are ready to implement with a real API set useMocks: false in config/config.js. The mocks are excluded from the build by default.

State

States are located under app/states. A state basically is a controller, with a view and state specific styling. Routes are specified using the powerful Angular-UI Route API in the config section in the controller.

Example:

yo angular-xl:state user

Produces app/states/user/index/user.js, test/spec/states/user/index/user.js, app/states/user/index/views/user.html and app/states/user/styles/_user.scss

Routing

Routes are configured in app/config/routes.js. Each individual controller registers its own route.

Controller

Generates a controller in app/states and an accompanying test in test/spec/states. Every controller is generated with an accompanying initService, that is responsible for fetching data and returning a promise. This helps you load data before the controller is instantiated.

Example:

yo angular-xl:controller user

Directive

Generates a directive in app/scripts/directives.

Example:

yo angular-xl:directive myDirective

Produces app/scripts/directives/my-directive.js:

angular.module('myMod').directive('myDirective', function () {
  return {
    template: '<div></div>',
    restrict: 'E',
    link: function postLink(scope, element, attrs) {
      element.text('this is the myDirective directive');
    }
  };
});

Component

A component is basically a element directive that by convention use a view located in app/views/component/<component-name>/<component-name>.html. This helps keep complexity low, and makes it easy to separate parts of your application into smaller and more maintainable parts. The view folder is configurable, and it is even possible to provide your own factory function for complete customizability. Generates a directive in app/scripts/components that uses a factory called componentFactory for convention over configuration.

Example:

yo angular-xl:component awesomeUnicorn

Produces these files: app/scripts/components/awesome-unicorn.js:

angular.module('yourModule.components')
    .controller('awesomeUnicornCtrl', function ($scope, $element) {
        $element.text('this is the awesome unicorn component');
    })
    .component('awesomeUnicorn', function () {
        return {
            controller: 'awesomeUnicornComponentCtrl'
        };
    });

test/spec/components/awesome-unicorn.js app/styles/components/awesome-unicorn/_awesome-unicorn.scss (and adds an import statement to it in app/styles/_components.scss) app/views/components/awesome-unicorn/awesome-unicorn.html

<div class="awesome-unicorn-component">
    <p>This is the awesome-unicorn component.</p>
</div>

Witch in turn lets you specify custom HTML tags like this to invoke a completely self contained component:

<awesome-unicorn-component></awesome-unicorn-component>

The view has specified a component name as a class, helping you avoid CSS collisions. Specify your styles specific for this component in SCSS under a .awesome-unicorn-component class wrapper, and only this component is targeted. This is an OK approach until shadow DOMs and web components become widely supported.

Filter

Generates a filter in app/scripts/filters.

Example:

yo angular-xl:filter myFilter

Produces app/scripts/filters/my-filter.js:

angular.module('myMod').filter('myFilter', function () {
  return function (input) {
    return 'myFilter filter:' + input;
  };
});

Service

Generates an AngularJS service.

Example:

yo angular-xl:service myService

Produces app/scripts/services/my-service.js:

angular.module('myMod').service('myService', function () {
  // ...
});

You can also do yo angular:factory, yo angular:provider, yo angular:value, and yo angular:constant for other types of services.

Model

Uses ngSymbiosis.model. Generates an model with basic CRUD functionality with methods like $save and $delete.

Example:

yo angular-xl:model category

Please use singluar nouns for your models and repositories. The models url will be pluralized automatically by default.

Produces app/models/category.js and an accompanying test:

angular.module('yourApp')
    .factory('CategoryModel', function (BaseModel, APIBaseUrl, $http) {

        var collectionUrl = 'categories';

        function CategoryModel(data) {
            data = data || {};
            data.url = APIBaseUrl + collectionUrl;
            BaseModel.call(this,data);
        }

        CategoryModel.$settings = {url: APIBaseUrl + collectionUrl};
        CategoryModel.prototype = Object.create(BaseModel.prototype);
        
        //You can add custom methods or override existing ones here
        //Example:
        CategoryModel.prototype.$delete: function () {
          var model = this;
          
          return $http.delete(model.$settings.urlBase + '/' + model.id, model).then(function (response) {
            model.$set(response.data, true);
            
            //Show an anoying alert on every delete
            alert('Hey there, you deleted something. Good for you.');
            
            return response;
          });
        }

        return CategoryModel;
    });

Then instantiate this in for example a controller

angular.module('yourApp')
    .controller('demo', function($scope, CategoryModel) {
        
            var category = new CategoryModel();

            category.title = 'New title';
            category.id = 5;

            category
                .$save() 
                //Since it has an id it will now do a PUT to /categories/5, 
                //if it did not have an id it would do a POST to /categories/
                .then(function () {
                    alert('Saved!');
                })
                .catch(function (err) {
                    alert('Failed!');
                });
    });

Repository

Uses ngSymbiosis.repository Generates a model and an accompanying repository to handle client side caching and change tracking. It uses $http by default, but you should override the methods for your own implementation. Return promises, and you're good.

Example:

yo angular-xl:repository school

Please use singluar nouns for your models and repositories. The models url will be pluralized automatically by default.

Produces app/scripts/models/school.js, app/scripts/repositories/school.js and an accompanying tests and mock data.

angular.module('yourApp')
    .factory('SchoolRepository', function ($injector, SchoolModel) {
        var BaseRepository = $injector.get('BaseRepository');
        return new BaseRepository({name: 'Category', model: SchoolModel});
    });

Example:

angular.module('myMod').service('myService', function (SchoolRepository) {
  var school = SchoolRepository.create({id:5, title:'Awesomesauce'});
  school.$save(); //Does a PUT to the applications configured API - /schools/1 with the elements data
});
//Does a GET to the models base url (/videos/)
VideoRepository.getAll().then(function (videos) {
    $scope.videos = videos;
});

//Does a GET for a specific entity (/videos/1)
VideoRepository.getById(1).then(function (video) {
    $scope.video = video;
});

Extending a repository with custom methods

Example, showing how to add a custom search method to a tags repository:


angular.module('yourApp')
    .factory('TagRepository', function ($injector, TagModel, $http) {
        var BaseRepository = $injector.get('BaseRepository');
        
        
        function TagRepository() {
            //Call `super`
            BaseRepository.apply(this, arguments);
        }
        //Inherit from BaseRepository
        TagRepository.prototype = Object.create(BaseRepository.prototype);

        //Add custom serach method
        TagRepository.prototype.search = function (query) {
            var repository = this;
            var Model = repository.$settings.model;

            return $http.get(Model.$settings.url + '/search?q=' + query, {tracker: repository.$settings.name + '.search'}).then(function (response) {
                if (angular.isArray(response.data)) {
                    return response.data.map(function (item) {
                        var instance = new Model(item);
                        repository.cache[item.id] = instance;
                        return instance;
                    });
                }
                else {
                    throw new Error('Unexpected response from API. Expected Array, got ' + typeof response.data, response.data);
                }
            });
        };

        //Return a new instance of the repository
        return new TagRepository({name: 'TagRepository', model: TagModel});
    });
    

Usage

TagRepository.search('query').then(function (hits) {
    //hits is an array of model instances
    doSomething(hits);
});

Decorator

Generates an AngularJS service decorator.

Example:

yo angular-xl:decorator serviceName

Produces app/scripts/decorators/servicename-decorator.js:

angular.module('myMod').config(function ($provide) {
    $provide.decorator('serviceName', function ($delegate) {
      // ...
      return $delegate;
    });
  });

CoffeeScript

CoffeScript is not supported for now for maintenance reasons. Coffescript is awesome, but I won't spend the time necessary to maintain different versions for now. May be added in the future.

Minification Safe

The recommended build process uses ngmin, a tool that automatically adds these annotations. However, if you'd rather not use ngmin, you have to add these annotations manually yourself.

Bower Components

The following packages are always installed by the app generator:

  • angular
  • log
  • angular-mocks
  • angular-animate
  • angular-scenario
  • angular-component-factory
  • angular-ui-router
  • angular-promise-tracker
  • angular-loading-bar
  • angular-xeditable
  • angular-ui-bootstrap
  • ng-symbiosis-utils
  • ng-symbiosis-routeprovider
  • ng-symbiosis-repository
  • ng-symbiosis-model

The following additional modules are optional:

  • angular-cookies
  • angular-loader
  • angular-touch
  • angular-resource
  • angular-sanitize
  • ngStorage

All of these can be updated with bower update as new versions of AngularJS are released. When you install new dependancies you have to add a reference to the script files in resources.json under external. The build task will inject this into index.html during runtime, and when you build the project it will by convention use the minified version of the source file, that should be located in the same folder, with the exact same filename with a .min suffix. This will be concatenated without minification.

Configuration

Yeoman generated projects can be further tweaked according to your needs by modifying project files appropriately.

Output

You can change the app directory by adding a appPath property to bower.json. For instance, if you wanted to easily integrate with Express.js, you could add the following:

{
  "name": "yo-test",
  "version": "0.0.0",
  ...
  "appPath": "public"
}

This will cause Yeoman-generated client-side files to be placed in public.

Resources.json

All configuration about what files and in what order the files are supposed to be loaded is specified in resources.json. This configuration is shared between both jasmine, minifiers and index.html.

Resource.json contains two sections. One for JS and one for SCSS.

"config/routes.js",
"scripts/**/*.js"

Files will be matched only once, so in the aforementioned example the routes config will be loaded before everything else is included.

Add a reference in resource to the unminified version of the library you want to use, as it will automatically use the library suffixed with .min during build time.

manifest.appcache

When you build your application, the will automatically be created a cache manifest file in the dist folder. The manifest file must be served with the MIME type text/cache-manifest. Read more about the HTML5 Appcache specification here

Testing

Running grunt test will run the unit tests with karma. Under the folder test/coverage you will find your whole application structure mapped into matching HTML documents describing how tests cover your code. Use this to your advantage. Crush bugs before they are born.

Contribute

See the contributing docs

When submitting an issue, please follow the guidelines. Especially important is to make sure Yeoman is up-to-date, and providing the command or commands that cause the issue.

When submitting a PR, make sure that the commit messages match the AngularJS conventions.

When submitting a bugfix, write a test that exposes the bug and fails before applying your fix. Submit the test alongside the fix.

When submitting a new feature, add tests that cover the feature.

License

BSD license

Analytics