@cloudbase/container 2.5.32-beta.0 → 2.5.33-beta.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,12 @@
1
+ interface IRequestPorps {
2
+ url: string;
3
+ data?: string | object | ArrayBuffer;
4
+ header?: Record<string, string>;
5
+ timeout?: number;
6
+ method?: string;
7
+ dataType?: 'json' | string;
8
+ responseType?: 'text' | 'arrayBuffer';
9
+ mode?: 'cors' | 'no-cors' | 'same-origin';
10
+ }
11
+ export declare function request({ url, method, header, data, timeout, dataType, responseType, mode, }: IRequestPorps): Promise<any>;
12
+ export {};
@@ -0,0 +1,101 @@
1
+ var __assign = (this && this.__assign) || function () {
2
+ __assign = Object.assign || function(t) {
3
+ for (var s, i = 1, n = arguments.length; i < n; i++) {
4
+ s = arguments[i];
5
+ for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p))
6
+ t[p] = s[p];
7
+ }
8
+ return t;
9
+ };
10
+ return __assign.apply(this, arguments);
11
+ };
12
+ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
13
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
14
+ return new (P || (P = Promise))(function (resolve, reject) {
15
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
16
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
17
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
18
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
19
+ });
20
+ };
21
+ var __generator = (this && this.__generator) || function (thisArg, body) {
22
+ var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g;
23
+ return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
24
+ function verb(n) { return function (v) { return step([n, v]); }; }
25
+ function step(op) {
26
+ if (f) throw new TypeError("Generator is already executing.");
27
+ while (g && (g = 0, op[0] && (_ = 0)), _) try {
28
+ if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
29
+ if (y = 0, t) op = [op[0] & 2, t.value];
30
+ switch (op[0]) {
31
+ case 0: case 1: t = op; break;
32
+ case 4: _.label++; return { value: op[1], done: false };
33
+ case 5: _.label++; y = op[1]; op = [0]; continue;
34
+ case 7: op = _.ops.pop(); _.trys.pop(); continue;
35
+ default:
36
+ if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
37
+ if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
38
+ if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
39
+ if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
40
+ if (t[2]) _.ops.pop();
41
+ _.trys.pop(); continue;
42
+ }
43
+ op = body.call(thisArg, _);
44
+ } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
45
+ if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
46
+ }
47
+ };
48
+ import { constants } from '@cloudbase/utilities';
49
+ import { COMPONENT_NAME } from '../constants';
50
+ import { serializeRequestBody } from './index';
51
+ var getSdkName = constants.getSdkName, ERRORS = constants.ERRORS;
52
+ export function request(_a) {
53
+ var url = _a.url, _b = _a.method, method = _b === void 0 ? 'GET' : _b, _c = _a.header, header = _c === void 0 ? {} : _c, data = _a.data, _d = _a.timeout, timeout = _d === void 0 ? 60000 : _d, _e = _a.dataType, dataType = _e === void 0 ? 'json' : _e, _f = _a.responseType, responseType = _f === void 0 ? 'text' : _f, mode = _a.mode;
54
+ return __awaiter(this, void 0, void 0, function () {
55
+ var headers, abortController, done;
56
+ return __generator(this, function (_g) {
57
+ headers = __assign({}, header);
58
+ data = serializeRequestBody(headers, data);
59
+ abortController = new AbortController();
60
+ done = false;
61
+ return [2, Promise.race([
62
+ new Promise(function (_, reject) {
63
+ setTimeout(function () {
64
+ var _a;
65
+ var error = new Error('请求超时');
66
+ error.code = 'SERVER_TIMEOUT';
67
+ if (!done) {
68
+ (_a = abortController.abort) === null || _a === void 0 ? void 0 : _a.call(abortController);
69
+ }
70
+ reject(error);
71
+ }, timeout);
72
+ }),
73
+ fetch(url, {
74
+ method: method,
75
+ headers: headers,
76
+ body: data,
77
+ signal: abortController.signal,
78
+ mode: mode,
79
+ }).then(function (response) {
80
+ done = true;
81
+ if (responseType === 'arrayBuffer') {
82
+ return response.arrayBuffer();
83
+ }
84
+ if (dataType === 'json') {
85
+ try {
86
+ return response.json();
87
+ }
88
+ catch (e) {
89
+ throw new Error("[".concat(getSdkName(), "][").concat(ERRORS.INVALID_PARAMS, "][").concat(COMPONENT_NAME, ".callContainer] response data must be json"));
90
+ }
91
+ }
92
+ return response.text();
93
+ }, function (e) {
94
+ done = true;
95
+ throw e;
96
+ }),
97
+ ])];
98
+ });
99
+ });
100
+ }
101
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicmVxdWVzdC5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uL3NyYy91dGlscy9yZXF1ZXN0LnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7O0FBQUEsT0FBTyxFQUFFLFNBQVMsRUFBRSxNQUFNLHNCQUFzQixDQUFBO0FBQ2hELE9BQU8sRUFBRSxjQUFjLEVBQUUsTUFBTSxjQUFjLENBQUE7QUFDN0MsT0FBTyxFQUFFLG9CQUFvQixFQUFFLE1BQU0sU0FBUyxDQUFBO0FBQ3RDLElBQUEsVUFBVSxHQUFhLFNBQVMsV0FBdEIsRUFBRSxNQUFNLEdBQUssU0FBUyxPQUFkLENBQWM7QUFnQnhDLE1BQU0sVUFBZ0IsT0FBTyxDQUFDLEVBU2Q7UUFSZCxHQUFHLFNBQUEsRUFDSCxjQUFjLEVBQWQsTUFBTSxtQkFBRyxLQUFLLEtBQUEsRUFDZCxjQUFXLEVBQVgsTUFBTSxtQkFBRyxFQUFFLEtBQUEsRUFDWCxJQUFJLFVBQUEsRUFDSixlQUFlLEVBQWYsT0FBTyxtQkFBRyxLQUFLLEtBQUEsRUFDZixnQkFBaUIsRUFBakIsUUFBUSxtQkFBRyxNQUFNLEtBQUEsRUFDakIsb0JBQXFCLEVBQXJCLFlBQVksbUJBQUcsTUFBTSxLQUFBLEVBQ3JCLElBQUksVUFBQTs7OztZQUVFLE9BQU8sZ0JBQVEsTUFBTSxDQUFFLENBQUE7WUFFN0IsSUFBSSxHQUFHLG9CQUFvQixDQUFDLE9BQU8sRUFBRSxJQUFJLENBQUMsQ0FBQTtZQUVwQyxlQUFlLEdBQUcsSUFBSSxlQUFlLEVBQUUsQ0FBQTtZQUN6QyxJQUFJLEdBQUcsS0FBSyxDQUFBO1lBQ2hCLFdBQU8sT0FBTyxDQUFDLElBQUksQ0FBQztvQkFDbEIsSUFBSSxPQUFPLENBQUMsVUFBQyxDQUFDLEVBQUUsTUFBTTt3QkFDcEIsVUFBVSxDQUFDOzs0QkFDVCxJQUFNLEtBQUssR0FBRyxJQUFJLEtBQUssQ0FBQyxNQUFNLENBQUMsQ0FDOUI7NEJBQUMsS0FBYSxDQUFDLElBQUksR0FBRyxnQkFBZ0IsQ0FBQTs0QkFDdkMsSUFBSSxDQUFDLElBQUksRUFBRTtnQ0FDVCxNQUFBLGVBQWUsQ0FBQyxLQUFLLCtEQUFJLENBQUE7NkJBQzFCOzRCQUNELE1BQU0sQ0FBQyxLQUFLLENBQUMsQ0FBQTt3QkFDZixDQUFDLEVBQUUsT0FBTyxDQUFDLENBQUE7b0JBQ2IsQ0FBQyxDQUFDO29CQUNGLEtBQUssQ0FBQyxHQUFHLEVBQUU7d0JBQ1QsTUFBTSxRQUFBO3dCQUNOLE9BQU8sU0FBQTt3QkFDUCxJQUFJLEVBQUUsSUFBVzt3QkFDakIsTUFBTSxFQUFFLGVBQWUsQ0FBQyxNQUFNO3dCQUM5QixJQUFJLE1BQUE7cUJBQ0wsQ0FBQyxDQUFDLElBQUksQ0FDTCxVQUFDLFFBQVE7d0JBQ1AsSUFBSSxHQUFHLElBQUksQ0FBQTt3QkFDWCxJQUFJLFlBQVksS0FBSyxhQUFhLEVBQUU7NEJBQ2xDLE9BQU8sUUFBUSxDQUFDLFdBQVcsRUFBRSxDQUFBO3lCQUM5Qjt3QkFDRCxJQUFJLFFBQVEsS0FBSyxNQUFNLEVBQUU7NEJBQ3ZCLElBQUk7Z0NBQ0YsT0FBTyxRQUFRLENBQUMsSUFBSSxFQUFFLENBQUE7NkJBQ3ZCOzRCQUFDLE9BQU8sQ0FBQyxFQUFFO2dDQUNWLE1BQU0sSUFBSSxLQUFLLENBQUMsV0FBSSxVQUFVLEVBQUUsZUFBSyxNQUFNLENBQUMsY0FBYyxlQUFLLGNBQWMsK0NBQTRDLENBQUUsQ0FBQTs2QkFDNUg7eUJBQ0Y7d0JBQ0QsT0FBTyxRQUFRLENBQUMsSUFBSSxFQUFFLENBQUE7b0JBQ3hCLENBQUMsRUFDRCxVQUFDLENBQUM7d0JBQ0EsSUFBSSxHQUFHLElBQUksQ0FBQTt3QkFDWCxNQUFNLENBQUMsQ0FBQTtvQkFDVCxDQUFDLENBQ0Y7aUJBQ0YsQ0FBQyxFQUFBOzs7Q0FDSCIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7IGNvbnN0YW50cyB9IGZyb20gJ0BjbG91ZGJhc2UvdXRpbGl0aWVzJ1xuaW1wb3J0IHsgQ09NUE9ORU5UX05BTUUgfSBmcm9tICcuLi9jb25zdGFudHMnXG5pbXBvcnQgeyBzZXJpYWxpemVSZXF1ZXN0Qm9keSB9IGZyb20gJy4vaW5kZXgnXG5jb25zdCB7IGdldFNka05hbWUsIEVSUk9SUyB9ID0gY29uc3RhbnRzXG5cbmludGVyZmFjZSBJUmVxdWVzdFBvcnBzIHtcbiAgdXJsOiBzdHJpbmdcbiAgZGF0YT86IHN0cmluZyB8IG9iamVjdCB8IEFycmF5QnVmZmVyXG4gIGhlYWRlcj86IFJlY29yZDxzdHJpbmcsIHN0cmluZz5cbiAgdGltZW91dD86IG51bWJlclxuICBtZXRob2Q/OiBzdHJpbmdcbiAgZGF0YVR5cGU/OiAnanNvbicgfCBzdHJpbmdcbiAgcmVzcG9uc2VUeXBlPzogJ3RleHQnIHwgJ2FycmF5QnVmZmVyJ1xuICBtb2RlPzogJ2NvcnMnIHwgJ25vLWNvcnMnIHwgJ3NhbWUtb3JpZ2luJ1xufVxuXG4vKipcbiAqIOWwgeijheWvuem9kCB3eC5yZXF1ZXN0XG4gKi9cbmV4cG9ydCBhc3luYyBmdW5jdGlvbiByZXF1ZXN0KHtcbiAgdXJsLFxuICBtZXRob2QgPSAnR0VUJyxcbiAgaGVhZGVyID0ge30sXG4gIGRhdGEsXG4gIHRpbWVvdXQgPSA2MDAwMCxcbiAgZGF0YVR5cGUgPSAnanNvbicsXG4gIHJlc3BvbnNlVHlwZSA9ICd0ZXh0JyxcbiAgbW9kZSxcbn06IElSZXF1ZXN0UG9ycHMpIHtcbiAgY29uc3QgaGVhZGVycyA9IHsgLi4uaGVhZGVyIH1cblxuICBkYXRhID0gc2VyaWFsaXplUmVxdWVzdEJvZHkoaGVhZGVycywgZGF0YSlcblxuICBjb25zdCBhYm9ydENvbnRyb2xsZXIgPSBuZXcgQWJvcnRDb250cm9sbGVyKClcbiAgbGV0IGRvbmUgPSBmYWxzZVxuICByZXR1cm4gUHJvbWlzZS5yYWNlKFtcbiAgICBuZXcgUHJvbWlzZSgoXywgcmVqZWN0KSA9PiB7XG4gICAgICBzZXRUaW1lb3V0KCgpID0+IHtcbiAgICAgICAgY29uc3QgZXJyb3IgPSBuZXcgRXJyb3IoJ+ivt+axgui2heaXticpXG4gICAgICAgIDsoZXJyb3IgYXMgYW55KS5jb2RlID0gJ1NFUlZFUl9USU1FT1VUJ1xuICAgICAgICBpZiAoIWRvbmUpIHtcbiAgICAgICAgICBhYm9ydENvbnRyb2xsZXIuYWJvcnQ/LigpXG4gICAgICAgIH1cbiAgICAgICAgcmVqZWN0KGVycm9yKVxuICAgICAgfSwgdGltZW91dClcbiAgICB9KSxcbiAgICBmZXRjaCh1cmwsIHtcbiAgICAgIG1ldGhvZCxcbiAgICAgIGhlYWRlcnMsXG4gICAgICBib2R5OiBkYXRhIGFzIGFueSxcbiAgICAgIHNpZ25hbDogYWJvcnRDb250cm9sbGVyLnNpZ25hbCxcbiAgICAgIG1vZGUsXG4gICAgfSkudGhlbihcbiAgICAgIChyZXNwb25zZSkgPT4ge1xuICAgICAgICBkb25lID0gdHJ1ZVxuICAgICAgICBpZiAocmVzcG9uc2VUeXBlID09PSAnYXJyYXlCdWZmZXInKSB7XG4gICAgICAgICAgcmV0dXJuIHJlc3BvbnNlLmFycmF5QnVmZmVyKClcbiAgICAgICAgfVxuICAgICAgICBpZiAoZGF0YVR5cGUgPT09ICdqc29uJykge1xuICAgICAgICAgIHRyeSB7XG4gICAgICAgICAgICByZXR1cm4gcmVzcG9uc2UuanNvbigpXG4gICAgICAgICAgfSBjYXRjaCAoZSkge1xuICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKGBbJHtnZXRTZGtOYW1lKCl9XVske0VSUk9SUy5JTlZBTElEX1BBUkFNU31dWyR7Q09NUE9ORU5UX05BTUV9LmNhbGxDb250YWluZXJdIHJlc3BvbnNlIGRhdGEgbXVzdCBiZSBqc29uYCwpXG4gICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIHJldHVybiByZXNwb25zZS50ZXh0KClcbiAgICAgIH0sXG4gICAgICAoZSkgPT4ge1xuICAgICAgICBkb25lID0gdHJ1ZVxuICAgICAgICB0aHJvdyBlXG4gICAgICB9LFxuICAgICksXG4gIF0pXG59XG4iXX0=
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@cloudbase/container",
3
- "version": "2.5.32-beta.0",
3
+ "version": "2.5.33-beta.0",
4
4
  "description": "cloudbase javascript sdk functions componets",
