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

cycle-gear

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

cycle-gear - npm Package Compare versions

Comparing version 4.1.0 to 5.0.0

@@ -13,2 +13,3 @@ import { Observable } from 'xstream';

export interface Gear<TActions, TModel> {
name?: string;
catch?: (error: any, actions: TActions) => Observable<any>;

@@ -19,3 +20,9 @@ intent?: (sources: any) => TActions;

}
export declare type ToothReduce<TActions, TModel, TAccumulator> = (accumulator: TAccumulator, current: [TModel, Gear<TActions, TModel>]) => TAccumulator;
export interface ToothConnector<TActions, TModel, TAccumulator> {
reduce: ToothReduce<TActions, TModel, TAccumulator>;
init: () => TAccumulator;
}
export declare type Transmission = ((sources: any) => Observable<Gear<any, any>>) | Observable<Gear<any, any>>;
export declare type Gearbox = ((sources: any) => Observable<Iterable<Gear<any, any>>>) | Observable<Iterable<Gear<any, any>>>;
export interface PedalOptions {

@@ -26,2 +33,8 @@ defaultGear?: Gear<any, any>;

}
export interface MotorOptions extends PedalOptions {
sourcesWrapper?: (sources: any, gear: Gear<any, any>) => any;
defaultConnector?: ToothConnector<any, any, any>;
connectors?: Map<string, ToothReduce<any, any, any>>;
}
export declare function pedal(transmission: Transmission, {defaultGear, defaultFilter, sinkMap}?: PedalOptions): (sources: any) => {};
export declare function motor(gearbox: Gearbox, {defaultGear, defaultFilter, defaultConnector, sourcesWrapper, connectors, sinkMap}?: MotorOptions): (sources: any) => {};
import { adapt } from '@cycle/run/lib/adapt';
import xs from 'xstream';
export function pedal(transmission, { defaultGear = { intent: () => ({}), model: () => xs.of({}), teeth: {} }, defaultFilter = () => true, sinkMap = new Map() } = {}) {
function defaultsAndHelpers(defaultGear, defaultFilter) {
const defaultCatch = defaultGear.catch || ((error) => xs.throw(error));

@@ -43,2 +43,25 @@ const defaultIntent = defaultGear.intent || (() => ({}));

};
return { defaultIntent, defaultModel, defaultCatch, teeth, toothFilter, toothView, emptyTeeth };
}
function spinGear(sources, defaultIntent, defaultModel, defaultCatch, teeth, toothFilter, toothView) {
const modelCache = new WeakMap();
return gear => {
let state;
if (modelCache.has(gear)) {
state = modelCache.get(gear);
}
else {
const actions = gear.intent ? gear.intent(sources) : defaultIntent(sources);
state = xs.fromObservable(gear.model ? gear.model(actions) : defaultModel(actions))
.replaceError((err) => xs.fromObservable(gear.catch ? gear.catch(err, actions) : defaultCatch(err, actions)))
.remember();
}
const views = teeth.reduce((accum, tooth) => Object.assign(accum, {
[tooth]: state.filter(toothFilter(tooth, (gear.teeth || {})[tooth])).map(toothView(tooth, (gear.teeth || {})[tooth]))
}), {});
return views;
};
}
export function pedal(transmission, { defaultGear = { intent: () => ({}), model: () => xs.of({}), teeth: {} }, defaultFilter = () => true, sinkMap = new Map() } = {}) {
const { defaultIntent, defaultModel, defaultCatch, teeth, toothFilter, toothView, emptyTeeth } = defaultsAndHelpers(defaultGear, defaultFilter);
return (sources) => {

@@ -53,12 +76,3 @@ let gear;

const spin = xs.fromObservable(gear)
.map(gear => {
const actions = gear.intent ? gear.intent(sources) : defaultIntent(sources);
const state = xs.fromObservable(gear.model ? gear.model(actions) : defaultModel(actions))
.replaceError((err) => xs.fromObservable(gear.catch ? gear.catch(err, actions) : defaultCatch(err, actions)))
.remember();
const views = teeth.reduce((accum, tooth) => Object.assign(accum, {
[tooth]: state.filter(toothFilter(tooth, (gear.teeth || {})[tooth])).map(toothView(tooth, (gear.teeth || {})[tooth]))
}), {});
return views;
})
.map(spinGear(sources, defaultIntent, defaultModel, defaultCatch, teeth, toothFilter, toothView))
.startWith(emptyTeeth)

@@ -72,1 +86,51 @@ .remember();

}
function spinGears(sources, defaultIntent, defaultModel, defaultCatch, teeth, toothFilter, toothView, sourcesWrapper, defaultConnector, connectors) {
const modelCache = new WeakMap();
return gears => {
const views = teeth.reduce((acc, cur) => (Object.assign({}, acc, { [cur]: [] })), {});
for (let gear of gears) {
let state;
if (modelCache.has(gear)) {
state = modelCache.get(gear);
}
else {
const wrappedSources = sourcesWrapper(sources, gear);
const actions = gear.intent ? gear.intent(wrappedSources) : defaultIntent(wrappedSources);
state = xs.fromObservable(gear.model ? gear.model(actions) : defaultModel(actions))
.replaceError((err) => xs.fromObservable(gear.catch ? gear.catch(err, actions) : defaultCatch(err, actions)))
.remember();
}
for (let tooth of teeth) {
views[tooth].push(state
.filter(toothFilter(tooth, (gear.teeth || {})[tooth]))
.map(state => [toothView(tooth, (gear.teeth || {})[tooth])(state), gear]));
}
}
return teeth.reduce((accum, tooth) => (Object.assign({}, accum, { [tooth]: xs.merge(...views[tooth])
.fold(connectors.has(tooth) ? connectors.get(tooth).reduce : defaultConnector.reduce, connectors.has(tooth) ? connectors.get(tooth).init() : defaultConnector.init()) })), {});
};
}
const defaultDefaultConnector = {
reduce: (acc, [cur, gear]) => (Object.assign({}, acc, { [gear.name || '?']: cur })),
init: () => ({})
};
export function motor(gearbox, { defaultGear = { intent: () => ({}), model: () => xs.of({}), teeth: {} }, defaultFilter = () => true, defaultConnector = defaultDefaultConnector, sourcesWrapper = (sources) => sources, connectors = new Map(), sinkMap = new Map() } = {}) {
const { defaultIntent, defaultModel, defaultCatch, teeth, toothFilter, toothView, emptyTeeth } = defaultsAndHelpers(defaultGear, defaultFilter);
return (sources) => {
let gears;
if (gearbox instanceof Function) {
gears = gearbox(sources);
}
else {
gears = gearbox;
}
const spin = xs.fromObservable(gears)
.map(spinGears(sources, defaultIntent, defaultModel, defaultCatch, teeth, toothFilter, toothView, sourcesWrapper, defaultConnector, connectors))
.startWith(emptyTeeth)
.remember();
const sinks = teeth.reduce((accum, tooth) => Object.assign(accum, {
[sinkMap.has(tooth) ? sinkMap.get(tooth) : tooth]: adapt(spin.map((views) => views[tooth]).flatten())
}), {});
return sinks;
};
}

@@ -13,2 +13,3 @@ import { Observable } from 'xstream';

export interface Gear<TActions, TModel> {
name?: string;
catch?: (error: any, actions: TActions) => Observable<any>;

@@ -19,3 +20,9 @@ intent?: (sources: any) => TActions;

}
export declare type ToothReduce<TActions, TModel, TAccumulator> = (accumulator: TAccumulator, current: [TModel, Gear<TActions, TModel>]) => TAccumulator;
export interface ToothConnector<TActions, TModel, TAccumulator> {
reduce: ToothReduce<TActions, TModel, TAccumulator>;
init: () => TAccumulator;
}
export declare type Transmission = ((sources: any) => Observable<Gear<any, any>>) | Observable<Gear<any, any>>;
export declare type Gearbox = ((sources: any) => Observable<Iterable<Gear<any, any>>>) | Observable<Iterable<Gear<any, any>>>;
export interface PedalOptions {

@@ -26,2 +33,8 @@ defaultGear?: Gear<any, any>;

}
export interface MotorOptions extends PedalOptions {
sourcesWrapper?: (sources: any, gear: Gear<any, any>) => any;
defaultConnector?: ToothConnector<any, any, any>;
connectors?: Map<string, ToothReduce<any, any, any>>;
}
export declare function pedal(transmission: Transmission, {defaultGear, defaultFilter, sinkMap}?: PedalOptions): (sources: any) => {};
export declare function motor(gearbox: Gearbox, {defaultGear, defaultFilter, defaultConnector, sourcesWrapper, connectors, sinkMap}?: MotorOptions): (sources: any) => {};
"use strict";
var __assign = (this && this.__assign) || Object.assign || function(t) {
for (var s, i = 1, n = arguments.length; i < n; i++) {
s = arguments[i];
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p))
t[p] = s[p];
}
return t;
};
var __values = (this && this.__values) || function (o) {
var m = typeof Symbol === "function" && o[Symbol.iterator], i = 0;
if (m) return m.call(o);
return {
next: function () {
if (o && i >= o.length) o = void 0;
return { value: o && o[i++], done: !o };
}
};
};
var __read = (this && this.__read) || function (o, n) {
var m = typeof Symbol === "function" && o[Symbol.iterator];
if (!m) return o;
var i = m.call(o), r, ar = [], e;
try {
while ((n === void 0 || n-- > 0) && !(r = i.next()).done) ar.push(r.value);
}
catch (error) { e = { error: error }; }
finally {
try {
if (r && !r.done && (m = i["return"])) m.call(i);
}
finally { if (e) throw e.error; }
}
return ar;
};
var __spread = (this && this.__spread) || function () {
for (var ar = [], i = 0; i < arguments.length; i++) ar = ar.concat(__read(arguments[i]));
return ar;
};
Object.defineProperty(exports, "__esModule", { value: true });
var adapt_1 = require("@cycle/run/lib/adapt");
var xstream_1 = require("xstream");
function pedal(transmission, _a) {
var _b = _a === void 0 ? {} : _a, _c = _b.defaultGear, defaultGear = _c === void 0 ? { intent: function () { return ({}); }, model: function () { return xstream_1.default.of({}); }, teeth: {} } : _c, _d = _b.defaultFilter, defaultFilter = _d === void 0 ? function () { return true; } : _d, _e = _b.sinkMap, sinkMap = _e === void 0 ? new Map() : _e;
function defaultsAndHelpers(defaultGear, defaultFilter) {
var defaultCatch = defaultGear.catch || (function (error) { return xstream_1.default.throw(error); });

@@ -18,11 +55,20 @@ var defaultIntent = defaultGear.intent || (function () { return ({}); });

if (defaultGear.teeth) {
for (var _i = 0, teeth_1 = teeth; _i < teeth_1.length; _i++) {
var tooth = teeth_1[_i];
var defGearTooth = defaultGear.teeth[tooth];
if (defGearTooth instanceof Function) {
toothDefaults[tooth] = { filter: defaultFilter, view: defGearTooth };
try {
for (var teeth_1 = __values(teeth), teeth_1_1 = teeth_1.next(); !teeth_1_1.done; teeth_1_1 = teeth_1.next()) {
var tooth = teeth_1_1.value;
var defGearTooth = defaultGear.teeth[tooth];
if (defGearTooth instanceof Function) {
toothDefaults[tooth] = { filter: defaultFilter, view: defGearTooth };
}
else {
toothDefaults[tooth] = { filter: defGearTooth.filter || defaultFilter, view: defGearTooth.view };
}
}
else {
toothDefaults[tooth] = { filter: defGearTooth.filter || defaultFilter, view: defGearTooth.view };
}
catch (e_1_1) { e_1 = { error: e_1_1 }; }
finally {
try {
if (teeth_1_1 && !teeth_1_1.done && (_a = teeth_1.return)) _a.call(teeth_1);
}
finally { if (e_1) throw e_1.error; }
}

@@ -51,2 +97,30 @@ }

};
return { defaultIntent: defaultIntent, defaultModel: defaultModel, defaultCatch: defaultCatch, teeth: teeth, toothFilter: toothFilter, toothView: toothView, emptyTeeth: emptyTeeth };
var e_1, _a;
}
function spinGear(sources, defaultIntent, defaultModel, defaultCatch, teeth, toothFilter, toothView) {
var modelCache = new WeakMap();
return function (gear) {
var state;
if (modelCache.has(gear)) {
state = modelCache.get(gear);
}
else {
var actions_1 = gear.intent ? gear.intent(sources) : defaultIntent(sources);
state = xstream_1.default.fromObservable(gear.model ? gear.model(actions_1) : defaultModel(actions_1))
.replaceError(function (err) { return xstream_1.default.fromObservable(gear.catch ? gear.catch(err, actions_1) : defaultCatch(err, actions_1)); })
.remember();
}
var views = teeth.reduce(function (accum, tooth) {
return Object.assign(accum, (_a = {},
_a[tooth] = state.filter(toothFilter(tooth, (gear.teeth || {})[tooth])).map(toothView(tooth, (gear.teeth || {})[tooth])),
_a));
var _a;
}, {});
return views;
};
}
function pedal(transmission, _a) {
var _b = _a === void 0 ? {} : _a, _c = _b.defaultGear, defaultGear = _c === void 0 ? { intent: function () { return ({}); }, model: function () { return xstream_1.default.of({}); }, teeth: {} } : _c, _d = _b.defaultFilter, defaultFilter = _d === void 0 ? function () { return true; } : _d, _e = _b.sinkMap, sinkMap = _e === void 0 ? new Map() : _e;
var _f = defaultsAndHelpers(defaultGear, defaultFilter), defaultIntent = _f.defaultIntent, defaultModel = _f.defaultModel, defaultCatch = _f.defaultCatch, teeth = _f.teeth, toothFilter = _f.toothFilter, toothView = _f.toothView, emptyTeeth = _f.emptyTeeth;
return function (sources) {

@@ -61,15 +135,3 @@ var gear;

var spin = xstream_1.default.fromObservable(gear)
.map(function (gear) {
var actions = gear.intent ? gear.intent(sources) : defaultIntent(sources);
var state = xstream_1.default.fromObservable(gear.model ? gear.model(actions) : defaultModel(actions))
.replaceError(function (err) { return xstream_1.default.fromObservable(gear.catch ? gear.catch(err, actions) : defaultCatch(err, actions)); })
.remember();
var views = teeth.reduce(function (accum, tooth) {
return Object.assign(accum, (_a = {},
_a[tooth] = state.filter(toothFilter(tooth, (gear.teeth || {})[tooth])).map(toothView(tooth, (gear.teeth || {})[tooth])),
_a));
var _a;
}, {});
return views;
})
.map(spinGear(sources, defaultIntent, defaultModel, defaultCatch, teeth, toothFilter, toothView))
.startWith(emptyTeeth)

@@ -87,1 +149,93 @@ .remember();

exports.pedal = pedal;
function spinGears(sources, defaultIntent, defaultModel, defaultCatch, teeth, toothFilter, toothView, sourcesWrapper, defaultConnector, connectors) {
var modelCache = new WeakMap();
return function (gears) {
var views = teeth.reduce(function (acc, cur) {
return (__assign({}, acc, (_a = {}, _a[cur] = [], _a)));
var _a;
}, {});
var _loop_1 = function (gear) {
var state = void 0;
if (modelCache.has(gear)) {
state = modelCache.get(gear);
}
else {
var wrappedSources = sourcesWrapper(sources, gear);
var actions_2 = gear.intent ? gear.intent(wrappedSources) : defaultIntent(wrappedSources);
state = xstream_1.default.fromObservable(gear.model ? gear.model(actions_2) : defaultModel(actions_2))
.replaceError(function (err) { return xstream_1.default.fromObservable(gear.catch ? gear.catch(err, actions_2) : defaultCatch(err, actions_2)); })
.remember();
}
var _loop_2 = function (tooth) {
views[tooth].push(state
.filter(toothFilter(tooth, (gear.teeth || {})[tooth]))
.map(function (state) { return [toothView(tooth, (gear.teeth || {})[tooth])(state), gear]; }));
};
try {
for (var teeth_2 = __values(teeth), teeth_2_1 = teeth_2.next(); !teeth_2_1.done; teeth_2_1 = teeth_2.next()) {
var tooth = teeth_2_1.value;
_loop_2(tooth);
}
}
catch (e_2_1) { e_2 = { error: e_2_1 }; }
finally {
try {
if (teeth_2_1 && !teeth_2_1.done && (_a = teeth_2.return)) _a.call(teeth_2);
}
finally { if (e_2) throw e_2.error; }
}
var e_2, _a;
};
try {
for (var gears_1 = __values(gears), gears_1_1 = gears_1.next(); !gears_1_1.done; gears_1_1 = gears_1.next()) {
var gear = gears_1_1.value;
_loop_1(gear);
}
}
catch (e_3_1) { e_3 = { error: e_3_1 }; }
finally {
try {
if (gears_1_1 && !gears_1_1.done && (_a = gears_1.return)) _a.call(gears_1);
}
finally { if (e_3) throw e_3.error; }
}
return teeth.reduce(function (accum, tooth) {
return (__assign({}, accum, (_a = {}, _a[tooth] = xstream_1.default.merge.apply(xstream_1.default, __spread(views[tooth])).fold(connectors.has(tooth) ? connectors.get(tooth).reduce : defaultConnector.reduce, connectors.has(tooth) ? connectors.get(tooth).init() : defaultConnector.init()), _a)));
var _a;
}, {});
var e_3, _a;
};
}
var defaultDefaultConnector = {
reduce: function (acc, _a) {
var _b = __read(_a, 2), cur = _b[0], gear = _b[1];
return (__assign({}, acc, (_c = {}, _c[gear.name || '?'] = cur, _c)));
var _c;
},
init: function () { return ({}); }
};
function motor(gearbox, _a) {
var _b = _a === void 0 ? {} : _a, _c = _b.defaultGear, defaultGear = _c === void 0 ? { intent: function () { return ({}); }, model: function () { return xstream_1.default.of({}); }, teeth: {} } : _c, _d = _b.defaultFilter, defaultFilter = _d === void 0 ? function () { return true; } : _d, _e = _b.defaultConnector, defaultConnector = _e === void 0 ? defaultDefaultConnector : _e, _f = _b.sourcesWrapper, sourcesWrapper = _f === void 0 ? function (sources) { return sources; } : _f, _g = _b.connectors, connectors = _g === void 0 ? new Map() : _g, _h = _b.sinkMap, sinkMap = _h === void 0 ? new Map() : _h;
var _j = defaultsAndHelpers(defaultGear, defaultFilter), defaultIntent = _j.defaultIntent, defaultModel = _j.defaultModel, defaultCatch = _j.defaultCatch, teeth = _j.teeth, toothFilter = _j.toothFilter, toothView = _j.toothView, emptyTeeth = _j.emptyTeeth;
return function (sources) {
var gears;
if (gearbox instanceof Function) {
gears = gearbox(sources);
}
else {
gears = gearbox;
}
var spin = xstream_1.default.fromObservable(gears)
.map(spinGears(sources, defaultIntent, defaultModel, defaultCatch, teeth, toothFilter, toothView, sourcesWrapper, defaultConnector, connectors))
.startWith(emptyTeeth)
.remember();
var sinks = teeth.reduce(function (accum, tooth) {
return Object.assign(accum, (_a = {},
_a[sinkMap.has(tooth) ? sinkMap.get(tooth) : tooth] = adapt_1.adapt(spin.map(function (views) { return views[tooth]; }).flatten()),
_a));
var _a;
}, {});
return sinks;
};
}
exports.motor = motor;

@@ -18,2 +18,3 @@ import { adapt } from '@cycle/run/lib/adapt'

export interface Gear<TActions, TModel> {
name?: string
catch?: (error: any, actions: TActions) => Observable<any>

@@ -25,4 +26,13 @@ intent?: (sources: any) => TActions

export type ToothReduce<TActions, TModel, TAccumulator> = (accumulator: TAccumulator, current: [TModel, Gear<TActions, TModel>]) => TAccumulator
export interface ToothConnector<TActions, TModel, TAccumulator> {
reduce: ToothReduce<TActions, TModel, TAccumulator>
init: () => TAccumulator
}
export type Transmission = ((sources: any) => Observable<Gear<any, any>>) | Observable<Gear<any, any>>
export type Gearbox = ((sources: any) => Observable<Iterable<Gear<any, any>>>) | Observable<Iterable<Gear<any, any>>>
export interface PedalOptions {

@@ -34,16 +44,18 @@ defaultGear?: Gear<any, any>

export function pedal(transmission: Transmission, {
defaultGear = { intent: () => ({}), model: () => xs.of({}), teeth: {} as GearTeeth<any> },
defaultFilter = () => true,
sinkMap = new Map()
}: PedalOptions = {}) {
export interface MotorOptions extends PedalOptions {
sourcesWrapper?: (sources: any, gear: Gear<any, any>) => any
defaultConnector?: ToothConnector<any, any, any>
connectors?: Map<string, ToothReduce<any, any, any>>
}
function defaultsAndHelpers(defaultGear: Gear<any, any>, defaultFilter: (model: any) => boolean) {
const defaultCatch = defaultGear.catch || ((error: any) => xs.throw(error))
const defaultIntent = defaultGear.intent || (() => ({}))
const defaultModel = defaultGear.model || (() => xs.of({}))
// Fully expand tooth defaults to avoid doing all the tests below every time
const toothDefaults: { [name: string]: GearTooth<any> } = {}
const toothDefaults: {
[name: string]: GearTooth<any>
} = {}
const teeth = Object.keys(defaultGear.teeth || {})
const emptyTeeth = teeth.reduce((accum, cur) => Object.assign(accum, { [cur]: xs.never() }), {})
if (defaultGear.teeth) {

@@ -54,3 +66,4 @@ for (let tooth of teeth) {

toothDefaults[tooth] = { filter: defaultFilter, view: defGearTooth }
} else {
}
else {
toothDefaults[tooth] = { filter: defGearTooth.filter || defaultFilter, view: defGearTooth.view }

@@ -65,3 +78,4 @@ }

return toothDefaults[name].filter || defaultFilter
} else {
}
else {
return tooth.filter || toothDefaults[name].filter || defaultFilter

@@ -75,5 +89,7 @@ }

return toothDefaults[name].view
} else if (tooth instanceof Function) {
}
else if (tooth instanceof Function) {
return tooth
} else {
}
else {
return tooth.view

@@ -83,2 +99,45 @@ }

return { defaultIntent, defaultModel, defaultCatch, teeth, toothFilter, toothView, emptyTeeth }
}
function spinGear(sources: any,
defaultIntent: (sources: any) => any,
defaultModel: (actions: any) => Observable<any>,
defaultCatch: (error: any, actions: any) => Observable<any>,
teeth: string[],
toothFilter: (name: string, tooth: GearTooth<any> | GearView<any>) => (model: any) => boolean,
toothView: (name: string, tooth: GearTooth<any> | GearView<any>) => GearView<any>): (t: Gear<any, any>) => {} {
const modelCache = new WeakMap<Gear<any, any>, xs<any>>()
return gear => {
let state: xs<any>
if (modelCache.has(gear)) {
state = modelCache.get(gear) as xs<any>
} else {
const actions = gear.intent ? gear.intent(sources) : defaultIntent(sources)
state = xs.fromObservable(gear.model ? gear.model(actions) : defaultModel(actions))
.replaceError((err: any) => xs.fromObservable(gear.catch ? gear.catch(err, actions) : defaultCatch(err, actions)))
.remember()
}
const views = teeth.reduce((accum, tooth) => Object.assign(accum, {
[tooth]: state.filter(toothFilter(tooth, (gear.teeth || {})[tooth])).map(toothView(tooth, (gear.teeth || {})[tooth]))
}), {})
return views
}
}
export function pedal(transmission: Transmission, {
defaultGear = { intent: () => ({}), model: () => xs.of({}), teeth: {} as GearTeeth<any> },
defaultFilter = () => true,
sinkMap = new Map()
}: PedalOptions = {}) {
const {
defaultIntent,
defaultModel,
defaultCatch,
teeth,
toothFilter,
toothView,
emptyTeeth
} = defaultsAndHelpers(defaultGear, defaultFilter)
return (sources: any) => {

@@ -93,14 +152,87 @@ let gear: Observable<Gear<any, any>>

const spin = xs.fromObservable<Gear<any, any>>(gear)
.map(gear => {
const actions = gear.intent ? gear.intent(sources) : defaultIntent(sources)
const state = xs.fromObservable(gear.model ? gear.model(actions) : defaultModel(actions))
.map(spinGear(sources, defaultIntent, defaultModel, defaultCatch, teeth, toothFilter, toothView))
.startWith(emptyTeeth)
.remember()
const sinks = teeth.reduce((accum, tooth) => Object.assign(accum, {
[sinkMap.has(tooth) ? sinkMap.get(tooth) : tooth]: adapt(spin.map((views: any) => views[tooth]).flatten())
}),
{})
return sinks
}
}
function spinGears(sources: any,
defaultIntent: (sources: any) => any,
defaultModel: (actions: any) => Observable<any>,
defaultCatch: (error: any, actions: any) => Observable<any>,
teeth: string[],
toothFilter: (name: string, tooth: GearTooth<any> | GearView<any>) => (model: any) => boolean,
toothView: (name: string, tooth: GearTooth<any> | GearView<any>) => GearView<any>,
sourcesWrapper: (sources: any, gear: Gear<any, any>) => any,
defaultConnector: ToothConnector<any, any, any>,
connectors: Map<string, ToothConnector<any, any, any>>): (t: Iterable<Gear<any, any>>) => {} {
const modelCache = new WeakMap<Gear<any, any>, xs<any>>()
return gears => {
const views = teeth.reduce((acc, cur) => ({...acc, [cur]: [] }), {} as {[tooth: string]: Array<Observable<any>>})
for (let gear of gears) {
let state: xs<any>
if (modelCache.has(gear)) {
state = modelCache.get(gear) as xs<any>
} else {
const wrappedSources = sourcesWrapper(sources, gear)
const actions = gear.intent ? gear.intent(wrappedSources) : defaultIntent(wrappedSources)
state = xs.fromObservable(gear.model ? gear.model(actions) : defaultModel(actions))
.replaceError((err: any) => xs.fromObservable(gear.catch ? gear.catch(err, actions) : defaultCatch(err, actions)))
.remember()
const views = teeth.reduce((accum, tooth) => Object.assign(accum, {
[tooth]: state.filter(toothFilter(tooth, (gear.teeth || {})[tooth])).map(toothView(tooth, (gear.teeth || {})[tooth]))
}),
{})
}
for (let tooth of teeth) {
views[tooth].push(state
.filter(toothFilter(tooth, (gear.teeth || {})[tooth]))
.map(state => [toothView(tooth, (gear.teeth || {})[tooth])(state), gear]))
}
}
return teeth.reduce((accum, tooth) => ({
...accum,
[tooth]: xs.merge(...views[tooth])
.fold(connectors.has(tooth) ? connectors.get(tooth)!.reduce : defaultConnector.reduce,
connectors.has(tooth) ? connectors.get(tooth)!.init() : defaultConnector.init())
}),
{})
}
}
return views
})
const defaultDefaultConnector = {
reduce: (acc: any, [cur, gear]: [any, Gear<any, any>]) => ({...acc, [gear.name || '?']: cur}),
init: () => ({})
}
export function motor(gearbox: Gearbox, {
defaultGear = { intent: () => ({}), model: () => xs.of({}), teeth: {} as GearTeeth<any> },
defaultFilter = () => true,
defaultConnector = defaultDefaultConnector,
sourcesWrapper = (sources: any) => sources,
connectors = new Map(),
sinkMap = new Map()
}: MotorOptions = {}) {
const {
defaultIntent,
defaultModel,
defaultCatch,
teeth,
toothFilter,
toothView,
emptyTeeth
} = defaultsAndHelpers(defaultGear, defaultFilter)
return (sources: any) => {
let gears: Observable<Iterable<Gear<any, any>>>
if (gearbox instanceof Function) {
gears = gearbox(sources)
} else {
gears = gearbox
}
const spin = xs.fromObservable<Iterable<Gear<any, any>>>(gears)
.map(spinGears(sources, defaultIntent, defaultModel, defaultCatch, teeth, toothFilter, toothView, sourcesWrapper, defaultConnector, connectors))
.startWith(emptyTeeth)

@@ -107,0 +239,0 @@ .remember()

{
"name": "cycle-gear",
"version": "4.1.0",
"version": "5.0.0",
"description": "Main function factory for CycleJS",

@@ -37,2 +37,3 @@ "main": "dist/index.js",

"tslint-config-standard": "^3.0.0",
"tslint-language-service": "^0.9.6",
"typescript": "^2.1.5"

@@ -39,0 +40,0 @@ },

@@ -48,1 +48,12 @@ # cycle-gear

`transmission` might be some other sort of user-action dependent state machine.
## `motor`
`motor` is a main factory function for the `Gear` pattern. It takes a `gearbox` of
Gears, default states for gears, which teeth to bind to which sinks, connectors to
merge the output of gears, and from that builds a Cycle main to wire the gears up to
Cycle sources and sinks.
A `gearbox` is an observable of iterable sets of gears or a factory from Cycle sources
to an observable of iterable sets of gears. This can be useful for component systems
that have many similar, interlocking parts.

@@ -10,4 +10,8 @@ {

"noUnusedParameters": true,
"downlevelIteration": true,
"declaration": true,
"outDir": "./dist/"
"outDir": "./dist/",
"plugins": [
{ "name": "tslint-language-service"}
]
},

@@ -14,0 +18,0 @@ "files": [