-
-
Notifications
You must be signed in to change notification settings - Fork 2k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat: add @ngrx/component package to platform
- Loading branch information
1 parent
3997cc2
commit 4126aee
Showing
24 changed files
with
776 additions
and
1 deletion.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,31 @@ | ||
package(default_visibility = ["//visibility:public"]) | ||
|
||
load("//tools:defaults.bzl", "ng_module", "ng_package") | ||
|
||
ng_module( | ||
name = "component", | ||
srcs = glob([ | ||
"*.ts", | ||
"src/**/*.ts", | ||
]), | ||
module_name = "@ngrx/component", | ||
deps = [ | ||
"@npm//@angular/common", | ||
"@npm//@angular/core", | ||
"@npm//rxjs", | ||
"@npm//typescript", | ||
], | ||
) | ||
|
||
ng_package( | ||
name = "npm_package", | ||
srcs = glob(["**/*.externs.js"]) + [ | ||
"package.json", | ||
], | ||
entry_point = "modules/component/index.js", | ||
packages = [ | ||
], | ||
deps = [ | ||
":component", | ||
], | ||
) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
# Change Log | ||
|
||
See [CHANGELOG.md](https://github.com/ngrx/platform/blob/master/CHANGELOG.md) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
# @ngrx/store | ||
|
||
The sources for this package are in the main [NgRx](https://github.com/ngrx/platform) repo. Please file issues and pull requests against that repo. | ||
|
||
License: MIT |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
/** | ||
* DO NOT EDIT | ||
* | ||
* This file is automatically generated at build | ||
*/ | ||
|
||
export * from './public_api'; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,28 @@ | ||
{ | ||
"name": "@ngrx/component", | ||
"version": "0.8.2-beta.0", | ||
"description": "Reactive Extensions for Angular Components", | ||
"repository": { | ||
"type": "git", | ||
"url": "git+https://github.com/ngrx/platform.git" | ||
}, | ||
"keywords": [ | ||
"RxJS", | ||
"Angular", | ||
"NgRx", | ||
"Components", | ||
"Angular CLI" | ||
], | ||
"author": "NgRx", | ||
"license": "MIT", | ||
"bugs": { | ||
"url": "https://github.com/ngrx/platform/issues" | ||
}, | ||
"homepage": "https://github.com/ngrx/platform#readme", | ||
"peerDependencies": { | ||
"@angular/common": "NG_VERSION", | ||
"@angular/core": "NG_VERSION", | ||
"rxjs": "RXJS_VERSION" | ||
}, | ||
"sideEffects": false | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
export * from './src/index'; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,15 @@ | ||
import { NgModule } from '@angular/core'; | ||
import { LetDirective } from './let/let.directive'; | ||
import { Async$Pipe } from './push$/async$.pipe'; | ||
import { Push$Pipe } from './push$/push$.pipe'; | ||
|
||
const DECLARATIONS = [LetDirective, Push$Pipe, Async$Pipe]; | ||
|
||
const EXPORTS = [DECLARATIONS]; | ||
|
||
@NgModule({ | ||
declarations: [DECLARATIONS], | ||
imports: [], | ||
exports: [EXPORTS], | ||
}) | ||
export class NgRxComponentModule {} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,39 @@ | ||
import { AsyncSubject, BehaviorSubject, ReplaySubject, Subject } from 'rxjs'; | ||
|
||
export type subjectFactory = () => Subject<any>; | ||
|
||
export function getSubjectFactory<T>(): subjectFactory { | ||
return () => new Subject<T>(); | ||
} | ||
|
||
export function behaviourSubjectFactory<T>(init: T): subjectFactory { | ||
return () => new BehaviorSubject(init); | ||
} | ||
|
||
export function getReplaySubjectFactory<T>(bufferSize = 1): subjectFactory { | ||
return () => new ReplaySubject<T>(bufferSize); | ||
} | ||
|
||
export function getAsyncSubjectFactory<T>(): subjectFactory { | ||
return () => new AsyncSubject<T>(); | ||
} | ||
|
||
export function getPropertySubject<T = any>( | ||
// tslint:disable-next-line | ||
objInstance: Object | any, | ||
property: PropertyKey, | ||
sFactory: () => Subject<T> = getReplaySubjectFactory(1), | ||
subProperty: PropertyKey = '' | ||
): Subject<T> { | ||
if (subProperty === '') { | ||
return objInstance[property] || (objInstance[property] = sFactory()); | ||
} else { | ||
if (!objInstance[property]) { | ||
objInstance[property] = {}; | ||
} | ||
return ( | ||
objInstance[property][subProperty] || | ||
(objInstance[property][subProperty] = sFactory()) | ||
); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
import { Type, ɵstringify as stringify } from '@angular/core'; | ||
|
||
export function invalidInputValueError(type: Type<any>, value: Object) { | ||
return Error( | ||
`invalidInputValueError: '${value}' for directive '${stringify(type)}'` | ||
); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
export const STATE_DEFAULT = undefined; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,142 @@ | ||
import { | ||
ɵComponentDef as ComponentDef, | ||
ɵNG_COMPONENT_DEF as NG_COMPONENT_DEF, | ||
Type, | ||
} from '@angular/core'; | ||
import { | ||
getPropertySubject, | ||
getReplaySubjectFactory, | ||
} from '../core/get-property-subject'; | ||
import { EMPTY, Observable, of, pipe, UnaryFunction } from 'rxjs'; | ||
import { catchError, take, takeUntil } from 'rxjs/operators'; | ||
|
||
export enum HookNames { | ||
afterContentChecked = 'afterContentChecked', | ||
afterContentInit = 'afterContentInit', | ||
afterViewChecked = 'afterViewChecked', | ||
afterViewInit = 'afterViewInit', | ||
doCheck = 'doCheck', | ||
onChanges = 'onChanges', | ||
onDestroy = 'onDestroy', | ||
onInit = 'onInit', | ||
} | ||
|
||
interface Hooks { | ||
afterContentChecked: string; | ||
afterContentInit: string; | ||
afterViewChecked: string; | ||
afterViewInit: string; | ||
doCheck: string; | ||
onChanges: string; | ||
onDestroy: string; | ||
onInit: string; | ||
} | ||
|
||
const hooksWrapped: { [x in keyof Hooks]: boolean } = { | ||
afterContentChecked: false, | ||
afterContentInit: false, | ||
afterViewChecked: false, | ||
afterViewInit: false, | ||
doCheck: false, | ||
onChanges: true, | ||
onDestroy: false, | ||
onInit: false, | ||
}; | ||
|
||
const singleShotOperators = ( | ||
destroy$: Observable<any> | ||
): UnaryFunction<any, any> => | ||
pipe( | ||
take(1), | ||
catchError(e => of()), | ||
takeUntil(destroy$) | ||
); | ||
const onGoingOperators = (destroy$: Observable<any>): UnaryFunction<any, any> => | ||
pipe( | ||
catchError(e => EMPTY), | ||
takeUntil(destroy$) | ||
); | ||
|
||
const getHooksOperatorsMap = ( | ||
destroy$: Observable<any> | ||
): { [x in keyof Hooks]: UnaryFunction<any, any> } => ({ | ||
afterContentChecked: singleShotOperators(destroy$), | ||
afterContentInit: singleShotOperators(destroy$), | ||
afterViewChecked: onGoingOperators(destroy$), | ||
afterViewInit: singleShotOperators(destroy$), | ||
doCheck: onGoingOperators(destroy$), | ||
onChanges: onGoingOperators(destroy$), | ||
onDestroy: pipe( | ||
catchError(e => of()), | ||
take(1) | ||
), | ||
onInit: singleShotOperators(destroy$), | ||
}); | ||
|
||
export function Hook$<T>(hookName: keyof Hooks): PropertyDecorator { | ||
return ( | ||
// tslint:disable-next-line | ||
component: Object, | ||
propertyKey: PropertyKey | ||
) => { | ||
const keyUniquePerPrototype = Symbol('@ngrx-hook$'); | ||
const subjectFactory = getReplaySubjectFactory(1); | ||
|
||
const cDef: ComponentDef<any> = (component as any).constructor[ | ||
NG_COMPONENT_DEF | ||
]; | ||
|
||
let target: any; | ||
let hook; | ||
let originalHook: any; | ||
|
||
if (cDef === undefined) { | ||
target = component; | ||
hook = getCompHookName(hookName); | ||
originalHook = target[hook]; | ||
} else { | ||
// @TODO I guess this is a miss conception that ngChanges is wrapped in a function. | ||
target = hooksWrapped[hookName] ? component : cDef; | ||
hook = hooksWrapped[hookName] ? getCompHookName(hookName) : hookName; | ||
originalHook = hooksWrapped[hookName] | ||
? (cDef as any)[hook] | ||
: (component as any)[hook]; | ||
} | ||
|
||
target[hook] = function(args: any) { | ||
getPropertySubject<T>( | ||
this, | ||
keyUniquePerPrototype, | ||
subjectFactory, | ||
hookName | ||
).next(args); | ||
// tslint:disable-next-line:no-unused-expression | ||
originalHook && originalHook.call(component, args); | ||
}; | ||
|
||
const propertyKeyDescriptor: TypedPropertyDescriptor<Observable<T>> = { | ||
get() { | ||
const destroy$ = getPropertySubject<T>( | ||
this, | ||
keyUniquePerPrototype, | ||
subjectFactory, | ||
HookNames.onDestroy | ||
).asObservable(); | ||
const hookOperators = getHooksOperatorsMap(destroy$)[hookName]; | ||
return getPropertySubject<T>( | ||
this, | ||
keyUniquePerPrototype, | ||
subjectFactory, | ||
hookName | ||
) | ||
.asObservable() | ||
.pipe(hookOperators); | ||
}, | ||
}; | ||
Object.defineProperty(target, propertyKey, propertyKeyDescriptor); | ||
}; | ||
} | ||
|
||
function getCompHookName(hookName: string): string { | ||
return 'ng' + hookName[0].toUpperCase() + hookName.slice(1); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
import { SimpleChanges } from '@angular/core'; | ||
import { pipe, UnaryFunction, Observable } from 'rxjs'; | ||
import { distinctUntilChanged, map } from 'rxjs/operators'; | ||
|
||
export function selectChange<T>( | ||
prop: string | ||
): UnaryFunction<Observable<SimpleChanges>, Observable<T>> { | ||
return pipe( | ||
map((change: SimpleChanges) => change[prop].currentValue), | ||
distinctUntilChanged() | ||
); | ||
} |
18 changes: 18 additions & 0 deletions
18
modules/component/src/host-listener$/host-listener$.decorator.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,18 @@ | ||
import { ElementRef } from '@angular/core'; | ||
import { fromEvent } from 'rxjs'; | ||
|
||
export function HostListener$<T>(eventName: string): PropertyDecorator { | ||
return ( | ||
// tslint:disable-next-line | ||
target: Object, | ||
propertyKey: string | symbol | ||
) => { | ||
Object.defineProperty(target, propertyKey, { | ||
get() { | ||
// @TODO investigate @ViewChild for usage | ||
const elementRef = this.injector.get(ElementRef); | ||
return fromEvent(elementRef.nativeElement, eventName); | ||
}, | ||
}); | ||
}; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
export { Hook$ } from './hook$/hook$.decorator'; | ||
export { selectChange } from './hook$/operators/selectChange'; | ||
export { HostListener$ } from './host-listener$/host-listener$.decorator'; | ||
export { Input$ } from './input$/input$.decorator'; | ||
export { LocalStateService } from './local-state/local-state'; | ||
export { selectSlice } from './local-state/operators/selectSlice'; | ||
export { Push$Pipe } from './push$/push$.pipe'; | ||
export { Async$Pipe } from './push$/async$.pipe'; | ||
export { detectChanges } from './push$/operators/detectChanges'; | ||
export { LetDirective } from './let/let.directive'; | ||
export { NgRxComponentModule } from './component.module'; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,36 @@ | ||
import { Observable } from 'rxjs'; | ||
import { | ||
getPropertySubject, | ||
getReplaySubjectFactory, | ||
} from '../core/get-property-subject'; | ||
|
||
export function Input$<T>(): PropertyDecorator { | ||
return ( | ||
// @TODO get better typing | ||
// tslint:disable-next-line | ||
component: Object, | ||
propertyKey: PropertyKey | ||
) => { | ||
const keyUniquePerPrototype = Symbol('@ngrx-Input$'); | ||
|
||
const propertyKeyDescriptor: TypedPropertyDescriptor<Observable<T>> = { | ||
set(newValue) { | ||
// @TODO: Get type of property instead of any | ||
getPropertySubject<any>( | ||
this, | ||
keyUniquePerPrototype, | ||
getReplaySubjectFactory(1) | ||
).next(newValue); | ||
}, | ||
get() { | ||
return getPropertySubject<any>( | ||
this, | ||
keyUniquePerPrototype, | ||
getReplaySubjectFactory(1) | ||
); | ||
}, | ||
}; | ||
|
||
Object.defineProperty(component, propertyKey, propertyKeyDescriptor); | ||
}; | ||
} |
Oops, something went wrong.