├── .editorconfig ├── .eslintrc.json ├── .gitattributes ├── .gitignore ├── .travis.yml ├── API.md ├── HISTORY.md ├── LICENSE ├── README.md ├── bower.json ├── build-examples.js ├── es └── index.js ├── examples ├── drag-and-drop │ ├── build.js │ ├── index.html │ └── script.js ├── multiple-clicks │ ├── build.js │ ├── index.html │ ├── node_modules │ │ ├── flyd-aftersilence │ │ │ ├── LICENSE │ │ │ ├── README.md │ │ │ ├── aftersilence.js │ │ │ ├── package.json │ │ │ └── test │ │ │ │ └── index.js │ │ └── flyd │ │ │ ├── .travis.yml │ │ │ ├── LICENSE │ │ │ ├── README.md │ │ │ ├── bower.json │ │ │ ├── coverage │ │ │ ├── coverage.json │ │ │ └── lcov.info │ │ │ ├── examples │ │ │ ├── multiple-clicks │ │ │ │ ├── build.js │ │ │ │ ├── index.html │ │ │ │ ├── package.json │ │ │ │ └── script.js │ │ │ ├── secret-combination │ │ │ │ ├── index.html │ │ │ │ └── script.js │ │ │ └── sum │ │ │ │ └── index.html │ │ │ ├── flyd.js │ │ │ ├── package.json │ │ │ ├── perf │ │ │ ├── perf.js │ │ │ └── test.js │ │ │ └── test │ │ │ └── index.js │ ├── package.json │ └── script.js ├── ramda-transducer │ ├── README.md │ ├── build.js │ ├── package.json │ └── script.js ├── secret-combination │ ├── build.js │ ├── index.html │ ├── node_modules │ │ ├── flyd-filter │ │ │ ├── LICENSE │ │ │ ├── README.md │ │ │ ├── filter.js │ │ │ ├── package.json │ │ │ └── test │ │ │ │ └── index.js │ │ ├── flyd-inlast │ │ │ ├── LICENSE │ │ │ ├── README.md │ │ │ ├── inlast.js │ │ │ ├── package.json │ │ │ └── test │ │ │ │ └── index.js │ │ ├── flyd-lift │ │ │ ├── LICENSE │ │ │ ├── README.md │ │ │ ├── flyd-lift.js │ │ │ ├── package.json │ │ │ └── test │ │ │ │ └── index.js │ │ ├── flyd-sampleon │ │ │ ├── LICENSE │ │ │ ├── README.md │ │ │ ├── package.json │ │ │ ├── sampleon.js │ │ │ └── test │ │ │ │ └── index.js │ │ └── flyd │ │ │ ├── .travis.yml │ │ │ ├── LICENSE │ │ │ ├── README.md │ │ │ ├── bower.json │ │ │ ├── coverage │ │ │ ├── coverage.json │ │ │ └── lcov.info │ │ │ ├── examples │ │ │ ├── multiple-clicks │ │ │ │ ├── build.js │ │ │ │ ├── index.html │ │ │ │ ├── package.json │ │ │ │ └── script.js │ │ │ ├── secret-combination │ │ │ │ ├── index.html │ │ │ │ └── script.js │ │ │ └── sum │ │ │ │ └── index.html │ │ │ ├── flyd.js │ │ │ ├── package.json │ │ │ ├── perf │ │ │ ├── perf.js │ │ │ └── test.js │ │ │ └── test │ │ │ └── index.js │ ├── package.json │ └── script.js ├── sum │ ├── build.js │ ├── index.html │ └── script.js └── who-to-follow │ ├── build.js │ ├── index.html │ ├── package.json │ └── script.js ├── flyd.js ├── flyd.min.js ├── index.d.ts ├── lib └── index.js ├── module ├── aftersilence │ ├── README.md │ ├── index.js │ └── test │ │ └── index.js ├── batchwhen │ ├── README.md │ ├── index.js │ └── test │ │ └── index.js ├── diff │ ├── README.md │ ├── index.js │ └── test │ │ └── index.js ├── droprepeats │ ├── README.md │ ├── index.js │ └── test │ │ └── index.js ├── every │ ├── README.md │ ├── index.js │ └── test │ │ ├── browsertest │ │ ├── index.html │ │ └── script.js │ │ └── index.js ├── filter │ ├── README.md │ ├── index.js │ └── test │ │ └── index.js ├── forwardto │ ├── README.md │ ├── index.js │ └── test │ │ └── index.js ├── inlast │ ├── README.md │ ├── index.js │ └── test │ │ └── index.js ├── keepwhen │ ├── README.md │ ├── index.js │ └── test │ │ └── index.js ├── lift │ ├── README.md │ ├── index.js │ └── test │ │ └── index.js ├── mergeall │ ├── README.md │ ├── index.js │ └── test │ │ └── index.js ├── obj │ ├── README.md │ ├── index.js │ └── test │ │ └── index.js ├── previous │ ├── README.md │ ├── index.js │ └── test │ │ └── index.js ├── sampleon │ ├── README.md │ ├── index.js │ └── test │ │ └── index.js ├── scanmerge │ ├── README.md │ ├── index.js │ └── test │ │ └── index.js ├── switchlatest │ ├── README.md │ ├── index.js │ └── test │ │ └── index.js └── takeuntil │ ├── README.md │ ├── index.js │ └── test │ └── index.js ├── package-lock.json ├── package.json ├── perf ├── perf.js └── run-benchmarks ├── rollup.config.dev.js ├── rollup.config.js └── test └── index.js /.editorconfig: -------------------------------------------------------------------------------- 1 | [*] 2 | indent_style = space 3 | indent_size = 2 4 | -------------------------------------------------------------------------------- /.eslintrc.json: -------------------------------------------------------------------------------- 1 | { 2 | "env": { 3 | "node": true, 4 | "mocha": true 5 | }, 6 | "globals": { 7 | "Symbol": true 8 | }, 9 | "rules": { 10 | "no-eval": 2, 11 | "eqeqeq": 0, 12 | "no-eq-null": 0, 13 | "new-cap": 0, 14 | "no-plusplus": 0, 15 | "no-undef": 2, 16 | "no-unused-vars": 2, 17 | "brace-style": [ 18 | 2, 19 | "1tbs", 20 | { 21 | "allowSingleLine": true 22 | } 23 | ], 24 | "no-mixed-spaces-and-tabs": 2, 25 | "no-multi-str": 2, 26 | "one-var": [ 27 | 2, 28 | { 29 | "uninitialized": "always", 30 | "initialized": "never" 31 | } 32 | ], 33 | "quote-props": [ 34 | 2, 35 | "as-needed", 36 | { 37 | "keywords": true 38 | } 39 | ], 40 | "key-spacing": 0, 41 | "space-unary-ops": 0, 42 | "no-spaced-func": 2, 43 | "space-before-function-paren": [ 44 | 2, 45 | "never" 46 | ], 47 | "spaced-comment": [ 48 | 2, 49 | "always" 50 | ], 51 | "array-bracket-spacing": [ 52 | 2, 53 | "never", 54 | { 55 | "singleValue": false 56 | } 57 | ], 58 | "space-in-parens": [ 59 | 2, 60 | "never" 61 | ], 62 | "no-trailing-spaces": 2, 63 | "yoda": [ 64 | 2, 65 | "never" 66 | ], 67 | "comma-style": [ 68 | 2, 69 | "last" 70 | ], 71 | "curly": [ 72 | 2, 73 | "multi-line" 74 | ], 75 | "dot-notation": 0, 76 | "eol-last": 2, 77 | "wrap-iife": [ 78 | 2, 79 | "outside" 80 | ], 81 | "space-infix-ops": 2, 82 | "space-return-throw-case": 0, 83 | "keyword-spacing": ["error", {"after": true}], 84 | "lines-around-comment": 0, 85 | "space-before-blocks": [ 86 | 2, 87 | "always" 88 | ], 89 | "indent": [ 90 | 2, 91 | 2, 92 | { 93 | "SwitchCase": 1 94 | } 95 | ], 96 | "quotes": [ 97 | 2, 98 | "single", 99 | "avoid-escape" 100 | ], 101 | "comma-dangle": [ 102 | 2, 103 | "never" 104 | ], 105 | "no-debugger": 2, 106 | "no-dupe-args": 2, 107 | "no-dupe-keys": 2, 108 | "no-duplicate-case": 2, 109 | "no-extra-semi": 2, 110 | "no-unreachable": 2 111 | } 112 | } 113 | -------------------------------------------------------------------------------- /.gitattributes: -------------------------------------------------------------------------------- 1 | * eol=lf -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | ### Node template 2 | # Logs 3 | logs 4 | *.log 5 | 6 | # Dependency directory 7 | node_modules 8 | bower_components 9 | 10 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: node_js 2 | node_js: 3 | - "6" 4 | - "7" 5 | - "8" 6 | after_success: 7 | - "npm run post-to-coveralls-io" 8 | -------------------------------------------------------------------------------- /API.md: -------------------------------------------------------------------------------- 1 | ## `flyd` 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | ## `flyd.combine` 11 | 12 | Create a new dependent stream 13 | 14 | __Signature__: `(...Stream * -> Stream b -> b) -> [Stream *] -> Stream b` 15 | 16 | ### Parameters 17 | 18 | * `fn` **`Function`** the function used to combine the streams 19 | * `dependencies` **`Array`** the streams that this one depends on 20 | 21 | 22 | ### Examples 23 | 24 | ```js 25 | var n1 = flyd.stream(0); 26 | var n2 = flyd.stream(0); 27 | var max = flyd.combine(function(n1, n2, self, changed) { 28 | return n1() > n2() ? n1() : n2(); 29 | }, [n1, n2]); 30 | ``` 31 | 32 | Returns `stream` the dependent stream 33 | 34 | 35 | ## `flyd.curryN` 36 | 37 | Returns `fn` curried to `n`. Use this function to curry functions exposed by 38 | modules for Flyd. 39 | 40 | ### Parameters 41 | 42 | * `arity` **`Integer`** the function arity 43 | * `fn` **`Function`** the function to curry 44 | 45 | 46 | ### Examples 47 | 48 | ```js 49 | function add(x, y) { return x + y; }; 50 | var a = flyd.curryN(2, add); 51 | a(2)(4) // => 6 52 | ``` 53 | 54 | Returns `Function` the curried function 55 | 56 | 57 | ## `flyd.endsOn` 58 | 59 | Changes which `endsStream` should trigger the ending of `s`. 60 | 61 | __Signature__: `Stream a -> Stream b -> Stream b` 62 | 63 | ### Parameters 64 | 65 | * `endStream` **`stream`** the stream to trigger the ending 66 | * `stream` **`stream`** the stream to be ended by the endStream 67 | * `the` **`stream`** stream modified to be ended by endStream 68 | 69 | 70 | ### Examples 71 | 72 | ```js 73 | var n = flyd.stream(1); 74 | var killer = flyd.stream(); 75 | // `double` ends when `n` ends or when `killer` emits any value 76 | var double = flyd.endsOn(flyd.merge(n.end, killer), flyd.combine(function(n) { 77 | return 2 * n(); 78 | }, [n]); 79 | ``` 80 | 81 | 82 | 83 | ## `flyd.immediate` 84 | 85 | Invokes the body (the function to calculate the value) of a dependent stream 86 | 87 | By default the body of a dependent stream is only called when all the streams 88 | upon which it depends has a value. `immediate` can circumvent this behaviour. 89 | It immediately invokes the body of a dependent stream. 90 | 91 | __Signature__: `Stream a -> Stream a` 92 | 93 | ### Parameters 94 | 95 | * `stream` **`stream`** the dependent stream 96 | 97 | 98 | ### Examples 99 | 100 | ```js 101 | var s = flyd.stream(); 102 | var hasItems = flyd.immediate(flyd.combine(function(s) { 103 | return s() !== undefined && s().length > 0; 104 | }, [s]); 105 | console.log(hasItems()); // logs `false`. Had `immediate` not been 106 | // used `hasItems()` would've returned `undefined` 107 | s([1]); 108 | console.log(hasItems()); // logs `true`. 109 | s([]); 110 | console.log(hasItems()); // logs `false`. 111 | ``` 112 | 113 | Returns `stream` the same stream 114 | 115 | 116 | ## `flyd.isStream` 117 | 118 | Returns `true` if the supplied argument is a Flyd stream and `false` otherwise. 119 | 120 | __Signature__: `* -> Boolean` 121 | 122 | ### Parameters 123 | 124 | * `value` **`Any`** the value to test 125 | 126 | 127 | ### Examples 128 | 129 | ```js 130 | var s = flyd.stream(1); 131 | var n = 1; 132 | flyd.isStream(s); //=> true 133 | flyd.isStream(n); //=> false 134 | ``` 135 | 136 | Returns `Boolean` `true` if is a Flyd streamn, `false` otherwise 137 | 138 | 139 | ## `flyd.map` 140 | 141 | Map a stream 142 | 143 | Returns a new stream consisting of every value from `s` passed through 144 | `fn`. I.e. `map` creates a new stream that listens to `s` and 145 | applies `fn` to every new value. 146 | __Signature__: `(a -> result) -> Stream a -> Stream result` 147 | 148 | ### Parameters 149 | 150 | * `fn` **`Function`** the function that produces the elements of the new stream 151 | * `stream` **`stream`** the stream to map 152 | 153 | 154 | ### Examples 155 | 156 | ```js 157 | var numbers = flyd.stream(0); 158 | var squaredNumbers = flyd.map(function(n) { return n*n; }, numbers); 159 | ``` 160 | 161 | Returns `stream` a new stream with the mapped values 162 | 163 | 164 | ## `flyd.merge` 165 | 166 | Creates a new stream down which all values from both `stream1` and `stream2` 167 | will be sent. 168 | 169 | __Signature__: `Stream a -> Stream a -> Stream a` 170 | 171 | ### Parameters 172 | 173 | * `source1` **`stream`** one stream to be merged 174 | * `source2` **`stream`** the other stream to be merged 175 | 176 | 177 | ### Examples 178 | 179 | ```js 180 | var btn1Clicks = flyd.stream(); 181 | button1Elm.addEventListener(btn1Clicks); 182 | var btn2Clicks = flyd.stream(); 183 | button2Elm.addEventListener(btn2Clicks); 184 | var allClicks = flyd.merge(btn1Clicks, btn2Clicks); 185 | ``` 186 | 187 | Returns `stream` a stream with the values from both sources 188 | 189 | 190 | ## `flyd.on` 191 | 192 | Listen to stream events 193 | 194 | Similair to `map` except that the returned stream is empty. Use `on` for doing 195 | side effects in reaction to stream changes. Use the returned stream only if you 196 | need to manually end it. 197 | 198 | __Signature__: `(a -> result) -> Stream a -> Stream undefined` 199 | 200 | ### Parameters 201 | 202 | * `cb` **`Function`** the callback 203 | * `stream` **`stream`** the stream 204 | 205 | 206 | 207 | Returns `stream` an empty stream (can be ended) 208 | 209 | 210 | ## `flyd.scan` 211 | 212 | Creates a new stream with the results of calling the function on every incoming 213 | stream with and accumulator and the incoming value. 214 | 215 | __Signature__: `(a -> b -> a) -> a -> Stream b -> Stream a` 216 | 217 | ### Parameters 218 | 219 | * `fn` **`Function`** the function to call 220 | * `val` **`Any`** the initial value of the accumulator 221 | * `stream` **`stream`** the stream source 222 | 223 | 224 | ### Examples 225 | 226 | ```js 227 | var numbers = flyd.stream(); 228 | var sum = flyd.scan(function(sum, n) { return sum+n; }, 0, numbers); 229 | numbers(2)(3)(5); 230 | sum(); // 10 231 | ``` 232 | 233 | Returns `stream` the new stream 234 | 235 | 236 | ## `flyd.stream` 237 | 238 | Creates a new stream 239 | 240 | __Signature__: `a -> Stream a` 241 | 242 | ### Parameters 243 | 244 | * `initialValue` **`Any`** (Optional) the initial value of the stream 245 | 246 | 247 | ### Examples 248 | 249 | ```js 250 | var n = flyd.stream(1); // Stream with initial value `1` 251 | var s = flyd.stream(); // Stream with no initial value 252 | ``` 253 | 254 | Returns `stream` the stream 255 | 256 | 257 | ## `flyd.transduce` 258 | 259 | Creates a new stream resulting from applying `transducer` to `stream`. 260 | 261 | __Signature__: `Transducer -> Stream a -> Stream b` 262 | 263 | ### Parameters 264 | 265 | * `xform` **`Transducer`** the transducer transformation 266 | * `source` **`stream`** the stream source 267 | 268 | 269 | ### Examples 270 | 271 | ```js 272 | var t = require('transducers.js'); 273 | 274 | var results = []; 275 | var s1 = flyd.stream(); 276 | var tx = t.compose(t.map(function(x) { return x * 2; }), t.dedupe()); 277 | var s2 = flyd.transduce(tx, s1); 278 | flyd.combine(function(s2) { results.push(s2()); }, [s2]); 279 | s1(1)(1)(2)(3)(3)(3)(4); 280 | results; // => [2, 4, 6, 8] 281 | ``` 282 | 283 | Returns `stream` the new stream 284 | 285 | 286 | ## `stream.ap` 287 | 288 | Returns a new stream which is the result of applying the 289 | functions from `this` stream to the values in `stream` parameter. 290 | 291 | `this` stream must be a stream of functions. 292 | 293 | _Note:_ This function is included in order to support the fantasy land 294 | specification. 295 | 296 | __Signature__: Called bound to `Stream (a -> b)`: `a -> Stream b` 297 | 298 | ### Parameters 299 | 300 | * `stream` **`stream`** the values stream 301 | 302 | 303 | ### Examples 304 | 305 | ```js 306 | var add = flyd.curryN(2, function(x, y) { return x + y; }); 307 | var numbers1 = flyd.stream(); 308 | var numbers2 = flyd.stream(); 309 | var addToNumbers1 = flyd.map(add, numbers1); 310 | var added = addToNumbers1.ap(numbers2); 311 | ``` 312 | 313 | Returns `stream` a new stram with the functions applied to values 314 | 315 | 316 | ## `stream.end` 317 | 318 | 319 | 320 | 321 | 322 | 323 | 324 | 325 | ## `stream.map` 326 | 327 | Returns a new stream identical to the original except every 328 | value will be passed through `f`. 329 | 330 | _Note:_ This function is included in order to support the fantasy land 331 | specification. 332 | 333 | __Signature__: Called bound to `Stream a`: `(a -> b) -> Stream b` 334 | 335 | ### Parameters 336 | 337 | * `function` **`Function`** the function to apply 338 | 339 | 340 | ### Examples 341 | 342 | ```js 343 | var numbers = flyd.stream(0); 344 | var squaredNumbers = numbers.map(function(n) { return n*n; }); 345 | ``` 346 | 347 | Returns `stream` a new stream with the values mapped 348 | 349 | 350 | ## `stream.of` 351 | 352 | 353 | 354 | ### Parameters 355 | 356 | * `value` **`Any`** the initial value 357 | 358 | 359 | ### Examples 360 | 361 | ```js 362 | var n = flyd.stream(1); 363 | var m = n.of(1); 364 | ``` 365 | 366 | Returns `stream` the new stream 367 | 368 | 369 | ## `stream.toString` 370 | 371 | Get a human readable view of a stream 372 | 373 | 374 | 375 | 376 | Returns `String` the stream string representation 377 | -------------------------------------------------------------------------------- /HISTORY.md: -------------------------------------------------------------------------------- 1 | ### v.0.2.0 2 | 3 | * Fixed bug in `flyd/module/scanmerge` 4 | * Removed dependent stream syntax `flyd.stream([streams], combinFn)` in 5 | favor of the function `combine`. `flyd.stream` is now only used for 6 | creating top level streams. 7 | * Added `flyd.combine` 8 | 9 | ``` 10 | flyd.combine((depA, depB, ..., depN, self, changed) => *, [depA, depB, ..., depN]); 11 | ``` 12 | 13 | `self` is the combined stream and `changed` is an array of the streams 14 | that have changed. 15 | 16 | To update replace 17 | 18 | ```javascript 19 | var a = flyd.stream(); 20 | var b = flyd.stream(); 21 | var sum = flyd.stream([a, b], function() { 22 | return a() + b(); 23 | } 24 | ``` 25 | 26 | with 27 | 28 | ``` 29 | var b = flyd.stream(0); 30 | var a = flyd.stream(0); 31 | var sum = flyd.combine(function(a, b) { 32 | return a + b; 33 | }, [a, b]); 34 | ``` -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2015 Simon Friis Vindum 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | 23 | -------------------------------------------------------------------------------- /bower.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "flyd", 3 | "main": "flyd.js", 4 | "version": "0.1.14", 5 | "homepage": "https://github.com/paldepind/flyd", 6 | "authors": [ 7 | "Simon Friis Vindum" 8 | ], 9 | "description": "The less is more, modular functional reactive programming library", 10 | "moduleType": [ 11 | "amd", 12 | "globals", 13 | "node" 14 | ], 15 | "keywords": [ 16 | "functional", 17 | "reactive", 18 | "modular" 19 | ], 20 | "license": "MIT", 21 | "ignore": [ 22 | "**/.*", 23 | "node_modules", 24 | "bower_components", 25 | "test", 26 | "tests" 27 | ] 28 | } 29 | -------------------------------------------------------------------------------- /build-examples.js: -------------------------------------------------------------------------------- 1 | const rollup = require('rollup'); 2 | const resolve = require('rollup-plugin-node-resolve'); 3 | const commonjs = require('rollup-plugin-commonjs'); 4 | 5 | const fs = require('fs'); 6 | const path = require('path'); 7 | 8 | async function build(example) { 9 | console.log('Building ' + example); 10 | 11 | const inputOptions = { 12 | input: path.resolve(`./examples/${example}/script.js`), 13 | plugins: [ 14 | resolve(), 15 | commonjs() 16 | ] 17 | } 18 | const outputOptions = { 19 | format: 'iife', 20 | file: path.resolve(`./examples/${example}/build.js`), 21 | name: example.replace(/-/g, ''), 22 | } 23 | // create a bundle 24 | const bundle = await rollup.rollup(inputOptions); 25 | 26 | // write bundle 27 | await bundle.write(outputOptions); 28 | 29 | console.log('Built ' + example); 30 | } 31 | 32 | const examples = fs.readdirSync('./examples'); 33 | 34 | Promise.all(examples.map(build)) 35 | .then(()=> console.log('Success!')) 36 | .catch(err => { 37 | console.error('Failed!'); 38 | console.error(err); 39 | process.exit(1); 40 | }); -------------------------------------------------------------------------------- /examples/drag-and-drop/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Multiple clicks 6 | 7 | 8 | 20 | 21 | 22 |
23 | Drag Me 24 |
25 |

26 | See the source code 27 |

28 | 29 | 30 | -------------------------------------------------------------------------------- /examples/drag-and-drop/script.js: -------------------------------------------------------------------------------- 1 | var flyd = require('../../lib'); 2 | var takeUntil = require('../../module/takeuntil'); 3 | 4 | document.addEventListener('DOMContentLoaded', function() { 5 | var dragElm = document.getElementById('drag'); 6 | 7 | var mousedown = flyd.stream(); 8 | var mousemove = flyd.stream(); 9 | var mouseup = flyd.stream(); 10 | 11 | dragElm.addEventListener('mousedown', mousedown); 12 | document.addEventListener('mousemove', mousemove); 13 | document.addEventListener('mouseup', mouseup); 14 | 15 | var mousedrag = flyd.chain(function(md) { 16 | var startX = md.offsetX, startY = md.offsetY; 17 | 18 | return takeUntil(flyd.map(function(mm) { 19 | mm.preventDefault(); 20 | 21 | return { 22 | left: mm.clientX - startX, 23 | top: mm.clientY - startY 24 | }; 25 | }, mousemove), mouseup); 26 | }, mousedown); 27 | 28 | flyd.on(function(pos) { 29 | dragElm.style.top = pos.top + 'px'; 30 | dragElm.style.left = pos.left + 'px'; 31 | }, mousedrag); 32 | }); 33 | -------------------------------------------------------------------------------- /examples/multiple-clicks/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Multiple clicks 6 | 7 | 8 | 9 | 10 | 11 | Double click it 12 |

13 | See the source code 14 |

