feat(schematics): use @ngrx/schematics
* ngrx collection now extends @ngrx/schematics * modify the nrwl `ngrx` schematic to use `@ngrx/schematics` to generate the initial source for actions, reducers, and effects * modify the generated source to conform to Nx standards * generate init and interface files * remove template files for action, effect, and reducer scaffolding * modify collection to extend `@ngrx/schematics` so the ngrx commands are also easily accessible * inject dataloaded enums into action class * configure nx workspace devDep on @ngrx/schematics version * override ngrx effects.spec.ts with nx templated version fixes #174.
This commit is contained in:
parent
2acf28c50d
commit
4edc8e6c8b
@ -1,4 +1,4 @@
|
||||
import { newApp, newProject, runCLI, updateFile } from '../utils';
|
||||
import { newApp, newProject, runCLI } from '../utils';
|
||||
|
||||
describe('ngrx', () => {
|
||||
it(
|
||||
@ -9,47 +9,11 @@ describe('ngrx', () => {
|
||||
runCLI(
|
||||
'generate ngrx app --module=apps/myapp/src/app/app.module.ts --root --collection=@nrwl/schematics'
|
||||
);
|
||||
updateFile(
|
||||
'apps/myapp/src/app/+state/app.interfaces.ts',
|
||||
`
|
||||
export interface App {
|
||||
rootCount: number;
|
||||
}
|
||||
export interface AppState {
|
||||
readonly app: App;
|
||||
}
|
||||
`
|
||||
);
|
||||
|
||||
updateFile(
|
||||
'apps/myapp/src/app/+state/app.init.ts',
|
||||
`
|
||||
import { App } from './app.interfaces';
|
||||
export const appInitialState: App = {
|
||||
rootCount: 0
|
||||
};
|
||||
`
|
||||
);
|
||||
console.log('build');
|
||||
console.log(runCLI('build'));
|
||||
|
||||
updateFile(
|
||||
'apps/myapp/src/app/+state/app.reducer.spec.ts',
|
||||
`
|
||||
import { appReducer } from './app.reducer';
|
||||
import { App } from './app.interfaces';
|
||||
import { DataLoaded } from './app.actions';
|
||||
|
||||
describe('appReducer', () => {
|
||||
it('should work', () => {
|
||||
const state: App = {rootCount: 0};
|
||||
const action: DataLoaded = {type: 'DATA_LOADED', payload: {}};
|
||||
const actual = appReducer(state, action);
|
||||
expect(actual).toEqual({rootCount: 0});
|
||||
});
|
||||
});
|
||||
`
|
||||
);
|
||||
|
||||
runCLI('build');
|
||||
console.log('test');
|
||||
runCLI('test --single-run');
|
||||
},
|
||||
1000000
|
||||
|
||||
@ -5,8 +5,8 @@ import {
|
||||
runCLI,
|
||||
runNgNew,
|
||||
updateFile,
|
||||
readJson,
|
||||
readFile
|
||||
readFile,
|
||||
readJson
|
||||
} from '../utils';
|
||||
import { angularCliSchema } from '../../packages/schematics/src/lib-versions';
|
||||
|
||||
|
||||
@ -53,7 +53,8 @@ export function copyMissingPackages(): void {
|
||||
'jasmine-marbles',
|
||||
'@nrwl',
|
||||
'angular',
|
||||
'@angular/upgrade'
|
||||
'@angular/upgrade',
|
||||
'npm-run-all'
|
||||
];
|
||||
modulesToCopy.forEach(m => copyNodeModule(projectName, m));
|
||||
}
|
||||
|
||||
@ -34,6 +34,7 @@
|
||||
"@angular/upgrade": "5.2.7",
|
||||
"@ngrx/effects": "5.2.0",
|
||||
"@ngrx/router-store": "5.2.0",
|
||||
"@ngrx/schematics": "^5.2.0",
|
||||
"@ngrx/store": "5.2.0",
|
||||
"@ngrx/store-devtools": "5.2.0",
|
||||
"@types/jasmine": "~2.8.3",
|
||||
@ -67,6 +68,9 @@
|
||||
"author": "Victor Savkin",
|
||||
"license": "MIT",
|
||||
"jest": {
|
||||
"modulePathIgnorePatterns": ["tmp", "files"]
|
||||
"modulePathIgnorePatterns": [
|
||||
"tmp",
|
||||
"files"
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
@ -2,21 +2,42 @@
|
||||
"name": "@nrwl/schematics",
|
||||
"version": "0.0.1",
|
||||
"description": "Nrwl Extensions for Angular: Schematics",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "git+https://github.com/nrwl/nx.git"
|
||||
},
|
||||
"keywords": [
|
||||
"RxJS",
|
||||
"Angular",
|
||||
"Workspace",
|
||||
"NgRx",
|
||||
"Schematics",
|
||||
"Angular CLI"
|
||||
],
|
||||
"bin": {
|
||||
"create-nx-workspace": "./bin/create-nx-workspace.js",
|
||||
"nx": "./src/command-line/nx.js"
|
||||
},
|
||||
"main": "index.js",
|
||||
"types": "index.d.js",
|
||||
"peerDependencies": {},
|
||||
"peerDependencies": { },
|
||||
"author": "Victor Savkin",
|
||||
"license": "MIT",
|
||||
"bugs": {
|
||||
"url": "https://github.com/nrwl/nx/issues"
|
||||
},
|
||||
"homepage": "https://github.com/nrwl/nx#readme",
|
||||
"schematics": "./src/collection.json",
|
||||
"dependencies": {
|
||||
"@ngrx/schematics": "5.2.0",
|
||||
"@schematics/angular": "0.4.6",
|
||||
"app-root-path": "^2.0.1",
|
||||
"npm-run-all": "4.1.2",
|
||||
"semver": "5.4.1",
|
||||
"tmp": "0.0.33",
|
||||
"yargs-parser": "9.0.2"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@angular-devkit/schematics": "0.4.6"
|
||||
}
|
||||
}
|
||||
|
||||
6
packages/schematics/src/README.md
Normal file
6
packages/schematics/src/README.md
Normal file
@ -0,0 +1,6 @@
|
||||
@nrwl/schematics
|
||||
=======
|
||||
|
||||
The sources for this package are in the main [nrwl/nx](https://github.com/nrwl/nx) repo. Please file issues and pull requests against that repo.
|
||||
|
||||
License: MIT
|
||||
@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "nx",
|
||||
"version": "0.1",
|
||||
"extends": "@schematics/angular",
|
||||
"extends": "@ngrx/schematics",
|
||||
"schematics": {
|
||||
"workspace": {
|
||||
"factory": "./collection/workspace",
|
||||
|
||||
1
packages/schematics/src/collection/application/files/__directory__/package.json
Normal file → Executable file
1
packages/schematics/src/collection/application/files/__directory__/package.json
Normal file → Executable file
@ -47,6 +47,7 @@
|
||||
"devDependencies": {
|
||||
"@angular/cli": "<%= angularCliVersion %>",
|
||||
"@angular/compiler-cli": "<%= angularVersion %>",
|
||||
"@ngrx/schematics": "<%= ngrxSchematicsVersion %>",
|
||||
"@nrwl/schematics": "<%= schematicsVersion %>",
|
||||
"@angular/language-service": "<%= angularVersion %>",<% if (!minimal) { %>
|
||||
"@types/jasmine": "~2.8.3",
|
||||
|
||||
@ -1,12 +0,0 @@
|
||||
export interface LoadData {
|
||||
type: 'LOAD_DATA';
|
||||
payload: {};
|
||||
}
|
||||
|
||||
export interface DataLoaded {
|
||||
type: 'DATA_LOADED';
|
||||
payload: {};
|
||||
}
|
||||
|
||||
export type <%= className %>Action = LoadData | DataLoaded;
|
||||
|
||||
@ -1,13 +1,17 @@
|
||||
import {TestBed, async} from '@angular/core/testing';
|
||||
import {TestBed} from '@angular/core/testing';
|
||||
import {StoreModule} from '@ngrx/store';
|
||||
import {provideMockActions} from '@ngrx/effects/testing';
|
||||
import {DataPersistence} from '@nrwl/nx';
|
||||
import {hot} from '@nrwl/nx/testing';
|
||||
|
||||
import {<%= className %>Effects} from './<%= fileName %>.effects';
|
||||
import {Load<%= className %>, <%= className %>Loaded } from './<%= fileName %>.actions';
|
||||
|
||||
import { Observable } from 'rxjs/Observable';
|
||||
|
||||
describe('<%= className %>Effects', () => {
|
||||
let actions;
|
||||
let effects: <%= className %>Effects;
|
||||
let actions$: Observable<any>;
|
||||
let effects$: <%= className %>Effects;
|
||||
|
||||
beforeEach(() => {
|
||||
TestBed.configureTestingModule({
|
||||
@ -17,18 +21,18 @@ describe('<%= className %>Effects', () => {
|
||||
providers: [
|
||||
<%= className %>Effects,
|
||||
DataPersistence,
|
||||
provideMockActions(() => actions)
|
||||
provideMockActions(() => actions$)
|
||||
],
|
||||
});
|
||||
|
||||
effects = TestBed.get(<%= className %>Effects);
|
||||
effects$ = TestBed.get(<%= className %>Effects);
|
||||
});
|
||||
|
||||
describe('someEffect', () => {
|
||||
it('should work', () => {
|
||||
actions = hot('-a-|', {a: {type: 'LOAD_DATA'}});
|
||||
expect(effects.loadData).toBeObservable(
|
||||
hot('-a-|', {a: {type: 'DATA_LOADED', payload: {}}})
|
||||
actions$ = hot('-a-|', {a: new Load<%= className %>({})});
|
||||
expect(effects$.load<%= className %>$).toBeObservable(
|
||||
hot('-a-|', {a: new <%= className %>Loaded({})})
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
@ -1,25 +0,0 @@
|
||||
import {Injectable} from '@angular/core';
|
||||
import {Effect, Actions} from '@ngrx/effects';
|
||||
import {DataPersistence} from '@nrwl/nx';
|
||||
import {of} from 'rxjs/observable/of';
|
||||
import 'rxjs/add/operator/switchMap';
|
||||
import {<%= className %>State} from './<%= fileName %>.interfaces';
|
||||
import {LoadData, DataLoaded} from './<%= fileName %>.actions';
|
||||
|
||||
@Injectable()
|
||||
export class <%= className %>Effects {
|
||||
@Effect() loadData = this.dataPersistence.fetch('LOAD_DATA', {
|
||||
run: (action: LoadData, state: <%= className %>State) => {
|
||||
return {
|
||||
type: 'DATA_LOADED',
|
||||
payload: {}
|
||||
};
|
||||
},
|
||||
|
||||
onError: (action: LoadData, error) => {
|
||||
console.error('Error', error);
|
||||
}
|
||||
});
|
||||
|
||||
constructor(private actions: Actions, private dataPersistence: DataPersistence<<%= className %>State>) {}
|
||||
}
|
||||
@ -1,5 +0,0 @@
|
||||
import {<%= className %>} from './<%= fileName %>.interfaces';
|
||||
|
||||
export const <%= propertyName %>InitialState: <%= className %> = {
|
||||
// fill it initial state here
|
||||
};
|
||||
@ -1,7 +0,0 @@
|
||||
export interface <%= className %> {
|
||||
// define state here
|
||||
}
|
||||
|
||||
export interface <%= className %>State {
|
||||
readonly <%= propertyName %>: <%= className %>;
|
||||
}
|
||||
@ -1,13 +1,10 @@
|
||||
import { <%= propertyName %>Reducer } from './<%= fileName %>.reducer';
|
||||
import { <%= propertyName %>InitialState } from './<%= fileName %>.init';
|
||||
import { <%= className %> } from './<%= fileName %>.interfaces';
|
||||
import { DataLoaded } from './<%= fileName %>.actions';
|
||||
import { <%= className %>Loaded } from './<%= fileName %>.actions';
|
||||
import { <%= propertyName %>Reducer, initialState } from './<%= fileName %>.reducer';
|
||||
|
||||
describe('<%= propertyName %>Reducer', () => {
|
||||
it('should work', () => {
|
||||
const state: <%= className %> = {};
|
||||
const action: DataLoaded = {type: 'DATA_LOADED', payload: {}};
|
||||
const actual = <%= propertyName %>Reducer(state, action);
|
||||
const action: <%= className %>Loaded = new <%= className %>Loaded({});
|
||||
const actual = <%= fileName %>Reducer(initialState, action);
|
||||
expect(actual).toEqual({});
|
||||
});
|
||||
});
|
||||
|
||||
@ -1,13 +0,0 @@
|
||||
import {<%= className %>} from './<%= fileName %>.interfaces';
|
||||
import {<%= className %>Action} from './<%= fileName %>.actions';
|
||||
|
||||
export function <%= propertyName %>Reducer(state: <%= className %>, action: <%= className %>Action): <%= className %> {
|
||||
switch (action.type) {
|
||||
case 'DATA_LOADED': {
|
||||
return {...state, ...action.payload};
|
||||
}
|
||||
default: {
|
||||
return state;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -2,238 +2,116 @@ import {
|
||||
apply,
|
||||
branchAndMerge,
|
||||
chain,
|
||||
externalSchematic,
|
||||
mergeWith,
|
||||
move,
|
||||
noop,
|
||||
Rule,
|
||||
template,
|
||||
Tree,
|
||||
url
|
||||
} from '@angular-devkit/schematics';
|
||||
import { Tree } from '@angular-devkit/schematics';
|
||||
|
||||
import {
|
||||
names,
|
||||
toClassName,
|
||||
toFileName,
|
||||
toPropertyName
|
||||
} from '../../utils/name-utils';
|
||||
import * as path from 'path';
|
||||
import * as ts from 'typescript';
|
||||
import {
|
||||
addImportToModule,
|
||||
addProviderToModule,
|
||||
insert,
|
||||
updateJson
|
||||
} from '../../utils/ast-utils';
|
||||
import { insertImport } from '@schematics/angular/utility/route-utils';
|
||||
import { Schema } from './schema';
|
||||
import {
|
||||
ngrxVersion,
|
||||
routerStoreVersion,
|
||||
ngrxStoreFreezeVersion
|
||||
} from '../../lib-versions';
|
||||
import * as path from 'path';
|
||||
|
||||
import { names, toFileName } from '../../utils/name-utils';
|
||||
import { wrapIntoFormat } from '../../utils/tasks';
|
||||
|
||||
function addImportsToModule(name: string, options: Schema): Rule {
|
||||
return (host: Tree) => {
|
||||
if (options.onlyAddFiles) {
|
||||
return host;
|
||||
}
|
||||
import {
|
||||
RequestContext,
|
||||
updateNgrxReducers,
|
||||
updateNgrxActions,
|
||||
updateNgrxEffects,
|
||||
addImportsToModule,
|
||||
addNgRxToPackageJson
|
||||
} from './rules';
|
||||
import { deleteFile } from '../../utils/rules/deleteFile';
|
||||
|
||||
if (!host.exists(options.module)) {
|
||||
throw new Error('Specified module does not exist');
|
||||
}
|
||||
|
||||
const modulePath = options.module;
|
||||
|
||||
const sourceText = host.read(modulePath)!.toString('utf-8');
|
||||
const source = ts.createSourceFile(
|
||||
modulePath,
|
||||
sourceText,
|
||||
ts.ScriptTarget.Latest,
|
||||
true
|
||||
);
|
||||
|
||||
if (options.onlyEmptyRoot) {
|
||||
insert(host, modulePath, [
|
||||
insertImport(source, modulePath, 'StoreModule', '@ngrx/store'),
|
||||
insertImport(source, modulePath, 'EffectsModule', '@ngrx/effects'),
|
||||
insertImport(
|
||||
source,
|
||||
modulePath,
|
||||
'StoreDevtoolsModule',
|
||||
'@ngrx/store-devtools'
|
||||
),
|
||||
insertImport(
|
||||
source,
|
||||
modulePath,
|
||||
'environment',
|
||||
'../environments/environment'
|
||||
),
|
||||
insertImport(
|
||||
source,
|
||||
modulePath,
|
||||
'StoreRouterConnectingModule',
|
||||
'@ngrx/router-store'
|
||||
),
|
||||
insertImport(source, modulePath, 'storeFreeze', 'ngrx-store-freeze'),
|
||||
...addImportToModule(
|
||||
source,
|
||||
modulePath,
|
||||
`StoreModule.forRoot({},{metaReducers: !environment.production ? [storeFreeze] : []})`
|
||||
),
|
||||
...addImportToModule(source, modulePath, `EffectsModule.forRoot([])`),
|
||||
...addImportToModule(
|
||||
source,
|
||||
modulePath,
|
||||
`!environment.production ? StoreDevtoolsModule.instrument() : []`
|
||||
),
|
||||
...addImportToModule(source, modulePath, `StoreRouterConnectingModule`)
|
||||
]);
|
||||
return host;
|
||||
} else {
|
||||
const reducerPath = `./${toFileName(options.directory)}/${toFileName(
|
||||
name
|
||||
)}.reducer`;
|
||||
const effectsPath = `./${toFileName(options.directory)}/${toFileName(
|
||||
name
|
||||
)}.effects`;
|
||||
const initPath = `./${toFileName(options.directory)}/${toFileName(
|
||||
name
|
||||
)}.init`;
|
||||
|
||||
const reducerName = `${toPropertyName(name)}Reducer`;
|
||||
const effectsName = `${toClassName(name)}Effects`;
|
||||
const initName = `${toPropertyName(name)}InitialState`;
|
||||
|
||||
const common = [
|
||||
insertImport(source, modulePath, 'StoreModule', '@ngrx/store'),
|
||||
insertImport(source, modulePath, 'EffectsModule', '@ngrx/effects'),
|
||||
insertImport(source, modulePath, reducerName, reducerPath),
|
||||
insertImport(source, modulePath, initName, initPath),
|
||||
insertImport(source, modulePath, effectsName, effectsPath),
|
||||
...addProviderToModule(source, modulePath, effectsName)
|
||||
];
|
||||
|
||||
if (options.root) {
|
||||
insert(host, modulePath, [
|
||||
...common,
|
||||
insertImport(
|
||||
source,
|
||||
modulePath,
|
||||
'StoreDevtoolsModule',
|
||||
'@ngrx/store-devtools'
|
||||
),
|
||||
insertImport(
|
||||
source,
|
||||
modulePath,
|
||||
'environment',
|
||||
'../environments/environment'
|
||||
),
|
||||
insertImport(
|
||||
source,
|
||||
modulePath,
|
||||
'StoreRouterConnectingModule',
|
||||
'@ngrx/router-store'
|
||||
),
|
||||
insertImport(source, modulePath, 'storeFreeze', 'ngrx-store-freeze'),
|
||||
...addImportToModule(
|
||||
source,
|
||||
modulePath,
|
||||
`StoreModule.forRoot({${toPropertyName(name)}: ${reducerName}}, {
|
||||
initialState: {${toPropertyName(name)}: ${initName}},
|
||||
metaReducers: !environment.production ? [storeFreeze] : []
|
||||
})`
|
||||
),
|
||||
...addImportToModule(
|
||||
source,
|
||||
modulePath,
|
||||
`EffectsModule.forRoot([${effectsName}])`
|
||||
),
|
||||
...addImportToModule(
|
||||
source,
|
||||
modulePath,
|
||||
`!environment.production ? StoreDevtoolsModule.instrument() : []`
|
||||
),
|
||||
...addImportToModule(
|
||||
source,
|
||||
modulePath,
|
||||
`StoreRouterConnectingModule`
|
||||
)
|
||||
]);
|
||||
} else {
|
||||
insert(host, modulePath, [
|
||||
...common,
|
||||
...addImportToModule(
|
||||
source,
|
||||
modulePath,
|
||||
`StoreModule.forFeature('${toPropertyName(
|
||||
name
|
||||
)}', ${reducerName}, {initialState: ${initName}})`
|
||||
),
|
||||
...addImportToModule(
|
||||
source,
|
||||
modulePath,
|
||||
`EffectsModule.forFeature([${effectsName}])`
|
||||
)
|
||||
]);
|
||||
}
|
||||
|
||||
return host;
|
||||
}
|
||||
/**
|
||||
* Rule to generate the Nx 'ngrx' Collection
|
||||
*/
|
||||
export default function generateNgrxCollection(_options: Schema): Rule {
|
||||
return wrapIntoFormat((host: Tree) => {
|
||||
const options = normalizeOptions(_options);
|
||||
const context: RequestContext = {
|
||||
featureName: options.name,
|
||||
moduleDir: path.dirname(options.module),
|
||||
options,
|
||||
host
|
||||
};
|
||||
}
|
||||
|
||||
function addNgRxToPackageJson(): Rule {
|
||||
return updateJson('package.json', packageJson => {
|
||||
if (!packageJson['dependencies']) {
|
||||
packageJson['dependencies'] = {};
|
||||
}
|
||||
return chain([
|
||||
branchAndMerge(generateNgrxFiles(context)),
|
||||
branchAndMerge(generateNxFiles(context)),
|
||||
|
||||
if (!packageJson['dependencies']['@ngrx/store']) {
|
||||
packageJson['dependencies']['@ngrx/store'] = ngrxVersion;
|
||||
}
|
||||
if (!packageJson['dependencies']['@ngrx/router-store']) {
|
||||
packageJson['dependencies']['@ngrx/router-store'] = routerStoreVersion;
|
||||
}
|
||||
if (!packageJson['dependencies']['@ngrx/effects']) {
|
||||
packageJson['dependencies']['@ngrx/effects'] = ngrxVersion;
|
||||
}
|
||||
if (!packageJson['dependencies']['@ngrx/store-devtools']) {
|
||||
packageJson['dependencies']['@ngrx/store-devtools'] = ngrxVersion;
|
||||
}
|
||||
if (!packageJson['dependencies']['ngrx-store-freeze']) {
|
||||
packageJson['dependencies']['ngrx-store-freeze'] = ngrxStoreFreezeVersion;
|
||||
}
|
||||
return packageJson;
|
||||
addImportsToModule(context),
|
||||
|
||||
updateNgrxActions(context),
|
||||
updateNgrxReducers(context),
|
||||
updateNgrxEffects(context),
|
||||
|
||||
options.skipPackageJson ? noop() : addNgRxToPackageJson()
|
||||
]);
|
||||
});
|
||||
}
|
||||
|
||||
export default function(schema: Schema): Rule {
|
||||
return wrapIntoFormat(() => {
|
||||
const options = normalizeOptions(schema);
|
||||
const name = options.name;
|
||||
const moduleDir = path.dirname(options.module);
|
||||
// ********************************************************
|
||||
// Internal Function
|
||||
// ********************************************************
|
||||
|
||||
if (options.onlyEmptyRoot) {
|
||||
return chain([
|
||||
addImportsToModule(name, options),
|
||||
options.skipPackageJson ? noop() : addNgRxToPackageJson()
|
||||
]);
|
||||
} else {
|
||||
/**
|
||||
* Generate the Nx files that are NOT created by the @ngrx/schematic(s)
|
||||
*/
|
||||
function generateNxFiles(context: RequestContext) {
|
||||
const templateSource = apply(url('./files'), [
|
||||
template({ ...options, tmpl: '', ...names(name) }),
|
||||
move(moduleDir)
|
||||
template({ ...context.options, tmpl: '', ...names(context.featureName) }),
|
||||
move(context.moduleDir)
|
||||
]);
|
||||
return chain([
|
||||
branchAndMerge(chain([mergeWith(templateSource)])),
|
||||
addImportsToModule(name, options),
|
||||
options.skipPackageJson ? noop() : addNgRxToPackageJson()
|
||||
]);
|
||||
}
|
||||
});
|
||||
return chain([mergeWith(templateSource)]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Using @ngrx/schematics, generate scaffolding for 'feature': action, reducer, effect files
|
||||
*/
|
||||
function generateNgrxFiles(context: RequestContext) {
|
||||
const filePrefix = `app/${context.featureName}/${context.featureName}`;
|
||||
|
||||
return chain([
|
||||
externalSchematic('@ngrx/schematics', 'feature', {
|
||||
name: context.featureName,
|
||||
sourceDir: './',
|
||||
flat: false
|
||||
}),
|
||||
deleteFile(`/${filePrefix}.effects.spec.ts`),
|
||||
deleteFile(`/${filePrefix}.reducer.spec.ts`),
|
||||
moveToNxMonoTree(
|
||||
context.featureName,
|
||||
context.moduleDir,
|
||||
context.options.directory
|
||||
)
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* @ngrx/schematics generates files in:
|
||||
* `/apps/<ngrxFeatureName>/`
|
||||
*
|
||||
* For Nx monorepo, however, we need to move the files to either
|
||||
* a) apps/<appName>/src/app/<directory>, or
|
||||
* b) libs/<libName>/src/<directory>
|
||||
*/
|
||||
function moveToNxMonoTree(
|
||||
ngrxFeatureName: string,
|
||||
nxDir: string,
|
||||
directory: string
|
||||
): Rule {
|
||||
return move(`app/${ngrxFeatureName}`, path.join(nxDir, directory));
|
||||
}
|
||||
|
||||
/**
|
||||
* Extract the parent 'directory' for the specified
|
||||
*/
|
||||
function normalizeOptions(options: Schema): Schema {
|
||||
return { ...options, directory: toFileName(options.directory) };
|
||||
}
|
||||
|
||||
203
packages/schematics/src/collection/ngrx/ngrx.md
Normal file
203
packages/schematics/src/collection/ngrx/ngrx.md
Normal file
@ -0,0 +1,203 @@
|
||||
# ngrx
|
||||
--------
|
||||
|
||||
## Overview
|
||||
|
||||
Generates a ngrx feature set containing an `init`, `interfaces`, `actions`, `reducer` and `effects` files.
|
||||
|
||||
You use this schematic to build out a new ngrx feature area that provides a new piece of state.
|
||||
|
||||
## Command
|
||||
|
||||
```sh
|
||||
ng generate ngrx FeatureName [options]
|
||||
```
|
||||
|
||||
##### OR
|
||||
|
||||
```sh
|
||||
ng generate f FeatureName [options]
|
||||
```
|
||||
|
||||
### Options
|
||||
|
||||
Specifies the name of the ngrx feature (e.g., Products, User, etc.)
|
||||
|
||||
- `name`
|
||||
- Type: `string`
|
||||
- Required: true
|
||||
|
||||
Path to Angular Module. Also used to determine the parent directory for the new **+state**
|
||||
directory; unless the `--directory` option is used to override the dir name.
|
||||
|
||||
> e.g. --module=apps/myapp/src/app/app.module.ts
|
||||
|
||||
- `--module`
|
||||
- Type: `string`
|
||||
- Required: true
|
||||
|
||||
Specifies the directory name used to nest the **ngrx** files within a folder.
|
||||
|
||||
- `--directory`
|
||||
- Type: `string`
|
||||
- Default: `+state`
|
||||
|
||||
#### Examples
|
||||
|
||||
Generate a `User` feature set and register it within an `Angular Module`.
|
||||
|
||||
```sh
|
||||
ng generate ngrx User -m apps/myapp/src/app/app.module.ts
|
||||
ng g ngrx Producrts -m libs/mylib/src/mylib.module.ts
|
||||
```
|
||||
|
||||
|
||||
Generate a `User` feature set within a `user` folder and register it with the `user.module.ts` file in the same `user` folder.
|
||||
|
||||
```sh
|
||||
ng g ngrx User -m apps/myapp/src/app/app.module.ts -directory user
|
||||
```
|
||||
|
||||
## Generated Files
|
||||
|
||||
The files generated are shown below and include placeholders for the *feature* name specified.
|
||||
|
||||
> The <Feature> notation used be below indicates a placeholder for the actual *feature* name.
|
||||
|
||||
* [<feature>.actions.ts](#featureactionsts)
|
||||
* [<feature>.reducer.ts](#featurereducerts)
|
||||
* [<feature>.effects.ts](#featureeffectsts)
|
||||
* [<feature>.selectors.ts](#featureselectorsts)
|
||||
* [<feature>.facade.ts](#featurefacadests)
|
||||
|
||||
* [../app.module.ts](#appmodulets)
|
||||
|
||||
#### <feature>.actions.ts
|
||||
|
||||
```ts
|
||||
import {Action} from "@ngrx/store";
|
||||
|
||||
export enum <Feature>ActionTypes {
|
||||
<Feature> = "[<Feature>] Action",
|
||||
Load<Feature> = "[<Feature>] Load Data",
|
||||
<Feature>Loaded = "[<Feature>] Data Loaded"
|
||||
}
|
||||
|
||||
export class <Feature> implements Action {
|
||||
readonly type = <Feature>ActionTypes.<Feature>;
|
||||
}
|
||||
|
||||
export class Load<Feature> implements Action {
|
||||
readonly type = <Feature>ActionTypes.Load<Feature>;
|
||||
constructor(public payload: any) { }
|
||||
}
|
||||
|
||||
export class DataLoaded implements Action {
|
||||
readonly type = <Feature>ActionTypes.<Feature>Loaded;
|
||||
constructor(public payload: any) { }
|
||||
}
|
||||
|
||||
export type <Feature>Actions = <Feature> | Load<Feature> | <Feature>Loaded;
|
||||
```
|
||||
|
||||
#### <feature>.reducer.ts
|
||||
```ts
|
||||
import { <Feature> } from './<feature>.interfaces';
|
||||
import { <Feature>Action, <Feature>ActionTypes } from './<feature>.actions';
|
||||
|
||||
/**
|
||||
* Interface for the '<Feature>' data used in
|
||||
* - <Feature>State, and
|
||||
* - <feature>Reducer
|
||||
*/
|
||||
export interface <Feature>Data {
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Interface to the part of the Store containing <Feature>State
|
||||
* and other information related to <Feature>Data.
|
||||
*/
|
||||
export interface <Feature>State {
|
||||
readonly <feature>: <Feature>Data;
|
||||
}
|
||||
|
||||
export const initialState: <Feature>Data = { };
|
||||
|
||||
export function <feature>Reducer(state: <Feature>Data = initialState, action: <Feature>Actions): <Feature>Data {
|
||||
switch (action.type) {
|
||||
case <Feature>ActionTypes.<Feature>Loaded: {
|
||||
return { ...state, ...action.payload };
|
||||
}
|
||||
default: {
|
||||
return state;
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
#### <feature>.effects.ts
|
||||
```ts
|
||||
import { Injectable } from '@angular/core';
|
||||
import { Effect, Actions } from '@ngrx/effects';
|
||||
import { DataPersistence } from '@nrwl/nx';
|
||||
|
||||
import { <Feature> } from './<feature>.interfaces';
|
||||
import { Load<Feature>, <Feature>Loaded, <Feature>ActionTypes } from './<feature>.actions';
|
||||
|
||||
@Injectable()
|
||||
export class <Feature>Effects {
|
||||
@Effect() load<Feature>$ = this.dataPersistence.fetch(<Feature>ActionTypes.Load<Feature>, {
|
||||
run: (action: Load<Feature>, state: <Feature>) => {
|
||||
return new <Feature>Loaded({});
|
||||
},
|
||||
|
||||
onError: (action: Load<Feature>, error) => {
|
||||
console.error('Error', error);
|
||||
}
|
||||
});
|
||||
|
||||
constructor(
|
||||
private actions: Actions,
|
||||
private dataPersistence: DataPersistence<Feature>) { }
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
#### ../app.module.ts
|
||||
```ts
|
||||
import { NgModule } from '@angular/core';
|
||||
import { BrowserModule } from '@angular/platform-browser';
|
||||
import { RouterModule } from '@angular/router';
|
||||
import { AppComponent } from './app.component';
|
||||
import { StoreModule } from '@ngrx/store';
|
||||
import { EffectsModule } from '@ngrx/effects';
|
||||
import {
|
||||
<feature>Reducer,
|
||||
<Feature>State,
|
||||
<Feature>Data,
|
||||
initialState as <feature>InitialState
|
||||
} from './+state/<Feature>.reducer';
|
||||
import { <Feature>Effects } from './+state/<Feature>.effects';
|
||||
import { StoreDevtoolsModule } from '@ngrx/store-devtools';
|
||||
import { environment } from '../environments/environment';
|
||||
import { StoreRouterConnectingModule } from '@ngrx/router-store';
|
||||
import { storeFreeze } from 'ngrx-store-freeze';
|
||||
|
||||
@NgModule({
|
||||
imports: [BrowserModule, RouterModule.forRoot([]),
|
||||
StoreModule.forRoot({ <feature>: <feature>Reducer }, {
|
||||
initialState: { <feature>: <feature>InitialState },
|
||||
metaReducers: !environment.production ? [storeFreeze] : []
|
||||
}),
|
||||
EffectsModule.forRoot([<Feature>Effects]),
|
||||
!environment.production ? StoreDevtoolsModule.instrument() : [],
|
||||
StoreRouterConnectingModule],
|
||||
declarations: [AppComponent],
|
||||
bootstrap: [AppComponent],
|
||||
providers: [<Feature>Effects]
|
||||
})
|
||||
export class AppModule {
|
||||
}
|
||||
|
||||
```
|
||||
@ -1,10 +1,20 @@
|
||||
import { SchematicTestRunner } from '@angular-devkit/schematics/testing';
|
||||
import * as path from 'path';
|
||||
import {
|
||||
SchematicTestRunner,
|
||||
UnitTestTree
|
||||
} from '@angular-devkit/schematics/testing';
|
||||
import { Tree, VirtualTree } from '@angular-devkit/schematics';
|
||||
import { createApp, createEmptyWorkspace } from '../../utils/testing-utils';
|
||||
import { getFileContent } from '@schematics/angular/utility/test';
|
||||
import { readJson } from '../../utils/ast-utils';
|
||||
|
||||
import * as path from 'path';
|
||||
import { findModuleParent } from '../../utils/name-utils';
|
||||
import {
|
||||
createApp,
|
||||
createEmptyWorkspace,
|
||||
AppConfig,
|
||||
getAppConfig
|
||||
} from '../../utils/testing-utils';
|
||||
|
||||
describe('ngrx', () => {
|
||||
const schematicRunner = new SchematicTestRunner(
|
||||
'@nrwl/schematics',
|
||||
@ -29,21 +39,23 @@ describe('ngrx', () => {
|
||||
},
|
||||
appTree
|
||||
);
|
||||
|
||||
const appModule = getFileContent(tree, '/apps/myapp/src/app/app.module.ts');
|
||||
expect(appModule).toContain(
|
||||
'StoreModule.forRoot({},{metaReducers: !environment.production ? [storeFreeze] : []})'
|
||||
);
|
||||
expect(appModule).toContain('EffectsModule.forRoot');
|
||||
|
||||
expect(tree.exists('apps/myapp/src/app/+state')).toBeFalsy();
|
||||
|
||||
[
|
||||
'StoreModule.forRoot({},{ metaReducers : !environment.production ? [storeFreeze] : [] })',
|
||||
'EffectsModule.forRoot'
|
||||
].forEach(text => {
|
||||
expect(appModule).toContain(text);
|
||||
});
|
||||
});
|
||||
|
||||
it('should add root', () => {
|
||||
const tree = schematicRunner.runSchematic(
|
||||
'ngrx',
|
||||
{
|
||||
name: 'state',
|
||||
name: 'app',
|
||||
module: 'apps/myapp/src/app/app.module.ts',
|
||||
root: true
|
||||
},
|
||||
@ -51,31 +63,26 @@ describe('ngrx', () => {
|
||||
);
|
||||
|
||||
const appModule = getFileContent(tree, '/apps/myapp/src/app/app.module.ts');
|
||||
|
||||
console.log(appModule);
|
||||
|
||||
expect(appModule).toContain('StoreModule.forRoot');
|
||||
expect(appModule).toContain('EffectsModule.forRoot');
|
||||
expect(appModule).toContain('!environment.production ? [storeFreeze] : []');
|
||||
|
||||
expect(
|
||||
tree.exists(`/apps/myapp/src/app/+state/state.actions.ts`)
|
||||
).toBeTruthy();
|
||||
expect(
|
||||
tree.exists(`/apps/myapp/src/app/+state/state.effects.ts`)
|
||||
).toBeTruthy();
|
||||
expect(
|
||||
tree.exists(`/apps/myapp/src/app/+state/state.effects.spec.ts`)
|
||||
).toBeTruthy();
|
||||
expect(
|
||||
tree.exists(`/apps/myapp/src/app/+state/state.init.ts`)
|
||||
).toBeTruthy();
|
||||
expect(
|
||||
tree.exists(`/apps/myapp/src/app/+state/state.interfaces.ts`)
|
||||
).toBeTruthy();
|
||||
expect(
|
||||
tree.exists(`/apps/myapp/src/app/+state/state.reducer.ts`)
|
||||
).toBeTruthy();
|
||||
expect(
|
||||
tree.exists(`/apps/myapp/src/app/+state/state.reducer.spec.ts`)
|
||||
).toBeTruthy();
|
||||
expect(appModule).toContain('appReducer, initialState');
|
||||
expect(appModule).not.toContain('AppData');
|
||||
expect(appModule).not.toContain('AppState');
|
||||
|
||||
[
|
||||
'/apps/myapp/src/app/+state/app.actions.ts',
|
||||
'/apps/myapp/src/app/+state/app.effects.ts',
|
||||
'/apps/myapp/src/app/+state/app.effects.spec.ts',
|
||||
'/apps/myapp/src/app/+state/app.reducer.ts',
|
||||
'/apps/myapp/src/app/+state/app.reducer.spec.ts'
|
||||
].forEach(fileName => {
|
||||
expect(tree.exists(fileName)).toBeTruthy();
|
||||
});
|
||||
});
|
||||
|
||||
it('should add feature', () => {
|
||||
@ -173,4 +180,102 @@ describe('ngrx', () => {
|
||||
)
|
||||
).toThrow("should have required property 'module'");
|
||||
});
|
||||
|
||||
it('should create the ngrx files', () => {
|
||||
const appConfig = getAppConfig();
|
||||
const hasFile = file => expect(tree.exists(file)).toBeTruthy();
|
||||
const tree = buildNgrxTree(appConfig);
|
||||
const statePath = `${findModuleParent(appConfig.appModule)}/+state`;
|
||||
|
||||
hasFile(`${statePath}/user.actions.ts`);
|
||||
hasFile(`${statePath}/user.effects.ts`);
|
||||
hasFile(`${statePath}/user.effects.spec.ts`);
|
||||
hasFile(`${statePath}/user.reducer.ts`);
|
||||
hasFile(`${statePath}/user.reducer.spec.ts`);
|
||||
});
|
||||
|
||||
it('should create ngrx action enums', () => {
|
||||
const appConfig = getAppConfig();
|
||||
const tree = buildNgrxTree(appConfig);
|
||||
|
||||
const statePath = `${findModuleParent(appConfig.appModule)}/+state`;
|
||||
const content = getFileContent(tree, `${statePath}/user.actions.ts`);
|
||||
|
||||
expect(content).toContain('UserActionTypes');
|
||||
expect(content).toContain("LoadUser = '[User] Load Data'");
|
||||
expect(content).toContain("UserLoaded = '[User] Data Loaded'");
|
||||
});
|
||||
|
||||
it('should create ngrx action classes', () => {
|
||||
const appConfig = getAppConfig();
|
||||
const tree = buildNgrxTree(appConfig);
|
||||
|
||||
const statePath = `${findModuleParent(appConfig.appModule)}/+state`;
|
||||
const content = getFileContent(tree, `${statePath}/user.actions.ts`);
|
||||
|
||||
expect(content).toContain('class LoadUser implements Action');
|
||||
expect(content).toContain('class UserLoaded implements Action');
|
||||
});
|
||||
|
||||
it('should enhance the ngrx action type', () => {
|
||||
const appConfig = getAppConfig();
|
||||
const tree = buildNgrxTree(appConfig);
|
||||
|
||||
const statePath = `${findModuleParent(appConfig.appModule)}/+state`;
|
||||
const content = getFileContent(tree, `${statePath}/user.actions.ts`);
|
||||
expect(content).toContain(
|
||||
'type UserActions = User | LoadUser | UserLoaded'
|
||||
);
|
||||
});
|
||||
|
||||
it('should enhance the ngrx reducer', () => {
|
||||
const appConfig = getAppConfig();
|
||||
const tree = buildNgrxTree(appConfig);
|
||||
|
||||
const statePath = `${findModuleParent(appConfig.appModule)}/+state`;
|
||||
const content = getFileContent(tree, `${statePath}/user.reducer.ts`);
|
||||
|
||||
expect(content).not.toContain('function reducer');
|
||||
|
||||
[
|
||||
`import { UserActions, UserActionTypes } from \'./user.actions\'`,
|
||||
`export interface UserData`,
|
||||
`export interface UserState`,
|
||||
`readonly user: UserData`,
|
||||
`const initialState: UserData`,
|
||||
'function userReducer(state = initialState, action: UserActions): UserData',
|
||||
'case UserActionTypes.UserLoaded'
|
||||
].forEach(text => {
|
||||
expect(content).toContain(text);
|
||||
});
|
||||
});
|
||||
|
||||
it('should enhance the ngrx effects', () => {
|
||||
const appConfig = getAppConfig();
|
||||
const tree = buildNgrxTree(appConfig);
|
||||
const statePath = `${findModuleParent(appConfig.appModule)}/+state`;
|
||||
const content = getFileContent(tree, `${statePath}/user.effects.ts`);
|
||||
|
||||
[
|
||||
`import { DataPersistence } from \'@nrwl/nx\'`,
|
||||
`import { UserActions, UserActionTypes, LoadUser, UserLoaded } from \'./user.actions\'`,
|
||||
`loadUser$`,
|
||||
`run: (action: LoadUser, state: UserState)`,
|
||||
`return new UserLoaded(state)`,
|
||||
'constructor(private actions$: Actions, private dataPersistence: DataPersistence<UserState>)'
|
||||
].forEach(text => {
|
||||
expect(content).toContain(text);
|
||||
});
|
||||
});
|
||||
|
||||
function buildNgrxTree(appConfig: AppConfig): UnitTestTree {
|
||||
return schematicRunner.runSchematic(
|
||||
'ngrx',
|
||||
{
|
||||
name: 'user',
|
||||
module: appConfig.appModule
|
||||
},
|
||||
appTree
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
@ -0,0 +1,119 @@
|
||||
import { Rule, Tree } from '@angular-devkit/schematics';
|
||||
import { Change } from '@ngrx/schematics/src/utility/change';
|
||||
import { insertImport } from '@schematics/angular/utility/route-utils';
|
||||
import * as ts from 'typescript';
|
||||
import {
|
||||
toClassName,
|
||||
toFileName,
|
||||
toPropertyName
|
||||
} from '../../../utils/name-utils';
|
||||
import {
|
||||
insert,
|
||||
addImportToModule,
|
||||
addProviderToModule
|
||||
} from '../../../utils/ast-utils';
|
||||
import { RequestContext } from './request-context';
|
||||
|
||||
export function addImportsToModule(context: RequestContext): Rule {
|
||||
return (host: Tree) => {
|
||||
if (context.options.onlyAddFiles) {
|
||||
return host;
|
||||
}
|
||||
|
||||
if (!host.exists(context.options.module)) {
|
||||
throw new Error('Specified module does not exist');
|
||||
}
|
||||
const modulePath = context.options.module;
|
||||
const sourceText = host.read(modulePath)!.toString('utf-8');
|
||||
const source = ts.createSourceFile(
|
||||
modulePath,
|
||||
sourceText,
|
||||
ts.ScriptTarget.Latest,
|
||||
true
|
||||
);
|
||||
const addImport = (symbolName: string, fileName: string): Change => {
|
||||
return insertImport(source, modulePath, symbolName, fileName);
|
||||
};
|
||||
|
||||
const dir = `./${toFileName(context.options.directory)}`;
|
||||
const pathPrefix = `${dir}/${toFileName(context.featureName)}`;
|
||||
const reducerPath = `${pathPrefix}.reducer`;
|
||||
const effectsPath = `${pathPrefix}.effects`;
|
||||
|
||||
const featureName = `${toPropertyName(context.featureName)}`;
|
||||
const reducerName = `${toPropertyName(context.featureName)}Reducer`;
|
||||
const effectsName = `${toClassName(context.featureName)}Effects`;
|
||||
const reducerImports = `${reducerName}, initialState as ${featureName}InitialState`;
|
||||
|
||||
const storeReducers = `{ ${featureName}: ${reducerName} }`;
|
||||
const storeInitState = `initialState : { ${featureName} : ${featureName}InitialState }`;
|
||||
const storeMetaReducers = `metaReducers : !environment.production ? [storeFreeze] : []`;
|
||||
|
||||
const storeForRoot = `StoreModule.forRoot(
|
||||
${storeReducers},
|
||||
{
|
||||
${storeInitState},
|
||||
${storeMetaReducers}
|
||||
}
|
||||
)`;
|
||||
const storeForEmptyRoot = `StoreModule.forRoot({},{ ${storeMetaReducers} })`;
|
||||
const effectsForRoot = `EffectsModule.forRoot([${effectsName}])`;
|
||||
const effectsForEmptyRoot = `EffectsModule.forRoot([])`;
|
||||
const storeForFeature = `StoreModule.forFeature('${featureName}', ${reducerName}, { ${storeInitState} })`;
|
||||
const effectsForFeature = `EffectsModule.forFeature([${effectsName}])`;
|
||||
const devTools = `!environment.production ? StoreDevtoolsModule.instrument() : []`;
|
||||
const storeRouterModule = 'StoreRouterConnectingModule';
|
||||
|
||||
// InsertImport [symbol,source] value pairs
|
||||
const storeModule = ['StoreModule', '@ngrx/store'];
|
||||
const effectsModule = ['EffectsModule', '@ngrx/effects'];
|
||||
const storeDevTools = ['StoreDevtoolsModule', '@ngrx/store-devtools'];
|
||||
const environment = ['environment', '../environments/environment'];
|
||||
const storeRouter = ['StoreRouterConnectingModule', '@ngrx/router-store'];
|
||||
const storeFreeze = ['storeFreeze', 'ngrx-store-freeze'];
|
||||
|
||||
if (context.options.onlyEmptyRoot) {
|
||||
insert(host, modulePath, [
|
||||
addImport.apply(this, storeModule),
|
||||
addImport.apply(this, effectsModule),
|
||||
addImport.apply(this, storeDevTools),
|
||||
addImport.apply(this, environment),
|
||||
addImport.apply(this, storeRouter),
|
||||
addImport.apply(this, storeFreeze),
|
||||
...addImportToModule(source, modulePath, storeForEmptyRoot),
|
||||
...addImportToModule(source, modulePath, effectsForEmptyRoot),
|
||||
...addImportToModule(source, modulePath, devTools),
|
||||
...addImportToModule(source, modulePath, storeRouterModule)
|
||||
]);
|
||||
} else {
|
||||
const common = [
|
||||
addImport.apply(this, storeModule),
|
||||
addImport.apply(this, effectsModule),
|
||||
addImport(reducerImports, reducerPath),
|
||||
addImport(effectsName, effectsPath),
|
||||
...addProviderToModule(source, modulePath, effectsName)
|
||||
];
|
||||
|
||||
if (context.options.root) {
|
||||
insert(host, modulePath, [
|
||||
...common,
|
||||
addImport.apply(this, storeDevTools),
|
||||
addImport.apply(this, environment),
|
||||
addImport.apply(this, storeRouter),
|
||||
addImport.apply(this, storeFreeze),
|
||||
...addImportToModule(source, modulePath, storeForRoot),
|
||||
...addImportToModule(source, modulePath, effectsForRoot),
|
||||
...addImportToModule(source, modulePath, devTools),
|
||||
...addImportToModule(source, modulePath, storeRouterModule)
|
||||
]);
|
||||
} else {
|
||||
insert(host, modulePath, [
|
||||
...common,
|
||||
...addImportToModule(source, modulePath, storeForFeature),
|
||||
...addImportToModule(source, modulePath, effectsForFeature)
|
||||
]);
|
||||
}
|
||||
}
|
||||
return host;
|
||||
};
|
||||
}
|
||||
@ -0,0 +1,41 @@
|
||||
import { Rule, Tree } from '@angular-devkit/schematics';
|
||||
import {
|
||||
ngrxVersion,
|
||||
routerStoreVersion,
|
||||
ngrxStoreFreezeVersion
|
||||
} from '../../../lib-versions';
|
||||
import { serializeJson } from '../../../utils/fileutils';
|
||||
|
||||
export function addNgRxToPackageJson(): Rule {
|
||||
return (host: Tree) => {
|
||||
if (!host.exists('package.json')) return host;
|
||||
|
||||
const sourceText = host.read('package.json')!.toString('utf-8');
|
||||
const json = JSON.parse(sourceText);
|
||||
if (!json['dependencies']) {
|
||||
json['dependencies'] = {};
|
||||
}
|
||||
|
||||
if (!json['dependencies']['@ngrx/store']) {
|
||||
json['dependencies']['@ngrx/store'] = ngrxVersion;
|
||||
}
|
||||
if (!json['dependencies']['@ngrx/effects']) {
|
||||
json['dependencies']['@ngrx/effects'] = ngrxVersion;
|
||||
}
|
||||
if (!json['dependencies']['@ngrx/entity']) {
|
||||
json['dependencies']['@ngrx/entity'] = ngrxVersion;
|
||||
}
|
||||
if (!json['dependencies']['@ngrx/store-devtools']) {
|
||||
json['dependencies']['@ngrx/store-devtools'] = ngrxVersion;
|
||||
}
|
||||
if (!json['dependencies']['@ngrx/router-store']) {
|
||||
json['dependencies']['@ngrx/router-store'] = routerStoreVersion;
|
||||
}
|
||||
if (!json['dependencies']['ngrx-store-freeze']) {
|
||||
json['dependencies']['ngrx-store-freeze'] = ngrxStoreFreezeVersion;
|
||||
}
|
||||
|
||||
host.overwrite('package.json', serializeJson(json));
|
||||
return host;
|
||||
};
|
||||
}
|
||||
6
packages/schematics/src/collection/ngrx/rules/index.ts
Normal file
6
packages/schematics/src/collection/ngrx/rules/index.ts
Normal file
@ -0,0 +1,6 @@
|
||||
export { RequestContext } from './request-context';
|
||||
export { updateNgrxReducers } from './update-reducers';
|
||||
export { updateNgrxActions } from './update-actions';
|
||||
export { updateNgrxEffects } from './update-effects';
|
||||
export { addImportsToModule } from './add-imports-to-module';
|
||||
export { addNgRxToPackageJson } from './add-ngrx-to-package-json';
|
||||
@ -0,0 +1,23 @@
|
||||
import * as path from 'path';
|
||||
|
||||
import { Tree } from '@angular-devkit/schematics';
|
||||
import { Schema } from '../schema';
|
||||
import * as stringUtils from '../../../utils/strings';
|
||||
|
||||
/**
|
||||
* Schematic request context
|
||||
*/
|
||||
export interface RequestContext {
|
||||
featureName: string;
|
||||
moduleDir: string;
|
||||
options?: Schema;
|
||||
host?: Tree;
|
||||
}
|
||||
|
||||
export function buildNameToNgrxFile(context: RequestContext, suffice: string) {
|
||||
return path.join(
|
||||
context.moduleDir,
|
||||
context.options.directory,
|
||||
`${stringUtils.dasherize(context.featureName)}.${suffice}`
|
||||
);
|
||||
}
|
||||
103
packages/schematics/src/collection/ngrx/rules/update-actions.ts
Normal file
103
packages/schematics/src/collection/ngrx/rules/update-actions.ts
Normal file
@ -0,0 +1,103 @@
|
||||
import * as ts from 'typescript';
|
||||
import { SchematicsException, Rule, Tree } from '@angular-devkit/schematics';
|
||||
import { stripIndents } from '@angular-devkit/core/src/utils/literals';
|
||||
import { toClassName } from '../../../utils/name-utils';
|
||||
import {
|
||||
insert,
|
||||
addClass,
|
||||
addEnumeratorValues,
|
||||
addUnionTypes
|
||||
} from '../../../utils/ast-utils';
|
||||
|
||||
import { RequestContext, buildNameToNgrxFile } from './request-context';
|
||||
|
||||
/**
|
||||
* Add custom actions to <featureName>.actions.ts
|
||||
* See Ngrx Enhancement doc: https://bit.ly/2I5QwxQ
|
||||
*
|
||||
* Desired output:
|
||||
*
|
||||
* ```
|
||||
* import {Action} from "@ngrx/store";
|
||||
*
|
||||
* export enum <Feature>ActionTypes {
|
||||
* <Feature> = "[<Feature>] Action",
|
||||
* Load<Feature> = "[<Feature>] Load Data",
|
||||
* <Feature>Loaded = "[<Feature>] Data Loaded"
|
||||
* }
|
||||
*
|
||||
* export class <Feature> implements Action {
|
||||
* readonly type = <Feature>ActionTypes.<Feature>;
|
||||
* }
|
||||
*
|
||||
* export class Load<Feature> implements Action {
|
||||
* readonly type = <Feature>ActionTypes.Load<Feature>;
|
||||
* constructor(public payload: any) { }
|
||||
* }
|
||||
*
|
||||
* export class <Feature>LOADED implements Action {
|
||||
* readonly type = <Feature>ActionTypes.<Feature>LOADED;
|
||||
* constructor(public payload: any) { }
|
||||
* }
|
||||
*
|
||||
* export type <FeatureActions> = <Feature> | Load<Feature> | <Feature>Loaded
|
||||
*
|
||||
* ```
|
||||
*
|
||||
*/
|
||||
export function updateNgrxActions(context: RequestContext): Rule {
|
||||
return (host: Tree) => {
|
||||
const clazzName = toClassName(context.featureName);
|
||||
const componentPath = buildNameToNgrxFile(context, 'actions.ts');
|
||||
const text = host.read(componentPath);
|
||||
|
||||
if (text === null) {
|
||||
throw new SchematicsException(`File ${componentPath} does not exist.`);
|
||||
}
|
||||
|
||||
const sourceText = text.toString('utf-8');
|
||||
const source = ts.createSourceFile(
|
||||
componentPath,
|
||||
sourceText,
|
||||
ts.ScriptTarget.Latest,
|
||||
true
|
||||
);
|
||||
|
||||
insert(host, componentPath, [
|
||||
...addEnumeratorValues(source, componentPath, `${clazzName}ActionTypes`, [
|
||||
{
|
||||
name: `Load${clazzName}`,
|
||||
value: `[${clazzName}] Load Data`
|
||||
},
|
||||
{
|
||||
name: `${clazzName}Loaded`,
|
||||
value: `[${clazzName}] Data Loaded`
|
||||
}
|
||||
]),
|
||||
addClass(
|
||||
source,
|
||||
componentPath,
|
||||
`Load${clazzName}`,
|
||||
stripIndents`
|
||||
export class Load${clazzName} implements Action {
|
||||
readonly type = ${clazzName}ActionTypes.Load${clazzName};
|
||||
constructor(public payload: any) { }
|
||||
}`
|
||||
),
|
||||
addClass(
|
||||
source,
|
||||
componentPath,
|
||||
`${clazzName}Loaded`,
|
||||
stripIndents`
|
||||
export class ${clazzName}Loaded implements Action {
|
||||
readonly type = ${clazzName}ActionTypes.${clazzName}Loaded;
|
||||
constructor(public payload: any) { }
|
||||
}`
|
||||
),
|
||||
addUnionTypes(source, componentPath, `${clazzName}Actions`, [
|
||||
`Load${clazzName}`,
|
||||
`${clazzName}Loaded`
|
||||
])
|
||||
]);
|
||||
};
|
||||
}
|
||||
101
packages/schematics/src/collection/ngrx/rules/update-effects.ts
Normal file
101
packages/schematics/src/collection/ngrx/rules/update-effects.ts
Normal file
@ -0,0 +1,101 @@
|
||||
import * as ts from 'typescript';
|
||||
import { SchematicsException, Rule, Tree } from '@angular-devkit/schematics';
|
||||
import { InsertChange } from '@schematics/angular/utility/change';
|
||||
import { findNodes } from '@schematics/angular/utility/ast-utils';
|
||||
import { insertImport } from '@schematics/angular/utility/route-utils';
|
||||
import { stripIndents } from '@angular-devkit/core/src/utils/literals';
|
||||
|
||||
import { toClassName } from '../../../utils/name-utils';
|
||||
import { insert } from '../../../utils/ast-utils';
|
||||
import { RequestContext, buildNameToNgrxFile } from './request-context';
|
||||
|
||||
/**
|
||||
*
|
||||
* Desired output:
|
||||
*
|
||||
* ```
|
||||
* import { Injectable } from '@angular/core';
|
||||
* import { Effect, Actions } from '@ngrx/effects';
|
||||
* import { DataPersistence } from '@nrwl/nx';
|
||||
*
|
||||
* import { <Feature>, <Feature>State } from './<feature>.reducer';
|
||||
* import { Load<Feature>, <Feature>Loaded, <Feature>ActionTypes } from './<feature>.actions';
|
||||
*
|
||||
* @Injectable()
|
||||
* export class <Feature>Effects {
|
||||
* @Effect() load<Feature>$ = this.dataPersistence.fetch(<Feature>ActionTypes.Load<Feature>, {
|
||||
* run: (action: Load<Feature>, state: <Feature>State) => {
|
||||
* return new <Feature>Loaded({});
|
||||
* },
|
||||
*
|
||||
* onError: (action: Load<Feature>, error) => {
|
||||
* console.error('Error', error);
|
||||
* }
|
||||
* });
|
||||
*
|
||||
* constructor(
|
||||
* private actions: Actions,
|
||||
* private dataPersistence: DataPersistence<<Feature>State>) { }
|
||||
* }
|
||||
*
|
||||
*/
|
||||
export function updateNgrxEffects(context: RequestContext): Rule {
|
||||
return (host: Tree) => {
|
||||
const clazzName = toClassName(context.featureName);
|
||||
const componentPath = buildNameToNgrxFile(context, 'effects.ts');
|
||||
const featureReducer = `./${context.featureName}.reducer`;
|
||||
const text = host.read(componentPath);
|
||||
|
||||
if (text === null) {
|
||||
throw new SchematicsException(`File ${componentPath} does not exist.`);
|
||||
}
|
||||
|
||||
const modulePath = context.options.module;
|
||||
const sourceText = text.toString('utf-8');
|
||||
const source = ts.createSourceFile(
|
||||
componentPath,
|
||||
sourceText,
|
||||
ts.ScriptTarget.Latest,
|
||||
true
|
||||
);
|
||||
const updateConstructor = () => {
|
||||
const astConstructor = findNodes(source, ts.SyntaxKind.Constructor)[0];
|
||||
const lastParameter = findNodes(
|
||||
astConstructor,
|
||||
ts.SyntaxKind.Parameter
|
||||
).pop();
|
||||
|
||||
return new InsertChange(
|
||||
componentPath,
|
||||
lastParameter.end,
|
||||
stripIndents`, private dataPersistence: DataPersistence<${clazzName}State>`
|
||||
);
|
||||
};
|
||||
const addEffect$ = () => {
|
||||
const toInsert = `\n
|
||||
@Effect()
|
||||
load${clazzName}$ = this.dataPersistence.fetch(${clazzName}ActionTypes.Load${clazzName}, {
|
||||
run: (action: Load${clazzName}, state: ${clazzName}State) => {
|
||||
return new ${clazzName}Loaded(state);
|
||||
},
|
||||
|
||||
onError: (action: Load${clazzName}, error) => {
|
||||
console.error('Error', error);
|
||||
}
|
||||
});`;
|
||||
const astConstructor = findNodes(source, ts.SyntaxKind.Constructor)[0];
|
||||
return new InsertChange(componentPath, astConstructor.pos, toInsert);
|
||||
};
|
||||
|
||||
const actionsFile = `./${context.featureName}.actions`;
|
||||
const actionImports = `Load${clazzName}, ${clazzName}Loaded`;
|
||||
|
||||
insert(host, componentPath, [
|
||||
insertImport(source, modulePath, actionImports, actionsFile),
|
||||
insertImport(source, modulePath, `${clazzName}State`, featureReducer),
|
||||
insertImport(source, modulePath, 'DataPersistence', `@nrwl/nx`),
|
||||
updateConstructor(),
|
||||
addEffect$()
|
||||
]);
|
||||
};
|
||||
}
|
||||
186
packages/schematics/src/collection/ngrx/rules/update-reducers.ts
Normal file
186
packages/schematics/src/collection/ngrx/rules/update-reducers.ts
Normal file
@ -0,0 +1,186 @@
|
||||
import * as ts from 'typescript';
|
||||
import { SchematicsException, Rule, Tree } from '@angular-devkit/schematics';
|
||||
import {
|
||||
Change,
|
||||
ReplaceChange,
|
||||
InsertChange
|
||||
} from '@schematics/angular/utility/change';
|
||||
import {
|
||||
findNodes,
|
||||
insertAfterLastOccurrence
|
||||
} from '@schematics/angular/utility/ast-utils';
|
||||
import { insertImport } from '@schematics/angular/utility/route-utils';
|
||||
import { toClassName, toPropertyName } from '../../../utils/name-utils';
|
||||
import { insert, findNodesOfType } from '../../../utils/ast-utils';
|
||||
import { RequestContext, buildNameToNgrxFile } from './request-context';
|
||||
|
||||
/**
|
||||
* Update ngrx-generated Reducer to confirm to DataLoaded action to <featureName>.reducer.ts
|
||||
*
|
||||
* Desired output:
|
||||
*
|
||||
* ```
|
||||
* import { <Feature>Actions, <Feature>ActionTypes } from './<feature>.actions';
|
||||
*
|
||||
* export interface <Feature>State {
|
||||
* }
|
||||
*
|
||||
* export const initialState: <Feature>State = {
|
||||
* };
|
||||
*
|
||||
* export function <feature>Reducer(
|
||||
* state : <Feature>State = initialState,
|
||||
* action: <Feature>Actions ) : <Feature>State
|
||||
* {
|
||||
* switch (action.type) {
|
||||
* case <Feature>ActionTypes.<Feature>Loaded: {
|
||||
* return { ...state, ...action.payload };
|
||||
* }
|
||||
* default: {
|
||||
* return state;
|
||||
* }
|
||||
* }
|
||||
* }
|
||||
* ```
|
||||
*
|
||||
*
|
||||
*/
|
||||
export function updateNgrxReducers(context: RequestContext): Rule {
|
||||
return (host: Tree) => {
|
||||
const clazzName = toClassName(context.featureName);
|
||||
const propertyName = toPropertyName(context.featureName);
|
||||
const componentPath = buildNameToNgrxFile(context, 'reducer.ts');
|
||||
const text = host.read(componentPath);
|
||||
|
||||
if (text === null) {
|
||||
throw new SchematicsException(`File ${componentPath} does not exist.`);
|
||||
}
|
||||
|
||||
const modulePath = context.options.module;
|
||||
const sourceText = text.toString('utf-8');
|
||||
const source = ts.createSourceFile(
|
||||
componentPath,
|
||||
sourceText,
|
||||
ts.ScriptTarget.Latest,
|
||||
true
|
||||
);
|
||||
const renameStateInterface = () => {
|
||||
const name = findNodesOfType(
|
||||
source,
|
||||
ts.SyntaxKind.InterfaceDeclaration,
|
||||
(it: ts.InterfaceDeclaration) => it.name.getText() === 'State',
|
||||
(it: ts.InterfaceDeclaration) => it.name,
|
||||
true
|
||||
);
|
||||
return new ReplaceChange(
|
||||
componentPath,
|
||||
name.pos,
|
||||
'State',
|
||||
`${clazzName}Data`
|
||||
);
|
||||
};
|
||||
const addInterfaceComments = () => {
|
||||
const node = findNodes(source, ts.SyntaxKind.InterfaceDeclaration, 1)[0];
|
||||
const toAdd = `
|
||||
/**
|
||||
* Interface for the '${clazzName}' data used in
|
||||
* - ${clazzName}State, and
|
||||
* - ${propertyName}Reducer
|
||||
*/`;
|
||||
return new InsertChange(componentPath, node.pos + 1, `\n ${toAdd}`);
|
||||
};
|
||||
const addFeatureState = () => {
|
||||
const node = findNodes(source, ts.SyntaxKind.VariableStatement, 1)[0];
|
||||
const toAdd = `
|
||||
/**
|
||||
* Interface to the part of the Store containing ${clazzName}State
|
||||
* and other information related to ${clazzName}Data.
|
||||
*/
|
||||
export interface ${clazzName}State {
|
||||
readonly ${propertyName}: ${clazzName}Data;
|
||||
}`;
|
||||
return new InsertChange(componentPath, node.pos, `\n${toAdd}`);
|
||||
};
|
||||
const renameInitialState = () => {
|
||||
const getIdentifier = node => node.typeName;
|
||||
const target = findNodes(source, ts.SyntaxKind.VariableStatement, 1);
|
||||
const name = findNodesOfType(
|
||||
target[0],
|
||||
ts.SyntaxKind.TypeReference,
|
||||
it => {
|
||||
return getIdentifier(it).getText() === 'State';
|
||||
},
|
||||
it => getIdentifier(it),
|
||||
true
|
||||
);
|
||||
return new ReplaceChange(
|
||||
componentPath,
|
||||
name.pos,
|
||||
'State',
|
||||
`${clazzName}Data`
|
||||
);
|
||||
};
|
||||
const updateReducerFn = () => {
|
||||
let actions: Change[] = [];
|
||||
findNodes(source, ts.SyntaxKind.FunctionDeclaration)
|
||||
.filter((it: ts.FunctionDeclaration) => it.name.getText() === 'reducer')
|
||||
.map((it: ts.FunctionDeclaration) => {
|
||||
const fnName: ts.Identifier = it.name;
|
||||
const typeName = findNodes(it, ts.SyntaxKind.Identifier).reduce(
|
||||
(result: ts.Identifier, it: ts.Identifier): ts.Identifier => {
|
||||
return !!result
|
||||
? result
|
||||
: it.getText() === 'State' ? it : undefined;
|
||||
},
|
||||
undefined
|
||||
);
|
||||
|
||||
actions = [
|
||||
new ReplaceChange(
|
||||
componentPath,
|
||||
fnName.pos,
|
||||
fnName.getText(),
|
||||
`${propertyName}Reducer`
|
||||
),
|
||||
new ReplaceChange(
|
||||
componentPath,
|
||||
typeName.pos,
|
||||
typeName.getText(),
|
||||
`${clazzName}Data`
|
||||
)
|
||||
];
|
||||
});
|
||||
|
||||
return actions;
|
||||
};
|
||||
const updateSwitchStatement = () => {
|
||||
const toInsert = `
|
||||
|
||||
case ${clazzName}ActionTypes.${clazzName}Loaded: {
|
||||
return { ...state, ...action.payload };
|
||||
}`;
|
||||
return insertAfterLastOccurrence(
|
||||
findNodes(source, ts.SyntaxKind.SwitchStatement),
|
||||
toInsert,
|
||||
componentPath,
|
||||
0,
|
||||
ts.SyntaxKind.CaseClause
|
||||
);
|
||||
};
|
||||
|
||||
insert(host, componentPath, [
|
||||
addInterfaceComments(),
|
||||
addFeatureState(),
|
||||
renameStateInterface(),
|
||||
renameInitialState(),
|
||||
insertImport(
|
||||
source,
|
||||
modulePath,
|
||||
`${clazzName}Actions`,
|
||||
`./${context.featureName}.actions`
|
||||
),
|
||||
...updateReducerFn(),
|
||||
updateSwitchStatement()
|
||||
]);
|
||||
};
|
||||
}
|
||||
@ -6,17 +6,22 @@
|
||||
"properties": {
|
||||
"name": {
|
||||
"type": "string",
|
||||
"description": "Name of the directory (e.g., state)."
|
||||
"description": "Name of the ngrx feature (e.g., Products, User, etc.)."
|
||||
},
|
||||
"module": {
|
||||
"type": "string",
|
||||
"description": "Path to an Angular module (e.g., src/app/app.module.ts)."
|
||||
"description": "Path to ngModule; host directory will contain the new '+state' directory (e.g., src/libs/mylib/mylib.module.ts)."
|
||||
},
|
||||
"onlyAddFiles": {
|
||||
"type": "boolean",
|
||||
"default": false,
|
||||
"description": "Only add new NgRx files, without changing the module file (e.g., --onlyAddFiles)."
|
||||
},
|
||||
"directory": {
|
||||
"type": "string",
|
||||
"default": "+state",
|
||||
"description": "The directory name for the ngrx files: contains actions, effects, reducers. (e.g., +state)"
|
||||
},
|
||||
"root": {
|
||||
"type": "boolean",
|
||||
"default": false,
|
||||
@ -31,11 +36,6 @@
|
||||
"type": "boolean",
|
||||
"default": false,
|
||||
"description": "Do not add ngrx dependencies to package.json (e.g., --skipPackageJson)"
|
||||
},
|
||||
"directory": {
|
||||
"type": "string",
|
||||
"default": "+state",
|
||||
"description": "The store directory name (e.g., +state)"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
|
||||
0
packages/schematics/src/collection/workspace/index.ts
Normal file → Executable file
0
packages/schematics/src/collection/workspace/index.ts
Normal file → Executable file
@ -1,7 +1,7 @@
|
||||
export const angularCliVersion = '1.7.1';
|
||||
export const angularVersion = '5.2.6';
|
||||
export const angularJsVersion = '1.6.6';
|
||||
export const ngrxVersion = '5.1.0';
|
||||
export const ngrxVersion = '5.2.0';
|
||||
export const ngrxStoreFreezeVersion = '^0.2.1';
|
||||
export const routerStoreVersion = '5.0.1';
|
||||
export const nxVersion = '*';
|
||||
@ -14,6 +14,7 @@ export const typescriptVersion = '2.6.2';
|
||||
export const rxjsVersion = '^5.5.6';
|
||||
export const devKitCoreVersion = '^0.0.29';
|
||||
export const devKitSchematicsVersion = '0.0.52';
|
||||
export const ngrxSchematicsVersion = '5.2.0';
|
||||
export const schematicsAngularVersion = '0.1.17';
|
||||
|
||||
export const libVersions = {
|
||||
@ -32,5 +33,6 @@ export const libVersions = {
|
||||
devKitCoreVersion,
|
||||
devKitSchematicsVersion,
|
||||
schematicsAngularVersion,
|
||||
ngrxSchematicsVersion,
|
||||
routerStoreVersion
|
||||
};
|
||||
|
||||
218
packages/schematics/src/utils/ast-utils.ts
Normal file → Executable file
218
packages/schematics/src/utils/ast-utils.ts
Normal file → Executable file
@ -2,24 +2,27 @@
|
||||
* @license
|
||||
* Copyright Google Inc. All Rights Reserved.
|
||||
*
|
||||
* Use of this source code is governed by an MIT-style license that can be
|
||||
* Use of this source code is governed by an MIT- style license that can be
|
||||
* found in the LICENSE file at https://angular.io/license
|
||||
*/
|
||||
import { Tree, Rule } from '@angular-devkit/schematics';
|
||||
import {
|
||||
findNodes,
|
||||
getDecoratorMetadata,
|
||||
getSourceNodes
|
||||
getSourceNodes,
|
||||
insertAfterLastOccurrence
|
||||
} from '@schematics/angular/utility/ast-utils';
|
||||
import {
|
||||
Change,
|
||||
InsertChange,
|
||||
NoopChange,
|
||||
RemoveChange
|
||||
RemoveChange,
|
||||
ReplaceChange
|
||||
} from '@schematics/angular/utility/change';
|
||||
|
||||
import * as ts from 'typescript';
|
||||
import { toFileName } from './name-utils';
|
||||
import * as path from 'path';
|
||||
import { toFileName } from './name-utils';
|
||||
import { serializeJson } from './fileutils';
|
||||
|
||||
// This should be moved to @schematics/angular once it allows to pass custom expressions as providers
|
||||
@ -226,9 +229,10 @@ export function removeFromNgModule(
|
||||
}
|
||||
}
|
||||
|
||||
function findClass(
|
||||
export function findClass(
|
||||
source: ts.SourceFile,
|
||||
className: string
|
||||
className: string,
|
||||
silent: boolean = false
|
||||
): ts.ClassDeclaration {
|
||||
const nodes = getSourceNodes(source);
|
||||
|
||||
@ -238,7 +242,7 @@ function findClass(
|
||||
(<any>n).name.text === className
|
||||
)[0];
|
||||
|
||||
if (!clazz) {
|
||||
if (!clazz && !silent) {
|
||||
throw new Error(`Cannot find class '${className}'`);
|
||||
}
|
||||
|
||||
@ -531,6 +535,10 @@ export function insert(host: Tree, modulePath: string, changes: Change[]) {
|
||||
recorder.remove((<any>change).pos - 1, (<any>change).toRemove.length + 1);
|
||||
} else if (change instanceof NoopChange) {
|
||||
// do nothing
|
||||
} else if (change instanceof ReplaceChange) {
|
||||
const action = <any>change;
|
||||
recorder.remove(action.pos + 1, action.oldText.length);
|
||||
recorder.insertLeft(action.pos + 1, action.newText);
|
||||
} else {
|
||||
throw new Error(`Unexpected Change '${change}'`);
|
||||
}
|
||||
@ -658,3 +666,199 @@ export function readBootstrapInfo(
|
||||
bootstrapComponentFileName
|
||||
};
|
||||
}
|
||||
|
||||
export function addClass(
|
||||
source: ts.SourceFile,
|
||||
modulePath: string,
|
||||
clazzName: string,
|
||||
clazzSrc: string
|
||||
): Change {
|
||||
if (!findClass(source, clazzName, true)) {
|
||||
const nodes = findNodes(source, ts.SyntaxKind.ClassDeclaration);
|
||||
return insertAfterLastOccurrence(
|
||||
nodes,
|
||||
offset(clazzSrc, 0, true),
|
||||
modulePath,
|
||||
0,
|
||||
ts.SyntaxKind.ClassDeclaration
|
||||
);
|
||||
}
|
||||
return new NoopChange();
|
||||
}
|
||||
|
||||
export function addUnionTypes(
|
||||
source: ts.SourceFile,
|
||||
modulePath: string,
|
||||
typeName: string,
|
||||
typeValues: string[]
|
||||
) {
|
||||
const target: ts.TypeAliasDeclaration = findNodesOfType(
|
||||
source,
|
||||
ts.SyntaxKind.TypeAliasDeclaration,
|
||||
it => it.name.getText() === typeName
|
||||
);
|
||||
if (!target) {
|
||||
throw new Error(`Cannot find union type '${typeName}'`);
|
||||
}
|
||||
|
||||
const node = target.type as ts.TypeReferenceNode;
|
||||
|
||||
// Append new types to create a union type...
|
||||
return new InsertChange(
|
||||
modulePath,
|
||||
node.end,
|
||||
['', ...typeValues].join(' | ')
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Add 1..n enumerators using name + (optional) value pairs
|
||||
*/
|
||||
export function addEnumeratorValues(
|
||||
source: ts.SourceFile,
|
||||
modulePath: string,
|
||||
enumName: string,
|
||||
pairs: NameValue[] = []
|
||||
): Change[] {
|
||||
const target = findNodesOfType(
|
||||
source,
|
||||
ts.SyntaxKind.EnumDeclaration,
|
||||
it => it.name.getText() === enumName
|
||||
);
|
||||
const list = target ? target.members : undefined;
|
||||
if (!target) {
|
||||
throw new Error(`Cannot find enum '${enumName}'`);
|
||||
}
|
||||
const addComma = !(list.hasTrailingComma || list.length === 0);
|
||||
|
||||
return pairs.reduce((buffer, it) => {
|
||||
const member = it.value ? `${it.name} = '${it.value}'` : it.name;
|
||||
const memberExists = () => {
|
||||
return list.filter(m => m.name.getText() === it.name).length;
|
||||
};
|
||||
|
||||
if (memberExists()) {
|
||||
throw new Error(`Enum '${enumName}.${it.name}' already exists`);
|
||||
}
|
||||
|
||||
return [
|
||||
...buffer,
|
||||
new InsertChange(modulePath, list.end, (addComma ? ', ' : '') + member)
|
||||
];
|
||||
}, []);
|
||||
}
|
||||
|
||||
/**
|
||||
* Find Enum declaration in source based on name
|
||||
* e.g.
|
||||
* export enum ProductsActionTypes {
|
||||
* ProductsAction = '[Products] Action'
|
||||
* }
|
||||
*/
|
||||
const IDENTITY = a => a;
|
||||
export function findNodesOfType(
|
||||
source: ts.Node,
|
||||
kind: ts.SyntaxKind,
|
||||
predicate: (a: any) => boolean,
|
||||
extract: (a: any) => any = IDENTITY,
|
||||
firstOnly: boolean = true
|
||||
): any {
|
||||
const nodes = findNodes(source, kind);
|
||||
const matching = nodes.filter((i: any) => predicate(i)).map(extract);
|
||||
return matching.length ? (firstOnly ? matching[0] : matching) : undefined;
|
||||
}
|
||||
|
||||
export interface NameValue {
|
||||
name: string;
|
||||
value?: string;
|
||||
}
|
||||
|
||||
export function insertImport(
|
||||
source: ts.SourceFile,
|
||||
fileToEdit: string,
|
||||
symbolName: string,
|
||||
fileName: string,
|
||||
isDefault = false
|
||||
): Change {
|
||||
const rootNode = source;
|
||||
const allImports = findNodes(rootNode, ts.SyntaxKind.ImportDeclaration);
|
||||
|
||||
// get nodes that map to import statements from the file fileName
|
||||
const relevantImports = allImports.filter(node => {
|
||||
// StringLiteral of the ImportDeclaration is the import file (fileName in this case).
|
||||
const importFiles = node
|
||||
.getChildren()
|
||||
.filter(child => child.kind === ts.SyntaxKind.StringLiteral)
|
||||
.map(n => (n as ts.StringLiteral).text);
|
||||
|
||||
return importFiles.filter(file => file === fileName).length === 1;
|
||||
});
|
||||
|
||||
if (relevantImports.length > 0) {
|
||||
let importsAsterisk = false;
|
||||
// imports from import file
|
||||
const imports: ts.Node[] = [];
|
||||
relevantImports.forEach(n => {
|
||||
Array.prototype.push.apply(
|
||||
imports,
|
||||
findNodes(n, ts.SyntaxKind.Identifier)
|
||||
);
|
||||
if (findNodes(n, ts.SyntaxKind.AsteriskToken).length > 0) {
|
||||
importsAsterisk = true;
|
||||
}
|
||||
});
|
||||
|
||||
// if imports * from fileName, don't add symbolName
|
||||
if (importsAsterisk) {
|
||||
return new NoopChange();
|
||||
}
|
||||
|
||||
const importTextNodes = imports.filter(
|
||||
n => (n as ts.Identifier).text === symbolName
|
||||
);
|
||||
|
||||
// insert import if it's not there
|
||||
if (importTextNodes.length === 0) {
|
||||
const fallbackPos =
|
||||
findNodes(
|
||||
relevantImports[0],
|
||||
ts.SyntaxKind.CloseBraceToken
|
||||
)[0].getStart() ||
|
||||
findNodes(relevantImports[0], ts.SyntaxKind.FromKeyword)[0].getStart();
|
||||
|
||||
return insertAfterLastOccurrence(
|
||||
imports,
|
||||
`, ${symbolName}`,
|
||||
fileToEdit,
|
||||
fallbackPos
|
||||
);
|
||||
}
|
||||
|
||||
return new NoopChange();
|
||||
}
|
||||
|
||||
// no such import declaration exists
|
||||
const useStrict = findNodes(rootNode, ts.SyntaxKind.StringLiteral).filter(
|
||||
(n: ts.StringLiteral) => n.text === 'use strict'
|
||||
);
|
||||
let fallbackPos = 0;
|
||||
if (useStrict.length > 0) {
|
||||
fallbackPos = useStrict[0].end;
|
||||
}
|
||||
const open = isDefault ? '' : '{ ';
|
||||
const close = isDefault ? '' : ' }';
|
||||
// if there are no imports or 'use strict' statement, insert import at beginning of file
|
||||
const insertAtBeginning = allImports.length === 0 && useStrict.length === 0;
|
||||
const separator = insertAtBeginning ? '' : ';\n';
|
||||
const toInsert =
|
||||
`${separator}import ${open}${symbolName}${close}` +
|
||||
` from '${fileName}'${insertAtBeginning ? ';\n' : ''}`;
|
||||
|
||||
return insertAfterLastOccurrence(
|
||||
allImports,
|
||||
toInsert,
|
||||
fileToEdit,
|
||||
fallbackPos,
|
||||
ts.SyntaxKind.StringLiteral
|
||||
);
|
||||
}
|
||||
|
||||
@ -1,3 +1,5 @@
|
||||
import * as path from 'path';
|
||||
|
||||
export function names(name: string): any {
|
||||
return {
|
||||
name,
|
||||
@ -30,3 +32,11 @@ export function toFileName(s: string): string {
|
||||
function toCapitalCase(s: string): string {
|
||||
return s.charAt(0).toUpperCase() + s.substr(1);
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine the parent directory for the ngModule specified
|
||||
* in the full-path option 'module'
|
||||
*/
|
||||
export function findModuleParent(modulePath) {
|
||||
return path.dirname(modulePath);
|
||||
}
|
||||
|
||||
10
packages/schematics/src/utils/rules/deleteFile.ts
Normal file
10
packages/schematics/src/utils/rules/deleteFile.ts
Normal file
@ -0,0 +1,10 @@
|
||||
import { forEach, FileEntry, Rule } from '@angular-devkit/schematics';
|
||||
|
||||
/**
|
||||
* Remove a file from the Virtual Schematic Tree
|
||||
*/
|
||||
export function deleteFile(from: string): Rule {
|
||||
return forEach((entry: FileEntry): FileEntry | null => {
|
||||
return entry.path === from ? null : entry;
|
||||
});
|
||||
}
|
||||
152
packages/schematics/src/utils/strings.ts
Normal file
152
packages/schematics/src/utils/strings.ts
Normal file
@ -0,0 +1,152 @@
|
||||
/**
|
||||
* @license
|
||||
* Copyright Google Inc. All Rights Reserved.
|
||||
*
|
||||
* Use of this source code is governed by an MIT-style license that can be
|
||||
* found in the LICENSE file at https://angular.io/license
|
||||
*/
|
||||
const STRING_DASHERIZE_REGEXP = /[ _]/g;
|
||||
const STRING_DECAMELIZE_REGEXP = /([a-z\d])([A-Z])/g;
|
||||
const STRING_CAMELIZE_REGEXP = /(-|_|\.|\s)+(.)?/g;
|
||||
const STRING_UNDERSCORE_REGEXP_1 = /([a-z\d])([A-Z]+)/g;
|
||||
const STRING_UNDERSCORE_REGEXP_2 = /-|\s+/g;
|
||||
|
||||
/**
|
||||
* Converts a camelized string into all lower case separated by underscores.
|
||||
*
|
||||
```javascript
|
||||
decamelize('innerHTML'); // 'inner_html'
|
||||
decamelize('action_name'); // 'action_name'
|
||||
decamelize('css-class-name'); // 'css-class-name'
|
||||
decamelize('my favorite items'); // 'my favorite items'
|
||||
```
|
||||
|
||||
@method decamelize
|
||||
@param {String} str The string to decamelize.
|
||||
@return {String} the decamelized string.
|
||||
*/
|
||||
export function decamelize(str: string): string {
|
||||
return str.replace(STRING_DECAMELIZE_REGEXP, '$1_$2').toLowerCase();
|
||||
}
|
||||
|
||||
/**
|
||||
Replaces underscores, spaces, or camelCase with dashes.
|
||||
|
||||
```javascript
|
||||
dasherize('innerHTML'); // 'inner-html'
|
||||
dasherize('action_name'); // 'action-name'
|
||||
dasherize('css-class-name'); // 'css-class-name'
|
||||
dasherize('my favorite items'); // 'my-favorite-items'
|
||||
```
|
||||
|
||||
@method dasherize
|
||||
@param {String} str The string to dasherize.
|
||||
@return {String} the dasherized string.
|
||||
*/
|
||||
export function dasherize(str?: string): string {
|
||||
return decamelize(str || '').replace(STRING_DASHERIZE_REGEXP, '-');
|
||||
}
|
||||
|
||||
/**
|
||||
Returns the lowerCamelCase form of a string.
|
||||
|
||||
```javascript
|
||||
camelize('innerHTML'); // 'innerHTML'
|
||||
camelize('action_name'); // 'actionName'
|
||||
camelize('css-class-name'); // 'cssClassName'
|
||||
camelize('my favorite items'); // 'myFavoriteItems'
|
||||
camelize('My Favorite Items'); // 'myFavoriteItems'
|
||||
```
|
||||
|
||||
@method camelize
|
||||
@param {String} str The string to camelize.
|
||||
@return {String} the camelized string.
|
||||
*/
|
||||
export function camelize(str: string): string {
|
||||
return str
|
||||
.replace(
|
||||
STRING_CAMELIZE_REGEXP,
|
||||
(_match: string, _separator: string, chr: string) => {
|
||||
return chr ? chr.toUpperCase() : '';
|
||||
}
|
||||
)
|
||||
.replace(/^([A-Z])/, (match: string) => match.toLowerCase());
|
||||
}
|
||||
|
||||
/**
|
||||
Returns the UpperCamelCase form of a string.
|
||||
|
||||
```javascript
|
||||
'innerHTML'.classify(); // 'InnerHTML'
|
||||
'action_name'.classify(); // 'ActionName'
|
||||
'css-class-name'.classify(); // 'CssClassName'
|
||||
'my favorite items'.classify(); // 'MyFavoriteItems'
|
||||
```
|
||||
|
||||
@method classify
|
||||
@param {String} str the string to classify
|
||||
@return {String} the classified string
|
||||
*/
|
||||
export function classify(str: string): string {
|
||||
return str
|
||||
.split('.')
|
||||
.map(part => capitalize(camelize(part)))
|
||||
.join('.');
|
||||
}
|
||||
|
||||
/**
|
||||
More general than decamelize. Returns the lower\_case\_and\_underscored
|
||||
form of a string.
|
||||
|
||||
```javascript
|
||||
'innerHTML'.underscore(); // 'inner_html'
|
||||
'action_name'.underscore(); // 'action_name'
|
||||
'css-class-name'.underscore(); // 'css_class_name'
|
||||
'my favorite items'.underscore(); // 'my_favorite_items'
|
||||
```
|
||||
|
||||
@method underscore
|
||||
@param {String} str The string to underscore.
|
||||
@return {String} the underscored string.
|
||||
*/
|
||||
export function underscore(str: string): string {
|
||||
return str
|
||||
.replace(STRING_UNDERSCORE_REGEXP_1, '$1_$2')
|
||||
.replace(STRING_UNDERSCORE_REGEXP_2, '_')
|
||||
.toLowerCase();
|
||||
}
|
||||
|
||||
/**
|
||||
Returns the Capitalized form of a string
|
||||
|
||||
```javascript
|
||||
'innerHTML'.capitalize() // 'InnerHTML'
|
||||
'action_name'.capitalize() // 'Action_name'
|
||||
'css-class-name'.capitalize() // 'Css-class-name'
|
||||
'my favorite items'.capitalize() // 'My favorite items'
|
||||
```
|
||||
|
||||
@method capitalize
|
||||
@param {String} str The string to capitalize.
|
||||
@return {String} The capitalized string.
|
||||
*/
|
||||
export function capitalize(str: string): string {
|
||||
return str.charAt(0).toUpperCase() + str.substr(1);
|
||||
}
|
||||
|
||||
export function group(name: string, group: string | undefined) {
|
||||
return group ? `${group}/${name}` : name;
|
||||
}
|
||||
|
||||
export function featurePath(
|
||||
group: boolean | undefined,
|
||||
flat: boolean | undefined,
|
||||
path: string,
|
||||
name: string
|
||||
) {
|
||||
if (group && !flat) {
|
||||
return `../../${path}/${name}/`;
|
||||
}
|
||||
|
||||
return group ? `../${path}/` : './';
|
||||
}
|
||||
@ -1,5 +1,16 @@
|
||||
import { Tree } from '@angular-devkit/schematics';
|
||||
|
||||
export interface AppConfig {
|
||||
appName: string; // name of app or lib
|
||||
appModule: string; // app/app.module.ts in the above sourceDir
|
||||
}
|
||||
|
||||
var appConfig: AppConfig; // configure built in createApp()
|
||||
|
||||
export function getAppConfig(): AppConfig {
|
||||
return appConfig;
|
||||
}
|
||||
|
||||
export function createEmptyWorkspace(tree: Tree): Tree {
|
||||
tree.create('/.angular-cli.json', JSON.stringify({}));
|
||||
tree.create('/package.json', JSON.stringify({}));
|
||||
@ -22,8 +33,14 @@ export function createEmptyWorkspace(tree: Tree): Tree {
|
||||
}
|
||||
|
||||
export function createApp(tree: Tree, appName: string): Tree {
|
||||
// save for getAppDir() lookup by external *.spec.ts tests
|
||||
appConfig = {
|
||||
appName,
|
||||
appModule: `/apps/${appName}/src/app/app.module.ts`
|
||||
};
|
||||
|
||||
tree.create(
|
||||
`/apps/${appName}/src/app/app.module.ts`,
|
||||
appConfig.appModule,
|
||||
`
|
||||
import { NgModule } from '@angular/core';
|
||||
import { BrowserModule } from '@angular/platform-browser';
|
||||
|
||||
336
yarn.lock
336
yarn.lock
@ -151,6 +151,10 @@
|
||||
version "5.2.0"
|
||||
resolved "https://registry.yarnpkg.com/@ngrx/router-store/-/router-store-5.2.0.tgz#bf4b174ce19a36eba8211fc1ddeaf1e35ae74368"
|
||||
|
||||
"@ngrx/schematics@^5.2.0":
|
||||
version "5.2.0"
|
||||
resolved "https://registry.yarnpkg.com/@ngrx/schematics/-/schematics-5.2.0.tgz#ab7180d79f0ec68bd4ac3ef4ec83b9348d18d26c"
|
||||
|
||||
"@ngrx/store-devtools@5.2.0":
|
||||
version "5.2.0"
|
||||
resolved "https://registry.yarnpkg.com/@ngrx/store-devtools/-/store-devtools-5.2.0.tgz#2fff916a9aa349375826772b359dbb64b9e5d622"
|
||||
@ -205,8 +209,8 @@
|
||||
"@types/jasmine" "*"
|
||||
|
||||
"@types/node@~6.0.60":
|
||||
version "6.0.102"
|
||||
resolved "https://registry.yarnpkg.com/@types/node/-/node-6.0.102.tgz#a6cf3b9843286b63eb362a8522bc382d96fe68d1"
|
||||
version "6.0.103"
|
||||
resolved "https://registry.yarnpkg.com/@types/node/-/node-6.0.103.tgz#4fddb6c254756e98004039da4e4f4230d1e397ca"
|
||||
|
||||
"@types/prettier@^1.10.0":
|
||||
version "1.10.0"
|
||||
@ -297,12 +301,13 @@ ajv@^5.0.0, ajv@^5.1.0, ajv@~5.5.1:
|
||||
json-schema-traverse "^0.3.0"
|
||||
|
||||
ajv@^6.1.0, ajv@^6.1.1:
|
||||
version "6.2.1"
|
||||
resolved "https://registry.yarnpkg.com/ajv/-/ajv-6.2.1.tgz#28a6abc493a2abe0fb4c8507acaedb43fa550671"
|
||||
version "6.4.0"
|
||||
resolved "https://registry.yarnpkg.com/ajv/-/ajv-6.4.0.tgz#d3aff78e9277549771daf0164cff48482b754fc6"
|
||||
dependencies:
|
||||
fast-deep-equal "^1.0.0"
|
||||
fast-json-stable-stringify "^2.0.0"
|
||||
json-schema-traverse "^0.3.0"
|
||||
uri-js "^3.0.2"
|
||||
|
||||
align-text@^0.1.1, align-text@^0.1.3:
|
||||
version "0.1.4"
|
||||
@ -567,8 +572,8 @@ asynckit@^0.4.0:
|
||||
resolved "https://registry.yarnpkg.com/asynckit/-/asynckit-0.4.0.tgz#c79ed97f7f34cb8f2ba1bc9790bcc366474b4b79"
|
||||
|
||||
atob@^2.0.0:
|
||||
version "2.0.3"
|
||||
resolved "https://registry.yarnpkg.com/atob/-/atob-2.0.3.tgz#19c7a760473774468f20b2d2d03372ad7d4cbf5d"
|
||||
version "2.1.0"
|
||||
resolved "https://registry.yarnpkg.com/atob/-/atob-2.1.0.tgz#ab2b150e51d7b122b9efc8d7340c06b6c41076bc"
|
||||
|
||||
autoprefixer@^7.1.1, autoprefixer@^7.2.3:
|
||||
version "7.2.6"
|
||||
@ -928,8 +933,8 @@ brorand@^1.0.1:
|
||||
resolved "https://registry.yarnpkg.com/brorand/-/brorand-1.1.0.tgz#12c25efe40a45e3c323eb8675a0a0ce57b22371f"
|
||||
|
||||
browser-pack@^6.0.1:
|
||||
version "6.0.4"
|
||||
resolved "https://registry.yarnpkg.com/browser-pack/-/browser-pack-6.0.4.tgz#9a73beb3b48f9e36868be007b64400102c04a99f"
|
||||
version "6.1.0"
|
||||
resolved "https://registry.yarnpkg.com/browser-pack/-/browser-pack-6.1.0.tgz#c34ba10d0b9ce162b5af227c7131c92c2ecd5774"
|
||||
dependencies:
|
||||
JSONStream "^1.0.3"
|
||||
combine-source-map "~0.8.0"
|
||||
@ -1071,6 +1076,10 @@ buffer-crc32@^0.2.5:
|
||||
version "0.2.13"
|
||||
resolved "https://registry.yarnpkg.com/buffer-crc32/-/buffer-crc32-0.2.13.tgz#0d333e3f00eac50aa1454abd30ef8c2a5d9a7242"
|
||||
|
||||
buffer-from@^1.0.0:
|
||||
version "1.0.0"
|
||||
resolved "https://registry.yarnpkg.com/buffer-from/-/buffer-from-1.0.0.tgz#4cb8832d23612589b0406e9e2956c17f06fdf531"
|
||||
|
||||
buffer-indexof@^1.0.0:
|
||||
version "1.1.1"
|
||||
resolved "https://registry.yarnpkg.com/buffer-indexof/-/buffer-indexof-1.1.1.tgz#52fabcc6a606d1a00302802648ef68f639da268c"
|
||||
@ -1210,8 +1219,8 @@ camelcase@^4.0.0, camelcase@^4.1.0:
|
||||
resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-4.1.0.tgz#d545635be1e33c542649c69173e5de6acfae34dd"
|
||||
|
||||
caniuse-lite@^1.0.30000792, caniuse-lite@^1.0.30000805:
|
||||
version "1.0.30000813"
|
||||
resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30000813.tgz#7b25e27fdfb8d133f3c932b01f77452140fcc6c9"
|
||||
version "1.0.30000821"
|
||||
resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30000821.tgz#0f3223f1e048ed96451c56ca6cf197058c42cb93"
|
||||
|
||||
capture-stack-trace@^1.0.0:
|
||||
version "1.0.0"
|
||||
@ -1242,7 +1251,7 @@ chalk@^1.1.1, chalk@^1.1.3:
|
||||
strip-ansi "^3.0.0"
|
||||
supports-color "^2.0.0"
|
||||
|
||||
chalk@^2.0.0, chalk@^2.0.1, chalk@^2.1.0, chalk@^2.3.0, chalk@^2.3.1:
|
||||
chalk@^2.0.0, chalk@^2.0.1, chalk@^2.1.0, chalk@^2.3.0, chalk@^2.3.1, chalk@^2.3.2:
|
||||
version "2.3.2"
|
||||
resolved "https://registry.yarnpkg.com/chalk/-/chalk-2.3.2.tgz#250dc96b07491bfd601e648d66ddf5f60c7a5c65"
|
||||
dependencies:
|
||||
@ -1274,8 +1283,8 @@ chokidar@^1.4.1, chokidar@^1.4.2, chokidar@^1.6.0, chokidar@^1.7.0:
|
||||
fsevents "^1.0.0"
|
||||
|
||||
chokidar@^2.0.0, chokidar@^2.0.2:
|
||||
version "2.0.2"
|
||||
resolved "https://registry.yarnpkg.com/chokidar/-/chokidar-2.0.2.tgz#4dc65139eeb2714977735b6a35d06e97b494dfd7"
|
||||
version "2.0.3"
|
||||
resolved "https://registry.yarnpkg.com/chokidar/-/chokidar-2.0.3.tgz#dcbd4f6cbb2a55b4799ba8a840ac527e5f4b1176"
|
||||
dependencies:
|
||||
anymatch "^2.0.0"
|
||||
async-each "^1.0.0"
|
||||
@ -1289,7 +1298,7 @@ chokidar@^2.0.0, chokidar@^2.0.2:
|
||||
readdirp "^2.0.0"
|
||||
upath "^1.0.0"
|
||||
optionalDependencies:
|
||||
fsevents "^1.0.0"
|
||||
fsevents "^1.1.2"
|
||||
|
||||
chownr@^1.0.1:
|
||||
version "1.0.1"
|
||||
@ -1369,8 +1378,8 @@ clone-deep@^2.0.1:
|
||||
shallow-clone "^1.0.0"
|
||||
|
||||
clone@^2.1.1:
|
||||
version "2.1.1"
|
||||
resolved "https://registry.yarnpkg.com/clone/-/clone-2.1.1.tgz#d217d1e961118e3ac9a4b8bba3285553bf647cdb"
|
||||
version "2.1.2"
|
||||
resolved "https://registry.yarnpkg.com/clone/-/clone-2.1.2.tgz#1b7f4b9f591f1e8f83670401600345a02887435f"
|
||||
|
||||
co@^4.6.0:
|
||||
version "4.6.0"
|
||||
@ -1415,16 +1424,7 @@ combine-lists@^1.0.0:
|
||||
dependencies:
|
||||
lodash "^4.5.0"
|
||||
|
||||
combine-source-map@~0.7.1:
|
||||
version "0.7.2"
|
||||
resolved "https://registry.yarnpkg.com/combine-source-map/-/combine-source-map-0.7.2.tgz#0870312856b307a87cc4ac486f3a9a62aeccc09e"
|
||||
dependencies:
|
||||
convert-source-map "~1.1.0"
|
||||
inline-source-map "~0.6.0"
|
||||
lodash.memoize "~3.0.3"
|
||||
source-map "~0.5.3"
|
||||
|
||||
combine-source-map@~0.8.0:
|
||||
combine-source-map@^0.8.0, combine-source-map@~0.8.0:
|
||||
version "0.8.0"
|
||||
resolved "https://registry.yarnpkg.com/combine-source-map/-/combine-source-map-0.8.0.tgz#a58d0df042c186fcf822a8e8015f5450d2d79a8b"
|
||||
dependencies:
|
||||
@ -1439,13 +1439,9 @@ combined-stream@1.0.6, combined-stream@^1.0.5, combined-stream@~1.0.5:
|
||||
dependencies:
|
||||
delayed-stream "~1.0.0"
|
||||
|
||||
commander@2.14.x, commander@~2.14.1:
|
||||
version "2.14.1"
|
||||
resolved "https://registry.yarnpkg.com/commander/-/commander-2.14.1.tgz#2235123e37af8ca3c65df45b026dbd357b01b9aa"
|
||||
|
||||
commander@^2.12.0, commander@^2.12.1, commander@^2.9.0:
|
||||
version "2.15.0"
|
||||
resolved "https://registry.yarnpkg.com/commander/-/commander-2.15.0.tgz#ad2a23a1c3b036e392469b8012cec6b33b4c1322"
|
||||
commander@2.15.x, commander@^2.12.0, commander@^2.12.1, commander@^2.9.0, commander@~2.15.0:
|
||||
version "2.15.1"
|
||||
resolved "https://registry.yarnpkg.com/commander/-/commander-2.15.1.tgz#df46e867d0fc2aec66a34662b406a9ccafff5b0f"
|
||||
|
||||
commander@~2.13.0:
|
||||
version "2.13.0"
|
||||
@ -1489,7 +1485,7 @@ compressible@~2.0.13:
|
||||
|
||||
compression@^1.5.2:
|
||||
version "1.7.2"
|
||||
resolved "https://registry.yarnpkg.com/compression/-/compression-1.7.2.tgz#aaffbcd6aaf854b44ebb280353d5ad1651f59a69"
|
||||
resolved "http://registry.npmjs.org/compression/-/compression-1.7.2.tgz#aaffbcd6aaf854b44ebb280353d5ad1651f59a69"
|
||||
dependencies:
|
||||
accepts "~1.3.4"
|
||||
bytes "3.0.0"
|
||||
@ -1503,10 +1499,11 @@ concat-map@0.0.1:
|
||||
version "0.0.1"
|
||||
resolved "https://registry.yarnpkg.com/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b"
|
||||
|
||||
concat-stream@^1.5.0:
|
||||
version "1.6.1"
|
||||
resolved "https://registry.yarnpkg.com/concat-stream/-/concat-stream-1.6.1.tgz#261b8f518301f1d834e36342b9fea095d2620a26"
|
||||
concat-stream@^1.5.0, concat-stream@^1.6.1:
|
||||
version "1.6.2"
|
||||
resolved "https://registry.yarnpkg.com/concat-stream/-/concat-stream-1.6.2.tgz#904bdf194cd3122fc675c77fc4ac3d4ff0fd1a34"
|
||||
dependencies:
|
||||
buffer-from "^1.0.0"
|
||||
inherits "^2.0.3"
|
||||
readable-stream "^2.2.2"
|
||||
typedarray "^0.0.6"
|
||||
@ -1520,8 +1517,8 @@ concat-stream@~1.5.0, concat-stream@~1.5.1:
|
||||
typedarray "~0.0.5"
|
||||
|
||||
configstore@^3.0.0:
|
||||
version "3.1.1"
|
||||
resolved "https://registry.yarnpkg.com/configstore/-/configstore-3.1.1.tgz#094ee662ab83fad9917678de114faaea8fcdca90"
|
||||
version "3.1.2"
|
||||
resolved "https://registry.yarnpkg.com/configstore/-/configstore-3.1.2.tgz#c6f25defaeef26df12dd33414b001fe81a543f8f"
|
||||
dependencies:
|
||||
dot-prop "^4.1.0"
|
||||
graceful-fs "^4.1.2"
|
||||
@ -1614,8 +1611,8 @@ copy-webpack-plugin@~4.4.1:
|
||||
serialize-javascript "^1.4.0"
|
||||
|
||||
core-js@^2.2.0, core-js@^2.4.0, core-js@^2.5.0:
|
||||
version "2.5.3"
|
||||
resolved "https://registry.yarnpkg.com/core-js/-/core-js-2.5.3.tgz#8acc38345824f16d8365b7c9b4259168e8ed603e"
|
||||
version "2.5.4"
|
||||
resolved "https://registry.yarnpkg.com/core-js/-/core-js-2.5.4.tgz#f2c8bf181f2a80b92f360121429ce63a2f0aeae0"
|
||||
|
||||
core-object@^3.1.0:
|
||||
version "3.1.5"
|
||||
@ -2112,12 +2109,12 @@ ee-first@1.1.1:
|
||||
resolved "https://registry.yarnpkg.com/ee-first/-/ee-first-1.1.1.tgz#590c61156b0ae2f4f0255732a158b266bc56b21d"
|
||||
|
||||
ejs@^2.5.7:
|
||||
version "2.5.7"
|
||||
resolved "https://registry.yarnpkg.com/ejs/-/ejs-2.5.7.tgz#cc872c168880ae3c7189762fd5ffc00896c9518a"
|
||||
version "2.5.8"
|
||||
resolved "https://registry.yarnpkg.com/ejs/-/ejs-2.5.8.tgz#2ab6954619f225e6193b7ac5f7c39c48fefe4380"
|
||||
|
||||
electron-to-chromium@^1.3.30:
|
||||
version "1.3.37"
|
||||
resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.3.37.tgz#4a92734e0044c8cf0b1553be57eae21a4c6e5fab"
|
||||
version "1.3.41"
|
||||
resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.3.41.tgz#7e33643e00cd85edfd17e04194f6d00e73737235"
|
||||
|
||||
elliptic@^6.0.0:
|
||||
version "6.4.0"
|
||||
@ -2218,8 +2215,8 @@ error-ex@^1.2.0, error-ex@^1.3.1:
|
||||
is-arrayish "^0.2.1"
|
||||
|
||||
es-abstract@^1.4.3, es-abstract@^1.7.0:
|
||||
version "1.10.0"
|
||||
resolved "https://registry.yarnpkg.com/es-abstract/-/es-abstract-1.10.0.tgz#1ecb36c197842a00d8ee4c2dfd8646bb97d60864"
|
||||
version "1.11.0"
|
||||
resolved "https://registry.yarnpkg.com/es-abstract/-/es-abstract-1.11.0.tgz#cce87d518f0496893b1a30cd8461835535480681"
|
||||
dependencies:
|
||||
es-to-primitive "^1.1.1"
|
||||
function-bind "^1.1.1"
|
||||
@ -2236,11 +2233,12 @@ es-to-primitive@^1.1.1:
|
||||
is-symbol "^1.0.1"
|
||||
|
||||
es5-ext@^0.10.14, es5-ext@^0.10.35, es5-ext@^0.10.9, es5-ext@~0.10.14:
|
||||
version "0.10.40"
|
||||
resolved "https://registry.yarnpkg.com/es5-ext/-/es5-ext-0.10.40.tgz#ab3d2179b943008c5e9ef241beb25ef41424c774"
|
||||
version "0.10.42"
|
||||
resolved "https://registry.yarnpkg.com/es5-ext/-/es5-ext-0.10.42.tgz#8c07dd33af04d5dcd1310b5cef13bea63a89ba8d"
|
||||
dependencies:
|
||||
es6-iterator "~2.0.3"
|
||||
es6-symbol "~3.1.1"
|
||||
next-tick "1"
|
||||
|
||||
es6-iterator@^2.0.1, es6-iterator@~2.0.1, es6-iterator@~2.0.3:
|
||||
version "2.0.3"
|
||||
@ -2681,8 +2679,8 @@ find-up@^2.0.0, find-up@^2.1.0:
|
||||
locate-path "^2.0.0"
|
||||
|
||||
flush-write-stream@^1.0.0:
|
||||
version "1.0.2"
|
||||
resolved "https://registry.yarnpkg.com/flush-write-stream/-/flush-write-stream-1.0.2.tgz#c81b90d8746766f1a609a46809946c45dd8ae417"
|
||||
version "1.0.3"
|
||||
resolved "https://registry.yarnpkg.com/flush-write-stream/-/flush-write-stream-1.0.3.tgz#c5d586ef38af6097650b49bc41b55fabb19f35bd"
|
||||
dependencies:
|
||||
inherits "^2.0.1"
|
||||
readable-stream "^2.0.4"
|
||||
@ -2805,7 +2803,7 @@ fs.realpath@^1.0.0:
|
||||
version "1.0.0"
|
||||
resolved "https://registry.yarnpkg.com/fs.realpath/-/fs.realpath-1.0.0.tgz#1504ad2523158caa40db4a2787cb01411994ea4f"
|
||||
|
||||
fsevents@^1.0.0:
|
||||
fsevents@^1.0.0, fsevents@^1.1.2:
|
||||
version "1.1.3"
|
||||
resolved "https://registry.yarnpkg.com/fsevents/-/fsevents-1.1.3.tgz#11f82318f5fe7bb2cd22965a108e9306208216d8"
|
||||
dependencies:
|
||||
@ -3229,12 +3227,12 @@ html-entities@^1.2.0:
|
||||
resolved "https://registry.yarnpkg.com/html-entities/-/html-entities-1.2.1.tgz#0df29351f0721163515dfb9e5543e5f6eed5162f"
|
||||
|
||||
html-minifier@^3.2.3:
|
||||
version "3.5.10"
|
||||
resolved "https://registry.yarnpkg.com/html-minifier/-/html-minifier-3.5.10.tgz#8522c772c388db81aa5c26f62033302d906ea1c7"
|
||||
version "3.5.12"
|
||||
resolved "https://registry.yarnpkg.com/html-minifier/-/html-minifier-3.5.12.tgz#6bfad4d0327f5b8d2b62f5854654ac3703b9b031"
|
||||
dependencies:
|
||||
camel-case "3.0.x"
|
||||
clean-css "4.1.x"
|
||||
commander "2.14.x"
|
||||
commander "2.15.x"
|
||||
he "1.1.x"
|
||||
ncname "1.0.x"
|
||||
param-case "2.1.x"
|
||||
@ -3269,7 +3267,7 @@ http-deceiver@^1.2.7:
|
||||
version "1.2.7"
|
||||
resolved "https://registry.yarnpkg.com/http-deceiver/-/http-deceiver-1.2.7.tgz#fa7168944ab9a519d337cb0bec7284dc3e723d87"
|
||||
|
||||
http-errors@1.6.2, http-errors@~1.6.2:
|
||||
http-errors@1.6.2:
|
||||
version "1.6.2"
|
||||
resolved "https://registry.yarnpkg.com/http-errors/-/http-errors-1.6.2.tgz#0a002cc85707192a7e7946ceedc11155f60ec736"
|
||||
dependencies:
|
||||
@ -3278,6 +3276,15 @@ http-errors@1.6.2, http-errors@~1.6.2:
|
||||
setprototypeof "1.0.3"
|
||||
statuses ">= 1.3.1 < 2"
|
||||
|
||||
http-errors@~1.6.2:
|
||||
version "1.6.3"
|
||||
resolved "https://registry.yarnpkg.com/http-errors/-/http-errors-1.6.3.tgz#8b55680bb4be283a0b5bf4ea2e38580be1d9320d"
|
||||
dependencies:
|
||||
depd "~1.1.2"
|
||||
inherits "2.0.3"
|
||||
setprototypeof "1.1.0"
|
||||
statuses ">= 1.4.0 < 2"
|
||||
|
||||
http-parser-js@>=0.4.0:
|
||||
version "0.4.11"
|
||||
resolved "https://registry.yarnpkg.com/http-parser-js/-/http-parser-js-0.4.11.tgz#5b720849c650903c27e521633d94696ee95f3529"
|
||||
@ -3362,8 +3369,8 @@ iconv-lite@0.4.19:
|
||||
resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.4.19.tgz#f7468f60135f5e5dad3399c0a81be9a1603a082b"
|
||||
|
||||
ieee754@^1.1.4:
|
||||
version "1.1.8"
|
||||
resolved "https://registry.yarnpkg.com/ieee754/-/ieee754-1.1.8.tgz#be33d40ac10ef1926701f6f08a2d86fbfd1ad3e4"
|
||||
version "1.1.11"
|
||||
resolved "https://registry.yarnpkg.com/ieee754/-/ieee754-1.1.11.tgz#c16384ffe00f5b7835824e67b6f2bd44a5229455"
|
||||
|
||||
iferr@^0.1.5:
|
||||
version "0.1.5"
|
||||
@ -3444,12 +3451,12 @@ inline-source-map@~0.6.0:
|
||||
source-map "~0.5.3"
|
||||
|
||||
insert-module-globals@^7.0.0:
|
||||
version "7.0.2"
|
||||
resolved "https://registry.yarnpkg.com/insert-module-globals/-/insert-module-globals-7.0.2.tgz#012c56baa7d3307a8b417d4ec5270cf9741c18f4"
|
||||
version "7.0.5"
|
||||
resolved "https://registry.yarnpkg.com/insert-module-globals/-/insert-module-globals-7.0.5.tgz#6d0a6f28d4a7e0eae171ad305e0f47bdfe0c258e"
|
||||
dependencies:
|
||||
JSONStream "^1.0.3"
|
||||
combine-source-map "~0.7.1"
|
||||
concat-stream "~1.5.1"
|
||||
combine-source-map "^0.8.0"
|
||||
concat-stream "^1.6.1"
|
||||
is-buffer "^1.1.0"
|
||||
lexical-scope "^1.2.0"
|
||||
process "~0.11.0"
|
||||
@ -3467,8 +3474,8 @@ interpret@^1.0.0:
|
||||
resolved "https://registry.yarnpkg.com/interpret/-/interpret-1.1.0.tgz#7ed1b1410c6a0e0f78cf95d3b8440c63f78b8614"
|
||||
|
||||
invariant@^2.2.2:
|
||||
version "2.2.3"
|
||||
resolved "https://registry.yarnpkg.com/invariant/-/invariant-2.2.3.tgz#1a827dfde7dcbd7c323f0ca826be8fa7c5e9d688"
|
||||
version "2.2.4"
|
||||
resolved "https://registry.yarnpkg.com/invariant/-/invariant-2.2.4.tgz#610f3c92c9359ce1db616e538008d23ff35158e6"
|
||||
dependencies:
|
||||
loose-envify "^1.0.0"
|
||||
|
||||
@ -3692,8 +3699,8 @@ is-path-cwd@^1.0.0:
|
||||
resolved "https://registry.yarnpkg.com/is-path-cwd/-/is-path-cwd-1.0.0.tgz#d225ec23132e89edd38fda767472e62e65f1106d"
|
||||
|
||||
is-path-in-cwd@^1.0.0:
|
||||
version "1.0.0"
|
||||
resolved "https://registry.yarnpkg.com/is-path-in-cwd/-/is-path-in-cwd-1.0.0.tgz#6477582b8214d602346094567003be8a9eac04dc"
|
||||
version "1.0.1"
|
||||
resolved "https://registry.yarnpkg.com/is-path-in-cwd/-/is-path-in-cwd-1.0.1.tgz#5ac48b345ef675339bd6c7a48a912110b241cf52"
|
||||
dependencies:
|
||||
is-path-inside "^1.0.0"
|
||||
|
||||
@ -3759,7 +3766,7 @@ is-wsl@^1.1.0:
|
||||
version "1.1.0"
|
||||
resolved "https://registry.yarnpkg.com/is-wsl/-/is-wsl-1.1.0.tgz#1f16e4aa22b04d1336b66188a66af3c600c3a66d"
|
||||
|
||||
isarray@0.0.1, isarray@~0.0.1:
|
||||
isarray@0.0.1:
|
||||
version "0.0.1"
|
||||
resolved "https://registry.yarnpkg.com/isarray/-/isarray-0.0.1.tgz#8a18acfca9a8f4177e09abfc6038939b05d1eedf"
|
||||
|
||||
@ -3771,6 +3778,10 @@ isarray@2.0.1:
|
||||
version "2.0.1"
|
||||
resolved "https://registry.yarnpkg.com/isarray/-/isarray-2.0.1.tgz#a37d94ed9cda2d59865c9f76fe596ee1f338741e"
|
||||
|
||||
isarray@^2.0.4:
|
||||
version "2.0.4"
|
||||
resolved "https://registry.yarnpkg.com/isarray/-/isarray-2.0.4.tgz#38e7bcbb0f3ba1b7933c86ba1894ddfc3781bbb7"
|
||||
|
||||
isbinaryfile@^3.0.0:
|
||||
version "3.0.2"
|
||||
resolved "https://registry.yarnpkg.com/isbinaryfile/-/isbinaryfile-3.0.2.tgz#4a3e974ec0cba9004d3fc6cde7209ea69368a621"
|
||||
@ -3811,8 +3822,8 @@ istanbul-api@^1.1.1:
|
||||
once "^1.4.0"
|
||||
|
||||
istanbul-instrumenter-loader@^3.0.0:
|
||||
version "3.0.0"
|
||||
resolved "https://registry.yarnpkg.com/istanbul-instrumenter-loader/-/istanbul-instrumenter-loader-3.0.0.tgz#9f553923b22360bac95e617aaba01add1f7db0b2"
|
||||
version "3.0.1"
|
||||
resolved "https://registry.yarnpkg.com/istanbul-instrumenter-loader/-/istanbul-instrumenter-loader-3.0.1.tgz#9957bd59252b373fae5c52b7b5188e6fde2a0949"
|
||||
dependencies:
|
||||
convert-source-map "^1.5.0"
|
||||
istanbul-lib-instrument "^1.7.3"
|
||||
@ -4155,8 +4166,8 @@ json-loader@^0.5.4:
|
||||
resolved "https://registry.yarnpkg.com/json-loader/-/json-loader-0.5.7.tgz#dca14a70235ff82f0ac9a3abeb60d337a365185d"
|
||||
|
||||
json-parse-better-errors@^1.0.1:
|
||||
version "1.0.1"
|
||||
resolved "https://registry.yarnpkg.com/json-parse-better-errors/-/json-parse-better-errors-1.0.1.tgz#50183cd1b2d25275de069e9e71b467ac9eab973a"
|
||||
version "1.0.2"
|
||||
resolved "https://registry.yarnpkg.com/json-parse-better-errors/-/json-parse-better-errors-1.0.2.tgz#bb867cfb3450e69107c131d1c514bab3dc8bcaa9"
|
||||
|
||||
json-schema-traverse@^0.3.0:
|
||||
version "0.3.1"
|
||||
@ -4302,11 +4313,11 @@ kind-of@^6.0.0, kind-of@^6.0.2:
|
||||
resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-6.0.2.tgz#01146b36a6218e64e58f3a8d66de5d7fc6f6d051"
|
||||
|
||||
labeled-stream-splicer@^2.0.0:
|
||||
version "2.0.0"
|
||||
resolved "https://registry.yarnpkg.com/labeled-stream-splicer/-/labeled-stream-splicer-2.0.0.tgz#a52e1d138024c00b86b1c0c91f677918b8ae0a59"
|
||||
version "2.0.1"
|
||||
resolved "https://registry.yarnpkg.com/labeled-stream-splicer/-/labeled-stream-splicer-2.0.1.tgz#9cffa32fd99e1612fd1d86a8db962416d5292926"
|
||||
dependencies:
|
||||
inherits "^2.0.1"
|
||||
isarray "~0.0.1"
|
||||
isarray "^2.0.4"
|
||||
stream-splicer "^2.0.0"
|
||||
|
||||
latest-version@^3.0.0:
|
||||
@ -4380,8 +4391,8 @@ libqp@1.1.0:
|
||||
resolved "https://registry.yarnpkg.com/libqp/-/libqp-1.1.0.tgz#f5e6e06ad74b794fb5b5b66988bf728ef1dedbe8"
|
||||
|
||||
license-webpack-plugin@^1.0.0:
|
||||
version "1.3.0"
|
||||
resolved "https://registry.yarnpkg.com/license-webpack-plugin/-/license-webpack-plugin-1.3.0.tgz#b2c547f1a16d80426eecef38560d1312438d988e"
|
||||
version "1.3.1"
|
||||
resolved "https://registry.yarnpkg.com/license-webpack-plugin/-/license-webpack-plugin-1.3.1.tgz#688b76472188ef597918b7cae3eec7dc2fa5a0e8"
|
||||
dependencies:
|
||||
ejs "^2.5.7"
|
||||
|
||||
@ -4528,8 +4539,8 @@ lower-case@^1.1.1:
|
||||
resolved "https://registry.yarnpkg.com/lower-case/-/lower-case-1.1.4.tgz#9a2cabd1b9e8e0ae993a4bf7d5875c39c42e8eac"
|
||||
|
||||
lowercase-keys@^1.0.0:
|
||||
version "1.0.0"
|
||||
resolved "https://registry.yarnpkg.com/lowercase-keys/-/lowercase-keys-1.0.0.tgz#4e3366b39e7f5457e35f1324bdf6f88d0bfc7306"
|
||||
version "1.0.1"
|
||||
resolved "https://registry.yarnpkg.com/lowercase-keys/-/lowercase-keys-1.0.1.tgz#6f9e30b47084d971a7c820ff15a6c5167b74c26f"
|
||||
|
||||
lru-cache@4.1.x, lru-cache@^4.0.1, lru-cache@^4.1.1:
|
||||
version "4.1.2"
|
||||
@ -4542,12 +4553,18 @@ lru-cache@~2.6.5:
|
||||
version "2.6.5"
|
||||
resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-2.6.5.tgz#e56d6354148ede8d7707b58d143220fd08df0fd5"
|
||||
|
||||
magic-string@0.22.4, magic-string@^0.22.3, magic-string@^0.22.4:
|
||||
magic-string@0.22.4:
|
||||
version "0.22.4"
|
||||
resolved "https://registry.yarnpkg.com/magic-string/-/magic-string-0.22.4.tgz#31039b4e40366395618c1d6cf8193c53917475ff"
|
||||
dependencies:
|
||||
vlq "^0.2.1"
|
||||
|
||||
magic-string@^0.22.3, magic-string@^0.22.4:
|
||||
version "0.22.5"
|
||||
resolved "https://registry.yarnpkg.com/magic-string/-/magic-string-0.22.5.tgz#8e9cf5afddf44385c1da5bc2a6a0dbd10b03657e"
|
||||
dependencies:
|
||||
vlq "^0.2.2"
|
||||
|
||||
mailcomposer@4.0.1:
|
||||
version "4.0.1"
|
||||
resolved "https://registry.yarnpkg.com/mailcomposer/-/mailcomposer-4.0.1.tgz#0e1c44b2a07cf740ee17dc149ba009f19cadfeb4"
|
||||
@ -4673,8 +4690,8 @@ micromatch@^2.1.5, micromatch@^2.3.11:
|
||||
regex-cache "^0.4.2"
|
||||
|
||||
micromatch@^3.1.4, micromatch@^3.1.8:
|
||||
version "3.1.9"
|
||||
resolved "https://registry.yarnpkg.com/micromatch/-/micromatch-3.1.9.tgz#15dc93175ae39e52e93087847096effc73efcf89"
|
||||
version "3.1.10"
|
||||
resolved "https://registry.yarnpkg.com/micromatch/-/micromatch-3.1.10.tgz#70859bc95c9840952f359a068a3fc49f9ecfac23"
|
||||
dependencies:
|
||||
arr-diff "^4.0.0"
|
||||
array-unique "^0.3.2"
|
||||
@ -4688,7 +4705,7 @@ micromatch@^3.1.4, micromatch@^3.1.8:
|
||||
object.pick "^1.3.0"
|
||||
regex-not "^1.0.0"
|
||||
snapdragon "^0.8.1"
|
||||
to-regex "^3.0.1"
|
||||
to-regex "^3.0.2"
|
||||
|
||||
miller-rabin@^4.0.0:
|
||||
version "4.0.1"
|
||||
@ -4838,9 +4855,9 @@ multicast-dns@^6.0.1:
|
||||
dns-packet "^1.3.1"
|
||||
thunky "^1.0.2"
|
||||
|
||||
nan@^2.3.0, nan@^2.3.2:
|
||||
version "2.9.2"
|
||||
resolved "https://registry.yarnpkg.com/nan/-/nan-2.9.2.tgz#f564d75f5f8f36a6d9456cca7a6c4fe488ab7866"
|
||||
nan@^2.10.0, nan@^2.3.0:
|
||||
version "2.10.0"
|
||||
resolved "https://registry.yarnpkg.com/nan/-/nan-2.10.0.tgz#96d0cd610ebd58d4b4de9cc0c6828cda99c7548f"
|
||||
|
||||
nanomatch@^1.2.9:
|
||||
version "1.2.9"
|
||||
@ -4881,6 +4898,10 @@ netmask@~1.0.4:
|
||||
version "1.0.6"
|
||||
resolved "https://registry.yarnpkg.com/netmask/-/netmask-1.0.6.tgz#20297e89d86f6f6400f250d9f4f6b4c1945fcd35"
|
||||
|
||||
next-tick@1:
|
||||
version "1.0.0"
|
||||
resolved "https://registry.yarnpkg.com/next-tick/-/next-tick-1.0.0.tgz#ca86d1fe8828169b0120208e3dc8424b9db8342c"
|
||||
|
||||
ng-packagr@2.2.0:
|
||||
version "2.2.0"
|
||||
resolved "https://registry.yarnpkg.com/ng-packagr/-/ng-packagr-2.2.0.tgz#a66b7d822c40e8aa0dee34e06cca05151c522a3b"
|
||||
@ -5004,14 +5025,14 @@ node-pre-gyp@^0.6.39:
|
||||
tar-pack "^3.4.0"
|
||||
|
||||
node-sass-tilde-importer@^1.0.0:
|
||||
version "1.0.1"
|
||||
resolved "https://registry.yarnpkg.com/node-sass-tilde-importer/-/node-sass-tilde-importer-1.0.1.tgz#3eab5247a3bf53354766bb1e6fd2214ce17e74ee"
|
||||
version "1.0.2"
|
||||
resolved "https://registry.yarnpkg.com/node-sass-tilde-importer/-/node-sass-tilde-importer-1.0.2.tgz#1a15105c153f648323b4347693fdb0f331bad1ce"
|
||||
dependencies:
|
||||
find-parent-dir "^0.3.0"
|
||||
|
||||
node-sass@^4.5.3, node-sass@^4.7.2:
|
||||
version "4.7.2"
|
||||
resolved "https://registry.yarnpkg.com/node-sass/-/node-sass-4.7.2.tgz#9366778ba1469eb01438a9e8592f4262bcb6794e"
|
||||
version "4.8.3"
|
||||
resolved "https://registry.yarnpkg.com/node-sass/-/node-sass-4.8.3.tgz#d077cc20a08ac06f661ca44fb6f19cd2ed41debb"
|
||||
dependencies:
|
||||
async-foreach "^0.1.3"
|
||||
chalk "^1.1.1"
|
||||
@ -5025,7 +5046,7 @@ node-sass@^4.5.3, node-sass@^4.7.2:
|
||||
lodash.mergewith "^4.6.0"
|
||||
meow "^3.7.0"
|
||||
mkdirp "^0.5.1"
|
||||
nan "^2.3.2"
|
||||
nan "^2.10.0"
|
||||
node-gyp "^3.3.1"
|
||||
npmlog "^4.0.0"
|
||||
request "~2.79.0"
|
||||
@ -5170,8 +5191,8 @@ number-is-nan@^1.0.0:
|
||||
resolved "https://registry.yarnpkg.com/number-is-nan/-/number-is-nan-1.0.1.tgz#097b602b53422a522c1afb8790318336941a011d"
|
||||
|
||||
"nwmatcher@>= 1.3.9 < 2.0.0":
|
||||
version "1.4.3"
|
||||
resolved "https://registry.yarnpkg.com/nwmatcher/-/nwmatcher-1.4.3.tgz#64348e3b3d80f035b40ac11563d278f8b72db89c"
|
||||
version "1.4.4"
|
||||
resolved "https://registry.yarnpkg.com/nwmatcher/-/nwmatcher-1.4.4.tgz#2285631f34a95f0d0395cd900c96ed39b58f346e"
|
||||
|
||||
oauth-sign@~0.8.1, oauth-sign@~0.8.2:
|
||||
version "0.8.2"
|
||||
@ -5243,8 +5264,8 @@ onetime@^2.0.0:
|
||||
mimic-fn "^1.0.0"
|
||||
|
||||
opn@^5.1.0:
|
||||
version "5.2.0"
|
||||
resolved "https://registry.yarnpkg.com/opn/-/opn-5.2.0.tgz#71fdf934d6827d676cecbea1531f95d354641225"
|
||||
version "5.3.0"
|
||||
resolved "https://registry.yarnpkg.com/opn/-/opn-5.3.0.tgz#64871565c863875f052cfdf53d3e3cb5adb53b1c"
|
||||
dependencies:
|
||||
is-wsl "^1.1.0"
|
||||
|
||||
@ -5625,8 +5646,8 @@ postcss-load-plugins@^2.3.0:
|
||||
object-assign "^4.1.0"
|
||||
|
||||
postcss-loader@^2.0.10:
|
||||
version "2.1.1"
|
||||
resolved "https://registry.yarnpkg.com/postcss-loader/-/postcss-loader-2.1.1.tgz#208935af3b1d65e1abb1a870a912dd12e7b36895"
|
||||
version "2.1.3"
|
||||
resolved "https://registry.yarnpkg.com/postcss-loader/-/postcss-loader-2.1.3.tgz#eb210da734e475a244f76ccd61f9860f5bb3ee09"
|
||||
dependencies:
|
||||
loader-utils "^1.1.0"
|
||||
postcss "^6.0.0"
|
||||
@ -5648,12 +5669,12 @@ postcss-value-parser@^3.2.3:
|
||||
resolved "https://registry.yarnpkg.com/postcss-value-parser/-/postcss-value-parser-3.3.0.tgz#87f38f9f18f774a4ab4c8a232f5c5ce8872a9d15"
|
||||
|
||||
postcss@^6.0.0, postcss@^6.0.1, postcss@^6.0.16, postcss@^6.0.17, postcss@^6.0.2, postcss@^6.x:
|
||||
version "6.0.19"
|
||||
resolved "https://registry.yarnpkg.com/postcss/-/postcss-6.0.19.tgz#76a78386f670b9d9494a655bf23ac012effd1555"
|
||||
version "6.0.21"
|
||||
resolved "https://registry.yarnpkg.com/postcss/-/postcss-6.0.21.tgz#8265662694eddf9e9a5960db6da33c39e4cd069d"
|
||||
dependencies:
|
||||
chalk "^2.3.1"
|
||||
chalk "^2.3.2"
|
||||
source-map "^0.6.1"
|
||||
supports-color "^5.2.0"
|
||||
supports-color "^5.3.0"
|
||||
|
||||
precise-commits@1.0.0:
|
||||
version "1.0.0"
|
||||
@ -5790,6 +5811,10 @@ punycode@1.4.1, punycode@^1.2.4, punycode@^1.3.2, punycode@^1.4.1:
|
||||
version "1.4.1"
|
||||
resolved "https://registry.yarnpkg.com/punycode/-/punycode-1.4.1.tgz#c0d5a63b2718800ad8e1eb0fa5269c84dd41845e"
|
||||
|
||||
punycode@^2.1.0:
|
||||
version "2.1.0"
|
||||
resolved "https://registry.yarnpkg.com/punycode/-/punycode-2.1.0.tgz#5f863edc89b96db09074bad7947bf09056ca4e7d"
|
||||
|
||||
q@~1.4.0:
|
||||
version "1.4.1"
|
||||
resolved "https://registry.yarnpkg.com/q/-/q-1.4.1.tgz#55705bcd93c5f3673530c2c2cbc0c2b3addc286e"
|
||||
@ -5868,8 +5893,8 @@ raw-loader@^0.5.1:
|
||||
resolved "https://registry.yarnpkg.com/raw-loader/-/raw-loader-0.5.1.tgz#0c3d0beaed8a01c966d9787bf778281252a979aa"
|
||||
|
||||
rc@^1.0.1, rc@^1.1.6, rc@^1.1.7:
|
||||
version "1.2.5"
|
||||
resolved "https://registry.yarnpkg.com/rc/-/rc-1.2.5.tgz#275cd687f6e3b36cc756baa26dfee80a790301fd"
|
||||
version "1.2.6"
|
||||
resolved "https://registry.yarnpkg.com/rc/-/rc-1.2.6.tgz#eb18989c6d4f4f162c399f79ddd29f3835568092"
|
||||
dependencies:
|
||||
deep-extend "~0.4.0"
|
||||
ini "~1.3.0"
|
||||
@ -6229,8 +6254,8 @@ resolve@1.1.7:
|
||||
resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.1.7.tgz#203114d82ad2c5ed9e8e0411b3932875e889e97b"
|
||||
|
||||
resolve@^1.1.3, resolve@^1.1.4, resolve@^1.1.6, resolve@^1.1.7, resolve@^1.3.2, resolve@^1.4.0:
|
||||
version "1.5.0"
|
||||
resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.5.0.tgz#1f09acce796c9a762579f31b2c1cc4c3cddf9f36"
|
||||
version "1.6.0"
|
||||
resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.6.0.tgz#0fbd21278b27b4004481c395349e7aba60a9ff5c"
|
||||
dependencies:
|
||||
path-parse "^1.0.5"
|
||||
|
||||
@ -6293,8 +6318,8 @@ rollup-plugin-license@^0.6.0:
|
||||
moment "2.21.0"
|
||||
|
||||
rollup-plugin-node-resolve@^3.0.0:
|
||||
version "3.2.0"
|
||||
resolved "https://registry.yarnpkg.com/rollup-plugin-node-resolve/-/rollup-plugin-node-resolve-3.2.0.tgz#31534952f3ab21f9473c1d092be7ed43937ea4d4"
|
||||
version "3.3.0"
|
||||
resolved "https://registry.yarnpkg.com/rollup-plugin-node-resolve/-/rollup-plugin-node-resolve-3.3.0.tgz#c26d110a36812cbefa7ce117cadcd3439aa1c713"
|
||||
dependencies:
|
||||
builtin-modules "^2.0.0"
|
||||
is-module "^1.0.0"
|
||||
@ -6318,8 +6343,8 @@ run-queue@^1.0.0, run-queue@^1.0.3:
|
||||
aproba "^1.1.1"
|
||||
|
||||
rxjs@^5.5.0, rxjs@^5.5.6:
|
||||
version "5.5.6"
|
||||
resolved "https://registry.yarnpkg.com/rxjs/-/rxjs-5.5.6.tgz#e31fb96d6fd2ff1fd84bcea8ae9c02d007179c02"
|
||||
version "5.5.8"
|
||||
resolved "https://registry.yarnpkg.com/rxjs/-/rxjs-5.5.8.tgz#b2b0809a57614ad6254c03d7446dea0d83ca3791"
|
||||
dependencies:
|
||||
symbol-observable "1.0.1"
|
||||
|
||||
@ -6521,8 +6546,8 @@ setprototypeof@1.1.0:
|
||||
resolved "https://registry.yarnpkg.com/setprototypeof/-/setprototypeof-1.1.0.tgz#d0bd85536887b6fe7c0d818cb962d9d91c54e656"
|
||||
|
||||
sha.js@^2.4.0, sha.js@^2.4.8, sha.js@~2.4.4:
|
||||
version "2.4.10"
|
||||
resolved "https://registry.yarnpkg.com/sha.js/-/sha.js-2.4.10.tgz#b1fde5cd7d11a5626638a07c604ab909cfa31f9b"
|
||||
version "2.4.11"
|
||||
resolved "https://registry.yarnpkg.com/sha.js/-/sha.js-2.4.11.tgz#37a5cf0b81ecbc6943de109ba2960d1b26584ae7"
|
||||
dependencies:
|
||||
inherits "^2.0.1"
|
||||
safe-buffer "^5.0.1"
|
||||
@ -6750,8 +6775,8 @@ source-map-support@^0.4.1, source-map-support@^0.4.15:
|
||||
source-map "^0.5.6"
|
||||
|
||||
source-map-support@^0.5.0:
|
||||
version "0.5.3"
|
||||
resolved "https://registry.yarnpkg.com/source-map-support/-/source-map-support-0.5.3.tgz#2b3d5fff298cfa4d1afd7d4352d569e9a0158e76"
|
||||
version "0.5.4"
|
||||
resolved "https://registry.yarnpkg.com/source-map-support/-/source-map-support-0.5.4.tgz#54456efa89caa9270af7cd624cc2f123e51fbae8"
|
||||
dependencies:
|
||||
source-map "^0.6.0"
|
||||
|
||||
@ -6780,10 +6805,8 @@ source-map@^0.6.0, source-map@^0.6.1, source-map@~0.6.1:
|
||||
resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.6.1.tgz#74722af32e9614e9c287a8d0bbde48b5e2f1a263"
|
||||
|
||||
sourcemap-codec@^1.3.0:
|
||||
version "1.4.0"
|
||||
resolved "https://registry.yarnpkg.com/sourcemap-codec/-/sourcemap-codec-1.4.0.tgz#905439c4c65a4db421a2f2d06065bd8b55846a8e"
|
||||
dependencies:
|
||||
vlq "^1.0.0"
|
||||
version "1.4.1"
|
||||
resolved "https://registry.yarnpkg.com/sourcemap-codec/-/sourcemap-codec-1.4.1.tgz#c8fd92d91889e902a07aee392bdd2c5863958ba2"
|
||||
|
||||
spdx-correct@^3.0.0:
|
||||
version "3.0.0"
|
||||
@ -6808,8 +6831,8 @@ spdx-license-ids@^3.0.0:
|
||||
resolved "https://registry.yarnpkg.com/spdx-license-ids/-/spdx-license-ids-3.0.0.tgz#7a7cd28470cc6d3a1cfe6d66886f6bc430d3ac87"
|
||||
|
||||
spdy-transport@^2.0.18:
|
||||
version "2.0.20"
|
||||
resolved "https://registry.yarnpkg.com/spdy-transport/-/spdy-transport-2.0.20.tgz#735e72054c486b2354fe89e702256004a39ace4d"
|
||||
version "2.1.0"
|
||||
resolved "https://registry.yarnpkg.com/spdy-transport/-/spdy-transport-2.1.0.tgz#4bbb15aaffed0beefdd56ad61dbdc8ba3e2cb7a1"
|
||||
dependencies:
|
||||
debug "^2.6.8"
|
||||
detect-node "^2.0.3"
|
||||
@ -6847,8 +6870,8 @@ sprintf-js@~1.0.2:
|
||||
resolved "https://registry.yarnpkg.com/sprintf-js/-/sprintf-js-1.0.3.tgz#04e6926f662895354f3dd015203633b857297e2c"
|
||||
|
||||
sshpk@^1.7.0:
|
||||
version "1.13.1"
|
||||
resolved "https://registry.yarnpkg.com/sshpk/-/sshpk-1.13.1.tgz#512df6da6287144316dc4c18fe1cf1d940739be3"
|
||||
version "1.14.1"
|
||||
resolved "https://registry.yarnpkg.com/sshpk/-/sshpk-1.14.1.tgz#130f5975eddad963f1d56f92b9ac6c51fa9f83eb"
|
||||
dependencies:
|
||||
asn1 "~0.2.3"
|
||||
assert-plus "^1.0.0"
|
||||
@ -6861,8 +6884,8 @@ sshpk@^1.7.0:
|
||||
tweetnacl "~0.14.0"
|
||||
|
||||
ssri@^5.2.4:
|
||||
version "5.2.4"
|
||||
resolved "https://registry.yarnpkg.com/ssri/-/ssri-5.2.4.tgz#9985e14041e65fc397af96542be35724ac11da52"
|
||||
version "5.3.0"
|
||||
resolved "https://registry.yarnpkg.com/ssri/-/ssri-5.3.0.tgz#ba3872c9c6d33a0704a7d71ff045e5ec48999d06"
|
||||
dependencies:
|
||||
safe-buffer "^5.1.1"
|
||||
|
||||
@ -6873,14 +6896,18 @@ static-extend@^0.1.1:
|
||||
define-property "^0.2.5"
|
||||
object-copy "^0.1.0"
|
||||
|
||||
"statuses@>= 1.3.1 < 2", statuses@~1.4.0:
|
||||
version "1.4.0"
|
||||
resolved "https://registry.yarnpkg.com/statuses/-/statuses-1.4.0.tgz#bb73d446da2796106efcc1b601a253d6c46bd087"
|
||||
"statuses@>= 1.3.1 < 2", "statuses@>= 1.4.0 < 2":
|
||||
version "1.5.0"
|
||||
resolved "https://registry.yarnpkg.com/statuses/-/statuses-1.5.0.tgz#161c7dac177659fd9811f43771fa99381478628c"
|
||||
|
||||
statuses@~1.3.1:
|
||||
version "1.3.1"
|
||||
resolved "https://registry.yarnpkg.com/statuses/-/statuses-1.3.1.tgz#faf51b9eb74aaef3b3acf4ad5f61abf24cb7b93e"
|
||||
|
||||
statuses@~1.4.0:
|
||||
version "1.4.0"
|
||||
resolved "https://registry.yarnpkg.com/statuses/-/statuses-1.4.0.tgz#bb73d446da2796106efcc1b601a253d6c46bd087"
|
||||
|
||||
stdout-stream@^1.4.0:
|
||||
version "1.4.0"
|
||||
resolved "https://registry.yarnpkg.com/stdout-stream/-/stdout-stream-1.4.0.tgz#a2c7c8587e54d9427ea9edb3ac3f2cd522df378b"
|
||||
@ -6915,8 +6942,8 @@ stream-each@^1.1.0:
|
||||
stream-shift "^1.0.0"
|
||||
|
||||
stream-http@^2.0.0, stream-http@^2.7.2:
|
||||
version "2.8.0"
|
||||
resolved "https://registry.yarnpkg.com/stream-http/-/stream-http-2.8.0.tgz#fd86546dac9b1c91aff8fc5d287b98fafb41bc10"
|
||||
version "2.8.1"
|
||||
resolved "https://registry.yarnpkg.com/stream-http/-/stream-http-2.8.1.tgz#d0441be1a457a73a733a8a7b53570bebd9ef66a4"
|
||||
dependencies:
|
||||
builtin-status-codes "^3.0.0"
|
||||
inherits "^2.0.1"
|
||||
@ -6973,9 +7000,9 @@ string.prototype.padend@^3.0.0:
|
||||
es-abstract "^1.4.3"
|
||||
function-bind "^1.0.2"
|
||||
|
||||
string_decoder@^1.0.0, string_decoder@~1.0.0, string_decoder@~1.0.3:
|
||||
version "1.0.3"
|
||||
resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-1.0.3.tgz#0fc67d7c141825de94282dd536bec6b9bce860ab"
|
||||
string_decoder@^1.0.0:
|
||||
version "1.1.1"
|
||||
resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-1.1.1.tgz#9cf1611ba62685d7030ae9e4ba34149c3af03fc8"
|
||||
dependencies:
|
||||
safe-buffer "~5.1.0"
|
||||
|
||||
@ -6983,6 +7010,12 @@ string_decoder@~0.10.x:
|
||||
version "0.10.31"
|
||||
resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-0.10.31.tgz#62e203bc41766c6c28c9fc84301dab1c5310fa94"
|
||||
|
||||
string_decoder@~1.0.0, string_decoder@~1.0.3:
|
||||
version "1.0.3"
|
||||
resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-1.0.3.tgz#0fc67d7c141825de94282dd536bec6b9bce860ab"
|
||||
dependencies:
|
||||
safe-buffer "~5.1.0"
|
||||
|
||||
stringstream@~0.0.4, stringstream@~0.0.5:
|
||||
version "0.0.5"
|
||||
resolved "https://registry.yarnpkg.com/stringstream/-/stringstream-0.0.5.tgz#4e484cd4de5a0bbbee18e46307710a8a81621878"
|
||||
@ -7075,7 +7108,7 @@ supports-color@^4.0.0, supports-color@^4.2.1:
|
||||
dependencies:
|
||||
has-flag "^2.0.0"
|
||||
|
||||
supports-color@^5.1.0, supports-color@^5.2.0, supports-color@^5.3.0:
|
||||
supports-color@^5.1.0, supports-color@^5.3.0:
|
||||
version "5.3.0"
|
||||
resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-5.3.0.tgz#5b24ac15db80fa927cf5227a4a33fd3c4c7676c0"
|
||||
dependencies:
|
||||
@ -7218,7 +7251,7 @@ to-regex-range@^2.1.0:
|
||||
is-number "^3.0.0"
|
||||
repeat-string "^1.6.1"
|
||||
|
||||
to-regex@^3.0.1:
|
||||
to-regex@^3.0.1, to-regex@^3.0.2:
|
||||
version "3.0.2"
|
||||
resolved "https://registry.yarnpkg.com/to-regex/-/to-regex-3.0.2.tgz#13cfdd9b336552f30b51f33a8ae1b42a7a7599ce"
|
||||
dependencies:
|
||||
@ -7294,8 +7327,8 @@ tsscmp@~1.0.0:
|
||||
resolved "https://registry.yarnpkg.com/tsscmp/-/tsscmp-1.0.5.tgz#7dc4a33af71581ab4337da91d85ca5427ebd9a97"
|
||||
|
||||
tsutils@^2.12.1:
|
||||
version "2.22.2"
|
||||
resolved "https://registry.yarnpkg.com/tsutils/-/tsutils-2.22.2.tgz#0b9f3d87aa3eb95bd32d26ce2b88aa329a657951"
|
||||
version "2.25.0"
|
||||
resolved "https://registry.yarnpkg.com/tsutils/-/tsutils-2.25.0.tgz#14d616ef59224a3c9fb7eb483e1c182b6665ae5e"
|
||||
dependencies:
|
||||
tslib "^1.8.1"
|
||||
|
||||
@ -7350,10 +7383,10 @@ uglify-es@^3.3.4:
|
||||
source-map "~0.6.1"
|
||||
|
||||
uglify-js@3.3.x, uglify-js@^3.0.7:
|
||||
version "3.3.14"
|
||||
resolved "https://registry.yarnpkg.com/uglify-js/-/uglify-js-3.3.14.tgz#d3d84d18722ff342fa96029cca71c67367700079"
|
||||
version "3.3.16"
|
||||
resolved "https://registry.yarnpkg.com/uglify-js/-/uglify-js-3.3.16.tgz#23ba13efa27aa00885be7417819e8a9787f94028"
|
||||
dependencies:
|
||||
commander "~2.14.1"
|
||||
commander "~2.15.0"
|
||||
source-map "~0.6.1"
|
||||
|
||||
uglify-js@^2.6, uglify-js@^2.8.29:
|
||||
@ -7378,8 +7411,8 @@ uglifyjs-webpack-plugin@^0.4.6:
|
||||
webpack-sources "^1.0.1"
|
||||
|
||||
uglifyjs-webpack-plugin@^1.1.8:
|
||||
version "1.2.3"
|
||||
resolved "https://registry.yarnpkg.com/uglifyjs-webpack-plugin/-/uglifyjs-webpack-plugin-1.2.3.tgz#bf23197b37a8fc953fecfbcbab66e506f9a0ae72"
|
||||
version "1.2.4"
|
||||
resolved "https://registry.yarnpkg.com/uglifyjs-webpack-plugin/-/uglifyjs-webpack-plugin-1.2.4.tgz#5eec941b2e9b8538be0a20fc6eda25b14c7c1043"
|
||||
dependencies:
|
||||
cacache "^10.0.4"
|
||||
find-cache-dir "^1.0.0"
|
||||
@ -7399,8 +7432,8 @@ ultron@~1.1.0:
|
||||
resolved "https://registry.yarnpkg.com/ultron/-/ultron-1.1.1.tgz#9fe1536a10a664a65266a1e3ccf85fd36302bc9c"
|
||||
|
||||
umd@^3.0.0:
|
||||
version "3.0.2"
|
||||
resolved "https://registry.yarnpkg.com/umd/-/umd-3.0.2.tgz#95bdbc6d3983050df600431f44e5faeb4b7b3d45"
|
||||
version "3.0.3"
|
||||
resolved "https://registry.yarnpkg.com/umd/-/umd-3.0.3.tgz#aa9fe653c42b9097678489c01000acb69f0b26cf"
|
||||
|
||||
underscore@~1.7.0:
|
||||
version "1.7.0"
|
||||
@ -7457,13 +7490,14 @@ upath@^1.0.0:
|
||||
resolved "https://registry.yarnpkg.com/upath/-/upath-1.0.4.tgz#ee2321ba0a786c50973db043a50b7bcba822361d"
|
||||
|
||||
update-notifier@^2.3.0:
|
||||
version "2.3.0"
|
||||
resolved "https://registry.yarnpkg.com/update-notifier/-/update-notifier-2.3.0.tgz#4e8827a6bb915140ab093559d7014e3ebb837451"
|
||||
version "2.4.0"
|
||||
resolved "https://registry.yarnpkg.com/update-notifier/-/update-notifier-2.4.0.tgz#f9b4c700fbfd4ec12c811587258777d563d8c866"
|
||||
dependencies:
|
||||
boxen "^1.2.1"
|
||||
chalk "^2.0.1"
|
||||
configstore "^3.0.0"
|
||||
import-lazy "^2.1.0"
|
||||
is-ci "^1.0.10"
|
||||
is-installed-globally "^0.1.0"
|
||||
is-npm "^1.0.0"
|
||||
latest-version "^3.0.0"
|
||||
@ -7474,6 +7508,12 @@ upper-case@^1.1.1:
|
||||
version "1.1.3"
|
||||
resolved "https://registry.yarnpkg.com/upper-case/-/upper-case-1.1.3.tgz#f6b4501c2ec4cdd26ba78be7222961de77621598"
|
||||
|
||||
uri-js@^3.0.2:
|
||||
version "3.0.2"
|
||||
resolved "https://registry.yarnpkg.com/uri-js/-/uri-js-3.0.2.tgz#f90b858507f81dea4dcfbb3c4c3dbfa2b557faaa"
|
||||
dependencies:
|
||||
punycode "^2.1.0"
|
||||
|
||||
urix@^0.1.0:
|
||||
version "0.1.0"
|
||||
resolved "https://registry.yarnpkg.com/urix/-/urix-0.1.0.tgz#da937f7a62e21fec1fd18d49b35c2935067a6c72"
|
||||
@ -7575,14 +7615,10 @@ verror@1.10.0:
|
||||
core-util-is "1.0.2"
|
||||
extsprintf "^1.2.0"
|
||||
|
||||
vlq@^0.2.1:
|
||||
vlq@^0.2.1, vlq@^0.2.2:
|
||||
version "0.2.3"
|
||||
resolved "https://registry.yarnpkg.com/vlq/-/vlq-0.2.3.tgz#8f3e4328cf63b1540c0d67e1b2778386f8975b26"
|
||||
|
||||
vlq@^1.0.0:
|
||||
version "1.0.0"
|
||||
resolved "https://registry.yarnpkg.com/vlq/-/vlq-1.0.0.tgz#8101be90843422954c2b13eb27f2f3122bdcc806"
|
||||
|
||||
vm-browserify@0.0.4, vm-browserify@~0.0.1:
|
||||
version "0.0.4"
|
||||
resolved "https://registry.yarnpkg.com/vm-browserify/-/vm-browserify-0.0.4.tgz#5d7ea45bbef9e4a6ff65f95438e0a87c357d5a73"
|
||||
@ -7961,5 +7997,5 @@ yeast@0.1.2:
|
||||
resolved "https://registry.yarnpkg.com/yeast/-/yeast-0.1.2.tgz#008e06d8094320c372dbc2f8ed76a0ca6c8ac419"
|
||||
|
||||
zone.js@^0.8.19:
|
||||
version "0.8.20"
|
||||
resolved "https://registry.yarnpkg.com/zone.js/-/zone.js-0.8.20.tgz#a218c48db09464b19ff6fc8f0d4bb5b1046e185d"
|
||||
version "0.8.21"
|
||||
resolved "https://registry.yarnpkg.com/zone.js/-/zone.js-0.8.21.tgz#8c0e8e361bd326ee1474e4f96e17d5ef99bec4b2"
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user