5
5
  "main": "dist/cjs/index.js",
6
6
  "module": "dist/esm/index.js",
@@ -34,5 +34,5 @@
34
34
  "brotli": "^1.3.3",
35
35
  "brotli-dec-wasm": "^2.0.1"
36
36
  },
37
- "gitHead": "c8039847f82e5b0c2607b8d49c0760c40d1e0b2e"
37
+ "gitHead": "59fd9b92ed116c4cf58fe503d90b8d9835eb8226"
38
38
  }
@@ -0,0 +1 @@
1
+ export const COMPONENT_NAME = 'container'
package/src/index.ts CHANGED
@@ -6,90 +6,31 @@ import { constants, utils, helpers } from '@cloudbase/utilities'
6
6
  import decompress from 'brotli/decompress'
7
7
 
8
8
  import Go from './go_wams_exec'
9
+ import { isBuffer, parseURL, serializeRequestBody } from './utils'
10
+ import { request } from './utils/request'
11
+ import { COMPONENT_NAME } from './constants'
9
12
 
10
13
  declare const cloudbase: ICloudbase
11
14
 
12
- const { getSdkName, ERRORS, COMMUNITY_SITE_URL } = constants
15
+ const { ERRORS, COMMUNITY_SITE_URL } = constants
13
16
  const { execCallback, printWarn } = utils
