Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

knockout-decorators

Package Overview
Dependencies
Maintainers
1
Versions
25
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

knockout-decorators - npm Package Compare versions

Comparing version 0.8.0 to 0.9.0

90

dist/knockout-decorators.d.ts
/// <reference types="knockout" />
export interface ComponentConstructor {
new (params?: any, element?: Node, templateNodes?: Node[]): any;
}
export declare type ComponentDecorator = (constructor: ComponentConstructor) => void;
export declare type TemplateConfig = (string | Node[] | DocumentFragment | {
require: string;
} | {
element: string | Node;
});
/**
* Register Knockout component by decorating ViewModel class
* Property decorator that creates hidden (shallow) ko.observable with ES6 getter and setter for it
* If initialized by Array then hidden (shallow) ko.observableArray will be created
*/
export declare function component(name: string, options?: Object): ComponentDecorator;
export declare function component(name: string, template: TemplateConfig, options?: Object): ComponentDecorator;
export declare function component(name: string, template: TemplateConfig, styles: string | string[], options?: Object): ComponentDecorator;
export declare function observable(prototype: Object, key: string | symbol): void;
/**
* Property decorator that creates hidden ko.observable with ES6 getter and setter for it
* Property decorator that creates hidden (deep) ko.observable with ES6 getter and setter for it
* If initialized by Array then hidden (deep) ko.observableArray will be created
*/
export declare function observable(prototype: Object, key: string | symbol): void;
export declare function reactive(prototype: Object, key: string | symbol): void;
/**

@@ -30,3 +21,3 @@ * Accessor decorator that wraps ES6 getter to hidden ko.pureComputed

/**
* Property decorator that creates hidden ko.observableArray with ES6 getter and setter for it
* Property decorator that creates hidden (shallow) ko.observableArray with ES6 getter and setter for it
*/

@@ -47,2 +38,11 @@ export declare function observableArray(prototype: Object, key: string | symbol): void;

subscribe(callback: (val: any[]) => void, callbackTarget: any, event: string): KnockoutSubscription;
/**
* Run mutator function that can write to array at some index (`array[index] = value;`)
* Then notify about observableArray changes
*/
mutate(mutator: (arrayValue: T[]) => void): void;
/**
* Replace value at some index and return old value
*/
set(index: number, value: T): T;
}

