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

@cycle/run

Package Overview
Dependencies
Maintainers
2
Versions
41
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@cycle/run - npm Package Compare versions

Comparing version 3.1.0 to 4.0.0-rc.1

lib/types.d.ts

28

CHANGELOG.md

@@ -7,3 +7,3 @@ <a name="3.1.0"></a>

* **run:** sinks to support TypeScript interface ([c59ec55](https://github.com/cyclejs/cyclejs/tree/master/run/commit/c59ec55))
* **run:** sinks to support TypeScript interface ([c59ec55](https://github.com/cyclejs/cyclejs/commit/c59ec55))

@@ -18,4 +18,4 @@

* **run:** check for matching stream types of sinks and drivers ([4b4094c](https://github.com/cyclejs/cyclejs/tree/master/run/commit/4b4094c))
* **run:** reintroduce Driver function TS type ([1ad62cb](https://github.com/cyclejs/cyclejs/tree/master/run/commit/1ad62cb))
* **run:** check for matching stream types of sinks and drivers ([4b4094c](https://github.com/cyclejs/cyclejs/commit/4b4094c))
* **run:** reintroduce Driver function TS type ([1ad62cb](https://github.com/cyclejs/cyclejs/commit/1ad62cb))

@@ -39,3 +39,3 @@

* **run:** type check keyof drivers and main with TypeScript 2.2 ([da528c7](https://github.com/cyclejs/cyclejs/tree/master/run/commit/da528c7))
* **run:** type check keyof drivers and main with TypeScript 2.2 ([da528c7](https://github.com/cyclejs/cyclejs/commit/da528c7))

@@ -67,4 +67,4 @@

* **run:** fix race condition for drivers that subscribe late ([58b7991](https://github.com/cyclejs/cyclejs/tree/master/run/commit/58b7991))
* **run:** sink proxy completes on dispose, not with setTimeout ([47931fc](https://github.com/cyclejs/cyclejs/tree/master/run/commit/47931fc))
* **run:** fix race condition for drivers that subscribe late ([58b7991](https://github.com/cyclejs/cyclejs/commit/58b7991))
* **run:** sink proxy completes on dispose, not with setTimeout ([47931fc](https://github.com/cyclejs/cyclejs/commit/47931fc))

@@ -87,3 +87,3 @@

* **run:** fix race condition for drivers that subscribe late ([58b7991](https://github.com/cyclejs/cyclejs/tree/master/run/commit/58b7991))
* **run:** fix race condition for drivers that subscribe late ([58b7991](https://github.com/cyclejs/cyclejs/commit/58b7991))

@@ -98,3 +98,3 @@

* **run:** support drivers that dont return sources ([cda7602](https://github.com/cyclejs/cyclejs/tree/master/run/commit/cda7602))
* **run:** support drivers that dont return sources ([cda7602](https://github.com/cyclejs/cyclejs/commit/cda7602))

@@ -109,3 +109,3 @@

* **run:** adapt() sources, do not adapt() sinks ([0fd15ed](https://github.com/cyclejs/cyclejs/tree/master/run/commit/0fd15ed))
* **run:** adapt() sources, do not adapt() sinks ([0fd15ed](https://github.com/cyclejs/cyclejs/commit/0fd15ed))

@@ -120,3 +120,3 @@

* **run:** update to TypeScript 2.1 ([b7cabbc](https://github.com/cyclejs/cyclejs/tree/master/run/commit/b7cabbc))
* **run:** update to TypeScript 2.1 ([b7cabbc](https://github.com/cyclejs/cyclejs/commit/b7cabbc))

@@ -131,3 +131,3 @@

* **run:** clear buffers after all sink replicators are mutated ([432e4a6](https://github.com/cyclejs/cyclejs/tree/master/run/commit/432e4a6))
* **run:** clear buffers after all sink replicators are mutated ([432e4a6](https://github.com/cyclejs/cyclejs/commit/432e4a6))

@@ -142,4 +142,4 @@

* **run:** adapt sink to target stream lib before calling driver ([5edd925](https://github.com/cyclejs/cyclejs/tree/master/run/commit/5edd925))
* **run:** only free up buffers after replicator has been mutated ([bf8a7e1](https://github.com/cyclejs/cyclejs/tree/master/run/commit/bf8a7e1))
* **run:** adapt sink to target stream lib before calling driver ([5edd925](https://github.com/cyclejs/cyclejs/commit/5edd925))
* **run:** only free up buffers after replicator has been mutated ([bf8a7e1](https://github.com/cyclejs/cyclejs/commit/bf8a7e1))

@@ -154,3 +154,3 @@

* **run:** use FantasyObservable in Sinks, not xstream Stream ([d68a50e](https://github.com/cyclejs/cyclejs/tree/master/run/commit/d68a50e))
* **run:** use FantasyObservable in Sinks, not xstream Stream ([d68a50e](https://github.com/cyclejs/cyclejs/commit/d68a50e))

@@ -157,0 +157,0 @@

@@ -33,3 +33,3 @@ (function(f){if(typeof exports==="object"&&typeof module!=="undefined"){module.exports=f()}else if(typeof define==="function"&&define.amd){define([],f)}else{var g;if(typeof window!=="undefined"){g=window}else if(typeof global!=="undefined"){g=global}else if(typeof self!=="undefined"){g=self}else{g=this}g.Cycle = f()}})(function(){var define,module,exports;return (function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error("Cannot find module '"+o+"'");throw f.code="MODULE_NOT_FOUND",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o<r.length;o++)s(r[o]);return s})({1:[function(require,module,exports){

if (drivers.hasOwnProperty(name_1)) {
sinkProxies[name_1] = xstream_1.default.createWithMemory();
sinkProxies[name_1] = xstream_1.default.create();
}

@@ -54,5 +54,5 @@ }

for (var name_3 in sources) {
if (sources.hasOwnProperty(name_3)
&& sources[name_3]
&& typeof sources[name_3]['shamefullySendNext'] === 'function') {
if (sources.hasOwnProperty(name_3) &&
sources[name_3] &&
typeof sources[name_3]['shamefullySendNext'] === 'function') {
sources[name_3] = adapt_1.adapt(sources[name_3]);

@@ -75,8 +75,14 @@ }

});
var subscriptions = sinkNames
.map(function (name) { return xstream_1.default.fromObservable(sinks[name]).subscribe(replicators[name]); });
var subscriptions = sinkNames.map(function (name) {
return xstream_1.default.fromObservable(sinks[name]).subscribe(replicators[name]);
});
sinkNames.forEach(function (name) {
var listener = sinkProxies[name];
var next = function (x) { listener._n(x); };
var error = function (err) { logToConsoleError(err); listener._e(err); };
var next = function (x) {
listener._n(x);
};
var error = function (err) {
logToConsoleError(err);
listener._e(err);
};
buffers[name]._n.forEach(next);

@@ -99,3 +105,5 @@ buffers[name]._e.forEach(error);

for (var k in sources) {
if (sources.hasOwnProperty(k) && sources[k] && sources[k].dispose) {
if (sources.hasOwnProperty(k) &&
sources[k] &&
sources[k].dispose) {
sources[k].dispose();

@@ -138,4 +146,3 @@ }

if (typeof main !== "function") {
throw new Error("First argument given to Cycle must be the 'main' " +
"function.");
throw new Error("First argument given to Cycle must be the 'main' " + "function.");
}

@@ -158,3 +165,3 @@ if (typeof drivers !== "object" || drivers === null) {

}
function run() {
function _run() {
var disposeReplication = replicateMany(sinks, sinkProxies);

@@ -166,4 +173,3 @@ return function dispose() {

}
;
return { sinks: sinks, sources: sources, run: run };
return { sinks: sinks, sources: sources, run: _run };
}

@@ -199,7 +205,8 @@ exports.setup = setup;

function run(main, drivers) {
var _a = setup(main, drivers), run = _a.run, sinks = _a.sinks;
if (typeof window !== 'undefined' && window['CyclejsDevTool_startGraphSerializer']) {
window['CyclejsDevTool_startGraphSerializer'](sinks);
var program = setup(main, drivers);
if (typeof window !== 'undefined' &&
window['CyclejsDevTool_startGraphSerializer']) {
window['CyclejsDevTool_startGraphSerializer'](program.sinks);
}
return run();
return program.run();
}

@@ -206,0 +213,0 @@ exports.run = run;

@@ -1,1 +0,7 @@

(function(f){if(typeof exports==="object"&&typeof module!=="undefined"){module.exports=f()}else if(typeof define==="function"&&define.amd){define([],f)}else{var g;if(typeof window!=="undefined"){g=window}else if(typeof global!=="undefined"){g=global}else if(typeof self!=="undefined"){g=self}else{g=this}g.Cycle=f()}})(function(){var define,module,exports;return function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error("Cannot find module '"+o+"'");throw f.code="MODULE_NOT_FOUND",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o<r.length;o++)s(r[o]);return s}({1:[function(require,module,exports){"use strict";Object.defineProperty(exports,"__esModule",{value:true});var adaptStream=function(x){return x};function setAdapt(f){adaptStream=f}exports.setAdapt=setAdapt;function adapt(stream){return adaptStream(stream)}exports.adapt=adapt},{}],2:[function(require,module,exports){(function(global){"use strict";Object.defineProperty(exports,"__esModule",{value:true});var xstream_1=typeof window!=="undefined"?window["xstream"]:typeof global!=="undefined"?global["xstream"]:null;var adapt_1=require("./adapt");function logToConsoleError(err){var target=err.stack||err;if(console&&console.error){console.error(target)}else if(console&&console.log){console.log(target)}}function makeSinkProxies(drivers){var sinkProxies={};for(var name_1 in drivers){if(drivers.hasOwnProperty(name_1)){sinkProxies[name_1]=xstream_1.default.createWithMemory()}}return sinkProxies}function callDrivers(drivers,sinkProxies){var sources={};for(var name_2 in drivers){if(drivers.hasOwnProperty(name_2)){sources[name_2]=drivers[name_2](sinkProxies[name_2],name_2);if(sources[name_2]&&typeof sources[name_2]==="object"){sources[name_2]._isCycleSource=name_2}}}return sources}function adaptSources(sources){for(var name_3 in sources){if(sources.hasOwnProperty(name_3)&&sources[name_3]&&typeof sources[name_3]["shamefullySendNext"]==="function"){sources[name_3]=adapt_1.adapt(sources[name_3])}}return sources}function replicateMany(sinks,sinkProxies){var sinkNames=Object.keys(sinks).filter(function(name){return!!sinkProxies[name]});var buffers={};var replicators={};sinkNames.forEach(function(name){buffers[name]={_n:[],_e:[]};replicators[name]={next:function(x){return buffers[name]._n.push(x)},error:function(err){return buffers[name]._e.push(err)},complete:function(){}}});var subscriptions=sinkNames.map(function(name){return xstream_1.default.fromObservable(sinks[name]).subscribe(replicators[name])});sinkNames.forEach(function(name){var listener=sinkProxies[name];var next=function(x){listener._n(x)};var error=function(err){logToConsoleError(err);listener._e(err)};buffers[name]._n.forEach(next);buffers[name]._e.forEach(error);replicators[name].next=next;replicators[name].error=error;replicators[name]._n=next;replicators[name]._e=error});buffers=null;return function disposeReplication(){subscriptions.forEach(function(s){return s.unsubscribe()});sinkNames.forEach(function(name){return sinkProxies[name]._c()})}}function disposeSources(sources){for(var k in sources){if(sources.hasOwnProperty(k)&&sources[k]&&sources[k].dispose){sources[k].dispose()}}}function isObjectEmpty(obj){return Object.keys(obj).length===0}function setup(main,drivers){if(typeof main!=="function"){throw new Error("First argument given to Cycle must be the 'main' "+"function.")}if(typeof drivers!=="object"||drivers===null){throw new Error("Second argument given to Cycle must be an object "+"with driver functions as properties.")}if(isObjectEmpty(drivers)){throw new Error("Second argument given to Cycle must be an object "+"with at least one driver function declared as a property.")}var sinkProxies=makeSinkProxies(drivers);var sources=callDrivers(drivers,sinkProxies);var adaptedSources=adaptSources(sources);var sinks=main(adaptedSources);if(typeof window!=="undefined"){window.Cyclejs=window.Cyclejs||{};window.Cyclejs.sinks=sinks}function run(){var disposeReplication=replicateMany(sinks,sinkProxies);return function dispose(){disposeSources(sources);disposeReplication()}}return{sinks:sinks,sources:sources,run:run}}exports.setup=setup;function run(main,drivers){var _a=setup(main,drivers),run=_a.run,sinks=_a.sinks;if(typeof window!=="undefined"&&window["CyclejsDevTool_startGraphSerializer"]){window["CyclejsDevTool_startGraphSerializer"](sinks)}return run()}exports.run=run;exports.default=run}).call(this,typeof global!=="undefined"?global:typeof self!=="undefined"?self:typeof window!=="undefined"?window:{})},{"./adapt":1}]},{},[2])(2)});
(function(n){"object"===typeof exports&&"undefined"!==typeof module?module.exports=n():"function"===typeof define&&define.amd?define([],n):("undefined"!==typeof window?window:"undefined"!==typeof global?global:"undefined"!==typeof self?self:this).Cycle=n()})(function(){return function l(h,a,g){function p(f,d){if(!a[f]){if(!h[f]){var k="function"==typeof require&&require;if(!d&&k)return k(f,!0);if(m)return m(f,!0);d=Error("Cannot find module '"+f+"'");throw d.code="MODULE_NOT_FOUND",d;}d=a[f]={exports:{}};
h[f][0].call(d.exports,function(a){var d=h[f][1][a];return p(d?d:a)},d,d.exports,l,h,a,g)}return a[f].exports}for(var m="function"==typeof require&&require,k=0;k<g.length;k++)p(g[k]);return p}({1:[function(l,h,a){Object.defineProperty(a,"__esModule",{value:!0});var g=function(a){return a};a.setAdapt=function(a){g=a};a.adapt=function(a){return g(a)}},{}],2:[function(l,h,a){(function(g){function h(e){var b={},a;for(a in e)e.hasOwnProperty(a)&&(b[a]=r.default.create());return b}function m(a,b){var e=
{},c;for(c in a)a.hasOwnProperty(c)&&(e[c]=a[c](b[c],c),e[c]&&"object"===typeof e[c]&&(e[c]._isCycleSource=c));return e}function k(a){for(var b in a)a.hasOwnProperty(b)&&a[b]&&"function"===typeof a[b].shamefullySendNext&&(a[b]=t.adapt(a[b]));return a}function f(a,b){var e=Object.keys(a).filter(function(a){return!!b[a]}),c={},d={};e.forEach(function(a){c[a]={_n:[],_e:[]};d[a]={next:function(b){return c[a]._n.push(b)},error:function(b){return c[a]._e.push(b)},complete:function(){}}});var f=e.map(function(b){return r.default.fromObservable(a[b]).subscribe(d[b])});
e.forEach(function(a){var e=b[a],f=function(a){e._n(a)},g=function(a){var b=a.stack||a;console&&console.error?console.error(b):console&&console.log&&console.log(b);e._e(a)};c[a]._n.forEach(f);c[a]._e.forEach(g);d[a].next=f;d[a].error=g;d[a]._n=f;d[a]._e=g});c=null;return function(){f.forEach(function(a){return a.unsubscribe()});e.forEach(function(a){return b[a]._c()})}}function d(a,b){if("function"!==typeof a)throw Error("First argument given to Cycle must be the 'main' function.");if("object"!==
typeof b||null===b)throw Error("Second argument given to Cycle must be an object with driver functions as properties.");if(0===Object.keys(b).length)throw Error("Second argument given to Cycle must be an object with at least one driver function declared as a property.");var d=h(b),c=m(b,d);b=k(c);var e=a(b);"undefined"!==typeof window&&(window.Cyclejs=window.Cyclejs||{},window.Cyclejs.sinks=e);return{sinks:e,sources:c,run:function(){var a=f(e,d);return function(){for(var b in c)c.hasOwnProperty(b)&&
c[b]&&c[b].dispose&&c[b].dispose();a()}}}}function q(a,b){a=d(a,b);"undefined"!==typeof window&&window.CyclejsDevTool_startGraphSerializer&&window.CyclejsDevTool_startGraphSerializer(a.sinks);return a.run()}Object.defineProperty(a,"__esModule",{value:!0});var r="undefined"!==typeof window?window.xstream:"undefined"!==typeof g?g.xstream:null,t=l("./adapt");a.setup=d;a.run=q;a.default=q}).call(this,"undefined"!==typeof global?global:"undefined"!==typeof self?self:"undefined"!==typeof window?window:
{})},{"./adapt":1}]},{},[2])(2)});

@@ -1,56 +0,4 @@

import { MemoryStream } from 'xstream';
export interface FantasyObserver {
next(x: any): void;
error(err: any): void;
complete(c?: any): void;
}
export interface FantasySubscription {
unsubscribe(): void;
}
export interface FantasyObservable {
subscribe(observer: FantasyObserver): FantasySubscription;
}
export declare type DisposeFunction = () => void;
export interface DevToolEnabledSource {
_isCycleSource: string;
}
export interface Driver<Sink, Source> {
(stream: Sink, driverName?: string): Source;
}
export declare type Drivers<So extends Sources, Si extends Sinks> = {
[P in keyof (So & Si)]: Driver<Si[P], So[P]>;
};
export declare type Sources = {
[name: string]: any;
};
export declare type Sinks = {
[name: string]: any;
};
export declare type FantasySinks<Si> = {
[S in keyof Si]: FantasyObservable;
};
import { CycleProgram, DisposeFunction, Drivers, Sources, FantasySinks } from './types';
export { FantasyObserver, FantasySubscription, FantasyObservable, DevToolEnabledSource, Sources, Sinks, SinkProxies, FantasySinks, Driver, Drivers, DisposeFunction, CycleProgram } from './types';
/**
* Sink proxies should be MemoryStreams in order to fix race conditions for
* drivers that subscribe to sink proxies "later".
*
* Recall that there are two steps:
* 1. Setup (sink proxies -> drivers -> sources -> main -> sink)
* 2. Execution (also known as replication: sink proxies imitate sinks)
*
* If a driver does not synchronously/immediately subscribe to the sink proxy
* in step (1), but instead does that later, if step (2) feeds a value from the
* sink to the sink proxy, then when the driver subscribes to the sink proxy,
* it should receive that value. This is why we need MemoryStreams, not just
* Streams. Note: Cycle DOM driver is an example of such case, since it waits
* for 'readystatechange'.
*/
export declare type SinkProxies<Si extends Sinks> = {
[P in keyof Si]: MemoryStream<any>;
};
export interface CycleProgram<So extends Sources, Si extends Sinks> {
sources: So;
sinks: Si;
run(): DisposeFunction;
}
/**
* A function that prepares the Cycle application to be executed. Takes a `main`

@@ -57,0 +5,0 @@ * function and prepares to circularly connects it to the given collection of

@@ -18,3 +18,3 @@ "use strict";

if (drivers.hasOwnProperty(name_1)) {
sinkProxies[name_1] = xstream_1.default.createWithMemory();
sinkProxies[name_1] = xstream_1.default.create();
}

@@ -39,5 +39,5 @@ }

for (var name_3 in sources) {
if (sources.hasOwnProperty(name_3)
&& sources[name_3]
&& typeof sources[name_3]['shamefullySendNext'] === 'function') {
if (sources.hasOwnProperty(name_3) &&
sources[name_3] &&
typeof sources[name_3]['shamefullySendNext'] === 'function') {
sources[name_3] = adapt_1.adapt(sources[name_3]);

@@ -60,8 +60,14 @@ }

});
var subscriptions = sinkNames
.map(function (name) { return xstream_1.default.fromObservable(sinks[name]).subscribe(replicators[name]); });
var subscriptions = sinkNames.map(function (name) {
return xstream_1.default.fromObservable(sinks[name]).subscribe(replicators[name]);
});
sinkNames.forEach(function (name) {
var listener = sinkProxies[name];
var next = function (x) { listener._n(x); };
var error = function (err) { logToConsoleError(err); listener._e(err); };
var next = function (x) {
listener._n(x);
};
var error = function (err) {
logToConsoleError(err);
listener._e(err);
};
buffers[name]._n.forEach(next);

@@ -84,3 +90,5 @@ buffers[name]._e.forEach(error);

for (var k in sources) {
if (sources.hasOwnProperty(k) && sources[k] && sources[k].dispose) {
if (sources.hasOwnProperty(k) &&
sources[k] &&
sources[k].dispose) {
sources[k].dispose();

@@ -123,4 +131,3 @@ }

if (typeof main !== "function") {
throw new Error("First argument given to Cycle must be the 'main' " +
"function.");
throw new Error("First argument given to Cycle must be the 'main' " + "function.");
}

@@ -143,3 +150,3 @@ if (typeof drivers !== "object" || drivers === null) {

}
function run() {
function _run() {
var disposeReplication = replicateMany(sinks, sinkProxies);

@@ -151,4 +158,3 @@ return function dispose() {

}
;
return { sinks: sinks, sources: sources, run: run };
return { sinks: sinks, sources: sources, run: _run };
}

@@ -184,7 +190,8 @@ exports.setup = setup;

function run(main, drivers) {
var _a = setup(main, drivers), run = _a.run, sinks = _a.sinks;
if (typeof window !== 'undefined' && window['CyclejsDevTool_startGraphSerializer']) {
window['CyclejsDevTool_startGraphSerializer'](sinks);
var program = setup(main, drivers);
if (typeof window !== 'undefined' &&
window['CyclejsDevTool_startGraphSerializer']) {
window['CyclejsDevTool_startGraphSerializer'](program.sinks);
}
return run();
return program.run();
}

@@ -191,0 +198,0 @@ exports.run = run;

{
"name": "@cycle/run",
"version": "3.1.0",
"version": "4.0.0-rc.1",
"description": "The Cycle.js run() function to use with xstream",

@@ -47,21 +47,7 @@ "license": "MIT",

"scripts": {
"lint": "../node_modules/.bin/tslint --config ../tslint.json --project tsconfig.json",
"prelib": "rm -rf lib/ && mkdir -p lib/",
"lib": "../node_modules/.bin/tsc",
"premocha": "npm run lib",
"mocha": "../node_modules/.bin/mocha test/*.ts --require ts-node/register",
"test": "npm run lint && npm run mocha",
"test": "npm run mocha",
"test-ci": "npm run test",
"browserify": "../node_modules/.bin/browserify lib/index.js --global-transform=browserify-shim --standalone Cycle --exclude xstream -o dist/cycle-run.js",
"uglify": "../node_modules/.bin/uglifyjs dist/cycle-run.js -o dist/cycle-run.min.js",
"predist": "rm -rf dist/ && mkdir -p dist/",
"dist": "npm run lib && npm run browserify && npm run uglify",
"docs": "node ../.scripts/make-api-docs.js ${PWD##*/}",
"preversion": "npm test",
"version": "npm run dist && npm run docs && npm run changelog",
"postversion": "git add -A && git commit -m \"release(${PWD##*/}): v$(cat package.json | ../node_modules/.bin/jase version)\" && git push origin master && npm publish",
"release-patch": "false",
"release-minor": "npm --no-git-tag-version version minor",
"release-major": "npm --no-git-tag-version version major",
"changelog": "node ../.scripts/update-changelogs.js ${PWD##*/}"
"minify": "node ../.scripts/minify.js dist/cycle-run.js dist/cycle-run.min.js"
},

@@ -68,0 +54,0 @@ "publishConfig": {

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

[Documentation for Cycle Run on cycle.js.org](https://cycle.js.org/api/run.html)
- [**Read the docs here**](https://cycle.js.org/api/run.html)
- [**Edit the docs here**](https://github.com/cyclejs/cyclejs/blob/master/docs/content/api/run.md)

@@ -15,2 +15,2 @@ import {Stream} from 'xstream';

return adaptStream(stream);
}
}

@@ -1,69 +0,29 @@

import xs, {Stream, MemoryStream} from 'xstream';
import xs, {Stream} from 'xstream';
import {adapt} from './adapt';
import {
CycleProgram,
DevToolEnabledSource,
DisposeFunction,
Drivers,
SinkProxies,
Sources,
Sinks,
FantasySinks,
} from './types';
export interface FantasyObserver {
next(x: any): void;
error(err: any): void;
complete(c?: any): void;
}
export {
FantasyObserver,
FantasySubscription,
FantasyObservable,
DevToolEnabledSource,
Sources,
Sinks,
SinkProxies,
FantasySinks,
Driver,
Drivers,
DisposeFunction,
CycleProgram,
} from './types';
export interface FantasySubscription {
unsubscribe(): void;
}
export interface FantasyObservable {
subscribe(observer: FantasyObserver): FantasySubscription;
}
export type DisposeFunction = () => void;
export interface DevToolEnabledSource {
_isCycleSource: string;
}
export interface Driver<Sink, Source> {
(stream: Sink, driverName?: string): Source;
}
export type Drivers<So extends Sources, Si extends Sinks> = {
[P in keyof (So & Si)]: Driver<Si[P], So[P]>;
};
export type Sources = {
[name: string]: any;
};
export type Sinks = {
[name: string]: any;
};
export type FantasySinks<Si> = {
[S in keyof Si]: FantasyObservable;
};
/**
* Sink proxies should be MemoryStreams in order to fix race conditions for
* drivers that subscribe to sink proxies "later".
*
* Recall that there are two steps:
* 1. Setup (sink proxies -> drivers -> sources -> main -> sink)
* 2. Execution (also known as replication: sink proxies imitate sinks)
*
* If a driver does not synchronously/immediately subscribe to the sink proxy
* in step (1), but instead does that later, if step (2) feeds a value from the
* sink to the sink proxy, then when the driver subscribes to the sink proxy,
* it should receive that value. This is why we need MemoryStreams, not just
* Streams. Note: Cycle DOM driver is an example of such case, since it waits
* for 'readystatechange'.
*/
export type SinkProxies<Si extends Sinks> = {
[P in keyof Si]: MemoryStream<any>;
};
export interface CycleProgram<So extends Sources, Si extends Sinks> {
sources: So;
sinks: Si;
run(): DisposeFunction;
}
function logToConsoleError(err: any) {

@@ -79,7 +39,8 @@ const target = err.stack || err;

function makeSinkProxies<So extends Sources, Si extends Sinks>(
drivers: Drivers<So, Si>): SinkProxies<Si> {
drivers: Drivers<So, Si>,
): SinkProxies<Si> {
const sinkProxies: SinkProxies<Si> = {} as SinkProxies<Si>;
for (const name in drivers) {
if (drivers.hasOwnProperty(name)) {
sinkProxies[name] = xs.createWithMemory<any>();
sinkProxies[name] = xs.create<any>();
}

@@ -91,4 +52,5 @@ }

function callDrivers<So extends Sources, Si extends Sinks>(
drivers: Drivers<So, Si>,
sinkProxies: SinkProxies<Si>): So {
drivers: Drivers<So, Si>,
sinkProxies: SinkProxies<Si>,
): So {
const sources: So = {} as So;

@@ -109,6 +71,8 @@ for (const name in drivers) {

for (const name in sources) {
if (sources.hasOwnProperty(name)
&& sources[name]
&& typeof sources[name]['shamefullySendNext'] === 'function') {
sources[name] = adapt(sources[name] as any as Stream<any>);
if (
sources.hasOwnProperty(name) &&
sources[name] &&
typeof sources[name]['shamefullySendNext'] === 'function'
) {
sources[name] = adapt((sources[name] as any) as Stream<any>);
}

@@ -132,3 +96,3 @@ }

complete(): void;
};
}
};

@@ -140,13 +104,16 @@

_e: Array<any>;
};
}
};
function replicateMany<So extends Sources, Si extends Sinks>(
sinks: Si,
sinkProxies: SinkProxies<Si>): DisposeFunction {
const sinkNames: Array<keyof Si> = Object.keys(sinks).filter(name => !!sinkProxies[name]);
sinks: Si,
sinkProxies: SinkProxies<Si>,
): DisposeFunction {
const sinkNames: Array<keyof Si> = Object.keys(sinks).filter(
name => !!sinkProxies[name],
);
let buffers: ReplicationBuffers<Si> = {} as ReplicationBuffers<Si>;
const replicators: SinkReplicators<Si> = {} as SinkReplicators<Si>;
sinkNames.forEach((name) => {
sinkNames.forEach(name => {
buffers[name] = {_n: [], _e: []};

@@ -160,9 +127,15 @@ replicators[name] = {

const subscriptions = sinkNames
.map(name => xs.fromObservable(sinks[name] as any).subscribe(replicators[name]));
const subscriptions = sinkNames.map(name =>
xs.fromObservable(sinks[name] as any).subscribe(replicators[name]),
);
sinkNames.forEach((name) => {
sinkNames.forEach(name => {
const listener = sinkProxies[name];
const next = (x: any) => { listener._n(x); };
const error = (err: any) => { logToConsoleError(err); listener._e(err); };
const next = (x: any) => {
listener._n(x);
};
const error = (err: any) => {
logToConsoleError(err);
listener._e(err);
};
buffers[name]._n.forEach(next);

@@ -181,3 +154,3 @@ buffers[name]._e.forEach(error);

subscriptions.forEach(s => s.unsubscribe());
sinkNames.forEach((name) => sinkProxies[name]._c());
sinkNames.forEach(name => sinkProxies[name]._c());
};

@@ -188,3 +161,7 @@ }

for (const k in sources) {
if (sources.hasOwnProperty(k) && sources[k] && (sources[k] as any).dispose) {
if (
sources.hasOwnProperty(k) &&
sources[k] &&
(sources[k] as any).dispose
) {
(sources[k] as any).dispose();

@@ -228,15 +205,21 @@ }

export function setup<So extends Sources, Si extends FantasySinks<Si>>(
main: (sources: So) => Si,
drivers: Drivers<So, Si>): CycleProgram<So, Si> {
main: (sources: So) => Si,
drivers: Drivers<So, Si>,
): CycleProgram<So, Si> {
if (typeof main !== `function`) {
throw new Error(`First argument given to Cycle must be the 'main' ` +
`function.`);
throw new Error(
`First argument given to Cycle must be the 'main' ` + `function.`,
);
}
if (typeof drivers !== `object` || drivers === null) {
throw new Error(`Second argument given to Cycle must be an object ` +
`with driver functions as properties.`);
throw new Error(
`Second argument given to Cycle must be an object ` +
`with driver functions as properties.`,
);
}
if (isObjectEmpty(drivers)) {
throw new Error(`Second argument given to Cycle must be an object ` +
`with at least one driver function declared as a property.`);
throw new Error(
`Second argument given to Cycle must be an object ` +
`with at least one driver function declared as a property.`,
);
}

@@ -252,3 +235,3 @@

}
function run(): DisposeFunction {
function _run(): DisposeFunction {
const disposeReplication = replicateMany(sinks, sinkProxies);

@@ -259,4 +242,4 @@ return function dispose() {

};
};
return {sinks, sources, run};
}
return {sinks, sources, run: _run};
}

@@ -292,11 +275,15 @@

export function run<So extends Sources, Si extends FantasySinks<Si>>(
main: (sources: So) => Si,
drivers: Drivers<So, Si>): DisposeFunction {
const {run, sinks} = setup(main, drivers);
if (typeof window !== 'undefined' && window['CyclejsDevTool_startGraphSerializer']) {
window['CyclejsDevTool_startGraphSerializer'](sinks);
main: (sources: So) => Si,
drivers: Drivers<So, Si>,
): DisposeFunction {
const program = setup(main, drivers);
if (
typeof window !== 'undefined' &&
window['CyclejsDevTool_startGraphSerializer']
) {
window['CyclejsDevTool_startGraphSerializer'](program.sinks);
}
return run();
return program.run();
}
export default run;

@@ -16,8 +16,8 @@ import 'mocha';

describe('setup', function () {
it('should be a function', function () {
describe('setup', function() {
it('should be a function', function() {
assert.strictEqual(typeof setup, 'function');
});
it('should throw if first argument is not a function', function () {
it('should throw if first argument is not a function', function() {
assert.throws(() => {

@@ -28,3 +28,3 @@ (setup as any)('not a function');

it('should throw if second argument is not an object', function () {
it('should throw if second argument is not an object', function() {
assert.throws(() => {

@@ -35,3 +35,3 @@ (setup as any)(() => {}, 'not an object');

it('should throw if second argument is an empty object', function () {
it('should throw if second argument is an empty object', function() {
assert.throws(() => {

@@ -42,3 +42,3 @@ (setup as any)(() => {}, {});

it('should return sinks object and sources object', function () {
it('should return sinks object and sources object', function() {
function app(ext: any): any {

@@ -61,3 +61,3 @@ return {

it('should type-check keyof sources and sinks in main and drivers', function () {
it('should type-check keyof sources and sinks in main and drivers', function() {
type Sources = {

@@ -80,10 +80,11 @@ str: Stream<string>;

const stringDriver: Driver<Stream<string>, Stream<string>> =
(sink: Stream<string>) => xs.of('b');
const stringDriver: Driver<Stream<string>, Stream<string>> = (
sink: Stream<string>,
) => xs.of('b');
const numberWriteOnlyDriver: Driver<Stream<number>, void> =
(sink: Stream<number>) => {};
const numberWriteOnlyDriver: Driver<Stream<number>, void> = (
sink: Stream<number>,
) => {};
const objectReadOnlyDriver: Driver<void, Stream<object>> =
() => xs.of({});
const objectReadOnlyDriver: Driver<void, Stream<object>> = () => xs.of({});

@@ -97,7 +98,7 @@ setup(app, {

it('should type-check keyof sources and sinks, supporting interfaces', function () {
it('should type-check keyof sources and sinks, supporting interfaces', function() {
interface Sources {
str: Stream<string>;
obj: Stream<object>;
};
}

@@ -107,3 +108,3 @@ interface Sinks {

num: Stream<number>;
};
}

@@ -122,10 +123,11 @@ function app(sources: Sources): Sinks {

const stringDriver: Driver<Stream<string>, Stream<string>> =
(sink: Stream<string>) => xs.of('b');
const stringDriver: Driver<Stream<string>, Stream<string>> = (
sink: Stream<string>,
) => xs.of('b');
const numberWriteOnlyDriver: Driver<Stream<number>, void> =
(sink: Stream<number>) => {};
const numberWriteOnlyDriver: Driver<Stream<number>, void> = (
sink: Stream<number>,
) => {};
const objectReadOnlyDriver: Driver<void, Stream<object>> =
() => xs.of({});
const objectReadOnlyDriver: Driver<void, Stream<object>> = () => xs.of({});

@@ -139,3 +141,3 @@ setup(app, {

it('should type-check and allow more drivers than sinks', function () {
it('should type-check and allow more drivers than sinks', function() {
type Sources = {

@@ -148,4 +150,3 @@ str: Stream<string>;

function app(sources: Sources) {
return {
};
return {};
}

@@ -168,3 +169,3 @@

it('should call DevTool internal function to pass sinks', function () {
it('should call DevTool internal function to pass sinks', function() {
let sandbox = sinon.sandbox.create();

@@ -187,3 +188,3 @@ let spy = sandbox.spy();

it('should return a run() which in turn returns a dispose()', function (done) {
it('should return a run() which in turn returns a dispose()', function(done) {
type TestSources = {

@@ -220,3 +221,3 @@ other: Stream<number>;

it('should support sink-only drivers', function (done) {
it('should support sink-only drivers', function(done) {
function app(sources: any): any {

@@ -241,3 +242,3 @@ return {

it('should not adapt() sinks', function (done) {
it('should not adapt() sinks', function(done) {
function app(sources: any): any {

@@ -265,3 +266,3 @@ return {

it('should adapt() a simple source (stream)', function (done) {
it('should adapt() a simple source (stream)', function(done) {
let appCalled = false;

@@ -290,3 +291,3 @@ function app(sources: any): any {

it('should not work after has been disposed', function (done) {
it('should not work after has been disposed', function(done) {
type MySources = {

@@ -309,3 +310,3 @@ other: Stream<string>;

sources.other.addListener({
next: (x) => {
next: x => {
assert.notStrictEqual(x, 'x3');

@@ -323,8 +324,8 @@ if (x === 'x2') {

describe('run', function () {
it('should be a function', function () {
describe('run', function() {
it('should be a function', function() {
assert.strictEqual(typeof run, 'function');
});
it('should throw if first argument is not a function', function () {
it('should throw if first argument is not a function', function() {
assert.throws(() => {

@@ -335,3 +336,3 @@ (run as any)('not a function');

it('should throw if second argument is not an object', function () {
it('should throw if second argument is not an object', function() {
assert.throws(() => {

@@ -342,3 +343,3 @@ (run as any)(() => {}, 'not an object');

it('should throw if second argument is an empty object', function () {
it('should throw if second argument is an empty object', function() {
assert.throws(() => {

@@ -349,3 +350,3 @@ (run as any)(() => {}, {});

it('should return a dispose function', function () {
it('should return a dispose function', function() {
let sandbox = sinon.sandbox.create();

@@ -377,7 +378,11 @@ const spy = sandbox.spy();

it('should happen synchronously', function (done) {
it('should happen synchronously', function(done) {
let sandbox = sinon.sandbox.create();
const spy = sandbox.spy();
function app(sources: any): any {
sources.other.addListener({next: () => {}, error: () => {}, complete: () => {}});
sources.other.addListener({
next: () => {},
error: () => {},
complete: () => {},
});
return {

@@ -403,3 +408,5 @@ other: xs.of(10),

it('should support driver that asynchronously subscribes to sink', function (done) {
it('should support driver that asynchronously subscribes to sink', function(
done,
) {
function app(sources: any): any {

@@ -413,3 +420,13 @@ return {

function driver(sink: Stream<number>): Stream<any> {
const buffer: Array<number> = [];
sink.addListener({
next: x => {
buffer.push(x);
},
});
setTimeout(() => {
while (buffer.length > 0) {
const x = buffer.shift();
assert.strictEqual(x, expected.shift());
}
sink.subscribe({

@@ -434,3 +451,134 @@ next(x) {

it('should report errors from main() in the console', function (done) {
it('should forbid cross-driver synchronous races (#592)', function(done) {
this.timeout(4000);
function child(sources: any, num: number) {
const vdom$ = sources.HTTP
// .select('cat')
// .flatten()
.map((res: any) => res.body.name)
.map((name: string) => 'My name is ' + name);
const request$ = num === 1
? xs.of({
category: 'cat',
url: 'http://jsonplaceholder.typicode.com/users/1',
})
: xs.never();
return {
HTTP: request$,
DOM: vdom$,
};
}
function mainHTTPThenDOM(sources: any) {
const sinks$ = xs.periodic(100).take(6).map(i => {
if (i % 2 === 1) {
return child(sources, i);
} else {
return {
HTTP: xs.empty(),
DOM: xs.of(''),
};
}
});
// order of sinks is important to reproduce the bug
return {
HTTP: sinks$.map(sinks => sinks.HTTP).flatten(),
DOM: sinks$.map(sinks => sinks.DOM).flatten(),
};
}
function mainDOMThenHTTP(sources: any) {
const sinks$ = xs.periodic(100).take(6).map(i => {
if (i % 2 === 1) {
return child(sources, i);
} else {
return {
HTTP: xs.empty(),
DOM: xs.of(''),
};
}
});
// order of sinks is important to reproduce the bug
return {
DOM: sinks$.map(sinks => sinks.DOM).flatten(),
HTTP: sinks$.map(sinks => sinks.HTTP).flatten(),
};
}
let requestsSent = 0;
const expectedDOMSinks = [
/* HTTP then DOM: */ '',
'My name is Louis',
'',
'',
/* DOM then HTTP: */ '',
'My name is Louis',
'',
'',
];
function domDriver(sink: Stream<string>) {
sink.addListener({
next: s => {
assert.strictEqual(s, expectedDOMSinks.shift());
},
error: (err: any) => {},
});
}
function httpDriver(sink: Stream<any>) {
let isBufferOpen = true;
const buffer: Array<any> = [];
const earlySource = xs.create({
start(listener: any) {
while (buffer.length > 0) {
listener.next(buffer.shift());
}
isBufferOpen = false;
},
stop() {},
});
const source = sink.map(req => ({body: {name: 'Louis'}}));
source.addListener({
next: x => {
if (isBufferOpen) {
buffer.push(x);
}
},
error: (err: any) => {},
});
return xs.merge(earlySource, source).debug(x => {
requestsSent += 1;
});
}
// HTTP then DOM:
const dispose = run(mainHTTPThenDOM, {
HTTP: httpDriver,
DOM: domDriver,
});
setTimeout(() => {
assert.strictEqual(expectedDOMSinks.length, 4);
assert.strictEqual(requestsSent, 1);
dispose();
// DOM then HTTP:
run(mainDOMThenHTTP, {
HTTP: httpDriver,
DOM: domDriver,
});
setTimeout(() => {
assert.strictEqual(expectedDOMSinks.length, 0);
assert.strictEqual(requestsSent, 2);
done();
}, 1000);
}, 1000);
});
it('should report errors from main() in the console', function(done) {
let sandbox = sinon.sandbox.create();

@@ -463,3 +611,6 @@ sandbox.stub(console, 'error');

sinon.assert.calledOnce(console.error as any);
sinon.assert.calledWithExactly(console.error as any, sinon.match('malfunction'));
sinon.assert.calledWithExactly(
console.error as any,
sinon.match('malfunction'),
);

@@ -466,0 +617,0 @@ // Should be false because the error was already reported in the console.

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