utils.js 3.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158
  1. export function assign(target, source) {
  2. for (const key in source) {
  3. if (source.hasOwnProperty(key)) {
  4. target[key] = source[key];
  5. }
  6. }
  7. }
  8. export function chunk(iterable, length) {
  9. const results = [];
  10. const lengthOfIterable = iterable.length;
  11. for (let i = 0; i < lengthOfIterable; i += length) {
  12. const chunked = [];
  13. for (let ci = i; ci < i + length; ci++) {
  14. chunked.push(iterable[ci]);
  15. }
  16. results.push(chunked);
  17. }
  18. return results;
  19. }
  20. export function endsWith(string, expectedEnding) {
  21. if (string.length < expectedEnding.length) {
  22. return false;
  23. }
  24. const actualEnding = string.substr(string.length - expectedEnding.length);
  25. return actualEnding === expectedEnding;
  26. }
  27. export function forEach(iterable, func) {
  28. const { length } = iterable;
  29. for (let i = 0; i < length; i++) {
  30. func(iterable[i], i);
  31. }
  32. }
  33. export function invert(oldObj) {
  34. const newObj = {};
  35. for (const key in oldObj) {
  36. if (oldObj.hasOwnProperty(key)) {
  37. const value = oldObj[key];
  38. newObj[value] = key;
  39. }
  40. }
  41. return newObj;
  42. }
  43. export function range(n) {
  44. const results = [];
  45. for (let i = 0; i < n; i++) {
  46. results.push(i);
  47. }
  48. return results;
  49. }
  50. export function times(numTimes, func) {
  51. const results = [];
  52. for (let i = 0; i < numTimes; i++) {
  53. results.push(func(i));
  54. }
  55. return results;
  56. }
  57. export function toArray(iterable) {
  58. const results = [];
  59. const { length } = iterable;
  60. for (let i = 0; i < length; i++) {
  61. results.push(iterable[i]);
  62. }
  63. return results;
  64. }
  65. export function toArrayRecursively(input) {
  66. if (input.length) {
  67. return toArray(input).map(toArrayRecursively);
  68. }
  69. return input;
  70. }
  71. // copied from https://github.com/academia-de-codigo/parse-content-range-header/blob/master/index.js
  72. export function parseContentRange(headerValue) {
  73. if (!headerValue) {
  74. return null;
  75. }
  76. if (typeof headerValue !== 'string') {
  77. throw new Error('invalid argument');
  78. }
  79. const parseInt = (number) => Number.parseInt(number, 10);
  80. // Check for presence of unit
  81. let matches = headerValue.match(/^(\w*) /);
  82. const unit = matches && matches[1];
  83. // check for start-end/size header format
  84. matches = headerValue.match(/(\d+)-(\d+)\/(\d+|\*)/);
  85. if (matches) {
  86. return {
  87. unit,
  88. first: parseInt(matches[1]),
  89. last: parseInt(matches[2]),
  90. length: matches[3] === '*' ? null : parseInt(matches[3]),
  91. };
  92. }
  93. // check for size header format
  94. matches = headerValue.match(/(\d+|\*)/);
  95. if (matches) {
  96. return {
  97. unit,
  98. first: null,
  99. last: null,
  100. length: matches[1] === '*' ? null : parseInt(matches[1]),
  101. };
  102. }
  103. return null;
  104. }
  105. /*
  106. * Promisified wrapper around 'setTimeout' to allow 'await'
  107. */
  108. export async function wait(milliseconds) {
  109. return new Promise((resolve) => setTimeout(resolve, milliseconds));
  110. }
  111. export function zip(a, b) {
  112. const A = Array.isArray(a) ? a : Array.from(a);
  113. const B = Array.isArray(b) ? b : Array.from(b);
  114. return A.map((k, i) => [k, B[i]]);
  115. }
  116. // Based on https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Error
  117. export class AbortError extends Error {
  118. constructor(params) {
  119. // Pass remaining arguments (including vendor specific ones) to parent constructor
  120. super(params);
  121. // Maintains proper stack trace for where our error was thrown (only available on V8)
  122. if (Error.captureStackTrace) {
  123. Error.captureStackTrace(this, AbortError);
  124. }
  125. this.name = 'AbortError';
  126. }
  127. }
  128. export class CustomAggregateError extends Error {
  129. constructor(errors, message) {
  130. super(message);
  131. this.errors = errors;
  132. this.message = message;
  133. this.name = 'AggregateError';
  134. }
  135. }
  136. export const AggregateError = CustomAggregateError;