create.js 9.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240
  1. "use strict";
  2. var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
  3. if (k2 === undefined) k2 = k;
  4. Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } });
  5. }) : (function(o, m, k, k2) {
  6. if (k2 === undefined) k2 = k;
  7. o[k2] = m[k];
  8. }));
  9. var __exportStar = (this && this.__exportStar) || function(m, exports) {
  10. for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
  11. };
  12. Object.defineProperty(exports, "__esModule", { value: true });
  13. exports.defaultHandler = void 0;
  14. const is_1 = require("@sindresorhus/is");
  15. const as_promise_1 = require("./as-promise");
  16. const create_rejection_1 = require("./as-promise/create-rejection");
  17. const core_1 = require("./core");
  18. const deep_freeze_1 = require("./utils/deep-freeze");
  19. const errors = {
  20. RequestError: as_promise_1.RequestError,
  21. CacheError: as_promise_1.CacheError,
  22. ReadError: as_promise_1.ReadError,
  23. HTTPError: as_promise_1.HTTPError,
  24. MaxRedirectsError: as_promise_1.MaxRedirectsError,
  25. TimeoutError: as_promise_1.TimeoutError,
  26. ParseError: as_promise_1.ParseError,
  27. CancelError: as_promise_1.CancelError,
  28. UnsupportedProtocolError: as_promise_1.UnsupportedProtocolError,
  29. UploadError: as_promise_1.UploadError
  30. };
  31. // The `delay` package weighs 10KB (!)
  32. const delay = async (ms) => new Promise(resolve => {
  33. setTimeout(resolve, ms);
  34. });
  35. const { normalizeArguments } = core_1.default;
  36. const mergeOptions = (...sources) => {
  37. let mergedOptions;
  38. for (const source of sources) {
  39. mergedOptions = normalizeArguments(undefined, source, mergedOptions);
  40. }
  41. return mergedOptions;
  42. };
  43. const getPromiseOrStream = (options) => options.isStream ? new core_1.default(undefined, options) : as_promise_1.default(options);
  44. const isGotInstance = (value) => ('defaults' in value && 'options' in value.defaults);
  45. const aliases = [
  46. 'get',
  47. 'post',
  48. 'put',
  49. 'patch',
  50. 'head',
  51. 'delete'
  52. ];
  53. exports.defaultHandler = (options, next) => next(options);
  54. const callInitHooks = (hooks, options) => {
  55. if (hooks) {
  56. for (const hook of hooks) {
  57. hook(options);
  58. }
  59. }
  60. };
  61. const create = (defaults) => {
  62. // Proxy properties from next handlers
  63. defaults._rawHandlers = defaults.handlers;
  64. defaults.handlers = defaults.handlers.map(fn => ((options, next) => {
  65. // This will be assigned by assigning result
  66. let root;
  67. const result = fn(options, newOptions => {
  68. root = next(newOptions);
  69. return root;
  70. });
  71. if (result !== root && !options.isStream && root) {
  72. const typedResult = result;
  73. const { then: promiseThen, catch: promiseCatch, finally: promiseFianlly } = typedResult;
  74. Object.setPrototypeOf(typedResult, Object.getPrototypeOf(root));
  75. Object.defineProperties(typedResult, Object.getOwnPropertyDescriptors(root));
  76. // These should point to the new promise
  77. // eslint-disable-next-line promise/prefer-await-to-then
  78. typedResult.then = promiseThen;
  79. typedResult.catch = promiseCatch;
  80. typedResult.finally = promiseFianlly;
  81. }
  82. return result;
  83. }));
  84. // Got interface
  85. const got = ((url, options = {}, _defaults) => {
  86. var _a, _b;
  87. let iteration = 0;
  88. const iterateHandlers = (newOptions) => {
  89. return defaults.handlers[iteration++](newOptions, iteration === defaults.handlers.length ? getPromiseOrStream : iterateHandlers);
  90. };
  91. // TODO: Remove this in Got 12.
  92. if (is_1.default.plainObject(url)) {
  93. const mergedOptions = {
  94. ...url,
  95. ...options
  96. };
  97. core_1.setNonEnumerableProperties([url, options], mergedOptions);
  98. options = mergedOptions;
  99. url = undefined;
  100. }
  101. try {
  102. // Call `init` hooks
  103. let initHookError;
  104. try {
  105. callInitHooks(defaults.options.hooks.init, options);
  106. callInitHooks((_a = options.hooks) === null || _a === void 0 ? void 0 : _a.init, options);
  107. }
  108. catch (error) {
  109. initHookError = error;
  110. }
  111. // Normalize options & call handlers
  112. const normalizedOptions = normalizeArguments(url, options, _defaults !== null && _defaults !== void 0 ? _defaults : defaults.options);
  113. normalizedOptions[core_1.kIsNormalizedAlready] = true;
  114. if (initHookError) {
  115. throw new as_promise_1.RequestError(initHookError.message, initHookError, normalizedOptions);
  116. }
  117. return iterateHandlers(normalizedOptions);
  118. }
  119. catch (error) {
  120. if (options.isStream) {
  121. throw error;
  122. }
  123. else {
  124. return create_rejection_1.default(error, defaults.options.hooks.beforeError, (_b = options.hooks) === null || _b === void 0 ? void 0 : _b.beforeError);
  125. }
  126. }
  127. });
  128. got.extend = (...instancesOrOptions) => {
  129. const optionsArray = [defaults.options];
  130. let handlers = [...defaults._rawHandlers];
  131. let isMutableDefaults;
  132. for (const value of instancesOrOptions) {
  133. if (isGotInstance(value)) {
  134. optionsArray.push(value.defaults.options);
  135. handlers.push(...value.defaults._rawHandlers);
  136. isMutableDefaults = value.defaults.mutableDefaults;
  137. }
  138. else {
  139. optionsArray.push(value);
  140. if ('handlers' in value) {
  141. handlers.push(...value.handlers);
  142. }
  143. isMutableDefaults = value.mutableDefaults;
  144. }
  145. }
  146. handlers = handlers.filter(handler => handler !== exports.defaultHandler);
  147. if (handlers.length === 0) {
  148. handlers.push(exports.defaultHandler);
  149. }
  150. return create({
  151. options: mergeOptions(...optionsArray),
  152. handlers,
  153. mutableDefaults: Boolean(isMutableDefaults)
  154. });
  155. };
  156. // Pagination
  157. const paginateEach = (async function* (url, options) {
  158. // TODO: Remove this `@ts-expect-error` when upgrading to TypeScript 4.
  159. // Error: Argument of type 'Merge<Options, PaginationOptions<T, R>> | undefined' is not assignable to parameter of type 'Options | undefined'.
  160. // @ts-expect-error
  161. let normalizedOptions = normalizeArguments(url, options, defaults.options);
  162. normalizedOptions.resolveBodyOnly = false;
  163. const pagination = normalizedOptions.pagination;
  164. if (!is_1.default.object(pagination)) {
  165. throw new TypeError('`options.pagination` must be implemented');
  166. }
  167. const all = [];
  168. let { countLimit } = pagination;
  169. let numberOfRequests = 0;
  170. while (numberOfRequests < pagination.requestLimit) {
  171. if (numberOfRequests !== 0) {
  172. // eslint-disable-next-line no-await-in-loop
  173. await delay(pagination.backoff);
  174. }
  175. // @ts-expect-error FIXME!
  176. // TODO: Throw when result is not an instance of Response
  177. // eslint-disable-next-line no-await-in-loop
  178. const result = (await got(undefined, undefined, normalizedOptions));
  179. // eslint-disable-next-line no-await-in-loop
  180. const parsed = await pagination.transform(result);
  181. const current = [];
  182. for (const item of parsed) {
  183. if (pagination.filter(item, all, current)) {
  184. if (!pagination.shouldContinue(item, all, current)) {
  185. return;
  186. }
  187. yield item;
  188. if (pagination.stackAllItems) {
  189. all.push(item);
  190. }
  191. current.push(item);
  192. if (--countLimit <= 0) {
  193. return;
  194. }
  195. }
  196. }
  197. const optionsToMerge = pagination.paginate(result, all, current);
  198. if (optionsToMerge === false) {
  199. return;
  200. }
  201. if (optionsToMerge === result.request.options) {
  202. normalizedOptions = result.request.options;
  203. }
  204. else if (optionsToMerge !== undefined) {
  205. normalizedOptions = normalizeArguments(undefined, optionsToMerge, normalizedOptions);
  206. }
  207. numberOfRequests++;
  208. }
  209. });
  210. got.paginate = paginateEach;
  211. got.paginate.all = (async (url, options) => {
  212. const results = [];
  213. for await (const item of paginateEach(url, options)) {
  214. results.push(item);
  215. }
  216. return results;
  217. });
  218. // For those who like very descriptive names
  219. got.paginate.each = paginateEach;
  220. // Stream API
  221. got.stream = ((url, options) => got(url, { ...options, isStream: true }));
  222. // Shortcuts
  223. for (const method of aliases) {
  224. got[method] = ((url, options) => got(url, { ...options, method }));
  225. got.stream[method] = ((url, options) => {
  226. return got(url, { ...options, method, isStream: true });
  227. });
  228. }
  229. Object.assign(got, errors);
  230. Object.defineProperty(got, 'defaults', {
  231. value: defaults.mutableDefaults ? defaults : deep_freeze_1.default(defaults),
  232. writable: defaults.mutableDefaults,
  233. configurable: defaults.mutableDefaults,
  234. enumerable: true
  235. });
  236. got.mergeOptions = mergeOptions;
  237. return got;
  238. };
  239. exports.default = create;
  240. __exportStar(require("./types"), exports);