├── .gitignore
├── .idea
├── .name
├── encodings.xml
├── generator-express-rest-api.iml
├── jsLibraryMappings.xml
├── libraries
│ └── generator_express_rest_api_node_modules.xml
├── misc.xml
├── modules.xml
├── scopes
│ └── scope_settings.xml
├── vcs.xml
└── workspace.xml
├── .travis.yml
├── LICENSE
├── README.md
├── generators
├── app
│ ├── index.js
│ └── templates
│ │ ├── _package.json
│ │ ├── app
│ │ └── config
│ │ │ ├── route-config.js
│ │ │ ├── route.config.json
│ │ │ ├── settings
│ │ │ ├── settings-config.js
│ │ │ ├── settings.config.dev.json
│ │ │ ├── settings.config.prod.json
│ │ │ └── settings.config.test.json
│ │ │ └── worker-config.js
│ │ ├── server.js
│ │ └── test
│ │ ├── mocha.opts
│ │ └── tests.initialize.js
├── controller
│ ├── index.js
│ └── templates
│ │ ├── app
│ │ └── controllers
│ │ │ └── _controller.js
│ │ └── test
│ │ └── spec
│ │ └── controllers
│ │ └── _controller.tests.js
├── repository
│ ├── index.js
│ └── templates
│ │ ├── app
│ │ └── repositories
│ │ │ └── _repository.js
│ │ └── test
│ │ └── spec
│ │ └── repositories
│ │ └── _repository.tests.js
└── service
│ ├── index.js
│ └── templates
│ ├── app
│ └── services
│ │ └── _service.js
│ └── test
│ └── spec
│ └── services
│ └── _service.tests.js
├── package.json
├── projectFilesBackup
└── .idea
│ └── workspace.xml
└── test
├── app
└── index.tests.js
├── mocha.opts
└── tests.initialize.js
/.gitignore:
--------------------------------------------------------------------------------
1 | # Logs
2 | logs
3 | *.log
4 |
5 | # Runtime data
6 | pids
7 | *.pid
8 | *.seed
9 |
10 | # Directory for instrumented libs generated by jscoverage/JSCover
11 | lib-cov
12 |
13 | # Coverage directory used by tools like istanbul
14 | coverage
15 |
16 | # Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files)
17 | .grunt
18 |
19 | # Compiled binary addons (http://nodejs.org/api/addons.html)
20 | build/Release
21 |
22 | # Dependency directory
23 | # Commenting this out is preferred by some people, see
24 | # https://www.npmjs.org/doc/misc/npm-faq.html#should-i-check-my-node_modules-folder-into-git-
25 | node_modules
26 |
27 | # Users Environment Variables
28 | .lock-wscript
29 |
--------------------------------------------------------------------------------
/.idea/.name:
--------------------------------------------------------------------------------
1 | generator-express-rest-api
--------------------------------------------------------------------------------
/.idea/encodings.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/.idea/generator-express-rest-api.iml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
--------------------------------------------------------------------------------
/.idea/jsLibraryMappings.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/.idea/libraries/generator_express_rest_api_node_modules.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
--------------------------------------------------------------------------------
/.idea/misc.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/.idea/modules.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
--------------------------------------------------------------------------------
/.idea/scopes/scope_settings.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
--------------------------------------------------------------------------------
/.idea/vcs.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/.idea/workspace.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 |
77 |
78 |
79 |
80 |
81 |
82 |
83 |
84 |
85 |
86 |
87 |
88 |
89 |
90 |
91 |
92 |
93 |
94 |
95 |
96 |
97 |
98 |
99 |
100 |
101 |
102 |
103 |
104 |
105 |
106 |
107 |
108 |
109 |
110 |
111 |
112 |
113 |
114 |
115 |
116 |
117 |
118 |
119 |
120 |
121 |
126 |
127 |
128 |
129 |
130 |
131 |
132 |
133 |
134 |
135 |
136 |
137 |
138 |
139 |
140 |
141 |
142 |
143 |
144 |
145 |
146 |
147 |
148 |
149 |
150 |
151 |
152 |
153 |
154 |
155 |
156 |
157 |
158 |
159 |
160 |
161 |
162 |
163 |
164 |
165 |
166 | true
167 |
168 |
169 |
170 |
171 |
172 | $PROJECT_DIR$/node_modules/mocha
173 |
174 |
175 |
176 |
177 |
178 |
179 |
180 |
181 |
182 |
183 |
184 |
185 |
186 |
187 |
188 |
189 |
190 |
191 |
192 |
193 |
194 |
195 |
196 |
197 |
198 |
199 |
200 |
201 |
202 |
203 |
204 |
205 |
206 |
207 |
208 |
209 |
210 |
211 |
212 |
213 |
214 |
215 |
216 |
217 |
218 |
219 |
220 |
221 |
222 |
223 |
224 |
225 |
226 |
227 |
228 |
229 |
230 |
231 |
232 |
233 |
234 |
235 |
236 |
237 |
238 |
239 |
240 |
241 |
242 |
243 |
244 |
245 |
246 |
247 |
248 |
249 |
250 |
251 |
252 |
253 |
254 |
255 |
256 |
257 |
258 |
259 |
260 |
261 |
262 |
263 |
264 |
265 |
266 |
267 |
268 |
269 |
270 |
271 |
272 |
273 |
274 |
275 |
276 |
277 |
278 |
279 |
280 |
281 |
282 |
283 |
284 |
285 |
286 |
287 |
288 |
289 |
290 |
291 |
292 |
293 |
294 |
295 |
296 |
297 |
298 |
299 |
300 |
301 |
302 |
303 |
304 |
305 |
306 |
307 |
308 |
309 |
310 |
311 |
312 |
313 |
314 |
315 |
316 |
317 |
318 |
319 |
320 |
321 |
322 |
323 |
324 |
325 |
326 |
327 |
328 |
329 |
330 |
331 |
332 |
333 |
334 | true
335 |
336 |
337 |
338 |
339 |
340 | $PROJECT_DIR$
341 | true
342 |
343 | bdd
344 |
345 |
346 | false
347 |
348 |
349 |
350 |
351 | $PROJECT_DIR$
352 | true
353 |
354 | bdd
355 |
356 | $PROJECT_DIR$/test
357 | false
358 |
359 |
360 |
361 |
362 |
363 |
364 |
365 |
366 |
367 |
368 |
369 |
370 |
371 | 1412338391155
372 |
373 | 1412338391155
374 |
375 |
376 |
377 |
378 |
379 |
380 |
381 |
382 |
383 |
384 |
385 |
386 |
387 |
388 |
389 |
390 |
391 |
392 |
393 |
394 |
395 |
396 |
397 |
398 |
399 |
400 |
401 |
402 |
403 |
404 |
405 |
406 |
407 |
408 |
409 |
410 |
411 |
412 |
413 |
414 |
415 |
416 |
417 |
418 |
419 | file://$PROJECT_DIR$/test/app/index.tests.js
420 | 6
421 |
422 |
423 |
424 |
425 |
426 |
427 |
428 |
429 |
430 |
431 |
432 |
433 |
434 |
435 |
436 |
437 |
438 |
439 |
440 |
441 |
442 |
443 |
444 |
445 |
446 |
447 |
448 |
449 |
450 |
451 |
452 |
453 |
454 |
455 |
456 |
457 |
458 |
459 |
460 |
461 |
462 |
463 |
464 |
465 |
466 |
467 |
468 |
469 |
470 |
471 |
472 |
473 |
474 |
475 |
476 |
477 |
478 |
479 |
480 |
481 |
482 |
483 |
484 |
485 |
486 |
487 |
488 |
489 |
490 |
491 |
492 |
493 |
494 |
495 |
496 |
497 |
498 |
499 |
500 |
501 |
502 |
503 |
504 |
505 |
506 |
507 |
508 |
509 |
510 |
511 |
512 |
513 |
514 |
515 |
516 |
517 |
518 |
519 |
520 |
521 |
522 |
523 |
524 |
525 |
526 |
527 |
528 |
529 |
530 |
531 |
532 |
533 |
534 |
535 |
536 |
537 |
538 |
539 |
540 |
541 |
542 |
543 |
544 |
545 |
546 |
547 |
548 |
549 |
550 |
551 |
552 |
553 |
554 |
555 |
556 |
557 |
558 |
559 |
560 |
561 |
562 |
563 |
564 |
565 |
566 |
567 |
568 |
569 |
570 |
571 |
572 |
573 |
574 |
575 |
576 |
577 |
578 |
579 |
580 |
581 |
582 |
583 |
584 |
585 |
586 |
587 |
588 |
589 |
590 |
591 |
592 |
593 |
594 |
595 |
596 |
597 |
598 |
599 |
600 |
601 |
602 |
603 |
604 |
605 |
606 |
607 |
608 |
609 |
610 |
611 |
612 |
613 |
614 |
615 |
616 |
617 |
618 |
619 |
620 |
621 |
622 |
623 |
624 |
625 |
626 |
627 |
628 |
629 |
630 |
631 |
632 |
633 |
634 |
635 |
636 |
637 |
638 |
639 |
640 |
641 |
642 |
643 |
644 |
645 |
646 |
647 |
648 |
649 |
650 |
651 |
652 |
653 |
654 |
655 |
656 |
657 |
658 |
659 |
660 |
661 |
662 |
663 |
664 |
665 |
666 |
667 |
668 |
669 |
670 |
671 |
672 |
673 |
674 |
675 |
676 |
677 |
678 |
679 |
680 |
681 |
682 |
683 |
684 |
685 |
686 |
687 |
688 |
689 |
690 |
691 |
692 |
693 |
694 |
695 |
696 |
697 |
698 |
699 |
700 |
701 |
702 |
703 |
704 |
705 |
706 |
707 |
708 |
709 |
710 |
711 |
712 |
713 |
714 |
715 |
716 |
717 |
718 |
719 |
720 |
721 |
722 |
723 |
724 |
725 |
726 |
727 |
728 |
729 |
730 |
731 |
732 |
733 |
734 |
735 |
736 |
737 |
738 |
739 |
740 |
741 |
742 |
743 |
744 |
745 |
746 |
747 |
748 |
749 |
750 |
751 |
752 |
753 |
754 |
755 |
756 |
757 |
758 |
759 |
760 |
761 |
762 |
763 |
764 |
765 |
766 |
767 |
768 |
769 |
770 |
771 |
772 |
773 |
774 |
775 |
776 |
777 |
778 |
779 |
780 |
781 |
782 |
783 |
784 |
785 |
786 |
787 |
788 |
789 |
790 |
791 |
792 |
793 |
794 |
795 |
796 |
797 |
798 |
799 |
800 |
801 |
802 |
803 |
--------------------------------------------------------------------------------
/.travis.yml:
--------------------------------------------------------------------------------
1 | language: node_js
2 | node_js:
3 | - "0.12"
4 | - "0.11"
5 | - "0.10"
6 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | The MIT License (MIT)
2 |
3 | Copyright (c) 2014 Tim Walker
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
23 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | [](https://travis-ci.org/trwalker/generator-express-rest-api)
2 |
3 | generator-express-rest-api
4 | ==========================
5 |
6 | ### Summary
7 | This is a Yeoman generator to quick scaffold a RESTful API using expresss, cluter-service, mocha, chai, sinon, and istanbul. The structure generated follows the MVC controller/service/repository pattern.
8 |
9 | ### Installing Yeoman
10 | http://yeoman.io/learning/index.html
11 |
12 | ### Windows Pre-Requisites
13 | Python 2.7.x: https://www.python.org/downloads/
14 |
15 | ### Installing Generator
16 | `> npm install -g generator-express-rest-api`
17 |
18 | ### Scaffolding Application
19 | `> yo express-rest-api`
20 |
21 | ### Scaffolding Controller, Controller Test, and Updates Route Config
22 | `> yo express-rest-api:controller`
23 |
24 | ### Scaffolding Service and Service Test
25 | `> yo express-rest-api:service`
26 |
27 | ### Scaffolding Repository and Repository Test
28 | `> yo express-rest-api:repository`
29 |
30 | ### Application NPM Commands ###
31 | ```
32 | // installs everything that is required to run your new application
33 | > npm run install-local
34 | ```
35 | ```
36 | // runs application
37 | > npm start
38 | ```
39 | ```
40 | // runs application in debug mode
41 | > npm run debug
42 | ```
43 | ```
44 | // runs mocha tests
45 | > npm test
46 | ```
47 | ```
48 | // runs istanbul code coverage
49 | > npm run test-coverage
50 | ```
51 |
52 | ### Application Folder Structure Example
53 | ```
54 | package.json
55 | server.js
56 | \app
57 | \..\config
58 | \..\settings
59 | \..\..\settings-config.js
60 | \..\route.config.json
61 | \..\route-config.js
62 | \..\worker-config.js
63 |
64 | \..\controllers
65 | \..\..\v1
66 | \..\..\..\users
67 | \..\..\..\..\users-controller.js
68 |
69 | \..\services
70 | \..\..\users
71 | \..\..\..\user-service.js
72 |
73 | \..\repositories
74 | \..\..\users
75 | \..\..\..\user-repository.js
76 | \test
77 | \..\spec
78 | \..\mocha.opts
79 | \..\tests.initialize.js
80 |
81 | \..\..\controllers
82 | \..\..\..\v1
83 | \..\..\..\..\users
84 | \..\..\..\..\..\users-controller.tests.js
85 |
86 | \..\..\services
87 | \..\..\..\users
88 | \..\..\..\..\user-service.tests.js
89 |
90 | \..\..\repositories
91 | \..\..\..\users
92 | \..\..\..\..\user-repository.tests.js
93 | ```
94 |
95 | ### Example Application: Marvel Node API
96 | https://github.com/trwalker/marvel-node
97 |
--------------------------------------------------------------------------------
/generators/app/index.js:
--------------------------------------------------------------------------------
1 | var yeoman = require('yeoman-generator');
2 | var fs = require('fs');
3 | var path = require('path');
4 |
5 | module.exports = yeoman.generators.Base.extend({
6 | initializingStep: function() {
7 | this.questions = [];
8 | this.applicationName = path.basename(process.cwd());
9 | this.version = '1.0.0';
10 | this.applicationDescription = '';
11 | this.author = '';
12 | this.gitRepository = '';
13 | this.license = '';
14 | },
15 |
16 | promptingStep: function() {
17 | this.questions.push({ type : 'input',
18 | name : 'applicationName',
19 | message : 'Application Name',
20 | default : this.applicationName });
21 |
22 | this.questions.push({ type : 'input',
23 | name : 'version',
24 | message : 'Version',
25 | default : this.version });
26 |
27 | this.questions.push({ type : 'input',
28 | name : 'applicationDescription',
29 | message : 'Application Description',
30 | default : this.applicationDescription });
31 |
32 | this.questions.push({ type : 'input',
33 | name : 'author',
34 | message : 'Author',
35 | default : this.author });
36 |
37 | this.questions.push({ type : 'input',
38 | name : 'gitRepository',
39 | message : 'Git Repository',
40 | default : this.gitRepository });
41 |
42 | this.questions.push({ type : 'input',
43 | name : 'license',
44 | message : 'License',
45 | default : this.license });
46 |
47 | var done = this.async();
48 |
49 | var generator = this;
50 |
51 | var handleAnswers = function(answers) {
52 | generator.applicationName = answers.applicationName;
53 | generator.version = answers.version;
54 | generator.applicationDescription = answers.applicationDescription;
55 | generator.author = answers.author;
56 | generator.gitRepository = answers.gitRepository;
57 | generator.license = answers.license;
58 |
59 | done();
60 | };
61 |
62 | this.prompt(this.questions, handleAnswers.bind(this));
63 | },
64 |
65 | configuringStep: function() {
66 | copyTemplate(this, '_package.json', 'package.json');
67 | },
68 |
69 | defaultStep: function() {
70 | },
71 |
72 | writingStep: function() {
73 | copyTemplate(this, 'server.js', 'server.js');
74 |
75 | copyTemplate(this, 'app/config/route.config.json', 'app/config/route.config.json');
76 | copyTemplate(this, 'app/config/route-config.js', 'app/config/route-config.js');
77 | copyTemplate(this, 'app/config/worker-config.js', 'app/config/worker-config.js');
78 |
79 | copyTemplate(this, 'app/config/settings/settings-config.js', 'app/config/settings/settings-config.js');
80 | copyTemplate(this, 'app/config/settings/settings.config.dev.json', 'app/config/settings/settings.config.dev.json');
81 | copyTemplate(this, 'app/config/settings/settings.config.test.json', 'app/config/settings/settings.config.test.json');
82 | copyTemplate(this, 'app/config/settings/settings.config.prod.json', 'app/config/settings/settings.config.prod.json');
83 |
84 | copyTemplate(this, 'test/mocha.opts', 'test/mocha.opts');
85 | copyTemplate(this, 'test/tests.initialize.js', 'test/tests.initialize.js');
86 | },
87 |
88 | conflictsStep: function() {
89 | },
90 |
91 | installStep: function() {
92 | },
93 |
94 | endStep: function() {
95 | this.npmInstall(['express', 'cluster-service', 'body-parser'], { 'save': true });
96 | this.npmInstall(['mocha', 'chai', 'sinon', 'istanbul'], { 'saveDev': true });
97 | }
98 | });
99 |
100 | var copyTemplate = function(generator, template, path) {
101 | if(fs.existsSync(path)) {
102 | console.log('The file "' + path + '" already exists!');
103 | }
104 | else {
105 | generator.template(template, path);
106 | }
107 | };
108 |
--------------------------------------------------------------------------------
/generators/app/templates/_package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "<%= applicationName %>",
3 | "version": "<%= version %>",
4 | "description": "<%= applicationDescription %>",
5 | "main": "server.js",
6 | "scripts": {
7 | "test": "mocha",
8 | "test-coverage": "npm test && istanbul cover node_modules/mocha/bin/_mocha -- -R spec",
9 | "install-local": "npm install -g mocha & npm install -g node-inspector & npm install",
10 | "start": "node server.js 1 prod 127.0.0.1 3000 9000",
11 | "debug": "node-debug server.js 0 dev 127.0.0.1 3000 9000"
12 | },
13 | "repository": {
14 | "type": "git",
15 | "url": "<%= gitRepository %>"
16 | },
17 | "keywords": [
18 | "none"
19 | ],
20 | "author": "<%= author %>",
21 | "license": "<%= license %>",
22 | "devDependencies": {
23 | },
24 | "dependencies": {
25 | }
26 | }
27 |
--------------------------------------------------------------------------------
/generators/app/templates/app/config/route-config.js:
--------------------------------------------------------------------------------
1 | var settingsConfig = require('./settings/settings-config');
2 |
3 | function RouteConfig() {
4 | }
5 |
6 | function registerRoutes(application) {
7 | var config = loadRouteConfig();
8 |
9 | for(var i = 0, length = config.routes.length; i < length; i++) {
10 | var routeItem = config.routes[i];
11 |
12 | var controller = loadController(routeItem);
13 | var route = getRoute(routeItem);
14 | var method = getMethod(routeItem);
15 | var action = getAction(routeItem);
16 |
17 | registerRoute(application, controller, route, method, action);
18 | }
19 |
20 | createConfigRoute(application);
21 | }
22 |
23 | function loadRouteConfig() {
24 | var config;
25 |
26 | try {
27 | config = require('./route.config.json');
28 |
29 | if(!config.routes || config.routes.length === 0) {
30 | throw '"routes" not defined';
31 | }
32 | }
33 | catch(e) {
34 | throw 'Unable to parse "lib/config/route.config.json": ' + e;
35 | }
36 |
37 | return config;
38 | }
39 |
40 | function loadController(routeItem) {
41 | var controller;
42 |
43 | if(!routeItem || !routeItem.controller) {
44 | throw 'Undefined "controller" property in "lib/config/route.config.json"';
45 | }
46 |
47 | try {
48 | controller = require(routeItem.controller);
49 | }
50 | catch(e) {
51 | throw 'Unable to load ' + routeItem.controller + ": " + e;
52 | }
53 |
54 | return controller;
55 | }
56 |
57 | function getRoute(routeItem) {
58 | if(!routeItem || !routeItem.route || routeItem.route.length === 0) {
59 | throw 'Undefined or empty "route" property in "lib/config/route.config.json"';
60 | }
61 |
62 | return routeItem.route;
63 | }
64 |
65 | function getMethod(routeItem) {
66 | if(!routeItem || !routeItem.method || routeItem.method.length === 0) {
67 | throw 'Undefined or empty "method" property in "lib/config/route.config.json"';
68 | }
69 |
70 | var method = routeItem.method.toLowerCase();
71 |
72 | switch(method) {
73 | case 'get':
74 | case 'put':
75 | case 'post':
76 | case 'delete':
77 | return method;
78 | break;
79 | default:
80 | throw 'Invalid REST "method" property in "lib/config/route.config.json": ' + method;
81 | }
82 | }
83 |
84 | function getAction(routeItem) {
85 | if(!routeItem || !routeItem.action || routeItem.action.length === 0) {
86 | return getMethod(routeItem);
87 | }
88 | return routeItem.action;
89 | }
90 |
91 |
92 | function registerRoute(application, controller, route, method, action) {
93 | application.route(route)[method](function(req, res, next) {
94 | controller[action](req, res, next);
95 | });
96 | }
97 |
98 | function createConfigRoute(application) {
99 | application.route('/config').get(function(req, res, next) {
100 | res.status(200).json(settingsConfig.settings);
101 | });
102 | }
103 |
104 | RouteConfig.prototype = {
105 | registerRoutes: registerRoutes
106 | };
107 |
108 | var routeConfig = new RouteConfig();
109 |
110 | module.exports = routeConfig;
111 |
--------------------------------------------------------------------------------
/generators/app/templates/app/config/route.config.json:
--------------------------------------------------------------------------------
1 | {
2 | "routes": [
3 | ]
4 | }
5 |
--------------------------------------------------------------------------------
/generators/app/templates/app/config/settings/settings-config.js:
--------------------------------------------------------------------------------
1 | var os = require('os');
2 | var commandLineArgs = process.argv;
3 |
4 | function SettingsConfig() {
5 | this.settings = {};
6 |
7 | initializeSettings(this.settings);
8 | }
9 |
10 | function initializeSettings(settings) {
11 | createArgumentSettings(settings);
12 | loadConfigSettings(settings);
13 | loadServerSettings(settings);
14 | }
15 |
16 | function createArgumentSettings(settings) {
17 | settings.clusterEnabled = commandLineArgs[2] ? parseInt(commandLineArgs[2]) : 0;
18 | settings.environment = commandLineArgs[3] ? commandLineArgs[3].toLowerCase() : 'prod';
19 | settings.hostName = commandLineArgs[4] ? commandLineArgs[4] : '127.0.0.1';
20 | settings.masterPort = commandLineArgs[5] ? parseInt(commandLineArgs[5]) : 3000;
21 | settings.workerPort = commandLineArgs[6] ? parseInt(commandLineArgs[6]) : 9000;
22 | }
23 |
24 | function loadConfigSettings(settings) {
25 | var config = loadEnvironmentConfigFile(settings);
26 |
27 | var settingsLength = config.settings.length;
28 |
29 | for(var i = 0; i < settingsLength; i++) {
30 | var configSetting = config.settings[i];
31 |
32 | if(configSetting.name && configSetting.value) {
33 | settings[configSetting.name] = configSetting.value;
34 | }
35 | }
36 | }
37 |
38 | function loadServerSettings(settings) {
39 | settings.serverName = os.hostname().toLowerCase();
40 | settings.serverCores = os.cpus().length;
41 | }
42 |
43 | function loadEnvironmentConfigFile(settings) {
44 | var config;
45 |
46 | var configLocation = './settings.config.prod.json';
47 |
48 | switch(settings.environment) {
49 | case 'dev':
50 | configLocation = './settings.config.dev.json';
51 | break;
52 | case 'test':
53 | configLocation = './settings.config.test.json';
54 | break;
55 | }
56 |
57 | try {
58 | config = require(configLocation);
59 | }
60 | catch(e) {
61 | throw 'Unable to parse "lib/config/settings/"' + configLocation + ': ' + e;
62 | }
63 |
64 | if(!config.settings) {
65 | throw 'Property "settings" is no defined: ' + configLocation;
66 | }
67 |
68 | return config;
69 | }
70 |
71 | var settingsConfig = new SettingsConfig();
72 |
73 | module.exports = settingsConfig;
74 |
--------------------------------------------------------------------------------
/generators/app/templates/app/config/settings/settings.config.dev.json:
--------------------------------------------------------------------------------
1 | {
2 | "settings": [
3 | { "name": "queueLength", "value": 10 }
4 | ]
5 | }
6 |
--------------------------------------------------------------------------------
/generators/app/templates/app/config/settings/settings.config.prod.json:
--------------------------------------------------------------------------------
1 | {
2 | "settings": [
3 | { "name": "queueLength", "value": 511 }
4 | ]
5 | }
6 |
--------------------------------------------------------------------------------
/generators/app/templates/app/config/settings/settings.config.test.json:
--------------------------------------------------------------------------------
1 | {
2 | "settings": [
3 | { "name": "queueLength", "value": 10 }
4 | ]
5 | }
6 |
--------------------------------------------------------------------------------
/generators/app/templates/app/config/worker-config.js:
--------------------------------------------------------------------------------
1 | var http = require('http');
2 | var express = require('express');
3 | var application = express();
4 | var bodyParser = require('body-parser');
5 | var routeConfig = require('./route-config');
6 | var settingsConfig = require('./settings/settings-config');
7 |
8 | function configureWorker(application) {
9 | configureApplication(application);
10 | configureRoutes(application);
11 |
12 | startServer(application);
13 | }
14 |
15 | function configureApplication(application) {
16 | application.use(bodyParser.json());
17 |
18 | application.use(function(req, res, next) {
19 | res.set('Cache-Control', 'no-cache, no-store, must-revalidate');
20 | res.set('Pragma', 'no-cache');
21 | res.set('Expires', '0');
22 | res.type('application/json');
23 | next();
24 | });
25 | }
26 |
27 | function configureRoutes(application) {
28 | routeConfig.registerRoutes(application);
29 | }
30 |
31 | function startServer(application) {
32 | var server = http.createServer(application);
33 |
34 | server.listen(settingsConfig.settings.workerPort, settingsConfig.settings.hostName, settingsConfig.settings.queueLength, function() {
35 | console.log('listening at http://%s:%s', settingsConfig.settings.hostName, settingsConfig.settings.workerPort);
36 | });
37 | }
38 |
39 | configureWorker(application);
40 |
--------------------------------------------------------------------------------
/generators/app/templates/server.js:
--------------------------------------------------------------------------------
1 | var settingsConfig = require('./app/config/settings/settings-config');
2 |
3 | if(settingsConfig.settings.clusterEnabled === 1) {
4 | require('cluster-service').start({ workers: './app/config/worker-config.js',
5 | accessKey: settingsConfig.settings.clusterAccessKey,
6 | host: settingsConfig.settings.hostName,
7 | port: settingsConfig.settings.masterPort });
8 | }
9 | else {
10 | require('./app/config/worker-config.js');
11 | }
12 |
--------------------------------------------------------------------------------
/generators/app/templates/test/mocha.opts:
--------------------------------------------------------------------------------
1 | -R spec
2 | -u bdd
3 | --recursive
--------------------------------------------------------------------------------
/generators/app/templates/test/tests.initialize.js:
--------------------------------------------------------------------------------
1 |
2 | beforeEach(function() {
3 | global.expect = require('chai').expect;
4 | global.sinon = require('sinon');
5 | });
--------------------------------------------------------------------------------
/generators/controller/index.js:
--------------------------------------------------------------------------------
1 | var yeoman = require('yeoman-generator');
2 | var fs = require('fs');
3 |
4 | const routeConfigRequirePath = '/app/config/route.config.json';
5 |
6 | module.exports = yeoman.generators.Base.extend({
7 | initializingStep: function() {
8 | this.questions = [];
9 | this.controllerName = 'clowns';
10 | this.controllerClassName = 'Clowns';
11 | this.controllerInstanceName = 'clowns';
12 | this.controllerVersion = 'v1';
13 | this.controllerFolderPath = 'circus';
14 | this.controllerRequirePathFromTest = '';
15 | this.controllerRoute = '/clowns/:clownid';
16 | this.controllerMethod = 'GET';
17 | this.httpMethods = [ 'GET', 'PUT', 'POST', 'DELETE' ];
18 | },
19 |
20 | promptingStep: function() {
21 | this.questions.push({ type : 'input',
22 | name : 'controllerName',
23 | message : 'Controller Name (dash delimited, leave off -controller)',
24 | default : this.controllerName });
25 |
26 | this.questions.push({ type : 'input',
27 | name : 'controllerVersion',
28 | message : 'Controller Version',
29 | default : this.controllerVersion });
30 |
31 | this.questions.push({ type : 'input',
32 | name : 'controllerFolderPath',
33 | message : 'Controller Folder Path (relative path after the version folder, no starting or training slashes)',
34 | default : this.controllerFolderPath });
35 |
36 | this.questions.push({ type : 'input',
37 | name : 'controllerRoute',
38 | message : 'Controller Route (HTTP request route without the version)',
39 | default : this.controllerRoute });
40 |
41 | this.questions.push({ type : 'list',
42 | name : 'controllerMethod',
43 | message : 'Controller Method',
44 | choices : this.httpMethods,
45 | default : 0 });
46 |
47 | var done = this.async();
48 |
49 | var generator = this;
50 |
51 | var handleAnswers = function(answers) {
52 | generator.controllerName = answers.controllerName.toLowerCase();
53 | generator.controllerClassName = generator._.classify(answers.controllerName);
54 | generator.controllerInstanceName = generator._.camelize(generator.controllerName);
55 | generator.controllerVersion = answers.controllerVersion;
56 | generator.controllerFolderPath = answers.controllerFolderPath.toLowerCase();
57 | generator.controllerRequirePathFromTest = getTestRequirePrefix(generator.controllerFolderPath) + 'app/controllers/' + generator.controllerVersion + '/' + generator.controllerFolderPath + '/' + generator.controllerName + "-controller";
58 | generator.controllerRoute = answers.controllerRoute.toLowerCase();
59 | generator.controllerMethod = answers.controllerMethod;
60 |
61 | done();
62 | };
63 |
64 | this.prompt(this.questions, handleAnswers.bind(this));
65 | },
66 |
67 | configuringStep: function() {
68 | },
69 |
70 | defaultStep: function() {
71 | },
72 |
73 | writingStep: function() {
74 | if(tryUpdateRouteConfig(this)) {
75 | copyController(this);
76 | copyControllerTest(this);
77 | }
78 | },
79 |
80 | conflictsStep: function() {
81 | },
82 |
83 | installStep: function() {
84 | },
85 |
86 | endStep: function() {
87 | }
88 | });
89 |
90 | function getTestRequirePrefix(controllerFolderPath) {
91 | var requirePrefix = '../../../../';
92 |
93 | if(controllerFolderPath.length !== 0) {
94 | var folderCount = (controllerFolderPath.match(/\//g) || []).length + 1;
95 |
96 | for(var i = 0; i < folderCount; i++) {
97 | requirePrefix = '../' + requirePrefix;
98 | }
99 | }
100 |
101 | return requirePrefix;
102 | }
103 |
104 | function copyController(generator) {
105 | var controllerDestination = generator.destinationRoot() +
106 | '/app/controllers/' +
107 | generator.controllerVersion +
108 | '/' +
109 | generator.controllerFolderPath +
110 | '/' +
111 | generator.controllerName.toLowerCase() +
112 | '-controller.js';
113 |
114 | copyTemplate(generator, 'app/controllers/_controller.js', controllerDestination);
115 | }
116 |
117 | function copyControllerTest(generator) {
118 | var controllerTestDestination = generator.destinationRoot() +
119 | '/test/spec/controllers/' +
120 | generator.controllerVersion +
121 | '/' +
122 | generator.controllerFolderPath +
123 | '/' +
124 | generator.controllerName.toLowerCase() +
125 | '-controller.tests.js';
126 |
127 | copyTemplate(generator, 'test/spec/controllers/_controller.tests.js', controllerTestDestination);
128 | }
129 |
130 | function tryUpdateRouteConfig(generator) {
131 | var success = false;
132 |
133 | var routeConfigPath = generator.destinationRoot() + routeConfigRequirePath;
134 |
135 | try {
136 | var routeConfig = require(routeConfigPath);
137 |
138 | if (routeConfig && routeConfig.routes) {
139 | var controllerRoute = '/' + generator.controllerVersion + generator.controllerRoute;
140 |
141 | if(doesRouteExistInConfig(routeConfig, controllerRoute)) {
142 | console.log('Route already exists in route.config.json. Route: ' + controllerRoute);
143 | console.log('If you want to add a new http method to an existing controller you must modify ' + routeConfigRequirePath + ' and add the method to the controller.');
144 | }
145 | else {
146 | writeToRouteConfig(generator, routeConfig, routeConfigPath, controllerRoute);
147 | success = true;
148 | }
149 | }
150 | else {
151 | console.log('Badly formatted route config "' + routeConfigPath + '", routes array is not defined');
152 | }
153 | }
154 | catch (e) {
155 | var message = 'Error parsing and updating route config "' + routeConfigPath + '":' + e;
156 | console.log(message);
157 | }
158 |
159 | return success;
160 | }
161 |
162 | function doesRouteExistInConfig(routeConfig, controllerRoute) {
163 | var i, routesLength;
164 |
165 | for(i = 0, routesLength = routeConfig.routes.length; i < routesLength; i++) {
166 | var routeItem = routeConfig.routes[i];
167 | if(routeItem.route === controllerRoute) {
168 | return true;
169 | }
170 | }
171 |
172 | return false;
173 | }
174 |
175 | function writeToRouteConfig(generator, routeConfig, routeConfigPath, controllerRoute) {
176 | var controllerRequirePath = getControllerRequirePath(generator);
177 |
178 | routeConfig.routes.push({ route: controllerRoute,
179 | method: generator.controllerMethod,
180 | controller: controllerRequirePath });
181 |
182 | fs.writeFileSync(routeConfigPath, JSON.stringify(routeConfig, null, 2));
183 | }
184 |
185 | function getControllerRequirePath(generator) {
186 | return '../controllers/' +
187 | generator.controllerVersion +
188 | '/' +
189 | generator.controllerFolderPath +
190 | '/' +
191 | generator.controllerName.toLowerCase() +
192 | '-controller';
193 | }
194 |
195 | function copyTemplate(generator, template, path) {
196 | if(fs.existsSync(path)) {
197 | console.log('The file "' + path + '" already exists!');
198 | }
199 | else {
200 | generator.template(template, path);
201 | }
202 | }
203 |
--------------------------------------------------------------------------------
/generators/controller/templates/app/controllers/_controller.js:
--------------------------------------------------------------------------------
1 |
2 | function <%= controllerClassName %>Controller() {
3 | }
4 |
5 | function <%= controllerMethod.toLowerCase() %>(req, res, next) {
6 | res.status(200).json({ hello: 'world' });
7 | }
8 |
9 | <%= controllerClassName %>Controller.prototype = {
10 | <%= controllerMethod.toLowerCase() %>: <%= controllerMethod.toLowerCase() %>
11 | };
12 |
13 | var <%= controllerInstanceName %>Controller = new <%= controllerClassName %>Controller();
14 |
15 | module.exports = <%= controllerInstanceName %>Controller;
16 |
--------------------------------------------------------------------------------
/generators/controller/templates/test/spec/controllers/_controller.tests.js:
--------------------------------------------------------------------------------
1 |
2 | describe('<%= controllerClassName %>Controller Tests', function() {
3 |
4 | var <%= controllerInstanceName %>Controller;
5 | var req;
6 | var res;
7 | var next;
8 |
9 | beforeEach(function() {
10 | req = {};
11 | res = { status: function(code) { return { json: function(obj) {} }} };
12 |
13 | sinon.spy(res, "status");
14 |
15 | <%= controllerInstanceName %>Controller = require('<%= controllerRequirePathFromTest %>');
16 | });
17 |
18 | describe('<%= controllerMethod.toLowerCase() %>()', function() {
19 |
20 | it('should be a function', function(done) {
21 | expect(<%= controllerInstanceName %>Controller.<%= controllerMethod.toLowerCase() %>).to.be.a('function');
22 | done();
23 | });
24 |
25 | it('should call res.status() one time', function(done) {
26 | <%= controllerInstanceName %>Controller.<%= controllerMethod.toLowerCase() %>(req, res, next);
27 |
28 | expect(res.status.callCount).to.equal(1);
29 | done();
30 | });
31 |
32 | it('should call res.status() with 200', function(done) {
33 | <%= controllerInstanceName %>Controller.<%= controllerMethod.toLowerCase() %>(req, res, next);
34 |
35 | expect(res.status.calledWith(200)).to.equal(true);
36 | done();
37 | });
38 |
39 | });
40 | });
41 |
--------------------------------------------------------------------------------
/generators/repository/index.js:
--------------------------------------------------------------------------------
1 | var yeoman = require('yeoman-generator');
2 | var fs = require('fs');
3 |
4 | module.exports = yeoman.generators.Base.extend({
5 | initializingStep: function() {
6 | this.questions = [];
7 | this.repositoryName = 'clown';
8 | this.repositoryClassName = 'Clown';
9 | this.repositoryInstanceName = 'clown';
10 | this.repositoryFolderPath = 'circus';
11 | this.repositoryRequirePathFromTest = '';
12 | },
13 |
14 | promptingStep: function() {
15 | this.questions.push({ type : 'input',
16 | name : 'repositoryName',
17 | message : 'Repository Name (dash delimited, leave off -repository)',
18 | default : this.repositoryName });
19 |
20 | this.questions.push({ type : 'input',
21 | name : 'repositoryFolderPath',
22 | message : 'Repository Folder Path (relative path, no starting or training slashes)',
23 | default : this.repositoryFolderPath });
24 |
25 | var done = this.async();
26 |
27 | var generator = this;
28 |
29 | var handleAnswers = function(answers) {
30 | generator.repositoryName = answers.repositoryName.toLowerCase();
31 | generator.repositoryClassName = generator._.classify(answers.repositoryName);
32 | generator.repositoryInstanceName = generator._.camelize(generator.repositoryName);
33 | generator.repositoryFolderPath = answers.repositoryFolderPath.toLowerCase();
34 | generator.repositoryRequirePathFromTest = getTestRequirePrefix(generator.repositoryFolderPath) + 'app/repositories/' + generator.repositoryFolderPath + '/' + generator.repositoryName + '-repository';
35 |
36 | done();
37 | };
38 |
39 | this.prompt(this.questions, handleAnswers.bind(this));
40 | },
41 |
42 | configuringStep: function() {
43 | },
44 |
45 | defaultStep: function() {
46 | },
47 |
48 | writingStep: function() {
49 | copyRepository(this);
50 | copyRepositoryTest(this);
51 | },
52 |
53 | conflictsStep: function() {
54 | },
55 |
56 | installStep: function() {
57 | },
58 |
59 | endStep: function() {
60 | }
61 | });
62 |
63 | function getTestRequirePrefix(repositoryFolderPath) {
64 | var requirePrefix = '../../../';
65 |
66 | if(repositoryFolderPath.length !== 0) {
67 | var folderCount = (repositoryFolderPath.match(/\//g) || []).length + 1;
68 |
69 | for(var i = 0; i < folderCount; i++) {
70 | requirePrefix = '../' + requirePrefix;
71 | }
72 | }
73 |
74 | return requirePrefix;
75 | }
76 |
77 | function copyRepository(generator) {
78 | var repositoryDestination = generator.destinationRoot() +
79 | '/app/repositories/' +
80 | generator.repositoryFolderPath +
81 | '/' +
82 | generator.repositoryName.toLowerCase() +
83 | '-repository.js';
84 |
85 | copyTemplate(generator, 'app/repositories/_repository.js', repositoryDestination);
86 | }
87 |
88 | function copyRepositoryTest(generator) {
89 | var repositoryTestDestination = generator.destinationRoot() +
90 | '/test/spec/repositories/' +
91 | generator.repositoryFolderPath +
92 | '/' +
93 | generator.repositoryName.toLowerCase() +
94 | '-repository.tests.js';
95 |
96 | copyTemplate(generator, 'test/spec/repositories/_repository.tests.js', repositoryTestDestination);
97 | }
98 |
99 | function copyTemplate(generator, template, path) {
100 | if(fs.existsSync(path)) {
101 | console.log('The file "' + path + '" already exists!');
102 | }
103 | else {
104 | generator.template(template, path);
105 | }
106 | }
107 |
--------------------------------------------------------------------------------
/generators/repository/templates/app/repositories/_repository.js:
--------------------------------------------------------------------------------
1 |
2 | function <%= repositoryClassName %>Repository() {
3 | }
4 |
5 | function get<%= repositoryClassName %>Data(id) {
6 | return { id: id };
7 | }
8 |
9 | <%= repositoryClassName %>Repository.prototype = {
10 | get<%= repositoryClassName %>Data: get<%= repositoryClassName %>Data
11 | };
12 |
13 | var <%= repositoryInstanceName %>Repository = new <%= repositoryClassName %>Repository();
14 |
15 | module.exports = <%= repositoryInstanceName %>Repository;
16 |
--------------------------------------------------------------------------------
/generators/repository/templates/test/spec/repositories/_repository.tests.js:
--------------------------------------------------------------------------------
1 |
2 | describe('<%= repositoryClassName %>Repository Tests', function() {
3 |
4 | var <%= repositoryInstanceName %>Repository;
5 |
6 | beforeEach(function() {
7 | <%= repositoryInstanceName %>Repository = require('<%= repositoryRequirePathFromTest %>');
8 | });
9 |
10 | describe('get<%= repositoryClassName %>Data()', function() {
11 |
12 | it('should be a function', function(done) {
13 | expect(<%= repositoryInstanceName %>Repository.get<%= repositoryClassName %>Data).to.be.a('function');
14 | done();
15 | });
16 |
17 | });
18 | });
19 |
--------------------------------------------------------------------------------
/generators/service/index.js:
--------------------------------------------------------------------------------
1 | var yeoman = require('yeoman-generator');
2 | var fs = require('fs');
3 |
4 | module.exports = yeoman.generators.Base.extend({
5 | initializingStep: function() {
6 | this.questions = [];
7 | this.serviceName = 'clown';
8 | this.serviceClassName = 'Clown';
9 | this.serviceInstanceName = 'clown';
10 | this.serviceFolderPath = 'circus';
11 | this.serviceRequirePathFromTest = '';
12 | },
13 |
14 | promptingStep: function() {
15 | this.questions.push({ type : 'input',
16 | name : 'serviceName',
17 | message : 'Service Name (dash delimited, leave off -service)',
18 | default : this.serviceName });
19 |
20 | this.questions.push({ type : 'input',
21 | name : 'serviceFolderPath',
22 | message : 'Service Folder Path (relative path, no starting or training slashes)',
23 | default : this.serviceFolderPath });
24 |
25 | var done = this.async();
26 |
27 | var generator = this;
28 |
29 | var handleAnswers = function(answers) {
30 | generator.serviceName = answers.serviceName.toLowerCase();
31 | generator.serviceClassName = generator._.classify(answers.serviceName);
32 | generator.serviceInstanceName = generator._.camelize(generator.serviceName);
33 | generator.serviceFolderPath = answers.serviceFolderPath.toLowerCase();
34 | generator.serviceRequirePathFromTest = getTestRequirePrefix(generator.serviceFolderPath) + 'app/services/' + generator.serviceFolderPath + '/' + generator.serviceName + '-service';
35 |
36 | done();
37 | };
38 |
39 | this.prompt(this.questions, handleAnswers.bind(this));
40 | },
41 |
42 | configuringStep: function() {
43 | },
44 |
45 | defaultStep: function() {
46 | },
47 |
48 | writingStep: function() {
49 | copyService(this);
50 | copyServiceTest(this);
51 | },
52 |
53 | conflictsStep: function() {
54 | },
55 |
56 | installStep: function() {
57 | },
58 |
59 | endStep: function() {
60 | }
61 | });
62 |
63 | function getTestRequirePrefix(serviceFolderPath) {
64 | var requirePrefix = '../../../';
65 |
66 | if(serviceFolderPath.length !== 0) {
67 | var folderCount = (serviceFolderPath.match(/\//g) || []).length + 1;
68 |
69 | for(var i = 0; i < folderCount; i++) {
70 | requirePrefix = '../' + requirePrefix;
71 | }
72 | }
73 |
74 | return requirePrefix;
75 | }
76 |
77 | function copyService(generator) {
78 | var serviceDestination = generator.destinationRoot() +
79 | '/app/services/' +
80 | generator.serviceFolderPath +
81 | '/' +
82 | generator.serviceName.toLowerCase() +
83 | '-service.js';
84 |
85 | copyTemplate(generator, 'app/services/_service.js', serviceDestination);
86 | }
87 |
88 | function copyServiceTest(generator) {
89 | var serviceTestDestination = generator.destinationRoot() +
90 | '/test/spec/services/' +
91 | generator.serviceFolderPath +
92 | '/' +
93 | generator.serviceName.toLowerCase() +
94 | '-service.tests.js';
95 |
96 | copyTemplate(generator, 'test/spec/services/_service.tests.js', serviceTestDestination);
97 | }
98 |
99 | function copyTemplate(generator, template, path) {
100 | if(fs.existsSync(path)) {
101 | console.log('The file "' + path + '" already exists!');
102 | }
103 | else {
104 | generator.template(template, path);
105 | }
106 | }
107 |
--------------------------------------------------------------------------------
/generators/service/templates/app/services/_service.js:
--------------------------------------------------------------------------------
1 |
2 | function <%= serviceClassName %>Service() {
3 | }
4 |
5 | function lookup<%= serviceClassName %>(id) {
6 | return { id: id };
7 | }
8 |
9 | <%= serviceClassName %>Service.prototype = {
10 | lookup<%= serviceClassName %>: lookup<%= serviceClassName %>
11 | };
12 |
13 | var <%= serviceInstanceName %>Service = new <%= serviceClassName %>Service();
14 |
15 | module.exports = <%= serviceInstanceName %>Service;
16 |
--------------------------------------------------------------------------------
/generators/service/templates/test/spec/services/_service.tests.js:
--------------------------------------------------------------------------------
1 |
2 | describe('<%= serviceClassName %>Service Tests', function() {
3 |
4 | var <%= serviceInstanceName %>Service;
5 |
6 | beforeEach(function() {
7 | <%= serviceInstanceName %>Service = require('<%= serviceRequirePathFromTest %>');
8 | });
9 |
10 | describe('lookup<%= serviceClassName %>', function() {
11 |
12 | it('should be a function', function(done) {
13 | expect(<%= serviceInstanceName %>Service.lookup<%= serviceClassName %>).to.be.a('function');
14 | done();
15 | });
16 |
17 | });
18 | });
19 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "generator-express-rest-api",
3 | "version": "1.2.1",
4 | "description": "Yeoman generator for a RESTful API using express, cluster-service, mocha, chai, sinon, and istanbul",
5 | "author": "Tim Walker ",
6 | "license": "MIT",
7 | "scripts": {
8 | "test": "mocha"
9 | },
10 | "repository": {
11 | "type": "git",
12 | "url": "https://github.com/trwalker/generator-express-rest-api.git"
13 | },
14 | "keywords": [
15 | "yo",
16 | "yeoman",
17 | "generator",
18 | "express",
19 | "rest",
20 | "api",
21 | "service"
22 | ],
23 | "bugs": {
24 | "url": "https://github.com/trwalker/generator-express-rest-api/issues"
25 | },
26 | "homepage": "https://github.com/trwalker/generator-express-rest-api",
27 | "dependencies": {
28 | "yeoman-generator": "^0.17.3"
29 | },
30 | "devDependencies": {
31 | "chai": "^1.9.1",
32 | "mocha": "^1.21.4",
33 | "sinon": "^1.10.3"
34 | }
35 | }
36 |
--------------------------------------------------------------------------------
/projectFilesBackup/.idea/workspace.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 |
77 |
78 |
79 |
80 |
81 |
82 |
83 |
84 |
85 |
86 |
87 |
88 |
89 |
90 |
91 |
92 |
93 |
94 |
95 |
96 |
97 |
98 |
99 |
100 |
101 |
102 |
103 |
104 |
105 |
106 |
107 |
108 |
109 |
110 |
111 |
112 |
113 |
114 |
115 |
116 |
117 |
118 |
119 |
120 |
121 |
122 |
123 |
124 |
125 |
126 |
127 |
128 |
129 |
130 |
131 |
132 |
133 |
134 |
135 |
136 |
137 |
138 |
139 |
140 |
141 |
142 |
143 |
144 |
145 |
146 |
147 |
148 |
149 |
150 |
151 |
152 |
153 |
154 |
155 |
156 |
157 |
158 |
159 |
160 |
161 |
162 |
163 |
164 |
165 |
166 |
167 |
168 |
169 |
170 |
171 |
172 |
173 |
174 |
175 |
176 |
177 |
178 |
179 |
180 |
181 |
182 |
183 |
184 |
185 |
186 |
187 |
188 |
189 |
190 |
191 |
192 |
193 |
194 |
195 |
196 |
197 |
198 |
199 |
200 |
201 |
202 |
203 |
204 |
205 |
206 |
207 |
208 |
209 |
210 |
211 |
212 |
213 |
214 |
215 |
216 |
217 |
218 |
219 |
220 |
221 |
222 |
223 |
224 |
225 |
226 |
227 |
228 |
229 |
230 |
231 |
232 |
233 |
234 |
235 |
236 |
237 |
238 |
239 |
240 |
241 |
242 |
243 |
244 |
245 |
246 |
247 |
248 |
249 |
250 |
251 |
252 |
253 |
254 |
255 |
256 |
257 |
258 |
259 |
260 |
261 |
262 |
263 |
264 |
265 | 1412338391155
266 | 1412338391155
267 |
268 |
269 |
270 |
271 |
272 |
273 |
274 |
275 |
276 |
277 |
278 |
279 |
280 |
281 |
282 |
283 |
284 |
285 |
286 |
287 |
288 |
289 |
290 |
291 |
292 |
293 |
294 |
295 |
296 |
297 |
298 |
299 |
300 |
301 |
302 |
303 |
304 |
305 |
306 |
307 |
308 |
309 |
310 |
311 |
312 |
313 |
314 |
315 |
316 |
317 |
318 |
319 |
320 |
321 |
322 |
323 |
324 |
325 |
326 |
327 |
328 |
329 |
330 |
331 |
332 |
333 |
334 |
335 |
336 |
337 |
338 |
339 |
340 |
341 |
342 |
343 |
344 |
345 |
346 |
347 |
348 |
349 |
350 |
351 |
352 |
353 |
354 |
355 |
356 |
357 |
358 |
359 |
360 |
361 |
362 |
363 |
364 |
365 |
366 |
367 |
368 |
369 |
370 |
371 |
372 |
373 |
374 |
375 |
376 |
377 |
378 |
379 |
380 |
381 |
382 |
383 |
384 |
385 |
386 |
387 |
388 |
389 |
390 |
391 |
392 |
393 |
394 |
395 |
396 |
397 |
398 |
399 |
400 |
401 |
402 |
403 |
404 |
405 |
406 |
407 |
408 |
409 |
410 |
411 |
412 |
413 |
414 |
415 |
416 |
417 |
418 |
419 |
420 |
421 |
422 |
423 |
424 |
425 |
426 |
427 |
428 |
429 |
430 |
431 |
432 |
433 |
434 |
435 |
436 |
437 |
438 |
439 |
440 |
441 |
442 |
443 |
444 |
445 |
446 |
447 |
448 |
449 |
450 |
451 |
452 |
453 |
454 |
455 |
456 |
457 |
458 |
459 |
460 |
461 |
462 |
463 |
464 |
465 |
466 |
467 |
468 |
469 |
470 |
471 |
472 |
473 |
474 |
475 |
476 |
477 |
478 |
479 |
480 |
481 |
482 |
483 |
484 |
485 |
486 |
487 |
488 |
489 |
490 |
491 |
492 |
493 |
494 |
495 |
496 |
497 |
498 |
499 |
500 |
501 |
502 |
503 |
504 |
505 |
506 |
507 |
508 |
509 |
510 |
511 |
512 |
513 |
514 |
515 |
516 |
517 |
518 |
519 |
520 |
521 |
522 |
523 |
524 |
525 |
526 |
527 |
528 |
529 |
530 |
531 |
532 |
533 |
534 |
535 |
536 |
537 |
538 |
539 |
540 |
541 |
542 |
543 |
544 |
545 |
546 |
547 |
548 |
549 |
550 |
551 |
552 |
553 |
554 |
555 |
556 |
557 |
558 |
559 |
560 |
561 |
562 |
563 |
564 |
565 |
566 |
567 |
568 |
569 |
570 |
571 |
572 |
573 |
574 |
575 |
576 |
577 |
578 |
579 |
580 |
581 |
582 |
583 |
584 |
585 |
586 |
587 |
588 |
589 |
590 |
591 |
592 |
593 |
594 |
595 |
596 |
597 |
598 |
599 |
600 |
601 |
602 |
603 |
604 |
605 |
--------------------------------------------------------------------------------
/test/app/index.tests.js:
--------------------------------------------------------------------------------
1 |
2 | describe('App Generator Tests', function() {
3 |
4 | var appGenerator;
5 |
6 | beforeEach(function() {
7 | appGenerator = require('../../generators/app/index');
8 | });
9 |
10 | describe('generator', function() {
11 |
12 | it('should be defined', function(done) {
13 | expect(appGenerator).to.exist;
14 |
15 | done();
16 | });
17 |
18 | });
19 | });
20 |
--------------------------------------------------------------------------------
/test/mocha.opts:
--------------------------------------------------------------------------------
1 | -R spec
2 | -u bdd
3 | --recursive
4 |
--------------------------------------------------------------------------------
/test/tests.initialize.js:
--------------------------------------------------------------------------------
1 |
2 | beforeEach(function() {
3 | global.expect = require('chai').expect;
4 | global.sinon = require('sinon');
5 | });
6 |
--------------------------------------------------------------------------------