From 6cf93ab64c16e85e4bad38d2fe302d049c633a1c Mon Sep 17 00:00:00 2001 From: Hans Larsen Date: Tue, 23 May 2017 15:11:52 -0700 Subject: [PATCH 01/12] refactor: various housekeeping stuff --- .gitignore | 2 + .nvmrc | 1 + package.json | 24 +- tsconfig.json | 21 +- yarn.lock | 1806 +++++++++++++++++++++++++++++++++++++++++++++++++ 5 files changed, 1840 insertions(+), 14 deletions(-) create mode 100644 .nvmrc create mode 100644 yarn.lock diff --git a/.gitignore b/.gitignore index 00edd8eb80..8297c37d03 100644 --- a/.gitignore +++ b/.gitignore @@ -1,4 +1,5 @@ # Outputs +bazel-* build/ dist/ @@ -11,6 +12,7 @@ jsconfig.json typings/ # Misc +coverage/ node_modules/ tmp/ npm-debug.log* diff --git a/.nvmrc b/.nvmrc new file mode 100644 index 0000000000..62f9457511 --- /dev/null +++ b/.nvmrc @@ -0,0 +1 @@ +6 \ No newline at end of file diff --git a/package.json b/package.json index c9c67e9e07..2863b49dfd 100644 --- a/package.json +++ b/package.json @@ -3,10 +3,14 @@ "version": "0.0.0", "description": "Software Development Kit for Angular", "bin": { - "sdk-admin": "./bin/sdk-admin" + "sdk-admin": "./bin/sdk-admin", + "schematics": "./bin/schematics" }, "keywords": [], - "scripts": {}, + "scripts": { + "build": "sdk-admin build", + "test": "sdk-admin test" + }, "repository": { "type": "git", "url": "https://github.com/angular/sdk.git" @@ -22,28 +26,34 @@ }, "homepage": "https://github.com/angular/sdk", "dependencies": { + "@ngtools/json-schema": "^1.0.9", + "@ngtools/logger": "^1.0.1", "@types/chalk": "^0.4.28", "@types/common-tags": "^1.2.4", "@types/glob": "^5.0.29", - "@types/jasmine": "~2.2.0", + "@types/istanbul": "^0.4.29", + "@types/jasmine": "^2.5.47", "@types/minimist": "^1.2.0", "@types/node": "^6.0.36", "@types/semver": "^5.3.30", - "chai": "^3.5.0", + "@types/source-map": "^0.5.0", "chalk": "^1.1.3", "common-tags": "^1.3.1", "conventional-changelog": "^1.1.0", "glob": "^7.0.3", - "jasmine": "^2.4.1", + "istanbul": "^0.4.5", + "jasmine": "^2.6.0", "jasmine-spec-reporter": "^3.2.0", - "minimatch": "^3.0.3", + "marked-terminal": "^2.0.0", "minimist": "^1.2.0", "npm-run": "^4.1.0", "npm-run-all": "^4.0.0", "rxjs": "^5.0.1", "semver": "^5.3.0", + "source-map": "^0.5.6", + "temp": "^0.8.3", "ts-node": "^2.0.0", "tslint": "^4.0.2", - "typescript": "~2.2.0" + "typescript": "~2.3.0" } } diff --git a/tsconfig.json b/tsconfig.json index d96166a3c2..dcc70bea6a 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -3,7 +3,6 @@ "declaration": true, "emitDecoratorMetadata": true, "experimentalDecorators": true, - "mapRoot": "", "module": "commonjs", "moduleResolution": "node", "noEmitOnError": true, @@ -13,12 +12,15 @@ "outDir": "./build", "rootDir": ".", "skipLibCheck": true, - "sourceMap": true, - "sourceRoot": "", + "inlineSourceMap": true, + "sourceRoot": ".", + // Inline sources are necessary for out tests to show the proper sources, since we are using + // Istanbul (not Constantinople) as well, and applying both source maps to get the original + // source in devtools. + "inlineSources": true, + "strictNullChecks": true, "target": "es6", "lib": [ - "es2015", - "es2016", "es2017" ], "baseUrl": "", @@ -28,12 +30,17 @@ "types": [ "jasmine", "node" - ] + ], + "paths": { + "@angular/schematics": [ "./packages/schematics/src/index" ] + } }, "exclude": [ + "bazel-*/**/*", "build/**/*", "dist/**/*", "node_modules/**/*", - "tmp/**/*" + "tmp/**/*", + "packages/schematics-cli/schematics/*/files/**" ] } diff --git a/yarn.lock b/yarn.lock new file mode 100644 index 0000000000..723362359c --- /dev/null +++ b/yarn.lock @@ -0,0 +1,1806 @@ +# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. +# yarn lockfile v1 + + +"@ngtools/json-schema@^1.0.9": + version "1.0.9" + resolved "https://registry.yarnpkg.com/@ngtools/json-schema/-/json-schema-1.0.9.tgz#19e46db409c66b4c43841eab514ff9640871affc" + +"@ngtools/logger@^1.0.1": + version "1.0.2" + resolved "https://registry.yarnpkg.com/@ngtools/logger/-/logger-1.0.2.tgz#51db0a60ddace9bbfaee1f93e48fed935f2461ed" + dependencies: + rxjs "^5.0.1" + +"@types/chalk@^0.4.28": + version "0.4.31" + resolved "https://registry.yarnpkg.com/@types/chalk/-/chalk-0.4.31.tgz#a31d74241a6b1edbb973cf36d97a2896834a51f9" + +"@types/common-tags@^1.2.4": + version "1.2.5" + resolved "https://registry.yarnpkg.com/@types/common-tags/-/common-tags-1.2.5.tgz#14f29893992eb325594b83d739af02f2b6520f46" + +"@types/glob@^5.0.29": + version "5.0.30" + resolved "https://registry.yarnpkg.com/@types/glob/-/glob-5.0.30.tgz#1026409c5625a8689074602808d082b2867b8a51" + dependencies: + "@types/minimatch" "*" + "@types/node" "*" + +"@types/istanbul@^0.4.29": + version "0.4.29" + resolved "https://registry.yarnpkg.com/@types/istanbul/-/istanbul-0.4.29.tgz#29c8cbb747ac57280965545dc58514ba0dbb99af" + +"@types/jasmine@^2.5.47": + version "2.5.47" + resolved "https://registry.yarnpkg.com/@types/jasmine/-/jasmine-2.5.47.tgz#bbba9bcf0e95e7890c6f4a47394e8bacaa960eb6" + +"@types/minimatch@*": + version "2.0.29" + resolved "https://registry.yarnpkg.com/@types/minimatch/-/minimatch-2.0.29.tgz#5002e14f75e2d71e564281df0431c8c1b4a2a36a" + +"@types/minimist@^1.2.0": + version "1.2.0" + resolved "https://registry.yarnpkg.com/@types/minimist/-/minimist-1.2.0.tgz#69a23a3ad29caf0097f06eda59b361ee2f0639f6" + +"@types/node@*", "@types/node@^6.0.36": + version "6.0.73" + resolved "https://registry.yarnpkg.com/@types/node/-/node-6.0.73.tgz#85dc4bb6f125377c75ddd2519a1eeb63f0a4ed70" + +"@types/semver@^5.3.30": + version "5.3.31" + resolved "https://registry.yarnpkg.com/@types/semver/-/semver-5.3.31.tgz#b999d7d935f43f5207b01b00d3de20852f4ca75f" + +"@types/source-map@^0.5.0": + version "0.5.0" + resolved "https://registry.yarnpkg.com/@types/source-map/-/source-map-0.5.0.tgz#dd34bbd8e32fe4e74f2e3d8ac07f8aa5b45a47ac" + +JSONStream@^1.0.4: + version "1.3.1" + resolved "https://registry.yarnpkg.com/JSONStream/-/JSONStream-1.3.1.tgz#707f761e01dae9e16f1bcf93703b78c70966579a" + dependencies: + jsonparse "^1.2.0" + through ">=2.2.7 <3" + +abbrev@1, abbrev@1.0.x: + version "1.0.9" + resolved "https://registry.yarnpkg.com/abbrev/-/abbrev-1.0.9.tgz#91b4792588a7738c25f35dd6f63752a2f8776135" + +align-text@^0.1.1, align-text@^0.1.3: + version "0.1.4" + resolved "https://registry.yarnpkg.com/align-text/-/align-text-0.1.4.tgz#0cd90a561093f35d0a99256c22b7069433fad117" + dependencies: + kind-of "^3.0.2" + longest "^1.0.1" + repeat-string "^1.5.2" + +amdefine@>=0.0.4: + version "1.0.1" + resolved "https://registry.yarnpkg.com/amdefine/-/amdefine-1.0.1.tgz#4a5282ac164729e93619bcfd3ad151f817ce91f5" + +ansi-align@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/ansi-align/-/ansi-align-2.0.0.tgz#c36aeccba563b89ceb556f3690f0b1d9e3547f7f" + dependencies: + string-width "^2.0.0" + +ansi-regex@^2.0.0: + version "2.1.1" + resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-2.1.1.tgz#c3b33ab5ee360d86e0e628f0468ae7ef27d654df" + +ansi-styles@^2.2.1: + version "2.2.1" + resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-2.2.1.tgz#b432dd3358b634cf75e1e4664368240533c1ddbe" + +ansicolors@~0.2.1: + version "0.2.1" + resolved "https://registry.yarnpkg.com/ansicolors/-/ansicolors-0.2.1.tgz#be089599097b74a5c9c4a84a0cdbcdb62bd87aef" + +argparse@^1.0.7: + version "1.0.9" + resolved "https://registry.yarnpkg.com/argparse/-/argparse-1.0.9.tgz#73d83bc263f86e97f8cc4f6bae1b0e90a7d22c86" + dependencies: + sprintf-js "~1.0.2" + +array-filter@~0.0.0: + version "0.0.1" + resolved "https://registry.yarnpkg.com/array-filter/-/array-filter-0.0.1.tgz#7da8cf2e26628ed732803581fd21f67cacd2eeec" + +array-find-index@^1.0.1: + version "1.0.2" + resolved "https://registry.yarnpkg.com/array-find-index/-/array-find-index-1.0.2.tgz#df010aa1287e164bbda6f9723b0a96a1ec4187a1" + +array-ify@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/array-ify/-/array-ify-1.0.0.tgz#9e528762b4a9066ad163a6962a364418e9626ece" + +array-map@~0.0.0: + version "0.0.0" + resolved "https://registry.yarnpkg.com/array-map/-/array-map-0.0.0.tgz#88a2bab73d1cf7bcd5c1b118a003f66f665fa662" + +array-reduce@~0.0.0: + version "0.0.0" + resolved "https://registry.yarnpkg.com/array-reduce/-/array-reduce-0.0.0.tgz#173899d3ffd1c7d9383e4479525dbe278cab5f2b" + +arrify@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/arrify/-/arrify-1.0.1.tgz#898508da2226f380df904728456849c1501a4b0d" + +async@1.x, async@^1.4.0: + version "1.5.2" + resolved "https://registry.yarnpkg.com/async/-/async-1.5.2.tgz#ec6a61ae56480c0c3cb241c95618e20892f9672a" + +babel-code-frame@^6.20.0: + version "6.22.0" + resolved "https://registry.yarnpkg.com/babel-code-frame/-/babel-code-frame-6.22.0.tgz#027620bee567a88c32561574e7fd0801d33118e4" + dependencies: + chalk "^1.1.0" + esutils "^2.0.2" + js-tokens "^3.0.0" + +babel-runtime@^6.18.0: + version "6.23.0" + resolved "https://registry.yarnpkg.com/babel-runtime/-/babel-runtime-6.23.0.tgz#0a9489f144de70efb3ce4300accdb329e2fc543b" + dependencies: + core-js "^2.4.0" + regenerator-runtime "^0.10.0" + +balanced-match@^0.4.1: + version "0.4.2" + resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-0.4.2.tgz#cb3f3e3c732dc0f01ee70b403f302e61d7709838" + +boxen@^1.0.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/boxen/-/boxen-1.1.0.tgz#b1b69dd522305e807a99deee777dbd6e5167b102" + dependencies: + ansi-align "^2.0.0" + camelcase "^4.0.0" + chalk "^1.1.1" + cli-boxes "^1.0.0" + string-width "^2.0.0" + term-size "^0.1.0" + widest-line "^1.0.0" + +brace-expansion@^1.1.7: + version "1.1.7" + resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-1.1.7.tgz#3effc3c50e000531fb720eaff80f0ae8ef23cf59" + dependencies: + balanced-match "^0.4.1" + concat-map "0.0.1" + +buffer-shims@~1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/buffer-shims/-/buffer-shims-1.0.0.tgz#9978ce317388c649ad8793028c3477ef044a8b51" + +builtin-modules@^1.0.0: + version "1.1.1" + resolved "https://registry.yarnpkg.com/builtin-modules/-/builtin-modules-1.1.1.tgz#270f076c5a72c02f5b65a47df94c5fe3a278892f" + +camelcase-keys@^2.0.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/camelcase-keys/-/camelcase-keys-2.1.0.tgz#308beeaffdf28119051efa1d932213c91b8f92e7" + dependencies: + camelcase "^2.0.0" + map-obj "^1.0.0" + +camelcase@^1.0.2: + version "1.2.1" + resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-1.2.1.tgz#9bb5304d2e0b56698b2c758b08a3eaa9daa58a39" + +camelcase@^2.0.0: + version "2.1.1" + resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-2.1.1.tgz#7c1d16d679a1bbe59ca02cacecfb011e201f5a1f" + +camelcase@^4.0.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-4.1.0.tgz#d545635be1e33c542649c69173e5de6acfae34dd" + +capture-stack-trace@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/capture-stack-trace/-/capture-stack-trace-1.0.0.tgz#4a6fa07399c26bba47f0b2496b4d0fb408c5550d" + +cardinal@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/cardinal/-/cardinal-1.0.0.tgz#50e21c1b0aa37729f9377def196b5a9cec932ee9" + dependencies: + ansicolors "~0.2.1" + redeyed "~1.0.0" + +center-align@^0.1.1: + version "0.1.3" + resolved "https://registry.yarnpkg.com/center-align/-/center-align-0.1.3.tgz#aa0d32629b6ee972200411cbd4461c907bc2b7ad" + dependencies: + align-text "^0.1.3" + lazy-cache "^1.0.3" + +chalk@^1.0.0, chalk@^1.1.0, chalk@^1.1.1, chalk@^1.1.3: + version "1.1.3" + resolved "https://registry.yarnpkg.com/chalk/-/chalk-1.1.3.tgz#a8115c55e4a702fe4d150abd3872822a7e09fc98" + dependencies: + ansi-styles "^2.2.1" + escape-string-regexp "^1.0.2" + has-ansi "^2.0.0" + strip-ansi "^3.0.0" + supports-color "^2.0.0" + +cli-boxes@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/cli-boxes/-/cli-boxes-1.0.0.tgz#4fa917c3e59c94a004cd61f8ee509da651687143" + +cli-table@^0.3.1: + version "0.3.1" + resolved "https://registry.yarnpkg.com/cli-table/-/cli-table-0.3.1.tgz#f53b05266a8b1a0b934b3d0821e6e2dc5914ae23" + dependencies: + colors "1.0.3" + +cliui@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/cliui/-/cliui-2.1.0.tgz#4b475760ff80264c762c3a1719032e91c7fea0d1" + dependencies: + center-align "^0.1.1" + right-align "^0.1.1" + wordwrap "0.0.2" + +code-point-at@^1.0.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/code-point-at/-/code-point-at-1.1.0.tgz#0d070b4d043a5bea33a2f1a40e2edb3d9a4ccf77" + +colors@1.0.3: + version "1.0.3" + resolved "https://registry.yarnpkg.com/colors/-/colors-1.0.3.tgz#0433f44d809680fdeb60ed260f1b0c262e82a40b" + +colors@1.1.2, colors@^1.1.2: + version "1.1.2" + resolved "https://registry.yarnpkg.com/colors/-/colors-1.1.2.tgz#168a4701756b6a7f51a12ce0c97bfa28c084ed63" + +commander@^2.9.0: + version "2.9.0" + resolved "https://registry.yarnpkg.com/commander/-/commander-2.9.0.tgz#9c99094176e12240cb22d6c5146098400fe0f7d4" + dependencies: + graceful-readlink ">= 1.0.0" + +common-tags@^1.3.1: + version "1.4.0" + resolved "https://registry.yarnpkg.com/common-tags/-/common-tags-1.4.0.tgz#1187be4f3d4cf0c0427d43f74eef1f73501614c0" + dependencies: + babel-runtime "^6.18.0" + +compare-func@^1.3.1: + version "1.3.2" + resolved "https://registry.yarnpkg.com/compare-func/-/compare-func-1.3.2.tgz#99dd0ba457e1f9bc722b12c08ec33eeab31fa648" + dependencies: + array-ify "^1.0.0" + dot-prop "^3.0.0" + +concat-map@0.0.1: + version "0.0.1" + resolved "https://registry.yarnpkg.com/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b" + +configstore@^3.0.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/configstore/-/configstore-3.1.0.tgz#45df907073e26dfa1cf4b2d52f5b60545eaa11d1" + dependencies: + dot-prop "^4.1.0" + graceful-fs "^4.1.2" + make-dir "^1.0.0" + unique-string "^1.0.0" + write-file-atomic "^2.0.0" + xdg-basedir "^3.0.0" + +conventional-changelog-angular@^1.3.4: + version "1.3.4" + resolved "https://registry.yarnpkg.com/conventional-changelog-angular/-/conventional-changelog-angular-1.3.4.tgz#7d7cdfbd358948312904d02229a61fd6075cf455" + dependencies: + compare-func "^1.3.1" + github-url-from-git "^1.4.0" + q "^1.4.1" + +conventional-changelog-atom@^0.1.0: + version "0.1.0" + resolved "https://registry.yarnpkg.com/conventional-changelog-atom/-/conventional-changelog-atom-0.1.0.tgz#67a47c66a42b2f8909ef1587c9989ae1de730b92" + dependencies: + q "^1.4.1" + +conventional-changelog-codemirror@^0.1.0: + version "0.1.0" + resolved "https://registry.yarnpkg.com/conventional-changelog-codemirror/-/conventional-changelog-codemirror-0.1.0.tgz#7577a591dbf9b538e7a150a7ee62f65a2872b334" + dependencies: + q "^1.4.1" + +conventional-changelog-core@^1.9.0: + version "1.9.0" + resolved "https://registry.yarnpkg.com/conventional-changelog-core/-/conventional-changelog-core-1.9.0.tgz#de5dfbc091847656508d4a389e35c9a1bc49e7f4" + dependencies: + conventional-changelog-writer "^1.1.0" + conventional-commits-parser "^1.0.0" + dateformat "^1.0.12" + get-pkg-repo "^1.0.0" + git-raw-commits "^1.2.0" + git-remote-origin-url "^2.0.0" + git-semver-tags "^1.2.0" + lodash "^4.0.0" + normalize-package-data "^2.3.5" + q "^1.4.1" + read-pkg "^1.1.0" + read-pkg-up "^1.0.1" + through2 "^2.0.0" + +conventional-changelog-ember@^0.2.6: + version "0.2.6" + resolved "https://registry.yarnpkg.com/conventional-changelog-ember/-/conventional-changelog-ember-0.2.6.tgz#8b7355419f5127493c4c562473ab2fc792f1c2b6" + dependencies: + q "^1.4.1" + +conventional-changelog-eslint@^0.1.0: + version "0.1.0" + resolved "https://registry.yarnpkg.com/conventional-changelog-eslint/-/conventional-changelog-eslint-0.1.0.tgz#a52411e999e0501ce500b856b0a643d0330907e2" + dependencies: + q "^1.4.1" + +conventional-changelog-express@^0.1.0: + version "0.1.0" + resolved "https://registry.yarnpkg.com/conventional-changelog-express/-/conventional-changelog-express-0.1.0.tgz#55c6c841c811962036c037bdbd964a54ae310fce" + dependencies: + q "^1.4.1" + +conventional-changelog-jquery@^0.1.0: + version "0.1.0" + resolved "https://registry.yarnpkg.com/conventional-changelog-jquery/-/conventional-changelog-jquery-0.1.0.tgz#0208397162e3846986e71273b6c79c5b5f80f510" + dependencies: + q "^1.4.1" + +conventional-changelog-jscs@^0.1.0: + version "0.1.0" + resolved "https://registry.yarnpkg.com/conventional-changelog-jscs/-/conventional-changelog-jscs-0.1.0.tgz#0479eb443cc7d72c58bf0bcf0ef1d444a92f0e5c" + dependencies: + q "^1.4.1" + +conventional-changelog-jshint@^0.1.0: + version "0.1.0" + resolved "https://registry.yarnpkg.com/conventional-changelog-jshint/-/conventional-changelog-jshint-0.1.0.tgz#00cab8e9a3317487abd94c4d84671342918d2a07" + dependencies: + compare-func "^1.3.1" + q "^1.4.1" + +conventional-changelog-writer@^1.1.0: + version "1.4.1" + resolved "https://registry.yarnpkg.com/conventional-changelog-writer/-/conventional-changelog-writer-1.4.1.tgz#3f4cb4d003ebb56989d30d345893b52a43639c8e" + dependencies: + compare-func "^1.3.1" + conventional-commits-filter "^1.0.0" + dateformat "^1.0.11" + handlebars "^4.0.2" + json-stringify-safe "^5.0.1" + lodash "^4.0.0" + meow "^3.3.0" + semver "^5.0.1" + split "^1.0.0" + through2 "^2.0.0" + +conventional-changelog@^1.1.0: + version "1.1.4" + resolved "https://registry.yarnpkg.com/conventional-changelog/-/conventional-changelog-1.1.4.tgz#108bc750c2a317e200e2f9b413caaa1f8c7efa3b" + dependencies: + conventional-changelog-angular "^1.3.4" + conventional-changelog-atom "^0.1.0" + conventional-changelog-codemirror "^0.1.0" + conventional-changelog-core "^1.9.0" + conventional-changelog-ember "^0.2.6" + conventional-changelog-eslint "^0.1.0" + conventional-changelog-express "^0.1.0" + conventional-changelog-jquery "^0.1.0" + conventional-changelog-jscs "^0.1.0" + conventional-changelog-jshint "^0.1.0" + +conventional-commits-filter@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/conventional-commits-filter/-/conventional-commits-filter-1.0.0.tgz#6fc2a659372bc3f2339cf9ffff7e1b0344b93039" + dependencies: + is-subset "^0.1.1" + modify-values "^1.0.0" + +conventional-commits-parser@^1.0.0: + version "1.3.0" + resolved "https://registry.yarnpkg.com/conventional-commits-parser/-/conventional-commits-parser-1.3.0.tgz#e327b53194e1a7ad5dc63479ee9099a52b024865" + dependencies: + JSONStream "^1.0.4" + is-text-path "^1.0.0" + lodash "^4.2.1" + meow "^3.3.0" + split2 "^2.0.0" + through2 "^2.0.0" + trim-off-newlines "^1.0.0" + +core-js@^2.4.0: + version "2.4.1" + resolved "https://registry.yarnpkg.com/core-js/-/core-js-2.4.1.tgz#4de911e667b0eae9124e34254b53aea6fc618d3e" + +core-util-is@~1.0.0: + version "1.0.2" + resolved "https://registry.yarnpkg.com/core-util-is/-/core-util-is-1.0.2.tgz#b5fd54220aa2bc5ab57aab7140c940754503c1a7" + +create-error-class@^3.0.0: + version "3.0.2" + resolved "https://registry.yarnpkg.com/create-error-class/-/create-error-class-3.0.2.tgz#06be7abef947a3f14a30fd610671d401bca8b7b6" + dependencies: + capture-stack-trace "^1.0.0" + +cross-spawn-async@^2.1.1: + version "2.2.5" + resolved "https://registry.yarnpkg.com/cross-spawn-async/-/cross-spawn-async-2.2.5.tgz#845ff0c0834a3ded9d160daca6d390906bb288cc" + dependencies: + lru-cache "^4.0.0" + which "^1.2.8" + +cross-spawn@^5.0.1, cross-spawn@^5.1.0: + version "5.1.0" + resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-5.1.0.tgz#e8bd0efee58fcff6f8f94510a0a554bbfa235449" + dependencies: + lru-cache "^4.0.1" + shebang-command "^1.2.0" + which "^1.2.9" + +crypto-random-string@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/crypto-random-string/-/crypto-random-string-1.0.0.tgz#a230f64f568310e1498009940790ec99545bca7e" + +currently-unhandled@^0.4.1: + version "0.4.1" + resolved "https://registry.yarnpkg.com/currently-unhandled/-/currently-unhandled-0.4.1.tgz#988df33feab191ef799a61369dd76c17adf957ea" + dependencies: + array-find-index "^1.0.1" + +dargs@^4.0.1: + version "4.1.0" + resolved "https://registry.yarnpkg.com/dargs/-/dargs-4.1.0.tgz#03a9dbb4b5c2f139bf14ae53f0b8a2a6a86f4e17" + dependencies: + number-is-nan "^1.0.0" + +dateformat@^1.0.11, dateformat@^1.0.12: + version "1.0.12" + resolved "https://registry.yarnpkg.com/dateformat/-/dateformat-1.0.12.tgz#9f124b67594c937ff706932e4a642cca8dbbfee9" + dependencies: + get-stdin "^4.0.1" + meow "^3.3.0" + +decamelize@^1.0.0, decamelize@^1.1.2: + version "1.2.0" + resolved "https://registry.yarnpkg.com/decamelize/-/decamelize-1.2.0.tgz#f6534d15148269b20352e7bee26f501f9a191290" + +deep-extend@~0.4.0: + version "0.4.2" + resolved "https://registry.yarnpkg.com/deep-extend/-/deep-extend-0.4.2.tgz#48b699c27e334bf89f10892be432f6e4c7d34a7f" + +deep-is@~0.1.3: + version "0.1.3" + resolved "https://registry.yarnpkg.com/deep-is/-/deep-is-0.1.3.tgz#b369d6fb5dbc13eecf524f91b070feedc357cf34" + +define-properties@^1.1.2: + version "1.1.2" + resolved "https://registry.yarnpkg.com/define-properties/-/define-properties-1.1.2.tgz#83a73f2fea569898fb737193c8f873caf6d45c94" + dependencies: + foreach "^2.0.5" + object-keys "^1.0.8" + +diff@^3.0.1, diff@^3.1.0: + version "3.2.0" + resolved "https://registry.yarnpkg.com/diff/-/diff-3.2.0.tgz#c9ce393a4b7cbd0b058a725c93df299027868ff9" + +dot-prop@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/dot-prop/-/dot-prop-3.0.0.tgz#1b708af094a49c9a0e7dbcad790aba539dac1177" + dependencies: + is-obj "^1.0.0" + +dot-prop@^4.1.0: + version "4.1.1" + resolved "https://registry.yarnpkg.com/dot-prop/-/dot-prop-4.1.1.tgz#a8493f0b7b5eeec82525b5c7587fa7de7ca859c1" + dependencies: + is-obj "^1.0.0" + +duplexer3@^0.1.4: + version "0.1.4" + resolved "https://registry.yarnpkg.com/duplexer3/-/duplexer3-0.1.4.tgz#ee01dd1cac0ed3cbc7fdbea37dc0a8f1ce002ce2" + +duplexer@~0.1.1: + version "0.1.1" + resolved "https://registry.yarnpkg.com/duplexer/-/duplexer-0.1.1.tgz#ace6ff808c1ce66b57d1ebf97977acb02334cfc1" + +error-ex@^1.2.0: + version "1.3.1" + resolved "https://registry.yarnpkg.com/error-ex/-/error-ex-1.3.1.tgz#f855a86ce61adc4e8621c3cda21e7a7612c3a8dc" + dependencies: + is-arrayish "^0.2.1" + +es-abstract@^1.4.3: + version "1.7.0" + resolved "https://registry.yarnpkg.com/es-abstract/-/es-abstract-1.7.0.tgz#dfade774e01bfcd97f96180298c449c8623fb94c" + dependencies: + es-to-primitive "^1.1.1" + function-bind "^1.1.0" + is-callable "^1.1.3" + is-regex "^1.0.3" + +es-to-primitive@^1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/es-to-primitive/-/es-to-primitive-1.1.1.tgz#45355248a88979034b6792e19bb81f2b7975dd0d" + dependencies: + is-callable "^1.1.1" + is-date-object "^1.0.1" + is-symbol "^1.0.1" + +escape-string-regexp@^1.0.2: + version "1.0.5" + resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz#1b61c0562190a8dff6ae3bb2cf0200ca130b86d4" + +escodegen@1.8.x: + version "1.8.1" + resolved "https://registry.yarnpkg.com/escodegen/-/escodegen-1.8.1.tgz#5a5b53af4693110bebb0867aa3430dd3b70a1018" + dependencies: + esprima "^2.7.1" + estraverse "^1.9.1" + esutils "^2.0.2" + optionator "^0.8.1" + optionalDependencies: + source-map "~0.2.0" + +esprima@2.7.x, esprima@^2.7.1: + version "2.7.3" + resolved "https://registry.yarnpkg.com/esprima/-/esprima-2.7.3.tgz#96e3b70d5779f6ad49cd032673d1c312767ba581" + +esprima@^3.1.1: + version "3.1.3" + resolved "https://registry.yarnpkg.com/esprima/-/esprima-3.1.3.tgz#fdca51cee6133895e3c88d535ce49dbff62a4633" + +esprima@~3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/esprima/-/esprima-3.0.0.tgz#53cf247acda77313e551c3aa2e73342d3fb4f7d9" + +estraverse@^1.9.1: + version "1.9.3" + resolved "https://registry.yarnpkg.com/estraverse/-/estraverse-1.9.3.tgz#af67f2dc922582415950926091a4005d29c9bb44" + +esutils@^2.0.2: + version "2.0.2" + resolved "https://registry.yarnpkg.com/esutils/-/esutils-2.0.2.tgz#0abf4f1caa5bcb1f7a9d8acc6dea4faaa04bac9b" + +event-stream@~3.3.0: + version "3.3.4" + resolved "https://registry.yarnpkg.com/event-stream/-/event-stream-3.3.4.tgz#4ab4c9a0f5a54db9338b4c34d86bfce8f4b35571" + dependencies: + duplexer "~0.1.1" + from "~0" + map-stream "~0.1.0" + pause-stream "0.0.11" + split "0.3" + stream-combiner "~0.0.4" + through "~2.3.1" + +execa@^0.4.0: + version "0.4.0" + resolved "https://registry.yarnpkg.com/execa/-/execa-0.4.0.tgz#4eb6467a36a095fabb2970ff9d5e3fb7bce6ebc3" + dependencies: + cross-spawn-async "^2.1.1" + is-stream "^1.1.0" + npm-run-path "^1.0.0" + object-assign "^4.0.1" + path-key "^1.0.0" + strip-eof "^1.0.0" + +exit@^0.1.2: + version "0.1.2" + resolved "https://registry.yarnpkg.com/exit/-/exit-0.1.2.tgz#0632638f8d877cc82107d30a0fff1a17cba1cd0c" + +fast-levenshtein@~2.0.4: + version "2.0.6" + resolved "https://registry.yarnpkg.com/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz#3d8a5c66883a16a30ca8643e851f19baa7797917" + +find-up@^1.0.0: + version "1.1.2" + resolved "https://registry.yarnpkg.com/find-up/-/find-up-1.1.2.tgz#6b2e9822b1a2ce0a60ab64d610eccad53cb24d0f" + dependencies: + path-exists "^2.0.0" + pinkie-promise "^2.0.0" + +findup-sync@~0.3.0: + version "0.3.0" + resolved "https://registry.yarnpkg.com/findup-sync/-/findup-sync-0.3.0.tgz#37930aa5d816b777c03445e1966cc6790a4c0b16" + dependencies: + glob "~5.0.0" + +foreach@^2.0.5: + version "2.0.5" + resolved "https://registry.yarnpkg.com/foreach/-/foreach-2.0.5.tgz#0bee005018aeb260d0a3af3ae658dd0136ec1b99" + +from@~0: + version "0.1.7" + resolved "https://registry.yarnpkg.com/from/-/from-0.1.7.tgz#83c60afc58b9c56997007ed1a768b3ab303a44fe" + +fs.realpath@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/fs.realpath/-/fs.realpath-1.0.0.tgz#1504ad2523158caa40db4a2787cb01411994ea4f" + +function-bind@^1.0.2, function-bind@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/function-bind/-/function-bind-1.1.0.tgz#16176714c801798e4e8f2cf7f7529467bb4a5771" + +get-pkg-repo@^1.0.0: + version "1.3.0" + resolved "https://registry.yarnpkg.com/get-pkg-repo/-/get-pkg-repo-1.3.0.tgz#43c6b4c048b75dd604fc5388edecde557f6335df" + dependencies: + hosted-git-info "^2.1.4" + meow "^3.3.0" + normalize-package-data "^2.3.0" + parse-github-repo-url "^1.3.0" + through2 "^2.0.0" + +get-stdin@^4.0.1: + version "4.0.1" + resolved "https://registry.yarnpkg.com/get-stdin/-/get-stdin-4.0.1.tgz#b968c6b0a04384324902e8bf1a5df32579a450fe" + +get-stream@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/get-stream/-/get-stream-3.0.0.tgz#8e943d1358dc37555054ecbe2edb05aa174ede14" + +git-raw-commits@^1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/git-raw-commits/-/git-raw-commits-1.2.0.tgz#0f3a8bfd99ae0f2d8b9224d58892975e9a52d03c" + dependencies: + dargs "^4.0.1" + lodash.template "^4.0.2" + meow "^3.3.0" + split2 "^2.0.0" + through2 "^2.0.0" + +git-remote-origin-url@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/git-remote-origin-url/-/git-remote-origin-url-2.0.0.tgz#5282659dae2107145a11126112ad3216ec5fa65f" + dependencies: + gitconfiglocal "^1.0.0" + pify "^2.3.0" + +git-semver-tags@^1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/git-semver-tags/-/git-semver-tags-1.2.0.tgz#b31fd02c8ab578bd6c9b5cacca5e1c64c1177ac1" + dependencies: + meow "^3.3.0" + semver "^5.0.1" + +gitconfiglocal@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/gitconfiglocal/-/gitconfiglocal-1.0.0.tgz#41d045f3851a5ea88f03f24ca1c6178114464b9b" + dependencies: + ini "^1.3.2" + +github-url-from-git@^1.4.0: + version "1.5.0" + resolved "https://registry.yarnpkg.com/github-url-from-git/-/github-url-from-git-1.5.0.tgz#f985fedcc0a9aa579dc88d7aff068d55cc6251a0" + +glob@^5.0.15, glob@~5.0.0: + version "5.0.15" + resolved "https://registry.yarnpkg.com/glob/-/glob-5.0.15.tgz#1bc936b9e02f4a603fcc222ecf7633d30b8b93b1" + dependencies: + inflight "^1.0.4" + inherits "2" + minimatch "2 || 3" + once "^1.3.0" + path-is-absolute "^1.0.0" + +glob@^7.0.3, glob@^7.0.6, glob@^7.1.1: + version "7.1.2" + resolved "https://registry.yarnpkg.com/glob/-/glob-7.1.2.tgz#c19c9df9a028702d678612384a6552404c636d15" + dependencies: + fs.realpath "^1.0.0" + inflight "^1.0.4" + inherits "2" + minimatch "^3.0.4" + once "^1.3.0" + path-is-absolute "^1.0.0" + +got@^6.7.1: + version "6.7.1" + resolved "https://registry.yarnpkg.com/got/-/got-6.7.1.tgz#240cd05785a9a18e561dc1b44b41c763ef1e8db0" + dependencies: + create-error-class "^3.0.0" + duplexer3 "^0.1.4" + get-stream "^3.0.0" + is-redirect "^1.0.0" + is-retry-allowed "^1.0.0" + is-stream "^1.0.0" + lowercase-keys "^1.0.0" + safe-buffer "^5.0.1" + timed-out "^4.0.0" + unzip-response "^2.0.1" + url-parse-lax "^1.0.0" + +graceful-fs@^4.1.11, graceful-fs@^4.1.2: + version "4.1.11" + resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.1.11.tgz#0e8bdfe4d1ddb8854d64e04ea7c00e2a026e5658" + +"graceful-readlink@>= 1.0.0": + version "1.0.1" + resolved "https://registry.yarnpkg.com/graceful-readlink/-/graceful-readlink-1.0.1.tgz#4cafad76bc62f02fa039b2f94e9a3dd3a391a725" + +handlebars@^4.0.1, handlebars@^4.0.2: + version "4.0.10" + resolved "https://registry.yarnpkg.com/handlebars/-/handlebars-4.0.10.tgz#3d30c718b09a3d96f23ea4cc1f403c4d3ba9ff4f" + dependencies: + async "^1.4.0" + optimist "^0.6.1" + source-map "^0.4.4" + optionalDependencies: + uglify-js "^2.6" + +has-ansi@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/has-ansi/-/has-ansi-2.0.0.tgz#34f5049ce1ecdf2b0649af3ef24e45ed35416d91" + dependencies: + ansi-regex "^2.0.0" + +has-flag@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-1.0.0.tgz#9d9e793165ce017a00f00418c43f942a7b1d11fa" + +has@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/has/-/has-1.0.1.tgz#8461733f538b0837c9361e39a9ab9e9704dc2f28" + dependencies: + function-bind "^1.0.2" + +hosted-git-info@^2.1.4: + version "2.4.2" + resolved "https://registry.yarnpkg.com/hosted-git-info/-/hosted-git-info-2.4.2.tgz#0076b9f46a270506ddbaaea56496897460612a67" + +imurmurhash@^0.1.4: + version "0.1.4" + resolved "https://registry.yarnpkg.com/imurmurhash/-/imurmurhash-0.1.4.tgz#9218b9b2b928a238b13dc4fb6b6d576f231453ea" + +indent-string@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/indent-string/-/indent-string-2.1.0.tgz#8e2d48348742121b4a8218b7a137e9a52049dc80" + dependencies: + repeating "^2.0.0" + +inflight@^1.0.4: + version "1.0.6" + resolved "https://registry.yarnpkg.com/inflight/-/inflight-1.0.6.tgz#49bd6331d7d02d0c09bc910a1075ba8165b56df9" + dependencies: + once "^1.3.0" + wrappy "1" + +inherits@2, inherits@~2.0.1: + version "2.0.3" + resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.3.tgz#633c2c83e3da42a502f52466022480f4208261de" + +ini@^1.3.2, ini@~1.3.0: + version "1.3.4" + resolved "https://registry.yarnpkg.com/ini/-/ini-1.3.4.tgz#0537cb79daf59b59a1a517dff706c86ec039162e" + +is-arrayish@^0.2.1: + version "0.2.1" + resolved "https://registry.yarnpkg.com/is-arrayish/-/is-arrayish-0.2.1.tgz#77c99840527aa8ecb1a8ba697b80645a7a926a9d" + +is-buffer@^1.1.5: + version "1.1.5" + resolved "https://registry.yarnpkg.com/is-buffer/-/is-buffer-1.1.5.tgz#1f3b26ef613b214b88cbca23cc6c01d87961eecc" + +is-builtin-module@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/is-builtin-module/-/is-builtin-module-1.0.0.tgz#540572d34f7ac3119f8f76c30cbc1b1e037affbe" + dependencies: + builtin-modules "^1.0.0" + +is-callable@^1.1.1, is-callable@^1.1.3: + version "1.1.3" + resolved "https://registry.yarnpkg.com/is-callable/-/is-callable-1.1.3.tgz#86eb75392805ddc33af71c92a0eedf74ee7604b2" + +is-date-object@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/is-date-object/-/is-date-object-1.0.1.tgz#9aa20eb6aeebbff77fbd33e74ca01b33581d3a16" + +is-finite@^1.0.0: + version "1.0.2" + resolved "https://registry.yarnpkg.com/is-finite/-/is-finite-1.0.2.tgz#cc6677695602be550ef11e8b4aa6305342b6d0aa" + dependencies: + number-is-nan "^1.0.0" + +is-fullwidth-code-point@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz#ef9e31386f031a7f0d643af82fde50c457ef00cb" + dependencies: + number-is-nan "^1.0.0" + +is-fullwidth-code-point@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz#a3b30a5c4f199183167aaab93beefae3ddfb654f" + +is-npm@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/is-npm/-/is-npm-1.0.0.tgz#f2fb63a65e4905b406c86072765a1a4dc793b9f4" + +is-obj@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/is-obj/-/is-obj-1.0.1.tgz#3e4729ac1f5fde025cd7d83a896dab9f4f67db0f" + +is-redirect@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/is-redirect/-/is-redirect-1.0.0.tgz#1d03dded53bd8db0f30c26e4f95d36fc7c87dc24" + +is-regex@^1.0.3: + version "1.0.4" + resolved "https://registry.yarnpkg.com/is-regex/-/is-regex-1.0.4.tgz#5517489b547091b0930e095654ced25ee97e9491" + dependencies: + has "^1.0.1" + +is-retry-allowed@^1.0.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/is-retry-allowed/-/is-retry-allowed-1.1.0.tgz#11a060568b67339444033d0125a61a20d564fb34" + +is-stream@^1.0.0, is-stream@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/is-stream/-/is-stream-1.1.0.tgz#12d4a3dd4e68e0b79ceb8dbc84173ae80d91ca44" + +is-subset@^0.1.1: + version "0.1.1" + resolved "https://registry.yarnpkg.com/is-subset/-/is-subset-0.1.1.tgz#8a59117d932de1de00f245fcdd39ce43f1e939a6" + +is-symbol@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/is-symbol/-/is-symbol-1.0.1.tgz#3cc59f00025194b6ab2e38dbae6689256b660572" + +is-text-path@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/is-text-path/-/is-text-path-1.0.1.tgz#4e1aa0fb51bfbcb3e92688001397202c1775b66e" + dependencies: + text-extensions "^1.0.0" + +is-utf8@^0.2.0: + version "0.2.1" + resolved "https://registry.yarnpkg.com/is-utf8/-/is-utf8-0.2.1.tgz#4b0da1442104d1b336340e80797e865cf39f7d72" + +isarray@~1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/isarray/-/isarray-1.0.0.tgz#bb935d48582cba168c06834957a54a3e07124f11" + +isexe@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/isexe/-/isexe-2.0.0.tgz#e8fbf374dc556ff8947a10dcb0572d633f2cfa10" + +istanbul@^0.4.5: + version "0.4.5" + resolved "https://registry.yarnpkg.com/istanbul/-/istanbul-0.4.5.tgz#65c7d73d4c4da84d4f3ac310b918fb0b8033733b" + dependencies: + abbrev "1.0.x" + async "1.x" + escodegen "1.8.x" + esprima "2.7.x" + glob "^5.0.15" + handlebars "^4.0.1" + js-yaml "3.x" + mkdirp "0.5.x" + nopt "3.x" + once "1.x" + resolve "1.1.x" + supports-color "^3.1.0" + which "^1.1.1" + wordwrap "^1.0.0" + +jasmine-core@~2.6.0: + version "2.6.2" + resolved "https://registry.yarnpkg.com/jasmine-core/-/jasmine-core-2.6.2.tgz#74ea1f7cf428691af201107d631234027a09daab" + +jasmine-spec-reporter@^3.2.0: + version "3.3.0" + resolved "https://registry.yarnpkg.com/jasmine-spec-reporter/-/jasmine-spec-reporter-3.3.0.tgz#c63c3d43bacfd16e6da86c46d265957e0075f14c" + dependencies: + colors "1.1.2" + +jasmine@^2.6.0: + version "2.6.0" + resolved "https://registry.yarnpkg.com/jasmine/-/jasmine-2.6.0.tgz#6b22e70883e8e589d456346153b4d206ddbe217f" + dependencies: + exit "^0.1.2" + glob "^7.0.6" + jasmine-core "~2.6.0" + +js-tokens@^3.0.0: + version "3.0.1" + resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-3.0.1.tgz#08e9f132484a2c45a30907e9dc4d5567b7f114d7" + +js-yaml@3.x: + version "3.8.4" + resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-3.8.4.tgz#520b4564f86573ba96662af85a8cafa7b4b5a6f6" + dependencies: + argparse "^1.0.7" + esprima "^3.1.1" + +json-stringify-safe@^5.0.1: + version "5.0.1" + resolved "https://registry.yarnpkg.com/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz#1296a2d58fd45f19a0f6ce01d65701e2c735b6eb" + +jsonify@~0.0.0: + version "0.0.0" + resolved "https://registry.yarnpkg.com/jsonify/-/jsonify-0.0.0.tgz#2c74b6ee41d93ca51b7b5aaee8f503631d252a73" + +jsonparse@^1.2.0: + version "1.3.1" + resolved "https://registry.yarnpkg.com/jsonparse/-/jsonparse-1.3.1.tgz#3f4dae4a91fac315f71062f8521cc239f1366280" + +kind-of@^3.0.2: + version "3.2.2" + resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-3.2.2.tgz#31ea21a734bab9bbb0f32466d893aea51e4a3c64" + dependencies: + is-buffer "^1.1.5" + +latest-version@^3.0.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/latest-version/-/latest-version-3.1.0.tgz#a205383fea322b33b5ae3b18abee0dc2f356ee15" + dependencies: + package-json "^4.0.0" + +lazy-cache@^1.0.3: + version "1.0.4" + resolved "https://registry.yarnpkg.com/lazy-cache/-/lazy-cache-1.0.4.tgz#a1d78fc3a50474cb80845d3b3b6e1da49a446e8e" + +lazy-req@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/lazy-req/-/lazy-req-2.0.0.tgz#c9450a363ecdda2e6f0c70132ad4f37f8f06f2b4" + +levn@~0.3.0: + version "0.3.0" + resolved "https://registry.yarnpkg.com/levn/-/levn-0.3.0.tgz#3b09924edf9f083c0490fdd4c0bc4421e04764ee" + dependencies: + prelude-ls "~1.1.2" + type-check "~0.3.2" + +load-json-file@^1.0.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/load-json-file/-/load-json-file-1.1.0.tgz#956905708d58b4bab4c2261b04f59f31c99374c0" + dependencies: + graceful-fs "^4.1.2" + parse-json "^2.2.0" + pify "^2.0.0" + pinkie-promise "^2.0.0" + strip-bom "^2.0.0" + +load-json-file@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/load-json-file/-/load-json-file-2.0.0.tgz#7947e42149af80d696cbf797bcaabcfe1fe29ca8" + dependencies: + graceful-fs "^4.1.2" + parse-json "^2.2.0" + pify "^2.0.0" + strip-bom "^3.0.0" + +lodash._reinterpolate@~3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/lodash._reinterpolate/-/lodash._reinterpolate-3.0.0.tgz#0ccf2d89166af03b3663c796538b75ac6e114d9d" + +lodash.assign@^4.2.0: + version "4.2.0" + resolved "https://registry.yarnpkg.com/lodash.assign/-/lodash.assign-4.2.0.tgz#0d99f3ccd7a6d261d19bdaeb9245005d285808e7" + +lodash.template@^4.0.2: + version "4.4.0" + resolved "https://registry.yarnpkg.com/lodash.template/-/lodash.template-4.4.0.tgz#e73a0385c8355591746e020b99679c690e68fba0" + dependencies: + lodash._reinterpolate "~3.0.0" + lodash.templatesettings "^4.0.0" + +lodash.templatesettings@^4.0.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/lodash.templatesettings/-/lodash.templatesettings-4.1.0.tgz#2b4d4e95ba440d915ff08bc899e4553666713316" + dependencies: + lodash._reinterpolate "~3.0.0" + +lodash@^4.0.0, lodash@^4.2.1: + version "4.17.4" + resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.4.tgz#78203a4d1c328ae1d86dca6460e369b57f4055ae" + +longest@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/longest/-/longest-1.0.1.tgz#30a0b2da38f73770e8294a0d22e6625ed77d0097" + +loud-rejection@^1.0.0: + version "1.6.0" + resolved "https://registry.yarnpkg.com/loud-rejection/-/loud-rejection-1.6.0.tgz#5b46f80147edee578870f086d04821cf998e551f" + dependencies: + currently-unhandled "^0.4.1" + signal-exit "^3.0.0" + +lowercase-keys@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/lowercase-keys/-/lowercase-keys-1.0.0.tgz#4e3366b39e7f5457e35f1324bdf6f88d0bfc7306" + +lru-cache@^4.0.0, lru-cache@^4.0.1: + version "4.0.2" + resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-4.0.2.tgz#1d17679c069cda5d040991a09dbc2c0db377e55e" + dependencies: + pseudomap "^1.0.1" + yallist "^2.0.0" + +make-dir@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/make-dir/-/make-dir-1.0.0.tgz#97a011751e91dd87cfadef58832ebb04936de978" + dependencies: + pify "^2.3.0" + +make-error@^1.1.1: + version "1.3.0" + resolved "https://registry.yarnpkg.com/make-error/-/make-error-1.3.0.tgz#52ad3a339ccf10ce62b4040b708fe707244b8b96" + +map-obj@^1.0.0, map-obj@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/map-obj/-/map-obj-1.0.1.tgz#d933ceb9205d82bdcf4886f6742bdc2b4dea146d" + +map-stream@~0.1.0: + version "0.1.0" + resolved "https://registry.yarnpkg.com/map-stream/-/map-stream-0.1.0.tgz#e56aa94c4c8055a16404a0674b78f215f7c8e194" + +marked-terminal@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/marked-terminal/-/marked-terminal-2.0.0.tgz#5eaf568be66f686541afa52a558280310a31de2d" + dependencies: + cardinal "^1.0.0" + chalk "^1.1.3" + cli-table "^0.3.1" + lodash.assign "^4.2.0" + node-emoji "^1.4.1" + +meow@^3.3.0: + version "3.7.0" + resolved "https://registry.yarnpkg.com/meow/-/meow-3.7.0.tgz#72cb668b425228290abbfa856892587308a801fb" + dependencies: + camelcase-keys "^2.0.0" + decamelize "^1.1.2" + loud-rejection "^1.0.0" + map-obj "^1.0.1" + minimist "^1.1.3" + normalize-package-data "^2.3.4" + object-assign "^4.0.1" + read-pkg-up "^1.0.1" + redent "^1.0.0" + trim-newlines "^1.0.0" + +"minimatch@2 || 3", minimatch@^3.0.2, minimatch@^3.0.4: + version "3.0.4" + resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.0.4.tgz#5166e286457f03306064be5497e8dbb0c3d32083" + dependencies: + brace-expansion "^1.1.7" + +minimist@0.0.8, minimist@~0.0.1: + version "0.0.8" + resolved "https://registry.yarnpkg.com/minimist/-/minimist-0.0.8.tgz#857fcabfc3397d2625b8228262e86aa7a011b05d" + +minimist@^1.1.3, minimist@^1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.0.tgz#a35008b20f41383eec1fb914f4cd5df79a264284" + +mkdirp@0.5.x, mkdirp@^0.5.1: + version "0.5.1" + resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-0.5.1.tgz#30057438eac6cf7f8c4767f38648d6697d75c903" + dependencies: + minimist "0.0.8" + +modify-values@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/modify-values/-/modify-values-1.0.0.tgz#e2b6cdeb9ce19f99317a53722f3dbf5df5eaaab2" + +node-emoji@^1.4.1: + version "1.5.1" + resolved "https://registry.yarnpkg.com/node-emoji/-/node-emoji-1.5.1.tgz#fd918e412769bf8c448051238233840b2aff16a1" + dependencies: + string.prototype.codepointat "^0.2.0" + +nopt@3.x: + version "3.0.6" + resolved "https://registry.yarnpkg.com/nopt/-/nopt-3.0.6.tgz#c6465dbf08abcd4db359317f79ac68a646b28ff9" + dependencies: + abbrev "1" + +normalize-package-data@^2.3.0, normalize-package-data@^2.3.2, normalize-package-data@^2.3.4, normalize-package-data@^2.3.5: + version "2.3.8" + resolved "https://registry.yarnpkg.com/normalize-package-data/-/normalize-package-data-2.3.8.tgz#d819eda2a9dedbd1ffa563ea4071d936782295bb" + dependencies: + hosted-git-info "^2.1.4" + is-builtin-module "^1.0.0" + semver "2 || 3 || 4 || 5" + validate-npm-package-license "^3.0.1" + +npm-path@^2.0.2, npm-path@^2.0.3: + version "2.0.3" + resolved "https://registry.yarnpkg.com/npm-path/-/npm-path-2.0.3.tgz#15cff4e1c89a38da77f56f6055b24f975dfb2bbe" + dependencies: + which "^1.2.10" + +npm-run-all@^4.0.0: + version "4.0.2" + resolved "https://registry.yarnpkg.com/npm-run-all/-/npm-run-all-4.0.2.tgz#a84669348e6db6ccbe052200b4cdb6bfe034a4fe" + dependencies: + chalk "^1.1.3" + cross-spawn "^5.0.1" + minimatch "^3.0.2" + ps-tree "^1.0.1" + read-pkg "^2.0.0" + shell-quote "^1.6.1" + string.prototype.padend "^3.0.0" + +npm-run-path@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/npm-run-path/-/npm-run-path-1.0.0.tgz#f5c32bf595fe81ae927daec52e82f8b000ac3c8f" + dependencies: + path-key "^1.0.0" + +npm-run@^4.1.0: + version "4.1.2" + resolved "https://registry.yarnpkg.com/npm-run/-/npm-run-4.1.2.tgz#1030e1ec56908c89fcc3fa366d03a2c2ba98eb99" + dependencies: + cross-spawn "^5.1.0" + minimist "^1.2.0" + npm-path "^2.0.3" + npm-which "^3.0.1" + serializerr "^1.0.3" + sync-exec "^0.6.2" + +npm-which@^3.0.1: + version "3.0.1" + resolved "https://registry.yarnpkg.com/npm-which/-/npm-which-3.0.1.tgz#9225f26ec3a285c209cae67c3b11a6b4ab7140aa" + dependencies: + commander "^2.9.0" + npm-path "^2.0.2" + which "^1.2.10" + +number-is-nan@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/number-is-nan/-/number-is-nan-1.0.1.tgz#097b602b53422a522c1afb8790318336941a011d" + +object-assign@^4.0.1, object-assign@^4.1.1: + version "4.1.1" + resolved "https://registry.yarnpkg.com/object-assign/-/object-assign-4.1.1.tgz#2109adc7965887cfc05cbbd442cac8bfbb360863" + +object-keys@^1.0.8: + version "1.0.11" + resolved "https://registry.yarnpkg.com/object-keys/-/object-keys-1.0.11.tgz#c54601778ad560f1142ce0e01bcca8b56d13426d" + +once@1.x, once@^1.3.0: + version "1.4.0" + resolved "https://registry.yarnpkg.com/once/-/once-1.4.0.tgz#583b1aa775961d4b113ac17d9c50baef9dd76bd1" + dependencies: + wrappy "1" + +optimist@^0.6.1, optimist@~0.6.0: + version "0.6.1" + resolved "https://registry.yarnpkg.com/optimist/-/optimist-0.6.1.tgz#da3ea74686fa21a19a111c326e90eb15a0196686" + dependencies: + minimist "~0.0.1" + wordwrap "~0.0.2" + +optionator@^0.8.1: + version "0.8.2" + resolved "https://registry.yarnpkg.com/optionator/-/optionator-0.8.2.tgz#364c5e409d3f4d6301d6c0b4c05bba50180aeb64" + dependencies: + deep-is "~0.1.3" + fast-levenshtein "~2.0.4" + levn "~0.3.0" + prelude-ls "~1.1.2" + type-check "~0.3.2" + wordwrap "~1.0.0" + +os-tmpdir@^1.0.0: + version "1.0.2" + resolved "https://registry.yarnpkg.com/os-tmpdir/-/os-tmpdir-1.0.2.tgz#bbe67406c79aa85c5cfec766fe5734555dfa1274" + +package-json@^4.0.0: + version "4.0.1" + resolved "https://registry.yarnpkg.com/package-json/-/package-json-4.0.1.tgz#8869a0401253661c4c4ca3da6c2121ed555f5eed" + dependencies: + got "^6.7.1" + registry-auth-token "^3.0.1" + registry-url "^3.0.3" + semver "^5.1.0" + +parse-github-repo-url@^1.3.0: + version "1.4.0" + resolved "https://registry.yarnpkg.com/parse-github-repo-url/-/parse-github-repo-url-1.4.0.tgz#286c53e2c9962e0641649ee3ac9508fca4dd959c" + +parse-json@^2.2.0: + version "2.2.0" + resolved "https://registry.yarnpkg.com/parse-json/-/parse-json-2.2.0.tgz#f480f40434ef80741f8469099f8dea18f55a4dc9" + dependencies: + error-ex "^1.2.0" + +path-exists@^2.0.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/path-exists/-/path-exists-2.1.0.tgz#0feb6c64f0fc518d9a754dd5efb62c7022761f4b" + dependencies: + pinkie-promise "^2.0.0" + +path-is-absolute@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/path-is-absolute/-/path-is-absolute-1.0.1.tgz#174b9268735534ffbc7ace6bf53a5a9e1b5c5f5f" + +path-key@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/path-key/-/path-key-1.0.0.tgz#5d53d578019646c0d68800db4e146e6bdc2ac7af" + +path-type@^1.0.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/path-type/-/path-type-1.1.0.tgz#59c44f7ee491da704da415da5a4070ba4f8fe441" + dependencies: + graceful-fs "^4.1.2" + pify "^2.0.0" + pinkie-promise "^2.0.0" + +path-type@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/path-type/-/path-type-2.0.0.tgz#f012ccb8415b7096fc2daa1054c3d72389594c73" + dependencies: + pify "^2.0.0" + +pause-stream@0.0.11: + version "0.0.11" + resolved "https://registry.yarnpkg.com/pause-stream/-/pause-stream-0.0.11.tgz#fe5a34b0cbce12b5aa6a2b403ee2e73b602f1445" + dependencies: + through "~2.3" + +pify@^2.0.0, pify@^2.3.0: + version "2.3.0" + resolved "https://registry.yarnpkg.com/pify/-/pify-2.3.0.tgz#ed141a6ac043a849ea588498e7dca8b15330e90c" + +pinkie-promise@^2.0.0: + version "2.0.1" + resolved "https://registry.yarnpkg.com/pinkie-promise/-/pinkie-promise-2.0.1.tgz#2135d6dfa7a358c069ac9b178776288228450ffa" + dependencies: + pinkie "^2.0.0" + +pinkie@^2.0.0, pinkie@^2.0.4: + version "2.0.4" + resolved "https://registry.yarnpkg.com/pinkie/-/pinkie-2.0.4.tgz#72556b80cfa0d48a974e80e77248e80ed4f7f870" + +prelude-ls@~1.1.2: + version "1.1.2" + resolved "https://registry.yarnpkg.com/prelude-ls/-/prelude-ls-1.1.2.tgz#21932a549f5e52ffd9a827f570e04be62a97da54" + +prepend-http@^1.0.1: + version "1.0.4" + resolved "https://registry.yarnpkg.com/prepend-http/-/prepend-http-1.0.4.tgz#d4f4562b0ce3696e41ac52d0e002e57a635dc6dc" + +process-nextick-args@~1.0.6: + version "1.0.7" + resolved "https://registry.yarnpkg.com/process-nextick-args/-/process-nextick-args-1.0.7.tgz#150e20b756590ad3f91093f25a4f2ad8bff30ba3" + +protochain@^1.0.5: + version "1.0.5" + resolved "https://registry.yarnpkg.com/protochain/-/protochain-1.0.5.tgz#991c407e99de264aadf8f81504b5e7faf7bfa260" + +ps-tree@^1.0.1: + version "1.1.0" + resolved "https://registry.yarnpkg.com/ps-tree/-/ps-tree-1.1.0.tgz#b421b24140d6203f1ed3c76996b4427b08e8c014" + dependencies: + event-stream "~3.3.0" + +pseudomap@^1.0.1: + version "1.0.2" + resolved "https://registry.yarnpkg.com/pseudomap/-/pseudomap-1.0.2.tgz#f052a28da70e618917ef0a8ac34c1ae5a68286b3" + +q@^1.4.1: + version "1.5.0" + resolved "https://registry.yarnpkg.com/q/-/q-1.5.0.tgz#dd01bac9d06d30e6f219aecb8253ee9ebdc308f1" + +rc@^1.0.1, rc@^1.1.6: + version "1.2.1" + resolved "https://registry.yarnpkg.com/rc/-/rc-1.2.1.tgz#2e03e8e42ee450b8cb3dce65be1bf8974e1dfd95" + dependencies: + deep-extend "~0.4.0" + ini "~1.3.0" + minimist "^1.2.0" + strip-json-comments "~2.0.1" + +read-pkg-up@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/read-pkg-up/-/read-pkg-up-1.0.1.tgz#9d63c13276c065918d57f002a57f40a1b643fb02" + dependencies: + find-up "^1.0.0" + read-pkg "^1.0.0" + +read-pkg@^1.0.0, read-pkg@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/read-pkg/-/read-pkg-1.1.0.tgz#f5ffaa5ecd29cb31c0474bca7d756b6bb29e3f28" + dependencies: + load-json-file "^1.0.0" + normalize-package-data "^2.3.2" + path-type "^1.0.0" + +read-pkg@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/read-pkg/-/read-pkg-2.0.0.tgz#8ef1c0623c6a6db0dc6713c4bfac46332b2368f8" + dependencies: + load-json-file "^2.0.0" + normalize-package-data "^2.3.2" + path-type "^2.0.0" + +readable-stream@^2.1.5: + version "2.2.9" + resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-2.2.9.tgz#cf78ec6f4a6d1eb43d26488cac97f042e74b7fc8" + dependencies: + buffer-shims "~1.0.0" + core-util-is "~1.0.0" + inherits "~2.0.1" + isarray "~1.0.0" + process-nextick-args "~1.0.6" + string_decoder "~1.0.0" + util-deprecate "~1.0.1" + +redent@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/redent/-/redent-1.0.0.tgz#cf916ab1fd5f1f16dfb20822dd6ec7f730c2afde" + dependencies: + indent-string "^2.1.0" + strip-indent "^1.0.1" + +redeyed@~1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/redeyed/-/redeyed-1.0.1.tgz#e96c193b40c0816b00aec842698e61185e55498a" + dependencies: + esprima "~3.0.0" + +regenerator-runtime@^0.10.0: + version "0.10.5" + resolved "https://registry.yarnpkg.com/regenerator-runtime/-/regenerator-runtime-0.10.5.tgz#336c3efc1220adcedda2c9fab67b5a7955a33658" + +registry-auth-token@^3.0.1: + version "3.3.1" + resolved "https://registry.yarnpkg.com/registry-auth-token/-/registry-auth-token-3.3.1.tgz#fb0d3289ee0d9ada2cbb52af5dfe66cb070d3006" + dependencies: + rc "^1.1.6" + safe-buffer "^5.0.1" + +registry-url@^3.0.3: + version "3.1.0" + resolved "https://registry.yarnpkg.com/registry-url/-/registry-url-3.1.0.tgz#3d4ef870f73dde1d77f0cf9a381432444e174942" + dependencies: + rc "^1.0.1" + +repeat-string@^1.5.2: + version "1.6.1" + resolved "https://registry.yarnpkg.com/repeat-string/-/repeat-string-1.6.1.tgz#8dcae470e1c88abc2d600fff4a776286da75e637" + +repeating@^2.0.0: + version "2.0.1" + resolved "https://registry.yarnpkg.com/repeating/-/repeating-2.0.1.tgz#5214c53a926d3552707527fbab415dbc08d06dda" + dependencies: + is-finite "^1.0.0" + +resolve@1.1.x, resolve@^1.1.7: + version "1.1.7" + resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.1.7.tgz#203114d82ad2c5ed9e8e0411b3932875e889e97b" + +right-align@^0.1.1: + version "0.1.3" + resolved "https://registry.yarnpkg.com/right-align/-/right-align-0.1.3.tgz#61339b722fe6a3515689210d24e14c96148613ef" + dependencies: + align-text "^0.1.1" + +rimraf@~2.2.6: + version "2.2.8" + resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-2.2.8.tgz#e439be2aaee327321952730f99a8929e4fc50582" + +rxjs@^5.0.1: + version "5.4.0" + resolved "https://registry.yarnpkg.com/rxjs/-/rxjs-5.4.0.tgz#a7db14ab157f9d7aac6a56e655e7a3860d39bf26" + dependencies: + symbol-observable "^1.0.1" + +safe-buffer@^5.0.1: + version "5.0.1" + resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.0.1.tgz#d263ca54696cd8a306b5ca6551e92de57918fbe7" + +semver-diff@^2.0.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/semver-diff/-/semver-diff-2.1.0.tgz#4bbb8437c8d37e4b0cf1a68fd726ec6d645d6d36" + dependencies: + semver "^5.0.3" + +"semver@2 || 3 || 4 || 5", semver@^5.0.1, semver@^5.0.3, semver@^5.1.0, semver@^5.3.0: + version "5.3.0" + resolved "https://registry.yarnpkg.com/semver/-/semver-5.3.0.tgz#9b2ce5d3de02d17c6012ad326aa6b4d0cf54f94f" + +serializerr@^1.0.3: + version "1.0.3" + resolved "https://registry.yarnpkg.com/serializerr/-/serializerr-1.0.3.tgz#12d4c5aa1c3ffb8f6d1dc5f395aa9455569c3f91" + dependencies: + protochain "^1.0.5" + +shebang-command@^1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/shebang-command/-/shebang-command-1.2.0.tgz#44aac65b695b03398968c39f363fee5deafdf1ea" + dependencies: + shebang-regex "^1.0.0" + +shebang-regex@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/shebang-regex/-/shebang-regex-1.0.0.tgz#da42f49740c0b42db2ca9728571cb190c98efea3" + +shell-quote@^1.6.1: + version "1.6.1" + resolved "https://registry.yarnpkg.com/shell-quote/-/shell-quote-1.6.1.tgz#f4781949cce402697127430ea3b3c5476f481767" + dependencies: + array-filter "~0.0.0" + array-map "~0.0.0" + array-reduce "~0.0.0" + jsonify "~0.0.0" + +signal-exit@^3.0.0: + version "3.0.2" + resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-3.0.2.tgz#b5fdc08f1287ea1178628e415e25132b73646c6d" + +slide@^1.1.5: + version "1.1.6" + resolved "https://registry.yarnpkg.com/slide/-/slide-1.1.6.tgz#56eb027d65b4d2dce6cb2e2d32c4d4afc9e1d707" + +source-map-support@^0.4.0: + version "0.4.15" + resolved "https://registry.yarnpkg.com/source-map-support/-/source-map-support-0.4.15.tgz#03202df65c06d2bd8c7ec2362a193056fef8d3b1" + dependencies: + source-map "^0.5.6" + +source-map@^0.4.4: + version "0.4.4" + resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.4.4.tgz#eba4f5da9c0dc999de68032d8b4f76173652036b" + dependencies: + amdefine ">=0.0.4" + +source-map@^0.5.6, source-map@~0.5.1: + version "0.5.6" + resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.5.6.tgz#75ce38f52bf0733c5a7f0c118d81334a2bb5f412" + +source-map@~0.2.0: + version "0.2.0" + resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.2.0.tgz#dab73fbcfc2ba819b4de03bd6f6eaa48164b3f9d" + dependencies: + amdefine ">=0.0.4" + +spdx-correct@~1.0.0: + version "1.0.2" + resolved "https://registry.yarnpkg.com/spdx-correct/-/spdx-correct-1.0.2.tgz#4b3073d933ff51f3912f03ac5519498a4150db40" + dependencies: + spdx-license-ids "^1.0.2" + +spdx-expression-parse@~1.0.0: + version "1.0.4" + resolved "https://registry.yarnpkg.com/spdx-expression-parse/-/spdx-expression-parse-1.0.4.tgz#9bdf2f20e1f40ed447fbe273266191fced51626c" + +spdx-license-ids@^1.0.2: + version "1.2.2" + resolved "https://registry.yarnpkg.com/spdx-license-ids/-/spdx-license-ids-1.2.2.tgz#c9df7a3424594ade6bd11900d596696dc06bac57" + +split2@^2.0.0: + version "2.1.1" + resolved "https://registry.yarnpkg.com/split2/-/split2-2.1.1.tgz#7a1f551e176a90ecd3345f7246a0cfe175ef4fd0" + dependencies: + through2 "^2.0.2" + +split@0.3: + version "0.3.3" + resolved "https://registry.yarnpkg.com/split/-/split-0.3.3.tgz#cd0eea5e63a211dfff7eb0f091c4133e2d0dd28f" + dependencies: + through "2" + +split@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/split/-/split-1.0.0.tgz#c4395ce683abcd254bc28fe1dabb6e5c27dcffae" + dependencies: + through "2" + +sprintf-js@~1.0.2: + version "1.0.3" + resolved "https://registry.yarnpkg.com/sprintf-js/-/sprintf-js-1.0.3.tgz#04e6926f662895354f3dd015203633b857297e2c" + +stream-combiner@~0.0.4: + version "0.0.4" + resolved "https://registry.yarnpkg.com/stream-combiner/-/stream-combiner-0.0.4.tgz#4d5e433c185261dde623ca3f44c586bcf5c4ad14" + dependencies: + duplexer "~0.1.1" + +string-width@^1.0.1: + version "1.0.2" + resolved "https://registry.yarnpkg.com/string-width/-/string-width-1.0.2.tgz#118bdf5b8cdc51a2a7e70d211e07e2b0b9b107d3" + dependencies: + code-point-at "^1.0.0" + is-fullwidth-code-point "^1.0.0" + strip-ansi "^3.0.0" + +string-width@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/string-width/-/string-width-2.0.0.tgz#635c5436cc72a6e0c387ceca278d4e2eec52687e" + dependencies: + is-fullwidth-code-point "^2.0.0" + strip-ansi "^3.0.0" + +string.prototype.codepointat@^0.2.0: + version "0.2.0" + resolved "https://registry.yarnpkg.com/string.prototype.codepointat/-/string.prototype.codepointat-0.2.0.tgz#6b26e9bd3afcaa7be3b4269b526de1b82000ac78" + +string.prototype.padend@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/string.prototype.padend/-/string.prototype.padend-3.0.0.tgz#f3aaef7c1719f170c5eab1c32bf780d96e21f2f0" + dependencies: + define-properties "^1.1.2" + es-abstract "^1.4.3" + function-bind "^1.0.2" + +string_decoder@~1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-1.0.1.tgz#62e200f039955a6810d8df0a33ffc0f013662d98" + dependencies: + safe-buffer "^5.0.1" + +strip-ansi@^3.0.0: + version "3.0.1" + resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-3.0.1.tgz#6a385fb8853d952d5ff05d0e8aaf94278dc63dcf" + dependencies: + ansi-regex "^2.0.0" + +strip-bom@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/strip-bom/-/strip-bom-2.0.0.tgz#6219a85616520491f35788bdbf1447a99c7e6b0e" + dependencies: + is-utf8 "^0.2.0" + +strip-bom@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/strip-bom/-/strip-bom-3.0.0.tgz#2334c18e9c759f7bdd56fdef7e9ae3d588e68ed3" + +strip-eof@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/strip-eof/-/strip-eof-1.0.0.tgz#bb43ff5598a6eb05d89b59fcd129c983313606bf" + +strip-indent@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/strip-indent/-/strip-indent-1.0.1.tgz#0c7962a6adefa7bbd4ac366460a638552ae1a0a2" + dependencies: + get-stdin "^4.0.1" + +strip-json-comments@^2.0.0, strip-json-comments@~2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-2.0.1.tgz#3c531942e908c2697c0ec344858c286c7ca0a60a" + +supports-color@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-2.0.0.tgz#535d045ce6b6363fa40117084629995e9df324c7" + +supports-color@^3.1.0: + version "3.2.3" + resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-3.2.3.tgz#65ac0504b3954171d8a64946b2ae3cbb8a5f54f6" + dependencies: + has-flag "^1.0.0" + +symbol-observable@^1.0.1: + version "1.0.4" + resolved "https://registry.yarnpkg.com/symbol-observable/-/symbol-observable-1.0.4.tgz#29bf615d4aa7121bdd898b22d4b3f9bc4e2aa03d" + +sync-exec@^0.6.2: + version "0.6.2" + resolved "https://registry.yarnpkg.com/sync-exec/-/sync-exec-0.6.2.tgz#717d22cc53f0ce1def5594362f3a89a2ebb91105" + +temp@^0.8.3: + version "0.8.3" + resolved "https://registry.yarnpkg.com/temp/-/temp-0.8.3.tgz#e0c6bc4d26b903124410e4fed81103014dfc1f59" + dependencies: + os-tmpdir "^1.0.0" + rimraf "~2.2.6" + +term-size@^0.1.0: + version "0.1.1" + resolved "https://registry.yarnpkg.com/term-size/-/term-size-0.1.1.tgz#87360b96396cab5760963714cda0d0cbeecad9ca" + dependencies: + execa "^0.4.0" + +text-extensions@^1.0.0: + version "1.4.0" + resolved "https://registry.yarnpkg.com/text-extensions/-/text-extensions-1.4.0.tgz#c385d2e80879fe6ef97893e1709d88d9453726e9" + +through2@^2.0.0, through2@^2.0.2: + version "2.0.3" + resolved "https://registry.yarnpkg.com/through2/-/through2-2.0.3.tgz#0004569b37c7c74ba39c43f3ced78d1ad94140be" + dependencies: + readable-stream "^2.1.5" + xtend "~4.0.1" + +through@2, "through@>=2.2.7 <3", through@~2.3, through@~2.3.1: + version "2.3.8" + resolved "https://registry.yarnpkg.com/through/-/through-2.3.8.tgz#0dd4c9ffaabc357960b1b724115d7e0e86a2e1f5" + +timed-out@^4.0.0: + version "4.0.1" + resolved "https://registry.yarnpkg.com/timed-out/-/timed-out-4.0.1.tgz#f32eacac5a175bea25d7fab565ab3ed8741ef56f" + +trim-newlines@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/trim-newlines/-/trim-newlines-1.0.0.tgz#5887966bb582a4503a41eb524f7d35011815a613" + +trim-off-newlines@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/trim-off-newlines/-/trim-off-newlines-1.0.1.tgz#9f9ba9d9efa8764c387698bcbfeb2c848f11adb3" + +ts-node@^2.0.0: + version "2.1.2" + resolved "https://registry.yarnpkg.com/ts-node/-/ts-node-2.1.2.tgz#45087b45e7b371b3daf04ecc470ec29a836655ea" + dependencies: + arrify "^1.0.0" + chalk "^1.1.1" + diff "^3.1.0" + make-error "^1.1.1" + minimist "^1.2.0" + mkdirp "^0.5.1" + pinkie "^2.0.4" + source-map-support "^0.4.0" + tsconfig "^6.0.0" + v8flags "^2.0.11" + xtend "^4.0.0" + yn "^1.2.0" + +tsconfig@^6.0.0: + version "6.0.0" + resolved "https://registry.yarnpkg.com/tsconfig/-/tsconfig-6.0.0.tgz#6b0e8376003d7af1864f8df8f89dd0059ffcd032" + dependencies: + strip-bom "^3.0.0" + strip-json-comments "^2.0.0" + +tslint@^4.0.2: + version "4.5.1" + resolved "https://registry.yarnpkg.com/tslint/-/tslint-4.5.1.tgz#05356871bef23a434906734006fc188336ba824b" + dependencies: + babel-code-frame "^6.20.0" + colors "^1.1.2" + diff "^3.0.1" + findup-sync "~0.3.0" + glob "^7.1.1" + optimist "~0.6.0" + resolve "^1.1.7" + tsutils "^1.1.0" + update-notifier "^2.0.0" + +tsutils@^1.1.0: + version "1.9.1" + resolved "https://registry.yarnpkg.com/tsutils/-/tsutils-1.9.1.tgz#b9f9ab44e55af9681831d5f28d0aeeaf5c750cb0" + +type-check@~0.3.2: + version "0.3.2" + resolved "https://registry.yarnpkg.com/type-check/-/type-check-0.3.2.tgz#5884cab512cf1d355e3fb784f30804b2b520db72" + dependencies: + prelude-ls "~1.1.2" + +typescript@~2.3.0: + version "2.3.3" + resolved "https://registry.yarnpkg.com/typescript/-/typescript-2.3.3.tgz#9639f3c3b40148e8ca97fe08a51dd1891bb6be22" + +uglify-js@^2.6: + version "2.8.27" + resolved "https://registry.yarnpkg.com/uglify-js/-/uglify-js-2.8.27.tgz#47787f912b0f242e5b984343be8e35e95f694c9c" + dependencies: + source-map "~0.5.1" + yargs "~3.10.0" + optionalDependencies: + uglify-to-browserify "~1.0.0" + +uglify-to-browserify@~1.0.0: + version "1.0.2" + resolved "https://registry.yarnpkg.com/uglify-to-browserify/-/uglify-to-browserify-1.0.2.tgz#6e0924d6bda6b5afe349e39a6d632850a0f882b7" + +unique-string@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/unique-string/-/unique-string-1.0.0.tgz#9e1057cca851abb93398f8b33ae187b99caec11a" + dependencies: + crypto-random-string "^1.0.0" + +unzip-response@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/unzip-response/-/unzip-response-2.0.1.tgz#d2f0f737d16b0615e72a6935ed04214572d56f97" + +update-notifier@^2.0.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/update-notifier/-/update-notifier-2.1.0.tgz#ec0c1e53536b76647a24b77cb83966d9315123d9" + dependencies: + boxen "^1.0.0" + chalk "^1.0.0" + configstore "^3.0.0" + is-npm "^1.0.0" + latest-version "^3.0.0" + lazy-req "^2.0.0" + semver-diff "^2.0.0" + xdg-basedir "^3.0.0" + +url-parse-lax@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/url-parse-lax/-/url-parse-lax-1.0.0.tgz#7af8f303645e9bd79a272e7a14ac68bc0609da73" + dependencies: + prepend-http "^1.0.1" + +user-home@^1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/user-home/-/user-home-1.1.1.tgz#2b5be23a32b63a7c9deb8d0f28d485724a3df190" + +util-deprecate@~1.0.1: + version "1.0.2" + resolved "https://registry.yarnpkg.com/util-deprecate/-/util-deprecate-1.0.2.tgz#450d4dc9fa70de732762fbd2d4a28981419a0ccf" + +v8flags@^2.0.11: + version "2.1.1" + resolved "https://registry.yarnpkg.com/v8flags/-/v8flags-2.1.1.tgz#aab1a1fa30d45f88dd321148875ac02c0b55e5b4" + dependencies: + user-home "^1.1.1" + +validate-npm-package-license@^3.0.1: + version "3.0.1" + resolved "https://registry.yarnpkg.com/validate-npm-package-license/-/validate-npm-package-license-3.0.1.tgz#2804babe712ad3379459acfbe24746ab2c303fbc" + dependencies: + spdx-correct "~1.0.0" + spdx-expression-parse "~1.0.0" + +which@^1.1.1, which@^1.2.10, which@^1.2.8, which@^1.2.9: + version "1.2.14" + resolved "https://registry.yarnpkg.com/which/-/which-1.2.14.tgz#9a87c4378f03e827cecaf1acdf56c736c01c14e5" + dependencies: + isexe "^2.0.0" + +widest-line@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/widest-line/-/widest-line-1.0.0.tgz#0c09c85c2a94683d0d7eaf8ee097d564bf0e105c" + dependencies: + string-width "^1.0.1" + +window-size@0.1.0: + version "0.1.0" + resolved "https://registry.yarnpkg.com/window-size/-/window-size-0.1.0.tgz#5438cd2ea93b202efa3a19fe8887aee7c94f9c9d" + +wordwrap@0.0.2: + version "0.0.2" + resolved "https://registry.yarnpkg.com/wordwrap/-/wordwrap-0.0.2.tgz#b79669bb42ecb409f83d583cad52ca17eaa1643f" + +wordwrap@^1.0.0, wordwrap@~1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/wordwrap/-/wordwrap-1.0.0.tgz#27584810891456a4171c8d0226441ade90cbcaeb" + +wordwrap@~0.0.2: + version "0.0.3" + resolved "https://registry.yarnpkg.com/wordwrap/-/wordwrap-0.0.3.tgz#a3d5da6cd5c0bc0008d37234bbaf1bed63059107" + +wrappy@1: + version "1.0.2" + resolved "https://registry.yarnpkg.com/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f" + +write-file-atomic@^2.0.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/write-file-atomic/-/write-file-atomic-2.1.0.tgz#1769f4b551eedce419f0505deae2e26763542d37" + dependencies: + graceful-fs "^4.1.11" + imurmurhash "^0.1.4" + slide "^1.1.5" + +xdg-basedir@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/xdg-basedir/-/xdg-basedir-3.0.0.tgz#496b2cc109eca8dbacfe2dc72b603c17c5870ad4" + +xtend@^4.0.0, xtend@~4.0.1: + version "4.0.1" + resolved "https://registry.yarnpkg.com/xtend/-/xtend-4.0.1.tgz#a5c6d532be656e23db820efb943a1f04998d63af" + +yallist@^2.0.0: + version "2.1.2" + resolved "https://registry.yarnpkg.com/yallist/-/yallist-2.1.2.tgz#1c11f9218f076089a47dd512f93c6699a6a81d52" + +yargs@~3.10.0: + version "3.10.0" + resolved "https://registry.yarnpkg.com/yargs/-/yargs-3.10.0.tgz#f7ee7bd857dd7c1d2d38c0e74efbd681d1431fd1" + dependencies: + camelcase "^1.0.2" + cliui "^2.1.0" + decamelize "^1.0.0" + window-size "0.1.0" + +yn@^1.2.0: + version "1.3.0" + resolved "https://registry.yarnpkg.com/yn/-/yn-1.3.0.tgz#1b0812abb8d805d48966f8df385dc9dacc9a19d8" + dependencies: + object-assign "^4.1.1" From 6cfd8ca64205e8334160c2029a5804f3e8d93790 Mon Sep 17 00:00:00 2001 From: Hans Larsen Date: Tue, 23 May 2017 15:15:21 -0700 Subject: [PATCH 02/12] build: add sdk-admin binary, bootstrap-local, ... Includes unit testing script and bunch of unit testing configuration. --- bin/sdk-admin | 21 +++++ lib/bootstrap-local.js | 83 ++++++++++++++++++ lib/packages.js | 65 ++++++++++++++ package.json | 6 +- scripts/test.ts | 194 +++++++++++++++++++++++++++++++++++++++++ 5 files changed, 365 insertions(+), 4 deletions(-) create mode 100755 bin/sdk-admin create mode 100644 lib/bootstrap-local.js create mode 100644 lib/packages.js create mode 100644 scripts/test.ts diff --git a/bin/sdk-admin b/bin/sdk-admin new file mode 100755 index 0000000000..75ce66a972 --- /dev/null +++ b/bin/sdk-admin @@ -0,0 +1,21 @@ +#!/usr/bin/env node +'use strict'; + +/** + * This file is useful for not having to load bootstrap-local in various javascript. + * Simply use package.json to have npm scripts that use this script as well, or use + * this script directly. + */ + +require('../lib/bootstrap-local'); + +const minimist = require('minimist'); + +const args = minimist(process.argv.slice(2)); + + +switch (args._[0]) { + case 'test': require('../scripts/test').default(args); break; + + default: console.log('Unknown command: ' + args._[0]); break; +} diff --git a/lib/bootstrap-local.js b/lib/bootstrap-local.js new file mode 100644 index 0000000000..fafffe7fec --- /dev/null +++ b/lib/bootstrap-local.js @@ -0,0 +1,83 @@ +/* eslint-disable no-console */ +'use strict'; + +const fs = require('fs'); +const path = require('path'); +const ts = require('typescript'); + + +Error.stackTraceLimit = Infinity; + +global._SdkIsLocal = true; +global._SdkRoot = path.resolve(__dirname, '..'); +global._SdkPackages = require('./packages').packages; +global._SdkTools = require('./packages').tools; + +global._SdkRequireHook = null; + + +const compilerOptions = ts.readConfigFile(path.join(__dirname, '../tsconfig.json'), p => { + return fs.readFileSync(p, 'utf-8'); +}).config; + + +const oldRequireTs = require.extensions['.ts']; +require.extensions['.ts'] = function (m, filename) { + // If we're in node module, either call the old hook or simply compile the + // file without transpilation. We do not touch node_modules/**. + // We do touch `Angular SDK` files anywhere though. + if (!filename.match(/@angular\/cli\b/) && filename.match(/node_modules/)) { + if (oldRequireTs) { + return oldRequireTs(m, filename); + } + return m._compile(fs.readFileSync(filename), filename); + } + + // Node requires all require hooks to be sync. + const source = fs.readFileSync(filename).toString(); + + try { + let result = ts.transpile(source, compilerOptions['compilerOptions'], filename); + + if (global._SdkRequireHook) { + result = global._SdkRequireHook(result, filename); + } + + // Send it to node to execute. + return m._compile(result, filename); + } catch (err) { + console.error('Error while running script "' + filename + '":'); + console.error(err.stack); + throw err; + } +}; + + +// If we're running locally, meaning npm linked. This is basically "developer mode". +if (!__dirname.match(new RegExp(`\\${path.sep}node_modules\\${path.sep}`))) { + const packages = require('./packages').packages; + + // We mock the module loader so that we can fake our packages when running locally. + const Module = require('module'); + const oldLoad = Module._load; + const oldResolve = Module._resolveFilename; + + Module._resolveFilename = function (request, parent) { + if (request in packages) { + return packages[request].main; + } else if (request.startsWith('@angular/cli/')) { + // We allow deep imports (for now). + // TODO: move tests to inside @angular/cli package so they don't have to deep import. + const dir = path.dirname(parent.filename); + return path.relative(dir, path.join(__dirname, '../packages', request)); + } else { + let match = Object.keys(packages).find(pkgName => request.startsWith(pkgName + '/')); + if (match) { + const p = path.join(packages[match].root, request.substr(match.length)); + return oldResolve.call(this, p, parent); + } else { + return oldResolve.apply(this, arguments); + } + } + }; +} diff --git a/lib/packages.js b/lib/packages.js new file mode 100644 index 0000000000..97dadd51dd --- /dev/null +++ b/lib/packages.js @@ -0,0 +1,65 @@ +'use strict'; + +const fs = require('fs'); +const glob = require('glob'); +const path = require('path'); + +const packageRoot = path.join(__dirname, '../packages'); +const toolsRoot = path.join(__dirname, '../tools'); +const distRoot = path.join(__dirname, '../dist'); + + +// All the supported packages. Go through the packages directory and create a _map of +// name => fullPath. +const packages = + [].concat( + glob.sync(path.join(packageRoot, '*/package.json')), + glob.sync(path.join(packageRoot, '*/*/package.json'))) + .filter(p => !p.match(/blueprints/)) + .map(pkgPath => path.relative(packageRoot, path.dirname(pkgPath))) + .map(pkgName => { + return { name: pkgName, root: path.join(packageRoot, pkgName) }; + }) + .reduce((packages, pkg) => { + let pkgJson = JSON.parse(fs.readFileSync(path.join(pkg.root, 'package.json'), 'utf8')); + let name = pkgJson['name']; + let bin = {}; + Object.keys(pkgJson['bin'] || {}).forEach(binName => { + bin[binName] = path.resolve(pkg.root, pkgJson['bin'][binName]); + }); + + packages[name] = { + dist: path.join(distRoot, pkg.name), + packageJson: path.join(pkg.root, 'package.json'), + root: pkg.root, + relative: path.relative(path.dirname(__dirname), pkg.root), + main: path.resolve(pkg.root, 'src/index.ts'), + bin: bin + }; + return packages; + }, {}); + +const tools = glob.sync(path.join(toolsRoot, '**/package.json')) + .map(toolPath => path.relative(toolsRoot, path.dirname(toolPath))) + .map(toolName => { + const root = path.join(toolsRoot, toolName); + const pkgJson = JSON.parse(fs.readFileSync(path.join(root, 'package.json'), 'utf8')); + const name = pkgJson['name']; + const dist = path.join(distRoot, toolName); + + return { + name, + main: path.join(dist, pkgJson['main']), + mainTs: path.join(toolsRoot, toolName, pkgJson['main'].replace(/\.js$/, '.ts')), + root, + packageJson: path.join(toolsRoot, toolName, 'package.json'), + dist + }; + }) + .reduce((tools, tool) => { + tools[tool.name] = tool; + return tools; + }, {}); + + +module.exports = { packages, tools }; diff --git a/package.json b/package.json index 2863b49dfd..f7b9d07045 100644 --- a/package.json +++ b/package.json @@ -3,13 +3,11 @@ "version": "0.0.0", "description": "Software Development Kit for Angular", "bin": { - "sdk-admin": "./bin/sdk-admin", - "schematics": "./bin/schematics" + "sdk-admin": "./bin/sdk-admin" }, "keywords": [], "scripts": { - "build": "sdk-admin build", - "test": "sdk-admin test" + "test": "./bin/sdk-admin test" }, "repository": { "type": "git", diff --git a/scripts/test.ts b/scripts/test.ts new file mode 100644 index 0000000000..45ea8d03fd --- /dev/null +++ b/scripts/test.ts @@ -0,0 +1,194 @@ +import 'jasmine'; + +import * as glob from 'glob'; +import * as Istanbul from 'istanbul'; +import {SpecReporter as JasmineSpecReporter} from 'jasmine-spec-reporter'; +import {join, relative} from 'path'; +import {Position, SourceMapConsumer, SourceMapGenerator} from 'source-map'; + + +const Jasmine = require('jasmine'); + +const projectBaseDir = join(__dirname, '../packages'); +require('source-map-support').install({ + hookRequire: true +}); + + +declare let global: any & { + __coverage__: any; +}; + +const inlineSourceMapRe = /\/\/# sourceMappingURL=data:application\/json;base64,(\S+)$/; + + +// Use the internal SDK Hook of the require extension installed by our bootstrapping code to add +// Istanbul collection to the code. +const codeMap = new Map(); + +(global as any)._SdkRequireHook = function(code: string, filename: string) { + // Skip spec files. + if (filename.match(/_spec\.ts$/)) { + return code; + } + if (codeMap.get(filename)) { + return codeMap.get(filename)!.code; + } + + const instrumenter = new Istanbul.Instrumenter({ + esModules: true, + codeGenerationOptions: { + sourceMap: filename, + sourceMapWithCode: true + } + }); + let instrumentedCode = instrumenter.instrumentSync(code, filename); + const sourceMapGenerator: SourceMapGenerator = (instrumenter as any).sourceMap; + const match = code.match(inlineSourceMapRe); + + if (match) { + // Fix source maps for exception reporting (since the exceptions happen in the instrumented + // code. + const sourceMapJson = JSON.parse(Buffer.from(match[1], 'base64').toString()); + const consumer = new SourceMapConsumer(sourceMapJson); + sourceMapGenerator.applySourceMap(consumer, filename); + + instrumentedCode = instrumentedCode.replace(inlineSourceMapRe, '') + + '//# sourceMappingURL=data:application/json;base64,' + + new Buffer(sourceMapGenerator.toString()).toString('base64'); + + // Keep the consumer from the original source map, because the reports from Istanbul are + // already mapped against the code. + codeMap.set(filename, { code: instrumentedCode, map: consumer }); + } + + return instrumentedCode; +}; + + +// Add the Istanbul reporter. +const istanbulCollector = new Istanbul.Collector({}); +const istanbulReporter = new Istanbul.Reporter(undefined, 'coverage/'); +istanbulReporter.addAll(['json', 'lcov']); + + +interface CoverageLocation { + start: Position; + end: Position; +} + +class IstanbulReporter implements jasmine.CustomReporter { + // Update a location object from a SourceMap. Will ignore the location if the sourcemap does + // not have a valid mapping. + private _updateLocation(consumer: SourceMapConsumer, location: CoverageLocation) { + const start = consumer.originalPositionFor(location.start); + const end = consumer.originalPositionFor(location.end); + + // Filter invalid original positions. + if (start.line !== null && start.column !== null) { + // Filter unwanted properties. + location.start = { line: start.line, column: start.column }; + } + if (end.line !== null && end.column !== null) { + location.end = { line: end.line, column: end.column }; + } + } + + private _updateCoverageJsonSourceMap(coverageJson: any) { + // Update the coverageJson with the SourceMap. + for (const path of Object.keys(coverageJson)) { + const entry = codeMap.get(path); + if (!entry) { + continue; + } + + const consumer = entry.map; + const coverage = coverageJson[path]; + + // Update statement maps. + for (const branchId of Object.keys(coverage.branchMap)) { + debugger; + const branch = coverage.branchMap[branchId]; + let line: number | null = null; + let column = 0; + do { + line = consumer.originalPositionFor({ line: branch.line, column: column++ }).line; + } while (line === null && column < 100); + + branch.line = line; + + for (const location of branch.locations) { + this._updateLocation(consumer, location); + } + } + + for (const id of Object.keys(coverage.statementMap)) { + const location = coverage.statementMap[id]; + this._updateLocation(consumer, location); + } + + for (const id of Object.keys(coverage.fnMap)) { + const fn = coverage.fnMap[id]; + fn.line = consumer.originalPositionFor({ line: fn.line, column: 0 }).line; + this._updateLocation(consumer, fn.loc); + } + } + } + + jasmineDone(_runDetails: jasmine.RunDetails): void { + if (global.__coverage__) { + this._updateCoverageJsonSourceMap(global.__coverage__); + istanbulCollector.add(global.__coverage__); + } + + istanbulReporter.write(istanbulCollector, true, () => {}); + } +} + + +// Create a Jasmine runner and configure it. +const runner = new Jasmine({ projectBaseDir: projectBaseDir }); + +if (process.argv.indexOf('--spec-reporter') != -1) { + runner.env.clearReporters(); + runner.env.addReporter(new JasmineSpecReporter({ + stacktrace: { + // Filter all JavaScript files that appear after a TypeScript file (callers) from the stack + // trace. + filter: (x: string) => { + return x.substr(0, x.indexOf('\n', x.indexOf('\n', x.lastIndexOf('.ts:')) + 1)); + } + }, + suite: { + displayNumber: true + }, + summary: { + displayStacktrace: true, + displayErrorMessages: true + } + })); +} +runner.env.addReporter(new IstanbulReporter()); + + +// Manually set exit code (needed with custom reporters) +runner.onComplete((success: boolean) => { + process.exitCode = success ? 0 : 1; +}); + + +glob.sync('packages/**/*.spec.ts') + .filter(p => !/schematics_cli\/schematics\//.test(p)) + .forEach(path => { + console.error(`Invalid spec file name: ${path}. You're using the old convention.`); + }); + +// Run the tests. +const allTests = + glob.sync('packages/**/*_spec.ts') + .map(p => relative(projectBaseDir, p)) + .filter(p => !/schematics_cli\/schematics\//.test(p)); + +export default function(_args: any) { + runner.execute(allTests); +} From 9f618a1290c286f37705dfe0380bbb9dfd911860 Mon Sep 17 00:00:00 2001 From: Hans Larsen Date: Tue, 23 May 2017 15:18:18 -0700 Subject: [PATCH 03/12] feat(@angular/schematics): implement the schematics library This is not including a README, which will come later. --- packages/schematics/package.json | 31 ++ packages/schematics/src/engine/collection.ts | 53 +++ packages/schematics/src/engine/context.ts | 16 + packages/schematics/src/engine/engine.ts | 71 ++++ packages/schematics/src/engine/interface.ts | 81 +++++ packages/schematics/src/engine/schematic.ts | 44 +++ .../schematics/src/engine/schematic_spec.ts | 63 ++++ .../schematics/src/exception/exception.ts | 24 ++ packages/schematics/src/index.ts | 52 +++ packages/schematics/src/rules/base.ts | 125 +++++++ packages/schematics/src/rules/base_spec.ts | 116 +++++++ packages/schematics/src/rules/move.ts | 10 + packages/schematics/src/rules/random.ts | 43 +++ packages/schematics/src/rules/schematic.ts | 19 ++ .../schematics/src/rules/schematic_spec.ts | 103 ++++++ packages/schematics/src/rules/template.ts | 106 ++++++ .../schematics/src/rules/template/template.ts | 309 ++++++++++++++++++ .../schematics/src/rules/template_spec.ts | 98 ++++++ packages/schematics/src/rules/url.ts | 9 + .../schematics/src/rules/utils/is-binary.ts | 21 ++ packages/schematics/src/sink/dryrun.ts | 110 +++++++ packages/schematics/src/sink/dryrun_spec.ts | 83 +++++ packages/schematics/src/sink/filesystem.ts | 95 ++++++ .../schematics/src/sink/filesystem_spec.ts | 45 +++ packages/schematics/src/sink/sink.ts | 140 ++++++++ .../schematics/src/sink/virtual-filesystem.ts | 94 ++++++ packages/schematics/src/tree/action.ts | 136 ++++++++ packages/schematics/src/tree/action_spec.ts | 73 +++++ packages/schematics/src/tree/empty.ts | 6 + packages/schematics/src/tree/entry.ts | 20 ++ packages/schematics/src/tree/filesystem.ts | 47 +++ .../schematics/src/tree/filesystem_spec.ts | 15 + packages/schematics/src/tree/filtered.ts | 29 ++ packages/schematics/src/tree/filtered_spec.ts | 15 + packages/schematics/src/tree/interface.ts | 52 +++ packages/schematics/src/tree/memory-host.ts | 44 +++ packages/schematics/src/tree/node-host.ts | 22 ++ packages/schematics/src/tree/null.ts | 50 +++ packages/schematics/src/tree/recorder.ts | 39 +++ packages/schematics/src/tree/static.ts | 27 ++ packages/schematics/src/tree/virtual.ts | 257 +++++++++++++++ packages/schematics/src/tree/virtual_spec.ts | 133 ++++++++ .../schematics/src/utility/linked-list.ts | 59 ++++ packages/schematics/src/utility/path.ts | 37 +++ packages/schematics/src/utility/path_spec.ts | 34 ++ .../schematics/src/utility/update-buffer.ts | 253 ++++++++++++++ .../src/utility/update-buffer_spec.ts | 174 ++++++++++ packages/schematics/tsconfig.json | 9 + 48 files changed, 3492 insertions(+) create mode 100644 packages/schematics/package.json create mode 100644 packages/schematics/src/engine/collection.ts create mode 100644 packages/schematics/src/engine/context.ts create mode 100644 packages/schematics/src/engine/engine.ts create mode 100644 packages/schematics/src/engine/interface.ts create mode 100644 packages/schematics/src/engine/schematic.ts create mode 100644 packages/schematics/src/engine/schematic_spec.ts create mode 100644 packages/schematics/src/exception/exception.ts create mode 100644 packages/schematics/src/index.ts create mode 100644 packages/schematics/src/rules/base.ts create mode 100644 packages/schematics/src/rules/base_spec.ts create mode 100644 packages/schematics/src/rules/move.ts create mode 100644 packages/schematics/src/rules/random.ts create mode 100644 packages/schematics/src/rules/schematic.ts create mode 100644 packages/schematics/src/rules/schematic_spec.ts create mode 100644 packages/schematics/src/rules/template.ts create mode 100644 packages/schematics/src/rules/template/template.ts create mode 100644 packages/schematics/src/rules/template_spec.ts create mode 100644 packages/schematics/src/rules/url.ts create mode 100644 packages/schematics/src/rules/utils/is-binary.ts create mode 100644 packages/schematics/src/sink/dryrun.ts create mode 100644 packages/schematics/src/sink/dryrun_spec.ts create mode 100644 packages/schematics/src/sink/filesystem.ts create mode 100644 packages/schematics/src/sink/filesystem_spec.ts create mode 100644 packages/schematics/src/sink/sink.ts create mode 100644 packages/schematics/src/sink/virtual-filesystem.ts create mode 100644 packages/schematics/src/tree/action.ts create mode 100644 packages/schematics/src/tree/action_spec.ts create mode 100644 packages/schematics/src/tree/empty.ts create mode 100644 packages/schematics/src/tree/entry.ts create mode 100644 packages/schematics/src/tree/filesystem.ts create mode 100644 packages/schematics/src/tree/filesystem_spec.ts create mode 100644 packages/schematics/src/tree/filtered.ts create mode 100644 packages/schematics/src/tree/filtered_spec.ts create mode 100644 packages/schematics/src/tree/interface.ts create mode 100644 packages/schematics/src/tree/memory-host.ts create mode 100644 packages/schematics/src/tree/node-host.ts create mode 100644 packages/schematics/src/tree/null.ts create mode 100644 packages/schematics/src/tree/recorder.ts create mode 100644 packages/schematics/src/tree/static.ts create mode 100644 packages/schematics/src/tree/virtual.ts create mode 100644 packages/schematics/src/tree/virtual_spec.ts create mode 100644 packages/schematics/src/utility/linked-list.ts create mode 100644 packages/schematics/src/utility/path.ts create mode 100644 packages/schematics/src/utility/path_spec.ts create mode 100644 packages/schematics/src/utility/update-buffer.ts create mode 100644 packages/schematics/src/utility/update-buffer_spec.ts create mode 100644 packages/schematics/tsconfig.json diff --git a/packages/schematics/package.json b/packages/schematics/package.json new file mode 100644 index 0000000000..d543213b32 --- /dev/null +++ b/packages/schematics/package.json @@ -0,0 +1,31 @@ +{ + "name": "@angular/schematics", + "version": "0.0.0", + "description": "CLI tool for Angular", + "main": "src/index.js", + "typings": "src/index.d.ts", + "keywords": [ + "angular", + "sdk", + "blueprints", + "code generation", + "schematics", + "Angular SDK" + ], + "repository": { + "type": "git", + "url": "https://github.com/angular/sdk.git" + }, + "engines": { + "node": ">= 6.9.0", + "npm": ">= 3.0.0" + }, + "author": "Angular Authors", + "license": "MIT", + "bugs": { + "url": "https://github.com/angular/sdk/issues" + }, + "homepage": "https://github.com/angular/sdk", + "dependencies": { + } +} diff --git a/packages/schematics/src/engine/collection.ts b/packages/schematics/src/engine/collection.ts new file mode 100644 index 0000000000..23f2d49ce7 --- /dev/null +++ b/packages/schematics/src/engine/collection.ts @@ -0,0 +1,53 @@ +import {SchematicEngine} from './engine'; +import {Collection, CollectionDescription, Schematic, SchematicDescription} from './interface'; +import {BaseException} from '../exception/exception'; + + + +export class UnknownSchematicNameException extends BaseException { + constructor(collection: string, name: string) { + super(`Schematic named "${name}" could not be found in collection "${collection}".`); + } +} +export class InvalidSchematicException extends BaseException { + constructor(name: string) { super(`Invalid schematic: "${name}".`); } +} + + +export class CollectionImpl implements Collection { + private _schematics: { [name: string]: (options: any) => Schematic | null } = {}; + + constructor(private _description: CollectionDescription, + private _engine: SchematicEngine) { + Object.keys(this._description.schematics).forEach(name => { + this._schematics[name] = (options: any) => this._engine.createSchematic(name, this, options); + }); + } + + get engine() { return this._engine; } + get name() { return this._description.name || ''; } + get path() { return this._description.path || ''; } + + listSchematicNames(): string[] { + return Object.keys(this._schematics); + } + + getSchematicDescription(name: string): SchematicDescription | null { + if (!(name in this._description.schematics)) { + return null; + } + return this._description.schematics[name]; + } + + createSchematic(name: string, options: T): Schematic { + if (!(name in this._schematics)) { + throw new UnknownSchematicNameException(this.name, name); + } + + const schematic = this._schematics[name](options); + if (!schematic) { + throw new InvalidSchematicException(name); + } + return schematic; + } +} diff --git a/packages/schematics/src/engine/context.ts b/packages/schematics/src/engine/context.ts new file mode 100644 index 0000000000..b0b6da146d --- /dev/null +++ b/packages/schematics/src/engine/context.ts @@ -0,0 +1,16 @@ +import {Engine, Schematic, SchematicContext} from './interface'; +import {MergeStrategy, Tree} from '../tree/interface'; + +import {Observable} from 'rxjs/Observable'; + + +export class SchematicContextImpl implements SchematicContext { + constructor(private _schematic: Schematic, + private _host: Observable, + private _strategy = MergeStrategy.Default) {} + + get host() { return this._host; } + get engine(): Engine { return this._schematic.collection.engine; } + get schematic() { return this._schematic; } + get strategy() { return this._strategy; } +} diff --git a/packages/schematics/src/engine/engine.ts b/packages/schematics/src/engine/engine.ts new file mode 100644 index 0000000000..ce6d8473ae --- /dev/null +++ b/packages/schematics/src/engine/engine.ts @@ -0,0 +1,71 @@ +import {CollectionImpl} from './collection'; +import { + Collection, + Engine, EngineHost, + ProtocolHandler, + Schematic, + SchematicContext, + Source +} from './interface'; +import {SchematicImpl} from './schematic'; +import {BaseException} from '../exception/exception'; +import {empty} from '../tree/static'; + +import {Url, parse, format} from 'url'; + + +export class InvalidSourceUrlException extends BaseException { + constructor(url: string) { super(`Invalid source url: "${url}".`); } +} +export class UnknownUrlSourceProtocol extends BaseException { + constructor(url: string) { super(`Unknown Protocol on url "${url}".`); } +} + + +export class SchematicEngine implements Engine { + private _protocolMap = new Map(); + + constructor(private _options: EngineHost) { + // Default implementations. + this._protocolMap.set('null', () => { + return () => empty(); + }); + this._protocolMap.set('', (url: Url) => { + // Make a copy, change the protocol. + const fileUrl = parse(format(url)); + fileUrl.protocol = 'file:'; + return (context: SchematicContext) => context.engine.createSourceFromUrl(fileUrl)(context); + }); + } + + createCollection(name: string): Collection | null { + const description = this._options.loadCollection(name); + if (!description) { + return null; + } + + return new CollectionImpl(description, this); + } + + createSchematic(name: string, collection: Collection, options: T): Schematic | null { + const description = this._options.loadSchematic(name, collection, options); + if (!description) { + return null; + } + + return new SchematicImpl(description, collection); + } + + registerUrlProtocolHandler(protocol: string, handler: ProtocolHandler) { + this._protocolMap.set(protocol, handler); + } + + createSourceFromUrl(url: Url): Source { + const protocol = (url.protocol || '').replace(/:$/, ''); + const handler = this._protocolMap.get(protocol); + if (!handler) { + throw new UnknownUrlSourceProtocol(url.toString()); + } + return handler(url); + } +} diff --git a/packages/schematics/src/engine/interface.ts b/packages/schematics/src/engine/interface.ts new file mode 100644 index 0000000000..7127dad274 --- /dev/null +++ b/packages/schematics/src/engine/interface.ts @@ -0,0 +1,81 @@ +import {MergeStrategy, Tree} from '../tree/interface'; + +import {Observable} from 'rxjs/Observable'; +import {Url} from 'url'; + + +export interface EngineHost { + loadCollection(name: string): CollectionDescription | null; + loadSchematic(name: string, + collection: Collection, + options: T): ResolvedSchematicDescription | null; +} + + +export interface Schematic { + readonly name: string; + readonly description: string; + readonly path: string; + readonly collection: Collection; + + call(host: Observable, parentContext: Partial): Observable; +} + + +export interface ProtocolHandler { + (url: Url): Source; +} + + + +export interface Engine { + createCollection(name: string): Collection | null; + createSchematic(name: string, collection: Collection, options: T): Schematic | null; + registerUrlProtocolHandler(protocol: string, handler: ProtocolHandler): void; + createSourceFromUrl(url: Url): Source; +} + + +export interface Collection { + readonly engine: Engine; + readonly name: string; + readonly path: string; + + listSchematicNames(): string[]; + getSchematicDescription(name: string): SchematicDescription | null; + createSchematic(name: string, options: T): Schematic; +} + + +export interface SchematicContext { + readonly engine: Engine; + readonly schematic: Schematic; + readonly host: Observable; + readonly strategy: MergeStrategy; +} + + +export interface CollectionDescription { + readonly path: string; + readonly name?: string; + readonly version?: string; + readonly schematics: { [name: string]: SchematicDescription }; +} + +export interface SchematicDescription { + readonly factory: string; + readonly description: string; + readonly schema?: string; +} + + +export interface ResolvedSchematicDescription extends SchematicDescription { + readonly name: string; + readonly path: string; + readonly rule: Rule; +} + +export type RuleFactory = (options: T) => Rule; + +export type Source = (context: SchematicContext) => Tree | Observable; +export type Rule = (tree: Tree, context: SchematicContext) => Tree | Observable; diff --git a/packages/schematics/src/engine/schematic.ts b/packages/schematics/src/engine/schematic.ts new file mode 100644 index 0000000000..d2eb1509bf --- /dev/null +++ b/packages/schematics/src/engine/schematic.ts @@ -0,0 +1,44 @@ +import {SchematicContextImpl} from './context'; +import {Collection, ResolvedSchematicDescription, Schematic, SchematicContext} from './interface'; +import {MergeStrategy, Tree} from '../tree/interface'; +import {BaseException} from '../exception/exception'; + +import {Observable} from 'rxjs/Observable'; +import 'rxjs/add/observable/fromPromise'; +import 'rxjs/add/observable/of'; +import 'rxjs/add/operator/concatMap'; + + +export class InvalidSchematicsNameException extends BaseException { + constructor(path: string, name: string) { + super(`Schematics at path "${path}" has invalid name "${name}".`); + } +} + + +export class SchematicImpl implements Schematic { + constructor(private _descriptor: ResolvedSchematicDescription, + private _collection: Collection) { + if (!_descriptor.name.match(/^[-_.a-zA-Z0-9]+$/)) { + throw new InvalidSchematicsNameException(_descriptor.path, _descriptor.name); + } + } + + get name() { return this._descriptor.name; } + get description() { return this._descriptor.description; } + get path() { return this._descriptor.path; } + get collection() { return this._collection; } + + call(host: Observable, parentContext: Partial): Observable { + const context = new SchematicContextImpl(this, host, + parentContext.strategy || MergeStrategy.Default); + return host.concatMap(tree => { + const result = this._descriptor.rule(tree, context); + if (result instanceof Observable) { + return result; + } else { + return Observable.of(result); + } + }); + } +} diff --git a/packages/schematics/src/engine/schematic_spec.ts b/packages/schematics/src/engine/schematic_spec.ts new file mode 100644 index 0000000000..b04fdf771f --- /dev/null +++ b/packages/schematics/src/engine/schematic_spec.ts @@ -0,0 +1,63 @@ +import {ResolvedSchematicDescription} from './interface'; +import {SchematicImpl} from './schematic'; +import {Tree} from '../tree/interface'; +import {branch, empty} from '../tree/static'; + +import 'rxjs/add/operator/toArray'; +import 'rxjs/add/operator/toPromise'; +import {Observable} from 'rxjs/Observable'; + + + +describe('Schematic', () => { + it('works with a rule', done => { + let inner: any = null; + const desc: ResolvedSchematicDescription = { + name: 'test', + description: '', + factory: '', + path: 'a/b/c', + rule: (tree: Tree) => { + inner = branch(tree); + tree.create('a/b/c', 'some content'); + return tree; + } + }; + + const schematic = new SchematicImpl(desc, null !); + + schematic.call(Observable.of(empty()), {}) + .toPromise() + .then(x => { + expect(inner.files).toEqual([]); + expect(x.files).toEqual(['/a/b/c']); + }) + .then(done, done.fail); + }); + + it('works with a rule that returns an observable', done => { + let inner: any = null; + const desc: ResolvedSchematicDescription = { + name: 'test', + description: '', + factory: '', + path: 'a/b/c', + rule: (fem: Tree) => { + inner = fem; + return Observable.of(empty()); + } + }; + + + const schematic = new SchematicImpl(desc, null !); + schematic.call(Observable.of(empty()), {}) + .toPromise() + .then(x => { + expect(inner.files).toEqual([]); + expect(x.files).toEqual([]); + expect(inner).not.toBe(x); + }) + .then(done, done.fail); + }); + +}); diff --git a/packages/schematics/src/exception/exception.ts b/packages/schematics/src/exception/exception.ts new file mode 100644 index 0000000000..4b1401791c --- /dev/null +++ b/packages/schematics/src/exception/exception.ts @@ -0,0 +1,24 @@ +// Starting with TS 2.1, Error cannot be properly extended anymore, so we implement the same +// interface but in a different package. +export class BaseException extends Error { + constructor(message = '') { + super(message); + } +} + + +// Exceptions +export class FileDoesNotExistException extends BaseException { + constructor(path: string) { super(`Path "${path}" does not exist.`); } +} +export class FileAlreadyExistException extends BaseException { + constructor(path: string) { super(`Path "${path}" already exist.`); } +} +export class ContentHasMutatedException extends BaseException { + constructor(path: string) { + super(`Content at path "${path}" has changed between the start and the end of an update.`); + } +} +export class InvalidUpdateRecordException extends BaseException { + constructor() { super(`Invalid record instance.`); } +} diff --git a/packages/schematics/src/index.ts b/packages/schematics/src/index.ts new file mode 100644 index 0000000000..e6422fb43c --- /dev/null +++ b/packages/schematics/src/index.ts @@ -0,0 +1,52 @@ +import {FilePredicate, MergeStrategy} from './tree/interface'; +import {Tree as TreeInterface} from './tree/interface'; +import {branch, empty, merge, optimize, partition} from './tree/static'; + + +export { BaseException } from './exception/exception'; + +export * from './tree/action'; +export * from './engine/collection'; +export * from './engine/engine'; +export * from './engine/interface'; +export * from './tree/interface'; +export * from './rules/base'; +export * from './rules/move'; +export * from './rules/random'; +export * from './rules/schematic'; +export * from './rules/template'; +export * from './rules/url'; +export * from './tree/empty'; +export * from './tree/filesystem'; +export * from './tree/memory-host'; +export {UpdateRecorder} from './tree/interface'; +export * from './engine/schematic'; +export * from './sink/dryrun'; +export {FileSystemSink} from './sink/filesystem'; +export * from './utility/path'; + + +export interface TreeConstructor { + new (): TreeInterface; + + empty(): TreeInterface; + branch(tree: TreeInterface): TreeInterface; + merge(tree: TreeInterface, other: TreeInterface, strategy?: MergeStrategy): TreeInterface; + partition(tree: TreeInterface, predicate: FilePredicate): [TreeInterface, TreeInterface]; + optimize(tree: TreeInterface): TreeInterface; +} + +export type Tree = TreeInterface; +export const Tree: TreeConstructor = { + empty() { return empty(); }, + branch(tree: TreeInterface) { return branch(tree); }, + merge(tree: TreeInterface, + other: TreeInterface, + strategy: MergeStrategy = MergeStrategy.Default) { + return merge(tree, other, strategy); + }, + partition(tree: TreeInterface, predicate: FilePredicate) { + return partition(tree, predicate); + }, + optimize(tree: TreeInterface) { return optimize(tree); } +} as any; diff --git a/packages/schematics/src/rules/base.ts b/packages/schematics/src/rules/base.ts new file mode 100644 index 0000000000..d982a9e066 --- /dev/null +++ b/packages/schematics/src/rules/base.ts @@ -0,0 +1,125 @@ +import {MergeStrategy, FilePredicate} from '../tree/interface'; +import {Rule, SchematicContext, Source} from '../engine/interface'; +import {BaseException} from '../exception/exception'; +import {VirtualTree} from '../tree/virtual'; +import {FilteredTree} from '../tree/filtered'; +import {Tree} from '../tree/interface'; +import {empty as staticEmpty} from '../tree/static'; + +import {Observable} from 'rxjs/Observable'; +import 'rxjs/add/observable/of'; +import 'rxjs/add/operator/map'; +import 'rxjs/add/operator/mergeMap'; + + +export class InvalidRuleResultException extends BaseException { + constructor(value: any) { + let v: string = 'Unknown Type'; + if (value === undefined) { + v = 'undefined'; + } else if (value === null) { + v = 'null'; + } else if (typeof value == 'function') { + v = `Function()`; + } else if (typeof value != 'object') { + v = `${typeof value}(${JSON.stringify(value)})`; + } else { + if (Object.getPrototypeOf(value) == Object) { + v = `Object(${JSON.stringify(value)})`; + } else if (value.constructor) { + v = `Instance of class ${value.constructor.name}`; + } else { + v = 'Unknown Object'; + } + } + super(`Invalid rule or source result: ${v}.`); + } +} + + +export function source(tree: Tree): Source { + return () => tree; +} +export function empty(): Source { + return () => staticEmpty(); +} + + +export function callSource(source: Source, context: SchematicContext): Observable { + const result = source(context); + + if (result instanceof VirtualTree) { + return Observable.of(result); + } else if (result instanceof Observable) { + return result; + } else { + throw new InvalidRuleResultException(result); + } +} +export function callRule(rule: Rule, + input: Observable, + context: SchematicContext): Observable { + return input.mergeMap(i => { + const result = rule(i, context); + + if (result instanceof VirtualTree) { + return Observable.of(result as Tree); + } else if (result instanceof Observable) { + return result; + } else { + throw new InvalidRuleResultException(result); + } + }); +} + + +export function chain(rules: Rule[]): Rule { + return (tree: Tree, context: SchematicContext) => { + return rules.reduce((acc: Observable, curr: Rule) => { + return callRule(curr, acc, context); + }, Observable.of(tree)); + }; +} + + +export function apply(source: Source, rules: Rule[]): Source { + return (context: SchematicContext) => { + return callRule(chain(rules), callSource(source, context), context); + }; +} + + +export function merge(sources: Source[], strategy: MergeStrategy = MergeStrategy.Default): Source { + const empty = Observable.of(staticEmpty()); + return (context: SchematicContext) => { + return sources.reduce((acc: Observable, curr: Source) => { + const result = callSource(curr, context); + return acc.concatMap(x => { + return result.map(y => VirtualTree.merge(x, y, strategy || context.strategy)); + }); + }, empty); + }; +} + + +export function mergeWith(sources: Source[], + strategy: MergeStrategy = MergeStrategy.Default): Rule { + return (tree: Tree, context: SchematicContext) => { + return sources.reduce((acc: Observable, curr: Source) => { + const result = callSource(curr, context); + return acc.concatMap(x => { + return result.map(y => VirtualTree.merge(x, y, strategy || context.strategy)); + }); + }, Observable.of(tree)); + }; +} + + +export function noop(): Rule { + return (tree: Tree, _context: SchematicContext) => tree; +} + + +export function filter(predicate: FilePredicate): Rule { + return (tree: Tree) => new FilteredTree(tree, predicate); +} diff --git a/packages/schematics/src/rules/base_spec.ts b/packages/schematics/src/rules/base_spec.ts new file mode 100644 index 0000000000..c42fd22f35 --- /dev/null +++ b/packages/schematics/src/rules/base_spec.ts @@ -0,0 +1,116 @@ +import {apply, callRule, callSource, chain} from './base'; +import {Rule, SchematicContext, Source} from '../engine/interface'; +import {Tree} from '../tree/interface'; +import {empty} from '../tree/static'; + +import {Observable} from 'rxjs/Observable'; +import 'rxjs/add/operator/toPromise'; + + + +const context: SchematicContext = null !; + + +describe('chain', () => { + it('works with simple rules', done => { + const rulesCalled: Tree[] = []; + + const tree0 = empty(); + const tree1 = empty(); + const tree2 = empty(); + const tree3 = empty(); + + const rule0: Rule = (tree: Tree) => { rulesCalled[0] = tree; return tree1; }; + const rule1: Rule = (tree: Tree) => { rulesCalled[1] = tree; return tree2; }; + const rule2: Rule = (tree: Tree) => { rulesCalled[2] = tree; return tree3; }; + + callRule(chain([ rule0, rule1, rule2 ]), Observable.of(tree0), context) + .toPromise() + .then(result => { + expect(result).not.toBe(tree0); + expect(rulesCalled[0]).toBe(tree0); + expect(rulesCalled[1]).toBe(tree1); + expect(rulesCalled[2]).toBe(tree2); + expect(result).toBe(tree3); + }) + .then(done, done.fail); + }); + + it('works with observable rules', done => { + const rulesCalled: Tree[] = []; + + const tree0 = empty(); + const tree1 = empty(); + const tree2 = empty(); + const tree3 = empty(); + + const rule0: Rule = (tree: Tree) => { rulesCalled[0] = tree; return Observable.of(tree1); }; + const rule1: Rule = (tree: Tree) => { rulesCalled[1] = tree; return Observable.of(tree2); }; + const rule2: Rule = (tree: Tree) => { rulesCalled[2] = tree; return tree3; }; + + callRule(chain([ rule0, rule1, rule2 ]), Observable.of(tree0), context) + .toPromise() + .then(result => { + expect(result).not.toBe(tree0); + expect(rulesCalled[0]).toBe(tree0); + expect(rulesCalled[1]).toBe(tree1); + expect(rulesCalled[2]).toBe(tree2); + expect(result).toBe(tree3); + }) + .then(done, done.fail); + }); +}); + +describe('apply', () => { + it('works with simple rules', done => { + const rulesCalled: Tree[] = []; + let sourceCalled = false; + + const tree0 = empty(); + const tree1 = empty(); + const tree2 = empty(); + const tree3 = empty(); + + const source: Source = () => { sourceCalled = true; return tree0; }; + const rule0: Rule = (tree: Tree) => { rulesCalled[0] = tree; return tree1; }; + const rule1: Rule = (tree: Tree) => { rulesCalled[1] = tree; return tree2; }; + const rule2: Rule = (tree: Tree) => { rulesCalled[2] = tree; return tree3; }; + + callSource(apply(source, [ rule0, rule1, rule2 ]), context) + .toPromise() + .then(result => { + expect(result).not.toBe(tree0); + expect(rulesCalled[0]).toBe(tree0); + expect(rulesCalled[1]).toBe(tree1); + expect(rulesCalled[2]).toBe(tree2); + expect(result).toBe(tree3); + }) + .then(done, done.fail); + }); + + it('works with observable rules', done => { + const rulesCalled: Tree[] = []; + let sourceCalled = false; + + const tree0 = empty(); + const tree1 = empty(); + const tree2 = empty(); + const tree3 = empty(); + + const source: Source = () => { sourceCalled = true; return tree0; }; + const rule0: Rule = (tree: Tree) => { rulesCalled[0] = tree; return Observable.of(tree1); }; + const rule1: Rule = (tree: Tree) => { rulesCalled[1] = tree; return Observable.of(tree2); }; + const rule2: Rule = (tree: Tree) => { rulesCalled[2] = tree; return tree3; }; + + callSource(apply(source, [ rule0, rule1, rule2 ]), context) + .toPromise() + .then(result => { + expect(result).not.toBe(tree0); + expect(rulesCalled[0]).toBe(tree0); + expect(rulesCalled[1]).toBe(tree1); + expect(rulesCalled[2]).toBe(tree2); + expect(result).toBe(tree3); + }) + .then(done, done.fail); + }); +}); diff --git a/packages/schematics/src/rules/move.ts b/packages/schematics/src/rules/move.ts new file mode 100644 index 0000000000..8a8bd4b2d5 --- /dev/null +++ b/packages/schematics/src/rules/move.ts @@ -0,0 +1,10 @@ +import {Rule} from '../engine/interface'; +import {Tree} from '../tree/interface'; + + +export function move(root: string): Rule { + return (tree: Tree) => { + tree.files.forEach(originalPath => tree.rename(originalPath, `${root}/${originalPath}`)); + return tree; + }; +} diff --git a/packages/schematics/src/rules/random.ts b/packages/schematics/src/rules/random.ts new file mode 100644 index 0000000000..42f1eff7c1 --- /dev/null +++ b/packages/schematics/src/rules/random.ts @@ -0,0 +1,43 @@ +import {Source} from '../engine/interface'; +import {VirtualTree} from '../tree/virtual'; + + +function generateStringOfLength(l: number) { + return new Array(l).fill(0).map(_x => { + return 'abcdefghijklmnopqrstuvwxyz'[Math.floor(Math.random() * 26)]; + }).join(''); +} + + +function random(from: number, to: number) { + return Math.floor(Math.random() * (to - from)) + from; +} + + +export interface RandomOptions { + root?: string; + multi?: boolean | number; + multiFiles?: boolean | number; +} + + +export default function(options: RandomOptions): Source { + return () => { + const root = ('root' in options) ? options.root : '/'; + + const map = new VirtualTree(); + const nbFiles = ('multiFiles' in options) + ? (typeof options.multiFiles == 'number' ? options.multiFiles : random(2, 12)) + : 1; + + for (let i = 0; i < nbFiles; i++) { + const path = 'a/b/c/d/e/f'.slice(Math.random() * 10); + const fileName = generateStringOfLength(20); + const content = generateStringOfLength(100); + + map.create(root + '/' + path + '/' + fileName, content); + } + + return map; + }; +} diff --git a/packages/schematics/src/rules/schematic.ts b/packages/schematics/src/rules/schematic.ts new file mode 100644 index 0000000000..8c8579a4bd --- /dev/null +++ b/packages/schematics/src/rules/schematic.ts @@ -0,0 +1,19 @@ +import {Rule, SchematicContext} from '../engine/interface'; +import {Tree} from '../tree/interface'; +import {branch} from '../tree/static'; + +import {Observable} from 'rxjs/Observable'; + + +export type SchematicOptions = { + name: string; + options: any; +}; + + +export function schematic(options: SchematicOptions): Rule { + return (host: Tree, context: SchematicContext) => { + const schematic = context.schematic.collection.createSchematic(options.name, options.options); + return schematic.call(Observable.of(branch(host)), context); + }; +} diff --git a/packages/schematics/src/rules/schematic_spec.ts b/packages/schematics/src/rules/schematic_spec.ts new file mode 100644 index 0000000000..4ae9ef612e --- /dev/null +++ b/packages/schematics/src/rules/schematic_spec.ts @@ -0,0 +1,103 @@ +// import { +// Tree, +// TreeTransformFactory, +// SchematicDescription +// } from '@angular/schematics'; +// import {Schematic} from './schematic'; +// +// import 'rxjs/add/operator/toArray'; +// import 'rxjs/add/operator/toPromise'; +// import {Observable} from 'rxjs/Observable'; +// +// +// describe('Schematic', () => { +// +// it('works without a transform', done => { +// const desc: SchematicDescription = { +// name: 'test', +// description: '', +// inputs: [ +// 'null://', +// [ 'null://' ] +// ] +// }; +// +// const schematic = new Schematic(desc, 'some/path'); +// +// schematic.run({}) +// .toArray() +// .toPromise() +// .then(x => { +// expect(x.length).toBe(2); +// expect(x[0].find()).toEqual([]); +// }) +// .then(done, done.fail); +// }); +// +// it('works with a transform that returns an array', done => { +// const factory: TreeTransformFactory = (_options: any) => { +// return (fem: Tree) => { +// inner = fem; +// return []; +// }; +// }; +// +// let inner: any = null; +// const desc: SchematicDescription = { +// name: 'test', +// description: '', +// inputs: [ +// 'null://', +// [ +// 'null://', +// { $ref: factory } +// ] +// ] +// }; +// +// const schematic = new Schematic(desc, 'some/path'); +// +// schematic.run({}) +// .toArray() +// .toPromise() +// .then(x => { +// expect(inner.find()).toEqual([]); +// expect(x.length).toEqual(1); +// }) +// .then(done, done.fail); +// }); +// +// it('works with a transform that returns an observable', done => { +// const factory: TreeTransformFactory = (_options: any) => { +// return (fem: Tree) => { +// inner = fem; +// return Observable.empty(); +// }; +// }; +// +// let inner: any = null; +// const desc: SchematicDescription = { +// name: 'test', +// description: '', +// inputs: [ +// 'null://', +// [ +// 'null://', +// { $ref: factory } +// ] +// ] +// }; +// +// +// const schematic = new Schematic(desc, 'some/path'); +// schematic.run({}) +// .toArray() +// .toPromise() +// .then(x => { +// expect(inner.find()).toEqual([]); +// expect(x.length).toEqual(1); +// }) +// .then(done, done.fail); +// }); +// +// }); diff --git a/packages/schematics/src/rules/template.ts b/packages/schematics/src/rules/template.ts new file mode 100644 index 0000000000..bcb4da633a --- /dev/null +++ b/packages/schematics/src/rules/template.ts @@ -0,0 +1,106 @@ +import {chain} from './base'; +import {template as templateImpl} from './template/template'; +import {isBinary} from './utils/is-binary'; +import {Rule} from '../engine/interface'; +import {BaseException} from '../exception/exception'; +import {Tree} from '../tree/interface'; + + + +export class OptionIsNotDefinedException extends BaseException { + constructor(name: string) { super(`Option "${name}" is not defined.`); } +} + + +export class UnknownPipeException extends BaseException { + constructor(name: string) { super(`Pipe "${name}" is not defined.`); } +} + + +export class InvalidPipeException extends BaseException { + constructor(name: string) { super(`Pipe "${name}" is invalid.`); } +} + + +export const kPathTemplateComponentRE = /__([^_]+)__/g; +export const kPathTemplatePipeRE = /@([^@]+)/; + + + +export function applyContentTemplate(original: string, + options: T): string { + return templateImpl(original, {})(options); +} + + +export function contentTemplate(options: T): Rule { + return (tree: Tree) => { + tree.files.forEach(originalPath => { + // Lodash Template. + const content = tree.read(originalPath); + + if (content && !isBinary(content)) { + const output = applyContentTemplate(content.toString('utf-8'), options); + tree.overwrite(originalPath, output); + } + }); + + return tree; + }; +} + + +export function applyPathTemplate(original: string, + options: T): string { + // Path template. + return original.replace(kPathTemplateComponentRE, (_, match) => { + const [name, ...pipes] = match.split(kPathTemplatePipeRE); + const value = typeof options[name] == 'function' + ? options[name].call(options, original) + : options[name]; + + if (value === undefined) { + throw new OptionIsNotDefinedException(name); + } + + return pipes.reduce((acc: string, pipe: string) => { + if (!pipe) { + return acc; + } + if (!(pipe in options)) { + throw new UnknownPipeException(pipe); + } + if (typeof options[pipe] != 'function') { + throw new InvalidPipeException(pipe); + } + + // Coerce to string. + return '' + (options[pipe])(acc); + }, '' + value); + }); +} + + +export function pathTemplate(options: T): Rule { + return (tree: Tree) => { + tree.files.forEach(originalPath => { + const newPath = applyPathTemplate(originalPath, options); + if (originalPath === newPath) { + return; + } + + tree.rename(originalPath, newPath); + }); + + return tree; + }; +} + + + +export function template(options: T): Rule { + return chain([ + contentTemplate(options), + pathTemplate(options) + ]); +} diff --git a/packages/schematics/src/rules/template/template.ts b/packages/schematics/src/rules/template/template.ts new file mode 100644 index 0000000000..122097d79f --- /dev/null +++ b/packages/schematics/src/rules/template/template.ts @@ -0,0 +1,309 @@ +/** + * lodash (Custom Build) + * Build: `lodash modularize exports="npm" -o ./` + * Copyright jQuery Foundation and other contributors + * Released under MIT license + * Based on Underscore.js 1.8.3 + * Copyright Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors + */ +const reInterpolate = /<%=([\s\S]+?)%>/g; + + +/** Used to match HTML entities and HTML characters. */ +const reUnescapedHtml = /[&<>"'`]/g; + +/** Used to match template delimiters. */ +const reEscape = /<%-([\s\S]+?)%>/g, + reEvaluate = /<%([\s\S]+?)%>/g; + +/** Used to map characters to HTML entities. */ +const htmlEscapes: {[char: string]: string} = { + '&': '&', + '<': '<', + '>': '>', + '"': '"', + "'": ''', + '`': '`' +}; + + +export interface TemplateOptions { + sourceURL?: string; +} + +/** + * By default, the template delimiters used by lodash are like those in + * embedded Ruby (ERB). Change the following template settings to use + * alternative delimiters. + * + * @static + * @memberOf _ + * @type {Object} + */ +const kTemplateSettings = { + /** + * Used to detect `data` property values to be HTML-escaped. + */ + 'escape': reEscape, + + /** + * Used to detect code to be evaluated. + */ + 'evaluate': reEvaluate, + + /** + * Used to detect `data` property values to inject. + * + * @memberOf _.templateSettings + * @type {RegExp} + */ + 'interpolate': reInterpolate, + + /** + * Used to import variables into the compiled template. + * + * @memberOf _.templateSettings + * @type {Object} + */ + 'imports': { + + /** + * A reference to the `lodash` function. + * + * @memberOf _.templateSettings.imports + * @type {Function} + */ + '_': { 'escape': escape } + } +}; + +/** + * Converts the characters "&", "<", ">", '"', "'", and "\`" in `string` to + * their corresponding HTML entities. + * + * **Note:** No other characters are escaped. To escape additional + * characters use a third-party library like [_he_](https://mths.be/he). + * + * Though the ">" character is escaped for symmetry, characters like + * ">" and "/" don't need escaping in HTML and have no special meaning + * unless they're part of a tag or unquoted attribute value. See + * [Mathias Bynens's article](https://mathiasbynens.be/notes/ambiguous-ampersands) + * (under "semi-related fun fact") for more details. + * + * Backticks are escaped because in IE < 9, they can break out of + * attribute values or HTML comments. See [#59](https://html5sec.org/#59), + * [#102](https://html5sec.org/#102), [#108](https://html5sec.org/#108), and + * [#133](https://html5sec.org/#133) of the + * [HTML5 Security Cheatsheet](https://html5sec.org/) for more details. + * + * When working with HTML you should always + * [quote attribute values](http://wonko.com/post/html-escaping) to reduce + * XSS vectors. + * + * @static + * @since 0.1.0 + * @memberOf _ + * @category String + * @param {string} [s=''] The string to escape. + * @returns {string} Returns the escaped string. + * @example + * + * _.escape('fred, barney, & pebbles'); + * // => 'fred, barney, & pebbles' + */ +function escape(s: string) { + return s ? s.replace(reUnescapedHtml, key => htmlEscapes[key]) : ''; +} + +/** Used to match empty string literals in compiled template source. */ +const reEmptyStringLeading = /\b__p \+= '';/g; +const reEmptyStringMiddle = /\b(__p \+=) '' \+/g; +const reEmptyStringTrailing = /(__e\(.*?\)|\b__t\)) \+\n'';/g; + +/** Used to ensure capturing order of template delimiters. */ +const reNoMatch = /($^)/; + +/** Used to match unescaped characters in compiled string literals. */ +const reUnescapedString = /['\n\r\u2028\u2029\\]/g; + +/** Used to escape characters for inclusion in compiled string literals. */ +const stringEscapes: {[char: string]: string} = { + '\\': '\\', + "'": "'", + '\n': 'n', + '\r': 'r', + '\u2028': 'u2028', + '\u2029': 'u2029' +}; + +/** + * Creates a compiled template function that can interpolate data properties + * in "interpolate" delimiters, HTML-escape interpolated data properties in + * "escape" delimiters, and execute JavaScript in "evaluate" delimiters. Data + * properties may be accessed as free variables in the template. If a setting + * object is given, it takes precedence over `_.templateSettings` values. + * + * **Note:** In the development build `_.template` utilizes + * [sourceURLs](http://www.html5rocks.com/en/tutorials/developertools/sourcemaps/#toc-sourceurl) + * for easier debugging. + * + * For more information on precompiling templates see + * [lodash's custom builds documentation](https://lodash.com/custom-builds). + * + * For more information on Chrome extension sandboxes see + * [Chrome's extensions documentation](https://developer.chrome.com/extensions/sandboxingEval). + * + * @static + * @since 0.1.0 + * @memberOf _ + * @category String + * @param {string} [content=''] The template string. + * @param {Object} [options={}] The options object. + * @param {RegExp} [options.escape=_.templateSettings.escape] + * The HTML "escape" delimiter. + * @param {RegExp} [options.evaluate=_.templateSettings.evaluate] + * The "evaluate" delimiter. + * @param {Object} [options.imports=_.templateSettings.imports] + * An object to import into the template as free variables. + * @param {RegExp} [options.interpolate=_.templateSettings.interpolate] + * The "interpolate" delimiter. + * @param {string} [options.sourceURL='templateSources[n]'] + * The sourceURL of the compiled template. + * @param {string} [options.variable='obj'] + * The data object variable name. + * @param- {Object} [guard] Enables use as an iteratee for methods like `_.map`. + * @returns {Function} Returns the compiled template function. + * @example + * + * // Use the "interpolate" delimiter to create a compiled template. + * var compiled = _.template('hello <%= user %>!'); + * compiled({ 'user': 'fred' }); + * // => 'hello fred!' + * + * // Use the HTML "escape" delimiter to escape data property values. + * var compiled = _.template('<%- value %>'); + * compiled({ 'value': '