comp.js 1.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081
  1. 'use strict';
  2. const {Transform} = require('stream');
  3. const {none, Final, Many, sanitize} = require('../index');
  4. const next = async (value, fns, index, push) => {
  5. for (let i = index; i <= fns.length; ++i) {
  6. if (value && typeof value.then == 'function') {
  7. // thenable
  8. value = await value;
  9. }
  10. if (value === none) break;
  11. if (value instanceof Final) {
  12. push(value.value);
  13. break;
  14. }
  15. if (value instanceof Many) {
  16. if (i == fns.length) {
  17. value.values.forEach(val => push(val));
  18. break;
  19. }
  20. const values = value.values;
  21. for (let j = 0; j < values.length; ++j) {
  22. await next(values[j], fns, i, push);
  23. }
  24. break;
  25. }
  26. if (value && typeof value.next == 'function') {
  27. // generator
  28. for (;;) {
  29. let data = value.next();
  30. if (data && typeof data.then == 'function') {
  31. data = await data;
  32. }
  33. if (data.done) break;
  34. await next(data.value, fns, i, push);
  35. }
  36. break;
  37. }
  38. const fn = fns[i];
  39. if (!fn) {
  40. push(value);
  41. break;
  42. }
  43. value = fn(value);
  44. }
  45. };
  46. const comp = (...fns) => {
  47. fns = fns.filter(fn => fn);
  48. return fns.length
  49. ? new Transform({
  50. writableObjectMode: true,
  51. readableObjectMode: true,
  52. transform(chunk, encoding, callback) {
  53. next(chunk, fns, 0, value => sanitize(value, this)).then(() => callback(null), error => callback(error));
  54. }
  55. })
  56. : null;
  57. };
  58. const nop = () => {};
  59. comp.asFun = (...fns) => {
  60. fns = fns.filter(fn => fn);
  61. if (!fns.length) return nop;
  62. return async value => {
  63. const results = [];
  64. await next(value, fns, 0, value => results.push(value));
  65. switch (results.length) {
  66. case 0:
  67. return none;
  68. case 1:
  69. return results[0];
  70. }
  71. return new Many(results);
  72. };
  73. };
  74. module.exports = comp;