14
17
  const { catchErrorsDecorator } = helpers
15
18
 
16
- const COMPONENT_NAME = 'container'
17
-
18
- /**
19
- * 封装对齐 wx.request
20
- */
21
- async function request({
22
- url,
23
- method = 'GET',
24
- header = {},
25
- data,
26
- timeout = 60000,
27
- dataType = 'json',
28
- responseType = 'text',
29
- }: {
30
- url: string
31
- data?: string | object | ArrayBuffer
32
- header?: Record<string, string>
33
- timeout?: number
34
- method?: string
35
- dataType?: 'json' | string
36
- responseType?: 'text' | 'arrayBuffer'
37
- }) {
38
- const headers = { ...header }
39
-
40
- if (typeof data === 'object' && !(data instanceof ArrayBuffer || ArrayBuffer.isView(data))) {
41
- if (!headers['Content-Type'] && !headers['content-type']) {
42
- headers['Content-Type'] = 'application/json'
43
- }
44
- try {
45
- data = JSON.stringify(data)
46
- } catch (e) {
47
- throw new Error(JSON.stringify({
48
- code: ERRORS.INVALID_PARAMS,
49
- msg: `[${COMPONENT_NAME}.callContainer] invalid data with content-type: application/json`,
50
- }),)
51
- }
52
- }
53
-
54
- const { signal, abort } = new AbortController()
55
-
56
- return Promise.race([
57
- new Promise((_, reject) => {
58
- setTimeout(() => {
59
- const error = new Error('请求超时')
60
- ;(error as any).code = 'SERVER_TIMEOUT'
61
- reject(error)
62
- abort()
63
- }, timeout)
64
- }),
65
- fetch(url, {
66
- method,
67
- headers,
68
- body: data,
69
- signal,
70
- }).then((response) => {
71
- if (responseType === 'arrayBuffer') {
72
- return response.arrayBuffer()
73
- }
74
- if (dataType === 'json') {
75
- try {
76
- return response.json()
77
- } catch (e) {
78
- throw new Error(`[${getSdkName()}][${ERRORS.INVALID_PARAMS}][${COMPONENT_NAME}.callContainer] response data must be json`,)
79
- }
80
- }
81
- return response.text()
82
- }),
83
- ])
84
- }
85
-
86
19
  class InvalieParamsError extends Error {
20
+ code: any
87
21
  constructor(scope, message) {
88
22
  const msg = JSON.stringify({
89
23
  code: ERRORS.INVALID_PARAMS,
90
24
  msg: `[${scope}] ${message}`,
91
25
  })
92
26
  super(msg)
27
+ this.code = ERRORS.INVALID_PARAMS
28
+ }
29
+ toJSON() {
30
+ return {
31
+ code: this.code,
32
+ message: this.message,
33
+ }
93
34
  }
94
35
  }
