UNPKG

@cloudbase/node-sdk

Version:

tencent cloud base server sdk for node.js

260 lines (259 loc) 9.63 kB
"use strict"; var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { if (k2 === undefined) k2 = k; var desc = Object.getOwnPropertyDescriptor(m, k); if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { desc = { enumerable: true, get: function() { return m[k]; } }; } Object.defineProperty(o, k2, desc); }) : (function(o, m, k, k2) { if (k2 === undefined) k2 = k; o[k2] = m[k]; })); var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { Object.defineProperty(o, "default", { enumerable: true, value: v }); }) : function(o, v) { o["default"] = v; }); var __importStar = (this && this.__importStar) || function (mod) { if (mod && mod.__esModule) return mod; var result = {}; if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k); __setModuleDefault(result, mod); return result; }; Object.defineProperty(exports, "__esModule", { value: true }); exports.AIRequestAdapter = void 0; const openapicommonrequester = __importStar(require("../utils/tcbopenapicommonrequester")); const web_streams_polyfill_1 = require("web-streams-polyfill"); const utils_1 = require("../utils/utils"); class AIRequestAdapter { constructor(config, getAccessToken) { this.config = config; this.getAccessToken = getAccessToken; } async fetch(options) { var _a, _b; const { url, stream = false, timeout, method = 'POST', headers, body } = options; const headersObj = {}; if (isHeaders(headers)) { headers.forEach((value, key) => { headersObj[key] = value; }); } else if (Array.isArray(headers)) { headers.forEach(([k, v]) => (headersObj[k] = v)); } else { Object.assign(headersObj, headers); } let parsedBody; if (typeof body === 'string') { try { parsedBody = JSON.parse(body); } catch (_c) { parsedBody = body; } } else { parsedBody = body; } const token = await this.getAccessToken(); const result = await openapicommonrequester.request({ config: this.config, data: parsedBody, method: (method === null || method === void 0 ? void 0 : method.toUpperCase()) || 'POST', url, headers: Object.assign({ 'Content-Type': 'application/json' }, headersObj), token, opts: { timeout: timeout || this.config.timeout, stream } }); const { body: bodyData, headers: responseHeaders, statusCode } = result; if (statusCode < 200 || statusCode >= 300) { let errorMessage = `Request failed with status code ${statusCode}`; let errorCode = `${statusCode}`; let requestId = ''; let errorBody = null; if (typeof bodyData === 'string') { errorBody = bodyData; } else if (Buffer.isBuffer(bodyData)) { errorBody = bodyData.toString('utf-8'); } else if (bodyData && typeof bodyData === 'object' && typeof bodyData.on === 'function') { errorBody = await readStreamToString(bodyData); } if (errorBody) { try { const errorData = JSON.parse(errorBody); if ((_a = errorData.error) === null || _a === void 0 ? void 0 : _a.message) { errorMessage = errorData.error.message; } else if (errorData.message) { errorMessage = errorData.message; } if ((_b = errorData.error) === null || _b === void 0 ? void 0 : _b.code) { errorCode = errorData.error.code; } else if (errorData.code) { errorCode = errorData.code; } if (errorData.requestId) { requestId = errorData.requestId; } } catch (_d) { errorMessage = errorBody || errorMessage; } } // 从响应头中获取 requestId if (!requestId && responseHeaders) { const headerRequestId = responseHeaders['x-cloudbase-request-id'] || responseHeaders['x-request-id'] || ''; requestId = Array.isArray(headerRequestId) ? headerRequestId[0] : headerRequestId; } throw (0, utils_1.E)({ code: errorCode, message: errorMessage, requestId }); } if (stream) { // 对于流式响应,将 Node.js 原生流转换为 Web ReadableStream let readableStream; if (bodyData && typeof bodyData === 'object' && 'on' in bodyData && typeof bodyData.on === 'function') { const nodeStream = bodyData; // Node 12 兼容: 使用标志位追踪 stream 状态,避免重复 close 导致异常 let streamClosed = false; readableStream = new web_streams_polyfill_1.ReadableStream({ start(controller) { nodeStream.on('data', (chunk) => { if (streamClosed) return; controller.enqueue(new Uint8Array(chunk)); }); nodeStream.on('end', () => { if (streamClosed) return; streamClosed = true; controller.close(); }); nodeStream.on('error', (err) => { if (streamClosed) return; streamClosed = true; controller.error(err); }); }, cancel() { streamClosed = true; nodeStream.destroy(); } }); } else if (bodyData instanceof Buffer) { readableStream = new web_streams_polyfill_1.ReadableStream({ start(controller) { controller.enqueue(new Uint8Array(bodyData)); controller.close(); } }); } else if (typeof bodyData === 'string') { const encoder = new TextEncoder(); readableStream = new web_streams_polyfill_1.ReadableStream({ start(controller) { controller.enqueue(encoder.encode(bodyData)); controller.close(); } }); } else { readableStream = new web_streams_polyfill_1.ReadableStream({ start(controller) { controller.close(); } }); } return { data: readableStream, statusCode, header: responseHeaders }; } let responseData; if (typeof bodyData === 'string') { try { responseData = JSON.parse(bodyData); } catch (_e) { responseData = bodyData; } } else if (bodyData instanceof Buffer) { const bodyString = bodyData.toString('utf-8'); try { responseData = JSON.parse(bodyString); } catch (_f) { responseData = bodyString; } } else { responseData = bodyData; } return { data: Promise.resolve(responseData), statusCode, header: responseHeaders }; } /** * post 方法 - AI 模块可能不使用,但需要实现接口 */ async post() { throw new Error('post method is not supported in AI module'); } /** * upload 方法 - AI 模块可能不使用,但需要实现接口 */ async upload() { throw new Error('upload method is not supported in AI module'); } /** * download 方法 - AI 模块可能不使用,但需要实现接口 */ async download() { throw new Error('download method is not supported in AI module'); } } exports.AIRequestAdapter = AIRequestAdapter; function isHeaders(h) { try { // Node.js 低版本可能没有 Headers return h instanceof Headers; } catch (_) { return false; } } /** * 从 Node.js 流中读取完整内容为字符串 */ async function readStreamToString(stream) { return await new Promise((resolve, reject) => { const chunks = []; stream.on('data', (chunk) => { chunks.push(chunk); }); stream.on('end', () => { resolve(Buffer.concat(chunks).toString('utf-8')); }); stream.on('error', (err) => { reject(err); }); }); }