feat(nx): remove @nrwl/bazel package
This commit is contained in:
parent
a5bc37c60d
commit
b8ee3ba478
@ -45,7 +45,6 @@
|
||||
- [Affected support for uncommitted changes](https://github.com/nrwl/nx/commit/113b51bd330c2af058675386e482d38f170a6688)
|
||||
- [Extend circular dependency check](https://github.com/nrwl/nx/commit/fff9659c3a108b613c6db89bcca4072494fbe85f)
|
||||
- [Add lint checks ensuring the integrity of the workspace](https://github.com/nrwl/nx/commit/ce553b732e8ca004e1ecf53cf54bcadb6ba1f7f3)
|
||||
- [Add ability to create bazel workspace](https://github.com/nrwl/nx/commit/5a26f241b1e8b8b87e2ab4da941d3d3c4c480046)
|
||||
|
||||
## Fixes
|
||||
|
||||
|
||||
@ -14,7 +14,7 @@ If you find a bug in the source code or a mistake in the documentation, you can
|
||||
|
||||
After cloning the project run: `yarn`.
|
||||
|
||||
After that run `yarn build` to build the `bazel`, `nx`, and `schematics` packages.
|
||||
After that run `yarn build` to build the `nx`, and `schematics` packages.
|
||||
|
||||
After that run `yarn linknpm`.
|
||||
|
||||
|
||||
@ -15,10 +15,10 @@
|
||||
<hr>
|
||||
|
||||
<p align="center">
|
||||
<a href="https://hubs.ly/H0g97pW0" target="_blank">
|
||||
<img
|
||||
<a href="https://hubs.ly/H0g97pW0" target="_blank">
|
||||
<img
|
||||
width="728"
|
||||
src="https://images.ctfassets.net/8eyogtwep6d2/40ASb6l6MR7V0w5ntqZ2yi/b4d439fcf56e50085d1f76df1bee41af/monorepo-banner-angularconsole.png"
|
||||
src="https://images.ctfassets.net/8eyogtwep6d2/40ASb6l6MR7V0w5ntqZ2yi/b4d439fcf56e50085d1f76df1bee41af/monorepo-banner-angularconsole.png"
|
||||
alt="Our Newest Enterprise Angular Book">
|
||||
</a>
|
||||
</p>
|
||||
|
||||
@ -1,41 +0,0 @@
|
||||
Bazel Commands
|
||||
|
||||
## Add new app
|
||||
|
||||
node_modules/.bin/ng generate app [name]
|
||||
|
||||
Example: node_modules/.bin/ng generate app test
|
||||
|
||||
## Add new component
|
||||
|
||||
node_modules/.bin/ng generate component [name] --directory=[dir]
|
||||
|
||||
Example: node_modules/.bin/ng generate component friends --directory=myDir
|
||||
|
||||
- must manually import the component's Bazel rule in the consuming Bazel rule
|
||||
|
||||
## Add new lib
|
||||
|
||||
node_modules/.bin/ng generate lib [name]
|
||||
|
||||
Example: node_modules/.bin/ng generate lib mylib
|
||||
|
||||
- must manually import the lib's Bazel rule in the consuming Bazel rule
|
||||
|
||||
## Run dev server
|
||||
|
||||
ibazel run apps/[app specific path]]/src:devserver (anything between apps/\*\*/src points to a specific app)
|
||||
|
||||
Example: ibazel run apps/my-dir/my-app/src:devserver
|
||||
|
||||
## Run prod server
|
||||
|
||||
bazel run apps/[app specific path]]/src:prodserver (anything between apps/\*\*/src points to a specific app)
|
||||
|
||||
Example: bazel run apps/my-dir/my-app/src:prodserver
|
||||
|
||||
## Run unit tests
|
||||
|
||||
ibazel test //libs/mylib/src:test
|
||||
|
||||
- currently works for libs
|
||||
@ -1,21 +0,0 @@
|
||||
{
|
||||
"name": "@nrwl/bazel",
|
||||
"version": "0.0.1",
|
||||
"description": "Nrwl Extensions for Angular: Bazel Schematics",
|
||||
"main": "index.js",
|
||||
"types": "index.d.js",
|
||||
"author": "Victor Savkin",
|
||||
"license": "MIT",
|
||||
"schematics": "./src/collection.json",
|
||||
"dependencies": {
|
||||
"@ngrx/schematics": "6.0.1",
|
||||
"app-root-path": "^2.0.1",
|
||||
"npm-run-all": "4.1.2",
|
||||
"semver": "5.4.1",
|
||||
"tmp": "0.0.33",
|
||||
"yargs-parser": "10.0.0"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@schematics/angular": "0.7.1"
|
||||
}
|
||||
}
|
||||
@ -1,28 +0,0 @@
|
||||
{
|
||||
"name": "nx-bazel",
|
||||
"version": "0.1",
|
||||
"extends": "@schematics/angular",
|
||||
"schematics": {
|
||||
"application": {
|
||||
"factory": "./collection/application",
|
||||
"schema": "./collection/application/schema.json",
|
||||
"description": "Create a Bazel workspace."
|
||||
},
|
||||
"app": {
|
||||
"factory": "./collection/app",
|
||||
"schema": "./collection/app/schema.json",
|
||||
"description": "Create an application."
|
||||
},
|
||||
"lib": {
|
||||
"factory": "./collection/lib",
|
||||
"schema": "./collection/lib/schema.json",
|
||||
"description": "Create a library"
|
||||
},
|
||||
"module": {
|
||||
"aliases": ["m"],
|
||||
"factory": "./collection/module",
|
||||
"schema": "./collection/module/schema.json",
|
||||
"description": "Create a Module"
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1,57 +0,0 @@
|
||||
load("@angular//:index.bzl", "ng_module")
|
||||
load("@build_bazel_rules_typescript//:defs.bzl", "ts_devserver")
|
||||
|
||||
package(default_visibility = ["//visibility:public"])
|
||||
|
||||
ng_module(
|
||||
name = "<%= sourceDir %>",
|
||||
srcs = glob(["main.ts"]),
|
||||
deps = [
|
||||
"//apps/<%= fullName %>/src/app",
|
||||
"@rxjs",
|
||||
],
|
||||
)
|
||||
|
||||
# Needed because the devserver only loads static files that appear under this
|
||||
# package.
|
||||
genrule(
|
||||
name = "zone.js",
|
||||
srcs = ["//:node_modules/zone.js/dist/zone.min.js"],
|
||||
outs = ["zone.min.js"],
|
||||
cmd = "cp $< $@",
|
||||
)
|
||||
|
||||
STATIC_FILES = [
|
||||
"favicon.ico",
|
||||
"index.html",
|
||||
"styles.css",
|
||||
":zone.js",
|
||||
]
|
||||
|
||||
ts_devserver(
|
||||
name = "devserver",
|
||||
data = ["//apps/<%= fullName %>/src/assets"],
|
||||
entry_module = "<%= workspaceName %>/apps/<%= fullName %>/src/main",
|
||||
scripts = ["//:angular_bundles"],
|
||||
serving_path = "/bundle.min.js",
|
||||
static_files = STATIC_FILES,
|
||||
deps = [":<%= sourceDir %>"],
|
||||
)
|
||||
|
||||
load("@build_bazel_rules_nodejs//:defs.bzl", "rollup_bundle", "nodejs_binary")
|
||||
|
||||
rollup_bundle(
|
||||
name = "bundle",
|
||||
entry_point = "<%= workspaceName %>/apps/<%= fullName %>/src/main",
|
||||
deps = [":<%= sourceDir %>"],
|
||||
)
|
||||
|
||||
nodejs_binary(
|
||||
name = "prodserver",
|
||||
args = ["./apps/<%= fullName %>/src"],
|
||||
data = STATIC_FILES + [
|
||||
":bundle",
|
||||
"//apps/<%= fullName %>/src/assets",
|
||||
],
|
||||
entry_point = "http-server/bin/http-server",
|
||||
)
|
||||
@ -1,6 +0,0 @@
|
||||
package(default_visibility = ["//visibility:public"])
|
||||
|
||||
filegroup(
|
||||
name = "assets",
|
||||
srcs = glob(["*"]),
|
||||
)
|
||||
Binary file not shown.
|
Before Width: | Height: | Size: 27 KiB |
Binary file not shown.
|
Before Width: | Height: | Size: 5.3 KiB |
@ -1,17 +0,0 @@
|
||||
<!doctype html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title><%= utils.classify(name) %></title>
|
||||
<base href="/">
|
||||
|
||||
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<link rel="icon" type="image/x-icon" href="favicon.ico">
|
||||
</head>
|
||||
<body>
|
||||
<<%= prefix %>-root></<%= prefix %>-root>
|
||||
<script src="/zone.min.js"></script>
|
||||
<script src="/bundle.min.js"></script>
|
||||
</body>
|
||||
</html>
|
||||
@ -1,7 +0,0 @@
|
||||
import { enableProdMode } from '@angular/core';
|
||||
import { platformBrowser } from '@angular/platform-browser';
|
||||
|
||||
import {AppModuleNgFactory} from './app/app.module.ngfactory';
|
||||
|
||||
platformBrowser().bootstrapModuleFactory(AppModuleNgFactory)
|
||||
.catch(err => console.log(err));
|
||||
@ -1,76 +0,0 @@
|
||||
/**
|
||||
* This file includes polyfills needed by Angular and is loaded before the app.
|
||||
* You can add your own extra polyfills to this file.
|
||||
*
|
||||
* This file is divided into 2 sections:
|
||||
* 1. Browser polyfills. These are applied before loading ZoneJS and are sorted by browsers.
|
||||
* 2. Application imports. Files imported after ZoneJS that should be loaded before your main
|
||||
* file.
|
||||
*
|
||||
* The current setup is for so-called "evergreen" browsers; the last versions of browsers that
|
||||
* automatically update themselves. This includes Safari >= 10, Chrome >= 55 (including Opera),
|
||||
* Edge >= 13 on the desktop, and iOS 10 and Chrome on mobile.
|
||||
*
|
||||
* Learn more in https://angular.io/docs/ts/latest/guide/browser-support.html
|
||||
*/
|
||||
|
||||
/***************************************************************************************************
|
||||
* BROWSER POLYFILLS
|
||||
*/
|
||||
|
||||
/** IE9, IE10 and IE11 requires all of the following polyfills. **/
|
||||
// import 'core-js/es6/symbol';
|
||||
// import 'core-js/es6/object';
|
||||
// import 'core-js/es6/function';
|
||||
// import 'core-js/es6/parse-int';
|
||||
// import 'core-js/es6/parse-float';
|
||||
// import 'core-js/es6/number';
|
||||
// import 'core-js/es6/math';
|
||||
// import 'core-js/es6/string';
|
||||
// import 'core-js/es6/date';
|
||||
// import 'core-js/es6/array';
|
||||
// import 'core-js/es6/regexp';
|
||||
// import 'core-js/es6/map';
|
||||
// import 'core-js/es6/weak-map';
|
||||
// import 'core-js/es6/set';
|
||||
|
||||
/** IE10 and IE11 requires the following for NgClass support on SVG elements */
|
||||
// import 'classlist.js'; // Run `npm install --save classlist.js`.
|
||||
|
||||
/** IE10 and IE11 requires the following for the Reflect API. */
|
||||
// import 'core-js/es6/reflect';
|
||||
|
||||
|
||||
/** Evergreen browsers require these. **/
|
||||
// Used for reflect-metadata in JIT. If you use AOT (and only Angular decorators), you can remove.
|
||||
import 'core-js/es7/reflect';
|
||||
|
||||
|
||||
/**
|
||||
* Required to support Web Animations `@angular/platform-browser/animations`.
|
||||
* Needed for: All but Chrome, Firefox and Opera. http://caniuse.com/#feat=web-animation
|
||||
**/
|
||||
// import 'web-animations-js'; // Run `npm install --save web-animations-js`.
|
||||
|
||||
|
||||
|
||||
/***************************************************************************************************
|
||||
* Zone JS is required by Angular itself.
|
||||
*/
|
||||
import 'zone.js/dist/zone'; // Included with Angular CLI.
|
||||
|
||||
|
||||
|
||||
/***************************************************************************************************
|
||||
* APPLICATION IMPORTS
|
||||
*/
|
||||
|
||||
/**
|
||||
* Date, currency, decimal and percent pipes.
|
||||
* Needed for: All but Chrome, Firefox, Edge, IE11 and Safari 10
|
||||
*/
|
||||
// import 'intl'; // Run `npm install --save intl`.
|
||||
/**
|
||||
* Need to import at least one locale-data with intl.
|
||||
*/
|
||||
// import 'intl/locale-data/jsonp/en';
|
||||
@ -1 +0,0 @@
|
||||
/* You can add global styles to this file, and also import other style files */
|
||||
@ -1,14 +0,0 @@
|
||||
{
|
||||
"extends": "<%= offsetFromRoot %>tsconfig.json",
|
||||
"compilerOptions": {
|
||||
"outDir": "<%= offsetFromRoot %>dist/out-tsc/apps/<%= fullName %>",
|
||||
"module": "es2015"
|
||||
},
|
||||
"include": [
|
||||
"**/*.ts"
|
||||
/* add all lazy-loaded libraries here: "<%= offsetFromRoot %>libs/my-lib/index.ts" */
|
||||
],
|
||||
"exclude": [
|
||||
"**/*.spec.ts"
|
||||
]
|
||||
}
|
||||
@ -1,14 +0,0 @@
|
||||
import { AppPage } from './app.po';
|
||||
|
||||
describe('<%= utils.dasherize(name) %> App', () => {
|
||||
let page: AppPage;
|
||||
|
||||
beforeEach(() => {
|
||||
page = new AppPage();
|
||||
});
|
||||
|
||||
it('should display welcome message', () => {
|
||||
page.navigateTo();
|
||||
expect(page.text()).toContain('Welcome');
|
||||
});
|
||||
});
|
||||
@ -1,11 +0,0 @@
|
||||
import { browser, by, element } from 'protractor';
|
||||
|
||||
export class AppPage {
|
||||
navigateTo() {
|
||||
return browser.get('/');
|
||||
}
|
||||
|
||||
text() {
|
||||
return browser.findElement(by.css('body')).getText();
|
||||
}
|
||||
}
|
||||
@ -1,20 +0,0 @@
|
||||
{
|
||||
"extends": "<%= offsetFromRoot %>tsconfig.json",
|
||||
"compilerOptions": {
|
||||
"outDir": "<%= offsetFromRoot %>dist/out-tsc/e2e/<%= fullName %>",
|
||||
"module": "commonjs",
|
||||
"target": "es5",
|
||||
"types": [
|
||||
"jasmine",
|
||||
"jasminewd2",
|
||||
"node"
|
||||
]
|
||||
},
|
||||
"include": [
|
||||
"../**/*.ts"
|
||||
/* add all lazy-loaded libraries here: "<%= offsetFromRoot %>libs/my-lib/index.ts" */
|
||||
],
|
||||
"exclude": [
|
||||
"**/*.spec.ts"
|
||||
]
|
||||
}
|
||||
@ -1,307 +0,0 @@
|
||||
import {
|
||||
apply,
|
||||
branchAndMerge,
|
||||
chain,
|
||||
externalSchematic,
|
||||
mergeWith,
|
||||
noop,
|
||||
Rule,
|
||||
template,
|
||||
Tree,
|
||||
url
|
||||
} from '@angular-devkit/schematics';
|
||||
import { Schema } from './schema';
|
||||
import { strings } from '@angular-devkit/core';
|
||||
import {
|
||||
addImportToModule,
|
||||
insert,
|
||||
addImportToTestBed,
|
||||
updateJsonInTree
|
||||
} from '../../utils/ast-utils';
|
||||
import { toFileName } from '../../utils/name-utils';
|
||||
import * as ts from 'typescript';
|
||||
import {
|
||||
addBootstrapToModule,
|
||||
insertImport
|
||||
} from '@schematics/angular/utility/ast-utils';
|
||||
import { addApp, readCliConfigFile } from '../../utils/fileutils';
|
||||
import { offsetFromRoot } from '../../utils/common';
|
||||
import { formatFiles } from '../../utils/rules/format-files';
|
||||
|
||||
interface NormalizedSchema extends Schema {
|
||||
fullName: string;
|
||||
fullPath: string;
|
||||
workspaceName: string;
|
||||
}
|
||||
|
||||
function addBootstrap(path: string): Rule {
|
||||
return (host: Tree) => {
|
||||
const modulePath = `${path}/app/app.module.ts`;
|
||||
const moduleSource = host.read(modulePath)!.toString('utf-8');
|
||||
const sourceFile = ts.createSourceFile(
|
||||
modulePath,
|
||||
moduleSource,
|
||||
ts.ScriptTarget.Latest,
|
||||
true
|
||||
);
|
||||
insert(host, modulePath, [
|
||||
insertImport(
|
||||
sourceFile,
|
||||
modulePath,
|
||||
'BrowserModule',
|
||||
'@angular/platform-browser'
|
||||
),
|
||||
...addImportToModule(sourceFile, modulePath, 'BrowserModule'),
|
||||
...addBootstrapToModule(
|
||||
sourceFile,
|
||||
modulePath,
|
||||
'AppComponent',
|
||||
'./app.component'
|
||||
)
|
||||
]);
|
||||
return host;
|
||||
};
|
||||
}
|
||||
|
||||
function addNxModule(path: string): Rule {
|
||||
return (host: Tree) => {
|
||||
const modulePath = `${path}/app/app.module.ts`;
|
||||
const moduleSource = host.read(modulePath)!.toString('utf-8');
|
||||
const sourceFile = ts.createSourceFile(
|
||||
modulePath,
|
||||
moduleSource,
|
||||
ts.ScriptTarget.Latest,
|
||||
true
|
||||
);
|
||||
insert(host, modulePath, [
|
||||
insertImport(sourceFile, modulePath, 'NxModule', '@nrwl/nx'),
|
||||
...addImportToModule(sourceFile, modulePath, 'NxModule.forRoot()')
|
||||
]);
|
||||
return host;
|
||||
};
|
||||
}
|
||||
function addAppToAngularCliJson(options: NormalizedSchema): Rule {
|
||||
return updateJsonInTree('.angular-cli.json', angularCliJson => {
|
||||
angularCliJson.apps = addApp(angularCliJson.apps, {
|
||||
name: options.fullName,
|
||||
root: options.fullPath,
|
||||
outDir: `dist/apps/${options.fullName}`,
|
||||
assets: ['assets', 'favicon.ico'],
|
||||
index: 'index.html',
|
||||
main: 'main.ts',
|
||||
polyfills: 'polyfills.ts',
|
||||
test: `${offsetFromRoot(options.fullPath)}test.js`,
|
||||
tsconfig: `tsconfig.app.json`,
|
||||
testTsconfig: `${offsetFromRoot(options.fullPath)}tsconfig.spec.json`,
|
||||
prefix: options.prefix,
|
||||
styles: [`styles.${options.style}`],
|
||||
scripts: [],
|
||||
environmentSource: 'environments/environment.ts',
|
||||
environments: {
|
||||
dev: 'environments/environment.ts',
|
||||
prod: 'environments/environment.prod.ts'
|
||||
}
|
||||
});
|
||||
|
||||
angularCliJson.lint = [
|
||||
...(angularCliJson.lint || []),
|
||||
{
|
||||
project: `${options.fullPath}/tsconfig.app.json`,
|
||||
exclude: '**/node_modules/**'
|
||||
},
|
||||
{
|
||||
project: `apps/${options.fullName}/e2e/tsconfig.e2e.json`,
|
||||
exclude: '**/node_modules/**'
|
||||
}
|
||||
];
|
||||
|
||||
return angularCliJson;
|
||||
});
|
||||
}
|
||||
|
||||
function addRouterRootConfiguration(path: string): Rule {
|
||||
return (host: Tree) => {
|
||||
const modulePath = `${path}/app/app.module.ts`;
|
||||
const moduleSource = host.read(modulePath)!.toString('utf-8');
|
||||
const sourceFile = ts.createSourceFile(
|
||||
modulePath,
|
||||
moduleSource,
|
||||
ts.ScriptTarget.Latest,
|
||||
true
|
||||
);
|
||||
insert(host, modulePath, [
|
||||
insertImport(sourceFile, modulePath, 'RouterModule', '@angular/router'),
|
||||
...addImportToModule(
|
||||
sourceFile,
|
||||
modulePath,
|
||||
`RouterModule.forRoot([], {initialNavigation: 'enabled'})`
|
||||
)
|
||||
]);
|
||||
|
||||
const componentSpecPath = `${path}/app/app.component.spec.ts`;
|
||||
const componentSpecSource = host.read(componentSpecPath)!.toString('utf-8');
|
||||
const componentSpecSourceFile = ts.createSourceFile(
|
||||
componentSpecPath,
|
||||
componentSpecSource,
|
||||
ts.ScriptTarget.Latest,
|
||||
true
|
||||
);
|
||||
insert(host, componentSpecPath, [
|
||||
insertImport(
|
||||
componentSpecSourceFile,
|
||||
componentSpecPath,
|
||||
'RouterTestingModule',
|
||||
'@angular/router/testing'
|
||||
),
|
||||
...addImportToTestBed(
|
||||
componentSpecSourceFile,
|
||||
componentSpecPath,
|
||||
`RouterTestingModule`
|
||||
)
|
||||
]);
|
||||
return host;
|
||||
};
|
||||
}
|
||||
|
||||
const staticComponentContent = `
|
||||
<div style="text-align:center">
|
||||
<h1>
|
||||
Welcome to an Angular CLI app built with Nrwl Nx!
|
||||
</h1>
|
||||
<img width="450" src="assets/nx-logo.png">
|
||||
</div>
|
||||
|
||||
<h2>Nx</h2>
|
||||
|
||||
An open source toolkit for enterprise Angular applications.
|
||||
|
||||
Nx is designed to help you create and build enterprise grade Angular applications. It provides an opinionated approach to application project structure and patterns.
|
||||
|
||||
<h2>Quick Start & Documentation</h2>
|
||||
|
||||
<a href="https://nrwl.io/nx">Watch a 5-minute video on how to get started with Nx.</a>`;
|
||||
|
||||
function updateComponentTemplate(options: NormalizedSchema): Rule {
|
||||
return (host: Tree) => {
|
||||
const content = options.routing
|
||||
? `${staticComponentContent}\n<router-outlet></router-outlet>`
|
||||
: staticComponentContent;
|
||||
host.overwrite(`${options.fullPath}/app/app.component.html`, content);
|
||||
};
|
||||
}
|
||||
|
||||
function addBazelBuildFile(path: string): Rule {
|
||||
return (host: Tree) => {
|
||||
const ngModule = `package(default_visibility = ["//visibility:public"])
|
||||
|
||||
load("@angular//:index.bzl", "ng_module")
|
||||
load("@build_bazel_rules_typescript//:defs.bzl", "ts_library", "ts_web_test")
|
||||
|
||||
ng_module(
|
||||
name = "app",
|
||||
srcs = glob(
|
||||
["*.ts"],
|
||||
exclude = ["*.spec.ts"],
|
||||
),
|
||||
assets = [
|
||||
"app.component.css",
|
||||
"app.component.html",
|
||||
],
|
||||
deps = [
|
||||
"@rxjs",
|
||||
],
|
||||
)
|
||||
|
||||
ts_library(
|
||||
name = "test_lib",
|
||||
testonly = 1,
|
||||
srcs = glob(["*.spec.ts"]),
|
||||
deps = [
|
||||
":app",
|
||||
],
|
||||
)
|
||||
|
||||
ts_web_test(
|
||||
name = "test",
|
||||
bootstrap = ["//:angular_bootstrap_scripts"],
|
||||
deps = [
|
||||
":test_lib",
|
||||
"//:angular_bundles",
|
||||
"//:angular_test_bundles",
|
||||
],
|
||||
)
|
||||
`;
|
||||
|
||||
host.create(`${path}/app/BUILD.bazel`, ngModule);
|
||||
};
|
||||
}
|
||||
|
||||
export default function(schema: Schema): Rule {
|
||||
let npmScope = schema.npmScope;
|
||||
if (!npmScope) {
|
||||
npmScope = readCliConfigFile().project.npmScope;
|
||||
}
|
||||
|
||||
const options = normalizeOptions(schema);
|
||||
const templateSource = apply(url('./files'), [
|
||||
template({
|
||||
utils: strings,
|
||||
dot: '.',
|
||||
tmpl: '',
|
||||
offsetFromRoot: offsetFromRoot(options.fullPath),
|
||||
...(options as object),
|
||||
npmScope
|
||||
})
|
||||
]);
|
||||
|
||||
const selector = `${options.prefix}-root`;
|
||||
|
||||
return chain([
|
||||
branchAndMerge(chain([mergeWith(templateSource)])),
|
||||
externalSchematic('@schematics/angular', 'module', {
|
||||
name: 'app',
|
||||
commonModule: false,
|
||||
flat: true,
|
||||
routing: false,
|
||||
sourceDir: options.fullPath,
|
||||
spec: false
|
||||
}),
|
||||
externalSchematic('@schematics/angular', 'component', {
|
||||
name: 'app',
|
||||
selector: selector,
|
||||
sourceDir: options.fullPath,
|
||||
flat: true,
|
||||
inlineStyle: options.inlineStyle,
|
||||
inlineTemplate: options.inlineTemplate,
|
||||
spec: !options.skipTests,
|
||||
styleext: options.style,
|
||||
viewEncapsulation: options.viewEncapsulation,
|
||||
changeDetection: options.changeDetection
|
||||
}),
|
||||
updateComponentTemplate(options),
|
||||
addBootstrap(options.fullPath),
|
||||
addNxModule(options.fullPath),
|
||||
addAppToAngularCliJson(options),
|
||||
addBazelBuildFile(options.fullPath),
|
||||
addAppToAngularCliJson(options),
|
||||
options.routing ? addRouterRootConfiguration(options.fullPath) : noop(),
|
||||
formatFiles(options)
|
||||
]);
|
||||
}
|
||||
|
||||
function normalizeOptions(options: Schema): NormalizedSchema {
|
||||
const name = toFileName(options.name);
|
||||
const fullName = options.directory
|
||||
? `${toFileName(options.directory)}/${name}`
|
||||
: name;
|
||||
const fullPath = `apps/${fullName}/src`;
|
||||
const workspaceName = readCliConfigFile().project.name;
|
||||
return {
|
||||
...options,
|
||||
sourceDir: 'src',
|
||||
name,
|
||||
fullName,
|
||||
fullPath,
|
||||
workspaceName
|
||||
};
|
||||
}
|
||||
15
packages/bazel/src/collection/app/schema.d.ts
vendored
15
packages/bazel/src/collection/app/schema.d.ts
vendored
@ -1,15 +0,0 @@
|
||||
export interface Schema {
|
||||
name: string;
|
||||
skipFormat: boolean;
|
||||
npmScope?: string;
|
||||
directory?: string;
|
||||
sourceDir?: string;
|
||||
inlineStyle?: boolean;
|
||||
inlineTemplate?: boolean;
|
||||
viewEncapsulation?: 'Emulated' | 'Native' | 'None';
|
||||
changeDetection?: 'Default' | 'OnPush';
|
||||
routing?: boolean;
|
||||
skipTests?: boolean;
|
||||
prefix?: string;
|
||||
style?: string;
|
||||
}
|
||||
@ -1,70 +0,0 @@
|
||||
{
|
||||
"$schema": "http://json-schema.org/schema",
|
||||
"id": "application",
|
||||
"title": "Create an application",
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"name": {
|
||||
"type": "string",
|
||||
"description": "Application name"
|
||||
},
|
||||
"npmScope": {
|
||||
"type": "string",
|
||||
"description": "Calculated stuff"
|
||||
},
|
||||
"directory": {
|
||||
"type": "string",
|
||||
"description": "A directory where the app is placed"
|
||||
},
|
||||
"inlineStyle": {
|
||||
"description": "Specifies if the style will be in the ts file.",
|
||||
"type": "boolean",
|
||||
"default": false,
|
||||
"alias": "is"
|
||||
},
|
||||
"inlineTemplate": {
|
||||
"description": "Specifies if the template will be in the ts file.",
|
||||
"type": "boolean",
|
||||
"default": false,
|
||||
"alias": "it"
|
||||
},
|
||||
"viewEncapsulation": {
|
||||
"description": "Specifies the view encapsulation strategy.",
|
||||
"enum": ["Emulated", "Native", "None"],
|
||||
"type": "string"
|
||||
},
|
||||
"changeDetection": {
|
||||
"description": "Specifies the change detection strategy.",
|
||||
"enum": ["Default", "OnPush"],
|
||||
"type": "string",
|
||||
"default": "Default"
|
||||
},
|
||||
"routing": {
|
||||
"type": "boolean",
|
||||
"default": false
|
||||
},
|
||||
"skipFormat": {
|
||||
"description": "Skip formatting files",
|
||||
"type": "boolean",
|
||||
"default": false
|
||||
},
|
||||
"skipTests": {
|
||||
"description": "Skip creating spec files.",
|
||||
"type": "boolean",
|
||||
"default": false,
|
||||
"alias": "st"
|
||||
},
|
||||
"prefix": {
|
||||
"type": "string",
|
||||
"description": "The prefix to apply to generated selectors.",
|
||||
"default": "app",
|
||||
"alias": "p"
|
||||
},
|
||||
"style": {
|
||||
"description": "The file extension to be used for style files.",
|
||||
"type": "string",
|
||||
"default": "css"
|
||||
}
|
||||
},
|
||||
"required": ["name"]
|
||||
}
|
||||
@ -1,61 +0,0 @@
|
||||
import { SchematicTestRunner } from '@angular-devkit/schematics/testing';
|
||||
import * as path from 'path';
|
||||
import { Tree, VirtualTree } from '@angular-devkit/schematics';
|
||||
|
||||
import { readJsonInTree } from '../../utils/ast-utils';
|
||||
|
||||
describe('application', () => {
|
||||
const schematicRunner = new SchematicTestRunner(
|
||||
'@nrwl/bazel',
|
||||
path.join(__dirname, '../../collection.json')
|
||||
);
|
||||
|
||||
let appTree: Tree;
|
||||
|
||||
beforeEach(() => {
|
||||
appTree = new VirtualTree();
|
||||
});
|
||||
|
||||
it('should generate files', () => {
|
||||
const tree = schematicRunner.runSchematic(
|
||||
'application',
|
||||
{ name: 'myApp', directory: 'my-app' },
|
||||
appTree
|
||||
);
|
||||
expect(tree.files).toEqual([
|
||||
'/my-app/BUILD.bazel',
|
||||
'/my-app/README.md',
|
||||
'/my-app/WORKSPACE',
|
||||
'/my-app/.angular-cli.json',
|
||||
'/my-app/.editorconfig',
|
||||
'/my-app/.gitignore',
|
||||
'/my-app/apps/.gitkeep',
|
||||
'/my-app/karma.conf.js',
|
||||
'/my-app/libs/.gitkeep',
|
||||
'/my-app/ngc.tsconfig.json',
|
||||
'/my-app/package.json',
|
||||
'/my-app/protractor.conf.js',
|
||||
'/my-app/test.js',
|
||||
'/my-app/tools/bazel.rc',
|
||||
'/my-app/tsconfig.json',
|
||||
'/my-app/tsconfig.spec.json',
|
||||
'/my-app/tslint.json'
|
||||
]);
|
||||
});
|
||||
|
||||
it('should update package.json', () => {
|
||||
const tree = schematicRunner.runSchematic(
|
||||
'application',
|
||||
{ name: 'myApp', directory: 'my-app' },
|
||||
appTree
|
||||
);
|
||||
const packageJson = readJsonInTree(tree, '/my-app/package.json');
|
||||
|
||||
expect(packageJson.devDependencies['@nrwl/schematics']).toBeDefined();
|
||||
expect(packageJson.dependencies['@nrwl/nx']).toBeDefined();
|
||||
expect(packageJson.dependencies['@ngrx/store']).toBeDefined();
|
||||
expect(packageJson.dependencies['@ngrx/effects']).toBeDefined();
|
||||
expect(packageJson.dependencies['@ngrx/router-store']).toBeDefined();
|
||||
expect(packageJson.dependencies['@ngrx/store-devtools']).toBeDefined();
|
||||
});
|
||||
});
|
||||
@ -1,81 +0,0 @@
|
||||
package(default_visibility = ["//visibility:public"])
|
||||
|
||||
exports_files(["tsconfig.json"])
|
||||
|
||||
# NOTE: this will move to node_modules/BUILD in a later release
|
||||
filegroup(
|
||||
name = "node_modules",
|
||||
# NB: rxjs is not in this list, because we build it from sources using the
|
||||
# label @rxjs//:rxjs
|
||||
srcs = glob(["/".join([
|
||||
"node_modules",
|
||||
pkg,
|
||||
"**",
|
||||
ext,
|
||||
]) for pkg in [
|
||||
"@angular",
|
||||
"@nrwl",
|
||||
"@ngrx",
|
||||
"tsickle",
|
||||
"tsutils",
|
||||
"typescript",
|
||||
"@types",
|
||||
] for ext in [
|
||||
"*.js",
|
||||
"*.json",
|
||||
"*.d.ts",
|
||||
]] + [
|
||||
"node_modules/http-server/**",
|
||||
]),
|
||||
)
|
||||
|
||||
ANGULAR_TESTING = [
|
||||
"node_modules/@angular/*/bundles/*-testing.umd.js",
|
||||
# We use AOT, so the compiler and the dynamic platform-browser should be
|
||||
# visible only in tests
|
||||
"node_modules/@angular/compiler/bundles/*.umd.js",
|
||||
"node_modules/@angular/platform-browser-dynamic/bundles/*.umd.js",
|
||||
]
|
||||
|
||||
# TODO: it's messy for users to need to specify the following
|
||||
# Angular dependency lists. It should live somewhere else.
|
||||
# See https://github.com/angular/angular/issues/21048
|
||||
|
||||
filegroup(
|
||||
name = "angular_bundles",
|
||||
srcs = glob(
|
||||
[
|
||||
"node_modules/@angular/*/bundles/*.umd.js",
|
||||
|
||||
"node_modules/@ngrx/store/bundles/store.umd.js",
|
||||
"node_modules/@ngrx/router-store/bundles/router-store.umd.js",
|
||||
"node_modules/@ngrx/effects/bundles/effects.umd.js",
|
||||
|
||||
"node_modules/@nrwl/nx/bundles/nrwl-nx.umd.js",
|
||||
],
|
||||
exclude = ANGULAR_TESTING + [
|
||||
"node_modules/@angular/bazel/**/*",
|
||||
"node_modules/@angular/cli/**/*",
|
||||
"node_modules/@angular/compiler-cli/**/*",
|
||||
"node_modules/@angular/language-service/**/*",
|
||||
],
|
||||
),
|
||||
)
|
||||
|
||||
filegroup(
|
||||
name = "angular_test_bundles",
|
||||
testonly = 1,
|
||||
srcs = glob(ANGULAR_TESTING),
|
||||
)
|
||||
|
||||
filegroup(
|
||||
name = "angular_bootstrap_scripts",
|
||||
# do not sort
|
||||
srcs = [
|
||||
"//:node_modules/zone.js/dist/zone.min.js",
|
||||
"//:node_modules/zone.js/dist/async-test.js",
|
||||
"//:node_modules/zone.js/dist/sync-test.js",
|
||||
"//:node_modules/zone.js/dist/proxy.min.js",
|
||||
"//:node_modules/zone.js/dist/jasmine-patch.js",
|
||||
],
|
||||
)
|
||||
@ -1,44 +0,0 @@
|
||||
# <%= utils.classify(name) %>
|
||||
|
||||
This project was generated with [Angular CLI](https://github.com/angular/angular-cli) using [Nrwl Nx](https://nrwl.io/nx).
|
||||
|
||||
## Nrwl Extensions for Angular (Nx)
|
||||
|
||||
<a href="https://nrwl.io/nx"><img src="https://preview.ibb.co/mW6sdw/nx_logo.png"></a>
|
||||
|
||||
Nx is an open source toolkit for enterprise Angular applications.
|
||||
|
||||
Nx is designed to help you create and build enterprise grade Angular applications. It provides an opinionated approach to application project structure and patterns.
|
||||
|
||||
## Quick Start & Documentation
|
||||
|
||||
[Watch a 5-minute video on how to get started with Nx.](http://nrwl.io/nx)
|
||||
|
||||
## Generate your first application
|
||||
|
||||
Run `ng generate app myapp` to generate an application. When using Nx, you can create multiple applications and libraries in the same CLI workspace. Read more [here](http://nrwl.io/nx).
|
||||
|
||||
## Development server
|
||||
|
||||
Run `ng serve --app=myapp` for a dev server. Navigate to `http://localhost:4200/`. The app will automatically reload if you change any of the source files.
|
||||
|
||||
## Code scaffolding
|
||||
|
||||
Run `ng generate component component-name --app=myapp` to generate a new component. You can also use `ng generate directive|pipe|service|class|guard|interface|enum|module`.
|
||||
|
||||
## Build
|
||||
|
||||
Run `ng build --app=myapp` to build the project. The build artifacts will be stored in the `dist/` directory. Use the `-prod` flag for a production build.
|
||||
|
||||
## Running unit tests
|
||||
|
||||
Run `ng test` to execute the unit tests via [Karma](https://karma-runner.github.io).
|
||||
|
||||
## Running end-to-end tests
|
||||
|
||||
Run `ng e2e` to execute the end-to-end tests via [Protractor](http://www.protractortest.org/).
|
||||
Before running the tests make sure you are serving the app via `ng serve`.
|
||||
|
||||
## Further help
|
||||
|
||||
To get more help on the Angular CLI use `ng help` or go check out the [Angular CLI README](https://github.com/angular/angular-cli/blob/master/README.md).
|
||||
@ -1,74 +0,0 @@
|
||||
workspace(name = "<%= name %>")
|
||||
|
||||
####################################
|
||||
# The Bazel buildtools repo contains tools like the BUILD file formatter, buildifier
|
||||
http_archive(
|
||||
name = "com_github_bazelbuild_buildtools",
|
||||
sha256 = "4d8d6244320dd751590f9100cf39fd7a4b75cd901e1f3ffdfd6f048328883695",
|
||||
# Note, this commit matches the version of buildifier in angular/ngcontainer
|
||||
url = "https://github.com/bazelbuild/buildtools/archive/b3b620e8bcff18ed3378cd3f35ebeb7016d71f71.zip",
|
||||
)
|
||||
|
||||
####################################
|
||||
# Fetch and install the NodeJS rules
|
||||
http_archive(
|
||||
name = "build_bazel_rules_nodejs",
|
||||
sha256 = "e9bc013417272b17f302dc169ad597f05561bb277451f010043f4da493417607",
|
||||
strip_prefix = "rules_nodejs-0.4.1",
|
||||
url = "https://github.com/bazelbuild/rules_nodejs/archive/0.4.1.zip",
|
||||
)
|
||||
|
||||
load("@build_bazel_rules_nodejs//:defs.bzl", "node_repositories")
|
||||
|
||||
node_repositories(package_json = ["//:package.json"])
|
||||
|
||||
####################################
|
||||
# Fetch and install the Sass rules
|
||||
git_repository(
|
||||
name = "io_bazel_rules_sass",
|
||||
remote = "https://github.com/bazelbuild/rules_sass.git",
|
||||
tag = "0.0.3",
|
||||
)
|
||||
|
||||
load("@io_bazel_rules_sass//sass:sass.bzl", "sass_repositories")
|
||||
|
||||
sass_repositories()
|
||||
|
||||
####################################
|
||||
# Fetch and install the TypeScript rules
|
||||
http_archive(
|
||||
name = "build_bazel_rules_typescript",
|
||||
sha256 = "a2c81776a4a492ff9f878f9705639f5647bef345f7f3e1da09c9eeb8dec80485",
|
||||
strip_prefix = "rules_typescript-0.10.1",
|
||||
url = "https://github.com/bazelbuild/rules_typescript/archive/0.10.1.zip",
|
||||
)
|
||||
|
||||
load("@build_bazel_rules_typescript//:defs.bzl", "ts_setup_workspace")
|
||||
|
||||
ts_setup_workspace()
|
||||
|
||||
# Some of the TypeScript is written in Go.
|
||||
# Bazel doesn't support transitive WORKSPACE deps, so we must repeat them here.
|
||||
http_archive(
|
||||
name = "io_bazel_rules_go",
|
||||
sha256 = "4b14d8dd31c6dbaf3ff871adcd03f28c3274e42abc855cb8fb4d01233c0154dc",
|
||||
url = "https://github.com/bazelbuild/rules_go/releases/download/0.10.1/rules_go-0.10.1.tar.gz",
|
||||
)
|
||||
|
||||
load("@io_bazel_rules_go//go:def.bzl", "go_rules_dependencies", "go_register_toolchains")
|
||||
|
||||
go_rules_dependencies()
|
||||
|
||||
go_register_toolchains()
|
||||
|
||||
####################################
|
||||
# Tell Bazel about some workspaces that were installed from npm.
|
||||
local_repository(
|
||||
name = "angular",
|
||||
path = "node_modules/@angular/bazel",
|
||||
)
|
||||
|
||||
local_repository(
|
||||
name = "rxjs",
|
||||
path = "node_modules/rxjs/src",
|
||||
)
|
||||
@ -1,64 +0,0 @@
|
||||
{
|
||||
"$schema": "<%= angularCliSchema %>",
|
||||
"project": {
|
||||
"name": "<%= utils.dasherize(name) %>",
|
||||
"npmScope": "<%= npmScope %>",
|
||||
"latestMigration": "<%= latestMigration %>"
|
||||
},
|
||||
"e2e": {
|
||||
"protractor": {
|
||||
"config": "./protractor.conf.js"
|
||||
}
|
||||
},
|
||||
"lint": [
|
||||
{
|
||||
"project": "./tsconfig.spec.json",
|
||||
"exclude": "**/node_modules/**"
|
||||
}
|
||||
],
|
||||
"test": {
|
||||
"karma": {
|
||||
"config": "./karma.conf.js"
|
||||
}
|
||||
},
|
||||
"apps": [
|
||||
{
|
||||
"name": "$workspaceRoot",
|
||||
"root": ".",
|
||||
"appRoot": ""
|
||||
}
|
||||
],
|
||||
"defaults": {
|
||||
"schematics": {
|
||||
"collection": "@nrwl/bazel"
|
||||
},
|
||||
"styleExt": "<%= style %>",<% if (!minimal) { %>
|
||||
"component": {}<% } else { %>
|
||||
"component": {
|
||||
"spec": false,
|
||||
"inlineStyle": true,
|
||||
"inlineTemplate": true
|
||||
},
|
||||
"directive": {
|
||||
"spec": false
|
||||
},
|
||||
"class": {
|
||||
"spec": false
|
||||
},
|
||||
"guard": {
|
||||
"spec": false
|
||||
},
|
||||
"module": {
|
||||
"spec": false
|
||||
},
|
||||
"pipe": {
|
||||
"spec": false
|
||||
},
|
||||
"service": {
|
||||
"spec": false
|
||||
} <% } %>
|
||||
},
|
||||
"warnings": {
|
||||
"typescriptMismatch": false
|
||||
}
|
||||
}
|
||||
@ -1,13 +0,0 @@
|
||||
# Editor configuration, see http://editorconfig.org
|
||||
root = true
|
||||
|
||||
[*]
|
||||
charset = utf-8
|
||||
indent_style = space
|
||||
indent_size = 2
|
||||
insert_final_newline = true
|
||||
trim_trailing_whitespace = true
|
||||
|
||||
[*.md]
|
||||
max_line_length = off
|
||||
trim_trailing_whitespace = false
|
||||
@ -1,42 +0,0 @@
|
||||
# See http://help.github.com/ignore-files/ for more about ignoring files.
|
||||
|
||||
# compiled output
|
||||
/dist
|
||||
/tmp
|
||||
/out-tsc
|
||||
|
||||
# dependencies
|
||||
/node_modules
|
||||
|
||||
# IDEs and editors
|
||||
/.idea
|
||||
.project
|
||||
.classpath
|
||||
.c9/
|
||||
*.launch
|
||||
.settings/
|
||||
*.sublime-workspace
|
||||
|
||||
# IDE - VSCode
|
||||
.vscode/*
|
||||
!.vscode/settings.json
|
||||
!.vscode/tasks.json
|
||||
!.vscode/launch.json
|
||||
!.vscode/extensions.json
|
||||
|
||||
# misc
|
||||
/.sass-cache
|
||||
/connect.lock
|
||||
/coverage
|
||||
/libpeerconnection.log
|
||||
npm-debug.log
|
||||
testem.log
|
||||
/typings
|
||||
|
||||
# e2e
|
||||
/e2e/*.js
|
||||
/e2e/*.map
|
||||
|
||||
# System Files
|
||||
.DS_Store
|
||||
Thumbs.db
|
||||
@ -1 +0,0 @@
|
||||
|
||||
@ -1,37 +0,0 @@
|
||||
// Karma configuration file, see link for more information
|
||||
// https://karma-runner.github.io/1.0/config/configuration-file.html
|
||||
|
||||
const { makeSureNoAppIsSelected } = require('@nrwl/schematics/src/utils/cli-config-utils');
|
||||
// Nx only supports running unit tests for all apps and libs.
|
||||
makeSureNoAppIsSelected();
|
||||
|
||||
module.exports = function (config) {
|
||||
config.set({
|
||||
basePath: '',
|
||||
frameworks: ['jasmine', '@angular/cli'],
|
||||
plugins: [
|
||||
require('karma-jasmine'),
|
||||
require('karma-chrome-launcher'),
|
||||
require('karma-jasmine-html-reporter'),
|
||||
require('karma-coverage-istanbul-reporter'),
|
||||
require('@angular/cli/plugins/karma')
|
||||
],
|
||||
client:{
|
||||
clearContext: false // leave Jasmine Spec Runner output visible in browser
|
||||
},
|
||||
coverageIstanbulReporter: {
|
||||
reports: [ 'html', 'lcovonly' ],
|
||||
fixWebpackSourcePaths: true
|
||||
},
|
||||
angularCli: {
|
||||
environment: 'dev'
|
||||
},
|
||||
reporters: ['progress', 'kjhtml'],
|
||||
port: 9876,
|
||||
colors: true,
|
||||
logLevel: config.LOG_INFO,
|
||||
autoWatch: true,
|
||||
browsers: ['Chrome'],
|
||||
singleRun: false
|
||||
});
|
||||
};
|
||||
@ -1,27 +0,0 @@
|
||||
// WORKAROUND https://github.com/angular/angular/issues/18810
|
||||
// This file is required to run ngc on angular libraries, to write files like
|
||||
// node_modules/@angular/core/core.ngsummary.json
|
||||
{
|
||||
"compilerOptions": {
|
||||
"lib": [
|
||||
"dom",
|
||||
"es2015"
|
||||
],
|
||||
"experimentalDecorators": true,
|
||||
"types": []
|
||||
},
|
||||
"include": [
|
||||
"node_modules/@angular/**/*",
|
||||
"node_modules/@nrwl/**/*",
|
||||
"node_modules/@ngrx/**/*",
|
||||
],
|
||||
"exclude": [
|
||||
"node_modules/@angular/bazel/**",
|
||||
"node_modules/@angular/router/**",
|
||||
"node_modules/@angular/cli/**",
|
||||
"node_modules/@angular/compiler-cli/**",
|
||||
"node_modules/@angular/tsc-wrapped/**",
|
||||
"node_modules/@nrwl/bazel/**",
|
||||
"node_modules/@nrwl/schematics/**",
|
||||
]
|
||||
}
|
||||
@ -1,72 +0,0 @@
|
||||
{
|
||||
"name": "<%= utils.dasherize(name) %>",
|
||||
"version": "0.0.0",
|
||||
"license": "MIT",
|
||||
"scripts": {
|
||||
"ng": "ng",
|
||||
"start": "ng serve",
|
||||
"build": "ng build",
|
||||
"test": "ng test",
|
||||
"lint": "ng lint",
|
||||
"e2e": "ng e2e",
|
||||
"affected:apps": "./node_modules/.bin/nx affected:apps",
|
||||
"affected:build": "./node_modules/.bin/nx affected:build",
|
||||
"affected:e2e": "./node_modules/.bin/nx affected:e2e",
|
||||
"affected:dep-graph": "./node_modules/.bin/nx affected:dep-graph",
|
||||
"format": "./node_modules/.bin/nx format:write",
|
||||
"format:write": "./node_modules/.bin/nx format:write",
|
||||
"format:check": "./node_modules/.bin/nx format:check",
|
||||
"update": "./node_modules/.bin/nx update",
|
||||
"update:check": "./node_modules/.bin/nx update:check",
|
||||
"update:skip": "./node_modules/.bin/nx update:skip",
|
||||
"dep-graph": "./node_modules/.bin/nx dep-graph",
|
||||
"postinstall": "ngc -p ngc.tsconfig.json"
|
||||
},
|
||||
"private": true,
|
||||
"dependencies": {
|
||||
"@angular/animations": "<%= angularVersion %>",
|
||||
"@angular/bazel": "angular/bazel-builds#d09df98b39658463fdfe3567b25a20cdd7130661",
|
||||
"@angular/common": "<%= angularVersion %>",
|
||||
"@angular/compiler": "<%= angularVersion %>",
|
||||
"@angular/core": "<%= angularVersion %>",
|
||||
"@angular/forms": "<%= angularVersion %>",
|
||||
"@angular/platform-browser": "<%= angularVersion %>",
|
||||
"@angular/platform-browser-dynamic": "<%= angularVersion %>",
|
||||
"@angular/router": "<%= angularVersion %>",
|
||||
"concurrently": "3.5.1",
|
||||
"core-js": "^2.4.1",
|
||||
"rxjs": "<%= rxjsVersion %>",
|
||||
"zone.js": "^0.8.19",
|
||||
"@nrwl/nx": "<%= nxVersion %>",
|
||||
"@ngrx/effects": "<%= ngrxVersion %>",
|
||||
"@ngrx/router-store": "<%= ngrxVersion %>",
|
||||
"@ngrx/store": "<%= ngrxVersion %>",
|
||||
"@ngrx/store-devtools": "<%= ngrxVersion %>"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@angular/cli": "<%= angularCliVersion %>",
|
||||
"@angular/compiler-cli": "<%= angularVersion %>",
|
||||
"@nrwl/schematics": "<%= schematicsVersion %>",
|
||||
"@nrwl/bazel": "<%= schematicsVersion %>",
|
||||
"@angular/language-service": "<%= angularVersion %>",
|
||||
"@bazel/ibazel": "^0.3.1",<% if (!minimal) { %>
|
||||
"@types/jasmine": "~2.8.3",
|
||||
"@types/jasminewd2": "~2.0.2",
|
||||
"@types/node": "~6.0.60",
|
||||
"codelyzer": "^4.0.1",
|
||||
"jasmine-core": "~2.8.0",
|
||||
"jasmine-spec-reporter": "~4.2.1",
|
||||
"karma": "~2.0.0",
|
||||
"karma-chrome-launcher": "~2.2.0",
|
||||
"karma-coverage-istanbul-reporter": "^1.2.1",
|
||||
"karma-jasmine": "~1.1.0",
|
||||
"karma-jasmine-html-reporter": "^0.2.2",
|
||||
"protractor": "~5.1.2",
|
||||
"ts-node": "~4.1.0",
|
||||
"tslint": "~5.9.1",<%
|
||||
} %>
|
||||
"typescript": "<%= typescriptVersion %>",
|
||||
"prettier": "<%= prettierVersion %>",
|
||||
"http-server": "0.11.1"
|
||||
}
|
||||
}
|
||||
@ -1,30 +0,0 @@
|
||||
// Protractor configuration file, see link for more information
|
||||
// https://github.com/angular/protractor/blob/master/lib/config.ts
|
||||
|
||||
const { SpecReporter } = require('jasmine-spec-reporter');
|
||||
const { getAppDirectoryUsingCliConfig } = require('@nrwl/schematics/src/utils/cli-config-utils');
|
||||
const appDir = getAppDirectoryUsingCliConfig();
|
||||
|
||||
exports.config = {
|
||||
allScriptsTimeout: 11000,
|
||||
specs: [
|
||||
appDir + '/e2e/**/*.e2e-spec.ts'
|
||||
],
|
||||
capabilities: {
|
||||
'browserName': 'chrome'
|
||||
},
|
||||
directConnect: true,
|
||||
baseUrl: 'http://localhost:8080/',
|
||||
framework: 'jasmine',
|
||||
jasmineNodeOpts: {
|
||||
showColors: true,
|
||||
defaultTimeoutInterval: 30000,
|
||||
print: function() {}
|
||||
},
|
||||
onPrepare() {
|
||||
require('ts-node').register({
|
||||
project: appDir + '/e2e/tsconfig.e2e.json'
|
||||
});
|
||||
jasmine.getEnv().addReporter(new SpecReporter({ spec: { displayStacktrace: true } }));
|
||||
}
|
||||
};
|
||||
@ -1,25 +0,0 @@
|
||||
// This file is required by karma.conf.js and loads recursively all the .spec and framework files
|
||||
require('zone.js/dist/zone-testing');
|
||||
const getTestBed = require('@angular/core/testing').getTestBed;
|
||||
const BrowserDynamicTestingModule = require('@angular/platform-browser-dynamic/testing').BrowserDynamicTestingModule;
|
||||
const platformBrowserDynamicTesting = require('@angular/platform-browser-dynamic/testing').platformBrowserDynamicTesting;
|
||||
|
||||
// Prevent Karma from running prematurely.
|
||||
__karma__.loaded = function () {};
|
||||
|
||||
// First, initialize the Angular testing environment.
|
||||
getTestBed().initTestEnvironment(
|
||||
BrowserDynamicTestingModule,
|
||||
platformBrowserDynamicTesting()
|
||||
);
|
||||
// Then we find all the tests.
|
||||
const contextApps = require.context('./apps', true, /\.spec\.ts$/);
|
||||
// And load the modules.
|
||||
contextApps.keys().map(contextApps);
|
||||
|
||||
const contextLibs = require.context('./libs', true, /\.spec\.ts$/);
|
||||
// And load the modules.
|
||||
contextLibs.keys().map(contextLibs);
|
||||
|
||||
// Finally, start Karma to run the tests.
|
||||
__karma__.start();
|
||||
@ -1,19 +0,0 @@
|
||||
# Make TypeScript compilation fast, by keeping a few copies of the compiler
|
||||
# running as daemons, and cache SourceFile AST's to reduce parse time.
|
||||
build --strategy=TypeScriptCompile=worker
|
||||
|
||||
# Don't create bazel-* symlinks in the WORKSPACE directory.
|
||||
# These require .gitignore and may scare users.
|
||||
# Also, it's a workaround for https://github.com/bazelbuild/rules_typescript/issues/12
|
||||
# which affects the common case of having `tsconfig.json` in the WORKSPACE directory.
|
||||
#
|
||||
# Instead, you should run `bazel info bazel-bin` to find out where the outputs went.
|
||||
build --symlink_prefix=dist/
|
||||
|
||||
test --test_output=errors
|
||||
|
||||
# Workaround https://github.com/bazelbuild/bazel/issues/3645
|
||||
# Limit Bazel to consuming 3072K of RAM
|
||||
build:ci --local_resources=3072,2.0,1.0
|
||||
|
||||
build:ci --noshow_progress
|
||||
@ -1,15 +0,0 @@
|
||||
{
|
||||
"compileOnSave": false,
|
||||
"compilerOptions": {
|
||||
"sourceMap": true,
|
||||
"declaration": false,
|
||||
"moduleResolution": "node",
|
||||
"emitDecoratorMetadata": true,
|
||||
"experimentalDecorators": true,
|
||||
"target": "es5",
|
||||
"lib": [
|
||||
"es2017",
|
||||
"dom"
|
||||
],
|
||||
}
|
||||
}
|
||||
@ -1,22 +0,0 @@
|
||||
{
|
||||
"extends": "./tsconfig.json",
|
||||
"compilerOptions": {
|
||||
"outDir": "./dist/out-tsc/spec",
|
||||
"module": "commonjs",
|
||||
"target": "es5",
|
||||
"types": [
|
||||
"jasmine",
|
||||
"node"
|
||||
]
|
||||
},
|
||||
"include": [
|
||||
"**/*.ts"
|
||||
],
|
||||
"exclude": [
|
||||
"**/e2e/*.ts",
|
||||
"**/*.e2e-spec.ts",
|
||||
"**/*.po.ts",
|
||||
"node_modules",
|
||||
"tmp"
|
||||
]
|
||||
}
|
||||
@ -1,102 +0,0 @@
|
||||
{
|
||||
"rulesDirectory": [
|
||||
"node_modules/codelyzer",
|
||||
"node_modules/@nrwl/schematics/src/tslint"
|
||||
],
|
||||
"rules": {
|
||||
"arrow-return-shorthand": true,
|
||||
"callable-types": true,
|
||||
"class-name": true,
|
||||
"forin": true,
|
||||
"deprecation": {
|
||||
"severity": "warn"
|
||||
},
|
||||
"import-blacklist": [
|
||||
true,
|
||||
"rxjs",
|
||||
"rxjs/Rx"
|
||||
],
|
||||
"interface-over-type-literal": true,
|
||||
"member-access": false,
|
||||
"member-ordering": [
|
||||
true,
|
||||
{
|
||||
"order": [
|
||||
"static-field",
|
||||
"instance-field",
|
||||
"static-method",
|
||||
"instance-method"
|
||||
]
|
||||
}
|
||||
],
|
||||
"no-arg": true,
|
||||
"no-bitwise": true,
|
||||
"no-console": [
|
||||
true,
|
||||
"debug",
|
||||
"info",
|
||||
"time",
|
||||
"timeEnd",
|
||||
"trace"
|
||||
],
|
||||
"no-construct": true,
|
||||
"no-debugger": true,
|
||||
"no-duplicate-super": true,
|
||||
"no-empty": false,
|
||||
"no-empty-interface": true,
|
||||
"no-eval": true,
|
||||
"no-inferrable-types": [
|
||||
true,
|
||||
"ignore-params"
|
||||
],
|
||||
"no-misused-new": true,
|
||||
"no-non-null-assertion": true,
|
||||
"no-shadowed-variable": true,
|
||||
"no-string-literal": false,
|
||||
"no-string-throw": true,
|
||||
"no-switch-case-fall-through": true,
|
||||
"no-unnecessary-initializer": true,
|
||||
"no-unused-expression": true,
|
||||
"no-use-before-declare": true,
|
||||
"no-var-keyword": true,
|
||||
"object-literal-sort-keys": false,
|
||||
"prefer-const": true,
|
||||
"radix": true,
|
||||
"triple-equals": [
|
||||
true,
|
||||
"allow-null-check"
|
||||
],
|
||||
"unified-signatures": true,
|
||||
"variable-name": false,
|
||||
"directive-selector": [
|
||||
true,
|
||||
"attribute",
|
||||
"app",
|
||||
"camelCase"
|
||||
],
|
||||
"component-selector": [
|
||||
true,
|
||||
"element",
|
||||
"app",
|
||||
"kebab-case"
|
||||
],
|
||||
"no-output-on-prefix": true,
|
||||
"use-input-property-decorator": true,
|
||||
"use-output-property-decorator": true,
|
||||
"use-host-property-decorator": true,
|
||||
"no-input-rename": true,
|
||||
"no-output-rename": true,
|
||||
"use-life-cycle-interface": true,
|
||||
"use-pipe-transform-interface": true,
|
||||
"component-class-suffix": true,
|
||||
"directive-class-suffix": true,
|
||||
|
||||
"nx-enforce-module-boundaries": [
|
||||
true,
|
||||
{
|
||||
"lazyLoad": [],
|
||||
"allow": []
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
@ -1,60 +0,0 @@
|
||||
import {
|
||||
apply,
|
||||
branchAndMerge,
|
||||
chain,
|
||||
mergeWith,
|
||||
Rule,
|
||||
SchematicContext,
|
||||
template,
|
||||
Tree,
|
||||
url
|
||||
} from '@angular-devkit/schematics';
|
||||
import { Schema } from './schema';
|
||||
import { strings } from '@angular-devkit/core';
|
||||
import {
|
||||
NodePackageInstallTask,
|
||||
RepositoryInitializerTask
|
||||
} from '@angular-devkit/schematics/tasks';
|
||||
import { libVersions } from '../../lib-versions';
|
||||
|
||||
export default function(options: Schema): Rule {
|
||||
if (!/^\w+$/.test(options.name)) {
|
||||
throw new Error(
|
||||
`${options.name} is invalid for a bazel workspace.\n` +
|
||||
'Your workspace name must contain only alphanumeric characters and underscores.'
|
||||
);
|
||||
}
|
||||
|
||||
return (host: Tree, context: SchematicContext) => {
|
||||
addTasks(options, context);
|
||||
const npmScope = options.npmScope ? options.npmScope : options.name;
|
||||
const templateSource = apply(url('./files'), [
|
||||
template({
|
||||
utils: strings,
|
||||
dot: '.',
|
||||
...libVersions,
|
||||
...(options as object),
|
||||
npmScope
|
||||
})
|
||||
]);
|
||||
return chain([branchAndMerge(chain([mergeWith(templateSource)]))])(
|
||||
host,
|
||||
context
|
||||
);
|
||||
};
|
||||
}
|
||||
|
||||
function addTasks(options: Schema, context: SchematicContext) {
|
||||
let packageTask;
|
||||
if (!options.skipInstall) {
|
||||
packageTask = context.addTask(
|
||||
new NodePackageInstallTask(options.directory)
|
||||
);
|
||||
}
|
||||
if (!options.skipGit) {
|
||||
context.addTask(
|
||||
new RepositoryInitializerTask(options.directory, options.commit),
|
||||
packageTask ? [packageTask] : []
|
||||
);
|
||||
}
|
||||
}
|
||||
@ -1,11 +0,0 @@
|
||||
export interface Schema {
|
||||
name: string;
|
||||
directory: string;
|
||||
npmScope?: string;
|
||||
prefix?: string;
|
||||
style?: string;
|
||||
minimal?: boolean;
|
||||
skipInstall?: boolean;
|
||||
commit?: { name: string; email: string; message?: string };
|
||||
skipGit?: boolean;
|
||||
}
|
||||
@ -1,72 +0,0 @@
|
||||
{
|
||||
"$schema": "http://json-schema.org/schema",
|
||||
"id": "workspace",
|
||||
"title": "Create an empty workspace",
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"name": {
|
||||
"type": "string",
|
||||
"description": "Workspace name"
|
||||
},
|
||||
"directory": {
|
||||
"type": "string",
|
||||
"description": "The directory name to create the app in.",
|
||||
"alias": "dir"
|
||||
},
|
||||
"npmScope": {
|
||||
"type": "string",
|
||||
"description": "Npm scope for importing libs."
|
||||
},
|
||||
"skipInstall": {
|
||||
"description": "Skip installing dependency packages.",
|
||||
"type": "boolean",
|
||||
"default": false
|
||||
},
|
||||
"skipGit": {
|
||||
"description": "Skip initializing a git repository.",
|
||||
"type": "boolean",
|
||||
"default": false,
|
||||
"alias": "sg"
|
||||
},
|
||||
"commit": {
|
||||
"description": "Initial repository commit information.",
|
||||
"default": null,
|
||||
"oneOf": [
|
||||
{ "type": "null" },
|
||||
{
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"name": {
|
||||
"type": "string"
|
||||
},
|
||||
"email": {
|
||||
"type": "string",
|
||||
"format": "email"
|
||||
},
|
||||
"message": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"required": ["name", "email"]
|
||||
}
|
||||
]
|
||||
},
|
||||
"prefix": {
|
||||
"type": "string",
|
||||
"description": "The prefix to apply to generated selectors.",
|
||||
"default": "app",
|
||||
"alias": "p"
|
||||
},
|
||||
"style": {
|
||||
"description": "The file extension to be used for style files.",
|
||||
"type": "string",
|
||||
"default": "css"
|
||||
},
|
||||
"minimal": {
|
||||
"description": "Should create a minimal app.",
|
||||
"type": "boolean",
|
||||
"default": false
|
||||
}
|
||||
},
|
||||
"required": ["name", "directory"]
|
||||
}
|
||||
@ -1,35 +0,0 @@
|
||||
# TODO: Make this private when we can import from the root index.ts
|
||||
package(default_visibility = ["//visibility:public"])
|
||||
|
||||
load("@angular//:index.bzl", "ng_module")
|
||||
load("@build_bazel_rules_typescript//:defs.bzl", "ts_library", "ts_web_test")
|
||||
|
||||
ng_module(
|
||||
name = "<%= sourceDir %>",
|
||||
srcs = glob(
|
||||
["*.ts"],
|
||||
exclude = ["*.spec.ts"],
|
||||
),
|
||||
deps = [
|
||||
"@rxjs",
|
||||
],
|
||||
)
|
||||
|
||||
ts_library(
|
||||
name = "test_lib",
|
||||
testonly = 1,
|
||||
srcs = glob(["*.spec.ts"]),
|
||||
deps = [
|
||||
":<%= sourceDir %>",
|
||||
],
|
||||
)
|
||||
|
||||
ts_web_test(
|
||||
name = "test",
|
||||
bootstrap = ["//:angular_bootstrap_scripts"],
|
||||
deps = [
|
||||
":test_lib",
|
||||
"//:angular_bundles",
|
||||
"//:angular_test_bundles",
|
||||
],
|
||||
)
|
||||
@ -1,7 +0,0 @@
|
||||
import { <%= className %> } from './<%=fileName%>';
|
||||
|
||||
describe('<%= className %>', () => {
|
||||
it('should work', () => {
|
||||
expect(new <%= className %>()).toBeDefined();
|
||||
});
|
||||
});
|
||||
@ -1,2 +0,0 @@
|
||||
export class <%= className %> {
|
||||
}
|
||||
@ -1,289 +0,0 @@
|
||||
import {
|
||||
apply,
|
||||
branchAndMerge,
|
||||
chain,
|
||||
mergeWith,
|
||||
noop,
|
||||
Rule,
|
||||
template,
|
||||
Tree,
|
||||
url
|
||||
} from '@angular-devkit/schematics';
|
||||
import { insertImport } from '@schematics/angular/utility/ast-utils';
|
||||
import * as path from 'path';
|
||||
import * as ts from 'typescript';
|
||||
|
||||
import {
|
||||
addGlobal,
|
||||
addImportToModule,
|
||||
addIncludeToTsConfig,
|
||||
addReexport,
|
||||
addRoute,
|
||||
getAngularCliConfig,
|
||||
insert
|
||||
} from '../../utils/ast-utils';
|
||||
import { offsetFromRoot } from '../../utils/common';
|
||||
import {
|
||||
names,
|
||||
toClassName,
|
||||
toFileName,
|
||||
toPropertyName
|
||||
} from '../../utils/name-utils';
|
||||
import { Schema } from './schema';
|
||||
import { formatFiles } from '../../utils/rules/format-files';
|
||||
|
||||
interface NormalizedSchema extends Schema {
|
||||
name: string;
|
||||
fullName: string;
|
||||
fullPath: string;
|
||||
tags?: string;
|
||||
}
|
||||
|
||||
function normalizeOptions(options: Schema): NormalizedSchema {
|
||||
const name = toFileName(options.name);
|
||||
const fullName = options.directory
|
||||
? `${toFileName(options.directory)}/${name}`
|
||||
: name;
|
||||
const fullPath = `libs/${fullName}/src`;
|
||||
return { ...options, sourceDir: 'src', name, fullName, fullPath };
|
||||
}
|
||||
|
||||
function addLazyLoadedRouterConfiguration(modulePath: string): Rule {
|
||||
return (host: Tree) => {
|
||||
const moduleSource = host.read(modulePath)!.toString('utf-8');
|
||||
const sourceFile = ts.createSourceFile(
|
||||
modulePath,
|
||||
moduleSource,
|
||||
ts.ScriptTarget.Latest,
|
||||
true
|
||||
);
|
||||
insert(host, modulePath, [
|
||||
insertImport(sourceFile, modulePath, 'RouterModule', '@angular/router'),
|
||||
...addImportToModule(
|
||||
sourceFile,
|
||||
modulePath,
|
||||
`
|
||||
RouterModule.forChild([
|
||||
/* {path: '', pathMatch: 'full', component: InsertYourComponentHere} */
|
||||
]) `
|
||||
)
|
||||
]);
|
||||
return host;
|
||||
};
|
||||
}
|
||||
|
||||
function addRouterConfiguration(
|
||||
schema: NormalizedSchema,
|
||||
indexFilePath: string,
|
||||
moduleFileName: string,
|
||||
modulePath: string
|
||||
): Rule {
|
||||
return (host: Tree) => {
|
||||
const indexSource = host.read(indexFilePath)!.toString('utf-8');
|
||||
const indexSourceFile = ts.createSourceFile(
|
||||
indexFilePath,
|
||||
indexSource,
|
||||
ts.ScriptTarget.Latest,
|
||||
true
|
||||
);
|
||||
const moduleSource = host.read(modulePath)!.toString('utf-8');
|
||||
const moduleSourceFile = ts.createSourceFile(
|
||||
modulePath,
|
||||
moduleSource,
|
||||
ts.ScriptTarget.Latest,
|
||||
true
|
||||
);
|
||||
const constName = `${toPropertyName(schema.name)}Routes`;
|
||||
|
||||
insert(host, modulePath, [
|
||||
insertImport(
|
||||
moduleSourceFile,
|
||||
modulePath,
|
||||
'RouterModule, Route',
|
||||
'@angular/router'
|
||||
),
|
||||
...addImportToModule(moduleSourceFile, modulePath, `RouterModule`),
|
||||
...addGlobal(
|
||||
moduleSourceFile,
|
||||
modulePath,
|
||||
`export const ${constName}: Route[] = [];`
|
||||
)
|
||||
]);
|
||||
insert(host, indexFilePath, [
|
||||
...addReexport(indexSourceFile, indexFilePath, moduleFileName, constName)
|
||||
]);
|
||||
return host;
|
||||
};
|
||||
}
|
||||
|
||||
function addLoadChildren(schema: NormalizedSchema): Rule {
|
||||
return (host: Tree) => {
|
||||
const json = getAngularCliConfig(host);
|
||||
|
||||
const moduleSource = host.read(schema.parentModule)!.toString('utf-8');
|
||||
const sourceFile = ts.createSourceFile(
|
||||
schema.parentModule,
|
||||
moduleSource,
|
||||
ts.ScriptTarget.Latest,
|
||||
true
|
||||
);
|
||||
|
||||
const loadChildren = `@${json.project.npmScope}/${toFileName(
|
||||
schema.fullName
|
||||
)}#${toClassName(schema.name)}Module`;
|
||||
insert(host, schema.parentModule, [
|
||||
...addRoute(
|
||||
schema.parentModule,
|
||||
sourceFile,
|
||||
`{path: '${toFileName(schema.name)}', loadChildren: '${loadChildren}'}`
|
||||
)
|
||||
]);
|
||||
|
||||
const tsConfig = findClosestTsConfigApp(host, schema.parentModule);
|
||||
if (tsConfig) {
|
||||
const tsConfigAppSource = host.read(tsConfig)!.toString('utf-8');
|
||||
const tsConfigAppFile = ts.createSourceFile(
|
||||
tsConfig,
|
||||
tsConfigAppSource,
|
||||
ts.ScriptTarget.Latest,
|
||||
true
|
||||
);
|
||||
const offset = offsetFromRoot(path.dirname(tsConfig));
|
||||
insert(host, tsConfig, [
|
||||
...addIncludeToTsConfig(
|
||||
tsConfig,
|
||||
tsConfigAppFile,
|
||||
`\n , "${offset}libs/${schema.fullName}/index.ts"\n`
|
||||
)
|
||||
]);
|
||||
|
||||
const e2e = `${path.dirname(
|
||||
path.dirname(tsConfig)
|
||||
)}/e2e/tsconfig.e2e.json`;
|
||||
if (host.exists(e2e)) {
|
||||
const tsConfigE2ESource = host.read(e2e)!.toString('utf-8');
|
||||
const tsConfigE2EFile = ts.createSourceFile(
|
||||
e2e,
|
||||
tsConfigE2ESource,
|
||||
ts.ScriptTarget.Latest,
|
||||
true
|
||||
);
|
||||
insert(host, e2e, [
|
||||
...addIncludeToTsConfig(
|
||||
e2e,
|
||||
tsConfigE2EFile,
|
||||
`\n , "${offset}libs/${schema.fullName}/index.ts"\n`
|
||||
)
|
||||
]);
|
||||
}
|
||||
} else {
|
||||
// we should warn the user about not finding the config
|
||||
}
|
||||
|
||||
return host;
|
||||
};
|
||||
}
|
||||
|
||||
function findClosestTsConfigApp(
|
||||
host: Tree,
|
||||
parentModule: string
|
||||
): string | null {
|
||||
const dir = path.parse(parentModule).dir;
|
||||
if (host.exists(`${dir}/tsconfig.app.json`)) {
|
||||
return `${dir}/tsconfig.app.json`;
|
||||
} else if (dir != '') {
|
||||
return findClosestTsConfigApp(host, dir);
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
function addChildren(schema: NormalizedSchema): Rule {
|
||||
return (host: Tree) => {
|
||||
const json = getAngularCliConfig(host);
|
||||
|
||||
const moduleSource = host.read(schema.parentModule)!.toString('utf-8');
|
||||
const sourceFile = ts.createSourceFile(
|
||||
schema.parentModule,
|
||||
moduleSource,
|
||||
ts.ScriptTarget.Latest,
|
||||
true
|
||||
);
|
||||
const constName = `${toPropertyName(schema.name)}Routes`;
|
||||
const importPath = `@${json.project.npmScope}/${toFileName(
|
||||
schema.fullName
|
||||
)}`;
|
||||
|
||||
insert(host, schema.parentModule, [
|
||||
insertImport(sourceFile, schema.parentModule, constName, importPath),
|
||||
...addRoute(
|
||||
schema.parentModule,
|
||||
sourceFile,
|
||||
`{path: '${toFileName(schema.name)}', children: ${constName}}`
|
||||
)
|
||||
]);
|
||||
return host;
|
||||
};
|
||||
}
|
||||
|
||||
function validateLibSchema(schema) {
|
||||
const options = normalizeOptions(schema);
|
||||
const moduleFileName = `${toFileName(options.name)}.module`;
|
||||
const modulePath = `${options.fullPath}/${moduleFileName}.ts`;
|
||||
const indexFile = `libs/${toFileName(options.fullName)}/index.ts`;
|
||||
|
||||
if (options.routing && options.nomodule) {
|
||||
throw new Error(`nomodule and routing cannot be used together`);
|
||||
}
|
||||
|
||||
if (!options.routing && options.lazy) {
|
||||
throw new Error(`routing must be set`);
|
||||
}
|
||||
|
||||
const routingRules: Array<Rule> = [
|
||||
options.routing && options.lazy
|
||||
? addLazyLoadedRouterConfiguration(modulePath)
|
||||
: noop(),
|
||||
options.routing && options.lazy && options.parentModule
|
||||
? addLoadChildren(options)
|
||||
: noop(),
|
||||
|
||||
options.routing && !options.lazy
|
||||
? addRouterConfiguration(options, indexFile, moduleFileName, modulePath)
|
||||
: noop(),
|
||||
options.routing && !options.lazy && options.parentModule
|
||||
? addChildren(options)
|
||||
: noop()
|
||||
];
|
||||
|
||||
const templateSource = apply(
|
||||
url(options.nomodule ? './files' : './ngfiles'),
|
||||
[
|
||||
template({
|
||||
...names(options.name),
|
||||
dot: '.',
|
||||
tmpl: '',
|
||||
...(options as object)
|
||||
})
|
||||
]
|
||||
);
|
||||
|
||||
return {
|
||||
options,
|
||||
moduleFileName,
|
||||
modulePath,
|
||||
indexFile,
|
||||
templateSource,
|
||||
routingRules
|
||||
};
|
||||
}
|
||||
|
||||
export default function(schema: Schema): Rule {
|
||||
const { templateSource, routingRules } = validateLibSchema(schema);
|
||||
|
||||
return chain([
|
||||
branchAndMerge(chain([mergeWith(templateSource)])),
|
||||
...routingRules,
|
||||
formatFiles(schema)
|
||||
]);
|
||||
}
|
||||
@ -1,35 +0,0 @@
|
||||
# TODO: Make this private when we can import from the root index.ts
|
||||
package(default_visibility = ["//visibility:public"])
|
||||
|
||||
load("@angular//:index.bzl", "ng_module")
|
||||
load("@build_bazel_rules_typescript//:defs.bzl", "ts_library", "ts_web_test")
|
||||
|
||||
ng_module(
|
||||
name = "<%= sourceDir %>",
|
||||
srcs = glob(
|
||||
["*.ts"],
|
||||
exclude = ["*.spec.ts"],
|
||||
),
|
||||
deps = [
|
||||
"@rxjs",
|
||||
],
|
||||
)
|
||||
|
||||
ts_library(
|
||||
name = "test_lib",
|
||||
testonly = 1,
|
||||
srcs = glob(["*.spec.ts"]),
|
||||
deps = [
|
||||
":<%= sourceDir %>",
|
||||
],
|
||||
)
|
||||
|
||||
ts_web_test(
|
||||
name = "test",
|
||||
bootstrap = ["//:angular_bootstrap_scripts"],
|
||||
deps = [
|
||||
":test_lib",
|
||||
"//:angular_bundles",
|
||||
"//:angular_test_bundles",
|
||||
],
|
||||
)
|
||||
@ -1,7 +0,0 @@
|
||||
import { <%= className %>Module } from './<%=fileName%>.module';
|
||||
|
||||
describe('<%= className %>Module', () => {
|
||||
it('should work', () => {
|
||||
expect(new <%= className %>Module()).toBeDefined();
|
||||
});
|
||||
});
|
||||
@ -1,8 +0,0 @@
|
||||
import { NgModule } from '@angular/core';
|
||||
import { CommonModule } from '@angular/common';
|
||||
|
||||
@NgModule({
|
||||
imports: [CommonModule]
|
||||
})
|
||||
export class <%= className %>Module {
|
||||
}
|
||||
15
packages/bazel/src/collection/lib/schema.d.ts
vendored
15
packages/bazel/src/collection/lib/schema.d.ts
vendored
@ -1,15 +0,0 @@
|
||||
export interface Schema {
|
||||
name: string;
|
||||
skipFormat: boolean;
|
||||
directory?: string;
|
||||
sourceDir?: string;
|
||||
nomodule: boolean;
|
||||
|
||||
spec?: boolean;
|
||||
flat?: boolean;
|
||||
commonModule?: boolean;
|
||||
|
||||
routing?: boolean;
|
||||
lazy?: boolean;
|
||||
parentModule?: string;
|
||||
}
|
||||
@ -1,41 +0,0 @@
|
||||
{
|
||||
"$schema": "http://json-schema.org/schema",
|
||||
"id": "library",
|
||||
"title": "Create a library",
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"name": {
|
||||
"type": "string",
|
||||
"description": "Library name"
|
||||
},
|
||||
"directory": {
|
||||
"type": "string",
|
||||
"description": "A directory where the app is placed"
|
||||
},
|
||||
"nomodule": {
|
||||
"type": "boolean",
|
||||
"default": false,
|
||||
"description": "Generate a simple TS library when set to true."
|
||||
},
|
||||
"routing": {
|
||||
"type": "boolean",
|
||||
"default": false,
|
||||
"description": "Add router configuration. See lazy for more information."
|
||||
},
|
||||
"skipFormat": {
|
||||
"description": "Skip formatting files",
|
||||
"type": "boolean",
|
||||
"default": false
|
||||
},
|
||||
"lazy": {
|
||||
"type": "boolean",
|
||||
"default": false,
|
||||
"description": "Add RouterModule.forChild when set to true, and a simple array of routes when set to false."
|
||||
},
|
||||
"parentModule": {
|
||||
"type": "string",
|
||||
"description": "Update the router configuration of the parent module using loadChildren or children, depending on what `lazy` is set to."
|
||||
}
|
||||
},
|
||||
"required": ["name"]
|
||||
}
|
||||
@ -1,24 +0,0 @@
|
||||
package(default_visibility = ["//visibility:public"])
|
||||
|
||||
load("@angular//:index.bzl", "ng_module")
|
||||
load("@build_bazel_rules_typescript//:defs.bzl", "ts_library")
|
||||
|
||||
ng_module(
|
||||
name = "<%= dasherize(name) %>",
|
||||
srcs = glob(
|
||||
["*.ts"],
|
||||
exclude = ["*.spec.ts"],
|
||||
),
|
||||
deps = [
|
||||
"@rxjs",
|
||||
],
|
||||
)
|
||||
|
||||
ts_library(
|
||||
name = "test_lib",
|
||||
testonly = 1,
|
||||
srcs = glob(["*.spec.ts"]),
|
||||
deps = [
|
||||
":<%= dasherize(name) %>",
|
||||
],
|
||||
)
|
||||
@ -1,43 +0,0 @@
|
||||
import { normalize, strings } from '@angular-devkit/core';
|
||||
import {
|
||||
apply,
|
||||
branchAndMerge,
|
||||
chain,
|
||||
externalSchematic,
|
||||
mergeWith,
|
||||
move,
|
||||
Rule,
|
||||
SchematicContext,
|
||||
SchematicsException,
|
||||
template,
|
||||
Tree,
|
||||
url,
|
||||
TaskConfigurationGenerator,
|
||||
TaskConfiguration
|
||||
} from '@angular-devkit/schematics';
|
||||
|
||||
import { Schema } from './schema';
|
||||
import { formatFiles } from '../../utils/rules/format-files';
|
||||
|
||||
export default function(schema: Schema): Rule {
|
||||
schema.path = schema.path ? normalize(schema.path) : schema.path;
|
||||
const sourceDir = schema.sourceDir;
|
||||
if (!sourceDir) {
|
||||
throw new SchematicsException(`sourceDir option is required.`);
|
||||
}
|
||||
|
||||
const templateSource = apply(url('./files'), [
|
||||
template({
|
||||
...strings,
|
||||
'if-flat': (s: string) => (schema.flat ? '' : s),
|
||||
...schema
|
||||
}),
|
||||
move(sourceDir)
|
||||
]);
|
||||
|
||||
return chain([
|
||||
branchAndMerge(chain([mergeWith(templateSource)])),
|
||||
externalSchematic('@schematics/angular', 'module', schema),
|
||||
formatFiles(schema)
|
||||
]);
|
||||
}
|
||||
55
packages/bazel/src/collection/module/schema.d.ts
vendored
55
packages/bazel/src/collection/module/schema.d.ts
vendored
@ -1,55 +0,0 @@
|
||||
/**
|
||||
* @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
|
||||
*/
|
||||
|
||||
export interface Schema {
|
||||
/**
|
||||
* The name of the module.
|
||||
*/
|
||||
name: string;
|
||||
|
||||
/**
|
||||
* Skip formatting of files
|
||||
*/
|
||||
skipFormat: boolean;
|
||||
/**
|
||||
* The path to create the module.
|
||||
*/
|
||||
path?: string;
|
||||
/**
|
||||
* The path of the source directory.
|
||||
*/
|
||||
sourceDir?: string;
|
||||
/**
|
||||
* The root of the application.
|
||||
*/
|
||||
appRoot?: string;
|
||||
/**
|
||||
* Generates a routing module.
|
||||
*/
|
||||
routing?: boolean;
|
||||
/**
|
||||
* The scope for the generated routing.
|
||||
*/
|
||||
routingScope?: 'Child' | 'Root';
|
||||
/**
|
||||
* Specifies if a spec file is generated.
|
||||
*/
|
||||
spec?: boolean;
|
||||
/**
|
||||
* Flag to indicate if a dir is created.
|
||||
*/
|
||||
flat?: boolean;
|
||||
/**
|
||||
* Flag to control whether the CommonModule is imported.
|
||||
*/
|
||||
commonModule?: boolean;
|
||||
/**
|
||||
* Allows specification of the declaring module.
|
||||
*/
|
||||
module?: string;
|
||||
}
|
||||
@ -1,70 +0,0 @@
|
||||
{
|
||||
"$schema": "http://json-schema.org/schema",
|
||||
"id": "module",
|
||||
"title": "NX Module Options Schema",
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"name": {
|
||||
"type": "string",
|
||||
"description": "The name of the module."
|
||||
},
|
||||
"path": {
|
||||
"type": "string",
|
||||
"format": "path",
|
||||
"description": "The path to create the module.",
|
||||
"default": "app",
|
||||
"visible": false
|
||||
},
|
||||
"sourceDir": {
|
||||
"type": "string",
|
||||
"format": "path",
|
||||
"description": "The path of the source directory.",
|
||||
"default": "src",
|
||||
"visible": false
|
||||
},
|
||||
"appRoot": {
|
||||
"type": "string",
|
||||
"format": "path",
|
||||
"description": "The root of the application.",
|
||||
"visible": false
|
||||
},
|
||||
"routing": {
|
||||
"type": "boolean",
|
||||
"description": "Generates a routing module.",
|
||||
"default": false
|
||||
},
|
||||
"routingScope": {
|
||||
"enum": ["Child", "Root"],
|
||||
"type": "string",
|
||||
"description": "The scope for the generated routing.",
|
||||
"default": "Child"
|
||||
},
|
||||
"spec": {
|
||||
"type": "boolean",
|
||||
"description": "Specifies if a spec file is generated.",
|
||||
"default": true
|
||||
},
|
||||
"flat": {
|
||||
"type": "boolean",
|
||||
"description": "Flag to indicate if a dir is created.",
|
||||
"default": false
|
||||
},
|
||||
"commonModule": {
|
||||
"type": "boolean",
|
||||
"description": "Flag to control whether the CommonModule is imported.",
|
||||
"default": true,
|
||||
"visible": false
|
||||
},
|
||||
"skipFormat": {
|
||||
"description": "Skip formatting files",
|
||||
"type": "boolean",
|
||||
"default": false
|
||||
},
|
||||
"module": {
|
||||
"type": "string",
|
||||
"description": "Allows specification of the declaring module.",
|
||||
"alias": "m"
|
||||
}
|
||||
},
|
||||
"required": ["name"]
|
||||
}
|
||||
@ -1,36 +0,0 @@
|
||||
export const angularCliVersion = '1.7.1';
|
||||
export const angularVersion = '5.2.7';
|
||||
export const angularJsVersion = '1.6.6';
|
||||
export const ngrxVersion = '5.1.0';
|
||||
export const ngrxStoreFreezeVersion = '^0.2.1';
|
||||
export const routerStoreVersion = '5.0.1';
|
||||
export const nxVersion = '*';
|
||||
export const schematicsVersion = '*';
|
||||
export const angularCliSchema =
|
||||
'./node_modules/@nrwl/schematics/src/schema.json';
|
||||
export const latestMigration = '20180313-add-tags';
|
||||
export const prettierVersion = '1.10.2';
|
||||
export const typescriptVersion = '2.6.2';
|
||||
export const rxjsVersion = '^5.5.6';
|
||||
export const devKitCoreVersion = '^0.0.29';
|
||||
export const devKitSchematicsVersion = '0.0.52';
|
||||
export const schematicsAngularVersion = '0.1.17';
|
||||
|
||||
export const libVersions = {
|
||||
angularVersion,
|
||||
angularCliVersion,
|
||||
angularJsVersion,
|
||||
ngrxVersion,
|
||||
ngrxStoreFreezeVersion,
|
||||
nxVersion,
|
||||
schematicsVersion,
|
||||
prettierVersion,
|
||||
angularCliSchema,
|
||||
latestMigration,
|
||||
typescriptVersion,
|
||||
rxjsVersion,
|
||||
devKitCoreVersion,
|
||||
devKitSchematicsVersion,
|
||||
schematicsAngularVersion,
|
||||
routerStoreVersion
|
||||
};
|
||||
@ -1,686 +0,0 @@
|
||||
{
|
||||
"$schema": "http://json-schema.org/schema",
|
||||
"id": "https://github.com/nrwl/nx/blob/master/packages/bazel/src/schema.json",
|
||||
"title": "Nrwl Nx Config Schema",
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"$schema": {
|
||||
"type": "string"
|
||||
},
|
||||
"project": {
|
||||
"description": "The global configuration of the project.",
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"name": {
|
||||
"description": "The name of the project.",
|
||||
"type": "string"
|
||||
},
|
||||
"latestMigration": {
|
||||
"description": "Npm scope for importing libs.",
|
||||
"type": "string"
|
||||
},
|
||||
"ejected": {
|
||||
"description": "Whether or not this project was ejected.",
|
||||
"type": "boolean",
|
||||
"default": false
|
||||
}
|
||||
},
|
||||
"additionalProperties": false
|
||||
},
|
||||
"apps": {
|
||||
"description": "Properties of the different applications in this project.",
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"tags": {
|
||||
"type": "array",
|
||||
"description": "Project tags",
|
||||
"items": {
|
||||
"type": "string"
|
||||
},
|
||||
"default": []
|
||||
},
|
||||
"name": {
|
||||
"type": "string",
|
||||
"description": "Name of the app."
|
||||
},
|
||||
"appRoot": {
|
||||
"type": "string",
|
||||
"description": "Directory where app files are placed.",
|
||||
"default": "app"
|
||||
},
|
||||
"appShell": {
|
||||
"type": "object",
|
||||
"description": "AppShell configuration.",
|
||||
"properties": {
|
||||
"app": {
|
||||
"type": "string",
|
||||
"description": "Index or name of the related AppShell app."
|
||||
},
|
||||
"route": {
|
||||
"type": "string",
|
||||
"description": "Default AppShell route to render."
|
||||
}
|
||||
}
|
||||
},
|
||||
"root": {
|
||||
"type": "string",
|
||||
"description": "The root directory of the app."
|
||||
},
|
||||
"outDir": {
|
||||
"type": "string",
|
||||
"default": "dist/",
|
||||
"description": "The output directory for build results."
|
||||
},
|
||||
"assets": {
|
||||
"type": "array",
|
||||
"description": "List of application assets.",
|
||||
"items": {
|
||||
"oneOf": [
|
||||
{
|
||||
"type": "string"
|
||||
},
|
||||
{
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"glob": {
|
||||
"type": "string",
|
||||
"default": "",
|
||||
"description": "The pattern to match."
|
||||
},
|
||||
"input": {
|
||||
"type": "string",
|
||||
"default": "",
|
||||
"description": "The dir to search within."
|
||||
},
|
||||
"output": {
|
||||
"type": "string",
|
||||
"default": "",
|
||||
"description": "The output path (relative to the outDir)."
|
||||
},
|
||||
"allowOutsideOutDir": {
|
||||
"type": "boolean",
|
||||
"description": "Allow assets to be copied outside the outDir.",
|
||||
"default": false
|
||||
}
|
||||
},
|
||||
"additionalProperties": false
|
||||
}
|
||||
]
|
||||
},
|
||||
"default": []
|
||||
},
|
||||
"budgets": {
|
||||
"type": "array",
|
||||
"description": "Threshold definitions for bundle sizes.",
|
||||
"items": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"type": {
|
||||
"type": "string",
|
||||
"enum": [
|
||||
"bundle",
|
||||
"initial",
|
||||
"allScript",
|
||||
"all",
|
||||
"anyScript",
|
||||
"any"
|
||||
],
|
||||
"description": "The type of budget"
|
||||
},
|
||||
"name": {
|
||||
"type": "string",
|
||||
"description": "The name of the bundle"
|
||||
},
|
||||
"baseline": {
|
||||
"type": "string",
|
||||
"description": "The baseline size for comparison."
|
||||
},
|
||||
"maximumWarning": {
|
||||
"type": "string",
|
||||
"description": "The maximum threshold for warning relative to the baseline."
|
||||
},
|
||||
"maximumError": {
|
||||
"type": "string",
|
||||
"description": "The maximum threshold for error relative to the baseline."
|
||||
},
|
||||
"minimumWarning": {
|
||||
"type": "string",
|
||||
"description": "The minimum threshold for warning relative to the baseline."
|
||||
},
|
||||
"minimumError": {
|
||||
"type": "string",
|
||||
"description": "The minimum threshold for error relative to the baseline."
|
||||
},
|
||||
"warning": {
|
||||
"type": "string",
|
||||
"description": "The threshold for warning relative to the baseline (min & max)."
|
||||
},
|
||||
"error": {
|
||||
"type": "string",
|
||||
"description": "The threshold for error relative to the baseline (min & max)."
|
||||
}
|
||||
}
|
||||
},
|
||||
"default": []
|
||||
},
|
||||
"deployUrl": {
|
||||
"type": "string",
|
||||
"description": "URL where files will be deployed."
|
||||
},
|
||||
"baseHref": {
|
||||
"type": "string",
|
||||
"description": "Base url for the application being built."
|
||||
},
|
||||
"platform": {
|
||||
"type": "string",
|
||||
"enum": ["browser", "server"],
|
||||
"default": "browser",
|
||||
"description": "The runtime platform of the app."
|
||||
},
|
||||
"index": {
|
||||
"type": "string",
|
||||
"default": "index.html",
|
||||
"description": "The name of the start HTML file."
|
||||
},
|
||||
"main": {
|
||||
"type": "string",
|
||||
"description": "The name of the main entry-point file."
|
||||
},
|
||||
"polyfills": {
|
||||
"type": "string",
|
||||
"description": "The name of the polyfills file."
|
||||
},
|
||||
"test": {
|
||||
"type": "string",
|
||||
"description": "The name of the test entry-point file."
|
||||
},
|
||||
"tsconfig": {
|
||||
"type": "string",
|
||||
"default": "tsconfig.app.json",
|
||||
"description": "The name of the TypeScript configuration file."
|
||||
},
|
||||
"testTsconfig": {
|
||||
"type": "string",
|
||||
"description": "The name of the TypeScript configuration file for unit tests."
|
||||
},
|
||||
"prefix": {
|
||||
"type": "string",
|
||||
"description": "The prefix to apply to generated selectors."
|
||||
},
|
||||
"serviceWorker": {
|
||||
"description": "Experimental support for a service worker from @angular/service-worker.",
|
||||
"type": "boolean",
|
||||
"default": false
|
||||
},
|
||||
"styles": {
|
||||
"description": "Global styles to be included in the build.",
|
||||
"type": "array",
|
||||
"items": {
|
||||
"oneOf": [
|
||||
{
|
||||
"type": "string"
|
||||
},
|
||||
{
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"input": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"additionalProperties": true
|
||||
}
|
||||
]
|
||||
},
|
||||
"additionalProperties": false
|
||||
},
|
||||
"stylePreprocessorOptions": {
|
||||
"description": "Options to pass to style preprocessors",
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"includePaths": {
|
||||
"description": "Paths to include. Paths will be resolved to project root.",
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "string"
|
||||
},
|
||||
"default": []
|
||||
}
|
||||
},
|
||||
"additionalProperties": false
|
||||
},
|
||||
"scripts": {
|
||||
"description": "Global scripts to be included in the build.",
|
||||
"type": "array",
|
||||
"items": {
|
||||
"oneOf": [
|
||||
{
|
||||
"type": "string"
|
||||
},
|
||||
{
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"input": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"additionalProperties": true,
|
||||
"required": ["input"]
|
||||
}
|
||||
]
|
||||
},
|
||||
"additionalProperties": false
|
||||
},
|
||||
"environmentSource": {
|
||||
"description": "Source file for environment config.",
|
||||
"type": "string"
|
||||
},
|
||||
"environments": {
|
||||
"description": "Name and corresponding file for environment config.",
|
||||
"type": "object",
|
||||
"additionalProperties": true
|
||||
}
|
||||
},
|
||||
"additionalProperties": false
|
||||
},
|
||||
"additionalProperties": false
|
||||
},
|
||||
"e2e": {
|
||||
"type": "object",
|
||||
"description": "Configuration for end-to-end tests.",
|
||||
"properties": {
|
||||
"protractor": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"config": {
|
||||
"description": "Path to the config file.",
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"additionalProperties": false
|
||||
}
|
||||
},
|
||||
"additionalProperties": false
|
||||
},
|
||||
"lint": {
|
||||
"description": "Properties to be passed to TSLint.",
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"files": {
|
||||
"description": "File glob(s) to lint.",
|
||||
"oneOf": [
|
||||
{
|
||||
"type": "string"
|
||||
},
|
||||
{
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
],
|
||||
"default": []
|
||||
},
|
||||
"project": {
|
||||
"description": "Location of the tsconfig.json project file. Will also use as files to lint if 'files' property not present.",
|
||||
"type": "string"
|
||||
},
|
||||
"tslintConfig": {
|
||||
"description": "Location of the tslint.json configuration.",
|
||||
"type": "string"
|
||||
},
|
||||
"exclude": {
|
||||
"description": "File glob(s) to ignore.",
|
||||
"oneOf": [
|
||||
{
|
||||
"type": "string"
|
||||
},
|
||||
{
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
],
|
||||
"default": []
|
||||
}
|
||||
},
|
||||
"required": ["project"],
|
||||
"additionalProperties": false
|
||||
}
|
||||
},
|
||||
"test": {
|
||||
"description": "Configuration for unit tests.",
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"karma": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"config": {
|
||||
"description": "Path to the karma config file.",
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"additionalProperties": false
|
||||
},
|
||||
"codeCoverage": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"exclude": {
|
||||
"description": "Globs to exclude from code coverage.",
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "string"
|
||||
},
|
||||
"default": []
|
||||
}
|
||||
},
|
||||
"additionalProperties": false
|
||||
}
|
||||
},
|
||||
"additionalProperties": false
|
||||
},
|
||||
"defaults": {
|
||||
"description": "Specify the default values for generating.",
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"styleExt": {
|
||||
"description": "The file extension to be used for style files.",
|
||||
"type": "string"
|
||||
},
|
||||
"poll": {
|
||||
"description": "How often to check for file updates.",
|
||||
"type": "number"
|
||||
},
|
||||
"lintFix": {
|
||||
"description": "Use lint to fix files after generation",
|
||||
"type": "boolean",
|
||||
"default": false
|
||||
},
|
||||
"class": {
|
||||
"description": "Options for generating a class.",
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"spec": {
|
||||
"description": "Specifies if a spec file is generated.",
|
||||
"type": "boolean",
|
||||
"default": false
|
||||
}
|
||||
}
|
||||
},
|
||||
"component": {
|
||||
"description": "Options for generating a component.",
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"flat": {
|
||||
"description": "Flag to indicate if a dir is created.",
|
||||
"type": "boolean",
|
||||
"default": true
|
||||
},
|
||||
"spec": {
|
||||
"description": "Specifies if a spec file is generated.",
|
||||
"type": "boolean",
|
||||
"default": true
|
||||
},
|
||||
"inlineStyle": {
|
||||
"description": "Specifies if the style will be in the ts file.",
|
||||
"type": "boolean",
|
||||
"default": false
|
||||
},
|
||||
"inlineTemplate": {
|
||||
"description": "Specifies if the template will be in the ts file.",
|
||||
"type": "boolean",
|
||||
"default": false
|
||||
},
|
||||
"viewEncapsulation": {
|
||||
"description": "Specifies the view encapsulation strategy.",
|
||||
"enum": ["Emulated", "Native", "None"],
|
||||
"type": "string"
|
||||
},
|
||||
"changeDetection": {
|
||||
"description": "Specifies the change detection strategy.",
|
||||
"enum": ["Default", "OnPush"],
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
},
|
||||
"directive": {
|
||||
"description": "Options for generating a directive.",
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"flat": {
|
||||
"description": "Flag to indicate if a dir is created.",
|
||||
"type": "boolean",
|
||||
"default": true
|
||||
},
|
||||
"spec": {
|
||||
"description": "Specifies if a spec file is generated.",
|
||||
"type": "boolean",
|
||||
"default": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"guard": {
|
||||
"description": "Options for generating a guard.",
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"flat": {
|
||||
"description": "Flag to indicate if a dir is created.",
|
||||
"type": "boolean",
|
||||
"default": true
|
||||
},
|
||||
"spec": {
|
||||
"description": "Specifies if a spec file is generated.",
|
||||
"type": "boolean",
|
||||
"default": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"interface": {
|
||||
"description": "Options for generating an interface.",
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"prefix": {
|
||||
"description": "Prefix to apply to interface names. (i.e. I)",
|
||||
"type": "string",
|
||||
"default": ""
|
||||
}
|
||||
}
|
||||
},
|
||||
"module": {
|
||||
"description": "Options for generating a module.",
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"flat": {
|
||||
"description": "Flag to indicate if a dir is created.",
|
||||
"type": "boolean",
|
||||
"default": false
|
||||
},
|
||||
"spec": {
|
||||
"description": "Specifies if a spec file is generated.",
|
||||
"type": "boolean",
|
||||
"default": false
|
||||
}
|
||||
}
|
||||
},
|
||||
"pipe": {
|
||||
"description": "Options for generating a pipe.",
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"flat": {
|
||||
"description": "Flag to indicate if a dir is created.",
|
||||
"type": "boolean",
|
||||
"default": true
|
||||
},
|
||||
"spec": {
|
||||
"description": "Specifies if a spec file is generated.",
|
||||
"type": "boolean",
|
||||
"default": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"service": {
|
||||
"description": "Options for generating a service.",
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"flat": {
|
||||
"description": "Flag to indicate if a dir is created.",
|
||||
"type": "boolean",
|
||||
"default": true
|
||||
},
|
||||
"spec": {
|
||||
"description": "Specifies if a spec file is generated.",
|
||||
"type": "boolean",
|
||||
"default": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"build": {
|
||||
"description": "Properties to be passed to the build command.",
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"sourcemaps": {
|
||||
"description": "Output sourcemaps.",
|
||||
"type": "boolean"
|
||||
},
|
||||
"baseHref": {
|
||||
"description": "Base url for the application being built.",
|
||||
"type": "string"
|
||||
},
|
||||
"progress": {
|
||||
"description": "The ssl key used by the server.",
|
||||
"type": "boolean"
|
||||
},
|
||||
"poll": {
|
||||
"description": "Enable and define the file watching poll time period (milliseconds).",
|
||||
"type": "number"
|
||||
},
|
||||
"deleteOutputPath": {
|
||||
"description": "Delete output path before build.",
|
||||
"type": "boolean",
|
||||
"default": true
|
||||
},
|
||||
"preserveSymlinks": {
|
||||
"description": "Do not use the real path when resolving modules.",
|
||||
"type": "boolean",
|
||||
"default": false
|
||||
},
|
||||
"showCircularDependencies": {
|
||||
"description": "Show circular dependency warnings on builds.",
|
||||
"type": "boolean",
|
||||
"default": true
|
||||
},
|
||||
"commonChunk": {
|
||||
"description": "Use a separate bundle containing code used across multiple bundles.",
|
||||
"type": "boolean",
|
||||
"default": true
|
||||
},
|
||||
"namedChunks": {
|
||||
"description": "Use file name for lazy loaded chunks.",
|
||||
"type": "boolean"
|
||||
}
|
||||
}
|
||||
},
|
||||
"serve": {
|
||||
"description": "Properties to be passed to the serve command.",
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"port": {
|
||||
"description": "The port the application will be served on.",
|
||||
"type": "number",
|
||||
"default": 4200
|
||||
},
|
||||
"host": {
|
||||
"description": "The host the application will be served on.",
|
||||
"type": "string",
|
||||
"default": "localhost"
|
||||
},
|
||||
"ssl": {
|
||||
"description": "Enables ssl for the application.",
|
||||
"type": "boolean",
|
||||
"default": false
|
||||
},
|
||||
"sslKey": {
|
||||
"description": "The ssl key used by the server.",
|
||||
"type": "string",
|
||||
"default": "ssl/server.key"
|
||||
},
|
||||
"sslCert": {
|
||||
"description": "The ssl certificate used by the server.",
|
||||
"type": "string",
|
||||
"default": "ssl/server.crt"
|
||||
},
|
||||
"proxyConfig": {
|
||||
"description": "Proxy configuration file.",
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
},
|
||||
"schematics": {
|
||||
"description": "Properties about schematics.",
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"collection": {
|
||||
"description": "The schematics collection to use.",
|
||||
"type": "string",
|
||||
"default": "@schematics/angular"
|
||||
},
|
||||
"newApp": {
|
||||
"description": "The new app schematic.",
|
||||
"type": "string",
|
||||
"default": "application"
|
||||
}
|
||||
},
|
||||
"additionalProperties": false
|
||||
}
|
||||
},
|
||||
"additionalProperties": false
|
||||
},
|
||||
"packageManager": {
|
||||
"description": "Specify which package manager tool to use.",
|
||||
"enum": ["npm", "cnpm", "yarn", "default"],
|
||||
"default": "default",
|
||||
"type": "string"
|
||||
},
|
||||
"warnings": {
|
||||
"description": "Allow people to disable console warnings.",
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"hmrWarning": {
|
||||
"description": "Show a warning when the user enabled the --hmr option.",
|
||||
"type": "boolean",
|
||||
"default": true
|
||||
},
|
||||
"nodeDeprecation": {
|
||||
"description": "Show a warning when the node version is incompatible.",
|
||||
"type": "boolean",
|
||||
"default": true
|
||||
},
|
||||
"packageDeprecation": {
|
||||
"description": "Show a warning when the user installed angular-cli.",
|
||||
"type": "boolean",
|
||||
"default": true
|
||||
},
|
||||
"versionMismatch": {
|
||||
"description": "Show a warning when the global version is newer than the local one.",
|
||||
"type": "boolean",
|
||||
"default": true
|
||||
},
|
||||
"typescriptMismatch": {
|
||||
"description": "Show a warning when the TypeScript version is incompatible",
|
||||
"type": "boolean",
|
||||
"default": true
|
||||
},
|
||||
"servePathDefault": {
|
||||
"description": "Show a warning when deploy-url/base-href use unsupported serve path values.",
|
||||
"type": "boolean",
|
||||
"default": true
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"additionalProperties": false
|
||||
}
|
||||
@ -1,671 +0,0 @@
|
||||
/**
|
||||
* @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 { Tree, Rule } from '@angular-devkit/schematics';
|
||||
import {
|
||||
findNodes,
|
||||
getDecoratorMetadata,
|
||||
getSourceNodes
|
||||
} from '@schematics/angular/utility/ast-utils';
|
||||
import {
|
||||
Change,
|
||||
InsertChange,
|
||||
NoopChange,
|
||||
RemoveChange
|
||||
} from '@schematics/angular/utility/change';
|
||||
import * as ts from 'typescript';
|
||||
import { toFileName } from './name-utils';
|
||||
import * as path from 'path';
|
||||
import { serializeJson } from '../utils/fileutils';
|
||||
|
||||
// This should be moved to @schematics/angular once it allows to pass custom expressions as providers
|
||||
function _addSymbolToNgModuleMetadata(
|
||||
source: ts.SourceFile,
|
||||
ngModulePath: string,
|
||||
metadataField: string,
|
||||
expression: string
|
||||
): Change[] {
|
||||
const nodes = getDecoratorMetadata(source, 'NgModule', '@angular/core');
|
||||
let node: any = nodes[0]; // tslint:disable-line:no-any
|
||||
|
||||
// Find the decorator declaration.
|
||||
if (!node) {
|
||||
return [];
|
||||
}
|
||||
// Get all the children property assignment of object literals.
|
||||
const matchingProperties: ts.ObjectLiteralElement[] = (node as ts.ObjectLiteralExpression).properties
|
||||
.filter(prop => prop.kind == ts.SyntaxKind.PropertyAssignment)
|
||||
// Filter out every fields that's not "metadataField". Also handles string literals
|
||||
// (but not expressions).
|
||||
.filter((prop: ts.PropertyAssignment) => {
|
||||
const name = prop.name;
|
||||
switch (name.kind) {
|
||||
case ts.SyntaxKind.Identifier:
|
||||
return (name as ts.Identifier).getText(source) == metadataField;
|
||||
case ts.SyntaxKind.StringLiteral:
|
||||
return (name as ts.StringLiteral).text == metadataField;
|
||||
}
|
||||
|
||||
return false;
|
||||
});
|
||||
|
||||
// Get the last node of the array literal.
|
||||
if (!matchingProperties) {
|
||||
return [];
|
||||
}
|
||||
if (matchingProperties.length == 0) {
|
||||
// We haven't found the field in the metadata declaration. Insert a new field.
|
||||
const expr = node as ts.ObjectLiteralExpression;
|
||||
let position: number;
|
||||
let toInsert: string;
|
||||
if (expr.properties.length == 0) {
|
||||
position = expr.getEnd() - 1;
|
||||
toInsert = ` ${metadataField}: [${expression}]\n`;
|
||||
} else {
|
||||
node = expr.properties[expr.properties.length - 1];
|
||||
position = node.getEnd();
|
||||
// Get the indentation of the last element, if any.
|
||||
const text = node.getFullText(source);
|
||||
if (text.match('^\r?\r?\n')) {
|
||||
toInsert = `,${
|
||||
text.match(/^\r?\n\s+/)[0]
|
||||
}${metadataField}: [${expression}]`;
|
||||
} else {
|
||||
toInsert = `, ${metadataField}: [${expression}]`;
|
||||
}
|
||||
}
|
||||
const newMetadataProperty = new InsertChange(
|
||||
ngModulePath,
|
||||
position,
|
||||
toInsert
|
||||
);
|
||||
return [newMetadataProperty];
|
||||
}
|
||||
|
||||
const assignment = matchingProperties[0] as ts.PropertyAssignment;
|
||||
|
||||
// If it's not an array, nothing we can do really.
|
||||
if (assignment.initializer.kind !== ts.SyntaxKind.ArrayLiteralExpression) {
|
||||
return [];
|
||||
}
|
||||
|
||||
const arrLiteral = assignment.initializer as ts.ArrayLiteralExpression;
|
||||
if (arrLiteral.elements.length == 0) {
|
||||
// Forward the property.
|
||||
node = arrLiteral;
|
||||
} else {
|
||||
node = arrLiteral.elements;
|
||||
}
|
||||
|
||||
if (!node) {
|
||||
console.log(
|
||||
'No app module found. Please add your new class to your component.'
|
||||
);
|
||||
|
||||
return [];
|
||||
}
|
||||
|
||||
if (Array.isArray(node)) {
|
||||
const nodeArray = (node as {}) as Array<ts.Node>;
|
||||
const symbolsArray = nodeArray.map(node => node.getText());
|
||||
if (symbolsArray.includes(expression)) {
|
||||
return [];
|
||||
}
|
||||
|
||||
node = node[node.length - 1];
|
||||
}
|
||||
|
||||
let toInsert: string;
|
||||
let position = node.getEnd();
|
||||
if (node.kind == ts.SyntaxKind.ObjectLiteralExpression) {
|
||||
// We haven't found the field in the metadata declaration. Insert a new
|
||||
// field.
|
||||
const expr = node as ts.ObjectLiteralExpression;
|
||||
if (expr.properties.length == 0) {
|
||||
position = expr.getEnd() - 1;
|
||||
toInsert = ` ${metadataField}: [${expression}]\n`;
|
||||
} else {
|
||||
node = expr.properties[expr.properties.length - 1];
|
||||
position = node.getEnd();
|
||||
// Get the indentation of the last element, if any.
|
||||
const text = node.getFullText(source);
|
||||
if (text.match('^\r?\r?\n')) {
|
||||
toInsert = `,${
|
||||
text.match(/^\r?\n\s+/)[0]
|
||||
}${metadataField}: [${expression}]`;
|
||||
} else {
|
||||
toInsert = `, ${metadataField}: [${expression}]`;
|
||||
}
|
||||
}
|
||||
} else if (node.kind == ts.SyntaxKind.ArrayLiteralExpression) {
|
||||
// We found the field but it's empty. Insert it just before the `]`.
|
||||
position--;
|
||||
toInsert = `${expression}`;
|
||||
} else {
|
||||
// Get the indentation of the last element, if any.
|
||||
const text = node.getFullText(source);
|
||||
if (text.match(/^\r?\n/)) {
|
||||
toInsert = `,${text.match(/^\r?\n(\r?)\s+/)[0]}${expression}`;
|
||||
} else {
|
||||
toInsert = `, ${expression}`;
|
||||
}
|
||||
}
|
||||
const insert = new InsertChange(ngModulePath, position, toInsert);
|
||||
return [insert];
|
||||
}
|
||||
|
||||
export function addParameterToConstructor(
|
||||
source: ts.SourceFile,
|
||||
modulePath: string,
|
||||
opts: { className: string; param: string }
|
||||
): Change[] {
|
||||
const clazz = findClass(source, opts.className);
|
||||
const constructor = clazz.members.filter(
|
||||
m => m.kind === ts.SyntaxKind.Constructor
|
||||
)[0];
|
||||
if (constructor) {
|
||||
throw new Error('Should be tested');
|
||||
} else {
|
||||
const methodHeader = `constructor(${opts.param})`;
|
||||
return addMethod(source, modulePath, {
|
||||
className: opts.className,
|
||||
methodHeader,
|
||||
body: null
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
export function addMethod(
|
||||
source: ts.SourceFile,
|
||||
modulePath: string,
|
||||
opts: { className: string; methodHeader: string; body: string }
|
||||
): Change[] {
|
||||
const clazz = findClass(source, opts.className);
|
||||
const body = opts.body
|
||||
? `
|
||||
${opts.methodHeader} {
|
||||
${offset(opts.body, 1, false)}
|
||||
}
|
||||
`
|
||||
: `
|
||||
${opts.methodHeader} {}
|
||||
`;
|
||||
|
||||
return [new InsertChange(modulePath, clazz.end - 1, offset(body, 1, true))];
|
||||
}
|
||||
|
||||
export function removeFromNgModule(
|
||||
source: ts.SourceFile,
|
||||
modulePath: string,
|
||||
property: string
|
||||
): Change[] {
|
||||
const nodes = getDecoratorMetadata(source, 'NgModule', '@angular/core');
|
||||
let node: any = nodes[0]; // tslint:disable-line:no-any
|
||||
|
||||
// Find the decorator declaration.
|
||||
if (!node) {
|
||||
return [];
|
||||
}
|
||||
|
||||
// Get all the children property assignment of object literals.
|
||||
const matchingProperty = getMatchingProperty(source, property);
|
||||
if (matchingProperty) {
|
||||
return [
|
||||
new RemoveChange(
|
||||
modulePath,
|
||||
matchingProperty.pos,
|
||||
matchingProperty.getFullText(source)
|
||||
)
|
||||
];
|
||||
} else {
|
||||
return [];
|
||||
}
|
||||
}
|
||||
|
||||
function findClass(
|
||||
source: ts.SourceFile,
|
||||
className: string
|
||||
): ts.ClassDeclaration {
|
||||
const nodes = getSourceNodes(source);
|
||||
|
||||
const clazz = <any>(
|
||||
nodes.filter(
|
||||
n =>
|
||||
n.kind === ts.SyntaxKind.ClassDeclaration &&
|
||||
(<any>n).name.text === className
|
||||
)[0]
|
||||
);
|
||||
|
||||
if (!clazz) {
|
||||
throw new Error(`Cannot find class '${className}'`);
|
||||
}
|
||||
|
||||
return clazz;
|
||||
}
|
||||
|
||||
export function offset(
|
||||
text: string,
|
||||
numberOfTabs: number,
|
||||
wrap: boolean
|
||||
): string {
|
||||
const lines = text
|
||||
.trim()
|
||||
.split('\n')
|
||||
.map(line => {
|
||||
let tabs = '';
|
||||
for (let c = 0; c < numberOfTabs; ++c) {
|
||||
tabs += ' ';
|
||||
}
|
||||
return `${tabs}${line}`;
|
||||
})
|
||||
.join('\n');
|
||||
|
||||
return wrap ? `\n${lines}\n` : lines;
|
||||
}
|
||||
|
||||
export function addImportToModule(
|
||||
source: ts.SourceFile,
|
||||
modulePath: string,
|
||||
symbolName: string
|
||||
): Change[] {
|
||||
return _addSymbolToNgModuleMetadata(
|
||||
source,
|
||||
modulePath,
|
||||
'imports',
|
||||
symbolName
|
||||
);
|
||||
}
|
||||
|
||||
export function addImportToTestBed(
|
||||
source: ts.SourceFile,
|
||||
specPath: string,
|
||||
symbolName: string
|
||||
): Change[] {
|
||||
const allCalls: ts.CallExpression[] = <any>(
|
||||
findNodes(source, ts.SyntaxKind.CallExpression)
|
||||
);
|
||||
|
||||
const configureTestingModuleObjectLiterals = allCalls
|
||||
.filter(c => c.expression.kind === ts.SyntaxKind.PropertyAccessExpression)
|
||||
.filter(
|
||||
(c: any) => c.expression.name.getText(source) === 'configureTestingModule'
|
||||
)
|
||||
.map(c =>
|
||||
c.arguments[0].kind === ts.SyntaxKind.ObjectLiteralExpression
|
||||
? c.arguments[0]
|
||||
: null
|
||||
);
|
||||
|
||||
if (configureTestingModuleObjectLiterals.length > 0) {
|
||||
const startPosition = configureTestingModuleObjectLiterals[0]
|
||||
.getFirstToken(source)
|
||||
.getEnd();
|
||||
return [
|
||||
new InsertChange(specPath, startPosition, `imports: [${symbolName}], `)
|
||||
];
|
||||
} else {
|
||||
return [];
|
||||
}
|
||||
}
|
||||
|
||||
export function addReexport(
|
||||
source: ts.SourceFile,
|
||||
modulePath: string,
|
||||
reexportedFileName: string,
|
||||
token: string
|
||||
): Change[] {
|
||||
const allExports = findNodes(source, ts.SyntaxKind.ExportDeclaration);
|
||||
if (allExports.length > 0) {
|
||||
const m = allExports.filter(
|
||||
(e: ts.ExportDeclaration) =>
|
||||
e.moduleSpecifier.getText(source).indexOf(reexportedFileName) > -1
|
||||
);
|
||||
if (m.length > 0) {
|
||||
const mm: ts.ExportDeclaration = <any>m[0];
|
||||
return [
|
||||
new InsertChange(modulePath, mm.exportClause.end - 1, `, ${token} `)
|
||||
];
|
||||
}
|
||||
}
|
||||
return [];
|
||||
}
|
||||
|
||||
export function getBootstrapComponent(
|
||||
source: ts.SourceFile,
|
||||
moduleClassName: string
|
||||
): string {
|
||||
const bootstrap = getMatchingProperty(source, 'bootstrap');
|
||||
if (!bootstrap) {
|
||||
throw new Error(`Cannot find bootstrap components in '${moduleClassName}'`);
|
||||
}
|
||||
const c = bootstrap.getChildren();
|
||||
const nodes = c[c.length - 1].getChildren();
|
||||
|
||||
const bootstrapComponent = nodes.slice(1, nodes.length - 1)[0];
|
||||
if (!bootstrapComponent) {
|
||||
throw new Error(`Cannot find bootstrap components in '${moduleClassName}'`);
|
||||
}
|
||||
|
||||
return bootstrapComponent.getText();
|
||||
}
|
||||
|
||||
function getMatchingObjectLiteralElement(
|
||||
node: any,
|
||||
source: ts.SourceFile,
|
||||
property: string
|
||||
) {
|
||||
return (
|
||||
(node as ts.ObjectLiteralExpression).properties
|
||||
.filter(prop => prop.kind == ts.SyntaxKind.PropertyAssignment)
|
||||
// Filter out every fields that's not "metadataField". Also handles string literals
|
||||
// (but not expressions).
|
||||
.filter((prop: ts.PropertyAssignment) => {
|
||||
const name = prop.name;
|
||||
switch (name.kind) {
|
||||
case ts.SyntaxKind.Identifier:
|
||||
return (name as ts.Identifier).getText(source) === property;
|
||||
case ts.SyntaxKind.StringLiteral:
|
||||
return (name as ts.StringLiteral).text === property;
|
||||
}
|
||||
return false;
|
||||
})[0]
|
||||
);
|
||||
}
|
||||
|
||||
function getMatchingProperty(
|
||||
source: ts.SourceFile,
|
||||
property: string
|
||||
): ts.ObjectLiteralElement {
|
||||
const nodes = getDecoratorMetadata(source, 'NgModule', '@angular/core');
|
||||
let node: any = nodes[0]; // tslint:disable-line:no-any
|
||||
|
||||
if (!node) return null;
|
||||
|
||||
// Get all the children property assignment of object literals.
|
||||
return getMatchingObjectLiteralElement(node, source, property);
|
||||
}
|
||||
|
||||
export function addRoute(
|
||||
ngModulePath: string,
|
||||
source: ts.SourceFile,
|
||||
route: string
|
||||
): Change[] {
|
||||
const routes = getListOfRoutes(source);
|
||||
if (!routes) return [];
|
||||
|
||||
if (routes.hasTrailingComma || routes.length === 0) {
|
||||
return [new InsertChange(ngModulePath, routes.end, route)];
|
||||
} else {
|
||||
return [new InsertChange(ngModulePath, routes.end, `, ${route}`)];
|
||||
}
|
||||
}
|
||||
|
||||
export function addIncludeToTsConfig(
|
||||
tsConfigPath: string,
|
||||
source: ts.SourceFile,
|
||||
include: string
|
||||
): Change[] {
|
||||
const includeKeywordPos = source.text.indexOf('"include":');
|
||||
if (includeKeywordPos > -1) {
|
||||
const includeArrayEndPos = source.text.indexOf(']', includeKeywordPos);
|
||||
return [new InsertChange(tsConfigPath, includeArrayEndPos, include)];
|
||||
} else {
|
||||
return [];
|
||||
}
|
||||
}
|
||||
|
||||
function getListOfRoutes(source: ts.SourceFile): ts.NodeArray<ts.Expression> {
|
||||
const imports: any = getMatchingProperty(source, 'imports');
|
||||
|
||||
if (imports.initializer.kind === ts.SyntaxKind.ArrayLiteralExpression) {
|
||||
const a = imports.initializer as ts.ArrayLiteralExpression;
|
||||
|
||||
for (let e of a.elements) {
|
||||
if (e.kind === 181) {
|
||||
const ee = e as ts.CallExpression;
|
||||
const text = ee.expression.getText(source);
|
||||
if (
|
||||
(text === 'RouterModule.forRoot' ||
|
||||
text === 'RouterModule.forChild') &&
|
||||
ee.arguments.length > 0
|
||||
) {
|
||||
const routes = ee.arguments[0];
|
||||
if (routes.kind === ts.SyntaxKind.ArrayLiteralExpression) {
|
||||
return (routes as ts.ArrayLiteralExpression).elements;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
export function getImport(
|
||||
source: ts.SourceFile,
|
||||
predicate: (a: any) => boolean
|
||||
): { moduleSpec: string; bindings: string[] }[] {
|
||||
const allImports = findNodes(source, ts.SyntaxKind.ImportDeclaration);
|
||||
const matching = allImports.filter((i: ts.ImportDeclaration) =>
|
||||
predicate(i.moduleSpecifier.getText())
|
||||
);
|
||||
|
||||
return matching.map((i: ts.ImportDeclaration) => {
|
||||
const moduleSpec = i.moduleSpecifier
|
||||
.getText()
|
||||
.substring(1, i.moduleSpecifier.getText().length - 1);
|
||||
const t = i.importClause.namedBindings.getText();
|
||||
const bindings = t
|
||||
.replace('{', '')
|
||||
.replace('}', '')
|
||||
.split(',')
|
||||
.map(q => q.trim());
|
||||
return { moduleSpec, bindings };
|
||||
});
|
||||
}
|
||||
|
||||
export function addProviderToModule(
|
||||
source: ts.SourceFile,
|
||||
modulePath: string,
|
||||
symbolName: string
|
||||
): Change[] {
|
||||
return _addSymbolToNgModuleMetadata(
|
||||
source,
|
||||
modulePath,
|
||||
'providers',
|
||||
symbolName
|
||||
);
|
||||
}
|
||||
|
||||
export function addDeclarationToModule(
|
||||
source: ts.SourceFile,
|
||||
modulePath: string,
|
||||
symbolName: string
|
||||
): Change[] {
|
||||
return _addSymbolToNgModuleMetadata(
|
||||
source,
|
||||
modulePath,
|
||||
'declarations',
|
||||
symbolName
|
||||
);
|
||||
}
|
||||
|
||||
export function addEntryComponents(
|
||||
source: ts.SourceFile,
|
||||
modulePath: string,
|
||||
symbolName: string
|
||||
): Change[] {
|
||||
return _addSymbolToNgModuleMetadata(
|
||||
source,
|
||||
modulePath,
|
||||
'entryComponents',
|
||||
symbolName
|
||||
);
|
||||
}
|
||||
|
||||
export function addGlobal(
|
||||
source: ts.SourceFile,
|
||||
modulePath: string,
|
||||
statement: string
|
||||
): Change[] {
|
||||
const allImports = findNodes(source, ts.SyntaxKind.ImportDeclaration);
|
||||
if (allImports.length > 0) {
|
||||
const lastImport = allImports[allImports.length - 1];
|
||||
return [
|
||||
new InsertChange(modulePath, lastImport.end + 1, `\n${statement}\n`)
|
||||
];
|
||||
} else {
|
||||
return [new InsertChange(modulePath, 0, `${statement}\n`)];
|
||||
}
|
||||
}
|
||||
|
||||
export function insert(host: Tree, modulePath: string, changes: Change[]) {
|
||||
const recorder = host.beginUpdate(modulePath);
|
||||
for (const change of changes) {
|
||||
if (change instanceof InsertChange) {
|
||||
recorder.insertLeft(change.pos, change.toAdd);
|
||||
} else if (change instanceof RemoveChange) {
|
||||
recorder.remove((<any>change).pos - 1, (<any>change).toRemove.length + 1);
|
||||
} else if (change instanceof NoopChange) {
|
||||
// do nothing
|
||||
} else {
|
||||
throw new Error(`Unexpected Change '${change}'`);
|
||||
}
|
||||
}
|
||||
host.commitUpdate(recorder);
|
||||
}
|
||||
|
||||
/**
|
||||
* This method is specifically for reading JSON files in a Tree
|
||||
* @param host The host tree
|
||||
* @param path The path to the JSON file
|
||||
* @returns The JSON data in the file.
|
||||
*/
|
||||
export function readJsonInTree<T = any>(host: Tree, path: string): T {
|
||||
if (!host.exists(path)) {
|
||||
throw new Error(`Cannot find ${path}`);
|
||||
}
|
||||
return JSON.parse(host.read(path)!.toString('utf-8'));
|
||||
}
|
||||
|
||||
/**
|
||||
* This method is specifically for updating JSON in a Tree
|
||||
* @param path Path of JSON file in the Tree
|
||||
* @param callback Manipulation of the JSON data
|
||||
* @returns A rule which updates a JSON file file in a Tree
|
||||
*/
|
||||
export function updateJsonInTree<T = any, O = T>(
|
||||
path: string,
|
||||
callback: (json: T) => O
|
||||
): Rule {
|
||||
return (host: Tree): Tree => {
|
||||
host.overwrite(path, serializeJson(callback(readJsonInTree(host, path))));
|
||||
return host;
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* This method is specifically for getting the .angular-cli.json data from a Tree
|
||||
* @param host The host tree
|
||||
*/
|
||||
export function getAngularCliConfig(host: Tree) {
|
||||
return readJsonInTree(host, '.angular-cli.json');
|
||||
}
|
||||
|
||||
export function getAppConfig(host: Tree, name: string): any {
|
||||
const angularCliJson = getAngularCliConfig(host);
|
||||
const apps = angularCliJson.apps;
|
||||
if (!apps || apps.length === 0) {
|
||||
throw new Error(`Cannot find app '${name}'`);
|
||||
}
|
||||
if (name) {
|
||||
const appConfig = apps.filter(a => a.name === name)[0];
|
||||
if (!appConfig) {
|
||||
throw new Error(`Cannot find app '${name}'`);
|
||||
} else {
|
||||
return appConfig;
|
||||
}
|
||||
}
|
||||
return apps[0];
|
||||
}
|
||||
|
||||
export function readBootstrapInfo(
|
||||
host: Tree,
|
||||
app: string
|
||||
): {
|
||||
moduleSpec: string;
|
||||
modulePath: string;
|
||||
mainPath: string;
|
||||
moduleClassName: string;
|
||||
moduleSource: ts.SourceFile;
|
||||
bootstrapComponentClassName: string;
|
||||
bootstrapComponentFileName: string;
|
||||
} {
|
||||
const config = getAppConfig(host, app);
|
||||
const mainPath = path.join(config.root, config.main);
|
||||
if (!host.exists(mainPath)) {
|
||||
throw new Error('Main file cannot be located');
|
||||
}
|
||||
|
||||
const mainSource = host.read(mainPath)!.toString('utf-8');
|
||||
const main = ts.createSourceFile(
|
||||
mainPath,
|
||||
mainSource,
|
||||
ts.ScriptTarget.Latest,
|
||||
true
|
||||
);
|
||||
const moduleImports = getImport(
|
||||
main,
|
||||
(s: string) => s.indexOf('.module') > -1
|
||||
);
|
||||
if (moduleImports.length !== 1) {
|
||||
throw new Error(`main.ts can only import a single module`);
|
||||
}
|
||||
const moduleImport = moduleImports[0];
|
||||
const moduleClassName = moduleImport.bindings.filter(b =>
|
||||
b.endsWith('Module')
|
||||
)[0];
|
||||
|
||||
const modulePath = `${path.join(
|
||||
path.dirname(mainPath),
|
||||
moduleImport.moduleSpec
|
||||
)}.ts`;
|
||||
if (!host.exists(modulePath)) {
|
||||
throw new Error(`Cannot find '${modulePath}'`);
|
||||
}
|
||||
|
||||
const moduleSourceText = host.read(modulePath)!.toString('utf-8');
|
||||
const moduleSource = ts.createSourceFile(
|
||||
modulePath,
|
||||
moduleSourceText,
|
||||
ts.ScriptTarget.Latest,
|
||||
true
|
||||
);
|
||||
|
||||
const bootstrapComponentClassName = getBootstrapComponent(
|
||||
moduleSource,
|
||||
moduleClassName
|
||||
);
|
||||
const bootstrapComponentFileName = `./${path.join(
|
||||
path.dirname(moduleImport.moduleSpec),
|
||||
`${toFileName(
|
||||
bootstrapComponentClassName.substring(
|
||||
0,
|
||||
bootstrapComponentClassName.length - 9
|
||||
)
|
||||
)}.component`
|
||||
)}`;
|
||||
|
||||
return {
|
||||
moduleSpec: moduleImport.moduleSpec,
|
||||
mainPath,
|
||||
modulePath,
|
||||
moduleSource,
|
||||
moduleClassName,
|
||||
bootstrapComponentClassName,
|
||||
bootstrapComponentFileName
|
||||
};
|
||||
}
|
||||
@ -1,43 +0,0 @@
|
||||
import * as yargsParser from 'yargs-parser';
|
||||
|
||||
import { readJsonFile } from './fileutils';
|
||||
|
||||
export function getAppDirectoryUsingCliConfig() {
|
||||
const cli = readJsonFile(process.cwd() + '/.angular-cli.json');
|
||||
|
||||
const appName = getAppName();
|
||||
|
||||
if (appName) {
|
||||
const app = cli.apps.find(a => a.name === appName);
|
||||
if (!app) {
|
||||
console.error(`Cannot find app '${appName}'.`);
|
||||
process.exit(1);
|
||||
} else if (app.root.startsWith('libs')) {
|
||||
console.error(`Cannot run e2e tests for a library.`);
|
||||
process.exit(1);
|
||||
} else {
|
||||
return `apps/${appName}`;
|
||||
}
|
||||
} else {
|
||||
console.error(`Please provide the app name using --app or -a.`);
|
||||
process.exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
export function makeSureNoAppIsSelected() {
|
||||
if (getAppName()) {
|
||||
console.error('Nx only supports running unit tests for all apps and libs.');
|
||||
console.error('You cannot use -a or --app.');
|
||||
console.error('Use fdescribe or fit to select a subset of tests to run.');
|
||||
process.exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
function getAppName() {
|
||||
return yargsParser(process.argv, {
|
||||
alias: {
|
||||
app: ['a']
|
||||
},
|
||||
string: ['app']
|
||||
}).app;
|
||||
}
|
||||
@ -1,44 +0,0 @@
|
||||
import { Options } from 'prettier';
|
||||
import * as cosmiconfig from 'cosmiconfig';
|
||||
|
||||
export function offsetFromRoot(fullPathToSourceDir: string): string {
|
||||
const parts = fullPathToSourceDir.split('/');
|
||||
let offset = '';
|
||||
for (let i = 0; i < parts.length; ++i) {
|
||||
offset += '../';
|
||||
}
|
||||
return offset;
|
||||
}
|
||||
|
||||
export const DEFAULT_NRWL_PRETTIER_CONFIG = {
|
||||
singleQuote: true
|
||||
};
|
||||
|
||||
export interface ExistingPrettierConfig {
|
||||
sourceFilepath: string;
|
||||
config: Options;
|
||||
}
|
||||
|
||||
export function resolveUserExistingPrettierConfig(): Promise<ExistingPrettierConfig | null> {
|
||||
const explorer = cosmiconfig('prettier', {
|
||||
sync: true,
|
||||
cache: false,
|
||||
rcExtensions: true,
|
||||
stopDir: process.cwd(),
|
||||
transform: result => {
|
||||
if (result && result.config) {
|
||||
delete result.config.$schema;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
});
|
||||
return Promise.resolve(explorer.load(process.cwd())).then(result => {
|
||||
if (!result) {
|
||||
return null;
|
||||
}
|
||||
return {
|
||||
sourceFilepath: result.filepath,
|
||||
config: result.config
|
||||
};
|
||||
});
|
||||
}
|
||||
@ -1,41 +0,0 @@
|
||||
import { addApp } from './fileutils';
|
||||
|
||||
describe('fileutils', () => {
|
||||
describe('sortApps', () => {
|
||||
it('should handle undefined', () => {
|
||||
expect(addApp(undefined, { name: 'a' })).toEqual([{ name: 'a' }]);
|
||||
});
|
||||
|
||||
it('should handle an empty array', () => {
|
||||
expect(addApp([], { name: 'a' })).toEqual([{ name: 'a' }]);
|
||||
});
|
||||
|
||||
it('should sort apps by name', () => {
|
||||
expect(addApp([{ name: 'a' }, { name: 'b' }], { name: 'c' })).toEqual([
|
||||
{ name: 'a' },
|
||||
{ name: 'b' },
|
||||
{ name: 'c' }
|
||||
]);
|
||||
});
|
||||
|
||||
it('should put workspaceRoot last', () => {
|
||||
expect(
|
||||
addApp([{ name: 'a' }, { name: 'z' }], { name: '$workspaceRoot' })
|
||||
).toEqual([{ name: 'a' }, { name: 'z' }, { name: '$workspaceRoot' }]);
|
||||
});
|
||||
|
||||
it('should prioritize apps with "main" defined', () => {
|
||||
expect(
|
||||
addApp([{ name: 'c' }, { name: 'a' }, { name: 'a', main: 'a' }], {
|
||||
name: 'b',
|
||||
main: 'b'
|
||||
})
|
||||
).toEqual([
|
||||
{ name: 'a', main: 'a' },
|
||||
{ name: 'b', main: 'b' },
|
||||
{ name: 'a' },
|
||||
{ name: 'c' }
|
||||
]);
|
||||
});
|
||||
});
|
||||
});
|
||||
@ -1,79 +0,0 @@
|
||||
import * as fs from 'fs';
|
||||
import * as path from 'path';
|
||||
|
||||
export function writeToFile(path: string, str: string) {
|
||||
fs.writeFileSync(path, str);
|
||||
}
|
||||
|
||||
/**
|
||||
* This method is specifically for updating a JSON file using the filesystem
|
||||
*
|
||||
* @remarks
|
||||
* If you are looking to update a JSON file in a tree, look for ./ast-utils#updateJsonInTree
|
||||
* @param path Path of the JSON file on the filesystem
|
||||
* @param callback Manipulation of the JSON data
|
||||
*/
|
||||
export function updateJsonFile(path: string, callback: (a: any) => any) {
|
||||
const json = readJsonFile(path);
|
||||
callback(json);
|
||||
writeToFile(path, JSON.stringify(json, null, 2));
|
||||
}
|
||||
|
||||
export function addApp(apps: any[] | undefined, newApp: any): any[] {
|
||||
if (!apps) {
|
||||
apps = [];
|
||||
}
|
||||
apps.push(newApp);
|
||||
|
||||
apps.sort((a: any, b: any) => {
|
||||
if (a.name === '$workspaceRoot') return 1;
|
||||
if (b.name === '$workspaceRoot') return -1;
|
||||
if (a.main && !b.main) return -1;
|
||||
if (!a.main && b.main) return 1;
|
||||
if (a.name > b.name) return 1;
|
||||
return -1;
|
||||
});
|
||||
|
||||
return apps;
|
||||
}
|
||||
|
||||
export function serializeJson(json: any): string {
|
||||
return `${JSON.stringify(json, null, 2)}\n`;
|
||||
}
|
||||
|
||||
/**
|
||||
* This method is specifically for reading a JSON file from the filesystem
|
||||
*
|
||||
* @remarks
|
||||
* If you are looking to read a JSON file in a Tree, use ./ast-utils#readJsonInTree
|
||||
* @param path Path of the JSON file on the filesystem
|
||||
*/
|
||||
export function readJsonFile(path: string): any {
|
||||
return JSON.parse(fs.readFileSync(path, 'utf-8'));
|
||||
}
|
||||
|
||||
export function readCliConfigFile(): any {
|
||||
return readJsonFile('.angular-cli.json');
|
||||
}
|
||||
|
||||
export function copyFile(file: string, target: string) {
|
||||
const f = path.basename(file);
|
||||
const source = fs.createReadStream(file);
|
||||
const dest = fs.createWriteStream(path.resolve(target, f));
|
||||
source.pipe(dest);
|
||||
source.on('error', e => console.error(e));
|
||||
}
|
||||
|
||||
function directoryExists(name) {
|
||||
try {
|
||||
return fs.statSync(name).isDirectory();
|
||||
} catch (e) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
export function createDirectory(name: string) {
|
||||
if (!directoryExists(name)) {
|
||||
fs.mkdirSync(name);
|
||||
}
|
||||
}
|
||||
@ -1,31 +0,0 @@
|
||||
export function names(name: string): any {
|
||||
return {
|
||||
name,
|
||||
className: toClassName(name),
|
||||
propertyName: toPropertyName(name),
|
||||
fileName: toFileName(name)
|
||||
};
|
||||
}
|
||||
|
||||
export function toClassName(str: string): string {
|
||||
return toCapitalCase(toPropertyName(str));
|
||||
}
|
||||
|
||||
export function toPropertyName(s: string): string {
|
||||
return s
|
||||
.replace(/(-|_|\.|\s)+(.)?/g, (_, __, chr) =>
|
||||
chr ? chr.toUpperCase() : ''
|
||||
)
|
||||
.replace(/^([A-Z])/, m => m.toLowerCase());
|
||||
}
|
||||
|
||||
export function toFileName(s: string): string {
|
||||
return s
|
||||
.replace(/([a-z\d])([A-Z])/g, '$1_$2')
|
||||
.toLowerCase()
|
||||
.replace(/[ _]/g, '-');
|
||||
}
|
||||
|
||||
function toCapitalCase(s: string): string {
|
||||
return s.charAt(0).toUpperCase() + s.substr(1);
|
||||
}
|
||||
@ -1,40 +0,0 @@
|
||||
import { readJsonInTree } from '../ast-utils';
|
||||
import {
|
||||
TaskConfigurationGenerator,
|
||||
TaskConfiguration,
|
||||
Tree,
|
||||
SchematicContext,
|
||||
Rule,
|
||||
noop
|
||||
} from '@angular-devkit/schematics';
|
||||
|
||||
class FormatFiles implements TaskConfigurationGenerator<any> {
|
||||
toConfiguration(): TaskConfiguration<any> {
|
||||
return {
|
||||
name: 'node-package',
|
||||
options: {
|
||||
packageName: 'run format -- --untracked', // workaround. we should define a custom task executor.
|
||||
quiet: true
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
export function formatFiles(options: { skipFormat: boolean }): Rule {
|
||||
if (options.skipFormat) {
|
||||
return noop();
|
||||
}
|
||||
return (host: Tree, context: SchematicContext) => {
|
||||
const packageJson = readJsonInTree(host, 'package.json');
|
||||
if (packageJson.scripts && packageJson.scripts.format) {
|
||||
context.addTask(new FormatFiles());
|
||||
} else {
|
||||
context.logger.warn(
|
||||
'The "format" npm script is missing in your package.json'
|
||||
);
|
||||
context.logger.warn(
|
||||
'Your files were not formated during this code generation'
|
||||
);
|
||||
}
|
||||
};
|
||||
}
|
||||
@ -1,88 +0,0 @@
|
||||
import { Tree } from '@angular-devkit/schematics';
|
||||
|
||||
export function createEmptyWorkspace(tree: Tree): Tree {
|
||||
tree.create('/.angular-cli.json', JSON.stringify({}));
|
||||
tree.create('/package.json', JSON.stringify({}));
|
||||
tree.create(
|
||||
'/tslint.json',
|
||||
JSON.stringify({
|
||||
rules: {
|
||||
'nx-enforce-module-boundaries': [
|
||||
true,
|
||||
{
|
||||
npmScope: '<%= npmScope %>',
|
||||
lazyLoad: [],
|
||||
allow: []
|
||||
}
|
||||
]
|
||||
}
|
||||
})
|
||||
);
|
||||
return tree;
|
||||
}
|
||||
|
||||
export function createApp(tree: Tree, appName: string): Tree {
|
||||
tree.create(
|
||||
`/apps/${appName}/src/app/app.module.ts`,
|
||||
`
|
||||
import { NgModule } from '@angular/core';
|
||||
import { BrowserModule } from '@angular/platform-browser';
|
||||
import { RouterModule } from '@angular/router';
|
||||
import { AppComponent } from './app.component';
|
||||
@NgModule({
|
||||
imports: [BrowserModule, RouterModule.forRoot([])],
|
||||
declarations: [AppComponent],
|
||||
bootstrap: [AppComponent]
|
||||
})
|
||||
export class AppModule {}
|
||||
`
|
||||
);
|
||||
tree.create(
|
||||
`/apps/${appName}/src/main.ts`,
|
||||
`
|
||||
import { enableProdMode } from '@angular/core';
|
||||
import { platformBrowserDynamic } from '@angular/platform-browser-dynamic';
|
||||
|
||||
import { AppModule } from './app/app.module';
|
||||
import { environment } from './environments/environment';
|
||||
|
||||
if (environment.production) {
|
||||
enableProdMode();
|
||||
}
|
||||
|
||||
platformBrowserDynamic()
|
||||
.bootstrapModule(AppModule)
|
||||
.catch(err => console.log(err));
|
||||
`
|
||||
);
|
||||
tree.create(
|
||||
`/apps/${appName}/src/tsconfig.app.json`,
|
||||
JSON.stringify({
|
||||
include: ['**/*.ts']
|
||||
})
|
||||
);
|
||||
tree.create(
|
||||
`/apps/${appName}/e2e/tsconfig.e2e.json`,
|
||||
JSON.stringify({
|
||||
include: ['../**/*.ts']
|
||||
})
|
||||
);
|
||||
tree.overwrite(
|
||||
'/.angular-cli.json',
|
||||
JSON.stringify({
|
||||
project: {
|
||||
name: 'proj',
|
||||
npmScope: 'proj'
|
||||
},
|
||||
apps: [
|
||||
{
|
||||
name: appName,
|
||||
root: `apps/${appName}/src`,
|
||||
main: 'main.ts',
|
||||
index: 'index.html'
|
||||
}
|
||||
]
|
||||
})
|
||||
);
|
||||
return tree;
|
||||
}
|
||||
Loading…
x
Reference in New Issue
Block a user