urx.cjs.development.js 25 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025
  1. 'use strict';
  2. Object.defineProperty(exports, '__esModule', { value: true });
  3. var PUBLISH = 0;
  4. var SUBSCRIBE = 1;
  5. var RESET = 2;
  6. var VALUE = 4;
  7. /**
  8. * Utils includes
  9. * - a handful of functional utilities inspired by or taken from the [Ramda library](https://ramdajs.com/);
  10. * - TypeScript crutches - the [[tup]] function.
  11. *
  12. * Use these for your convenience - they are here so that urx is zero-dependency package.
  13. *
  14. * @packageDocumentation
  15. */
  16. /**
  17. * Performs left to right composition of two functions.
  18. */
  19. function compose(a, b) {
  20. return function (arg) {
  21. return a(b(arg));
  22. };
  23. }
  24. /**
  25. * Takes a value and applies a function to it.
  26. */
  27. function thrush(arg, proc) {
  28. return proc(arg);
  29. }
  30. /**
  31. * Takes a 2 argument function and partially applies the first argument.
  32. */
  33. function curry2to1(proc, arg1) {
  34. return function (arg2) {
  35. return proc(arg1, arg2);
  36. };
  37. }
  38. /**
  39. * Takes a 1 argument function and returns a function which when called, executes it with the provided argument.
  40. */
  41. function curry1to0(proc, arg) {
  42. return function () {
  43. return proc(arg);
  44. };
  45. }
  46. /**
  47. * Returns a function which extracts the property from from the passed object.
  48. */
  49. function prop(property) {
  50. return function (object) {
  51. return object[property];
  52. };
  53. }
  54. /**
  55. * Calls callback with the first argument, and returns it.
  56. */
  57. function tap(arg, proc) {
  58. proc(arg);
  59. return arg;
  60. }
  61. /**
  62. * Utility function to help typescript figure out that what we pass is a tuple and not a generic array.
  63. * Taken from (this StackOverflow tread)[https://stackoverflow.com/questions/49729550/implicitly-create-a-tuple-in-typescript/52445008#52445008]
  64. */
  65. function tup() {
  66. for (var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++) {
  67. args[_key] = arguments[_key];
  68. }
  69. return args;
  70. }
  71. /**
  72. * Calls the passed function.
  73. */
  74. function call(proc) {
  75. proc();
  76. }
  77. /**
  78. * returns a function which when called always returns the passed value
  79. */
  80. function always(value) {
  81. return function () {
  82. return value;
  83. };
  84. }
  85. /**
  86. * returns a function which calls all passed functions in the passed order.
  87. * joinProc does not pass arguments or collect return values.
  88. */
  89. function joinProc() {
  90. for (var _len2 = arguments.length, procs = new Array(_len2), _key2 = 0; _key2 < _len2; _key2++) {
  91. procs[_key2] = arguments[_key2];
  92. }
  93. return function () {
  94. procs.map(call);
  95. };
  96. }
  97. function noop() {}
  98. /**
  99. * urx Actions operate on streams - `publish` publishes data in a stream, and `subscribe` attaches a subscription to a stream.
  100. * @packageDocumentation
  101. */
  102. /**
  103. * Subscribes the specified [[Subscription]] to the updates from the Emitter.
  104. * The emitter calls the subscription with the new data each time new data is published into it.
  105. *
  106. * ```ts
  107. * const foo = stream<number>();
  108. * subscribe(foo, (value) => console.log(value));
  109. * ```
  110. *
  111. * @returns an [[Unsubscribe]] handle - calling it will unbind the subscription from the emitter.
  112. *```ts
  113. * const foo = stream<number>();
  114. * const unsub = subscribe(foo, (value) => console.log(value));
  115. * unsub();
  116. *```
  117. */
  118. function subscribe(emitter, subscription) {
  119. return emitter(SUBSCRIBE, subscription);
  120. }
  121. /**
  122. * Publishes the value into the passed [[Publisher]].
  123. *
  124. * ```ts
  125. * const foo = stream<number>();
  126. * publish(foo, 42);
  127. * ```
  128. */
  129. function publish(publisher, value) {
  130. publisher(PUBLISH, value);
  131. }
  132. /**
  133. * Clears all subscriptions from the [[Emitter]].
  134. * ```ts
  135. * const foo = stream<number>();
  136. * subscribe(foo, (value) => console.log(value));
  137. * reset(foo);
  138. * publish(foo, 42);
  139. * ```
  140. */
  141. function reset(emitter) {
  142. emitter(RESET);
  143. }
  144. /**
  145. * Extracts the current value from a stateful stream. Use it only as an escape hatch, as it violates the concept of reactive programming.
  146. * ```ts
  147. * const foo = statefulStream(42);
  148. * console.log(getValue(foo));
  149. * ```
  150. */
  151. function getValue(depot) {
  152. return depot(VALUE);
  153. }
  154. /**
  155. * Connects two streams - any value emitted from the emitter will be published in the publisher.
  156. * ```ts
  157. * const foo = stream<number>();
  158. * const bar = stream<number>();
  159. * subscribe(bar, (value) => console.log(`Bar emitted ${value}`));
  160. *
  161. * connect(foo, bar);
  162. * publish(foo);
  163. * ```
  164. * @returns an [[Unsubscribe]] handle which will disconnect the two streams.
  165. */
  166. function connect(emitter, publisher) {
  167. return subscribe(emitter, curry2to1(publisher, PUBLISH));
  168. }
  169. /**
  170. * Executes the passed subscription at most once, for the next emit from the emitter.
  171. * ```ts
  172. * const foo = stream<number>()
  173. * handleNext(foo, value => console.log(value)) // called once, with 42
  174. * publish(foo, 42)
  175. * publish(foo, 43)
  176. * ```
  177. * @returns an [[Unsubscribe]] handle to unbind the subscription if necessary.
  178. */
  179. function handleNext(emitter, subscription) {
  180. var unsub = emitter(SUBSCRIBE, function (value) {
  181. unsub();
  182. subscription(value);
  183. });
  184. return unsub;
  185. }
  186. /**
  187. * Streams are the basic building blocks of a reactive system. Think of them as the system permanent "data tubes".
  188. *
  189. * A stream acts as both an [[Emitter]] and [[Publisher]]. Each stream can have multiple {@link Subscription | Subscriptions}.
  190. *
  191. * urx streams are either **stateless** or **stateful**.
  192. * Stateless streams emit data to existing subscriptions when published, without keeping track of it.
  193. * Stateful streams remember the last published value and immediately publish it to new subscriptions.
  194. *
  195. * ```ts
  196. * import { stream, statefulStream, publish, subscribe } from "@virtuoso.dev/urx";
  197. *
  198. * // foo is a stateless stream
  199. * const foo = stream<number>();
  200. *
  201. * publish(foo, 42);
  202. * // this subsription will not be called...
  203. * subscribe(foo, (value) => console.log(value));
  204. * // it will only catch published values after it
  205. * publish(foo, 43);
  206. *
  207. * // stateful streams always start with an initial value
  208. * const bar = statefulStream(42);
  209. *
  210. * // subscribing to a stateful stream
  211. * // immediately calls the subscription with the current value
  212. * subscribe(bar, (value) => console.log(value));
  213. *
  214. * // subsequent publishing works just like stateless streams
  215. * publish(bar, 43);
  216. * ```
  217. * @packageDocumentation
  218. */
  219. /**
  220. * Constructs a new stateless stream.
  221. * ```ts
  222. * const foo = stream<number>();
  223. * ```
  224. * @typeParam T the type of values to publish in the stream.
  225. * @returns a [[Stream]]
  226. */
  227. function stream() {
  228. var subscriptions = [];
  229. return function (action, arg) {
  230. switch (action) {
  231. case RESET:
  232. subscriptions.splice(0, subscriptions.length);
  233. return;
  234. case SUBSCRIBE:
  235. subscriptions.push(arg);
  236. return function () {
  237. var indexOf = subscriptions.indexOf(arg);
  238. if (indexOf > -1) {
  239. subscriptions.splice(indexOf, 1);
  240. }
  241. };
  242. case PUBLISH:
  243. subscriptions.slice().forEach(function (subscription) {
  244. subscription(arg);
  245. });
  246. return;
  247. default:
  248. throw new Error("unrecognized action " + action);
  249. }
  250. };
  251. }
  252. /**
  253. * Constructs a new stateful stream.
  254. * ```ts
  255. * const foo = statefulStream(42);
  256. * ```
  257. * @param initial the initial value in the stream.
  258. * @typeParam T the type of values to publish in the stream. If omitted, the function infers it from the initial value.
  259. * @returns a [[StatefulStream]]
  260. */
  261. function statefulStream(initial) {
  262. var value = initial;
  263. var innerSubject = stream();
  264. return function (action, arg) {
  265. switch (action) {
  266. case SUBSCRIBE:
  267. var subscription = arg;
  268. subscription(value);
  269. break;
  270. case PUBLISH:
  271. value = arg;
  272. break;
  273. case VALUE:
  274. return value;
  275. }
  276. return innerSubject(action, arg);
  277. };
  278. }
  279. /**
  280. * Event handlers are special emitters which can have **at most one active subscription**.
  281. * Subscribing to an event handler unsubscribes the previous subscription, if present.
  282. * ```ts
  283. * const foo = stream<number>();
  284. * const fooEvent = eventHandler(foo);
  285. *
  286. * // will be called once with 42
  287. * subscribe(fooEvent, (value) => console.log(`Sub 1 ${value}`));
  288. * publish(foo, 42);
  289. *
  290. * // unsubscribes sub 1
  291. * subscribe(fooEvent, (value) => console.log(`Sub 2 ${value}`));
  292. * publish(foo, 43);
  293. * ```
  294. * @param emitter the source emitter.
  295. * @returns the single-subscription emitter.
  296. */
  297. function eventHandler(emitter) {
  298. var unsub;
  299. var currentSubscription;
  300. var cleanup = function cleanup() {
  301. return unsub && unsub();
  302. };
  303. return function (action, subscription) {
  304. switch (action) {
  305. case SUBSCRIBE:
  306. if (subscription) {
  307. if (currentSubscription === subscription) {
  308. return;
  309. }
  310. cleanup();
  311. currentSubscription = subscription;
  312. unsub = subscribe(emitter, subscription);
  313. return unsub;
  314. } else {
  315. cleanup();
  316. return noop;
  317. }
  318. case RESET:
  319. cleanup();
  320. currentSubscription = null;
  321. return;
  322. default:
  323. throw new Error("unrecognized action " + action);
  324. }
  325. };
  326. }
  327. /**
  328. * Creates and connects a "junction" stream to the specified emitter. Often used with [[pipe]], to avoid the multiple evaluation of operator sets.
  329. *
  330. * ```ts
  331. * const foo = stream<number>();
  332. *
  333. * const fooX2 = pipe(
  334. * foo,
  335. * map((value) => {
  336. * console.log(`multiplying ${value}`);
  337. * return value * 2;
  338. * })
  339. * );
  340. *
  341. * subscribe(fooX2, (value) => console.log(value));
  342. * subscribe(fooX2, (value) => console.log(value));
  343. *
  344. * publish(foo, 42); // executes the map operator twice for each subscription.
  345. *
  346. * const sharedFooX2 = streamFromEmitter(pipe(
  347. * foo,
  348. * map((value) => {
  349. * console.log(`shared multiplying ${value}`);
  350. * return value * 2;
  351. * })
  352. * ));
  353. *
  354. * subscribe(sharedFooX2, (value) => console.log(value));
  355. * subscribe(sharedFooX2, (value) => console.log(value));
  356. *
  357. * publish(foo, 42);
  358. *```
  359. * @returns the resulting stream.
  360. */
  361. function streamFromEmitter(emitter) {
  362. return tap(stream(), function (stream) {
  363. return connect(emitter, stream);
  364. });
  365. }
  366. /**
  367. * Creates and connects a "junction" stateful stream to the specified emitter. Often used with [[pipe]], to avoid the multiple evaluation of operator sets.
  368. *
  369. * ```ts
  370. * const foo = stream<number>();
  371. *
  372. * const fooX2 = pipe(
  373. * foo,
  374. * map((value) => {
  375. * console.log(`multiplying ${value}`);
  376. * return value * 2;
  377. * })
  378. * );
  379. *
  380. * subscribe(fooX2, (value) => console.log(value));
  381. * subscribe(fooX2, (value) => console.log(value));
  382. *
  383. * publish(foo, 42); // executes the map operator twice for each subscription.
  384. *
  385. * const sharedFooX2 = statefulStreamFromEmitter(pipe(
  386. * foo,
  387. * map((value) => {
  388. * console.log(`shared multiplying ${value}`);
  389. * return value * 2;
  390. * })
  391. * ), 42);
  392. *
  393. * subscribe(sharedFooX2, (value) => console.log(value));
  394. * subscribe(sharedFooX2, (value) => console.log(value));
  395. *
  396. * publish(foo, 42);
  397. *```
  398. * @param initial the initial value in the stream.
  399. * @returns the resulting stateful stream.
  400. */
  401. function statefulStreamFromEmitter(emitter, initial) {
  402. return tap(statefulStream(initial), function (stream) {
  403. return connect(emitter, stream);
  404. });
  405. }
  406. /**
  407. *
  408. * Stream values can be transformed and controlled by {@link pipe | **piping**} through **operators**.
  409. * urx includes several operators like [[map]], [[filter]], [[scan]], and [[throttleTime]].
  410. * The [[withLatestFrom]] operator allows the combination of values from other streams.
  411. *
  412. * ```ts
  413. * const foo = stream<number>()
  414. *
  415. * // create an emitter that first adds 2 to the passed value, then multiplies it by * 2
  416. * const bar = pipe(foo, map(value => value + 2), map(value => value * 2))
  417. * subscribe(bar, value => console.log(value))
  418. * publish(foo, 2) // outputs 8
  419. * ```
  420. *
  421. * ### Implementing Custom Operators
  422. * To implement your own operators, implement the [[Operator]] interface.
  423. * @packageDocumentation
  424. */
  425. /** @internal */
  426. function combineOperators() {
  427. for (var _len = arguments.length, operators = new Array(_len), _key = 0; _key < _len; _key++) {
  428. operators[_key] = arguments[_key];
  429. }
  430. return function (subscriber) {
  431. return operators.reduceRight(thrush, subscriber);
  432. };
  433. }
  434. function pipe(source) {
  435. for (var _len2 = arguments.length, operators = new Array(_len2 > 1 ? _len2 - 1 : 0), _key2 = 1; _key2 < _len2; _key2++) {
  436. operators[_key2 - 1] = arguments[_key2];
  437. }
  438. // prettier-ignore
  439. var project = combineOperators.apply(void 0, operators);
  440. return function (action, subscription) {
  441. switch (action) {
  442. case SUBSCRIBE:
  443. return subscribe(source, project(subscription));
  444. case RESET:
  445. reset(source);
  446. return;
  447. default:
  448. throw new Error("unrecognized action " + action);
  449. }
  450. };
  451. }
  452. /**
  453. * The default [[Comparator]] for [[distinctUntilChanged]] and [[duc]].
  454. */
  455. function defaultComparator(previous, next) {
  456. return previous === next;
  457. }
  458. /**
  459. * Filters out identical values. Pass an optional [[Comparator]] if you need to filter non-primitive values.
  460. * ```ts
  461. * const foo = stream<number>()
  462. *
  463. * subscribe(
  464. * pipe(foo, distinctUntilChanged()),
  465. * console.log
  466. * ) // will be called only once
  467. *
  468. * publish(foo, 42)
  469. * publish(foo, 42)
  470. * ```
  471. */
  472. function distinctUntilChanged(comparator) {
  473. if (comparator === void 0) {
  474. comparator = defaultComparator;
  475. }
  476. var current;
  477. return function (done) {
  478. return function (next) {
  479. if (!comparator(current, next)) {
  480. current = next;
  481. done(next);
  482. }
  483. };
  484. };
  485. }
  486. /**
  487. * Filters out values for which the predicator does not return `true`-ish.
  488. * ```ts
  489. * const foo = stream<number>()
  490. *
  491. * subscribe(
  492. * pipe(foo, filter(value => value % 2 === 0)),
  493. * console.log
  494. * ) // will be called only with even values
  495. *
  496. * publish(foo, 2)
  497. * publish(foo, 3)
  498. * publish(foo, 4)
  499. * publish(foo, 5)
  500. * ```
  501. */
  502. function filter(predicate) {
  503. return function (done) {
  504. return function (value) {
  505. predicate(value) && done(value);
  506. };
  507. };
  508. }
  509. /**
  510. * Maps values using the provided project function.
  511. * ```ts
  512. * const foo = stream<number>()
  513. *
  514. * subscribe(
  515. * pipe(foo, map(value => value * 2)),
  516. * console.log
  517. * ) // 4, 6
  518. *
  519. * publish(foo, 2)
  520. * publish(foo, 3)
  521. * ```
  522. */
  523. function map(project) {
  524. return function (done) {
  525. return compose(done, project);
  526. };
  527. }
  528. /**
  529. * Maps values to the hard-coded value.
  530. * ```ts
  531. * const foo = stream<number>()
  532. *
  533. * subscribe(
  534. * pipe(foo, mapTo(3)),
  535. * console.log
  536. * ) // 3, 3
  537. *
  538. * publish(foo, 1)
  539. * publish(foo, 2)
  540. * ```
  541. */
  542. function mapTo(value) {
  543. return function (done) {
  544. return function () {
  545. return done(value);
  546. };
  547. };
  548. }
  549. /**
  550. * Works like Array#reduce.
  551. * Applies an accumulator function on the emitter, and outputs intermediate result. Starts with the initial value.
  552. * ```ts
  553. * const foo = stream<number>()
  554. *
  555. * subscribe(
  556. * pipe(foo, scan((acc, value) => acc + value, 2),
  557. * console.log
  558. * ) // 3, 5
  559. *
  560. * publish(foo, 1)
  561. * publish(foo, 2)
  562. * ```
  563. */
  564. function scan(scanner, initial) {
  565. return function (done) {
  566. return function (value) {
  567. return done(initial = scanner(initial, value));
  568. };
  569. };
  570. }
  571. /**
  572. * Skips the specified amount of values from the emitter.
  573. * ```ts
  574. * const foo = stream<number>()
  575. *
  576. * subscribe(
  577. * pipe(foo, skip(2)),
  578. * console.log
  579. * ) // 3, 4
  580. *
  581. * publish(foo, 1) // skipped
  582. * publish(foo, 2) // skipped
  583. * publish(foo, 3)
  584. * publish(foo, 4)
  585. * ```
  586. */
  587. function skip(times) {
  588. return function (done) {
  589. return function (value) {
  590. times > 0 ? times-- : done(value);
  591. };
  592. };
  593. }
  594. /**
  595. * Throttles flowing values at the provided interval in milliseconds.
  596. * [Throttle VS Debounce in SO](https://stackoverflow.com/questions/25991367/difference-between-throttling-and-debouncing-a-function).
  597. *
  598. * ```ts
  599. * const foo = stream<number>()
  600. * publish(foo, 1)
  601. *
  602. * setTimeout(() => publish(foo, 2), 20)
  603. * setTimeout(() => publish(foo, 3), 20)
  604. *
  605. * subscribe(pipe(foo, throttleTime(50)), val => {
  606. * console.log(value); // 3
  607. * })
  608. * ```
  609. */
  610. function throttleTime(interval) {
  611. var currentValue;
  612. var timeout;
  613. return function (done) {
  614. return function (value) {
  615. currentValue = value;
  616. if (timeout) {
  617. return;
  618. }
  619. timeout = setTimeout(function () {
  620. timeout = undefined;
  621. done(currentValue);
  622. }, interval);
  623. };
  624. };
  625. }
  626. /**
  627. * Debounces flowing values at the provided interval in milliseconds.
  628. * [Throttle VS Debounce in SO](https://stackoverflow.com/questions/25991367/difference-between-throttling-and-debouncing-a-function).
  629. *
  630. * ```ts
  631. * const foo = stream<number>()
  632. * publish(foo, 1)
  633. *
  634. * setTimeout(() => publish(foo, 2), 20)
  635. * setTimeout(() => publish(foo, 3), 20)
  636. *
  637. * subscribe(pipe(foo, debounceTime(50)), val => {
  638. * console.log(value); // 3
  639. * })
  640. * ```
  641. */
  642. function debounceTime(interval) {
  643. var currentValue;
  644. var timeout;
  645. return function (done) {
  646. return function (value) {
  647. currentValue = value;
  648. if (timeout) {
  649. clearTimeout(timeout);
  650. }
  651. timeout = setTimeout(function () {
  652. done(currentValue);
  653. }, interval);
  654. };
  655. };
  656. }
  657. function withLatestFrom() {
  658. for (var _len3 = arguments.length, sources = new Array(_len3), _key3 = 0; _key3 < _len3; _key3++) {
  659. sources[_key3] = arguments[_key3];
  660. }
  661. var values = new Array(sources.length);
  662. var called = 0;
  663. var pendingCall = null;
  664. var allCalled = Math.pow(2, sources.length) - 1;
  665. sources.forEach(function (source, index) {
  666. var bit = Math.pow(2, index);
  667. subscribe(source, function (value) {
  668. var prevCalled = called;
  669. called = called | bit;
  670. values[index] = value;
  671. if (prevCalled !== allCalled && called === allCalled && pendingCall) {
  672. pendingCall();
  673. pendingCall = null;
  674. }
  675. });
  676. });
  677. return function (done) {
  678. return function (value) {
  679. var call = function call() {
  680. return done([value].concat(values));
  681. };
  682. if (called === allCalled) {
  683. call();
  684. } else {
  685. pendingCall = call;
  686. }
  687. };
  688. };
  689. }
  690. /**
  691. * Transformers change and combine streams, similar to operators.
  692. * urx comes with two combinators - [[combineLatest]] and [[merge]], and one convenience filter - [[duc]].
  693. *
  694. * @packageDocumentation
  695. */
  696. /**
  697. * Merges one or more emitters from the same type into a new Emitter which emits values from any of the source emitters.
  698. * ```ts
  699. * const foo = stream<number>()
  700. * const bar = stream<number>()
  701. *
  702. * subscribe(merge(foo, bar), (value) => console.log(value)) // 42, 43
  703. *
  704. * publish(foo, 42)
  705. * publish(bar, 43)
  706. * ```
  707. */
  708. function merge() {
  709. for (var _len = arguments.length, sources = new Array(_len), _key = 0; _key < _len; _key++) {
  710. sources[_key] = arguments[_key];
  711. }
  712. return function (action, subscription) {
  713. switch (action) {
  714. case SUBSCRIBE:
  715. return joinProc.apply(void 0, sources.map(function (source) {
  716. return subscribe(source, subscription);
  717. }));
  718. case RESET:
  719. // do nothing, we are stateless
  720. return;
  721. default:
  722. throw new Error("unrecognized action " + action);
  723. }
  724. };
  725. }
  726. /**
  727. * A convenience wrapper that emits only the distinct values from the passed Emitter. Wraps [[pipe]] and [[distinctUntilChanged]].
  728. *
  729. * ```ts
  730. * const foo = stream<number>()
  731. *
  732. * // this line...
  733. * const a = duc(foo)
  734. *
  735. * // is equivalent to this
  736. * const b = pipe(distinctUntilChanged(foo))
  737. * ```
  738. *
  739. * @param source The source emitter.
  740. * @param comparator optional custom comparison function for the two values.
  741. *
  742. * @typeParam T the type of the value emitted by the source.
  743. *
  744. * @returns the resulting emitter.
  745. */
  746. function duc(source, comparator) {
  747. if (comparator === void 0) {
  748. comparator = defaultComparator;
  749. }
  750. return pipe(source, distinctUntilChanged(comparator));
  751. }
  752. function combineLatest() {
  753. var innerSubject = stream();
  754. for (var _len2 = arguments.length, emitters = new Array(_len2), _key2 = 0; _key2 < _len2; _key2++) {
  755. emitters[_key2] = arguments[_key2];
  756. }
  757. var values = new Array(emitters.length);
  758. var called = 0;
  759. var allCalled = Math.pow(2, emitters.length) - 1;
  760. emitters.forEach(function (source, index) {
  761. var bit = Math.pow(2, index);
  762. subscribe(source, function (value) {
  763. values[index] = value;
  764. called = called | bit;
  765. if (called === allCalled) {
  766. publish(innerSubject, values);
  767. }
  768. });
  769. });
  770. return function (action, subscription) {
  771. switch (action) {
  772. case SUBSCRIBE:
  773. if (called === allCalled) {
  774. subscription(values);
  775. }
  776. return subscribe(innerSubject, subscription);
  777. case RESET:
  778. return reset(innerSubject);
  779. default:
  780. throw new Error("unrecognized action " + action);
  781. }
  782. };
  783. }
  784. /**
  785. * `system` defines a specification of a system - its constructor, dependencies and if it should act as a singleton in a system dependency tree.
  786. * When called, system returns a [[SystemSpec]], which is then initialized along with its dependencies by passing it to [[init]].
  787. *
  788. * ```ts
  789. * @import { subscribe, publish, system, init, tup, connect, map, pipe } from 'urx'
  790. *
  791. * // a simple system with two streams
  792. * const sys1 = system(() => {
  793. * const a = stream<number>()
  794. * const b = stream<number>()
  795. *
  796. * connect(pipe(a, map(value => value * 2)), b)
  797. * return { a, b }
  798. * })
  799. *
  800. * // a second system which depends on the streams from the first one
  801. * const sys2 = system(([ {a, b} ]) => {
  802. * const c = stream<number>()
  803. * connect(pipe(b, map(value => value * 2)), c)
  804. * // re-export the `a` stream, keep `b` internal
  805. * return { a, c }
  806. * }, tup(sys1))
  807. *
  808. * // init will recursively initialize sys2 dependencies, in this case sys1
  809. * const { a, c } = init(sys2)
  810. * subscribe(c, c => console.log(`Value multiplied by 4`, c))
  811. * publish(a, 2)
  812. * ```
  813. *
  814. * #### Singletons in Dependency Tree
  815. *
  816. * By default, systems will be initialized only once if encountered multiple times in the dependency tree.
  817. * In the below dependency system tree, systems `b` and `c` will receive the same stream instances from system `a` when system `d` is initialized.
  818. * ```txt
  819. * a
  820. * / \
  821. * b c
  822. * \ /
  823. * d
  824. * ```
  825. * If `a` gets `{singleton: false}` as a last argument, `init` creates two separate instances - one for `b` and one for `c`.
  826. *
  827. * @param constructor the system constructor function. Initialize and connect the streams in its body.
  828. *
  829. * @param dependencies the system dependencies, which the constructor will receive as arguments.
  830. * Use the [[tup]] utility **For TypeScript type inference to work correctly**.
  831. * ```ts
  832. * const sys3 = system(() => { ... }, tup(sys2, sys1))
  833. * ```
  834. * @param __namedParameters Options
  835. * @param singleton determines if the system will act as a singleton in a system dependency tree. `true` by default.
  836. */
  837. function system(constructor, dependencies, _temp) {
  838. if (dependencies === void 0) {
  839. dependencies = [];
  840. }
  841. var _ref = _temp === void 0 ? {
  842. singleton: true
  843. } : _temp,
  844. singleton = _ref.singleton;
  845. return {
  846. id: id(),
  847. constructor: constructor,
  848. dependencies: dependencies,
  849. singleton: singleton
  850. };
  851. }
  852. /** @internal */
  853. var id = function id() {
  854. return Symbol();
  855. };
  856. /**
  857. * Initializes a [[SystemSpec]] by recursively initializing its dependencies.
  858. *
  859. * ```ts
  860. * // a simple system with two streams
  861. * const sys1 = system(() => {
  862. * const a = stream<number>()
  863. * const b = stream<number>()
  864. *
  865. * connect(pipe(a, map(value => value * 2)), b)
  866. * return { a, b }
  867. * })
  868. *
  869. * const { a, b } = init(sys1)
  870. * subscribe(b, b => console.log(b))
  871. * publish(a, 2)
  872. * ```
  873. *
  874. * @returns the [[System]] constructed by the spec constructor.
  875. * @param systemSpec the system spec to initialize.
  876. */
  877. function init(systemSpec) {
  878. var singletons = new Map();
  879. var _init = function _init(_ref2) {
  880. var id = _ref2.id,
  881. constructor = _ref2.constructor,
  882. dependencies = _ref2.dependencies,
  883. singleton = _ref2.singleton;
  884. if (singleton && singletons.has(id)) {
  885. return singletons.get(id);
  886. }
  887. var system = constructor(dependencies.map(function (e) {
  888. return _init(e);
  889. }));
  890. if (singleton) {
  891. singletons.set(id, system);
  892. }
  893. return system;
  894. };
  895. return _init(systemSpec);
  896. }
  897. exports.always = always;
  898. exports.call = call;
  899. exports.combineLatest = combineLatest;
  900. exports.compose = compose;
  901. exports.connect = connect;
  902. exports.curry1to0 = curry1to0;
  903. exports.curry2to1 = curry2to1;
  904. exports.debounceTime = debounceTime;
  905. exports.defaultComparator = defaultComparator;
  906. exports.distinctUntilChanged = distinctUntilChanged;
  907. exports.duc = duc;
  908. exports.eventHandler = eventHandler;
  909. exports.filter = filter;
  910. exports.getValue = getValue;
  911. exports.handleNext = handleNext;
  912. exports.init = init;
  913. exports.joinProc = joinProc;
  914. exports.map = map;
  915. exports.mapTo = mapTo;
  916. exports.merge = merge;
  917. exports.noop = noop;
  918. exports.pipe = pipe;
  919. exports.prop = prop;
  920. exports.publish = publish;
  921. exports.reset = reset;
  922. exports.scan = scan;
  923. exports.skip = skip;
  924. exports.statefulStream = statefulStream;
  925. exports.statefulStreamFromEmitter = statefulStreamFromEmitter;
  926. exports.stream = stream;
  927. exports.streamFromEmitter = streamFromEmitter;
  928. exports.subscribe = subscribe;
  929. exports.system = system;
  930. exports.tap = tap;
  931. exports.throttleTime = throttleTime;
  932. exports.thrush = thrush;
  933. exports.tup = tup;
  934. exports.withLatestFrom = withLatestFrom;
  935. //# sourceMappingURL=urx.cjs.development.js.map