switch to prettier
This commit is contained in:
parent
bc548c596e
commit
a43fbaeb9a
@ -1,3 +0,0 @@
|
||||
Language: JavaScript
|
||||
BasedOnStyle: Google
|
||||
ColumnLimit: 120
|
||||
@ -1,4 +1,4 @@
|
||||
import {checkFilesExist, cleanup, copyMissingPackages, ngNewBazel, readFile, runCLI, runSchematic} from '../utils';
|
||||
import { checkFilesExist, cleanup, copyMissingPackages, ngNewBazel, readFile, runCLI, runSchematic } from '../utils';
|
||||
|
||||
describe('application', () => {
|
||||
beforeEach(cleanup);
|
||||
@ -9,8 +9,14 @@ describe('application', () => {
|
||||
runSchematic('@nrwl/bazel:app --name=myApp');
|
||||
|
||||
checkFilesExist(
|
||||
`tsconfig.json`, `WORKSPACE`, `BUILD.bazel`, `apps/my-app/BUILD.bazel`, `apps/my-app/src/index.html`,
|
||||
`apps/my-app/src/app/app.module.ts`, `apps/my-app/src/app/app.component.ts`);
|
||||
`tsconfig.json`,
|
||||
`WORKSPACE`,
|
||||
`BUILD.bazel`,
|
||||
`apps/my-app/BUILD.bazel`,
|
||||
`apps/my-app/src/index.html`,
|
||||
`apps/my-app/src/app/app.module.ts`,
|
||||
`apps/my-app/src/app/app.component.ts`
|
||||
);
|
||||
|
||||
expect(readFile('apps/my-app/src/app/app.module.ts')).toContain('bootstrap: [AppComponent]');
|
||||
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
import {checkFilesExist, cleanup, copyMissingPackages, ngNewBazel, readFile, runCLI, runSchematic} from '../utils';
|
||||
import { checkFilesExist, cleanup, copyMissingPackages, ngNewBazel, readFile, runCLI, runSchematic } from '../utils';
|
||||
|
||||
describe('library', () => {
|
||||
beforeEach(cleanup);
|
||||
@ -9,8 +9,13 @@ describe('library', () => {
|
||||
runSchematic('@nrwl/bazel:lib --name=myLib');
|
||||
|
||||
checkFilesExist(
|
||||
'tsconfig.json', 'WORKSPACE', 'BUILD.bazel', 'libs/my-lib/BUILD.bazel', 'libs/my-lib/index.ts',
|
||||
'libs/my-lib/src/my-lib.ts');
|
||||
'tsconfig.json',
|
||||
'WORKSPACE',
|
||||
'BUILD.bazel',
|
||||
'libs/my-lib/BUILD.bazel',
|
||||
'libs/my-lib/index.ts',
|
||||
'libs/my-lib/src/my-lib.ts'
|
||||
);
|
||||
|
||||
const cliConfig = JSON.parse(readFile('.angular-cli.json'));
|
||||
expect(cliConfig.apps[0].name).toEqual('myLib');
|
||||
|
||||
@ -1,4 +1,15 @@
|
||||
import {checkFilesExist, cleanup, copyMissingPackages, ngNew, ngNewBazel, readFile, runCLI, runCommand, runSchematic, updateFile} from '../utils';
|
||||
import {
|
||||
checkFilesExist,
|
||||
cleanup,
|
||||
copyMissingPackages,
|
||||
ngNew,
|
||||
ngNewBazel,
|
||||
readFile,
|
||||
runCLI,
|
||||
runCommand,
|
||||
runSchematic,
|
||||
updateFile
|
||||
} from '../utils';
|
||||
|
||||
describe('angular library', () => {
|
||||
beforeEach(cleanup);
|
||||
@ -9,8 +20,13 @@ describe('angular library', () => {
|
||||
runSchematic('@nrwl/bazel:nglib --name=myLib');
|
||||
|
||||
checkFilesExist(
|
||||
'tsconfig.json', 'WORKSPACE', 'BUILD.bazel', 'libs/my-lib/BUILD.bazel', 'libs/my-lib/index.ts',
|
||||
'libs/my-lib/src/my-lib.module.ts');
|
||||
'tsconfig.json',
|
||||
'WORKSPACE',
|
||||
'BUILD.bazel',
|
||||
'libs/my-lib/BUILD.bazel',
|
||||
'libs/my-lib/index.ts',
|
||||
'libs/my-lib/src/my-lib.module.ts'
|
||||
);
|
||||
|
||||
const cliConfig = JSON.parse(readFile('.angular-cli.json'));
|
||||
expect(cliConfig.apps[0].name).toEqual('myLib');
|
||||
|
||||
@ -1,4 +1,15 @@
|
||||
import {checkFilesExist, cleanup, copyMissingPackages, ngNew, ngNewBazel, readFile, runCLI, runCommand, runSchematic, updateFile} from '../utils';
|
||||
import {
|
||||
checkFilesExist,
|
||||
cleanup,
|
||||
copyMissingPackages,
|
||||
ngNew,
|
||||
ngNewBazel,
|
||||
readFile,
|
||||
runCLI,
|
||||
runCommand,
|
||||
runSchematic,
|
||||
updateFile
|
||||
} from '../utils';
|
||||
|
||||
describe('workspace', () => {
|
||||
beforeEach(cleanup);
|
||||
|
||||
@ -1,4 +1,14 @@
|
||||
import {checkFilesExist, cleanup, copyMissingPackages, newApp, newLib, ngNew, readFile, runCLI, updateFile} from '../utils';
|
||||
import {
|
||||
checkFilesExist,
|
||||
cleanup,
|
||||
copyMissingPackages,
|
||||
newApp,
|
||||
newLib,
|
||||
ngNew,
|
||||
readFile,
|
||||
runCLI,
|
||||
updateFile
|
||||
} from '../utils';
|
||||
|
||||
describe('Nrwl Workspace', () => {
|
||||
beforeEach(cleanup);
|
||||
@ -16,6 +26,7 @@ describe('Nrwl Workspace', () => {
|
||||
expect(packageJson.dependencies['@ngrx/effects']).toBeDefined();
|
||||
expect(packageJson.dependencies['@ngrx/router-store']).toBeDefined();
|
||||
expect(packageJson.dependencies['@ngrx/store-devtools']).toBeDefined();
|
||||
|
||||
checkFilesExist('test.js', 'tsconfig.app.json', 'tsconfig.spec.json', 'tsconfig.e2e.json', 'apps', 'libs');
|
||||
});
|
||||
|
||||
@ -28,18 +39,25 @@ describe('Nrwl Workspace', () => {
|
||||
expect(angularCliJson.apps[0].name).toEqual('myapp');
|
||||
|
||||
checkFilesExist(
|
||||
'apps/myapp/src/main.ts', 'apps/myapp/src/app/app.module.ts', 'apps/myapp/src/app/app.component.ts',
|
||||
'apps/myapp/e2e/app.po.ts');
|
||||
'apps/myapp/src/main.ts',
|
||||
'apps/myapp/src/app/app.module.ts',
|
||||
'apps/myapp/src/app/app.component.ts',
|
||||
'apps/myapp/e2e/app.po.ts'
|
||||
);
|
||||
});
|
||||
|
||||
it('should build app', () => {
|
||||
ngNew('--collection=@nrwl/schematics');
|
||||
copyMissingPackages();
|
||||
newApp('myapp');
|
||||
runCLI('build --aot');
|
||||
checkFilesExist('dist/apps/myapp/main.bundle.js');
|
||||
expect(runCLI('test --single-run')).toContain('Executed 1 of 1 SUCCESS');
|
||||
}, 100000);
|
||||
it(
|
||||
'should build app',
|
||||
() => {
|
||||
ngNew('--collection=@nrwl/schematics');
|
||||
copyMissingPackages();
|
||||
newApp('myapp');
|
||||
runCLI('build --aot');
|
||||
checkFilesExist('dist/apps/myapp/main.bundle.js');
|
||||
expect(runCLI('test --single-run')).toContain('Executed 1 of 1 SUCCESS');
|
||||
},
|
||||
100000
|
||||
);
|
||||
});
|
||||
|
||||
describe('lib', () => {
|
||||
@ -53,14 +71,18 @@ describe('Nrwl Workspace', () => {
|
||||
checkFilesExist('libs/mylib/src/mylib.ts', 'libs/mylib/src/mylib.spec.ts', 'libs/mylib/index.ts');
|
||||
});
|
||||
|
||||
it('should test a lib', () => {
|
||||
ngNew('--collection=@nrwl/schematics');
|
||||
copyMissingPackages();
|
||||
newApp('myapp');
|
||||
newLib('generate lib mylib');
|
||||
it(
|
||||
'should test a lib',
|
||||
() => {
|
||||
ngNew('--collection=@nrwl/schematics');
|
||||
copyMissingPackages();
|
||||
newApp('myapp');
|
||||
newLib('generate lib mylib');
|
||||
|
||||
expect(runCLI('test --single-run')).toContain('Executed 2 of 2 SUCCESS');
|
||||
}, 100000);
|
||||
expect(runCLI('test --single-run')).toContain('Executed 2 of 2 SUCCESS');
|
||||
},
|
||||
100000
|
||||
);
|
||||
});
|
||||
|
||||
describe('nglib', () => {
|
||||
@ -71,22 +93,30 @@ describe('Nrwl Workspace', () => {
|
||||
checkFilesExist('libs/mylib/src/mylib.module.ts', 'libs/mylib/src/mylib.module.spec.ts', 'libs/mylib/index.ts');
|
||||
});
|
||||
|
||||
it('should test an ng lib', () => {
|
||||
ngNew('--collection=@nrwl/schematics');
|
||||
copyMissingPackages();
|
||||
newApp('myapp');
|
||||
newLib('mylib --ngmodule');
|
||||
it(
|
||||
'should test an ng lib',
|
||||
() => {
|
||||
ngNew('--collection=@nrwl/schematics');
|
||||
copyMissingPackages();
|
||||
newApp('myapp');
|
||||
newLib('mylib --ngmodule');
|
||||
|
||||
expect(runCLI('test --single-run')).toContain('Executed 2 of 2 SUCCESS');
|
||||
}, 100000);
|
||||
expect(runCLI('test --single-run')).toContain('Executed 2 of 2 SUCCESS');
|
||||
},
|
||||
100000
|
||||
);
|
||||
|
||||
it('should resolve dependencies on the lib', () => {
|
||||
ngNew('--collection=@nrwl/schematics --npmScope=nrwl');
|
||||
copyMissingPackages();
|
||||
newApp('myapp');
|
||||
newLib('mylib --ngmodule');
|
||||
it(
|
||||
'should resolve dependencies on the lib',
|
||||
() => {
|
||||
ngNew('--collection=@nrwl/schematics --npmScope=nrwl');
|
||||
copyMissingPackages();
|
||||
newApp('myapp');
|
||||
newLib('mylib --ngmodule');
|
||||
|
||||
updateFile('apps/myapp/src/app/app.module.ts', `
|
||||
updateFile(
|
||||
'apps/myapp/src/app/app.module.ts',
|
||||
`
|
||||
import { NgModule } from '@angular/core';
|
||||
import { BrowserModule } from '@angular/platform-browser';
|
||||
import { MylibModule } from '@nrwl/mylib';
|
||||
@ -98,9 +128,12 @@ describe('Nrwl Workspace', () => {
|
||||
bootstrap: [AppComponent]
|
||||
})
|
||||
export class AppModule {}
|
||||
`);
|
||||
`
|
||||
);
|
||||
|
||||
runCLI('build --aot');
|
||||
}, 100000);
|
||||
runCLI('build --aot');
|
||||
},
|
||||
100000
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
import {checkFilesExist, cleanup, copyMissingPackages, ngNew, readFile, runCLI} from '../utils';
|
||||
import { checkFilesExist, cleanup, copyMissingPackages, ngNew, readFile, runCLI } from '../utils';
|
||||
|
||||
describe('ngrx', () => {
|
||||
beforeEach(cleanup);
|
||||
@ -9,35 +9,48 @@ describe('ngrx', () => {
|
||||
runCLI('generate ngrx app --module=src/app/app.module.ts --root --collection=@nrwl/schematics');
|
||||
|
||||
checkFilesExist(
|
||||
`src/app/+state/app.actions.ts`, `src/app/+state/app.effects.ts`, `src/app/+state/app.effects.spec.ts`,
|
||||
`src/app/+state/app.init.ts`, `src/app/+state/app.interfaces.ts`, `src/app/+state/app.reducer.ts`,
|
||||
`src/app/+state/app.reducer.spec.ts`);
|
||||
`src/app/+state/app.actions.ts`,
|
||||
`src/app/+state/app.effects.ts`,
|
||||
`src/app/+state/app.effects.spec.ts`,
|
||||
`src/app/+state/app.init.ts`,
|
||||
`src/app/+state/app.interfaces.ts`,
|
||||
`src/app/+state/app.reducer.ts`,
|
||||
`src/app/+state/app.reducer.spec.ts`
|
||||
);
|
||||
|
||||
const contents = readFile('src/app/app.module.ts');
|
||||
expect(contents).toContain('StoreModule.forRoot');
|
||||
expect(contents).toContain('EffectsModule.forRoot');
|
||||
});
|
||||
|
||||
it('should build', () => {
|
||||
ngNew();
|
||||
copyMissingPackages();
|
||||
runCLI('generate ngrx app --module=src/app/app.module.ts --root --collection=@nrwl/schematics');
|
||||
it(
|
||||
'should build',
|
||||
() => {
|
||||
ngNew();
|
||||
copyMissingPackages();
|
||||
runCLI('generate ngrx app --module=src/app/app.module.ts --root --collection=@nrwl/schematics');
|
||||
|
||||
runCLI('build');
|
||||
runCLI('test --single-run');
|
||||
}, 100000);
|
||||
runCLI('build');
|
||||
runCLI('test --single-run');
|
||||
},
|
||||
100000
|
||||
);
|
||||
|
||||
it('should add empty root configuration', () => {
|
||||
ngNew();
|
||||
copyMissingPackages();
|
||||
runCLI('generate ngrx app --module=src/app/app.module.ts --onlyEmptyRoot --collection=@nrwl/schematics');
|
||||
it(
|
||||
'should add empty root configuration',
|
||||
() => {
|
||||
ngNew();
|
||||
copyMissingPackages();
|
||||
runCLI('generate ngrx app --module=src/app/app.module.ts --onlyEmptyRoot --collection=@nrwl/schematics');
|
||||
|
||||
const contents = readFile('src/app/app.module.ts');
|
||||
expect(contents).toContain('StoreModule.forRoot');
|
||||
expect(contents).toContain('EffectsModule.forRoot');
|
||||
const contents = readFile('src/app/app.module.ts');
|
||||
expect(contents).toContain('StoreModule.forRoot');
|
||||
expect(contents).toContain('EffectsModule.forRoot');
|
||||
|
||||
runCLI('build');
|
||||
}, 100000);
|
||||
runCLI('build');
|
||||
},
|
||||
100000
|
||||
);
|
||||
});
|
||||
|
||||
describe('feature', () => {
|
||||
@ -46,9 +59,14 @@ describe('ngrx', () => {
|
||||
runCLI('generate ngrx app --module=src/app/app.module.ts --collection=@nrwl/schematics');
|
||||
|
||||
checkFilesExist(
|
||||
`src/app/+state/app.actions.ts`, `src/app/+state/app.effects.ts`, `src/app/+state/app.effects.spec.ts`,
|
||||
`src/app/+state/app.init.ts`, `src/app/+state/app.interfaces.ts`, `src/app/+state/app.reducer.ts`,
|
||||
`src/app/+state/app.reducer.spec.ts`);
|
||||
`src/app/+state/app.actions.ts`,
|
||||
`src/app/+state/app.effects.ts`,
|
||||
`src/app/+state/app.effects.spec.ts`,
|
||||
`src/app/+state/app.init.ts`,
|
||||
`src/app/+state/app.interfaces.ts`,
|
||||
`src/app/+state/app.reducer.ts`,
|
||||
`src/app/+state/app.reducer.spec.ts`
|
||||
);
|
||||
|
||||
const contents = readFile('src/app/app.module.ts');
|
||||
expect(contents).toContain('StoreModule.forFeature');
|
||||
@ -61,9 +79,14 @@ describe('ngrx', () => {
|
||||
runCLI('generate ngrx app --module=src/app/app.module.ts --onlyAddFiles --collection=@nrwl/schematics');
|
||||
|
||||
checkFilesExist(
|
||||
`src/app/+state/app.actions.ts`, `src/app/+state/app.effects.ts`, `src/app/+state/app.effects.spec.ts`,
|
||||
`src/app/+state/app.init.ts`, `src/app/+state/app.interfaces.ts`, `src/app/+state/app.reducer.ts`,
|
||||
`src/app/+state/app.reducer.spec.ts`);
|
||||
`src/app/+state/app.actions.ts`,
|
||||
`src/app/+state/app.effects.ts`,
|
||||
`src/app/+state/app.effects.spec.ts`,
|
||||
`src/app/+state/app.init.ts`,
|
||||
`src/app/+state/app.interfaces.ts`,
|
||||
`src/app/+state/app.reducer.ts`,
|
||||
`src/app/+state/app.reducer.spec.ts`
|
||||
);
|
||||
|
||||
const contents = readFile('src/app/app.module.ts');
|
||||
expect(contents).not.toContain('StoreModule');
|
||||
|
||||
@ -1,26 +1,43 @@
|
||||
import {checkFilesExist, cleanup, copyMissingPackages, newApp, newLib, ngNew, readFile, runCLI, updateFile} from '../utils';
|
||||
import {
|
||||
checkFilesExist,
|
||||
cleanup,
|
||||
copyMissingPackages,
|
||||
newApp,
|
||||
newLib,
|
||||
ngNew,
|
||||
readFile,
|
||||
runCLI,
|
||||
updateFile
|
||||
} from '../utils';
|
||||
|
||||
describe('Lint', () => {
|
||||
beforeEach(cleanup);
|
||||
|
||||
it('should ensure module boundaries', () => {
|
||||
ngNew('--collection=@nrwl/schematics');
|
||||
copyMissingPackages();
|
||||
newApp('myapp');
|
||||
newLib('mylib');
|
||||
newLib('lazylib');
|
||||
it(
|
||||
'should ensure module boundaries',
|
||||
() => {
|
||||
ngNew('--collection=@nrwl/schematics');
|
||||
copyMissingPackages();
|
||||
newApp('myapp');
|
||||
newLib('mylib');
|
||||
newLib('lazylib');
|
||||
|
||||
const tslint = JSON.parse(readFile('tslint.json'));
|
||||
tslint.rules['nx-enforce-module-boundaries'][1].lazyLoad.push('lazylib');
|
||||
updateFile('tslint.json', JSON.stringify(tslint, null, 2));
|
||||
const tslint = JSON.parse(readFile('tslint.json'));
|
||||
tslint.rules['nx-enforce-module-boundaries'][1].lazyLoad.push('lazylib');
|
||||
updateFile('tslint.json', JSON.stringify(tslint, null, 2));
|
||||
|
||||
updateFile('apps/myapp/src/main.ts', `
|
||||
updateFile(
|
||||
'apps/myapp/src/main.ts',
|
||||
`
|
||||
import '../../../libs/mylib';
|
||||
import '@proj/lazylib';
|
||||
`);
|
||||
`
|
||||
);
|
||||
|
||||
const out = runCLI('lint --type-check', {silenceError: true});
|
||||
expect(out).toContain('relative imports of libraries are forbidden');
|
||||
expect(out).toContain('import of lazy-loaded libraries are forbidden');
|
||||
}, 100000);
|
||||
const out = runCLI('lint --type-check', { silenceError: true });
|
||||
expect(out).toContain('relative imports of libraries are forbidden');
|
||||
expect(out).toContain('import of lazy-loaded libraries are forbidden');
|
||||
},
|
||||
100000
|
||||
);
|
||||
});
|
||||
|
||||
@ -1,39 +1,51 @@
|
||||
import {cleanup, copyMissingPackages, newApp, ngNew, readFile, runCLI, runSchematic, updateFile} from '../utils';
|
||||
import { cleanup, copyMissingPackages, newApp, ngNew, readFile, runCLI, runSchematic, updateFile } from '../utils';
|
||||
|
||||
describe('Upgrade', () => {
|
||||
beforeEach(cleanup);
|
||||
|
||||
it('should generate an upgrade shell', () => {
|
||||
ngNew('--collection=@nrwl/schematics');
|
||||
newApp('myapp');
|
||||
it(
|
||||
'should generate an upgrade shell',
|
||||
() => {
|
||||
ngNew('--collection=@nrwl/schematics');
|
||||
newApp('myapp');
|
||||
|
||||
copyMissingPackages();
|
||||
updateFile('apps/myapp/src/legacy.js', `
|
||||
copyMissingPackages();
|
||||
updateFile(
|
||||
'apps/myapp/src/legacy.js',
|
||||
`
|
||||
const angular = window.angular.module('legacy', []);
|
||||
angular.component('rootLegacyCmp', {
|
||||
template: 'Expected Value'
|
||||
});
|
||||
`);
|
||||
`
|
||||
);
|
||||
|
||||
updateFile('apps/myapp/src/app/app.component.html', `
|
||||
updateFile(
|
||||
'apps/myapp/src/app/app.component.html',
|
||||
`
|
||||
EXPECTED [<rootLegacyCmp></rootLegacyCmp>]
|
||||
`);
|
||||
`
|
||||
);
|
||||
|
||||
updateFile('apps/myapp/src/app/app.component.spec.ts', ``);
|
||||
updateFile('apps/myapp/src/app/app.component.spec.ts', ``);
|
||||
|
||||
runCLI(
|
||||
runCLI(
|
||||
'generate upgrade-shell legacy --module=apps/myapp/src/app/app.module.ts --angularJsImport=../legacy ' +
|
||||
'--angularJsCmpSelector=rootLegacyCmp');
|
||||
'--angularJsCmpSelector=rootLegacyCmp'
|
||||
);
|
||||
|
||||
runCLI('build');
|
||||
runCLI('test --single-run');
|
||||
}, 100000);
|
||||
runCLI('build');
|
||||
runCLI('test --single-run');
|
||||
},
|
||||
100000
|
||||
);
|
||||
|
||||
it('should update package.json', () => {
|
||||
ngNew('--skip-install');
|
||||
runCLI(
|
||||
'generate upgrade-shell legacy --module=src/app/app.module.ts --angularJsImport=../legacy ' +
|
||||
'--angularJsCmpSelector=rootLegacyCmp --collection=@nrwl/schematics');
|
||||
'generate upgrade-shell legacy --module=src/app/app.module.ts --angularJsImport=../legacy ' +
|
||||
'--angularJsCmpSelector=rootLegacyCmp --collection=@nrwl/schematics'
|
||||
);
|
||||
|
||||
const contents = JSON.parse(readFile('package.json'));
|
||||
expect(contents.dependencies['@angular/upgrade']).toBeDefined();
|
||||
@ -43,8 +55,9 @@ describe('Upgrade', () => {
|
||||
it('should not update package.json when --skipPackageJson', () => {
|
||||
ngNew('--skipInstall');
|
||||
runCLI(
|
||||
'generate upgrade-shell legacy --module=src/app/app.module.ts --angularJsImport=../legacy ' +
|
||||
'--angularJsCmpSelector=rootLegacyCmp --skipPackageJson --collection=@nrwl/schematics');
|
||||
'generate upgrade-shell legacy --module=src/app/app.module.ts --angularJsImport=../legacy ' +
|
||||
'--angularJsCmpSelector=rootLegacyCmp --skipPackageJson --collection=@nrwl/schematics'
|
||||
);
|
||||
|
||||
const contents = JSON.parse(readFile('package.json'));
|
||||
expect(contents.dependencies['@angular/upgrade']).not.toBeDefined();
|
||||
|
||||
@ -1,4 +1,13 @@
|
||||
import {checkFilesExist, cleanup, copyMissingPackages, ngNew, readFile, runCLI, runSchematic, updateFile} from '../utils';
|
||||
import {
|
||||
checkFilesExist,
|
||||
cleanup,
|
||||
copyMissingPackages,
|
||||
ngNew,
|
||||
readFile,
|
||||
runCLI,
|
||||
runSchematic,
|
||||
updateFile
|
||||
} from '../utils';
|
||||
|
||||
describe('Nrwl Convert to Nx Workspace', () => {
|
||||
beforeEach(cleanup);
|
||||
@ -20,7 +29,7 @@ describe('Nrwl Convert to Nx Workspace', () => {
|
||||
|
||||
// update tsconfig.json
|
||||
const tsconfigJson = JSON.parse(readFile('tsconfig.json'));
|
||||
tsconfigJson.compilerOptions.paths = {'a': ['b']};
|
||||
tsconfigJson.compilerOptions.paths = { a: ['b'] };
|
||||
updateFile('tsconfig.json', JSON.stringify(tsconfigJson, null, 2));
|
||||
|
||||
// update angular-cli.json
|
||||
@ -56,8 +65,10 @@ describe('Nrwl Convert to Nx Workspace', () => {
|
||||
|
||||
// check if tsconfig.json get merged
|
||||
const updatedTsConfig = JSON.parse(readFile('tsconfig.json'));
|
||||
expect(updatedTsConfig.compilerOptions.paths).toEqual({'a': ['b'], '@proj/*': ['libs/*']});
|
||||
|
||||
expect(updatedTsConfig.compilerOptions.paths).toEqual({
|
||||
a: ['b'],
|
||||
'@proj/*': ['libs/*']
|
||||
});
|
||||
});
|
||||
|
||||
it('should generate a workspace and not change dependencies or devDependencies if they already exist', () => {
|
||||
@ -87,14 +98,18 @@ describe('Nrwl Convert to Nx Workspace', () => {
|
||||
expect(packageJson.dependencies['@ngrx/store-devtools']).toEqual(ngrxVersion);
|
||||
});
|
||||
|
||||
it('should build and test and support the existing AngularCLI generators', () => {
|
||||
ngNew();
|
||||
copyMissingPackages();
|
||||
it(
|
||||
'should build and test and support the existing AngularCLI generators',
|
||||
() => {
|
||||
ngNew();
|
||||
copyMissingPackages();
|
||||
|
||||
runCLI('generate workspace proj --collection=@nrwl/schematics');
|
||||
runCLI('generate lib mylib --ngmodule');
|
||||
runCLI('generate workspace proj --collection=@nrwl/schematics');
|
||||
runCLI('generate lib mylib --ngmodule');
|
||||
|
||||
updateFile('apps/proj/src/app/app.module.ts', `
|
||||
updateFile(
|
||||
'apps/proj/src/app/app.module.ts',
|
||||
`
|
||||
import { NgModule } from '@angular/core';
|
||||
import { BrowserModule } from '@angular/platform-browser';
|
||||
import { MylibModule } from '@proj/mylib';
|
||||
@ -106,20 +121,23 @@ describe('Nrwl Convert to Nx Workspace', () => {
|
||||
bootstrap: [AppComponent]
|
||||
})
|
||||
export class AppModule {}
|
||||
`);
|
||||
`
|
||||
);
|
||||
|
||||
expect(runCLI('build --aot')).toContain('{main} main.bundle.js');
|
||||
expect(runCLI('test --single-run')).toContain('Executed 4 of 4 SUCCESS');
|
||||
expect(runCLI('e2e')).toContain('Executed 1 of 1 spec SUCCESS');
|
||||
const generatorHelpText = runCLI('g -h');
|
||||
expect(generatorHelpText).toContain('class');
|
||||
expect(generatorHelpText).toContain('component');
|
||||
expect(generatorHelpText).toContain('directive');
|
||||
expect(generatorHelpText).toContain('enum');
|
||||
expect(generatorHelpText).toContain('guard');
|
||||
expect(generatorHelpText).toContain('interface');
|
||||
expect(generatorHelpText).toContain('module');
|
||||
expect(generatorHelpText).toContain('pipe');
|
||||
expect(generatorHelpText).toContain('service');
|
||||
}, 100000);
|
||||
expect(runCLI('build --aot')).toContain('{main} main.bundle.js');
|
||||
expect(runCLI('test --single-run')).toContain('Executed 4 of 4 SUCCESS');
|
||||
expect(runCLI('e2e')).toContain('Executed 1 of 1 spec SUCCESS');
|
||||
const generatorHelpText = runCLI('g -h');
|
||||
expect(generatorHelpText).toContain('class');
|
||||
expect(generatorHelpText).toContain('component');
|
||||
expect(generatorHelpText).toContain('directive');
|
||||
expect(generatorHelpText).toContain('enum');
|
||||
expect(generatorHelpText).toContain('guard');
|
||||
expect(generatorHelpText).toContain('interface');
|
||||
expect(generatorHelpText).toContain('module');
|
||||
expect(generatorHelpText).toContain('pipe');
|
||||
expect(generatorHelpText).toContain('service');
|
||||
},
|
||||
100000
|
||||
);
|
||||
});
|
||||
|
||||
35
e2e/utils.ts
35
e2e/utils.ts
@ -1,11 +1,13 @@
|
||||
import {execSync} from 'child_process';
|
||||
import {linkSync, mkdirSync, readFileSync, statSync, symlinkSync, writeFileSync} from 'fs';
|
||||
import { execSync } from 'child_process';
|
||||
import { linkSync, mkdirSync, readFileSync, statSync, symlinkSync, writeFileSync } from 'fs';
|
||||
import * as path from 'path';
|
||||
|
||||
const projectName: string = 'proj';
|
||||
|
||||
export function ngNew(command?: string): string {
|
||||
return execSync(`../node_modules/.bin/ng new proj ${command}`, {cwd: `./tmp`}).toString();
|
||||
return execSync(`../node_modules/.bin/ng new proj ${command}`, {
|
||||
cwd: `./tmp`
|
||||
}).toString();
|
||||
}
|
||||
|
||||
export function ngNewBazel(command?: string): string {
|
||||
@ -16,13 +18,18 @@ export function ngNewBazel(command?: string): string {
|
||||
return res;
|
||||
}
|
||||
|
||||
export function runCLI(command?: string, opts = {
|
||||
silenceError: false
|
||||
}): string {
|
||||
export function runCLI(
|
||||
command?: string,
|
||||
opts = {
|
||||
silenceError: false
|
||||
}
|
||||
): string {
|
||||
try {
|
||||
return execSync(`../../node_modules/.bin/ng ${command}`, {cwd: `./tmp/${projectName}`})
|
||||
.toString()
|
||||
.replace(/[\u001b\u009b][[()#;?]*(?:[0-9]{1,4}(?:;[0-9]{0,4})*)?[0-9A-ORZcf-nqry=><]/g, '');
|
||||
return execSync(`../../node_modules/.bin/ng ${command}`, {
|
||||
cwd: `./tmp/${projectName}`
|
||||
})
|
||||
.toString()
|
||||
.replace(/[\u001b\u009b][[()#;?]*(?:[0-9]{1,4}(?:;[0-9]{0,4})*)?[0-9A-ORZcf-nqry=><]/g, '');
|
||||
} catch (e) {
|
||||
if (opts.silenceError) {
|
||||
return e.stdout.toString();
|
||||
@ -35,24 +42,26 @@ export function runCLI(command?: string, opts = {
|
||||
|
||||
// switch to ng generate, once CLI is fixed
|
||||
export function newApp(name: string): string {
|
||||
return runCLI(`generate app ${name}`)
|
||||
return runCLI(`generate app ${name}`);
|
||||
// return execSync(`../../node_modules/.bin/schematics @nrwl/schematics:app --name=${name}
|
||||
// --collection=@nrwl/schematics`, { cwd: `./tmp/${projectName}` }).toString();
|
||||
}
|
||||
|
||||
// switch to ng generate, once CLI is fixed
|
||||
export function newLib(name: string): string {
|
||||
return runCLI(`generate lib ${name}`)
|
||||
return runCLI(`generate lib ${name}`);
|
||||
// return execSync(`../../node_modules/.bin/schematics @nrwl/schematics:lib --name=${name}
|
||||
// --collection=@nrwl/schematics`, { cwd: `./tmp/${projectName}` }).toString();
|
||||
}
|
||||
|
||||
export function runSchematic(command: string): string {
|
||||
return execSync(`../../node_modules/.bin/schematics ${command}`, {cwd: `./tmp/${projectName}`}).toString();
|
||||
return execSync(`../../node_modules/.bin/schematics ${command}`, {
|
||||
cwd: `./tmp/${projectName}`
|
||||
}).toString();
|
||||
}
|
||||
|
||||
export function runCommand(command: string): string {
|
||||
return execSync(command, {cwd: `./tmp/${projectName}`}).toString();
|
||||
return execSync(command, { cwd: `./tmp/${projectName}` }).toString();
|
||||
}
|
||||
|
||||
export function updateFile(f: string, content: string): void {
|
||||
|
||||
@ -38,7 +38,7 @@
|
||||
"@types/jasmine": "2.5.53",
|
||||
"@types/node": "8.0.7",
|
||||
"angular": "1.6.6",
|
||||
"clang-format": "1.0.55",
|
||||
"prettier": "1.7.4",
|
||||
"jasmine-core": "~2.6.2",
|
||||
"jest": "20.0.4",
|
||||
"karma": "~1.7.0",
|
||||
|
||||
@ -1,9 +1,19 @@
|
||||
import {apply, chain, mergeWith, move, Rule, externalSchematic, template, url, Tree,} from '@angular-devkit/schematics';
|
||||
import {Schema} from './schema';
|
||||
import {names, toFileName, insert} from '@nrwl/schematics';
|
||||
import {
|
||||
apply,
|
||||
chain,
|
||||
mergeWith,
|
||||
move,
|
||||
Rule,
|
||||
externalSchematic,
|
||||
template,
|
||||
url,
|
||||
Tree
|
||||
} from '@angular-devkit/schematics';
|
||||
import { Schema } from './schema';
|
||||
import { names, toFileName, insert } from '@nrwl/schematics';
|
||||
import * as path from 'path';
|
||||
import * as ts from 'typescript';
|
||||
import {addBootstrapToModule, addImportToModule} from '@schematics/angular/utility/ast-utils';
|
||||
import { addBootstrapToModule, addImportToModule } from '@schematics/angular/utility/ast-utils';
|
||||
|
||||
function addBootstrap(path: string): Rule {
|
||||
return (host: Tree) => {
|
||||
@ -32,7 +42,10 @@ function addAppToAngularCliJson(fullPath: string, options: Schema): Rule {
|
||||
styles: ['styles.css'],
|
||||
scripts: [],
|
||||
environmentSource: 'environments/environment.ts',
|
||||
environments: {'dev': 'environments/environment.ts', 'prod': 'environments/environment.prod.ts'}
|
||||
environments: {
|
||||
dev: 'environments/environment.ts',
|
||||
prod: 'environments/environment.prod.ts'
|
||||
}
|
||||
});
|
||||
|
||||
host.overwrite('.angular-cli.json', JSON.stringify(config, null, 2));
|
||||
@ -40,18 +53,17 @@ function addAppToAngularCliJson(fullPath: string, options: Schema): Rule {
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
export default function(options: Schema): Rule {
|
||||
const fullPath = path.join(options.directory, toFileName(options.name), options.sourceDir);
|
||||
return chain([
|
||||
mergeWith(apply(url('./files'), [template({...options, ...names(options.name), 'dot': '.', 'tmpl': ''})])),
|
||||
mergeWith(apply(url('./files'), [template({ ...options, ...names(options.name), dot: '.', tmpl: '' })])),
|
||||
externalSchematic('@schematics/angular', 'module', {
|
||||
name: 'app',
|
||||
commonModule: false,
|
||||
flat: true,
|
||||
routing: options.routing,
|
||||
sourceDir: fullPath,
|
||||
spec: false,
|
||||
spec: false
|
||||
}),
|
||||
externalSchematic('@schematics/angular', 'component', {
|
||||
name: 'app',
|
||||
@ -65,6 +77,7 @@ export default function(options: Schema): Rule {
|
||||
viewEncapsulation: options.viewEncapsulation,
|
||||
changeDetection: options.changeDetection
|
||||
}),
|
||||
addBootstrap(fullPath), addAppToAngularCliJson(fullPath, options)
|
||||
addBootstrap(fullPath),
|
||||
addAppToAngularCliJson(fullPath, options)
|
||||
]);
|
||||
}
|
||||
|
||||
4
packages/bazel/src/app/schema.d.ts
vendored
4
packages/bazel/src/app/schema.d.ts
vendored
@ -4,8 +4,8 @@ export interface Schema {
|
||||
sourceDir?: string;
|
||||
inlineStyle?: boolean;
|
||||
inlineTemplate?: boolean;
|
||||
viewEncapsulation?: ('Emulated'|'Native'|'None');
|
||||
changeDetection?: ('Default'|'OnPush');
|
||||
viewEncapsulation?: 'Emulated' | 'Native' | 'None';
|
||||
changeDetection?: 'Default' | 'OnPush';
|
||||
prefix?: string;
|
||||
style?: string;
|
||||
skipTests?: boolean;
|
||||
|
||||
@ -1,12 +1,12 @@
|
||||
import {apply, branchAndMerge, chain, mergeWith, Rule, template, Tree, url} from '@angular-devkit/schematics';
|
||||
import {Schema} from './schema';
|
||||
import { apply, branchAndMerge, chain, mergeWith, Rule, template, Tree, url } from '@angular-devkit/schematics';
|
||||
import { Schema } from './schema';
|
||||
import * as path from 'path';
|
||||
import {names, toFileName} from '@nrwl/schematics';
|
||||
import { names, toFileName } from '@nrwl/schematics';
|
||||
|
||||
function addLibToAngularCliJson(fullPath: string, schema: Schema): Rule {
|
||||
return (host: Tree) => {
|
||||
const source = JSON.parse(host.read('.angular-cli.json')!.toString('utf-8'));
|
||||
source.apps.push({name: schema.name, root: fullPath, appDir: false});
|
||||
source.apps.push({ name: schema.name, root: fullPath, appDir: false });
|
||||
host.overwrite('.angular-cli.json', JSON.stringify(source, null, 2));
|
||||
return host;
|
||||
};
|
||||
@ -15,9 +15,7 @@ function addLibToAngularCliJson(fullPath: string, schema: Schema): Rule {
|
||||
export default function(options: any): Rule {
|
||||
const fullPath = path.join(options.directory, toFileName(options.name), options.sourceDir);
|
||||
|
||||
const templateSource = apply(url('./files'), [template({...options, ...names(options.name), dot: '.', tmpl: ''})]);
|
||||
const templateSource = apply(url('./files'), [template({ ...options, ...names(options.name), dot: '.', tmpl: '' })]);
|
||||
|
||||
return chain([
|
||||
branchAndMerge(chain([mergeWith(templateSource), addLibToAngularCliJson(fullPath, options)])),
|
||||
]);
|
||||
return chain([branchAndMerge(chain([mergeWith(templateSource), addLibToAngularCliJson(fullPath, options)]))]);
|
||||
}
|
||||
|
||||
@ -1,13 +1,17 @@
|
||||
import {apply, branchAndMerge, chain, mergeWith, Rule, template, Tree, url} from '@angular-devkit/schematics';
|
||||
import {Schema} from './schema';
|
||||
import { apply, branchAndMerge, chain, mergeWith, Rule, template, Tree, url } from '@angular-devkit/schematics';
|
||||
import { Schema } from './schema';
|
||||
import * as path from 'path';
|
||||
import {names, toFileName} from '@nrwl/schematics';
|
||||
import { names, toFileName } from '@nrwl/schematics';
|
||||
|
||||
function addLibToAngularCliJson(fullPath: string, schema: Schema): Rule {
|
||||
return (host: Tree) => {
|
||||
const source = JSON.parse(host.read('.angular-cli.json')!.toString('utf-8'));
|
||||
source.apps.push(
|
||||
{name: schema.name, root: fullPath, appDir: false, prefix: schema.prefix ? schema.prefix : schema.name});
|
||||
source.apps.push({
|
||||
name: schema.name,
|
||||
root: fullPath,
|
||||
appDir: false,
|
||||
prefix: schema.prefix ? schema.prefix : schema.name
|
||||
});
|
||||
host.overwrite('.angular-cli.json', JSON.stringify(source, null, 2));
|
||||
return host;
|
||||
};
|
||||
@ -16,9 +20,7 @@ function addLibToAngularCliJson(fullPath: string, schema: Schema): Rule {
|
||||
export default function(options: any): Rule {
|
||||
const fullPath = path.join(options.directory, toFileName(options.name), options.sourceDir);
|
||||
|
||||
const templateSource = apply(url('./files'), [template({...options, ...names(options.name), dot: '.', tmpl: ''})]);
|
||||
const templateSource = apply(url('./files'), [template({ ...options, ...names(options.name), dot: '.', tmpl: '' })]);
|
||||
|
||||
return chain([
|
||||
branchAndMerge(chain([mergeWith(templateSource), addLibToAngularCliJson(fullPath, options)])),
|
||||
]);
|
||||
return chain([branchAndMerge(chain([mergeWith(templateSource), addLibToAngularCliJson(fullPath, options)]))]);
|
||||
}
|
||||
|
||||
@ -1,8 +1,11 @@
|
||||
import {apply, chain, mergeWith, move, Rule, schematic, template, url,} from '@angular-devkit/schematics';
|
||||
import {Schema} from './schema';
|
||||
import {names} from '@nrwl/schematics';
|
||||
import { apply, chain, mergeWith, move, Rule, schematic, template, url } from '@angular-devkit/schematics';
|
||||
import { Schema } from './schema';
|
||||
import { names } from '@nrwl/schematics';
|
||||
|
||||
export default function(options: Schema): Rule {
|
||||
return chain([mergeWith(apply(
|
||||
url('./files'), [template({...options, ...names(options.name), 'dot': '.', 'tmpl': ''}), move(options.name!)]))]);
|
||||
return chain([
|
||||
mergeWith(
|
||||
apply(url('./files'), [template({ ...options, ...names(options.name), dot: '.', tmpl: '' }), move(options.name!)])
|
||||
)
|
||||
]);
|
||||
}
|
||||
|
||||
@ -1,2 +1,2 @@
|
||||
export {DataPersistence} from './src/data-persistence';
|
||||
export {NxModule} from './src/nx.module';
|
||||
export { DataPersistence } from './src/data-persistence';
|
||||
export { NxModule } from './src/nx.module';
|
||||
|
||||
@ -1,49 +1,51 @@
|
||||
import 'rxjs/add/operator/delay';
|
||||
|
||||
import {Component, Injectable} from '@angular/core';
|
||||
import {ComponentFixture, fakeAsync, TestBed, tick} from '@angular/core/testing';
|
||||
import {ActivatedRouteSnapshot, Router} from '@angular/router';
|
||||
import {RouterTestingModule} from '@angular/router/testing';
|
||||
import {Actions, Effect, EffectsModule} from '@ngrx/effects';
|
||||
import {provideMockActions} from '@ngrx/effects/testing';
|
||||
import {StoreRouterConnectingModule} from '@ngrx/router-store';
|
||||
import {Store, StoreModule} from '@ngrx/store';
|
||||
import {Observable} from 'rxjs/Observable';
|
||||
import {of} from 'rxjs/observable/of';
|
||||
import {_throw} from 'rxjs/observable/throw';
|
||||
import {delay} from 'rxjs/operator/delay';
|
||||
import {Subject} from 'rxjs/Subject';
|
||||
import { Component, Injectable } from '@angular/core';
|
||||
import { ComponentFixture, fakeAsync, TestBed, tick } from '@angular/core/testing';
|
||||
import { ActivatedRouteSnapshot, Router } from '@angular/router';
|
||||
import { RouterTestingModule } from '@angular/router/testing';
|
||||
import { Actions, Effect, EffectsModule } from '@ngrx/effects';
|
||||
import { provideMockActions } from '@ngrx/effects/testing';
|
||||
import { StoreRouterConnectingModule } from '@ngrx/router-store';
|
||||
import { Store, StoreModule } from '@ngrx/store';
|
||||
import { Observable } from 'rxjs/Observable';
|
||||
import { of } from 'rxjs/observable/of';
|
||||
import { _throw } from 'rxjs/observable/throw';
|
||||
import { delay } from 'rxjs/operator/delay';
|
||||
import { Subject } from 'rxjs/Subject';
|
||||
|
||||
import {DataPersistence} from '../index';
|
||||
import {NxModule} from '../src/nx.module';
|
||||
import {readAll} from '../testing';
|
||||
import { DataPersistence } from '../index';
|
||||
import { NxModule } from '../src/nx.module';
|
||||
import { readAll } from '../testing';
|
||||
|
||||
// interfaces
|
||||
type Todo = {
|
||||
id: number; user: string;
|
||||
id: number;
|
||||
user: string;
|
||||
};
|
||||
type Todos = {
|
||||
selected: Todo;
|
||||
};
|
||||
type TodosState = {
|
||||
todos: Todos; user: string;
|
||||
todos: Todos;
|
||||
user: string;
|
||||
};
|
||||
|
||||
// actions
|
||||
type TodoLoaded = {
|
||||
type: 'TODO_LOADED',
|
||||
payload: Todo
|
||||
type: 'TODO_LOADED';
|
||||
payload: Todo;
|
||||
};
|
||||
type UpdateTodo = {
|
||||
type: 'UPDATE_TODO',
|
||||
payload: {newTitle: string;}
|
||||
type: 'UPDATE_TODO';
|
||||
payload: { newTitle: string };
|
||||
};
|
||||
type Action = TodoLoaded;
|
||||
|
||||
// reducers
|
||||
function todosReducer(state: Todos, action: Action): Todos {
|
||||
if (action.type === 'TODO_LOADED') {
|
||||
return {selected: action.payload};
|
||||
return { selected: action.payload };
|
||||
} else {
|
||||
return state;
|
||||
}
|
||||
@ -53,9 +55,7 @@ function userReducer(state: string, action: Action): string {
|
||||
return 'bob';
|
||||
}
|
||||
|
||||
|
||||
|
||||
@Component({template: `ROOT[<router-outlet></router-outlet>]`})
|
||||
@Component({ template: `ROOT[<router-outlet></router-outlet>]` })
|
||||
class RootCmp {}
|
||||
|
||||
@Component({
|
||||
@ -79,8 +79,10 @@ describe('DataPersistence', () => {
|
||||
TestBed.configureTestingModule({
|
||||
declarations: [RootCmp, TodoComponent],
|
||||
imports: [
|
||||
StoreModule.forRoot({todos: todosReducer, user: userReducer}), StoreRouterConnectingModule,
|
||||
RouterTestingModule.withRoutes([{path: 'todo/:id', component: TodoComponent}]), NxModule.forRoot()
|
||||
StoreModule.forRoot({ todos: todosReducer, user: userReducer }),
|
||||
StoreRouterConnectingModule,
|
||||
RouterTestingModule.withRoutes([{ path: 'todo/:id', component: TodoComponent }]),
|
||||
NxModule.forRoot()
|
||||
]
|
||||
});
|
||||
});
|
||||
@ -91,28 +93,37 @@ describe('DataPersistence', () => {
|
||||
@Effect()
|
||||
loadTodo = this.s.navigation(TodoComponent, {
|
||||
run: (a: ActivatedRouteSnapshot, state: TodosState) => {
|
||||
return ({type: 'TODO_LOADED', payload: {id: a.params['id'], user: state.user}});
|
||||
return {
|
||||
type: 'TODO_LOADED',
|
||||
payload: { id: a.params['id'], user: state.user }
|
||||
};
|
||||
},
|
||||
onError: () => null
|
||||
});
|
||||
constructor(private s: DataPersistence<any>) {}
|
||||
}
|
||||
|
||||
beforeEach(
|
||||
() => {TestBed.configureTestingModule(
|
||||
{providers: [TodoEffects], imports: [EffectsModule.forRoot([TodoEffects])]})});
|
||||
beforeEach(() => {
|
||||
TestBed.configureTestingModule({
|
||||
providers: [TodoEffects],
|
||||
imports: [EffectsModule.forRoot([TodoEffects])]
|
||||
});
|
||||
});
|
||||
|
||||
it('should work', fakeAsync(() => {
|
||||
const root = TestBed.createComponent(RootCmp);
|
||||
it(
|
||||
'should work',
|
||||
fakeAsync(() => {
|
||||
const root = TestBed.createComponent(RootCmp);
|
||||
|
||||
const router: Router = TestBed.get(Router);
|
||||
router.navigateByUrl('/todo/123');
|
||||
tick(0);
|
||||
root.detectChanges(false);
|
||||
const router: Router = TestBed.get(Router);
|
||||
router.navigateByUrl('/todo/123');
|
||||
tick(0);
|
||||
root.detectChanges(false);
|
||||
|
||||
expect(root.elementRef.nativeElement.innerHTML).toContain('ID 123');
|
||||
expect(root.elementRef.nativeElement.innerHTML).toContain('User bob');
|
||||
}));
|
||||
expect(root.elementRef.nativeElement.innerHTML).toContain('ID 123');
|
||||
expect(root.elementRef.nativeElement.innerHTML).toContain('User bob');
|
||||
})
|
||||
);
|
||||
});
|
||||
|
||||
describe('`run` throwing an error', () => {
|
||||
@ -124,38 +135,47 @@ describe('DataPersistence', () => {
|
||||
if (a.params['id'] === '123') {
|
||||
throw new Error('boom');
|
||||
} else {
|
||||
return ({type: 'TODO_LOADED', payload: {id: a.params['id'], user: state.user}});
|
||||
return {
|
||||
type: 'TODO_LOADED',
|
||||
payload: { id: a.params['id'], user: state.user }
|
||||
};
|
||||
}
|
||||
},
|
||||
onError: (a, e) => ({type: 'ERROR', payload: {error: e}})
|
||||
onError: (a, e) => ({ type: 'ERROR', payload: { error: e } })
|
||||
});
|
||||
constructor(private s: DataPersistence<any>) {}
|
||||
}
|
||||
|
||||
beforeEach(
|
||||
() => {TestBed.configureTestingModule(
|
||||
{providers: [TodoEffects], imports: [EffectsModule.forRoot([TodoEffects])]})});
|
||||
beforeEach(() => {
|
||||
TestBed.configureTestingModule({
|
||||
providers: [TodoEffects],
|
||||
imports: [EffectsModule.forRoot([TodoEffects])]
|
||||
});
|
||||
});
|
||||
|
||||
it('should work', fakeAsync(() => {
|
||||
const root = TestBed.createComponent(RootCmp);
|
||||
it(
|
||||
'should work',
|
||||
fakeAsync(() => {
|
||||
const root = TestBed.createComponent(RootCmp);
|
||||
|
||||
const router: Router = TestBed.get(Router);
|
||||
let action;
|
||||
TestBed.get(Actions).subscribe(a => action = a);
|
||||
const router: Router = TestBed.get(Router);
|
||||
let action;
|
||||
TestBed.get(Actions).subscribe(a => (action = a));
|
||||
|
||||
router.navigateByUrl('/todo/123');
|
||||
tick(0);
|
||||
root.detectChanges(false);
|
||||
expect(root.elementRef.nativeElement.innerHTML).not.toContain('ID 123');
|
||||
expect(action.type).toEqual('ERROR');
|
||||
expect(action.payload.error.message).toEqual('boom');
|
||||
router.navigateByUrl('/todo/123');
|
||||
tick(0);
|
||||
root.detectChanges(false);
|
||||
expect(root.elementRef.nativeElement.innerHTML).not.toContain('ID 123');
|
||||
expect(action.type).toEqual('ERROR');
|
||||
expect(action.payload.error.message).toEqual('boom');
|
||||
|
||||
// can recover after an error
|
||||
router.navigateByUrl('/todo/456');
|
||||
tick(0);
|
||||
root.detectChanges(false);
|
||||
expect(root.elementRef.nativeElement.innerHTML).toContain('ID 456');
|
||||
}));
|
||||
// can recover after an error
|
||||
router.navigateByUrl('/todo/456');
|
||||
tick(0);
|
||||
root.detectChanges(false);
|
||||
expect(root.elementRef.nativeElement.innerHTML).toContain('ID 456');
|
||||
})
|
||||
);
|
||||
});
|
||||
|
||||
describe('`run` returning an error observable', () => {
|
||||
@ -167,43 +187,52 @@ describe('DataPersistence', () => {
|
||||
if (a.params['id'] === '123') {
|
||||
return _throw('boom');
|
||||
} else {
|
||||
return ({type: 'TODO_LOADED', payload: {id: a.params['id'], user: state.user}});
|
||||
return {
|
||||
type: 'TODO_LOADED',
|
||||
payload: { id: a.params['id'], user: state.user }
|
||||
};
|
||||
}
|
||||
},
|
||||
onError: (a, e) => ({type: 'ERROR', payload: {error: e}})
|
||||
onError: (a, e) => ({ type: 'ERROR', payload: { error: e } })
|
||||
});
|
||||
constructor(private s: DataPersistence<any>) {}
|
||||
}
|
||||
|
||||
beforeEach(
|
||||
() => {TestBed.configureTestingModule(
|
||||
{providers: [TodoEffects], imports: [EffectsModule.forRoot([TodoEffects])]})});
|
||||
beforeEach(() => {
|
||||
TestBed.configureTestingModule({
|
||||
providers: [TodoEffects],
|
||||
imports: [EffectsModule.forRoot([TodoEffects])]
|
||||
});
|
||||
});
|
||||
|
||||
it('should work', fakeAsync(() => {
|
||||
const root = TestBed.createComponent(RootCmp);
|
||||
it(
|
||||
'should work',
|
||||
fakeAsync(() => {
|
||||
const root = TestBed.createComponent(RootCmp);
|
||||
|
||||
const router: Router = TestBed.get(Router);
|
||||
let action;
|
||||
TestBed.get(Actions).subscribe(a => action = a);
|
||||
const router: Router = TestBed.get(Router);
|
||||
let action;
|
||||
TestBed.get(Actions).subscribe(a => (action = a));
|
||||
|
||||
router.navigateByUrl('/todo/123');
|
||||
tick(0);
|
||||
root.detectChanges(false);
|
||||
expect(root.elementRef.nativeElement.innerHTML).not.toContain('ID 123');
|
||||
expect(action.type).toEqual('ERROR');
|
||||
expect(action.payload.error).toEqual('boom');
|
||||
router.navigateByUrl('/todo/123');
|
||||
tick(0);
|
||||
root.detectChanges(false);
|
||||
expect(root.elementRef.nativeElement.innerHTML).not.toContain('ID 123');
|
||||
expect(action.type).toEqual('ERROR');
|
||||
expect(action.payload.error).toEqual('boom');
|
||||
|
||||
router.navigateByUrl('/todo/456');
|
||||
tick(0);
|
||||
root.detectChanges(false);
|
||||
expect(root.elementRef.nativeElement.innerHTML).toContain('ID 456');
|
||||
}));
|
||||
router.navigateByUrl('/todo/456');
|
||||
tick(0);
|
||||
root.detectChanges(false);
|
||||
expect(root.elementRef.nativeElement.innerHTML).toContain('ID 456');
|
||||
})
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
describe('fetch', () => {
|
||||
beforeEach(() => {
|
||||
TestBed.configureTestingModule({providers: [DataPersistence]});
|
||||
TestBed.configureTestingModule({ providers: [DataPersistence] });
|
||||
});
|
||||
|
||||
describe('no id', () => {
|
||||
@ -213,7 +242,10 @@ describe('DataPersistence', () => {
|
||||
loadTodos = this.s.fetch('GET_TODOS', {
|
||||
run: (a: any, state: TodosState) => {
|
||||
// we need to introduce the delay to "enable" switchMap
|
||||
return of ({type: 'TODOS', payload: {user: state.user, todos: 'some todos'}}).delay(1);
|
||||
return of({
|
||||
type: 'TODOS',
|
||||
payload: { user: state.user, todos: 'some todos' }
|
||||
}).delay(1);
|
||||
},
|
||||
|
||||
onError: (a: UpdateTodo, e: any) => null
|
||||
@ -232,16 +264,16 @@ describe('DataPersistence', () => {
|
||||
actions = new Subject<any>();
|
||||
TestBed.configureTestingModule({
|
||||
providers: [TodoEffects, provideMockActions(() => actions)],
|
||||
imports: [StoreModule.forRoot({user: userReducer})]
|
||||
})
|
||||
imports: [StoreModule.forRoot({ user: userReducer })]
|
||||
});
|
||||
});
|
||||
|
||||
it('should work', async (done) => {
|
||||
actions = of({type: 'GET_TODOS', payload: {}}, {type: 'GET_TODOS', payload: {}});
|
||||
it('should work', async done => {
|
||||
actions = of({ type: 'GET_TODOS', payload: {} }, { type: 'GET_TODOS', payload: {} });
|
||||
|
||||
expect(await readAll(TestBed.get(TodoEffects).loadTodos)).toEqual([
|
||||
{type: 'TODOS', payload: {user: 'bob', todos: 'some todos'}},
|
||||
{type: 'TODOS', payload: {user: 'bob', todos: 'some todos'}}
|
||||
{ type: 'TODOS', payload: { user: 'bob', todos: 'some todos' } },
|
||||
{ type: 'TODOS', payload: { user: 'bob', todos: 'some todos' } }
|
||||
]);
|
||||
|
||||
done();
|
||||
@ -254,7 +286,7 @@ describe('DataPersistence', () => {
|
||||
@Effect()
|
||||
loadTodo = this.s.fetch('GET_TODO', {
|
||||
id: (a: any, state: TodosState) => a.payload.id,
|
||||
run: (a: any, state: TodosState) => of({type: 'TODO', payload: a.payload}).delay(1),
|
||||
run: (a: any, state: TodosState) => of({ type: 'TODO', payload: a.payload }).delay(1),
|
||||
onError: (a: UpdateTodo, e: any) => null
|
||||
});
|
||||
|
||||
@ -271,17 +303,20 @@ describe('DataPersistence', () => {
|
||||
actions = new Subject<any>();
|
||||
TestBed.configureTestingModule({
|
||||
providers: [TodoEffects, provideMockActions(() => actions)],
|
||||
imports: [StoreModule.forRoot({user: userReducer})]
|
||||
})
|
||||
imports: [StoreModule.forRoot({ user: userReducer })]
|
||||
});
|
||||
});
|
||||
|
||||
it('should work', async (done) => {
|
||||
actions =
|
||||
of({type: 'GET_TODO', payload: {id: 1, value: '1'}}, {type: 'GET_TODO', payload: {id: 2, value: '2a'}},
|
||||
{type: 'GET_TODO', payload: {id: 2, value: '2b'}});
|
||||
it('should work', async done => {
|
||||
actions = of(
|
||||
{ type: 'GET_TODO', payload: { id: 1, value: '1' } },
|
||||
{ type: 'GET_TODO', payload: { id: 2, value: '2a' } },
|
||||
{ type: 'GET_TODO', payload: { id: 2, value: '2b' } }
|
||||
);
|
||||
|
||||
expect(await readAll(TestBed.get(TodoEffects).loadTodo)).toEqual([
|
||||
{type: 'TODO', payload: {id: 1, value: '1'}}, {type: 'TODO', payload: {id: 2, value: '2b'}}
|
||||
{ type: 'TODO', payload: { id: 1, value: '1' } },
|
||||
{ type: 'TODO', payload: { id: 2, value: '2b' } }
|
||||
]);
|
||||
|
||||
done();
|
||||
@ -291,7 +326,7 @@ describe('DataPersistence', () => {
|
||||
|
||||
describe('pessimisticUpdate', () => {
|
||||
beforeEach(() => {
|
||||
TestBed.configureTestingModule({providers: [DataPersistence]});
|
||||
TestBed.configureTestingModule({ providers: [DataPersistence] });
|
||||
});
|
||||
|
||||
describe('successful', () => {
|
||||
@ -299,8 +334,10 @@ describe('DataPersistence', () => {
|
||||
class TodoEffects {
|
||||
@Effect()
|
||||
loadTodo = this.s.pessimisticUpdate('UPDATE_TODO', {
|
||||
run: (a: UpdateTodo, state: TodosState) =>
|
||||
({type: 'TODO_UPDATED', payload: {user: state.user, newTitle: a.payload.newTitle}}),
|
||||
run: (a: UpdateTodo, state: TodosState) => ({
|
||||
type: 'TODO_UPDATED',
|
||||
payload: { user: state.user, newTitle: a.payload.newTitle }
|
||||
}),
|
||||
onError: (a: UpdateTodo, e: any) => null
|
||||
});
|
||||
|
||||
@ -317,15 +354,21 @@ describe('DataPersistence', () => {
|
||||
actions = new Subject<any>();
|
||||
TestBed.configureTestingModule({
|
||||
providers: [TodoEffects, provideMockActions(() => actions)],
|
||||
imports: [StoreModule.forRoot({user: userReducer})]
|
||||
})
|
||||
imports: [StoreModule.forRoot({ user: userReducer })]
|
||||
});
|
||||
});
|
||||
|
||||
it('should work', async (done) => {
|
||||
actions = of({type: 'UPDATE_TODO', payload: {newTitle: 'newTitle'}});
|
||||
it('should work', async done => {
|
||||
actions = of({
|
||||
type: 'UPDATE_TODO',
|
||||
payload: { newTitle: 'newTitle' }
|
||||
});
|
||||
|
||||
expect(await readAll(TestBed.get(TodoEffects).loadTodo)).toEqual([
|
||||
{type: 'TODO_UPDATED', payload: {user: 'bob', newTitle: 'newTitle'}}
|
||||
{
|
||||
type: 'TODO_UPDATED',
|
||||
payload: { user: 'bob', newTitle: 'newTitle' }
|
||||
}
|
||||
]);
|
||||
|
||||
done();
|
||||
@ -341,7 +384,10 @@ describe('DataPersistence', () => {
|
||||
throw new Error('boom');
|
||||
},
|
||||
|
||||
onError: (a: UpdateTodo, e: any) => ({type: 'ERROR', payload: {error: e}})
|
||||
onError: (a: UpdateTodo, e: any) => ({
|
||||
type: 'ERROR',
|
||||
payload: { error: e }
|
||||
})
|
||||
});
|
||||
|
||||
constructor(private s: DataPersistence<any>) {}
|
||||
@ -357,12 +403,15 @@ describe('DataPersistence', () => {
|
||||
actions = new Subject<any>();
|
||||
TestBed.configureTestingModule({
|
||||
providers: [TodoEffects, provideMockActions(() => actions)],
|
||||
imports: [StoreModule.forRoot({user: userReducer})]
|
||||
})
|
||||
imports: [StoreModule.forRoot({ user: userReducer })]
|
||||
});
|
||||
});
|
||||
|
||||
it('should work', async (done) => {
|
||||
actions = of({type: 'UPDATE_TODO', payload: {newTitle: 'newTitle'}});
|
||||
it('should work', async done => {
|
||||
actions = of({
|
||||
type: 'UPDATE_TODO',
|
||||
payload: { newTitle: 'newTitle' }
|
||||
});
|
||||
|
||||
const [a]: any = await readAll(TestBed.get(TodoEffects).loadTodo);
|
||||
|
||||
@ -382,7 +431,10 @@ describe('DataPersistence', () => {
|
||||
return _throw('boom');
|
||||
},
|
||||
|
||||
onError: (a: UpdateTodo, e: any) => ({type: 'ERROR', payload: {error: e}})
|
||||
onError: (a: UpdateTodo, e: any) => ({
|
||||
type: 'ERROR',
|
||||
payload: { error: e }
|
||||
})
|
||||
});
|
||||
|
||||
constructor(private s: DataPersistence<any>) {}
|
||||
@ -398,12 +450,15 @@ describe('DataPersistence', () => {
|
||||
actions = new Subject<any>();
|
||||
TestBed.configureTestingModule({
|
||||
providers: [TodoEffects, provideMockActions(() => actions)],
|
||||
imports: [StoreModule.forRoot({user: userReducer})]
|
||||
})
|
||||
imports: [StoreModule.forRoot({ user: userReducer })]
|
||||
});
|
||||
});
|
||||
|
||||
it('should work', async (done) => {
|
||||
actions = of({type: 'UPDATE_TODO', payload: {newTitle: 'newTitle'}});
|
||||
it('should work', async done => {
|
||||
actions = of({
|
||||
type: 'UPDATE_TODO',
|
||||
payload: { newTitle: 'newTitle' }
|
||||
});
|
||||
|
||||
const [a]: any = await readAll(TestBed.get(TodoEffects).loadTodo);
|
||||
|
||||
@ -412,12 +467,12 @@ describe('DataPersistence', () => {
|
||||
|
||||
done();
|
||||
});
|
||||
})
|
||||
});
|
||||
});
|
||||
|
||||
describe('optimisticUpdate', () => {
|
||||
beforeEach(() => {
|
||||
TestBed.configureTestingModule({providers: [DataPersistence]});
|
||||
TestBed.configureTestingModule({ providers: [DataPersistence] });
|
||||
});
|
||||
|
||||
describe('`run` throws an error', () => {
|
||||
@ -429,7 +484,10 @@ describe('DataPersistence', () => {
|
||||
throw new Error('boom');
|
||||
},
|
||||
|
||||
undoAction: (a: UpdateTodo, e: any) => ({type: 'UNDO_UPDATE_TODO', payload: a.payload})
|
||||
undoAction: (a: UpdateTodo, e: any) => ({
|
||||
type: 'UNDO_UPDATE_TODO',
|
||||
payload: a.payload
|
||||
})
|
||||
});
|
||||
|
||||
constructor(private s: DataPersistence<any>) {}
|
||||
@ -445,12 +503,15 @@ describe('DataPersistence', () => {
|
||||
actions = new Subject<any>();
|
||||
TestBed.configureTestingModule({
|
||||
providers: [TodoEffects, provideMockActions(() => actions)],
|
||||
imports: [StoreModule.forRoot({user: userReducer})]
|
||||
})
|
||||
imports: [StoreModule.forRoot({ user: userReducer })]
|
||||
});
|
||||
});
|
||||
|
||||
it('should work', async (done) => {
|
||||
actions = of({type: 'UPDATE_TODO', payload: {newTitle: 'newTitle'}});
|
||||
it('should work', async done => {
|
||||
actions = of({
|
||||
type: 'UPDATE_TODO',
|
||||
payload: { newTitle: 'newTitle' }
|
||||
});
|
||||
|
||||
const [a]: any = await readAll(TestBed.get(TodoEffects).loadTodo);
|
||||
|
||||
|
||||
@ -1,9 +1,9 @@
|
||||
import {from} from 'rxjs/observable/from'
|
||||
import {readAll, readFirst} from '../src/testing-utils';
|
||||
import { from } from 'rxjs/observable/from';
|
||||
import { readAll, readFirst } from '../src/testing-utils';
|
||||
|
||||
describe('TestingUtils', () => {
|
||||
describe('readAll', () => {
|
||||
it('should transform Observable<T> to Promise<Array<T>>', async (done) => {
|
||||
it('should transform Observable<T> to Promise<Array<T>>', async done => {
|
||||
const obs = from([1, 2, 3]);
|
||||
const result = await readAll(obs);
|
||||
|
||||
@ -14,7 +14,7 @@ describe('TestingUtils', () => {
|
||||
});
|
||||
|
||||
describe('readFirst', () => {
|
||||
it('should transform first item emitted from Observable<T> to Promise<T>', async (done) => {
|
||||
it('should transform first item emitted from Observable<T> to Promise<T>', async done => {
|
||||
const obs = from([1, 2, 3]);
|
||||
const result = await readFirst(obs);
|
||||
|
||||
|
||||
@ -1,32 +1,32 @@
|
||||
import {Injectable, Type} from '@angular/core';
|
||||
import {ActivatedRouteSnapshot, RouterStateSnapshot} from '@angular/router';
|
||||
import {Actions} from '@ngrx/effects';
|
||||
import {ROUTER_NAVIGATION, RouterNavigationAction} from '@ngrx/router-store';
|
||||
import {Action, State, Store} from '@ngrx/store';
|
||||
import {Observable} from 'rxjs/Observable';
|
||||
import {of} from 'rxjs/observable/of';
|
||||
import {_catch} from 'rxjs/operator/catch';
|
||||
import {concatMap} from 'rxjs/operator/concatMap';
|
||||
import {filter} from 'rxjs/operator/filter';
|
||||
import {groupBy} from 'rxjs/operator/groupBy';
|
||||
import {map} from 'rxjs/operator/map';
|
||||
import {mergeMap} from 'rxjs/operator/mergeMap';
|
||||
import {switchMap} from 'rxjs/operator/switchMap';
|
||||
import {withLatestFrom} from 'rxjs/operator/withLatestFrom';
|
||||
import { Injectable, Type } from '@angular/core';
|
||||
import { ActivatedRouteSnapshot, RouterStateSnapshot } from '@angular/router';
|
||||
import { Actions } from '@ngrx/effects';
|
||||
import { ROUTER_NAVIGATION, RouterNavigationAction } from '@ngrx/router-store';
|
||||
import { Action, State, Store } from '@ngrx/store';
|
||||
import { Observable } from 'rxjs/Observable';
|
||||
import { of } from 'rxjs/observable/of';
|
||||
import { _catch } from 'rxjs/operator/catch';
|
||||
import { concatMap } from 'rxjs/operator/concatMap';
|
||||
import { filter } from 'rxjs/operator/filter';
|
||||
import { groupBy } from 'rxjs/operator/groupBy';
|
||||
import { map } from 'rxjs/operator/map';
|
||||
import { mergeMap } from 'rxjs/operator/mergeMap';
|
||||
import { switchMap } from 'rxjs/operator/switchMap';
|
||||
import { withLatestFrom } from 'rxjs/operator/withLatestFrom';
|
||||
|
||||
/**
|
||||
* See {@link DataPersistence.pessimisticUpdate} for more information.
|
||||
*/
|
||||
export interface PessimisticUpdateOpts {
|
||||
run(a: Action, state?: any): Observable<Action>|Action|void;
|
||||
onError(a: Action, e: any): Observable<any>|any;
|
||||
run(a: Action, state?: any): Observable<Action> | Action | void;
|
||||
onError(a: Action, e: any): Observable<any> | any;
|
||||
}
|
||||
/**
|
||||
* See {@link DataPersistence.pessimisticUpdate} for more information.
|
||||
*/
|
||||
export interface OptimisticUpdateOpts {
|
||||
run(a: Action, state?: any): Observable<any>|any;
|
||||
undoAction(a: Action, e: any): Observable<Action>|Action;
|
||||
run(a: Action, state?: any): Observable<any> | any;
|
||||
undoAction(a: Action, e: any): Observable<Action> | Action;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -34,16 +34,16 @@ export interface OptimisticUpdateOpts {
|
||||
*/
|
||||
export interface FetchOpts {
|
||||
id?(a: Action, state?: any): any;
|
||||
run(a: Action, state?: any): Observable<Action>|Action|void;
|
||||
onError?(a: Action, e: any): Observable<any>|any;
|
||||
run(a: Action, state?: any): Observable<Action> | Action | void;
|
||||
onError?(a: Action, e: any): Observable<any> | any;
|
||||
}
|
||||
|
||||
/**
|
||||
* See {@link DataPersistence.navigation} for more information.
|
||||
*/
|
||||
export interface HandleNavigationOpts {
|
||||
run(a: ActivatedRouteSnapshot, state?: any): Observable<Action>|Action|void;
|
||||
onError?(a: ActivatedRouteSnapshot, e: any): Observable<any>|any;
|
||||
run(a: ActivatedRouteSnapshot, state?: any): Observable<Action> | Action | void;
|
||||
onError?(a: ActivatedRouteSnapshot, e: any): Observable<any> | any;
|
||||
}
|
||||
|
||||
type Pair = [Action, any];
|
||||
@ -211,10 +211,10 @@ export class DataPersistence<T> {
|
||||
const allPairs = withLatestFrom.call(nav, this.store);
|
||||
|
||||
if (opts.id) {
|
||||
const groupedFetches: Observable<Observable<Pair>> = groupBy.call(allPairs, (p) => opts.id(p[0], p[1]));
|
||||
return mergeMap.call(
|
||||
groupedFetches,
|
||||
(pairs: Observable<Pair>) => switchMap.call(pairs, this.runWithErrorHandling(opts.run, opts.onError)));
|
||||
const groupedFetches: Observable<Observable<Pair>> = groupBy.call(allPairs, p => opts.id(p[0], p[1]));
|
||||
return mergeMap.call(groupedFetches, (pairs: Observable<Pair>) =>
|
||||
switchMap.call(pairs, this.runWithErrorHandling(opts.run, opts.onError))
|
||||
);
|
||||
} else {
|
||||
return concatMap.call(allPairs, this.runWithErrorHandling(opts.run, opts.onError));
|
||||
}
|
||||
@ -256,10 +256,11 @@ export class DataPersistence<T> {
|
||||
*/
|
||||
navigation(component: Type<any>, opts: HandleNavigationOpts): Observable<any> {
|
||||
const nav = filter.call(
|
||||
map.call(
|
||||
this.actions.ofType(ROUTER_NAVIGATION),
|
||||
(a: RouterNavigationAction<RouterStateSnapshot>) => findSnapshot(component, a.payload.routerState.root)),
|
||||
s => !!s);
|
||||
map.call(this.actions.ofType(ROUTER_NAVIGATION), (a: RouterNavigationAction<RouterStateSnapshot>) =>
|
||||
findSnapshot(component, a.payload.routerState.root)
|
||||
),
|
||||
s => !!s
|
||||
);
|
||||
|
||||
const pairs = withLatestFrom.call(nav, this.store);
|
||||
return switchMap.call(pairs, this.runWithErrorHandling(opts.run, opts.onError));
|
||||
@ -269,11 +270,11 @@ export class DataPersistence<T> {
|
||||
return a => {
|
||||
try {
|
||||
const r = wrapIntoObservable(run(a[0], a[1]));
|
||||
return _catch.call(r, e => wrapIntoObservable(onError(a[0], e)))
|
||||
return _catch.call(r, e => wrapIntoObservable(onError(a[0], e)));
|
||||
} catch (e) {
|
||||
return wrapIntoObservable(onError(a[0], e));
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
@ -294,8 +295,8 @@ function wrapIntoObservable(obj: any): Observable<any> {
|
||||
if (!!obj && typeof obj.subscribe === 'function') {
|
||||
return obj;
|
||||
} else if (!obj) {
|
||||
return of ();
|
||||
return of();
|
||||
} else {
|
||||
return of (obj);
|
||||
return of(obj);
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
import {ModuleWithProviders, NgModule} from '@angular/core';
|
||||
import {DataPersistence} from './data-persistence';
|
||||
import { ModuleWithProviders, NgModule } from '@angular/core';
|
||||
import { DataPersistence } from './data-persistence';
|
||||
|
||||
/**
|
||||
* @whatItDoes Provides services for enterprise Angular applications.
|
||||
@ -9,6 +9,6 @@ import {DataPersistence} from './data-persistence';
|
||||
@NgModule({})
|
||||
export class NxModule {
|
||||
static forRoot(): ModuleWithProviders {
|
||||
return {ngModule: NxModule, providers: [DataPersistence]};
|
||||
return { ngModule: NxModule, providers: [DataPersistence] };
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
import {Observable} from 'rxjs/Observable';
|
||||
import {first} from 'rxjs/operator/first';
|
||||
import {toArray} from 'rxjs/operator/toArray';
|
||||
import {toPromise} from 'rxjs/operator/toPromise';
|
||||
import { Observable } from 'rxjs/Observable';
|
||||
import { first } from 'rxjs/operator/first';
|
||||
import { toArray } from 'rxjs/operator/toArray';
|
||||
import { toPromise } from 'rxjs/operator/toPromise';
|
||||
|
||||
/**
|
||||
* @whatItDoes reads all the values from an observable and returns a promise
|
||||
|
||||
@ -1,2 +1,2 @@
|
||||
export {cold, hot} from 'jasmine-marbles';
|
||||
export {readAll, readFirst} from './src/testing-utils';
|
||||
export { cold, hot } from 'jasmine-marbles';
|
||||
export { readAll, readFirst } from './src/testing-utils';
|
||||
|
||||
@ -1,2 +1,2 @@
|
||||
export {addImportToModule, addProviderToModule, insert} from './src/utility/ast-utils';
|
||||
export {names, toClassName, toFileName, toPropertyName} from './src/utility/name-utils';
|
||||
export { addImportToModule, addProviderToModule, insert } from './src/utility/ast-utils';
|
||||
export { names, toClassName, toFileName, toPropertyName } from './src/utility/name-utils';
|
||||
|
||||
@ -1,12 +1,26 @@
|
||||
import {apply, branchAndMerge, chain, externalSchematic, mergeWith, move, Rule, template, Tree, url, MergeStrategy, filter, noop} from '@angular-devkit/schematics';
|
||||
import {Schema} from './schema';
|
||||
import {
|
||||
apply,
|
||||
branchAndMerge,
|
||||
chain,
|
||||
externalSchematic,
|
||||
mergeWith,
|
||||
move,
|
||||
Rule,
|
||||
template,
|
||||
Tree,
|
||||
url,
|
||||
MergeStrategy,
|
||||
filter,
|
||||
noop
|
||||
} from '@angular-devkit/schematics';
|
||||
import { Schema } from './schema';
|
||||
import * as stringUtils from '@schematics/angular/strings';
|
||||
import {addImportToModule, insert, toFileName} from '@nrwl/schematics';
|
||||
import { addImportToModule, insert, toFileName } from '@nrwl/schematics';
|
||||
import * as path from 'path';
|
||||
import * as ts from 'typescript';
|
||||
import {addBootstrapToModule} from '@schematics/angular/utility/ast-utils';
|
||||
import {insertImport} from '@schematics/angular/utility/route-utils';
|
||||
import {addApp} from '../utility/config-file-utils';
|
||||
import { addBootstrapToModule } from '@schematics/angular/utility/ast-utils';
|
||||
import { insertImport } from '@schematics/angular/utility/route-utils';
|
||||
import { addApp } from '../utility/config-file-utils';
|
||||
|
||||
function addBootstrap(path: string): Rule {
|
||||
return (host: Tree) => {
|
||||
@ -29,7 +43,7 @@ function addNxModule(path: string): Rule {
|
||||
const sourceFile = ts.createSourceFile(modulePath, moduleSource, ts.ScriptTarget.Latest, true);
|
||||
insert(host, modulePath, [
|
||||
insertImport(sourceFile, modulePath, 'NxModule', '@nrwl/nx'),
|
||||
...addImportToModule(sourceFile, modulePath, 'NxModule.forRoot()'),
|
||||
...addImportToModule(sourceFile, modulePath, 'NxModule.forRoot()')
|
||||
]);
|
||||
return host;
|
||||
};
|
||||
@ -43,21 +57,24 @@ function addAppToAngularCliJson(options: Schema): Rule {
|
||||
const sourceText = host.read('.angular-cli.json')!.toString('utf-8');
|
||||
const json = JSON.parse(sourceText);
|
||||
json.apps = addApp(json.apps, {
|
||||
'name': options.name,
|
||||
'root': fullPath(options),
|
||||
'outDir': `dist/apps/${options.name}`,
|
||||
'assets': ['assets', 'favicon.ico'],
|
||||
'index': 'index.html',
|
||||
'main': 'main.ts',
|
||||
'polyfills': 'polyfills.ts',
|
||||
'test': '../../../test.js',
|
||||
'tsconfig': '../../../tsconfig.app.json',
|
||||
'testTsconfig': '../../../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'}
|
||||
name: options.name,
|
||||
root: fullPath(options),
|
||||
outDir: `dist/apps/${options.name}`,
|
||||
assets: ['assets', 'favicon.ico'],
|
||||
index: 'index.html',
|
||||
main: 'main.ts',
|
||||
polyfills: 'polyfills.ts',
|
||||
test: '../../../test.js',
|
||||
tsconfig: '../../../tsconfig.app.json',
|
||||
testTsconfig: '../../../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'
|
||||
}
|
||||
});
|
||||
|
||||
host.overwrite('.angular-cli.json', JSON.stringify(json, null, 2));
|
||||
@ -66,19 +83,21 @@ function addAppToAngularCliJson(options: Schema): Rule {
|
||||
}
|
||||
|
||||
export default function(schema: Schema): Rule {
|
||||
const options = {...schema, name: toFileName(schema.name)};
|
||||
const templateSource =
|
||||
apply(url('./files'), [template({utils: stringUtils, dot: '.', tmpl: '', ...options as object})]);
|
||||
const options = { ...schema, name: toFileName(schema.name) };
|
||||
const templateSource = apply(url('./files'), [
|
||||
template({ utils: stringUtils, dot: '.', tmpl: '', ...(options as object) })
|
||||
]);
|
||||
|
||||
const selector = `${options.prefix}-root`;
|
||||
return chain([
|
||||
branchAndMerge(chain([mergeWith(templateSource)])), externalSchematic('@schematics/angular', 'module', {
|
||||
branchAndMerge(chain([mergeWith(templateSource)])),
|
||||
externalSchematic('@schematics/angular', 'module', {
|
||||
name: 'app',
|
||||
commonModule: false,
|
||||
flat: true,
|
||||
routing: options.routing,
|
||||
sourceDir: fullPath(options),
|
||||
spec: false,
|
||||
spec: false
|
||||
}),
|
||||
externalSchematic('@schematics/angular', 'component', {
|
||||
name: 'app',
|
||||
@ -94,15 +113,16 @@ export default function(schema: Schema): Rule {
|
||||
}),
|
||||
|
||||
mergeWith(
|
||||
apply(
|
||||
url('./component-files'),
|
||||
[
|
||||
options.inlineTemplate ? filter(path => !path.endsWith('.html')) : noop(),
|
||||
template({...options, tmpl: ''}),
|
||||
move(path.join(fullPath(options), 'app')),
|
||||
]),
|
||||
MergeStrategy.Overwrite),
|
||||
addBootstrap(fullPath(options)), addNxModule(fullPath(options)), addAppToAngularCliJson(options)
|
||||
apply(url('./component-files'), [
|
||||
options.inlineTemplate ? filter(path => !path.endsWith('.html')) : noop(),
|
||||
template({ ...options, tmpl: '' }),
|
||||
move(path.join(fullPath(options), 'app'))
|
||||
]),
|
||||
MergeStrategy.Overwrite
|
||||
),
|
||||
addBootstrap(fullPath(options)),
|
||||
addNxModule(fullPath(options)),
|
||||
addAppToAngularCliJson(options)
|
||||
]);
|
||||
}
|
||||
|
||||
|
||||
4
packages/schematics/src/app/schema.d.ts
vendored
4
packages/schematics/src/app/schema.d.ts
vendored
@ -3,8 +3,8 @@ export interface Schema {
|
||||
sourceDir?: string;
|
||||
inlineStyle?: boolean;
|
||||
inlineTemplate?: boolean;
|
||||
viewEncapsulation?: ('Emulated'|'Native'|'None');
|
||||
changeDetection?: ('Default'|'OnPush');
|
||||
viewEncapsulation?: 'Emulated' | 'Native' | 'None';
|
||||
changeDetection?: 'Default' | 'OnPush';
|
||||
routing?: boolean;
|
||||
skipTests?: boolean;
|
||||
prefix?: string;
|
||||
|
||||
@ -1,3 +0,0 @@
|
||||
Language: JavaScript
|
||||
BasedOnStyle: Google
|
||||
ColumnLimit: 120
|
||||
@ -9,7 +9,7 @@
|
||||
"test": "ng test",
|
||||
"lint": "ng lint",
|
||||
"e2e": "ng e2e",
|
||||
"format": "find apps/ -iname '*.ts' | xargs clang-format -i && find libs/ -iname '*.ts' | xargs clang-format -i"
|
||||
"format": "prettier --single-quote --print-width 120 --write '{apps,libs}/**/*.ts'"
|
||||
},
|
||||
"private": true,
|
||||
"dependencies": {
|
||||
@ -52,6 +52,6 @@
|
||||
"ts-node": "~3.2.0",
|
||||
"tslint": "~5.3.2",<% } %>
|
||||
"typescript": "~2.3.3",
|
||||
"clang-format": "1.0.55"
|
||||
"prettier": "<%= prettierVersion %>"
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,12 +1,19 @@
|
||||
import {apply, branchAndMerge, chain, mergeWith, move, Rule, template, Tree, url} from '@angular-devkit/schematics';
|
||||
import {Schema} from './schema';
|
||||
import { apply, branchAndMerge, chain, mergeWith, move, Rule, template, Tree, url } from '@angular-devkit/schematics';
|
||||
import { Schema } from './schema';
|
||||
import * as stringUtils from '@schematics/angular/strings';
|
||||
import {libVersions} from '../utility/lib-versions';
|
||||
import { libVersions } from '../utility/lib-versions';
|
||||
|
||||
export default function(options: Schema): Rule {
|
||||
const npmScope = options.npmScope ? options.npmScope : options.name;
|
||||
const templateSource =
|
||||
apply(url('./files'), [template({utils: stringUtils, dot: '.', ...libVersions, ...options as object, npmScope})]);
|
||||
const templateSource = apply(url('./files'), [
|
||||
template({
|
||||
utils: stringUtils,
|
||||
dot: '.',
|
||||
...libVersions,
|
||||
...(options as object),
|
||||
npmScope
|
||||
})
|
||||
]);
|
||||
|
||||
return chain([branchAndMerge(chain([mergeWith(templateSource)]))]);
|
||||
}
|
||||
|
||||
@ -1,8 +1,19 @@
|
||||
import {apply, branchAndMerge, chain, externalSchematic, mergeWith, move, Rule, template, Tree, url} from '@angular-devkit/schematics';
|
||||
import {Schema} from './schema';
|
||||
import {names, toFileName} from '@nrwl/schematics';
|
||||
import {
|
||||
apply,
|
||||
branchAndMerge,
|
||||
chain,
|
||||
externalSchematic,
|
||||
mergeWith,
|
||||
move,
|
||||
Rule,
|
||||
template,
|
||||
Tree,
|
||||
url
|
||||
} from '@angular-devkit/schematics';
|
||||
import { Schema } from './schema';
|
||||
import { names, toFileName } from '@nrwl/schematics';
|
||||
import * as path from 'path';
|
||||
import {addApp} from '../utility/config-file-utils';
|
||||
import { addApp } from '../utility/config-file-utils';
|
||||
|
||||
function addLibToAngularCliJson(options: Schema): Rule {
|
||||
return (host: Tree) => {
|
||||
@ -12,8 +23,12 @@ function addLibToAngularCliJson(options: Schema): Rule {
|
||||
|
||||
const sourceText = host.read('.angular-cli.json')!.toString('utf-8');
|
||||
const json = JSON.parse(sourceText);
|
||||
json.apps =
|
||||
addApp(json.apps, {'name': options.name, 'root': fullPath(options), 'test': '../../../test.js', 'appRoot': ''});
|
||||
json.apps = addApp(json.apps, {
|
||||
name: options.name,
|
||||
root: fullPath(options),
|
||||
test: '../../../test.js',
|
||||
appRoot: ''
|
||||
});
|
||||
|
||||
host.overwrite('.angular-cli.json', JSON.stringify(json, null, 2));
|
||||
return host;
|
||||
@ -21,12 +36,17 @@ function addLibToAngularCliJson(options: Schema): Rule {
|
||||
}
|
||||
|
||||
export default function(schema: Schema): Rule {
|
||||
const options = {...schema, name: toFileName(schema.name)};
|
||||
const options = { ...schema, name: toFileName(schema.name) };
|
||||
const fullPath = path.join('libs', toFileName(options.name), options.sourceDir);
|
||||
|
||||
const templateSource = apply(
|
||||
url(options.ngmodule ? './ngfiles' : './files'),
|
||||
[template({...names(options.name), dot: '.', tmpl: '', ...options as object})]);
|
||||
const templateSource = apply(url(options.ngmodule ? './ngfiles' : './files'), [
|
||||
template({
|
||||
...names(options.name),
|
||||
dot: '.',
|
||||
tmpl: '',
|
||||
...(options as object)
|
||||
})
|
||||
]);
|
||||
|
||||
return chain([branchAndMerge(chain([mergeWith(templateSource)])), addLibToAngularCliJson(options)]);
|
||||
}
|
||||
|
||||
@ -1,13 +1,24 @@
|
||||
import {apply, branchAndMerge, chain, mergeWith, move, noop, Rule, template, Tree, url} from '@angular-devkit/schematics';
|
||||
import {
|
||||
apply,
|
||||
branchAndMerge,
|
||||
chain,
|
||||
mergeWith,
|
||||
move,
|
||||
noop,
|
||||
Rule,
|
||||
template,
|
||||
Tree,
|
||||
url
|
||||
} from '@angular-devkit/schematics';
|
||||
|
||||
import {names, toClassName, toFileName, toPropertyName} from '../utility/name-utils';
|
||||
import { names, toClassName, toFileName, toPropertyName } from '../utility/name-utils';
|
||||
import * as path from 'path';
|
||||
import * as ts from 'typescript';
|
||||
import {addImportToModule, addProviderToModule, insert, offset} from '../utility/ast-utils';
|
||||
import {insertImport} from '@schematics/angular/utility/route-utils';
|
||||
import {Schema} from './schema';
|
||||
import {InsertChange} from '@schematics/angular/utility/change';
|
||||
import {ngrxVersion} from '../utility/lib-versions';
|
||||
import { addImportToModule, addProviderToModule, insert, offset } from '../utility/ast-utils';
|
||||
import { insertImport } from '@schematics/angular/utility/route-utils';
|
||||
import { Schema } from './schema';
|
||||
import { InsertChange } from '@schematics/angular/utility/change';
|
||||
import { ngrxVersion } from '../utility/lib-versions';
|
||||
|
||||
function addImportsToModule(name: string, options: Schema): Rule {
|
||||
return (host: Tree) => {
|
||||
@ -35,7 +46,6 @@ function addImportsToModule(name: string, options: Schema): Rule {
|
||||
...addImportToModule(source, modulePath, `!environment.production ? StoreDevtoolsModule.instrument() : []`)
|
||||
]);
|
||||
return host;
|
||||
|
||||
} else {
|
||||
const reducerPath = `./+state/${toFileName(name)}.reducer`;
|
||||
const effectsPath = `./+state/${toFileName(name)}.effects`;
|
||||
@ -61,14 +71,16 @@ function addImportsToModule(name: string, options: Schema): Rule {
|
||||
insertImport(source, modulePath, 'environment', '../environments/environment'),
|
||||
...addImportToModule(source, modulePath, `StoreModule.forRoot(${reducerName}, {initialState: ${initName}})`),
|
||||
...addImportToModule(source, modulePath, `EffectsModule.forRoot([${effectsName}])`),
|
||||
...addImportToModule(source, modulePath, `!environment.production ? StoreDevtoolsModule.instrument() : []`),
|
||||
...addImportToModule(source, modulePath, `!environment.production ? StoreDevtoolsModule.instrument() : []`)
|
||||
]);
|
||||
} else {
|
||||
insert(host, modulePath, [
|
||||
...common,
|
||||
...addImportToModule(
|
||||
source, modulePath,
|
||||
`StoreModule.forFeature('${toPropertyName(name)}', ${reducerName}, {initialState: ${initName}})`),
|
||||
source,
|
||||
modulePath,
|
||||
`StoreModule.forFeature('${toPropertyName(name)}', ${reducerName}, {initialState: ${initName}})`
|
||||
),
|
||||
...addImportToModule(source, modulePath, `EffectsModule.forFeature([${effectsName}])`)
|
||||
]);
|
||||
}
|
||||
@ -112,9 +124,10 @@ export default function(options: Schema): Rule {
|
||||
if (options.onlyEmptyRoot) {
|
||||
return chain([addImportsToModule(name, options), options.skipPackageJson ? noop() : addNgRxToPackageJson()]);
|
||||
} else {
|
||||
const templateSource = apply(url('./files'), [template({...options, tmpl: '', ...names(name)}), move(moduleDir)]);
|
||||
const templateSource = apply(url('./files'), [template({ ...options, tmpl: '', ...names(name) }), move(moduleDir)]);
|
||||
return chain([
|
||||
branchAndMerge(chain([mergeWith(templateSource)])), addImportsToModule(name, options),
|
||||
branchAndMerge(chain([mergeWith(templateSource)])),
|
||||
addImportsToModule(name, options),
|
||||
options.skipPackageJson ? noop() : addNgRxToPackageJson()
|
||||
]);
|
||||
}
|
||||
|
||||
@ -1,14 +1,17 @@
|
||||
import {RuleFailure} from 'tslint';
|
||||
import { RuleFailure } from 'tslint';
|
||||
import * as ts from 'typescript';
|
||||
|
||||
import {Rule} from './nxEnforceModuleBoundariesRule';
|
||||
import { Rule } from './nxEnforceModuleBoundariesRule';
|
||||
|
||||
describe('Enforce Module Boundaries', () => {
|
||||
it('should not error when everything is in order', () => {
|
||||
const failures = runRule({npmScope: 'mycompany'}, `
|
||||
const failures = runRule(
|
||||
{ npmScope: 'mycompany' },
|
||||
`
|
||||
import '@mycompany/mylib';
|
||||
import '../blah';
|
||||
`);
|
||||
`
|
||||
);
|
||||
|
||||
expect(failures.length).toEqual(0);
|
||||
});
|
||||
@ -21,14 +24,14 @@ describe('Enforce Module Boundaries', () => {
|
||||
});
|
||||
|
||||
it('should error about deep imports into libraries', () => {
|
||||
const failures = runRule({npmScope: 'mycompany'}, `import '@mycompany/mylib/blah';`);
|
||||
const failures = runRule({ npmScope: 'mycompany' }, `import '@mycompany/mylib/blah';`);
|
||||
|
||||
expect(failures.length).toEqual(1);
|
||||
expect(failures[0].getFailure()).toEqual('deep imports into libraries are forbidden');
|
||||
});
|
||||
|
||||
it('should error on importing a lazy-loaded library', () => {
|
||||
const failures = runRule({npmScope: 'mycompany', lazyLoad: ['mylib']}, `import '@mycompany/mylib';`);
|
||||
const failures = runRule({ npmScope: 'mycompany', lazyLoad: ['mylib'] }, `import '@mycompany/mylib';`);
|
||||
|
||||
expect(failures.length).toEqual(1);
|
||||
expect(failures[0].getFailure()).toEqual('import of lazy-loaded libraries are forbidden');
|
||||
@ -36,7 +39,11 @@ describe('Enforce Module Boundaries', () => {
|
||||
});
|
||||
|
||||
function runRule(ruleArguments: any, content: string): RuleFailure[] {
|
||||
const options: any = {ruleArguments: [ruleArguments], ruleSeverity: 'error', ruleName: 'enforceModuleBoundaries'};
|
||||
const options: any = {
|
||||
ruleArguments: [ruleArguments],
|
||||
ruleSeverity: 'error',
|
||||
ruleName: 'enforceModuleBoundaries'
|
||||
};
|
||||
|
||||
const sourceFile = ts.createSourceFile('proj/apps/myapp/src/main.ts', content, ts.ScriptTarget.Latest, true);
|
||||
const rule = new Rule(options, 'proj');
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
import * as path from 'path';
|
||||
import * as Lint from 'tslint';
|
||||
import {IOptions} from 'tslint';
|
||||
import { IOptions } from 'tslint';
|
||||
import * as ts from 'typescript';
|
||||
|
||||
export class Rule extends Lint.Rules.AbstractRule {
|
||||
@ -29,10 +29,8 @@ class EnforceModuleBoundariesWalker extends Lint.RuleWalker {
|
||||
|
||||
if (impParts[0] === npmScope && impParts.length > 2) {
|
||||
this.addFailureAt(node.getStart(), node.getWidth(), 'deep imports into libraries are forbidden');
|
||||
|
||||
} else if (impParts[0] === npmScope && impParts.length === 2 && lazyLoad && lazyLoad.indexOf(impParts[1]) > -1) {
|
||||
this.addFailureAt(node.getStart(), node.getWidth(), 'import of lazy-loaded libraries are forbidden');
|
||||
|
||||
} else if (this.isRelative(imp) && this.isRelativeImportIntoAnotherProject(imp)) {
|
||||
this.addFailureAt(node.getStart(), node.getWidth(), 'relative imports of libraries are forbidden');
|
||||
}
|
||||
|
||||
@ -1,13 +1,34 @@
|
||||
import {apply, branchAndMerge, chain, mergeWith, move, noop, Rule, SchematicContext, template, Tree, url} from '@angular-devkit/schematics';
|
||||
import {
|
||||
apply,
|
||||
branchAndMerge,
|
||||
chain,
|
||||
mergeWith,
|
||||
move,
|
||||
noop,
|
||||
Rule,
|
||||
SchematicContext,
|
||||
template,
|
||||
Tree,
|
||||
url
|
||||
} from '@angular-devkit/schematics';
|
||||
|
||||
import {names, toClassName, toFileName, toPropertyName} from '../utility/name-utils';
|
||||
import { names, toClassName, toFileName, toPropertyName } from '../utility/name-utils';
|
||||
import * as path from 'path';
|
||||
import * as ts from 'typescript';
|
||||
import {addDeclarationToModule, addEntryComponents, addImportToModule, addMethod, addParameterToConstructor, addProviderToModule, getBootstrapComponent, insert, removeFromNgModule} from '../utility/ast-utils';
|
||||
import {insertImport} from '@schematics/angular/utility/route-utils';
|
||||
import {Schema} from './schema';
|
||||
import {angularJsVersion} from '../utility/lib-versions';
|
||||
|
||||
import {
|
||||
addDeclarationToModule,
|
||||
addEntryComponents,
|
||||
addImportToModule,
|
||||
addMethod,
|
||||
addParameterToConstructor,
|
||||
addProviderToModule,
|
||||
getBootstrapComponent,
|
||||
insert,
|
||||
removeFromNgModule
|
||||
} from '../utility/ast-utils';
|
||||
import { insertImport } from '@schematics/angular/utility/route-utils';
|
||||
import { Schema } from './schema';
|
||||
import { angularJsVersion } from '../utility/lib-versions';
|
||||
|
||||
function addImportsToModule(moduleClassName: string, options: Schema): Rule {
|
||||
return (host: Tree) => {
|
||||
@ -22,8 +43,11 @@ function addImportsToModule(moduleClassName: string, options: Schema): Rule {
|
||||
|
||||
insert(host, modulePath, [
|
||||
insertImport(
|
||||
source, modulePath, `configure${toClassName(options.name)}, upgradedComponents`,
|
||||
`./${toFileName(options.name)}-setup`),
|
||||
source,
|
||||
modulePath,
|
||||
`configure${toClassName(options.name)}, upgradedComponents`,
|
||||
`./${toFileName(options.name)}-setup`
|
||||
),
|
||||
insertImport(source, modulePath, 'UpgradeModule', '@angular/upgrade/static'),
|
||||
...addImportToModule(source, modulePath, 'UpgradeModule'),
|
||||
...addDeclarationToModule(source, modulePath, '...upgradedComponents'),
|
||||
@ -34,7 +58,6 @@ function addImportsToModule(moduleClassName: string, options: Schema): Rule {
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
function addNgDoBootstrapToModule(moduleClassName: string, options: Schema): Rule {
|
||||
return (host: Tree) => {
|
||||
if (!host.exists(options.module)) {
|
||||
@ -46,8 +69,10 @@ function addNgDoBootstrapToModule(moduleClassName: string, options: Schema): Rul
|
||||
const source = ts.createSourceFile(modulePath, sourceText, ts.ScriptTarget.Latest, true);
|
||||
|
||||
insert(host, modulePath, [
|
||||
...addParameterToConstructor(
|
||||
source, modulePath, {className: moduleClassName, param: 'private upgrade: UpgradeModule'}),
|
||||
...addParameterToConstructor(source, modulePath, {
|
||||
className: moduleClassName,
|
||||
param: 'private upgrade: UpgradeModule'
|
||||
}),
|
||||
...addMethod(source, modulePath, {
|
||||
className: moduleClassName,
|
||||
methodHeader: 'ngDoBootstrap(): void',
|
||||
@ -74,8 +99,9 @@ function createFiles(angularJsImport: string, moduleClassName: string, moduleFil
|
||||
const moduleSource = ts.createSourceFile(modulePath, moduleSourceText, ts.ScriptTarget.Latest, true);
|
||||
|
||||
const bootstrapComponentClassName = getBootstrapComponent(moduleSource, moduleClassName);
|
||||
const bootstrapComponentFileName =
|
||||
`${toFileName(bootstrapComponentClassName.substring(0, bootstrapComponentClassName.length - 9))}.component`;
|
||||
const bootstrapComponentFileName = `${toFileName(
|
||||
bootstrapComponentClassName.substring(0, bootstrapComponentClassName.length - 9)
|
||||
)}.component`;
|
||||
|
||||
const moduleDir = path.dirname(options.module);
|
||||
const templateSource = apply(url('./files'), [
|
||||
@ -97,7 +123,6 @@ function createFiles(angularJsImport: string, moduleClassName: string, moduleFil
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
function addUpgradeToPackageJson() {
|
||||
return (host: Tree) => {
|
||||
if (!host.exists('package.json')) return host;
|
||||
@ -127,7 +152,8 @@ export default function(options: Schema): Rule {
|
||||
|
||||
return chain([
|
||||
createFiles(angularJsImport, moduleClassName, moduleFileName, options),
|
||||
addImportsToModule(moduleClassName, options), addNgDoBootstrapToModule(moduleClassName, options),
|
||||
addImportsToModule(moduleClassName, options),
|
||||
addNgDoBootstrapToModule(moduleClassName, options),
|
||||
options.skipPackageJson ? noop() : addUpgradeToPackageJson()
|
||||
]);
|
||||
}
|
||||
|
||||
@ -5,17 +5,20 @@
|
||||
* 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} from '@angular-devkit/schematics';
|
||||
import {getDecoratorMetadata, getSourceNodes, insertAfterLastOccurrence} from '@schematics/angular/utility/ast-utils';
|
||||
import {Change, InsertChange, NoopChange, RemoveChange} from '@schematics/angular/utility/change';
|
||||
import { Tree } from '@angular-devkit/schematics';
|
||||
import { getDecoratorMetadata, getSourceNodes, insertAfterLastOccurrence } from '@schematics/angular/utility/ast-utils';
|
||||
import { Change, InsertChange, NoopChange, RemoveChange } from '@schematics/angular/utility/change';
|
||||
import * as ts from 'typescript';
|
||||
|
||||
|
||||
// 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[] {
|
||||
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
|
||||
let node: any = nodes[0]; // tslint:disable-line:no-any
|
||||
|
||||
// Find the decorator declaration.
|
||||
if (!node) {
|
||||
@ -23,23 +26,21 @@ function _addSymbolToNgModuleMetadata(
|
||||
}
|
||||
|
||||
// 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;
|
||||
}
|
||||
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;
|
||||
});
|
||||
return false;
|
||||
});
|
||||
|
||||
// Get the last node of the array literal.
|
||||
if (!matchingProperties) {
|
||||
@ -90,7 +91,7 @@ function _addSymbolToNgModuleMetadata(
|
||||
}
|
||||
|
||||
if (Array.isArray(node)) {
|
||||
const nodeArray = node as {} as Array<ts.Node>;
|
||||
const nodeArray = (node as {}) as Array<ts.Node>;
|
||||
const symbolsArray = nodeArray.map(node => node.getText());
|
||||
if (symbolsArray.includes(expression)) {
|
||||
return [];
|
||||
@ -137,27 +138,37 @@ function _addSymbolToNgModuleMetadata(
|
||||
}
|
||||
|
||||
export function addParameterToConstructor(
|
||||
source: ts.SourceFile, modulePath: string, opts: {className: string, param: string}): Change[] {
|
||||
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});
|
||||
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[] {
|
||||
source: ts.SourceFile,
|
||||
modulePath: string,
|
||||
opts: { className: string; methodHeader: string; body: string }
|
||||
): Change[] {
|
||||
const clazz = findClass(source, opts.className);
|
||||
const body = opts.body ? `
|
||||
const body = opts.body
|
||||
? `
|
||||
${opts.methodHeader} {
|
||||
${offset(opts.body, 1, false)}
|
||||
}
|
||||
` :
|
||||
`
|
||||
`
|
||||
: `
|
||||
${opts.methodHeader} {}
|
||||
`;
|
||||
|
||||
@ -167,7 +178,7 @@ ${opts.methodHeader} {}
|
||||
|
||||
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
|
||||
let node: any = nodes[0]; // tslint:disable-line:no-any
|
||||
|
||||
// Find the decorator declaration.
|
||||
if (!node) {
|
||||
@ -177,7 +188,7 @@ export function removeFromNgModule(source: ts.SourceFile, modulePath: string, pr
|
||||
// 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))]
|
||||
return [new RemoveChange(modulePath, matchingProperty.pos, matchingProperty.getFullText(source))];
|
||||
} else {
|
||||
return [];
|
||||
}
|
||||
@ -186,8 +197,9 @@ export function removeFromNgModule(source: ts.SourceFile, modulePath: string, pr
|
||||
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];
|
||||
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}'`);
|
||||
@ -197,27 +209,23 @@ function findClass(source: ts.SourceFile, className: string): ts.ClassDeclaratio
|
||||
}
|
||||
|
||||
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');
|
||||
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,
|
||||
);
|
||||
return _addSymbolToNgModuleMetadata(source, modulePath, 'imports', symbolName);
|
||||
}
|
||||
|
||||
export function getBootstrapComponent(source: ts.SourceFile, moduleClassName: string): string {
|
||||
@ -238,13 +246,13 @@ export function getBootstrapComponent(source: ts.SourceFile, moduleClassName: st
|
||||
|
||||
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
|
||||
let node: any = nodes[0]; // tslint:disable-line:no-any
|
||||
|
||||
if (!node) return null;
|
||||
|
||||
// Get all the children property assignment of object literals.
|
||||
return (node as ts.ObjectLiteralExpression)
|
||||
.properties
|
||||
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).
|
||||
@ -257,7 +265,8 @@ function getMatchingProperty(source: ts.SourceFile, property: string): ts.Object
|
||||
return (name as ts.StringLiteral).text === property;
|
||||
}
|
||||
return false;
|
||||
})[0];
|
||||
})[0]
|
||||
);
|
||||
}
|
||||
|
||||
export function addProviderToModule(source: ts.SourceFile, modulePath: string, symbolName: string): Change[] {
|
||||
@ -272,7 +281,6 @@ export function addEntryComponents(source: ts.SourceFile, modulePath: string, sy
|
||||
return _addSymbolToNgModuleMetadata(source, modulePath, 'entryComponents', symbolName);
|
||||
}
|
||||
|
||||
|
||||
export function insert(host: Tree, modulePath: string, changes: Change[]) {
|
||||
const recorder = host.beginUpdate(modulePath);
|
||||
for (const change of changes) {
|
||||
|
||||
@ -1,23 +1,30 @@
|
||||
import {addApp} from './config-file-utils';
|
||||
import { addApp } from './config-file-utils';
|
||||
|
||||
describe('configFileUtils', () => {
|
||||
describe('sortApps', () => {
|
||||
it('should handle undefined', () => {
|
||||
expect(addApp(undefined, {name: 'a'})).toEqual([{name: 'a'}]);
|
||||
expect(addApp(undefined, { name: 'a' })).toEqual([{ name: 'a' }]);
|
||||
});
|
||||
|
||||
it('should handle an empty array', () => {
|
||||
expect(addApp([], {name: 'a'})).toEqual([{name: 'a'}]);
|
||||
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'}]);
|
||||
expect(addApp([{ name: 'a' }, { name: 'b' }], { name: 'c' })).toEqual([
|
||||
{ name: 'a' },
|
||||
{ name: 'b' },
|
||||
{ name: 'c' }
|
||||
]);
|
||||
});
|
||||
|
||||
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'}
|
||||
]);
|
||||
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,4 +1,4 @@
|
||||
export function addApp(apps: any[]|undefined, newApp: any): any[] {
|
||||
export function addApp(apps: any[] | undefined, newApp: any): any[] {
|
||||
if (!apps) {
|
||||
apps = [];
|
||||
}
|
||||
|
||||
@ -4,6 +4,7 @@ export const angularJsVersion = '1.6.6';
|
||||
export const ngrxVersion = '^4.0.0';
|
||||
export const nxVersion = 'nrwl/nx-build';
|
||||
export const schematicsVersion = 'nrwl/schematics-build';
|
||||
export const prettierVersion = '1.7.4';
|
||||
|
||||
export const libVersions = {
|
||||
angularVersion,
|
||||
@ -11,5 +12,6 @@ export const libVersions = {
|
||||
angularJsVersion,
|
||||
ngrxVersion,
|
||||
nxVersion,
|
||||
schematicsVersion
|
||||
schematicsVersion,
|
||||
prettierVersion
|
||||
};
|
||||
|
||||
@ -1,5 +1,10 @@
|
||||
export function names(name: string): any {
|
||||
return {name, className: toClassName(name), propertyName: toPropertyName(name), fileName: toFileName(name)};
|
||||
return {
|
||||
name,
|
||||
className: toClassName(name),
|
||||
propertyName: toPropertyName(name),
|
||||
fileName: toFileName(name)
|
||||
};
|
||||
}
|
||||
|
||||
export function toClassName(str: string): string {
|
||||
@ -7,12 +12,16 @@ export function toClassName(str: string): string {
|
||||
}
|
||||
|
||||
export function toPropertyName(s: string): string {
|
||||
return s.replace(/(-|_|\.|\s)+(.)?/g, (_, __, chr) => chr ? chr.toUpperCase() : '')
|
||||
.replace(/^([A-Z])/, m => m.toLowerCase());
|
||||
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, '-');
|
||||
return s
|
||||
.replace(/([a-z\d])([A-Z])/g, '$1_$2')
|
||||
.toLowerCase()
|
||||
.replace(/[ _]/g, '-');
|
||||
}
|
||||
|
||||
function toCapitalCase(s: string): string {
|
||||
|
||||
@ -1,3 +0,0 @@
|
||||
Language: JavaScript
|
||||
BasedOnStyle: Google
|
||||
ColumnLimit: 120
|
||||
@ -1,11 +1,23 @@
|
||||
import {apply, branchAndMerge, chain, externalSchematic, mergeWith, move, Rule, template, Tree, url, schematic} from '@angular-devkit/schematics';
|
||||
import {Schema} from './schema';
|
||||
import {
|
||||
apply,
|
||||
branchAndMerge,
|
||||
chain,
|
||||
externalSchematic,
|
||||
mergeWith,
|
||||
move,
|
||||
Rule,
|
||||
template,
|
||||
Tree,
|
||||
url,
|
||||
schematic
|
||||
} from '@angular-devkit/schematics';
|
||||
import { Schema } from './schema';
|
||||
import * as path from 'path';
|
||||
import {angularCliVersion, ngrxVersion, nxVersion, schematicsVersion} from '../utility/lib-versions';
|
||||
import { angularCliVersion, ngrxVersion, nxVersion, prettierVersion, schematicsVersion } from '../utility/lib-versions';
|
||||
import * as fs from 'fs';
|
||||
import {join} from 'path';
|
||||
import {updateJsonFile} from '../utility/fileutils';
|
||||
import {toFileName} from '@nrwl/schematics';
|
||||
import { join } from 'path';
|
||||
import { updateJsonFile } from '../utility/fileutils';
|
||||
import { toFileName } from '@nrwl/schematics';
|
||||
|
||||
function updatePackageJson() {
|
||||
return (host: Tree) => {
|
||||
@ -43,8 +55,10 @@ function updatePackageJson() {
|
||||
if (!packageJson.dependencies['@angular/cli']) {
|
||||
packageJson.dependencies['@angular/cli'] = angularCliVersion;
|
||||
}
|
||||
packageJson.scripts['format'] =
|
||||
`find apps/ -iname '*.ts' | xargs clang-format -i && find libs/ -iname '*.ts' | xargs clang-format -i`;
|
||||
if (!packageJson.devDependencies['prettier']) {
|
||||
packageJson.devDependencies['prettier'] = prettierVersion;
|
||||
}
|
||||
packageJson.scripts['format'] = `prettier --single-quote --print-width 120 --write '{apps,libs}/**/*.ts'`;
|
||||
host.overwrite('package.json', JSON.stringify(packageJson, null, 2));
|
||||
return host;
|
||||
};
|
||||
@ -60,8 +74,11 @@ function updateAngularCLIJson(options: Schema) {
|
||||
throw new Error('Can only convert projects with one app');
|
||||
}
|
||||
|
||||
angularCliJson.lint =
|
||||
[{'project': './tsconfig.app.json'}, {'project': './tsconfig.spec.json'}, {'project': './tsconfig.e2e.json'}];
|
||||
angularCliJson.lint = [
|
||||
{ project: './tsconfig.app.json' },
|
||||
{ project: './tsconfig.spec.json' },
|
||||
{ project: './tsconfig.e2e.json' }
|
||||
];
|
||||
|
||||
const app = angularCliJson.apps[0];
|
||||
app.root = path.join('apps', options.name, app.root);
|
||||
@ -69,7 +86,7 @@ function updateAngularCLIJson(options: Schema) {
|
||||
app.test = '../../../test.js';
|
||||
app.tsconfig = '../../../tsconfig.app.json';
|
||||
app.testTsconfig = '../../../tsconfig.spec.json';
|
||||
app.scripts = app.scripts.map((p) => path.join('../../', p));
|
||||
app.scripts = app.scripts.map(p => path.join('../../', p));
|
||||
if (!angularCliJson.defaults) {
|
||||
angularCliJson.defaults = {};
|
||||
}
|
||||
@ -90,16 +107,16 @@ function updateTsConfigsJson(options: Schema) {
|
||||
return (host: Tree) => {
|
||||
const npmScope = options && options.npmScope ? options.npmScope : options.name;
|
||||
|
||||
updateJsonFile('tsconfig.json', (json) => setUpCompilerOptions(json, npmScope));
|
||||
updateJsonFile('tsconfig.json', json => setUpCompilerOptions(json, npmScope));
|
||||
|
||||
updateJsonFile('tsconfig.app.json', (json) => {
|
||||
updateJsonFile('tsconfig.app.json', json => {
|
||||
json['extends'] = './tsconfig.json';
|
||||
if (!json.exclude) json.exclude = [];
|
||||
json.exclude = dedup(json.exclude.concat(['**/*.spec.ts', '**/*.e2e-spec.ts', 'node_modules', 'tmp']));
|
||||
setUpCompilerOptions(json, npmScope);
|
||||
});
|
||||
|
||||
updateJsonFile('tsconfig.spec.json', (json) => {
|
||||
updateJsonFile('tsconfig.spec.json', json => {
|
||||
json['extends'] = './tsconfig.json';
|
||||
if (!json.exclude) json.exclude = [];
|
||||
json.files = ['test.js'];
|
||||
@ -107,7 +124,7 @@ function updateTsConfigsJson(options: Schema) {
|
||||
setUpCompilerOptions(json, npmScope);
|
||||
});
|
||||
|
||||
updateJsonFile('tsconfig.e2e.json', (json) => {
|
||||
updateJsonFile('tsconfig.e2e.json', json => {
|
||||
json['extends'] = './tsconfig.json';
|
||||
if (!json.exclude) json.exclude = [];
|
||||
json.exclude = dedup(json.exclude.concat(['**/*.spec.ts', 'node_modules', 'tmp']));
|
||||
@ -122,11 +139,11 @@ function updateTsLintJson(options: Schema) {
|
||||
return (host: Tree) => {
|
||||
const npmScope = options && options.npmScope ? options.npmScope : options.name;
|
||||
|
||||
updateJsonFile('tslint.json', (json) => {
|
||||
updateJsonFile('tslint.json', json => {
|
||||
['no-trailing-whitespace', 'one-line', 'quotemark', 'typedef-whitespace', 'whitespace'].forEach(key => {
|
||||
json[key] = undefined;
|
||||
});
|
||||
json['nx-enforce-module-boundaries'] = [true, {'npmScope': npmScope, 'lazyLoad': []}];
|
||||
json['nx-enforce-module-boundaries'] = [true, { npmScope: npmScope, lazyLoad: [] }];
|
||||
});
|
||||
return host;
|
||||
};
|
||||
@ -138,8 +155,9 @@ function updateProtractorConf() {
|
||||
throw new Error('Cannot find protractor.conf.js');
|
||||
}
|
||||
const protractorConf = host.read('protractor.conf.js')!.toString('utf-8');
|
||||
const updatedConf = protractorConf.replace(`./e2e/**/*.e2e-spec.ts`, `./apps/**/*.e2e-spec.ts`)
|
||||
.replace(`e2e/tsconfig.e2e.json`, `./tsconfig.e2e.json`);
|
||||
const updatedConf = protractorConf
|
||||
.replace(`./e2e/**/*.e2e-spec.ts`, `./apps/**/*.e2e-spec.ts`)
|
||||
.replace(`e2e/tsconfig.e2e.json`, `./tsconfig.e2e.json`);
|
||||
|
||||
host.overwrite('protractor.conf.js', updatedConf);
|
||||
|
||||
@ -186,12 +204,14 @@ function dedup(array: any[]): any[] {
|
||||
}
|
||||
|
||||
export default function(schema: Schema): Rule {
|
||||
const options = {...schema, name: toFileName(schema.name)};
|
||||
const options = { ...schema, name: toFileName(schema.name) };
|
||||
return chain([
|
||||
moveFiles(options), branchAndMerge(chain([
|
||||
mergeWith(apply(url('./files'), [])),
|
||||
])),
|
||||
updatePackageJson(), updateAngularCLIJson(options), updateTsConfigsJson(options), updateProtractorConf(),
|
||||
moveFiles(options),
|
||||
branchAndMerge(chain([mergeWith(apply(url('./files'), []))])),
|
||||
updatePackageJson(),
|
||||
updateAngularCLIJson(options),
|
||||
updateTsConfigsJson(options),
|
||||
updateProtractorConf(),
|
||||
updateTsLintJson(options)
|
||||
]);
|
||||
}
|
||||
|
||||
@ -1,15 +1,3 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
find packages/ -iname "*.ts" | xargs -n1 clang-format -output-replacements-xml | grep -c "<replacement " >/dev/null
|
||||
if [ $? -ne 1 ]
|
||||
then
|
||||
echo "Please run yarn format"
|
||||
exit 1;
|
||||
fi
|
||||
|
||||
find e2e/ -iname "*.ts" | xargs -n1 clang-format -output-replacements-xml | grep -c "<replacement " >/dev/null
|
||||
if [ $? -ne 1 ]
|
||||
then
|
||||
echo "Please run yarn format"
|
||||
exit 1;
|
||||
fi
|
||||
prettier --single-quote --print-width 120 --list-different '{packages,e2e}/**/*.ts'
|
||||
|
||||
@ -1,4 +1,3 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
find packages/ -iname "*.ts" | xargs clang-format -i
|
||||
find e2e/ -iname "*.ts" | xargs clang-format -i
|
||||
prettier --single-quote --print-width 120 --write '{packages,e2e}/**/*.ts'
|
||||
|
||||
14
yarn.lock
14
yarn.lock
@ -968,14 +968,6 @@ circular-dependency-plugin@^3.0.0:
|
||||
version "3.0.0"
|
||||
resolved "https://registry.yarnpkg.com/circular-dependency-plugin/-/circular-dependency-plugin-3.0.0.tgz#9b68692e35b0e3510998d0164b6ae5011bea5760"
|
||||
|
||||
clang-format@1.0.55:
|
||||
version "1.0.55"
|
||||
resolved "https://registry.yarnpkg.com/clang-format/-/clang-format-1.0.55.tgz#8031271329e27a779a5d08fc5dce24d7c52c14d5"
|
||||
dependencies:
|
||||
async "^1.5.2"
|
||||
glob "^7.0.0"
|
||||
resolve "^1.1.6"
|
||||
|
||||
clap@^1.0.9:
|
||||
version "1.2.3"
|
||||
resolved "https://registry.yarnpkg.com/clap/-/clap-1.2.3.tgz#4f36745b32008492557f46412d66d50cb99bce51"
|
||||
@ -4532,6 +4524,10 @@ preserve@^0.2.0:
|
||||
version "0.2.0"
|
||||
resolved "https://registry.yarnpkg.com/preserve/-/preserve-0.2.0.tgz#815ed1f6ebc65926f865b310c0713bcb3315ce4b"
|
||||
|
||||
prettier@1.7.4:
|
||||
version "1.7.4"
|
||||
resolved "https://registry.yarnpkg.com/prettier/-/prettier-1.7.4.tgz#5e8624ae9363c80f95ec644584ecdf55d74f93fa"
|
||||
|
||||
pretty-error@^2.0.2:
|
||||
version "2.1.1"
|
||||
resolved "https://registry.yarnpkg.com/pretty-error/-/pretty-error-2.1.1.tgz#5f4f87c8f91e5ae3f3ba87ab4cf5e03b1a17f1a3"
|
||||
@ -4902,7 +4898,7 @@ resolve@1.1.7:
|
||||
version "1.1.7"
|
||||
resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.1.7.tgz#203114d82ad2c5ed9e8e0411b3932875e889e97b"
|
||||
|
||||
resolve@^1.1.6, resolve@^1.1.7, resolve@^1.3.2:
|
||||
resolve@^1.1.7, resolve@^1.3.2:
|
||||
version "1.4.0"
|
||||
resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.4.0.tgz#a75be01c53da25d934a98ebd0e4c4a7312f92a86"
|
||||
dependencies:
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user