@@ -53,4 +53,28 @@ /**

export declare function extend(extenders: Object): PropertyDecorator;
/**
* Apply extenders to decorated @observable
*/
export declare function extend(extendersFactory: () => Object): PropertyDecorator;
export interface ComponentConstructor {
new (params?: any, element?: Node, templateNodes?: Node[]): any;
}
export declare type ComponentDecorator = (constructor: ComponentConstructor) => void;
export declare type TemplateConfig = (string | Node[] | DocumentFragment | {
require: string;
} | {
element: string | Node;
});
/**
* Register Knockout component by decorating ViewModel class
*/
export declare function component(name: string, options?: Object): ComponentDecorator;
/**
* Register Knockout component by decorating ViewModel class
*/
export declare function component(name: string, template: TemplateConfig, options?: Object): ComponentDecorator;
/**
* Register Knockout component by decorating ViewModel class
*/
export declare function component(name: string, template: TemplateConfig, styles: string | string[], options?: Object): ComponentDecorator;
/**
* Like https://github.com/jayphelps/core-decorators.js @autobind but less smart and complex

@@ -61,5 +85,12 @@ * Do NOT use with ES6 inheritance!

/**
* Subscribe callback to dependency changes
* Define hidden ko.subscribable, that notifies subscribers when decorated method is invoked
*/
export declare function subscribe<T>(getDependency: () => T, callback: (value: T) => void, options?: {
export declare function event(prototype: Object, key: string | symbol): void;
export declare type EventProperty = Function & {
subscribe(callback: Function): KnockoutSubscription;
};
/**
* Subscribe callback to `@observable` or `@computed` dependency changes or to some `@event`
*/
export declare function subscribe<T>(dependencyOrEvent: () => T, callback: (value: T) => void, options?: {
once?: boolean;

@@ -69,6 +100,27 @@ event?: string;

/**
* Subscribe callback to some `@event`
*/
export declare function subscribe<T>(event: (arg: T) => void, callback: (arg: T) => void, options?: {
once?: boolean;
}): KnockoutSubscription;
/**
* Subscribe callback to some `@event`
*/
export declare function subscribe<T1, T2>(event: (arg1: T1, arg2: T2) => void, callback: (arg1: T1, arg2: T2) => void, options?: {
once?: boolean;
}): KnockoutSubscription;
/**
* Subscribe callback to some `@event`
*/
export declare function subscribe<T1, T2, T3>(event: (arg1: T1, arg2: T2, arg3: T3, ...args: any[]) => void, callback: (arg1: T1, arg2: T2, arg3: T3, ...args: any[]) => void, options?: {
once?: boolean;
}): KnockoutSubscription;
/**
* Get internal ko.observable() for object property decodated by @observable
*/
export declare function unwrap(instance: Object, key: string | symbol): any;
/**
* Get internal ko.observable() for object property decodated by @observable
*/
export declare function unwrap<T>(instance: Object, key: string | symbol): KnockoutObservable<T>;
export as namespace KnockoutDecorators;
export as namespace KnockoutDecorators;

@@ -7,136 +7,98 @@ (function (global, factory) {

/**
* Copyright (c) 2016 Dmitry Panyushkin
* Available under MIT license
*/
var assign = ko.utils.extend;
var extendObject = ko.utils.extend;
var objectForEach = ko.utils.objectForEach;
var defProp = Object.defineProperty.bind(Object);
var getDescriptor = Object.getOwnPropertyDescriptor.bind(Object);
var defineProperty = Object.defineProperty.bind(Object);
var getPrototypeOf = Object.getPrototypeOf.bind(Object);
var getOwnPropertyDescriptor = Object.getOwnPropertyDescriptor.bind(Object);
var hasOwnProperty = Function.prototype.call.bind(Object.prototype.hasOwnProperty);
var slice = Function.prototype.call.bind(Array.prototype.slice);
/**
* Register Knockout component by decorating ViewModel class
* @param name { String } Name of component
* @param template { Any } Knockout template definition
* @param styles { Any } Ignored parameter (used for `require()` styles by webpack etc.)
* @param options { Object } Another options that passed directly to `ko.components.register()`
*/
function component(name, template, styles, options) {
if (options === void 0) {
if (styles === void 0) {
if (typeof template === "object"
&& template.constructor === Object
&& !("require" in template)
&& !("element" in template)) {
options = template;
template = void 0;
}
}
else if (typeof styles === "object") {
options = styles;
styles = void 0;
}
var arraySlice = Function.prototype.call.bind(Array.prototype.slice);
var EXTENDERS_KEY = typeof Symbol !== "undefined"
? Symbol("ko_decorators_extenders") : "__ko_decorators_extenders__";
function applyExtenders(instance, key, target) {
var dictionary = instance[EXTENDERS_KEY];
var extenders = dictionary && dictionary[key];
if (extenders) {
extenders.forEach(function (extender) {
var koExtender = extender instanceof Function
? extender.call(instance) : extender;
target = target.extend(koExtender);
});
}
return function (constructor) {
ko.components.register(name, assign({
viewModel: constructor.length < 2 ? constructor : {
createViewModel: function (params, _a) {
var element = _a.element, templateNodes = _a.templateNodes;
return new constructor(params, element, templateNodes);
}
},
template: template || "<!---->",
synchronous: true,
}, options));
};
return target;
}
/*===========================================================================*/
/**
* Property decorator that creates hidden ko.observable with ES6 getter and setter for it
*/
function observable$1(prototype, key) {
defProp(prototype, key, {
configurable: true,
get: function () {
var observable$$1 = applyExtenders(this, key, ko.observable());
defProp(this, key, {
configurable: true,
enumerable: true,
get: observable$$1,
set: observable$$1,
});
return observable$$1();
},
set: function (value) {
var observable$$1 = applyExtenders(this, key, ko.observable());
defProp(this, key, {
configurable: true,
enumerable: true,
get: observable$$1,
set: observable$$1,
});
observable$$1(value);
},
});
function defineExtenders(prototype, key, extendersOrFactory) {
var dictionary = prototype[EXTENDERS_KEY];
// if there is no ExtendersDictionary or ExtendersDictionary lives in base class prototype
if (!hasOwnProperty(prototype, EXTENDERS_KEY)) {
// clone ExtendersDictionary from base class prototype or create new ExtendersDictionary
prototype[EXTENDERS_KEY] = dictionary = extendObject({}, dictionary);
// clone Extenders arrays for each property key
objectForEach(dictionary, function (key, extenders) {
dictionary[key] = extenders.slice();
});
}
// get existing Extenders array or create new array
var extenders = dictionary[key] || (dictionary[key] = []);
// add new Extenders
extenders.push(extendersOrFactory);
}
/*===========================================================================*/
/**
* Accessor decorator that wraps ES6 getter to hidden ko.pureComputed
*
* Setter is not wrapped to hidden ko.pureComputed and stays unchanged
*
* But we can still extend getter @computed by extenders like { rateLimit: 500 }
* Copyright (c) 2016-2017 Dmitry Panyushkin
* Available under MIT license
*/
function computed$1(prototype, key, desc) {
var _a = desc || (desc = getDescriptor(prototype, key)), get = _a.get, set = _a.set;
desc.get = function () {
var computed$$1 = applyExtenders(this, key, ko.pureComputed(get, this));
defProp(this, key, {
configurable: true,
get: computed$$1,
set: set
});
return computed$$1();
};
return desc;
// TODO: make @computed extendable (by @extend decorator)
}
var arrayMethods = ["pop", "push", "reverse", "shift", "sort", "splice", "unshift"];
var observableArrayMethods = ["remove", "removeAll", "destroy", "destroyAll", "replace", "subscribe"];
function defObservableArray(instance, key) {
var deepArrayMethods = ["pop", "reverse", "shift", "sort"];
var allArrayMethods = deepArrayMethods.concat(["push", "splice", "unshift"]);
var deepObservableArrayMethods = ["remove", "removeAll", "destroy", "destroyAll", "replace", "subscribe"];
var allObservableArrayMethods = deepObservableArrayMethods.concat(["replace"]);
var allMethods = allArrayMethods.concat(allObservableArrayMethods, ["mutate", "set"]);
function defineObservableArray(instance, key, value, deep) {
var obsArray = applyExtenders(instance, key, ko.observableArray());
var insideObsArray = false;
defProp(instance, key, {
defineProperty(instance, key, {
configurable: true,
enumerable: true,
get: obsArray,
set: function (value) {
var lastValue = obsArray.peek();
// if we got new value
if (lastValue !== value) {
if (Array.isArray(lastValue)) {
// if lastValue array methods were already patched
if (hasOwnProperty(lastValue, "subscribe")) {
// clear patched array methods on lastValue (see unit tests)
clearArrayMethods(lastValue);
}
set: setter,
});
setter(value);
function setter(newValue) {
var lastValue = obsArray.peek();
// if we got new value
if (lastValue !== newValue) {
if (Array.isArray(lastValue)) {
// if lastValue array methods were already patched
if (hasOwnProperty(lastValue, "mutate")) {
// clear patched array methods on lastValue (see unit tests)
allMethods.forEach(function (fnName) {
delete lastValue[fnName];
});
}
if (Array.isArray(value)) {
// if new value array methods were already connected with another @observableArray
if (hasOwnProperty(value, "subscribe")) {
// clone new value to prevent corruption of another @observableArray (see unit tests)
value = slice(value);
}
if (Array.isArray(newValue)) {
// if new value array methods were already connected with another @observable
if (hasOwnProperty(newValue, "mutate")) {
// clone new value to prevent corruption of another @observable (see unit tests)
newValue = newValue.slice();
}
// if deep option is set
if (deep) {
// make all array items reactive
for (var i = 0; i < newValue.length; ++i) {
newValue[i] = prepareReactiveValue(newValue[i]);
}
// call ko.observableArray.fn[fnName] instead of Array.prototype[fnName]
patchArrayMethods(value);
}
// call ko.observableArray.fn[fnName] instead of Array.prototype[fnName]
patchArrayMethods(newValue);
}
insideObsArray = true;
obsArray(value);
insideObsArray = false;
}
});
// update obsArray contents
insideObsArray = true;
obsArray(newValue);
insideObsArray = false;
}
function patchArrayMethods(array) {
arrayMethods.forEach(function (fnName) { return defProp(array, fnName, {
var arrayMethods = deep ? deepArrayMethods : allArrayMethods;
arrayMethods.forEach(function (fnName) { return defineProperty(array, fnName, {
configurable: true,

@@ -153,3 +115,4 @@ value: function () {

}); });
observableArrayMethods.forEach(function (fnName) { return defProp(array, fnName, {
var observableArrayMethods = deep ? deepObservableArrayMethods : allObservableArrayMethods;
observableArrayMethods.forEach(function (fnName) { return defineProperty(array, fnName, {
configurable: true,

@@ -163,61 +126,282 @@ value: function () {

}); });
if (deep) {
defineProperty(array, "push", {
configurable: true,
value: function () {
if (insideObsArray) {
return Array.prototype.push.apply(array, arguments);
}
var args = arraySlice(arguments);
for (var i = 0; i < args.length; ++i) {
args[i] = prepareReactiveValue(args[i]);
}
insideObsArray = true;
var result = obsArray.push.apply(obsArray, args);
insideObsArray = false;
return result;
}
});
defineProperty(array, "unshift", {
configurable: true,
value: function () {
if (insideObsArray) {
return Array.prototype.unshift.apply(array, arguments);
}
var args = arraySlice(arguments);
for (var i = 0; i < args.length; ++i) {
args[i] = prepareReactiveValue(args[i]);
}
insideObsArray = true;
var result = obsArray.unshift.apply(obsArray, args);
insideObsArray = false;
return result;
}
});
defineProperty(array, "splice", {
configurable: true,
value: function () {
if (insideObsArray) {
return Array.prototype.splice.apply(array, arguments);
}
var result;
insideObsArray = true;
switch (arguments.length) {
case 0:
case 1:
case 2: {
result = obsArray.splice.apply(obsArray, arguments);
break;
}
case 3: {
result = obsArray.splice(arguments[0], arguments[1], prepareReactiveValue(arguments[2]));
break;
}
default: {
var args = arraySlice(arguments);
for (var i = 2; i < args.length; ++i) {
args[i] = prepareReactiveValue(args[i]);
}
result = obsArray.splice.apply(obsArray, arguments);
break;
}
}
insideObsArray = false;
return result;
}
});
defineProperty(array, "replace", {
configurable: true,
value: function (oldItem, newItem) {
insideObsArray = true;
var result = obsArray.replace(oldItem, prepareReactiveValue(newItem));
insideObsArray = false;
return result;
}
});
defineProperty(array, "mutate", {
configurable: true,
value: function (mutator) {
var array = obsArray.peek();
obsArray.valueWillMutate();
mutator(array);
for (var i = 0; i < array.length; ++i) {
array[i] = prepareReactiveValue(array[i]);
}
obsArray.valueHasMutated();
}
});
defineProperty(array, "set", {
configurable: true,
value: function (index, newItem) {
return obsArray.splice(index, 1, prepareReactiveValue(newItem))[0];
}
});
}
else {
defineProperty(array, "mutate", {
configurable: true,
value: function (mutator) {
obsArray.valueWillMutate();
mutator(obsArray.peek());
obsArray.valueHasMutated();
}
});
defineProperty(array, "set", {
configurable: true,
value: function (index, newItem) {
return obsArray.splice(index, 1, newItem)[0];
}
});
}
}
}
// moved outside of defObservableArray function to prevent creation of unnecessary closure
function clearArrayMethods(array) {
arrayMethods.forEach(function (fnName) {
delete array[fnName];
/**
* Copyright (c) 2016-2017 Dmitry Panyushkin
* Available under MIT license
*/
function defineObservableProperty(instance, key, value, deep) {
var observable$$1 = applyExtenders(instance, key, ko.observable());
var setter = observable$$1;
if (deep) {
setter = function (newValue) {
observable$$1(prepareReactiveValue(newValue));
};
}
defineProperty(instance, key, {
configurable: true,
enumerable: true,
get: observable$$1,
set: setter,
});
observableArrayMethods.forEach(function (fnName) {
delete array[fnName];
setter(value);
}
function prepareReactiveValue(value) {
if (typeof value === "object") {
if (Array.isArray(value) || value === null) {
// value is Array or null
return value;
}
else if (value.constructor === Object) {
// value is plain Object
return prepareReactiveObject(value);
}
else if (hasOwnProperty(value, "constructor")) {
var prototype = getPrototypeOf(value);
if (prototype === Object.prototype || prototype === null) {
// value is plain Object
return prepareReactiveObject(value);
}
}
}
// value is primitive, function or class instance
return value;
}
var REACTIVE_KEY = typeof Symbol !== "undefined"
? Symbol("ko_decorators_reactive") : "__ko_decorators_reactive__";
function prepareReactiveObject(instance) {
if (!hasOwnProperty(instance, REACTIVE_KEY)) {
// mark instance as ObservableObject
defineProperty(instance, REACTIVE_KEY, {
configurable: true,
value: void 0,
});
// define deep observable properties
objectForEach(instance, function (key, value) {
if (Array.isArray(value)) {
defineObservableArray(instance, key, value, true);
}
else {
defineObservableProperty(instance, key, value, true);
}
});
}
return instance;
}
/**
* Copyright (c) 2016-2017 Dmitry Panyushkin
* Available under MIT license
*/
function defineEventProperty(instance, key) {
var subscribable$$1 = new ko.subscribable();
var event = function () {
var eventArgs = arraySlice(arguments);
subscribable$$1.notifySubscribers(eventArgs);
};
event.subscribe = function (callback) {
return subscribable$$1.subscribe(function (eventArgs) {
callback.apply(null, eventArgs);
});
};
defineProperty(instance, key, {
configurable: true,
value: event,
});
return event;
}
/**
* Property decorator that creates hidden ko.observableArray with ES6 getter and setter for it
* Copyright (c) 2016-2017 Dmitry Panyushkin
* Available under MIT license
* Version: 0.9.0
*/
function observableArray$1(prototype, key) {
defProp(prototype, key, {
/**
* Property decorator that creates hidden (shallow) ko.observable with ES6 getter and setter for it
* If initialized by Array then hidden (shallow) ko.observableArray will be created
*/
function observable$1(prototype, key) {
defineProperty(prototype, key, {
configurable: true,
get: function () {
defObservableArray(this, key);
this[key] = [];
return this[key];
throw new Error("@observable property '" + key.toString() + "' was not initialized");
},
set: function (value) {
defObservableArray(this, key);
this[key] = value;
if (Array.isArray(value)) {
defineObservableArray(this, key, value, false);
}
else {
defineObservableProperty(this, key, value, false);
}
},
});
}
/*===========================================================================*/
var DECORATORS_KEY = typeof Symbol !== "undefined"
? Symbol("ko_decorators") : "__ko_decorators__";
function getOrCreateMetaData(prototype) {
var metaData = prototype[DECORATORS_KEY];
if (!prototype.hasOwnProperty(DECORATORS_KEY)) {
// clone MetaData from base class prototype
prototype[DECORATORS_KEY] = metaData = assign({}, metaData);
// clone extenders arrays for each property key
objectForEach(metaData, function (key, extenders) {
metaData[key] = extenders.slice();
});
}
return metaData;
/*---------------------------------------------------------------------------*/
/**
* Property decorator that creates hidden (deep) ko.observable with ES6 getter and setter for it
* If initialized by Array then hidden (deep) ko.observableArray will be created
*/
function reactive(prototype, key) {
defineProperty(prototype, key, {
configurable: true,
get: function () {
throw new Error("@reactive property '" + key.toString() + "' was not initialized");
},
set: function (value) {
if (Array.isArray(value)) {
defineObservableArray(this, key, value, true);
}
else {
defineObservableProperty(this, key, value, true);
}
},
});
}
function getOrCreateExtenders(metaData, key) {
return metaData[key] || (metaData[key] = []);
}
function applyExtenders(instance, key, target) {
var metaData = instance[DECORATORS_KEY];
var extenders = metaData && metaData[key];
if (extenders) {
extenders.forEach(function (extender) {
var koExtender = extender instanceof Function
? extender.call(instance) : extender;
target = target.extend(koExtender);
/*---------------------------------------------------------------------------*/
/**
* Accessor decorator that wraps ES6 getter to hidden ko.pureComputed
*
* Setter is not wrapped to hidden ko.pureComputed and stays unchanged
*
* But we can still extend getter @computed by extenders like { rateLimit: 500 }
*/
function computed$1(prototype, key, desc) {
var _a = desc || (desc = getOwnPropertyDescriptor(prototype, key)), get = _a.get, set = _a.set;
desc.get = function () {
var computed$$1 = applyExtenders(this, key, ko.pureComputed(get, this));
defineProperty(this, key, {
configurable: true,
get: computed$$1,
set: set,
});
}
return target;
return computed$$1();
};
return desc;
}
/*---------------------------------------------------------------------------*/
/**
* Property decorator that creates hidden (shallow) ko.observableArray with ES6 getter and setter for it
*/
function observableArray$1(prototype, key) {
defineProperty(prototype, key, {
configurable: true,
get: function () {
throw new Error("@observableArray property '" + key.toString() + "' was not initialized");
},
set: function (value) {
defineObservableArray(this, key, value, false);
},
});
}
/**
* Apply extenders to decorated @observable

@@ -228,9 +412,43 @@ * @extendersOrFactory { Object | Function } Knockout extenders definition or factory that produces definition

return function (prototype, key) {
var medaData = getOrCreateMetaData(prototype);
var extenders = getOrCreateExtenders(medaData, key);
extenders.push(extendersOrFactory);
defineExtenders(prototype, key, extendersOrFactory);
};
}
/*===========================================================================*/
/**
* Register Knockout component by decorating ViewModel class
* @param name { String } Name of component
* @param template { Any } Knockout template definition
* @param styles { Any } Ignored parameter (used for `require()` styles by webpack etc.)
* @param options { Object } Another options that passed directly to `ko.components.register()`
*/
function component(name, template, styles, options) {
if (options === void 0) {
if (styles === void 0) {
if (typeof template === "object"
&& template.constructor === Object
&& !("require" in template)
&& !("element" in template)) {
options = template;
template = void 0;
}
}
else if (typeof styles === "object") {
options = styles;
styles = void 0;
}
}
return function (constructor) {
ko.components.register(name, extendObject({
viewModel: constructor.length < 2 ? constructor : {
createViewModel: function (params, _a) {
var element = _a.element, templateNodes = _a.templateNodes;
return new constructor(params, element, templateNodes);
}
},
template: template || "<!---->",
synchronous: true,
}, options));
};
}
/*---------------------------------------------------------------------------*/
/**
* Like https://github.com/jayphelps/core-decorators.js @autobind but less smart and complex

@@ -240,3 +458,3 @@ * Do NOT use with ES6 inheritance!

function autobind(prototype, key, desc) {
var _a = desc || (desc = getDescriptor(prototype, key)), value = _a.value, configurable = _a.configurable, enumerable = _a.enumerable;
var _a = desc || (desc = getOwnPropertyDescriptor(prototype, key)), value = _a.value, configurable = _a.configurable, enumerable = _a.enumerable;
return {

@@ -250,3 +468,3 @@ configurable: configurable,

var bound = value.bind(this);
defProp(this, key, {
defineProperty(this, key, {
configurable: true,

@@ -259,23 +477,56 @@ value: bound,

}
/*===========================================================================*/
/*---------------------------------------------------------------------------*/
/**
* Subscribe callback to dependency changes
* Define hidden ko.subscribable, that notifies subscribers when decorated method is invoked
*/
function subscribe(getDependency, callback, options) {
function event(prototype, key) {
defineProperty(prototype, key, {
configurable: true,
get: function () {
return defineEventProperty(this, key);
},
});
}
/**
* Subscribe callback to `@observable` or `@computed` dependency changes or to some `@event`
*/
function subscribe(dependencyOrEvent, callback, options) {
var once = options && options.once || false;
var event = options && options.event || "change";
var dependency = ko.computed(getDependency);
var subscription = dependency.subscribe(callback, null, event);
var originalDispose = subscription.dispose;
// dispose hidden computed with subscription
subscription.dispose = function () {
originalDispose.call(this);
dependency.dispose();
};
if (once) {
dependency.subscribe(function () {
subscription.dispose();
});
if (hasOwnProperty(dependencyOrEvent, "subscribe")) {
// subscribe to @event
var event_1 = dependencyOrEvent;
if (once) {
var subscription_1 = event_1.subscribe(function () {
subscription_1.dispose();
callback.apply(null, arguments);
});
return subscription_1;
}
else {
return event_1.subscribe(callback);
}
}
return subscription;
else {
// subscribe to @observable, @reactive or @computed
var event_2 = options && options.event || "change";
var computed_1 = ko.computed(dependencyOrEvent);
var handler = void 0;
if (once) {
handler = function () {
subscription_2.dispose();
callback.apply(null, arguments);
};
}
else {
handler = callback;
}
var subscription_2 = computed_1.subscribe(handler, null, event_2);
var originalDispose_1 = subscription_2.dispose;
// dispose hidden computed with subscription
subscription_2.dispose = function () {
originalDispose_1.call(this);
computed_1.dispose();
};
return subscription_2;
}
}

@@ -290,11 +541,13 @@ /**

}
return getDescriptor(instance, key).get;
return getOwnPropertyDescriptor(instance, key).get;
}
exports.component = component;
exports.observable = observable$1;
exports.reactive = reactive;
exports.computed = computed$1;
exports.observableArray = observableArray$1;
exports.extend = extend;
exports.component = component;
exports.autobind = autobind;
exports.event = event;
exports.subscribe = subscribe;

@@ -301,0 +554,0 @@ exports.unwrap = unwrap;

@@ -1,2 +0,2 @@

!function(e,t){"object"==typeof exports&&"undefined"!=typeof module?t(exports,require("knockout")):"function"==typeof define&&define.amd?define(["exports","knockout"],t):t(e.KnockoutDecorators=e.KnockoutDecorators||{},e.ko)}(this,function(e,t){"use strict";function n(e,n,r,o){return void 0===o&&(void 0===r?"object"!=typeof n||n.constructor!==Object||"require"in n||"element"in n||(o=n,n=void 0):"object"==typeof r&&(o=r,r=void 0)),function(r){t.components.register(e,v({viewModel:r.length<2?r:{createViewModel:function(e,t){var n=t.element,o=t.templateNodes;return new r(e,n,o)}},template:n||"<!---->",synchronous:!0},o))}}function r(e,n){y(e,n,{configurable:!0,get:function(){var e=f(this,n,t.observable());return y(this,n,{configurable:!0,enumerable:!0,get:e,set:e}),e()},set:function(e){var r=f(this,n,t.observable());y(this,n,{configurable:!0,enumerable:!0,get:r,set:r}),r(e)}})}function o(e,n,r){var o=r||(r=g(e,n)),i=o.get,u=o.set;return r.get=function(){var e=f(this,n,t.pureComputed(i,this));return y(this,n,{configurable:!0,get:e,set:u}),e()},r}function i(e,n){function r(e){k.forEach(function(t){return y(e,t,{configurable:!0,value:function(){if(i)return Array.prototype[t].apply(e,arguments);i=!0;var n=o[t].apply(o,arguments);return i=!1,n}})}),A.forEach(function(t){return y(e,t,{configurable:!0,value:function(){i=!0;var e=o[t].apply(o,arguments);return i=!1,e}})})}var o=f(e,n,t.observableArray()),i=!1;y(e,n,{configurable:!0,enumerable:!0,get:o,set:function(e){var t=o.peek();t!==e&&(Array.isArray(t)&&m(t,"subscribe")&&u(t),Array.isArray(e)&&(m(e,"subscribe")&&(e=j(e)),r(e))),i=!0,o(e),i=!1}})}function u(e){k.forEach(function(t){delete e[t]}),A.forEach(function(t){delete e[t]})}function c(e,t){y(e,t,{configurable:!0,get:function(){return i(this,t),this[t]=[],this[t]},set:function(e){i(this,t),this[t]=e}})}function s(e){var t=e[O];return e.hasOwnProperty(O)||(e[O]=t=v({},t),h(t,function(e,n){t[e]=n.slice()})),t}function a(e,t){return e[t]||(e[t]=[])}function f(e,t,n){var r=e[O],o=r&&r[t];return o&&o.forEach(function(t){var r=t instanceof Function?t.call(e):t;n=n.extend(r)}),n}function l(e){return function(t,n){var r=s(t),o=a(r,n);o.push(e)}}function b(e,t,n){var r=n||(n=g(e,t)),o=r.value,i=r.configurable,u=r.enumerable;return{configurable:i,enumerable:u,get:function(){if(this===e)return o;var n=o.bind(this);return y(this,t,{configurable:!0,value:n}),n}}}function p(e,n,r){var o=r&&r.once||!1,i=r&&r.event||"change",u=t.computed(e),c=u.subscribe(n,null,i),s=c.dispose;return c.dispose=function(){s.call(this),u.dispose()},o&&u.subscribe(function(){c.dispose()}),c}function d(e,t){return m(e,t)||e[t],g(e,t).get}var v=t.utils.extend,h=t.utils.objectForEach,y=Object.defineProperty.bind(Object),g=Object.getOwnPropertyDescriptor.bind(Object),m=Function.prototype.call.bind(Object.prototype.hasOwnProperty),j=Function.prototype.call.bind(Array.prototype.slice),k=["pop","push","reverse","shift","sort","splice","unshift"],A=["remove","removeAll","destroy","destroyAll","replace","subscribe"],O="undefined"!=typeof Symbol?Symbol("ko_decorators"):"__ko_decorators__";e.component=n,e.observable=r,e.computed=o,e.observableArray=c,e.extend=l,e.autobind=b,e.subscribe=p,e.unwrap=d,Object.defineProperty(e,"__esModule",{value:!0})});
!function(e,r){"object"==typeof exports&&"undefined"!=typeof module?r(exports,require("knockout")):"function"==typeof define&&define.amd?define(["exports","knockout"],r):r(e.KnockoutDecorators=e.KnockoutDecorators||{},e.ko)}(this,function(e,r){"use strict";function t(e,r,t){var n=e[x],o=n&&n[r];return o&&o.forEach(function(r){var n=r instanceof Function?r.call(e):r;t=t.extend(n)}),t}function n(e,r,t){var n=e[x];k(e,x)||(e[x]=n=m({},n),A(n,function(e,r){n[e]=r.slice()}));var o=n[r]||(n[r]=[]);o.push(t)}function o(e,n,o,i){function a(e){var r=l.peek();if(r!==e&&(Array.isArray(r)&&k(r,"mutate")&&F.forEach(function(e){delete r[e]}),Array.isArray(e))){if(k(e,"mutate")&&(e=e.slice()),i)for(var t=0;t<e.length;++t)e[t]=u(e[t]);c(e)}s=!0,l(e),s=!1}function c(e){var r=i?E:S;r.forEach(function(r){return _(e,r,{configurable:!0,value:function(){if(s)return Array.prototype[r].apply(e,arguments);s=!0;var t=l[r].apply(l,arguments);return s=!1,t}})});var t=i?M:P;t.forEach(function(r){return _(e,r,{configurable:!0,value:function(){s=!0;var e=l[r].apply(l,arguments);return s=!1,e}})}),i?(_(e,"push",{configurable:!0,value:function(){if(s)return Array.prototype.push.apply(e,arguments);for(var r=O(arguments),t=0;t<r.length;++t)r[t]=u(r[t]);s=!0;var n=l.push.apply(l,r);return s=!1,n}}),_(e,"unshift",{configurable:!0,value:function(){if(s)return Array.prototype.unshift.apply(e,arguments);for(var r=O(arguments),t=0;t<r.length;++t)r[t]=u(r[t]);s=!0;var n=l.unshift.apply(l,r);return s=!1,n}}),_(e,"splice",{configurable:!0,value:function(){if(s)return Array.prototype.splice.apply(e,arguments);var r;switch(s=!0,arguments.length){case 0:case 1:case 2:r=l.splice.apply(l,arguments);break;case 3:r=l.splice(arguments[0],arguments[1],u(arguments[2]));break;default:for(var t=O(arguments),n=2;n<t.length;++n)t[n]=u(t[n]);r=l.splice.apply(l,arguments)}return s=!1,r}}),_(e,"replace",{configurable:!0,value:function(e,r){s=!0;var t=l.replace(e,u(r));return s=!1,t}}),_(e,"mutate",{configurable:!0,value:function(e){var r=l.peek();l.valueWillMutate(),e(r);for(var t=0;t<r.length;++t)r[t]=u(r[t]);l.valueHasMutated()}}),_(e,"set",{configurable:!0,value:function(e,r){return l.splice(e,1,u(r))[0]}})):(_(e,"mutate",{configurable:!0,value:function(e){l.valueWillMutate(),e(l.peek()),l.valueHasMutated()}}),_(e,"set",{configurable:!0,value:function(e,r){return l.splice(e,1,r)[0]}}))}var l=t(e,n,r.observableArray()),s=!1;_(e,n,{configurable:!0,enumerable:!0,get:l,set:a}),a(o)}function i(e,n,o,i){var a=t(e,n,r.observable()),c=a;i&&(c=function(e){a(u(e))}),_(e,n,{configurable:!0,enumerable:!0,get:a,set:c}),c(o)}function u(e){if("object"==typeof e){if(Array.isArray(e)||null===e)return e;if(e.constructor===Object)return a(e);if(k(e,"constructor")){var r=w(e);if(r===Object.prototype||null===r)return a(e)}}return e}function a(e){return k(e,z)||(_(e,z,{configurable:!0,value:void 0}),A(e,function(r,t){Array.isArray(t)?o(e,r,t,!0):i(e,r,t,!0)})),e}function c(e,t){var n=new r.subscribable,o=function(){var e=O(arguments);n.notifySubscribers(e)};return o.subscribe=function(e){return n.subscribe(function(r){e.apply(null,r)})},_(e,t,{configurable:!0,value:o}),o}function l(e,r){_(e,r,{configurable:!0,get:function(){throw new Error("@observable property '"+r.toString()+"' was not initialized")},set:function(e){Array.isArray(e)?o(this,r,e,!1):i(this,r,e,!1)}})}function s(e,r){_(e,r,{configurable:!0,get:function(){throw new Error("@reactive property '"+r.toString()+"' was not initialized")},set:function(e){Array.isArray(e)?o(this,r,e,!0):i(this,r,e,!0)}})}function f(e,n,o){var i=o||(o=j(e,n)),u=i.get,a=i.set;return o.get=function(){var e=t(this,n,r.pureComputed(u,this));return _(this,n,{configurable:!0,get:e,set:a}),e()},o}function p(e,r){_(e,r,{configurable:!0,get:function(){throw new Error("@observableArray property '"+r.toString()+"' was not initialized")},set:function(e){o(this,r,e,!1)}})}function b(e){return function(r,t){n(r,t,e)}}function v(e,t,n,o){return void 0===o&&(void 0===n?"object"!=typeof t||t.constructor!==Object||"require"in t||"element"in t||(o=t,t=void 0):"object"==typeof n&&(o=n,n=void 0)),function(n){r.components.register(e,m({viewModel:n.length<2?n:{createViewModel:function(e,r){var t=r.element,o=r.templateNodes;return new n(e,t,o)}},template:t||"<!---->",synchronous:!0},o))}}function y(e,r,t){var n=t||(t=j(e,r)),o=n.value,i=n.configurable,u=n.enumerable;return{configurable:i,enumerable:u,get:function(){if(this===e)return o;var t=o.bind(this);return _(this,r,{configurable:!0,value:t}),t}}}function d(e,r){_(e,r,{configurable:!0,get:function(){return c(this,r)}})}function g(e,t,n){var o=n&&n.once||!1;if(k(e,"subscribe")){var i=e;if(o){var u=i.subscribe(function(){u.dispose(),t.apply(null,arguments)});return u}return i.subscribe(t)}var a=n&&n.event||"change",c=r.computed(e),l=void 0;l=o?function(){s.dispose(),t.apply(null,arguments)}:t;var s=c.subscribe(l,null,a),f=s.dispose;return s.dispose=function(){f.call(this),c.dispose()},s}function h(e,r){return k(e,r)||e[r],j(e,r).get}var m=r.utils.extend,A=r.utils.objectForEach,_=Object.defineProperty.bind(Object),w=Object.getPrototypeOf.bind(Object),j=Object.getOwnPropertyDescriptor.bind(Object),k=Function.prototype.call.bind(Object.prototype.hasOwnProperty),O=Function.prototype.call.bind(Array.prototype.slice),x="undefined"!=typeof Symbol?Symbol("ko_decorators_extenders"):"__ko_decorators_extenders__",E=["pop","reverse","shift","sort"],S=E.concat(["push","splice","unshift"]),M=["remove","removeAll","destroy","destroyAll","replace","subscribe"],P=M.concat(["replace"]),F=S.concat(P,["mutate","set"]),z="undefined"!=typeof Symbol?Symbol("ko_decorators_reactive"):"__ko_decorators_reactive__";e.observable=l,e.reactive=s,e.computed=f,e.observableArray=p,e.extend=b,e.component=v,e.autobind=y,e.event=d,e.subscribe=g,e.unwrap=h,Object.defineProperty(e,"__esModule",{value:!0})});
//# sourceMappingURL=knockout-decorators.min.js.map
{
"name": "knockout-decorators",
"version": "0.8.0",
"version": "0.9.0",
"description": "Decorators for use Knockout JS in TypeScript and ESNext environments",

@@ -13,4 +13,5 @@ "main": "dist/knockout-decorators.js",

"build-dist": "rollup -c & rollup -c rollup.config.min.js",
"build-typings": "tsc -p tsconfig.typings.json && shx rm -rf __temp && npm run fix-typings",
"fix-typings": "shx cat src/knockout-decorators.d.ts.tmpl >> dist/knockout-decorators.d.ts",
"build-typings": "tsc -p tsconfig.typings.json && npm run move-typings && npm run fix-typings",
"move-typings": "shx cp __temp/knockout-decorators.d.ts dist/knockout-decorators.d.ts && shx rm -rf __temp",
"fix-typings": "shx echo \"export as namespace KnockoutDecorators;\" >> dist/knockout-decorators.d.ts",
"test": "jest --no-cache"

@@ -17,0 +18,0 @@ },

@@ -37,5 +37,8 @@ # Knockout Decorators

* [@computed](#knockout-decorators-computed)
* [@reactive](#knockout-decorators-reactive)
* [@observableArray](#knockout-decorators-observableArray)
* [@extend](#knockout-decorators-extend)
* [@component](#knockout-decorators-component)
* [@autobind](#knockout-decorators-autobind)
* [@event](#knockout-decorators-event)
* [subscribe](#knockout-decorators-subscribe)

@@ -51,6 +54,10 @@ * [unwrap](#knockout-decorators-unwrap)

#### <a name="knockout-decorators-observable"></a> @observable
Property decorator that creates hidden `ko.observable` with ES6 getter and setter for it
Property decorator that creates hidden `ko.observable` with ES6 getter and setter for it<br>
If initialized by Array then hidden `ko.observableArray` will be created (see [@observableArray](#knockout-decorators-observableArray))
```js
import { observable } from "knockout-decorators";
class Model {
@observable field = 123;
@observable collection = [];
};

@@ -66,5 +73,7 @@ let model = new Model();

#### <a name="knockout-decorators-computed"></a> @computed
Accessor decorator that wraps ES6 getter to hidden `ko.pureComputed`
Accessor decorator that wraps ES6 getter to hidden `ko.pureComputed`<br>
Setter is not wrapped to hidden `ko.pureComputed` and stays unchanged
```js
import { observable, computed } from "knockout-decorators";
class Person {

@@ -87,5 +96,43 @@ @observable firstName = "";

#### <a name="knockout-decorators-reactive"></a> @reactive
Like [@observable](#knockout-decorators-observable), but creates "deep observable" property (see example below)<br>
If initialized by Array then hidden `ko.observableArray` will be created (see [@observableArray](#knockout-decorators-observableArray))
```js
import { reactive } from "knockout-decorators";
class ViewModel {
@reactive deepObservable = { // like @observable
firstName: "Clive Staples", // like @observable
lastName: "Lewis", // like @observable
array: [], // like @observableArray
object: { // like @observable
foo: "bar", // like @observable
reference: null, // like @observable
},
}
}
const vm = new ViewModel();
vm.deepObservable.object.reference = {
firstName: "Clive Staples", // make @observable
lastName: "Lewis", // make @observable
};
vm.deepObservable.array.push({
firstName: "Clive Staples", // make @observable
lastName: "Lewis", // make @observable
});
```
<br>
#### <a name="knockout-decorators-observableArray"></a> @observableArray
Property decorator that creates hidden `ko.observableArray` with ES6 getter and setter for it
```js
import { observableArray } from "knockout-decorators";
class Model {

@@ -99,3 +146,3 @@ @observableArray array = [1, 2, 3];

```
Functions from `ko.observableArray` (both Knockout-specific `remove`, `removeAll`, `destroy`, `destroyAll`, `replace`<br>
Functions from `ko.observableArray` (both Knockout-specific `remove`, `removeAll`, `destroy`, `destroyAll`, `replace`
and redefined `Array.prototype` functions `pop`, `push`, `reverse`, `shift`, `sort`, `splice`, `unshift`)

@@ -105,6 +152,9 @@ are also presents in decorated poperty.<br>

And also decorated array has a `subscribe` function from `ko.subscribable`
And also decorated array has:
* a `subscribe(callback: (value: any[]) => void)` function from `ko.subscribable`,
```js
import { observableArray, ObservableArray } from "knockout-decorators";
class Model {
@observableArray array = [1, 2, 3];
@observableArray array = [1, 2, 3] as ObservableArray<number>;
};

@@ -118,10 +168,39 @@ let model = new Model();

```
* a new `mutate(callback: () => void)` function that runs callback in which we can mutate array directly,
```js
import { observableArray, ObservableArray } from "knockout-decorators";
class Model {
@observableArray array = [1, 2, 3] as ObservableArray<number>;
};
let model = new Model();
model.array.mutate(() => {
model.array[1] = 200; // this changes are observed
model.array[2] = 300; // when mutation callback stops execution
});
```
* a new `set(i: number, value: any): any` function that sets a new value at specified index and returns the old value.
```js
import { observableArray, ObservableArray } from "knockout-decorators";
class Model {
@observableArray array = [1, 2, 3] as ObservableArray<number>;
};
let model = new Model();
let oldValue = model.array.set(2, 300) // this change is observed
console.log(model.array); // [console] ➜ [1, 2, 300]
console.log(oldValue); // [console] ➜ 3
```
<br>
#### <a name="knockout-decorators-extend"></a> @extend
Apply extenders to decorated `@observable`
Apply extenders to decorated `@observable`, `@reactive`, `@observableArray` or `@computed`
```js
@extend(extenders: Object)
@extend(extendersFactory: () => Object)
@extend(extenders: Object);
@extend(extendersFactory: () => Object);
```

@@ -132,2 +211,4 @@

```js
import { observable, computed, extend } from "knockout-decorators";
class ViewModel {

@@ -178,2 +259,4 @@ rateLimit: 50;

```js
import { component } from "knockout-decorators";
@component("my-component")

@@ -195,2 +278,4 @@ class Component {

```js
import { component } from "knockout-decorators";
@component("my-component",

@@ -224,26 +309,101 @@ require("./my-component.html"),

#### <a name="knockout-decorators-autobind"></a> @autobind
Bind class method to class instance. Clone of [core-decorators.js](https://github.com/jayphelps/core-decorators.js#autobind) `@autobind`
```js
import { observable, component, autobind } from "knockout-decorators";
@component("my-component", `
<ul data-bind="foreach: array">
<li data-bind="click: $component.remove">remove me</li>
</ul>
`)
class MyComponent {
@observable array = [1, 2, 3] as ObservableArray<number>;
@autobind
remove(item: number) {
this.array.remove(item);
}
}
```
<br>
#### <a name="knockout-decorators-event"></a> @event
Create subscribable function that invokes it's subscribers when it called.<br>
All arguments that passed to `@event` function are translated to it's subscribers.<br>
Internally uses hidden `ko.subscribable`.<br>
Subscribers can be attached by calling `.subscribe()` method of `EventProperty` type or by `subscribe()` [utility](#knockout-decorators-subscribe-event).
```js
import { event, EventProperty } from "knockout-decorators";
class Producer {
@event myEvent: EventProperty;
}
class Consumer {
constructor(producer: Producer) {
producer.myEvent.subscribe((arg1, arg2) => {
console.log("lambda:", arg1, arg2);
});
// `subscription` type is `KnockoutSubscription`
const subscription = producer.myEvent.subscribe(this.onEvent);
}
@autobind
onEvent(arg1, arg2) {
console.log("method:", arg1, arg2);
}
}
const producer = new Producer();
const consumer = new Consumer(producer);
// emit @event
producer.myEvent(123, "test");
// [console] ➜ lambda: 123 "test"
// [console] ➜ method: 123 "test"
```
<br>
#### <a name="knockout-decorators-subscribe"></a> subscribe
Subscribe to `@observable` or `@computed` dependency with creation of hidden `ko.computed()`
Subscribe to `@observable` (or `@computed`) dependency with creation of hidden `ko.computed()`
```js
subscribe<T>(getDependency: () => T, callback: (value: T) => void, options?: {
once?: boolean,
event?: string,
}): KnockoutSubscription
subscribe<T>(
dependency: () => T,
callback: (value: T) => void,
options?: { once?: boolean, event?: string }
): KnockoutSubscription;
```
Or subscribe to some `@event` property
```js
subscribe<T1, T2, ...>(
event: (arg1: T1, arg2: T2, ...) => void,
callback: (arg1: T1, arg2: T2, ...) => void,
options?: { once?: boolean }
): KnockoutSubscription;
```
| Argument | Default | Description |
|:--------------|:-----------|:--------------------------------------------------------------------|
| getDependency | | Function for getting observeble property |
| callback | | Callback that handle dependency changes |
| options | `null` | Options object |
| options.once | `false` | If `true` then subscription will be disposed after first invocation |
| optons.event | `"change"` | Event for passing to Knockout native `subscribe()` |
| Argument | Default | Description |
|:------------------|:-----------|:--------------------------------------------------------------------|
| dependencyOrEvent | | (1) Function for getting observeble property (2) @event property |
| callback | | Callback that handle dependency changes or @event notifications |
| options | `null` | Options object |
| options.once | `false` | If `true` then subscription will be disposed after first invocation |
| optons.event | `"change"` | Event name for passing to Knockout native `subscribe()` |
Subscribe to `@observable` changes
```js
import { observable, subscribe } from "knockout-decorators";
class ViewModel {
@observable field = "";
@observable field = 123;
constructor() {
subscribe(() => this.field, (value) => {
console.log(value);
console.log(value); // TypeScript detects that `value` type is `number`
});

@@ -257,12 +417,41 @@

console.log(value);
}, { event: "beforeChange" });
}, { event: "beforeChange" });
}
}
```
<a name="knockout-decorators-subscribe-event"></a>Subscribe to `@event` property
```js
import { event, subscribe } from "knockout-decorators";
class ViewModel {
@event myEvent: (arg: string) => void;
constructor() {
subscribe(this.myEvent, (arg) => {
console.log(arg); // TypeScript detects that `arg` type is `string`
});
subscribe(this.myEvent, (arg) => {
console.log(arg);
}, { once: true });
// `subscription` type is `KnockoutSubscription`
const subscription = subscribe(this.myEvent, (arg) => {
console.log(arg);
});
// unsubscribe from @event
subscription.dispose();
// emit @event
this.myEvent("event argument")
}
}
```
<br>
#### <a name="knockout-decorators-unwrap"></a> unwrap
Get internal `ko.observable()` for property decodated by `@observable`
or internal `ko.pureComputed()` for property decodated by `@computed`
Get hidden `ko.observable()` for property decodated by `@observable`
or hidden `ko.pureComputed()` for property decodated by `@computed`
```js

@@ -281,2 +470,4 @@ unwrap(instance: Object, key: string | symbol): any;

```js
import { observable, extend, unwrap } from "knockout-decorators";
class MyViewModel {

@@ -328,3 +519,3 @@ @extend({ required: "MyField is required" })

### <a name="knockout-decorators-changelog"></a>
### Breaking changes from v0.7.1 to 0.8.0
### Breaking changes from v0.7.1

@@ -352,3 +543,3 @@ 1. Removed `@subscribe` decorator

So in 0.8.0 instead of `@subscribe` decorator there is shorthand function `subscribe`
So from v0.8.0 instead of `@subscribe` decorator there is shorthand function `subscribe`
with some extra functionality like "subscribe once":

@@ -363,2 +554,2 @@ ```js

}
```
```

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc