Remove gulp tasks, and fix style issues

This commit is contained in:
Timothy Warren 2016-05-06 13:21:00 -04:00
parent edd7dd8492
commit 0eb0d18755
7 changed files with 115 additions and 287 deletions

52
.eslintrc.js Normal file
View File

@ -0,0 +1,52 @@
/*
* Configuration values for eslint
*/
module.exports = {
env: {
node: true,
es6: true,
},
// Each rule has an error level (0-2), and some have extra parameters
// 0 turns a rule off
// 1 makes a rule give a warning
// 2 makes a rule fail linting
rules: {
'linebreak-style': [2, 'unix'], // Only unix line endings
'arrow-parens': [2, 'always'], // No parens on arrow functions with one param
'no-console': [1], // Avoid using console methods
'no-constant-condition': [1],
'no-extra-semi': [1], // Enliminate extra semicolons
'no-func-assign': [1],
'no-obj-calls': [2],
'no-unexpected-multiline': [2], // Catch syntax errors due to automatic semicolon insertion
'no-unneeded-ternary': [2], // Avoid redundant ternary expressions
radix: [2], // Require radix parameter on parseInt
'no-with': [2], // No use of with construct
'no-eval': [2], // No use of eval
'no-unreachable': [1], // Avoid code that is not reachable
'no-irregular-whitespace': [1], // Highlight whitespace that isn't a tab or space
'no-new-wrappers': [2], // Avoid using primitive constructors
'no-new-func': [2], // Avoid Function constructor eval
curly: [2, 'multi-line'], // Require braces for if,for,while,do contructs that are not on the same line
'no-implied-eval': [2], // Avoid camoflauged eval
'no-invalid-this': [2],
'constructor-super': [2],
'no-dupe-args': [2], // Disallow functions to have more than one parameter with the same name
'no-dupe-keys': [2], // Disaalow objects to have more than one property with the same name
'no-dupe-class-members': [2], // Disallow classes to have more than one method/memeber with the same name
'no-this-before-super': [2],
'prefer-arrow-callback': [1], // Prefer arrow functions for callbacks
'no-var': [2], // Use let or const instead of var
'valid-jsdoc': [1],
semi: [2, 'always'], // Require use of semicolons
strict: [2, 'global'], // have a global 'use strict' in every code file
'callback-return': [1], // return when invoking a callback
'object-shorthand': [1, 'methods'], // Prefer shorthand for functions in object literals/classes, but avoid property shorthand
'prefer-template': [1], // Prefer template strings eg. `Hello ${name}`, to string concatenation
'no-case-declarations': [2], // Don't define variables in switch labels
'no-const-assign': [2], // Highlight instances where assigning to const declaration
'no-new-symbol': [2], // Symbol is not a constructor, don't use the new keyword
'no-unused-labels': [2], // Error on labels in code that aren't used
},
};

View File

@ -44,7 +44,6 @@
}, },
"disallowTrailingWhitespace": true, "disallowTrailingWhitespace": true,
"disallowYodaConditions": true, "disallowYodaConditions": true,
"esnext": true,
"requireBlocksOnNewline": 1, "requireBlocksOnNewline": 1,
"requireCamelCaseOrUpperCaseIdentifiers": true, "requireCamelCaseOrUpperCaseIdentifiers": true,
"requireCapitalizedConstructors": true, "requireCapitalizedConstructors": true,

14
app/config/database.js Normal file
View File

@ -0,0 +1,14 @@
'use strict';
const knexfile = require('../../knexfile');
const knexConfig = knexfile[process.env.NODE_ENV];
const knexConn = knexConfig.connection;
const params = {
driver: knexConfig.client,
connection: (knexConfig.client == "sqlite3") ? knexConn.filename : knexConn,
};
const nodeQuery = require('ci-node-query')(params);
module.exports = nodeQuery.getQuery();

View File

