├── .editorconfig
├── .gitattributes
├── .gitignore
├── .jshintrc
├── .travis.yml
├── CHANGELOG.md
├── CONTRIBUTING.md
├── Gruntfile.js
├── LICENSE
├── README.md
├── TRIAGING.md
├── bin
└── hoodie
├── doc
└── cli
│ ├── help.install.txt
│ ├── help.new.txt
│ ├── help.reset.txt
│ ├── help.start.txt
│ ├── help.txt
│ └── help.uninstall.txt
├── lib
├── cli.js
├── cli
│ ├── argv.js
│ ├── help.js
│ ├── install.js
│ ├── logo.js
│ ├── new.js
│ ├── reset.js
│ ├── start.js
│ ├── uninstall.js
│ ├── unknown.js
│ ├── util
│ │ ├── console.js
│ │ └── notifier.js
│ └── version.js
├── hoodie.js
├── hoodie
│ ├── install.js
│ ├── new.js
│ ├── reset.js
│ ├── start.js
│ ├── uninstall.js
│ ├── util
│ │ ├── command.js
│ │ ├── dir.js
│ │ ├── git.js
│ │ ├── insight.js
│ │ ├── packages.js
│ │ └── pid.js
│ └── version.js
└── main.js
├── package.json
└── spec
├── cli.spec.js
├── cli
├── help.spec.js
├── install.spec.js
├── new.spec.js
├── reset.spec.js
├── start.spec.js
├── uninstall.spec.js
└── unknown.spec.js
├── hoodie.spec.js
├── hoodie
├── install.spec.js
├── new.spec.js
├── reset.spec.js
├── start.spec.js
├── uninstall.spec.js
├── util
│ └── dir.spec.js
└── version.spec.js
├── integration
└── hoodie.js
├── main.spec.js
├── runner.js
└── support
└── helper.js
/.editorconfig:
--------------------------------------------------------------------------------
1 | root = true
2 |
3 | [*]
4 |
5 | end_of_line = lf
6 | insert_final_newline = true
7 | indent_style = space
8 | indent_size = 2
9 | trim_trailing_whitespace = true
10 |
11 | [*.md]
12 | trim_trailing_whitespace = false
13 |
--------------------------------------------------------------------------------
/.gitattributes:
--------------------------------------------------------------------------------
1 | * text=auto
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | .DS_Store
2 |
3 | node_modules/
4 | npm-debug.log
5 | .tmp
6 |
--------------------------------------------------------------------------------
/.jshintrc:
--------------------------------------------------------------------------------
1 | {
2 | "passfail": false,
3 | "maxerr": 200,
4 | "browser": true,
5 | "node": true,
6 | "dojo": false,
7 | "jquery": true,
8 | "devel": true,
9 | "predef": [
10 | "sinon",
11 | "define",
12 | "require",
13 | "Hoodie",
14 | "it",
15 | "describe",
16 | "expect",
17 | "beforeEach",
18 | "afterEach",
19 | "before",
20 | "after",
21 | "jasmine",
22 | "_and",
23 | "_but",
24 | "_when",
25 | "__bind",
26 | "__extends",
27 | "spyOn",
28 | "Mocks"
29 | ],
30 | "debug": false,
31 | "devel": false,
32 | "strict": false,
33 | "globalstrict": false,
34 | "asi": false,
35 | "laxbreak": false,
36 | "bitwise": true,
37 | "boss": false,
38 | "curly": true,
39 | "eqeqeq": true,
40 | "eqnull": true,
41 | "evil": false,
42 | "expr": true,
43 | "forin": true,
44 | "immed": true,
45 | "latedef": false,
46 | "loopfunc": false,
47 | "noarg": true,
48 | "regexp": false,
49 | "regexdash": false,
50 | "scripturl": false,
51 | "shadow": false,
52 | "supernew": false,
53 | "undef": true,
54 | "newcap": true,
55 | "noempty": true,
56 | "nonew": false,
57 | "nomen": false,
58 | "onevar": false,
59 | "plusplus": false,
60 | "sub": false,
61 | "trailing": true,
62 | "white": false,
63 | "unused": true,
64 | "multistr": true,
65 | "maxdepth": 4,
66 | "indent": 2,
67 | "quotmark": "single",
68 | "trailing": true
69 | }
70 |
71 |
--------------------------------------------------------------------------------
/.travis.yml:
--------------------------------------------------------------------------------
1 | before_script:
2 | - npm install -g grunt-cli
3 | before_deploy:
4 | - grunt before-deploy
5 | after_deploy:
6 | - grunt after-deploy
7 | language: node_js
8 | node_js:
9 | - '0.10'
10 | notifications:
11 | email: false
12 | slack:
13 | secure: XgxXg3pJLkWSk0qCrUm6ADU8suGQPAYa/Y+0u93dyCVU2d9H/3rOj2f1xjQiFU6ya9i/eFwfb83yS71r1OALFQNba6jy41BqLwwVpWHxieWSsXGqcTYaBLo+oNC3sGvl/rOK28n8de2xhqfE0YuEMiToGBWkcC+rFVFQ7Iv83pU=
14 | env:
15 | global:
16 | - secure: EAAejPpw+v+ooM5HQdRbQTSW85aAyKB51ADc30GnpD2TP4Cw8RgWHkYqEFm47X65b9UeZLp5CwzqWk9+QvTg09jloowvrLPCCEE+VznKx10Sb/chd0y9Dcg8L9vEUeWC2WKsL+xVMfsGyu3rILWWgvK5S3RH/C2n44X4ADa1doc=
17 | deploy:
18 | provider: npm
19 | email: stephan@thehoodiefirm.com
20 | on:
21 | all_branches: true
22 | tags: true
23 | api_key:
24 | secure: BKgTHGK2rBR5tWZ/7VSlyi+t0ttmFUyHbFv8t6pAMuvHC/TdZWQTGddosNsYLO5njTj9z4OHVz+/B8ESKcGHKAVjYPwdGSIMTgs8xXcG8FksTrKfwhTxckgYdPu2SghVkjczbJ3Frmn2KXxHWLpFepn52IIpyxTwUVw3VdGCTcg=
25 | sudo: false
26 | cache:
27 | directories:
28 | - node_modules
29 |
--------------------------------------------------------------------------------
/CHANGELOG.md:
--------------------------------------------------------------------------------
1 |
2 | ### 0.6.3 (2014-11-07)
3 |
4 |
5 | #### Bug Fixes
6 |
7 | * **new:** get registry url via config api ([b8ef5485](https://github.com/hoodiehq/hoodie-cli/commit/b8ef54858a646329461f1380c1d0e690890451c6), closes [#151](https://github.com/hoodiehq/hoodie-cli/issues/151))
8 |
9 |
10 |
11 | ### 0.6.2 (2014-10-21)
12 |
13 |
14 | #### Bug Fixes
15 |
16 | * **new:**
17 | * allow to install specific template version ([e353c4ee](https://github.com/hoodiehq/hoodie-cli/commit/e353c4eecbe856ca578373b8026041b9f7338a7f))
18 | * correct error handling for unpublished templates ([b123e5c3](https://github.com/hoodiehq/hoodie-cli/commit/b123e5c3c99ed041f43510f9f03eec97b1603800), closes [#149](https://github.com/hoodiehq/hoodie-cli/issues/149))
19 |
20 |
21 |
22 | ### 0.6.1 (2014-09-08)
23 |
24 |
25 | #### Bug Fixes
26 |
27 | * **new:** install template from cache if possible ([383305f5](https://github.com/hoodiehq/hoodie-cli/commit/383305f54c7162b0ce65b3ca5ed3b0194860be97))
28 |
29 |
30 |
31 | ## 0.6.0 (2014-08-07)
32 |
33 |
34 | #### Bug Fixes
35 |
36 | * **tracking:**
37 | * fix syntax err ([8edca8f1](https://github.com/hoodiehq/hoodie-cli/commit/8edca8f1c8cc81447a99b0ec410ac12267f3fc5b))
38 | * only set tracking code in non-ci env ([7a6bf73d](https://github.com/hoodiehq/hoodie-cli/commit/7a6bf73d85bc76e7e01b49437a220481eb84d559))
39 |
40 |
41 | #### Features
42 |
43 | * **analytics:** adds yeoman insights module ([48fb8903](https://github.com/hoodiehq/hoodie-cli/commit/48fb8903f0f6731fc994657dd2c0e3b73eb05134))
44 |
45 |
46 |
47 | ### 0.5.6 (2014-08-04)
48 |
49 |
50 |
51 | ### 0.5.5 (2014-08-01)
52 |
53 |
54 | #### Bug Fixes
55 |
56 | * **new:**
57 | * log npm error messages ([d64cfc9b](https://github.com/hoodiehq/hoodie-cli/commit/d64cfc9b49530a4cf173197e89a7d5abffa13da8))
58 | * use npm api rather than cli to fetch template ([51736586](https://github.com/hoodiehq/hoodie-cli/commit/51736586ed6127ddd1dd3331184f9593e5ea27b5))
59 |
60 |
61 |
62 | ### 0.5.4 (2014-07-31)
63 |
64 |
65 | #### Bug Fixes
66 |
67 | * **cp:** fixes copy and call to callbacks ([fd1d122d](https://github.com/hoodiehq/hoodie-cli/commit/fd1d122d033a94fbdf2e8ea228dd5b5b9af4f1e4))
68 | * **name:** adds default name back in ([d0bca1a7](https://github.com/hoodiehq/hoodie-cli/commit/d0bca1a7848e72e241ae6e0083f8610bf9fd458b))
69 | * **npm:** fix path template gets installed into ([891f81d5](https://github.com/hoodiehq/hoodie-cli/commit/891f81d53f7735e4621f4c59986c6c346753eb95))
70 | * **template:** adds helpers and fixes ([8f7f300f](https://github.com/hoodiehq/hoodie-cli/commit/8f7f300f1f6c962a0c1fbf04ef18ec027cd2dd96))
71 |
72 |
73 |
74 | ### 0.5.3 (2014-07-30)
75 |
76 |
77 | #### Features
78 |
79 | * **process:** prevent hoodie-server from crashing ([e54a75e4](https://github.com/hoodiehq/hoodie-cli/commit/e54a75e4edc1cf8af29713528089deffcd0fc5af))
80 |
81 |
82 |
83 | ### 0.5.2 (2014-07-25)
84 |
85 |
86 | #### Bug Fixes
87 |
88 | * **update-notifier:** pass pkg details to update-notifier ([e5cdc9ac](https://github.com/hoodiehq/hoodie-cli/commit/e5cdc9ac00b1648c252df678d00e533c4cfe328d))
89 |
90 |
91 |
92 | ### 0.5.1 (2014-07-17)
93 |
94 |
95 |
96 | ## 0.5.0 (2014-07-17)
97 |
98 |
99 | #### Features
100 |
101 | * **options:** Allow users to specify custom ports with hoodie start. ([dd14ec59](https://github.com/hoodiehq/hoodie-cli/commit/dd14ec597722f45e41015574eec993a6d2bdcbe6))
102 |
103 |
104 |
105 | ### 0.4.17 (2014-07-14)
106 |
107 |
108 |
109 | ### 0.4.16 (2014-07-14)
110 |
111 |
112 |
113 | ### 0.4.14 (2014-06-05)
114 |
115 |
116 |
117 | ### 0.4.13 (2014-06-04)
118 |
119 |
120 |
121 | ### 0.4.12 (2014-06-04)
122 |
123 |
124 |
--------------------------------------------------------------------------------
/CONTRIBUTING.md:
--------------------------------------------------------------------------------
1 | # Contributing to Hoodie.js
2 |
3 | Please take a moment to review this document in order to make the contribution
4 | process easy and effective for everyone involved.
5 |
6 | Following these guidelines helps to communicate that you respect the time of
7 | the developers managing and developing this open source project. In return,
8 | they should reciprocate that respect in addressing your issue, assessing
9 | changes, and helping you finalize your pull requests.
10 |
11 |
12 | ## Using the issue tracker
13 |
14 | First things first: **Do NOT report security vulnerablities in public issues!** Please disclose responsibly by letting [the Hoodie team](mailto:team@thehoodiefirm.com?subject=Security) know upfront. We will assess the issue as soon as possible on a best-effort basis and will give you an estimate for when we have a fix and release available for an eventual public disclosure.
15 |
16 | The issue tracker is the preferred channel for [bug reports](#bugs),
17 | [features requests](#features) and [submitting pull
18 | requests](#pull-requests), but please respect the following restrictions:
19 |
20 | * Please **do not** use the issue tracker for personal support requests. Use
21 | [#Hoodie.js](http://webchat.freenode.net/?channels=hoodie) on Freenode.
22 |
23 | * Please **do not** derail or troll issues. Keep the discussion on topic and
24 | respect the opinions of others.
25 |
26 |
27 |
28 | ## Bug reports
29 |
30 | A bug is a _demonstrable problem_ that is caused by the code in the repository.
31 | Good bug reports are extremely helpful - thank you!
32 |
33 | Guidelines for bug reports:
34 |
35 | 1. **Use the GitHub issue search** — check if the issue has already been
36 | reported.
37 |
38 | 2. **Check if the issue has been fixed** — try to reproduce it using the
39 | latest `master` or development branch in the repository.
40 |
41 | 3. **Isolate the problem** — ideally create a [reduced test
42 | case](http://css-tricks.com/6263-reduced-test-cases/).
43 |
44 | A good bug report shouldn't leave others needing to chase you up for more
45 | information. Please try to be as detailed as possible in your report. What is
46 | your environment? What steps will reproduce the issue? What OS experiences the
47 | problem? What would you expect to be the outcome? All these details will help
48 | people to fix any potential bugs.
49 |
50 | Example:
51 |
52 | > Short and descriptive example bug report title
53 | >
54 | > A summary of the issue and the browser/OS environment in which it occurs. If
55 | > suitable, include the steps required to reproduce the bug.
56 | >
57 | > 1. This is the first step
58 | > 2. This is the second step
59 | > 3. Further steps, etc.
60 | >
61 | > `` - a link to the reduced test case
62 | >
63 | > Any other information you want to share that is relevant to the issue being
64 | > reported. This might include the lines of code that you have identified as
65 | > causing the bug, and potential solutions (and your opinions on their
66 | > merits).
67 |
68 |
69 |
70 | ## Feature requests
71 |
72 | Feature requests are welcome. But take a moment to find out whether your idea
73 | fits with the scope and aims of the project. It's up to *you* to make a strong
74 | case to convince the project's developers of the merits of this feature. Please
75 | provide as much detail and context as possible.
76 |
77 |
78 |
79 | ## Pull requests
80 |
81 | Good pull requests - patches, improvements, new features - are a fantastic
82 | help. They should remain focused in scope and avoid containing unrelated
83 | commits.
84 |
85 | **Please ask first** before embarking on any significant pull request (e.g.
86 | implementing features, refactoring code), otherwise you risk spending a lot of
87 | time working on something that the project's developers might not want to merge
88 | into the project.
89 |
90 | Please adhere to the coding conventions used throughout a project (indentation,
91 | accurate comments, etc.) and any other requirements (such as test coverage).
92 |
93 | Adhering to the following this process is the best way to get your work
94 | included in the project:
95 |
96 | 1. [Fork](http://help.github.com/fork-a-repo/) the project, clone your fork,
97 | and configure the remotes:
98 |
99 | ```bash
100 | # Clone your fork of the repo into the current directory
101 | git clone https://github.com//hoodie.js
102 | # Navigate to the newly cloned directory
103 | cd Hoodie.js
104 | # Assign the original repo to a remote called "upstream"
105 | git remote add upstream https://github.com/hoodiehq/hoodie.js
106 | ```
107 |
108 | 2. If you cloned a while ago, get the latest changes from upstream:
109 |
110 | ```bash
111 | git checkout master
112 | git pull upstream master
113 | ```
114 |
115 | 3. Create a new topic branch (off the main project development branch) to
116 | contain your feature, change, or fix:
117 |
118 | ```bash
119 | git checkout -b
120 | ```
121 |
122 | 4. Make sure to update, or add to the tests when appropriate. Patches and
123 | features will not be accepted without tests. Run `npm test` to check that
124 | all tests pass after you've made changes.
125 |
126 | 5. Commit your changes in logical chunks. Please adhere to these [git commit
127 | message guidelines](http://tbaggery.com/2008/04/19/a-note-about-git-commit-messages.html)
128 | or your code is unlikely be merged into the main project. Use Git's
129 | [interactive rebase](https://help.github.com/articles/interactive-rebase)
130 | feature to tidy up your commits before making them public.
131 |
132 | 6. Locally merge (or rebase) the upstream development branch into your topic branch:
133 |
134 | ```bash
135 | git pull [--rebase] upstream master
136 | ```
137 |
138 | 7. Push your topic branch up to your fork:
139 |
140 | ```bash
141 | git push origin
142 | ```
143 |
144 | 8. [Open a Pull Request](https://help.github.com/articles/using-pull-requests/)
145 | with a clear title and description.
146 |
147 | 9. If you are asked to amend your changes before they can be merged in, please
148 | use `git commit --amend` (or rebasing for multi-commit Pull Requests) and
149 | force push to your remote feature branch. You may also be asked to squash
150 | commits.
151 |
152 | **IMPORTANT**: By submitting a patch, you agree to license your work under the
153 | same license as that used by the project.
154 |
155 |
156 | ## Triagers
157 |
158 | There is a [defined process](TRIAGING.md) to manage issues, because this helps to speed up releases and minimizes user pain.
159 | Triaging is a great way to contribute to Hoodie without having to write code.
160 | If you are interested, please [leave a comment here](https://github.com/hoodiehq/discussion/issues/50) asking to join the triaging team.
161 |
162 |
163 | ## Maintainers
164 |
165 | If you have commit access, please follow this process for merging patches and cutting new releases.
166 |
167 | ### Reviewing changes
168 |
169 | 1. Check that a change is within the scope and philosophy of the project.
170 | 2. Check that a change has any necessary tests and a proper, descriptive commit message.
171 | 3. Checkout the change and test it locally.
172 | 4. If the change is good, and authored by someone who cannot commit to
173 | `master`, please try to avoid using GitHub's merge button. Apply the change
174 | to `master` locally (feel free to amend any minor problems in the author's
175 | original commit if necessary).
176 | 5. If the change is good, and authored by another maintainer/collaborator, give
177 | them a "Ship it!" comment and let them handle the merge.
178 |
179 | ### Submitting changes
180 |
181 | 1. All non-trivial changes should be put up for review using GitHub Pull
182 | Requests.
183 | 2. Your change should not be merged into `master` (or another feature branch),
184 | without at least one "Ship it!" comment from another maintainer/collaborator
185 | on the project. "Looks good to me" is not the same as "Ship it!".
186 | 3. Try to avoid using GitHub's merge button. Locally rebase your change onto
187 | `master` and then push to GitHub.
188 | 4. Once a feature branch has been merged into its target branch, please delete
189 | the feature branch from the remote repository.
190 |
191 | ### Releasing a new version
192 |
193 | Releasing a new version is automated with `grunt release`.
194 | According to the semver spec the command tries to find the correct version based on changes made.
195 |
196 | You may still add flags to specify new versions explicitly.
197 | 1. `grunt release:patch`: 0.0.1 => 0.0.2
198 | 2. `grunt release:minor`: 0.0.2 => 0.1.0
199 | 3. `grunt release:major`: 0.1.0 => 1.0.0
200 | 4. `grunt release --setversion=4.12.3-alpha.19`: 1.0.0 => 4.12.3-alpha.19
201 |
--------------------------------------------------------------------------------
/Gruntfile.js:
--------------------------------------------------------------------------------
1 | /*global module:false*/
2 |
3 | module.exports = function (grunt) {
4 |
5 | 'use strict';
6 |
7 | require('load-grunt-tasks')(grunt);
8 |
9 | // Project configuration.
10 | grunt.initConfig({
11 |
12 | jshint: {
13 | files: [
14 | 'Gruntfile.js',
15 | 'lib/**/*.js',
16 | 'bin/*.js'
17 | ],
18 | options: {
19 | jshintrc: '.jshintrc'
20 | }
21 | },
22 |
23 | simplemocha: {
24 | options: {
25 | reporter: 'spec',
26 | node_env: 'testing',
27 | ignoreLeaks: true
28 | },
29 | full: { src: ['spec/runner.js'] }
30 | },
31 |
32 | watch: {
33 | files: ['<%= jshint.files %>'],
34 | tasks: 'jshint'
35 | }
36 |
37 | });
38 |
39 | // Default task.
40 | grunt.registerTask('test', ['jshint', 'simplemocha:full']);
41 | grunt.registerTask('ci', ['test', 'integration-test']);
42 | grunt.registerTask('default', ['test']);
43 | };
44 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | Copyright 2013-2016 the Hoodie Community and other contributors.
2 |
3 | Licensed under the Apache License, Version 2.0 (the "License");
4 | you may not use this file except in compliance with the License.
5 | You may obtain a copy of the License at
6 |
7 | http://www.apache.org/licenses/LICENSE-2.0
8 |
9 | Unless required by applicable law or agreed to in writing, software
10 | distributed under the License is distributed on an "AS IS" BASIS,
11 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | See the License for the specific language governing permissions and
13 | limitations under the License.
14 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Hoodie command line utility
2 | [](https://travis-ci.org/hoodiehq/hoodie-cli)
3 | [](https://david-dm.org/hoodiehq/hoodie-cli)
4 | [](https://david-dm.org/hoodiehq/hoodie-cli#info=devDependencies)
5 |
6 | [](https://nodei.co/npm/hoodie-cli/)
7 |
8 |
9 | ## Installation
10 | Please ensure you have [__node__](http://nodejs.org) installed.
11 |
12 | ```
13 | npm install -g hoodie-cli
14 | ```
15 |
16 |
17 | ## Usage
18 |
19 | See `hoodie -h` or `hoodie --help` for a summary of this information.
20 |
21 | + `hoodie new [-t ]`
22 | Creates a new hoodie app inside a new folder called `appname`. `appname` will also be your domain. If template is not set it will use the default repository `hoodiehq/my-first-hoodie`.
23 |
24 | + `hoodie start`
25 | Starts the hoodie app. The same as `npm start`.
26 |
27 | + `hoodie install `
28 | `hoodie uninstall `
29 | Un-/Installs a hoodie dependency via `npm`. Plugins are installed from the [hoodie GitHub account](http://github.com/hoodiehq) with a `plugin-` prefix, e.g.:
30 | ```
31 | hoodie install global-share
32 | # Cloned from https://github.com/hoodiehq/global-share
33 | ```
34 |
35 | + `hoodie reset`
36 | Resets hoodie server password.
37 |
38 |
39 | #### Running hoodie as a daemon
40 |
41 | Using `forever`
42 |
43 | ```bash
44 | forever start -o /var/log/app.out.log -e /var/log/app.err.log -a --killSignal=SIGTERM /path/to/myapp/node_modules/hoodie-server/bin/start
45 | ```
46 |
47 | ## License
48 |
49 | [Apache 2.0](http://www.apache.org/licenses/LICENSE-2.0)
50 |
--------------------------------------------------------------------------------
/TRIAGING.md:
--------------------------------------------------------------------------------
1 | # Triage new issues/PRs on github
2 |
3 | This document illustrates the steps the Hoodie community is taking to triage issues. The labels are used later on for [planning releases](#assigning-work). If you want to help by sorting issues please [leave a comment here](https://github.com/hoodiehq/discussion/issues/50) asking to join the triaging team.
4 |
5 | ## Triaging Process
6 |
7 | This process based on the idea of minimizing user pain
8 | [from this blog post](http://www.lostgarden.com/2008/05/improving-bug-triage-with-user-pain.html).
9 |
10 | 1. Open the list of [non triaged issues](https://github.com/organizations/hoodiehq/dashboard/issues/repos?direction=desc&milestone=none&page=1&sort=created&state=open)
11 | * Sort by submit date, with the newest issues first
12 | * You don't have to do issues in order; feel free to pick and choose issues as you please.
13 | * You can triage older issues as well
14 | * Triage to your heart's content
15 | 1. Assign yourself: Pick an issue that is not assigned to anyone and assign it to you
16 |
17 | 1. Understandable? - verify if the description of the request is clear.
18 | * If not, [close it][] according to the instructions below and go to the last step.
19 | 1. Duplicate?
20 | * If you've seen this issue before [close it][], and go to the last step.
21 | * Check if there are comments that link to a dupe. If so verify that this is indeed a dupe, [close it][], and go to the last step.
22 | 1. Bugs:
23 | * Label `Type: Bug`
24 | * Reproducible? - Steps to reproduce the bug are clear. If they are not, ask for a clarification. If there's no reply after a week, [close it][].
25 | * Reproducible on master?
26 |
27 | 1. Non bugs:
28 | * Label `Type: Feature`, `Type: Chore`, or `Type: Perf`
29 | * Belongs in core? – Often new features should be implemented as a plugin rather than an addition to the core.
30 | If this doesn't belong, [close it][], and go to the last step.
31 | * Label `needs: breaking change` - if needed
32 | * Label `needs: public api` - if the issue requires introduction of a new public API
33 | 1. Label `frequency: *` – How often does this issue come up? How many developers does this affect?
34 | * low - obscure issue affecting a handful of developers
35 | * moderate - impacts a common usage pattern
36 | * high - impacts most or all Hoodie apps
37 | 1. Label `severity: *` - How bad is the issue?
38 | * regression
39 | * memory leak
40 | * broken expected use - it's hard or impossible for a developer using Hoodie to accomplish something that Hoodie should be able to do
41 | * confusing - unexpected or inconsistent behavior; hard-to-debug
42 | * inconvenience - causes ugly/boilerplate code in apps
43 | 1. Label `starter` - These issues are good targets for PRs from the open source community. Apply to issues where the problem and solution are well defined in the comments, and it's not too complex.
44 |
45 | 1. Label `milestone: *` – Assign a milestone:
46 | * Backlog - triaged fixes and features, should be the default choice
47 | * x.y.z - e.g. 0.3.0
48 |
49 |
50 | 1. Unassign yourself from the issue
51 |
52 | ## Closing an Issue or PR
53 |
54 | We're grateful to anyone who takes the time to submit an issue, even if we ultimately decide not to act on it.
55 | Be kind and respectful as you close issues. Be sure to follow the [code of conduct][].
56 |
57 | 1. Always thank the person who submitted it.
58 | 1. If it's a duplicate, link to the older or more descriptive issue that supersedes the one you are closing.
59 | 1. Let them know if there's some way for them to follow-up.
60 | * When the issue is unclear or reproducible, note that you'll reopen it if they can clarify or provide a better example. Mention [plunker] or [fiddle] for examples. Watch your notifications and follow-up if they do provide clarification. :)
61 | * If appropriate, suggest implementing a feature as a third-party module.
62 |
63 | If in doubt, ask a core team member what to do.
64 |
65 | **Example:**
66 |
67 | > Thanks for submitting this issue!
68 | > Unfortunately, we don't think this functionality belongs in core.
69 | > The good news is that you could easily implement this as a plugin and publish it to npm with the `hoodie-plugin` keyword.
70 |
71 |
72 | ## Assigning Work
73 |
74 | These criteria are then used to calculate a "user pain" score.
75 | Work is assigned weekly to core team members starting with the highest pain, descending down to the lowest.
76 |
77 | ```
78 | pain = severity × frequency
79 | ```
80 |
81 | **severity:**
82 |
83 | - regression (5)
84 | - memory leak (4)
85 | - broken expected use (3)
86 | - confusing (2)
87 | - inconvenience (1)
88 |
89 | **frequency:**
90 |
91 | - low (1)
92 | - moderate (2)
93 | - high (3)
94 |
95 | **Note:** Regressions and memory leaks should almost always be set to `frequency: high`.
96 |
97 | [close it]: #closing-an-issue-or-pr
98 | [code of conduct]: http://hood.ie/code-of-conduct.html
99 | [plunker]: http://plnkr.co/
100 | [fiddle]: http://jsfiddle.net/
101 |
--------------------------------------------------------------------------------
/bin/hoodie:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env node
2 |
3 | var CLI = require('../lib/cli');
4 | var argv = require('optimist').argv;
5 |
6 | new CLI().argv(argv);
7 |
--------------------------------------------------------------------------------
/doc/cli/help.install.txt:
--------------------------------------------------------------------------------
1 | Installs hoodie plugin(s).
2 |
3 | Usage:
4 | $0 install
5 | $0 install ...
6 | $0 install -p ...
7 |
8 | Options:
9 | -p | --plugins Plugin(s) to be installed.
10 | -v | --verbose Verbose output.
11 |
12 | Arguments:
13 | Single plugin name or comma separated list.
14 |
--------------------------------------------------------------------------------
/doc/cli/help.new.txt:
--------------------------------------------------------------------------------
1 | Creates a new application at the provided path.
2 |
3 | Usage:
4 | $0 new
5 | $0 new []
6 | $0 new -n [-t ]
7 | $0 new -n [-t ] [-p ...]
8 |
9 | Options:
10 |
11 | --name, -n application name
12 | --template, -t template name (default: "hoodiehq/my-first-hoodie")
13 | --plugins, -p installs hoodie plugin(s)
14 | --use-ssh will install from `git@github.com:user/repo.git`
15 | --verbose, -v verbose output
16 |
17 | Examples:
18 |
19 | $ $0 new
20 | $ $0 new hoodieapp
21 | $ $0 new -n hoodieapp -t "50p/my-fresh-hoodie-yo"
22 | $ $0 new -n hoodieapp -t "50p/my-fresh-hoodie-yo" -p "users,shares,cheesecake"
23 |
--------------------------------------------------------------------------------
/doc/cli/help.reset.txt:
--------------------------------------------------------------------------------
1 | Reset Hoodie Server password.
2 |
3 | Usage:
4 | $0 reset password
5 |
--------------------------------------------------------------------------------
/doc/cli/help.start.txt:
--------------------------------------------------------------------------------
1 | Starts newly created hoodie app.
2 |
3 | Usage:
4 | $0 start
5 | $0 start -f | --force
6 | $0 start -n | --nobrowser
7 | $0 start -s | --allow-sudo
8 | $0 start -w | --www
9 | $0 start -c | --custom-ports ,,
10 |
11 | Options:
12 | -f | --force Force start even if hoodie is already running.
13 | -n | --nobrowser Whether to open browser upon hoodie start.
14 | -s | --allow-sudo Allow to start the app as a sudoer.
15 | -w | --www Set the directory hoodie will serve static assets from.
16 | -c | --custom-ports Allow user-specified ports (www,admin,couch).
17 |
18 | Arguments:
19 | Directory from where hoodie will serve static assets.
20 | Port number at which hoodie will serve the user's application.
21 | Port number at which hoodie will serve the Admin Dashboard.
22 | Port number at which hoodie will serve CouchDB.
23 |
24 | Examples:
25 |
26 | $ $0 start
27 | $ $0 start --nobrowser
28 | $ $0 start -n
29 | $ $0 start -w "production"
30 | $ $0 start --allow-sudo
31 | $ $0 start -s
32 | $ $0 start --custom-ports 7777,8888,9999
33 |
--------------------------------------------------------------------------------
/doc/cli/help.txt:
--------------------------------------------------------------------------------
1 | Hoodie command-line tool.
2 |
3 | Usage:
4 | $0 new []
5 | $0 start
6 | $0 install ...
7 | $0 uninstall ...
8 | $0 reset
9 | $0 -h | --help
10 | $0 -v | --verbose
11 |
12 | Options:
13 | -h --help output usage information
14 | -v --verbose verbose output
15 |
--------------------------------------------------------------------------------
/doc/cli/help.uninstall.txt:
--------------------------------------------------------------------------------
1 | Uninstalls hoodie plugin(s).
2 |
3 | Usage:
4 | $0 uninstall ...
5 | $0 uninstall -p ...
6 |
7 | Options:
8 | -p | --plugins Plugin(s) to be uninstalled.
9 | -v | --verbose Verbose output.
10 |
11 | Arguments:
12 | Single plugin name or comma separated list.
13 |
--------------------------------------------------------------------------------
/lib/cli.js:
--------------------------------------------------------------------------------
1 | var hoodie = require('./main');
2 | var con = require('./cli/util/console');
3 | var shell = require('shelljs');
4 |
5 | //
6 | // Command line interface object.
7 | //
8 |
9 | function CLI() {
10 | this.cli = this;
11 | }
12 |
13 |
14 | //
15 | // check whether we're running an outdated version
16 | // of hoodie-cli
17 | //
18 | hoodie.emit('checkUpdate');
19 |
20 | try {
21 |
22 | shell.which('git', {
23 | async: true,
24 | silent: true
25 | }, function (err) {
26 | throw err;
27 | });
28 |
29 | } catch (err) {
30 | hoodie.emit('warn', 'git command could not be found.');
31 | process.exit(1);
32 | }
33 |
34 |
35 | ///
36 | // Command line commands.
37 | //
38 |
39 | CLI.prototype.argv = require('./cli/argv');
40 |
41 | CLI.prototype.new = require('./cli/new');
42 | CLI.prototype.install = require('./cli/install');
43 | CLI.prototype.uninstall = require('./cli/uninstall');
44 | CLI.prototype.help = require('./cli/help');
45 | CLI.prototype.start = require('./cli/start');
46 | CLI.prototype.reset = require('./cli/reset');
47 |
48 | CLI.prototype.unknown = require('./cli/unknown');
49 | CLI.prototype.version = require('./cli/version');
50 | CLI.prototype.logo = require('./cli/logo');
51 |
52 |
53 | //
54 | // CLI messages.
55 | //
56 |
57 | hoodie.on('info', function() {
58 | con.info.apply(this, arguments);
59 | });
60 |
61 | hoodie.on('success', function() {
62 | con.success.apply(this, arguments);
63 | });
64 |
65 | hoodie.on('warn', function() {
66 | con.warn.apply(this, arguments);
67 | });
68 |
69 | hoodie.on('err', function() {
70 | con.err.apply(this, arguments);
71 | });
72 |
73 | hoodie.on('raw', function() {
74 | con.raw.apply(this, arguments);
75 | });
76 |
77 |
78 | module.exports = CLI;
79 |
--------------------------------------------------------------------------------
/lib/cli/argv.js:
--------------------------------------------------------------------------------
1 | //
2 | // Parse command-line arguments.
3 | //
4 | // Inspects the arguments and calls the appropriate action.
5 | //
6 | // Options:
7 | //
8 | // - `argv` {Object} is an optimist.argv object.
9 | // - `[callback]` {Function} is called on completion.
10 | //
11 |
12 | module.exports = function(argv, callback) {
13 |
14 | // optional callback
15 | callback = callback || function() {};
16 |
17 | // --help
18 | // --help
19 | if (argv.help || argv.h) {
20 | argv._.unshift('help');
21 | }
22 |
23 | // no command displays help
24 | if (!argv._.length) {
25 | argv._.unshift('help');
26 | }
27 |
28 | // lookup command to execute
29 | var command = this;
30 | for (var i = 0, l = argv._.length; i < l; i++) {
31 | if (typeof command[argv._[i]] === 'function') {
32 | command = command[argv._[i]];
33 | } else {
34 | break;
35 | }
36 | }
37 |
38 | // execute command
39 | if (command === this) {
40 | this.unknown(argv, callback);
41 | } else {
42 | command.call(this, argv, callback);
43 | }
44 |
45 | };
46 |
--------------------------------------------------------------------------------
/lib/cli/help.js:
--------------------------------------------------------------------------------
1 | var path = require('path');
2 | var fs = require('graceful-fs');
3 |
4 | //
5 | // $ hoodie help [command]
6 | //
7 | // Outputs the usage information for a given command.
8 | // Each command documents the help information under /doc/cli/command.txt
9 | //
10 | // Options:
11 | //
12 | // - `argv` {Object} is an optimist object.
13 | // - `callback` {Function} is null unless there is an error.
14 | //
15 |
16 | module.exports = function(argv, callback) {
17 |
18 | this.logo();
19 |
20 | // help file directory
21 | var basepath = path.join(__dirname, '..', '..', 'doc', 'cli');
22 | var filepath;
23 | var data;
24 |
25 | // filename format: command.command.txt
26 | filepath = argv._.slice(0);
27 | filepath.push('txt');
28 | filepath = filepath.join('.');
29 |
30 | // full path
31 | filepath = path.join(basepath, filepath);
32 |
33 | // get help info and replace $0 with process name
34 | data = fs.readFileSync(filepath, 'utf8');
35 | data = data.trim().replace(/\$0/g, argv.$0);
36 |
37 | console.log('\n' + data + '\n');
38 |
39 | callback(null);
40 | };
41 |
--------------------------------------------------------------------------------
/lib/cli/install.js:
--------------------------------------------------------------------------------
1 | var hoodie = require('../main');
2 |
3 | //
4 | // $ hoodie install
5 | //
6 | // Install hoodie plugins
7 | //
8 | // Options:
9 | //
10 | // - `argv` {Object} is an optimist object.
11 | // - `callback` {Function} is a completion callback.
12 | // - `e` {Error} is null unless there was an error.
13 | //
14 |
15 | module.exports = function(argv, callback) {
16 |
17 | this.logo();
18 |
19 | // display help on $ hoodie install
20 | if (argv._.length <= 0) {
21 | argv._.unshift('help');
22 | this.argv(argv, callback);
23 | return;
24 | }
25 |
26 | var data = {
27 | plugins: argv._[1] || argv.plugins || argv.p,
28 | verbose: argv.verbose || argv.v,
29 | link: argv.link
30 | };
31 |
32 | // install new plugin
33 | hoodie.install(data, function(err) {
34 | callback(err);
35 | });
36 |
37 | };
38 |
--------------------------------------------------------------------------------
/lib/cli/logo.js:
--------------------------------------------------------------------------------
1 | var clc = require('cli-color');
2 |
3 | module.exports = function() {
4 |
5 | var logo = [
6 | /* jshint ignore:start */
7 | ["", "", "", "", "", ""],
8 | [".d$b. .d$b.", " .d$$$$$$b. ", " .d$$$$$$b. ", ".d$$$$$$b. ", ".d$b.", ".d$$$$$$$$b."],
9 | ["$$$$$..$$$$$", ".$$$$$$$$$$$b ", ".$$$$$$$$$$$b ", "$$$$$$$$$$b ", "$$$$$", "$$$$$$$$$$P'"],
10 | ["$$$$$$$$$$$$", "d$$$$$$$$$$$$b", "d$$$$$$$$$$$$b", "$$$$$$$$$$$b", "$$$$$", "$$$$$$$$$$b."],
11 | ["$$$$$$$$$$$$", "Q$$$$$$$$$$$$P", "Q$$$$$$$$$$$$P", "$$$$$$$$$$$P", "$$$$$", "$$$$$$$$$$P'"],
12 | ["$$$$$´`$$$$$", "'$$$$$$$$$$$$'", "'$$$$$$$$$$$$'", "$$$$$$$$$$P ", "$$$$$", "$$$$$$$$$$b."],
13 | ["'Q$P' 'Q$P'", " 'Q$$$$$$P' ", " 'Q$$$$$$P' ", "'Q$$$$$$$P ", "'Q$P'", "'Q$$$$$$$$P'"],
14 | ["", "", "", "", "", ""]
15 | /* jshint ignore:end */
16 | ];
17 |
18 | logo.forEach(function(line) {
19 | var blue = clc.xterm(25);
20 | var green = clc.xterm(28);
21 | var yellow = clc.xterm(214);
22 | var orange = clc.xterm(202);
23 | var brown = clc.xterm(240);
24 | var red = clc.xterm(160);
25 |
26 | console.log(
27 | blue(line[0]) +
28 | green(line[1]) +
29 | yellow(line[2]) +
30 | orange(line[3]) +
31 | brown(line[4]) +
32 | red(line[5])
33 | );
34 | });
35 |
36 | this.version();
37 |
38 | };
39 |
--------------------------------------------------------------------------------
/lib/cli/new.js:
--------------------------------------------------------------------------------
1 | var hoodie = require('../main');
2 |
3 | //
4 | // $ hoodie create
5 | //
6 | // Create a hoodie project.
7 | //
8 | // Options:
9 | //
10 | // - `argv` {Object} is an optimist object.
11 | // - `callback` {Function} is a completion callback.
12 | // - `err` {Error} is null unless there was an error.
13 | //
14 |
15 | module.exports = function(argv, callback) {
16 |
17 | this.logo();
18 |
19 | // display help on $ hoodie new
20 | if (argv._.length <= 0) {
21 | argv._.unshift('help');
22 | this.argv(argv, callback);
23 | return;
24 | }
25 |
26 | // project info
27 | var data = {
28 | name: argv._[1] || argv.name || argv.n,
29 | template: argv._[2] || argv.template || argv.t,
30 | plugins: argv._[3] || argv.plugins || argv.p,
31 | ssh: argv['use-ssh'] || argv.s,
32 | verbose: argv.verbose || argv.v
33 | };
34 |
35 | // create the project
36 | hoodie.new(data, function(err) {
37 | callback(err);
38 | });
39 |
40 | };
41 |
--------------------------------------------------------------------------------
/lib/cli/reset.js:
--------------------------------------------------------------------------------
1 | var hoodie = require('../main');
2 |
3 | //
4 | // $ hoodie reset
5 | //
6 | // Resets given config param.
7 | //
8 | // Options:
9 | //
10 | // - `argv` {Object} is an optimist object.
11 | // - `callback` {Function} is a completion callback.
12 | // - `err` {Error} is null unless there was an error.
13 | //
14 |
15 | module.exports = function(argv, callback) {
16 |
17 | // display help on $ hoodie reset
18 | if (argv._.length <= 1) {
19 | argv._.unshift('help');
20 | this.argv(argv, callback);
21 | return;
22 | }
23 |
24 | // project info
25 | var data = {
26 | password: argv._[2] || argv.password || argv.p
27 | };
28 |
29 | // create the project
30 | hoodie.reset(data, function(err) {
31 | callback(err);
32 | });
33 |
34 | };
35 |
--------------------------------------------------------------------------------
/lib/cli/start.js:
--------------------------------------------------------------------------------
1 | var hoodie = require('../main');
2 |
3 | //
4 | // $ hoodie start
5 | //
6 | // Starts hoodie services.
7 | //
8 | // Options:
9 | //
10 | // - `argv` {Object} is an optimist object.
11 | // - `callback` {Function} is a completion callback.
12 | // - `err` {Error} is null unless there was an error.
13 | //
14 |
15 | module.exports = function(argv, callback) {
16 |
17 | this.logo();
18 |
19 | // display help on $ hoodie start
20 | if (argv._.length <= 0) {
21 | argv._.unshift('help');
22 | this.argv(argv, callback);
23 | return;
24 | }
25 |
26 | // start args
27 | var data = {
28 | noBrowser: argv.noBrowser || argv.n,
29 | www: argv.www || argv.w,
30 | sudo: argv['allow-sudo'] || argv.s,
31 | 'custom-ports': argv['custom-ports'] || argv.c,
32 | verbose: argv.verbose || argv.v,
33 | force: argv.force || argv.f
34 | };
35 |
36 | // start hoodie services
37 | hoodie.start(data, function(err) {
38 | callback(err);
39 | });
40 |
41 | };
42 |
--------------------------------------------------------------------------------
/lib/cli/uninstall.js:
--------------------------------------------------------------------------------
1 | var hoodie = require('../main');
2 |
3 | //
4 | // $ hoodie uninstall
5 | //
6 | // Uninstall hoodie plugins
7 | //
8 | // Options:
9 | //
10 | // - `argv` {Object} is an optimist object.
11 | // - `callback` {Function} is a completion callback.
12 | // - `e` {Error} is null unless there was an error.
13 | //
14 |
15 | module.exports = function(argv, callback) {
16 |
17 | this.logo();
18 |
19 | // display help on $ hoodie uninstall
20 | if (argv._.length <= 0) {
21 | argv._.unshift('help');
22 | this.argv(argv, callback);
23 | return;
24 | }
25 |
26 | var data = {
27 | plugins: argv._[1] || argv.plugins || argv.p,
28 | verbose: argv.verbose || argv.v
29 | };
30 |
31 | // uninstall plugin
32 | hoodie.uninstall(data, function(err) {
33 | callback(err);
34 | });
35 | };
36 |
--------------------------------------------------------------------------------
/lib/cli/unknown.js:
--------------------------------------------------------------------------------
1 | var cnsl = require('./util/console');
2 | var util = require('util');
3 |
4 | //
5 | // $ hoodie noop
6 | //
7 | // Outputs that the command-line command is unsupported.
8 | //
9 | // Options:
10 | //
11 | // - `argv` {Object} is an optimist object.
12 | // - `callback` {Function} is a completion callback.
13 | //
14 |
15 | module.exports = function(argv, callback) {
16 |
17 | this.logo();
18 |
19 | cnsl.warn(util.format(
20 | '\'%s\' is not a %s command. See \'%s help\'',
21 | argv._[0],
22 | argv.$0,
23 | argv.$0
24 | ));
25 |
26 | callback();
27 | };
28 |
--------------------------------------------------------------------------------
/lib/cli/util/console.js:
--------------------------------------------------------------------------------
1 | var prompt = require('prompt');
2 |
3 | //
4 | // Console Info.
5 | //
6 | // Passes the parameters to `console.log`.
7 | //
8 | // Outputs:
9 | //
10 | // $ [hoodie] message
11 | //
12 |
13 | module.exports.info = function() {
14 |
15 | var args = Array.prototype.slice.call(arguments);
16 |
17 | args.unshift('[hoodie]'.cyan);
18 |
19 | console.log.apply(this, args);
20 | };
21 |
22 | //
23 | // Console Success.
24 | //
25 | // Passes the parameters to `console.log`.
26 | //
27 | // Outputs:
28 | //
29 | // $ [hoodie] message
30 | //
31 |
32 | module.exports.success = function() {
33 |
34 | var args = Array.prototype.slice.call(arguments);
35 |
36 | args.unshift('[hoodie]'.green);
37 |
38 | console.log.apply(this, args);
39 | };
40 |
41 |
42 | //
43 | // Console Warning.
44 | //
45 | // Passes the parameters to `console.warn`.
46 | //
47 | // Outputs:
48 | //
49 | // $ [warning] message
50 | //
51 |
52 | module.exports.warn = function() {
53 |
54 | var args = Array.prototype.slice.call(arguments);
55 |
56 | args.unshift('[hoodie]'.yellow);
57 |
58 | console.log.apply(this, args);
59 |
60 | };
61 |
62 | //
63 | // Console Error.
64 | //
65 | // Passes the parameters to `console.error`.
66 | //
67 | // Outputs:
68 | //
69 | // $ [error] message
70 | //
71 |
72 | module.exports.err = function() {
73 |
74 | var args = Array.prototype.slice.call(arguments);
75 |
76 | args.unshift('[hoodie]'.red);
77 |
78 | console.log.apply(this, args);
79 |
80 | };
81 |
82 | //
83 | // Console Prompt.
84 | //
85 | // Prompts for a value.
86 | //
87 | // Outputs:
88 | //
89 | // $ [prompt] message:
90 | //
91 |
92 | module.exports.prompt = function(options, callback) {
93 |
94 | // prompt setup
95 | prompt.override = options.override;
96 | prompt.colors = false;
97 | prompt.message = '[prompt]'.green;
98 | prompt.delimiter = ' ';
99 | prompt.start();
100 |
101 | // begin prompting
102 | prompt.get(options.data, callback);
103 |
104 | };
105 |
106 | //
107 | // RAW Console Log.
108 | //
109 | // Passes the parameters to `console.log` with no prefix.
110 | //
111 | // Outputs:
112 | //
113 | // $ message
114 | //
115 |
116 | module.exports.raw = function() {
117 |
118 | var args = Array.prototype.slice.call(arguments);
119 |
120 | console.log.apply(this, args);
121 |
122 | };
123 |
--------------------------------------------------------------------------------
/lib/cli/util/notifier.js:
--------------------------------------------------------------------------------
1 | var updateNotifier = require('update-notifier');
2 | var pkg = require('../../../package.json');
3 |
4 | module.exports = function() {
5 |
6 | var notifier = updateNotifier({
7 | packageName: pkg.name,
8 | packageVersion: pkg.version,
9 | updateCheckInterval: 1000 * 60 * 60 * 1 // 1 hr
10 | });
11 |
12 | if (notifier.update) {
13 | notifier.notify(true);
14 | }
15 |
16 | };
17 |
18 |
--------------------------------------------------------------------------------
/lib/cli/version.js:
--------------------------------------------------------------------------------
1 | var hoodie = require('../main');
2 |
3 | //
4 | // $ hoodie version
5 | //
6 | // Outputs the version to the console.
7 | //
8 |
9 | module.exports = function() {
10 | hoodie.version();
11 | };
12 |
--------------------------------------------------------------------------------
/lib/hoodie.js:
--------------------------------------------------------------------------------
1 | var events = require('events');
2 | var util = require('util');
3 | var updateNotifier = require('./cli/util/notifier');
4 |
5 | //
6 | // Hoodie object.
7 | //
8 | // Events:
9 | //
10 | // - `error` {Event} triggered with info compatible with console.error.
11 | // - `log` {Event} triggered with info compatible with console.log.
12 | // - `warn` {Event} triggered with info compatible with console.warn.
13 | // - `raw` {Event} trigger with info that should not be formatted.
14 | //
15 |
16 | function initialize () {
17 |
18 | // error events must always have a listener.
19 | this.on('error', function(err) {
20 | console.log(err);
21 | });
22 |
23 | this.on('checkUpdate', function() {
24 | updateNotifier();
25 | });
26 |
27 | }
28 |
29 | function Hoodie() {
30 |
31 | // initialize Hoodie
32 | initialize.call(this);
33 |
34 | // initialize each command and inject the `hoodie` dependency.
35 | this.new = require('./hoodie/new').exec(this);
36 | this.install = require('./hoodie/install').exec(this);
37 | this.uninstall = require('./hoodie/uninstall').exec(this);
38 | this.start = require('./hoodie/start').exec(this);
39 | this.reset = require('./hoodie/reset').exec(this);
40 | this.version = require('./hoodie/version').exec(this);
41 | }
42 |
43 |
44 | util.inherits(Hoodie, events.EventEmitter);
45 |
46 |
47 | //
48 | // Initialize Hoodie.
49 | //
50 | module.exports = Hoodie;
51 |
--------------------------------------------------------------------------------
/lib/hoodie/install.js:
--------------------------------------------------------------------------------
1 | var Command = require('./util/command');
2 | var packages = require('./util/packages');
3 |
4 | var util = require('util');
5 | var async = require('async');
6 | var npm = require('npm');
7 |
8 | function CreateCommand() {
9 | return Command.apply(this, arguments);
10 | }
11 |
12 | util.inherits(CreateCommand, Command);
13 |
14 | //
15 | // Installs plugin.
16 | //
17 | // Installs a hoodie plugin
18 | //
19 | // Options:
20 | //
21 | // - `options` {Object} is data required to create an app
22 | // - `plugin` {String}
23 | // - [`callback`] {Function} is triggered after creating the app.
24 | // - `e` {Error} is null unless there is an error.
25 | //
26 | // Returns:
27 | //
28 | // {hoodie} for chaining.
29 | ///
30 |
31 | CreateCommand.prototype.run = function(options, callback) {
32 |
33 | // require options
34 | if (!options) {
35 | this.hoodie.emit('warn', 'requires options parameter:');
36 | return;
37 | }
38 |
39 | options.npmArgs = {
40 | loglevel: 'silent'
41 | };
42 |
43 | if (options.verbose) {
44 | options.npmArgs.loglevel = 'verbose';
45 | }
46 |
47 | // optional callback
48 | callback = callback || function() {};
49 |
50 | this.insight.track('hoodie', 'install');
51 |
52 | // install plugin
53 | this.execute(options, callback);
54 |
55 | return this.hoodie;
56 | };
57 |
58 |
59 | //
60 | // Execute.
61 | //
62 |
63 | CreateCommand.prototype.execute = function(options, callback) {
64 |
65 | var self = this;
66 |
67 | if (options.link) {
68 | npm.load(options.npmArgs, function(err, npm) {
69 | if (err) {
70 | self.hoodie.emit('warn', 'Error loading npm:');
71 | self.hoodie.emit('warn', err.message);
72 | process.exit(1);
73 | throw err;
74 | }
75 |
76 | npm.link(function(err) {
77 | if (err) {
78 | self.hoodie.emit('warn', 'Error installing: ');
79 | self.hoodie.emit('warn', err.message);
80 | process.exit(1);
81 | throw err;
82 | }
83 |
84 | self.hoodie.emit('info', 'Successfully linked modules');
85 | });
86 |
87 | });
88 | return;
89 | }
90 |
91 | if (!options.plugins) {
92 | var err = 'requires plugins parameter:';
93 | this.hoodie.emit('warn', err);
94 | callback(err);
95 | return;
96 | }
97 |
98 | // TODO: the below needs a refactor
99 | // probably worth breaking up the logic into smaller more
100 | // reusable pieces
101 |
102 | var pluginsArr = options.plugins.split(',');
103 |
104 | self.hoodie.emit('info', 'Installing plugin(s): ' + pluginsArr.join(' '));
105 |
106 | npm.load(options.npmArgs, function(err, npm) {
107 | if (err) {
108 | self.hoodie.emit('warn', 'Error loading npm:');
109 | self.hoodie.emit('warn', err.message);
110 | throw err;
111 | }
112 | npm.config.set('save', true);
113 |
114 | async.map(pluginsArr, function (p, cb) {
115 |
116 | var pluginName = p.trim();
117 |
118 | if (pluginName.match('hoodie-plugin-')) {
119 | pluginName = pluginName.replace('hoodie-plugin-', '');
120 | }
121 |
122 | var fullName = 'hoodie-plugin-' + pluginName;
123 |
124 | npm.install(fullName, function(err) {
125 | if (err) {
126 | self.hoodie.emit('warn', 'Error installing plugin: ' + pluginName);
127 | self.hoodie.emit('warn', err.message);
128 | process.exit(1);
129 | throw err;
130 | }
131 |
132 | self.hoodie.emit('info', 'Successfully installed ' + pluginName + ' plugin');
133 | return cb(null, p);
134 | });
135 | },
136 | function (err, plugins) {
137 | var modules = plugins.map(function (name) {
138 | return 'hoodie-plugin-' + name;
139 | });
140 |
141 | packages.extendPlugins('package.json', modules, function (err) {
142 | if (err) {
143 | self.hoodie.emit('warn', 'Error updating package.json');
144 | process.exit(1);
145 | throw err;
146 | }
147 | self.hoodie.emit('info', 'Successfully updated package.json');
148 | });
149 | });
150 |
151 | });
152 | };
153 |
154 | module.exports = {
155 | exec: function(hoodie) {
156 | return new CreateCommand(hoodie);
157 | }
158 | };
159 |
160 |
--------------------------------------------------------------------------------
/lib/hoodie/new.js:
--------------------------------------------------------------------------------
1 | var Command = require('./util/command');
2 | var dirUtils = require('./util/dir');
3 |
4 | var util = require('util');
5 | var fs = require('graceful-fs');
6 | var rmrf = require('rimraf');
7 | var async = require('async');
8 | var path = require('path');
9 | var shell = require('shelljs');
10 | var npm = require('npm');
11 | var StdOutFixture = require('fixture-stdout');
12 |
13 | function CreateCommand() {
14 | return Command.apply(this, arguments);
15 | }
16 |
17 | util.inherits(CreateCommand, Command);
18 |
19 | //
20 | // Create a New App.
21 | //
22 | // Creates an project on the local filesystem.
23 | //
24 | // Options:
25 | //
26 | // - `options` {Object} is data required to create an app
27 | // - `name` {String} is a directory path for the app.
28 | // - `template` {String} is the application name (default: 'hoodiehq/my-first-hoodie')
29 | // - [`callback`] {Function} is triggered after creating the app.
30 | // - `err` {Error} is null unless there is an error.
31 | //
32 | // Returns:
33 | //
34 | // {hoodie} for chaining.
35 | //
36 | CreateCommand.prototype.run = function(options, callback) {
37 |
38 | options.name = options.name || 'my-first-hoodie';
39 |
40 | options.tmpl_cfg = {
41 | template: options.template || dirUtils.getRepoFromTemplate(options),
42 | entity: dirUtils.getEntityFromTemplate(options),
43 | repo: dirUtils.getRepoFromTemplate(options),
44 | branch: dirUtils.getBranchFromTemplate(options),
45 | uri: undefined
46 | };
47 |
48 | options.tmpl_cfg.uri = dirUtils.buildGitURI(options);
49 | options.plugins = options.plugins || [];
50 | options.cwd = process.cwd();
51 | options.targetDir = dirUtils.appDir(options);
52 |
53 | if (options.ssh) {
54 | options.tmpl_cfg.template = '' + dirUtils.buildGitURI(options) + '';
55 | }
56 |
57 | options.npmArgs = {
58 | loglevel: 'silent'
59 | };
60 |
61 | if (options.verbose) {
62 | options.npmArgs.loglevel = 'verbose';
63 | }
64 |
65 | // optional callback
66 | callback = callback || function() {};
67 |
68 | this.execute(options, callback);
69 |
70 | this.insight.track('hoodie', 'new');
71 |
72 | return this.hoodie;
73 |
74 | };
75 |
76 | Command.prototype.mkdir = function (options, ctx, callback) {
77 |
78 | var self = ctx;
79 |
80 | try {
81 | shell.mkdir('-p', options.targetDir);
82 | return callback(null);
83 | } catch(e) {
84 | self.hoodie.emit('err', 'directory already exists');
85 | return callback(new Error());
86 | }
87 |
88 | };
89 |
90 | CreateCommand.prototype.checkCache = function (options, ctx, callback) {
91 |
92 | var self = ctx;
93 |
94 | var registryAvailable = function(npm, callback) {
95 | var host = npm.config.get('registry').replace(/https?:\/\/|\//g, '');
96 | require('dns').resolve(host, function(err) {
97 | if (err) {
98 | self.hoodie.emit('warn', 'Error reaching the npm registry: Trying to install from cache');
99 | return callback({
100 | useCache: true
101 | });
102 | }
103 | self.hoodie.emit('info', 'The npm registry is available');
104 | callback();
105 | });
106 | };
107 |
108 | var latest = function(npm, callback) {
109 | var fixture = new StdOutFixture();
110 | fixture.capture(function() {
111 | return false;
112 | });
113 |
114 | npm.info(options.tmpl_cfg.template, function(err, pkg) {
115 | fixture.release();
116 |
117 | if (err) {
118 | self.hoodie.emit('info', 'Template not published on npm');
119 | return callback();
120 | }
121 |
122 | options.tmpl_cfg.latest = Object.keys(pkg)[0];
123 | callback();
124 | });
125 | };
126 |
127 | var latestCached = function(npm, callback) {
128 | var fixture = new StdOutFixture();
129 | fixture.capture(function() {
130 | return false;
131 | });
132 |
133 | npm.commands.cache([
134 | 'ls',
135 | options.tmpl_cfg.template + '@' + options.tmpl_cfg.latest
136 | ], function(err, entries) {
137 |
138 | fixture.release();
139 |
140 | if (err) {
141 | self.hoodie.emit('warn', 'Error listing npm cache:');
142 | self.hoodie.emit('warn', err.message);
143 | return callback(err);
144 | }
145 |
146 | if (entries.length) {
147 | self.hoodie.emit('info', 'Installing from the npm cache');
148 | return callback({
149 | useCache: true
150 | });
151 | }
152 |
153 | self.hoodie.emit('info', 'Fresh install');
154 | return callback();
155 | });
156 | };
157 |
158 | npm.load(options.npmArgs, function(err, npm) {
159 | if (err) {
160 | self.hoodie.emit('warn', 'Error loading npm:');
161 | self.hoodie.emit('warn', err.message);
162 | return callback(err);
163 | }
164 |
165 | async.applyEachSeries([
166 | registryAvailable,
167 | latest,
168 | latestCached
169 | ], npm, function(err) {
170 | if (err && err.useCache) {
171 | options.npmArgs['cache-min'] = 1e12;
172 | options.npmArgs['no-registry'] = true;
173 | return callback();
174 | }
175 | if (err) {
176 | return callback(err);
177 | }
178 | callback();
179 | });
180 | });
181 |
182 | };
183 |
184 | CreateCommand.prototype.fetch = function (options, ctx, callback) {
185 |
186 | var self = ctx;
187 |
188 | self.hoodie.emit('info', 'This may take some time.');
189 |
190 | npm.load(options.npmArgs, function(err, npm) {
191 | if (err) {
192 | self.hoodie.emit('warn', 'Error loading npm:');
193 | self.hoodie.emit('warn', err.message);
194 | return callback(err);
195 | }
196 |
197 | var pkg = options.tmpl_cfg.template;
198 |
199 | if (options.tmpl_cfg.latest && !/@/.test(pkg)) {
200 | pkg += '@' + options.tmpl_cfg.latest;
201 | }
202 |
203 | npm.install(pkg, function(err, deps, pkg) {
204 | if (err) {
205 | self.hoodie.emit('warn', 'Error installing template:');
206 | self.hoodie.emit('warn', err.message);
207 | return callback(err);
208 | }
209 |
210 | options.srcDir = path.resolve(Object.keys(pkg)[0]);
211 | return callback(null);
212 | });
213 | });
214 |
215 | };
216 |
217 | //
218 | // Copy template directory to target location.
219 | //
220 | Command.prototype.copyToCwd = function (options, ctx, callback) {
221 |
222 | var self = ctx;
223 |
224 | try {
225 | self.hoodie.emit('info', 'Preparing: ' + options.name + ' ...');
226 | shell.cp('-R', options.srcDir + '/', options.targetDir);
227 | return callback(null);
228 | } catch(err) {
229 | self.hoodie.emit('err', 'cannot copy directory ');
230 | return callback(err);
231 | }
232 |
233 | };
234 |
235 | //
236 | // cleanup after 'npm install' - removes node_modules folder.
237 | //
238 | CreateCommand.prototype.cleanup = function(options, ctx, callback) {
239 |
240 | var self = ctx;
241 |
242 | rmrf(options.srcDir, function (err) {
243 |
244 | if (err) {
245 | self.hoodie.emit('error', 'Could not remove temporary template.');
246 | return callback(err);
247 | }
248 |
249 | return callback(null);
250 |
251 | });
252 |
253 | };
254 |
255 | //
256 | // Rename.
257 | //
258 | CreateCommand.prototype.rename = function (options, ctx, callback) {
259 |
260 | var self = ctx;
261 |
262 | process.chdir(dirUtils.appDir(options));
263 |
264 | var isPackageJson = function(filename) {
265 | return filename.match(/\.json$/);
266 | };
267 |
268 | // Replace my-first-hoodie in package.json and www/index.html
269 | var readFile = function(file) {
270 |
271 | if (isPackageJson(file)) {
272 | var package_json = JSON.parse(fs.readFileSync(file));
273 | package_json.name = options.name;
274 | return JSON.stringify(package_json, null, 2);
275 | }
276 |
277 | return fs.readFileSync(file)
278 | .toString()
279 | .replace(/\{\{my-first-hoodie\}\}/gi, options.name);
280 | };
281 |
282 | var writeFile = function(file) {
283 | return fs.writeFileSync(file, readFile(file));
284 | };
285 |
286 | var files = [
287 | 'package.json',
288 | 'npm-shrinkwrap.json',
289 | path.normalize('./www/index.html')
290 | ];
291 |
292 | files
293 | .filter(fs.existsSync)
294 | .forEach(writeFile);
295 |
296 | self.hoodie.emit('info', 'Updated package.json');
297 |
298 | return callback(null);
299 |
300 | };
301 |
302 | //
303 | // Execute.
304 | //
305 | CreateCommand.prototype.execute = function (options) {
306 |
307 | var self = this;
308 |
309 | async.applyEachSeries([
310 | self.mkdir,
311 | self.checkCache,
312 | self.fetch,
313 | self.copyToCwd,
314 | self.cleanup,
315 | self.rename
316 | ], options, self, function (err) {
317 |
318 | if (err) {
319 |
320 | var errStr = '\nSomething\'s wrong here...\n' +
321 | '\n' +
322 | 'Run \"hoodie new ' + options.name + ' --verbose\"\n' +
323 | 'and come talk to us on freenode #hoodie \n';
324 |
325 | self.hoodie.emit('error', errStr);
326 | process.exit(1);
327 | throw err;
328 | }
329 |
330 | self.hoodie.emit('info', 'Created project at', path.join(options.cwd, options.name));
331 |
332 | var sucStr = 'You can now start using your hoodie app\n' +
333 | '\n' +
334 | ' cd ' + options.name + '\n' +
335 | ' hoodie start\n';
336 |
337 | self.hoodie.emit('info', sucStr);
338 |
339 | });
340 |
341 | };
342 |
343 | module.exports = {
344 | exec: function (hoodie) {
345 | return new CreateCommand(hoodie);
346 | }
347 | };
348 |
349 |
--------------------------------------------------------------------------------
/lib/hoodie/reset.js:
--------------------------------------------------------------------------------
1 | var Command = require('./util/command');
2 |
3 | var fs = require('fs');
4 | var ini = require('ini');
5 | var path = require('path');
6 | var util = require('util');
7 |
8 |
9 | function CreateCommand() {
10 | return Command.apply(this, arguments);
11 | }
12 |
13 | util.inherits(CreateCommand, Command);
14 |
15 | //
16 | // Reset Config Param.
17 | //
18 | // Options:
19 | //
20 | // - `options` {Object} is data required to create an app
21 | // - `plugin` {String}
22 | // - [`callback`] {Function} is triggered after creating the app.
23 | // - `e` {Error} is null unless there is an error.
24 | //
25 | // Returns:
26 | //
27 | // {hoodie} for chaining.
28 | ///
29 |
30 | CreateCommand.prototype.run = function(options, callback) {
31 |
32 | // require options
33 | if (!options) {
34 | this.hoodie.emit('warn', 'requires options parameter:');
35 | return;
36 | }
37 |
38 | // optional callback
39 | callback = callback || function() {};
40 |
41 | this.insight.track('hoodie', 'reset');
42 |
43 | this.reset(callback);
44 |
45 | return this.hoodie;
46 | };
47 |
48 | //
49 | // Reset Password.
50 | //
51 |
52 | CreateCommand.prototype.reset = function (cb) {
53 |
54 | var self = this;
55 | var couchIniPath = path.join(process.cwd(), 'data/couch.ini');
56 | var config = ini.parse(fs.readFileSync(couchIniPath, 'utf-8'));
57 |
58 | delete config.admins;
59 |
60 | fs.writeFile(couchIniPath, ini.stringify(config), function (err) {
61 | if (err) {
62 | self.hoodie.emit('warn', 'oups, something went wrong');
63 | cb(err);
64 | return;
65 | }
66 |
67 | self.hoodie.emit(
68 | 'info', 'password reset sucessfully. Please run \'hoodie start\''
69 | );
70 | cb(null);
71 | });
72 |
73 | };
74 |
75 | module.exports = {
76 | exec: function(hoodie) {
77 | return new CreateCommand(hoodie);
78 | }
79 | };
80 |
81 |
--------------------------------------------------------------------------------
/lib/hoodie/start.js:
--------------------------------------------------------------------------------
1 | var Command = require('./util/command');
2 | var util = require('util');
3 | var fs = require('graceful-fs');
4 | var async = require('async');
5 | var fork = require('child_process').fork;
6 | var path = require('path');
7 |
8 | function CreateCommand() {
9 | return Command.apply(this, arguments);
10 | }
11 |
12 | util.inherits(CreateCommand, Command);
13 |
14 | //
15 | // Start hoodie services.
16 | //
17 | // Options:
18 | // - `browser` {String} whether to open a browser window upon app start
19 | //
20 | // - [`callback`] {Function} is triggered after creating the app.
21 | // - `e` {Error} is null unless there is an error.
22 | //
23 | // Returns:
24 | //
25 | // {hoodie} for chaining.
26 | ///
27 |
28 | CreateCommand.prototype.run = function(options, callback) {
29 |
30 | // require options
31 | if (!options) {
32 | this.hoodie.emit('warn', 'requires options parameter:');
33 | return;
34 | }
35 |
36 | this.insight.track('hoodie', 'start');
37 |
38 | // optional callback
39 | callback = callback || function() {};
40 |
41 | this.execute(options, callback);
42 |
43 | return this.hoodie;
44 | };
45 |
46 | //
47 | // Execute.
48 | //
49 |
50 | CreateCommand.prototype.execute = function(options, callback) {
51 | var self = this;
52 | var processArgs = [];
53 |
54 | // adds ability to bypass sudo check
55 | //
56 | if (!options.sudo) {
57 | if (process.env.SUDO_USER) {
58 | this.hoodie.emit('warn', 'Hoodie does not support being run as sudo. Please try again.');
59 | return callback();
60 | }
61 | }
62 |
63 | async.detect([
64 | path.resolve('node_modules/hoodie-server/bin/start')
65 | ], fs.exists, function (startPath) {
66 |
67 | // bail if hoodie start not found
68 | if (!startPath) {
69 | self.hoodie.emit('warn', 'Could not start hoodie.');
70 | return callback(new Error('Could not find hoodie-server'));
71 | }
72 |
73 | // serve from custom location
74 | if (options.www) {
75 | processArgs.push('--www', options.www);
76 | self.hoodie.emit('info', 'Serving hoodie from ' + options.www);
77 | }
78 | // configure custom ports
79 | if (options['custom-ports']) {
80 | processArgs.push('--custom-ports', options['custom-ports']);
81 | self.hoodie.emit('info', 'Serving hoodie on custom ports ' + options['custom-ports']);
82 | }
83 |
84 | if (options.verbose) {
85 | processArgs.push('-v');
86 | }
87 |
88 | if (options.force || !self.pid.exists()) {
89 | // forks hoodie app and listens for messages
90 | // coming through on the process
91 | var serverProcess = fork(startPath, processArgs);
92 |
93 | serverProcess.on('message', function (msg) {
94 |
95 | if (msg.app.started) {
96 |
97 | //write PID file
98 | try {
99 | self.pid.create(path.resolve('data/hoodie.pid'), options.force);
100 | } catch (err) {
101 | self.hoodie.emit('warn', err.message);
102 | process.exit(1);
103 | return callback(err);
104 | }
105 |
106 | // open hoodie app in browser
107 | if (!options.noBrowser) {
108 |
109 | self.openBrowser(msg.stack.www, function (err) {
110 |
111 | if (err) {
112 | self.hoodie.emit('warn', err.message);
113 | }
114 |
115 | self.hoodie.emit('info', 'Hoodie app is running!');
116 | return callback();
117 | });
118 | }
119 |
120 | }
121 |
122 | return callback();
123 |
124 | });
125 | } else {
126 | self.hoodie.emit('warn', 'Hoodie is already running!');
127 | }
128 |
129 |
130 | });
131 |
132 | // remove PID if process is terminated.
133 | ['SIGTERM', 'SIGINT', 'SIGHUP', 'SIGQUIT', 'exit'].forEach(function (s) {
134 | process.on(s, self.pid.remove);
135 | });
136 |
137 | };
138 |
139 | module.exports = {
140 | exec: function(hoodie) {
141 | return new CreateCommand(hoodie);
142 | }
143 | };
144 |
--------------------------------------------------------------------------------
/lib/hoodie/uninstall.js:
--------------------------------------------------------------------------------
1 | var Command = require('./util/command');
2 | var packages = require('./util/packages');
3 |
4 | var util = require('util');
5 | var async = require('async');
6 | var npm = require('npm');
7 |
8 | function CreateCommand() {
9 | return Command.apply(this, arguments);
10 | }
11 |
12 | util.inherits(CreateCommand, Command);
13 |
14 | //
15 | // Uninstalls plugin
16 | //
17 | // Uninstalls a hoodie plugin
18 | //
19 | // Options:
20 | //
21 | // - `options` {Object} is data required to create an app
22 | // - `plugin` {String}
23 | // - [`callback`] {Function} is triggered after creating the app.
24 | // - `e` {Error} is null unless there is an error.
25 | //
26 | // Returns:
27 | //
28 | // {hoodie} for chaining.
29 | ///
30 |
31 | CreateCommand.prototype.run = function(options, callback) {
32 |
33 | // require options
34 | if (!options) {
35 | this.hoodie.emit('warn', 'requires options parameter:');
36 | return;
37 | }
38 |
39 | if (!options.plugins) {
40 | this.hoodie.emit('warn', 'requires options.plugins parameter:');
41 | return;
42 | }
43 |
44 | options.npmArgs = {
45 | loglevel: 'silent'
46 | };
47 |
48 | if (options.verbose) {
49 | options.npmArgs.loglevel = 'verbose';
50 | }
51 |
52 | // optional callback
53 | callback = callback || function() {};
54 |
55 | // uninstall plugin
56 | this.execute(options, callback);
57 |
58 | this.insight.track('hoodie', 'uninstall');
59 |
60 | return this.hoodie;
61 | };
62 |
63 | //
64 | // Execute.
65 | //
66 |
67 | CreateCommand.prototype.execute = function(options, callback) {
68 |
69 | var self = this;
70 | var pluginsArr = options.plugins.split(',');
71 |
72 | self.hoodie.emit('info', 'Removing plugin(s): ' + pluginsArr);
73 |
74 | npm.load(options.npmArgs, function(err, npm) {
75 | if (err) {
76 | self.hoodie.emit('warn', 'Error loading npm:');
77 | self.hoodie.emit('warn', err.message);
78 | throw err;
79 | }
80 | npm.config.set('save', true);
81 |
82 | async.map(pluginsArr, function (plugin, cb) {
83 |
84 | var fullName = 'hoodie-plugin-' + plugin;
85 |
86 | npm.remove(fullName, function(err) {
87 | if (err) {
88 | self.hoodie.emit('warn', 'Error uninstalling plugin: ' + plugin);
89 | self.hoodie.emit('warn', err.message);
90 | callback(err);
91 | process.exit(1);
92 | throw err;
93 | }
94 |
95 | self.hoodie.emit('info', 'Successfully uninstalled ' + plugin + ' plugin');
96 | cb(null, plugin);
97 | });
98 | },
99 | function (err, plugins) {
100 | var modules = plugins.map(function (name) {
101 | return 'hoodie-plugin-' + name;
102 | });
103 | packages.removePlugins('package.json', modules, function (err) {
104 | if (err) {
105 | self.hoodie.emit('warn', 'Error updating package.json');
106 | process.exit(1);
107 | throw err;
108 | }
109 | self.hoodie.emit('info', 'Successfully updated package.json');
110 | });
111 | });
112 |
113 | });
114 | };
115 |
116 | module.exports = {
117 | exec: function(hoodie) {
118 | return new CreateCommand(hoodie);
119 | }
120 | };
121 |
122 |
--------------------------------------------------------------------------------
/lib/hoodie/util/command.js:
--------------------------------------------------------------------------------
1 | var openBrowser = require('open');
2 |
3 | var insightProvider = require('./insight');
4 | var pid = require('./pid');
5 |
6 | //
7 | // Base Command.
8 | //
9 | // > All your base are belong to us.
10 | //
11 | // All commands should inherit from the base `Command` object.
12 | //
13 | // This object handles the dependency injection of the `hoodie` object.
14 | //
15 | // This has two major benefits:
16 | // 1. Allows `hoodie` to create instances. This is helpful for testing.
17 | // 2. Allows test framework to mock public interfaces during tests.
18 | //
19 | // Options:
20 | //
21 | // - `hoodie` {Object} is the instance of `hoodie` for this command.
22 | //
23 | // Returns:
24 | //
25 | // {Function} that will call the inheriting class' `run` function.
26 | //
27 |
28 |
29 |
30 | function Command(hoodie) {
31 |
32 | var self = this;
33 |
34 | self.hoodie = hoodie;
35 |
36 | return function() {
37 | return self.run.apply(self, arguments);
38 | };
39 | }
40 |
41 | Command.prototype.insight = insightProvider();
42 |
43 | Command.prototype.pid = pid;
44 |
45 | //
46 | // Open app in browser
47 | //
48 | Command.prototype.openBrowser = function (www, callback) {
49 |
50 | var url = 'http://' + www.host + ':' + www.port;
51 | openBrowser(url, callback);
52 |
53 | };
54 |
55 | module.exports = Command;
56 |
57 |
--------------------------------------------------------------------------------
/lib/hoodie/util/dir.js:
--------------------------------------------------------------------------------
1 | var path = require('path');
2 |
3 | //
4 | // get is cache dir
5 | //
6 | exports.getCacheDir = function () {
7 | var homedir = 'HOME';
8 |
9 | if (process.platform === 'win32') {
10 | homedir = 'USERPROFILE';
11 | }
12 |
13 | var cacheDir = path.join(process.env[homedir], '.hoodie/cache/');
14 |
15 | return cacheDir;
16 | };
17 |
18 |
19 | //
20 | // build repo url
21 | //
22 | exports.buildGitURI = function (options) {
23 |
24 | var protocols = ['https://', 'git@'];
25 | var separator = ['/', ':'];
26 | var host = 'github.com';
27 |
28 | var cProtocol = options.ssh ? protocols[1] : protocols[0];
29 | var cSeparator = options.ssh ? separator[1] : separator[0];
30 |
31 | return cProtocol + host + cSeparator + options.tmpl_cfg.entity + separator[0] + options.tmpl_cfg.repo + '.git';
32 | };
33 |
34 |
35 | //
36 | // returns application name
37 | //
38 |
39 | exports.appDir = function (options) {
40 | return path.join(options.cwd, options.name);
41 | };
42 |
43 |
44 | exports.getRepoFromTemplate = function (options) {
45 |
46 | var tmpl = 'my-first-hoodie';
47 |
48 | if (!options.template) {
49 | return tmpl;
50 | }
51 |
52 | if (options.template) {
53 | return options.template.split('/').slice(-1)[0];
54 | }
55 |
56 | };
57 |
58 | exports.getEntityFromTemplate = function (options) {
59 |
60 | var entity = 'hoodiehq';
61 |
62 | if (!options.template) {
63 | return entity;
64 | }
65 |
66 | if (options.template) {
67 | return options.template.split('/')[0];
68 | }
69 |
70 | };
71 |
72 |
73 | exports.getBranchFromTemplate = function (options) {
74 |
75 | if (options.template) {
76 | return options.template.split('#').slice(-1)[0];
77 | }
78 |
79 | };
80 |
--------------------------------------------------------------------------------
/lib/hoodie/util/git.js:
--------------------------------------------------------------------------------
1 | var shell = require('shelljs');
2 |
3 | exports.bin = function () {
4 |
5 | var path = shell.which('git');
6 |
7 | // Add quotation in case the path contains a space
8 | // This happens on windows (c:\program files\nodejs\...)
9 | path = '"' + path + '"';
10 |
11 | return path;
12 |
13 | };
14 |
--------------------------------------------------------------------------------
/lib/hoodie/util/insight.js:
--------------------------------------------------------------------------------
1 | var Insight = require('insight');
2 | var pkg = require('../../../package.json');
3 |
4 | module.exports = function () {
5 |
6 | var trackingCode;
7 |
8 | if (!process.env.CI) {
9 | trackingCode = 'UA-53355776-2';
10 | } else {
11 | trackingCode = 'UA-00000000-0';
12 | }
13 |
14 | var insight = new Insight({
15 | trackingCode: trackingCode,
16 | packageName: pkg.name,
17 | packageVersion: pkg.version
18 | });
19 |
20 | insight.optOut = false;
21 |
22 |
23 | return insight;
24 |
25 | };
26 |
27 |
--------------------------------------------------------------------------------
/lib/hoodie/util/packages.js:
--------------------------------------------------------------------------------
1 | /*jshint -W079 */
2 |
3 | var fs = require('graceful-fs');
4 | var bind = require('lodash/function/bind');
5 | var difference = require('lodash/array/difference');
6 | var union = require('lodash/array/union');
7 |
8 | //
9 | // Modifies the hoodie.plugins property of a package.json file
10 | // Use extendPlugins() and removePlugins() instead of calling this directly
11 | //
12 |
13 | exports._modifyPlugins = function (p, transform, callback) {
14 | exports.readPackageJSON(p, function (err, pkg) {
15 | if (err) {
16 | return callback(err);
17 | }
18 | if (!pkg.hoodie) {
19 | pkg.hoodie = {};
20 | }
21 | if (!pkg.hoodie.plugins) {
22 | pkg.hoodie.plugins = [];
23 | }
24 | pkg.hoodie.plugins = transform(pkg.hoodie.plugins);
25 | exports.writePackageJSON(p, pkg, callback);
26 | });
27 | };
28 |
29 | //
30 | // Updates the hoodie.plugin property of a package.json file
31 | //
32 | // Options:
33 | //
34 | // - `p {String} the path to the package.json file to update
35 | // - plugins {Array} an array of plugin package names or paths to add
36 | // - callback {Function} called after package.json has written
37 | //
38 |
39 | exports.extendPlugins = function (p, plugins, callback) {
40 | return exports._modifyPlugins(
41 | p,
42 | bind(union, null, plugins),
43 | callback
44 | );
45 | };
46 |
47 | //
48 | // Updates the hoodie.plugin property of a package.json file, removing
49 | // the names plugins from the array
50 | //
51 | // Options:
52 | //
53 | // - `p {String} the path to the package.json file to update
54 | // - plugins {Array} an array of plugin package names or paths to remove
55 | // - callback {Function} called after package.json has written
56 | //
57 |
58 | exports.removePlugins = function (p, plugins, callback) {
59 | return exports._modifyPlugins(
60 | p,
61 | bind(difference, null, bind.placeholder, plugins),
62 | callback
63 | );
64 | };
65 |
66 | //
67 | // Reads the package.json file, returning the parsed JSON
68 | //
69 | // Options:
70 | //
71 | // - `p {String} the path to the package.json file to read
72 | // - callback {Function} called after package.json has been read
73 | //
74 |
75 | exports.readPackageJSON = function (p, callback) {
76 | fs.readFile(p, function (err, buf) {
77 | if (err) {
78 | return callback(err);
79 | }
80 | var pkg;
81 | try {
82 | pkg = JSON.parse(buf.toString());
83 | }
84 | catch (e) {
85 | return callback(e);
86 | }
87 | return callback(null, pkg);
88 | });
89 | };
90 |
91 | //
92 | // Writes the package.json file
93 | //
94 | // Options:
95 | //
96 | // - `p {String} the path to the package.json file to write
97 | // - pkg {Object} the json object to write to package.json
98 | // - callback {Function} called after package.json has been written
99 | //
100 |
101 | exports.writePackageJSON = function (p, pkg, callback) {
102 | var output = JSON.stringify(pkg, null, 2);
103 | fs.writeFile(p, output, callback);
104 | };
105 |
106 |
--------------------------------------------------------------------------------
/lib/hoodie/util/pid.js:
--------------------------------------------------------------------------------
1 | var fs = require('fs');
2 | var path = require('path');
3 |
4 | var internals = {
5 |
6 | path: null,
7 |
8 | writePid: function (path, force) {
9 | var pid = new Buffer(process.pid + '\n');
10 | var fd = fs.openSync(path, force ? 'w' : 'wx');
11 | var offset = 0;
12 |
13 | while (offset < pid.length) {
14 | offset += fs.writeSync(fd, pid, offset, pid.length - offset);
15 | }
16 |
17 | fs.closeSync(fd);
18 | },
19 |
20 | ulink: function (path) {
21 | try {
22 | fs.unlinkSync(path);
23 | internals.path = null;
24 | } catch (err) {
25 |
26 | }
27 | }
28 |
29 | };
30 |
31 | exports.create = function(path, force) {
32 | internals.path = path;
33 | internals.writePid(internals.path, force);
34 | };
35 |
36 | exports.remove = function () {
37 | internals.ulink(internals.path);
38 | };
39 |
40 | exports.exists = function () {
41 | return fs.existsSync(path.resolve('data/hoodie.pid'));
42 | };
43 |
44 |
--------------------------------------------------------------------------------
/lib/hoodie/version.js:
--------------------------------------------------------------------------------
1 | var Command = require('./util/command');
2 | var pkg = require('../../package.json');
3 |
4 | var util = require('util');
5 | var npm = require('npm');
6 |
7 | function VersionCommand() {
8 | return Command.apply(this, arguments);
9 | }
10 |
11 | util.inherits(VersionCommand, Command);
12 |
13 | //
14 | // Version reporter.
15 | //
16 | // Report the version of or hoodie.
17 | //
18 |
19 | VersionCommand.prototype.run = function() {
20 |
21 | var info = 'Version: ' + pkg.version +
22 | ' (node ' + process.version +
23 | ', npm ' + npm.version +
24 | ', platform: ' + process.platform + ')\n';
25 |
26 | console.log(info);
27 | };
28 |
29 |
30 | module.exports = {
31 | exec: function(hoodie) {
32 | return new VersionCommand(hoodie);
33 | }
34 | };
35 |
36 |
--------------------------------------------------------------------------------
/lib/main.js:
--------------------------------------------------------------------------------
1 | var Hoodie = require('./hoodie'); // jshint ignore:line
2 |
3 | module.exports = new Hoodie();
4 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "hoodie-cli",
3 | "description": "Hoodie command-line interface.",
4 | "version": "0.6.3",
5 | "preferGlobal": true,
6 | "dependencies": {
7 | "async": "^1.3.0",
8 | "cli-color": "^1.0.0",
9 | "colors": "^1.1.2",
10 | "fixture-stdout": "^0.2.1",
11 | "graceful-fs": "^4.1.2",
12 | "ini": "^1.2.1",
13 | "insight": "^0.6.0",
14 | "lodash": "^3.9.1",
15 | "npm": "^2.1.4",
16 | "open": "0.0.5",
17 | "optimist": "^0.6.1",
18 | "prompt": "^0.2.13",
19 | "rimraf": "^2.2.8",
20 | "semver": "^4.3.6",
21 | "shelljs": "^0.5.1",
22 | "update-notifier": "^0.5.0"
23 | },
24 | "engines": {
25 | "node": ">=0.10.22"
26 | },
27 | "keywords": [
28 | "cli",
29 | "hoodie",
30 | "hood.ie",
31 | "hoodie.js"
32 | ],
33 | "repository": {
34 | "type": "git",
35 | "url": "https://github.com/hoodiehq/hoodie-cli.git"
36 | },
37 | "scripts": {
38 | "test": "grunt ci --verbose"
39 | },
40 | "bin": {
41 | "hoodie": "./bin/hoodie"
42 | },
43 | "author": "The Hoodie Community and other contributors | http://hood.ie/",
44 | "devDependencies": {
45 | "expect.js": "^0.3.1",
46 | "grunt": "^0.4.5",
47 | "grunt-contrib-jshint": "^0.11.2",
48 | "grunt-contrib-watch": "^0.6.1",
49 | "grunt-release-hoodie": "^2.8.0",
50 | "grunt-simple-mocha": "^0.4.0",
51 | "load-grunt-tasks": "^3.2.0",
52 | "mocha": "^2.2.5",
53 | "nixt": "^0.4.1",
54 | "sinon": "^1.10.3"
55 | },
56 | "codename": "superb-ox",
57 | "license": "Apache-2.0"
58 | }
--------------------------------------------------------------------------------
/spec/cli.spec.js:
--------------------------------------------------------------------------------
1 | describe('$ hoodie commands ', function() {
2 |
3 | });
4 |
--------------------------------------------------------------------------------
/spec/cli/help.spec.js:
--------------------------------------------------------------------------------
1 | var CLI = require('../../lib/cli');
2 | var cli;
3 |
4 | var expect = require('expect.js');
5 |
6 | //
7 | // Specification: $ hoodie help
8 | //
9 |
10 | describe('hoodie help', function() {
11 |
12 | beforeEach(function() {
13 | cli = new CLI();
14 | this.sandbox.spy(process.stdout, 'write');
15 | });
16 |
17 | describe('$ hoodie help', function() {
18 | it('should output the usage information', function() {
19 | cli.argv({ _: [ 'help' ] });
20 | expect(process.stdout.write.args[9]).to.match(/Usage/);
21 | });
22 | });
23 |
24 | describe('$ hoodie --help', function() {
25 | it('should output the usage information', function() {
26 | cli.argv({ _: [], help: true });
27 | expect(process.stdout.write.args[9]).to.match(/Usage/);
28 | });
29 | });
30 |
31 | describe('$ hoodie -h', function() {
32 | it('should output the usage information', function() {
33 | cli.argv({ _: [], h: true });
34 | expect(process.stdout.write.args[9]).to.match(/Usage/);
35 | });
36 | });
37 |
38 | });
39 |
--------------------------------------------------------------------------------
/spec/cli/install.spec.js:
--------------------------------------------------------------------------------
1 | var hoodie = require('../../lib/main');
2 | var CLI = require('../../lib/cli');
3 | var cli;
4 | var stdout;
5 | var args;
6 |
7 | var expect = require('expect.js');
8 |
9 | /*
10 | * Specification: $ hoodie install
11 | */
12 |
13 | describe('hoodie install', function() {
14 |
15 | beforeEach(function() {
16 | cli = new CLI();
17 | this.sandbox.spy(process.stdout, 'write');
18 | stdout = process.stdout.write;
19 | });
20 |
21 | describe('$ hoodie help', function() {
22 | it('should include the command', function() {
23 | cli.argv({ _: ['help'] });
24 | expect(process.stdout.write.args[9]).to.match(/Usage/);
25 | });
26 | });
27 |
28 | describe('$ hoodie install --help', function() {
29 | it('should output usage info', function() {
30 | cli.argv({ _: ['install'], help: true });
31 | expect(process.stdout.write.args[9]).to.match(/Usage/);
32 | });
33 | });
34 |
35 | });
36 |
37 |
38 | /*
39 | * Specification: $ hoodie install
40 | */
41 |
42 | describe('hoodie install ', function() {
43 |
44 | beforeEach(function() {
45 | cli = new CLI();
46 | this.sandbox.spy(process.stdout, 'write');
47 | this.sandbox.stub(hoodie, 'install');
48 | args = {
49 | plugins: 'users',
50 | verbose: undefined,
51 | link: undefined
52 | };
53 | });
54 |
55 | describe('$ hoodie install "users"', function() {
56 | it('should try to install a plugins', function() {
57 | cli.argv({ _: ['install', 'users'] });
58 | expect(hoodie.install.calledWith(args)).to.be.ok();
59 | });
60 | });
61 |
62 | describe('$ hoodie install users', function() {
63 | it('should try to install a plugin', function() {
64 | cli.argv({ _: ['install', 'users'] });
65 | expect(hoodie.install.calledWith(args)).to.be.ok();
66 | });
67 | });
68 |
69 | describe('$ hoodie install hoodie-plugin-users', function() {
70 | it('should try to install a plugin', function() {
71 | cli.argv({ _: ['install', 'hoodie-plugin-users'] });
72 | args.plugins = 'hoodie-plugin-users';
73 | expect(hoodie.install.calledWith(args)).to.be.ok();
74 | });
75 | });
76 |
77 | describe('$ hoodie install --plugin users', function() {
78 | it('should try to install a plugin', function() {
79 | cli.argv({ _: ['install', 'users'] });
80 | expect(hoodie.install.calledWith(args)).to.be.ok();
81 | });
82 | });
83 |
84 | describe('$ hoodie install --plugin users,shares', function() {
85 | it('should try to install a plugin', function() {
86 | args.plugins = 'users,shares';
87 |
88 | cli.argv({ _: ['install', 'users,shares'] });
89 | expect(hoodie.install.calledWith(args)).to.be.ok();
90 | });
91 | });
92 |
93 | describe('$ hoodie install -p users', function() {
94 | it('should try to install a plugin', function() {
95 | cli.argv({ _: ['install', 'users'] });
96 | expect(hoodie.install.calledWith(args)).to.be.ok();
97 | });
98 | });
99 |
100 | describe('$ hoodie install -p users,shares', function() {
101 | it('should try to install a plugin', function() {
102 | args.plugins = 'users,shares';
103 |
104 | cli.argv({ _: ['install', 'users,shares'] });
105 | expect(hoodie.install.calledWith(args)).to.be.ok();
106 | });
107 | });
108 |
109 | });
110 |
--------------------------------------------------------------------------------
/spec/cli/new.spec.js:
--------------------------------------------------------------------------------
1 | var hoodie = require('../../lib/main');
2 | var CLI = require('../../lib/cli');
3 | var cli;
4 | var stdout;
5 |
6 | var expect = require('expect.js');
7 |
8 | /*
9 | * Specification: $ hoodie new
10 | */
11 |
12 | describe('hoodie help new', function() {
13 |
14 | beforeEach(function() {
15 | cli = new CLI();
16 | this.sandbox.spy(process.stdout, 'write');
17 | stdout = process.stdout.write;
18 | });
19 |
20 | describe('$ hoodie help', function() {
21 | it('should include the command', function() {
22 | cli.argv({ _: ['help'] });
23 | expect(process.stdout.write.args[9]).to.match(/Usage/);
24 | });
25 | });
26 |
27 | describe('$ hoodie new --help', function() {
28 | it('should output usage info', function() {
29 | cli.argv({ _: ['new'], help: true });
30 | expect(process.stdout.write.args[9]).to.match(/Usage/);
31 | });
32 | });
33 |
34 | describe('$ hoodie new -h', function() {
35 | it('should output usage info', function() {
36 | cli.argv({ _: ['new'], h: true });
37 | expect(process.stdout.write.args[9]).to.match(/Usage/);
38 | });
39 | });
40 |
41 | });
42 |
43 |
44 | /*
45 | * Specification: $ hoodie new
46 | */
47 |
48 | describe('hoodie new ', function() {
49 |
50 | beforeEach(function() {
51 | cli = new CLI();
52 | this.sandbox.spy(process.stdout, 'write');
53 | this.sandbox.stub(hoodie, 'new');
54 | });
55 |
56 | describe('$ hoodie new "appname"', function() {
57 | it('should try to create the app', function() {
58 | var args = {
59 | name: 'appname',
60 | template: undefined,
61 | plugins: undefined,
62 | ssh: undefined,
63 | verbose: undefined
64 | };
65 | cli.argv({ _: ['new', 'appname'] });
66 | expect(hoodie.new.args[0][0]).to.eql(args);
67 | expect(hoodie.new.args[0][1]).to.be.a('function');
68 | });
69 | });
70 |
71 | describe('$ hoodie new "appname"', function() {
72 | it('should try to create the app verbosely', function() {
73 | var args = {
74 | name: 'appname',
75 | template: undefined,
76 | plugins: undefined,
77 | ssh: undefined,
78 | verbose: true
79 | };
80 | cli.argv({ _: ['new', 'appname'], verbose: true });
81 | expect(hoodie.new.args[0][0]).to.eql(args);
82 | expect(hoodie.new.args[0][1]).to.be.a('function');
83 | });
84 | });
85 |
86 | describe('$ hoodie new "appname"', function() {
87 | it('should try to create the app verbosely without deleting the .git folder', function() {
88 | var args = {
89 | name: 'appname',
90 | template: undefined,
91 | plugins: undefined,
92 | ssh: undefined,
93 | verbose: true
94 | };
95 | cli.argv({ _: ['new', 'appname'], verbose: true});
96 | expect(hoodie.new.args[0][0]).to.eql(args);
97 | expect(hoodie.new.args[0][1]).to.be.a('function');
98 | });
99 | });
100 |
101 | describe('$ hoodie new appname 50p/massive-hoodie-yo', function() {
102 | it('should try to create the project', function() {
103 | var args = {
104 | name: 'appname',
105 | template: '50p/massive-hoodie-yo',
106 | plugins: undefined,
107 | ssh: undefined,
108 | verbose: undefined
109 | };
110 | cli.argv({ _: ['new', 'appname', '50p/massive-hoodie-yo'] });
111 | expect(hoodie.new.args[0][0]).to.eql(args);
112 | expect(hoodie.new.args[0][1]).to.be.a('function');
113 | });
114 | });
115 |
116 | describe('$ hoodie new appname --template 50p/massive-hoodie-yo', function() {
117 | it('should try to create the project', function() {
118 | var args = {
119 | name: 'appname',
120 | template: '50p/massive-hoodie-yo',
121 | plugins: undefined,
122 | ssh: undefined,
123 | verbose: undefined
124 | };
125 | cli.argv({ _: ['new', 'appname', '50p/massive-hoodie-yo'] });
126 | expect(hoodie.new.args[0][0]).to.eql(args);
127 | expect(hoodie.new.args[0][1]).to.be.a('function');
128 | });
129 | });
130 |
131 | describe('$ hoodie new -name appname --template 50p/massive-hoodie-yo#zipper', function() {
132 | it('should try to create the project', function() {
133 | var args = {
134 | name: 'appname',
135 | template: '50p/massive-hoodie-yo#zipper',
136 | plugins: undefined,
137 | ssh: undefined,
138 | verbose: undefined
139 | };
140 | cli.argv({ _: ['new', 'appname', '50p/massive-hoodie-yo#zipper'] });
141 | expect(hoodie.new.args[0][0]).to.eql(args);
142 | expect(hoodie.new.args[0][1]).to.be.a('function');
143 | });
144 | });
145 |
146 | describe('$ hoodie new -name appname --template 50p/massive-hoodie-yo', function() {
147 | it('should try to create the project', function() {
148 | var args = {
149 | name: 'appname',
150 | template: '50p/massive-hoodie-yo',
151 | plugins: undefined,
152 | ssh: undefined,
153 | verbose: undefined
154 | };
155 | cli.argv({ _: ['new', 'appname', '50p/massive-hoodie-yo'] });
156 | expect(hoodie.new.args[0][0]).to.eql(args);
157 | expect(hoodie.new.args[0][1]).to.be.a('function');
158 | });
159 | });
160 |
161 | describe('$ hoodie new -name appname --template 50p/massive-hoodie-yo --plugins users', function() {
162 | it('should try to create the project', function() {
163 | var args = {
164 | name: 'appname',
165 | template: '50p/massive-hoodie-yo',
166 | plugins: 'users',
167 | ssh: undefined,
168 | verbose: undefined
169 | };
170 | cli.argv({ _: ['new', 'appname', '50p/massive-hoodie-yo', 'users'] });
171 | expect(hoodie.new.args[0][0]).to.eql(args);
172 | expect(hoodie.new.args[0][1]).to.be.a('function');
173 | });
174 | });
175 |
176 | describe('$ hoodie new -name appname --template 50p/massive-hoodie-yo --plugins users,shares', function() {
177 | it('should try to create the project', function() {
178 | var args = {
179 | name: 'appname',
180 | template: '50p/massive-hoodie-yo',
181 | plugins: 'users,shares',
182 | ssh: undefined,
183 | verbose: undefined
184 | };
185 | cli.argv({ _: ['new', 'appname', '50p/massive-hoodie-yo', 'users,shares'] });
186 | expect(hoodie.new.args[0][0]).to.eql(args);
187 | expect(hoodie.new.args[0][1]).to.be.a('function');
188 | });
189 | });
190 |
191 | });
192 |
--------------------------------------------------------------------------------
/spec/cli/reset.spec.js:
--------------------------------------------------------------------------------
1 | var hoodie = require('../../lib/main');
2 | var CLI = require('../../lib/cli');
3 | var cli;
4 | var stdout;
5 |
6 | var expect = require('expect.js');
7 |
8 | /*
9 | * Specification: $ hoodie reset
10 | */
11 |
12 | describe('hoodie reset', function() {
13 |
14 | beforeEach(function() {
15 | cli = new CLI();
16 | this.sandbox.spy(process.stdout, 'write');
17 | stdout = process.stdout.write;
18 | });
19 |
20 | describe('$ hoodie help', function() {
21 | it('should include the command', function() {
22 | cli.argv({ _: ['help'] });
23 | expect(process.stdout.write.args[9]).to.match(/Usage/);
24 | });
25 | });
26 |
27 | describe('$ hoodie reset --help', function() {
28 | it('should output usage info', function() {
29 | cli.argv({ _: ['reset'], help: true });
30 | expect(process.stdout.write.args[9]).to.match(/Usage/);
31 | });
32 | });
33 |
34 | });
35 |
36 |
--------------------------------------------------------------------------------
/spec/cli/start.spec.js:
--------------------------------------------------------------------------------
1 | var hoodie = require('../../lib/main');
2 | var CLI = require('../../lib/cli');
3 | var cli;
4 | var stdout;
5 |
6 | var expect = require('expect.js');
7 |
8 | /*
9 | * Specification: $ hoodie start
10 | */
11 |
12 | describe('hoodie help start', function() {
13 |
14 | beforeEach(function() {
15 | cli = new CLI();
16 | this.sandbox.spy(process.stdout, 'write');
17 | stdout = process.stdout.write;
18 | });
19 |
20 | describe('$ hoodie help', function() {
21 | it('should include the command', function() {
22 | cli.argv({ _: ['help'] });
23 | expect(process.stdout.write.args[9]).to.match(/Usage/);
24 | });
25 | });
26 |
27 | describe('$ hoodie start --help', function() {
28 | it('should output usage info', function() {
29 | cli.argv({ _: ['new'], help: true });
30 | expect(process.stdout.write.args[9]).to.match(/Usage/);
31 | });
32 | });
33 |
34 | describe('$ hoodie start -h', function() {
35 | it('should output usage info', function() {
36 | cli.argv({ _: ['new'], h: true });
37 | expect(process.stdout.write.args[9]).to.match(/Usage/);
38 | });
39 | });
40 |
41 | });
42 |
43 |
44 | /*
45 | * Specification: $ hoodie start
46 | */
47 |
48 | describe('hoodie start', function() {
49 |
50 | beforeEach(function() {
51 | cli = new CLI();
52 | this.sandbox.spy(process.stdout, 'write');
53 | this.sandbox.stub(hoodie, 'start');
54 | });
55 |
56 | describe('$ hoodie start', function() {
57 | it('should try to start the app', function() {
58 | var args = {
59 | noBrowser: undefined,
60 | www: undefined,
61 | sudo: undefined,
62 | 'custom-ports': undefined,
63 | verbose: undefined,
64 | force: undefined
65 | };
66 | cli.argv({ _: ['start'] });
67 | expect(hoodie.start.args[0][0]).to.eql(args);
68 | expect(hoodie.start.args[0][1]).to.be.a('function');
69 | });
70 | });
71 |
72 | describe('$ hoodie start --noBrowser', function() {
73 | it('should try to start the app with noBrowser', function() {
74 | var args = {
75 | noBrowser: true,
76 | www: undefined,
77 | sudo: undefined,
78 | 'custom-ports': undefined,
79 | verbose: undefined,
80 | force: undefined
81 | };
82 | cli.argv({ _: ['start'], noBrowser: true});
83 | expect(hoodie.start.args[0][0]).to.eql(args);
84 | expect(hoodie.start.args[0][1]).to.be.a('function');
85 | });
86 | });
87 |
88 | describe('$ hoodie start --allow-sudo', function() {
89 | it('should try to start the app with --allow-sudo', function() {
90 | var args = {
91 | noBrowser: undefined,
92 | www: undefined,
93 | sudo: true,
94 | 'custom-ports': undefined,
95 | verbose: undefined,
96 | force: undefined
97 | };
98 | cli.argv({ _: ['start'], 'allow-sudo': true });
99 | expect(hoodie.start.args[0][0]).to.eql(args);
100 | expect(hoodie.start.args[0][1]).to.be.a('function');
101 | });
102 | });
103 |
104 | describe('$ hoodie start --noBrowser --www "production"', function() {
105 | it('should try to start the app with --noBrowser and --www', function() {
106 | var args = {
107 | noBrowser: true,
108 | www: 'production',
109 | sudo: undefined,
110 | 'custom-ports': undefined,
111 | verbose: undefined,
112 | force: undefined
113 | };
114 | cli.argv({ _: ['start'], noBrowser: true, www: 'production'});
115 | expect(hoodie.start.args[0][0]).to.eql(args);
116 | expect(hoodie.start.args[0][1]).to.be.a('function');
117 | });
118 | });
119 |
120 | describe('$ hoodie start --custom-ports "6666,7777,8888"', function() {
121 | it('should try to start the app with --custom-ports', function() {
122 | var args = {
123 | noBrowser: undefined,
124 | www: undefined,
125 | sudo: undefined,
126 | 'custom-ports': '6666,7777,8888',
127 | verbose: undefined,
128 | force: undefined
129 | };
130 | cli.argv({ _: ['start'], 'custom-ports': '6666,7777,8888'});
131 | expect(hoodie.start.args[0][0]).to.eql(args);
132 | expect(hoodie.start.args[0][1]).to.be.a('function');
133 | });
134 | });
135 |
136 | describe('$ hoodie start --force', function() {
137 | it('should try to start the app with --force', function() {
138 | var args = {
139 | noBrowser: undefined,
140 | www: undefined,
141 | sudo: undefined,
142 | 'custom-ports': undefined,
143 | verbose: undefined,
144 | force: true
145 | };
146 | cli.argv({ _: ['start'], force: true });
147 | expect(hoodie.start.args[0][0]).to.eql(args);
148 | expect(hoodie.start.args[0][1]).to.be.a('function');
149 | });
150 | });
151 |
152 | });
153 |
--------------------------------------------------------------------------------
/spec/cli/uninstall.spec.js:
--------------------------------------------------------------------------------
1 | var hoodie = require('../../lib/main');
2 | var CLI = require('../../lib/cli');
3 | var cli;
4 | var stdout;
5 | var args;
6 |
7 | var expect = require('expect.js');
8 |
9 | /*
10 | * Specification: $ hoodie uninstall
11 | */
12 |
13 | describe('hoodie uninstall', function() {
14 |
15 | beforeEach(function() {
16 | cli = new CLI();
17 | this.sandbox.spy(process.stdout, 'write');
18 | stdout = process.stdout.write;
19 | });
20 |
21 | describe('$ hoodie help', function() {
22 | it('should include the command', function() {
23 | cli.argv({ _: ['help'] });
24 | expect(process.stdout.write.args[9]).to.match(/Usage/);
25 | });
26 | });
27 |
28 | describe('$ hoodie uninstall --help', function() {
29 | it('should output usage info', function() {
30 | cli.argv({ _: ['uninstall'], help: true });
31 | expect(process.stdout.write.args[9]).to.match(/Usage/);
32 | });
33 | });
34 |
35 | });
36 |
37 |
38 | /*
39 | * Specification: $ hoodie uninstall
40 | */
41 |
42 | describe('hoodie uninstall ', function() {
43 |
44 | beforeEach(function() {
45 | cli = new CLI();
46 | this.sandbox.spy(process.stdout, 'write');
47 | this.sandbox.stub(hoodie, 'uninstall');
48 | args = {
49 | plugins: 'users',
50 | verbose: undefined
51 | };
52 | });
53 |
54 | describe('$ hoodie uninstall users', function() {
55 | it('should try to uninstall a plugin', function() {
56 | cli.argv({ _: ['uninstall', 'users'] });
57 | expect(hoodie.uninstall.calledWith(args)).to.be.ok();
58 | });
59 | });
60 |
61 | describe('$ hoodie uninstall users', function() {
62 | it('should try to uninstall a plugin', function() {
63 | cli.argv({ _: ['uninstall', 'users'] });
64 | expect(hoodie.uninstall.calledWith(args)).to.be.ok();
65 | });
66 | });
67 |
68 | describe('$ hoodie uninstall --plugins users', function() {
69 | it('should try to uninstall a plugin', function() {
70 | cli.argv({ _: ['uninstall', 'users'] });
71 | expect(hoodie.uninstall.calledWith(args)).to.be.ok();
72 | });
73 | });
74 |
75 | describe('$ hoodie uninstall --plugins users,shares', function() {
76 | it('should try to uninstall a plugin', function() {
77 | args.plugins = 'users,shares';
78 |
79 | cli.argv({ _: ['uninstall', 'users,shares'] });
80 | expect(hoodie.uninstall.calledWith(args)).to.be.ok();
81 | });
82 | });
83 |
84 | describe('$ hoodie uninstall --p users,shares', function() {
85 | it('should try to uninstall a plugin', function() {
86 | args.plugins = 'users,shares';
87 |
88 | cli.argv({ _: ['uninstall', 'users,shares'] });
89 | expect(hoodie.uninstall.calledWith(args)).to.be.ok();
90 | });
91 | });
92 |
93 | describe('$ hoodie uninstall --p users', function() {
94 | it('should try to uninstall a plugin', function() {
95 | cli.argv({ _: ['uninstall', 'users'] });
96 | expect(hoodie.uninstall.calledWith(args)).to.be.ok();
97 | });
98 | });
99 |
100 | });
101 |
--------------------------------------------------------------------------------
/spec/cli/unknown.spec.js:
--------------------------------------------------------------------------------
1 | var CLI = require('../../lib/cli');
2 | var cli;
3 |
4 | var expect = require('expect.js');
5 |
6 | /*
7 | * Specification: $ hoodie unknown
8 | */
9 |
10 | describe('hoodie unknown', function() {
11 |
12 | beforeEach(function() {
13 | cli = new CLI();
14 | this.sandbox.spy(process.stdout, 'write');
15 | });
16 |
17 | describe('$ hoodie noop', function() {
18 | it('should output the unknown command', function() {
19 | cli.argv({ _: ['noop'] });
20 | expect(process.stdout.write.args[9]).to.match(/noop/);
21 | });
22 | });
23 | });
24 |
--------------------------------------------------------------------------------
/spec/hoodie.spec.js:
--------------------------------------------------------------------------------
1 | var Hoodie = require('../lib/hoodie');
2 | var hoodie = new Hoodie();
3 |
4 | var expect = require('expect.js');
5 |
6 | /*!
7 | * Specification: hoodie.
8 | */
9 |
10 | describe('hoodie', function() {
11 |
12 | it('should define hoodie.install', function() {
13 | expect(hoodie).to.have.property('install');
14 | });
15 |
16 | it('should define hoodie.new', function() {
17 | expect(hoodie).to.have.property('new');
18 | });
19 |
20 | it('should define hoodie.start', function() {
21 | expect(hoodie).to.have.property('start');
22 | });
23 |
24 | it('should define hoodie.uninstall', function() {
25 | expect(hoodie).to.have.property('uninstall');
26 | });
27 |
28 | });
29 |
30 |
--------------------------------------------------------------------------------
/spec/hoodie/install.spec.js:
--------------------------------------------------------------------------------
1 | var Hoodie = require('../../lib/hoodie');
2 | var hoodie;
3 | var options;
4 |
5 | var expect = require('expect.js');
6 |
7 | /*
8 | * Specification: hoodie.install(options, [callback])
9 | */
10 |
11 | describe('hoodie.install(options, [callback])', function() {
12 |
13 | beforeEach(function() {
14 | hoodie = new Hoodie();
15 | options = {
16 | plugin: 'hoodie-plugin-users',
17 | verbose: undefined,
18 | link: undefined
19 | };
20 | this.sandbox.stub(hoodie, 'install').returns(function(options, callback) {
21 | callback(null);
22 | });
23 | });
24 |
25 | it('should not require callback', function() {
26 | expect(function() {
27 | hoodie.install(options);
28 | }).to.not.throwException();
29 | });
30 |
31 | describe('successfully install a plugin', function() {
32 |
33 | it('should trigger called without an error', function() {
34 | hoodie.install(options, function(e) {
35 | expect(e).to.eql(null);
36 | });
37 | });
38 |
39 | it('should trigger callback with an error', function() {
40 | hoodie.install(options, function(e) {
41 | expect(e).to.eql(null);
42 | });
43 | });
44 |
45 | });
46 |
47 | });
48 |
--------------------------------------------------------------------------------
/spec/hoodie/new.spec.js:
--------------------------------------------------------------------------------
1 | var Hoodie = require('../../lib/hoodie');
2 | var hoodie;
3 | var options;
4 |
5 | var expect = require('expect.js');
6 |
7 | /*
8 | * Specification: hoodie.new(options, [callback])
9 | */
10 |
11 | describe('hoodie.new(options, [callback])', function() {
12 |
13 | beforeEach(function() {
14 | hoodie = new Hoodie();
15 | options = {
16 | name: 'hoodieapp',
17 | template: '50p/yo-dawg'
18 | };
19 | this.sandbox.stub(hoodie, 'new').returns(function(options, callback) {
20 | callback(null);
21 | });
22 | });
23 |
24 | it('should not require callback', function() {
25 | expect(function() {
26 | hoodie.new(options);
27 | }).to.not.throwException();
28 | });
29 |
30 | describe('successfully created a project', function() {
31 |
32 | it('should trigger called without an error', function() {
33 | hoodie.new(options, function(e) {
34 | expect(e).to.be(null);
35 | });
36 | });
37 |
38 | it('should trigger called without an error', function() {
39 | options.template = '50/yo-dawg#some-test';
40 |
41 | hoodie.new(options, function(e) {
42 | expect(e).to.be(null);
43 | });
44 | });
45 |
46 | it('should trigger callback with an error', function() {
47 | hoodie.new(options, function(e) {
48 | expect(e).to.be(null);
49 | });
50 | });
51 |
52 |
53 | });
54 |
55 | describe('rejected invalid slug', function() {
56 |
57 | it('should trigger callback with an error', function() {
58 | options.template = '50/yo-dawg/i-heard-yo-like#some-test';
59 |
60 | hoodie.new(options, function(e) {
61 | expect(e instanceof Error).to.be(true);
62 | });
63 |
64 | options.template = 'yo-dawg';
65 |
66 | hoodie.new(options, function(e) {
67 | expect(e instanceof Error).to.be(true);
68 | });
69 |
70 | });
71 |
72 | });
73 |
74 | });
75 |
--------------------------------------------------------------------------------
/spec/hoodie/reset.spec.js:
--------------------------------------------------------------------------------
1 | var Hoodie = require('../../lib/hoodie');
2 | var hoodie;
3 | var options;
4 |
5 | var expect = require('expect.js');
6 |
7 | /*
8 | * Specification: hoodie.reset(options, [callback])
9 | */
10 |
11 | describe('hoodie.reset(options, [callback])', function() {
12 |
13 | beforeEach(function() {
14 | hoodie = new Hoodie();
15 | options = {
16 | password: 'password'
17 | };
18 | });
19 |
20 | describe('successfully reset password', function() {
21 |
22 | beforeEach(function() {
23 | this.sandbox.stub(hoodie, 'reset').returns(function(options, callback) {
24 | callback(null);
25 | });
26 | });
27 |
28 | it('should trigger callback with an error', function() {
29 | hoodie.reset(options, function(e) {
30 | expect(e).to.eql(null);
31 | });
32 | });
33 |
34 | });
35 |
36 | });
37 |
--------------------------------------------------------------------------------
/spec/hoodie/start.spec.js:
--------------------------------------------------------------------------------
1 | var Hoodie = require('../../lib/hoodie');
2 | var hoodie;
3 |
4 | var expect = require('expect.js');
5 | /*
6 | * Specification: hoodie.start(options, [callback])
7 | */
8 |
9 | describe('hoodie.start(options, [callback])', function() {
10 |
11 | beforeEach(function() {
12 | hoodie = new Hoodie();
13 | options = {
14 | noBrowser: undefined,
15 | www: undefined,
16 | sudo: undefined,
17 | 'custom-ports': undefined,
18 | verbose: undefined,
19 | force: undefined
20 | };
21 | this.sandbox.stub(hoodie, 'start').returns(function(options, callback) {
22 | callback(null);
23 | });
24 | });
25 |
26 | it('should not require callback', function() {
27 | expect(function() {
28 | hoodie.start(options);
29 | }).not.to.throwException();
30 | });
31 |
32 | describe('successfully start a hoodie app', function() {
33 |
34 | it('should trigger called without an error', function() {
35 | hoodie.start(options, function(e) {
36 | expect(e).to.be(null);
37 | });
38 | });
39 |
40 | it('should trigger callback with an error', function() {
41 | hoodie.start(options, function(e) {
42 | expect(e).to.eql(null);
43 | });
44 | });
45 | });
46 |
47 | });
48 |
49 |
--------------------------------------------------------------------------------
/spec/hoodie/uninstall.spec.js:
--------------------------------------------------------------------------------
1 | var Hoodie = require('../../lib/hoodie');
2 | var hoodie;
3 | var options;
4 |
5 | var expect = require('expect.js');
6 |
7 | /*
8 | * Specification: hoodie.uninstall(options, [callback])
9 | */
10 |
11 | describe('hoodie.uninstall(options, [callback])', function() {
12 |
13 | beforeEach(function() {
14 | hoodie = new Hoodie();
15 | options = {
16 | plugin: 'hoodieapp'
17 | };
18 | this.sandbox.spy(hoodie, 'uninstall');
19 | });
20 |
21 | it('should not require callback', function() {
22 | expect(function() {
23 | hoodie.uninstall(options);
24 | }).to.not.throwException();
25 | });
26 |
27 | describe('successfully uninstall a plugin', function() {
28 |
29 | beforeEach(function() {
30 | hoodie.uninstall(function(options, callback) {
31 | callback(null);
32 | });
33 | });
34 |
35 | it('should trigger called without an error', function() {
36 | hoodie.uninstall(options, function(e) {
37 | expect(e).to.be(null);
38 | });
39 | });
40 |
41 | it('should trigger callback with an error', function() {
42 | hoodie.uninstall(options, function(e) {
43 | expect(e).to.eql(null);
44 | });
45 | });
46 | });
47 |
48 | });
49 |
50 |
--------------------------------------------------------------------------------
/spec/hoodie/util/dir.spec.js:
--------------------------------------------------------------------------------
1 | var dir = require('../../../lib/hoodie/util/dir');
2 | var options;
3 |
4 | var expect = require('expect.js');
5 |
6 | /*
7 | * Specification: dir.buildGitURI(options)
8 | */
9 |
10 | describe('dir.buildGitURI(options)', function() {
11 | beforeEach(function() {
12 | options = {
13 | tmpl_cfg: {
14 | entity: 'hoodiehq',
15 | repo: 'my-first-hoodie'
16 | }
17 | };
18 | });
19 |
20 | it('should build a non-SSH GitHub URL by default', function() {
21 | expect(dir.buildGitURI(options)).to.be('https://github.com/hoodiehq/my-first-hoodie.git');
22 | })
23 |
24 | it('should build a non-SSH GitHub URL', function() {
25 | options.ssh = false;
26 | expect(dir.buildGitURI(options)).to.be('https://github.com/hoodiehq/my-first-hoodie.git');
27 | })
28 |
29 | it('should build an SSH GitHub URL', function() {
30 | options.ssh = true;
31 | expect(dir.buildGitURI(options)).to.be('git@github.com:hoodiehq/my-first-hoodie.git');
32 | });
33 | });
34 |
35 |
--------------------------------------------------------------------------------
/spec/hoodie/version.spec.js:
--------------------------------------------------------------------------------
1 | var hoodie = require('../../lib/hoodie');
2 | var hoodie;
3 |
4 | var expect = require('expect.js');
5 |
6 | /*
7 | * Specification: hoodie.version()
8 | */
9 |
10 | describe('hoodie.version()', function() {
11 |
12 | beforeEach(function() {
13 | hoodie = new hoodie();
14 | });
15 |
16 | it('should return a version string', function() {
17 | expect(hoodie.version).to.be.ok();
18 | });
19 |
20 | });
21 |
--------------------------------------------------------------------------------
/spec/integration/hoodie.js:
--------------------------------------------------------------------------------
1 | var cp = require('child_process')
2 | var writeFileSync = require('fs').writeFileSync
3 | var path = require('path')
4 |
5 | var nixt = require('nixt')
6 | var expect = require('expect.js')
7 |
8 | var cwd = path.resolve('./.tmp')
9 | var hoodieCwd = path.join(cwd, 'test')
10 |
11 | process.env.HOODIE_SETUP_PASSWORD = '12345'
12 |
13 | function hoodieStart (args, regex, cb) {
14 | var start = cp.spawn('../../bin/hoodie', ['start', '-n'].concat(args), {
15 | cwd: hoodieCwd,
16 | detached: true
17 | })
18 | var timeoutError = null;
19 | var killStart = process.kill.bind(process, -start.pid)
20 | var killTimeout = setTimeout(function () {
21 | timeoutError = new Error('timeout')
22 | killStart()
23 | }, 50000)
24 | start.stdout.on('data', function (data) {
25 | if (regex.test(data.toString())) {
26 | clearTimeout(killTimeout)
27 | killStart()
28 | }
29 | })
30 | start.on('close', function (code) {
31 | cb(timeoutError)
32 | })
33 | }
34 |
35 | describe('hoodie integration tests', function () {
36 | this.timeout(100000)
37 |
38 | before(function (done) {
39 | cp.exec('(rm -rf .tmp || true) && mkdir .tmp', done)
40 | })
41 |
42 | describe('hoodie help', function () {
43 | it('should output the usage information', function (done) {
44 | nixt()
45 | .cwd(cwd)
46 | .run('../bin/hoodie help')
47 | .stdout(/Usage/)
48 | .end(done)
49 | })
50 | })
51 |
52 | describe('hoodie new', function () {
53 | it('should create the app', function (done) {
54 | nixt()
55 | .cwd(cwd)
56 | .run('../bin/hoodie new test')
57 | .stdout(/You can now start using your hoodie app/)
58 | .end(done)
59 | })
60 | })
61 |
62 | describe('hoodie start', function () {
63 | it('should start the app', function (done) {
64 | hoodieStart([], /All plugins started\./, done)
65 | })
66 |
67 | it('should start the app after a crash', function (done) {
68 | writeFileSync(path.join(hoodieCwd, 'data/hoodie.pid'), '12345')
69 | hoodieStart([], /Hoodie is already running!/, done)
70 | })
71 |
72 | it('should start the app in force mode after a crash', function (done) {
73 | writeFileSync(path.join(hoodieCwd, 'data/hoodie.pid'), '12345')
74 | hoodieStart(['-f'], /All plugins started\./, done)
75 | })
76 | })
77 | })
78 |
--------------------------------------------------------------------------------
/spec/main.spec.js:
--------------------------------------------------------------------------------
1 | var Hoodie = require('../lib/hoodie');
2 | var hoodie = require('../lib/main');
3 |
4 | var expect = require('expect.js');
5 |
6 | /*!
7 | * Specification: hoodie.
8 | */
9 |
10 | describe('main', function() {
11 |
12 | it('should be an instance of Hoodie', function() {
13 | expect(hoodie).to.be.an(Hoodie);
14 | });
15 | });
16 |
--------------------------------------------------------------------------------
/spec/runner.js:
--------------------------------------------------------------------------------
1 | require('./support/helper');
2 | require('./main.spec');
3 | require('./hoodie.spec');
4 | require('./cli/help.spec');
5 | require('./cli/install.spec');
6 | require('./cli/new.spec');
7 | require('./cli/start.spec');
8 | require('./cli/reset.spec');
9 | require('./cli/uninstall.spec');
10 | require('./cli/unknown.spec');
11 | require('./hoodie/install.spec');
12 | require('./hoodie/new.spec');
13 | require('./hoodie/start.spec');
14 | require('./hoodie/uninstall.spec');
15 | require('./hoodie/reset.spec');
16 | require('./integration/hoodie');
17 |
--------------------------------------------------------------------------------
/spec/support/helper.js:
--------------------------------------------------------------------------------
1 | /*globals before:true, after:true*/
2 | var sinon = require('sinon');
3 |
4 | module.exports = {
5 | before: (function () {
6 |
7 | before(function () {
8 | this.sandbox = sinon.sandbox.create();
9 | });
10 |
11 | }()),
12 | beforeEach: (function () {
13 |
14 | beforeEach(function () {});
15 |
16 | }()),
17 | afterEach: (function () {
18 |
19 | afterEach(function () {
20 | this.sandbox.restore();
21 | });
22 |
23 | }()),
24 | after: (function () {
25 |
26 | after(function () {});
27 |
28 | }())
29 | };
30 |
31 |
--------------------------------------------------------------------------------