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

@dojo/compose

Package Overview
Dependencies
Maintainers
1
Versions
8
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@dojo/compose - npm Package Compare versions

Comparing version 2.0.0-beta.21 to 2.0.0-beta.22

0

aspect.d.ts

@@ -0,0 +0,0 @@ export interface AdvisingFunction extends Function {

@@ -0,0 +0,0 @@ (function (factory) {

@@ -0,0 +0,0 @@ import { EventCancelableObject } from '@dojo/interfaces/core';

@@ -0,0 +0,0 @@ (function (factory) {

@@ -0,0 +0,0 @@ import { Destroyable } from '@dojo/interfaces/bases';

@@ -0,0 +0,0 @@ (function (factory) {

@@ -0,0 +0,0 @@ import { EventTargettedObject } from '@dojo/interfaces/core';

38

bases/createEvented.js

@@ -20,2 +20,6 @@ (function (factory) {

/**
* A map that contains event type names that contain wildcards and their RegExp mapping
*/
var regexMap = new Map_1.default();
/**
* A guard which determines if the value is `Actionable`

@@ -51,2 +55,26 @@ *

/**
* Internal function to check if a target string matches a glob string that contains wildcards.
* Note: Due to limited use cases in event type name, currently only `*` that matches 0 or more characters is supported.
*
* @param globString The glob string that contains wildcards pattern
* @param targetString The string under test
* @return boolean match result
*/
function isGlobMatch(globString, targetString) {
if (globString.indexOf('*') !== -1) {
var regex = void 0;
if (regexMap.has(globString)) {
regex = regexMap.get(globString);
}
else {
regex = new RegExp("^" + globString.replace(/\*/g, '.*') + "$");
regexMap.set(globString, regex);
}
return regex.test(targetString);
}
else {
return globString === targetString;
}
}
/**
* Creates a new instance of an `Evented`

@@ -59,6 +87,8 @@ */

emit: function (event) {
var method = listenersMap.get(this).get(event.type);
if (method) {
method.call(this, event);
}
var _this = this;
listenersMap.get(this).forEach(function (method, type) {
if (isGlobMatch(type, event.type)) {
method.call(_this, event);
}
});
},

@@ -65,0 +95,0 @@ on: function () {

@@ -0,0 +0,0 @@ import { State, StatefulMixin, StatefulOptions } from '@dojo/interfaces/bases';

@@ -0,0 +0,0 @@ (function (factory) {

@@ -54,3 +54,2 @@ import { BeforeAdvice, AfterAdvice, AroundAdvice } from './aspect';

*
* @deprecated
* @param extension The object literal, class or factory to extend

@@ -72,3 +71,2 @@ * @template T The original type of the factory

*
* @deprecated
* @param base The base compose factory to extend

@@ -122,2 +120,23 @@ * @param extension The object literal, class or factory that is the extension

}
export interface ComposeFactory<T, O extends Options> extends ComposeMixinable<T, O> {
/**
* Add an initialization function to the factory's chain
*
* @param name An optional name for the function for debugging purposes
* @param init The initialization function
*/
init<P extends O>(name: string, init: ComposeInitializationFunction<T, P>): ComposeFactory<T, P>;
init<P extends O>(init: ComposeInitializationFunction<T, P>): ComposeFactory<T, P>;
}
export interface Compose {
/**
* Add the supplied initialization function to the factory's chain
*
* @param name Optional name for the init function
* @param base The base compose factory
* @param init The initialization function
*/
init<T, O, P extends O>(name: string, base: ComposeFactory<T, O>, init: ComposeInitializationFunction<T, P>): ComposeFactory<T, P>;
init<T, O, P extends O>(base: ComposeFactory<T, O>, init: ComposeInitializationFunction<T, P>): ComposeFactory<T, P>;
}
export interface OverlayFunction<T> {

@@ -218,6 +237,9 @@ /**

*
* @param mixin An object literal that describes what to mixin
* @param mixin An object literal that describes what to mixin, or a ComposeCreatedMixin that has "recorded"
* a series of operations to be performed to the base factory.
*/
mixin<U, P, S>(mixin: ComposeCreatedMixin<T, U, P, S>): ComposeFactory<T & U, O & P> & S;
mixin<U, P>(mixin: ComposeMixinable<U, P>): ComposeFactory<T & U, O & P>;
mixin<U, P>(mixin: ComposeMixinDescriptor<T, O, U, P>): ComposeFactory<T & U, O & P>;
mixin<U, P, S>(mixin: ComposeCreatedMixin<T, U, P, S>): ComposeFactory<T & U, O & P> & S;
}

@@ -229,6 +251,8 @@ export interface Compose {

* @param base The base factory that is the target of the mixin
* @param mixin An object literal that describes what to mixin
* @param mixin An object literal that describes what to mixin, or a ComposeCreatedMixin that has "recorded"
* a series of operations to be performed to the base factory.
*/
mixin<T, O, U, P>(base: ComposeFactory<T, O>, mixin: ComposeMixinable<U, P>): ComposeFactory<T & U, O & P>;
mixin<T, O, U, P>(base: ComposeFactory<T, O>, mixin: ComposeMixinDescriptor<T, O, U, P>): ComposeFactory<T & U, O & P>;
mixin<T, O, U, P, S>(base: ComposeFactory<T, O>, mixin: ComposeCreatedMixin<T, U, P, S>): ComposeFactory<T & U, O & P> & S;
}

@@ -314,2 +338,109 @@ export interface ComposeFactory<T, O extends Options> extends ComposeMixinable<T, O> {

}
/**
* Provides essentially the same methods as a compose factory, but is not a callable function.
* The arguments passed to each method modify the type of the generics, and when mixed into a ComposeFactory
* the resulting factory is the same as if these calls were made directly on the factory.
* The T and O generics behave similarly to in a compose factory, the S generic keeps track of any static modifications
* that have been made to the mixin, and the Target type indicates what type this mixin needs to be mixed into. The
* instance type in any initializer functions passed to init will be typed as Target & T if not specified.
*/
export interface ComposeCreatedMixin<Target, T, O, S> {
/**
* Extend a compose factory prototype with the supplied object literal, class, or
* factory.
*
* @param extension The object literal, class or factory that is the extension
* @template T The base type of the factory
* @template U The type of the extension
* @template O The type of the base factory options
* @template P The type of the extension factory options
*/
extend<U>(extension: U | GenericClass<U>): ComposeCreatedMixin<Target, T & U, O, S>;
extend<U>(className: string, extension: U | GenericClass<U>): ComposeCreatedMixin<Target, T & U, O, S>;
extend<U, P>(extension: ComposeFactory<U, P>): ComposeCreatedMixin<Target, T & U, O & P, S>;
extend<U, P>(className: string, extension: ComposeFactory<U, P>): ComposeCreatedMixin<Target, T & U, O & P, S>;
/**
* Override certain properties on the existing factory, returning a new factory. If the properties
* are not present in the existing factory, override will throw.
*
* @param properties The properties to override
*/
override(properties: any): this;
override(className: string, properties: any): this;
/**
* Add static properties to a factory
*
* @param staticProperties An object literal that contains methods and properties that should be "static" (e.g.
* added to the factory, instead of the factory's prototype)
*/
static<Z>(staticProperties: Z): ComposeCreatedMixin<Target, T, O, S & Z>;
/**
* A static method that takes a compose factory and applies an overlay function to the factory,
* returning a new compose factory with a mutated prototype.
*
* @param overlayFunction The function which receives the base factory's prototype
* @template T The type of the factory's prototype
* @template O The options for the factory's creation
*/
overlay(overlayFunction: OverlayFunction<T>): this;
/**
* Mixin additional mixins, initialization logic, and aspect advice into the factory
*
* @param mixin An object literal that describes what to mixin, or a ComposeCreatedMixin that has "recorded"
* a series of operations to be performed to the base factory.
*/
mixin<U, P>(mixin: ComposeMixinable<U, P>): ComposeCreatedMixin<Target, T & U, O & P, S>;
mixin<U, P>(mixin: ComposeMixinDescriptor<T, O, U, P>): ComposeCreatedMixin<Target, T & U, O & P, S>;
mixin<U, P, Z>(mixin: ComposeCreatedMixin<T, U, P, Z>): ComposeCreatedMixin<Target, T & U, O & P, S & Z>;
/**
* Extract a method from another Class or Factory and add it to the returned factory
*
* @param base The base Class or Factory
* @param method The name of the method to extract
*/
from(base: GenericClass<any> | ComposeFactory<any, any>, method: string): this;
/**
* Apply advice *before* the named method (join-point)
*
* @param method The method to apply the advice to
* @param advice The advice to be applied
*/
before(method: string, advice: BeforeAdvice): this;
/**
* Apply advice *after* the named method (join-point)
*
* @param method The method to apply the advice to
* @param advice The advice to be applied
*/
after<P>(method: string, advice: AfterAdvice<P>): this;
/**
* Apply advice *around* the named method (join-point)
*
* @param method The method to apply the advice to
* @param advice The advice to be applied
*/
around<P>(method: string, advice: AroundAdvice<P>): this;
/**
* Provide an object literal which can contain a map of advice to apply
*
* @param advice An object literal which contains the maps of advice to apply
*/
aspect(advice: AspectAdvice): this;
/**
* Add the supplied initialization function to the factory's chain
*
* @param name Optional name for the init function
* @param init The initialization function
*/
init<P extends O>(name: string, init: ComposeInitializationFunction<Target & T, P>): ComposeCreatedMixin<Target, T, P, S>;
init<P extends O>(init: ComposeInitializationFunction<Target & T, P>): ComposeCreatedMixin<Target, T, P, S>;
}
export interface Compose {
/**
* Creates a ComposeCreatedMixin. If provided, the target is used to determine the initial types for the mixin target,
* base, and in the case that the target is a ComposeFactory, the options.
* @param target Optional parameter that allows the Target, T, and sometimes O types to be inferred
*/
createMixin<Target, O, S>(target?: GenericClass<Target> | Target | ComposeFactory<Target, O>): ComposeCreatedMixin<Target, Target, O, S>;
}
export interface ComposeFactory<T, O extends Options> extends ComposeMixinable<T, O> {

@@ -316,0 +447,0 @@ /**

@@ -7,7 +7,6 @@ (function (factory) {

else if (typeof define === "function" && define.amd) {
define(["require", "exports", "@dojo/core/instrument", "@dojo/core/lang", "@dojo/shim/array", "@dojo/shim/WeakMap", "@dojo/shim/Symbol", "./aspect"], factory);
define(["require", "exports", "@dojo/core/lang", "@dojo/shim/array", "@dojo/shim/WeakMap", "@dojo/shim/Symbol", "./aspect"], factory);
}
})(function (require, exports) {
"use strict";
var instrument_1 = require("@dojo/core/instrument");
var lang_1 = require("@dojo/core/lang");

@@ -136,5 +135,5 @@ var array_1 = require("@dojo/shim/array");

function getInitFunctionNames(factory) {
var initFns = privateFactoryData.get(factory).initFns;
if (initFns) {
return initFns.map(function (fn) { return fn.name; });
var factoryData = privateFactoryData.get(factory);
if (factoryData) {
return factoryData.initFns.map(function (fn) { return fn.name; });
}

@@ -147,3 +146,2 @@ }

*
* @deprecated
*/

@@ -171,2 +169,3 @@ var doExtend = rebase(extend);

var doStatic = rebase(_static);
var doInit = rebase(init);
/**

@@ -187,3 +186,2 @@ * Take a mixin and return a factory descriptor for the mixin

}
;
/**

@@ -207,3 +205,4 @@ * Generate a factory descriptor for a class

factoryDescriptor: doFactoryDescriptor,
static: doStatic
static: doStatic,
init: doInit
};

@@ -327,3 +326,3 @@ /**

assignFactoryName(factory, className);
/* freeze the factory, so it cannot be accidently modified */
/* freeze the factory, so it cannot be accidentally modified */
Object.freeze(factory);

@@ -343,3 +342,2 @@ return factory;

function extend(base, className, extension) {
instrument_1.deprecated({ message: 'This function will be removed, use "override" instead.', name: 'extend' });
if (typeof className !== 'string') {

@@ -379,2 +377,24 @@ extension = className;

/**
* The internal implementation of adding an initialization functoin
*
* @param base The base compose factory
* @param className The optional name for the init function
* @param initFunction The initialization function
*/
function init(base, className, initFunction) {
if (typeof className !== 'string') {
initFunction = className;
className = undefined;
}
/* Label the initFunction */
if (initFunction && className) {
assignFunctionName(initFunction, "init" + className);
}
return createFactory({
className: className,
factories: [base],
initFunction: initFunction
});
}
/**
* Internal implementation of the overlay functionality, to allow a function to modify a

@@ -445,37 +465,49 @@ * compose factory prototype

/**
* A custom type guard that determines if a value is a ComposeCreatedMixin
*/
function isCreatedMixin(value) {
return value instanceof Mixin;
}
/**
* The internal implementation of mixin in values into a compose factory
*
* @param base The base compose factory that is the target for being mixed in
* @param name Optional name parameter
* @param toMixin The value to be mixed in
*/
function mixin(base, toMixin) {
/* ensure we are dealing with a mixinDescriptor */
var mixinDescriptor = isComposeMixinable(toMixin) ? toMixin.factoryDescriptor() : toMixin;
/* destructure out most of the factory creation options */
var mixin = mixinDescriptor.mixin, initFunction = mixinDescriptor.initialize, aspectAdvice = mixinDescriptor.aspectAdvice, className = mixinDescriptor.className;
/* we will at least be using the base factory to create the new one */
var factories = [base];
var proto;
/* if mixin is a compose factory, we will pass it as a factory used to create the new factory */
if (isComposeFactory(mixin)) {
factories.push(mixin);
if (isCreatedMixin(toMixin)) {
return execute(base, toMixin);
}
else {
/* of which, we can have a constructor function/class, or an object literal (or undefined) */
proto = typeof mixin === 'function' ? mixin.prototype : mixin;
/* ensure we are dealing with a mixinDescriptor */
var mixinDescriptor = isComposeMixinable(toMixin) ? toMixin.factoryDescriptor() : toMixin;
/* destructure out most of the factory creation options */
var mixin_1 = mixinDescriptor.mixin, initFunction = mixinDescriptor.initialize, aspectAdvice = mixinDescriptor.aspectAdvice, className = mixinDescriptor.className;
/* we will at least be using the base factory to create the new one */
var factories = [base];
var proto = void 0;
/* if mixin is a compose factory, we will pass it as a factory used to create the new factory */
if (isComposeFactory(mixin_1)) {
factories.push(mixin_1);
}
else {
/* of which, we can have a constructor function/class, or an object literal (or undefined) */
proto = typeof mixin_1 === 'function' ? mixin_1.prototype : mixin_1;
}
/* convert the advice, if any, to the format used by createFactory */
var advice = aspectAdviceToAdviceMap(aspectAdvice);
/* label the initFn */
if (initFunction) {
assignFunctionName(initFunction, "mixin" + (className || (isComposeFactory(mixin_1) && mixin_1.name) || base.name));
}
/* return the newly created factory */
return createFactory({
advice: advice,
factories: factories,
initFunction: initFunction,
className: className,
proto: proto
});
}
/* convert the advice, if any, to the format used by createFactory */
var advice = aspectAdviceToAdviceMap(aspectAdvice);
/* label the initFn */
if (initFunction) {
assignFunctionName(initFunction, "mixin" + (className || (isComposeFactory(mixin) && mixin.name) || base.name));
}
/* return the newly created factory */
return createFactory({
advice: advice,
factories: factories,
initFunction: initFunction,
className: className,
proto: proto
});
}

@@ -614,4 +646,124 @@ /**

}
/**
* Class that provides an implementation of the ComposeCreatedMixin interface. All method calls record their arguments
* and which method was called. When the mixin is applied these calls are retrieved and executed on the target factory.
*/
var Mixin = (function () {
function Mixin() {
this._calls = [];
}
Mixin.prototype.static = function () {
var args = [];
for (var _i = 0; _i < arguments.length; _i++) {
args[_i] = arguments[_i];
}
this._calls.push(['static', args]);
return this;
};
Mixin.prototype.extend = function () {
var args = [];
for (var _i = 0; _i < arguments.length; _i++) {
args[_i] = arguments[_i];
}
this._calls.push(['extend', args]);
return this;
};
Mixin.prototype.mixin = function () {
var args = [];
for (var _i = 0; _i < arguments.length; _i++) {
args[_i] = arguments[_i];
}
this._calls.push(['mixin', args]);
return this;
};
Mixin.prototype.overlay = function () {
var args = [];
for (var _i = 0; _i < arguments.length; _i++) {
args[_i] = arguments[_i];
}
this._calls.push(['overlay', args]);
return this;
};
Mixin.prototype.override = function () {
var args = [];
for (var _i = 0; _i < arguments.length; _i++) {
args[_i] = arguments[_i];
}
this._calls.push(['override', args]);
return this;
};
Mixin.prototype.from = function () {
var args = [];
for (var _i = 0; _i < arguments.length; _i++) {
args[_i] = arguments[_i];
}
this._calls.push(['from', args]);
return this;
};
Mixin.prototype.before = function () {
var args = [];
for (var _i = 0; _i < arguments.length; _i++) {
args[_i] = arguments[_i];
}
this._calls.push(['before', args]);
return this;
};
Mixin.prototype.after = function () {
var args = [];
for (var _i = 0; _i < arguments.length; _i++) {
args[_i] = arguments[_i];
}
this._calls.push(['after', args]);
return this;
};
Mixin.prototype.around = function () {
var args = [];
for (var _i = 0; _i < arguments.length; _i++) {
args[_i] = arguments[_i];
}
this._calls.push(['around', args]);
return this;
};
Mixin.prototype.aspect = function () {
var args = [];
for (var _i = 0; _i < arguments.length; _i++) {
args[_i] = arguments[_i];
}
this._calls.push(['aspect', args]);
return this;
};
Mixin.prototype.init = function () {
var args = [];
for (var _i = 0; _i < arguments.length; _i++) {
args[_i] = arguments[_i];
}
this._calls.push(['init', args]);
return this;
};
return Mixin;
}());
/**
* Creates a ComposeCreatedMixin. If provided, the target is used to determine the initial types for the mixin target,
* base, and in the case that the target is a ComposeFactory, the options.
* @param target Optional parameter that allows the Target, T, and sometimes O types to be inferred
*/
function createMixin(target) {
var mixin = new Mixin();
return mixin;
}
/**
* Applies a ComposeCreatedMixin to a ComposeFactory, returning a new ComposeFactory
* @param _base The compose factory to apply the mixin to
* @param toMixin The mixin to apply
*/
function execute(_base, toMixin) {
var base = _base, mixin = toMixin, calls = mixin._calls;
for (var i = 0; i < calls.length; i++) {
var _a = calls[i], fn = _a[0], args = _a[1];
base = base[fn].apply(base, args);
}
return base;
}
function create(className, base, initFunction) {
/* disambugate arguments */
/* disambiguate arguments */
if (typeof className !== 'string') {

@@ -673,3 +825,4 @@ initFunction = base;

around: around,
aspect: aspect
aspect: aspect,
createMixin: createMixin
});

@@ -676,0 +829,0 @@ Object.defineProperty(exports, "__esModule", { value: true });

@@ -0,0 +0,0 @@ import compose, { isComposeFactory } from './compose';

@@ -0,0 +0,0 @@ (function (factory) {

2

package.json
{
"name": "@dojo/compose",
"version": "2.0.0-beta.21",
"version": "2.0.0-beta.22",
"description": "A composition library, which works well in a TypeScript environment.",

@@ -5,0 +5,0 @@ "homepage": "http://dojotoolkit.org",

@@ -5,3 +5,3 @@ # @dojo/compose

[![codecov.io](http://codecov.io/github/dojo/compose/coverage.svg?branch=master)](http://codecov.io/github/dojo/compose?branch=master)
[![npm version](https://badge.fury.io/js/@dojo/compose.svg)](http://badge.fury.io/js/@dojo/compose)
[![npm version](https://badge.fury.io/js/%40dojo%2Fcompose.svg)](https://badge.fury.io/js/%40dojo%2Fcompose)

@@ -182,150 +182,65 @@ A composition library, which works well in a TypeScript environment.

```
### Adding Initialization Functions
### Mixing in Traits/State
As factories are extended or otherwise modified, it is often desirable to
provide additional initialization logic for the new factory. The `init` method
can be used to provide a new initializer to an existing factory. The type
of the instance and options will default to the type of the compose factory
prototype and the type of the options argument for the last provided
initializer.
Oftentimes the need arises to take an existing class and add not just properties, but also behavior, or traits. The `compose` module's default export has a `mixin` property that provides this functionality. It can be used to mix in another compose class:
```typescript
import * as compose from 'dojo/compose';
const fooFactory = compose.create({
foo: 'bar'
const createFoo = compose({
foo: ''
}, (instance, options: { foo: string } = { foo: 'foo' }) => {
// Instance type is inferred based on the type passed to
// compose
instance.foo = options.foo;
});
const barFactory = compose.create({
bar: function () {
console.log('bar');
}
});
const fooBarFactory = compose.mixin(fooFactory, barFactory);
const fooBar = fooBarFactory();
fooBar.bar(); // logs "bar"
const createFooWithNewInitializer = createFoo
.init((instance, options?) => {
// If we don't type the options it defaults to { foo: string }
instance.foo = (options && options.foo) || instance.foo;
});
const createFooBar = createFoo
.extend({ bar: 'bar' })
.init((instance, options?) => {
// Instance type is updated as the factory prototype is
// modified, it now has foo and bar properties
instance.foo = instance.bar = (options && options.foo) || instance.foo;
});
```
NOTE: Using mixin on a ComposeFactory will result in the init function for the mixed in factory to be called first, and any init functions for the base will follow.
It can also be used to mix in an ES6 class.
Note that when mixing in an ES6 class only methods will be mixed into the resulting class, not state.
```typescript
import * as compose from 'dojo/compose';
const fooFactory = compose.create({
foo: 'bar'
});
Sometimes, as in the `createFooBar` example above, additional properties may need to be added to the options parameter of the initialize function. A new type can be specified as a generic or by explicitly typing options in the function declaration.
class Bar {
bar() { console.log('bar'); }
}
const fooBarFactory = compose.mixin(fooFactory, { mixin: Bar });
const fooBar = fooBarFactory();
fooBar.bar(); // logs "bar"
```
It can also mixin in a plain object, but extend would be more appropriate in this case:
```typescript
import * as compose from 'dojo/compose';
const fooFactory = compose.create({
foo: 'bar'
const createFoo = compose({
foo: ''
}, (instance, options: { foo: string } = { foo: 'foo' }) => {
instance.foo = options.foo;
});
const bar = {
bar() { console.log('bar'); }
}
const fooBarFactory = compose.mixin(fooFactory, { mixin: bar });
const fooBar = fooBarFactory();
fooBar.bar(); // logs "bar"
```
The real benefit of using `mixin` is in those cases where simply modifying the type is not enough, and there is additional behavior that needs to be included via an initialization function or aspects.
```typescript
import * as compose from 'dojo/compose';
const fooFactory = compose.create({
foo: 'bar',
doSomething: function() {
console.log('something');
}
});
const bar = {
bar: 'uninitialized'
};
const initBar = function(instance: { bar: string }) {
instance.bar = 'initialized';
};
const bazFactory = compose.create({
baz: 'baz'
}, function(instance: { baz: string }) {
instance.baz = 'also initialized';
});
const bazAspect: AspectAdvice = {
after: {
doSomething: function() {
console.log('something else');
}
}
};
const fooBarBazFactory = fooFactory
.mixin({
mixin: bar,
initialize: initBar
})
.mixin({
mixin: bazFactory,
aspectAdvice: bazAspect
const createFooBar = createFoo
.extend({ bar: 'bar' })
// Extend options type with generic
.init<{ foo: string, bar: string }>((instance, options?) => {
instance.foo = (options && options.foo) || 'foo';
instance.bar = (options && options.bar) || 'bar';
});
const fooBarBaz = fooBarBazFactory();
console.log(fooBarBaz.bar); // logs 'initialized'
console.log(fooBarBaz.baz); // logs 'also initialized'
fooBarBaz.doSomething(); // logs 'something' and then 'something else'
const createFooBarToo = createFoo
.extend({ bar: 'bar' })
// Extend options type in function signature
.init(instance, options?: { foo: string, bar: string }) => {
instance.foo = (options && options.foo) || 'foo';
instance.bar = (options && options.bar) || 'bar';
});
```
Additionally, anything with a `factoryDescriptor` function that returns a `ComposeMixinDescriptor` object can be passed directy to mixin.
```typescript
const createFoo = compose({
foo: ''
})
const mixin = {
factoryDescriptor: function() {
return {
mixin: {
bar: 1
},
initialize: function(fooBar: { bar: number; foo: string; }) {
fooBar.bar = 3;
fooBar.foo = 'bar';
}
};
}
};
const createFooBar = createFoo.mixin(mixin);
const fooBar = createFooBar();
console.log(fooBar.foo) // logs 'foo'
console.log(fooBar.bar) // logs 3
```
The previous example, where a `ComposeFactory` was passed directly to `mixin` is possible because as a convenience all instances of `ComposeFactory`
are initialized with a version of the `factoryDescriptor` function that simply returns the factory itself as the `mixin` property. If a more complicated
factory descriptor is required, the `factoryDescriptor` method can be overridden using the `static` method, documented below.
### Merging of Arrays
When mixing in or extending classes which contain array literals as a value of a property, `compose` will merge these values
instead of over writting, which it does with other value types.
instead of over writing, which it does with other value types.

@@ -376,3 +291,3 @@ For example, if I have an array of strings in my original class, and provide a mixin which shares the same property that is

let fooBarFactory: FooBarClass = compose(Foo).mixin({ mixin: <any> Bar });
let fooBarFactory: FooBarClass = compose(Foo).extend(Bar);

@@ -460,2 +375,70 @@ let fooBar = fooBarFactory<number, any>();

### Mixins
One of the goals of compose is to enable the reuse of code, and to allow
clean separation of concerns. Mixins provide a way to encapsulate
functionality that may be reused across many different factories.
This example shows how to create and apply a mixin:
```typescript
const createFoo = compose({ foo: 'foo'});
const fooMixin = compose.createMixin(createFoo);
createFoo.mixin(fooMixin);
```
In this case the mixin won't actually do anything, because we applied it
immediately after creating it. Another thing to note in this exapmle, is
that passing `createFoo` to `createMixin` is optional, but is generally
a good idea. This lets the mixin know that it should be mixed into something
that provides at least the same functionality as `createFoo`, so the mixin
can automatically include the prototype and options types from `createFoo`.
In order to create a mixin that's actually useful, we can use any of the
`ComposeFactory` methods discussed above. The mixin will record these calls,
and when mixed into a factory will apply them as if they were called directly
on the factory.
```typescript
const createFoo = compose({
foo: 'foo'
}, (instance, options?: { foo: string }) => {
instance.foo = (options && options.foo) || 'foo';
});
const createFooBar = createFoo.extend({ bar: 'bar'});
const fooMixin = compose.createMixin(createFoo)
// Because we passed createFoo, the types of instance and options
// are both { foo: string }
.init((instance, options?) => {
instance.foo = (options && options.foo) + 'bar';
});
.extend({ baz: 'baz'});
const createFooBaz = createFoo.mixin(fooMixin);
/* Equivalent to calling
createFoo
.init((instance, options?) => {
instance.foo = (options && options.foo) + 'bar';
});
.extend({ baz: 'baz'});
*/
const createFooBarBaz = createFooBar.mixin(fooMixin);
/* Equivalent to calling
createFooBar
.init((instance, options?) => {
instance.foo = (options && options.foo) + 'bar';
});
.extend({ baz: 'baz'});
*/
```
Compose also provides the ability to mixin a factory directly, or a
`FactoryDescriptor` object, but these are allowed only for the backwards
compatibility. The `createMixin` API is the preferred method for creating
and applying mixins.
## How do I use this package?

@@ -484,3 +467,2 @@

```
## How do I contribute?

@@ -487,0 +469,0 @@

@@ -0,0 +0,0 @@ export interface CancelableEvent<T extends string, U> {

@@ -0,0 +0,0 @@ (function (factory) {

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

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