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-tom

v1.3.1

Published

Yeoman generator for AngularJS Apps in CoffeeScript

Downloads

91

Readme

Tom Build Status

:a: Yeoman Generator for AngularJS App Scaffold in CoffeeScript

Why Tom ? Because Tom Waits was playing all along the implementation and was a true inspiration :saxophone:

Features

Source Linting

  • CoffeeScript source code linting

Configuration

  • Environment-based configuration, set NODE_ENV environment variable to development on your machine for a successful build
  • Modify configuration attribtues at runtime

usage

Configuration is provider through a class called Config with two function for getting and setting configuration attribtues.

get

The example below shows a sample configuration for the api attribue in app/config/development.yml

api:
    credentials:
        key: '7968tuyfgjhavsbdfjk'
    host: 'http://api.service.url'
    redirect_url: 'http://my.place.url'

to load this configuration when needed

api = Config.get('api') # Object { credentials: ..., host: ..., redirect_url: ...}

you may also dig for a deeper path inside attribtues using dot notation

host = Config.get('api.host')
api_key = Conig.get('api.credentials.key')

set

setting an attribtue is as easy as getting it

Config.set('api.host', 'http://some.other.url')

Built-in Servers

Build Versioning

  • Keep builds history
  • Navigate and checkout build versions
  • Latest build is copied to its own directory current

Assets

CDN

Deliver your build's static files from an external CDN.

In the desired environment's configuration file. i.e. app/config/production.yml

specify endpoints

WARNING endpoints will be whitelisted with Angular's ng.$sceDelegateProvider.whitelist

cdn:
    url: 'http://cdn.service.url'

You may also specify an endpoint per asset type:

supported: html,css,js,img

cdn:
    url: 'http://cdn.service.url'
    html: 'http://cdn.assets.html.service.url'
    css: 'http://cdn.assets.css.service.url'
    js: 'http://cdn.assets.js.service.url'
    img: 'http://cdn.images.service.url'

And if one of the types does not exist it will fallback to cdn:url, however if the cdn configuration is not found the URIs will only be preceded by a / delivering from the same host (self).

serving assets

  • CDN.template('uri/here.html') for HTML
  • CDN.css('uri/style.css') for CSS
  • CDN.js('my/script.js') for Javascript
  • CDN.img('pretty/penguin.jpg') for images

deploy to AWS S3

  • deploy your assets directly to Amazon Simple Storage Service (using grunt-aws)
    • configure aws in aws.json
    • use grunt deploy:aws to deploy
tip: multiple buckets
// aws.json
{
    "s3": {
        "buckets": {
            "default": "my-default-duck",
            "html": "my-html-only"
        },

        "key": "",

        "secret": ""
    }
}
# Gruntfile.coffee

...

s3: {

    options:
        bucket: '<%= aws.s3.buckets.default %>'
        accessKeyId: '<%= aws.s3.key %>'
        secretAccessKey: '<%= aws.s3.secret %>'

    current:
        cwd: 'current/'
        src: '**'

    views:
        options:
            bucket: '<%= aws.s3.buckets.html %>'
        cwd: 'app/views/'
        src: '**'
}

...

Local Storage

  • Ships with a local storage service that wraps the browser's local storage feature
  • Supports storing mixed data types (arrays, objects, etc.) preserving data type

WebSockets

  • Ships with a socket service that makes it easy to communicate using WebSockets
  • It wraps the socket.io client library
  • Supports namespaces (a.k.a channels)

Testing

Tests will always use the latest build existing in your current directory

Installation

  • install yeoman
  • via npm npm install -g generator-tom
  • create your project's directory mkdir ~/dev/my-app && cd $_
  • yo tom
  • in another terminal session run grunt serve
  • grunt and you're done

Directory Structure

- app
    - assets            : asset resources (styles and images)
    - config            : app configuration files
    - src               : app features source files
    - views             : app views
