index.browser.js 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234
  1. import { processOptions, validateOptions } from "./_chunks/defaultOptionsValidator-DdN0wke7.js";
  2. import parseHeaders from "parse-headers";
  3. const middlewareReducer = (middleware) => function(hook, defaultValue, ...args) {
  4. const bailEarly = hook === "onError";
  5. let value = defaultValue;
  6. for (let i = 0; i < middleware[hook].length; i++) {
  7. const handler = middleware[hook][i];
  8. if (value = handler(value, ...args), bailEarly && !value)
  9. break;
  10. }
  11. return value;
  12. };
  13. function createPubSub() {
  14. const subscribers = /* @__PURE__ */ Object.create(null);
  15. let nextId = 0;
  16. function subscribe(subscriber) {
  17. const id = nextId++;
  18. return subscribers[id] = subscriber, function() {
  19. delete subscribers[id];
  20. };
  21. }
  22. function publish(event) {
  23. for (const id in subscribers)
  24. subscribers[id](event);
  25. }
  26. return {
  27. publish,
  28. subscribe
  29. };
  30. }
  31. const channelNames = [
  32. "request",
  33. "response",
  34. "progress",
  35. "error",
  36. "abort"
  37. ], middlehooks = [
  38. "processOptions",
  39. "validateOptions",
  40. "interceptRequest",
  41. "finalizeOptions",
  42. "onRequest",
  43. "onResponse",
  44. "onError",
  45. "onReturn",
  46. "onHeaders"
  47. ];
  48. function createRequester(initMiddleware, httpRequest) {
  49. const loadedMiddleware = [], middleware = middlehooks.reduce(
  50. (ware, name) => (ware[name] = ware[name] || [], ware),
  51. {
  52. processOptions: [processOptions],
  53. validateOptions: [validateOptions]
  54. }
  55. );
  56. function request(opts) {
  57. const onResponse = (reqErr, res, ctx) => {
  58. let error = reqErr, response = res;
  59. if (!error)
  60. try {
  61. response = applyMiddleware("onResponse", res, ctx);
  62. } catch (err) {
  63. response = null, error = err;
  64. }
  65. error = error && applyMiddleware("onError", error, ctx), error ? channels.error.publish(error) : response && channels.response.publish(response);
  66. }, channels = channelNames.reduce((target, name) => (target[name] = createPubSub(), target), {}), applyMiddleware = middlewareReducer(middleware), options = applyMiddleware("processOptions", opts);
  67. applyMiddleware("validateOptions", options);
  68. const context = { options, channels, applyMiddleware };
  69. let ongoingRequest;
  70. const unsubscribe = channels.request.subscribe((ctx) => {
  71. ongoingRequest = httpRequest(ctx, (err, res) => onResponse(err, res, ctx));
  72. });
  73. channels.abort.subscribe(() => {
  74. unsubscribe(), ongoingRequest && ongoingRequest.abort();
  75. });
  76. const returnValue = applyMiddleware("onReturn", channels, context);
  77. return returnValue === channels && channels.request.publish(context), returnValue;
  78. }
  79. return request.use = function(newMiddleware) {
  80. if (!newMiddleware)
  81. throw new Error("Tried to add middleware that resolved to falsey value");
  82. if (typeof newMiddleware == "function")
  83. throw new Error(
  84. "Tried to add middleware that was a function. It probably expects you to pass options to it."
  85. );
  86. if (newMiddleware.onReturn && middleware.onReturn.length > 0)
  87. throw new Error(
  88. "Tried to add new middleware with `onReturn` handler, but another handler has already been registered for this event"
  89. );
  90. return middlehooks.forEach((key) => {
  91. newMiddleware[key] && middleware[key].push(newMiddleware[key]);
  92. }), loadedMiddleware.push(newMiddleware), request;
  93. }, request.clone = () => createRequester(loadedMiddleware, httpRequest), initMiddleware.forEach(request.use), request;
  94. }
  95. var __accessCheck = (obj, member, msg) => {
  96. if (!member.has(obj))
  97. throw TypeError("Cannot " + msg);
  98. }, __privateGet = (obj, member, getter) => (__accessCheck(obj, member, "read from private field"), getter ? getter.call(obj) : member.get(obj)), __privateAdd = (obj, member, value) => {
  99. if (member.has(obj))
  100. throw TypeError("Cannot add the same private member more than once");
  101. member instanceof WeakSet ? member.add(obj) : member.set(obj, value);
  102. }, __privateSet = (obj, member, value, setter) => (__accessCheck(obj, member, "write to private field"), setter ? setter.call(obj, value) : member.set(obj, value), value), _method, _url, _resHeaders, _headers, _controller, _init, _useAbortSignal;
  103. class FetchXhr {
  104. constructor() {
  105. this.readyState = 0, this.responseType = "", __privateAdd(this, _method, void 0), __privateAdd(this, _url, void 0), __privateAdd(this, _resHeaders, void 0), __privateAdd(this, _headers, {}), __privateAdd(this, _controller, void 0), __privateAdd(this, _init, {}), __privateAdd(this, _useAbortSignal, void 0);
  106. }
  107. // eslint-disable-next-line @typescript-eslint/no-unused-vars -- _async is only declared for typings compatibility
  108. open(method, url, _async) {
  109. __privateSet(this, _method, method), __privateSet(this, _url, url), __privateSet(this, _resHeaders, ""), this.readyState = 1, this.onreadystatechange(), __privateSet(this, _controller, void 0);
  110. }
  111. abort() {
  112. __privateGet(this, _controller) && __privateGet(this, _controller).abort();
  113. }
  114. getAllResponseHeaders() {
  115. return __privateGet(this, _resHeaders);
  116. }
  117. setRequestHeader(name, value) {
  118. __privateGet(this, _headers)[name] = value;
  119. }
  120. // Allow setting extra fetch init options, needed for runtimes such as Vercel Edge to set `cache` and other options in React Server Components
  121. setInit(init, useAbortSignal = !0) {
  122. __privateSet(this, _init, init), __privateSet(this, _useAbortSignal, useAbortSignal);
  123. }
  124. send(body) {
  125. const textBody = this.responseType !== "arraybuffer", options = {
  126. ...__privateGet(this, _init),
  127. method: __privateGet(this, _method),
  128. headers: __privateGet(this, _headers),
  129. body
  130. };
  131. typeof AbortController == "function" && __privateGet(this, _useAbortSignal) && (__privateSet(this, _controller, new AbortController()), typeof EventTarget < "u" && __privateGet(this, _controller).signal instanceof EventTarget && (options.signal = __privateGet(this, _controller).signal)), typeof document < "u" && (options.credentials = this.withCredentials ? "include" : "omit"), fetch(__privateGet(this, _url), options).then((res) => (res.headers.forEach((value, key) => {
  132. __privateSet(this, _resHeaders, __privateGet(this, _resHeaders) + `${key}: ${value}\r
  133. `);
  134. }), this.status = res.status, this.statusText = res.statusText, this.readyState = 3, textBody ? res.text() : res.arrayBuffer())).then((resBody) => {
  135. typeof resBody == "string" ? this.responseText = resBody : this.response = resBody, this.readyState = 4, this.onreadystatechange();
  136. }).catch((err) => {
  137. var _a;
  138. if (err.name === "AbortError") {
  139. this.onabort();
  140. return;
  141. }
  142. (_a = this.onerror) == null || _a.call(this, err);
  143. });
  144. }
  145. }
  146. _method = /* @__PURE__ */ new WeakMap(), _url = /* @__PURE__ */ new WeakMap(), _resHeaders = /* @__PURE__ */ new WeakMap(), _headers = /* @__PURE__ */ new WeakMap(), _controller = /* @__PURE__ */ new WeakMap(), _init = /* @__PURE__ */ new WeakMap(), _useAbortSignal = /* @__PURE__ */ new WeakMap();
  147. const adapter = typeof XMLHttpRequest == "function" ? "xhr" : "fetch", XmlHttpRequest = adapter === "xhr" ? XMLHttpRequest : FetchXhr, httpRequester = (context, callback) => {
  148. var _a;
  149. const opts = context.options, options = context.applyMiddleware("finalizeOptions", opts), timers = {}, injectedResponse = context.applyMiddleware("interceptRequest", void 0, {
  150. adapter,
  151. context
  152. });
  153. if (injectedResponse) {
  154. const cbTimer = setTimeout(callback, 0, null, injectedResponse);
  155. return { abort: () => clearTimeout(cbTimer) };
  156. }
  157. let xhr = new XmlHttpRequest();
  158. xhr instanceof FetchXhr && typeof options.fetch == "object" && xhr.setInit(options.fetch, (_a = options.useAbortSignal) != null ? _a : !0);
  159. const headers = options.headers, delays = options.timeout;
  160. let aborted = !1, loaded = !1, timedOut = !1;
  161. if (xhr.onerror = (event) => {
  162. onError(
  163. new Error(
  164. `Request error while attempting to reach ${options.url}${event.lengthComputable ? `(${event.loaded} of ${event.total} bytes transferred)` : ""}`
  165. )
  166. );
  167. }, xhr.ontimeout = (event) => {
  168. onError(
  169. new Error(
  170. `Request timeout while attempting to reach ${options.url}${event.lengthComputable ? `(${event.loaded} of ${event.total} bytes transferred)` : ""}`
  171. )
  172. );
  173. }, xhr.onabort = () => {
  174. stopTimers(!0), aborted = !0;
  175. }, xhr.onreadystatechange = () => {
  176. resetTimers(), !(aborted || xhr.readyState !== 4) && xhr.status !== 0 && onLoad();
  177. }, xhr.open(
  178. options.method,
  179. options.url,
  180. !0
  181. // Always async
  182. ), xhr.withCredentials = !!options.withCredentials, headers && xhr.setRequestHeader)
  183. for (const key in headers)
  184. headers.hasOwnProperty(key) && xhr.setRequestHeader(key, headers[key]);
  185. return options.rawBody && (xhr.responseType = "arraybuffer"), context.applyMiddleware("onRequest", { options, adapter, request: xhr, context }), xhr.send(options.body || null), delays && (timers.connect = setTimeout(() => timeoutRequest("ETIMEDOUT"), delays.connect)), { abort };
  186. function abort() {
  187. aborted = !0, xhr && xhr.abort();
  188. }
  189. function timeoutRequest(code) {
  190. timedOut = !0, xhr.abort();
  191. const error = new Error(
  192. code === "ESOCKETTIMEDOUT" ? `Socket timed out on request to ${options.url}` : `Connection timed out on request to ${options.url}`
  193. );
  194. error.code = code, context.channels.error.publish(error);
  195. }
  196. function resetTimers() {
  197. delays && (stopTimers(), timers.socket = setTimeout(() => timeoutRequest("ESOCKETTIMEDOUT"), delays.socket));
  198. }
  199. function stopTimers(force) {
  200. (force || aborted || xhr.readyState >= 2 && timers.connect) && clearTimeout(timers.connect), timers.socket && clearTimeout(timers.socket);
  201. }
  202. function onError(error) {
  203. if (loaded)
  204. return;
  205. stopTimers(!0), loaded = !0, xhr = null;
  206. const err = error || new Error(`Network error while attempting to reach ${options.url}`);
  207. err.isNetworkError = !0, err.request = options, callback(err);
  208. }
  209. function reduceResponse() {
  210. return {
  211. body: xhr.response || (xhr.responseType === "" || xhr.responseType === "text" ? xhr.responseText : ""),
  212. url: options.url,
  213. method: options.method,
  214. headers: parseHeaders(xhr.getAllResponseHeaders()),
  215. statusCode: xhr.status,
  216. statusMessage: xhr.statusText
  217. };
  218. }
  219. function onLoad() {
  220. if (!(aborted || loaded || timedOut)) {
  221. if (xhr.status === 0) {
  222. onError(new Error("Unknown XHR error"));
  223. return;
  224. }
  225. stopTimers(), loaded = !0, callback(null, reduceResponse());
  226. }
  227. }
  228. }, getIt = (initMiddleware = [], httpRequest = httpRequester) => createRequester(initMiddleware, httpRequest), environment = "browser";
  229. export {
  230. adapter,
  231. environment,
  232. getIt
  233. };
  234. //# sourceMappingURL=index.browser.js.map