type-binder
Advanced tools
Comparing version 0.1.0 to 0.1.1
@@ -5,3 +5,4 @@ import "reflect-metadata"; | ||
export declare function generics(...generics: any[]): PropertyDecorator; | ||
export declare function track(): PropertyDecorator; | ||
export declare function track<T>(trackingCallback?: (value: T) => T): PropertyDecorator; | ||
export declare function trackEntries<T, E>(trackingCallback: (value: T) => E[]): PropertyDecorator; | ||
export declare function identifier<T>(identifier: (object: T, binder?: TypeBinder) => any, scope?: any): ClassDecorator; |
"use strict"; | ||
require("reflect-metadata"); | ||
var metadata_keys_1 = require("./metadata-keys"); | ||
var metadataKeys = require("./metadata-keys"); | ||
function bind(type) { | ||
return Reflect.metadata(metadata_keys_1.designTypeKey, type); | ||
return Reflect.metadata(metadataKeys.designType, type); | ||
} | ||
@@ -13,15 +13,20 @@ exports.bind = bind; | ||
} | ||
return Reflect.metadata(metadata_keys_1.designGenericTypesKey, generics); | ||
return Reflect.metadata(metadataKeys.designGenericTypes, generics); | ||
} | ||
exports.generics = generics; | ||
function track() { | ||
return Reflect.metadata(metadata_keys_1.trackProperty, true); | ||
function track(trackingCallback) { | ||
if (trackingCallback === void 0) { trackingCallback = function (value) { return value; }; } | ||
return Reflect.metadata(metadataKeys.binderPropertyTrack, trackingCallback); | ||
} | ||
exports.track = track; | ||
function trackEntries(trackingCallback) { | ||
return Reflect.metadata(metadataKeys.binderPropertyEntries, trackingCallback); | ||
} | ||
exports.trackEntries = trackEntries; | ||
function identifier(identifier, scope) { | ||
return function (target) { | ||
Reflect.defineMetadata(metadata_keys_1.objectIdentifierKey, identifier, target); | ||
Reflect.defineMetadata(metadata_keys_1.objectIdentifierScope, scope, target); | ||
Reflect.defineMetadata(metadataKeys.binderIdentifierKey, identifier, target); | ||
Reflect.defineMetadata(metadataKeys.binderIdentifierScope, scope, target); | ||
}; | ||
} | ||
exports.identifier = identifier; |
@@ -1,8 +0,10 @@ | ||
export declare const designTypeKey: string; | ||
export declare const designParamTypesKey: string; | ||
export declare const designReturnTypeKey: string; | ||
export declare const designGenericTypesKey: string; | ||
export declare const trackProperty: string; | ||
export declare const trackPropertyOriginal: string; | ||
export declare const objectIdentifierKey: string; | ||
export declare const objectIdentifierScope: string; | ||
export declare const designType: string; | ||
export declare const designParamTypes: string; | ||
export declare const designReturnType: string; | ||
export declare const designGenericTypes: string; | ||
export declare const binderPropertyTrack: string; | ||
export declare const binderPropertyTrackValue: string; | ||
export declare const binderPropertyEntries: string; | ||
export declare const binderPropertyEntriesValue: string; | ||
export declare const binderIdentifierKey: string; | ||
export declare const binderIdentifierScope: string; |
"use strict"; | ||
exports.designTypeKey = "design:type"; | ||
exports.designParamTypesKey = "design:paramtypes"; | ||
exports.designReturnTypeKey = "design:returntype"; | ||
exports.designGenericTypesKey = "design:generics"; | ||
exports.trackProperty = "binder:track:property"; | ||
exports.trackPropertyOriginal = "binder:track:original"; | ||
exports.objectIdentifierKey = "binder:identifier:key"; | ||
exports.objectIdentifierScope = "binder:identifier:scope"; | ||
exports.designType = "design:type"; | ||
exports.designParamTypes = "design:paramtypes"; | ||
exports.designReturnType = "design:returntype"; | ||
exports.designGenericTypes = "design:generictypes"; | ||
exports.binderPropertyTrack = "binder:property:track:callback"; | ||
exports.binderPropertyTrackValue = "binder:property:track:value"; | ||
exports.binderPropertyEntries = "binder:property:entries:callback"; | ||
exports.binderPropertyEntriesValue = "binder:property:entries:value"; | ||
exports.binderIdentifierKey = "binder:identifier:key"; | ||
exports.binderIdentifierScope = "binder:identifier:scope"; |
@@ -8,6 +8,6 @@ import "reflect-metadata"; | ||
setBindingCallback(type: any, callback: (value: any, generics: any[]) => any): void; | ||
propertyHasChanged(object: Object, property: string): boolean; | ||
bind<T>(value: any, type: new (...args) => T, ...generics: any[]): T; | ||
private createObject<T>(type, source); | ||
private createProperties<T>(type, target, source); | ||
static propertyHasChanged(object: Object, property: string): boolean; | ||
} |
"use strict"; | ||
require("reflect-metadata"); | ||
var metadata_keys_1 = require("./metadata-keys"); | ||
var metadataKeys = require("./metadata-keys"); | ||
var TypeBinder = (function () { | ||
@@ -24,12 +24,2 @@ function TypeBinder() { | ||
}; | ||
TypeBinder.prototype.propertyHasChanged = function (object, property) { | ||
if (Reflect.hasMetadata(metadata_keys_1.trackPropertyOriginal, object, property)) { | ||
var currentValue = object[property]; | ||
var originalValue = Reflect.getMetadata(metadata_keys_1.trackPropertyOriginal, object, property); | ||
return currentValue !== originalValue; | ||
} | ||
else { | ||
return false; | ||
} | ||
}; | ||
TypeBinder.prototype.bind = function (value, type) { | ||
@@ -58,5 +48,5 @@ var generics = []; | ||
var object; | ||
if (Reflect.hasMetadata(metadata_keys_1.objectIdentifierKey, type)) { | ||
var key = Reflect.getMetadata(metadata_keys_1.objectIdentifierKey, type)(source, this); | ||
var scope = Reflect.getMetadata(metadata_keys_1.objectIdentifierScope, type) || type; | ||
if (Reflect.hasMetadata(metadataKeys.binderIdentifierKey, type)) { | ||
var key = Reflect.getMetadata(metadataKeys.binderIdentifierKey, type)(source, this); | ||
var scope = Reflect.getMetadata(metadataKeys.binderIdentifierScope, type) || type; | ||
if (this.objectInstances.has(scope) && this.objectInstances.get(scope).has(key)) { | ||
@@ -82,4 +72,4 @@ object = this.objectInstances.get(scope).get(key); | ||
Object.getOwnPropertyNames(source).forEach(function (property) { | ||
var propertyType = Reflect.getMetadata(metadata_keys_1.designTypeKey, type.prototype, property); | ||
var propertyGenerics = Reflect.getMetadata(metadata_keys_1.designGenericTypesKey, type.prototype, property); | ||
var propertyType = Reflect.getMetadata(metadataKeys.designType, type.prototype, property); | ||
var propertyGenerics = Reflect.getMetadata(metadataKeys.designGenericTypes, type.prototype, property); | ||
properties[property] = { | ||
@@ -91,10 +81,27 @@ configurable: false, | ||
}; | ||
if (Reflect.getMetadata(metadata_keys_1.trackProperty, type.prototype, property)) { | ||
Reflect.defineMetadata(metadata_keys_1.trackPropertyOriginal, properties[property].value, target, property); | ||
if (Reflect.hasMetadata(metadataKeys.binderPropertyTrack, type.prototype, property)) { | ||
var trackingCallback = Reflect.getMetadata(metadataKeys.binderPropertyTrack, type.prototype, property); | ||
var value = trackingCallback(properties[property].value); | ||
Reflect.defineMetadata(metadataKeys.binderPropertyTrackValue, value, target, property); | ||
} | ||
if (Reflect.hasMetadata(metadataKeys.binderPropertyEntries, type.prototype, property)) { | ||
var trackingCallback = Reflect.getMetadata(metadataKeys.binderPropertyEntries, type.prototype, property); | ||
var value = trackingCallback(properties[property].value); | ||
Reflect.defineMetadata(metadataKeys.binderPropertyEntriesValue, value, target, property); | ||
} | ||
}); | ||
return properties; | ||
}; | ||
TypeBinder.propertyHasChanged = function (object, property) { | ||
if (Reflect.hasMetadata(metadataKeys.binderPropertyTrackValue, object, property)) { | ||
var currentValue = object[property]; | ||
var originalValue = Reflect.getMetadata(metadataKeys.binderPropertyTrackValue, object, property); | ||
return currentValue !== originalValue; | ||
} | ||
else { | ||
return false; | ||
} | ||
}; | ||
return TypeBinder; | ||
}()); | ||
exports.TypeBinder = TypeBinder; |
{ | ||
"name": "type-binder", | ||
"version": "0.1.0", | ||
"version": "0.1.1", | ||
"description": "A JavaScript type-binder.", | ||
@@ -41,5 +41,5 @@ "keywords": [ | ||
"run-sequence": "^1.2.2", | ||
"typescript": "^2.0.6", | ||
"typescript": "^2.0.7", | ||
"vinyl-paths": "^2.1.0" | ||
} | ||
} |
# JavaScript object type binding | ||
[![npm version](https://img.shields.io/npm/v/type-binder.svg)](https://www.npmjs.com/package/type-binder) | ||
[![CircleCI](https://img.shields.io/circleci/project/github/heruan/type-binder.svg)](https://circleci.com/gh/heruan/type-binder) | ||
## Type binding | ||
@@ -26,3 +29,3 @@ | ||
foo.sayHello(); // returns "Hello, my name is Foo!" | ||
foo.sayHello(); // returns "Hello, my name is Foo!" | ||
``` | ||
@@ -61,3 +64,3 @@ | ||
let foo = new TypeBinder().bind({ name: "Foo", children: [ { name: "Bar" }, { name: "Baz" } ] }); | ||
let foo = new TypeBinder().bind({ name: "Foo", children: [ { name: "Bar" }, { name: "Baz" } ] }, Person); | ||
@@ -105,5 +108,5 @@ for (let child of foo.children) { | ||
let foo1 = binder.bind({ "name": "Foo" }); | ||
let foo1 = binder.bind({ "name": "Foo" }, Person); | ||
let foo2 = binder.bind({ "name": "Foo" }); | ||
let foo2 = binder.bind({ "name": "Foo" }, Person); | ||
@@ -127,9 +130,9 @@ foo1 === foo2; // true | ||
let person = new TypeBinder().bind({ name: "Foo" }); | ||
let person = new TypeBinder().bind({ name: "Foo" }, Person); | ||
person.name = "Bar"; | ||
let changed = new TypeBinder().propertyHasChanged(person, "name"); | ||
let changed = TypeBinder.propertyHasChanged(person, "name"); | ||
changed === true; // true | ||
``` |
import "reflect-metadata"; | ||
import { TypeBinder } from "./type-binder"; | ||
import { designTypeKey, designGenericTypesKey, trackProperty, objectIdentifierKey, objectIdentifierScope } from "./metadata-keys"; | ||
import * as metadataKeys from "./metadata-keys"; | ||
export function bind(type: any): PropertyDecorator { | ||
return Reflect.metadata(designTypeKey, type); | ||
return Reflect.metadata(metadataKeys.designType, type); | ||
} | ||
export function generics(...generics: any[]): PropertyDecorator { | ||
return Reflect.metadata(designGenericTypesKey, generics); | ||
return Reflect.metadata(metadataKeys.designGenericTypes, generics); | ||
} | ||
export function track(): PropertyDecorator { | ||
return Reflect.metadata(trackProperty, true); | ||
export function track<T>(trackingCallback: (value: T) => T = (value: T) => value): PropertyDecorator { | ||
return Reflect.metadata(metadataKeys.binderPropertyTrack, trackingCallback); | ||
} | ||
export function trackEntries<T, E>(trackingCallback: (value: T) => E[]): PropertyDecorator { | ||
return Reflect.metadata(metadataKeys.binderPropertyEntries, trackingCallback); | ||
} | ||
export function identifier<T>(identifier: (object: T, binder?: TypeBinder) => any, scope?: any): ClassDecorator { | ||
return (target: Function) => { | ||
Reflect.defineMetadata(objectIdentifierKey, identifier, target); | ||
Reflect.defineMetadata(objectIdentifierScope, scope, target); | ||
Reflect.defineMetadata(metadataKeys.binderIdentifierKey, identifier, target); | ||
Reflect.defineMetadata(metadataKeys.binderIdentifierScope, scope, target); | ||
}; | ||
} |
@@ -1,8 +0,10 @@ | ||
export const designTypeKey = "design:type"; | ||
export const designParamTypesKey = "design:paramtypes"; | ||
export const designReturnTypeKey = "design:returntype"; | ||
export const designGenericTypesKey = "design:generics"; | ||
export const trackProperty = "binder:track:property"; | ||
export const trackPropertyOriginal = "binder:track:original"; | ||
export const objectIdentifierKey = "binder:identifier:key"; | ||
export const objectIdentifierScope = "binder:identifier:scope"; | ||
export const designType = "design:type"; | ||
export const designParamTypes = "design:paramtypes"; | ||
export const designReturnType = "design:returntype"; | ||
export const designGenericTypes = "design:generictypes"; | ||
export const binderPropertyTrack = "binder:property:track:callback"; | ||
export const binderPropertyTrackValue = "binder:property:track:value"; | ||
export const binderPropertyEntries = "binder:property:entries:callback"; | ||
export const binderPropertyEntriesValue = "binder:property:entries:value"; | ||
export const binderIdentifierKey = "binder:identifier:key"; | ||
export const binderIdentifierScope = "binder:identifier:scope"; |
import "reflect-metadata"; | ||
import { designTypeKey, designGenericTypesKey, trackProperty, trackPropertyOriginal, objectIdentifierKey, objectIdentifierScope } from "./metadata-keys"; | ||
import * as metadataKeys from "./metadata-keys"; | ||
@@ -36,12 +36,2 @@ export class TypeBinder { | ||
public propertyHasChanged(object: Object, property: string): boolean { | ||
if (Reflect.hasMetadata(trackPropertyOriginal, object, property)) { | ||
let currentValue = object[property]; | ||
let originalValue = Reflect.getMetadata(trackPropertyOriginal, object, property); | ||
return currentValue !== originalValue; | ||
} else { | ||
return false; | ||
} | ||
} | ||
public bind<T>(value: any, type: new(...args) => T, ...generics: any[]): T { | ||
@@ -65,5 +55,5 @@ if (Array.isArray(type)) { | ||
let object: T; | ||
if (Reflect.hasMetadata(objectIdentifierKey, type)) { | ||
let key = Reflect.getMetadata(objectIdentifierKey, type)(source, this); | ||
let scope = Reflect.getMetadata(objectIdentifierScope, type) || type; | ||
if (Reflect.hasMetadata(metadataKeys.binderIdentifierKey, type)) { | ||
let key = Reflect.getMetadata(metadataKeys.binderIdentifierKey, type)(source, this); | ||
let scope = Reflect.getMetadata(metadataKeys.binderIdentifierScope, type) || type; | ||
if (this.objectInstances.has(scope) && this.objectInstances.get(scope).has(key)) { | ||
@@ -87,4 +77,4 @@ object = <T> this.objectInstances.get(scope).get(key); | ||
Object.getOwnPropertyNames(source).forEach(property => { | ||
let propertyType = Reflect.getMetadata(designTypeKey, type.prototype, property); | ||
let propertyGenerics = Reflect.getMetadata(designGenericTypesKey, type.prototype, property); | ||
let propertyType = Reflect.getMetadata(metadataKeys.designType, type.prototype, property); | ||
let propertyGenerics = Reflect.getMetadata(metadataKeys.designGenericTypes, type.prototype, property); | ||
properties[property] = { | ||
@@ -96,5 +86,12 @@ configurable: false, | ||
}; | ||
if (Reflect.getMetadata(trackProperty, type.prototype, property)) { | ||
Reflect.defineMetadata(trackPropertyOriginal, properties[property].value, target, property); | ||
if (Reflect.hasMetadata(metadataKeys.binderPropertyTrack, type.prototype, property)) { | ||
let trackingCallback: (value: any) => any = Reflect.getMetadata(metadataKeys.binderPropertyTrack, type.prototype, property); | ||
let value = trackingCallback(properties[property].value); | ||
Reflect.defineMetadata(metadataKeys.binderPropertyTrackValue, value, target, property); | ||
} | ||
if (Reflect.hasMetadata(metadataKeys.binderPropertyEntries, type.prototype, property)) { | ||
let trackingCallback: <I, K, V>(value: I) => [K, V][] = Reflect.getMetadata(metadataKeys.binderPropertyEntries, type.prototype, property); | ||
let value = trackingCallback(properties[property].value); | ||
Reflect.defineMetadata(metadataKeys.binderPropertyEntriesValue, value, target, property); | ||
} | ||
}); | ||
@@ -104,2 +101,12 @@ return properties; | ||
public static propertyHasChanged(object: Object, property: string): boolean { | ||
if (Reflect.hasMetadata(metadataKeys.binderPropertyTrackValue, object, property)) { | ||
let currentValue = object[property]; | ||
let originalValue = Reflect.getMetadata(metadataKeys.binderPropertyTrackValue, object, property); | ||
return currentValue !== originalValue; | ||
} else { | ||
return false; | ||
} | ||
} | ||
} |
@@ -72,6 +72,6 @@ /// <reference path="../../typings/index.d.ts" /> | ||
let baz = new TypeBinder().bind(object, Baz); | ||
let diff = new TypeBinder().propertyHasChanged(baz, "number"); | ||
let diff = TypeBinder.propertyHasChanged(baz, "number"); | ||
expect(diff).toBe(false); | ||
baz.number = 456; | ||
diff = new TypeBinder().propertyHasChanged(baz, "number"); | ||
diff = TypeBinder.propertyHasChanged(baz, "number"); | ||
expect(diff).toBe(true); | ||
@@ -78,0 +78,0 @@ }); |
31567
459
135