15 | 16 | 17 | -------------------------------------------------------------------------------- /examples/multiple-clicks/node_modules/flyd-aftersilence/LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2015 Simon Friis Vindum 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | 23 | -------------------------------------------------------------------------------- /examples/multiple-clicks/node_modules/flyd-aftersilence/README.md: -------------------------------------------------------------------------------- 1 | # flyd-aftersilence 2 | Buffers values from a source stream in an array and emits it after a 3 | specified duration of silience from the source stream. 4 | 5 | __Signature__ 6 | 7 | `Stream a -> Stream b 8 | 9 | __Example__ 10 | 11 | ```javascript 12 | afterSilence(function(values) { 13 | console.log('You achieved a combo of + values.length + '!'); 14 | }, afterSilence(1000, birdsShot); 15 | ``` 16 | 17 | ```javascript 18 | afterSilence(function(values) { 19 | console.log('You typed: "' + values.join('') + '" without any pauses'); 20 | }, afterSilence(300, characterTyped); 21 | ``` 22 | -------------------------------------------------------------------------------- /examples/multiple-clicks/node_modules/flyd-aftersilence/aftersilence.js: -------------------------------------------------------------------------------- 1 | var flyd = require('flyd'); 2 | 3 | module.exports = function(dur, s) { 4 | var scheduled; 5 | var buffer = []; 6 | var ns = flyd.stream(); 7 | flyd.map(function(v) { 8 | buffer.push(v); 9 | clearTimeout(scheduled); 10 | scheduled = setTimeout(function() { 11 | ns(buffer); 12 | buffer = []; 13 | }, dur); 14 | }, s); 15 | return ns; 16 | }; 17 | -------------------------------------------------------------------------------- /examples/multiple-clicks/node_modules/flyd-aftersilence/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "flyd-aftersilence", 3 | "version": "0.0.2", 4 | "description": "Flyd module that buffers values from a stream and emits them after a specified duration of silience", 5 | "main": "aftersilence.js", 6 | "directories": { 7 | "test": "test" 8 | }, 9 | "scripts": { 10 | "test": "mocha" 11 | }, 12 | "repository": { 13 | "type": "git", 14 | "url": "https://github.com/paldepind/flyd-aftersilence.git" 15 | }, 16 | "keywords": [ 17 | "flyd", 18 | "buffer", 19 | "time", 20 | "silence", 21 | "delay", 22 | "group" 23 | ], 24 | "author": { 25 | "name": "Simon Friis Vindum" 26 | }, 27 | "license": "MIT", 28 | "bugs": { 29 | "url": "https://github.com/paldepind/flyd-aftersilence/issues" 30 | }, 31 | "homepage": "https://github.com/paldepind/flyd-aftersilence", 32 | "dependencies": { 33 | "flyd": "0.0.x" 34 | }, 35 | "readme": "# flyd-aftersilence\nBuffers values from a source stream in an array and emits it after a\nspecified duration of silience from the source stream.\n\n__Signature__\n\n`Stream a -> Stream b\n\n__Example__\n\n```javascript\nafterSilence(function(values) {\n console.log('You achieved a combo of + values.length + '!');\n}, afterSilence(1000, birdsShot);\n```\n\n```javascript\nafterSilence(function(values) {\n console.log('You typed: \"' + values.join('') + '\" without any pauses');\n}, afterSilence(300, characterTyped);\n```\n", 36 | "readmeFilename": "README.md", 37 | "gitHead": "08d1c025ddb3d45745e436587ab763180646e92c", 38 | "_id": "flyd-aftersilence@0.0.2", 39 | "_shasum": "f480d60ac20b7a266b8db72f96f3929c289798bc", 40 | "_from": "flyd-aftersilence@>=0.0.0 <0.1.0" 41 | } 42 | -------------------------------------------------------------------------------- /examples/multiple-clicks/node_modules/flyd-aftersilence/test/index.js: -------------------------------------------------------------------------------- 1 | var assert = require('assert'); 2 | var flyd = require('flyd'); 3 | var stream = flyd.stream; 4 | 5 | var afterSilence = require('../aftersilence.js'); 6 | 7 | // KISS way of testing time dependent code :) 8 | 9 | describe('afterSilence', function() { 10 | it('correctly buffers values', function(done) { 11 | var result = []; 12 | var i = 0; 13 | var s1 = stream(); 14 | var push = function() { 15 | s1(i++); 16 | }; 17 | var s2 = afterSilence(50, s1); 18 | flyd.map(function(vs) { 19 | result.push(vs); 20 | }, s2); 21 | setTimeout(push, 20); 22 | setTimeout(push, 30); 23 | setTimeout(push, 40); 24 | setTimeout(push, 95); 25 | setTimeout(push, 100); 26 | setTimeout(push, 110); 27 | setTimeout(push, 120); 28 | setTimeout(push, 175); 29 | setTimeout(function() { 30 | assert.deepEqual(result, [ 31 | [0, 1, 2], 32 | [3, 4, 5, 6], 33 | [7], 34 | ]); 35 | done(); 36 | }, 240); 37 | }); 38 | it('only emits values after specified silence', function(done) { 39 | var result = []; 40 | var i = 0; 41 | var s1 = stream(); 42 | var push = function() { 43 | s1(i++); 44 | }; 45 | var s2 = afterSilence(20, s1); 46 | flyd.map(function(vs) { 47 | result.push(vs); 48 | }, s2); 49 | setTimeout(push, 10); 50 | setTimeout(push, 20); 51 | setTimeout(push, 30); 52 | setTimeout(push, 40); 53 | setTimeout(function() { 54 | assert.equal(result.length, 0); 55 | }, 50); 56 | setTimeout(function() { 57 | assert.deepEqual(result, [[0, 1, 2, 3]]); 58 | done(); 59 | }, 65); 60 | }); 61 | }); 62 | -------------------------------------------------------------------------------- /examples/multiple-clicks/node_modules/flyd/.travis.yml: -------------------------------------------------------------------------------- 1 | language: node_js 2 | node_js: 3 | - "0.12" 4 | - "0.10" 5 | - "iojs" 6 | after_success: 7 | - ./node_modules/.bin/istanbul cover ./node_modules/mocha/bin/_mocha --report lcovonly -- -R spec && cat ./coverage/lcov.info | ./node_modules/coveralls/bin/coveralls.js && rm -rf ./coverage 8 | -------------------------------------------------------------------------------- /examples/multiple-clicks/node_modules/flyd/LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2015 Simon Friis Vindum 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | 23 | -------------------------------------------------------------------------------- /examples/multiple-clicks/node_modules/flyd/bower.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "flyd", 3 | "main": "flyd.js", 4 | "version": "0.0.1", 5 | "homepage": "https://github.com/paldepind/flyd", 6 | "authors": [ 7 | "Simon Friis Vindum" 8 | ], 9 | "description": "The less is more, modular functional reactive programming library", 10 | "moduleType": [ 11 | "amd", 12 | "globals", 13 | "node" 14 | ], 15 | "keywords": [ 16 | "functional", 17 | "reactive", 18 | "modular" 19 | ], 20 | "license": "MIT", 21 | "ignore": [ 22 | "**/.*", 23 | "node_modules", 24 | "bower_components", 25 | "test", 26 | "tests" 27 | ] 28 | } 29 | -------------------------------------------------------------------------------- /examples/multiple-clicks/node_modules/flyd/coverage/lcov.info: -------------------------------------------------------------------------------- 1 | TN: 2 | SF:/home/simon/projects/flyd/flyd.js 3 | FN:1,(anonymous_1) 4 | FN:9,(anonymous_2) 5 | FN:13,isFunction 6 | FN:17,isUndefined 7 | FN:27,flushQueue 8 | FN:35,addDependency 9 | FN:42,checkCirc 10 | FN:48,removeListener 11 | FN:54,map 12 | FN:55,(anonymous_10) 13 | FN:58,reduce 14 | FN:59,(anonymous_12) 15 | FN:64,merge 16 | FN:65,(anonymous_14) 17 | FN:75,ap 18 | FN:77,(anonymous_16) 19 | FN:80,of 20 | FN:84,initialDepsNotMet 21 | FN:86,(anonymous_19) 22 | FN:94,updateStream 23 | FN:103,destroyStream 24 | FN:112,stream 25 | FN:113,s 26 | FN:124,(anonymous_24) 27 | FN:157,(anonymous_25) 28 | FN:168,transduce 29 | FN:170,(anonymous_27) 30 | FN:175,StreamTransformer 31 | FN:176,(anonymous_29) 32 | FN:177,(anonymous_30) 33 | FN:178,(anonymous_31) 34 | FNF:31 35 | FNH:29 36 | FNDA:1,(anonymous_1) 37 | FNDA:1,(anonymous_2) 38 | FNDA:336,isFunction 39 | FNDA:646,isUndefined 40 | FNDA:152,flushQueue 41 | FNDA:212,addDependency 42 | FNDA:17,checkCirc 43 | FNDA:2,removeListener 44 | FNDA:7,map 45 | FNDA:14,(anonymous_10) 46 | FNDA:1,reduce 47 | FNDA:4,(anonymous_12) 48 | FNDA:1,merge 49 | FNDA:8,(anonymous_14) 50 | FNDA:9,ap 51 | FNDA:21,(anonymous_16) 52 | FNDA:7,of 53 | FNDA:167,initialDepsNotMet 54 | FNDA:37,(anonymous_19) 55 | FNDA:167,updateStream 56 | FNDA:2,destroyStream 57 | FNDA:114,stream 58 | FNDA:537,s 59 | FNDA:109,(anonymous_24) 60 | FNDA:22,(anonymous_25) 61 | FNDA:3,transduce 62 | FNDA:15,(anonymous_27) 63 | FNDA:3,StreamTransformer 64 | FNDA:0,(anonymous_29) 65 | FNDA:0,(anonymous_30) 66 | FNDA:10,(anonymous_31) 67 | DA:1,1 68 | DA:2,1 69 | DA:3,0 70 | DA:4,1 71 | DA:5,1 72 | DA:7,0 73 | DA:13,1 74 | DA:14,336 75 | DA:17,1 76 | DA:18,646 77 | DA:22,1 78 | DA:23,1 79 | DA:25,1 80 | DA:27,1 81 | DA:28,152 82 | DA:29,15 83 | DA:30,5 84 | DA:35,1 85 | DA:36,212 86 | DA:37,69 87 | DA:38,69 88 | DA:42,1 89 | DA:43,17 90 | DA:44,2 91 | DA:48,1 92 | DA:49,2 93 | DA:50,2 94 | DA:51,2 95 | DA:54,1 96 | DA:55,14 97 | DA:58,1 98 | DA:59,1 99 | DA:60,4 100 | DA:64,1 101 | DA:65,1 102 | DA:66,8 103 | DA:67,8 104 | DA:69,1 105 | DA:70,1 106 | DA:75,1 107 | DA:76,9 108 | DA:77,21 109 | DA:80,1 110 | DA:81,7 111 | DA:84,1 112 | DA:85,167 113 | DA:86,34 114 | DA:87,37 115 | DA:89,34 116 | DA:91,167 117 | DA:94,1 118 | DA:95,167 119 | DA:96,154 120 | DA:97,154 121 | DA:98,152 122 | DA:99,152 123 | DA:100,152 124 | DA:103,1 125 | DA:104,2 126 | DA:105,1 127 | DA:107,1 128 | DA:108,3 129 | DA:112,1 130 | DA:113,1 131 | DA:114,537 132 | DA:115,222 133 | DA:116,2 134 | DA:117,2 135 | DA:119,220 136 | DA:120,220 137 | DA:121,17 138 | DA:122,15 139 | DA:124,203 140 | DA:126,218 141 | DA:128,315 142 | DA:129,190 143 | DA:131,315 144 | DA:134,114 145 | DA:135,114 146 | DA:136,114 147 | DA:137,114 148 | DA:138,114 149 | DA:139,114 150 | DA:140,114 151 | DA:142,114 152 | DA:143,114 153 | DA:144,114 154 | DA:145,114 155 | DA:147,114 156 | DA:148,21 157 | DA:149,21 158 | DA:150,21 159 | DA:151,8 160 | DA:154,114 161 | DA:155,53 162 | DA:156,53 163 | DA:157,21 164 | DA:158,22 165 | DA:161,53 166 | DA:163,61 167 | DA:165,112 168 | DA:168,1 169 | DA:169,3 170 | DA:170,3 171 | DA:171,15 172 | DA:175,1 173 | DA:176,1 174 | DA:177,1 175 | DA:178,10 176 | DA:180,1 177 | LF:110 178 | LH:108 179 | BRDA:2,1,0,0 180 | BRDA:2,1,1,1 181 | BRDA:2,2,0,1 182 | BRDA:2,2,1,0 183 | BRDA:4,3,0,1 184 | BRDA:4,3,1,0 185 | BRDA:14,4,0,336 186 | BRDA:14,4,1,90 187 | BRDA:14,4,2,90 188 | BRDA:14,4,3,55 189 | BRDA:36,5,0,69 190 | BRDA:36,5,1,143 191 | BRDA:43,6,0,2 192 | BRDA:43,6,1,15 193 | BRDA:67,7,0,7 194 | BRDA:67,7,1,1 195 | BRDA:70,8,0,1 196 | BRDA:70,8,1,0 197 | BRDA:85,9,0,34 198 | BRDA:85,9,1,133 199 | BRDA:89,10,0,21 200 | BRDA:89,10,1,13 201 | BRDA:95,11,0,13 202 | BRDA:95,11,1,154 203 | BRDA:99,12,0,110 204 | BRDA:99,12,1,42 205 | BRDA:104,13,0,1 206 | BRDA:104,13,1,1 207 | BRDA:108,14,0,2 208 | BRDA:108,14,1,1 209 | BRDA:114,15,0,222 210 | BRDA:114,15,1,315 211 | BRDA:115,16,0,2 212 | BRDA:115,16,1,220 213 | BRDA:115,17,0,222 214 | BRDA:115,17,1,222 215 | BRDA:120,18,0,17 216 | BRDA:120,18,1,203 217 | BRDA:128,19,0,190 218 | BRDA:128,19,1,125 219 | BRDA:128,20,0,315 220 | BRDA:128,20,1,216 221 | BRDA:147,21,0,21 222 | BRDA:147,21,1,93 223 | BRDA:150,22,0,8 224 | BRDA:150,22,1,13 225 | BRDA:154,23,0,53 226 | BRDA:154,23,1,61 227 | BRDA:156,24,0,21 228 | BRDA:156,24,1,32 229 | BRF:50 230 | BRH:46 231 | end_of_record 232 | -------------------------------------------------------------------------------- /examples/multiple-clicks/node_modules/flyd/examples/multiple-clicks/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Multiple clicks 6 | 7 | 8 | 9 | 10 | 11 | Double click it 12 |

13 | See the source code 14 |

