feat(pipes): changed .append to .extend
BREAKING CHANGE: Pipes.append has been renamed into Pipes.extend. Pipes.extend prepends pipe factories instead of appending them.
This commit is contained in:
parent
e94270946a
commit
4c8ea12903
@ -40,18 +40,18 @@ export class Pipes {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Takes a {@link Pipes} config object and returns a binding used to append the
|
* Takes a {@link Pipes} config object and returns a binding used to extend the
|
||||||
* provided config to an inherited {@link Pipes} instance and return a new
|
* inherited {@link Pipes} instance with the provided config and return a new
|
||||||
* {@link Pipes} instance.
|
* {@link Pipes} instance.
|
||||||
*
|
*
|
||||||
* If the provided config contains a key that is not yet present in the
|
* If the provided config contains a key that is not yet present in the
|
||||||
* inherited {@link Pipes}' config, a new {@link PipeFactory} list will be created
|
* inherited {@link Pipes}' config, a new {@link PipeFactory} list will be created
|
||||||
* for that key. Otherwise, the provided config will be merged with the inherited
|
* for that key. Otherwise, the provided config will be merged with the inherited
|
||||||
* {@link Pipes} instance by appending pipes to their respective keys, without mutating
|
* {@link Pipes} instance by prepending pipes to their respective keys, without mutating
|
||||||
* the inherited {@link Pipes}.
|
* the inherited {@link Pipes}.
|
||||||
*
|
*
|
||||||
* The following example shows how to append a new {@link PipeFactory} to the
|
* The following example shows how to extend an existing list of `async` factories
|
||||||
* existing list of `async` factories, which will only be applied to the injector
|
* with a new {@link PipeFactory}, which will only be applied to the injector
|
||||||
* for this component and its children. This step is all that's required to make a new
|
* for this component and its children. This step is all that's required to make a new
|
||||||
* pipe available to this component's template.
|
* pipe available to this component's template.
|
||||||
*
|
*
|
||||||
@ -60,44 +60,42 @@ export class Pipes {
|
|||||||
* ```
|
* ```
|
||||||
* @Component({
|
* @Component({
|
||||||
* viewInjector: [
|
* viewInjector: [
|
||||||
* Pipes.append({
|
* Pipes.extend({
|
||||||
* async: [newAsyncPipe]
|
* async: [newAsyncPipe]
|
||||||
* })
|
* })
|
||||||
* ]
|
* ]
|
||||||
* })
|
* })
|
||||||
* ```
|
* ```
|
||||||
*/
|
*/
|
||||||
static append(config): Binding {
|
static extend(config): Binding {
|
||||||
return new Binding(Pipes, {
|
return new Binding(Pipes, {
|
||||||
toFactory: (pipes: Pipes) => {
|
toFactory: (pipes: Pipes) => {
|
||||||
if (!isPresent(pipes)) {
|
if (isBlank(pipes)) {
|
||||||
// Typically would occur when calling Pipe.append inside of dependencies passed to
|
// Typically would occur when calling Pipe.extend inside of dependencies passed to
|
||||||
// bootstrap(), which would override default pipes instead of append.
|
// bootstrap(), which would override default pipes instead of extending them.
|
||||||
throw new BaseException('Cannot append to Pipes without a parent injector');
|
throw new BaseException('Cannot extend Pipes without a parent injector');
|
||||||
}
|
}
|
||||||
var mergedConfig: StringMap<string, PipeFactory[]> = <StringMap<string, PipeFactory[]>>{};
|
return Pipes.create(config, pipes);
|
||||||
|
|
||||||
// Manual deep copy of existing Pipes config,
|
|
||||||
// so that lists of PipeFactories don't get mutated.
|
|
||||||
StringMapWrapper.forEach(pipes.config, (v: PipeFactory[], k: string) => {
|
|
||||||
var localPipeList: PipeFactory[] = mergedConfig[k] = [];
|
|
||||||
v.forEach((p: PipeFactory) => { localPipeList.push(p); });
|
|
||||||
});
|
|
||||||
|
|
||||||
StringMapWrapper.forEach(config, (v: PipeFactory[], k: string) => {
|
|
||||||
if (isListLikeIterable(mergedConfig[k])) {
|
|
||||||
mergedConfig[k] = ListWrapper.concat(mergedConfig[k], config[k]);
|
|
||||||
} else {
|
|
||||||
mergedConfig[k] = config[k];
|
|
||||||
}
|
|
||||||
});
|
|
||||||
return new Pipes(mergedConfig);
|
|
||||||
},
|
},
|
||||||
// Dependency technically isn't optional, but we can provide a better error message this way.
|
// Dependency technically isn't optional, but we can provide a better error message this way.
|
||||||
deps: [[Pipes, new UnboundedMetadata(), new OptionalMetadata()]]
|
deps: [[Pipes, new UnboundedMetadata(), new OptionalMetadata()]]
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static create(config, pipes: Pipes = null): Pipes {
|
||||||
|
if (isPresent(pipes)) {
|
||||||
|
StringMapWrapper.forEach(pipes.config, (v: PipeFactory[], k: string) => {
|
||||||
|
if (StringMapWrapper.contains(config, k)) {
|
||||||
|
var configFactories: PipeFactory[] = config[k];
|
||||||
|
config[k] = configFactories.concat(v);
|
||||||
|
} else {
|
||||||
|
config[k] = ListWrapper.clone(v);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
return new Pipes(config);
|
||||||
|
}
|
||||||
|
|
||||||
private _getListOfFactories(type: string, obj: any): PipeFactory[] {
|
private _getListOfFactories(type: string, obj: any): PipeFactory[] {
|
||||||
var listOfFactories = this.config[type];
|
var listOfFactories = this.config[type];
|
||||||
if (isBlank(listOfFactories)) {
|
if (isBlank(listOfFactories)) {
|
||||||
|
@ -76,13 +76,47 @@ export function main() {
|
|||||||
.toThrowError(`Cannot find 'type' pipe supporting object 'some object'`);
|
.toThrowError(`Cannot find 'type' pipe supporting object 'some object'`);
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('.append()', () => {
|
describe('.create()', () => {
|
||||||
it('should create a factory that appends new pipes to old', () => {
|
it("should create a new Pipes object", () => {
|
||||||
firstPipeFactory.spy("supports").andReturn(false);
|
firstPipeFactory.spy("supports").andReturn(true);
|
||||||
|
firstPipeFactory.spy("create").andReturn(firstPipe);
|
||||||
|
|
||||||
|
var pipes = Pipes.create({'async': [firstPipeFactory]});
|
||||||
|
expect(pipes.get("async", "first")).toBe(firstPipe);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("should prepend passed it config in existing registry", () => {
|
||||||
|
firstPipeFactory.spy("supports").andReturn(true);
|
||||||
secondPipeFactory.spy("supports").andReturn(true);
|
secondPipeFactory.spy("supports").andReturn(true);
|
||||||
secondPipeFactory.spy("create").andReturn(secondPipe);
|
secondPipeFactory.spy("create").andReturn(secondPipe);
|
||||||
|
|
||||||
|
var pipes1 = Pipes.create({'async': [firstPipeFactory]});
|
||||||
|
var pipes2 = Pipes.create({'async': [secondPipeFactory]}, pipes1);
|
||||||
|
|
||||||
|
expect(pipes2.get("async", "first")).toBe(secondPipe);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("should use inherited pipes when no overrides support the provided object", () => {
|
||||||
|
firstPipeFactory.spy("supports").andReturn(true);
|
||||||
|
firstPipeFactory.spy("create").andReturn(firstPipe);
|
||||||
|
secondPipeFactory.spy("supports").andReturn(false);
|
||||||
|
|
||||||
|
var pipes1 = Pipes.create({'async': [firstPipeFactory], 'date': [firstPipeFactory]});
|
||||||
|
var pipes2 = Pipes.create({'async': [secondPipeFactory]}, pipes1);
|
||||||
|
|
||||||
|
expect(pipes2.get("async", "first")).toBe(firstPipe);
|
||||||
|
expect(pipes2.get("date", "first")).toBe(firstPipe);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe(".extend()", () => {
|
||||||
|
it('should create a factory that prepend new pipes to old', () => {
|
||||||
|
firstPipeFactory.spy("supports").andReturn(true);
|
||||||
|
secondPipeFactory.spy("supports").andReturn(true);
|
||||||
|
secondPipeFactory.spy("create").andReturn(secondPipe);
|
||||||
|
|
||||||
var originalPipes = new Pipes({'async': [firstPipeFactory]});
|
var originalPipes = new Pipes({'async': [firstPipeFactory]});
|
||||||
var binding = Pipes.append({'async':<PipeFactory[]>[secondPipeFactory]});
|
var binding = Pipes.extend({'async':<PipeFactory[]>[secondPipeFactory]});
|
||||||
var pipes: Pipes = binding.toFactory(originalPipes);
|
var pipes: Pipes = binding.toFactory(originalPipes);
|
||||||
|
|
||||||
expect(pipes.config['async'].length).toBe(2);
|
expect(pipes.config['async'].length).toBe(2);
|
||||||
@ -90,33 +124,34 @@ export function main() {
|
|||||||
expect(pipes.get('async', 'second plz')).toBe(secondPipe);
|
expect(pipes.get('async', 'second plz')).toBe(secondPipe);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('should throw if calling extend when creating root injector', () => {
|
||||||
it('should append to di-inherited pipes', () => {
|
|
||||||
firstPipeFactory.spy("supports").andReturn(false);
|
|
||||||
secondPipeFactory.spy("supports").andReturn(true);
|
|
||||||
secondPipeFactory.spy("create").andReturn(secondPipe);
|
|
||||||
|
|
||||||
var originalPipes: Pipes = new Pipes({'async': [firstPipeFactory]});
|
|
||||||
var injector: Injector = Injector.resolveAndCreate([bind(Pipes).toValue(originalPipes)]);
|
|
||||||
var childInjector: Injector =
|
|
||||||
injector.resolveAndCreateChild([Pipes.append({'async': [secondPipeFactory]})]);
|
|
||||||
var parentPipes: Pipes = injector.get(Pipes);
|
|
||||||
var childPipes: Pipes = childInjector.get(Pipes);
|
|
||||||
expect(childPipes.config['async'].length).toBe(2);
|
|
||||||
expect(parentPipes.config['async'].length).toBe(1);
|
|
||||||
expect(childPipes.get('async', 'second plz')).toBe(secondPipe);
|
|
||||||
});
|
|
||||||
|
|
||||||
|
|
||||||
it('should throw if calling append when creating root injector', () => {
|
|
||||||
secondPipeFactory.spy("supports").andReturn(true);
|
secondPipeFactory.spy("supports").andReturn(true);
|
||||||
secondPipeFactory.spy("create").andReturn(secondPipe);
|
secondPipeFactory.spy("create").andReturn(secondPipe);
|
||||||
|
|
||||||
var injector: Injector =
|
var injector: Injector =
|
||||||
Injector.resolveAndCreate([Pipes.append({'async': [secondPipeFactory]})]);
|
Injector.resolveAndCreate([Pipes.extend({'async': [secondPipeFactory]})]);
|
||||||
|
|
||||||
expect(() => injector.get(Pipes))
|
expect(() => injector.get(Pipes))
|
||||||
.toThrowError(/Cannot append to Pipes without a parent injector/g);
|
.toThrowError(/Cannot extend Pipes without a parent injector/g);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should extend di-inherited pipes', () => {
|
||||||
|
firstPipeFactory.spy("supports").andReturn(true);
|
||||||
|
firstPipeFactory.spy("create").andReturn(firstPipe);
|
||||||
|
|
||||||
|
secondPipeFactory.spy("supports").andReturn(false);
|
||||||
|
|
||||||
|
var originalPipes: Pipes = new Pipes({'async': [firstPipeFactory]});
|
||||||
|
var injector: Injector = Injector.resolveAndCreate([bind(Pipes).toValue(originalPipes)]);
|
||||||
|
var childInjector: Injector =
|
||||||
|
injector.resolveAndCreateChild([Pipes.extend({'async': [secondPipeFactory]})]);
|
||||||
|
|
||||||
|
var parentPipes: Pipes = injector.get(Pipes);
|
||||||
|
var childPipes: Pipes = childInjector.get(Pipes);
|
||||||
|
|
||||||
|
expect(childPipes.config['async'].length).toBe(2);
|
||||||
|
expect(parentPipes.config['async'].length).toBe(1);
|
||||||
|
expect(childPipes.get('async', 'second plz')).toBe(firstPipe);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
Loading…
x
Reference in New Issue
Block a user