- builds                : builds versions (created after the first build)
- current               : the current build's code (created after the first build)
- lib                   : built-in libraries
- tests                 : all your tests go here
    - e2e               : end to end testing files (filnames should follow *Test.coffee)
        - config        : configuration for E2E tests
    - unit              : unit testing files (filenames should follow *Test.coffee)
        - config        : configuration for unit tests
- app.yml               : list your app's components

App Foundation

separate listing of dependencies makes it seamless to replace the implementation of a feature or module as long as their interface (usage) match, almost what the Liskov principle is about. An easy way to load the app's foundational components is to list them in app.yml as such:

classmap:
    - app/routes.coffee:routes
    - app/filters.coffee:filters
    - lib/CDN/CDN.coffee:CDN
    - lib/Config/Config.coffee:Config
    - lib/Socket/Socket.coffee:Socket
    - lib/Storage/StorageService.coffee:Storage
    - app/src/Main/controllers/MainController.coffee:MainController

autoload:
-
    expand: yes
    cwd: lib
    src:
    - Storage/**/*.coffee
    - Socket/**/*.coffee
    dest: lib/

classmap

will be translated as a browserify alias, exposing the file/module as specified after : which makes it possible to require the module by alias.

example: app/routes.coffee:routes can be included as require('routes') in any class

autoload

will be translated to aliasMappings in browserify, loads the files according to the patterns in src and exposes them according to the dest

example:

-
    expand: yes
    cwd: lib
    src:
    - Storage/**/*.coffee
    - Socket/**/*.coffee
    dest: lib/

now we can require('lib/Storage/StorageService') and anything under those directories.

Commands

grunt

lint, build, minify, and test. Ideal for compiling for production ahead of deployment.

grunt serve

run internal servers for development and testing.

  • development server to serve static content (index.html) http://localhost:9090
  • socket server using socket.io http://localhost:9091
  • testing server to be used when running E2E tests http://localhost:4444/wd/hub

grunt build-dev

lints & builds the project without minifying, sets the latest build as current. Ideal for development.

grunt test

run all tests.

grunt e2e-test

run E2E tests only.

grunt unit-test

run Unit tests only.

grunt list

list all the builds and show the current one.

grunt checkout:<build|step>

checkout a build (make it the current one).

  • by target grunt checkout:2601201422635
  • by step grunt checkout:next
    • supported steps: first, last, next, prev

grunt deploy:aws

deploy static assets to an AWS S3 bucket. Will upload everything inside current/ and app/views/

Running this project's tests

mocha --recursive

Generators

options

instructions between * are optional

###--bare skip the sub-directory level.

  • yo tom:controller main --bare will result in src/Main/MainController.coffee instead of src/Main/controllers/MainController.coffee

###--nofix skip prefix or postfix when naming.

  • yo tom:controller main --nofix will result in src/Main/controllers/Main.coffee instead of src/Main/controllers/MainController.coffee

controller

yo tom:controller <feature> *<controller>*

Example

yo tom:controller love brain

app/src/Love/controllers/BrainController

'use strict'

class BrainController

    ###*
     * Create a new BrainController instance
     *
     * @param  {Config/Config} Config
     * @param  {$scope} $scope
     * @param  {$location} $location
     * @return {BrainController}
    ###
    constructor: (@Config, @$scope, @$location)->

# inject controller dependencies
BrainController.$inject = ['Config', '$scope', '$location']

module.exports = (app)->
    # bring in dependencies
    require('src/Config/Config')(app)

    # register
    app.controller 'BrainController', BrainController

provider

yo tom:provider <feature> *<provider>*

Example

yo tom:provider Stream --nofix

app/src/Stream/providers/Stream.coffee

'use strict'

class Stream

    ###*
     * This method is used by Angular to inject dependencies
     * into this provider which in turn will be used
     * to be injected into the constructor.
     *
     * @param  {src/Config/Config} Config
     * @return {Stream}
    ###
    @$get: (Config)-> new this(Config)

    ###*
     * Create a new Stream instance.
     *
     * @param  {src/Config/Config} Config
     * @return {Stream}
    ###
    constructor: (@Config)->