15 | 16 | 17 | -------------------------------------------------------------------------------- /examples/multiple-clicks/node_modules/flyd/examples/multiple-clicks/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "multiple-clicks", 3 | "version": "1.0.0", 4 | "description": "", 5 | "main": ".build.js", 6 | "scripts": { 7 | "test": "echo \"Error: no test specified\" && exit 1" 8 | }, 9 | "author": "Simon Friis Vindum", 10 | "license": "MIT", 11 | "dependencies": { 12 | "flyd": "0.0.x", 13 | "flyd-aftersilence": "0.0.x" 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /examples/multiple-clicks/node_modules/flyd/examples/multiple-clicks/script.js: -------------------------------------------------------------------------------- 1 | var flyd = require('flyd'); 2 | var afterSilence = require('flyd-aftersilence'); 3 | 4 | document.addEventListener('DOMContentLoaded', function() { 5 | var btnElm = document.getElementById('btn'); 6 | var msgElm = document.getElementById('msg'); 7 | 8 | var clickStream = flyd.stream(); 9 | btnElm.addEventListener('click', clickStream); 10 | 11 | var groupedClicks = afterSilence(250, clickStream); 12 | var nrStream = flyd.map(function(clicks) { return clicks.length; }, groupedClicks); 13 | 14 | flyd.map(function(nr) { 15 | msgElm.textContent = nr === 1 ? 'click' : nr + ' clicks'; 16 | }, nrStream); 17 | 18 | flyd.map(function(nr) { 19 | msgElm.textContent = ''; 20 | }, afterSilence(1000, nrStream)); 21 | }); 22 | -------------------------------------------------------------------------------- /examples/multiple-clicks/node_modules/flyd/examples/secret-combination/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Secret combination 6 | 7 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | 114 |
115 | 116 | 117 | -------------------------------------------------------------------------------- /examples/multiple-clicks/node_modules/flyd/examples/secret-combination/script.js: -------------------------------------------------------------------------------- 1 | (function() { 2 | 'use strict'; 3 | 4 | var stream = flyd.stream; 5 | 6 | var magicSeq = 'abbaba'; 7 | 8 | var setMsg = function(msg) { message.innerHTML = msg; }; 9 | 10 | document.addEventListener('DOMContentLoaded', function() { 11 | var click = stream(function(click) { 12 | btnA.addEventListener('click', click.bind(null, 'a')); 13 | btnB.addEventListener('click', click.bind(null, 'b')); 14 | }); 15 | var corrects = flyd.reduce(function(cs, c) { 16 | var l = cs.length, correct = (c === magicSeq[l]); 17 | return !correct && l > 0 ? [] 18 | : !correct && l === 0 ? undefined 19 | : l + 1 < magicSeq.length ? cs.concat(c) 20 | : (setMsg('Combination unlocked!'), []); 21 | }, [], click); 22 | var scheduled = flyd.map(function(cor) { 23 | if (cor.length === 1) return setTimeout(function() { 24 | setMsg('You\'re not fast enough, try again'); 25 | corrects([]); 26 | }, 5000); 27 | }, corrects); 28 | flyd.map(function(c) { console.log(c); }, corrects); 29 | stream(function() { 30 | if (corrects().length === 0 && scheduled.val) clearTimeout(scheduled.val); 31 | }); 32 | }); 33 | })(); 34 | -------------------------------------------------------------------------------- /examples/multiple-clicks/node_modules/flyd/examples/sum/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Sum – a Flyd demo 6 | 7 | 103 | 104 | 150 | 151 | 152 |
153 |

Sum

154 |
155 |
156 |

Execute

157 |

158 | Also try calling x and y in your browser console. 159 |

160 |

161 | x(1) 162 | x(2) 163 | x(3) 164 | x(5) 165 | x(8) 166 | x(13) 167 |

168 |

169 | y(1) 170 | y(2) 171 | y(3) 172 | y(5) 173 | y(8) 174 | y(13) 175 |

176 |

177 | x(x() + 1) 178 | x(x() - 1) 179 |

180 |

181 | y(y() + 1) 182 | y(y() - 1) 183 |

184 |
185 |
186 |

Result

187 |

188 | x is ... 189 |

190 |

191 | y is ... 192 |

193 |

194 | sum is ... 195 |

196 |
197 |
198 |

Source code

199 | var x = stream(10); 200 | var y = stream(20); 201 | var sum = stream(function() { 202 | return x() + y(); 203 | }); 204 | var elm = document.getElementById('sumBox'); 205 | stream(function() { 206 | elm.innerHTML = sum(); 207 | }); 208 |
209 | 210 | 211 | -------------------------------------------------------------------------------- /examples/multiple-clicks/node_modules/flyd/flyd.js: -------------------------------------------------------------------------------- 1 | (function (root, factory) { 2 | if (typeof define === 'function' && define.amd) { 3 | define([], factory); // AMD. Register as an anonymous module. 4 | } else if (typeof exports === 'object') { 5 | module.exports = factory(); // NodeJS 6 | } else { // Browser globals (root is window) 7 | root.flyd = factory(); 8 | } 9 | }(this, function () { 10 | 11 | 'use strict'; 12 | 13 | function isFunction(obj) { 14 | return !!(obj && obj.constructor && obj.call && obj.apply); 15 | } 16 | 17 | function isUndefined(v) { 18 | return v === undefined; 19 | } 20 | 21 | // Globals 22 | var curStream; 23 | var nextId = 0; 24 | var queue = []; 25 | 26 | function flushQueue() { 27 | for (var q; q = queue.pop();) { 28 | for (var i = 0; i < q.l.length; ++i) { 29 | q.l[i](q.v); 30 | } 31 | } 32 | } 33 | 34 | function addDependency(to, from) { 35 | if (!(from.id in to.deps)) { 36 | to.deps[from.id] = from.listeners; 37 | from.listeners.push(to.update); 38 | } 39 | } 40 | 41 | function checkCirc(stream, id) { 42 | if (stream.deps[id]) { 43 | throw new Error('Circular dependency detected'); 44 | } 45 | } 46 | 47 | function removeListener(listeners, cb) { 48 | var idx = listeners.indexOf(cb); 49 | listeners[idx] = listeners[listeners.length - 1]; 50 | listeners.length--; 51 | } 52 | 53 | function map(s, f) { 54 | return stream([s], function() { return f(s()); }, true); 55 | } 56 | 57 | var reduce = curryN(3, function(f, acc, s) { 58 | var ns = stream([s], function() { 59 | return (acc = f(acc, s())); 60 | }, true); 61 | if (!ns.hasVal) ns(acc); 62 | return ns; 63 | }); 64 | 65 | var merge = curryN(2, function(s1, s2) { 66 | return stream(function(n, changed) { 67 | var v1, v2; 68 | if (changed) return changed(); 69 | else { 70 | v1 = s1(); v2 = s2(); 71 | return v1 === undefined ? v2 : v1; 72 | } 73 | }); 74 | }); 75 | 76 | function ap(s2) { 77 | var s1 = this; 78 | return stream(function() { return s1()(s2()); }); 79 | } 80 | 81 | function of(v) { 82 | return stream()(v); 83 | } 84 | 85 | function initialDepsNotMet(stream) { 86 | if (!isUndefined(stream.initialDeps)) { 87 | var met = stream.initialDeps.every(function(stream) { 88 | return stream.hasVal; 89 | }); 90 | if (met) stream.initialDeps = undefined; 91 | } 92 | return !isUndefined(stream.initialDeps); 93 | } 94 | 95 | function updateStream(stream, cb, changed) { 96 | if (initialDepsNotMet(stream)) return; 97 | curStream = stream; 98 | var returnVal = cb(stream, changed); 99 | curStream = undefined; 100 | if (returnVal !== undefined) stream(returnVal); 101 | flushQueue(); 102 | } 103 | 104 | function destroy(stream) { 105 | if (stream.listeners.length !== 0) { 106 | throw new Error('Trying to destroy stream with listeners attached'); 107 | } 108 | for (var id in stream.deps) { 109 | if (stream.deps[id]) removeListener(stream.deps[id], stream.update); 110 | } 111 | } 112 | 113 | function isStream(stream) { 114 | return isFunction(stream) && 'id' in stream; 115 | } 116 | 117 | function streamToString() { 118 | return 'stream(' + this.val + ')'; 119 | } 120 | 121 | function stream(arg) { 122 | function s(n) { 123 | if (arguments.length > 0) { 124 | if (!isUndefined(n) && n !== null && isFunction(n.then)) { 125 | n.then(s); 126 | return; 127 | } 128 | s.val = n; 129 | s.hasVal = true; 130 | if (!isUndefined(curStream)) { 131 | checkCirc(curStream, s.id); 132 | queue.push({v: s, l: s.listeners}); 133 | } else { 134 | s.listeners.forEach(function(f) { f(s); }); 135 | } 136 | return s; 137 | } else { 138 | if (curStream && curStream.dynamicDeps) { 139 | addDependency(curStream, s); 140 | } 141 | return s.val; 142 | } 143 | } 144 | s.hasVal = false; 145 | s.val = undefined; 146 | s.listeners = []; 147 | s.id = nextId++; 148 | s.deps = {}; 149 | s.initialDeps = undefined; 150 | s.deps[s.id] = false; 151 | s.dynamicDeps = true; 152 | 153 | s.map = map.bind(null, s); 154 | s.ap = ap; 155 | s.of = of; 156 | s.toString = streamToString; 157 | 158 | if (arguments.length > 1) { 159 | s.initialDeps = arg; 160 | arg = arguments[1]; 161 | if (arguments[2] === true) { 162 | s.dynamicDeps = false; 163 | } 164 | } 165 | if (arguments.length > 0) { 166 | if (isFunction(arg)) { 167 | s.update = updateStream.bind(null, s, arg); 168 | if (s.initialDeps) { 169 | s.initialDeps.forEach(function(stream) { 170 | addDependency(s, stream); 171 | }); 172 | } 173 | s.update(); 174 | } else { 175 | s.val = arg; 176 | s.hasVal = true; 177 | } 178 | } 179 | return s; 180 | } 181 | 182 | var transduce = curryN(2, function(xform, source) { 183 | xform = xform(new StreamTransformer(stream)); 184 | return stream([source], function() { 185 | return xform.step(undefined, source()); 186 | }); 187 | }); 188 | 189 | function StreamTransformer(res) { } 190 | StreamTransformer.prototype.init = function() { }; 191 | StreamTransformer.prototype.result = function() { }; 192 | StreamTransformer.prototype.step = function(s, v) { return v; }; 193 | 194 | // Own curry implementation snatched from Ramda 195 | // Figure out something nicer later on 196 | var _ = {placeholder: true}; 197 | 198 | // Detect both own and Ramda placeholder 199 | function isPlaceholder(p) { 200 | return p === _ || (p && p.ramda === 'placeholder'); 201 | } 202 | 203 | function toArray(arg) { 204 | var arr = []; 205 | for (var i = 0; i < arg.length; ++i) { 206 | arr[i] = arg[i]; 207 | } 208 | return arr; 209 | } 210 | 211 | // Modified versions of arity and curryN from Ramda 212 | function ofArity(n, fn) { 213 | if (arguments.length === 1) { 214 | return ofArity.bind(undefined, n); 215 | } 216 | switch (n) { 217 | case 0: 218 | return function () { 219 | return fn.apply(this, arguments); 220 | }; 221 | case 1: 222 | return function (a0) { 223 | void a0; 224 | return fn.apply(this, arguments); 225 | }; 226 | case 2: 227 | return function (a0, a1) { 228 | void a1; 229 | return fn.apply(this, arguments); 230 | }; 231 | case 3: 232 | return function (a0, a1, a2) { 233 | void a2; 234 | return fn.apply(this, arguments); 235 | }; 236 | case 4: 237 | return function (a0, a1, a2, a3) { 238 | void a3; 239 | return fn.apply(this, arguments); 240 | }; 241 | case 5: 242 | return function (a0, a1, a2, a3, a4) { 243 | void a4; 244 | return fn.apply(this, arguments); 245 | }; 246 | case 6: 247 | return function (a0, a1, a2, a3, a4, a5) { 248 | void a5; 249 | return fn.apply(this, arguments); 250 | }; 251 | case 7: 252 | return function (a0, a1, a2, a3, a4, a5, a6) { 253 | void a6; 254 | return fn.apply(this, arguments); 255 | }; 256 | case 8: 257 | return function (a0, a1, a2, a3, a4, a5, a6, a7) { 258 | void a7; 259 | return fn.apply(this, arguments); 260 | }; 261 | case 9: 262 | return function (a0, a1, a2, a3, a4, a5, a6, a7, a8) { 263 | void a8; 264 | return fn.apply(this, arguments); 265 | }; 266 | case 10: 267 | return function (a0, a1, a2, a3, a4, a5, a6, a7, a8, a9) { 268 | void a9; 269 | return fn.apply(this, arguments); 270 | }; 271 | default: 272 | throw new Error('First argument to arity must be a non-negative integer no greater than ten'); 273 | } 274 | } 275 | 276 | function curryN(length, fn) { 277 | return ofArity(length, function () { 278 | var n = arguments.length; 279 | var shortfall = length - n; 280 | var idx = n; 281 | while (--idx >= 0) { 282 | if (isPlaceholder(arguments[idx])) { 283 | shortfall += 1; 284 | } 285 | } 286 | if (shortfall <= 0) { 287 | return fn.apply(this, arguments); 288 | } else { 289 | var initialArgs = toArray(arguments); 290 | return curryN(shortfall, function () { 291 | var currentArgs = toArray(arguments); 292 | var combinedArgs = []; 293 | var idx = -1; 294 | while (++idx < n) { 295 | var val = initialArgs[idx]; 296 | combinedArgs[idx] = isPlaceholder(val) ? currentArgs.shift() : val; 297 | } 298 | return fn.apply(this, combinedArgs.concat(currentArgs)); 299 | }); 300 | } 301 | }); 302 | } 303 | 304 | 305 | return { 306 | stream: stream, 307 | isStream: isStream, 308 | transduce: transduce, 309 | merge: merge, 310 | reduce: reduce, 311 | destroy: destroy, 312 | map: curryN(2, function(f, s) { return map(s, f); }), 313 | curryN: curryN, 314 | _: _, 315 | }; 316 | 317 | })); 318 | -------------------------------------------------------------------------------- /examples/multiple-clicks/node_modules/flyd/perf/perf.js: -------------------------------------------------------------------------------- 1 | var _ = require('lodash'); 2 | var Benchmark = require('benchmark.js'); 3 | 4 | var flyd = require('../flyd'); 5 | var oldFlyd = require('../flyd-old'); 6 | 7 | var stream = flyd.stream; 8 | 9 | global.stream = flyd.stream; 10 | global.flyd = flyd; 11 | global.oldFlyd = oldFlyd; 12 | global.oldStream = oldFlyd.stream; 13 | 14 | // ************************************************ 15 | // Util functions 16 | 17 | var suites = []; 18 | 19 | function getHz(bench) { // hz adjusted for margin of error 20 | var result = 1 / (bench.stats.mean + bench.stats.moe); 21 | return isFinite(result) ? result : 0; 22 | } 23 | 24 | function printFastest(suite) { 25 | var formatNumber = Benchmark.formatNumber, 26 | fastest = suite.filter('fastest'), 27 | fastestHz = getHz(fastest[0]), 28 | slowest = suite.filter('slowest'), 29 | slowestHz = getHz(slowest[0]), 30 | aHz = getHz(suite[0]), 31 | bHz = getHz(suite[1]); 32 | if (fastest.length > 1) { 33 | console.log('It\'s too close to call.'); 34 | aHz = bHz = slowestHz; 35 | } else { 36 | var percent = ((fastestHz / slowestHz) - 1) * 100; 37 | console.log(' ' + fastest[0].name + ' is ' + 38 | formatNumber(percent < 1 ? percent.toFixed(2) : Math.round(percent)) + 39 | '% faster.'); 40 | } 41 | } 42 | 43 | Benchmark.Suite.options.onStart = function() { 44 | console.log('\n' + this.name + ':'); 45 | }; 46 | 47 | Benchmark.Suite.options.onCycle = function(event) { 48 | console.log(' ' + event.target); 49 | }; 50 | 51 | Benchmark.Suite.options.onComplete = function() { 52 | printFastest(this); 53 | suites.shift(); 54 | if (suites.length) { 55 | suites[0].run({async: true}); 56 | } 57 | }; 58 | 59 | // ************************************************ 60 | // Benchmarks! 61 | 62 | suites.push(Benchmark.Suite('dynamic dependencies').add('New', { 63 | setup: function() { 64 | var s = stream(); 65 | stream(function() { 66 | return s(); 67 | }); 68 | }, 69 | fn: function() { 70 | s(12); 71 | }, 72 | }).add('Old', { 73 | setup: function() { 74 | var s = oldStream(); 75 | oldStream(function() { 76 | return s(); 77 | }); 78 | }, 79 | fn: function() { 80 | s(12); 81 | }, 82 | })); 83 | 84 | suites.push(Benchmark.Suite('static dependencies').add('New', { 85 | setup: function() { 86 | var s = stream(); 87 | stream([s], function() { 88 | return s(); 89 | }); 90 | }, 91 | fn: function() { 92 | s(12); 93 | }, 94 | }).add('Old', { 95 | setup: function() { 96 | var s = oldStream(); 97 | oldStream([s], function() { 98 | return s(); 99 | }); 100 | }, 101 | fn: function() { 102 | s(12); 103 | }, 104 | })); 105 | 106 | suites.push(Benchmark.Suite('map').add('First', { 107 | setup: function() { 108 | var flyd = global.flyd; 109 | var stream = global.flyd.stream; 110 | function f(x) { return x; } 111 | var s1 = stream(); 112 | var s2 = s1.map(f); 113 | var s3 = s2.map(f); 114 | var s4 = s3.map(f); 115 | var s5 = s4.map(f); 116 | }, 117 | fn: function() { 118 | s1(12); 119 | }, 120 | }).add('Second', { 121 | setup: function() { 122 | var flyd = global.flyd; 123 | var stream = global.flyd.stream; 124 | function f(x) { return x; } 125 | var s1 = stream(); 126 | var s2 = s1.map(f); 127 | var s3 = s2.map(f); 128 | var s4 = s3.map(f); 129 | var s5 = s4.map(f); 130 | }, 131 | fn: function() { 132 | s1(12); 133 | }, 134 | })); 135 | 136 | suites.push(Benchmark.Suite('dynamic dependency graph').add('New', { 137 | setup: function() { 138 | var s1 = stream(); 139 | var s2 = stream(function() { 140 | s1(); s1(); 141 | }); 142 | var s3 = stream(function() { 143 | s1(); s2(); s1(); 144 | }); 145 | var s4 = stream(function() { 146 | s1(); s2(); s3(); s1(); s3(); 147 | }); 148 | stream(function() { 149 | s3(); s2(); s1(); s3(); s4(); 150 | }); 151 | }, 152 | fn: function() { 153 | s1(12); 154 | }, 155 | }).add('Old', { 156 | setup: function() { 157 | var s1 = oldStream(); 158 | var s2 = oldStream(function() { 159 | s1(); s1(); 160 | }); 161 | var s3 = oldStream(function() { 162 | s1(); s2(); s1(); 163 | }); 164 | var s4 = oldStream(function() { 165 | s1(); s2(); s3(); s1(); s3(); 166 | }); 167 | oldStream(function() { 168 | s3(); s2(); s1(); s3(); s4(); 169 | }); 170 | }, 171 | fn: function() { 172 | s1(12); 173 | }, 174 | })); 175 | 176 | suites[0].run({ 'async': true }); 177 | -------------------------------------------------------------------------------- /examples/multiple-clicks/node_modules/flyd/perf/test.js: -------------------------------------------------------------------------------- 1 | var _ = require('lodash'); 2 | var Benchmark = require('benchmark.js'); 3 | 4 | var flyd = require('../flyd'); 5 | var oldFlyd = require('../flyd'); 6 | 7 | var stream = flyd.stream; 8 | global.stream = flyd.stream; 9 | global.flyd = flyd; 10 | global.oldFlyd = oldFlyd; 11 | 12 | // ************************************************ 13 | // Util functions 14 | 15 | var suites = []; 16 | 17 | function getHz(bench) { // hz adjusted for margin of error 18 | var result = 1 / (bench.stats.mean + bench.stats.moe); 19 | return isFinite(result) ? result : 0; 20 | } 21 | 22 | function printFastest(suite) { 23 | var formatNumber = Benchmark.formatNumber, 24 | fastest = suite.filter('fastest'), 25 | fastestHz = getHz(fastest[0]), 26 | slowest = suite.filter('slowest'), 27 | slowestHz = getHz(slowest[0]), 28 | aHz = getHz(suite[0]), 29 | bHz = getHz(suite[1]); 30 | if (fastest.length > 1) { 31 | console.log('It\'s too close to call.'); 32 | aHz = bHz = slowestHz; 33 | } else { 34 | var percent = ((fastestHz / slowestHz) - 1) * 100; 35 | console.log(' ' + fastest[0].name + ' is ' + 36 | formatNumber(percent < 1 ? percent.toFixed(2) : Math.round(percent)) + 37 | '% faster.'); 38 | } 39 | } 40 | 41 | Benchmark.Suite.options.onStart = function() { 42 | console.log('\n' + this.name + ':'); 43 | }; 44 | 45 | Benchmark.Suite.options.onCycle = function(event) { 46 | console.log(' ' + event.target); 47 | }; 48 | 49 | Benchmark.Suite.options.onComplete = function() { 50 | printFastest(this); 51 | suites.shift(); 52 | if (suites.length) { 53 | suites[0].run({async: true}); 54 | } 55 | }; 56 | 57 | // ************************************************ 58 | // Benchmarks! 59 | 60 | suites.push(Benchmark.Suite('First map test').add('First', { 61 | setup: function() { 62 | function f(x) { return x; } 63 | var s1 = stream(); 64 | var s2 = s1.map(f); 65 | var s3 = s2.map(f); 66 | var s4 = s3.map(f); 67 | var s5 = s4.map(f); 68 | }, 69 | fn: function() { 70 | s1(12); 71 | }, 72 | }).add('Second', { 73 | setup: function() { 74 | function f(x) { return x; } 75 | var s1 = stream(); 76 | var s2 = s1.map(f); 77 | var s3 = s2.map(f); 78 | var s4 = s3.map(f); 79 | var s5 = s4.map(f); 80 | }, 81 | fn: function() { 82 | s1(12); 83 | }, 84 | })); 85 | 86 | suites.push(Benchmark.Suite('Second map test').add('First', { 87 | setup: function() { 88 | var flyd = global.flyd; 89 | var stream = global.flyd.stream; 90 | function f(x) { return x; } 91 | var s1 = stream(); 92 | var s2 = s1.map(f); 93 | var s3 = s2.map(f); 94 | var s4 = s3.map(f); 95 | var s5 = s4.map(f); 96 | }, 97 | fn: function() { 98 | s1(12); 99 | }, 100 | }).add('Second', { 101 | setup: function() { 102 | var flyd = global.flyd; 103 | var stream = global.flyd.stream; 104 | function f(x) { return x; } 105 | var s1 = stream(); 106 | var s2 = s1.map(f); 107 | var s3 = s2.map(f); 108 | var s4 = s3.map(f); 109 | var s5 = s4.map(f); 110 | }, 111 | fn: function() { 112 | s1(12); 113 | }, 114 | })); 115 | 116 | suites[0].run({ 'async': true }); 117 | -------------------------------------------------------------------------------- /examples/multiple-clicks/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "multiple-clicks", 3 | "version": "1.0.0", 4 | "description": "", 5 | "main": ".build.js", 6 | "scripts": { 7 | "test": "echo \"Error: no test specified\" && exit 1" 8 | }, 9 | "author": "Simon Friis Vindum", 10 | "license": "MIT", 11 | "dependencies": { 12 | "flyd": "0.0.x", 13 | "flyd-aftersilence": "0.0.x" 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /examples/multiple-clicks/script.js: -------------------------------------------------------------------------------- 1 | var flyd = require('../../lib'); 2 | var afterSilence = require('../../module/aftersilence'); 3 | 4 | document.addEventListener('DOMContentLoaded', function() { 5 | var btnElm = document.getElementById('btn'); 6 | var msgElm = document.getElementById('msg'); 7 | 8 | var clickStream = flyd.stream(); 9 | btnElm.addEventListener('click', clickStream); 10 | 11 | var groupedClicks = afterSilence(250, clickStream); 12 | var nrStream = flyd.map(function(clicks) { return clicks.length; }, groupedClicks); 13 | 14 | flyd.map(function(nr) { 15 | msgElm.textContent = nr === 1 ? 'click' : nr + ' clicks'; 16 | }, nrStream); 17 | 18 | flyd.map(function(nr) { 19 | msgElm.textContent = ''; 20 | }, afterSilence(1000, nrStream)); 21 | }); 22 | -------------------------------------------------------------------------------- /examples/ramda-transducer/README.md: -------------------------------------------------------------------------------- 1 | # Ramda transducer example 2 | 3 | ```javascript 4 | npm install 5 | node script 6 | ``` 7 | -------------------------------------------------------------------------------- /examples/ramda-transducer/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "ramda-transducer-example", 3 | "version": "1.0.0", 4 | "description": "", 5 | "main": "script.js", 6 | "scripts": { 7 | "test": "echo \"Error: no test specified\" && exit 1" 8 | }, 9 | "author": "Simon Friis Vindum", 10 | "license": "MIT", 11 | "dependencies": { 12 | "flyd": "^0.1.0", 13 | "ramda": "^0.17.0" 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /examples/ramda-transducer/script.js: -------------------------------------------------------------------------------- 1 | var R = require('ramda'); 2 | var flyd = require('../../lib'); 3 | 4 | // Let's create a stream of numbers 5 | var numbers = flyd.stream(); 6 | 7 | var isEven = R.compose(R.identical(0), R.modulo(R.__, 2)); 8 | 9 | // All even numbers multiplied by 3 10 | var drop3evenTimes3 = flyd.transduce(R.compose( 11 | R.drop(3), 12 | R.filter(isEven), 13 | R.map(R.multiply(3)) 14 | ), numbers); 15 | 16 | flyd.map(function(n) { console.log(n); }, drop3evenTimes3); 17 | 18 | numbers(9)(4)(2)(8)(6)(5)(2); 19 | -------------------------------------------------------------------------------- /examples/secret-combination/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Secret combination 6 | 7 | 107 | 108 | 109 | 110 | 111 | 112 |
113 |

114 | This is an implementation of the problem described in Comparing Core Async and Rx by Example 115 |

116 |

117 | See the source code 118 |

119 | 120 | 121 | -------------------------------------------------------------------------------- /examples/secret-combination/node_modules/flyd-filter/LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2015 Simon Friis Vindum 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | 23 | -------------------------------------------------------------------------------- /examples/secret-combination/node_modules/flyd-filter/README.md: -------------------------------------------------------------------------------- 1 | # flyd-filter 2 | Filter function for Flyd. 3 | 4 | # Usage 5 | 6 | ```javascript 7 | var numbers = flyd.stream(); 8 | var largeNumbers = filter(over5, numbers); 9 | flyd.map(function(n) { 10 | // called with 6, 7 and 10 11 | }, largeNumbers); 12 | numbers(2)(6)(5)(3)(7)(10)(5); 13 | 14 | ``` 15 | -------------------------------------------------------------------------------- /examples/secret-combination/node_modules/flyd-filter/filter.js: -------------------------------------------------------------------------------- 1 | var flyd = require('flyd'); 2 | 3 | module.exports = function(fn, s) { 4 | return flyd.stream([s], function(self) { 5 | if (fn(s())) self(s.val); 6 | }); 7 | }; 8 | -------------------------------------------------------------------------------- /examples/secret-combination/node_modules/flyd-filter/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "flyd-filter", 3 | "version": "1.0.1", 4 | "description": "Filter function for Flyd.", 5 | "main": "filter.js", 6 | "directories": { 7 | "test": "test" 8 | }, 9 | "scripts": { 10 | "test": "mocha" 11 | }, 12 | "repository": { 13 | "type": "git", 14 | "url": "https://github.com/paldepind/flyd-filter.git" 15 | }, 16 | "keywords": [ 17 | "filter", 18 | "flyd" 19 | ], 20 | "author": { 21 | "name": "Simon Friis Vindum" 22 | }, 23 | "license": "MIT", 24 | "bugs": { 25 | "url": "https://github.com/paldepind/flyd-filter/issues" 26 | }, 27 | "homepage": "https://github.com/paldepind/flyd-filter", 28 | "devDependencies": { 29 | "flyd": "0.1.x" 30 | }, 31 | "gitHead": "8fb8d361750daa31739d84ef68b74a84271cdae4", 32 | "readme": "# flyd-filter\nFilter function for Flyd.\n\n# Usage\n\n```javascript\nvar numbers = flyd.stream();\nvar largeNumbers = filter(over5, numbers);\nflyd.map(function(n) {\n // called with 6, 7 and 10\n}, largeNumbers);\nnumbers(2)(6)(5)(3)(7)(10)(5);\n\n```\n", 33 | "readmeFilename": "README.md", 34 | "_id": "flyd-filter@1.0.1", 35 | "_shasum": "643c538a644fa1e0b301ed00575b646295b850d6", 36 | "_from": "flyd-filter@>=1.0.0 <2.0.0" 37 | } 38 | -------------------------------------------------------------------------------- /examples/secret-combination/node_modules/flyd-filter/test/index.js: -------------------------------------------------------------------------------- 1 | var assert = require('assert'); 2 | var flyd = require('flyd'); 3 | 4 | var filter = require('../filter.js'); 5 | 6 | describe('filter', function() { 7 | it('only lets values passing the filter through', function() { 8 | function over5(n) { 9 | return n > 5; 10 | } 11 | var result = []; 12 | var numbers = flyd.stream(); 13 | var largeNumbers = filter(over5, numbers); 14 | flyd.map(function(n) { 15 | result.push(n); 16 | }, largeNumbers); 17 | numbers(2)(6)(5)(3)(7)(10)(5); 18 | assert.deepEqual(result, [6, 7, 10]); 19 | }); 20 | }); 21 | -------------------------------------------------------------------------------- /examples/secret-combination/node_modules/flyd-inlast/LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2015 Simon Friis Vindum 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | 23 | -------------------------------------------------------------------------------- /examples/secret-combination/node_modules/flyd-inlast/README.md: -------------------------------------------------------------------------------- 1 | # flyd-inlast 2 | Creates a stream with emits a list of all values from the source stream that where emitted in a specified duration. 3 | -------------------------------------------------------------------------------- /examples/secret-combination/node_modules/flyd-inlast/inlast.js: -------------------------------------------------------------------------------- 1 | var flyd = require('flyd'); 2 | 3 | module.exports = flyd.curryN(2, function(dur, s) { 4 | var values = []; 5 | return flyd.stream([s], function(self) { 6 | setTimeout(function() { 7 | self(values = values.slice(1)); 8 | }, dur); 9 | return (values = values.concat([s()])); 10 | }); 11 | }); 12 | -------------------------------------------------------------------------------- /examples/secret-combination/node_modules/flyd-inlast/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "flyd-inlast", 3 | "version": "0.0.1", 4 | "description": "Creates a stream with emits a list of all values from the source stream that where emitted in a specified duration.", 5 | "main": "inlast.js", 6 | "directories": { 7 | "test": "test" 8 | }, 9 | "scripts": { 10 | "test": "mocha" 11 | }, 12 | "repository": { 13 | "type": "git", 14 | "url": "https://github.com/paldepind/flyd-inlast.git" 15 | }, 16 | "keywords": [ 17 | "flyd", 18 | "inlast", 19 | "time", 20 | "duration" 21 | ], 22 | "author": { 23 | "name": "Simon Friis Vindum" 24 | }, 25 | "license": "MIT", 26 | "bugs": { 27 | "url": "https://github.com/paldepind/flyd-inlast/issues" 28 | }, 29 | "homepage": "https://github.com/paldepind/flyd-inlast", 30 | "dependencies": { 31 | "flyd": "^0.1.0" 32 | }, 33 | "readme": "# flyd-inlast\nCreates a stream with emits a list of all values from the source stream that where emitted in a specified duration.\n", 34 | "readmeFilename": "README.md", 35 | "gitHead": "a952b1a8692a0ecdcc41cbb5cb4a4e57da5a4324", 36 | "_id": "flyd-inlast@0.0.1", 37 | "_shasum": "f5b98d171c34964db9e6e32cd0d22c4a5c0ea4d9", 38 | "_from": "flyd-inlast@>=0.0.0 <0.1.0" 39 | } 40 | -------------------------------------------------------------------------------- /examples/secret-combination/node_modules/flyd-inlast/test/index.js: -------------------------------------------------------------------------------- 1 | var assert = require('assert'); 2 | var flyd = require('flyd'); 3 | var stream = flyd.stream; 4 | 5 | var inLast = require('../inlast.js'); 6 | 7 | describe('inLast', function() { 8 | it('adds values', function(done) { 9 | var s = stream(); 10 | var lastMs = inLast(50, s); 11 | s(1); 12 | setTimeout(function() { 13 | assert.deepEqual(lastMs(), [1]); 14 | s(2); 15 | }, 20); 16 | setTimeout(function() { 17 | assert.deepEqual(lastMs(), [1, 2]); 18 | done(); 19 | }, 40); 20 | }); 21 | it('adds and removes values', function(done) { 22 | var s = stream(); 23 | var lastMs = inLast(50, s); 24 | s(1); 25 | setTimeout(function() { 26 | assert.deepEqual(lastMs(), [1]); 27 | s(2); 28 | }, 35); 29 | setTimeout(function() { 30 | assert.deepEqual(lastMs(), [1, 2]); 31 | s(3); 32 | }, 40); 33 | setTimeout(function() { 34 | assert.deepEqual(lastMs(), [2, 3]); 35 | s(4); 36 | }, 60); 37 | setTimeout(function() { 38 | assert.deepEqual(lastMs(), [2, 3, 4]); 39 | s(5); 40 | }, 80); 41 | setTimeout(function() { 42 | assert.deepEqual(lastMs(), [4, 5]); 43 | done(); 44 | }, 100); 45 | }); 46 | it('is updated when values come and go', function(done) { 47 | var result = []; 48 | var s = stream(); 49 | var lastMs = inLast(50, s); 50 | flyd.map(function(a) { result.push(a); }, lastMs); 51 | s(1); 52 | setTimeout(function() { s(2); }, 35); 53 | setTimeout(function() { s(3); }, 40); 54 | // 1 leaves 55 | setTimeout(function() { s(4); }, 60); 56 | setTimeout(function() { s(5); }, 80); 57 | // 2 leaves 58 | // 3 leaves 59 | setTimeout(function() { 60 | assert.deepEqual(result, [ 61 | [1], 62 | [1, 2], 63 | [1, 2, 3], 64 | [2, 3], 65 | [2, 3, 4], 66 | [2, 3, 4, 5], 67 | [3, 4, 5], 68 | [4, 5], 69 | ]); 70 | done(); 71 | }, 100); 72 | }); 73 | }); 74 | -------------------------------------------------------------------------------- /examples/secret-combination/node_modules/flyd-lift/LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2015 Simon Friis Vindum 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | 23 | -------------------------------------------------------------------------------- /examples/secret-combination/node_modules/flyd-lift/README.md: -------------------------------------------------------------------------------- 1 | # flyd-lift 2 | Lift function for [Flyd](https://github.com/paldepind/flyd). 3 | 4 | # Usage 5 | 6 | ```javascript 7 | var addThree = function(a, b, c) { 8 | return a + b + c; 9 | }; 10 | 11 | var n1 = stream(1), 12 | n2 = stream(4), 13 | n3 = stream(9); 14 | 15 | var sum = lift(addThree, n1, n2, n3); 16 | 17 | sum(); // 14 18 | ``` 19 | -------------------------------------------------------------------------------- /examples/secret-combination/node_modules/flyd-lift/flyd-lift.js: -------------------------------------------------------------------------------- 1 | var flyd = require('flyd'); 2 | 3 | module.exports = function(f /* , streams */) { 4 | var streams = Array.prototype.slice.call(arguments, 1); 5 | var vals = []; 6 | return flyd.stream(streams, function() { 7 | for (var i = 0; i < streams.length; ++i) vals[i] = streams[i](); 8 | return f.apply(null, vals); 9 | }); 10 | }; 11 | -------------------------------------------------------------------------------- /examples/secret-combination/node_modules/flyd-lift/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "flyd-lift", 3 | "version": "1.0.2", 4 | "description": "Lift for Flyd.", 5 | "main": "flyd-lift.js", 6 | "directories": { 7 | "test": "test" 8 | }, 9 | "dependencies": { 10 | "flyd": "0.1.x" 11 | }, 12 | "devDependencies": {}, 13 | "scripts": { 14 | "test": "mocha" 15 | }, 16 | "repository": { 17 | "type": "git", 18 | "url": "https://github.com/paldepind/flyd-lift.git" 19 | }, 20 | "keywords": [ 21 | "flyd", 22 | "lift" 23 | ], 24 | "author": { 25 | "name": "Simon Friis Vindum" 26 | }, 27 | "license": "MIT", 28 | "bugs": { 29 | "url": "https://github.com/paldepind/flyd-lift/issues" 30 | }, 31 | "homepage": "https://github.com/paldepind/flyd-lift", 32 | "gitHead": "d1d1775dc9d7ef6898dac2601ba716e42efb279e", 33 | "readme": "# flyd-lift\nLift function for [Flyd](https://github.com/paldepind/flyd).\n\n# Usage\n\n```javascript\nvar addThree = function(a, b, c) {\n return a + b + c;\n};\n\nvar n1 = stream(1),\n n2 = stream(4),\n n3 = stream(9);\n\nvar sum = lift(addThree, n1, n2, n3);\n\nsum(); // 14\n```\n", 34 | "readmeFilename": "README.md", 35 | "_id": "flyd-lift@1.0.2", 36 | "_shasum": "b29bc378aee5f77fa90ae39f1451ab1611854ee0", 37 | "_from": "flyd-lift@1.0.2" 38 | } 39 | -------------------------------------------------------------------------------- /examples/secret-combination/node_modules/flyd-lift/test/index.js: -------------------------------------------------------------------------------- 1 | var assert = require('assert'); 2 | var flyd = require('flyd'); 3 | var stream = flyd.stream; 4 | var lift = require('../flyd-lift.js'); 5 | 6 | describe('lift', function() { 7 | it('applies a function to two streams', function() { 8 | var add = function(x, y) { return x + y; }; 9 | var x = stream(3); 10 | var y = stream(4); 11 | var sum = lift(add, x, y); 12 | assert.equal(sum(), x() + y()); 13 | x(12); 14 | assert.equal(sum(), x() + y()); 15 | y(3); 16 | assert.equal(sum(), x() + y()); 17 | }); 18 | it('applies a function to five streams', function() { 19 | var add = function(a, b, c, d, e) { return a + b + c + d + e; }; 20 | var a = stream(1); 21 | var b = stream(2); 22 | var c = stream(3); 23 | var d = stream(4); 24 | var e = stream(5); 25 | var sum = lift(add, a, b, c, d, e); 26 | assert.equal(sum(), a() + b() + c() + d() + e()); 27 | e(12); d(2); b(0); 28 | assert.equal(sum(), a() + b() + c() + d() + e()); 29 | a(3); c(3); 30 | assert.equal(sum(), a() + b() + c() + d() + e()); 31 | }); 32 | }); 33 | -------------------------------------------------------------------------------- /examples/secret-combination/node_modules/flyd-sampleon/LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2015 Simon Friis Vindum 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | 23 | -------------------------------------------------------------------------------- /examples/secret-combination/node_modules/flyd-sampleon/README.md: -------------------------------------------------------------------------------- 1 | # flyd-sampleon 2 | sampleOn for Flyd. 3 | 4 | Samples from the second stream every time an event occurs on the first 5 | stream. 6 | 7 | __Signature__ 8 | 9 | `Stream a -> Stream b -> Stream b` 10 | 11 | __Usage__ 12 | 13 | ```javascript 14 | // Assume `sendBtnClicked` emits whenever a send button is pressed and 15 | // `messageText` is a stream of the current content of an input field. 16 | // Then `sendMessage` emits the content of the text field whenever the button 17 | // is pressed. 18 | var sendMessage = sampleOn(sendBtnClicked, messageText); 19 | ``` 20 | -------------------------------------------------------------------------------- /examples/secret-combination/node_modules/flyd-sampleon/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "flyd-sampleon", 3 | "version": "1.0.3", 4 | "description": "sampleOn for Flyd", 5 | "main": "sampleon.js", 6 | "directories": { 7 | "test": "test" 8 | }, 9 | "scripts": { 10 | "test": "mocha" 11 | }, 12 | "repository": { 13 | "type": "git", 14 | "url": "https://github.com/paldepind/flyd-sampleon.git" 15 | }, 16 | "keywords": [ 17 | "flyd", 18 | "sampleon" 19 | ], 20 | "author": { 21 | "name": "Simon Friis Vindum" 22 | }, 23 | "license": "MIT", 24 | "bugs": { 25 | "url": "https://github.com/paldepind/flyd-sampleon/issues" 26 | }, 27 | "homepage": "https://github.com/paldepind/flyd-sampleon", 28 | "dependencies": { 29 | "flyd": "0.1.x" 30 | }, 31 | "readme": "# flyd-sampleon\nsampleOn for Flyd.\n\nSamples from the second stream every time an event occurs on the first\nstream.\n\n__Signature__\n\n`Stream a -> Stream b -> Stream b`\n\n__Usage__\n\n```javascript\n// Assume `sendBtnClicked` emits whenever a send button is pressed and\n// `messageText` is a stream of the current content of an input field.\n// Then `sendMessage` emits the content of the text field whenever the button\n// is pressed.\nvar sendMessage = sampleOn(sendBtnClicked, messageText);\n```\n", 32 | "readmeFilename": "README.md", 33 | "gitHead": "58189daed2195b44e1711796680d6b134d139685", 34 | "_id": "flyd-sampleon@1.0.3", 35 | "_shasum": "e4b6381ca35a0a4f08f3e4e31592fed382a74ac9", 36 | "_from": "flyd-sampleon@*" 37 | } 38 | -------------------------------------------------------------------------------- /examples/secret-combination/node_modules/flyd-sampleon/sampleon.js: -------------------------------------------------------------------------------- 1 | var flyd = require('flyd'); 2 | 3 | module.exports = flyd.curryN(2, function(s1, s2) { 4 | return flyd.stream([s1], function() { 5 | return s2(); 6 | }); 7 | }); 8 | -------------------------------------------------------------------------------- /examples/secret-combination/node_modules/flyd-sampleon/test/index.js: -------------------------------------------------------------------------------- 1 | var assert = require('assert'); 2 | var flyd = require('flyd'); 3 | var stream = flyd.stream; 4 | 5 | var sampleOn = require('../sampleon.js'); 6 | 7 | describe('sample On', function() { 8 | it('samples from second stream', function() { 9 | var result = []; 10 | var s1 = stream(); 11 | var s2 = stream(); 12 | var sampled = sampleOn(s1, s2); 13 | flyd.map(function(v) { 14 | result.push(v); 15 | }, sampled); 16 | s2(1); 17 | s1(1)(2)(3); 18 | s2(3)(4)(6); 19 | s1(5)(3); 20 | assert.deepEqual(result, [1, 1, 1, 6, 6]); 21 | }); 22 | it('has not value until value flows on trigger stream', function() { 23 | var result = []; 24 | var s1 = stream(); 25 | var s2 = stream(1); 26 | var sampled = sampleOn(s1, s2); 27 | flyd.map(function(v) { 28 | result.push(v); 29 | }, sampled); 30 | s2(1); 31 | s1(1)(2)(3); 32 | s2(3)(4)(6); 33 | s1(5)(3); 34 | assert.deepEqual(result, [1, 1, 1, 6, 6]); 35 | }); 36 | }); 37 | -------------------------------------------------------------------------------- /examples/secret-combination/node_modules/flyd/.travis.yml: -------------------------------------------------------------------------------- 1 | language: node_js 2 | node_js: 3 | - "0.12" 4 | - "0.10" 5 | - "iojs" 6 | after_success: 7 | - ./node_modules/.bin/istanbul cover ./node_modules/mocha/bin/_mocha --report lcovonly -- -R spec && cat ./coverage/lcov.info | ./node_modules/coveralls/bin/coveralls.js && rm -rf ./coverage 8 | -------------------------------------------------------------------------------- /examples/secret-combination/node_modules/flyd/LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2015 Simon Friis Vindum 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | 23 | -------------------------------------------------------------------------------- /examples/secret-combination/node_modules/flyd/bower.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "flyd", 3 | "main": "flyd.js", 4 | "version": "0.0.1", 5 | "homepage": "https://github.com/paldepind/flyd", 6 | "authors": [ 7 | "Simon Friis Vindum" 8 | ], 9 | "description": "The less is more, modular functional reactive programming library", 10 | "moduleType": [ 11 | "amd", 12 | "globals", 13 | "node" 14 | ], 15 | "keywords": [ 16 | "functional", 17 | "reactive", 18 | "modular" 19 | ], 20 | "license": "MIT", 21 | "ignore": [ 22 | "**/.*", 23 | "node_modules", 24 | "bower_components", 25 | "test", 26 | "tests" 27 | ] 28 | } 29 | -------------------------------------------------------------------------------- /examples/secret-combination/node_modules/flyd/coverage/lcov.info: -------------------------------------------------------------------------------- 1 | TN: 2 | SF:/home/simon/projects/flyd/flyd.js 3 | FN:1,(anonymous_1) 4 | FN:9,(anonymous_2) 5 | FN:13,isFunction 6 | FN:17,isUndefined 7 | FN:27,flushQueue 8 | FN:35,addDependency 9 | FN:42,checkCirc 10 | FN:48,removeListener 11 | FN:54,map 12 | FN:55,(anonymous_10) 13 | FN:58,reduce 14 | FN:59,(anonymous_12) 15 | FN:64,merge 16 | FN:65,(anonymous_14) 17 | FN:75,ap 18 | FN:77,(anonymous_16) 19 | FN:80,of 20 | FN:84,initialDepsNotMet 21 | FN:86,(anonymous_19) 22 | FN:94,updateStream 23 | FN:103,destroyStream 24 | FN:112,stream 25 | FN:113,s 26 | FN:124,(anonymous_24) 27 | FN:157,(anonymous_25) 28 | FN:168,transduce 29 | FN:170,(anonymous_27) 30 | FN:175,StreamTransformer 31 | FN:176,(anonymous_29) 32 | FN:177,(anonymous_30) 33 | FN:178,(anonymous_31) 34 | FNF:31 35 | FNH:29 36 | FNDA:1,(anonymous_1) 37 | FNDA:1,(anonymous_2) 38 | FNDA:336,isFunction 39 | FNDA:646,isUndefined 40 | FNDA:152,flushQueue 41 | FNDA:212,addDependency 42 | FNDA:17,checkCirc 43 | FNDA:2,removeListener 44 | FNDA:7,map 45 | FNDA:14,(anonymous_10) 46 | FNDA:1,reduce 47 | FNDA:4,(anonymous_12) 48 | FNDA:1,merge 49 | FNDA:8,(anonymous_14) 50 | FNDA:9,ap 51 | FNDA:21,(anonymous_16) 52 | FNDA:7,of 53 | FNDA:167,initialDepsNotMet 54 | FNDA:37,(anonymous_19) 55 | FNDA:167,updateStream 56 | FNDA:2,destroyStream 57 | FNDA:114,stream 58 | FNDA:537,s 59 | FNDA:109,(anonymous_24) 60 | FNDA:22,(anonymous_25) 61 | FNDA:3,transduce 62 | FNDA:15,(anonymous_27) 63 | FNDA:3,StreamTransformer 64 | FNDA:0,(anonymous_29) 65 | FNDA:0,(anonymous_30) 66 | FNDA:10,(anonymous_31) 67 | DA:1,1 68 | DA:2,1 69 | DA:3,0 70 | DA:4,1 71 | DA:5,1 72 | DA:7,0 73 | DA:13,1 74 | DA:14,336 75 | DA:17,1 76 | DA:18,646 77 | DA:22,1 78 | DA:23,1 79 | DA:25,1 80 | DA:27,1 81 | DA:28,152 82 | DA:29,15 83 | DA:30,5 84 | DA:35,1 85 | DA:36,212 86 | DA:37,69 87 | DA:38,69 88 | DA:42,1 89 | DA:43,17 90 | DA:44,2 91 | DA:48,1 92 | DA:49,2 93 | DA:50,2 94 | DA:51,2 95 | DA:54,1 96 | DA:55,14 97 | DA:58,1 98 | DA:59,1 99 | DA:60,4 100 | DA:64,1 101 | DA:65,1 102 | DA:66,8 103 | DA:67,8 104 | DA:69,1 105 | DA:70,1 106 | DA:75,1 107 | DA:76,9 108 | DA:77,21 109 | DA:80,1 110 | DA:81,7 111 | DA:84,1 112 | DA:85,167 113 | DA:86,34 114 | DA:87,37 115 | DA:89,34 116 | DA:91,167 117 | DA:94,1 118 | DA:95,167 119 | DA:96,154 120 | DA:97,154 121 | DA:98,152 122 | DA:99,152 123 | DA:100,152 124 | DA:103,1 125 | DA:104,2 126 | DA:105,1 127 | DA:107,1 128 | DA:108,3 129 | DA:112,1 130 | DA:113,1 131 | DA:114,537 132 | DA:115,222 133 | DA:116,2 134 | DA:117,2 135 | DA:119,220 136 | DA:120,220 137 | DA:121,17 138 | DA:122,15 139 | DA:124,203 140 | DA:126,218 141 | DA:128,315 142 | DA:129,190 143 | DA:131,315 144 | DA:134,114 145 | DA:135,114 146 | DA:136,114 147 | DA:137,114 148 | DA:138,114 149 | DA:139,114 150 | DA:140,114 151 | DA:142,114 152 | DA:143,114 153 | DA:144,114 154 | DA:145,114 155 | DA:147,114 156 | DA:148,21 157 | DA:149,21 158 | DA:150,21 159 | DA:151,8 160 | DA:154,114 161 | DA:155,53 162 | DA:156,53 163 | DA:157,21 164 | DA:158,22 165 | DA:161,53 166 | DA:163,61 167 | DA:165,112 168 | DA:168,1 169 | DA:169,3 170 | DA:170,3 171 | DA:171,15 172 | DA:175,1 173 | DA:176,1 174 | DA:177,1 175 | DA:178,10 176 | DA:180,1 177 | LF:110 178 | LH:108 179 | BRDA:2,1,0,0 180 | BRDA:2,1,1,1 181 | BRDA:2,2,0,1 182 | BRDA:2,2,1,0 183 | BRDA:4,3,0,1 184 | BRDA:4,3,1,0 185 | BRDA:14,4,0,336 186 | BRDA:14,4,1,90 187 | BRDA:14,4,2,90 188 | BRDA:14,4,3,55 189 | BRDA:36,5,0,69 190 | BRDA:36,5,1,143 191 | BRDA:43,6,0,2 192 | BRDA:43,6,1,15 193 | BRDA:67,7,0,7 194 | BRDA:67,7,1,1 195 | BRDA:70,8,0,1 196 | BRDA:70,8,1,0 197 | BRDA:85,9,0,34 198 | BRDA:85,9,1,133 199 | BRDA:89,10,0,21 200 | BRDA:89,10,1,13 201 | BRDA:95,11,0,13 202 | BRDA:95,11,1,154 203 | BRDA:99,12,0,110 204 | BRDA:99,12,1,42 205 | BRDA:104,13,0,1 206 | BRDA:104,13,1,1 207 | BRDA:108,14,0,2 208 | BRDA:108,14,1,1 209 | BRDA:114,15,0,222 210 | BRDA:114,15,1,315 211 | BRDA:115,16,0,2 212 | BRDA:115,16,1,220 213 | BRDA:115,17,0,222 214 | BRDA:115,17,1,222 215 | BRDA:120,18,0,17 216 | BRDA:120,18,1,203 217 | BRDA:128,19,0,190 218 | BRDA:128,19,1,125 219 | BRDA:128,20,0,315 220 | BRDA:128,20,1,216 221 | BRDA:147,21,0,21 222 | BRDA:147,21,1,93 223 | BRDA:150,22,0,8 224 | BRDA:150,22,1,13 225 | BRDA:154,23,0,53 226 | BRDA:154,23,1,61 227 | BRDA:156,24,0,21 228 | BRDA:156,24,1,32 229 | BRF:50 230 | BRH:46 231 | end_of_record 232 | -------------------------------------------------------------------------------- /examples/secret-combination/node_modules/flyd/examples/multiple-clicks/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Multiple clicks 6 | 7 | 8 | 9 | 10 | 11 | Double click it 12 |

13 | See the source code 14 |

15 | 16 | 17 | -------------------------------------------------------------------------------- /examples/secret-combination/node_modules/flyd/examples/multiple-clicks/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "multiple-clicks", 3 | "version": "1.0.0", 4 | "description": "", 5 | "main": ".build.js", 6 | "scripts": { 7 | "test": "echo \"Error: no test specified\" && exit 1" 8 | }, 9 | "author": "Simon Friis Vindum", 10 | "license": "MIT", 11 | "dependencies": { 12 | "flyd": "0.0.x", 13 | "flyd-aftersilence": "0.0.x" 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /examples/secret-combination/node_modules/flyd/examples/multiple-clicks/script.js: -------------------------------------------------------------------------------- 1 | var flyd = require('flyd'); 2 | var afterSilence = require('flyd-aftersilence'); 3 | 4 | document.addEventListener('DOMContentLoaded', function() { 5 | var btnElm = document.getElementById('btn'); 6 | var msgElm = document.getElementById('msg'); 7 | 8 | var clickStream = flyd.stream(); 9 | btnElm.addEventListener('click', clickStream); 10 | 11 | var groupedClicks = afterSilence(250, clickStream); 12 | var nrStream = flyd.map(function(clicks) { return clicks.length; }, groupedClicks); 13 | 14 | flyd.map(function(nr) { 15 | msgElm.textContent = nr === 1 ? 'click' : nr + ' clicks'; 16 | }, nrStream); 17 | 18 | flyd.map(function(nr) { 19 | msgElm.textContent = ''; 20 | }, afterSilence(1000, nrStream)); 21 | }); 22 | -------------------------------------------------------------------------------- /examples/secret-combination/node_modules/flyd/examples/secret-combination/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Secret combination 6 | 7 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | 114 |
115 | 116 | 117 | -------------------------------------------------------------------------------- /examples/secret-combination/node_modules/flyd/examples/secret-combination/script.js: -------------------------------------------------------------------------------- 1 | (function() { 2 | 'use strict'; 3 | 4 | var stream = flyd.stream; 5 | 6 | var magicSeq = 'abbaba'; 7 | 8 | var setMsg = function(msg) { message.innerHTML = msg; }; 9 | 10 | document.addEventListener('DOMContentLoaded', function() { 11 | var click = stream(); 12 | btnA.addEventListener('click', click.bind(null, 'a')); 13 | btnB.addEventListener('click', click.bind(null, 'b')); 14 | var corrects = flyd.reduce(function(cs, c) { 15 | var l = cs.length, correct = (c === magicSeq[l]); 16 | console.log(l, correct); 17 | return !correct && l > 0 ? [] 18 | : !correct && l === 0 ? [] 19 | : l + 1 < magicSeq.length ? cs.concat(c) 20 | : (setMsg('Combination unlocked!'), []); 21 | }, [], click); 22 | var scheduled = flyd.map(function(cor) { 23 | if (cor.length === 1) return setTimeout(function() { 24 | setMsg('You\'re not fast enough, try again'); 25 | corrects([]); 26 | }, 5000); 27 | }, corrects); 28 | flyd.map(function(c) { console.log(c); }, corrects); 29 | stream([corrects], function() { 30 | if (corrects().length === 0 && scheduled.val) clearTimeout(scheduled.val); 31 | }); 32 | }); 33 | })(); 34 | -------------------------------------------------------------------------------- /examples/secret-combination/node_modules/flyd/examples/sum/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Sum – a Flyd demo 6 | 7 | 103 | 104 | 147 | 148 | 149 |
150 |

Sum

151 |
152 |
153 |

Execute

154 |

155 | Also try calling x and y in your browser console. 156 |

157 |

158 | x(1) 159 | x(2) 160 | x(3) 161 | x(5) 162 | x(8) 163 | x(13) 164 |

165 |

166 | y(1) 167 | y(2) 168 | y(3) 169 | y(5) 170 | y(8) 171 | y(13) 172 |

173 |

174 | x(x() + 1) 175 | x(x() - 1) 176 |

177 |

178 | y(y() + 1) 179 | y(y() - 1) 180 |

181 |
182 |
183 |

Result

184 |

185 | x is ... 186 |

187 |

188 | y is ... 189 |

190 |

191 | sum is ... 192 |

193 |
194 |
195 |

Source code

196 | var x = stream(10); 197 | var y = stream(20); 198 | var sum = stream([x, y], function() { 199 | return x() + y(); 200 | }); 201 | var elm = document.getElementById('sumBox'); 202 | flyd.map(function(s) { 203 | elm.innerHTML = s; 204 | }, sum); 205 |
206 | 207 | 208 | -------------------------------------------------------------------------------- /examples/secret-combination/node_modules/flyd/flyd.js: -------------------------------------------------------------------------------- 1 | (function (root, factory) { 2 | if (typeof define === 'function' && define.amd) { 3 | define([], factory); // AMD. Register as an anonymous module. 4 | } else if (typeof exports === 'object') { 5 | module.exports = factory(); // NodeJS 6 | } else { // Browser globals (root is window) 7 | root.flyd = factory(); 8 | } 9 | }(this, function () { 10 | 11 | 'use strict'; 12 | 13 | function isFunction(obj) { 14 | return !!(obj && obj.constructor && obj.call && obj.apply); 15 | } 16 | 17 | function isUndefined(v) { 18 | return v === undefined; 19 | } 20 | 21 | // Globals 22 | var queue = []; 23 | var isFlushingQueue = false; 24 | 25 | function flushQueue() { 26 | if (isFlushingQueue) return; 27 | isFlushingQueue = true; 28 | for (var s; s = queue.shift();) { 29 | s.inQueue = false; 30 | s.update(); 31 | } 32 | isFlushingQueue = false; 33 | } 34 | 35 | function removeListener(listeners, s) { 36 | var idx = listeners.indexOf(s); 37 | listeners[idx] = listeners[listeners.length - 1]; 38 | listeners.length--; 39 | } 40 | 41 | function map(s, f) { 42 | return stream([s], function() { return f(s()); }); 43 | } 44 | 45 | var reduce = curryN(3, function(f, acc, s) { 46 | var ns = stream([s], function() { 47 | return (acc = f(acc, s())); 48 | }); 49 | if (!ns.hasVal) ns(acc); 50 | return ns; 51 | }); 52 | 53 | var merge = curryN(2, function(s1, s2) { 54 | return stream([s1, s2], function(n, changed) { 55 | var v1, v2; 56 | if (changed) return changed(); 57 | else { 58 | v1 = s1(); v2 = s2(); 59 | return v1 === undefined ? v2 : v1; 60 | } 61 | }, true); 62 | }); 63 | 64 | function ap(s2) { 65 | var s1 = this; 66 | return stream([s1, s2], function() { return s1()(s2()); }, true); 67 | } 68 | 69 | function of(v) { 70 | return stream()(v); 71 | } 72 | 73 | function initialDepsNotMet(stream) { 74 | if (!stream.depsMet) { 75 | stream.depsMet = stream.deps.every(function(s) { 76 | return s.hasVal; 77 | }); 78 | } 79 | return !stream.depsMet; 80 | } 81 | 82 | function updateStream() { 83 | if (initialDepsNotMet(this)) return; 84 | var returnVal = this.fn(this, this.depChanged); 85 | if (returnVal !== undefined) this(returnVal); 86 | } 87 | 88 | function destroy(stream) { 89 | if (stream.listeners.length !== 0) { 90 | throw new Error('Trying to destroy stream with listeners attached'); 91 | } 92 | stream.deps.forEach(function(dep) { removeListener(dep.listeners, stream); }); 93 | } 94 | 95 | function isStream(stream) { 96 | return isFunction(stream) && 'depsMet' in stream; 97 | } 98 | 99 | function streamToString() { 100 | return 'stream(' + this.val + ')'; 101 | } 102 | 103 | function stream(arg, fn, waitForDeps) { 104 | function s(n) { 105 | if (arguments.length > 0) { 106 | if (!isUndefined(n) && n !== null && isFunction(n.then)) { 107 | n.then(s); 108 | return; 109 | } 110 | s.val = n; 111 | s.hasVal = true; 112 | s.listeners.forEach(function(st) { 113 | st.depChanged = s; 114 | if (!st.inQueue) { 115 | st.inQueue = true; 116 | queue.push(st); 117 | } 118 | }); 119 | flushQueue(); 120 | return s; 121 | } else { 122 | return s.val; 123 | } 124 | } 125 | s.hasVal = false; 126 | s.val = undefined; 127 | s.listeners = []; 128 | s.deps = []; 129 | s.depsMet = isUndefined(waitForDeps) ? false : true; 130 | s.depChanged = undefined; 131 | s.inQueue = true; 132 | s.fn = fn; 133 | 134 | s.map = map.bind(null, s); 135 | s.ap = ap; 136 | s.of = of; 137 | s.toString = streamToString; 138 | 139 | if (arguments.length > 1) { 140 | s.update = updateStream; 141 | s.deps = arg; 142 | arg.forEach(function(dep) { 143 | dep.listeners.push(s); 144 | }); 145 | queue.push(s); 146 | flushQueue(); 147 | } else if (arguments.length === 1) { 148 | s.val = arg; 149 | s.hasVal = true; 150 | } 151 | return s; 152 | } 153 | 154 | var transduce = curryN(2, function(xform, source) { 155 | xform = xform(new StreamTransformer(stream)); 156 | return stream([source], function() { 157 | return xform.step(undefined, source()); 158 | }); 159 | }); 160 | 161 | function StreamTransformer(res) { } 162 | StreamTransformer.prototype.init = function() { }; 163 | StreamTransformer.prototype.result = function() { }; 164 | StreamTransformer.prototype.step = function(s, v) { return v; }; 165 | 166 | // Own curry implementation snatched from Ramda 167 | // Figure out something nicer later on 168 | var _ = {placeholder: true}; 169 | 170 | // Detect both own and Ramda placeholder 171 | function isPlaceholder(p) { 172 | return p === _ || (p && p.ramda === 'placeholder'); 173 | } 174 | 175 | function toArray(arg) { 176 | var arr = []; 177 | for (var i = 0; i < arg.length; ++i) { 178 | arr[i] = arg[i]; 179 | } 180 | return arr; 181 | } 182 | 183 | // Modified versions of arity and curryN from Ramda 184 | function ofArity(n, fn) { 185 | if (arguments.length === 1) { 186 | return ofArity.bind(undefined, n); 187 | } 188 | switch (n) { 189 | case 0: 190 | return function () { 191 | return fn.apply(this, arguments); 192 | }; 193 | case 1: 194 | return function (a0) { 195 | void a0; 196 | return fn.apply(this, arguments); 197 | }; 198 | case 2: 199 | return function (a0, a1) { 200 | void a1; 201 | return fn.apply(this, arguments); 202 | }; 203 | case 3: 204 | return function (a0, a1, a2) { 205 | void a2; 206 | return fn.apply(this, arguments); 207 | }; 208 | case 4: 209 | return function (a0, a1, a2, a3) { 210 | void a3; 211 | return fn.apply(this, arguments); 212 | }; 213 | case 5: 214 | return function (a0, a1, a2, a3, a4) { 215 | void a4; 216 | return fn.apply(this, arguments); 217 | }; 218 | case 6: 219 | return function (a0, a1, a2, a3, a4, a5) { 220 | void a5; 221 | return fn.apply(this, arguments); 222 | }; 223 | case 7: 224 | return function (a0, a1, a2, a3, a4, a5, a6) { 225 | void a6; 226 | return fn.apply(this, arguments); 227 | }; 228 | case 8: 229 | return function (a0, a1, a2, a3, a4, a5, a6, a7) { 230 | void a7; 231 | return fn.apply(this, arguments); 232 | }; 233 | case 9: 234 | return function (a0, a1, a2, a3, a4, a5, a6, a7, a8) { 235 | void a8; 236 | return fn.apply(this, arguments); 237 | }; 238 | case 10: 239 | return function (a0, a1, a2, a3, a4, a5, a6, a7, a8, a9) { 240 | void a9; 241 | return fn.apply(this, arguments); 242 | }; 243 | default: 244 | throw new Error('First argument to arity must be a non-negative integer no greater than ten'); 245 | } 246 | } 247 | 248 | function curryN(length, fn) { 249 | return ofArity(length, function () { 250 | var n = arguments.length; 251 | var shortfall = length - n; 252 | var idx = n; 253 | while (--idx >= 0) { 254 | if (isPlaceholder(arguments[idx])) { 255 | shortfall += 1; 256 | } 257 | } 258 | if (shortfall <= 0) { 259 | return fn.apply(this, arguments); 260 | } else { 261 | var initialArgs = toArray(arguments); 262 | return curryN(shortfall, function () { 263 | var currentArgs = toArray(arguments); 264 | var combinedArgs = []; 265 | var idx = -1; 266 | while (++idx < n) { 267 | var val = initialArgs[idx]; 268 | combinedArgs[idx] = isPlaceholder(val) ? currentArgs.shift() : val; 269 | } 270 | return fn.apply(this, combinedArgs.concat(currentArgs)); 271 | }); 272 | } 273 | }); 274 | } 275 | 276 | 277 | return { 278 | stream: stream, 279 | isStream: isStream, 280 | transduce: transduce, 281 | merge: merge, 282 | reduce: reduce, 283 | destroy: destroy, 284 | map: curryN(2, function(f, s) { return map(s, f); }), 285 | curryN: curryN, 286 | _: _, 287 | }; 288 | 289 | })); 290 | -------------------------------------------------------------------------------- /examples/secret-combination/node_modules/flyd/perf/perf.js: -------------------------------------------------------------------------------- 1 | var _ = require('lodash'); 2 | var Benchmark = require('benchmark.js'); 3 | 4 | var flyd = require('../flyd'); 5 | var oldFlyd = require('../flyd-old'); 6 | 7 | var stream = flyd.stream; 8 | 9 | global.stream = flyd.stream; 10 | global.flyd = flyd; 11 | global.oldFlyd = oldFlyd; 12 | global.oldStream = oldFlyd.stream; 13 | 14 | // ************************************************ 15 | // Util functions 16 | 17 | var suites = []; 18 | 19 | function getHz(bench) { // hz adjusted for margin of error 20 | var result = 1 / (bench.stats.mean + bench.stats.moe); 21 | return isFinite(result) ? result : 0; 22 | } 23 | 24 | function printFastest(suite) { 25 | var formatNumber = Benchmark.formatNumber, 26 | fastest = suite.filter('fastest'), 27 | fastestHz = getHz(fastest[0]), 28 | slowest = suite.filter('slowest'), 29 | slowestHz = getHz(slowest[0]), 30 | aHz = getHz(suite[0]), 31 | bHz = getHz(suite[1]); 32 | if (fastest.length > 1) { 33 | console.log('It\'s too close to call.'); 34 | aHz = bHz = slowestHz; 35 | } else { 36 | var percent = ((fastestHz / slowestHz) - 1) * 100; 37 | console.log(' ' + fastest[0].name + ' is ' + 38 | formatNumber(percent < 1 ? percent.toFixed(2) : Math.round(percent)) + 39 | '% faster.'); 40 | } 41 | } 42 | 43 | Benchmark.Suite.options.onStart = function() { 44 | console.log('\n' + this.name + ':'); 45 | }; 46 | 47 | Benchmark.Suite.options.onCycle = function(event) { 48 | console.log(' ' + event.target); 49 | }; 50 | 51 | Benchmark.Suite.options.onComplete = function() { 52 | printFastest(this); 53 | suites.shift(); 54 | if (suites.length) { 55 | suites[0].run({async: true}); 56 | } 57 | }; 58 | 59 | // ************************************************ 60 | // Benchmarks! 61 | 62 | suites.push(Benchmark.Suite('dynamic dependencies').add('New', { 63 | setup: function() { 64 | var s = stream(); 65 | stream(function() { 66 | return s(); 67 | }); 68 | }, 69 | fn: function() { 70 | s(12); 71 | }, 72 | }).add('Old', { 73 | setup: function() { 74 | var s = oldStream(); 75 | oldStream(function() { 76 | return s(); 77 | }); 78 | }, 79 | fn: function() { 80 | s(12); 81 | }, 82 | })); 83 | 84 | suites.push(Benchmark.Suite('static dependencies').add('New', { 85 | setup: function() { 86 | var s = stream(); 87 | stream([s], function() { 88 | return s(); 89 | }); 90 | }, 91 | fn: function() { 92 | s(12); 93 | }, 94 | }).add('Old', { 95 | setup: function() { 96 | var s = oldStream(); 97 | oldStream([s], function() { 98 | return s(); 99 | }); 100 | }, 101 | fn: function() { 102 | s(12); 103 | }, 104 | })); 105 | 106 | suites.push(Benchmark.Suite('map').add('First', { 107 | setup: function() { 108 | var flyd = global.flyd; 109 | var stream = global.flyd.stream; 110 | function f(x) { return x; } 111 | var s1 = stream(); 112 | var s2 = s1.map(f); 113 | var s3 = s2.map(f); 114 | var s4 = s3.map(f); 115 | var s5 = s4.map(f); 116 | }, 117 | fn: function() { 118 | s1(12); 119 | }, 120 | }).add('Second', { 121 | setup: function() { 122 | var flyd = global.flyd; 123 | var stream = global.flyd.stream; 124 | function f(x) { return x; } 125 | var s1 = stream(); 126 | var s2 = s1.map(f); 127 | var s3 = s2.map(f); 128 | var s4 = s3.map(f); 129 | var s5 = s4.map(f); 130 | }, 131 | fn: function() { 132 | s1(12); 133 | }, 134 | })); 135 | 136 | suites.push(Benchmark.Suite('dynamic dependency graph').add('New', { 137 | setup: function() { 138 | var s1 = stream(); 139 | var s2 = stream(function() { 140 | s1(); s1(); 141 | }); 142 | var s3 = stream(function() { 143 | s1(); s2(); s1(); 144 | }); 145 | var s4 = stream(function() { 146 | s1(); s2(); s3(); s1(); s3(); 147 | }); 148 | stream(function() { 149 | s3(); s2(); s1(); s3(); s4(); 150 | }); 151 | }, 152 | fn: function() { 153 | s1(12); 154 | }, 155 | }).add('Old', { 156 | setup: function() { 157 | var s1 = oldStream(); 158 | var s2 = oldStream(function() { 159 | s1(); s1(); 160 | }); 161 | var s3 = oldStream(function() { 162 | s1(); s2(); s1(); 163 | }); 164 | var s4 = oldStream(function() { 165 | s1(); s2(); s3(); s1(); s3(); 166 | }); 167 | oldStream(function() { 168 | s3(); s2(); s1(); s3(); s4(); 169 | }); 170 | }, 171 | fn: function() { 172 | s1(12); 173 | }, 174 | })); 175 | 176 | suites[0].run({ 'async': true }); 177 | -------------------------------------------------------------------------------- /examples/secret-combination/node_modules/flyd/perf/test.js: -------------------------------------------------------------------------------- 1 | var _ = require('lodash'); 2 | var Benchmark = require('benchmark.js'); 3 | 4 | var flyd = require('../flyd'); 5 | var oldFlyd = require('../flyd'); 6 | 7 | var stream = flyd.stream; 8 | global.stream = flyd.stream; 9 | global.flyd = flyd; 10 | global.oldFlyd = oldFlyd; 11 | 12 | // ************************************************ 13 | // Util functions 14 | 15 | var suites = []; 16 | 17 | function getHz(bench) { // hz adjusted for margin of error 18 | var result = 1 / (bench.stats.mean + bench.stats.moe); 19 | return isFinite(result) ? result : 0; 20 | } 21 | 22 | function printFastest(suite) { 23 | var formatNumber = Benchmark.formatNumber, 24 | fastest = suite.filter('fastest'), 25 | fastestHz = getHz(fastest[0]), 26 | slowest = suite.filter('slowest'), 27 | slowestHz = getHz(slowest[0]), 28 | aHz = getHz(suite[0]), 29 | bHz = getHz(suite[1]); 30 | if (fastest.length > 1) { 31 | console.log('It\'s too close to call.'); 32 | aHz = bHz = slowestHz; 33 | } else { 34 | var percent = ((fastestHz / slowestHz) - 1) * 100; 35 | console.log(' ' + fastest[0].name + ' is ' + 36 | formatNumber(percent < 1 ? percent.toFixed(2) : Math.round(percent)) + 37 | '% faster.'); 38 | } 39 | } 40 | 41 | Benchmark.Suite.options.onStart = function() { 42 | console.log('\n' + this.name + ':'); 43 | }; 44 | 45 | Benchmark.Suite.options.onCycle = function(event) { 46 | console.log(' ' + event.target); 47 | }; 48 | 49 | Benchmark.Suite.options.onComplete = function() { 50 | printFastest(this); 51 | suites.shift(); 52 | if (suites.length) { 53 | suites[0].run({async: true}); 54 | } 55 | }; 56 | 57 | // ************************************************ 58 | // Benchmarks! 59 | 60 | suites.push(Benchmark.Suite('First map test').add('First', { 61 | setup: function() { 62 | function f(x) { return x; } 63 | var s1 = stream(); 64 | var s2 = s1.map(f); 65 | var s3 = s2.map(f); 66 | var s4 = s3.map(f); 67 | var s5 = s4.map(f); 68 | }, 69 | fn: function() { 70 | s1(12); 71 | }, 72 | }).add('Second', { 73 | setup: function() { 74 | function f(x) { return x; } 75 | var s1 = stream(); 76 | var s2 = s1.map(f); 77 | var s3 = s2.map(f); 78 | var s4 = s3.map(f); 79 | var s5 = s4.map(f); 80 | }, 81 | fn: function() { 82 | s1(12); 83 | }, 84 | })); 85 | 86 | suites.push(Benchmark.Suite('Second map test').add('First', { 87 | setup: function() { 88 | var flyd = global.flyd; 89 | var stream = global.flyd.stream; 90 | function f(x) { return x; } 91 | var s1 = stream(); 92 | var s2 = s1.map(f); 93 | var s3 = s2.map(f); 94 | var s4 = s3.map(f); 95 | var s5 = s4.map(f); 96 | }, 97 | fn: function() { 98 | s1(12); 99 | }, 100 | }).add('Second', { 101 | setup: function() { 102 | var flyd = global.flyd; 103 | var stream = global.flyd.stream; 104 | function f(x) { return x; } 105 | var s1 = stream(); 106 | var s2 = s1.map(f); 107 | var s3 = s2.map(f); 108 | var s4 = s3.map(f); 109 | var s5 = s4.map(f); 110 | }, 111 | fn: function() { 112 | s1(12); 113 | }, 114 | })); 115 | 116 | suites[0].run({ 'async': true }); 117 | -------------------------------------------------------------------------------- /examples/secret-combination/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "secret-combination", 3 | "version": "1.0.0", 4 | "description": "", 5 | "main": "build.js", 6 | "scripts": { 7 | "test": "echo \"Error: no test specified\" && exit 1" 8 | }, 9 | "author": "Simon Friis Vindum", 10 | "license": "MIT", 11 | "dependencies": { 12 | "flyd": "0.1.x", 13 | "flyd-filter": "1.0.x", 14 | "flyd-inlast": "0.0.x", 15 | "flyd-lift": "1.0.x", 16 | "flyd-sampleon": "1.0.x" 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /examples/secret-combination/script.js: -------------------------------------------------------------------------------- 1 | var flyd = require('../../lib'); 2 | var stream = flyd.stream; 3 | var filter = require('../../module/filter'); 4 | var lift = require('../../module/lift'); 5 | var inLast = require('../../module/inlast'); 6 | var sampleOn = require('../../module/sampleon'); 7 | 8 | var magicSeq = 'abbaba'; 9 | var seqLen = magicSeq.length; 10 | var maxTime = 5000; 11 | 12 | var setMsg = function(msg) { message.innerHTML = msg; }; 13 | 14 | document.addEventListener('DOMContentLoaded', function() { 15 | var clicks = stream(); 16 | btnA.addEventListener('click', clicks.bind(null, 'a')); 17 | btnB.addEventListener('click', clicks.bind(null, 'b')); 18 | 19 | var correctClicks = flyd.reduce(function(n, c) { 20 | return magicSeq[n] === c ? n + 1 21 | : magicSeq[0] === c ? 1 22 | : 0; 23 | }, 0, clicks); 24 | 25 | var clicksInLast5s = inLast(maxTime, clicks); 26 | 27 | lift(function(corrects, inLast5s) { 28 | var complete = corrects === seqLen, inTime = inLast5s.length >= seqLen; 29 | setMsg(complete && inTime ? 'Combination unlocked' 30 | : complete && !inTime ? "You're not fast enough, try again!" 31 | : corrects); 32 | }, correctClicks, sampleOn(clicks, clicksInLast5s)); 33 | 34 | flyd.map(function(c) { console.log('cor', c); }, correctClicks); 35 | flyd.map(function(c) { console.log('lst', c); }, clicksInLast5s); 36 | }); 37 | -------------------------------------------------------------------------------- /examples/sum/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Sum – a Flyd demo 6 | 7 | 103 | 104 | 105 | 106 |
107 |

Sum

108 |
109 |
110 |

Execute

111 |

112 | Also try calling x and y in your browser console. 113 |

114 |

115 | x(1) 116 | x(2) 117 | x(3) 118 | x(5) 119 | x(8) 120 | x(13) 121 |

122 |

123 | y(1) 124 | y(2) 125 | y(3) 126 | y(5) 127 | y(8) 128 | y(13) 129 |

130 |

131 | x(x() + 1) 132 | x(x() - 1) 133 |

134 |

135 | y(y() + 1) 136 | y(y() - 1) 137 |

138 |
139 |
140 |

Result

141 |

142 | x is ... 143 |

144 |

145 | y is ... 146 |

147 |

148 | sum is ... 149 |

150 |
151 |
152 |

Source code

153 | var x = stream(10); 154 | var y = stream(20); 155 | var sum = flyd.combine(function(x, y) { 156 | return x() + y(); 157 | }, [x, y]); 158 | var elm = document.getElementById('sumBox'); 159 | flyd.map(function(s) { 160 | elm.innerHTML = s; 161 | }, sum); 162 |
163 | 164 | 165 | -------------------------------------------------------------------------------- /examples/sum/script.js: -------------------------------------------------------------------------------- 1 | var flyd = require("../../lib"); 2 | var stream = flyd.stream; 3 | var x, y; // Let x and y be globals 4 | document.addEventListener("DOMContentLoaded", function() { 5 | var sumBox = document.getElementById("sumBox"); 6 | var xBox = document.getElementById("xBox"); 7 | var yBox = document.getElementById("yBox"); 8 | x = stream(10); 9 | y = stream(20); 10 | var sum = flyd.combine( 11 | function(x, y) { 12 | return x() + y(); 13 | }, 14 | [x, y] 15 | ); 16 | flyd.map(function(sum) { 17 | sumBox.innerHTML = sum; 18 | }, sum); 19 | flyd.map(function(x) { 20 | if (typeof x !== "number") { 21 | // Use called x or y with invalid value 22 | console.log("Numbers only, please!"); 23 | } 24 | xBox.innerHTML = x; 25 | }, x); 26 | flyd.map(function(y) { 27 | if (typeof y !== "number") { 28 | // Use called x or y with invalid value 29 | console.log("Numbers only, please!"); 30 | } 31 | yBox.innerHTML = y; 32 | }, y); 33 | // Do animations 34 | function animate(s, elm) { 35 | flyd.map(function() { 36 | elm.style.background = "black"; 37 | elm.style.color = "yellow"; 38 | setTimeout(function() { 39 | elm.style.background = "#ececec"; 40 | elm.style.color = "black"; 41 | }, 220); 42 | }, s); 43 | } 44 | animate(x, xBox); 45 | animate(y, yBox); 46 | animate(sum, sumBox); 47 | }); 48 | -------------------------------------------------------------------------------- /examples/who-to-follow/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Who to follow 6 | 7 | 8 | 53 | 54 | 55 |
56 |
57 |

Who to follow

Refresh 58 |
59 | 76 |
77 |

78 | See the source code 79 |

80 | 81 | 82 | -------------------------------------------------------------------------------- /examples/who-to-follow/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "who-to-follow", 3 | "version": "1.0.0", 4 | "private": "true", 5 | "description": "", 6 | "main": "script.js", 7 | "scripts": { 8 | "test": "echo \"Error: no test specified\" && exit 1" 9 | }, 10 | "author": "", 11 | "license": "MIT", 12 | "dependencies": { 13 | "flyd": "^0.1.6", 14 | "whatwg-fetch": "^0.9.0" 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /examples/who-to-follow/script.js: -------------------------------------------------------------------------------- 1 | var flyd = require('../../lib'); 2 | require('whatwg-fetch'); 3 | 4 | document.addEventListener('DOMContentLoaded', function() { 5 | var suggestionsContainerElm = document.querySelector('.suggestions'); 6 | var suggestionsElms = suggestionsContainerElm.children; 7 | 8 | function update(model, action) { // Take action & model, return updated model 9 | if (action.type === 'refresh') { 10 | return {loaded: [], suggested: []}; 11 | } else if (action.type === 'loaded') { 12 | return {loaded: action.data, suggested: action.data.slice(0, 3)}; 13 | } else if (action.type === 'remove') { 14 | return { 15 | loaded: model.loaded, 16 | suggested: model.suggested.map(function(sug, i) { 17 | return action.nr === i ? model.loaded[Math.floor(Math.random()*model.loaded.length)] 18 | : sug; 19 | }) 20 | }; 21 | } 22 | } 23 | 24 | function render(model) { // Take model, modify DOM 25 | if (model.suggested.length === 0) { 26 | suggestionsContainerElm.style.visibility = 'hidden'; 27 | } else { 28 | suggestionsContainerElm.style.visibility = 'visible'; 29 | model.suggested.forEach(function(user, i) { 30 | var suggestionElm = suggestionsElms[i]; 31 | var usernameElm = suggestionElm.querySelector('.username'); 32 | usernameElm.href = user.html_url; 33 | usernameElm.textContent = user.login; 34 | var imgEl = suggestionElm.querySelector('img'); 35 | imgEl.src = ''; 36 | imgEl.src = user.avatar_url; 37 | }); 38 | } 39 | } 40 | 41 | var initialState = { 42 | loaded: [], 43 | suggested: [], 44 | }; 45 | 46 | // Streams 47 | var action$ = flyd.stream(); 48 | var model$ = flyd.scan(update, initialState, action$); 49 | flyd.map(render, model$); 50 | 51 | function makeRequest() { 52 | var randomOffset = Math.floor(Math.random()*500); 53 | return fetch('https://api.github.com/users?since=' + randomOffset) 54 | .then(function(res) { return res.json(); }) 55 | .then(function(data) { action$({type: 'loaded', data: data}); }); 56 | } 57 | makeRequest(); 58 | function sendRemoveAction(idx) { 59 | action$({type: 'remove', nr: idx}); 60 | } 61 | document.getElementById('refresh').addEventListener('click', makeRequest); 62 | document.getElementById('remove0').addEventListener('click', sendRemoveAction.bind(null, 0)); 63 | document.getElementById('remove1').addEventListener('click', sendRemoveAction.bind(null, 1)); 64 | document.getElementById('remove2').addEventListener('click', sendRemoveAction.bind(null, 2)); 65 | }); 66 | -------------------------------------------------------------------------------- /flyd.min.js: -------------------------------------------------------------------------------- 1 | !function(n,t){"object"==typeof exports&&"undefined"!=typeof module?module.exports=t():"function"==typeof define&&define.amd?define(t):n.flyd=t()}(this,function(){"use strict";var n=function(n,t){switch(n){case 0:return function(){return t.apply(this,arguments)};case 1:return function(n){return t.apply(this,arguments)};case 2:return function(n,e){return t.apply(this,arguments)};case 3:return function(n,e,r){return t.apply(this,arguments)};case 4:return function(n,e,r,u){return t.apply(this,arguments)};case 5:return function(n,e,r,u,a){return t.apply(this,arguments)};case 6:return function(n,e,r,u,a,i){return t.apply(this,arguments)};case 7:return function(n,e,r,u,a,i,s){return t.apply(this,arguments)};case 8:return function(n,e,r,u,a,i,s,o){return t.apply(this,arguments)};case 9:return function(n,e,r,u,a,i,s,o,d){return t.apply(this,arguments)};case 10:return function(n,e,r,u,a,i,s,o,d,f){return t.apply(this,arguments)};default:throw new Error("First argument to _arity must be a non-negative integer no greater than ten")}};var t=function(n){return null!=n&&"object"==typeof n&&!0===n["@@functional/placeholder"]};var e=function(n){return function e(r){return 0===arguments.length||t(r)?e:n.apply(this,arguments)}};var r=function e(r,u,a){return function(){for(var i=[],s=0,o=r,d=0;d=arguments.length)?f=u[d]:(f=arguments[s],s+=1),i[d]=f,t(f)||(o-=1),d+=1}return o<=0?a.apply(this,i):n(o,e(r,i,a))}},u=function(n){return function r(u,a){switch(arguments.length){case 0:return r;case 1:return t(u)?r:e(function(t){return n(u,t)});default:return t(u)&&t(a)?r:t(u)?e(function(t){return n(t,a)}):t(a)?e(function(t){return n(u,t)}):n(u,a)}}}(function(t,u){return 1===t?e(u):n(t,r(t,[],u))});function a(){return!0}var i,s=[],o=[],d=-1,f=!1,c=!1;var p={};function l(n,t){var e,r,u,i,s=w([],a);for(u=[],i=[],e=0;e=0;--d)!0===(e=o[d]).shouldUpdate&&A(e),e.queued=!1}(e),s.length>0&&x(),c=!1):i===e?function(n,t){var e,r;for(e=0;e0?[]:void 0,e.shouldUpdate=!1,S(n,e),e}function A(n){var t;if((!(t=n).end||!0!==t.end.val)&&function(n){return!0===n.depsMet||function(n){return n.depsMet=n.deps.every(function(n){return n.hasVal}),n.depsMet}(n)}(n))if(void 0===i){i=n,n.depsChanged&&(n.fnArgs[n.fnArgs.length-1]=n.depsChanged);var e=n.fn.apply(n.fn,n.fnArgs);void 0!==e&&n(e),i=void 0,void 0!==n.depsChanged&&(n.depsChanged=[]),n.shouldUpdate=!1,!1===(f||c)&&x(),function(n){return n.listeners.some(function(n){return n.shouldUpdate})}(n)&&(c?n.listeners.forEach(function(n){n.shouldUpdate&&q(A,n)}):n(n.val))}else q(A,n)}function O(n){var t,e=n.listeners;if(!1===n.queued){for(n.queued=!0,t=0;t0;){var n=s.shift(),t=n.updaters.shift();t&&n.shouldUpdate&&t(n)}f=!1}function S(n,t){for(var e=0;e0&&e(n),e},p.stream["fantasy-land/of"]=p.stream.of=p.stream,p.combine=u(2,l),p.isStream=function(n){return!!((t=n)&&t.constructor&&t.call&&t.apply)&&"hasVal"in n;var t},p.immediate=function(n){return!1===n.depsMet&&(n.depsMet=!0,A(n)),n},p.endsOn=function(n,t){return E(t.end),n.listeners.push(t.end),t.end.deps.push(n),t},p.map=u(2,h),p.chain=u(2,m),p.ap=u(2,C),p.on=u(2,function(n,t){return l(function(t){n(t.val)},[t])}),p.scan=u(3,function(n,t,e){var r=l(function(e,r){r(t=n(t,e.val))},[e]);return r.hasVal||r(t),r}),p.merge=u(2,function(n,t){var e=p.immediate(l(function(n,t,e,r){r[0]?e(r[0]()):n.hasVal?e(n.val):t.hasVal&&e(t.val)},[n,t]));return p.endsOn(l(function(){return!0},[n.end,t.end]),e),e}),p.transduce=u(2,function(n,t){return n=n(new P),l(function(t,e){var r=n["@@transducer/step"](void 0,t.val);return r&&!0===r["@@transducer/reduced"]?(e.end(!0),r["@@transducer/value"]):r},[t])}),p.curryN=u,p.fromPromise=function(n){var t=p.stream();return n.then(function(n){t(n),t.end(!0)}),t},p.flattenPromise=function(n){return l(function(n,t){n().then(t)},[n])},P.prototype["@@transducer/init"]=function(){},P.prototype["@@transducer/result"]=function(){},P.prototype["@@transducer/step"]=function(n,t){return t},p}); 2 | -------------------------------------------------------------------------------- /index.d.ts: -------------------------------------------------------------------------------- 1 | type CurriedFunction2 = ((t1: T1, t2: T2) => R) & ((t1: T1, ...rest: Array) => (t2: T2) => R); 2 | 3 | declare namespace flyd { 4 | interface Stream { 5 | (): T; 6 | (value: T): Stream; 7 | (value: Promise | PromiseLike): Stream; 8 | 9 | 10 | map(project: (value: T) => V): Stream; 11 | ap(this: Stream<(value: A) => B>, stream: Stream): Stream; 12 | chain(project: (value: T) => Stream): Stream; 13 | of(...values: V[]): Stream; 14 | 15 | pipe(operator: (input: Stream) => Stream): Stream; 16 | 17 | ['fantasy-land/map'](project: (value: T) => V): Stream; 18 | ['fantasy-land/ap'](fn: (value: Stream) => V): Stream; 19 | ['fantasy-land/chain'](project: (value: T) => Stream): Stream; 20 | ['fantasy-land/of'](...values: V[]): Stream; 21 | 22 | end: Stream; 23 | val: T; 24 | hasVal: boolean; 25 | } 26 | 27 | interface Combine { 28 | (fn: (value: Stream, self: Stream) => R | void, streams: [Stream]): Stream; 29 | ( 30 | fn: (value: Stream, t1: Stream, self: Stream) => R | void, 31 | streams: [Stream, Stream] 32 | ): Stream; 33 | ( 34 | fn: (value: Stream, t1: Stream, t2: Stream, self: Stream) => R | void, 35 | streams: [Stream, Stream, Stream] 36 | ): Stream; 37 | 38 | ( 39 | fn: (value: Stream, t1: Stream, t2: Stream, t3: Stream, self: Stream) => R | void, 40 | streams: [Stream, Stream, Stream, Stream] 41 | ): Stream; 42 | } 43 | 44 | interface CreateStream { 45 | (): Stream; 46 | (value: T): Stream; 47 | (value: Promise | PromiseLike): Stream; 48 | (): Stream; 49 | } 50 | 51 | interface Static { 52 | stream: CreateStream; 53 | 54 | immediate(stream: Stream): Stream; 55 | isStream(stream: any): boolean; 56 | 57 | combine: Combine; 58 | endsOn(end$: Stream, stream: Stream): Stream; 59 | 60 | map(accessor: (value: T) => V): (stream: Stream) => Stream; 61 | map(accessor: (value: T) => V, stream: Stream): Stream; 62 | 63 | ap(value$: Stream, transform$: Stream<(value: A) => B>): Stream; 64 | ap(value$: Stream): (transform$: Stream<(value: A) => B>) => Stream 65 | 66 | chain(accessor: (value: T) => Stream): (stream: Stream) => Stream; 67 | chain(accessor: (value: T) => Stream, stream: Stream): Stream; 68 | 69 | on(onfn: (value: T) => void): (stream: Stream) => Stream; 70 | on(onfn: (value: T) => void, stream: Stream): Stream; 71 | 72 | scan(reducer: (acc: T, value: V) => T, initial: T, stream: Stream): Stream; 73 | scan(reducer: (acc: T, value: V) => T, initial: T): (stream: Stream) => Stream; 74 | scan(reducer: (acc: T, value: V) => T): (initial: T) => (stream: Stream) => Stream; 75 | 76 | merge(stream1: Stream, stream2: Stream): Stream; 77 | merge(stream1: Stream): (stream2: Stream) => Stream; 78 | 79 | transduce(mapfn: Function, stream: Stream): Stream; 80 | transduce(mapfn: Function): (stream: Stream) => Stream; 81 | 82 | fromPromise(promise: PromiseLike): Stream; 83 | flattenPromise(promise$: Stream>): Stream; 84 | 85 | curryN(length: number, fn: (...args: Array) => void): Function; 86 | } 87 | } 88 | 89 | declare module 'flyd' { 90 | const f: flyd.Static; 91 | export = f; 92 | } 93 | 94 | declare module 'flyd/module/aftersilence' { 95 | interface aftersilence { 96 | (delay: number, stream: flyd.Stream): flyd.Stream; 97 | (delay: number): (stream: flyd.Stream) => flyd.Stream; 98 | } 99 | export = aftersilence; 100 | } 101 | declare module 'flyd/module/droprepeats' { 102 | interface dropRepeats { 103 | (s: flyd.Stream): flyd.Stream; 104 | } 105 | interface dropRepeatsWith { 106 | (isEqual: (a: T, b: T) => boolean, stream: flyd.Stream): flyd.Stream; 107 | (isEqual: (a: T, b: T) => boolean): (stream: flyd.Stream) => flyd.Stream; 108 | } 109 | 110 | export const dropRepeats: dropRepeats; 111 | export const dropRepeatsWith: dropRepeatsWith; 112 | } 113 | 114 | declare module 'flyd/module/every' { 115 | interface every { 116 | (ms: number): flyd.Stream; 117 | } 118 | const _every: every; 119 | export = _every; 120 | } 121 | 122 | declare module 'flyd/module/filter' { 123 | interface Filter { 124 | (project: (val: T) => val is V, stream: flyd.Stream): flyd.Stream; 125 | (project: (val: T) => val is V): (stream: flyd.Stream) => flyd.Stream; 126 | (predicate: (val: T) => any, stream: flyd.Stream): flyd.Stream; 127 | (predicate: (val: T) => any): (stream: flyd.Stream) => flyd.Stream; 128 | } 129 | const _Filter: Filter; 130 | export = _Filter; 131 | } 132 | 133 | declare module 'flyd/module/forwardto' { 134 | interface ForwardTo { 135 | (stream: flyd.Stream, project: (value: V) => T): flyd.Stream; 136 | (stream: flyd.Stream): (project: (value: V) => T) => flyd.Stream; 137 | } 138 | const _ForwardTo: ForwardTo; 139 | export = _ForwardTo; 140 | } 141 | 142 | declare module 'flyd/module/inlast' { 143 | interface InLast { 144 | (ms: number, stream: flyd.Stream): flyd.Stream; 145 | (ms: number): (stream: flyd.Stream) => flyd.Stream; 146 | } 147 | 148 | const _InLast: InLast; 149 | export = _InLast; 150 | } 151 | 152 | declare module 'flyd/module/keepwhen' { 153 | interface KeepWhen { 154 | (when: flyd.Stream, stream: flyd.Stream): flyd.Stream; 155 | (when: flyd.Stream): (stream: flyd.Stream) => flyd.Stream; 156 | } 157 | const _KeepWhen: KeepWhen; 158 | export = _KeepWhen; 159 | } 160 | 161 | declare module 'flyd/module/lift' { 162 | interface Lift { 163 | (liftFn: (t1: T1, t2: T2) => R, s1: flyd.Stream, s2: flyd.Stream): flyd.Stream; 164 | (liftFn: (t1: T1, t2: T2, t3: T3) => R, s1: flyd.Stream, s2: flyd.Stream, s3: flyd.Stream): flyd.Stream; 165 | (liftFn: (t1: T1, t2: T2, t3: T3, t4: T4) => R, s1: flyd.Stream, s2: flyd.Stream, s3: flyd.Stream, s4: flyd.Stream): flyd.Stream; 166 | (liftFn: (...rest: any[]) => T, ...streams: flyd.Stream[]): flyd.Stream; 167 | } 168 | 169 | const _Lift: Lift; 170 | export = _Lift; 171 | } 172 | 173 | declare module 'flyd/module/mergeall' { 174 | interface MergeAll { 175 | (streams: [flyd.Stream, flyd.Stream]): flyd.Stream; 176 | (streams: [flyd.Stream, flyd.Stream, flyd.Stream]): flyd.Stream; 177 | (streams: flyd.Stream[]): flyd.Stream; 178 | } 179 | const _MergeAll: MergeAll; 180 | export = _MergeAll; 181 | } 182 | 183 | declare module 'flyd/module/obj' { 184 | interface ObjModule { 185 | streamProps(obj: T): { [P in keyof T]: flyd.Stream }; 186 | stream }>(obj: T): flyd.Stream<{ [P in keyof T]: T[P]['val'] }>; 187 | extractProps(obj: any): any; 188 | } 189 | 190 | const _ObjModule: ObjModule; 191 | export = _ObjModule; 192 | } 193 | 194 | declare module 'flyd/module/previous' { 195 | type previous = (stream: flyd.Stream) => flyd.Stream; 196 | const _previous: previous; 197 | export = _previous; 198 | } 199 | 200 | declare module 'flyd/module/sampleon' { 201 | interface SampleOn { 202 | (samplewhen: flyd.Stream, stream: flyd.Stream): flyd.Stream; 203 | (samplewhen: flyd.Stream): (stream: flyd.Stream) => flyd.Stream; 204 | } 205 | const _SampleOn: SampleOn; 206 | export = _SampleOn; 207 | } 208 | 209 | declare module 'flyd/module/scanmerge' { 210 | type ScanFn = (acc: T, value: V) => T; 211 | interface ScanMerge { 212 | (pairs: Array<[flyd.Stream, ScanFn]>, initial: T): flyd.Stream; 213 | (pairs: Array<[flyd.Stream, ScanFn]>): (initial: T) => flyd.Stream; 214 | } 215 | const _ScanMerge: ScanMerge; 216 | export = _ScanMerge; 217 | } 218 | 219 | declare module 'flyd/module/switchlatest' { 220 | interface SwitchLatest { 221 | (stream: flyd.Stream>): flyd.Stream; 222 | } 223 | const _SwitchLatest: SwitchLatest; 224 | export = _SwitchLatest; 225 | } 226 | 227 | declare module 'flyd/module/takeuntil' { 228 | interface takeuntil { 229 | (source: flyd.Stream, end: flyd.Stream): flyd.Stream; 230 | (source: flyd.Stream): (end: flyd.Stream) => flyd.Stream; 231 | } 232 | const _takeuntil: takeuntil; 233 | export = _takeuntil; 234 | } 235 | -------------------------------------------------------------------------------- /module/aftersilence/README.md: -------------------------------------------------------------------------------- 1 | # flyd-aftersilence 2 | Buffers values from a source stream into an array and emits the array once the source stream has had the specified duration of silence. 3 | 4 | __Graph__ 5 | 6 | ```marbles 7 | (ticks represent 10ms) 8 | a: {-1-2-3--5-6-} 9 | afterSilence(20, a): {--------.---} 10 | [1,2,3] 11 | ``` 12 | 13 | __Signature__ 14 | 15 | `(Integer, Stream a) -> Stream b` 16 | 17 | __Example__ 18 | 19 | ```javascript 20 | const afterSilence = require('flyd/module/aftersilence') 21 | 22 | const source = flyd.stream() 23 | const result = flyd.afterSilence(100, source) 24 | 25 | source(1); source(2); source(3) 26 | result() // undefined 27 | 28 | // wait 100ms and print result 29 | setTimeout(() => console.log(result()), 100) 30 | // -> prints [1,2,3] 31 | ``` 32 | -------------------------------------------------------------------------------- /module/aftersilence/index.js: -------------------------------------------------------------------------------- 1 | var flyd = require('../../lib'); 2 | 3 | module.exports = flyd.curryN(2, function(dur, s) { 4 | var scheduled; 5 | var buffer = []; 6 | return flyd.combine(function(s, self) { 7 | buffer.push(s()); 8 | clearTimeout(scheduled); 9 | scheduled = setTimeout(function() { 10 | self(buffer); 11 | buffer = []; 12 | }, dur); 13 | }, [s]); 14 | }); 15 | -------------------------------------------------------------------------------- /module/aftersilence/test/index.js: -------------------------------------------------------------------------------- 1 | var assert = require('assert'); 2 | var flyd = require('../../../lib'); 3 | var stream = flyd.stream; 4 | 5 | var afterSilence = require('../index.js'); 6 | 7 | // KISS way of testing time dependent code :) 8 | 9 | describe('afterSilence', function() { 10 | it('correctly buffers values', function(done) { 11 | var result = []; 12 | var i = 0; 13 | var s1 = stream(); 14 | var push = function() { 15 | s1(i++); 16 | }; 17 | var s2 = afterSilence(50, s1); 18 | flyd.map(function(vs) { 19 | result.push(vs); 20 | }, s2); 21 | setTimeout(push, 20); 22 | setTimeout(push, 30); 23 | setTimeout(push, 40); 24 | setTimeout(push, 95); 25 | setTimeout(push, 100); 26 | setTimeout(push, 110); 27 | setTimeout(push, 120); 28 | setTimeout(push, 175); 29 | setTimeout(function() { 30 | assert.deepEqual(result, [ 31 | [0, 1, 2], 32 | [3, 4, 5, 6], 33 | [7] 34 | ]); 35 | done(); 36 | }, 240); 37 | }); 38 | it('only emits values after specified silence', function(done) { 39 | var result = []; 40 | var i = 0; 41 | var s1 = stream(); 42 | var push = function() { 43 | s1(i++); 44 | }; 45 | var s2 = afterSilence(20, s1); 46 | flyd.map(function(vs) { 47 | result.push(vs); 48 | }, s2); 49 | setTimeout(push, 10); 50 | setTimeout(push, 20); 51 | setTimeout(push, 30); 52 | setTimeout(push, 40); 53 | setTimeout(function() { 54 | assert.equal(result.length, 0); 55 | }, 50); 56 | setTimeout(function() { 57 | assert.deepEqual(result, [[0, 1, 2, 3]]); 58 | done(); 59 | }, 65); 60 | }); 61 | }); 62 | -------------------------------------------------------------------------------- /module/batchwhen/README.md: -------------------------------------------------------------------------------- 1 | # flyd-batchwhen 2 | 3 | Batches values from the second stream (sA) based on the the first stream (sBool) 4 | as a control signal. When sBool is false, sA are passed through as a single 5 | element list. When sBool is true, then values feom sA are batched into a list, 6 | and the batch is emitted when sBool returns to false. This function is convenient 7 | for throttling user inputs. 8 | 9 | # Usage 10 | 11 | ```js 12 | var action$ = flyd.stream() 13 | var throttle$ = flyd.stream(false) 14 | var batchedAction$ = flyd.batchWhen(throttle$, action$) 15 | 16 | action$(1) 17 | // batchedAction$ => [1] 18 | action$(2) 19 | // batchedAction$ => [2] 20 | throttle$(true) 21 | action$(3) 22 | action$(4) 23 | throttle$(false) 24 | // batchedAction$ => [3, 4] 25 | throttle$(true) 26 | throttle$(false) 27 | ``` -------------------------------------------------------------------------------- /module/batchwhen/index.js: -------------------------------------------------------------------------------- 1 | var flyd = require('../../lib'); 2 | var dropRepeats = require('../droprepeats').dropRepeats; 3 | var contains = require('ramda/src/contains'); 4 | 5 | // Stream bool -> Stream a -> Stream a 6 | module.exports = flyd.curryN(2, function(sBool, sA) { 7 | var batch = []; 8 | 9 | var ns = flyd.combine(function(sBool, sA, self, changed) { 10 | 11 | var sBoolChanged = contains(sBool, changed); 12 | var sAChanged = contains(sA, changed); 13 | 14 | 15 | if (sA() !== undefined) { 16 | // if A is undefined then we dont batch anything 17 | if (sBoolChanged) { 18 | if (sAChanged) { 19 | if (sBool()) { 20 | // if Bool and A change and were batching then 21 | // push to the batch 22 | batch.push(sA()); 23 | } else { 24 | // if Bool and A change and we're not batching 25 | // anymore, then push the batch 26 | batch.push(sA()); 27 | self(batch); 28 | batch = []; 29 | } 30 | } else { 31 | if (!sBool()) { 32 | // if Bool changed but A didnt then push the batch 33 | // if there were any batching 34 | if (batch.length > 0) { 35 | self(batch); 36 | batch = []; 37 | } 38 | } 39 | } 40 | } else if (sAChanged) { 41 | if (sBool()) { 42 | // if we're batching then push to the batch 43 | batch.push(sA()); 44 | } else { 45 | // otherwise send it alone 46 | self([sA()]); 47 | } 48 | } else { 49 | // when we just initialize 50 | // if theres a value in A 51 | if (sBool()) { 52 | batch.push(sA()); 53 | } else { 54 | self([sA()]); 55 | } 56 | } 57 | } 58 | 59 | }, [dropRepeats(sBool), sA]); 60 | 61 | return ns; 62 | }); 63 | -------------------------------------------------------------------------------- /module/batchwhen/test/index.js: -------------------------------------------------------------------------------- 1 | var assert = require('assert'); 2 | var flyd = require('../../../lib'); 3 | var stream = flyd.stream; 4 | 5 | var batchWhen = require('../index.js'); 6 | 7 | describe('batchWhen', function() { 8 | it('batches the second stream with the first stream, initally false', function() { 9 | var result = []; 10 | var s = stream(1); 11 | var b = stream(false); 12 | var k = batchWhen(b, s); 13 | flyd.map(function(v) { 14 | result.push(v); 15 | }, k); 16 | s(2); 17 | b(true); 18 | s(3); 19 | s(4); 20 | b(false); 21 | b(true); 22 | b(false); 23 | s(5); 24 | assert.deepEqual(result, [[1], [2], [3, 4], [5]]); 25 | }); 26 | 27 | it('batches the second stream with the first stream, initially true', function() { 28 | var result = []; 29 | var s = stream(1); 30 | var b = stream(true); 31 | var k = batchWhen(b, s); 32 | flyd.map(function(v) { 33 | result.push(v); 34 | }, k); 35 | s(2); 36 | b(false); 37 | s(3); 38 | s(4); 39 | b(true); 40 | b(false); 41 | b(true); 42 | b(false); 43 | s(5); 44 | assert.deepEqual(result, [[1, 2], [3], [4], [5]]); 45 | }); 46 | 47 | it('batches the second stream with the first stream, initially true, with no value', function() { 48 | var result = []; 49 | var s = stream(); 50 | var b = stream(true); 51 | var k = batchWhen(b, s); 52 | flyd.map(function(v) { 53 | result.push(v); 54 | }, k); 55 | s(2); 56 | s(3); 57 | b(false); 58 | s(4); 59 | b(true); 60 | b(false); 61 | b(true); 62 | b(false); 63 | s(5); 64 | assert.deepEqual(result, [[2, 3], [4], [5]]); 65 | }); 66 | 67 | it('batches the second stream with the first stream, initially false, with no value', function() { 68 | var result = []; 69 | var s = stream(); 70 | var b = stream(false); 71 | var k = batchWhen(b, s); 72 | flyd.map(function(v) { 73 | result.push(v); 74 | }, k); 75 | s(2); 76 | b(true); 77 | s(3); 78 | s(4); 79 | b(false); 80 | b(true); 81 | b(false); 82 | s(5); 83 | assert.deepEqual(result, [[2], [3, 4], [5]]); 84 | }); 85 | 86 | }); 87 | -------------------------------------------------------------------------------- /module/diff/README.md: -------------------------------------------------------------------------------- 1 | # flyd-diff 2 | 3 | Similar to map, but this function gets both the previous and the current value of the stream. 4 | 5 | __Graph__ 6 | 7 | ``` 8 | a: {-1-1-2-3-5-} 9 | 10 | diff(add, a): {---2-3-5-8-} 11 | ``` 12 | 13 | __Signature__ 14 | 15 | `((a, a) -> a) -> Stream a -> Stream a` 16 | 17 | __Usage__ 18 | 19 | ``` 20 | const diff = require('flyd/module/diff') 21 | 22 | const velocity = flyd.stream(0) 23 | const acceleration = diff((previous, current) => current - previous, velocity) 24 | 25 | velocity(2)(5) 26 | acceleration() // 3 27 | 28 | velocity(1) 29 | acceleration() // -4 30 | ``` 31 | -------------------------------------------------------------------------------- /module/diff/index.js: -------------------------------------------------------------------------------- 1 | var flyd = require('../../lib'); 2 | 3 | var previous = require('../previous'); 4 | 5 | module.exports = flyd.curryN(2, function(diffFunc, s) { 6 | var prevS = previous(s); 7 | return flyd.combine(function() { 8 | return diffFunc(prevS(), s()); 9 | }, [s, prevS]); 10 | }); 11 | -------------------------------------------------------------------------------- /module/diff/test/index.js: -------------------------------------------------------------------------------- 1 | var assert = require('assert'); 2 | var flyd = require('../../../lib'); 3 | var stream = flyd.stream; 4 | 5 | var diff = require('../index.js'); 6 | 7 | describe('diff', function() { 8 | it('calls the diff function with the previous and new value', function() { 9 | var s = stream(1); 10 | var returnArguments = function() { 11 | return Array.prototype.slice.call(arguments); 12 | }; 13 | var d = diff(returnArguments, s); 14 | s(1)(2)(3); 15 | assert.deepEqual(d(), [2, 3]); 16 | }); 17 | 18 | it('starts streaming after the second value is pushed into the source stream', function() { 19 | var s = stream(); 20 | var calls = 0; 21 | flyd.on(); 22 | diff(function() { calls += 1; }, s); 23 | s(1); 24 | assert.equal(calls, 0); 25 | s(2); 26 | assert.equal(calls, 1); 27 | }); 28 | }); 29 | -------------------------------------------------------------------------------- /module/droprepeats/README.md: -------------------------------------------------------------------------------- 1 | # flyd-droprepeats 2 | 3 | Drops consecutively repeated values from a 4 | [Flyd](https://github.com/paldepind/flyd) stream. Equality is determined by reference. 5 | 6 | ## dropRepeats(s) 7 | 8 | __Graph__ 9 | 10 | ``` 11 | a: {---11--12-2-3-4-} 12 | dropRepeats(a): {---1----2---3-4-} 13 | ``` 14 | 15 | __Signature__ 16 | 17 | `Stream a -> Stream a` 18 | 19 | __Usage__ 20 | 21 | ```js 22 | const dropRepeats = require('flyd/module/droprepeats').dropRepeats 23 | 24 | const s = flyd.stream() 25 | const noRepeats = dropRepeats(s) 26 | const collect = flyd.scan((ls, n) => ls.concat(n), [], noRepeats) 27 | s(1)(2)(2)(3) 28 | collect() // [1, 2, 3] 29 | ``` 30 | 31 | ## dropRepeatsWith(fn, s) 32 | 33 | Drops repeated values from stream `s`, but also takes a function `fn` that 34 | will be used to determine equality. 35 | 36 | __Signature__ 37 | 38 | `(a -> a -> Boolean) -> Stream a -> Stream a` 39 | 40 | __Usage__ 41 | 42 | ```js 43 | const dropRepeatsWith = require('flyd/module/droprepeats').dropRepeatsWith 44 | const s = flyd.stream() 45 | 46 | // Ramda's `equals` determines equality by value 47 | const R = require('ramda') 48 | const noRepeats = dropRepeatsWith(R.equals, s) 49 | const collect = flyd.scan((ls, n) => ls.concat(n), [], noRepeats) 50 | s({ foo: 'bar' }) 51 | s({ foo: 'bar' }) 52 | collect() // [{ foo: 'bar' }] 53 | ``` 54 | -------------------------------------------------------------------------------- /module/droprepeats/index.js: -------------------------------------------------------------------------------- 1 | var flyd = require('../../lib'); 2 | 3 | function dropRepeatsWith(eq, s) { 4 | var prev; 5 | return flyd.combine(function(s, self) { 6 | if (!self.hasVal || !eq(s.val, prev)) { 7 | self(s.val); 8 | prev = s.val; 9 | } 10 | }, [s]); 11 | } 12 | 13 | exports.dropRepeats = function(s) { 14 | return dropRepeatsWith(strictEq, s); 15 | }; 16 | 17 | exports.dropRepeatsWith = flyd.curryN(2, dropRepeatsWith); 18 | 19 | function strictEq(a, b) { 20 | return a === b; 21 | } 22 | -------------------------------------------------------------------------------- /module/droprepeats/test/index.js: -------------------------------------------------------------------------------- 1 | var flyd = require('../../../lib'); 2 | var stream = flyd.stream; 3 | var dropRepeats = require('../').dropRepeats; 4 | var dropRepeatsWith = require('../').dropRepeatsWith; 5 | var R = require('ramda'); 6 | var assert = require('assert'); 7 | 8 | var collect = flyd.scan(R.flip(R.append), []); 9 | 10 | describe('dropRepeats', function() { 11 | it('drops consecutive repeated values', function() { 12 | var s = stream(); 13 | var all = collect(dropRepeats(s)); 14 | s(1)(2)(2)(3); 15 | assert.deepEqual(all(), [1, 2, 3]); 16 | }); 17 | 18 | it('doesn\'t determine equality by value', function() { 19 | var s = stream(); 20 | var all = collect(dropRepeats(s)); 21 | s({ foo: 'bar' }); 22 | s({ foo: 'bar' }); 23 | assert.deepEqual(all(), [ 24 | { foo: 'bar' }, 25 | { foo: 'bar' } 26 | ]); 27 | }); 28 | }); 29 | 30 | describe('dropRepeatsWith', function() { 31 | it('takes a function for using custom equality logic', function() { 32 | var s = stream(); 33 | var all = collect(dropRepeatsWith(R.equals, s)); 34 | s({ foo: 'bar' }); 35 | s({ foo: 'bar' }); 36 | assert.deepEqual(all(), [ 37 | { foo: 'bar' } 38 | ]); 39 | }); 40 | 41 | it('always includes first value so we can safely test for equality', function() { 42 | var s = stream(); 43 | var all = collect(dropRepeatsWith(function(a, b) { 44 | return a[0] === b[0] || a[1] === b[1]; 45 | }, s)); 46 | s([1, 2]); 47 | s([1, 3]); 48 | s([2, 3]); 49 | assert.deepEqual(all(), [ 50 | [1, 2], 51 | [2, 3] 52 | ]); 53 | }); 54 | 55 | it('is curried', function() { 56 | var s = stream(); 57 | var equalsDropper = dropRepeatsWith(R.equals); 58 | var all = collect(equalsDropper(s)); 59 | s({ foo: 'bar' }); 60 | s({ foo: 'bar' }); 61 | assert.deepEqual(all(), [ 62 | { foo: 'bar' } 63 | ]); 64 | }); 65 | }); 66 | -------------------------------------------------------------------------------- /module/every/README.md: -------------------------------------------------------------------------------- 1 | # flyd-every 2 | Takes a number of milliseconds `ms` and creates a stream of the current time updated every `ms`. 3 | 4 | The stream emits current timestamp values using `Date.now()` (eg `1475273004713`) 5 | 6 | __Graph__ 7 | 8 | ``` 9 | (ticks represent 10ms) 10 | every(30): {--t--t--t--t--t--> 11 | ``` 12 | 13 | __Signature__ 14 | 15 | `Number -> Stream Number` 16 | 17 | __Usage__ 18 | 19 | ```javascript 20 | const every = require('flyd/module/every') 21 | const everySecond = every(1000) 22 | 23 | // Print once every second 24 | flyd.on(time => console.log('Current time is', time), everySecond) 25 | 26 | // count every second 27 | const count = flyd.scan(n => n + 1, 0, everySecond) 28 | flyd.map(c => console.log(c), count) // 0 ... 1 ... 2 ... 3 ... 4 ... 5 29 | ``` 30 | -------------------------------------------------------------------------------- /module/every/index.js: -------------------------------------------------------------------------------- 1 | var flyd = require('../../lib'); 2 | 3 | module.exports = function(dur) { 4 | var s = flyd.stream(); 5 | var target = Date.now(); 6 | function timer() { 7 | if (s.end()) return; 8 | var now = Date.now(); 9 | target += dur; 10 | s(now); 11 | setTimeout(timer, target - now); 12 | } 13 | timer(); 14 | return s; 15 | }; 16 | -------------------------------------------------------------------------------- /module/every/test/browsertest/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Every drift test 6 | 7 | 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /module/every/test/browsertest/script.js: -------------------------------------------------------------------------------- 1 | var flyd = require('flyd'); 2 | var every = require('../every.js'); 3 | 4 | var startTime; 5 | var dur = 1000; 6 | var ticks = 0; 7 | var e = every(dur); 8 | flyd.map(function(t) { 9 | startTime === undefined ? startTime = t : ++ticks; 10 | console.log(t); 11 | console.log('Drift: ' + (startTime + (ticks * dur) - t)); 12 | // console.log(t); 13 | }, e); 14 | -------------------------------------------------------------------------------- /module/every/test/index.js: -------------------------------------------------------------------------------- 1 | var assert = require('assert'); 2 | var flyd = require('../../../lib'); 3 | var every = require('../index.js'); 4 | 5 | describe('every', function() { 6 | var e; 7 | afterEach(function() { 8 | e.end(true); 9 | }); 10 | it('invokes callback the correct amount of times', function(done) { 11 | var times = 0; 12 | e = every(50); 13 | flyd.map(function() { ++times; }, e); 14 | setTimeout(function() { 15 | assert.equal(5, times); 16 | done(); 17 | }, 225); 18 | }); 19 | it('ends', function(done) { 20 | var times = 0; 21 | e = every(50); 22 | var endVal; 23 | flyd.map(function() { ++times; }, e); 24 | setTimeout(function() { 25 | assert.equal(5, times); 26 | endVal = e(); 27 | e.end(true); 28 | setTimeout(function() { 29 | assert.equal(endVal, e()); 30 | done(); 31 | }, 225); 32 | }, 225); 33 | }); 34 | }); 35 | -------------------------------------------------------------------------------- /module/filter/README.md: -------------------------------------------------------------------------------- 1 | # flyd-filter 2 | 3 | Using a predicate function, select only the elements of a stream that the predicate function finds truthy. 4 | 5 | __Graph__ 6 | 7 | ``` 8 | a: {1--2--3--4--5--} 9 | filter(isEven, a): {---2-----4-----} 10 | ``` 11 | 12 | __Signature__ 13 | 14 | `(a -> Boolean) -> Stream a -> Stream a` 15 | 16 | __Usage__ 17 | 18 | ```javascript 19 | const filter = require('flyd/module/filter') 20 | 21 | const numbers = flyd.stream() 22 | const largeNumbers = filter(n => n > 5, numbers) 23 | 24 | // Collect large numbers into an array 25 | const collect = flyd.scan((ls, n) => ls.concat(n), [], largeNumbers) 26 | 27 | numbers(2)(6)(5)(3)(7)(10)(5); 28 | collect() // [6, 7, 10] 29 | ``` 30 | -------------------------------------------------------------------------------- /module/filter/index.js: -------------------------------------------------------------------------------- 1 | var flyd = require('../../lib'); 2 | 3 | module.exports = flyd.curryN(2, function(fn, s) { 4 | return flyd.combine(function(s, self) { 5 | if (fn(s())) self(s.val); 6 | }, [s]); 7 | }); 8 | -------------------------------------------------------------------------------- /module/filter/test/index.js: -------------------------------------------------------------------------------- 1 | var assert = require('assert'); 2 | var flyd = require('../../../lib'); 3 | 4 | var filter = require('../index.js'); 5 | 6 | function over5(n) { 7 | return n > 5; 8 | } 9 | 10 | describe('filter', function() { 11 | it('only lets values passing the filter through', function() { 12 | var result = []; 13 | var numbers = flyd.stream(); 14 | var largeNumbers = filter(over5, numbers); 15 | flyd.map(function(n) { 16 | result.push(n); 17 | }, largeNumbers); 18 | numbers(2)(6)(5)(3)(7)(10)(5); 19 | assert.deepEqual(result, [6, 7, 10]); 20 | }); 21 | it('is curried', function() { 22 | var numbers = flyd.stream(); 23 | assert(filter(over5)(numbers)); 24 | }); 25 | }); 26 | -------------------------------------------------------------------------------- /module/forwardto/README.md: -------------------------------------------------------------------------------- 1 | # flyd-forwardto 2 | 3 | Forward values from one stream into another existing stream. 4 | 5 | Create a new stream that passes all values through a function and forwards them 6 | to a target stream. 7 | 8 | __Graph__ 9 | 10 | ``` 11 | a: {1---2---3---} 12 | forwardTo(a, parseInt): {--2---3---2-} 13 | flyd.map(square, a): {1-4-4-9-9-4-} 14 | ``` 15 | 16 | __Signature__ 17 | 18 | `Stream b -> (a -> b) -> Stream a` 19 | 20 | __Example__ 21 | 22 | ```javascript 23 | const forwardTo = require('flyd/module/forwardto') 24 | const R = require('ramda') 25 | 26 | // A stream of numbers 27 | const numbers = flyd.stream() 28 | // Another stream that squares the numbers 29 | const squaredNumbers = flyd.map(R.square, numbers) 30 | 31 | // A stream of numbers as strings 32 | // we want to convert them to ints and forward them into the numbers stream above: 33 | const stringNumbers = forwardTo(numbers, parseInt) 34 | 35 | stringNumbers('7') 36 | squaredNumbers() // -> 49 37 | numbers(4) 38 | squaredNumbers() // -> 16 39 | stringNumbers('9') 40 | squaredNumbers() // -> 81 41 | ``` 42 | 43 | -------------------------------------------------------------------------------- /module/forwardto/index.js: -------------------------------------------------------------------------------- 1 | var flyd = require('../../lib'); 2 | 3 | module.exports = flyd.curryN(2, function(targ, fn) { 4 | var s = flyd.stream(); 5 | flyd.map(function(v) { targ(fn(v)); }, s); 6 | return s; 7 | }); 8 | -------------------------------------------------------------------------------- /module/forwardto/test/index.js: -------------------------------------------------------------------------------- 1 | var assert = require('assert'); 2 | var flyd = require('../../../lib'); 3 | var forwardTo = require('../index.js'); 4 | 5 | describe('forwardTo', function() { 6 | it('forwards values', function() { 7 | var result = []; 8 | var target = flyd.stream(); 9 | function fn1(v) { result.push(v); } 10 | function fn2(v) { result.push(2 * v); return v; } 11 | flyd.map(fn1, target); 12 | var fw = forwardTo(target, fn2); 13 | fw(1)(2)(3); 14 | assert.deepEqual(result, [2, 1, 4, 2, 6, 3]); 15 | }); 16 | }); 17 | -------------------------------------------------------------------------------- /module/inlast/README.md: -------------------------------------------------------------------------------- 1 | # flyd-inlast 2 | 3 | Creates a stream that emits an array of all values from a source stream which where emitted in a specified duration. 4 | 5 | Using a duration `ms`, it will collect all values that are emitted within an `ms` time period, buffering them into an array. 6 | 7 | "Get a list of values that were emitted from a stream __in the last__ n milliseconds" 8 | 9 | Also see [aftersilence](/module/aftersilence). 10 | 11 | __Graph__ 12 | 13 | ``` 14 | (each tick is 10ms) 15 | a: {--2----3--4-----} 16 | inlast(40, a): {--.----.--.-----} 17 | [2] [3][3,4] 18 | ``` 19 | 20 | __Signature__ 21 | 22 | ``` 23 | Integer -> Stream a -> Stream [a] 24 | ``` 25 | 26 | __Usage__ 27 | 28 | ```js 29 | const inlast = require('flyd/module/inlast') 30 | 31 | const s = flyd.stream() 32 | const in = inlast(100, s) 33 | in() // -> [] 34 | s(1)(2)(3); in() // -> [1,2,3] 35 | 36 | // emit a first value, wait 200ms, then emit a second value. 37 | // in stream will only emit the second most recent value, discarding the older one. 38 | s(1) 39 | setTimeout(()=> { 40 | s(2) 41 | in() // -> [2] 42 | }, 200) 43 | ``` 44 | -------------------------------------------------------------------------------- /module/inlast/index.js: -------------------------------------------------------------------------------- 1 | var flyd = require('../../lib'); 2 | 3 | module.exports = flyd.curryN(2, function(dur, s) { 4 | var values = []; 5 | return flyd.combine(function(s, self) { 6 | setTimeout(function() { 7 | self(values = values.slice(1)); 8 | }, dur); 9 | return (values = values.concat([s()])); 10 | }, [s]); 11 | }); 12 | -------------------------------------------------------------------------------- /module/inlast/test/index.js: -------------------------------------------------------------------------------- 1 | var assert = require('assert'); 2 | var flyd = require('../../../lib'); 3 | var stream = flyd.stream; 4 | 5 | var inLast = require('../index.js'); 6 | 7 | describe('inLast', function() { 8 | it('adds values', function(done) { 9 | var s = stream(); 10 | var lastMs = inLast(50, s); 11 | s(1); 12 | setTimeout(function() { 13 | assert.deepEqual(lastMs(), [1]); 14 | s(2); 15 | }, 20); 16 | setTimeout(function() { 17 | assert.deepEqual(lastMs(), [1, 2]); 18 | done(); 19 | }, 40); 20 | }); 21 | it('adds and removes values', function(done) { 22 | var s = stream(); 23 | var lastMs = inLast(50, s); 24 | s(1); 25 | setTimeout(function() { 26 | assert.deepEqual(lastMs(), [1]); 27 | s(2); 28 | }, 35); 29 | setTimeout(function() { 30 | assert.deepEqual(lastMs(), [1, 2]); 31 | s(3); 32 | }, 40); 33 | setTimeout(function() { 34 | assert.deepEqual(lastMs(), [2, 3]); 35 | s(4); 36 | }, 60); 37 | setTimeout(function() { 38 | assert.deepEqual(lastMs(), [2, 3, 4]); 39 | s(5); 40 | }, 80); 41 | setTimeout(function() { 42 | assert.deepEqual(lastMs(), [4, 5]); 43 | done(); 44 | }, 100); 45 | }); 46 | it('is updated when values come and go', function(done) { 47 | var result = []; 48 | var s = stream(); 49 | var lastMs = inLast(50, s); 50 | flyd.map(function(a) { result.push(a); }, lastMs); 51 | s(1); 52 | setTimeout(function() { s(2); }, 35); 53 | setTimeout(function() { s(3); }, 40); 54 | // 1 leaves 55 | setTimeout(function() { s(4); }, 60); 56 | setTimeout(function() { s(5); }, 80); 57 | // 2 leaves 58 | // 3 leaves 59 | setTimeout(function() { 60 | assert.deepEqual(result, [ 61 | [1], 62 | [1, 2], 63 | [1, 2, 3], 64 | [2, 3], 65 | [2, 3, 4], 66 | [2, 3, 4, 5], 67 | [3, 4, 5], 68 | [4, 5] 69 | ]); 70 | done(); 71 | }, 100); 72 | }); 73 | }); 74 | -------------------------------------------------------------------------------- /module/keepwhen/README.md: -------------------------------------------------------------------------------- 1 | # flyd-keepwhen 2 | 3 | Keeps values from the second stream when the first stream is true (truth is tested with `!== false`). 4 | 5 | __Graph__ 6 | 7 | ``` 8 | a: {-t---f---t----} 9 | b: {---1---2---3--} 10 | keepWhen(a, b): {---1-------3--} 11 | ``` 12 | 13 | __Signature__ 14 | 15 | `Stream Boolean -> Stream a -> Stream a` 16 | 17 | __Usage__ 18 | 19 | ``` 20 | const keepWhen = require('flyd/module/keepwhen') 21 | 22 | const source = flyd.stream() 23 | const test = flyd.stream() 24 | const result = keepWhen(test, source) 25 | 26 | // when stream must !== false 27 | source(1) 28 | result() // -> 1 29 | source(2) 30 | result() // -> 2 31 | test(true) 32 | source(3) 33 | result() // -> 3 34 | test(false) 35 | source(4) 36 | result() // -> 3 37 | test('hi') 38 | source(5) 39 | result() // -> 5 40 | // null or undefined are considered truthy for source 41 | test(null) 42 | source(6) 43 | result() // -> 6 44 | // only false will prevent values from emitting 45 | test(false) 46 | source(7) 47 | result() // -> 6 48 | ``` 49 | -------------------------------------------------------------------------------- /module/keepwhen/index.js: -------------------------------------------------------------------------------- 1 | var flyd = require('../../lib'); 2 | 3 | // Stream bool -> Stream a -> Stream a 4 | module.exports = flyd.curryN(2, function(sBool, sA) { 5 | return flyd.combine(function(sA, self) { 6 | if (sBool() !== false) self(sA()); 7 | }, [sA]); 8 | }); 9 | -------------------------------------------------------------------------------- /module/keepwhen/test/index.js: -------------------------------------------------------------------------------- 1 | var assert = require('assert'); 2 | var flyd = require('../../../lib'); 3 | var stream = flyd.stream; 4 | 5 | var keepWhen = require('../index.js'); 6 | 7 | describe('keepWhen', function() { 8 | it('keeps values from second stream when first is true', function() { 9 | var result = []; 10 | var s = stream(1); 11 | var b = stream(false); 12 | var k = keepWhen(b, s); 13 | flyd.map(function(v) { 14 | result.push(v); 15 | }, k); 16 | s(2); 17 | b(true); 18 | s(3)(4); 19 | b(false); 20 | s(5); 21 | b(true); 22 | s(6); 23 | assert.deepEqual(result, [3, 4, 6]); 24 | }); 25 | it('doesnt emit anything until second stream has a value', function() { 26 | var result = []; 27 | var s = stream(); 28 | var b = stream(false); 29 | var k = keepWhen(b, s); 30 | flyd.map(function(v) { 31 | result.push(v); 32 | }, k); 33 | b(true)(false)(true); 34 | s(3)(4); 35 | assert.deepEqual(result, [3, 4]); 36 | }); 37 | }); 38 | -------------------------------------------------------------------------------- /module/lift/README.md: -------------------------------------------------------------------------------- 1 | # flyd-lift 2 | 3 | Merge the latest values from multiple streams into a single stream using a function. 4 | 5 | Emits a new value every time any source stream has a new value. 6 | 7 | __Graph__ 8 | 9 | ``` 10 | a: {---1----2----} 11 | b: {-----1----2--} 12 | lift(add, a, b): {-----2--3-4--} 13 | ``` 14 | 15 | __Signature__ 16 | 17 | `( ((a, b, ...) -> c), (Stream a, Stream b, ...) ) -> Stream c` 18 | 19 | __Usage__ 20 | 21 | ```javascript 22 | const lift = require('flyd/module/lift') 23 | 24 | const n1 = flyd.stream(1) 25 | const n2 = flyd.stream(4) 26 | const n3 = flyd.stream(9) 27 | 28 | const addThree = (a, b, c) => a + b + c 29 | const sum = lift(addThree, n1, n2, n3) 30 | 31 | sum() // 14 32 | 33 | n2(5) 34 | sum() // 15 35 | ``` 36 | -------------------------------------------------------------------------------- /module/lift/index.js: -------------------------------------------------------------------------------- 1 | var flyd = require('../../lib'); 2 | 3 | module.exports = function(f /* , streams */) { 4 | var streams = Array.prototype.slice.call(arguments, 1); 5 | var vals = []; 6 | return flyd.combine(function() { 7 | for (var i = 0; i < streams.length; ++i) vals[i] = streams[i](); 8 | return f.apply(null, vals); 9 | }, streams); 10 | }; 11 | -------------------------------------------------------------------------------- /module/lift/test/index.js: -------------------------------------------------------------------------------- 1 | var assert = require('assert'); 2 | var flyd = require('../../../lib'); 3 | var stream = flyd.stream; 4 | var lift = require('../index.js'); 5 | 6 | describe('lift', function() { 7 | it('applies a function to two streams', function() { 8 | var add = function(x, y) { return x + y; }; 9 | var x = stream(3); 10 | var y = stream(4); 11 | var sum = lift(add, x, y); 12 | assert.equal(sum(), x() + y()); 13 | x(12); 14 | assert.equal(sum(), x() + y()); 15 | y(3); 16 | assert.equal(sum(), x() + y()); 17 | }); 18 | it('applies a function to five streams', function() { 19 | var add = function(a, b, c, d, e) { return a + b + c + d + e; }; 20 | var a = stream(1); 21 | var b = stream(2); 22 | var c = stream(3); 23 | var d = stream(4); 24 | var e = stream(5); 25 | var sum = lift(add, a, b, c, d, e); 26 | assert.equal(sum(), a() + b() + c() + d() + e()); 27 | e(12); d(2); b(0); 28 | assert.equal(sum(), a() + b() + c() + d() + e()); 29 | a(3); c(3); 30 | assert.equal(sum(), a() + b() + c() + d() + e()); 31 | }); 32 | }); 33 | -------------------------------------------------------------------------------- /module/mergeall/README.md: -------------------------------------------------------------------------------- 1 | # flyd-mergeall 2 | Flyd module for merging several streams into one. 3 | 4 | __Graph__ 5 | 6 | ``` 7 | a: {---1---2---3---} 8 | b: {--1-----2-----3} 9 | mergeAll([a,b]): {--11---22--3--3} 10 | ``` 11 | 12 | __Signature__ 13 | 14 | `[Stream a] -> Stream a` 15 | 16 | __Example__ 17 | 18 | ```javascript 19 | const mergeAll = require('flyd/module/mergeall') 20 | 21 | const s1 = flyd.stream() 22 | const s2 = flyd.stream() 23 | const s3 = flyd.stream() 24 | var merged = mergeAll([s1, s2, s3]) 25 | s1(1) 26 | merged() // 1 27 | s2(2) 28 | merged() // 2 29 | s3(3) 30 | merged() // 3 31 | ``` 32 | 33 | -------------------------------------------------------------------------------- /module/mergeall/index.js: -------------------------------------------------------------------------------- 1 | var flyd = require('../../lib'); 2 | 3 | module.exports = function mergeAll(streams) { 4 | var s = flyd.immediate(flyd.combine(function() { 5 | var self = arguments[arguments.length - 2]; 6 | if (arguments[arguments.length - 1][0]) { 7 | self(arguments[arguments.length - 1][0]()); 8 | return; 9 | } 10 | [].slice.call(arguments, 0, arguments.length - 2) 11 | .some(function(s1) { 12 | if (s1.hasVal) { 13 | self(s1.val); 14 | return true; 15 | } 16 | }); 17 | }, streams)); 18 | flyd.endsOn(flyd.combine(function() { 19 | return true; 20 | }, streams.map(function(sm) { return sm.end; })), s); 21 | return s; 22 | }; 23 | 24 | -------------------------------------------------------------------------------- /module/mergeall/test/index.js: -------------------------------------------------------------------------------- 1 | var assert = require('assert'); 2 | var flyd = require('../../../lib'); 3 | var stream = flyd.stream; 4 | 5 | var mergeAll = require('../index.js'); 6 | 7 | describe('mergeAll', function() { 8 | it('merges multiple streams', function() { 9 | var s1 = stream(); 10 | var s2 = stream(); 11 | var s3 = stream(); 12 | var merged = mergeAll([s1, s2, s3]); 13 | s1(1); 14 | assert.equal(merged(), 1); 15 | s2(2); 16 | assert.equal(merged(), 2); 17 | s3(3); 18 | assert.equal(merged(), 3); 19 | s2('hello'); 20 | assert.equal(merged(), 'hello'); 21 | }); 22 | it('has initial value', function() { 23 | var s1 = stream(1); 24 | var s2 = stream(2); 25 | var s3 = stream(); 26 | var merged = mergeAll([s1, s2, s3]); 27 | assert.equal(merged(), 1); 28 | s3(3); 29 | assert.equal(merged(), 3); 30 | }); 31 | it('ends when all the merged streams end', function() { 32 | var s1 = stream(); 33 | var s2 = stream(); 34 | var s3 = stream(); 35 | var merged = mergeAll([s1, s2, s3]); 36 | s1.end(true); 37 | assert.equal(s1.end(), true); 38 | assert.equal(merged.end(), undefined); 39 | s2.end(true); 40 | assert.equal(s2.end(), true); 41 | assert.equal(merged.end(), undefined); 42 | s3.end(true); 43 | assert.equal(s3.end(), true); 44 | assert.equal(merged.end(), true); 45 | }); 46 | }); 47 | -------------------------------------------------------------------------------- /module/obj/README.md: -------------------------------------------------------------------------------- 1 | # flyd-obj 2 | 3 | Functions for working with Flyd stream in objects. 4 | 5 | - Convert object values from plain values into streams with __streamProps__ 6 | - Convert object values from streams into plain values with __extractProps__ 7 | - Convert a plain object with stream values into a single stream of plain objects with __stream__ 8 | 9 | These functions perform these conversions recursively in nested objects. 10 | 11 | ## streamProps(obj) 12 | 13 | Given an object of normal values, turn every value into a stream. It will 14 | stream nested properties recursively. 15 | 16 | __Signature__ 17 | 18 | `Object a -> Object (Stream a)` 19 | 20 | __Usage__ 21 | 22 | ```js 23 | const flydObj = require('flyd/module/object') 24 | const obj = {x: 1, y: {z: 2}} 25 | const objOfStreams = flydObj.streamProps(obj) 26 | 27 | objOfStreams.x() // 1 28 | objOfStreams.y.z() // 2 29 | ``` 30 | 31 | ## extractProps(obj) 32 | 33 | Given an object that contains streams for values, extract everything into an 34 | object of regular values. It will extract nested properties recursively. 35 | 36 | __Signature__ 37 | 38 | `Object (Stream a) -> Object a` 39 | 40 | __Usage__ 41 | 42 | ```js 43 | const objOfStreams = {x: flyd.stream(1), y: {z: flyd.stream(2)}} 44 | const obj = flydObj.extractProps(objOfStreams) 45 | //obj is {x: 1, y: {z: 2}} 46 | ``` 47 | 48 | ## stream(obj) 49 | 50 | Given an object containing streams, combine all the streams into a single stream of plain objects. 51 | 52 | __Signature__ 53 | 54 | `Object (Stream a) -> Stream (Object a)` 55 | 56 | __Usage__ 57 | 58 | ```js 59 | const click = flyd.stream() 60 | const message = flyd.map(() => 'Hello world!', state.click) 61 | const state = {click, message} 62 | 63 | const stateStream = flydObj.stream(state) 64 | 65 | stateStream() // {click: undefined, message: undefined} 66 | 67 | click(true) 68 | stateStream() // {click: true, message: 'Hello World!'} 69 | ``` 70 | 71 | -------------------------------------------------------------------------------- /module/obj/index.js: -------------------------------------------------------------------------------- 1 | var flyd = require('../../lib'); 2 | 3 | function isPlainObject(obj) { 4 | return obj !== null && typeof obj === 'object' && Object.getPrototypeOf(obj) === Object.prototype; 5 | } 6 | 7 | var streamProps = function(from) { 8 | var to = {}; 9 | for (var key in from) { 10 | if (from.hasOwnProperty(key)) { 11 | to[key] = isPlainObject(from[key]) ? streamProps(from[key]) : flyd.stream(from[key]); 12 | } 13 | } 14 | return to; 15 | }; 16 | 17 | var extractProps = function(obj) { 18 | var newObj = {}; 19 | for (var key in obj) { 20 | if (obj.hasOwnProperty(key)) { 21 | newObj[key] = isPlainObject(obj[key]) ? extractProps(obj[key]) 22 | : flyd.isStream(obj[key]) ? obj[key]() 23 | : obj[key]; 24 | } 25 | } 26 | return newObj; 27 | }; 28 | 29 | var stream = function(obj) { 30 | var streams = Object.keys(obj).map(function(key) { 31 | return isPlainObject(obj[key]) ? stream(obj[key]) 32 | : flyd.isStream(obj[key]) ? obj[key] 33 | : flyd.stream(obj[key]); 34 | }); 35 | return flyd.combine(function() { 36 | return extractProps(obj); 37 | }, streams); 38 | }; 39 | 40 | module.exports = { 41 | streamProps: streamProps, 42 | extractProps: extractProps, 43 | stream: stream 44 | }; 45 | -------------------------------------------------------------------------------- /module/obj/test/index.js: -------------------------------------------------------------------------------- 1 | var assert = require('assert'); 2 | var flyd = require('../../../lib'); 3 | var stream = flyd.stream; 4 | 5 | var obj = require('../index.js'); 6 | 7 | describe('stream props', function() { 8 | it('converts the properties in an object to streams', function() { 9 | var o = {one: 1, two: 2, three: 3}; 10 | var oS = obj.streamProps(o); 11 | assert.equal(o.one, oS.one()); 12 | assert.equal(o.two, oS.two()); 13 | assert.equal(o.three, oS.three()); 14 | }); 15 | it('handles converting nested properties to nested streams', function() { 16 | var o = {nested: {value: 'val', deeper: {deepVal: 'deepVal'}}}; 17 | var oS = obj.streamProps(o); 18 | assert.equal(o.nested.value, oS.nested.value()); 19 | assert.equal(o.nested.deeper.deepVal, oS.nested.deeper.deepVal()); 20 | }); 21 | }); 22 | 23 | describe('stream object', function() { 24 | var o = {one: 1, two: 2, three: 3}; 25 | it('returns a stream', function() { 26 | var oS = obj.stream(obj.streamProps(o)); 27 | assert(flyd.isStream(oS)); 28 | }); 29 | it('flow unwrapped object down stream when props change', function() { 30 | var oS = obj.streamProps(o); 31 | var result = []; 32 | flyd.map(function(o) { result.push(o); }, obj.stream(oS)); 33 | oS.one(4); 34 | oS.three(4); 35 | oS.two(4); 36 | assert.deepEqual(result, [ 37 | {one: 1, two: 2, three: 3}, 38 | {one: 4, two: 2, three: 3}, 39 | {one: 4, two: 2, three: 4}, 40 | {one: 4, two: 4, three: 4} 41 | ]); 42 | }); 43 | it('handles prop changes in nested objects', function() { 44 | var o = {nested: {value: 'val', deeper: {deepVal: 'deepVal'}}}; 45 | var oS = obj.streamProps(o); 46 | var result = []; 47 | flyd.map(function(o) { result.push(o); }, obj.stream(oS)); 48 | oS.nested.value('val2'); 49 | oS.nested.deeper.deepVal('deepVal2'); 50 | oS.nested.value('val3'); 51 | assert.deepEqual(result, [ 52 | {nested: {value: 'val', deeper: {deepVal: 'deepVal'}}}, 53 | {nested: {value: 'val2', deeper: {deepVal: 'deepVal'}}}, 54 | {nested: {value: 'val2', deeper: {deepVal: 'deepVal2'}}}, 55 | {nested: {value: 'val3', deeper: {deepVal: 'deepVal2'}}} 56 | ]); 57 | }); 58 | it('retains the values of non-streams', function() { 59 | var oS = {nested: {value: stream('val'), deeper: {constant: 'constantVal'}}}; 60 | var result = []; 61 | flyd.map(function(o) { result.push(o); }, obj.stream(oS)); 62 | oS.nested.value('val2'); 63 | oS.nested.value('val3'); 64 | assert.deepEqual(result, [ 65 | {nested: {value: 'val', deeper: {constant: 'constantVal'}}}, 66 | {nested: {value: 'val2', deeper: {constant: 'constantVal'}}}, 67 | {nested: {value: 'val3', deeper: {constant: 'constantVal'}}} 68 | ]); 69 | }); 70 | }); 71 | 72 | describe('extract', function() { 73 | it('extracts the values from streams in object', function() { 74 | var oS = {one: stream(1), two: stream(2), three: stream(3)}; 75 | var o = obj.extractProps(oS); 76 | assert.equal(o.one, oS.one()); 77 | assert.equal(o.two, oS.two()); 78 | assert.equal(o.three, oS.three()); 79 | }); 80 | it('handles values that are not streams', function() { 81 | var oS = {one: stream(1), undef: undefined, nll: null, two: 2}; 82 | var o = obj.extractProps(oS); 83 | assert.equal(o.one, oS.one()); 84 | assert.equal(o.undef, oS.undef); 85 | assert.equal(o.nll, oS.nll); 86 | assert.equal(o.two, oS.two); 87 | }); 88 | it('handles nested values', function() { 89 | var oS = {nested: {value: stream('val'), deeper: {deepVal: stream('deepVal'), constant: 3}}}; 90 | var o = obj.extractProps(oS); 91 | assert.equal(o.nested.value, oS.nested.value()); 92 | assert.equal(o.nested.deeper.deepVal, oS.nested.deeper.deepVal()); 93 | assert.equal(o.nested.deeper.constant, oS.nested.deeper.constant); 94 | }); 95 | }); 96 | -------------------------------------------------------------------------------- /module/previous/README.md: -------------------------------------------------------------------------------- 1 | # flyd-previous 2 | 3 | Returns a stream that is always one value behind the original stream. 4 | 5 | __Graph__ 6 | 7 | ``` 8 | a: {---1---2---3---4} 9 | previous(a): {-------1---2---3} 10 | ``` 11 | 12 | __Signature__ 13 | 14 | `Stream a -> Stream a` 15 | 16 | __Usage__ 17 | 18 | ``` 19 | const previous = require('flyd/module/previous') 20 | 21 | const s = flyd.stream() 22 | const prev = previous(s) 23 | 24 | s(1) 25 | prev() // undefined 26 | s(2) 27 | prev() // 1 28 | s(3) 29 | prev() // 2 30 | ``` 31 | -------------------------------------------------------------------------------- /module/previous/index.js: -------------------------------------------------------------------------------- 1 | var flyd = require('../../lib'); 2 | 3 | module.exports = function(s) { 4 | var previousValue; 5 | return flyd.combine(skipFirstCall(function(s, self) { 6 | self(previousValue); 7 | previousValue = s(); 8 | }), [s]); 9 | }; 10 | 11 | function skipFirstCall(func) { 12 | var functionToCall = function() { 13 | functionToCall = func; 14 | } 15 | return function() { 16 | return functionToCall.apply(this, arguments); 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /module/previous/test/index.js: -------------------------------------------------------------------------------- 1 | var assert = require('assert'); 2 | var flyd = require('../../../lib'); 3 | var stream = flyd.stream; 4 | 5 | var previous = require('../index.js'); 6 | 7 | describe('previous', function() { 8 | it('is always one value behind the source stream', function() { 9 | var s = stream(1); 10 | var p = previous(s); 11 | s(2)(3)(4); 12 | assert.equal(p(), 3); 13 | }); 14 | 15 | it('starts streaming after the second value is pushed into the source stream', function() { 16 | var s = stream(); 17 | var p = previous(s); 18 | var calls = 0; 19 | flyd.on(function() { calls += 1; }, p); 20 | s(1); 21 | assert.equal(calls, 0); 22 | s(2); 23 | assert.equal(calls, 1); 24 | }); 25 | }); 26 | -------------------------------------------------------------------------------- /module/sampleon/README.md: -------------------------------------------------------------------------------- 1 | # flyd-sampleon 2 | 3 | Sample from the second stream every time an event occurs on the first 4 | stream. 5 | 6 | __Graph__ 7 | 8 | ``` 9 | a: {--t--t--t-------t} 10 | b: {---1---2---3---4-} 11 | sampleOn(a, b): {-----1--2-------4} 12 | ``` 13 | 14 | __Signature__ 15 | 16 | `Stream a -> Stream b -> Stream b` 17 | 18 | __Usage__ 19 | 20 | ```javascript 21 | const sampleOn = require('flyd/module/sampleon') 22 | 23 | const sample = flyd.stream() 24 | const on = flyd.stream() 25 | const result = sampleOn(on, sample) 26 | 27 | on(true) 28 | result() // undefined 29 | 30 | sample(1) 31 | on(true) 32 | result() // 1 33 | 34 | sample(2) 35 | sample(3) 36 | on(true) 37 | result() // 3 38 | ``` 39 | -------------------------------------------------------------------------------- /module/sampleon/index.js: -------------------------------------------------------------------------------- 1 | var flyd = require('../../lib'); 2 | 3 | module.exports = flyd.curryN(2, function(s1, s2) { 4 | return flyd.combine(function() { 5 | return s2(); 6 | }, [s1]); 7 | }); 8 | -------------------------------------------------------------------------------- /module/sampleon/test/index.js: -------------------------------------------------------------------------------- 1 | var assert = require('assert'); 2 | var flyd = require('../../../lib'); 3 | var stream = flyd.stream; 4 | 5 | var sampleOn = require('../index.js'); 6 | 7 | describe('sample On', function() { 8 | it('samples from second stream', function() { 9 | var result = []; 10 | var s1 = stream(); 11 | var s2 = stream(); 12 | var sampled = sampleOn(s1, s2); 13 | flyd.map(function(v) { 14 | result.push(v); 15 | }, sampled); 16 | s2(1); 17 | s1(1)(2)(3); 18 | s2(3)(4)(6); 19 | s1(5)(3); 20 | assert.deepEqual(result, [1, 1, 1, 6, 6]); 21 | }); 22 | it('has not value until value flows on trigger stream', function() { 23 | var result = []; 24 | var s1 = stream(); 25 | var s2 = stream(1); 26 | var sampled = sampleOn(s1, s2); 27 | flyd.map(function(v) { 28 | result.push(v); 29 | }, sampled); 30 | s2(1); 31 | s1(1)(2)(3); 32 | s2(3)(4)(6); 33 | s1(5)(3); 34 | assert.deepEqual(result, [1, 1, 1, 6, 6]); 35 | }); 36 | }); 37 | -------------------------------------------------------------------------------- /module/scanmerge/README.md: -------------------------------------------------------------------------------- 1 | # flyd-scanmerge 2 | Flyd module for conveniently merging and scanning several streams into one. 3 | 4 | scanmerge takes an array of pairs of streams and scan functions. It merges all those streams using the given functions into a single stream. 5 | 6 | A common use case is to take many UI event streams, pair each one with an updater function, so they all combine into a single UI state object. 7 | 8 | __Graph__ 9 | 10 | ``` 11 | n1: {2---3----2---3} 12 | n2: {--2---2----1--} 13 | scanMerge([[n1, add], [n2, sub]], 0): {2-0-3-1--3-2-5} 14 | ``` 15 | 16 | __Signature__ 17 | 18 | `[[Stream b, (a, b -> a)]] -> a -> Stream a` 19 | 20 | __Usage__ 21 | 22 | ```javascript 23 | const scanMerge = require('flyd/module/scanmerge') 24 | const add = flyd.stream(0) 25 | const sub = flyd.stream(0) 26 | const mult = flyd.stream(1) 27 | const res = scanMerge([ 28 | [add, function(sum, n) { return sum + n; }] 29 | , [sub, function(sum, n) { return sum - n; }] 30 | , [mult, function(sum, n) { return sum * n; }] 31 | ], 0) 32 | add(5); sub(8); sub(4); add(12); mult(3) 33 | res() // 15 34 | ``` 35 | 36 | ```javascript 37 | const append = flyd.stream() 38 | const remove = flyd.stream() 39 | const items = scanMerge([ 40 | [append, (list, elem) => list.concat(elem)], 41 | , [remove, (list, item) => list.filter(elm => elm !== item)] 42 | ], []) 43 | append(1)(2)(3)(4)(5) 44 | remove(3) 45 | items() // [1,2,4,5] 46 | ``` 47 | -------------------------------------------------------------------------------- /module/scanmerge/index.js: -------------------------------------------------------------------------------- 1 | var flyd = require('../../lib'); 2 | 3 | module.exports = flyd.curryN(2, function(pairs, acc) { 4 | var streams = pairs.map(function(p) { return p[0]; }); 5 | // use immediate because we want each stream to fire regardless of if the others have ever had a value 6 | return flyd.immediate(flyd.combine(function() { 7 | var changed = arguments[arguments.length - 1]; 8 | // var self = arguments[arguments.length - 2]; 9 | // because of atomic updates we can have more than one changed 10 | // meaning more than one function should be fired, lets do it in order so its predictable 11 | for (var p = 0; p < pairs.length; p++) { 12 | // because changed is an array of references it doesn't matter if we pull the first match in the case of multiple matches 13 | var idx = changed.indexOf(pairs[p][0]); 14 | if (idx !== -1) { 15 | acc = pairs[p][1](acc, changed[idx]()); 16 | } 17 | } 18 | return acc; 19 | }, streams)); 20 | }); 21 | -------------------------------------------------------------------------------- /module/scanmerge/test/index.js: -------------------------------------------------------------------------------- 1 | var assert = require('assert'); 2 | var flyd = require('../../../lib'); 3 | var stream = flyd.stream; 4 | 5 | var scanMerge = require('../index'); 6 | 7 | describe('scanMerge', function() { 8 | it('scans and merges multiple streams', function() { 9 | var add = stream(); 10 | var sub = stream(); 11 | var sum = scanMerge([ 12 | [add, function(sum, n) { return sum + n; }], 13 | [sub, function(sum, n) { return sum - n; }] 14 | ], 0); 15 | add(5); sub(8); sub(4); add(12); 16 | assert.equal(sum(), 5); 17 | }); 18 | it('initially has initial value', function() { 19 | var add = stream(2); 20 | var sub = stream(4); 21 | var sum = scanMerge([ 22 | [add, function(sum, n) { return sum + n; }], 23 | [sub, function(sum, n) { return sum - n; }] 24 | ], 0); 25 | assert.equal(sum(), 0); 26 | }); 27 | it('handles second example', function() { 28 | var addItem = flyd.stream(); 29 | var rmItem = flyd.stream(); 30 | var items = scanMerge([ 31 | [addItem, function(list, item) { return list.concat([item]); }], 32 | [rmItem, function(list, item) { 33 | return list.filter(function(elm) { return elm !== item; }); 34 | }] 35 | ], []); 36 | addItem(1)(2)(3)(4)(5); 37 | rmItem(3); 38 | assert.deepEqual(items(), [1, 2, 4, 5]); 39 | }); 40 | }); 41 | -------------------------------------------------------------------------------- /module/switchlatest/README.md: -------------------------------------------------------------------------------- 1 | # flyd-switchlatest 2 | 3 | Flattens a stream of streams. The result stream reflects changes from the 4 | last stream only. 5 | 6 | __Graph__ 7 | 8 | ``` 9 | a: {--.----.----} 10 | {ab} {a-b} 11 | switchLatest(a): {--ab---a-b--} 12 | ``` 13 | 14 | __Signature__ 15 | 16 | `Stream (Stream a) -> Stream b` 17 | 18 | __Usage__ 19 | 20 | ```javascript 21 | const switchLatest = require('flyd/module/switchlatest') 22 | 23 | const chatrooms = flyd.stream() 24 | // For each chatroom on the chatrooms stream, create a stream of chat messages. 25 | // This gives us a series of streams nested within a parent stream. 26 | const messages = flyd.map(createMessageStream, chatrooms) 27 | 28 | // Create a single, unnested stream of chat messages 29 | const currentMessages = switchLatest(messagesStreams) 30 | ``` 31 | 32 | -------------------------------------------------------------------------------- /module/switchlatest/index.js: -------------------------------------------------------------------------------- 1 | var flyd = require('../../lib'); 2 | var takeUntil = require('../takeuntil'); 3 | var drop = require('ramda/src/drop'); 4 | 5 | var dropCurrentValue = flyd.transduce(drop(1)); 6 | 7 | module.exports = function(s) { 8 | return flyd.combine(function(stream$, self) { 9 | var value$ = stream$(); 10 | flyd.on(self, takeUntil(value$, dropCurrentValue(stream$))); 11 | }, [s]); 12 | }; 13 | -------------------------------------------------------------------------------- /module/switchlatest/test/index.js: -------------------------------------------------------------------------------- 1 | var flyd = require('../../../lib'); 2 | var stream = flyd.stream; 3 | var assert = require('assert'); 4 | 5 | var switchLatest = require('../index.js'); 6 | 7 | describe('switchLatest', function() { 8 | it('emits values from first stream in stream', function() { 9 | var result = []; 10 | var source = stream(); 11 | var is = stream(); 12 | var s = switchLatest(source); 13 | flyd.map(function(v) { result.push(v); }, s); 14 | source(is); 15 | is(1)(2)(3); 16 | assert.deepEqual(result, [1, 2, 3]); 17 | }); 18 | it('emits values from first and second stream in stream', function() { 19 | var result = []; 20 | var source = stream(); 21 | var is1 = stream(); 22 | var is2 = stream(); 23 | var s = switchLatest(source); 24 | flyd.map(function(v) { result.push(v); }, s); 25 | source(is1); 26 | is1(1); 27 | source(is2); 28 | is1(-1); 29 | is2(2)(3); 30 | assert.deepEqual(result, [1, 2, 3]); 31 | }); 32 | it('ends when source stream ends', function() { 33 | var result = []; 34 | var source = stream(); 35 | var is = stream(); 36 | var s = switchLatest(source); 37 | flyd.map(function(v) { result.push(v); }, s); 38 | source(is); is(1)(2); 39 | assert.deepEqual(result, [1, 2]); 40 | assert(!source.ended); 41 | source.end(true); 42 | assert.equal(true, source.end()); 43 | }); 44 | }); 45 | -------------------------------------------------------------------------------- /module/takeuntil/README.md: -------------------------------------------------------------------------------- 1 | # flyd-takeuntil 2 | Emit values from a stream until a second stream emits a value. 3 | 4 | __Graph__ 5 | 6 | ``` 7 | a: {---1---2---3---4} 8 | b: {---------x------} 9 | takeUntil(a, b): {---1---2--------} 10 | ``` 11 | 12 | __Signature__ 13 | 14 | `Stream a -> Stream b -> Stream a` 15 | 16 | __Usage__ 17 | 18 | ```javascript 19 | const takeUntil = require('flyd/module/takeuntil') 20 | 21 | const source = flyd.stream() 22 | const end = flyd.stream() 23 | const result = takeUntil(source, end) 24 | 25 | source(1)(2) 26 | result() // 2 27 | source(3) 28 | result() // 3 29 | 30 | end(true) 31 | result() // 3 32 | source(4)(5) 33 | result() // 3 34 | ``` 35 | -------------------------------------------------------------------------------- /module/takeuntil/index.js: -------------------------------------------------------------------------------- 1 | var flyd = require('../../lib'); 2 | 3 | module.exports = flyd.curryN(2, function(src, term) { 4 | return flyd.endsOn(flyd.merge(term, src.end), flyd.combine(function(src, self) { 5 | self(src()); 6 | }, [src])); 7 | }); 8 | -------------------------------------------------------------------------------- /module/takeuntil/test/index.js: -------------------------------------------------------------------------------- 1 | var flyd = require('../../../lib'); 2 | var stream = flyd.stream; 3 | var assert = require('assert'); 4 | 5 | var takeUntil = require('../index'); 6 | 7 | describe('takeUntil', function() { 8 | it('emits values from first stream', function() { 9 | var result = []; 10 | var source = stream(); 11 | var terminator = stream(); 12 | var s = takeUntil(source, terminator); 13 | flyd.map(function(v) { result.push(v); }, s); 14 | source(1)(2)(3); 15 | assert.deepEqual(result, [1, 2, 3]); 16 | }); 17 | it('ends when value emitted from second stream', function() { 18 | var result = []; 19 | var source = stream(); 20 | var terminator = stream(); 21 | var s = takeUntil(source, terminator); 22 | flyd.map(function(v) { result.push(v); }, s); 23 | s(1); 24 | terminator(true); 25 | s(2); 26 | assert.deepEqual(result, [1]); 27 | assert(s.end()); 28 | }); 29 | it('ends if source stream ends', function() { 30 | var result = []; 31 | var source = stream(); 32 | var terminator = stream(); 33 | var s = takeUntil(source, terminator); 34 | flyd.map(function(v) { result.push(v); }, s); 35 | s(1); 36 | source.end(true); 37 | s(2); 38 | assert.deepEqual(result, [1]); 39 | assert(s.end()); 40 | }); 41 | }); 42 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "flyd", 3 | "version": "0.2.8", 4 | "description": "The less is more, modular, functional reactive programming library", 5 | "main": "lib/index.js", 6 | "unpkg": "flyd.min.js", 7 | "directories": { 8 | "example": "examples", 9 | "test": "test" 10 | }, 11 | "dependencies": { 12 | "ramda": "^0.25.0", 13 | "whatwg-fetch": "^3.0.0" 14 | }, 15 | "devDependencies": { 16 | "benchmark": "^1.0.0", 17 | "bluebird": "^2.9.13", 18 | "browserify": "^10.2.4", 19 | "coveralls": "^2.11.2", 20 | "eslint": "^2.7.0", 21 | "istanbul": "^0.3.15", 22 | "mocha": "^2.2.1", 23 | "mocha-lcov-reporter": "0.0.2", 24 | "np": "^2.19.0", 25 | "rollup": "^0.56.2", 26 | "rollup-plugin-commonjs": "^8.3.0", 27 | "rollup-plugin-node-resolve": "^3.0.3", 28 | "rollup-plugin-replace": "^2.0.0", 29 | "rollup-plugin-uglify": "^3.0.0", 30 | "transducers.js": "0.3.x" 31 | }, 32 | "scripts": { 33 | "test-lib": "mocha", 34 | "test": "eslint --fix lib/ test/ module/ && mocha test/*.js module/**/test/*.js", 35 | "docs": "documentation -f md lib/index.js > API.md", 36 | "perf": "./perf/run-benchmarks", 37 | "coverage": "istanbul cover _mocha -- -R spec", 38 | "post-to-coveralls-io": "istanbul cover _mocha --report lcovonly -- -R spec && cat ./coverage/lcov.info | coveralls && rm -rf ./coverage", 39 | "build": "rollup -c rollup.config.dev.js && rollup -c rollup.config.js && node ./build-examples.js", 40 | "release": "np" 41 | }, 42 | "repository": { 43 | "type": "git", 44 | "url": "https://github.com/paldepind/flyd.git" 45 | }, 46 | "keywords": [ 47 | "functional", 48 | "reactive", 49 | "modular", 50 | "library" 51 | ], 52 | "author": "Simon Friis Vindum", 53 | "license": "MIT", 54 | "bugs": { 55 | "url": "https://github.com/paldepind/flyd/issues" 56 | }, 57 | "homepage": "https://github.com/paldepind/flyd", 58 | "testling": { 59 | "harness": "mocha", 60 | "files": "test/*.js", 61 | "browsers": [ 62 | "ie/8..latest", 63 | "firefox/16..latest", 64 | "firefox/nightly", 65 | "chrome/22..latest", 66 | "chrome/canary", 67 | "opera/12..latest", 68 | "opera/next", 69 | "safari/5.1..latest", 70 | "ipad/6.0..latest", 71 | "iphone/6.0..latest", 72 | "android-browser/4.2..latest" 73 | ] 74 | } 75 | } 76 | -------------------------------------------------------------------------------- /perf/perf.js: -------------------------------------------------------------------------------- 1 | var Benchmark = require('benchmark'); 2 | 3 | 4 | // Attach benchmarks' dependencies to the global 5 | // scope, since the current version of benchmark.js 6 | // doesn't allow for anything simpler 7 | global.stream = require('../flyd').stream; 8 | global.oldStream = require('../flyd-old').stream; 9 | 10 | // ************************************************ 11 | // Util functions 12 | 13 | var suites = []; 14 | 15 | function getHz(bench) { // hz adjusted for margin of error 16 | var result = 1 / (bench.stats.mean + bench.stats.moe); 17 | return isFinite(result) ? result : 0; 18 | } 19 | 20 | function printFastest(suite) { 21 | var formatNumber = Benchmark.formatNumber, 22 | fastest = suite.filter('fastest'), 23 | fastestHz = getHz(fastest[0]), 24 | slowest = suite.filter('slowest'), 25 | slowestHz = getHz(slowest[0]), 26 | aHz = getHz(suite[0]), 27 | bHz = getHz(suite[1]); 28 | if (fastest.length > 1) { 29 | console.log('It\'s too close to call.'); 30 | aHz = bHz = slowestHz; 31 | } else { 32 | var percent = ((fastestHz / slowestHz) - 1) * 100; 33 | console.log(' ' + fastest[0].name + ' is ' + 34 | formatNumber(percent < 1 ? percent.toFixed(2) : Math.round(percent)) + 35 | '% faster.'); 36 | } 37 | } 38 | 39 | Benchmark.Suite.options.onStart = function() { 40 | console.log('\n' + this.name + ':'); 41 | }; 42 | 43 | Benchmark.Suite.options.onCycle = function(event) { 44 | console.log(' ' + event.target); 45 | }; 46 | 47 | Benchmark.Suite.options.onComplete = function() { 48 | printFastest(this); 49 | suites.shift(); 50 | if (suites.length) { 51 | suites[0].run({async: true}); 52 | } 53 | }; 54 | 55 | // ************************************************ 56 | // Benchmarks! 57 | 58 | suites.push(Benchmark.Suite('dynamic dependencies').add('New', { 59 | setup: function() { 60 | var s = stream(); 61 | stream(function() { 62 | return s(); 63 | }); 64 | }, 65 | fn: function() { 66 | s(12); 67 | }, 68 | }).add('Old', { 69 | setup: function() { 70 | var s = oldStream(); 71 | oldStream(function() { 72 | return s(); 73 | }); 74 | }, 75 | fn: function() { 76 | s(12); 77 | }, 78 | })); 79 | 80 | suites.push(Benchmark.Suite('static dependencies').add('New', { 81 | setup: function() { 82 | var s = stream(); 83 | stream([s], function() { 84 | return s(); 85 | }); 86 | }, 87 | fn: function() { 88 | s(12); 89 | }, 90 | }).add('Old', { 91 | setup: function() { 92 | var s = oldStream(); 93 | oldStream([s], function() { 94 | return s(); 95 | }); 96 | }, 97 | fn: function() { 98 | s(12); 99 | }, 100 | })); 101 | 102 | suites.push(Benchmark.Suite('map').add('First', { 103 | setup: function() { 104 | function f(x) { return x; } 105 | var s1 = stream(); 106 | var s2 = s1.map(f); 107 | var s3 = s2.map(f); 108 | var s4 = s3.map(f); 109 | var s5 = s4.map(f); 110 | }, 111 | fn: function() { 112 | s1(12); 113 | }, 114 | }).add('Second', { 115 | setup: function() { 116 | function f(x) { return x; } 117 | var s1 = stream(); 118 | var s2 = s1.map(f); 119 | var s3 = s2.map(f); 120 | var s4 = s3.map(f); 121 | var s5 = s4.map(f); 122 | }, 123 | fn: function() { 124 | s1(12); 125 | }, 126 | })); 127 | 128 | suites.push(Benchmark.Suite('dynamic dependency graph').add('New', { 129 | setup: function() { 130 | var s1 = stream(); 131 | var s2 = stream(function() { 132 | s1(); s1(); 133 | }); 134 | var s3 = stream(function() { 135 | s1(); s2(); s1(); 136 | }); 137 | var s4 = stream(function() { 138 | s1(); s2(); s3(); s1(); s3(); 139 | }); 140 | stream(function() { 141 | s3(); s2(); s1(); s3(); s4(); 142 | }); 143 | }, 144 | fn: function() { 145 | s1(12); 146 | }, 147 | }).add('Old', { 148 | setup: function() { 149 | var s1 = oldStream(); 150 | var s2 = oldStream(function() { 151 | s1(); s1(); 152 | }); 153 | var s3 = oldStream(function() { 154 | s1(); s2(); s1(); 155 | }); 156 | var s4 = oldStream(function() { 157 | s1(); s2(); s3(); s1(); s3(); 158 | }); 159 | oldStream(function() { 160 | s3(); s2(); s1(); s3(); s4(); 161 | }); 162 | }, 163 | fn: function() { 164 | s1(12); 165 | }, 166 | })); 167 | 168 | suites[0].run({ 'async': true }); 169 | -------------------------------------------------------------------------------- /perf/run-benchmarks: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | ## Retrieve older version of the source, to be compared 4 | ## in performance against the current version. 5 | 6 | DIRECTORY_CONTAINING_THIS_SCRIPT=$( cd $(dirname $0) ; pwd -P ) 7 | REPOSITORY_ROOT="$DIRECTORY_CONTAINING_THIS_SCRIPT/.." 8 | 9 | 10 | SOURCE_FILENAME="flyd" 11 | SOURCE_FILENAME_WITH_EXTENSION="$SOURCE_FILENAME.js" 12 | 13 | OLD_VERSION_FILENAME="$SOURCE_FILENAME-old" 14 | OLD_VERSION_FILENAME_WITH_EXTENSION="$OLD_VERSION_FILENAME.js" 15 | 16 | 17 | # The first passed argument is the number of commits (in the 18 | # current branch) you want to 'undo' in order to get 19 | # to the desired old version. 20 | # It defaults to 1. 21 | if [ "$1" -eq "$1" ] 2>/dev/null && [ "$1" -gt "0" ] 2>/dev/null 22 | then 23 | how_many_commits_back="$1" 24 | else 25 | how_many_commits_back="1" 26 | fi 27 | 28 | 29 | # Leave a copy of the old version's source 30 | # in the root of the repository 31 | 32 | cd "$REPOSITORY_ROOT" 33 | 34 | git checkout HEAD~$how_many_commits_back -- $SOURCE_FILENAME_WITH_EXTENSION 35 | 36 | cp $SOURCE_FILENAME_WITH_EXTENSION $OLD_VERSION_FILENAME_WITH_EXTENSION 37 | 38 | git checkout HEAD -- $SOURCE_FILENAME_WITH_EXTENSION 39 | 40 | 41 | 42 | ## Run the benchmarks 43 | cd "$DIRECTORY_CONTAINING_THIS_SCRIPT" 44 | 45 | node perf.js 46 | 47 | 48 | 49 | ## Remove the old version of the source 50 | cd "$REPOSITORY_ROOT" 51 | 52 | rm $OLD_VERSION_FILENAME_WITH_EXTENSION 53 | -------------------------------------------------------------------------------- /rollup.config.dev.js: -------------------------------------------------------------------------------- 1 | import resolve from 'rollup-plugin-node-resolve'; 2 | import commonjs from 'rollup-plugin-commonjs'; 3 | import replace from 'rollup-plugin-replace'; 4 | 5 | export default [{ 6 | input: './lib/index.js', 7 | output: { 8 | file: './flyd.js', 9 | name: 'flyd', 10 | format: 'umd' 11 | }, 12 | plugins: [ 13 | resolve(), 14 | commonjs() 15 | ] 16 | }, { 17 | input: './lib/index.js', 18 | output: { 19 | file: './es/index.js', 20 | format: 'es' 21 | }, 22 | external: ['ramda/src/curryN'], 23 | plugins: [ 24 | commonjs(), 25 | // below can be optimized after the rollup issue resolved 26 | // https://github.com/rollup/rollup/issues/2491 27 | replace({ 28 | 'ramda/src/curryN': 'ramda/es/curryN' 29 | }) 30 | ] 31 | }]; 32 | -------------------------------------------------------------------------------- /rollup.config.js: -------------------------------------------------------------------------------- 1 | import resolve from 'rollup-plugin-node-resolve'; 2 | import commonjs from 'rollup-plugin-commonjs'; 3 | import uglify from 'rollup-plugin-uglify'; 4 | 5 | export default { 6 | input: './lib/index.js', 7 | output: { 8 | file: './flyd.min.js', 9 | name: 'flyd', 10 | format: 'umd' 11 | }, 12 | plugins: [ 13 | resolve(), 14 | commonjs(), 15 | uglify() 16 | ] 17 | }; --------------------------------------------------------------------------------