Skip to content

Commit

Permalink
feat(lib): Introduce @ngrx/schematics
Browse files Browse the repository at this point in the history
Closes #53
  • Loading branch information
brandonroberts committed Dec 5, 2017
1 parent 2fbcd24 commit ebccc9e
Show file tree
Hide file tree
Showing 78 changed files with 4,110 additions and 67 deletions.
2 changes: 2 additions & 0 deletions .prettierignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
/dist
/modules/schematics/src/*/files/*
1 change: 1 addition & 0 deletions build/builder.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ export default createBuilder([
['Cleaning TypeScript files', tasks.cleanTypeScriptFiles],
['Removing remaining sourcemap files', tasks.removeRemainingSourceMapFiles],
['Copying type definition files', tasks.copyTypeDefinitionFiles],
['Copying schematic files', tasks.copySchematicFiles],
['Minifying UMD bundles', tasks.minifyUmdBundles],
['Copying documents', tasks.copyDocs],
['Copying package.json files', tasks.copyPackageJsonFiles],
Expand Down
12 changes: 12 additions & 0 deletions build/config.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
export interface PackageDescription {
name: string;
hasTestingModule: boolean;
bundle: boolean;
}

export interface Config {
Expand All @@ -12,25 +13,36 @@ export const packages: PackageDescription[] = [
{
name: 'store',
hasTestingModule: false,
bundle: true,
},
{
name: 'effects',
hasTestingModule: true,
bundle: true,
},
{
name: 'router-store',
hasTestingModule: false,
bundle: true,
},
{
name: 'store-devtools',
hasTestingModule: false,
bundle: true,
},
{
name: 'entity',
hasTestingModule: false,
bundle: true,
},
{
name: 'codegen',
hasTestingModule: false,
bundle: true,
},
{
name: 'schematics',
hasTestingModule: false,
bundle: false,
},
];
48 changes: 46 additions & 2 deletions build/tasks.ts
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,9 @@ async function _compilePackagesWithNgc(pkg: string) {
: [pkg, 'index'];

const entryTypeDefinition = `export * from './${exportPath}/${moduleName}';`;
const entryMetadata = `{"__symbolic":"module","version":3,"metadata":{},"exports":[{"from":"./${pkg}/index"}]}`;
const entryMetadata = `{"__symbolic":"module","version":3,"metadata":{},"exports":[{"from":"./${
pkg
}/index"}]}`;

await Promise.all([
util.writeFile(`./dist/packages/${pkg}.d.ts`, entryTypeDefinition),
Expand All @@ -57,6 +59,9 @@ export async function bundleFesms(config: Config) {
const pkgs = util.getAllPackages(config);

await mapAsync(pkgs, async pkg => {
if (!util.shouldBundle(config, pkg)) {
return;
}
const topLevelName = util.getTopLevelName(pkg);

await util.exec('rollup', [
Expand All @@ -79,6 +84,9 @@ export async function downLevelFesmsToES5(config: Config) {
const tscArgs = ['--target es5', '--module es2015', '--noLib', '--sourceMap'];

await mapAsync(packages, async pkg => {
if (!util.shouldBundle(config, pkg)) {
return;
}
const topLevelName = util.getTopLevelName(pkg);

const file = `./dist/${topLevelName}/${config.scope}/${pkg}.js`;
Expand All @@ -98,6 +106,9 @@ export async function downLevelFesmsToES5(config: Config) {
*/
export async function createUmdBundles(config: Config) {
await mapAsync(util.getAllPackages(config), async pkg => {
if (!util.shouldBundle(config, pkg)) {
return;
}
const topLevelName = util.getTopLevelName(pkg);
const destinationName = util.getDestinationName(pkg);

Expand Down Expand Up @@ -128,6 +139,9 @@ export async function cleanTypeScriptFiles(config: Config) {
*/
export async function renamePackageEntryFiles(config: Config) {
await mapAsync(util.getAllPackages(config), async pkg => {
if (!util.shouldBundle(config, pkg)) {
return;
}
const bottomLevelName = util.getBottomLevelName(pkg);

const files = await util.getListOfFiles(`./dist/packages/${pkg}/index.**`);
Expand Down Expand Up @@ -177,6 +191,9 @@ export async function minifyUmdBundles(config: Config) {
const uglifyArgs = ['-c', '-m', '--comments'];

await mapAsync(util.getAllPackages(config), async pkg => {
if (!util.shouldBundle(config, pkg)) {
return;
}
const topLevelName = util.getTopLevelName(pkg);
const destinationName = util.getDestinationName(pkg);
const file = `./dist/${topLevelName}/bundles/${destinationName}.umd.js`;
Expand All @@ -186,7 +203,9 @@ export async function minifyUmdBundles(config: Config) {
file,
...uglifyArgs,
`-o ${out}`,
`--source-map "filename='${out}.map' includeSources='${file}', content='${file}.map'"`,
`--source-map "filename='${out}.map' includeSources='${file}', content='${
file
}.map'"`,
]);
});
}
Expand Down Expand Up @@ -273,3 +292,28 @@ export function mapAsync<T>(
) {
return Promise.all(list.map(mapFn));
}

/**
* Copy schematics files
*/
export async function copySchematicFiles(config: Config) {
const packages = util
.getTopLevelPackages(config)
.filter(pkg => !util.shouldBundle(config, pkg));

const collectionFiles = await util.getListOfFiles(
`./modules/?(${packages.join('|')})/collection.json`
);
const schemaFiles = await util.getListOfFiles(
`./modules/?(${packages.join('|')})/src/*/schema.*`
);
const templateFiles = await util.getListOfFiles(
`./modules/?(${packages.join('|')})/src/*/files/*`
);
const files = [...collectionFiles, ...schemaFiles, ...templateFiles];

await mapAsync(files, async file => {
const target = file.replace('modules/', 'dist/');
await util.copy(file, target);
});
}
15 changes: 12 additions & 3 deletions build/util.ts
Original file line number Diff line number Diff line change
Expand Up @@ -134,9 +134,12 @@ export function createBuilder(tasks: TaskDef[]) {
}

export function flatMap<K, J>(list: K[], mapFn: (item: K) => J[]): J[] {
return list.reduce(function(newList, nextItem) {
return [...newList, ...mapFn(nextItem)];
}, [] as J[]);
return list.reduce(
function(newList, nextItem) {
return [...newList, ...mapFn(nextItem)];
},
[] as J[]
);
}

export function getTopLevelPackages(config: Config) {
Expand Down Expand Up @@ -178,3 +181,9 @@ export function getBottomLevelName(packageName: string) {
export function baseDir(...dirs: string[]): string {
return `"${path.resolve(__dirname, '../', ...dirs)}"`;
}

export function shouldBundle(config: Config, packageName: string) {
const pkg = config.packages.find(pkg => pkg.name === packageName);

return pkg ? pkg.bundle : false;
}
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ describe('Login Page', () => {
* HTML.
*
* We can also use this as a validation tool against changes
* to the component's template against the currently stored
* to the component's template against the currently stored
* snapshot.
*/
expect(fixture).toMatchSnapshot();
Expand Down
8 changes: 4 additions & 4 deletions example-app/app/books/effects/book.ts
Original file line number Diff line number Diff line change
Expand Up @@ -61,10 +61,10 @@ export class BookEffects {
@Inject(SEARCH_DEBOUNCE)
private debounce: number,
/**
* You inject an optional Scheduler that will be undefined
* in normal application usage, but its injected here so that you can mock out
* during testing using the RxJS TestScheduler for simulating passages of time.
*/
* You inject an optional Scheduler that will be undefined
* in normal application usage, but its injected here so that you can mock out
* during testing using the RxJS TestScheduler for simulating passages of time.
*/
@Optional()
@Inject(SEARCH_SCHEDULER)
private scheduler: Scheduler
Expand Down
4 changes: 2 additions & 2 deletions example-app/app/books/reducers/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ export interface BooksState {
}

export interface State extends fromRoot.State {
'books': BooksState;
books: BooksState;
}

export const reducers = {
Expand Down Expand Up @@ -39,7 +39,7 @@ export const reducers = {
/**
* The createFeatureSelector function selects a piece of state from the root of the state object.
* This is used for selecting feature states that are loaded eagerly or lazily.
*/
*/
export const getBooksState = createFeatureSelector<BooksState>('books');

/**
Expand Down
2 changes: 1 addition & 1 deletion modules/codegen/src/metadata/get-type.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ export function getType(
}

return ts.isLiteralTypeNode(typeProperty.type as any)
? typeProperty.type as any
? (typeProperty.type as any)
: undefined;

// return !!typeProperty && ts.isLiteralTypeNode(typeProperty.type) ? typeProperty.type : undefined;
Expand Down
4 changes: 2 additions & 2 deletions modules/codegen/src/metadata/is-action-descendent.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,9 @@ export function isActionDescendent(
return heritageClauses.some(clause => {
/**
* TODO: This breaks if the interface looks like this:
*
*
* interface MyAction extends ngrx.Action { }
*
*
*/
return clause.types.some(type => type.expression.getText() === 'Action');
});
Expand Down
14 changes: 9 additions & 5 deletions modules/effects/spec/actions.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -63,11 +63,15 @@ describe('Actions', function() {
const actions = [ADD, ADD, SUBTRACT, ADD, SUBTRACT];
const expected = actions.filter(type => type === ADD);

actions$.ofType(ADD).map(update => update.type).toArray().subscribe({
next(actual) {
expect(actual).toEqual(expected);
},
});
actions$
.ofType(ADD)
.map(update => update.type)
.toArray()
.subscribe({
next(actual) {
expect(actual).toEqual(expected);
},
});

actions.forEach(action => dispatcher.next({ type: action }));
dispatcher.complete();
Expand Down
48 changes: 24 additions & 24 deletions modules/effects/src/effects_resolver.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,31 +14,31 @@ export function mergeEffects(
): Observable<EffectNotification> {
const sourceName = getSourceForInstance(sourceInstance).constructor.name;

const observables: Observable<any>[] = getSourceMetadata(
sourceInstance
).map(({ propertyName, dispatch }): Observable<EffectNotification> => {
const observable: Observable<any> =
typeof sourceInstance[propertyName] === 'function'
? sourceInstance[propertyName]()
: sourceInstance[propertyName];

if (dispatch === false) {
return ignoreElements.call(observable);
const observables: Observable<any>[] = getSourceMetadata(sourceInstance).map(
({ propertyName, dispatch }): Observable<EffectNotification> => {
const observable: Observable<any> =
typeof sourceInstance[propertyName] === 'function'
? sourceInstance[propertyName]()
: sourceInstance[propertyName];

if (dispatch === false) {
return ignoreElements.call(observable);
}

const materialized$ = materialize.call(observable);

return map.call(
materialized$,
(notification: Notification<Action>): EffectNotification => ({
effect: sourceInstance[propertyName],
notification,
propertyName,
sourceName,
sourceInstance,
})
);
}

const materialized$ = materialize.call(observable);

return map.call(
materialized$,
(notification: Notification<Action>): EffectNotification => ({
effect: sourceInstance[propertyName],
notification,
propertyName,
sourceName,
sourceInstance,
})
);
});
);

return merge(...observables);
}
Expand Down
6 changes: 6 additions & 0 deletions modules/schematics/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
@ngrx/schematics
=======

The sources for this package are in the main [ngrx/platform](https://github.com/ngrx/platform) repo. Please file issues and pull requests against that repo.

License: MIT
Loading

0 comments on commit ebccc9e

Please sign in to comment.