Stream.$inject = ['Config']

module.exports = (app)->
    # bring in dependencies
    require('src/Config/Config')(app)

    # register
    app.provider 'Stream', -> Stream

service

yo tom:service <feature> *<service>*

Example

yo tom:service Api --bare

app/src/Api/ApiService.coffee

'use strict'

class ApiService

    ###*
     * Create a new ApiService instnace.
     *
     * @param  {$window} $window
     * @return {ApiService}
    ###
    constructor: (@$window)->

ApiService.$inject = ['$window']

module.exports = (app)-> app.service 'ApiService', ApiService

factory

yo tom:factory <feature> *<factory>*

Example

yo tom:factory chocolate --bare

app/src/Chocolate/ChocolateFactory.coffee

'use strict'

class ChocolateFactory

    ###*
     * Create a new ChocolateFactory.
     *
     * @return {ChocolateFactory}
    ###
    constructor: ->

module.exports = (app)-> app.factory 'ChocolateFactory', ChocolateFactory

directive

nofix option is ignored

options

--restrict

set the restrict option. Default 'EA'

yo tom:directive --restrict=E

--controller

create a controller along with this directive

yo tom:directive --controller

or you may specify the controller prefix

yo tom:directive --controller=edit will resutl in EditController

--templateUrl

set a URL for your template, will also create an empty template defaulting to the name of the directive in app/views/<directive>.html

--transclude

set the transclude option to true. Default not included

Examples

yo tom:directive customers myCustomer --transclude --restrict=E --bare

app/src/Customers/myCustomer.coffee

'use strict'

module.exports = (app)-> app.directive 'myCustomer', ->

    {
        restrict: 'E'
        transclude: yes
        template: ''
        scope: { }
        link: (scope, element, attrs)->
    }

yo tom:directive customers myCustomer --bare --controller --templateUrl=app/views/my-customer.html

app/src/Customers/myCustomer.coffee

'use strict'

class MyCustomerController

    ###*
     * Create a new MyCustomerController instance
     *
     * @param  {Config/Config} Config
     * @param  {$scope} $scope
     * @return {MyCustomerController}
    ###
    constructor: (@Config, @$scope)->

# inject controller dependencies
MyCustomerController.$inject = ['Config', '$scope']

module.exports = (app)-> app.directive 'myCustomer', ->

    {
        restrict: 'EA'
        templateUrl: 'app/views/mycustomer.html'
        controller: MyCustomerController
    }

using controllers

when implementing a controller for a directive, you might like to have methods accessible to the directive directly, these methods should be registered to $scope:

class MyCustomerController

    constructor: (@Config, @$scope)->
        @$scope.customers = [
            {
                name: 'Naomi'
                address: '1600 Amphetheatre'
                active: no
            }

        @$scope.activate = => @$scope.customer.active = yes
        @$scope.disactivate = => @$scope.customer.active = no

        # you can also proxy to the class preserving context
        @$scope.do = @justDoIt

    justDoIt: -> # √

# inject controller dependencies
MyCustomerController.$inject = ['Config', '$scope']

module.exports = (app)-> app.directive 'myCustomer', ->

    {
        restrict: 'EA'
        controller: MyCustomerController
        templateUrl: '/app/views/customer.html'
    }

and the directive can access it directly:

<div>{{customer.name}} - {{customer.address}}</div>
<div ng-show="customer.active">Active!</div>
<a href ng-hide="customer.active" ng-click="activate()">Activate!</a>
<a href ng-show="customer.active" ng-click="disactivate()">Disactivate</a>
<a href ng-click="do()">Just Do It</a>

TODO

  • sub generator for tests
  • exception handling

License

MIT license Copyright © Vinelab