diff --git a/koaton b/koaton index 6c95934..640bdb0 100644 --- a/koaton +++ b/koaton @@ -10,5 +10,5 @@ if (__dirname.indexOf('Development') > -1) { }); require('./src'); } else { - require('./lib'); + require('./index'); } diff --git a/package.json b/package.json index d04d659..22bac61 100644 --- a/package.json +++ b/package.json @@ -8,8 +8,8 @@ "export:live": "npm run export & chokidar src -c \"cls && npm run export\"", "eslint:live": "npm run eslint & chokidar src -c \"cls && npm run eslint\"", "eslint": "eslint .", - "export": "rimraf -rf lib && koaton-exporter src/*.js src/**/*.js ./ -r src/", - "test": "cross-env NODE_ENV=koaton mocha test/unit/**/*.js test/integration.js --compilers js:babel-register", + "export": "koaton-exporter src/*.js src/**/*.js ./ -r src/ -t v2", + "test": "cross-env NODE_ENV=koaton mocha test/integration.js --compilers js:babel-register", "test:live": "npm t -- -w", "cover": "nyc npm t", "cover:watch": "npm run cover & chokidar src test -c \"cls & npm run cover\"", diff --git a/src/commands/build.js b/src/commands/build.js index 6c8aeb4..1c5eeb9 100644 --- a/src/commands/build.js +++ b/src/commands/build.js @@ -1,205 +1,15 @@ /* eslint no-div-regex: 0 */ import * as path from 'upath'; -import * as crypto from 'crypto'; -import * as fs from 'fs-extra'; -import * as uglify from 'uglify-js'; -import * as Concat from 'concat-with-sourcemaps'; -import { sync as glob } from 'glob'; import copystatic from '../support/CopyStatic'; import utils from '../utils'; import Command from 'cmd-line/lib/Command'; -import BundleItem from '../support/BundleItem'; // import spin from '../spinner'; import { buildNginx } from '../functions/nginx'; import { buildAllImages } from '../functions/imagecompressor'; import EmberBuilder from '../support/EmberBuilder'; - +import { buildCSS, buildJS } from '../functions/builder'; // const spinner = spin(); -const hasFileName = function (file, content) { - const basename = path.trimExt(file); - const ext = file.replace(basename, ''); - const hasher = crypto.createHash('sha1'); - hasher.update(content); - const hash = hasher.digest('hex').slice(0, 20); - return basename + '_' + hash + ext; -}; - -async function buildCSS (target, bundle, development, onlypaths, logger) { - let error = []; - process.stdout.write(`Building ${target} `); - let start = process.hrtime(); - const ITEM = scfg.bundles[target] || new BundleItem(target, []); - ITEM.clear(); - utils.writeuseslog = logger; - const less = require('less'), - sass = function (options) { - return new Promise(function (resolve, reject) { - require('node-sass').render(options, function (err, result) { - if (err) reject(err); - resolve(result); - }); - }); - }, - CssImporter = require('node-sass-css-importer')(), - LessPluginCleanCSS = require('less-plugin-clean-css'); - const concat = new Concat(true, path.join('css', target + '.map'), '\n'), - cleanCSSPlugin = new LessPluginCleanCSS({ - advanced: true - }), - watchinFiles = {}; - let urlocurrencies = []; - for (let index in bundle.content) { - if (!development) { - utils.rmdir(path.join('public', 'css', index + target)); - } - let file = path.normalize(bundle.content[index]), - basename = path.basename(file); - if (file.indexOf('.less') > -1) { - let content = await less.render(fs.readFileSync(file, 'utf-8'), { - plugins: [cleanCSSPlugin], - filename: file, - compres: true, - sourceMap: onlypaths ? {} : { - outputSourceFiles: true, - sourceMapBasepath: path.normalize(file.replace(basename, '')), - sourceMapFileInline: development, - sourceMapRootpath: '/' + basename - } - }); - urlocurrencies = urlocurrencies.concat(content.css.toString().match(/url\(.*\)[ |;]/igm)); - if (development) { - watchinFiles[index + target] = content.imports; - watchinFiles[index + target].push(file); - if (!onlypaths) { - utils.write(path.join('public', 'css', index + target), content.css.toString(), 'utf-8', true); - } - ITEM.add(`/css/${index + target}`); - } else { - concat.add(basename, content.css, concat.map); - } - } else if (file.indexOf('.scss') > -1 || file.indexOf('.sass') > -1) { - let content = await sass({ - sourceMap: onlypaths ? false : '/', - sourceMapRoot: onlypaths ? undefined : '/' + target + '/', - sourceMapContents: onlypaths ? undefined : true, - sourceMapEmbed: onlypaths ? undefined : development, - outputStyle: 'compressed', - file: file, - importer: [CssImporter] - }); - urlocurrencies = urlocurrencies.concat(content.css.toString().match(/url\(.*\)[ |;]/igm)); - if (development) { - watchinFiles[index + target] = content.stats.includedFiles; - if (!onlypaths) { - utils.write(path.join('public', 'css', index + target), content.css.toString(), 'utf-8', true); - } - ITEM.add(`/css/${index + target}`); - } else { - concat.add(basename, content.css, concat.map); - } - } else if (file.indexOf('.css')) { - watchinFiles[index + target] = glob(ProyPath(file)); - if (watchinFiles[index + target].length === 0) { - error.push(`${__nok.red} Pattern ${file} ${'not found'.red}`); - } - const concatCSS = new Concat(true, path.join('css', index + target + '.css'), '\n'); - if (!development || !onlypaths) { - for (const url of watchinFiles[index + target]) { - concatCSS.add(target, fs.readFileSync(url)); - } - } - urlocurrencies = urlocurrencies.concat(concatCSS.content.toString().match(/url\(.*\)[ |;]/igm)); - if (development && !onlypaths) { - utils.write(ProyPath('public', 'css', index + target), concatCSS.content, 'utf-8', true); - ITEM.add(`/css/${index + target}`); - } else if (!development) { - concat.add(basename, concatCSS.content); - } - } - scfg.bundles.remove(ITEM).add(ITEM); - } - if (!onlypaths) { - if (!development) { - const file = hasFileName(target, concat.content.toString()); - utils.write( - path.join('public', 'css', file), - concat.content.toString(), 'utf-8', true); - ITEM.clear().add(`/css/${file}`); - scfg.bundles.remove(ITEM).add(ITEM); - } - } - utils.writeuseslog = undefined; - let [seconds, nanoseconds] = process.hrtime(start); - process.stdout.clearLine(); - process.stdout.cursorTo(0); - console.log(` ${__ok.green} ${target} ${(seconds * 1000) + Math.ceil(nanoseconds / 1e6)} ms`); - if (error.length > 0) { - console.log(error.join('\n')); - } - return watchinFiles; -} -async function buildJS (target, bundle, development, onlypaths, logger) { - let error = []; - process.stdout.write(`Building ${target} `); - let start = process.hrtime(); - const ITEM = scfg.bundles[target] || new BundleItem(target, []); - ITEM.clear(); - utils.writeuseslog = logger; - let AllFiles = []; - for (const pattern of bundle) { - let bundle = glob(ProyPath(pattern)); - if (bundle.length === 0) { - error.push(`${__nok.red} Pattern ${pattern} ${'not found'.red}`); - } - AllFiles = AllFiles.concat(bundle); - } - process.stdout.write(`(${AllFiles.length} files) `); - if (onlypaths) { - return AllFiles; - } - let readfiles = {}; - for (const file of AllFiles) { - readfiles[path.basename(file)] = fs.readFileSync(file, 'utf-8'); - } - let map = target.replace('.js', '.map'); - let result = uglify.minify(readfiles, { - mangle: false, - sourceMap: onlypaths ? false : { - root: '/src/', - includeSources: onlypaths ? false : development, - // filename: target, - url: path.join('/js', map) - }, - compress: { - dead_code: true, - sequences: true, - unused: true - } - }); - if (!onlypaths) { - const file = development ? path.changeExt(target, '.min.js') : hasFileName(target, result.code.toString()); - utils.write(path.join('public', 'js', file), result.code, { - encoding: 'utf-8' - }, true); - if (development) { - fs.writeFileSync(path.join('public', 'js', map), result.map, 'utf8'); - } - - ITEM.add('/js/' + file); - } - utils.writeuseslog = undefined; - scfg.bundles.remove(ITEM).add(ITEM); - let [seconds, nanoseconds] = process.hrtime(start); - process.stdout.clearLine(); - process.stdout.cursorTo(0); - console.log(` ${__ok.green} ${target} ${(seconds * 1000) + Math.ceil(nanoseconds / 1e6)} ms`); - if (error.length > 0) { - console.log(error.join('\n')); - } - return {[target]: AllFiles}; -}; -export { buildCSS, buildJS }; async function buildApps () { if (Object.keys(configuration.ember).length === 0) return 0; await Events('pre', 'ember_build'); @@ -228,11 +38,11 @@ async function buildBundles () { } } console.log(` Updating bundles (env: ${scfg.env})`); - for (const key in configuration.bundles) { - if (key.indexOf('.css') > -1) { - await buildCSS(key, configuration.bundles[key], scfg.env === 'development'); - } else if (key.indexOf('.js') > -1) { - await buildJS(key, configuration.bundles[key], scfg.env === 'development'); + for (const bundle of configuration.bundles) { + if (bundle.kind === '.css') { + await buildCSS(bundle.file, bundle, scfg.env === 'development'); + } else if (bundle.kind === '.js') { + await buildJS(bundle.file, bundle, scfg.env === 'development'); } } } diff --git a/src/functions/builder.js b/src/functions/builder.js new file mode 100644 index 0000000..7bbfcbf --- /dev/null +++ b/src/functions/builder.js @@ -0,0 +1,192 @@ +import BundleItem from '../support/BundleItem'; +import * as crypto from 'crypto'; +import * as fs from 'fs-extra'; +import * as uglify from 'uglify-js'; +import * as Concat from 'concat-with-sourcemaps'; +import { sync as glob } from 'glob'; +import * as path from 'upath'; +import utils from '../utils'; + +const hasFileName = function (file, content) { + const basename = path.trimExt(file); + const ext = file.replace(basename, ''); + const hasher = crypto.createHash('sha1'); + hasher.update(content); + const hash = hasher.digest('hex').slice(0, 20); + return basename + '_' + hash + ext; +}; + +export async function buildCSS (target, bundle, development, onlypaths, logger) { + let error = []; + process.stdout.write(`Building ${target} `); + let start = process.hrtime(); + const ITEM = scfg.bundles[target] || new BundleItem(target, []); + ITEM.clear(); + utils.writeuseslog = logger; + const less = require('less'), + sass = function (options) { + return new Promise(function (resolve, reject) { + require('node-sass').render(options, function (err, result) { + if (err) reject(err); + resolve(result); + }); + }); + }, + CssImporter = require('node-sass-css-importer')(), + LessPluginCleanCSS = require('less-plugin-clean-css'); + const concat = new Concat(true, path.join('css', target + '.map'), '\n'), + cleanCSSPlugin = new LessPluginCleanCSS({ + advanced: true + }), + watchinFiles = {}; + let urlocurrencies = []; + for (let index in bundle.content) { + if (!development) { + utils.rmdir(path.join('public', 'css', index + target)); + } + let file = path.normalize(bundle.content[index]), + basename = path.basename(file); + if (file.indexOf('.less') > -1) { + let content = await less.render(fs.readFileSync(file, 'utf-8'), { + plugins: [cleanCSSPlugin], + filename: file, + compres: true, + sourceMap: onlypaths ? {} : { + outputSourceFiles: true, + sourceMapBasepath: path.normalize(file.replace(basename, '')), + sourceMapFileInline: development, + sourceMapRootpath: '/' + basename + } + }); + urlocurrencies = urlocurrencies.concat(content.css.toString().match(/url\(.*\)[ |;]/igm)); + if (development) { + watchinFiles[index + target] = content.imports; + watchinFiles[index + target].push(file); + if (!onlypaths) { + utils.write(path.join('public', 'css', index + target), content.css.toString(), 'utf-8', true); + } + ITEM.add(`/css/${index + target}`); + } else { + concat.add(basename, content.css, concat.map); + } + } else if (file.indexOf('.scss') > -1 || file.indexOf('.sass') > -1) { + let content = await sass({ + sourceMap: onlypaths ? false : '/', + sourceMapRoot: onlypaths ? undefined : '/' + target + '/', + sourceMapContents: onlypaths ? undefined : true, + sourceMapEmbed: onlypaths ? undefined : development, + outputStyle: 'compressed', + file: file, + importer: [CssImporter] + }); + urlocurrencies = urlocurrencies.concat(content.css.toString().match(/url\(.*\)[ |;]/igm)); + if (development) { + watchinFiles[index + target] = content.stats.includedFiles; + if (!onlypaths) { + utils.write(path.join('public', 'css', index + target), content.css.toString(), 'utf-8', true); + } + ITEM.add(`/css/${index + target}`); + } else { + concat.add(basename, content.css, concat.map); + } + } else if (file.indexOf('.css')) { + watchinFiles[index + target] = glob(ProyPath(file)); + if (watchinFiles[index + target].length === 0) { + error.push(`${__nok.red} Pattern ${file} ${'not found'.red}`); + } + const concatCSS = new Concat(true, path.join('css', index + target + '.css'), '\n'); + if (!development || !onlypaths) { + for (const url of watchinFiles[index + target]) { + concatCSS.add(target, fs.readFileSync(url)); + } + } + urlocurrencies = urlocurrencies.concat(concatCSS.content.toString().match(/url\(.*\)[ |;]/igm)); + if (development && !onlypaths) { + utils.write(ProyPath('public', 'css', index + target), concatCSS.content, 'utf-8', true); + ITEM.add(`/css/${index + target}`); + } else if (!development) { + concat.add(basename, concatCSS.content); + } + } + scfg.bundles.remove(ITEM).add(ITEM); + } + if (!onlypaths) { + if (!development) { + const file = hasFileName(target, concat.content.toString()); + utils.write( + path.join('public', 'css', file), + concat.content.toString(), 'utf-8', true); + ITEM.clear().add(`/css/${file}`); + scfg.bundles.remove(ITEM).add(ITEM); + } + } + utils.writeuseslog = undefined; + let [seconds, nanoseconds] = process.hrtime(start); + process.stdout.clearLine(); + process.stdout.cursorTo(0); + console.log(` ${__ok.green} ${target} ${(seconds * 1000) + Math.ceil(nanoseconds / 1e6)} ms`); + if (error.length > 0) { + console.log(error.join('\n')); + } + return watchinFiles; +} +export async function buildJS (target, bundle, development, onlypaths, logger) { + let error = []; + process.stdout.write(`Building ${target} `); + let start = process.hrtime(); + const ITEM = scfg.bundles[target] || new BundleItem(target, []); + ITEM.clear(); + utils.writeuseslog = logger; + let AllFiles = []; + for (const pattern of bundle) { + let bundle = glob(ProyPath(pattern)); + if (bundle.length === 0) { + error.push(`${__nok.red} Pattern ${pattern} ${'not found'.red}`); + } + AllFiles = AllFiles.concat(bundle); + } + process.stdout.write(`(${AllFiles.length} files) `); + if (onlypaths) { + return AllFiles; + } + let readfiles = {}; + for (const file of AllFiles) { + readfiles[path.basename(file)] = fs.readFileSync(file, 'utf-8'); + } + let map = target.replace('.js', '.map'); + let result = uglify.minify(readfiles, { + mangle: false, + sourceMap: onlypaths ? false : { + root: '/src/', + includeSources: onlypaths ? false : development, + // filename: target, + url: path.join('/js', map) + }, + compress: { + dead_code: true, + sequences: true, + unused: true + } + }); + if (!onlypaths) { + const file = development ? path.changeExt(target, '.min.js') : hasFileName(target, result.code.toString()); + utils.write(path.join('public', 'js', file), result.code, { + encoding: 'utf-8' + }, true); + if (development) { + fs.writeFileSync(path.join('public', 'js', map), result.map, 'utf8'); + } + + ITEM.add('/js/' + file); + } + utils.writeuseslog = undefined; + scfg.bundles.remove(ITEM).add(ITEM); + let [seconds, nanoseconds] = process.hrtime(start); + process.stdout.clearLine(); + process.stdout.cursorTo(0); + console.log(` ${__ok.green} ${target} ${(seconds * 1000) + Math.ceil(nanoseconds / 1e6)} ms`); + if (error.length > 0) { + console.log(error.join('\n')); + } + return {[target]: AllFiles}; +}; diff --git a/src/support/BundleItem.js b/src/support/BundleItem.js index 8a53153..bdbc962 100644 --- a/src/support/BundleItem.js +++ b/src/support/BundleItem.js @@ -1,16 +1,11 @@ import * as path from 'upath'; import { watch as Watch } from 'chokidar'; -import { buildCSS, buildJS } from '../commands/build'; -const builder = { - css: buildCSS, - js: buildJS -}; const bundletemplates = { - 'css': (file) => { + '.css': (file) => { return ``; }, - 'js': (file) => { + '.js': (file) => { return ``; } }; @@ -54,7 +49,7 @@ export default class BundleItem { */ Object.defineProperty(this, 'kind', { enumerable: false, - value: target.replace(path.trimExt(target), '').replace('.', '') + value: target.replace(path.trimExt(target), '') // .replace('.', '') }); Object.defineProperty(this, 'file', { enumerable: true, @@ -77,13 +72,13 @@ export default class BundleItem { }); } } - async build (logger) { + async build (logger, builder) { try { this.sources.forEach(f => { this.watcher.unwatch(f); }); } catch (Ex) { } - let data = await builder[this.kind](this.file, this, configuration.server.env === 'development', false, logger); + let data = await builder(this.file, this, configuration.server.env === 'development', false, logger); let sources = []; let files = []; for (const key in data) { diff --git a/src/support/CheckBundles.js b/src/support/CheckBundles.js index b233ffb..e8b83f8 100644 --- a/src/support/CheckBundles.js +++ b/src/support/CheckBundles.js @@ -1,7 +1,6 @@ import spin from '../spinner'; import { livereload } from '../utils/livereload'; import mkdir from '../utils/mkdir'; -import notifier from './Notifier'; import BundleItem from './BundleItem'; import { watch as Watch } from 'chokidar'; import { resolve } from 'path'; diff --git a/src/support/EmberBuilder.js b/src/support/EmberBuilder.js index ba740fa..267c8d2 100644 --- a/src/support/EmberBuilder.js +++ b/src/support/EmberBuilder.js @@ -71,7 +71,7 @@ export default class EmberBuilder { let text = await readFile(ProyPath('public', this.directory, 'index.html'), { encoding: 'utf-8' }), indextemplate = await readFile(TemplatePath('ember_apps', 'index.handlebars'), 'utf-8'), meta = new RegExp(``); - const links = new RegExp('', 'gm'); const transformlinks = (text, expresion) => { return text.match(expresion).join('\n') diff --git a/templates/package.json b/templates/package.json index 8f5f2ec..ef5a912 100644 --- a/templates/package.json +++ b/templates/package.json @@ -18,7 +18,7 @@ "author": "", "license": "", "dependencies": { - "koaton":"^2.0.5" + "koaton":"^2.2.0" }, "config": { "commitizen": { diff --git a/test/configuration/build.js b/test/configuration/build.js index a8217f6..73e81ef 100644 --- a/test/configuration/build.js +++ b/test/configuration/build.js @@ -55,19 +55,19 @@ tests.push(new TestNode('(no args)', [{}], true)) } } requireNoCache(ProyPath('node_modules', 'koaton/support', 'globals')); - configuration.ember = requireNoCache(ProyPath('config', 'ember')).default; + // configuration.ember = requireNoCache(ProyPath('config', 'ember')).default; scfg.env = 'development'; global.scfg = new ServerConfiguaration(); for (const key of Object.keys(configuration.bundles)) { if (!configuration.bundles[key].content) { let bundle = new BundleItem(key, configuration.bundles[key]); - configuration.bundles[key] = bundle; + scfg.bundles[key] = bundle; } } }) .Exists('public', 'css', '0admin.css') .Exists('public', 'js', 'admin.min.js') - .Exists('public', 'js', 'admin.js.map') + .Exists('public', 'js', 'admin.map') .Expect('Builds Ember Apps', true, () => { for (const app of scfg.emberApps) { fs.accessSync(ProyPath('public', app.directory)); @@ -87,7 +87,7 @@ tests.push(new TestNode('(no args)', [{}], true)) return true; }) .Expect('Copy Static Content', true, () => { - const copy = requireSafe(ProyPath('config', 'copy'), {}); + const copy = require(ProyPath('config', 'static'), {}); for (const dir in copy) { for (const idx in copy[dir]) { let directories = glob(ProyPath(copy[dir][idx])); diff --git a/test/integration.js b/test/integration.js index 8c0581c..c3d6d68 100644 --- a/test/integration.js +++ b/test/integration.js @@ -24,16 +24,15 @@ const notestcase = function (testname) { }); }); }; -function takeone (data) { +async function takeone (data) { if (data.length === 0) { return Promise.resolve(true); } let test = data.splice(0, 1)[0]; let [message, mustbe, Actual] = test(); - return Actual.then((actual) => { - assert.equal(actual, mustbe, message); - return takeone(data); - }); + let actual = await Actual; + assert.equal(actual, mustbe, message); + return takeone(data); } const testcase = function testcase (TestConfig, cwd, testname, command) { describe(testname, function () { @@ -47,26 +46,22 @@ const testcase = function testcase (TestConfig, cwd, testname, command) { const WriteO = process.stdout.write; try { let buffer = ''; - process.stderr.write = () => { - }; - process.stdout.write = () => { - }; - console.log = (...data) => { - ori(...data); - buffer += (data || '').toString(); - }; + // process.stderr.write = () => { + // }; + // process.stdout.write = () => { + // }; + // console.log = (...data) => { + // ori(...data); + // buffer += (data || '').toString(); + // }; if (testdata.asyncs) { let res = command.action.apply(null, testdata.args); testdata.expect.splice(0, 1); - return res.then((childIPIDs) => { - return takeone(testdata.expect).then(() => { - for (const pid of childIPIDs) { - process.kill(pid); - } - }); - }, (err) => { - console.log(err); - }); + let childIPIDs = await res; + await takeone(testdata.expect); + for (const pid of childIPIDs) { + process.kill(pid); + } } else { let res = await command.action.apply(null, testdata.args); // console.log = ori;