UNPKG

@ant-design/x-sdk

Version:

placeholder for @ant-design/x-sdk

230 lines (228 loc) 6.96 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.default = exports.XRequestClass = exports.AbstractXRequestClass = void 0; exports.setXRequestGlobalOptions = setXRequestGlobalOptions; var _xStream = _interopRequireDefault(require("../x-stream")); var _xFetch = _interopRequireDefault(require("./x-fetch")); function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } /** * @description Global options for the request */ const globalOptions = { manual: false, headers: { 'Content-Type': 'application/json' } }; /** * Set global options for the request * @param options XRequestGlobalOptions<Input, Output> */ function setXRequestGlobalOptions(options) { Object.assign(globalOptions, options); } class AbstractXRequestClass { baseURL; options; constructor(baseURL, options) { if (!baseURL || typeof baseURL !== 'string') throw new Error('The baseURL is not valid!'); this.baseURL = baseURL; this.options = options || {}; } } exports.AbstractXRequestClass = AbstractXRequestClass; class XRequestClass extends AbstractXRequestClass { _asyncHandler; timeoutHandler; _isTimeout = false; streamTimeoutHandler; _isStreamTimeout = false; abortController; _isRequesting = false; _manual = false; get asyncHandler() { return this._asyncHandler; } get isTimeout() { return this._isTimeout; } set isTimeout(value) { this._isTimeout = value; } get isStreamTimeout() { return this._isStreamTimeout; } set isStreamTimeout(value) { this._isStreamTimeout = value; } get isRequesting() { return this._isRequesting; } get manual() { return this._manual; } constructor(baseURL, options) { super(baseURL, options); this._manual = options?.manual || false; if (!this.manual) { this.init(); } } run(params) { if (this.manual) { this.init(params); } else { console.warn('The request is not manual, so it cannot be run!'); } } abort() { clearTimeout(this.timeoutHandler); clearTimeout(this.streamTimeoutHandler); this.abortController.abort(); } init(extraParams) { this.abortController = new AbortController(); const { callbacks, params, headers = {}, transformStream, fetch, timeout, streamTimeout, middlewares, ...otherOptions } = this.options; const requestInit = { ...otherOptions, method: 'POST', body: JSON.stringify({ ...params, ...(extraParams || {}) }), params: { ...params, ...extraParams }, headers: Object.assign({}, globalOptions.headers || {}, headers), signal: this.abortController.signal, middlewares }; if (timeout && timeout > 0) { this.timeoutHandler = window.setTimeout(() => { this.isTimeout = true; this.finishRequest(); callbacks?.onError?.(new Error('TimeoutError')); }, timeout); } this.startRequest(); // save and export a async handler to wait for the request to be finished // though it is not necessary, but it is useful for some scenarios this._asyncHandler = (0, _xFetch.default)(this.baseURL, { fetch, ...requestInit }).then(async response => { clearTimeout(this.timeoutHandler); if (this.isTimeout) return; if (transformStream) { let transformer = transformStream; if (typeof transformStream === 'function') { transformer = transformStream(this.baseURL, response.headers); } await this.customResponseHandler(response, callbacks, transformer, streamTimeout); return; } const contentType = response.headers.get('content-type') || ''; const mimeType = contentType.split(';')[0].trim(); switch (mimeType) { /** SSE */ case 'text/event-stream': await this.sseResponseHandler(response, callbacks, streamTimeout); break; /** JSON */ case 'application/json': await this.jsonResponseHandler(response, callbacks); break; default: throw new Error(`The response content-type: ${contentType} is not support!`); } }).catch(error => { clearTimeout(this.timeoutHandler); this.finishRequest(); // abort() throw a DOMException, so we need to check it const err = error instanceof Error || error instanceof DOMException ? error : new Error('Unknown error!'); callbacks?.onError?.(err); }); } startRequest() { this._isRequesting = true; } finishRequest() { this._isRequesting = false; } customResponseHandler = async (response, callbacks, transformStream, streamTimeout) => { const stream = (0, _xStream.default)({ readableStream: response.body, transformStream }); await this.processStream(stream, response, callbacks, streamTimeout); }; sseResponseHandler = async (response, callbacks, streamTimeout) => { const stream = (0, _xStream.default)({ readableStream: response.body }); await this.processStream(stream, response, callbacks, streamTimeout); }; async processStream(stream, response, callbacks, streamTimeout) { const chunks = []; const iterator = stream[Symbol.asyncIterator](); let result; do { // if streamTimeout is set, start the stream timeout timer // every time the stream is updated, reset the timer if (streamTimeout) { this.streamTimeoutHandler = window.setTimeout(() => { this.isStreamTimeout = true; this.finishRequest(); callbacks?.onError?.(new Error('StreamTimeoutError')); }, streamTimeout); } result = await iterator.next(); chunks.push(result.value); callbacks?.onUpdate?.(result.value, response.headers); clearTimeout(this.streamTimeoutHandler); if (this.isStreamTimeout) { break; } } while (!result.done); if (streamTimeout) { clearTimeout(this.streamTimeoutHandler); if (this.isStreamTimeout) { this.finishRequest(); return; } } this.finishRequest(); callbacks?.onSuccess?.(chunks, response.headers); } jsonResponseHandler = async (response, callbacks) => { const chunk = await response.json(); if (chunk?.success === false) { const error = new Error(chunk.message || 'System error'); error.name = chunk.name || 'SystemError'; callbacks?.onError?.(error); } else { callbacks?.onUpdate?.(chunk, response.headers); this.finishRequest(); // keep type consistency with stream mode callbacks?.onSuccess?.([chunk], response.headers); } }; } exports.XRequestClass = XRequestClass; function XRequest(baseURL, options) { return new XRequestClass(baseURL, options); } var _default = exports.default = XRequest;