refactor(bazel): Create `ng-add` schematic for Bazel (#28436)
The logic to create additional files needed for Bazel are currently hosted in `ng new`. Such files include the main.*.ts files needed for AOT and a different angular.json to use Bazel builder, among others. This commit refactors the logic into `ng add` so that it can be used to perform the same modifications in an existing project. Users could do so by running `ng add @angular/bazel`. With this change, `ng new` effectively becomes an orchestrator that runs the original `ng new` followed by `ng add @angular/bazel`. PR Close #28436
This commit is contained in:
parent
744b0205e2
commit
4a92fa9471
|
@ -1,141 +0,0 @@
|
|||
{
|
||||
"$schema": "./node_modules/@angular/cli/lib/config/schema.json",
|
||||
"version": 1,
|
||||
"newProjectRoot": "projects",
|
||||
"projects": {
|
||||
"demo": {
|
||||
"root": "",
|
||||
"sourceRoot": "src",
|
||||
"projectType": "application",
|
||||
"prefix": "app",
|
||||
"schematics": {},
|
||||
"architect": {
|
||||
"build": {
|
||||
"builder": "@angular-devkit/build-angular:browser",
|
||||
"options": {
|
||||
"outputPath": "dist/demo",
|
||||
"index": "src/index.html",
|
||||
"main": "src/main.ts",
|
||||
"polyfills": "src/polyfills.ts",
|
||||
"tsConfig": "src/tsconfig.app.json",
|
||||
"assets": [
|
||||
"src/favicon.ico",
|
||||
"src/assets"
|
||||
],
|
||||
"styles": [
|
||||
"src/styles.scss"
|
||||
],
|
||||
"scripts": []
|
||||
},
|
||||
"configurations": {
|
||||
"production": {
|
||||
"fileReplacements": [
|
||||
{
|
||||
"replace": "src/environments/environment.ts",
|
||||
"with": "src/environments/environment.prod.ts"
|
||||
}
|
||||
],
|
||||
"optimization": true,
|
||||
"outputHashing": "all",
|
||||
"sourceMap": false,
|
||||
"extractCss": true,
|
||||
"namedChunks": false,
|
||||
"aot": true,
|
||||
"extractLicenses": true,
|
||||
"vendorChunk": false,
|
||||
"buildOptimizer": true,
|
||||
"budgets": [
|
||||
{
|
||||
"type": "initial",
|
||||
"maximumWarning": "2mb",
|
||||
"maximumError": "5mb"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
},
|
||||
"serve": {
|
||||
"builder": "@angular-devkit/build-angular:dev-server",
|
||||
"options": {
|
||||
"browserTarget": "demo:build"
|
||||
},
|
||||
"configurations": {
|
||||
"production": {
|
||||
"browserTarget": "demo:build:production"
|
||||
},
|
||||
"ci": {
|
||||
"progress": false
|
||||
}
|
||||
}
|
||||
},
|
||||
"extract-i18n": {
|
||||
"builder": "@angular-devkit/build-angular:extract-i18n",
|
||||
"options": {
|
||||
"browserTarget": "demo:build"
|
||||
}
|
||||
},
|
||||
"test": {
|
||||
"builder": "@angular-devkit/build-angular:karma",
|
||||
"options": {
|
||||
"main": "src/test.ts",
|
||||
"polyfills": "src/polyfills.ts",
|
||||
"tsConfig": "src/tsconfig.spec.json",
|
||||
"karmaConfig": "src/karma.conf.js",
|
||||
"styles": [
|
||||
"src/styles.scss"
|
||||
],
|
||||
"scripts": [],
|
||||
"assets": [
|
||||
"src/favicon.ico",
|
||||
"src/assets"
|
||||
]
|
||||
}
|
||||
},
|
||||
"lint": {
|
||||
"builder": "@angular-devkit/build-angular:tslint",
|
||||
"options": {
|
||||
"tsConfig": [
|
||||
"src/tsconfig.app.json",
|
||||
"src/tsconfig.spec.json"
|
||||
],
|
||||
"exclude": [
|
||||
"**/node_modules/**"
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"demo-e2e": {
|
||||
"root": "e2e/",
|
||||
"projectType": "application",
|
||||
"prefix": "",
|
||||
"architect": {
|
||||
"e2e": {
|
||||
"builder": "@angular-devkit/build-angular:protractor",
|
||||
"options": {
|
||||
"protractorConfig": "e2e/protractor.conf.js",
|
||||
"devServerTarget": "demo:serve"
|
||||
},
|
||||
"configurations": {
|
||||
"production": {
|
||||
"devServerTarget": "demo:serve:production"
|
||||
},
|
||||
"ci": {
|
||||
"devServerTarget": "demo:serve:ci"
|
||||
}
|
||||
}
|
||||
},
|
||||
"lint": {
|
||||
"builder": "@angular-devkit/build-angular:tslint",
|
||||
"options": {
|
||||
"tsConfig": "e2e/tsconfig.e2e.json",
|
||||
"exclude": [
|
||||
"**/node_modules/**"
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"defaultProject": "demo"
|
||||
}
|
|
@ -5,6 +5,7 @@ set -eux -o pipefail
|
|||
function testBazel() {
|
||||
# Set up
|
||||
bazel version
|
||||
ng version
|
||||
rm -rf demo
|
||||
# Create project
|
||||
ng new demo --collection=@angular/bazel --defaults --skip-git --style=scss
|
||||
|
@ -21,11 +22,11 @@ function testBazel() {
|
|||
|
||||
function testNonBazel() {
|
||||
# Replace angular.json that uses Bazel builder with the default generated by CLI
|
||||
cp ../angular.json.original ./angular.json
|
||||
mv ./angular.json.bak ./angular.json
|
||||
rm -rf dist src/main.dev.ts src/main.prod.ts
|
||||
ng build --progress=false
|
||||
ng test --progress=false --watch=false
|
||||
ng e2e --configuration=ci --webdriver-update=false
|
||||
ng e2e --configuration=production --webdriver-update=false
|
||||
}
|
||||
|
||||
testBazel
|
||||
|
|
|
@ -29,12 +29,12 @@
|
|||
rxjs "6.3.3"
|
||||
source-map "0.7.3"
|
||||
|
||||
"@angular-devkit/core@7.1.3", "@angular-devkit/core@^7.0.4":
|
||||
version "7.1.3"
|
||||
resolved "https://registry.yarnpkg.com/@angular-devkit/core/-/core-7.1.3.tgz#3d82a7e99aeb6259ff941d82b65759cb1c397042"
|
||||
integrity sha512-pGBInxmuR5DAhZ1RSfIlkv7cdgh3EDNXXea9ZObEuI9MuFsIWUKODT5oKbRrsOWM6IqwNmx68VEW+xQm2DXyJw==
|
||||
"@angular-devkit/core@7.2.3", "@angular-devkit/core@^7.0.4":
|
||||
version "7.2.3"
|
||||
resolved "https://registry.yarnpkg.com/@angular-devkit/core/-/core-7.2.3.tgz#03fad4edcbfbf5b2f0d35a121eca45b1273b238a"
|
||||
integrity sha512-NnN8O+97nJAxqD2zVTDlU8dSzrGCZmqYMDqDoRJJChYxAgmGwP4lhb+Jyi5D34tPxgKRTnjTOwC+G7D+WrXSDQ==
|
||||
dependencies:
|
||||
ajv "6.5.3"
|
||||
ajv "6.6.2"
|
||||
chokidar "2.0.4"
|
||||
fast-json-stable-stringify "2.0.0"
|
||||
rxjs "6.3.3"
|
||||
|
@ -51,12 +51,12 @@
|
|||
rxjs "6.3.3"
|
||||
source-map "0.7.3"
|
||||
|
||||
"@angular-devkit/schematics@7.1.3":
|
||||
version "7.1.3"
|
||||
resolved "https://registry.yarnpkg.com/@angular-devkit/schematics/-/schematics-7.1.3.tgz#30d03fde5bb27d6606d9a6e055188382408670d6"
|
||||
integrity sha512-Snmfog/n5k1PWdDaI+Top1F978vlXZFTvxHRPzlMCGhGsY+LMOpeRLVHADI+WP1q1LZ+2BjLELZVA2GP35AH8A==
|
||||
"@angular-devkit/schematics@7.2.3":
|
||||
version "7.2.3"
|
||||
resolved "https://registry.yarnpkg.com/@angular-devkit/schematics/-/schematics-7.2.3.tgz#e85269fc44d87fd79314875084ecdecdc42020b5"
|
||||
integrity sha512-zhnI1zxEcjx4OZ0yIzAAOujS8fzXE6nxjyC1viqliQbbjbikA6WIL7UT0jQXZKDsRBl8VXOyutBOaeOXuqktTQ==
|
||||
dependencies:
|
||||
"@angular-devkit/core" "7.1.3"
|
||||
"@angular-devkit/core" "7.2.3"
|
||||
rxjs "6.3.3"
|
||||
|
||||
"@angular-devkit/schematics@7.3.0-rc.0", "@angular-devkit/schematics@^7.3.0-rc.0":
|
||||
|
@ -139,13 +139,13 @@
|
|||
typescript "3.2.2"
|
||||
|
||||
"@schematics/angular@^7.0.4":
|
||||
version "7.1.3"
|
||||
resolved "https://registry.yarnpkg.com/@schematics/angular/-/angular-7.1.3.tgz#2cdbc6471358cf429fbea7ab192edc7246c87bd5"
|
||||
integrity sha512-6Wq6vNjGTc0zmudPogTjiegtTUc0pORTCxI39iinUM+5iemMrCLYKJmYLi5mPFU4OG/Q2fnT06A3dYUorhtLkA==
|
||||
version "7.2.3"
|
||||
resolved "https://registry.yarnpkg.com/@schematics/angular/-/angular-7.2.3.tgz#e08baf642fad4ff7b27a2724379c4583a5a381b5"
|
||||
integrity sha512-hKp+qaM8YU55+JukteXOVY2N5IQBDIIIXkyPcikbC2GBXUeNOMiPqw9au9sjHrgtFp+SVGoaFzzz9+MOCc1gig==
|
||||
dependencies:
|
||||
"@angular-devkit/core" "7.1.3"
|
||||
"@angular-devkit/schematics" "7.1.3"
|
||||
typescript "3.1.6"
|
||||
"@angular-devkit/core" "7.2.3"
|
||||
"@angular-devkit/schematics" "7.2.3"
|
||||
typescript "3.2.2"
|
||||
|
||||
"@schematics/update@0.13.0-rc.0":
|
||||
version "0.13.0-rc.0"
|
||||
|
@ -208,6 +208,16 @@ ajv@6.5.3:
|
|||
json-schema-traverse "^0.4.1"
|
||||
uri-js "^4.2.2"
|
||||
|
||||
ajv@6.6.2:
|
||||
version "6.6.2"
|
||||
resolved "https://registry.yarnpkg.com/ajv/-/ajv-6.6.2.tgz#caceccf474bf3fc3ce3b147443711a24063cc30d"
|
||||
integrity sha512-FBHEW6Jf5TB9MGBgUUA9XHkTbjXYfAUjY43ACMfmdMRHniyoMHjHjzD50OK8LGDWQwp4rWEsIq5kEqq7rvIM1g==
|
||||
dependencies:
|
||||
fast-deep-equal "^2.0.1"
|
||||
fast-json-stable-stringify "^2.0.0"
|
||||
json-schema-traverse "^0.4.1"
|
||||
uri-js "^4.2.2"
|
||||
|
||||
ajv@6.7.0:
|
||||
version "6.7.0"
|
||||
resolved "https://registry.yarnpkg.com/ajv/-/ajv-6.7.0.tgz#e3ce7bb372d6577bb1839f1dfdfcbf5ad2948d96"
|
||||
|
@ -219,9 +229,9 @@ ajv@6.7.0:
|
|||
uri-js "^4.2.2"
|
||||
|
||||
ansi-escapes@^3.0.0:
|
||||
version "3.1.0"
|
||||
resolved "https://registry.yarnpkg.com/ansi-escapes/-/ansi-escapes-3.1.0.tgz#f73207bb81207d75fd6c83f125af26eea378ca30"
|
||||
integrity sha512-UgAb8H9D41AQnu/PbWlCofQVcnV4Gs2bBJi9eZPxfU/hgglFh3SMDMENRIqdr7H6XFnXdoknctFByVsCOotTVw==
|
||||
version "3.2.0"
|
||||
resolved "https://registry.yarnpkg.com/ansi-escapes/-/ansi-escapes-3.2.0.tgz#8780b98ff9dbf5638152d1f1fe5c1d7b4442976b"
|
||||
integrity sha512-cBhpre4ma+U0T1oM5fXg7Dy1Jw7zzwv7lt/GoCpr+hDQJoYnKVPLL4dCvSEFMmQurOQvSrwT7SL/DAlhBI97RQ==
|
||||
|
||||
ansi-regex@^2.0.0:
|
||||
version "2.1.1"
|
||||
|
@ -383,27 +393,7 @@ bytebuffer@~5:
|
|||
dependencies:
|
||||
long "~3"
|
||||
|
||||
cacache@^11.0.1:
|
||||
version "11.3.1"
|
||||
resolved "https://registry.yarnpkg.com/cacache/-/cacache-11.3.1.tgz#d09d25f6c4aca7a6d305d141ae332613aa1d515f"
|
||||
integrity sha512-2PEw4cRRDu+iQvBTTuttQifacYjLPhET+SYO/gEFMy8uhi+jlJREDAjSF5FWSdV/Aw5h18caHA7vMTw2c+wDzA==
|
||||
dependencies:
|
||||
bluebird "^3.5.1"
|
||||
chownr "^1.0.1"
|
||||
figgy-pudding "^3.1.0"
|
||||
glob "^7.1.2"
|
||||
graceful-fs "^4.1.11"
|
||||
lru-cache "^4.1.3"
|
||||
mississippi "^3.0.0"
|
||||
mkdirp "^0.5.1"
|
||||
move-concurrently "^1.0.1"
|
||||
promise-inflight "^1.0.1"
|
||||
rimraf "^2.6.2"
|
||||
ssri "^6.0.0"
|
||||
unique-filename "^1.1.0"
|
||||
y18n "^4.0.0"
|
||||
|
||||
cacache@^11.3.2:
|
||||
cacache@^11.0.1, cacache@^11.3.2:
|
||||
version "11.3.2"
|
||||
resolved "https://registry.yarnpkg.com/cacache/-/cacache-11.3.2.tgz#2d81e308e3d258ca38125b676b98b2ac9ce69bfa"
|
||||
integrity sha512-E0zP4EPGDOaT2chM08Als91eYnf8Z+eH1awwwVsngUmgppfM5jjJ8l3z5vO5p5w/I3LsiXawb1sW0VY65pQABg==
|
||||
|
@ -444,9 +434,9 @@ camelcase@^2.0.1:
|
|||
integrity sha1-fB0W1nmhu+WcoCys7PsBHiAfWh8=
|
||||
|
||||
chalk@^2.0.0:
|
||||
version "2.4.1"
|
||||
resolved "https://registry.yarnpkg.com/chalk/-/chalk-2.4.1.tgz#18c49ab16a037b6eb0152cc83e3471338215b66e"
|
||||
integrity sha512-ObN6h1v2fTJSmUXoS3nMQ92LbDK9be4TV+6G+omQlGJFdcUX5heKi1LZ1YnRMIgwTLEj3E24bT6tYni50rlCfQ==
|
||||
version "2.4.2"
|
||||
resolved "https://registry.yarnpkg.com/chalk/-/chalk-2.4.2.tgz#cd42541677a54333cf541a49108c1432b44c9424"
|
||||
integrity sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==
|
||||
dependencies:
|
||||
ansi-styles "^3.2.1"
|
||||
escape-string-regexp "^1.0.5"
|
||||
|
@ -477,7 +467,7 @@ chokidar@2.0.4:
|
|||
optionalDependencies:
|
||||
fsevents "^1.2.2"
|
||||
|
||||
chownr@^1.0.1, chownr@^1.1.1:
|
||||
chownr@^1.1.1:
|
||||
version "1.1.1"
|
||||
resolved "https://registry.yarnpkg.com/chownr/-/chownr-1.1.1.tgz#54726b8b8fff4df053c42187e801fb4412df1494"
|
||||
integrity sha512-j38EvO5+LHX84jlo6h4UzmOwi0UgW61WRyPtJz4qaadK5eY3BTS5TY/S1Stc3Uk2lIM6TPevAlULiEJwie860g==
|
||||
|
@ -770,7 +760,7 @@ fast-json-stable-stringify@2.0.0, fast-json-stable-stringify@^2.0.0:
|
|||
resolved "https://registry.yarnpkg.com/fast-json-stable-stringify/-/fast-json-stable-stringify-2.0.0.tgz#d5142c0caee6b1189f87d3a76111064f86c8bbf2"
|
||||
integrity sha1-1RQsDK7msRifh9OnYREGT4bIu/I=
|
||||
|
||||
figgy-pudding@^3.1.0, figgy-pudding@^3.4.1, figgy-pudding@^3.5.1:
|
||||
figgy-pudding@^3.4.1, figgy-pudding@^3.5.1:
|
||||
version "3.5.1"
|
||||
resolved "https://registry.yarnpkg.com/figgy-pudding/-/figgy-pudding-3.5.1.tgz#862470112901c727a0e495a80744bd5baa1d6790"
|
||||
integrity sha512-vNKxJHTEKNThjfrdJwHc7brvM6eVevuO5nTj6ez8ZQ1qbXTvGthucRF7S4vf2cr71QVnT70V34v0S1DyQsti0w==
|
||||
|
@ -843,9 +833,9 @@ fs.realpath@^1.0.0:
|
|||
integrity sha1-FQStJSMVjKpA20onh8sBQRmU6k8=
|
||||
|
||||
fsevents@^1.2.2:
|
||||
version "1.2.4"
|
||||
resolved "https://registry.yarnpkg.com/fsevents/-/fsevents-1.2.4.tgz#f41dcb1af2582af3692da36fc55cbd8e1041c426"
|
||||
integrity sha512-z8H8/diyk76B7q5wg+Ud0+CqzcAF3mBBI/bA5ne5zrRUUIvNkJY//D3BqyH571KuAC4Nr7Rw7CjWX4r0y9DvNg==
|
||||
version "1.2.7"
|
||||
resolved "https://registry.yarnpkg.com/fsevents/-/fsevents-1.2.7.tgz#4851b664a3783e52003b3c66eb0eee1074933aa4"
|
||||
integrity sha512-Pxm6sI2MeBD7RdD12RYsqaP0nMiwx8eZBXCa6z2L+mRHm2DYrOYwihmhjpkdjUHwQhslWQjRpEgNq4XvBmaAuw==
|
||||
dependencies:
|
||||
nan "^2.9.2"
|
||||
node-pre-gyp "^0.10.0"
|
||||
|
@ -889,7 +879,7 @@ glob-parent@^3.1.0:
|
|||
is-glob "^3.1.0"
|
||||
path-dirname "^1.0.0"
|
||||
|
||||
glob@^7.0.0, glob@^7.0.5, glob@^7.1.2, glob@^7.1.3:
|
||||
glob@^7.0.0, glob@^7.0.5, glob@^7.1.3:
|
||||
version "7.1.3"
|
||||
resolved "https://registry.yarnpkg.com/glob/-/glob-7.1.3.tgz#3960832d3f1574108342dafd3a67b332c0969df1"
|
||||
integrity sha512-vcfuiIxogLV4DlGBHIUOwI0IbrJ8HWPc4MU7HzviGeNho/UJDfi6B5p3sHeWIQ0KGIU0Jpxi5ZHxemQfLkkAwQ==
|
||||
|
@ -1042,9 +1032,9 @@ inquirer@6.2.1:
|
|||
through "^2.3.6"
|
||||
|
||||
interpret@^1.0.0:
|
||||
version "1.1.0"
|
||||
resolved "https://registry.yarnpkg.com/interpret/-/interpret-1.1.0.tgz#7ed1b1410c6a0e0f78cf95d3b8440c63f78b8614"
|
||||
integrity sha1-ftGxQQxqDg94z5XTuEQMY/eLhhQ=
|
||||
version "1.2.0"
|
||||
resolved "https://registry.yarnpkg.com/interpret/-/interpret-1.2.0.tgz#d5061a6224be58e8083985f5014d844359576296"
|
||||
integrity sha512-mT34yGKMNceBQUoVn7iCDKDntA7SC6gycMAWzGx1z/CMCTV7b2AAtXlo3nRyHZ1FelRkQbQjprHSYGwzLtkVbw==
|
||||
|
||||
invert-kv@^1.0.0:
|
||||
version "1.0.0"
|
||||
|
@ -1435,9 +1425,9 @@ mute-stream@0.0.7:
|
|||
integrity sha1-MHXOk7whuPq0PhvE2n6BFe0ee6s=
|
||||
|
||||
nan@^2.9.2:
|
||||
version "2.11.1"
|
||||
resolved "https://registry.yarnpkg.com/nan/-/nan-2.11.1.tgz#90e22bccb8ca57ea4cd37cc83d3819b52eea6766"
|
||||
integrity sha512-iji6k87OSXa0CcrLl9z+ZiYSuR2o+c0bGuNmXdrhTQTakxytAFsC56SArGYoiHlJlFoHSnvmhpceZJaXkVuOtA==
|
||||
version "2.12.1"
|
||||
resolved "https://registry.yarnpkg.com/nan/-/nan-2.12.1.tgz#7b1aa193e9aa86057e3c7bbd0ac448e770925552"
|
||||
integrity sha512-JY7V6lRkStKcKTvHO5NVSQRv+RV+FIL5pvDoLiAtSL9pKlC5x9PKQcZDsq7m4FO4d57mkhC6Z+QhAh3Jdk5JFw==
|
||||
|
||||
nanomatch@^1.2.9:
|
||||
version "1.2.13"
|
||||
|
@ -1531,9 +1521,9 @@ npm-package-arg@6.1.0, npm-package-arg@^6.0.0, npm-package-arg@^6.1.0:
|
|||
validate-npm-package-name "^3.0.0"
|
||||
|
||||
npm-packlist@^1.1.12, npm-packlist@^1.1.6:
|
||||
version "1.1.12"
|
||||
resolved "https://registry.yarnpkg.com/npm-packlist/-/npm-packlist-1.1.12.tgz#22bde2ebc12e72ca482abd67afc51eb49377243a"
|
||||
integrity sha512-WJKFOVMeAlsU/pjXuqVdzU0WfgtIBCupkEVwn+1Y0ERAbUfWw8R4GjgVbaKnUjRoD2FoQbHOCbOyT5Mbs9Lw4g==
|
||||
version "1.2.0"
|
||||
resolved "https://registry.yarnpkg.com/npm-packlist/-/npm-packlist-1.2.0.tgz#55a60e793e272f00862c7089274439a4cc31fc7f"
|
||||
integrity sha512-7Mni4Z8Xkx0/oegoqlcao/JpPCPEMtUvsmB0q7mgvlMinykJLSRTYuFqoQLYgGY8biuxIeiHO+QNJKbCfljewQ==
|
||||
dependencies:
|
||||
ignore-walk "^3.0.1"
|
||||
npm-bundled "^1.0.1"
|
||||
|
@ -1548,9 +1538,9 @@ npm-pick-manifest@^2.2.3:
|
|||
semver "^5.4.1"
|
||||
|
||||
npm-registry-fetch@^3.8.0:
|
||||
version "3.8.0"
|
||||
resolved "https://registry.yarnpkg.com/npm-registry-fetch/-/npm-registry-fetch-3.8.0.tgz#aa7d9a7c92aff94f48dba0984bdef4bd131c88cc"
|
||||
integrity sha512-hrw8UMD+Nob3Kl3h8Z/YjmKamb1gf7D1ZZch2otrIXM3uFLB5vjEY6DhMlq80z/zZet6eETLbOXcuQudCB3Zpw==
|
||||
version "3.9.0"
|
||||
resolved "https://registry.yarnpkg.com/npm-registry-fetch/-/npm-registry-fetch-3.9.0.tgz#44d841780e2833f06accb34488f8c7450d1a6856"
|
||||
integrity sha512-srwmt8YhNajAoSAaDWndmZgx89lJwIZ1GWxOuckH4Coek4uHv5S+o/l9FLQe/awA+JwTnj4FJHldxhlXdZEBmw==
|
||||
dependencies:
|
||||
JSONStream "^1.3.4"
|
||||
bluebird "^3.5.1"
|
||||
|
@ -1710,7 +1700,7 @@ path-is-absolute@^1.0.0:
|
|||
resolved "https://registry.yarnpkg.com/path-is-absolute/-/path-is-absolute-1.0.1.tgz#174b9268735534ffbc7ace6bf53a5a9e1b5c5f5f"
|
||||
integrity sha1-F0uSaHNVNP+8es5r9TpanhtcX18=
|
||||
|
||||
path-parse@^1.0.5:
|
||||
path-parse@^1.0.6:
|
||||
version "1.0.6"
|
||||
resolved "https://registry.yarnpkg.com/path-parse/-/path-parse-1.0.6.tgz#d62dbb5679405d72c4737ec58600e9ddcf06d24c"
|
||||
integrity sha512-GSmOT2EbHrINBf9SR7CDELwlJ8AENk3Qn7OikK4nFYAu3Ote2+JYNVvkpAEQm3/TLNEJFD/xZJjzyxg3KBWOzw==
|
||||
|
@ -1858,11 +1848,11 @@ resolve-url@^0.2.1:
|
|||
integrity sha1-LGN/53yJOv0qZj/iGqkIAGjiBSo=
|
||||
|
||||
resolve@^1.1.6:
|
||||
version "1.8.1"
|
||||
resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.8.1.tgz#82f1ec19a423ac1fbd080b0bab06ba36e84a7a26"
|
||||
integrity sha512-AicPrAC7Qu1JxPCZ9ZgCZlY35QgFnNqc+0LtbRNxnVw4TXvjQ72wnuL9JQcEBgXkI9JM8MsT9kaQoHcpCRJOYA==
|
||||
version "1.10.0"
|
||||
resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.10.0.tgz#3bdaaeaf45cc07f375656dfd2e54ed0810b101ba"
|
||||
integrity sha512-3sUr9aq5OfSg2S9pNtPA9hL1FVEAjvfOC4leW0SNf/mpnaakz2a9femSd6LqAww2RaFctwyf1lCqnTHuF1rxDg==
|
||||
dependencies:
|
||||
path-parse "^1.0.5"
|
||||
path-parse "^1.0.6"
|
||||
|
||||
restore-cursor@^2.0.0:
|
||||
version "2.0.0"
|
||||
|
@ -1883,11 +1873,11 @@ retry@^0.10.0:
|
|||
integrity sha1-52OI0heZLCUnUCQdPTlW/tmNj/Q=
|
||||
|
||||
rimraf@^2.5.4, rimraf@^2.6.1, rimraf@^2.6.2:
|
||||
version "2.6.2"
|
||||
resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-2.6.2.tgz#2ed8150d24a16ea8651e6d6ef0f47c4158ce7a36"
|
||||
integrity sha512-lreewLK/BlghmxtfH36YYVg1i8IAce4TI7oao75I1g245+6BctqTVQiBP3YUJ9C6DQOXJmkYR9X9fCLtCOJc5w==
|
||||
version "2.6.3"
|
||||
resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-2.6.3.tgz#b2d104fe0d8fb27cf9e0a1cda8262dd3833c6cab"
|
||||
integrity sha512-mwqeW5XsA2qAejG46gYdENaxXjx9onRNCfn7L0duuP4hCuTIi/QO7PDK07KJfp1d+izWPrzEJDcSqBa0OZQriA==
|
||||
dependencies:
|
||||
glob "^7.0.5"
|
||||
glob "^7.1.3"
|
||||
|
||||
run-async@^2.2.0:
|
||||
version "2.3.0"
|
||||
|
@ -1983,10 +1973,10 @@ signal-exit@^3.0.0, signal-exit@^3.0.2:
|
|||
resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-3.0.2.tgz#b5fdc08f1287ea1178628e415e25132b73646c6d"
|
||||
integrity sha1-tf3AjxKH6hF4Yo5BXiUTK3NkbG0=
|
||||
|
||||
smart-buffer@^4.0.1:
|
||||
version "4.0.1"
|
||||
resolved "https://registry.yarnpkg.com/smart-buffer/-/smart-buffer-4.0.1.tgz#07ea1ca8d4db24eb4cac86537d7d18995221ace3"
|
||||
integrity sha512-RFqinRVJVcCAL9Uh1oVqE6FZkqsyLiVOYEZ20TqIOjuX7iFVJ+zsbs4RIghnw/pTs7mZvt8ZHhvm1ZUrR4fykg==
|
||||
smart-buffer@4.0.2:
|
||||
version "4.0.2"
|
||||
resolved "https://registry.yarnpkg.com/smart-buffer/-/smart-buffer-4.0.2.tgz#5207858c3815cc69110703c6b94e46c15634395d"
|
||||
integrity sha512-JDhEpTKzXusOqXZ0BUIdH+CjFdO/CR3tLlf5CN34IypI+xMmXW1uB16OOY8z3cICbJlDAVJzNbwBhNO0wt9OAw==
|
||||
|
||||
snapdragon-node@^2.0.1:
|
||||
version "2.1.1"
|
||||
|
@ -2027,12 +2017,12 @@ socks-proxy-agent@^4.0.0:
|
|||
socks "~2.2.0"
|
||||
|
||||
socks@~2.2.0:
|
||||
version "2.2.2"
|
||||
resolved "https://registry.yarnpkg.com/socks/-/socks-2.2.2.tgz#f061219fc2d4d332afb4af93e865c84d3fa26e2b"
|
||||
integrity sha512-g6wjBnnMOZpE0ym6e0uHSddz9p3a+WsBaaYQaBaSCJYvrC4IXykQR9MNGjLQf38e9iIIhp3b1/Zk8YZI3KGJ0Q==
|
||||
version "2.2.3"
|
||||
resolved "https://registry.yarnpkg.com/socks/-/socks-2.2.3.tgz#7399ce11e19b2a997153c983a9ccb6306721f2dc"
|
||||
integrity sha512-+2r83WaRT3PXYoO/1z+RDEBE7Z2f9YcdQnJ0K/ncXXbV5gJ6wYfNAebYFYiiUjM6E4JyXnPY8cimwyvFYHVUUA==
|
||||
dependencies:
|
||||
ip "^1.1.5"
|
||||
smart-buffer "^4.0.1"
|
||||
smart-buffer "4.0.2"
|
||||
|
||||
source-map-resolve@^0.5.0:
|
||||
version "0.5.2"
|
||||
|
@ -2095,9 +2085,9 @@ spdx-expression-parse@^3.0.0:
|
|||
spdx-license-ids "^3.0.0"
|
||||
|
||||
spdx-license-ids@^3.0.0:
|
||||
version "3.0.2"
|
||||
resolved "https://registry.yarnpkg.com/spdx-license-ids/-/spdx-license-ids-3.0.2.tgz#a59efc09784c2a5bada13cfeaf5c75dd214044d2"
|
||||
integrity sha512-qky9CVt0lVIECkEsYbNILVnPvycuEBkXoMFLRWsREkomQLevYhtRKC+R91a5TOAQ3bCMjikRwhyaRqj1VYatYg==
|
||||
version "3.0.3"
|
||||
resolved "https://registry.yarnpkg.com/spdx-license-ids/-/spdx-license-ids-3.0.3.tgz#81c0ce8f21474756148bbb5f3bfc0f36bf15d76e"
|
||||
integrity sha512-uBIcIl3Ih6Phe3XHK1NqboJLdGfwr1UN3k6wSD1dZpmPsIkb8AGNbZYJ1fOBk834+Gxy8rpfDxrS6XLEMZMY2g==
|
||||
|
||||
split-string@^3.0.1, split-string@^3.0.2:
|
||||
version "3.1.0"
|
||||
|
@ -2280,11 +2270,6 @@ typedarray@^0.0.6:
|
|||
resolved "https://registry.yarnpkg.com/typedarray/-/typedarray-0.0.6.tgz#867ac74e3864187b1d3d47d996a78ec5c8830777"
|
||||
integrity sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c=
|
||||
|
||||
typescript@3.1.6:
|
||||
version "3.1.6"
|
||||
resolved "https://registry.yarnpkg.com/typescript/-/typescript-3.1.6.tgz#b6543a83cfc8c2befb3f4c8fba6896f5b0c9be68"
|
||||
integrity sha512-tDMYfVtvpb96msS1lDX9MEdHrW4yOuZ4Kdc4Him9oU796XldPYF/t2+uKoX0BBa0hXXwDlqYQbXY5Rzjzc5hBA==
|
||||
|
||||
typescript@3.2.2:
|
||||
version "3.2.2"
|
||||
resolved "https://registry.yarnpkg.com/typescript/-/typescript-3.2.2.tgz#fe8101c46aa123f8353523ebdcf5730c2ae493e5"
|
||||
|
@ -2300,7 +2285,7 @@ union-value@^1.0.0:
|
|||
is-extendable "^0.1.1"
|
||||
set-value "^0.4.3"
|
||||
|
||||
unique-filename@^1.1.0, unique-filename@^1.1.1:
|
||||
unique-filename@^1.1.1:
|
||||
version "1.1.1"
|
||||
resolved "https://registry.yarnpkg.com/unique-filename/-/unique-filename-1.1.1.tgz#1d69769369ada0583103a1e6ae87681b56573230"
|
||||
integrity sha512-Vmp0jIp2ln35UTXuryvjzkjGdRyf9b2lTXuSYUiPmzRcl3FDtYqAwOnTJkAngD9SWhnoJzDbTKwaOrZ+STtxNQ==
|
||||
|
|
|
@ -23,6 +23,7 @@ npm_package(
|
|||
"//packages/bazel/src/ngc-wrapped:ngc_lib",
|
||||
"//packages/bazel/src/protractor/utils",
|
||||
"//packages/bazel/src/schematics/bazel-workspace",
|
||||
"//packages/bazel/src/schematics/ng-add",
|
||||
"//packages/bazel/src/schematics/ng-new",
|
||||
],
|
||||
)
|
||||
|
|
|
@ -15,6 +15,7 @@ jasmine_node_test(
|
|||
bootstrap = ["angular/tools/testing/init_node_spec.js"],
|
||||
deps = [
|
||||
"//packages/bazel/src/schematics/bazel-workspace:test",
|
||||
"//packages/bazel/src/schematics/ng-add:test",
|
||||
"//packages/bazel/src/schematics/ng-new:test",
|
||||
"//tools/testing:node",
|
||||
],
|
||||
|
|
|
@ -86,6 +86,10 @@ export default function(options: BazelWorkspaceOptions): Rule {
|
|||
}
|
||||
});
|
||||
|
||||
if (!host.exists('yarn.lock')) {
|
||||
host.create('yarn.lock', '');
|
||||
}
|
||||
|
||||
const workspaceVersions = {
|
||||
'RULES_NODEJS_VERSION': '0.16.5',
|
||||
'RULES_TYPESCRIPT_VERSION': '0.22.1',
|
||||
|
|
|
@ -29,17 +29,19 @@ describe('Bazel-workspace Schematic', () => {
|
|||
expect(files).toContain('/yarn.lock');
|
||||
});
|
||||
|
||||
it('should find existing Angular version', () => {
|
||||
let host = new UnitTestTree(new HostTree);
|
||||
host.create('/node_modules/@angular/core/package.json', JSON.stringify({
|
||||
name: '@angular/core',
|
||||
version: '6.6.6',
|
||||
}));
|
||||
const options = {...defaultOptions};
|
||||
host = schematicRunner.runSchematic('bazel-workspace', options, host);
|
||||
expect(host.files).toContain('/WORKSPACE');
|
||||
const workspace = host.readContent('/WORKSPACE');
|
||||
expect(workspace).toMatch('ANGULAR_VERSION = "6.6.6"');
|
||||
it('should generate empty yarn.lock file', () => {
|
||||
const host = schematicRunner.runSchematic('bazel-workspace', defaultOptions);
|
||||
expect(host.files).toContain('/yarn.lock');
|
||||
expect(host.readContent('/yarn.lock')).toBe('');
|
||||
});
|
||||
|
||||
it('should not replace yarn.lock if it exists', () => {
|
||||
let host = new UnitTestTree(new HostTree());
|
||||
host.create('yarn.lock', 'some content');
|
||||
expect(host.files).toContain('/yarn.lock');
|
||||
host = schematicRunner.runSchematic('bazel-workspace', defaultOptions, host);
|
||||
expect(host.files).toContain('/yarn.lock');
|
||||
expect(host.readContent('/yarn.lock')).toBe('some content');
|
||||
});
|
||||
|
||||
it('should have the correct entry_module for devserver', () => {
|
||||
|
|
|
@ -2,6 +2,11 @@
|
|||
"name": "@angular/bazel",
|
||||
"version": "0.1",
|
||||
"schematics": {
|
||||
"ng-add": {
|
||||
"factory": "./ng-add",
|
||||
"schema": "ng-add/schema.json",
|
||||
"description": "Add Bazel build files and configurations to a project"
|
||||
},
|
||||
"ng-new": {
|
||||
"factory": "./ng-new",
|
||||
"schema": "./ng-new/schema.json",
|
||||
|
@ -14,4 +19,4 @@
|
|||
"hidden": true
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,36 @@
|
|||
package(default_visibility = ["//visibility:public"])
|
||||
|
||||
load("//tools:defaults.bzl", "ts_library")
|
||||
|
||||
ts_library(
|
||||
name = "ng-add",
|
||||
srcs = [
|
||||
"index.ts",
|
||||
"schema.d.ts",
|
||||
],
|
||||
data = glob(["files/**/*"]) + [
|
||||
"schema.json",
|
||||
],
|
||||
deps = [
|
||||
"//packages/bazel/src/schematics/bazel-workspace",
|
||||
"@ngdeps//@angular-devkit/core",
|
||||
"@ngdeps//@angular-devkit/schematics",
|
||||
"@ngdeps//@schematics/angular",
|
||||
"@ngdeps//typescript",
|
||||
],
|
||||
)
|
||||
|
||||
ts_library(
|
||||
name = "test",
|
||||
testonly = True,
|
||||
srcs = [
|
||||
"index_spec.ts",
|
||||
],
|
||||
data = [
|
||||
"//packages/bazel/src/schematics:package_assets",
|
||||
],
|
||||
deps = [
|
||||
":ng-add",
|
||||
"@ngdeps//@angular-devkit/schematics",
|
||||
],
|
||||
)
|
|
@ -0,0 +1,232 @@
|
|||
/**
|
||||
* @license
|
||||
* Copyright Google Inc. All Rights Reserved.
|
||||
*
|
||||
* Use of this source code is governed by an MIT-style license that can be
|
||||
* found in the LICENSE file at https://angular.io/license
|
||||
*
|
||||
* @fileoverview Schematics for ng-new project that builds with Bazel.
|
||||
*/
|
||||
|
||||
import {SchematicContext, apply, applyTemplates, chain, mergeWith, move, Rule, schematic, Tree, url, SchematicsException, UpdateRecorder,} from '@angular-devkit/schematics';
|
||||
import {parseJsonAst, JsonAstObject, strings, JsonValue} from '@angular-devkit/core';
|
||||
import {findPropertyInAstObject, insertPropertyInAstObjectInOrder} from '@schematics/angular/utility/json-utils';
|
||||
import {validateProjectName} from '@schematics/angular/utility/validation';
|
||||
import {getWorkspacePath} from '@schematics/angular/utility/config';
|
||||
import {Schema} from './schema';
|
||||
|
||||
/**
|
||||
* Packages that build under Bazel require additional dev dependencies. This
|
||||
* function adds those dependencies to "devDependencies" section in
|
||||
* package.json.
|
||||
*/
|
||||
function addDevDependenciesToPackageJson(options: Schema) {
|
||||
return (host: Tree) => {
|
||||
const packageJson = 'package.json';
|
||||
if (!host.exists(packageJson)) {
|
||||
throw new Error(`Could not find ${packageJson}`);
|
||||
}
|
||||
const packageJsonContent = host.read(packageJson);
|
||||
if (!packageJsonContent) {
|
||||
throw new Error('Failed to read package.json content');
|
||||
}
|
||||
const jsonAst = parseJsonAst(packageJsonContent.toString()) as JsonAstObject;
|
||||
const deps = findPropertyInAstObject(jsonAst, 'dependencies') as JsonAstObject;
|
||||
const devDeps = findPropertyInAstObject(jsonAst, 'devDependencies') as JsonAstObject;
|
||||
|
||||
const angularCoreNode = findPropertyInAstObject(deps, '@angular/core');
|
||||
if (!angularCoreNode) {
|
||||
throw new Error('@angular/core dependency not found in package.json');
|
||||
}
|
||||
const angularCoreVersion = angularCoreNode.value as string;
|
||||
|
||||
const devDependencies: {[k: string]: string} = {
|
||||
'@angular/bazel': angularCoreVersion,
|
||||
// TODO(kyliau): Consider moving this to latest-versions.ts
|
||||
'@bazel/bazel': '^0.22.1',
|
||||
'@bazel/ibazel': '^0.9.0',
|
||||
'@bazel/karma': '^0.22.1',
|
||||
'@bazel/typescript': '^0.22.1',
|
||||
};
|
||||
|
||||
const recorder = host.beginUpdate(packageJson);
|
||||
for (const packageName of Object.keys(devDependencies)) {
|
||||
const version = devDependencies[packageName];
|
||||
const indent = 4;
|
||||
insertPropertyInAstObjectInOrder(recorder, devDeps, packageName, version, indent);
|
||||
}
|
||||
host.commitUpdate(recorder);
|
||||
return host;
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Append main.dev.ts and main.prod.ts to src directory. These files are needed
|
||||
* by Bazel for devserver and prodserver, respectively. They are different from
|
||||
* main.ts generated by CLI because they use platformBrowser (AOT) instead of
|
||||
* platformBrowserDynamic (JIT).
|
||||
*/
|
||||
function addDevAndProdMainForAot(options: Schema) {
|
||||
return (host: Tree) => {
|
||||
return mergeWith(apply(url('./files'), [
|
||||
applyTemplates({
|
||||
utils: strings,
|
||||
...options,
|
||||
'dot': '.',
|
||||
}),
|
||||
move('/src'),
|
||||
]));
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Append '/bazel-out' to the gitignore file.
|
||||
*/
|
||||
function updateGitignore() {
|
||||
return (host: Tree) => {
|
||||
const gitignore = '/.gitignore';
|
||||
if (!host.exists(gitignore)) {
|
||||
return host;
|
||||
}
|
||||
const gitIgnoreContent = host.read(gitignore).toString();
|
||||
if (gitIgnoreContent.includes('\n/bazel-out\n')) {
|
||||
return host;
|
||||
}
|
||||
const compiledOutput = '# compiled output\n';
|
||||
const index = gitIgnoreContent.indexOf(compiledOutput);
|
||||
const insertionIndex = index >= 0 ? index + compiledOutput.length : gitIgnoreContent.length;
|
||||
const recorder = host.beginUpdate(gitignore);
|
||||
recorder.insertRight(insertionIndex, '/bazel-out\n');
|
||||
host.commitUpdate(recorder);
|
||||
return host;
|
||||
};
|
||||
}
|
||||
|
||||
function replacePropertyInAstObject(
|
||||
recorder: UpdateRecorder, node: JsonAstObject, propertyName: string, value: JsonValue,
|
||||
indent: number) {
|
||||
const property = findPropertyInAstObject(node, propertyName);
|
||||
if (property === null) {
|
||||
throw new Error(`Property ${propertyName} does not exist in JSON object`);
|
||||
}
|
||||
const {start, text} = property;
|
||||
recorder.remove(start.offset, text.length);
|
||||
const indentStr = '\n' +
|
||||
' '.repeat(indent);
|
||||
const content = JSON.stringify(value, null, ' ').replace(/\n/g, indentStr);
|
||||
recorder.insertLeft(start.offset, content);
|
||||
}
|
||||
|
||||
function updateAngularJsonToUseBazelBuilder(options: Schema): Rule {
|
||||
return (host: Tree, context: SchematicContext) => {
|
||||
const {name} = options;
|
||||
const workspacePath = getWorkspacePath(host);
|
||||
if (!workspacePath) {
|
||||
throw new Error('Could not find angular.json');
|
||||
}
|
||||
const workspaceContent = host.read(workspacePath).toString();
|
||||
const workspaceJsonAst = parseJsonAst(workspaceContent) as JsonAstObject;
|
||||
const projects = findPropertyInAstObject(workspaceJsonAst, 'projects');
|
||||
if (!projects) {
|
||||
throw new SchematicsException('Expect projects in angular.json to be an Object');
|
||||
}
|
||||
const project = findPropertyInAstObject(projects as JsonAstObject, name);
|
||||
if (!project) {
|
||||
throw new SchematicsException(`Expected projects to contain ${name}`);
|
||||
}
|
||||
const recorder = host.beginUpdate(workspacePath);
|
||||
const indent = 8;
|
||||
const architect =
|
||||
findPropertyInAstObject(project as JsonAstObject, 'architect') as JsonAstObject;
|
||||
replacePropertyInAstObject(
|
||||
recorder, architect, 'build', {
|
||||
builder: '@angular/bazel:build',
|
||||
options: {
|
||||
targetLabel: '//src:bundle.js',
|
||||
bazelCommand: 'build',
|
||||
},
|
||||
configurations: {
|
||||
production: {
|
||||
targetLabel: '//src:bundle',
|
||||
},
|
||||
},
|
||||
},
|
||||
indent);
|
||||
replacePropertyInAstObject(
|
||||
recorder, architect, 'serve', {
|
||||
builder: '@angular/bazel:build',
|
||||
options: {
|
||||
targetLabel: '//src:devserver',
|
||||
bazelCommand: 'run',
|
||||
},
|
||||
configurations: {
|
||||
production: {
|
||||
targetLabel: '//src:prodserver',
|
||||
},
|
||||
},
|
||||
},
|
||||
indent);
|
||||
replacePropertyInAstObject(
|
||||
recorder, architect, 'test', {
|
||||
builder: '@angular/bazel:build',
|
||||
options: {'bazelCommand': 'test', 'targetLabel': '//src/...'},
|
||||
},
|
||||
indent);
|
||||
|
||||
const e2e = `${options.name}-e2e`;
|
||||
const e2eNode = findPropertyInAstObject(projects as JsonAstObject, e2e);
|
||||
if (e2eNode) {
|
||||
const architect =
|
||||
findPropertyInAstObject(e2eNode as JsonAstObject, 'architect') as JsonAstObject;
|
||||
replacePropertyInAstObject(
|
||||
recorder, architect, 'e2e', {
|
||||
builder: '@angular/bazel:build',
|
||||
options: {
|
||||
bazelCommand: 'test',
|
||||
targetLabel: '//e2e:devserver_test',
|
||||
},
|
||||
configurations: {
|
||||
production: {
|
||||
targetLabel: '//e2e:prodserver_test',
|
||||
},
|
||||
}
|
||||
},
|
||||
indent);
|
||||
}
|
||||
|
||||
host.commitUpdate(recorder);
|
||||
return host;
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a backup for the original angular.json file in case user wants to
|
||||
* eject Bazel and revert to the original workflow.
|
||||
*/
|
||||
function backupAngularJson(): Rule {
|
||||
return (host: Tree, context: SchematicContext) => {
|
||||
const workspacePath = getWorkspacePath(host);
|
||||
if (!workspacePath) {
|
||||
return;
|
||||
}
|
||||
host.create(
|
||||
`${workspacePath}.bak`, '// This is a backup file of the original angular.json. ' +
|
||||
'This file is needed in case you want to revert to the workflow without Bazel.\n\n' +
|
||||
host.read(workspacePath));
|
||||
};
|
||||
}
|
||||
|
||||
export default function(options: Schema): Rule {
|
||||
return (host: Tree) => {
|
||||
validateProjectName(options.name);
|
||||
|
||||
return chain([
|
||||
schematic('bazel-workspace', options),
|
||||
addDevAndProdMainForAot(options),
|
||||
addDevDependenciesToPackageJson(options),
|
||||
backupAngularJson(),
|
||||
updateAngularJsonToUseBazelBuilder(options),
|
||||
updateGitignore(),
|
||||
]);
|
||||
};
|
||||
}
|
|
@ -0,0 +1,171 @@
|
|||
/**
|
||||
* @license
|
||||
* Copyright Google Inc. All Rights Reserved.
|
||||
*
|
||||
* Use of this source code is governed by an MIT-style license that can be
|
||||
* found in the LICENSE file at https://angular.io/license
|
||||
*/
|
||||
|
||||
import {HostTree} from '@angular-devkit/schematics';
|
||||
import {SchematicTestRunner, UnitTestTree} from '@angular-devkit/schematics/testing';
|
||||
|
||||
describe('ng-add schematic', () => {
|
||||
|
||||
const defaultOptions = {name: 'demo'};
|
||||
let host: UnitTestTree;
|
||||
let schematicRunner: SchematicTestRunner;
|
||||
|
||||
beforeEach(() => {
|
||||
host = new UnitTestTree(new HostTree());
|
||||
host.create('package.json', JSON.stringify({
|
||||
name: 'demo',
|
||||
dependencies: {
|
||||
'@angular/core': '1.2.3',
|
||||
},
|
||||
devDependencies: {
|
||||
'typescript': '3.2.2',
|
||||
},
|
||||
}));
|
||||
host.create('angular.json', JSON.stringify({
|
||||
projects: {
|
||||
'demo': {
|
||||
architect: {
|
||||
build: {},
|
||||
serve: {},
|
||||
test: {},
|
||||
'extract-i18n': {
|
||||
builder: '@angular-devkit/build-angular:extract-i18n',
|
||||
},
|
||||
},
|
||||
},
|
||||
'demo-e2e': {
|
||||
architect: {
|
||||
e2e: {},
|
||||
lint: {
|
||||
builder: '@angular-devkit/build-angular:tslint',
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
}));
|
||||
schematicRunner =
|
||||
new SchematicTestRunner('@angular/bazel', require.resolve('../collection.json'));
|
||||
});
|
||||
|
||||
it('throws if package.json is not found', () => {
|
||||
expect(host.files).toContain('/package.json');
|
||||
host.delete('/package.json');
|
||||
expect(() => schematicRunner.runSchematic('ng-add', defaultOptions))
|
||||
.toThrowError('Could not find package.json');
|
||||
});
|
||||
|
||||
it('throws if angular.json is not found', () => {
|
||||
expect(host.files).toContain('/angular.json');
|
||||
host.delete('/angular.json');
|
||||
expect(() => schematicRunner.runSchematic('ng-add', defaultOptions, host))
|
||||
.toThrowError('Could not find angular.json');
|
||||
});
|
||||
|
||||
it('should add @angular/bazel to package.json dependencies', () => {
|
||||
host = schematicRunner.runSchematic('ng-add', defaultOptions, host);
|
||||
const {files} = host;
|
||||
expect(files).toContain('/package.json');
|
||||
const content = host.readContent('/package.json');
|
||||
expect(() => JSON.parse(content)).not.toThrow();
|
||||
const json = JSON.parse(content);
|
||||
const core = '@angular/core';
|
||||
const bazel = '@angular/bazel';
|
||||
expect(Object.keys(json)).toContain('dependencies');
|
||||
expect(Object.keys(json)).toContain('devDependencies');
|
||||
expect(Object.keys(json.dependencies)).toContain(core);
|
||||
expect(Object.keys(json.devDependencies)).toContain(bazel);
|
||||
expect(json.dependencies[core]).toBe(json.devDependencies[bazel]);
|
||||
});
|
||||
|
||||
it('should add @bazel/* dev dependencies', () => {
|
||||
host = schematicRunner.runSchematic('ng-add', defaultOptions, host);
|
||||
const content = host.readContent('/package.json');
|
||||
const json = JSON.parse(content);
|
||||
const devDeps = Object.keys(json.devDependencies);
|
||||
expect(devDeps).toContain('@bazel/bazel');
|
||||
expect(devDeps).toContain('@bazel/ibazel');
|
||||
expect(devDeps).toContain('@bazel/karma');
|
||||
expect(devDeps).toContain('@bazel/typescript');
|
||||
});
|
||||
|
||||
it('should create Bazel workspace file', () => {
|
||||
host = schematicRunner.runSchematic('ng-add', defaultOptions, host);
|
||||
const {files} = host;
|
||||
expect(files).toContain('/WORKSPACE');
|
||||
expect(files).toContain('/BUILD.bazel');
|
||||
});
|
||||
|
||||
it('should produce main.dev.ts and main.prod.ts for AOT', () => {
|
||||
host.create('/src/main.ts', 'generated by CLI');
|
||||
host = schematicRunner.runSchematic('ng-add', defaultOptions, host);
|
||||
const {files} = host;
|
||||
// main.dev.ts and main.prod.ts are used by Bazel for AOT
|
||||
expect(files).toContain('/src/main.dev.ts');
|
||||
expect(files).toContain('/src/main.prod.ts');
|
||||
// main.ts is produced by original ng-add schematics
|
||||
// This file should be present for backwards compatibility.
|
||||
expect(files).toContain('/src/main.ts');
|
||||
});
|
||||
|
||||
it('should not overwrite index.html with script tags', () => {
|
||||
host.create('/src/index.html', '<html>Hello World</html>');
|
||||
host = schematicRunner.runSchematic('ng-add', defaultOptions, host);
|
||||
const {files} = host;
|
||||
expect(files).toContain('/src/index.html');
|
||||
const content = host.readContent('/src/index.html');
|
||||
expect(content).not.toMatch('<script src="/zone.min.js"></script>');
|
||||
expect(content).not.toMatch('<script src="/bundle.min.js"></script>');
|
||||
});
|
||||
|
||||
it('should generate main.dev.ts and main.prod.ts', () => {
|
||||
host = schematicRunner.runSchematic('ng-add', defaultOptions, host);
|
||||
const {files} = host;
|
||||
expect(files).toContain('/src/main.dev.ts');
|
||||
expect(files).toContain('/src/main.prod.ts');
|
||||
});
|
||||
|
||||
it('should overwrite .gitignore for bazel-out directory', () => {
|
||||
host.create('.gitignore', '\n# compiled output\n');
|
||||
host = schematicRunner.runSchematic('ng-add', defaultOptions, host);
|
||||
const {files} = host;
|
||||
expect(files).toContain('/.gitignore');
|
||||
const content = host.readContent('/.gitignore');
|
||||
expect(content).toMatch('\n# compiled output\n/bazel-out\n');
|
||||
});
|
||||
|
||||
it('should create a backup for original angular.json', () => {
|
||||
expect(host.files).toContain('/angular.json');
|
||||
const original = host.readContent('/angular.json');
|
||||
host = schematicRunner.runSchematic('ng-add', defaultOptions, host);
|
||||
expect(host.files).toContain('/angular.json.bak');
|
||||
const content = host.readContent('/angular.json.bak');
|
||||
expect(content.startsWith('// This is a backup file')).toBe(true);
|
||||
expect(content).toMatch(original);
|
||||
});
|
||||
|
||||
it('should update angular.json to use Bazel builder', () => {
|
||||
host = schematicRunner.runSchematic('ng-add', defaultOptions, host);
|
||||
const {files} = host;
|
||||
expect(files).toContain('/angular.json');
|
||||
const content = host.readContent('/angular.json');
|
||||
expect(() => JSON.parse(content)).not.toThrow();
|
||||
const json = JSON.parse(content);
|
||||
const demo = json.projects.demo;
|
||||
const demo_e2e = json.projects['demo-e2e'];
|
||||
const {build, serve, test} = demo.architect;
|
||||
expect(build.builder).toBe('@angular/bazel:build');
|
||||
expect(serve.builder).toBe('@angular/bazel:build');
|
||||
expect(test.builder).toBe('@angular/bazel:build');
|
||||
const {e2e, lint} = demo_e2e.architect;
|
||||
expect(e2e.builder).toBe('@angular/bazel:build');
|
||||
// it should leave non-Bazel commands unmodified
|
||||
expect(demo.architect['extract-i18n'].builder)
|
||||
.toBe('@angular-devkit/build-angular:extract-i18n');
|
||||
expect(lint.builder).toBe('@angular-devkit/build-angular:tslint');
|
||||
});
|
||||
});
|
|
@ -0,0 +1,13 @@
|
|||
|
||||
// THIS FILE IS AUTOMATICALLY GENERATED. TO UPDATE THIS FILE YOU NEED TO CHANGE
|
||||
// THE CORRESPONDING JSON SCHEMA FILE. See README.md.
|
||||
|
||||
// tslint:disable:no-global-tslint-disable
|
||||
// tslint:disable
|
||||
|
||||
export interface Schema {
|
||||
/**
|
||||
* The name of the project.
|
||||
*/
|
||||
name: string;
|
||||
}
|
|
@ -0,0 +1,20 @@
|
|||
{
|
||||
"$schema": "http://json-schema.org/schema",
|
||||
"id": "SchematicsAngularBazelNgAdd",
|
||||
"title": "Angular Bazel Ng Add Schema",
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"name": {
|
||||
"description": "The name of the project.",
|
||||
"type": "string",
|
||||
"format": "html-selector",
|
||||
"$default": {
|
||||
"$source": "argv",
|
||||
"index": 0
|
||||
}
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"name"
|
||||
]
|
||||
}
|
|
@ -12,11 +12,9 @@ ts_library(
|
|||
"schema.json",
|
||||
],
|
||||
deps = [
|
||||
"//packages/bazel/src/schematics/bazel-workspace",
|
||||
"@ngdeps//@angular-devkit/core",
|
||||
"//packages/bazel/src/schematics/ng-add",
|
||||
"@ngdeps//@angular-devkit/schematics",
|
||||
"@ngdeps//@schematics/angular",
|
||||
"@ngdeps//typescript",
|
||||
],
|
||||
)
|
||||
|
||||
|
|
|
@ -8,211 +8,19 @@
|
|||
* @fileoverview Schematics for ng-new project that builds with Bazel.
|
||||
*/
|
||||
|
||||
import {SchematicContext, apply, applyTemplates, chain, externalSchematic, MergeStrategy, mergeWith, move, Rule, schematic, Tree, url, SchematicsException, UpdateRecorder,} from '@angular-devkit/schematics';
|
||||
import {parseJsonAst, JsonAstObject, strings, JsonValue} from '@angular-devkit/core';
|
||||
import {findPropertyInAstObject, insertPropertyInAstObjectInOrder} from '@schematics/angular/utility/json-utils';
|
||||
import {Rule, Tree, chain, externalSchematic, schematic} from '@angular-devkit/schematics';
|
||||
import {validateProjectName} from '@schematics/angular/utility/validation';
|
||||
import {getWorkspace} from '@schematics/angular/utility/config';
|
||||
import {Schema} from './schema';
|
||||
|
||||
/**
|
||||
* Packages that build under Bazel require additional dev dependencies. This
|
||||
* function adds those dependencies to "devDependencies" section in
|
||||
* package.json.
|
||||
*/
|
||||
function addDevDependenciesToPackageJson(options: Schema) {
|
||||
return (host: Tree) => {
|
||||
const packageJson = `${options.name}/package.json`;
|
||||
|
||||
if (!host.exists(packageJson)) {
|
||||
throw new Error(`Could not find ${packageJson}`);
|
||||
}
|
||||
const packageJsonContent = host.read(packageJson);
|
||||
if (!packageJsonContent) {
|
||||
throw new Error('Failed to read package.json content');
|
||||
}
|
||||
const jsonAst = parseJsonAst(packageJsonContent.toString()) as JsonAstObject;
|
||||
const deps = findPropertyInAstObject(jsonAst, 'dependencies') as JsonAstObject;
|
||||
const devDeps = findPropertyInAstObject(jsonAst, 'devDependencies') as JsonAstObject;
|
||||
|
||||
const angularCoreNode = findPropertyInAstObject(deps, '@angular/core');
|
||||
const angularCoreVersion = angularCoreNode !.value as string;
|
||||
|
||||
const devDependencies: {[k: string]: string} = {
|
||||
'@angular/bazel': angularCoreVersion,
|
||||
// TODO(kyliau): Consider moving this to latest-versions.ts
|
||||
'@bazel/bazel': '^0.22.1',
|
||||
'@bazel/ibazel': '^0.9.0',
|
||||
'@bazel/karma': '^0.22.1',
|
||||
'@bazel/typescript': '^0.22.1',
|
||||
};
|
||||
|
||||
const recorder = host.beginUpdate(packageJson);
|
||||
for (const packageName of Object.keys(devDependencies)) {
|
||||
const version = devDependencies[packageName];
|
||||
const indent = 4;
|
||||
insertPropertyInAstObjectInOrder(recorder, devDeps, packageName, version, indent);
|
||||
}
|
||||
host.commitUpdate(recorder);
|
||||
return host;
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Append main.dev.ts and main.prod.ts to src directory. These files are needed
|
||||
* by Bazel for devserver and prodserver, respectively. They are different from
|
||||
* main.ts generated by CLI because they use platformBrowser (AOT) instead of
|
||||
* platformBrowserDynamic (JIT).
|
||||
*/
|
||||
function addDevAndProdMainForAot(options: Schema) {
|
||||
return (host: Tree) => {
|
||||
let newProjectRoot = '';
|
||||
try {
|
||||
const workspace = getWorkspace(host);
|
||||
newProjectRoot = workspace.newProjectRoot || '';
|
||||
} catch {
|
||||
}
|
||||
const srcDir = `${newProjectRoot}/${options.name}/src`;
|
||||
|
||||
return mergeWith(apply(url('./files'), [
|
||||
applyTemplates({
|
||||
utils: strings,
|
||||
...options,
|
||||
'dot': '.',
|
||||
}),
|
||||
move(srcDir),
|
||||
]));
|
||||
};
|
||||
}
|
||||
|
||||
function overwriteGitignore(options: Schema) {
|
||||
return (host: Tree) => {
|
||||
const gitignore = `${options.name}/.gitignore`;
|
||||
if (!host.exists(gitignore)) {
|
||||
return host;
|
||||
}
|
||||
const gitIgnoreContent = host.read(gitignore);
|
||||
if (!gitIgnoreContent) {
|
||||
throw new Error('Failed to read .gitignore content');
|
||||
}
|
||||
|
||||
if (gitIgnoreContent.includes('/bazel-out\n')) {
|
||||
return host;
|
||||
}
|
||||
const lines = gitIgnoreContent.toString().split(/\n/g);
|
||||
const recorder = host.beginUpdate(gitignore);
|
||||
const compileOutput = lines.findIndex((line: string) => line === '# compiled output');
|
||||
recorder.insertRight(compileOutput, '\n/bazel-out');
|
||||
host.commitUpdate(recorder);
|
||||
|
||||
return host;
|
||||
};
|
||||
}
|
||||
|
||||
function replacePropertyInAstObject(
|
||||
recorder: UpdateRecorder, node: JsonAstObject, propertyName: string, value: JsonValue,
|
||||
indent: number) {
|
||||
const property = findPropertyInAstObject(node, propertyName);
|
||||
if (property === null) {
|
||||
throw new Error(`Property ${propertyName} does not exist in JSON object`);
|
||||
}
|
||||
const {start, text} = property;
|
||||
recorder.remove(start.offset, text.length);
|
||||
const indentStr = '\n' +
|
||||
' '.repeat(indent);
|
||||
const content = JSON.stringify(value, null, ' ').replace(/\n/g, indentStr);
|
||||
recorder.insertLeft(start.offset, content);
|
||||
}
|
||||
|
||||
function updateWorkspaceFileToUseBazelBuilder(options: Schema): Rule {
|
||||
return (host: Tree, context: SchematicContext) => {
|
||||
const {name} = options;
|
||||
const workspacePath = `${name}/angular.json`;
|
||||
if (!host.exists(workspacePath)) {
|
||||
throw new SchematicsException(`Workspace file ${workspacePath} not found.`);
|
||||
}
|
||||
const workspaceBuffer = host.read(workspacePath) !;
|
||||
const workspaceJsonAst = parseJsonAst(workspaceBuffer.toString()) as JsonAstObject;
|
||||
const projects = findPropertyInAstObject(workspaceJsonAst, 'projects');
|
||||
if (!projects) {
|
||||
throw new SchematicsException('Expect projects in angular.json to be an Object');
|
||||
}
|
||||
const project = findPropertyInAstObject(projects as JsonAstObject, name);
|
||||
if (!project) {
|
||||
throw new SchematicsException(`Expected projects to contain ${name}`);
|
||||
}
|
||||
const recorder = host.beginUpdate(workspacePath);
|
||||
const indent = 6;
|
||||
replacePropertyInAstObject(
|
||||
recorder, project as JsonAstObject, 'architect', {
|
||||
'build': {
|
||||
'builder': '@angular/bazel:build',
|
||||
'options': {'targetLabel': '//src:bundle.js', 'bazelCommand': 'build'},
|
||||
'configurations': {'production': {'targetLabel': '//src:bundle'}}
|
||||
},
|
||||
'serve': {
|
||||
'builder': '@angular/bazel:build',
|
||||
'options': {'targetLabel': '//src:devserver', 'bazelCommand': 'run'},
|
||||
'configurations': {'production': {'targetLabel': '//src:prodserver'}}
|
||||
},
|
||||
'extract-i18n': {
|
||||
'builder': '@angular-devkit/build-angular:extract-i18n',
|
||||
'options': {'browserTarget': `${name}:build`}
|
||||
},
|
||||
'test': {
|
||||
'builder': '@angular/bazel:build',
|
||||
'options': {'bazelCommand': 'test', 'targetLabel': '//src/...'}
|
||||
},
|
||||
'lint': {
|
||||
'builder': '@angular-devkit/build-angular:tslint',
|
||||
'options': {
|
||||
'tsConfig': ['src/tsconfig.app.json', 'src/tsconfig.spec.json'],
|
||||
'exclude': ['**/node_modules/**']
|
||||
}
|
||||
}
|
||||
},
|
||||
indent);
|
||||
|
||||
const e2e = `${options.name}-e2e`;
|
||||
const e2eNode = findPropertyInAstObject(projects as JsonAstObject, e2e);
|
||||
if (e2eNode) {
|
||||
replacePropertyInAstObject(
|
||||
recorder, e2eNode as JsonAstObject, 'architect', {
|
||||
'e2e': {
|
||||
'builder': '@angular/bazel:build',
|
||||
'options': {'bazelCommand': 'test', 'targetLabel': '//e2e:devserver_test'},
|
||||
'configurations': {'production': {'targetLabel': '//e2e:prodserver_test'}}
|
||||
},
|
||||
'lint': {
|
||||
'builder': '@angular-devkit/build-angular:tslint',
|
||||
'options': {'tsConfig': 'e2e/tsconfig.e2e.json', 'exclude': ['**/node_modules/**']}
|
||||
}
|
||||
},
|
||||
indent);
|
||||
}
|
||||
|
||||
host.commitUpdate(recorder);
|
||||
return host;
|
||||
};
|
||||
}
|
||||
|
||||
export default function(options: Schema): Rule {
|
||||
return (host: Tree) => {
|
||||
validateProjectName(options.name);
|
||||
|
||||
return chain([
|
||||
externalSchematic(
|
||||
'@schematics/angular', 'ng-new',
|
||||
{
|
||||
...options,
|
||||
}),
|
||||
addDevDependenciesToPackageJson(options),
|
||||
addDevAndProdMainForAot(options),
|
||||
schematic('bazel-workspace', options, {
|
||||
externalSchematic('@schematics/angular', 'ng-new', options),
|
||||
schematic('ng-add', options, {
|
||||
scope: options.name,
|
||||
}),
|
||||
overwriteGitignore(options),
|
||||
updateWorkspaceFileToUseBazelBuilder(options),
|
||||
]);
|
||||
};
|
||||
}
|
||||
|
|
|
@ -8,7 +8,7 @@
|
|||
|
||||
import {SchematicTestRunner} from '@angular-devkit/schematics/testing';
|
||||
|
||||
describe('Ng-new Schematic', () => {
|
||||
describe('ng-new schematic', () => {
|
||||
const schematicRunner =
|
||||
new SchematicTestRunner('@angular/bazel', require.resolve('../collection.json'), );
|
||||
const defaultOptions = {
|
||||
|
@ -22,94 +22,15 @@ describe('Ng-new Schematic', () => {
|
|||
const {files} = host;
|
||||
// External schematic should produce workspace file angular.json
|
||||
expect(files).toContain('/demo/angular.json');
|
||||
});
|
||||
|
||||
it('should add @angular/bazel to package.json dependencies', () => {
|
||||
const options = {...defaultOptions};
|
||||
const host = schematicRunner.runSchematic('ng-new', options);
|
||||
const {files} = host;
|
||||
expect(files).toContain('/demo/package.json');
|
||||
const content = host.readContent('/demo/package.json');
|
||||
expect(() => JSON.parse(content)).not.toThrow();
|
||||
const json = JSON.parse(content);
|
||||
const core = '@angular/core';
|
||||
const bazel = '@angular/bazel';
|
||||
expect(Object.keys(json)).toContain('dependencies');
|
||||
expect(Object.keys(json)).toContain('devDependencies');
|
||||
expect(Object.keys(json.dependencies)).toContain(core);
|
||||
expect(Object.keys(json.devDependencies)).toContain(bazel);
|
||||
expect(json.dependencies[core]).toBe(json.devDependencies[bazel]);
|
||||
});
|
||||
|
||||
it('should add @bazel/* dev dependencies', () => {
|
||||
const options = {...defaultOptions};
|
||||
const host = schematicRunner.runSchematic('ng-new', options);
|
||||
const content = host.readContent('/demo/package.json');
|
||||
const json = JSON.parse(content);
|
||||
const devDeps = Object.keys(json.devDependencies);
|
||||
expect(devDeps).toContain('@bazel/karma');
|
||||
expect(devDeps).toContain('@bazel/typescript');
|
||||
});
|
||||
|
||||
it('should create Bazel workspace file', () => {
|
||||
it('should call ng-add to generate Bazel files', () => {
|
||||
const options = {...defaultOptions};
|
||||
const host = schematicRunner.runSchematic('ng-new', options);
|
||||
const {files} = host;
|
||||
expect(files).toContain('/demo/WORKSPACE');
|
||||
expect(files).toContain('/demo/BUILD.bazel');
|
||||
});
|
||||
|
||||
it('should produce main.prod.ts for AOT', () => {
|
||||
const options = {...defaultOptions};
|
||||
const host = schematicRunner.runSchematic('ng-new', options);
|
||||
const {files} = host;
|
||||
// main.prod.ts is used by Bazel for AOT
|
||||
expect(files).toContain('/demo/src/main.prod.ts');
|
||||
// main.ts is produced by original ng-new schematics
|
||||
// This file should be present for backwards compatibility.
|
||||
expect(files).toContain('/demo/src/main.ts');
|
||||
});
|
||||
|
||||
it('should not overwrite index.html with script tags', () => {
|
||||
const options = {...defaultOptions};
|
||||
const host = schematicRunner.runSchematic('ng-new', options);
|
||||
const {files} = host;
|
||||
expect(files).toContain('/demo/src/index.html');
|
||||
const content = host.readContent('/demo/src/index.html');
|
||||
expect(content).not.toMatch('<script src="/zone.min.js"></script>');
|
||||
expect(content).not.toMatch('<script src="/bundle.min.js"></script>');
|
||||
});
|
||||
|
||||
it('should generate main.dev.ts and main.prod.ts', () => {
|
||||
const options = {...defaultOptions};
|
||||
const host = schematicRunner.runSchematic('ng-new', options);
|
||||
const {files} = host;
|
||||
expect(files).toContain('/demo/src/main.dev.ts');
|
||||
expect(files).toContain('/demo/src/main.prod.ts');
|
||||
});
|
||||
|
||||
it('should overwrite .gitignore for bazel-out directory', () => {
|
||||
const options = {...defaultOptions};
|
||||
const host = schematicRunner.runSchematic('ng-new', options);
|
||||
const {files} = host;
|
||||
expect(files).toContain('/demo/.gitignore');
|
||||
const content = host.readContent('/demo/.gitignore');
|
||||
expect(content).toMatch('/bazel-out');
|
||||
});
|
||||
|
||||
it('should update angular.json to use Bazel builder', () => {
|
||||
const options = {...defaultOptions};
|
||||
const host = schematicRunner.runSchematic('ng-new', options);
|
||||
const {files} = host;
|
||||
expect(files).toContain('/demo/angular.json');
|
||||
const content = host.readContent('/demo/angular.json');
|
||||
expect(() => JSON.parse(content)).not.toThrow();
|
||||
const json = JSON.parse(content);
|
||||
let {architect} = json.projects.demo;
|
||||
expect(architect.build.builder).toBe('@angular/bazel:build');
|
||||
expect(architect.serve.builder).toBe('@angular/bazel:build');
|
||||
expect(architect.test.builder).toBe('@angular/bazel:build');
|
||||
architect = json.projects['demo-e2e'].architect;
|
||||
expect(architect.e2e.builder).toBe('@angular/bazel:build');
|
||||
expect(files).toContain('/demo/src/BUILD.bazel');
|
||||
});
|
||||
});
|
||||
|
|
|
@ -43,7 +43,9 @@
|
|||
"commit": {
|
||||
"description": "Initial repository commit information.",
|
||||
"oneOf": [
|
||||
{ "type": "boolean" },
|
||||
{
|
||||
"type": "boolean"
|
||||
},
|
||||
{
|
||||
"type": "object",
|
||||
"properties": {
|
||||
|
@ -85,7 +87,12 @@
|
|||
},
|
||||
"viewEncapsulation": {
|
||||
"description": "Specifies the view encapsulation strategy.",
|
||||
"enum": ["Emulated", "Native", "None", "ShadowDom"],
|
||||
"enum": [
|
||||
"Emulated",
|
||||
"Native",
|
||||
"None",
|
||||
"ShadowDom"
|
||||
],
|
||||
"type": "string"
|
||||
},
|
||||
"version": {
|
||||
|
@ -118,11 +125,22 @@
|
|||
"message": "Which stylesheet format would you like to use?",
|
||||
"type": "list",
|
||||
"items": [
|
||||
{ "value": "css", "label": "CSS" },
|
||||
{ "value": "scss", "label": "SCSS [ http://sass-lang.com ]" },
|
||||
{ "value": "sass", "label": "SASS [ http://sass-lang.com ]" },
|
||||
{ "value": "less", "label": "LESS [ http://lesscss.org ]" },
|
||||
{ "value": "styl", "label": "Stylus [ http://stylus-lang.com ]" }
|
||||
{
|
||||
"value": "css",
|
||||
"label": "CSS"
|
||||
},
|
||||
{
|
||||
"value": "sass",
|
||||
"label": "Sass [ http://sass-lang.com ]"
|
||||
},
|
||||
{
|
||||
"value": "less",
|
||||
"label": "Less [ http://lesscss.org ]"
|
||||
},
|
||||
{
|
||||
"value": "styl",
|
||||
"label": "Stylus [ http://stylus-lang.com ]"
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
|
|
Loading…
Reference in New Issue