95
36
 
@@ -99,32 +40,56 @@ interface ICallTcbContainerOptions extends ICallContainerOptions {
99
40
  }
100
41
 
101
42
  interface IInitTcbContainerOptions {
102
- config: Omit<IContianerConfig, 'wasmUrl'>
43
+ config: Omit<IContianerConfig, 'wasmUrl' | 'jsUrl'>
103
44
  success: (res: { statusCode: string | number; header: ICallContainerOptions['header']; data: any }) => void
104
45
  fail: (res: { data: { code: number; message: string } }) => void
105
46
  }
106
47
 
48
+ function genContainerError(data, scope = COMPONENT_NAME, defaultMessage = 'call container error') {
49
+ const error = data instanceof Error ? data : new Error(`[${scope}] ${data?.message || defaultMessage}`)
50
+ ;(error as any).code = data?.code || 'UNKNOWN_ERROR'
51
+ return error
52
+ }
53
+
107
54
  class CloudbaseContainers {
108
55
  private readonly config: IContianerConfig
109
56
  private wasm: Promise<WebAssembly.Exports>
110
57
  private containerInitPromise: /* Promise<any>*/ any | null
111
58
 
112
59
  constructor(config: IContianerConfig) {
113
- this.config = config
114
- if (!this.config.wasmUrl) {
115
- throw new Error(JSON.stringify({
116
- code: ERRORS.INVALID_PARAMS,
117
- msg: `[${COMPONENT_NAME}] 缺少 wasmUrl`,
118
- }),)
60
+ this.config = {
61
+ ...config,
62
+ }
63
+
64
+ if (!this.config.wasmUrl && !this.config.jsUrl && !(window as any).cloudbase_private_link) {
65
+ throw new InvalieParamsError(`${COMPONENT_NAME}`, '缺少 privatelink sdk 地址')
119
66
  }
120
- this.wasm = getExportFunction(this.config.wasmUrl, {
121
- utils: {
122
- info(e) {
123
- console.log(e)
67
+
68
+ if (this.config.wasmUrl) {
69
+ this.wasm = getExportFunction(this.config.wasmUrl, {
70
+ utils: {
71
+ info(e) {
72
+ console.log(e)
73
+ },
74
+ request,
124
75
  },
125
- request,
126
- },
127
- })
76
+ }).catch((e) => {
77
+ if (this.config.jsUrl) {
78
+ console.warn('load wams error, fall back to use js', e)
79
+ return loadJSExportFunction(this.config.jsUrl)
80
+ } if ((window as any).cloudbase_private_link) {
81
+ return (window as any).cloudbase_private_link
82
+ }
83
+ throw e
84
+ })
85
+ } else if (this.config.jsUrl) {
86
+ this.wasm = loadJSExportFunction(this.config.jsUrl)
87
+ } else {
88
+ this.wasm = Promise.resolve({
89
+ initContainer: (window as any).cloudbase_private_link.initContainer,
90
+ callContainer: (window as any).cloudbase_private_link.callContainer,
91
+ })
92
+ }
128
93
  }
129
94
 
130
95
  @catchErrorsDecorator({
@@ -142,8 +107,8 @@ class CloudbaseContainers {
142
107
  })
143
108
  public async callContainer(options: ICallContainerOptions, callback?: Function) {
144
109
  await this.initContainer(this.config)
110
+ const SCOPE = `${COMPONENT_NAME}.callContainer`
145
111
  const { callContainer }: { callContainer: (options: ICallTcbContainerOptions) => void } = (await this.wasm) as any
146
-
147
112
  const {
148
113
  url,
149
114
  method = 'GET',
@@ -153,26 +118,79 @@ class CloudbaseContainers {
153
118
  dataType = 'json',
154
119
  responseType = 'text',
155
120
  ...restOptions
156
- } = options
121
+ } = {
122
+ ...options,
123
+ }
157
124
 
158
125
  if (!url) {
159
- throw new InvalieParamsError(`${COMPONENT_NAME}.callContainer`, 'invalid request url')
126
+ throw new InvalieParamsError(SCOPE, 'invalid request url')
127
+ }
128
+
129
+ if (!method) {
130
+ throw new InvalieParamsError(SCOPE, 'invalid request method')
160
131
  }
161
132
 
162
133
  // @ts-ignore
163
134
 
164
135
  try {
165
136
  const res = await new Promise((resolve, reject) => {
166
- const params = { url, method, header, data, timeout, dataType, responseType, ...restOptions }
137
+ const params = {
138
+ url,
139
+ method,
140
+ header,
141
+ data: serializeRequestBody(header, data),
142
+ timeout,
143
+ dataType,
144
+ responseType,
145
+ ...restOptions,
146
+ }
147
+
148
+ /**
149
+ * 非 buffer
150
+ */
151
+ if (params.data !== undefined && !isBuffer(params.data)) {
152
+ if (typeof params.data !== 'string' && method === 'GET') {
153
+ try {
154
+ const list = Object.entries(params.data || {}).reduce(
155
+ (list, [key, value]: [string, string | number | boolean]) => {
156
+ list.push(`${encodeURIComponent(key)}=${encodeURIComponent(String(value))}`)
157
+ return list
158
+ },
159
+ [],
160
+ )
161
+ if (list.length) {
162
+ params.data = list.join('&')
163
+ }
164
+ } catch (e) {}
165
+ }
166
+
167
+ if (method === 'GET' && typeof params.data === 'string') {
168
+ const parsedUrl = parseURL(url)
169
+ if (parsedUrl.search) {
170
+ parsedUrl.search += params.data
171
+ } else {
172
+ parsedUrl.search = `?${params.data}`
173
+ }
174
+ params.url = parsedUrl.href
175
+ params.data = undefined
176
+ }
177
+ }
178
+
179
+ if (
180
+ data
181
+ && (isBuffer(params.data) || typeof params.data === 'string')
182
+ && (data as any)?.length > 1000 * 1024 * 10
183
+ ) {
184
+ reject(new InvalieParamsError(SCOPE, 'body too large'))
185
+ return
186
+ }
167
187
 
168
188
  callContainer({
169
189
  ...params,
170
190
  success: resolve,
171
191
  fail: (res) => {
172
192
  const { data } = res || {}
173
- const error = new Error(data?.message || 'call container error')
174
- ;(error as any).code = data?.code || 'UNKNOWN_ERROR'
175
- reject(error)
193
+ reject(genContainerError(data, SCOPE, 'call container error'))
176
194
  },
177
195
  })
178
196
  })
@@ -182,7 +200,7 @@ class CloudbaseContainers {
182
200
  }
183
201
  }
184
202
 
185
- async initContainer(config: Omit<IContianerConfig, 'wasmUrl'>) {
203
+ async initContainer(config: Omit<IContianerConfig, 'wasmUrl' | 'jsUrl'>) {
186
204
  const { initContainer }: { initContainer: (options: IInitTcbContainerOptions) => void } = (await this.wasm) as any
187
205
  if (!this.containerInitPromise) {
188
206
  this.containerInitPromise = new Promise((resolve, reject) => {
@@ -190,18 +208,12 @@ class CloudbaseContainers {
190
208
  config,
191
209
  success(res) {
192
210
  if (String(res.statusCode) !== '200') {
193
- reject(new Error(JSON.stringify({
194
- code: 'INIT_ERROR',
195
- msg: `[${COMPONENT_NAME}] ${res.statusCode} ${JSON.stringify(res.data)}`,
196
- }),),)
211
+ reject(genContainerError(res.data, `${COMPONENT_NAME}.initContainer`, 'init container fail'))
197
212
  }
198
213
  resolve(res)
199
214
  },
200
215
  fail(res) {
201
- reject(new Error(JSON.stringify({
202
- code: 'INIT_ERROR',
203
- msg: `[${COMPONENT_NAME}] ${JSON.stringify(res.data)}`,
204
- }),),)
216
+ reject(genContainerError(res.data, `${COMPONENT_NAME}.initContainer`, 'init container fail'))
205
217
  this._containerInitPromis = null
206
218
  },
207
219
  })
@@ -294,7 +306,10 @@ async function getExportFunction(url, module, mode = 'go') {
294
306
  }, 500),),
295
307
  ])
296
308
 
297
- return { callContainer: (window as any).callContainer, initContainer: (window as any).initContainer }
309
+ return {
310
+ callContainer: (window as any).callContainer,
311
+ initContainer: (window as any).initContainer,
312
+ }
298
313
  }
299
314
 
300
315
  // if (mode === 'go') {
@@ -306,21 +321,42 @@ async function getExportFunction(url, module, mode = 'go') {
306
321
  return reuslt.instance.exports
307
322
  }
308
323
 
324
+ function loadUmdModule(jsUrl: string, umdModuleName: string, targetDoc: Document = document) {
325
+ return new Promise<any>((resolve, reject) => {
326
+ const win = targetDoc.defaultView
327
+
328
+ const script = targetDoc.createElement('script')
329
+ script.setAttribute('src', jsUrl)
330
+ script.setAttribute('class', umdModuleName)
331
+ script.addEventListener('load', () => {
332
+ if (Object.prototype.hasOwnProperty.call(win, umdModuleName)) {
333
+ return resolve(win[umdModuleName as any])
334
+ }
335
+ const error = new Error(`Fail to load UMD module ${umdModuleName} from [${jsUrl}].`)
336
+ return reject(error)
337
+ })
338
+
339
+ script.addEventListener('error', (e) => {
340
+ const error = new Error(`main bundle [${umdModuleName}] load failed from [${jsUrl}]: ${e?.message || ''}`)
341
+ reject(error)
342
+ })
343
+ targetDoc.body.appendChild(script)
344
+ })
345
+ }
346
+
347
+ async function loadJSExportFunction(url) {
348
+ return loadUmdModule(url, 'cloudbase_private_link')
349
+ }
350
+
309
351
  function isBrotliCompressed(url) {
310
352
  let brotliCompressed = false
311
353
 
312
354
  let pathname = ''
313
355
  try {
314
- const a = document.createElement('a')
315
- a.href = url
316
- pathname = a.pathname
356
+ const location = parseURL(url)
357
+ pathname = location.pathname
317
358
  } catch (e) {
318
- try {
319
- const res = new URL(url)
320
- pathname = res?.pathname
321
- } catch (e) {
322
- pathname = url
323
- }
359
+ pathname = url
324
360
  }
325
361
 
326
362
  if (/\.br$/.test(pathname)) {
@@ -0,0 +1,60 @@
1
+ import { constants } from '@cloudbase/utilities'
2
+ import { COMPONENT_NAME } from '../constants'
3
+ const { ERRORS } = constants
4
+
5
+ export function parseURL(_url: string) {
6
+ if (document) {
7
+ const a = document.createElement('a')
8
+ a.href = _url
9
+ return a
10
+ }
11
+ return new URL(new Request(_url).url)
12
+ }
13
+
14
+ export function isBuffer(buf: any) {
15
+ return buf instanceof ArrayBuffer || ArrayBuffer.isView(buf)
16
+ }
17
+
18
+ export function serializeRequestBody<T>(headers, data: T): T | string {
19
+ let res: T | string = data
20
+ const contentType_key = 'Content-Type'
21
+ if (typeof data === 'object' && !isBuffer(data)) {
22
+ if (!headers[contentType_key] && !headers['content-type']) {
23
+ headers[contentType_key] = 'application/json'
24
+ }
25
+
26
+ const contentType = headers[contentType_key] || headers['content-type']
27
+
28
+ switch (contentType) {
29
+ case 'application/json': {
30
+ try {
31
+ res = JSON.stringify(data)
32
+ } catch (e) {
33
+ throw new Error(JSON.stringify({
34
+ code: ERRORS.INVALID_PARAMS,
35
+ msg: `[${COMPONENT_NAME}.callContainer] invalid data with content-type: application/json, ${e.message}`,
36
+ }),)
37
+ }
38
+ break
39
+ }
40
+ case 'application/x-www-form-urlencoded': {
41
+ try {
42
+ const list = Object.entries(data || {}).reduce((list, [key, value]: [string, string]) => {
43
+ list.push(`${encodeURIComponent(key)}=${encodeURIComponent(value)}`)
44
+ return list
45
+ }, [])
46
+ if (list.length) {
47
+ res = list.join('&')
48
+ }
49
+ } catch (e) {
50
+ throw new Error(JSON.stringify({
51
+ code: ERRORS.INVALID_PARAMS,
52
+ msg: `[${COMPONENT_NAME}.callContainer] invalid data with content-type: application/x-www-form-urlencoded,${e.message}`,
53
+ }),)
54
+ }
55
+ break
56
+ }
57
+ }
58
+ }
59
+ return res
60
+ }
@@ -0,0 +1,74 @@
1
+ import { constants } from '@cloudbase/utilities'
2
+ import { COMPONENT_NAME } from '../constants'
3
+ import { serializeRequestBody } from './index'
4
+ const { getSdkName, ERRORS } = constants
5
+
6
+ interface IRequestPorps {
7
+ url: string
8
+ data?: string | object | ArrayBuffer
9
+ header?: Record<string, string>
10
+ timeout?: number
11
+ method?: string
12
+ dataType?: 'json' | string
13
+ responseType?: 'text' | 'arrayBuffer'
14
+ mode?: 'cors' | 'no-cors' | 'same-origin'
15
+ }
16
+
17
+ /**
18
+ * 封装对齐 wx.request
19
+ */
20
+ export async function request({
21
+ url,
22
+ method = 'GET',
23
+ header = {},
24
+ data,
25
+ timeout = 60000,
26
+ dataType = 'json',
27
+ responseType = 'text',
28
+ mode,
29
+ }: IRequestPorps) {
30
+ const headers = { ...header }
31
+
32
+ data = serializeRequestBody(headers, data)
33
+
34
+ const abortController = new AbortController()
35
+ let done = false
36
+ return Promise.race([
37
+ new Promise((_, reject) => {
38
+ setTimeout(() => {
39
+ const error = new Error('请求超时')
40
+ ;(error as any).code = 'SERVER_TIMEOUT'
41
+ if (!done) {
42
+ abortController.abort?.()
43
+ }
44
+ reject(error)
45
+ }, timeout)
46
+ }),
47
+ fetch(url, {
48
+ method,
49
+ headers,
50
+ body: data as any,
51
+ signal: abortController.signal,
52
+ mode,
53
+ }).then(
54
+ (response) => {
55
+ done = true
56
+ if (responseType === 'arrayBuffer') {
57
+ return response.arrayBuffer()
58
+ }
59
+ if (dataType === 'json') {
60
+ try {
61
+ return response.json()
62
+ } catch (e) {
63
+ throw new Error(`[${getSdkName()}][${ERRORS.INVALID_PARAMS}][${COMPONENT_NAME}.callContainer] response data must be json`,)
64
+ }
65
+ }
66
+ return response.text()
67
+ },
68
+ (e) => {
69
+ done = true
70
+ throw e
71
+ },
72
+ ),
73
+ ])
74
+ }