comp.js 2.0 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485
  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. value !== none && 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. if (i == fns.length) {
  35. push(data.value);
  36. } else {
  37. await next(data.value, fns, i, push);
  38. }
  39. }
  40. break;
  41. }
  42. const fn = fns[i];
  43. if (!fn) {
  44. push(value);
  45. break;
  46. }
  47. value = fn(value);
  48. }
  49. };
  50. const comp = (...fns) => {
  51. fns = fns.filter(fn => fn);
  52. return fns.length
  53. ? new Transform({
  54. writableObjectMode: true,
  55. readableObjectMode: true,
  56. transform(chunk, encoding, callback) {
  57. next(chunk, fns, 0, value => sanitize(value, this)).then(() => callback(null), error => callback(error));
  58. }
  59. })
  60. : null;
  61. };
  62. const nop = () => {};
  63. comp.asFun = (...fns) => {
  64. fns = fns.filter(fn => fn);
  65. if (!fns.length) return nop;
  66. return async value => {
  67. const results = [];
  68. await next(value, fns, 0, value => results.push(value));
  69. switch (results.length) {
  70. case 0:
  71. return none;
  72. case 1:
  73. return results[0];
  74. }
  75. return new Many(results);
  76. };
  77. };
  78. module.exports = comp;