Home Reference Source Test

src/StreamWalker.ts

  1. /* eslint-disable @typescript-eslint/no-explicit-any */
  2. /* eslint-disable @typescript-eslint/explicit-function-return-type */
  3. import {Event} from './event'
  4. import * as eventstoreError from './errors'
  5. /**
  6. * Stream walker
  7. */
  8. export class StreamWalker {
  9. /** iterable */
  10. protected iterable: AsyncIterableIterator<Event | null>
  11.  
  12. /**
  13. * Creates an instance of stream walker.
  14. */
  15. public constructor(iterable: AsyncIterableIterator<Event | null>) {
  16. this.iterable = iterable
  17. }
  18.  
  19. /** standard async iterable function */
  20. public async *[Symbol.asyncIterator]() {
  21. for await (const value of this.iterable) {
  22. yield value
  23. }
  24. }
  25.  
  26. /**
  27. * The map() method creates a new iterator with the results of calling a provided function on every element in the calling iterator
  28. */
  29. public map(fn: Function, thisArg?: Function): StreamWalker {
  30. if (typeof fn !== 'function') {
  31. throw eventstoreError.newImplementationError(fn + 'is not a function')
  32. }
  33.  
  34. const a = async function*(iterable: AsyncIterable<Event | null>) {
  35. for await (const value of iterable) {
  36. yield await fn.call(thisArg, value)
  37. }
  38. }
  39. return new StreamWalker(a(this.iterable))
  40. }
  41.  
  42. /**
  43. * The filter() method creates a new iterator with all elements that pass the test implemented by the provided function
  44. */
  45. public filter(fn: Function, thisArg?: Function): StreamWalker {
  46. if (typeof fn !== 'function') {
  47. throw eventstoreError.newImplementationError(fn + 'is not a function')
  48. }
  49.  
  50. const iterable = this.iterable
  51. const b = async function*(innerFn: Function, thisInnerArg?: Function) {
  52. for await (const value of iterable) {
  53. if (await innerFn.call(thisInnerArg, value)) {
  54. yield value
  55. }
  56. }
  57. }
  58.  
  59. return new StreamWalker(b(fn, thisArg))
  60. }
  61.  
  62. /**
  63. * The forEach() method executes a provided function once for each iterator element
  64. */
  65. public async forEach(fn: Function, thisArg?: Function, ...args: any[]): Promise<void> {
  66. if (typeof fn !== 'function') {
  67. throw eventstoreError.newImplementationError(fn + 'is not a function')
  68. }
  69. const iterable = this.iterable
  70. for await (const value of iterable) {
  71. await fn.call(thisArg, value, ...args)
  72. }
  73. }
  74.  
  75. /**
  76. * The reduce() method applies a function against an accumulator and each element in the iterator (from left to right) to reduce it to a single value
  77. */
  78. public async reduce(
  79. accumulatorFunction: Function,
  80. initialValue: any = null,
  81. thisArg?: Function
  82. ): Promise<any> {
  83. if (typeof accumulatorFunction !== 'function') {
  84. throw eventstoreError.newImplementationError(accumulatorFunction + 'is not a function')
  85. }
  86. const iterable = this.iterable
  87. let returnValue = initialValue
  88. for await (const value of iterable) {
  89. returnValue = await accumulatorFunction.call(thisArg, returnValue, value)
  90. }
  91. return returnValue
  92. }
  93.  
  94. /**
  95. * Converts an iterator to an array.
  96. * The returned array will contain all single elements of iterator
  97. */
  98. public async toArray(): Promise<(Event | null)[]> {
  99. const iterable = this.iterable
  100. const arrayValue = []
  101. for await (const value of iterable) {
  102. arrayValue.push(value)
  103. }
  104. return arrayValue
  105. }
  106.  
  107. /**
  108. * The every() method tests whether all elements in the iterator pass the test implemented by the provided function
  109. */
  110. public async every(fn: Function, thisArg?: Function): Promise<boolean> {
  111. if (typeof fn !== 'function') {
  112. throw eventstoreError.newImplementationError(fn + 'is not a function')
  113. }
  114. const iterable = this.iterable
  115. for await (const value of iterable) {
  116. if ((await fn.call(thisArg, value)) === false) {
  117. return false
  118. }
  119. }
  120. return true
  121. }
  122. }