medium.js 2.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778
  1. function ItoI(a) {
  2. return a;
  3. }
  4. function innerCreateMedium(defaults, middleware = ItoI) {
  5. let buffer = [];
  6. let assigned = false;
  7. const medium = {
  8. read() {
  9. if (assigned) {
  10. throw new Error('Sidecar: could not `read` from an `assigned` medium. `read` could be used only with `useMedium`.');
  11. }
  12. if (buffer.length) {
  13. return buffer[buffer.length - 1];
  14. }
  15. return defaults;
  16. },
  17. useMedium(data) {
  18. const item = middleware(data, assigned);
  19. buffer.push(item);
  20. return () => {
  21. buffer = buffer.filter((x) => x !== item);
  22. };
  23. },
  24. assignSyncMedium(cb) {
  25. assigned = true;
  26. while (buffer.length) {
  27. const cbs = buffer;
  28. buffer = [];
  29. cbs.forEach(cb);
  30. }
  31. buffer = {
  32. push: (x) => cb(x),
  33. filter: () => buffer,
  34. };
  35. },
  36. assignMedium(cb) {
  37. assigned = true;
  38. let pendingQueue = [];
  39. if (buffer.length) {
  40. const cbs = buffer;
  41. buffer = [];
  42. cbs.forEach(cb);
  43. pendingQueue = buffer;
  44. }
  45. const executeQueue = () => {
  46. const cbs = pendingQueue;
  47. pendingQueue = [];
  48. cbs.forEach(cb);
  49. };
  50. const cycle = () => Promise.resolve().then(executeQueue);
  51. cycle();
  52. buffer = {
  53. push: (x) => {
  54. pendingQueue.push(x);
  55. cycle();
  56. },
  57. filter: (filter) => {
  58. pendingQueue = pendingQueue.filter(filter);
  59. return buffer;
  60. },
  61. };
  62. },
  63. };
  64. return medium;
  65. }
  66. export function createMedium(defaults, middleware = ItoI) {
  67. return innerCreateMedium(defaults, middleware);
  68. }
  69. // eslint-disable-next-line @typescript-eslint/ban-types
  70. export function createSidecarMedium(options = {}) {
  71. const medium = innerCreateMedium(null);
  72. medium.options = {
  73. async: true,
  74. ssr: false,
  75. ...options,
  76. };
  77. return medium;
  78. }