0.2.1 • Published 7 years ago
zangetsu v0.2.1
Zangetsu (斬月, Slaying Moon) is a sword used by the character Ichigo Kurosaki in the Bleach series.
$ yarn add zangetsuMutable & Immutable
This library exposes two namespaces: Mutable and Immutable.
Use Immutable if you need to produce a new object.
Mutable - to modify existing one.
import { Immutable } from 'zangetsu';
...
let foo = {foo: 'Foo'};
let bar = {bar: 'Bar'};
let fooBar = Immutable.compose(foo).append(bar);
assert(fooBar !== foo); // different objectsimport { Mutable } from 'zangetsu';
...
let foo = {foo: 'Foo'};
let bar = {bar: 'Bar'};
let fooBar = Mutable.compose(foo).append(bar);
assert(fooBar === foo); // fooBar and foo hold same reference. In other words foo is not { foo: 'Foo' } any more.
console.log(foo); // will print out { foo: 'Foo', bar: 'Bar' }Declarative Syntax
This library can extend objects with additional fields, remove fields with projection operator $ and do it as a part of logical branching (if, elseif and else):
import { Immutable } from 'zangetsu';
...
Immutable
// compose a new object
.compose({
hello: 'World!'
})
// extend with another object
.append({
alice: 'Alice'
})
// extend if condition is satisfied
.if(hasFoo && hasBar, {
foo: 'Foo',
bar: 'Bar'
})
// or if another condition is satisfied
.elseif(hasFoo, {
foo: 'Foo'
})
// the chain could be long and it will stay readable
.elseif(hasBar, {
bar: 'Bar'
})
.else({
noFooNoBar: 'NoFooNoBar'
})
// build projections to filter fields
.$({
hello: false,
alice: false,
foo: true,
bar: true,
noFooNoBar: true
})
// return the result
.val();hasFoo \ hasBar | true | false |
|---|---|---|
| true | { foo: 'Foo', bar: 'Bar' } | { foo: 'Foo' } |
| false | { bar: 'Bar' } | { noFooNoBar: 'NoFooNoBar' } |
Real Life Example
Suppose you need to compose an HTTP request to upload a file to a server. You decided to set content type based on a file extension and apply gzip for javascript and css files.
import { Immutable } from 'zangetsu';
...
const createRequest = (payload: any, fileExt: string) =>
Immutable
.compose({
body: { ...payload }
}).if(fileExt === 'js', {
contentType: 'text/javascript'
}).elseif(fileExt === 'css', {
contentType: 'text/css'
}).else({
contentType: 'application/octet-stream'
}).if(['js', 'css'].includes(fileExt), {
encoding: 'gzip'
}).val();API
| Method | Description |
|---|---|
| compose(a) | Creates a wrapper for a given object a. |
| append(b) | Appends an object b to the context a. |
| if(condition, b) | Appends a given object b to the context `a if and only if the condition is satisfied. |
| elseif(condition, c) | Appends a given object c to the context a if and only if the condition is satisfied and all previous conditions were falsy. |
| else(d) | Appends a given object d to the context a if all previous conditions were falsy. |
| $(projection) | Creates a projection of a context object a and returns only true fields. |
| val() | Simply returns the context object a. |
export interface IComposer<A> {
append<B>(b: B): IComposer<A & B>;
if<B>(condition: boolean, b: B): IComposer<A | (A & B)>;
elseif<C>(condition: boolean, c: C): IComposer<A | (A & C)>
else<D>(d: D): IComposer<A | (A & D)>;
$(projection: {[K in keyof A]: Boolean}): IComposer<{[K in keyof A]: A[K] }>;
val(): A;
}License
MIT