@ -6,8 +6,8 @@
*/ */
module.exports = { module.exports = {
get_db_type(knex) { getDbType(knex) {
switch(knex.client.config.client) { switch (knex.client.config.client) {
case 'postgresql': case 'postgresql':
case 'postgres': case 'postgres':
case 'pg': case 'pg':
@ -18,28 +18,28 @@ module.exports = {
} }
}, },
pg_timestamp_update_function () { pgTimestampUpdateFunction() {
return `CREATE OR REPLACE FUNCTION progblog_update_modified_column() return `CREATE OR REPLACE FUNCTION progblog_update_modified_column()
RETURNS TRIGGER AS $$ RETURNS TRIGGER AS $$
BEGIN BEGIN
NEW.updated_at = now(); NEW.updated_at = now();
RETURN NEW; RETURN NEW;
END; END;
$$ language 'plpgsql';`; $$ language 'plpgsql';`;
}, },
pg_create_timestamp_update_trigger(table) { pgCreateTimestampUpdateTrigger(table) {
return `CREATE TRIGGER update_${table}_modtime return `CREATE TRIGGER update_${table}_modtime
BEFORE UPDATE ON "${table}" BEFORE UPDATE ON "${table}"
FOR EACH ROW FOR EACH ROW
EXECUTE PROCEDURE progblog_update_modified_column();`; EXECUTE PROCEDURE progblog_update_modified_column();`;
}, },
pg_delete_timestamp_update_trigger(table) { pgDeleteTimestampUpdateTrigger(table) {
return `DROP TRIGGER IF EXISTS update_${table}_modtime ON "${table}";`; return `DROP TRIGGER IF EXISTS update_${table}_modtime ON "${table}";`;
}, },
sqlite3_create_timestamp_update_trigger(table) { sqlite3CreateTimestampUpdateTrigger(table) {
return `CREATE TRIGGER IF NOT EXISTS [UpdateModified] return `CREATE TRIGGER IF NOT EXISTS [UpdateModified]
BEFORE UPDATE ON "${table}" BEFORE UPDATE ON "${table}"
FOR EACH ROW FOR EACH ROW
@ -48,7 +48,7 @@ module.exports = {
END`; END`;
}, },
sqlite3_delete_timestamp_update_trigger() { sqlite3DeleteTimestampUpdateTrigger() {
return `DROP TRIGGER IF EXISTS [UpdateModified]`; return `DROP TRIGGER IF EXISTS [UpdateModified]`;
}, },
}; };

View File

@ -1,246 +0,0 @@
'use strict';
const apidoc = require('gulp-apidoc'),
documentation = require('gulp-documentation'),
eslint = require('gulp-eslint'),
gulp = require('gulp'),
istanbul = require('gulp-istanbul'),
jscs = require('gulp-jscs'),
mocha = require('gulp-mocha'),
pipe = require('gulp-pipe'),
nsp = require('gulp-nsp');
/*
* Path(s) to all source files
*/
const SRC_FILES = [
'app/base/**/*.js',
'app/config/**/*.js',
'app/controllers/**/*.js',
'app/helpers/**/*.js',
'app/models/**/*.js',
'app/*.js',
];
/*
* Path to unit test files
*/
const UNIT_TEST_FILES = ['test/unit/**/*_test.js'];
/*
* Path to integration test files
*/
const INTEGRATION_TEST_FILES = ['test/integration/**/*_test.js'];
/*
* Path(s) to all test files
*/
const TEST_FILES = ['test/**/*_test.js'];
/*
* Configuration values for eslint
*/
const ESLINT_SETTINGS = {
env: {
node: true,
es6: true,
},
// Each rule has an error level (0-2), and some have extra parameters
// 0 turns a rule off
// 1 makes a rule give a warning
// 2 makes a rule fail linting
rules: {
'linebreak-style': [2, 'unix'], // Only unix line endings
'arrow-parens': [2, 'always'], // No parens on arrow functions with one param
'no-console': [1], // Avoid using console methods
'no-constant-condition': [1],
'no-extra-semi': [1], // Enliminate extra semicolons
'no-func-assign': [1],
'no-obj-calls': [2],
'no-unexpected-multiline': [2], // Catch syntax errors due to automatic semicolon insertion
'no-unneeded-ternary': [2], // Avoid redundant ternary expressions
radix: [2], // Require radix parameter on parseInt
'no-with': [2], // No use of with construct
'no-eval': [2], // No use of eval
'no-unreachable': [1], // Avoid code that is not reachable
'no-irregular-whitespace': [1], // Highlight whitespace that isn't a tab or space
'no-new-wrappers': [2], // Avoid using primitive constructors
'no-new-func': [2], // Avoid Function constructor eval
curly: [2, 'multi-line'], // Require braces for if,for,while,do contructs that are not on the same line
'no-implied-eval': [2], // Avoid camoflauged eval
'no-invalid-this': [2],
'constructor-super': [2],
'no-dupe-args': [2], // Disallow functions to have more than one parameter with the same name
'no-dupe-keys': [2], // Disaalow objects to have more than one property with the same name
'no-dupe-class-members': [2], // Disallow classes to have more than one method/memeber with the same name
'no-this-before-super': [2],
'prefer-arrow-callback': [1], // Prefer arrow functions for callbacks
'no-var': [2], // Use let or const instead of var
'valid-jsdoc': [1],
semi: [2, 'always'], // Require use of semicolons
strict: [2, 'global'], // have a global 'use strict' in every code file
'callback-return': [1], // return when invoking a callback
'object-shorthand': [1, 'methods'], // Prefer shorthand for functions in object literals/classes, but avoid property shorthand
'prefer-template': [1], // Prefer template strings eg. `Hello ${name}`, to string concatenation
'no-case-declarations': [2], // Don't define variables in switch labels
'no-const-assign': [2], // Highlight instances where assigning to const declaration
'no-new-symbol': [2], // Symbol is not a constructor, don't use the new keyword
'no-unused-labels': [2], // Error on labels in code that aren't used
},
};
/*
* Configuration values for mocha
*/
const MOCHA_SETTINGS = {
ui: 'tdd',
bail: true,
slow: 1000,
timeout: 5000,
};
/*
* Check syntax and style of test/miscellaneous files
*/
gulp.task('lint-tests', () => {
const LINT_TESTS_FILES = TEST_FILES.concat([
'gulpfile.js',
'server.js',
'migrations/*.js',
]);
// eslint
pipe(gulp.src(LINT_TESTS_FILES), [
eslint(ESLINT_SETTINGS),
eslint.format(),
eslint.failAfterError(),
]);
// JSCS rules are defined in /.jscsrc
pipe(gulp.src(['test/**/*.js', 'gulpfile.js']), [
jscs(),
jscs.reporter(),
]);
});
/*
* Check syntax and style of source files
*/
gulp.task('lint-src', () => {
// eslint
pipe(gulp.src(SRC_FILES), [
eslint(ESLINT_SETTINGS),
eslint.format(),
eslint.failAfterError(),
]);
// JSCS
// JSCS rules are defined in /.jscsrc
pipe(gulp.src(SRC_FILES), [
jscs(),
jscs.reporter(),
]);
});
/*
* Run all lint tasks
*/
gulp.task('lint', ['lint-src', 'lint-tests']);
/*
* Create internal method documentation of source files
*/
gulp.task('src-docs', () => {
pipe(gulp.src(SRC_FILES), [
documentation({
format: 'html',
}),
gulp.dest('public/generated/docs'),
]);
});
/*
* Create api documentation from source files
*/
gulp.task('api-docs', (done) => {
apidoc({
src: 'app/',
dest: 'public/generated/api-docs/',
}, done);
});
/*
* Run all documentation generation tasks
*/
gulp.task('docs', ['src-docs', 'api-docs']);
/*
* Run integration tests
*/
gulp.task('integration-test', ['lint'], () => {
return gulp.src(INTEGRATION_TEST_FILES)
.pipe(mocha(MOCHA_SETTINGS));
});
/*
* Run unit tests
*/
gulp.task('unit-test', ['lint'], () => {
return gulp.src(UNIT_TEST_FILES)
.pipe(mocha(MOCHA_SETTINGS));
});
/*
* Run all tests
*/
gulp.task('test', ['lint'], () => {
return gulp.src(TEST_FILES)
.pipe(mocha(MOCHA_SETTINGS));
});
/*
* Run hooks for istanbul coverage generation
*/
gulp.task('pre-coverage', () => {
return pipe(gulp.src(SRC_FILES), [
istanbul(),
istanbul.hookRequire(),
]);
});
/*
* Run unit tests and generate code coverage
*
* Does not run integration tests
*/
gulp.task('coverage', ['lint', 'pre-coverage'], () => {
return pipe(gulp.src(UNIT_TEST_FILES), [
mocha(MOCHA_SETTINGS),
istanbul.writeReports({
dir: 'public/generated/coverage',
reporters:['clover', 'lcov', 'lcovonly', 'html', 'text'],
}),
]);
});
/*
* Check dependencies for known security vulnerabilites
*/
gulp.task('audit', (cb) => {
nsp({
package: `${__dirname}/package.json`,
}, cb);
});
/*
* Run all tasks
*/
gulp.task('default', [
'audit',
'lint',
'docs',
'coverage',
]);
// End of gulpfile.js

View File

@ -3,7 +3,7 @@
const helpers = require('../app/migration_helpers'); const helpers = require('../app/migration_helpers');
exports.up = function(knex, Promise) { exports.up = function(knex, Promise) {
const dbType = helpers.get_db_type(knex); const dbType = helpers.getDbType(knex);
// Defer has the promise resulting from creating the initial tables // Defer has the promise resulting from creating the initial tables
let defer = knex.schema.createTableIfNotExists('users', (table) => { let defer = knex.schema.createTableIfNotExists('users', (table) => {
@ -40,33 +40,33 @@ exports.up = function(knex, Promise) {
if ('pg' === dbType) { if ('pg' === dbType) {
// Create the function to update // Create the function to update
return knex.schema.raw(helpers.pg_timestamp_update_function()) return knex.schema.raw(helpers.pgTimestampUpdateFunction())
// Create the tables // Create the tables
.then(() => defer) .then(() => defer)
// Add trigger for tables // Add trigger for tables
.then(() => knex.schema.raw(helpers.pg_create_timestamp_update_trigger('users'))) .then(() => knex.schema.raw(helpers.pgCreateTimestampUpdateTrigger('users')))
.then(() => knex.schema.raw(helpers.pg_create_timestamp_update_trigger('posts'))); .then(() => knex.schema.raw(helpers.pgCreateTimestampUpdateTrigger('posts')));
} else if ('sqlite3' === dbType) { } else if ('sqlite3' === dbType) {
return defer.then(() => knex.schema.raw(helpers.sqlite3_create_timestamp_update_trigger('users'))) return defer.then(() => knex.schema.raw(helpers.sqlite3CreateTimestampUpdateTrigger('users')))
.then(() => knex.schema.raw(helpers.sqlite3_create_timestamp_update_trigger('posts'))); .then(() => knex.schema.raw(helpers.sqlite3CreateTimestampUpdateTrigger('posts')));
} else { } else {
return defer; return defer;
} }
}; };
exports.down = function(knex, Promise) { exports.down = function(knex, Promise) {
const dbType = helpers.get_db_type(knex); const dbType = helpers.getDbType(knex);
let defer = knex.schema.dropTableIfExists('posts') let defer = knex.schema.dropTableIfExists('posts')
.then(() => knex.schema.dropTableIfExists('users')); .then(() => knex.schema.dropTableIfExists('users'));
if ('pg' === dbType) { if ('pg' === dbType) {
return knex.schema.raw(helpers.pg_delete_timestamp_update_trigger('users')) return knex.schema.raw(helpers.pgDeleteTimestampUpdateTrigger('users'))
.then(() => knex.schema.raw(helpers.pg_delete_timestamp_update_trigger('posts'))) .then(() => knex.schema.raw(helpers.pgDeleteTimestampUpdateTrigger('posts')))
.then(() => defer); .then(() => defer);
} else if ('sqlite3' === dbType) { } else if ('sqlite3' === dbType) {
return knex.schema.raw(helpers.sqlite3_delete_timestamp_update_trigger('users')) return knex.schema.raw(helpers.sqlite3DeleteTimestampUpdateTrigger('users'))
.then(() => knex.schema.raw(helpers.sqlite3_delete_timestamp_update_trigger('posts'))) .then(() => knex.schema.raw(helpers.sqlite3DeleteTimestampUpdateTrigger('posts')))
.then(() => defer); .then(() => defer);
} else { } else {
return defer; return defer;

View File

@ -3,12 +3,12 @@
"dependencies": { "dependencies": {
"axios": "^0.9.1", "axios": "^0.9.1",
"body-parser": "~1.13.2", "body-parser": "~1.13.2",
"ci-node-query": "^3.1.0", "ci-node-query": "^4.0.0",
"cookie-parser": "~1.3.5", "cookie-parser": "~1.3.5",
"debug": "~2.2.0", "debug": "~2.2.0",
"dotenv": "^2.0.0", "dotenv": "^2.0.0",
"errors": "^0.3.0", "errors": "^0.3.0",
"eslint": "^1.10.3", "eslint": "^2.9.0",
"express": "4.*", "express": "4.*",
"express-handlebars": "^3.0.0", "express-handlebars": "^3.0.0",
"express-negotiate": "0.0.5", "express-negotiate": "0.0.5",
@ -17,32 +17,32 @@
"glob": "^6.0.4", "glob": "^6.0.4",
"helmet": "^1.1.0", "helmet": "^1.1.0",
"highlight.js": "^9.1.0", "highlight.js": "^9.1.0",
"jscs": "^2.11.0",
"knex": "^0.10.0", "knex": "^0.10.0",
"lodash": "^4.5.0", "lodash": "^4.5.0",
"markdown-it": "^6.0.0", "markdown-it": "^6.0.0",
"moment": "^2.11.2", "moment": "^2.11.2",
"morgan": "~1.6.1", "morgan": "~1.6.1",
"nodemon": "^1.9.0", "nodemon": "^1.9.0",
"nsp": "^2.4.0",
"scrypt": "^6.0.1", "scrypt": "^6.0.1",
"sqlite3": "^3.1.1", "sqlite3": "^3.1.1",
"winston": "^2.1.1" "winston": "^2.1.1"
}, },
"description": "A simple blog with built-in code snippet functionality", "description": "A simple blog with built-in code snippet functionality",
"devDependencies": { "devDependencies": {
"chai": "^3.4.1", "apidoc": "^0.15.1",
"chai-as-promised": "^5.2.0", "chai": "^3.5.0",
"eslint": "1.10.*", "chai-as-promised": "^5.3.0",
"gulp": "3.9.*", "documentation": "^4.0.0-beta1",
"gulp-apidoc": "0.2.*", "eslint": "^3.0.0",
"gulp-documentation": "2.1.*", "globstar": "^1.0.0",
"gulp-eslint": "^2.0.0",
"gulp-istanbul": "^0.10.3",
"gulp-jscs": "3.0.*",
"gulp-mocha": "2.2.*",
"gulp-nsp": "^2.3.0",
"gulp-pipe": "1.0.*",
"istanbul": "0.4.*", "istanbul": "0.4.*",
"mocha": "2.3.*", "jscs": "^3.0.0",
"mocha": "^2.4.5",
"npm-run-all": "^1.6.0",
"nsp": "^2.2.1",
"parallelshell": "^2.0.0",
"pre-commit": "^1.1.2", "pre-commit": "^1.1.2",
"sinon": "^1.17.3", "sinon": "^1.17.3",
"sinon-chai": "^2.8.0", "sinon-chai": "^2.8.0",
@ -57,11 +57,11 @@
], ],
"license": "MIT", "license": "MIT",
"main": "./server.js", "main": "./server.js",
"name": "crispy-train", "name": "ProgBlog",
"pre-commit": { "pre-commit": {
"silent": false, "silent": false,
"run": [ "run": [
"gulp" "default"
] ]
}, },
"repository": { "repository": {
@ -69,9 +69,18 @@
"url": "https://git.timshomepage.net/timw4mail/ProgBlog.git" "url": "https://git.timshomepage.net/timw4mail/ProgBlog.git"
}, },
"scripts": { "scripts": {
"start": "nodemon server.js", "audit": "nsp check",
"gulp": "gulp default", "build": "npm-run-all --parallel lint:src lint:tests docs:src docs:api coverage",
"test": "gulp test" "coverage": "istanbul cover ./node_modules/mocha/bin/_mocha",
"default": "npm-run-all --parallel audit lint:src lint:tests test",
"docs": "npm-run-all --parallel docs:src docs:api",
"docs:api": "apidoc -i ./app/ -o ./public/api-docs/",
"docs:src": "globstar -- documentation build -f html -o public/docs \"app/**/*.js\"",
"lint": "npm-run-all lint:tests lint:src",
"lint:src": "jscs server.js ./app && eslint server.js ./app",
"lint:tests": "jscs ./test && eslint ./test",
"start": "nodemon --debug server.js",
"test": "mocha"
}, },
"version": "0.0.1" "version": "0.0.1"
} }