diff --git a/.npmignore b/.npmignore
index ec6ff802d..c823223d9 100644
--- a/.npmignore
+++ b/.npmignore
@@ -1,2 +1,3 @@
angular-fullstack-deps
test
+.idea
diff --git a/angular-fullstack-deps b/angular-fullstack-deps
index 29cd1a011..7c3662328 160000
--- a/angular-fullstack-deps
+++ b/angular-fullstack-deps
@@ -1 +1 @@
-Subproject commit 29cd1a01184213b1c4a278d0f98b9a46ef000c7d
+Subproject commit 7c3662328ffd32f819ae381825399ed578c11f98
diff --git a/app/generator.js b/app/generator.js
index 5bb5bc92d..cd5e5d1be 100644
--- a/app/generator.js
+++ b/app/generator.js
@@ -144,7 +144,9 @@ export default class Generator extends Base {
this.scriptExt = answers.transpiler === 'ts' ? 'ts' : 'js';
this.templateExt = answers.markup;
- this.styleExt = answers.stylesheet === 'sass' ? 'scss' : answers.stylesheet;
+
+ var styleExt = {sass: 'scss', stylus: 'styl'}[answers.stylesheet];
+ this.styleExt = styleExt ? styleExt : answers.stylesheet;
cb();
}.bind(this));
diff --git a/app/templates/Gruntfile(grunt).js b/app/templates/Gruntfile(grunt).js
index 87846d184..5f12dcfce 100644
--- a/app/templates/Gruntfile(grunt).js
+++ b/app/templates/Gruntfile(grunt).js
@@ -161,7 +161,7 @@ module.exports = function (grunt) {
},
src: ['<%%= yeoman.server %>/**/*.{spec,integration}.js']
},
- all: ['<%%= yeoman.client %>/{app,components}/**/!(*.spec|*.mock).js'],
+ all: ['<%%= yeoman.client %>/{app,components}/**/!(*.spec|*.mock|app.constant).js'],
test: {
src: ['<%%= yeoman.client %>/{app,components}/**/*.{spec,mock}.js']
}
@@ -424,7 +424,8 @@ module.exports = function (grunt) {
dest: '<%%= yeoman.dist %>',
src: [
'package.json',
- '<%%= yeoman.server %>/**/*'
+ '<%%= yeoman.server %>/**/*',
+ '!<%%= yeoman.server %>/config/local.env.sample.js'
]
}]
},
@@ -636,7 +637,7 @@ module.exports = function (grunt) {
files: [{
expand: true,
cwd: '<%%= yeoman.server %>',
- src: ['**/*.{js,json}'],
+ src: ['**/*.js'],
dest: '<%%= yeoman.dist %>/<%%= yeoman.server %>'
}]
}
diff --git a/app/templates/_bower.json b/app/templates/_bower.json
index b0de0c559..59b5007ca 100644
--- a/app/templates/_bower.json
+++ b/app/templates/_bower.json
@@ -12,7 +12,7 @@
"angular-cookies": "~1.4.0",
"angular-sanitize": "~1.4.0",<% if (filters.ngroute) { %>
"angular-route": "~1.4.0",<% } if (filters.uibootstrap) { %>
- "angular-bootstrap": "~0.13.0",<% } %>
+ "angular-bootstrap": "~1.1.2",<% } %>
"font-awesome": ">=4.1.0",
"lodash": "~2.4.1"<% if(filters.socketio) { %>,
"angular-socket-io": "~0.7.0"<% } if (filters.uirouter) { %>,
diff --git a/app/templates/_package.json b/app/templates/_package.json
index 13c47e4e3..b68dc4c34 100644
--- a/app/templates/_package.json
+++ b/app/templates/_package.json
@@ -150,8 +150,8 @@
"karma-ng-jade2js-preprocessor": "^0.2.0",<% } else { %>
"karma-ng-html2js-preprocessor": "~0.2.0",<% } %>
"karma-spec-reporter": "~0.0.20",
- "sinon-chai": "^2.8.0",<% if (filters.mocha) { %>
- "mocha": "^2.2.5",
+ "sinon-chai": "^2.8.0",
+ "mocha": "^2.2.5",<% if (filters.mocha) { %>
"karma-mocha": "^0.2.0",
"karma-chai-plugins": "^0.6.0",<% } if (filters.jasmine) { %>
"jasmine-core": "^2.3.4",
diff --git a/app/templates/client/app/app(less).less b/app/templates/client/app/app(less).less
index 9cfcfdb16..db107e3e5 100644
--- a/app/templates/client/app/app(less).less
+++ b/app/templates/client/app/app(less).less
@@ -24,7 +24,6 @@
}
<% } %>
// injector
-@import 'account/login/login.less';
@import 'admin/admin.less';
@import 'main/main.less';
// endinjector
diff --git a/app/templates/client/app/app(sass).scss b/app/templates/client/app/app(sass).scss
index e20f3f0ad..fc95c6bdc 100644
--- a/app/templates/client/app/app(sass).scss
+++ b/app/templates/client/app/app(sass).scss
@@ -24,7 +24,6 @@
<% } %>
// Component styles are injected through grunt
// injector
-@import 'account/login/login.scss';
@import 'admin/admin.scss';
@import 'main/main.scss';
// endinjector
diff --git a/app/templates/client/app/app(stylus).styl b/app/templates/client/app/app(stylus).styl
index de156ca97..ffb293544 100644
--- a/app/templates/client/app/app(stylus).styl
+++ b/app/templates/client/app/app(stylus).styl
@@ -45,7 +45,6 @@
<% } %>
// Component styles are injected through grunt
// injector
-@import "account/login/login"
@import "admin/admin"
@import "main/main"
// endinjector
diff --git a/app/templates/client/app/main/main(html).html b/app/templates/client/app/main/main(html).html
index 0ee458852..1c413a22a 100644
--- a/app/templates/client/app/main/main(html).html
+++ b/app/templates/client/app/main/main(html).html
@@ -11,7 +11,7 @@
'Allo, 'Allo!
<% if (filters.socketio) { %>
diff --git a/app/templates/client/app/main/main(jade).jade b/app/templates/client/app/main/main(jade).jade
index 3191ca2d2..5a732f9dc 100644
--- a/app/templates/client/app/main/main(jade).jade
+++ b/app/templates/client/app/main/main(jade).jade
@@ -10,7 +10,7 @@ header#banner.hero-unit
h1.page-header Features:
ul.nav.nav-tabs.nav-stacked.col-md-4.col-lg-4.col-sm-6(ng-repeat='thing in main.awesomeThings')
li
- a(href='#', tooltip='{{thing.info}}')
+ a(href='#', uib-tooltip='{{thing.info}}')
| {{thing.name}}<% if (filters.socketio) { %>
button.close(type='button', ng-click='main.deleteThing(thing)') ×<% } %><% if (filters.socketio) { %>
diff --git a/app/templates/client/components/modal(uibootstrap)/modal.service.js b/app/templates/client/components/modal(uibootstrap)/modal.service.js
index d878f69dd..d7807e6b5 100644
--- a/app/templates/client/components/modal(uibootstrap)/modal.service.js
+++ b/app/templates/client/components/modal(uibootstrap)/modal.service.js
@@ -1,19 +1,19 @@
'use strict';
angular.module('<%= scriptAppName %>')
- .factory('Modal', function($rootScope, $modal) {
+ .factory('Modal', function($rootScope, $uibModal) {
/**
* Opens a modal
* @param {Object} scope - an object to be merged with modal's scope
* @param {String} modalClass - (optional) class(es) to be applied to the modal
- * @return {Object} - the instance $modal.open() returns
+ * @return {Object} - the instance $uibModal.open() returns
*/
function openModal(scope = {}, modalClass = 'modal-default') {
var modalScope = $rootScope.$new();
angular.extend(modalScope, scope);
- return $modal.open({
+ return $uibModal.open({
templateUrl: 'components/modal/modal.html',
windowClass: modalClass,
scope: modalScope
diff --git a/app/templates/client/components/navbar/navbar(html).html b/app/templates/client/components/navbar/navbar(html).html
index 8337fb6c2..4b6692d36 100644
--- a/app/templates/client/components/navbar/navbar(html).html
+++ b/app/templates/client/components/navbar/navbar(html).html
@@ -9,7 +9,7 @@
<%= lodash.slugify(lodash.humanize(appname)) %>
-
+
- ui-sref-active="active"<% } else { %>ng-class="{active: nav.isActive(item.link)}"<% } %>>
ui-sref="{{item.state}}"<% } else { %>ng-href="{{item.link}}"<% } %>>{{item.title}}
diff --git a/app/templates/client/components/navbar/navbar(jade).jade b/app/templates/client/components/navbar/navbar(jade).jade
index abce652ff..d8a86b647 100644
--- a/app/templates/client/components/navbar/navbar(jade).jade
+++ b/app/templates/client/components/navbar/navbar(jade).jade
@@ -8,7 +8,7 @@ div.navbar.navbar-default.navbar-static-top(ng-controller='NavbarController')
span.icon-bar
a.navbar-brand(href='/') <%= lodash.slugify(lodash.humanize(appname)) %>
- div#navbar-main.navbar-collapse.collapse(collapse='nav.isCollapsed')
+ div#navbar-main.navbar-collapse.collapse(uib-collapse='nav.isCollapsed')
ul.nav.navbar-nav
li(ng-repeat='item in nav.menu', <% if (filters.uirouter) { %>ui-sref-active='active'<% } else { %>ng-class='{active: nav.isActive(item.link)}'<% } %>)
a(<% if (filters.uirouter) { %>ui-sref='{{item.state}}'<% } else { %>ng-href='{{item.link}}'<% } %>) {{item.title}}<% if (filters.auth) { %>
diff --git a/app/templates/client/tslint.json(ts) b/app/templates/client/tslint.json(ts)
index e0e318d21..8870b5fe1 100644
--- a/app/templates/client/tslint.json(ts)
+++ b/app/templates/client/tslint.json(ts)
@@ -27,7 +27,6 @@
"no-shadowed-variable": true,
"no-string-literal": true,
"no-switch-case-fall-through": true,
- "no-trailing-comma": true,
"no-trailing-whitespace": true,
"no-unused-expression": true,
"no-unused-variable": true,
@@ -42,6 +41,7 @@
"quotemark": [true, "single"],
"radix": true,
"semicolon": true,
+ "trailing-comma": false,
"triple-equals": [true, "allow-null-check"],
"typedef-whitespace": [true, {
"call-signature": "nospace",
diff --git a/app/templates/gulpfile.babel(gulp).js b/app/templates/gulpfile.babel(gulp).js
index 7f9fe93ee..a511442c1 100644
--- a/app/templates/gulpfile.babel(gulp).js
+++ b/app/templates/gulpfile.babel(gulp).js
@@ -218,7 +218,26 @@ gulp.task('inject:js', () => {
transform: (filepath) => ''
}))
.pipe(gulp.dest(clientPath));
-});
+});<% if(filters.ts) { %>
+
+gulp.task('inject:tsconfig', () => {
+ let src = gulp.src([
+ `${clientPath}/**/!(*.spec|*.mock).ts`,
+ `!${clientPath}/bower_components/**/*`,
+ `${clientPath}/typings/**/*.d.ts`
+ ], {read: false})
+ .pipe(plugins.sort());
+
+ return gulp.src('./tsconfig.client.json')
+ .pipe(plugins.inject(src, {
+ starttag: '"files": [',
+ endtag: ']',
+ transform: (filepath, file, i, length) => {
+ return `"${filepath.substr(1)}"${i + 1 < length ? ',' : ''}`;
+ }
+ }))
+ .pipe(gulp.dest('./'));
+});<% } %>
gulp.task('inject:css', () => {
return gulp.src(paths.client.mainView)
@@ -280,7 +299,7 @@ gulp.task('copy:constant', () => {
})
let tsProject = plugins.typescript.createProject('./tsconfig.client.json');
-gulp.task('transpile:client', ['constant', 'copy:constant'], () => {
+gulp.task('transpile:client', ['inject:tsconfig', 'constant', 'copy:constant'], () => {
return tsProject.src()
.pipe(plugins.sourcemaps.init())
.pipe(plugins.typescript(tsProject)).js
@@ -312,7 +331,11 @@ gulp.task('transpile:server', () => {
gulp.task('lint:scripts', cb => runSequence(['lint:scripts:client', 'lint:scripts:server'], cb));
gulp.task('lint:scripts:client', () => {
- return gulp.src(_.union(paths.client.scripts, _.map(paths.client.test, blob => '!' + blob)))
+ return gulp.src(_.union(
+ paths.client.scripts,
+ _.map(paths.client.test, blob => '!' + blob),
+ [`!${clientPath}/app/app.constant.<%= scriptExt %>`]
+ ))
.pipe(lintClientScripts());
});
@@ -373,15 +396,19 @@ gulp.task('watch', () => {
.pipe(plugins.livereload());
});
- plugins.watch(paths.client.views)
+ plugins.watch(paths.client.views)<% if(filters.jade) { %>
+ .pipe(plugins.jade())
+ .pipe(gulp.dest('.tmp'))<% } %>
.pipe(plugins.plumber())
- .pipe(plugins.livereload());
+ .pipe(plugins.livereload());<% if(filters.babel) { %>
plugins.watch(paths.client.scripts) //['inject:js']
.pipe(plugins.plumber())
.pipe(transpileClient())
.pipe(gulp.dest('.tmp'))
- .pipe(plugins.livereload());
+ .pipe(plugins.livereload());<% } %><% if(filters.ts) { %>
+
+ gulp.watch(paths.client.scripts, ['inject:tsconfig', 'lint:scripts:client', 'transpile:client']);<% } %>
plugins.watch(_.union(paths.server.scripts, testFiles))
.pipe(plugins.plumber())
@@ -393,7 +420,7 @@ gulp.task('watch', () => {
gulp.task('serve', cb => {
runSequence(['clean:tmp', 'constant'<% if(filters.ts) { %>, 'tsd'<% } %>],
- ['lint:scripts', 'inject'<% if(filters.jade) { %>, 'jade'<% } %>],
+ ['lint:scripts', 'inject'<% if(filters.jade) { %>, 'jade'<% } %><% if(filters.ts) { %>, 'inject:tsconfig'<% } %>],
['wiredep:client'],
['transpile:client', 'styles'],
['start:server', 'start:client'],
diff --git a/app/templates/server/api/user(auth)/user.model(sequelizeModels).js b/app/templates/server/api/user(auth)/user.model(sequelizeModels).js
index 500f6b81f..e2c625378 100644
--- a/app/templates/server/api/user(auth)/user.model(sequelizeModels).js
+++ b/app/templates/server/api/user(auth)/user.model(sequelizeModels).js
@@ -38,10 +38,10 @@ module.exports = function(sequelize, DataTypes) {
},
provider: DataTypes.STRING,
salt: DataTypes.STRING<% if (filters.oauth) { %>,<% if (filters.facebookAuth) { %>
- facebook: DataTypes.TEXT,<% } %><% if (filters.twitterAuth) { %>
- twitter: DataTypes.TEXT,<% } %><% if (filters.googleAuth) { %>
- google: DataTypes.TEXT,<% } %>
- github: DataTypes.TEXT<% } %>
+ facebook: DataTypes.JSON,<% } %><% if (filters.twitterAuth) { %>
+ twitter: DataTypes.JSON,<% } %><% if (filters.googleAuth) { %>
+ google: DataTypes.JSON,<% } %>
+ github: DataTypes.JSON<% } %>
}, {
diff --git a/app/templates/server/auth(auth)/facebook(facebookAuth)/passport.js b/app/templates/server/auth(auth)/facebook(facebookAuth)/passport.js
index 438e4c003..f8395575b 100644
--- a/app/templates/server/auth(auth)/facebook(facebookAuth)/passport.js
+++ b/app/templates/server/auth(auth)/facebook(facebookAuth)/passport.js
@@ -13,9 +13,9 @@ export function setup(User, config) {
},
function(accessToken, refreshToken, profile, done) {
<% if (filters.mongooseModels) { %>User.findOneAsync({<% }
- if (filters.sequelizeModels) { %>User.find({<% } %>
+ if (filters.sequelizeModels) { %>User.find({where:{<% } %>
'facebook.id': profile.id
- })
+ <% if (filters.sequelizeModels) { %>}<% } %>})
.then(user => {
if (user) {
return done(null, user);
diff --git a/app/templates/server/auth(auth)/google(googleAuth)/passport.js b/app/templates/server/auth(auth)/google(googleAuth)/passport.js
index 29f18d4ba..d1bff242a 100644
--- a/app/templates/server/auth(auth)/google(googleAuth)/passport.js
+++ b/app/templates/server/auth(auth)/google(googleAuth)/passport.js
@@ -9,9 +9,9 @@ export function setup(User, config) {
},
function(accessToken, refreshToken, profile, done) {
<% if (filters.mongooseModels) { %>User.findOneAsync({<% }
- if (filters.sequelizeModels) { %>User.find({<% } %>
+ if (filters.sequelizeModels) { %>User.find({where:{<% } %>
'google.id': profile.id
- })
+ <% if (filters.sequelizeModels) { %>}<% } %>})
.then(user => {
if (user) {
return done(null, user);
diff --git a/app/templates/server/auth(auth)/twitter(twitterAuth)/passport.js b/app/templates/server/auth(auth)/twitter(twitterAuth)/passport.js
index 43a7752ed..4bbfb16bf 100644
--- a/app/templates/server/auth(auth)/twitter(twitterAuth)/passport.js
+++ b/app/templates/server/auth(auth)/twitter(twitterAuth)/passport.js
@@ -9,9 +9,9 @@ export function setup(User, config) {
},
function(token, tokenSecret, profile, done) {
<% if (filters.mongooseModels) { %>User.findOneAsync({<% }
- if (filters.sequelizeModels) { %>User.find({<% } %>
- 'twitter.id_str': profile.id
- })
+ if (filters.sequelizeModels) { %>User.find({where:{<% } %>
+ 'twitter.id': profile.id
+ <% if (filters.sequelizeModels) { %>}<% } %>})
.then(user => {
if (user) {
return done(null, user);
diff --git a/package.json b/package.json
index d2cd698aa..382e981b5 100644
--- a/package.json
+++ b/package.json
@@ -1,6 +1,6 @@
{
"name": "generator-angular-fullstack",
- "version": "3.3.0-beta.0",
+ "version": "3.3.0",
"description": "Yeoman generator for creating MEAN stack applications, using MongoDB, Express, AngularJS, and Node",
"keywords": [
"yeoman-generator",
diff --git a/readme.md b/readme.md
index 495ea7527..e7668dd43 100644
--- a/readme.md
+++ b/readme.md
@@ -16,9 +16,9 @@ Source code: https://github.com/DaftMonk/fullstack-demo
## Usage
-Install `yo`, `grunt-cli`, `bower`, and `generator-angular-fullstack`:
+Install `yo`, `grunt-cli`/`gulp-cli`, `bower`, and `generator-angular-fullstack`:
```
-npm install -g yo grunt-cli bower generator-angular-fullstack
+npm install -g yo grunt-cli gulp-cli bower generator-angular-fullstack
```
Make a new directory, and `cd` into it:
@@ -135,7 +135,7 @@ Options:
-h, --help # Print the generator's options and usage
--skip-cache # Do not remember prompt answers Default: false
--route # URL for the endpoint
- --models # Specify which model(s) to use
+ --models # Specify which model(s) to use Options: mongoose, sequelize
--endpointDirectory # Parent directory for enpoints
Arguments:
@@ -297,7 +297,7 @@ To make your deployment process easier consider using [grunt-build-control](http
**Pushing Updates**
- grunt
+ grunt build
Commit and push the resulting build, located in your dist folder: