From 711e2ebfc3fc8a82263fd12850855713439bf651 Mon Sep 17 00:00:00 2001 From: Burak Tasci Date: Sun, 3 Sep 2017 09:40:46 +0300 Subject: [PATCH] build(rollup): migrate to `rollup` (#64) * build(npm): update npm scripts, deps * build(webpack): remove webpack test config * refactor: migrate test config to `jest` * refactor: centralize tsconfig * docs: add jest badge to README * refactor(core): refactor `jest` migration * build: update ignorers * build(webpack): remove webpack prod config * build(gulp): remove gulp tasks * build(rollup): add rollup tasks * build(npm): update npm scripts, deps Fixes #56 --- .gitattributes | 17 -- .gitignore | 12 +- .jshintrc | 29 --- config/build-config.json | 8 - config/gulp-tasks.js | 259 ------------------- config/helpers.js | 12 - config/webpack.prod.js | 86 ------ gulpfile.js | 1 - package.json | 9 +- packages/@ngx-meta/core/.npmignore | 18 -- packages/@ngx-meta/core/package.json | 22 +- packages/@ngx-meta/core/tsconfig.es2015.json | 34 +++ packages/@ngx-meta/core/tsconfig.es5.json | 16 ++ tools/build/build-config.json | 19 ++ tools/build/helpers.ts | 10 + tools/build/inline-resources.ts | 73 ++++++ tools/build/rollup.ts | 206 +++++++++++++++ tools/typings.d.ts | 5 + tsconfig.json | 7 +- 19 files changed, 381 insertions(+), 462 deletions(-) delete mode 100644 .gitattributes delete mode 100644 .jshintrc delete mode 100644 config/build-config.json delete mode 100644 config/gulp-tasks.js delete mode 100644 config/helpers.js delete mode 100644 config/webpack.prod.js delete mode 100644 gulpfile.js delete mode 100644 packages/@ngx-meta/core/.npmignore create mode 100644 packages/@ngx-meta/core/tsconfig.es2015.json create mode 100644 packages/@ngx-meta/core/tsconfig.es5.json create mode 100644 tools/build/build-config.json create mode 100644 tools/build/helpers.ts create mode 100644 tools/build/inline-resources.ts create mode 100644 tools/build/rollup.ts create mode 100644 tools/typings.d.ts diff --git a/.gitattributes b/.gitattributes deleted file mode 100644 index bdb0cab..0000000 --- a/.gitattributes +++ /dev/null @@ -1,17 +0,0 @@ -# Auto detect text files and perform LF normalization -* text=auto - -# Custom for Visual Studio -*.cs diff=csharp - -# Standard to msysgit -*.doc diff=astextplain -*.DOC diff=astextplain -*.docx diff=astextplain -*.DOCX diff=astextplain -*.dot diff=astextplain -*.DOT diff=astextplain -*.pdf diff=astextplain -*.PDF diff=astextplain -*.rtf diff=astextplain -*.RTF diff=astextplain diff --git a/.gitignore b/.gitignore index 0bdbc4c..5761cb2 100644 --- a/.gitignore +++ b/.gitignore @@ -1,24 +1,18 @@ # See http://help.github.com/ignore-files/ for more about ignoring files. # compiled output -bundles/ -*.js -*.d.ts -*.metadata.json +.temp/ +dist/ # dependencies node_modules/ -yarn.lock +yarn.* # IDEs and editors .idea/ # build tools coverage/ -!gulpfile.js -!karma.conf.js -!spec-bundle.js # misc -!config/*.js npm-debug.log diff --git a/.jshintrc b/.jshintrc deleted file mode 100644 index 439607c..0000000 --- a/.jshintrc +++ /dev/null @@ -1,29 +0,0 @@ -{ - "bitwise": true, - "eqeqeq": true, - "forin": true, - "noarg": true, - "noempty": true, - "nonbsp": true, - "nonew": true, - "undef": true, - "varstmt": true, - "esversion": 6, - "latedef": true, - "unused": true, - "indent": 2, - "quotmark": "single", - "maxcomplexity": 20, - "maxlen": 140, - "maxerr": 50, - "globals": {}, - "strict": true, - "laxbreak": true, - "loopfunc": true, - "browser": true, - "module": true, - "node": true, - "trailing": true, - "onevar": true, - "white": true -} \ No newline at end of file diff --git a/config/build-config.json b/config/build-config.json deleted file mode 100644 index d4b10b6..0000000 --- a/config/build-config.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "@ngx-meta": { - "core": { - "angularVersion": 4, - "runTests": true - } - } -} diff --git a/config/gulp-tasks.js b/config/gulp-tasks.js deleted file mode 100644 index 3b673b0..0000000 --- a/config/gulp-tasks.js +++ /dev/null @@ -1,259 +0,0 @@ -'use strict'; - -const packages = require('./build-config.json'); -const gulp = require('gulp'), - $ = require('gulp-load-plugins')({ - pattern: [ - 'gulp-*', - 'rimraf', - 'webpack' - ] - }), - $$ = require('./helpers'); - -const tasks = {}; - -const clean = { - bundles: done => { - for (const group of Object.keys(packages)) - for (const item of Object.keys(packages[group])) - $.rimraf(`./packages/${group}/${item}/bundles`, done); - }, - 'index.js': done => { - for (const group of Object.keys(packages)) - for (const item of Object.keys(packages[group])) - $.rimraf(`./packages/${group}/${item}/index.js`, done); - }, - 'index.d.ts': done => { - for (const group of Object.keys(packages)) - for (const item of Object.keys(packages[group])) - $.rimraf(`./packages/${group}/${item}/index.d.ts`, done); - }, - 'index.metadata.json': done => { - for (const group of Object.keys(packages)) - for (const item of Object.keys(packages[group])) - $.rimraf(`./packages/${group}/${item}/index.metadata.json`, done); - }, - 'src/*.js': done => { - for (const group of Object.keys(packages)) - for (const item of Object.keys(packages[group])) - $.rimraf(`./packages/${group}/${item}/src/**/*.js`, done); - }, - 'src/*.d.ts': done => { - for (const group of Object.keys(packages)) - for (const item of Object.keys(packages[group])) - $.rimraf(`./packages/${group}/${item}/src/**/*.d.ts`, done); - }, - 'src/*.metadata.json': done => { - for (const group of Object.keys(packages)) - for (const item of Object.keys(packages[group])) - $.rimraf(`./packages/${group}/${item}/src/**/*.metadata.json`, done); - }, - 'testing/*.js': done => { - for (const group of Object.keys(packages)) - for (const item of Object.keys(packages[group])) - $.rimraf(`./packages/${group}/${item}/testing/**/*.js`, done); - }, - 'testing/*.d.ts': done => { - for (const group of Object.keys(packages)) - for (const item of Object.keys(packages[group])) - $.rimraf(`./packages/${group}/${item}/testing/**/*.d.ts`, done); - } -}; - -clean.bundles.displayName = 'clean:bundles'; -clean['index.js'].displayName = 'clean:./index.js'; -clean['index.d.ts'].displayName = 'clean:./index.d.ts'; -clean['index.metadata.json'].displayName = 'clean:./index.metadata.json'; -clean['src/*.js'].displayName = 'clean:./src/*.js'; -clean['src/*.d.ts'].displayName = 'clean:./src/*.js'; -clean['src/*.metadata.json'].displayName = 'clean:./src/*.js'; -clean['testing/*.js'].displayName = 'clean:./testing/*.js'; -clean['testing/*.d.ts'].displayName = 'clean:./testing/*.d.ts'; - -const ts = { - compile: done => { - const options = { - continueOnError: false, - pipeStdout: false, - customTemplatingThing: 'test' - }; - const reportOptions = { - err: true, - stderr: true, - stdout: true - }; - const compileOne = (group, item, d) => { - return gulp.src(`./packages/${group}/${item}/tsconfig.json`) - .pipe($.exec(`"./packages/${group}/${item}/node_modules/.bin/ngc" -p "./packages/${group}/${item}/tsconfig.json"`, options)) - .pipe($.exec.reporter(reportOptions)) - .on('end', d); - }; - - const subTasks = []; - - for (const group of Object.keys(packages)) - for (const item of Object.keys(packages[group])) { - const fn = d => compileOne(group, item, d); - fn.displayName = `compile:ngc:${group}:${item}`; - - subTasks.push(fn); - } - - return gulp.series(subTasks, d => d())(done); - }, - lint: done => { - return gulp.src([ - './**/index.ts', - './**/src/**/*.ts', - '!./**/src/**/*.d.ts', - './**/testing/**/*.ts', - '!./**/testing/**/*.d.ts', - './**/tests/**/*.ts', - '!./**/tests/**/*.d.ts', - '!./**/node_modules/**/*' - ]) - .pipe($.tslint({formatter: 'verbose'})) - .pipe($.tslint.report({emitError: false})) - .on('end', done); - } -}; - -ts.compile.displayName = 'compile:ngc'; -ts.lint.displayName = 'tslint'; - -const bundle = { - webpack: done => { - const chalk = require('chalk'); - - const bundleOne = (group, item, settings, d) => { - const webpack = require('./webpack.prod.js'); - - $.webpack(webpack(group, item, settings)) - .run((err, stats) => { - if (err) { - console.log(chalk.red(`Error: ${err}`)); - d(); - } else { - const statsJson = stats.toJson(), - warnings = statsJson.warnings, - errors = statsJson.errors; - - for (const key of Object.keys(warnings)) - console.log(chalk.gray(`Warning: ${warnings[key]}\n`)); - - if (warnings.length > 0) - console.log(chalk.gray(` (${warnings.length}) warning(s) total.\n`)); - - for (const key of Object.keys(errors)) - console.log(chalk.red(`Error: ${errors[key]}\n`)); - - if (errors.length > 0) - console.log(chalk.red(` (${errors.length}) error(s) total.\n`)); - - for (const key of Object.keys(stats.compilation.assets)) - console.log(`Webpack: output ${chalk.green(key)}`); - - console.log(`Webpack: ${chalk.blue(`finished`)}`); - - d(); - } - }); - }; - - const subTasks = []; - - for (const group of Object.keys(packages)) - for (const item of Object.keys(packages[group])) { - const fn = d => bundleOne(group, item, packages[group][item], d); - fn.displayName = `bundle:webpack:${group}:${item}`; - - subTasks.push(fn); - } - - return gulp.series(subTasks, d => d())(done); - } -}; - -bundle.webpack.displayName = 'bundle:webpack'; - -const tests = { - run: done => { - const server = require('karma').Server; - - const testOne = (group, item, settings, d) => { - const webpack = require('./webpack.test.js'); - - new server({ - configFile: $$.root(`./packages/${group}/${item}/config/karma.conf.js`), - webpack: webpack(group, item, settings), - coverageIstanbulReporter: { - reports: [ - 'html', - 'json', - 'lcovonly', - 'text-summary' - ], - dir: `./coverage/${group}/${item}`, - fixWebpackSourcePaths: true, - 'report-config': { - html: {subdir: 'html'} - } - } - }, () => d()).start(); - }; - - const subTasks = []; - - for (const group of Object.keys(packages)) - for (const item of Object.keys(packages[group])) - if (packages[group][item].runTests) { - const fn = d => testOne(group, item, packages[group][item], d); - fn.displayName = `tests:run:${group}:${item}`; - - subTasks.push(fn); - } - - return gulp.series(subTasks, d => { - d(); - process.exit(0); - })(done); - } -}; - -tests.run.displayName = 'tests:run'; - -tasks.clean = clean; -tasks.ts = ts; -tasks.bundle = bundle; -tasks.tests = tests; - -gulp.task('clean', - gulp.parallel( - clean.bundles, - clean['index.js'], - clean['index.d.ts'], - clean['index.metadata.json'], - clean['src/*.js'], - clean['src/*.d.ts'], - clean['src/*.metadata.json'], - clean['testing/*.js'], - clean['testing/*.d.ts'] - )); - -gulp.task('make', - gulp.series( - 'clean', - tasks.ts.compile, - tasks.bundle.webpack - )); - -gulp.task('test', - gulp.series( - tasks.tests.run - )); - -gulp.task('tslint', - gulp.series( - tasks.ts.lint - )); diff --git a/config/helpers.js b/config/helpers.js deleted file mode 100644 index 4cba16a..0000000 --- a/config/helpers.js +++ /dev/null @@ -1,12 +0,0 @@ -const $ = {}; - -$.path = require('path'); - -const root = function(args) { - const ROOT = $.path.resolve(__dirname, '..'); - args = Array.prototype.slice.call(arguments, 0); - - return $.path.join.apply($.path, [ROOT].concat(args)); -}; - -exports.root = root; diff --git a/config/webpack.prod.js b/config/webpack.prod.js deleted file mode 100644 index 73a23fc..0000000 --- a/config/webpack.prod.js +++ /dev/null @@ -1,86 +0,0 @@ -const helpers = require('./helpers'); - -const checkerPlugin = require('awesome-typescript-loader').CheckerPlugin, - contextReplacementPlugin = require('webpack/lib/ContextReplacementPlugin'), - loaderOptionsPlugin = require('webpack/lib/LoaderOptionsPlugin'), - uglifyJsPlugin = require('webpack/lib/optimize/UglifyJsPlugin'); - -module.exports = (group, item, settings) => { - return { - entry: helpers.root(`packages/${group}/${item}/index.ts`), - resolve: { - extensions: ['.ts', '.js'] - }, - output: { - path: helpers.root(`packages/${group}/${item}/bundles`), - publicPath: '/', - filename: `${item}.umd.min.js`, - libraryTarget: 'umd', - library: group.replace(/@/g, '') - }, - externals: [/^@angular\//, /^rxjs\//, /^lodash/], - module: { - rules: [ - { - enforce: 'pre', - test: /\.ts$/, - use: 'tslint-loader', - exclude: [helpers.root('node_modules')] - }, - { - test: /\.ts$/, - use: `awesome-typescript-loader?declaration=false&configFileName=${helpers.root(`packages/${group}/${item}/tsconfig.json`)}`, - exclude: [/\.(spec|e2e)\.ts$/] - } - ] - }, - plugins: [ - new checkerPlugin(), - new contextReplacementPlugin( - // fix the warning in ./~/@angular/core/src/linker/system_js_ng_module_factory_loader.js - settings.angularVersion === 2 - ? /angular([\\\/])core([\\\/])(esm([\\\/])src|src)([\\\/])linker/ - : /angular([\\\/])core([\\\/])@angular/, - helpers.root(`packages/${group}/${item}/src`) - ), - new loaderOptionsPlugin({ - options: { - tslint: { - failOnHint: false - } - } - }), - new uglifyJsPlugin({ - beautify: false, - output: { - comments: false - }, - mangle: { - screw_ie8: true - }, - compress: { - screw_ie8: true, - warnings: false, - conditionals: true, - unused: true, - comparisons: true, - sequences: true, - dead_code: true, - evaluate: true, - if_return: true, - join_vars: true, - negate_iife: false // we need this for lazy v8 - } - }) - ], - node: { - global: true, - crypto: 'empty', - fs: 'empty', - process: false, - module: false, - clearImmediate: false, - setImmediate: false - } - }; -}; diff --git a/gulpfile.js b/gulpfile.js deleted file mode 100644 index 82254aa..0000000 --- a/gulpfile.js +++ /dev/null @@ -1 +0,0 @@ -module.exports = require('./config/gulp-tasks.js'); diff --git a/package.json b/package.json index 36af2bb..0e0dbe3 100644 --- a/package.json +++ b/package.json @@ -17,9 +17,10 @@ }, "homepage": "https://github.com/fulls1z3/ngx-meta#readme", "scripts": { - "clean": "gulp clean --color", - "lint": "gulp tslint --color", - "make": "gulp make --color", + "clean": "rimraf .temp dist", + "build": "ts-node ./tools/build/rollup.ts && rimraf .temp", + "lint": "tslint -p ./tslint.json --force", + "rebuild": "npm run clean && npm run build", "test": "jest --runInBand --colors" }, "devDependencies": { @@ -53,7 +54,7 @@ }, "jest": { "preset": "jest-preset-angular", - "setupTestFrameworkScriptFile": "./config/jest.setup.ts", + "setupTestFrameworkScriptFile": "./tools/test/jest.setup.ts", "globals": { "ts-jest": { "tsConfigFile": "./tsconfig.json" diff --git a/packages/@ngx-meta/core/.npmignore b/packages/@ngx-meta/core/.npmignore deleted file mode 100644 index d51b938..0000000 --- a/packages/@ngx-meta/core/.npmignore +++ /dev/null @@ -1,18 +0,0 @@ -# https://docs.npmjs.com/misc/developers#keeping-files-out-of-your-package - -# compiled output -*.ts -!*.d.ts - -# dependencies -/node_modules -yarn.* - -# build tools -/config -.npmignore -tsconfig.json - -# misc -/tests -npm-debug.log diff --git a/packages/@ngx-meta/core/package.json b/packages/@ngx-meta/core/package.json index 76b22f1..02296b8 100644 --- a/packages/@ngx-meta/core/package.json +++ b/packages/@ngx-meta/core/package.json @@ -26,21 +26,17 @@ "url": "https://github.com/fulls1z3/ngx-meta/core/issues" }, "homepage": "https://github.com/fulls1z3/ngx-meta/tree/master/packages/@ngx-meta/core#readme", - "main": "./bundles/core.umd.min.js", - "module": "./index.js", - "typings": "./index.d.ts", + "main": "./bundles/core.umd.js", + "module": "./@ngx-meta/core.es5.js", + "es2015": "./@ngx-meta/core.js", + "typings": "./core.d.ts", "dependencies": { - "tslib": "^1.7.1" - }, - "devDependencies": { - "@angular/compiler-cli": "~4.3.0", - "lodash": "^4.17.4", - "@types/lodash": "4.14.55" + "tslib": "~1.7.1" }, "peerDependencies": { - "@angular/core": "^4.0.0", - "@angular/platform-browser": "^4.0.0", - "@angular/router": "^4.0.0", - "rxjs": "^5.0.1" + "@angular/core": ">=4.0.0 <5.0.0", + "@angular/platform-browser": ">=4.0.0 <5.0.0", + "@angular/router": ">=4.0.0 <5.0.0", + "rxjs": ">=5.0.1" } } diff --git a/packages/@ngx-meta/core/tsconfig.es2015.json b/packages/@ngx-meta/core/tsconfig.es2015.json new file mode 100644 index 0000000..d2350e1 --- /dev/null +++ b/packages/@ngx-meta/core/tsconfig.es2015.json @@ -0,0 +1,34 @@ +{ + "extends": "../../../../tsconfig.json", + "compilerOptions": { + "target": "es2015", + "module": "es2015", + "noImplicitAny": true, + "suppressImplicitAnyIndexErrors": true, + "importHelpers": true, + "sourceMap": true, + "inlineSources": true, + "declaration": true, + "removeComments": true, + "stripInternal": true, + "outDir": "../../../../.temp/packages/@ngx-meta/core-es2015/", + "rootDir": "./", + "baseUrl": "", + "typeRoots": ["../../../../node_modules/@types"], + "types": ["node"], + "lib": [ + "es2015", + "dom" + ] + }, + "include": [], + "files": ["./index.ts"], + "angularCompilerOptions": { + "annotateForClosureCompiler": true, + "strictMetadataEmit": true, + "skipTemplateCodegen": true, + "flatModuleOutFile": "core.js", + "flatModuleId": "core", + "genDir": "../../../../.temp/gen-dir/" + } +} diff --git a/packages/@ngx-meta/core/tsconfig.es5.json b/packages/@ngx-meta/core/tsconfig.es5.json new file mode 100644 index 0000000..507917a --- /dev/null +++ b/packages/@ngx-meta/core/tsconfig.es5.json @@ -0,0 +1,16 @@ +{ + "extends": "./tsconfig.es2015.json", + "compilerOptions": { + "target": "es5", + "outDir": "../../../../.temp/packages/@ngx-meta/core-es5/" + }, + "files": ["./index.ts"], + "angularCompilerOptions": { + "annotateForClosureCompiler": true, + "strictMetadataEmit": true, + "skipTemplateCodegen": true, + "flatModuleOutFile": "core.js", + "flatModuleId": "core", + "genDir": "../../../../.temp/gen-dir/" + } +} diff --git a/tools/build/build-config.json b/tools/build/build-config.json new file mode 100644 index 0000000..815e5f0 --- /dev/null +++ b/tools/build/build-config.json @@ -0,0 +1,19 @@ +{ + "@ngx-meta": { + "core": { + "angularVersion": 4, + "bundle": { + "globals": { + "@angular/platform-browser": "ng.platformBrowser", + "@angular/router": "ng.router", + "rxjs/Observable": "Rx.Observable" + }, + "external": [ + "rxjs/add/observable/of", + "rxjs/add/observable/fromPromise" + ] + }, + "runTests": true + } + } +} diff --git a/tools/build/helpers.ts b/tools/build/helpers.ts new file mode 100644 index 0000000..3c96c09 --- /dev/null +++ b/tools/build/helpers.ts @@ -0,0 +1,10 @@ +import * as path from 'path'; + +export const NODE_MODULES = 'node_modules'; + +export function root(args: any = ''): string { + const ROOT = path.resolve(__dirname, '../..'); + args = [].slice.call(arguments, 0); + + return path.join.apply(path, [ROOT].concat(args)); +} diff --git a/tools/build/inline-resources.ts b/tools/build/inline-resources.ts new file mode 100644 index 0000000..9133884 --- /dev/null +++ b/tools/build/inline-resources.ts @@ -0,0 +1,73 @@ +import { readFile, readFileSync, writeFile } from 'fs'; +import * as path from 'path'; +import * as glob from 'glob'; + +const inlineTemplate = (content: string, urlResolver: Function) => + content.replace(/templateUrl:\s*'([^']+?\.html)'/g, (m, templateUrl) => { + const templateFile = urlResolver(templateUrl); + const templateContent = readFileSync(templateFile, {encoding: 'utf-8'}); + const shortenedTemplate = (templateContent as string) + .replace(/([\n\r]\s*)+/gm, ' ') + .replace(/"/g, '\\"'); + + return `template: "${shortenedTemplate}"`; + }); + +const inlineStyle = (content: string, urlResolver: Function) => + content.replace(/styleUrls:\s*(\[[\s\S]*?\])/gm, (m, styleUrls) => { + // tslint:disable-next-line + const urls = eval(styleUrls); + + const res = urls.map((styleUrl: string) => { + const styleFile = urlResolver(styleUrl); + const styleContent = readFileSync(styleFile, {encoding: 'utf-8'}); + const shortenedStyle = (styleContent as string) + .replace(/([\n\r]\s*)+/gm, ' ') + .replace(/"/g, '\\"'); + + return `"${shortenedStyle}"`; + }); + + return `styles: [${res}]`; + }); + +const inlineResourcesFromString = (content: string, urlResolver: Function) => [ + inlineTemplate, + inlineStyle +].reduce((res, fn) => fn(res, urlResolver), content); + +function promiseify(fn: any): any { + return function(): any { + const args = [].slice.call(arguments, 0); + + return new Promise((resolve, reject) => { + // tslint:disable-next-line + fn.apply(this, args.concat([(err: any, value: any) => { + if (err) + reject(err); + else + resolve(value); + }])); + }); + }; +} + +const readFileAsync = promiseify(readFile); +const writeFileAsync = promiseify(writeFile); + +export const inlineResources = (projectPath: string) => { + const files = glob.sync('**/*.ts', {cwd: projectPath}); + + return Promise.all(files + .map((filePath: string) => { + const fullFilePath = path.join(projectPath, filePath); + + return readFileAsync(fullFilePath, 'utf-8') + .then((content: string) => inlineResourcesFromString(content, + (url: string) => path.join(path.dirname(fullFilePath), url))) + .then((content: string) => writeFileAsync(fullFilePath, content)) + .catch((err: string) => { + console.error('An error occured: ', err); + }); + })); +}; diff --git a/tools/build/rollup.ts b/tools/build/rollup.ts new file mode 100644 index 0000000..10bd8ab --- /dev/null +++ b/tools/build/rollup.ts @@ -0,0 +1,206 @@ +import { existsSync, mkdirSync, readFileSync, writeFileSync } from 'fs'; +import * as path from 'path'; +import * as glob from 'glob'; +import * as camelCase from 'camelcase'; +import { main as ngc } from '@angular/compiler-cli/src/main'; +import * as rollup from 'rollup'; +import * as commonJs from 'rollup-plugin-commonjs'; +import * as sourceMaps from 'rollup-plugin-sourcemaps'; +import * as resolve from 'rollup-plugin-node-resolve'; +import * as uglify from 'rollup-plugin-uglify'; + +import { NODE_MODULES, root } from './helpers'; +import { inlineResources } from './inline-resources'; + +const compilationFolder = root('.temp'); +let globals = { + tslib: 'tslib', + '@angular/core': 'ng.core' +}; + +const relativeCopy = (fileGlob: string, from: string, to: string) => { + return new Promise((res, reject) => { + glob(fileGlob, { + cwd: from, + nodir: true + }, (err: string, files: Array) => { + if (err) + reject(err); + + for (const file of files) { + if (file.indexOf(NODE_MODULES) >= 0) + continue; + + const origin = path.join(from, file); + const destination = path.join(to, file); + const data = readFileSync(origin, 'utf-8'); + + recursiveMkDir(path.dirname(destination)); + writeFileSync(destination, data); + } + + res(); + }); + }); +}; + +const recursiveMkDir = (dir: string) => { + if (!existsSync(dir)) { + recursiveMkDir(path.dirname(dir)); + mkdirSync(dir); + } +}; + +import * as buildConfig from './build-config.json'; + +const build = (group: string, item: string, settings: any) => { + const paths = { + src: root(`packages/${group}/${item}`), + temp: path.join(compilationFolder, `packages/${group}/${item}`), + es2015: path.join(compilationFolder, `packages/${group}/${item}-es2015`), + es5: path.join(compilationFolder, `packages/${group}/${item}-es5`), + dist: root(`dist/${group}/${item}`) + }; + + globals = { + ...globals, + ...settings.bundle.globals + }; + const external = settings.bundle.external + ? settings.bundle.external.concat(Object.keys(globals)) + : Object.keys(globals); + + return Promise.resolve() + .then(() => relativeCopy('**/*', paths.src, paths.temp) + .then(() => inlineResources(paths.temp)) + // tslint:disable-next-line + .then(() => console.log(`>>> ${group}/${item}: Inlining succeeded`)) + ) + .then(() => ngc({project: `${paths.temp}/tsconfig.es2015.json`}) + .then(exitCode => new Promise((res, reject) => { + exitCode === 0 + ? res() + : reject(); + })) + // tslint:disable-next-line + .then(() => console.log(`>>> ${group}/${item}: ES2015 compilation succeeded`)) + ) + .then(() => ngc({project: `${paths.temp}/tsconfig.es5.json`}) + .then(exitCode => new Promise((res, reject) => { + exitCode === 0 + ? res() + : reject(); + })) + // tslint:disable-next-line + .then(() => console.log(`>>> ${group}/${item}: ES5 compilation succeeded`)) + ) + .then(() => Promise.resolve() + .then(() => relativeCopy('**/*.d.ts', paths.es2015, paths.dist)) + .then(() => relativeCopy('**/*.metadata.json', paths.es2015, paths.dist)) + // tslint:disable-next-line + .then(() => console.log(`>>> ${group}/${item}: Typings and metadata copy succeeded`)) + ) + .then(() => { + const es5Entry = path.join(paths.es5, `${settings.angularVersion > 2 ? item : 'index'}.js`); + const es2015Entry = path.join(paths.es2015, `${settings.angularVersion > 2 ? item : 'index'}.js`); + const rollupBaseConfig = { + moduleName: `${camelCase(group.replace(/@/g, ''))}.${camelCase(item)}`, + sourceMap: true, + globals, + external, + plugins: [ + resolve({ + module: true, + jsnext: true + }), + commonJs({ + include: ['node_modules/rxjs/**'] + }), + sourceMaps() + ] + }; + + const umdConfig = { + ...rollupBaseConfig, + entry: es5Entry, + dest: path.join(paths.dist, 'bundles', `${item}.umd.js`), + format: 'umd' + }; + + const minUmdConfig = { + ...rollupBaseConfig, + entry: es5Entry, + dest: path.join(paths.dist, 'bundles', `${item}.umd.min.js`), + format: 'umd', + plugins: rollupBaseConfig.plugins.concat([uglify({})]) + }; + + const es5config = { + ...rollupBaseConfig, + entry: es5Entry, + dest: path.join(paths.dist, `${group}/${item}.es5.js`), + format: 'es' + }; + + const es2015config = { + ...rollupBaseConfig, + entry: es2015Entry, + dest: path.join(paths.dist, `${group}/${item}.js`), + format: 'es' + }; + + const bundles = [ + umdConfig, + minUmdConfig, + es5config, + es2015config + ] + .map(options => rollup.rollup(options) + .then((bundle: any) => bundle.write(options))); + + return Promise.all(bundles) + // tslint:disable-next-line + .then(() => console.log(`>>> ${group}/${item}: All bundles generated successfully`)); + }) + .then(() => Promise.resolve() + .then(() => relativeCopy('LICENSE', root(), paths.dist)) + .then(() => relativeCopy('package.json', paths.src, paths.dist)) + .then(() => relativeCopy('README.md', paths.src, paths.dist)) + // tslint:disable-next-line + .then(() => console.log(`>>> ${group}/${item}: Package files copy succeeded`)) + // tslint:disable-next-line + .then(() => console.log(`\n`)) + ) + .catch(e => { + console.error(`>>> ${group}/${item}: Build failed, see below for errors\n`); + console.error(e); + process.exit(1); + }); +}; + +const libs = []; + +for (const group of Object.keys(buildConfig)) + if (group !== '__once__') + for (const item of Object.keys(buildConfig[group])) + libs.push({ + group, + item, + settings: buildConfig[group][item] + }); + else + libs.push({ + group: '', + item: Object.keys(buildConfig[group])[0], + settings: buildConfig[group][Object.keys(buildConfig[group])[0]] + }); + +const toSeries = (series: any) => series + .reduce((promise: Promise, fn: Function) => promise + .then((res: any) => fn() + .then(Array.prototype.concat.bind(res))), Promise.resolve([])); + +const builds = libs + .map((lib: any) => () => build(lib.group, lib.item, lib.settings)); + +toSeries(builds); diff --git a/tools/typings.d.ts b/tools/typings.d.ts new file mode 100644 index 0000000..c9980c6 --- /dev/null +++ b/tools/typings.d.ts @@ -0,0 +1,5 @@ +// custom typings +declare module '*' { + let json: any; + export = json; +} diff --git a/tsconfig.json b/tsconfig.json index acc36b0..e6516a1 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -5,8 +5,6 @@ "moduleResolution": "node", "emitDecoratorMetadata": true, "experimentalDecorators": true, - "noImplicitAny": true, - "suppressImplicitAnyIndexErrors": true, "importHelpers": true, "lib": [ "es2017", @@ -14,10 +12,7 @@ ] }, "include": [ - "scripts/*.ts", + "tools/**/*.ts", "packages/**/*.ts" - ], - "exclude": [ - "node_modules" ] }