├── .commitlintrc.js ├── .eslintignore ├── .eslintrc.js ├── .gitignore ├── .npmignore ├── CHANGELOG.md ├── LICENSE ├── Open Source Notice.txt ├── README.md ├── README_zh.md ├── babel.config.js ├── jest.config.js ├── package.json ├── src ├── base │ ├── fetch.ts │ ├── service.ts │ ├── sign.ts │ ├── sts2.ts │ ├── types.ts │ └── utils.ts ├── index.ts ├── services │ ├── acep │ │ ├── demo.js │ │ ├── index.ts │ │ └── types.ts │ ├── billing │ │ ├── demo.js │ │ ├── index.ts │ │ └── types.ts │ ├── cdn │ │ ├── demo.js │ │ └── index.ts │ ├── edit │ │ ├── demo.js │ │ ├── index.ts │ │ └── types.ts │ ├── i18nOpenapi │ │ ├── demo.js │ │ ├── index.ts │ │ └── types.ts │ ├── iam │ │ ├── README.md │ │ ├── demo.js │ │ └── index.ts │ ├── imagex │ │ ├── client.ts │ │ ├── demo.js │ │ ├── index.ts │ │ ├── type.ts │ │ └── types.ts │ ├── live │ │ ├── const.ts │ │ ├── demo.js │ │ └── index.ts │ ├── livesaas │ │ ├── const.ts │ │ ├── demo.js │ │ └── index.ts │ ├── maas │ │ ├── demo.js │ │ ├── error.ts │ │ ├── index.ts │ │ ├── types.ts │ │ └── v2 │ │ │ ├── demo.js │ │ │ ├── index.ts │ │ │ └── types.ts │ ├── rocketmq │ │ ├── Client.ts │ │ ├── Consumer.ts │ │ ├── Producer.ts │ │ ├── Worker.ts │ │ ├── index.ts │ │ ├── protocol │ │ │ ├── errors.ts │ │ │ └── v1.ts │ │ ├── types.ts │ │ └── utils │ │ │ ├── agent.ts │ │ │ ├── common.ts │ │ │ ├── error.ts │ │ │ ├── logger.ts │ │ │ └── request.ts │ ├── rtc │ │ ├── README.md │ │ ├── demo.js │ │ ├── index.ts │ │ └── types.ts │ ├── sms │ │ ├── demo.js │ │ ├── index.ts │ │ └── types.ts │ ├── sts │ │ ├── README.md │ │ └── index.ts │ ├── tls │ │ ├── README.md │ │ ├── demo.js │ │ ├── example │ │ │ ├── hostGroup.demo.js │ │ │ ├── index.demo.js │ │ │ ├── log.demo.js │ │ │ ├── project.demo.js │ │ │ └── topic.demo.js │ │ ├── index.ts │ │ ├── lz4.js │ │ ├── service.ts │ │ ├── tls.proto │ │ ├── types.ts │ │ └── utils.ts │ ├── vikingdb │ │ ├── abstractService.ts │ │ ├── collection │ │ │ ├── backend.ts │ │ │ ├── index.ts │ │ │ ├── pathname.ts │ │ │ └── types.ts │ │ ├── custom │ │ │ ├── index.ts │ │ │ └── types.ts │ │ ├── data │ │ │ ├── backend.ts │ │ │ ├── index.ts │ │ │ ├── pathname.ts │ │ │ └── types.ts │ │ ├── embedding │ │ │ ├── backend.ts │ │ │ ├── index.ts │ │ │ ├── pathname.ts │ │ │ └── types.ts │ │ ├── index.ts │ │ ├── index │ │ │ ├── backend.ts │ │ │ ├── index.ts │ │ │ ├── pathname.ts │ │ │ └── types.ts │ │ ├── search │ │ │ ├── backend.ts │ │ │ ├── index.ts │ │ │ ├── pathname.ts │ │ │ └── types.ts │ │ ├── task │ │ │ ├── backend.ts │ │ │ ├── index.ts │ │ │ ├── pathname.ts │ │ │ └── types.ts │ │ └── types.ts │ └── vod │ │ ├── constants.ts │ │ ├── demo.js │ │ ├── index.ts │ │ └── types.ts └── typings.d.ts ├── test ├── acep.test.js ├── billing.test.js ├── edit.test.js ├── i18nOpenapi.test.js ├── iam.test.js ├── imagex.test.js ├── imagex_test_pic.png ├── live.test.js ├── livesaas.test.js ├── maas.test.js ├── rocketmq.test.js ├── rtc.test.js ├── schema │ ├── acep.js │ ├── billing.js │ ├── edit.js │ ├── i18nOpenapi.js │ ├── iam.js │ ├── imagex.js │ ├── live.js │ ├── livesaas.js │ ├── maas.js │ ├── response.js │ ├── rtc.js │ ├── sms.js │ ├── tls.js │ └── vod │ │ ├── index.js │ │ └── schema.js ├── service.test.js ├── sign.test.ts ├── sms.test.js ├── tls.test.js └── vod.test.js └── tsconfig.json /.commitlintrc.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | extends: [ 3 | '@commitlint/config-conventional' 4 | ], 5 | rules: { 6 | } 7 | }; -------------------------------------------------------------------------------- /.eslintignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | lib 3 | src/services/tls/lz4.js -------------------------------------------------------------------------------- /.eslintrc.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | parser: "@typescript-eslint/parser", 3 | extends: [ 4 | "eslint:recommended", 5 | "plugin:@typescript-eslint/recommended", 6 | "prettier/@typescript-eslint", 7 | "plugin:prettier/recommended", 8 | ], 9 | plugins: ["@typescript-eslint", "jest", "babel"], 10 | parserOptions: { 11 | ecmaVersion: 2018, 12 | ecmaFeatures: { 13 | experimentalObjectRestSpread: true, 14 | jsx: true, 15 | }, 16 | sourceType: "module", 17 | }, 18 | env: { 19 | browser: true, 20 | node: true, 21 | commonjs: true, 22 | es6: true, 23 | "jest/globals": true, 24 | }, 25 | globals: {}, 26 | rules: { 27 | // Place to specify ESLint rules. Can be used to overwrite rules specified from the extended configs 28 | // e.g. "@typescript-eslint/explicit-function-return-type": "off", 29 | "@typescript-eslint/explicit-member-accessibility": "off", 30 | "@typescript-eslint/no-unused-vars": "error", 31 | "@typescript-eslint/camelcase": "off", 32 | "@typescript-eslint/no-empty-interface": "warn", 33 | "@typescript-eslint/explicit-module-boundary-types": "off", 34 | "prettier/prettier": ["error", { trailingComma: "es5", printWidth: 100 }], 35 | "linebreak-style": ["error", "unix"], 36 | "no-console": ["error", { allow: ["warn", "error"] }], 37 | "no-case-declarations": 0, 38 | "no-param-reassign": 0, 39 | "no-underscore-dangle": 0, 40 | "no-useless-constructor": 0, 41 | "no-use-before-define": ["error", { functions: false, classes: false }], 42 | "no-unused-vars": [2, { vars: "all", args: "none" }], 43 | "no-restricted-syntax": 0, 44 | "no-plusplus": 0, 45 | "no-return-assign": 0, 46 | "no-script-url": 0, 47 | "no-extend-native": 0, 48 | "no-restricted-globals": 0, 49 | "no-nested-ternary": 0, 50 | "no-empty": 0, 51 | "no-void": 0, 52 | "no-useless-escape": 0, 53 | "no-bitwise": 0, 54 | "no-mixed-operators": 0, 55 | "consistent-return": 0, 56 | "one-var": 0, 57 | "prefer-promise-reject-errors": 0, 58 | "prefer-destructuring": 0, 59 | "global-require": 0, 60 | "guard-for-in": 0, 61 | "func-names": 0, 62 | strict: 0, 63 | radix: 0, 64 | "no-prototype-builtins": 0, 65 | "class-methods-use-this": 0, 66 | "import/no-dynamic-require": 0, 67 | "import/no-unresolved": 0, 68 | "import/extensions": 0, 69 | "import/no-extraneous-dependencies": 0, 70 | "import/prefer-default-export": 0, 71 | "jsx-a11y/anchor-is-valid": 0, 72 | "jsx-a11y/no-static-element-interactions": 0, 73 | "jsx-a11y/click-events-have-key-events": 0, 74 | "jsx-a11y/no-noninteractive-element-interactions": 0, 75 | "jsx-a11y/alt-text": 0, 76 | "jsx-a11y/label-has-for": 0, 77 | "jsx-a11y/label-has-associated-control": 0, 78 | "array-callback-return": 0, 79 | "no-cond-assign": 0, 80 | "@typescript-eslint/explicit-function-return-type": 0, 81 | "@typescript-eslint/no-use-before-define": 0, 82 | "@typescript-eslint/no-var-requires": 0, 83 | "@typescript-eslint/no-empty-function": 0, 84 | "no-shadow": 0, 85 | "no-continue": 0, 86 | "no-loop-func": 0, 87 | "prefer-spread": 0, 88 | }, 89 | overrides: [ 90 | { 91 | files: ["*.js"], 92 | rules: { 93 | "@typescript-eslint/camelcase": "off", 94 | "@typescript-eslint/no-var-requires": "off", 95 | }, 96 | }, 97 | ], 98 | }; 99 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | lib 3 | .idea/ 4 | *.lock -------------------------------------------------------------------------------- /.npmignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | .eslintignore 3 | .eslintrc.js 4 | .gitignore 5 | .commitlintrc 6 | .idea 7 | babel.config.js 8 | tsconfig.json 9 | src 10 | test 11 | *.lock -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Volcano Engine OpenAPI node sdk 2 | 3 | [中文文档](./README_zh.md) 4 | 5 | ## Requirements: 6 | 7 | - Node.js >= 12 8 | 9 | ## Installation 10 | ```shell 11 | npm install -S @volcengine/openapi 12 | ``` 13 | 14 | ## Basic Usage 15 | 16 | ### 1. Setting OpenAPI service's AK&SK 17 | 18 | Available in three settings 19 | 20 | #### 1. Use API to set AK&SK 21 | ```ts 22 | // Use the default service instance. You can also create a new instance. 23 | // `const iamService = new iam.IamService();` 24 | const iamService = iam.defaultService; 25 | 26 | // set aksk 27 | iamService.setAccessKeyId(AccessKeyId); 28 | iamService.setSecretKey(SecretKey); 29 | // If you use sts to request, you need to set up `SessionToken` after aksk is set 30 | iamService.setSessionToken(SessionToken); 31 | ``` 32 | 33 | #### 2. Use environment variables to set AK & SK 34 | ```shell 35 | VOLC_ACCESSKEY="your ak" VOLC_SECRETKEY="your sk" 36 | ``` 37 | 38 | #### 3. Use configuration file 39 | Put it in `~/.volc/config` in json format, the format is: 40 | ``` 41 | {"VOLC_ACCESSKEY":"your ak","VOLC_SECRETKEY":"your sk"} 42 | ``` 43 | 44 | ## Request OpenAPI 45 | 46 | Take the ListUsers API of the iam service as an example 47 | 48 | ```ts 49 | import { iam } from'@volcengine/openapi'; 50 | 51 | async function main(AccessKeyId, SecretKey) { 52 | // Use the default service instance. You can also create a new instance. 53 | // `const iamService = new iam.IamService();` 54 | const iamService = iam.defaultService; 55 | 56 | // set aksk 57 | iamService.setAccessKeyId(AccessKeyId); 58 | iamService.setSecretKey(SecretKey); 59 | 60 | // Request OpenAPI 61 | const usersResponse = await iamService.ListUsers({ 62 | Limit: 10, 63 | Offset: 0, 64 | }); 65 | } 66 | ``` 67 | 68 | ## OpenAPI signature method 69 | 70 | ### By HTTP Header 71 | 72 | ```ts 73 | import {Signer} from '@volcengine/openapi'; 74 | 75 | // http request data 76 | const openApiRequestData: RequestObj = { 77 | region: 'cn-north-1', 78 | method: 'GET', 79 | // [optional] http request url query 80 | params: {}, 81 | // http request headers 82 | headers: {}, 83 | // [optional] http request body 84 | body: "", 85 | } 86 | 87 | const signer = new Signer(openApiRequestData, "iam"); 88 | 89 | // sign 90 | signer.addAuthorization({accessKeyId, secretKey, sessionToken}); 91 | 92 | // Print signed headers 93 | console.log(openApiRequestData.headers); 94 | ``` 95 | 96 | ### By HTTP Query 97 | 98 | ```ts 99 | const openApiRequestData: RequestObj = { 100 | method: "POST", 101 | region: "cn-north-1", 102 | params: { 103 | Action: "AssumeRole", 104 | Version: "2018-01-01", 105 | RoleTrn: "trn:iam::200:role/STSRole", 106 | RoleSessionName: "test", 107 | }, 108 | } 109 | 110 | const credentials: Credentials = { 111 | accessKeyId: VOLC_ACCESSKEY, 112 | secretKey: VOLC_SECRETKEY, 113 | sessionToken: "", 114 | } 115 | 116 | const signer = new Signer(openApiRequestData, "sts"); 117 | 118 | const signedQueryString = signer.getSignUrl(credentials); 119 | ``` -------------------------------------------------------------------------------- /README_zh.md: -------------------------------------------------------------------------------- 1 | # 火山引擎 OpenAPI node sdk 2 | 3 | ## 环境要求: 4 | 5 | - Node.js >= 12 6 | 7 | ## 安装 8 | 9 | ```shell 10 | npm install -S @volcengine/openapi 11 | ``` 12 | 13 | ## 基本用法 14 | 15 | ### 1. 配置 OpenAPI 服务的 AK&SK 16 | 17 | 提供三种设置方式 18 | 19 | #### 1. 使用 API 设置 AK&SK 20 | 21 | ``` 22 | // 使用默认的service实例。你也可以创建一个新实例。 23 | // `const iamService = new iam.IamService();` 24 | const iamService = iam.defaultService; 25 | 26 | // 设置aksk 27 | iamService.setAccessKeyId(AccessKeyId); 28 | iamService.setSecretKey(SecretKey); 29 | // 如果使用sts进行请求,设置完成aksk之后还需要设置一下`SessionToken` 30 | iamService.setSessionToken(SessionToken); 31 | ``` 32 | 33 | #### 2. 使用环境变量设置 AK&SK 34 | 35 | ``` 36 | VOLC_ACCESSKEY="your ak" VOLC_SECRETKEY="your sk" 37 | ``` 38 | 39 | #### 3. 使用配置文件 40 | 41 | 以json格式放在`~/.volc/config`中,格式为: 42 | 43 | ``` 44 | {"VOLC_ACCESSKEY":"your ak","VOLC_SECRETKEY":"your sk"} 45 | ``` 46 | 47 | ## 2. 接口调用 48 | 49 | 以调用`iam`服务的`ListUsers` API为例 50 | 51 | ``` 52 | import { iam } from '@volcengine/openapi'; 53 | 54 | async main(AccessKeyId, SecretKey) { 55 | // 使用默认的service实例。你也可以创建一个新实例。 56 | // `const iamService = new iam.IamService();` 57 | const iamService = iam.defaultService; 58 | 59 | // 设置aksk 60 | iamService.setAccessKeyId(AccessKeyId); 61 | iamService.setSecretKey(SecretKey); 62 | 63 | // 请求预定义的OpenAPI 64 | const usersResponse = await iamService.ListUsers({ 65 | Limit: 10, 66 | Offset: 0, 67 | }); 68 | } 69 | ``` 70 | 71 | ## OpenAPI 签名方法 72 | 73 | ### Header 方式 74 | ```ts 75 | import {Signer} from '@volcengine/openapi'; 76 | 77 | // 请求数据 78 | const openApiRequestData: RequestObj = { 79 | region: 'cn-north-1', 80 | method: 'GET', 81 | // [可选] http request url query 82 | params: {}, 83 | // http request headers 84 | headers: {}, 85 | // [可选] http request body 86 | body: "", 87 | } 88 | 89 | const signer = new Signer(openApiRequestData, "iam"); 90 | 91 | // 签名 92 | signer.addAuthorization({accessKeyId, secretKey, sessionToken}); 93 | 94 | // 打印签名后的 headers 95 | console.log(openApiRequestData.headers); 96 | ``` 97 | 98 | ### Query 方式 99 | 100 | ```ts 101 | import {Signer} from '@volcengine/openapi'; 102 | 103 | // 请求数据 104 | const openApiRequestData: RequestObj = { 105 | method: "POST", 106 | region: "cn-north-1", 107 | params: { 108 | Action: "AssumeRole", 109 | Version: "2018-01-01", 110 | RoleTrn: "trn:iam::200:role/STSRole", 111 | RoleSessionName: "test", 112 | }, 113 | } 114 | 115 | const credentials: Credentials = { 116 | accessKeyId: VOLC_ACCESSKEY, 117 | secretKey: VOLC_SECRETKEY, 118 | sessionToken: "", 119 | } 120 | 121 | const signer = new Signer(openApiRequestData, "sts"); 122 | 123 | // 最终经过加签的 HTTP Query Params 124 | const signedQueryString = signer.getSignUrl(credentials); 125 | ``` -------------------------------------------------------------------------------- /babel.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | presets: [["@babel/preset-env", { targets: { node: "current" } }], "@babel/preset-typescript"], 3 | }; 4 | -------------------------------------------------------------------------------- /jest.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | verbose: true, 3 | testTimeout: 1000 * 80, 4 | testRegex: `\/.*test\/.+\.(test|spec)\.(ts|js)$`, 5 | }; 6 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@volcengine/openapi", 3 | "version": "1.30.2", 4 | "description": "火山引擎OpenAPI SDK nodejs版", 5 | "main": "lib/index.js", 6 | "engines": { 7 | "node": ">=12" 8 | }, 9 | "scripts": { 10 | "cp:tls-proto": "cp src/services/tls/tls.proto lib/services/tls/tls.proto", 11 | "cp:tls-lz4": "cp src/services/tls/lz4.js lib/services/tls/lz4.js", 12 | "build": "rm -rf lib && tsc && yarn cp:tls-proto && yarn cp:tls-lz4", 13 | "lint": "eslint . --ext ts --fix --quiet", 14 | "dev": "tsc --watch", 15 | "dev:proxy": "VOLC_PROXY_PORT=8888 yarn dev", 16 | "test": "yarn build && jest --env=node", 17 | "test-mq": "jest ./test/rocketmq.test.js --env=node", 18 | "test-maas": "jest ./test/maas.test.js --env=node", 19 | "test-tls": "jest ./test/tls.test.js --env=node", 20 | "test-vod": "jest ./test/vod.test.js --env=node" 21 | }, 22 | "repository": { 23 | "type": "git", 24 | "url": "git@github.com:volcengine/volc-sdk-nodejs.git" 25 | }, 26 | "author": "", 27 | "license": "Apache-2.0", 28 | "devDependencies": { 29 | "@babel/preset-env": "^7.16.4", 30 | "@babel/preset-typescript": "^7.12.7", 31 | "@commitlint/cli": "^11.0.0", 32 | "@commitlint/config-conventional": "^11.0.0", 33 | "@types/ajv": "^1.0.0", 34 | "@types/crypto-js": "^4.2.0", 35 | "@types/debug": "^4.1.5", 36 | "@types/jest": "^26.0.19", 37 | "@types/node-fetch": "^2.5.7", 38 | "@typescript-eslint/eslint-plugin": "^4.10.0", 39 | "@typescript-eslint/parser": "^4.10.0", 40 | "ajv": "^7.0.2", 41 | "eslint": "^7.16.0", 42 | "eslint-config-prettier": "^4.3.0", 43 | "eslint-plugin-babel": "^5.3.1", 44 | "eslint-plugin-jest": "^22.6.4", 45 | "eslint-plugin-prettier": "^3.1.0", 46 | "eslint-plugin-react": "^7.18.3", 47 | "husky": "^4.3.6", 48 | "jest": "^26.6.3", 49 | "lodash.merge": "^4.6.2", 50 | "prettier": "^2.2.1", 51 | "typescript": "^4.1.3" 52 | }, 53 | "dependencies": { 54 | "axios": "^0.21.1", 55 | "crc": "^4.1.0", 56 | "crypto-js": "^4.2.0", 57 | "dayjs": "^1.11.5", 58 | "debug": "^4.3.1", 59 | "form-data": "^3.0.0", 60 | "lodash.get": "^4.4.2", 61 | "p-limit": "^3.0.0", 62 | "protobufjs": "7.2.5", 63 | "uuid": "^8.3.2" 64 | }, 65 | "husky": { 66 | "hooks": { 67 | "commit-msg": "commitlint -e $GIT_PARAMS", 68 | "pre-commit": "yarn lint" 69 | } 70 | } 71 | } 72 | -------------------------------------------------------------------------------- /src/base/fetch.ts: -------------------------------------------------------------------------------- 1 | import axios, { AxiosRequestConfig } from "axios"; 2 | import { createDebug, packageVersion } from "./utils"; 3 | import { OpenApiResponse } from "./types"; 4 | 5 | const debug = createDebug("fetch"); 6 | const ua = `volc-sdk-nodejs/v${packageVersion}`; 7 | 8 | export default async function request( 9 | url: string, 10 | reqInfo: AxiosRequestConfig 11 | ): Promise> { 12 | const { headers = {} } = reqInfo; 13 | const reqOption: AxiosRequestConfig = { 14 | url: url.trim(), 15 | timeout: 10000, 16 | ...reqInfo, 17 | proxy: process.env.VOLC_PROXY_PORT 18 | ? { 19 | protocol: "http", 20 | host: process.env.VOLC_PROXY_HOST || "127.0.0.1", 21 | port: +process.env.VOLC_PROXY_PORT, 22 | } 23 | : undefined, 24 | headers: { 25 | "Content-Type": "application/x-www-form-urlencoded", 26 | ...headers, 27 | "User-Agent": ua, 28 | }, 29 | validateStatus: null, 30 | }; 31 | debug("fetch begin. options: %j", reqOption); 32 | const res = await axios(reqOption); 33 | const body = res.data; 34 | debug("fetch end. headers: %j response: %j", res.headers, body); 35 | return body; 36 | } 37 | -------------------------------------------------------------------------------- /src/base/sts2.ts: -------------------------------------------------------------------------------- 1 | import { InnerToken, ServiceOptions, SecurityToken2, Policy } from "./types"; 2 | import { v4 as uuidv4 } from "uuid"; 3 | import crypto from "crypto"; 4 | 5 | const LETTERS = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"; 6 | 7 | function base64(str: string): string { 8 | return Buffer.from(str).toString("base64"); 9 | } 10 | 11 | function randStringRunes(n: number): string { 12 | const arr: string[] = []; 13 | for (let i = 0; i < n; i++) { 14 | arr.push(LETTERS[Math.floor(Math.random() * 32)]); 15 | } 16 | return arr.join(""); 17 | } 18 | 19 | function GenerateAccessKeyId(prefix: string): string { 20 | const uid = uuidv4(); 21 | const uidBase64 = base64(uid.replace(/-/g, "")).replace(/=|\/|\+|-/g, ""); 22 | return prefix + uidBase64; 23 | } 24 | 25 | function toBuffer(x: any) { 26 | if (x instanceof Buffer) return x; 27 | return Buffer.from(x, "utf8"); 28 | } 29 | 30 | function ZeroPadding(data, blockSize: number) { 31 | const padding = blockSize - (data.length % blockSize); 32 | if (padding === 0) { 33 | return data; 34 | } 35 | const buff = Buffer.alloc(padding); 36 | const totalLength = data.length + padding; 37 | return Buffer.concat([data, buff], totalLength); 38 | } 39 | 40 | function AesEncryptCBCWithBase64(data, key) { 41 | if ([16, 24, 32].indexOf(key.length) < 0) { 42 | throw new Error("aes cbc block size must be 16|24|32 bytes"); 43 | } 44 | 45 | data = toBuffer(data); 46 | 47 | key = toBuffer(key); 48 | 49 | const blocksize = key.length; 50 | const iv = key; 51 | const cipher = crypto.createCipheriv(`aes-128-cbc`, key, iv); 52 | const finaldata = ZeroPadding(data, blocksize); 53 | 54 | let encrypted = cipher.update(finaldata); 55 | const final = cipher.final(); 56 | encrypted = Buffer.concat([encrypted, final], encrypted.length + final.length); 57 | return Buffer.from(encrypted).toString("base64"); 58 | } 59 | 60 | function GenerateSecretKey(): string { 61 | const randomString = randStringRunes(32); 62 | return AesEncryptCBCWithBase64(randomString, "volcenginenodejs"); 63 | } 64 | 65 | function CreateTempAKSK(): { AccessKeyId: string; SecretAccessKey: string } { 66 | return { 67 | AccessKeyId: GenerateAccessKeyId("AKTP"), 68 | SecretAccessKey: GenerateSecretKey(), 69 | }; 70 | } 71 | 72 | function hmac(type: string, str: string, secret): string { 73 | return crypto.createHmac(type, secret).update(str).digest("hex"); 74 | } 75 | 76 | function hash(type, str: string) { 77 | return crypto.createHash(type).update(str).digest(); 78 | } 79 | 80 | function CreateInnerToken( 81 | config: ServiceOptions, 82 | sts: SecurityToken2, 83 | inlinePolicy: Policy | undefined, 84 | t: number 85 | ): InnerToken { 86 | const key = hash("md5", config.secretKey as string); 87 | 88 | let SignedSecretAccessKey = AesEncryptCBCWithBase64(sts.SecretAccessKey, key); 89 | SignedSecretAccessKey = SignedSecretAccessKey.slice(0, -24); 90 | 91 | const signStr = Object.values({ 92 | LTAccessKeyId: config.accessKeyId, 93 | AccessKeyId: sts.AccessKeyId, 94 | ExpiredTime: t, 95 | SignedSecretAccessKey, 96 | PolicyString: inlinePolicy ? JSON.stringify(inlinePolicy) : "", 97 | }).join("|"); 98 | 99 | return { 100 | LTAccessKeyId: config.accessKeyId as string, 101 | AccessKeyId: sts.AccessKeyId, 102 | SignedSecretAccessKey, 103 | ExpiredTime: t, 104 | PolicyString: inlinePolicy ? JSON.stringify(inlinePolicy) : "", 105 | Signature: hmac("sha256", signStr, key), 106 | }; 107 | } 108 | 109 | export { CreateInnerToken, CreateTempAKSK, base64 }; 110 | -------------------------------------------------------------------------------- /src/base/types.ts: -------------------------------------------------------------------------------- 1 | import { Method } from "axios"; 2 | export interface OpenApiError { 3 | Code?: string; 4 | Message: string; 5 | CodeN?: number; 6 | } 7 | export interface OpenApiResponseMetadataParams { 8 | RequestId?: string; 9 | Action?: string; 10 | Version?: string; 11 | Service?: string; 12 | Region?: string; 13 | Error?: OpenApiError; 14 | } 15 | export interface OpenApiResponseMetadata extends OpenApiResponseMetadataParams { 16 | RequestId: string; 17 | Service: string; 18 | } 19 | export interface OpenApiResponse { 20 | ResponseMetadata: OpenApiResponseMetadata; 21 | Result?: T; 22 | } 23 | 24 | export interface STS { 25 | /** 26 | * create time of STS. unix timestamp. 27 | */ 28 | CurrentTime: string | number; 29 | /** 30 | * expire time of STS. unix timestamp. 31 | */ 32 | ExpiredTime: string | number; 33 | AccessKeyId: string; 34 | SecretKey: string; 35 | SessionToken: string; 36 | } 37 | export interface RequestObj { 38 | region: string; 39 | method: string; 40 | params?: any; 41 | pathname?: string; 42 | headers?: any; 43 | body?: any; 44 | } 45 | export interface SignerOptions { 46 | bodySha256?: string; 47 | } 48 | export interface CredentialsBase { 49 | accessKeyId?: string; 50 | secretKey?: string; 51 | sessionToken?: string; 52 | } 53 | export interface Credentials extends CredentialsBase { 54 | accessKeyId: string; 55 | secretKey: string; 56 | } 57 | export interface ServiceOptionsBase extends CredentialsBase { 58 | /** 59 | * openpai host default is 'cn-north-1' 60 | */ 61 | region?: string; 62 | /** 63 | * openpai host default is 'open.volcengineapi.com' 64 | */ 65 | host?: string; 66 | serviceName?: string; 67 | /** 68 | * openpai host default is 'http' 69 | */ 70 | protocol?: string; 71 | /** 72 | * default open api version of this service 73 | */ 74 | defaultVersion?: string; 75 | } 76 | export interface ServiceOptions extends ServiceOptionsBase { 77 | serviceName: string; 78 | } 79 | export interface FetchParams { 80 | Action: string; 81 | Version?: string; 82 | query?: any; 83 | pathname?: string; 84 | } 85 | export interface CreateAPIParams { 86 | /** 87 | * OpenAPI Version. If not provide, will use service defaultVersion. 88 | */ 89 | Version?: string; 90 | /** 91 | * http method like GET POST PUT 92 | */ 93 | method?: Method; 94 | /** 95 | * body content type. support: json urlencode form-data 96 | */ 97 | contentType?: "json" | "urlencode" | "form-data"; 98 | /** 99 | * keys in query 100 | */ 101 | queryKeys?: string[]; 102 | } 103 | 104 | export interface Statement { 105 | Effect: string; 106 | Action: string[]; 107 | Resource: string[]; 108 | Condition?: string; 109 | } 110 | 111 | export interface Policy { 112 | Statement: Statement[]; 113 | } 114 | 115 | export interface SecurityToken2 { 116 | AccessKeyId: string; 117 | SecretAccessKey: string; 118 | CurrentTime?: string; 119 | ExpiredTime?: string; 120 | SessionToken?: string; 121 | } 122 | 123 | export interface InnerToken { 124 | LTAccessKeyId: string; 125 | AccessKeyId: string; 126 | SignedSecretAccessKey: string; 127 | ExpiredTime: number; 128 | PolicyString: string; 129 | Signature: string; 130 | } 131 | -------------------------------------------------------------------------------- /src/base/utils.ts: -------------------------------------------------------------------------------- 1 | import debug from "debug"; 2 | import fs from "fs"; 3 | import path from "path"; 4 | import packageInfo from "../../package.json"; 5 | export const packageName = packageInfo.name; 6 | export const packageVersion = packageInfo.version; 7 | export function createDebug(moduleName: string): debug.Debugger { 8 | return debug(`${packageName}:${moduleName}`); 9 | } 10 | export function getDefaultOption() { 11 | const defaultOptions = { 12 | host: "open.volcengineapi.com", 13 | region: "cn-north-1", 14 | protocol: "https:", 15 | // Read aksk by environment variables 16 | accessKeyId: process.env.VOLC_ACCESSKEY, 17 | secretKey: process.env.VOLC_SECRETKEY, 18 | }; 19 | try { 20 | // Read aksk from ~/.volc/config. Priority is lower than environment variables 21 | if (process.env.HOME && !(defaultOptions.accessKeyId && defaultOptions.secretKey)) { 22 | const homeConfigPath = path.resolve(process.env.HOME, ".volc/config"); 23 | if (fs.existsSync(homeConfigPath)) { 24 | const configData = JSON.parse(fs.readFileSync(homeConfigPath, { encoding: "utf-8" })); 25 | if (!defaultOptions.accessKeyId && configData.VOLC_ACCESSKEY) { 26 | defaultOptions.accessKeyId = configData.VOLC_ACCESSKEY; 27 | } 28 | if (!defaultOptions.secretKey && configData.VOLC_SECRETKEY) { 29 | defaultOptions.secretKey = configData.VOLC_SECRETKEY; 30 | } 31 | } 32 | } 33 | } catch {} 34 | return defaultOptions; 35 | } 36 | -------------------------------------------------------------------------------- /src/index.ts: -------------------------------------------------------------------------------- 1 | import Service from "./base/service"; 2 | import Signer from "./base/sign"; 3 | import * as iam from "./services/iam"; 4 | import * as imagex from "./services/imagex"; 5 | import * as edit from "./services/edit"; 6 | import * as i18nOpenapi from "./services/i18nOpenapi"; 7 | import * as acep from "./services/acep"; 8 | import * as rtcOpenapi from "./services/rtc"; 9 | import * as vodOpenapi from "./services/vod"; 10 | import * as tlsOpenapi from "./services/tls"; 11 | import * as liveOpenapi from "./services/live"; 12 | import * as livesaasOpenapi from "./services/livesaas"; 13 | import * as rocketmq from "./services/rocketmq"; 14 | import * as billing from "./services/billing"; 15 | import * as sts from "./services/sts"; 16 | import * as cdn from "./services/cdn"; 17 | import * as sms from "./services/sms"; 18 | import * as maas from "./services/maas"; 19 | import * as vikingdb from "./services/vikingdb"; 20 | 21 | export { 22 | Service, 23 | Signer, 24 | iam, 25 | imagex, 26 | edit, 27 | i18nOpenapi, 28 | acep, 29 | rtcOpenapi, 30 | vodOpenapi, 31 | tlsOpenapi, 32 | liveOpenapi, 33 | livesaasOpenapi, 34 | rocketmq, 35 | billing, 36 | sts, 37 | cdn, 38 | sms, 39 | maas, 40 | vikingdb, 41 | }; 42 | -------------------------------------------------------------------------------- /src/services/acep/demo.js: -------------------------------------------------------------------------------- 1 | import { acep } from "@volcengine/openapi"; 2 | 3 | export async function main() { 4 | const newService = acep; 5 | const res = await newService.GetListPod({ 6 | product_id: '1426095758716702720' 7 | }) 8 | console.log(res) 9 | } 10 | -------------------------------------------------------------------------------- /src/services/acep/index.ts: -------------------------------------------------------------------------------- 1 | import Service from "../../base/service"; 2 | import { ServiceOptions } from "../../base/types"; 3 | import { 4 | IGetListPodParams, 5 | IListPodResult, 6 | IPodStartParams, 7 | IPodStartResult, 8 | IPodStopParams, 9 | IPodStopResult, 10 | } from "./types"; 11 | 12 | export class ACEPService extends Service { 13 | constructor(options?: ServiceOptions) { 14 | super({ 15 | ...options, 16 | defaultVersion: "2020-10-25", 17 | serviceName: "ACEP", 18 | }); 19 | } 20 | GetListPod = this.createAPI("ListPod"); 21 | PodStart = this.createAPI("PodStart", { 22 | method: "POST", 23 | contentType: "json", 24 | }); 25 | PodStop = this.createAPI("PodStop", { 26 | method: "POST", 27 | contentType: "json", 28 | }); 29 | } 30 | 31 | export const defaultService = new ACEPService(); 32 | -------------------------------------------------------------------------------- /src/services/acep/types.ts: -------------------------------------------------------------------------------- 1 | export interface ResponseMetadata { 2 | Action: string; 3 | Region: string; 4 | RequestId: string; 5 | Service: string; 6 | Version: string; 7 | } 8 | 9 | export interface Launcher { 10 | id: number; 11 | package_name: string; 12 | version_code: number; 13 | download_url: string; 14 | md5: string; 15 | status: number; 16 | product_type_list?: any; 17 | launcher_name: string; 18 | } 19 | 20 | export interface Product { 21 | product_id: string; 22 | product_type: number; 23 | product_name: string; 24 | account_id: number; 25 | owner_list: string; 26 | width: number; 27 | height: number; 28 | density: number; 29 | launcher_id: number; 30 | audit_status: number; 31 | rtc_app_id: string; 32 | rtc_app_key: string; 33 | create_at: number; 34 | description: string; 35 | media_service_id: number; 36 | media_service_name: string; 37 | user_name: string; 38 | user_list?: any; 39 | launcher: Launcher; 40 | } 41 | 42 | export interface Row { 43 | pod_id: string; 44 | pod_name?: any; 45 | product_id: string; 46 | group_id: string; 47 | instance_no: string; 48 | business_id: string; 49 | user_id: string; 50 | sn: string; 51 | ip: string; 52 | host_ip: string; 53 | status: number; 54 | width: number; 55 | height: number; 56 | dc: string; 57 | type: number; 58 | cpu: number; 59 | cpu_core: number; 60 | size: number; 61 | available_size: number; 62 | memory: number; 63 | sdk: number; 64 | package_id: string; 65 | online_time: number; 66 | online: number; 67 | room_id: string; 68 | expire_at: number; 69 | product: Product; 70 | app_id?: any; 71 | } 72 | 73 | export interface ITheListPodResult { 74 | row: Row[]; 75 | total: number; 76 | } 77 | 78 | export interface IListPodResult { 79 | ResponseMetadata: ResponseMetadata; 80 | Result: ITheListPodResult; 81 | } 82 | 83 | export interface IGetListPodParams { 84 | product_id?: string; 85 | pod_id?: string; 86 | offset?: number; 87 | count?: number; 88 | } 89 | export interface IPodStartParams { 90 | product_id: string; 91 | pod_id?: string; 92 | app_id?: string; 93 | client_user_id: string; 94 | } 95 | export interface IThePodStartResult { 96 | pod_id: string; 97 | rtc_app_id: string; 98 | client_user_id: string; 99 | pod_user_id: string; 100 | room_id: string; 101 | token: string; 102 | width: number; 103 | height: number; 104 | rotation: 0 | 270; 105 | fps: number; 106 | kbps: number; 107 | } 108 | export interface IPodStartResult { 109 | ResponseMetadata: ResponseMetadata; 110 | Result: IThePodStartResult; 111 | } 112 | 113 | export interface IPodStopParams { 114 | pod_id: string; 115 | } 116 | 117 | export interface IPodStopResult { 118 | ResponseMetadata: ResponseMetadata; 119 | Result: null | "success"; 120 | } 121 | -------------------------------------------------------------------------------- /src/services/billing/demo.js: -------------------------------------------------------------------------------- 1 | import { billing } from "@volcengine/openapi"; 2 | 3 | export async function main(AccessKeyId, SecretKey) { 4 | // 使用默认的service实例 也可以创建一个新实例 const billingService = new billing.BillingService(); 5 | const billingService = billing.defaultService; 6 | // 设置aksk 7 | billingService.setAccessKeyId(AccessKeyId); 8 | billingService.setSecretKey(SecretKey); 9 | 10 | // 请求预定义的OpenAPI 11 | await billingService.ListBill({ 12 | Limit: 10, 13 | Offset: 0, 14 | }); 15 | 16 | // 自定义OpenAPI请求 17 | await billingService.fetchOpenAPI({ 18 | Action: "ListBill", 19 | Version: "2022-01-01", 20 | query: { 21 | BillPeriod: "2022-01", 22 | Limit: "10", 23 | Offset: "0", 24 | Product: "", 25 | BillingMode: "", 26 | BillCategoryParent: "", 27 | PayStatus: "", 28 | IgnoreZero: "0", 29 | NeedRecordNum: "1", 30 | }, 31 | }); 32 | 33 | // 请求预定义的OpenAPI 34 | await billingService.ListBillDetail({ 35 | Limit: 10, 36 | Offset: 0, 37 | }); 38 | 39 | // 自定义OpenAPI请求 40 | await billingService.fetchOpenAPI({ 41 | Action: "ListBillDetail", 42 | Version: "2022-01-01", 43 | query: { 44 | BillPeriod: "2022-01", 45 | Limit: "10", 46 | Offset: "0", 47 | GroupTerm: "0", 48 | GroupPeriod: "2", 49 | Product: "", 50 | BillingMode: "", 51 | BillCategory: "", 52 | InstanceNo: "", 53 | IgnoreZero: "0", 54 | NeedRecordNum: "1", 55 | }, 56 | }); 57 | 58 | // 请求预定义的OpenAPI 59 | await billingService.ListBillOverviewByProd({ 60 | Limit: 10, 61 | Offset: 0, 62 | }); 63 | 64 | // 自定义OpenAPI请求 65 | await billingService.fetchOpenAPI({ 66 | Action: "ListBillOverviewByProd", 67 | Version: "2022-01-01", 68 | query: { 69 | BillPeriod: "2022-01", 70 | Limit: "10", 71 | Offset: "0", 72 | Product: "", 73 | BillingMode: "", 74 | BillCategoryParent: "", 75 | IgnoreZero: "0", 76 | NeedRecordNum: "1", 77 | }, 78 | }); 79 | } 80 | -------------------------------------------------------------------------------- /src/services/billing/index.ts: -------------------------------------------------------------------------------- 1 | import Service from "../../base/service"; 2 | import { ServiceOptions } from "../../base/types"; 3 | import { 4 | ListBillParams, 5 | ListBillResult, 6 | ListBillDetailParams, 7 | ListBillDetailResult, 8 | ListBillOverviewByProdParams, 9 | ListBillOverviewByProdResult, 10 | } from "./types"; 11 | 12 | export class BillingService extends Service { 13 | constructor(options?: ServiceOptions) { 14 | super({ 15 | ...options, 16 | host: "billing.volcengineapi.com", 17 | defaultVersion: "2022-01-01", 18 | serviceName: "billing", 19 | }); 20 | } 21 | 22 | ListBill = this.createAPI("ListBill", { 23 | method: "POST", 24 | contentType: "json", 25 | Version: "2022-01-01", 26 | }); 27 | 28 | ListBillDetail = this.createAPI("ListBillDetail", { 29 | method: "POST", 30 | contentType: "json", 31 | Version: "2022-01-01", 32 | }); 33 | 34 | ListBillOverviewByProd = this.createAPI< 35 | ListBillOverviewByProdParams, 36 | ListBillOverviewByProdResult 37 | >("ListBillOverviewByProd", { 38 | method: "POST", 39 | contentType: "json", 40 | Version: "2022-01-01", 41 | }); 42 | } 43 | 44 | export const defaultService = new BillingService(); 45 | -------------------------------------------------------------------------------- /src/services/billing/types.ts: -------------------------------------------------------------------------------- 1 | interface Bill { 2 | BillPeriod: string; 3 | PayerID: string; 4 | PayerUserName: string; 5 | PayerCustomerName: string; 6 | OwnerID: string; 7 | OwnerUserName: string; 8 | OwnerCustomerName: string; 9 | Product: string; 10 | ProductZh: string; 11 | BusinessMode: string; 12 | BillingMode: string; 13 | ExpenseBeginTime: string; 14 | ExpenseEndTime: string; 15 | TradeTime: string; 16 | BillID: string; 17 | BillCategoryParent: string; 18 | OriginalBillAmount: string; 19 | PreferentialBillAmount: string; 20 | RoundBillAmount: string; 21 | DiscountBillAmount: string; 22 | CouponAmount: string; 23 | PayableAmount: string; 24 | PaidAmount: string; 25 | UnpaidAmount: string; 26 | Currency: string; 27 | PayStatus: string; 28 | } 29 | 30 | export interface ListBillParams { 31 | BillPeriod: string; 32 | Limit: string; 33 | Offset: string; 34 | Product: string; 35 | BillingMode: string; 36 | BillCategoryParent: string; 37 | PayStatus: string; 38 | IgnoreZero: string; 39 | NeedRecordNum: string; 40 | } 41 | 42 | export interface ListBillResult { 43 | Total: number; 44 | Offset: number; 45 | Limit: number; 46 | BillList: Bill[]; 47 | } 48 | 49 | interface BillDetail { 50 | BillPeriod: string; 51 | ExpenseDate: string; 52 | PayerID: string; 53 | PayerUserName: string; 54 | PayerCustomerName: string; 55 | OwnerID: string; 56 | OwnerUserName: string; 57 | OwnerCustomerName: string; 58 | BusinessMode: string; 59 | Product: string; 60 | ProductZh: string; 61 | BillingMode: string; 62 | ExpenseBeginTime: string; 63 | ExpenseEndTime: string; 64 | UseDuration: string; 65 | UseDurationUnit: string; 66 | TradeTime: string; 67 | BillID: string; 68 | BillCategoryParent: string; 69 | InstanceNo: string; 70 | InstanceName: string; 71 | ConfigName: string; 72 | Element: string; 73 | Region: string; 74 | Zone: string; 75 | Factor: string; 76 | ExpandField: string; 77 | Price: string; 78 | PriceUnit: string; 79 | Count: string; 80 | Unit: string; 81 | DeductionCount: string; 82 | OriginalBillAmount: string; 83 | PreferentialBillAmount: string; 84 | DiscountBillAmount: string; 85 | CouponAmount: string; 86 | PayableAmount: string; 87 | PaidAmount: string; 88 | UnpaidAmount: string; 89 | Currency: string; 90 | } 91 | 92 | export interface ListBillDetailParams { 93 | BillPeriod: string; 94 | Limit: string; 95 | Offset: string; 96 | GroupTerm: string; 97 | GroupPeriod: string; 98 | Product: string; 99 | BillingMode: string; 100 | BillCategory: string; 101 | InstanceNo: string; 102 | IgnoreZero: string; 103 | NeedRecordNum: string; 104 | } 105 | 106 | export interface ListBillDetailResult { 107 | Total: number; 108 | Offset: number; 109 | Limit: number; 110 | BillList: BillDetail[]; 111 | } 112 | 113 | interface BillOverviewByProd { 114 | BillPeriod: string; 115 | PayerID: string; 116 | PayerUserName: string; 117 | PayerCustomerName: string; 118 | OwnerID: string; 119 | OwnerUserName: string; 120 | OwnerCustomerName: string; 121 | BusinessMode: string; 122 | Product: string; 123 | ProductZh: string; 124 | BillingMode: string; 125 | BillCategoryParent: string; 126 | OriginalBillAmount: string; 127 | PreferentialBillAmount: string; 128 | RoundBillAmount: string; 129 | DiscountBillAmount: string; 130 | CouponAmount: string; 131 | PayableAmount: string; 132 | PaidAmount: string; 133 | UnpaidAmount: string; 134 | } 135 | 136 | export interface ListBillOverviewByProdParams { 137 | BillPeriod: string; 138 | Limit: string; 139 | Offset: string; 140 | Product: string; 141 | BillingMode: string; 142 | BillCategoryParent: string; 143 | IgnoreZero: string; 144 | NeedRecordNum: string; 145 | } 146 | 147 | export interface ListBillOverviewByProdResult { 148 | Total: number; 149 | Offset: number; 150 | Limit: number; 151 | BillList: BillOverviewByProd[]; 152 | } 153 | -------------------------------------------------------------------------------- /src/services/cdn/demo.js: -------------------------------------------------------------------------------- 1 | import { cdn } from "@volcengine/openapi"; 2 | 3 | export async function main(AccessKeyId, SecretKey) { 4 | // 使用默认的service实例 也可以创建一个新实例 const CdnService = new cdn.CdnService(); 5 | const CdnService = cdn.defaultService; 6 | 7 | // 设置ak、sk 8 | CdnService.setAccessKeyId(AccessKeyId); 9 | CdnService.setSecretKey(SecretKey); 10 | 11 | // 预定义OpenAPI请求 12 | const body = { 13 | IP: "1.1.1.1", 14 | }; 15 | await CdnService.DescribeIPInfo(body); 16 | // 无需传入body的OpenAPI请求 17 | // 以下两种皆可 18 | await CdnService.DescribeContentQuota(); 19 | await CdnService.DescribeContentQuota({}); 20 | 21 | // 自定义OpenAPI请求 22 | await CdnService.fetchOpenAPI({ 23 | Action: "DescribeIPInfo", 24 | Version: "2021-03-01", 25 | method: "POST", 26 | headers: { 27 | "content-type": "application/json", 28 | }, 29 | data: { 30 | IP: "1.1.1.1", 31 | }, 32 | }); 33 | } 34 | -------------------------------------------------------------------------------- /src/services/edit/demo.js: -------------------------------------------------------------------------------- 1 | import { edit } from "@volcengine/openapi"; 2 | 3 | export async function main(AccessKeyId, SecretKey, SessionToken) { 4 | // 使用默认的service实例 也可以创建一个新实例 const editService = new edit.EditService(); 5 | const editService = edit.defaultService; 6 | // 设置aksk 7 | editService.setAccessKeyId(AccessKeyId); 8 | editService.setSecretKey(SecretKey); 9 | if (SessionToken) { 10 | // 使用sts请求时 设置SessionToken 11 | editService.setSessionToken(SessionToken); 12 | } 13 | 14 | // 请求预定义的OpenAPI 15 | await editService.GetDirectEditResult({ ReqIds: ['xxxxxx'] }); 16 | 17 | // 自定义OpenAPI请求 18 | await editService.fetchOpenAPI({ 19 | Action: "GetDirectEditResult", 20 | Version: "2018-01-01", 21 | method: 'POST', 22 | headers: { 23 | "content-type": "application/json", 24 | }, 25 | data: { 26 | ReqIds: ['xxxxxx'], 27 | } 28 | }); 29 | } 30 | -------------------------------------------------------------------------------- /src/services/edit/index.ts: -------------------------------------------------------------------------------- 1 | import Service from "../../base/service"; 2 | import { ServiceOptions } from "../../base/types"; 3 | import { 4 | SubmitDirectEditTaskAsyncParams, 5 | SubmitDirectEditTaskAsyncResult, 6 | GetDirectEditResultParams, 7 | DirectEditResult, 8 | SubmitTemplateTaskAsyncParams, 9 | SubmitTemplateTaskAsyncResult, 10 | } from "./types"; 11 | 12 | export class EditService extends Service { 13 | constructor(options?: ServiceOptions) { 14 | super({ 15 | defaultVersion: "2018-01-01", 16 | serviceName: "edit", 17 | host: "vedit.volcengineapi.com", 18 | ...options, 19 | }); 20 | } 21 | SubmitDirectEditTaskAsync = this.createAPI< 22 | SubmitDirectEditTaskAsyncParams, 23 | SubmitDirectEditTaskAsyncResult 24 | >("SubmitDirectEditTaskAsync", { method: "POST", contentType: "json" }); 25 | GetDirectEditResult = this.createAPI( 26 | "GetDirectEditResult", 27 | { method: "POST", contentType: "json" } 28 | ); 29 | SubmitTemplateTaskAsync = this.createAPI< 30 | SubmitTemplateTaskAsyncParams, 31 | SubmitTemplateTaskAsyncResult 32 | >("SubmitTemplateTaskAsync", { method: "POST", contentType: "json" }); 33 | } 34 | 35 | export const defaultService = new EditService(); 36 | -------------------------------------------------------------------------------- /src/services/edit/types.ts: -------------------------------------------------------------------------------- 1 | export interface IUploadInfo { 2 | Uploader: string; 3 | VideoName: string; 4 | } 5 | 6 | export interface IRect { 7 | PosX?: string; 8 | PosY?: string; 9 | Width: string; 10 | Height: string; 11 | } 12 | 13 | export interface IDelogo { 14 | StartTime?: number; 15 | Duration?: number; 16 | Position: IRect; 17 | } 18 | 19 | export interface IGblur { 20 | StartTime?: number; 21 | Duration?: number; 22 | Position: IRect; 23 | Sigma?: number; 24 | } 25 | 26 | export interface IMosaic { 27 | StartTime?: number; 28 | Duration?: number; 29 | Position: IRect; 30 | Size?: number; 31 | } 32 | 33 | export interface ITextAnimation { 34 | Type: string; 35 | Speed: string; 36 | Duration: number; 37 | } 38 | 39 | export interface IOutputInfo { 40 | Mode?: "normal" | "split"; 41 | Width: number; 42 | Height: number; 43 | Format?: "mp4" | "hls" | "jpg"; 44 | SegmentTime?: number; 45 | Fps?: number; 46 | Quality?: "low" | "medium" | "high"; 47 | NoEncode?: number; 48 | PosterTime?: number; 49 | } 50 | 51 | export interface IVideoElement { 52 | Type: "video"; 53 | StartTime?: number; 54 | Duration?: number; 55 | Source: string; 56 | Position?: IRect; 57 | Crop?: IRect; 58 | Speed?: number; 59 | Rotate?: number; 60 | Delogo?: IDelogo[]; 61 | Gblurs?: IGblur[]; 62 | Mosaics?: IMosaic[]; 63 | Trims?: number[][]; 64 | VFlip?: number; 65 | HFlip?: number; 66 | BorderRadius?: string; 67 | Filters?: any; 68 | ExtraFilters?: any[]; 69 | Volume?: string; 70 | Mute?: number; 71 | Subtitle?: string; 72 | Overwrite?: number; 73 | ParamName?: string; 74 | } 75 | 76 | export interface IImageElement { 77 | Type: "image"; 78 | StartTime?: number; 79 | Source: string; 80 | Position?: IRect; 81 | Duration: number; 82 | Crop?: IRect; 83 | Pad?: number; 84 | Rotate?: number; 85 | VFlip?: number; 86 | HFlip?: number; 87 | BorderRadius?: string; 88 | Filters?: any; 89 | ExtraFilters?: any[]; 90 | Overwrite?: number; 91 | ParamName?: string; 92 | } 93 | 94 | export interface ITextElement { 95 | Type: "text"; 96 | StartTime?: number; 97 | Duration: number; 98 | Text: string; 99 | Position: IRect; 100 | FontType?: string; 101 | FontSize?: number; 102 | FontColor?: string; 103 | BackgroundColor?: string; 104 | ShadowColor?: string; 105 | HorizontalAlign?: number; 106 | VerticalAlign?: number; 107 | MultiLine?: number; 108 | LineSpace?: number; 109 | ReplaceSuffix?: number; 110 | Animation?: ITextAnimation; 111 | FontWeight?: "normal" | "bold"; 112 | Italic?: number; 113 | Underline?: number; 114 | Overwrite?: number; 115 | ParamName?: string; 116 | } 117 | 118 | export interface IAudioElement { 119 | Type: "audio"; 120 | StartTime?: number; 121 | Duration?: number; 122 | Source: string; 123 | Trims?: number[][]; 124 | Volume?: string; 125 | Loop?: 0 | 1; 126 | Overwrite?: number; 127 | ParamName?: string; 128 | } 129 | 130 | export interface IMVElement { 131 | Type: "mv"; 132 | Template: number; 133 | SourceList: any[]; 134 | SourceType?: string; 135 | Position?: IRect; 136 | } 137 | 138 | export interface ISegment { 139 | BackGround?: string; 140 | Duration?: number; 141 | Transition?: string; 142 | TransitionTime?: number; 143 | Elements: (IVideoElement | IAudioElement | ITextElement | IImageElement | IMVElement)[]; 144 | } 145 | 146 | export interface IEditParam { 147 | Upload: IUploadInfo; 148 | Output: IOutputInfo; 149 | Segments?: ISegment[]; 150 | GlobalElements?: (IVideoElement | IAudioElement | ITextElement | IImageElement | IMVElement)[]; 151 | [propName: string]: any; 152 | } 153 | 154 | export interface SubmitDirectEditTaskAsyncParams { 155 | Uploader: string; 156 | Application?: string; 157 | FuncVersion?: string; 158 | EditParam: IEditParam; 159 | Priority?: number; 160 | VideoName?: string; 161 | CallbackUri?: string; 162 | CallbackArgs?: string; 163 | } 164 | 165 | export interface SubmitDirectEditTaskAsyncResult { 166 | ReqId: string; 167 | } 168 | 169 | export interface GetDirectEditResultParams { 170 | ReqIds?: string[]; 171 | } 172 | 173 | export interface DirectEditResult { 174 | ReqId: string; 175 | EditParam: IEditParam; 176 | CallbackUri: string; 177 | CallbackArgs: string; 178 | Priority: number; 179 | Status: string; 180 | Message: string; 181 | OutputVid: string; 182 | SubVid: string[]; 183 | TaskId: string; 184 | } 185 | 186 | interface ITemplateParamItem { 187 | Name?: string; 188 | Type: "audio" | "video" | "image" | "text"; 189 | Position?: string; 190 | Source?: string; 191 | Text?: string; 192 | StartTime: number; 193 | Duration: number; 194 | } 195 | 196 | export interface SubmitTemplateTaskAsyncParams { 197 | Type?: string; 198 | TemplateId: string; 199 | Space: string; 200 | VideoName?: string[]; 201 | Params?: ITemplateParamItem[][]; 202 | ExtraParams?: any[]; 203 | Priority?: number; 204 | CallbackUri?: string; 205 | CallbackArgs?: string; 206 | } 207 | 208 | export interface SubmitTemplateTaskAsyncResult { 209 | ReqId: string[]; 210 | } 211 | -------------------------------------------------------------------------------- /src/services/i18nOpenapi/demo.js: -------------------------------------------------------------------------------- 1 | import { i18nOpenapi } from "@volcengine/openapi"; 2 | 3 | async function main(AccessKeyId, SecretKey, SessionToken) { 4 | // 使用默认的service实例 也可以创建一个新实例 const i18nOpenapiService = new i18nOpenapi.i18nOpenapiService(); 5 | const i18nOpenapiService = i18nOpenapi.defaultService; 6 | // 设置aksk 7 | i18nOpenapiService.setAccessKeyId(AccessKeyId); 8 | i18nOpenapiService.setSecretKey(SecretKey); 9 | 10 | if (SessionToken) { 11 | // 使用sts请求时 设置SessionToken 12 | i18nOpenapiService.setSessionToken(SessionToken); 13 | } 14 | 15 | // 获取项目列表 16 | await i18nOpenapiService.Projects(); 17 | 18 | // 获取空间详情 19 | await i18nOpenapiService.ProjectNamespaceDetail({ 20 | projectId: 111, 21 | namespaceId: 222, 22 | }); 23 | 24 | // 创建空间 25 | await i18nOpenapiService.ProjectNamespaceDetail({ 26 | projectId: 111, 27 | name: "空间名称", 28 | description: "空间描述", 29 | }); 30 | } 31 | -------------------------------------------------------------------------------- /src/services/iam/README.md: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/volcengine/volc-sdk-nodejs/677e35e1c1d1bb892f0c66256edad03a7d3949bc/src/services/iam/README.md -------------------------------------------------------------------------------- /src/services/iam/demo.js: -------------------------------------------------------------------------------- 1 | import { iam } from "@volcengine/openapi"; 2 | 3 | export async function main(AccessKeyId, SecretKey, SessionToken) { 4 | // 使用默认的service实例 也可以创建一个新实例 const iamService = new iam.IamService(); 5 | const iamService = iam.defaultService; 6 | // 设置aksk 7 | iamService.setAccessKeyId(AccessKeyId); 8 | iamService.setSecretKey(SecretKey); 9 | if (SessionToken) { 10 | // 使用sts请求时 设置SessionToken 11 | iamService.setSessionToken(SessionToken); 12 | } 13 | 14 | // 请求预定义的OpenAPI 15 | await iamService.ListUsers({ 16 | Limit: 10, 17 | Offset: 0, 18 | }); 19 | 20 | // 自定义OpenAPI请求 21 | await iamService.fetchOpenAPI({ 22 | Action: "ListUsers", 23 | Version: "2018-01-01", 24 | query: { 25 | Limit: 10, 26 | Offset: 0, 27 | }, 28 | }); 29 | } 30 | -------------------------------------------------------------------------------- /src/services/iam/index.ts: -------------------------------------------------------------------------------- 1 | import Service from "../../base/service"; 2 | import { ServiceOptions } from "../../base/types"; 3 | 4 | interface ListParams { 5 | Limit?: number; 6 | Offset?: number; 7 | Query?: string; 8 | } 9 | interface User { 10 | CreateDate: string; 11 | UpdateDate: string; 12 | Status: string; 13 | AccountId: number; 14 | UserName: string; 15 | Description: string; 16 | DisplayName: string; 17 | Email: string; 18 | MobilePhone: string; 19 | Trn: string; 20 | Source: string; 21 | } 22 | interface ListUserResult { 23 | UserMetadata: User[]; 24 | } 25 | export class IamService extends Service { 26 | constructor(options?: ServiceOptions) { 27 | super({ 28 | ...options, 29 | defaultVersion: "2018-01-01", 30 | serviceName: "iam", 31 | }); 32 | } 33 | ListUsers = this.createAPI("ListUsers"); 34 | } 35 | 36 | export const defaultService = new IamService(); 37 | -------------------------------------------------------------------------------- /src/services/imagex/demo.js: -------------------------------------------------------------------------------- 1 | import { imagex } from "@volcengine/openapi"; 2 | import path from 'path'; 3 | 4 | export async function main(AccessKeyId, SecretKey, SessionToken) { 5 | // 使用默认的service实例 也可以创建一个新实例 const imagexService = new imagex.imagexService(); 6 | const imagexService = imagex.defaultService; 7 | // 设置aksk 8 | imagexService.setAccessKeyId(AccessKeyId); 9 | imagexService.setSecretKey(SecretKey); 10 | if (SessionToken) { 11 | // 使用sts请求时 设置SessionToken 12 | imagexService.setSessionToken(SessionToken); 13 | } 14 | 15 | // 请求预定义的OpenAPI 16 | await imagexService.PreviewImageUploadFile({ 17 | ServiceId: 'your service id', 18 | StoreUri: 'image StoreUri', 19 | }); 20 | 21 | await imagexService.UploadImages({ 22 | serviceId: 'your service id', 23 | files: [path.resolve(__dirname, 'xxx1.png'), path.resolve(__dirname, 'xxx2.png')], 24 | fileKeys: ['key1', 'key2'] 25 | }); 26 | 27 | // 自定义OpenAPI请求 28 | await imagexService.fetchOpenAPI({ 29 | Action: "PreviewImageUploadFile", 30 | Version: "2018-01-01", 31 | query: { 32 | ServiceId: 'your service id', 33 | StoreUri: 'image StoreUri', 34 | } 35 | }); 36 | 37 | // 生成临时上传密钥 38 | imagexService.GetUploadAuth(); 39 | 40 | //获取上传图片的签名URL 41 | imagexService.GetUploadAuthToken({ 42 | ServiceId: "your service id", 43 | // 默认900 (15min) 44 | "X-Expires": "60", 45 | }); 46 | } 47 | -------------------------------------------------------------------------------- /src/services/imagex/types.ts: -------------------------------------------------------------------------------- 1 | interface IStoreInfo { 2 | StoreUri: string; 3 | Auth: string; 4 | } 5 | 6 | interface IOptionInfo { 7 | StoreUri: string; 8 | FileName?: string; 9 | } 10 | 11 | interface IFunction { 12 | Name: string; 13 | Input: any; 14 | } 15 | 16 | interface IResult { 17 | Uri: string; 18 | Encryption: any; 19 | } 20 | 21 | interface IImageInfo { 22 | FileName: string; 23 | ImageUri: string; 24 | ImageWidth: number; 25 | ImageHeight: number; 26 | ImageMd5: string; 27 | ImageFormat: string; 28 | ImageSize: number; 29 | FrameCnt: number; 30 | Duration: number; 31 | } 32 | 33 | export interface ApplyImageUploadParams { 34 | ServiceId: string; 35 | SessionKey?: string; 36 | UploadNum?: number; 37 | StoreKeys?: string[]; 38 | } 39 | export interface ApplyImageUploadResult { 40 | UploadAddress: { 41 | StoreInfos: IStoreInfo[]; 42 | UploadHosts: string[]; 43 | SessionKey: string; 44 | }; 45 | RequestId: string; 46 | } 47 | 48 | export interface CommitImageUploadParams { 49 | ServiceId: string; 50 | SessionKey: string; 51 | OptionInfos?: IOptionInfo[]; 52 | Functions?: IFunction[]; 53 | } 54 | 55 | export interface CommitImageUploadResult { 56 | Results: IResult[]; 57 | RequestId: string; 58 | PluginResult: IImageInfo[]; 59 | } 60 | 61 | export interface UpdateImageUploadFilesParams { 62 | ServiceId: string; 63 | Action: number; 64 | ImageUrls: string[]; 65 | } 66 | 67 | export interface UpdateImageUploadFilesResult { 68 | ServiceId: string; 69 | ImageUrls: string[]; 70 | FailUrls: string[]; 71 | } 72 | 73 | export interface PreviewImageUploadFileParams { 74 | ServiceId: string; 75 | StoreUri: string; 76 | } 77 | export interface PreviewImageUploadFileResult { 78 | ServiceId: string; 79 | FileName: string; 80 | StoreUri: string; 81 | ImageURL: string; 82 | ImageFormat: string; 83 | ImageSize: number; 84 | ImageWidth: number; 85 | ImageHeight: number; 86 | ImageFrames?: number; 87 | ImageDuration?: number; 88 | } 89 | 90 | // 指定上传策略 91 | export type UploadPolicy = { 92 | /** 93 | * 上传格式黑名单, 示例 image/* video/* 94 | */ 95 | ContentTypeBlackList?: string[]; 96 | /** 97 | * 上传格式白名单, 示例 image/* video/* 98 | */ 99 | ContentTypeWhiteList?: string[]; 100 | /** 101 | * 上传文件大小上限, 单位 byte, 示例 1024 102 | */ 103 | FileSizeUpLimit?: string; 104 | /** 105 | * 上传文件大小下限, 单位 byte, 示例 1024 106 | */ 107 | FileSizeBottomLimit?: string; 108 | }; 109 | 110 | // 生成上传临时密钥配置参数 111 | export interface GetUploadAuthParams { 112 | /** 指定服务 ID 列表 */ 113 | serviceIds?: string[]; 114 | /** 密钥超时时间 */ 115 | expire?: number; 116 | /** 指定资源存储名称 */ 117 | storeKeys?: string[]; 118 | /** 是否开启上传覆盖 */ 119 | uploadOverwrite?: boolean; 120 | /** 上传策略配置 */ 121 | uploadPolicy?: UploadPolicy; 122 | } 123 | 124 | export interface GetUploadAuthTokenParams { 125 | /** 指定服务 ID */ 126 | ServiceId: string; 127 | /** 指定过期时间 */ 128 | "X-Expires": number; 129 | } 130 | 131 | type PutError = { 132 | errMsg: string; 133 | errCode?: string; 134 | errStatus?: string | number; 135 | errCodeN?: string; 136 | reqId?: string; 137 | uploadid?: string; 138 | }; 139 | 140 | export type UploadPutResult = { 141 | success: boolean; 142 | uri: string; 143 | putErr?: PutError; 144 | }; 145 | -------------------------------------------------------------------------------- /src/services/live/const.ts: -------------------------------------------------------------------------------- 1 | export const CasterPlayerAction = ["Live:GetCasterPlayerInfo"]; 2 | -------------------------------------------------------------------------------- /src/services/live/demo.js: -------------------------------------------------------------------------------- 1 | import { liveOpenapi } from "@volcengine/openapi"; 2 | 3 | export async function main(AccessKeyId, SecretKey) { 4 | const liveCasterService = new liveOpenapi.liveCasterService({ 5 | accessKeyId: AccessKeyId, 6 | secretKey: SecretKey, 7 | }); 8 | // 获得导播预览组件的 UserToken 9 | const playerUserToken = liveCasterService.GetCasterPlayerUserToken(); 10 | } 11 | -------------------------------------------------------------------------------- /src/services/live/index.ts: -------------------------------------------------------------------------------- 1 | import Service from "../../base/service"; 2 | import { ServiceOptionsBase } from "../../base/types"; 3 | import { CasterPlayerAction } from "./const"; 4 | 5 | export class LiveCasterService extends Service { 6 | constructor(options?: ServiceOptionsBase) { 7 | super({ 8 | host: "live.volcengineapi.com", 9 | serviceName: "live", 10 | defaultVersion: "2018-01-01", 11 | ...options, 12 | }); 13 | } 14 | 15 | GetCasterPlayerUserToken = () => { 16 | const policy = { 17 | Statement: [ 18 | { 19 | Effect: "Allow", 20 | Action: [...CasterPlayerAction], 21 | Resource: ["*"], 22 | }, 23 | ], 24 | }; 25 | const UserToken = this.signSts2(policy); 26 | return UserToken; 27 | }; 28 | } 29 | -------------------------------------------------------------------------------- /src/services/livesaas/const.ts: -------------------------------------------------------------------------------- 1 | export const LivesaasUploadAction = [ 2 | "Livesaas:GetUploadTokenSDK", 3 | "Livesaas:UploadActivityMediaSDK", 4 | "Livesaas:CheckSpaceActivityMediaSDK", 5 | "Livesaas:UpdateMediaCoverImageSDK", 6 | ]; 7 | 8 | export const Domain = { 9 | "cn-north-1": "livesaas.volcengineapi.com", 10 | "ap-singapore-1": "open.byteplusapi.com", 11 | }; 12 | -------------------------------------------------------------------------------- /src/services/livesaas/demo.js: -------------------------------------------------------------------------------- 1 | import { livesaasOpenapi } from "@volcengine/openapi"; 2 | 3 | export async function main(AccessKeyId, SecretKey) { 4 | const livesaasService = new livesaasOpenapi.LivesaasService({ 5 | accessKeyId: AccessKeyId, 6 | secretKey: SecretKey, 7 | }); 8 | // 获得上传用户的 UserToken 9 | const uploadUserToken = livesaasService.GetLivesaasUploadUserToken(); 10 | } -------------------------------------------------------------------------------- /src/services/livesaas/index.ts: -------------------------------------------------------------------------------- 1 | import Service from "../../base/service"; 2 | import { ServiceOptionsBase } from "../../base/types"; 3 | import { LivesaasUploadAction, Domain } from "./const"; 4 | 5 | export class LivesaasService extends Service { 6 | constructor(options?: ServiceOptionsBase) { 7 | super({ 8 | host: Domain[options?.region || "ap-singapore-1"], 9 | serviceName: "livesaas", 10 | defaultVersion: "2019-10-10", 11 | ...options, 12 | }); 13 | } 14 | 15 | GetLivesaasUploadUserToken = () => { 16 | const policy = { 17 | Statement: [ 18 | { 19 | Effect: "Allow", 20 | Action: [...LivesaasUploadAction], 21 | Resource: ["*"], 22 | }, 23 | ], 24 | }; 25 | const UserToken = this.signSts2(policy); 26 | return UserToken; 27 | }; 28 | } 29 | -------------------------------------------------------------------------------- /src/services/maas/demo.js: -------------------------------------------------------------------------------- 1 | /* eslint-disable no-console */ 2 | import { maas } from "@volcengine/openapi"; 3 | 4 | // 创建一个新实例 5 | const maasService = new maas.MaasService({ 6 | host: "maas-api.ml-platform-cn-beijing.volces.com", 7 | region: "cn-beijing", 8 | }); 9 | 10 | // 从环境变量设置 ak & sk 11 | maasService.setAccessKeyId(process.env.VOLC_ACCESSKEY); 12 | maasService.setSecretKey(process.env.VOLC_SECRETKEY); 13 | 14 | const chatParams = { 15 | model: { 16 | name: "${YOUR_MODEL_NAME}", 17 | }, 18 | messages: [ 19 | { 20 | role: maas.ChatRole.User, 21 | content: "天为什么这么蓝?", 22 | }, 23 | { 24 | role: maas.ChatRole.Assistant, 25 | content: "因为有你", 26 | }, 27 | { 28 | role: maas.ChatRole.User, 29 | content: "花儿为什么这么香?", 30 | }, 31 | ], 32 | parameters: { 33 | max_new_tokens: 1000, 34 | temperature: 1, 35 | }, 36 | }; 37 | 38 | const tokenizationParams = { 39 | model: { 40 | name: "${YOUR_MODEL_NAME}", 41 | version: "${YOUR_VERSION}", 42 | }, 43 | text: "天空为什么这么蓝?", 44 | }; 45 | 46 | const classificationParams = { 47 | model: { 48 | name: "${YOUR_MODEL_NAME}", 49 | version: "${YOUR_VERSION}", 50 | }, 51 | query: "中国的第一个经济特区是?", 52 | labels: ["北京", "珠海", "深圳", "厦门", "上海"], 53 | }; 54 | const embeddingsParams = { 55 | model: { 56 | name: "bge-large-zh", 57 | }, 58 | input: ["天很蓝", "海很深"], 59 | }; 60 | await maasService 61 | .Chat(chatParams) 62 | .then((result) => { 63 | console.log(result?.choice?.message?.content || "no content"); 64 | console.log(result?.usage || "no usage"); 65 | }) 66 | .catch((reason) => { 67 | console.error(reason); 68 | }); 69 | 70 | try { 71 | for await (const result of maasService.StreamChat(chatParams)) { 72 | console.log(result?.choice?.message?.content || "no content"); 73 | // usage only appears in the last item. 74 | console.log(result?.usage || "no usage"); 75 | } 76 | } catch (ex) { 77 | console.error(ex); 78 | } 79 | 80 | await maasService 81 | .Tokenization(tokenizationParams) 82 | .then((result) => { 83 | console.log(result?.total_tokens || "no total_tokens"); 84 | console.log(result?.tokens || "no tokens"); 85 | }) 86 | .catch((reason) => { 87 | console.error(reason); 88 | }); 89 | 90 | await maasService 91 | .Classification({ ...classificationParams }) 92 | .then((result) => { 93 | console.log(result?.label || "no label"); 94 | console.log(result?.label_logprobos || "no label_logprobos"); 95 | }) 96 | .catch((reason) => { 97 | console.error(reason); 98 | }); 99 | 100 | await maasService 101 | .Embeddings({ ...embeddingsParams }) 102 | .then((result) => { 103 | console.log(result?.object || "no object"); 104 | console.log(result?.data || "no data"); 105 | }) 106 | .catch((reason) => { 107 | console.error(reason); 108 | }); 109 | -------------------------------------------------------------------------------- /src/services/maas/error.ts: -------------------------------------------------------------------------------- 1 | export class MaasError extends Error { 2 | code: string; 3 | code_n: number; 4 | msg: string; 5 | 6 | constructor(code: string, message: string, code_n: number) { 7 | super(message); 8 | 9 | this.name = this.constructor.name; 10 | 11 | Error.captureStackTrace(this, this.constructor); 12 | 13 | this.msg = message; 14 | this.code = code; 15 | this.code_n = code_n; 16 | } 17 | 18 | toString() { 19 | return ( 20 | "Detailed exception information is listed below.\n" + 21 | `code_n: ${this.code_n}\n` + 22 | `code: ${this.code}\n` + 23 | `message: ${this.message}` 24 | ); 25 | } 26 | } 27 | 28 | export function new_client_sdk_error(message) { 29 | return new MaasError("ClientSDKRequestError", String(message), 1709701); 30 | } 31 | -------------------------------------------------------------------------------- /src/services/maas/v2/demo.js: -------------------------------------------------------------------------------- 1 | /* eslint-disable no-console */ 2 | import { maas } from "@volcengine/openapi"; 3 | // 创建一个新实例 4 | const maasService = new maas.MaasServiceV2({ 5 | host: "maas-api.ml-platform-cn-beijing.volces.com", 6 | region: "cn-beijing", 7 | }); 8 | 9 | // 从环境变量设置 ak & sk 10 | maasService.setAccessKeyId(process.env.VOLC_ACCESSKEY); 11 | maasService.setSecretKey(process.env.VOLC_SECRETKEY); 12 | 13 | const endpointId = "${YOUR_ENDPOINT_ID}"; 14 | const chatParams = { 15 | parameters: { 16 | max_new_tokens: 1000, 17 | min_new_tokens: 1, 18 | temperature: 0.7, 19 | top_p: 0.9, 20 | top_k: 0, 21 | max_prompt_tokens: 4000, 22 | }, 23 | messages: [ 24 | { 25 | role: "user", 26 | content: "天为什么这么蓝?", 27 | }, 28 | { 29 | role: "assistant", 30 | content: "因为有你", 31 | }, 32 | { 33 | role: "user", 34 | content: "花儿为什么这么香?", 35 | }, 36 | ], 37 | }; 38 | const tokenizationParams = { 39 | text: "花儿为什么这么香?", 40 | }; 41 | const classificationParams = { 42 | query: "花儿为什么这么香?", 43 | labels: ["陈述句", "疑问句", "肯定句"], 44 | }; 45 | const embeddingsParams = { 46 | input: ["天很蓝", "海很深"], 47 | }; 48 | 49 | await maasService 50 | .Chat(endpointId, chatParams) 51 | .then((result) => { 52 | console.log(result?.choice?.message?.content || "no content"); 53 | console.log(result?.usage || "no usage"); 54 | }) 55 | .catch((reason) => { 56 | console.error(reason); 57 | }); 58 | 59 | await maasService 60 | .Tokenization(endpointId, tokenizationParams) 61 | .then((result) => { 62 | console.log(result?.total_tokens || "no total_tokens"); 63 | console.log(result?.tokens || "no tokens"); 64 | }) 65 | .catch((reason) => { 66 | console.error(reason); 67 | }); 68 | 69 | await maasService 70 | .Classification(endpointId, classificationParams) 71 | .Classification.then((result) => { 72 | console.log(result?.label || "no label"); 73 | console.log(result?.label_logprobos || "no label_logprobos"); 74 | }) 75 | .catch((reason) => { 76 | console.error(reason); 77 | }); 78 | 79 | await maasService 80 | .Embeddings(endpointId, embeddingsParams) 81 | .then((result) => { 82 | console.log(result?.object || "no object"); 83 | console.log(result?.data || "no data"); 84 | }) 85 | .catch((reason) => { 86 | console.error(reason); 87 | }); 88 | -------------------------------------------------------------------------------- /src/services/maas/v2/types.ts: -------------------------------------------------------------------------------- 1 | export type ServiceOptions = { 2 | host?: string; 3 | region?: string; 4 | timeout?: number; 5 | }; 6 | 7 | interface IFunction { 8 | name: string; 9 | description: string; 10 | parameters?: Record; 11 | examples?: string[]; 12 | } 13 | 14 | export interface Tool { 15 | type: string; 16 | function: IFunction; 17 | } 18 | 19 | export interface FunctionCall { 20 | // The name of the function to call. 21 | name: string; 22 | 23 | // The arguments to call the function with, generated by model, formatted as json, may not valid, 24 | // the caller should validate the arguments before calling the function. 25 | arguments: string; 26 | } 27 | 28 | export interface ToolCall { 29 | Function: FunctionCall; 30 | id: string; 31 | type: string; 32 | } 33 | 34 | export enum ChatRole { 35 | User = "user", 36 | Assistant = "assistant", 37 | System = "system", 38 | Function = "function", 39 | } 40 | 41 | export interface Reference { 42 | // url 43 | url: string; 44 | 45 | // the index of url 46 | idx: number; 47 | 48 | // the logo of url 49 | logo_url: string; 50 | 51 | // the url be used for pc 52 | pc_url: string; 53 | 54 | // the topic of url 55 | site_name: string; 56 | } 57 | 58 | export interface Message { 59 | content: string; 60 | name?: string; 61 | references?: Reference[]; 62 | role: ChatRole; 63 | tool_call_id?: string; 64 | tool_calls?: ToolCall[]; 65 | } 66 | 67 | export interface Parameters { 68 | // Exponential scaling output probability distribution 69 | temperature?: number; 70 | 71 | // The maximum number of tokens to generate in the char completion. 72 | max_tokens?: number; 73 | 74 | // An alternative to sampling with temperature, called nucleus sampling, 75 | // where the model considers the results of the tokens with top_p probability 76 | // mass 77 | top_p?: number; 78 | 79 | // Number between -2.0 and 2.0. Positive values penalize new tokens based 80 | // on whether they appear in the text so far, increasing the model's 81 | // likelihood to talk about new topics. 82 | presence_penalty?: number; 83 | 84 | // Number between -2.0 and 2.0. Positive values penalize new tokens based on 85 | // their existing frequency in the text so far, decreasing the model's 86 | // likelihood to repeat the same line verbatim. 87 | frequency_penalty?: number; 88 | 89 | // The maximum number of tokens to generate, ignoring the number of tokens in 90 | // the prompt 91 | max_new_tokens?: number; 92 | 93 | // The parameter for repetition penalty, from [1.0, 2.0] 94 | repetition_penalty?: number; 95 | 96 | // Whether or not to use sampling, use greedy decoding otherwise. Default to 97 | // false 98 | do_sample?: boolean; 99 | 100 | // The number of highest probability vocabulary tokens to keep for 101 | // top-k-filtering. 102 | top_k?: number; 103 | 104 | // the minimum number of tokens to generate 105 | min_new_tokens?: number; 106 | 107 | // the maximum number of prompt tokens, if prompt tokens length over this 108 | // limit, it will be truncated as prompt[-max_prompt_tokens:] 109 | max_prompt_tokens?: number; 110 | 111 | logprobs?: number; 112 | } 113 | 114 | export interface ChatReq { 115 | crypto_token?: string; 116 | extra?: Record; 117 | messages: Message[]; 118 | parameters?: Parameters; 119 | stream?: boolean; 120 | tools?: Tool[]; 121 | user?: string; 122 | } 123 | 124 | interface ChoiceLog { 125 | content: string; 126 | input: string; 127 | } 128 | 129 | interface Logprobs { 130 | text_offset: number[]; 131 | token_logprobs: number[]; 132 | tokens: string[]; 133 | top_logprobs: Record[]; 134 | } 135 | 136 | export interface Choice { 137 | index?: number; 138 | message?: Message; 139 | finish_reason?: string; 140 | action?: ChoiceLog; 141 | logprobs?: Logprobs; 142 | observation?: ChoiceLog; 143 | thought?: ChoiceLog; 144 | } 145 | 146 | export interface Usage { 147 | // The number of prompt tokens 148 | prompt_tokens: number; 149 | 150 | // The number of generated tokens 151 | completion_tokens: number; 152 | 153 | // The number of all: prompt_tokens + completion_tokens 154 | total_tokens: number; 155 | } 156 | 157 | export interface Error { 158 | code: string; 159 | code_n: number; 160 | message: string; 161 | } 162 | 163 | export interface ChatResp { 164 | req_id?: string; 165 | error?: Error; 166 | choices?: Choice[]; 167 | usage?: Usage; 168 | extra?: { [key: string]: string }; 169 | } 170 | 171 | export interface TokenizeReq { 172 | text: string; 173 | } 174 | 175 | export interface TokenizeResp { 176 | req_id: string; 177 | error?: Error; 178 | tokens: string[]; 179 | total_tokens: number; 180 | } 181 | 182 | export interface ClassificationReq { 183 | labels: string[]; 184 | query: string; 185 | } 186 | export interface LabelLogprobosValue { 187 | req_id?: string; 188 | tokens: string[]; 189 | token_logprobos: string[]; 190 | } 191 | 192 | export interface ClassificationResp { 193 | req_id: string; 194 | error?: Error; 195 | label: string; 196 | label_logprobos: Record; 197 | usage?: Usage; 198 | } 199 | 200 | export interface EmbeddingsReq { 201 | input: string[]; 202 | } 203 | 204 | export interface Embedding { 205 | index?: number; 206 | embedding: number[]; 207 | object: string; 208 | } 209 | 210 | export interface EmbeddingsResp { 211 | req_id?: string; 212 | object?: string; 213 | data: Embedding[]; 214 | usage?: Usage; 215 | error?: Error; 216 | } 217 | -------------------------------------------------------------------------------- /src/services/rocketmq/Client.ts: -------------------------------------------------------------------------------- 1 | import { v4 as uuidv4 } from "uuid"; 2 | import Signer from "../../base/sign"; 3 | import { sendRequest, SendRequestOptions } from "./utils/request"; 4 | import { ClientOptions, ConsumerOptions } from "./types"; 5 | import { Consumer } from "./Consumer"; 6 | import { Producer } from "./Producer"; 7 | import { MQError } from "./utils/error"; 8 | import { instanceNeedNamespace, requiredCheck } from "./utils/common"; 9 | 10 | const SDK_VERSION = "0.0.2"; 11 | // client 对应session超时时间 12 | const SESSION_TIMEOUT = 60; 13 | 14 | const SERVICE_NAME = "rocketmq"; 15 | 16 | interface ClientRequestOption extends Omit { 17 | path: string; 18 | data: Omit; 19 | } 20 | 21 | export class Client { 22 | private _endpoint: string; 23 | private _instanceId: string; 24 | private _accessKey: string; 25 | private _secretKey: string; 26 | 27 | constructor(options: ClientOptions) { 28 | if (!options) { 29 | throw new MQError("[RocketMQ-node-sdk] Please pass the config of client"); 30 | } 31 | 32 | const fields = requiredCheck(options, ["endpoint", "instanceId", "accessKey", "secretKey"]); 33 | 34 | if (fields.length > 0) { 35 | throw new MQError(`[RocketMQ-node-sdk] ${fields.join(", ")} is necessary`); 36 | } 37 | 38 | const { endpoint, accessKey, secretKey, instanceId } = options; 39 | 40 | const endpointInfo = new URL(options.endpoint); 41 | 42 | if (endpointInfo.protocol !== "http:" || !endpointInfo.hostname) { 43 | throw new MQError("[RocketMQ-node-sdk] endpoint is not a correct HTTP address"); 44 | } 45 | 46 | this._endpoint = endpoint; 47 | this._accessKey = accessKey; 48 | this._secretKey = secretKey; 49 | this._instanceId = instanceId; 50 | } 51 | 52 | get VERSION() { 53 | return SDK_VERSION; 54 | } 55 | 56 | get SESSION_TIMEOUT() { 57 | return SESSION_TIMEOUT; 58 | } 59 | 60 | createProducer() { 61 | return new Producer(this); 62 | } 63 | 64 | createConsumer(options: ConsumerOptions) { 65 | return new Consumer(this, options); 66 | } 67 | 68 | async _request(options: ClientRequestOption): Promise { 69 | const singer = this._sign(options); 70 | const { headers } = options; 71 | 72 | const url = new URL(options.path, this._endpoint).href; 73 | 74 | const res = await sendRequest({ 75 | ...options, 76 | url, 77 | headers: { ...headers, ...singer.request.headers }, 78 | data: singer.request.body, 79 | }); 80 | 81 | return res; 82 | } 83 | 84 | getTopicId(topic: string) { 85 | if (instanceNeedNamespace(this._instanceId)) { 86 | return `${this._instanceId}%${topic}`; 87 | } 88 | return topic; 89 | } 90 | 91 | getGroupId(group: string) { 92 | if (instanceNeedNamespace(this._instanceId)) { 93 | return `${this._instanceId}%${group}`; 94 | } 95 | return group; 96 | } 97 | 98 | private _createRequestId() { 99 | const requestId = uuidv4(); 100 | return requestId; 101 | } 102 | 103 | private _sign(options: ClientRequestOption) { 104 | const { method, path, data } = options; 105 | 106 | const urlInfo = new URL(path, this._endpoint); 107 | 108 | const singer = new Signer( 109 | { 110 | region: "all", 111 | method: method as string, 112 | pathname: path, 113 | headers: { Host: urlInfo.host }, 114 | body: { ...data, requestId: this._createRequestId() }, 115 | }, 116 | SERVICE_NAME 117 | ); 118 | 119 | singer.addAuthorization({ accessKeyId: this._accessKey, secretKey: this._secretKey }); 120 | 121 | return singer; 122 | } 123 | } 124 | -------------------------------------------------------------------------------- /src/services/rocketmq/Producer.ts: -------------------------------------------------------------------------------- 1 | import { Client } from "./Client"; 2 | import { PublishMessageOptions } from "./types"; 3 | import { MQError, isMQError } from "./utils/error"; 4 | import { isNeedReconnectError } from "./utils/common"; 5 | import * as v1 from "./protocol/v1"; 6 | import { MQAgent } from "./utils/agent"; 7 | import { Worker } from "./Worker"; 8 | 9 | export class MessageProperties { 10 | properties: Record; 11 | constructor() { 12 | this.properties = {}; 13 | } 14 | 15 | delayAfter(second: number) { 16 | this.properties["__DELAY_AFTER"] = String(second); 17 | } 18 | 19 | delayAt(timeStamp: number) { 20 | this.properties["__DELAY_AT"] = String(timeStamp); 21 | } 22 | 23 | putProperty(key: string, value: string) { 24 | this.properties[key] = value; 25 | } 26 | } 27 | 28 | export class Producer extends Worker { 29 | private _producerAgent: MQAgent; 30 | 31 | constructor(client: Client) { 32 | if (!client) throw new MQError("Please pass the client instance of producer"); 33 | 34 | super(client, { type: "producer" }); 35 | 36 | this._producerAgent = this._workerAgent; 37 | } 38 | 39 | connect() { 40 | return this._connect({ properties: {} }); 41 | } 42 | 43 | close() { 44 | return this._close(); 45 | } 46 | 47 | async publishMessage(options: PublishMessageOptions): Promise { 48 | if (!options) { 49 | throw new MQError(`[RocketMQ-node-sdk] please pass the message option`); 50 | } 51 | 52 | if (!options.topic) { 53 | throw new MQError(`[RocketMQ-node-sdk] topic can not be empty`); 54 | } 55 | 56 | if (!options.body) { 57 | throw new MQError(`[RocketMQ-node-sdk] body can not be empty`); 58 | } 59 | 60 | if (this._workerStatus !== "connected") { 61 | throw new MQError( 62 | `[RocketMQ-node-sdk] Can not publish message when producer's status is ${this._workerStatus}` 63 | ); 64 | } 65 | 66 | try { 67 | // 如果正在重连,这里会等待重连成功后promise resolve 68 | await this._waitReconnectIfNecessary(); 69 | 70 | const startTime = Date.now(); 71 | const res = await this._publishMessageRequest(options); 72 | 73 | this._logger.debug(`Publish message succeed.`, { 74 | timeSpent: Date.now() - startTime, 75 | payload: options, 76 | }); 77 | return res; 78 | } catch (error) { 79 | if (isNeedReconnectError(error)) { 80 | this._logger.debug(`Lost connection when publishing message: ${error.message}`); 81 | this._reconnect(); 82 | // 开启重连后,将当前消息重发,并返回给调用方 83 | return this.publishMessage(options); 84 | } 85 | const msg = `Producer publish message failed: ${error.message}`; 86 | this._logger.error(msg, { 87 | payload: isMQError(error) ? error.cause : undefined, 88 | }); 89 | 90 | throw new MQError(`[RocketMQ-node-sdk] ${msg}`); 91 | } 92 | } 93 | 94 | private async _publishMessageRequest(options: PublishMessageOptions): Promise { 95 | const { topic, body, tag, shardingKey = "", keys, messageProperties } = options; 96 | 97 | const res = await this._client._request({ 98 | method: "POST", 99 | path: "/v1/messages", 100 | data: { 101 | clientToken: this._clientToken as string, 102 | message: { 103 | topic: this._client.getTopicId(topic), 104 | body, 105 | tag, 106 | shardingKey, 107 | keys, 108 | properties: messageProperties?.properties || {}, 109 | }, 110 | }, 111 | httpAgent: this._producerAgent, 112 | }); 113 | 114 | return res.result; 115 | } 116 | } 117 | -------------------------------------------------------------------------------- /src/services/rocketmq/index.ts: -------------------------------------------------------------------------------- 1 | export { Client } from "./Client"; 2 | export { Producer, MessageProperties } from "./Producer"; 3 | export { Consumer } from "./Consumer"; 4 | -------------------------------------------------------------------------------- /src/services/rocketmq/protocol/errors.ts: -------------------------------------------------------------------------------- 1 | export enum ErrorCode { 2 | Success = "0", 3 | 4 | InvalidParameter = "100000", 5 | TopicNotExist = "100001", 6 | GroupNotExist = "100002", 7 | UnsurpportedClientType = "100003", 8 | NoAccessPermissionForTopic = "100004", 9 | NoAccessPermissionForGroup = "100005", 10 | InvalidProperties = "100006", 11 | ClientNotFound = "100007", 12 | ReqBodyNotExist = "100008", 13 | InternalServerError = "100009", 14 | ClientHasTaskRunning = "100010", 15 | ReqBodyTooLarge = "100011", 16 | AckMessageError = "100012", 17 | UnknownError = "100013", 18 | 19 | // 拉取消息的参数不合法 20 | InvalidPollRequestParameter = "100018", 21 | ProducerGroupHasAlreadyExist = "100019", 22 | 23 | // 延时等级不合法 24 | InvalidDelayTimeLevel = "100020", 25 | 26 | // 下面号段的errorCode是可以重试的 27 | RetryErrorCodeStart = "300000", 28 | 29 | // 流控相关 30 | TooManyWaitAckMessage = "300001", 31 | 32 | // proxy 维度流控 33 | TooManyOpenRequest = "300002", 34 | // 太多ack消息的qps clientToken 维度流控 35 | TooManyAckRequest = "300003", 36 | // 太多写入消息的qps clientToken 维度流控 37 | TooManySendRequest = "300004", 38 | } 39 | -------------------------------------------------------------------------------- /src/services/rocketmq/protocol/v1.ts: -------------------------------------------------------------------------------- 1 | // auto generated by rpc-ts-gen don't break 2 | /* tslint-disable */ 3 | /* eslint-disable */ 4 | 5 | export enum RequestType { 6 | 7 | Open = "Open", 8 | 9 | Close = "Close", 10 | 11 | Heartbeat = "Heartbeat", 12 | 13 | Send = "Send", 14 | 15 | Consume = "Consume", 16 | 17 | Ack = "Ack", 18 | 19 | ConsumerGroupInfo = "ConsumerGroupInfo" 20 | } 21 | 22 | export interface OpenReq { 23 | clientVersion: string; 24 | properties: Record; 25 | requestId: string; 26 | type: string; 27 | clientToken?: string; 28 | group?: string; 29 | subscriptions?: Record; 30 | } 31 | 32 | export interface OpenRespResult { 33 | /** 前端精度问题,改成了string,原来类型为i64这里预期返回java里的System.currentTimestamp()毫秒级别时间戳 */ 34 | clientToken: string; 35 | nextHeartbeatDeadline: string; 36 | } 37 | 38 | export interface OpenResp { 39 | requestId: string; 40 | code: string; 41 | msg: string; 42 | result: OpenRespResult; 43 | } 44 | 45 | export interface HeartbeatReq { 46 | clientToken: string; 47 | requestId: string; 48 | properties?: Record; 49 | } 50 | 51 | export interface CloseReq { 52 | clientToken: string; 53 | requestId: string; 54 | properties?: Record; 55 | } 56 | 57 | export interface SendMessage { 58 | topic: string; 59 | tag?: string; 60 | shardingKey?: string; 61 | keys?: string[]; 62 | properties?: Record; 63 | body: string; 64 | } 65 | 66 | export interface SendReq { 67 | clientToken: string; 68 | requestId: string; 69 | message: SendMessage; 70 | } 71 | 72 | export interface MessageMeta { 73 | topic: string; 74 | /** 前端精度问题从i64改成了string这里对应类型是64位整形 */ 75 | queueId: string; 76 | queueOffset: string; 77 | /** onlytransactionalmessagehasmsgHandle */ 78 | msgId: string; 79 | msgHandle?: string; 80 | } 81 | export type SendResult = MessageMeta; 82 | 83 | export interface SendResp { 84 | clientToken: string; 85 | requestId: string; 86 | code: string; 87 | msg: string; 88 | result: SendResult; 89 | } 90 | 91 | export interface ConsumeReq { 92 | clientToken: string; 93 | requestId: string; 94 | maxMessageNumber?: number; 95 | maxWaitTimeMs?: number; 96 | } 97 | 98 | export interface ConsumeMessage { 99 | /** 前端精度问题,这里预期是32位整形 */ 100 | topic: string; 101 | /** 前端精度问题,这里预期是64位整形 */ 102 | queueId: string; 103 | /** 前端精度问题,这里预期是64位整形,表示毫秒级别时间戳 */ 104 | queueOffset: string; 105 | bornTimeStamp: string; 106 | /** 前端精度问题,这里预期是64位整形,表示毫秒级别时间戳 */ 107 | bornHost: string; 108 | storeTimeStamp: string; 109 | msgId: string; 110 | reconsumeTimes: number; 111 | /** 每条消息实际只有一个tag */ 112 | keys: string[]; 113 | tag: string; 114 | properties: Record; 115 | body: string; 116 | bodyCRC: string; 117 | msgHandle: string; 118 | } 119 | 120 | export interface ConsumeResult { 121 | messages: ConsumeMessage[]; 122 | } 123 | 124 | export interface ConsumeResp { 125 | clientToken: string; 126 | requestId: string; 127 | code: string; 128 | msg: string; 129 | result: ConsumeResult; 130 | } 131 | 132 | export interface AckReq { 133 | clientToken: string; 134 | requestId: string; 135 | acks: string[]; 136 | nacks: string[]; 137 | } 138 | 139 | export interface FailAckHandleEntry { 140 | msgHandle: string; 141 | code: string; 142 | msg: string; 143 | } 144 | 145 | export interface AckResult { 146 | failHandles: FailAckHandleEntry[]; 147 | } 148 | 149 | export interface AckResp { 150 | clientToken: string; 151 | requestId: string; 152 | code: string; 153 | msg: string; 154 | result: AckResult; 155 | } 156 | -------------------------------------------------------------------------------- /src/services/rocketmq/types.ts: -------------------------------------------------------------------------------- 1 | import { ConsumeMessage } from "./protocol/v1"; 2 | import { MessageProperties } from "./Producer"; 3 | 4 | /** Client */ 5 | export interface ClientOptions { 6 | endpoint: string; 7 | instanceId: string; 8 | accessKey: string; 9 | secretKey: string; 10 | } 11 | 12 | export type WorkerStatus = 13 | | "initialized" 14 | | "connecting" 15 | | "connectFailed" 16 | | "connected" 17 | | "closing" 18 | | "closeFailed" 19 | | "closed"; 20 | 21 | /** producer */ 22 | export interface PublishMessageOptions { 23 | topic: string; 24 | shardingKey?: string; 25 | tag?: string; 26 | keys?: string[]; 27 | body: string; 28 | messageProperties?: MessageProperties; 29 | } 30 | 31 | export interface ConsumerOptions { 32 | /** 33 | * Group ID for consumer. 34 | */ 35 | group: string; 36 | /** 37 | * Limit number of messages per poll. 38 | * @default 10 39 | */ 40 | maxMessageNumber?: number; 41 | /** 42 | * Duration for waiting message. 43 | * @default 3000 44 | */ 45 | maxWaitTimeMs?: number; 46 | /** 47 | * Polling request interval (MS). 48 | * @default 0 49 | */ 50 | pollingInterval?: number; 51 | } 52 | 53 | export interface ConsumerSubscribeOption { 54 | topic: string; 55 | tag?: string; 56 | } 57 | 58 | export interface ConsumerRunOptions { 59 | eachMessage: (message: ConsumeMessage) => Promise; 60 | } 61 | 62 | export interface ACKMessagesOptions { 63 | acks: string[]; 64 | nacks?: string[]; 65 | } 66 | -------------------------------------------------------------------------------- /src/services/rocketmq/utils/agent.ts: -------------------------------------------------------------------------------- 1 | import http from "http"; 2 | 3 | export type MQAgentOptions = http.AgentOptions; 4 | 5 | export class MQAgent extends http.Agent { 6 | constructor(options: MQAgentOptions) { 7 | super(options); 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /src/services/rocketmq/utils/common.ts: -------------------------------------------------------------------------------- 1 | import { isMQError } from "./error"; 2 | import { ErrorCode } from "../protocol/errors"; 3 | 4 | export function sleep(time: number) { 5 | return new Promise((rs) => setTimeout(rs, time)); 6 | } 7 | 8 | export function requiredCheck(obj: T, keys: Array): string[] { 9 | const fields: string[] = []; 10 | for (const key of keys) { 11 | if (obj[key] === undefined) { 12 | fields.push(key as string); 13 | } 14 | } 15 | return fields; 16 | } 17 | 18 | export class Resolver { 19 | promise: Promise; 20 | 21 | resolve: (data: R) => void; 22 | 23 | reject: (e: any) => void; 24 | 25 | constructor() { 26 | this.promise = new Promise((rs, rj) => { 27 | this.resolve = rs; 28 | this.reject = rj; 29 | }); 30 | } 31 | } 32 | 33 | export function isNeedReconnectError(err: any): boolean { 34 | if (isMQError(err) && err.type === "REQUEST_ERROR") { 35 | const cause = err.cause; 36 | // 两种情况需要重连 37 | // 1. 没有状态码, 说明有网络问题 38 | // 2. 有状态码,但是code是ClientNotFound 说明token已经失效 39 | return !cause?.status || cause?.response?.code === ErrorCode.ClientNotFound; 40 | } else { 41 | return false; 42 | } 43 | } 44 | 45 | export function instanceNeedNamespace(instanceId: string): boolean { 46 | return /^MQ_INST/.test(instanceId); 47 | } 48 | -------------------------------------------------------------------------------- /src/services/rocketmq/utils/error.ts: -------------------------------------------------------------------------------- 1 | export type ErrorType = "NORMAL_ERROR" | "REQUEST_ERROR"; 2 | 3 | export interface MQErrorConfig { 4 | type?: ErrorType; 5 | cause?: any; 6 | } 7 | 8 | export class MQError extends Error { 9 | type: ErrorType; 10 | 11 | cause: any; 12 | 13 | constructor(e: any, config?: MQErrorConfig) { 14 | const { type = "NORMAL_ERROR", cause } = config || {}; 15 | super(e); 16 | 17 | this.type = type; 18 | this.cause = cause; 19 | } 20 | } 21 | 22 | export function isMQError(error: any): error is MQError { 23 | return error instanceof MQError; 24 | } 25 | -------------------------------------------------------------------------------- /src/services/rocketmq/utils/logger.ts: -------------------------------------------------------------------------------- 1 | import dayjs from "dayjs"; 2 | 3 | export type LogType = "ERROR" | "INFO" | "WARN" | "DEBUG"; 4 | 5 | export enum LogLevel { 6 | DEBUG = 0, 7 | INFO = 1, 8 | WARN = 2, 9 | ERROR = 3, 10 | } 11 | 12 | export interface LoggerConfig { 13 | namespace: string; 14 | } 15 | 16 | export interface LogParams { 17 | timeSpent?: number; 18 | payload?: Record; 19 | } 20 | 21 | export interface FormatConfig { 22 | logType: LogType; 23 | } 24 | 25 | export default class Logger { 26 | private _namespace: string; 27 | private _logLevel: LogLevel; 28 | 29 | constructor(config: LoggerConfig) { 30 | const { namespace } = config; 31 | 32 | this._namespace = namespace; 33 | this._logLevel = this.getLogLevel(); 34 | } 35 | 36 | error(msg: string, params: LogParams = {}) { 37 | if (LogLevel.ERROR < this._logLevel) return; 38 | 39 | const logMsg = this._formatLog(msg, params, { logType: "ERROR" }); 40 | this._print(logMsg); 41 | } 42 | 43 | warn(msg: string, params: LogParams = {}) { 44 | if (LogLevel.WARN < this._logLevel) return; 45 | 46 | const logMsg = this._formatLog(msg, params, { logType: "WARN" }); 47 | this._print(logMsg); 48 | } 49 | 50 | info(msg: string, params: LogParams = {}) { 51 | if (LogLevel.INFO < this._logLevel) return; 52 | 53 | const logMsg = this._formatLog(msg, params, { logType: "INFO" }); 54 | this._print(logMsg); 55 | } 56 | 57 | debug(msg: string, params: LogParams = {}) { 58 | if (LogLevel.DEBUG < this._logLevel) return; 59 | 60 | const logMsg = this._formatLog(msg, params, { logType: "DEBUG" }); 61 | this._print(logMsg); 62 | } 63 | 64 | private _formatLog(msg: string, params: LogParams, config: FormatConfig) { 65 | const { logType } = config; 66 | const { timeSpent, payload } = params; 67 | 68 | const timeNow = dayjs().format("YYYY-MM-DD HH:mm:ss"); 69 | 70 | const msgList: string[] = [timeNow, logType, `[${this._namespace}]`]; 71 | 72 | if (msg) msgList.push(msg); 73 | if (timeSpent !== undefined) msgList.push(`${timeSpent}ms`); 74 | if (payload) msgList.push(JSON.stringify(payload)); 75 | 76 | return msgList.join("\t"); 77 | } 78 | 79 | private _print(msg) { 80 | console.log(msg); // eslint-disable-line 81 | } 82 | 83 | private getLogLevel() { 84 | const level = Number(process.env.MQ_LOG_LEVEL); 85 | if (Number.isNaN(level)) { 86 | return LogLevel.INFO; 87 | } 88 | if (level < LogLevel.DEBUG || level > LogLevel.ERROR) { 89 | return LogLevel.INFO; 90 | } 91 | return level; 92 | } 93 | } 94 | -------------------------------------------------------------------------------- /src/services/rocketmq/utils/request.ts: -------------------------------------------------------------------------------- 1 | import axios, { AxiosError, AxiosRequestConfig } from "axios"; 2 | import { MQError } from "./error"; 3 | 4 | export type SendRequestOptions = AxiosRequestConfig; 5 | 6 | export async function sendRequest(options: SendRequestOptions) { 7 | const { data } = options; 8 | 9 | try { 10 | const result = await axios(options); 11 | 12 | return result.data; 13 | } catch (error) { 14 | const response = (error as AxiosError).response; 15 | const status = response?.status; 16 | const respData = response?.data; 17 | 18 | const message = respData?.msg || response?.statusText || error.message; 19 | 20 | throw new MQError(message, { 21 | type: "REQUEST_ERROR", 22 | cause: { status, params: data, response: respData }, 23 | }); 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /src/services/rtc/README.md: -------------------------------------------------------------------------------- 1 | volc-sdk-nodejs是签名的sdk,并非接口的sdk。 2 | 3 | volc-sdk-nodejs/src/services/rtc 中仅实现了ListIndicators和ListRooms两个接口,并非包含所有接口。 4 | 5 | 用户可以参考demo.js中的实现,或把它拷贝到自己的项目中追加所需的API 6 | -------------------------------------------------------------------------------- /src/services/rtc/demo.js: -------------------------------------------------------------------------------- 1 | import { rtcOpenapi } from "@volcengine/openapi"; 2 | 3 | async function main(AccessKeyId, SecretKey, SessionToken) { 4 | // 使用默认的service实例 也可以创建一个新实例 const rtcOpenapiService = new rtcOpenapi.RtcService(); 5 | const rtcOpenapiService = rtcOpenapi.defaultService; 6 | // 设置aksk 7 | rtcOpenapiService.setAccessKeyId(AccessKeyId); 8 | rtcOpenapiService.setSecretKey(SecretKey); 9 | 10 | if (SessionToken) { 11 | // 使用sts请求时 设置SessionToken 12 | rtcOpenapiService.setSessionToken(SessionToken); 13 | } 14 | 15 | // 获取房间信息 16 | await rtcOpenapiService.StartRecord({ 17 | "AppId" : "Your_AppId", 18 | "BusinessId" : "Your_BusinessId", 19 | "RoomId" : "Your_RoomId", 20 | "TaskId": "Your_TaskId", 21 | "RecordMode": 0, 22 | "FileFormatConfig": { 23 | "FileFormat": ["HLS", "FLV"] 24 | }, 25 | "FileNameConfig": { 26 | "Prefix": ["directory1", "directory2"], 27 | "Pattern": "" 28 | }, 29 | "StorageConfig": { 30 | "Type": 0, 31 | "TosConfig": { 32 | "UserAccountId": "Your_UserAccountId", 33 | "Region": "Your_Region", 34 | "Bucket": "Your_Bucket" 35 | } 36 | } 37 | }); 38 | 39 | // 获取质量数据 40 | await rtcOpenapiService.StopRecord({ 41 | "AppId" : "Your_AppId", 42 | "RoomId" : "Your_RoomId", 43 | "TaskId": "Your_TaskId" 44 | }); 45 | 46 | // 自定义OpenAPI请求 47 | await rtcOpenapiService.fetchOpenAPI({ 48 | Action: "GetRecordTask", 49 | Version: "2022-06-01", 50 | query: { 51 | AppId: "Your_AppId", 52 | RoomId: "Your_RoomId", 53 | TaskId: "Your_TaskId" 54 | }, 55 | }); 56 | } -------------------------------------------------------------------------------- /src/services/rtc/index.ts: -------------------------------------------------------------------------------- 1 | import Service from "../../base/service"; 2 | import { ServiceOptions } from "../../base/types"; 3 | import { 4 | StartRecordParams, 5 | StartRecordResult, 6 | StopRecordParams, 7 | StopRecordResult, 8 | GetRecordTaskParams, 9 | GetRecordTaskResult, 10 | } from "./types"; 11 | 12 | export class RtcService extends Service { 13 | constructor(options?: ServiceOptions) { 14 | super({ 15 | ...options, 16 | defaultVersion: "2022-06-01", 17 | serviceName: "rtc", 18 | }); 19 | } 20 | 21 | StartRecord = this.createAPI("StartRecord", { 22 | method: "POST", 23 | contentType: "json", 24 | Version: "2022-06-01", 25 | }); 26 | 27 | StopRecord = this.createAPI("StopRecord", { 28 | method: "POST", 29 | contentType: "json", 30 | Version: "2022-06-01", 31 | }); 32 | 33 | GetRecordTask = this.createAPI("GetRecordTask", { 34 | method: "GET", 35 | contentType: "json", 36 | Version: "2022-06-01", 37 | queryKeys: ["AppId", "RoomId", "TaskId"], 38 | }); 39 | } 40 | 41 | export const defaultService = new RtcService(); 42 | -------------------------------------------------------------------------------- /src/services/rtc/types.ts: -------------------------------------------------------------------------------- 1 | interface IRoom { 2 | RoomId: string; 3 | AppId: string; 4 | UserNum: number; 5 | StreamNum: number; 6 | State: number; 7 | CreatedAt: string; 8 | UpdatedAt: string; 9 | } 10 | 11 | interface IData { 12 | TimeStamp: string; 13 | Value: number; 14 | } 15 | 16 | interface IIndicator { 17 | Name: string; 18 | Unit: string; 19 | Data: IData[]; 20 | } 21 | 22 | export interface ListRoomsParams { 23 | Action: string; 24 | Version: string; 25 | AppId: string; 26 | RoomId?: string; 27 | Reverse?: number; 28 | Offset?: string; 29 | Limit?: number; 30 | } 31 | 32 | export interface ListRoomsResult { 33 | Total: number; 34 | ActiveNum: number; 35 | InactiveNum: number; 36 | Offset: number; 37 | Limit: number; 38 | Rooms: IRoom[]; 39 | } 40 | 41 | export interface ListIndicatorsParams { 42 | AppId: string; 43 | StartTime: string; 44 | EndTime: string; 45 | Indicator: string; 46 | OS?: string; 47 | Network?: string; 48 | } 49 | 50 | export interface ListIndicatorsResult { 51 | Indicators: IIndicator[]; 52 | } 53 | 54 | type Stream = { Index?: number; UserId: string; StreamType?: number }; 55 | 56 | type Streams = { 57 | StreamList: Stream[]; 58 | }; 59 | 60 | type Encode = { 61 | VideoWidth?: number; 62 | VideoFps?: number; 63 | VideoBitrate?: number; 64 | VideoCodec?: number; 65 | VideoGop?: number; 66 | AudioCodec?: number; 67 | AudioProfile?: number; 68 | AudioBitrate?: number; 69 | AudioSampleRate?: number; 70 | AudioChannels?: number; 71 | }; 72 | 73 | type Canvas = { 74 | Width: number; 75 | Height: number; 76 | Background: string; 77 | }; 78 | 79 | type Region = { 80 | StreamIndex: number; 81 | LocationX: number; 82 | LocationY: number; 83 | WidthProportion: number; 84 | HeightProportion: number; 85 | Zorder?: number; 86 | Alpha?: number; 87 | RenderMode?: number; 88 | SourceCrop?: { 89 | LocationX: number; 90 | LocationY: number; 91 | WidthProportion: number; 92 | HeightProportion: number; 93 | }; 94 | AlternateImage: string; 95 | }; 96 | type CustomLayout = { 97 | Canvas: Canvas; 98 | Regions: Region[]; 99 | }; 100 | export interface StartRecordParams { 101 | AppId: string; 102 | BusinessId?: string; 103 | RoomId: string; 104 | TaskId: string; 105 | RecordMode?: number; 106 | TargetStreams?: Streams; 107 | ExcludeStreams?: Streams; 108 | Encode?: Encode; 109 | Layout: { 110 | LayoutMode?: number; 111 | MainVideoStream?: Stream; 112 | CustomLayout: CustomLayout; 113 | }; 114 | FileFormatConfig: { 115 | FileFormat: string[]; 116 | }; 117 | FileNameConfig: { 118 | Prefix: string[]; 119 | Pattern: string; 120 | }; 121 | StorageConfig: { 122 | Type: number; 123 | TosConfig: { 124 | UserAccountId: string; 125 | Region: string; 126 | Bucket: string; 127 | }; 128 | }; 129 | } 130 | 131 | export type StartRecordResult = string; 132 | 133 | export interface StopRecordParams { 134 | AppId: string; 135 | BusinessId?: string; 136 | RoomId: string; 137 | TaskId: string; 138 | } 139 | 140 | export type StopRecordResult = string; 141 | 142 | export interface GetRecordTaskParams { 143 | Action: string; 144 | Version: string; 145 | AppId: string; 146 | RoomId: string; 147 | TaskId: string; 148 | } 149 | 150 | export interface GetRecordTaskResult { 151 | RecordTask: { 152 | StartTime: number; 153 | EndTime: number; 154 | Status: number; 155 | StopReason: string; 156 | RecordFileList: { 157 | Vid: string; 158 | Duration: number; 159 | Size: number; 160 | StartTime: number; 161 | StreamList: [ 162 | { 163 | UserId: string; 164 | StreamType: number; 165 | } 166 | ]; 167 | }[]; 168 | }; 169 | } 170 | -------------------------------------------------------------------------------- /src/services/sms/demo.js: -------------------------------------------------------------------------------- 1 | import { sms } from "@volcengine/openapi"; 2 | 3 | export async function main(AccessKeyId, SecretKey) { 4 | const smsService = sms.defaultService; 5 | smsService.setAccessKeyId(AccessKeyId); 6 | smsService.setSecretKey(SecretKey); 7 | 8 | // 发送单条测试短信 9 | await smsService.Send({ 10 | SmsAccount: "7384exxx", 11 | Sign: "测试签名", 12 | TemplateID: "SPT_1000000", 13 | PhoneNumbers: "186xxxxxxxx", 14 | TemplateParam: JSON.stringify({ content: "Hello World" }), 15 | Tag: "tag", 16 | }); 17 | } 18 | main(); 19 | -------------------------------------------------------------------------------- /src/services/sms/index.ts: -------------------------------------------------------------------------------- 1 | import Service from "../../base/service"; 2 | import { ServiceOptions } from "../../base/types"; 3 | import { 4 | BatchSendSmsParams, 5 | SendSmsParams, 6 | ConversionParams, 7 | ConversionResponse, 8 | CheckVerifyCodeParams, 9 | CheckVerifyCodeResponse, 10 | SendVerifyCodeParams, 11 | SendVerifyCodeResponse, 12 | SendSmsResponse, 13 | BatchSendSmsResponse, 14 | ApplyVmsTemplateParams, 15 | ApplyVmsTemplateResponse, 16 | GetVmsTemplateStatusParams, 17 | GetVmsTemplateStatusResponse, 18 | GetSmsTemplateAndOrderListParams, 19 | GetSmsTemplateAndOrderListResponse, 20 | ApplySmsTemplateParams, 21 | ApplySmsTemplateResponse, 22 | DeleteSmsTemplateParams, 23 | DeleteSmsTemplateResponse, 24 | GetSubAccountListParams, 25 | GetSubAccountListResponse, 26 | GetSubAccountDetailParams, 27 | GetSubAccountDetailResponse, 28 | InsertSmsSubAccountParams, 29 | InsertSmsSubAccountResponse, 30 | ApplySmsSignatureParams, 31 | ApplySmsSignatureResponse, 32 | DeleteSignatureParams, 33 | DeleteSignatureResponse, 34 | GetSignatureAndOrderListParams, 35 | GetSignatureAndOrderListResponse, 36 | } from "./types"; 37 | enum HttpMethod { 38 | GET = "GET", 39 | DELETE = "DELETE", 40 | POST = "POST", 41 | PUT = "PUT", 42 | Patch = "PATCH", // RFC 5789 43 | Connect = "CONNECT", 44 | Options = "OPTIONS", 45 | Trace = "TRACE", 46 | } 47 | const ServiceVersion20200101 = "2020-01-01"; 48 | const ServiceVersion20210101 = "2021-01-01"; 49 | const ServiceVersion20210111 = "2021-01-11"; 50 | 51 | export class SmsService extends Service { 52 | constructor(options?: ServiceOptions) { 53 | super({ 54 | ...options, 55 | host: "sms.volcengineapi.com", 56 | serviceName: "volcSMS", 57 | }); 58 | } 59 | 60 | /** sms group */ 61 | Send = this.createAPI("SendSms", { 62 | method: HttpMethod.POST, 63 | contentType: "json", 64 | Version: ServiceVersion20200101, 65 | }); 66 | 67 | BatchSend = this.createAPI("SendBatchSms", { 68 | method: HttpMethod.POST, 69 | contentType: "json", 70 | Version: ServiceVersion20210101, 71 | }); 72 | 73 | Conversion = this.createAPI("Conversion", { 74 | method: HttpMethod.POST, 75 | contentType: "json", 76 | Version: ServiceVersion20200101, 77 | }); 78 | 79 | SendVerifyCode = this.createAPI( 80 | "SendSmsVerifyCode", 81 | { 82 | method: HttpMethod.POST, 83 | contentType: "json", 84 | Version: ServiceVersion20200101, 85 | } 86 | ); 87 | 88 | CheckVerifyCode = this.createAPI( 89 | "CheckSmsVerifyCode", 90 | { 91 | method: HttpMethod.POST, 92 | contentType: "json", 93 | Version: ServiceVersion20200101, 94 | } 95 | ); 96 | 97 | /* sms - end */ 98 | 99 | /* vms */ 100 | ApplyVmsTemplate = this.createAPI( 101 | "ApplyVmsTemplate", 102 | { 103 | method: HttpMethod.POST, 104 | contentType: "json", 105 | Version: ServiceVersion20210111, 106 | } 107 | ); 108 | 109 | GetVmsTemplateStatus = this.createAPI( 110 | "GetVmsTemplateStatus", 111 | { 112 | method: HttpMethod.POST, 113 | contentType: "json", 114 | Version: ServiceVersion20210111, 115 | } 116 | ); 117 | 118 | SendVms = this.createAPI("SendSms", { 119 | method: HttpMethod.POST, 120 | contentType: "json", 121 | Version: ServiceVersion20210111, 122 | }); 123 | /* vms -end */ 124 | 125 | /* template -start */ 126 | GetSmsTemplateAndOrderList = this.createAPI< 127 | GetSmsTemplateAndOrderListParams, 128 | GetSmsTemplateAndOrderListResponse 129 | >("GetSmsTemplateAndOrderList", { 130 | method: HttpMethod.GET, 131 | contentType: "json", 132 | Version: ServiceVersion20210111, 133 | }); 134 | 135 | ApplySmsTemplate = this.createAPI( 136 | "ApplySmsTemplate", 137 | { 138 | method: HttpMethod.POST, 139 | contentType: "json", 140 | Version: ServiceVersion20210111, 141 | } 142 | ); 143 | 144 | DeleteSmsTemplate = this.createAPI( 145 | "DeleteSmsTemplate", 146 | { 147 | method: HttpMethod.POST, 148 | contentType: "json", 149 | Version: ServiceVersion20210111, 150 | } 151 | ); 152 | /* template end*/ 153 | 154 | /* subAccount start*/ 155 | GetSubAccountList = this.createAPI( 156 | "GetSubAccountList", 157 | { 158 | method: HttpMethod.GET, 159 | contentType: "json", 160 | Version: ServiceVersion20210111, 161 | } 162 | ); 163 | 164 | GetSubAccountDetail = this.createAPI( 165 | "GetSubAccountDetail", 166 | { 167 | method: HttpMethod.GET, 168 | contentType: "json", 169 | Version: ServiceVersion20210111, 170 | } 171 | ); 172 | 173 | InsertSmsSubAccount = this.createAPI( 174 | "InsertSmsSubAccount", 175 | { 176 | method: HttpMethod.POST, 177 | contentType: "json", 178 | Version: ServiceVersion20210111, 179 | } 180 | ); 181 | /* subAccount end*/ 182 | 183 | /* signature start*/ 184 | GetSignatureAndOrderList = this.createAPI< 185 | GetSignatureAndOrderListParams, 186 | GetSignatureAndOrderListResponse 187 | >("GetSignatureAndOrderList", { 188 | method: HttpMethod.GET, 189 | contentType: "json", 190 | Version: ServiceVersion20210111, 191 | }); 192 | 193 | ApplySmsSignature = this.createAPI( 194 | "ApplySmsSignature", 195 | { 196 | method: HttpMethod.GET, 197 | contentType: "json", 198 | Version: ServiceVersion20210111, 199 | } 200 | ); 201 | 202 | DeleteSignature = this.createAPI( 203 | "DeleteSignature", 204 | { 205 | method: HttpMethod.POST, 206 | contentType: "json", 207 | Version: ServiceVersion20210111, 208 | } 209 | ); 210 | /* signature end*/ 211 | } 212 | 213 | export const defaultService = new SmsService(); 214 | -------------------------------------------------------------------------------- /src/services/sts/README.md: -------------------------------------------------------------------------------- 1 | ### sts openapi service -------------------------------------------------------------------------------- /src/services/sts/index.ts: -------------------------------------------------------------------------------- 1 | import Service from "../../base/service"; 2 | import { ServiceOptions } from "../../base/types"; 3 | 4 | interface AssumeRoleParams { 5 | RoleTrn: string; 6 | RoleSessionName: string; 7 | DurationSeconds?: number; 8 | Policy?: string; 9 | } 10 | 11 | interface AssumeRoleResult { 12 | Credentials: { 13 | CurrentTime: string; 14 | ExpiredTime: string; 15 | AccessKeyId: string; 16 | SecretAccessKey: string; 17 | SessionToken: string; 18 | }; 19 | AssumedRoleUser: { 20 | Trn: string; 21 | AssumedRoleId: string; 22 | }; 23 | } 24 | 25 | export class StsService extends Service { 26 | constructor(options?: ServiceOptions) { 27 | super({ 28 | ...options, 29 | defaultVersion: "2018-01-01", 30 | serviceName: "sts", 31 | }); 32 | } 33 | 34 | AssumeRole = this.createAPI("AssumeRole"); 35 | } 36 | 37 | export const defaultService = new StsService(); 38 | -------------------------------------------------------------------------------- /src/services/tls/demo.js: -------------------------------------------------------------------------------- 1 | const { tlsOpenapi } = require("@volcengine/openapi"); 2 | export async function main(AccessKeyId, SecretKey, SessionToken) { 3 | const tlsOpenapiService = tlsOpenapi.defaultService; 4 | // tls的openApi需要设置host 5 | tlsOpenapiService.setHost("your host"); 6 | // 指定host对应的region,如不设置默认region为 cn-north-1 7 | tlsOpenapiService.setRegion("your region"); 8 | // 设置aksk 9 | tlsOpenapiService.setSecretKey(SecretKey); 10 | tlsOpenapiService.setAccessKeyId(AccessKeyId); 11 | // 设置协议版本,如不设置则默认是https 12 | tlsOpenapiService.setProtocol("http:"); 13 | // 设置openApi版本,如不设置默认为0.2.0 14 | tlsOpenapiService.setVersion("0.2.0"); 15 | 16 | if (SessionToken) { 17 | // 使用sts请求时 设置SessionToken 18 | tlsOpenapiService.setSessionToken(SessionToken); 19 | } 20 | 21 | // 获取项目列表 22 | tlsOpenapiService.DescribeProjects({ 23 | PageNumber: 0, 24 | PageSize: 10, 25 | ProjectName: "项目名称", 26 | ProjectId: "项目ID", 27 | }); 28 | } 29 | -------------------------------------------------------------------------------- /src/services/tls/example/hostGroup.demo.js: -------------------------------------------------------------------------------- 1 | const { tlsOpenapi } = require("@volcengine/openapi"); 2 | 3 | // host group 4 | async function main() { 5 | const tlsOpenapiService = tlsOpenapi.defaultService; 6 | tlsOpenapiService.setHost("your host"); 7 | tlsOpenapiService.setSecretKey("your secret key"); 8 | tlsOpenapiService.setAccessKeyId("your access key id"); 9 | 10 | // create host group 11 | const hostGroupCreateResp = await tlsOpenapiService.CreateHostGroup({ 12 | HostGroupName: "host group name", 13 | HostGroupType: "host group type", 14 | HostIdentifier: "host identifier", 15 | }); 16 | 17 | // query host group 18 | const hostGroupQueryResp = await tlsOpenapiService.DescribeHostGroup({ 19 | HostGroupId: "host group id", 20 | }); 21 | 22 | // modify host group 23 | const hostGroupModifyResp = await tlsOpenapiService.ModifyHostGroup({ 24 | HostGroupId: "host group id", 25 | HostGroupName: "host group name", 26 | HostGroupType: "host group type", 27 | HostIdentifier: "host identifier", 28 | }); 29 | 30 | // delete host group 31 | const hostGroupDeleteResp = await tlsOpenapiService.DeleteHostGroup({ 32 | HostGroupId: "host group id", 33 | }); 34 | 35 | // query host groups 36 | const hostGroupListResp = await tlsOpenapiService.DescribeHostGroups({ 37 | PageNumber: 1, 38 | PageSize: 10, 39 | }); 40 | } 41 | -------------------------------------------------------------------------------- /src/services/tls/example/index.demo.js: -------------------------------------------------------------------------------- 1 | const { tlsOpenapi } = require("@volcengine/openapi"); 2 | 3 | // index 4 | async function main() { 5 | const tlsOpenapiService = tlsOpenapi.defaultService; 6 | tlsOpenapiService.setHost("your host"); 7 | tlsOpenapiService.setSecretKey("your secret key"); 8 | tlsOpenapiService.setAccessKeyId("your access key id"); 9 | 10 | // create index 11 | const indexCreateResp = await tlsOpenapiService.CreateIndex({ 12 | TopicId: "topic id", 13 | FullText: { 14 | CaseSensitive: false, 15 | Delimiter: "_", 16 | IncludeChinese: false, 17 | }, 18 | }); 19 | 20 | // query index 21 | const indexQueryResp = await tlsOpenapiService.DescribeIndex({ 22 | TopicId: "topic id", 23 | }); 24 | 25 | // modify index 26 | const indexModifyResp = await tlsOpenapiService.ModifyIndex({ 27 | TopicId: "topic id", 28 | FullText: { 29 | CaseSensitive: false, 30 | Delimiter: "_", 31 | IncludeChinese: false, 32 | }, 33 | }); 34 | 35 | const indexDeleteResp = await tlsOpenapiService.DeleteIndex({ 36 | TopicId: "topic id", 37 | }); 38 | } 39 | -------------------------------------------------------------------------------- /src/services/tls/example/log.demo.js: -------------------------------------------------------------------------------- 1 | const { tlsOpenapi } = require("@volcengine/openapi"); 2 | 3 | // log 4 | async function main() { 5 | const tlsOpenapiService = tlsOpenapi.defaultService; 6 | tlsOpenapiService.setHost("your host"); 7 | tlsOpenapiService.setSecretKey("your secret key"); 8 | tlsOpenapiService.setAccessKeyId("your access key id"); 9 | 10 | // search logs 11 | const searchLogsResp = await tlsOpenapiService.SearchLogs({ 12 | StartTime: "log start time", 13 | EndTime: "log end time", 14 | Limit: "page size", 15 | Query: "query phrases", 16 | TopicId: "topic id", 17 | }); 18 | 19 | // put logs 20 | const logsBuffer = await tlsOpenapi.TlsService.objToProtoBuffer({ 21 | LogGroups: [ 22 | { 23 | Logs: [ 24 | { 25 | Time: Date.now(), 26 | Contents: [{ Key: "TEST", Value: "TEST" }], 27 | }, 28 | ], 29 | Source: "TEST", 30 | LogTags: [{ Key: "Tag", Value: "Tag" }], 31 | FileName: "TEST", 32 | ContextFlow: "TEST", 33 | }, 34 | ], 35 | }); 36 | 37 | const putLogsResp = await tlsOpenapiService.PutLogs({ 38 | TopicId: "topic id", 39 | CompressType: "logs compress type", 40 | LogGroupList: logsBuffer, 41 | }); 42 | } 43 | -------------------------------------------------------------------------------- /src/services/tls/example/project.demo.js: -------------------------------------------------------------------------------- 1 | const { tlsOpenapi } = require("@volcengine/openapi"); 2 | 3 | // project 4 | async function main() { 5 | const tlsOpenapiService = tlsOpenapi.defaultService; 6 | tlsOpenapiService.setHost("your host"); 7 | tlsOpenapiService.setSecretKey("your secret key"); 8 | tlsOpenapiService.setAccessKeyId("your access key id"); 9 | 10 | // create project 11 | const projectCreateResp = await tlsOpenapiService.CreateProject({ 12 | ProjectName: "project name", 13 | Region: "project belong to which region", 14 | }); 15 | 16 | // query project 17 | const projectQueryResp = await tlsOpenapiService.DescribeProject({ 18 | ProjectId: "project id", 19 | }); 20 | 21 | // modify project 22 | const projectModifyResp = await tlsOpenapiService.ModifyProject({ 23 | ProjectId: "project id", 24 | Description: "project description", 25 | }); 26 | 27 | // delete project 28 | const projectDeleteResp = await tlsOpenapiService.DeleteProject({ 29 | ProjectId: "project id", 30 | }); 31 | 32 | // query projects 33 | const projectListResp = await tlsOpenapiService.DescribeProjects({ 34 | PageNumber: 1, 35 | PageSize: 10, 36 | ProjectId: "project id", 37 | ProjectName: "project name", 38 | }); 39 | } 40 | -------------------------------------------------------------------------------- /src/services/tls/example/topic.demo.js: -------------------------------------------------------------------------------- 1 | const { tlsOpenapi } = require("@volcengine/openapi"); 2 | 3 | // topic 4 | async function main() { 5 | const tlsOpenapiService = tlsOpenapi.defaultService; 6 | tlsOpenapiService.setHost("your host"); 7 | tlsOpenapiService.setSecretKey("your secret key"); 8 | tlsOpenapiService.setAccessKeyId("your access key id"); 9 | 10 | // create topic 11 | const topicCreateResp = await tlsOpenapiService.CreateTopic({ 12 | ProjectId: "project id", 13 | ShardCount: "shard count", 14 | TopicName: "topic name", 15 | ttl: "topic ttl", 16 | }); 17 | 18 | // query topic 19 | const topicQueryResp = await tlsOpenapiService.DescribeTopic({ 20 | TopicId: "topic id", 21 | }); 22 | 23 | // modify topic 24 | const topicModifyResp = await tlsOpenapiService.ModifyTopic({ 25 | TopicId: "topic id", 26 | Description: "topic description", 27 | }); 28 | 29 | // delete topic 30 | const topicDeleteResp = await tlsOpenapiService.DeleteTopic({ 31 | TopicId: "topic id", 32 | }); 33 | 34 | // query topics 35 | const topicListResp = await tlsOpenapiService.DescribeTopics({ 36 | PageNumber: 1, 37 | PageSize: 10, 38 | ProjectId: "project id", 39 | TopicId: "topic id", 40 | TopicName: "topic name", 41 | }); 42 | } 43 | -------------------------------------------------------------------------------- /src/services/tls/service.ts: -------------------------------------------------------------------------------- 1 | import axios, { AxiosRequestConfig } from "axios"; 2 | import Signer from "../../base/sign"; 3 | import protobuf from "protobufjs"; 4 | import LZ4 from "./lz4"; 5 | import path from "path"; 6 | import { getDefaultOption } from "./utils"; 7 | import { 8 | IPutLogsReq, 9 | IPutLogsResp, 10 | LogGroupList, 11 | Protocol, 12 | TlsCreateAPIParams, 13 | TlsServiceOptions, 14 | } from "./types"; 15 | 16 | const TIMEOUT = 100000; 17 | 18 | const defaultOptions = getDefaultOption(); 19 | 20 | export default class Service { 21 | constructor(options: TlsServiceOptions) { 22 | this.options = { 23 | ...defaultOptions, 24 | ...options, 25 | }; 26 | } 27 | 28 | private options: TlsServiceOptions; 29 | 30 | setRegion = (region: string) => { 31 | this.options.region = region; 32 | }; 33 | 34 | setHost = (host: string) => (this.options.host = host); 35 | 36 | setVersion = (version: string) => (this.options.version = version); 37 | 38 | setProtocol = (protocol: Protocol) => (this.options.protocol = protocol); 39 | 40 | setAccessKeyId = (accessKeyId: string) => (this.options.accessKeyId = accessKeyId); 41 | 42 | setSecretKey = (secretKey: string) => (this.options.secretKey = secretKey); 43 | 44 | setSessionToken = (sessionToken: string) => (this.options.sessionToken = sessionToken); 45 | 46 | static async fetch(uri: string, requestObj: any): Promise { 47 | const res = await axios({ 48 | url: uri, 49 | timeout: TIMEOUT, 50 | ...requestObj, 51 | }); 52 | return res?.data; 53 | } 54 | 55 | /** 56 | * transfer json to protobuf buffer 57 | */ 58 | static async objToProtoBuffer(obj: LogGroupList) { 59 | const root = await protobuf.load(path.join(__dirname, "./tls.proto")); 60 | const type = root.lookupType("pb.LogGroupList"); 61 | const errMsg = type.verify(obj); 62 | if (errMsg) throw new Error(errMsg); 63 | const message = type.create(obj); 64 | return type.encode(message).finish(); 65 | } 66 | 67 | // protobuf buffer compress 68 | static LZ4Compress(input) { 69 | let output = Buffer.alloc(LZ4.encodeBound(input.length)); 70 | const compressedSize = LZ4.encodeBlock(input, output); 71 | if (!compressedSize) { 72 | throw new Error("no need to compress"); 73 | } 74 | output = output.slice(0, compressedSize); 75 | return output; 76 | } 77 | 78 | createAPI(Path: string, createParams?: TlsCreateAPIParams) { 79 | const { method = "GET", version: versionFromParam } = createParams || {}; 80 | return async (requestData: RequestData, config?: AxiosRequestConfig) => { 81 | const { 82 | accessKeyId, 83 | secretKey, 84 | sessionToken, 85 | host, 86 | protocol, 87 | version: versionFromOptions, 88 | serviceName, 89 | region, 90 | } = this.options; 91 | 92 | const version = versionFromParam || versionFromOptions; 93 | 94 | if (!accessKeyId || !secretKey || !host) 95 | throw new Error(`[tls-node-sdk] host and accessKeyId and secretKey is necessary`); 96 | const requestObj: any = { 97 | region, 98 | method, 99 | pathname: `/${Path}`, 100 | ...config, 101 | headers: { 102 | ...config?.headers, 103 | "x-tls-apiversion": version, 104 | }, 105 | }; 106 | if (method === "GET") { 107 | requestObj.params = requestData; 108 | } else { 109 | requestObj.headers["content-type"] = "application/json"; 110 | requestObj.body = requestData; 111 | requestObj.data = requestData; 112 | } 113 | const signer = new Signer(requestObj, serviceName as string); 114 | signer.addAuthorization({ accessKeyId, secretKey, sessionToken }); 115 | return Service.fetch(`${protocol}//${host}/${Path}`.trim(), requestObj); 116 | }; 117 | } 118 | 119 | createPutLogsAPI(Path: string) { 120 | return async (requestData: IPutLogsReq, config?: AxiosRequestConfig): Promise => { 121 | const { LogGroupList, CompressType, TopicId, HashKey } = requestData; 122 | if (!LogGroupList) throw new Error(`LogGroupList is necessary`); 123 | 124 | // transfer json to compressed protobuf buffer 125 | const pbMessage = LogGroupList; 126 | let lz4CompressFailed = false; 127 | let output = pbMessage; 128 | if (CompressType === "lz4") { 129 | try { 130 | output = Service.LZ4Compress(pbMessage); 131 | } catch (err) { 132 | lz4CompressFailed = true; 133 | } 134 | } 135 | 136 | const { accessKeyId, secretKey, sessionToken, host, version, protocol, serviceName, region } = 137 | this.options; 138 | if (!accessKeyId || !secretKey || !host || !region) { 139 | const missingParams: string[] = []; 140 | if (!accessKeyId) missingParams.push("accessKeyId"); 141 | if (!secretKey) missingParams.push("secretKey"); 142 | if (!host) missingParams.push("host"); 143 | if (!region) missingParams.push("region"); 144 | throw new Error(`[tls-node-sdk] ${missingParams.join(" and ")} is necessary`); 145 | } 146 | 147 | const requestObj: any = { 148 | region, 149 | method: "POST", 150 | pathname: `/${Path}`, 151 | ...config, 152 | headers: { 153 | ...config?.headers, 154 | "x-tls-apiversion": version, 155 | "content-type": "application/x-protobuf", 156 | "x-tls-compresstype": !lz4CompressFailed ? CompressType : "", 157 | "x-tls-hashkey": HashKey || "", 158 | "x-tls-bodyrawsize": pbMessage.length, 159 | }, 160 | }; 161 | if (!requestObj.headers["x-tls-compresstype"]) { 162 | delete requestObj.headers["x-tls-compresstype"]; 163 | } 164 | requestObj.body = output; 165 | requestObj.data = output; 166 | requestObj.params = { 167 | TopicId, 168 | }; 169 | const signer = new Signer(requestObj, serviceName as string); 170 | signer.addAuthorization({ accessKeyId, secretKey, sessionToken }); 171 | return Service.fetch(`${protocol}//${host}/${Path}`.trim(), requestObj); 172 | }; 173 | } 174 | } 175 | -------------------------------------------------------------------------------- /src/services/tls/tls.proto: -------------------------------------------------------------------------------- 1 | syntax = "proto3"; 2 | package pb; 3 | message LogContent 4 | { 5 | string Key = 1; 6 | string Value = 2; 7 | } 8 | 9 | message Log 10 | { 11 | int64 Time = 1;// UNIX Time Format 12 | 13 | repeated LogContent Contents = 2; 14 | 15 | } 16 | message LogTag 17 | { 18 | string Key = 1; 19 | string Value = 2; 20 | } 21 | message LogGroup 22 | { 23 | repeated Log Logs = 1; 24 | string Source = 2; 25 | repeated LogTag LogTags = 3; 26 | string FileName = 4; 27 | string ContextFlow = 5; 28 | } 29 | 30 | message LogGroupList 31 | { 32 | repeated LogGroup LogGroups = 1; 33 | } 34 | -------------------------------------------------------------------------------- /src/services/tls/utils.ts: -------------------------------------------------------------------------------- 1 | import fs from "fs"; 2 | import path from "path"; 3 | 4 | export function getDefaultOption() { 5 | const defaultOptions = { 6 | host: process.env.VOLCENGINE_ENDPOINT, 7 | region: process.env.VOLCENGINE_REGION, 8 | protocol: "https:", 9 | accessKeyId: process.env.VOLCENGINE_ACCESS_KEY_ID, 10 | secretKey: process.env.VOLCENGINE_ACCESS_KEY_SECRET, 11 | }; 12 | try { 13 | // Read aksk from ~/.volc/config. Priority is lower than environment variables 14 | if (process.env.HOME && !(defaultOptions.accessKeyId && defaultOptions.secretKey)) { 15 | const homeConfigPath = path.resolve(process.env.HOME, ".volc/config"); 16 | if (fs.existsSync(homeConfigPath)) { 17 | const configData = JSON.parse(fs.readFileSync(homeConfigPath, { encoding: "utf-8" })); 18 | if (!defaultOptions.accessKeyId && configData.VOLCENGINE_ACCESS_KEY_ID) { 19 | defaultOptions.accessKeyId = configData.VOLCENGINE_ACCESS_KEY_ID; 20 | } 21 | if (!defaultOptions.secretKey && configData.VOLCENGINE_ACCESS_KEY_SECRET) { 22 | defaultOptions.secretKey = configData.VOLCENGINE_ACCESS_KEY_SECRET; 23 | } 24 | if (!defaultOptions.host && configData.VOLCENGINE_ENDPOINT) { 25 | defaultOptions.host = configData.VOLCENGINE_ENDPOINT; 26 | } 27 | if (!defaultOptions.region && configData.VOLCENGINE_REGION) { 28 | defaultOptions.region = configData.VOLCENGINE_REGION; 29 | } 30 | } 31 | } 32 | } catch {} 33 | return defaultOptions; 34 | } 35 | -------------------------------------------------------------------------------- /src/services/vikingdb/abstractService.ts: -------------------------------------------------------------------------------- 1 | import { 2 | type RequestOptions, 3 | VikingdbError, 4 | VikingdbErrorCode, 5 | type VikingdbRegion, 6 | VikingdbRequestError, 7 | } from "./types"; 8 | import Signer from "../../base/sign"; 9 | import type { RequestObj } from "../../base/types"; 10 | import axios, { type AxiosError } from "axios"; 11 | 12 | interface BackendResponse { 13 | code: VikingdbErrorCode; 14 | request_id: string; 15 | data: T; 16 | message: string; 17 | } 18 | 19 | export interface Response extends BackendResponse { 20 | original_request: string; 21 | } 22 | 23 | export abstract class AbstractService { 24 | private region2Url: Record = { 25 | "cn-beijing": "https://api-vikingdb.volces.com", 26 | "cn-shanghai": "https://api-vikingdb.mlp.cn-shanghai.volces.com", 27 | }; 28 | 29 | private get basename() { 30 | return this.region2Url[this.region]; 31 | } 32 | 33 | constructor( 34 | private ak: string, 35 | private sk: string, 36 | private region: VikingdbRegion, 37 | private sessionToken?: string 38 | ) {} 39 | 40 | private sign(pathname: string, body: string, headers: RequestOptions["headers"]) { 41 | const requestObj: RequestObj = { 42 | region: this.region, 43 | headers: { 44 | Accept: "application/json", 45 | "Content-Type": "application/json", 46 | ...headers, 47 | }, 48 | method: "POST", 49 | pathname, 50 | body, 51 | }; 52 | const signer = new Signer(requestObj, "air"); 53 | signer.addAuthorization({ 54 | accessKeyId: this.ak, 55 | secretKey: this.sk, 56 | sessionToken: this.sessionToken, 57 | }); 58 | return requestObj.headers; 59 | } 60 | 61 | protected async request, R = void>( 62 | pathname: string, 63 | data: T = {} as T, 64 | { timeout = 30 * 1000, ...rest }: RequestOptions = { 65 | timeout: 30 * 1000, 66 | } 67 | ): Promise> { 68 | const body = this.encode(data); 69 | const headers = this.sign(pathname, body, rest.headers); 70 | try { 71 | const response = await axios({ 72 | baseURL: this.basename, 73 | url: pathname, 74 | method: "POST", 75 | timeout, 76 | headers, 77 | data: body, 78 | }); 79 | const result: BackendResponse = response.data; 80 | return { 81 | ...result, 82 | original_request: body, 83 | }; 84 | } catch (e) { 85 | const error: AxiosError = e; 86 | if (error.isAxiosError && error.response) { 87 | const result: BackendResponse = error.response.data; 88 | // 业务错误 89 | throw new VikingdbRequestError(result.code, result.message, body, result.request_id); 90 | } 91 | throw new VikingdbError(VikingdbErrorCode.ErrSdk, error.message); 92 | } 93 | } 94 | 95 | protected encode(value: unknown): string { 96 | return JSON.stringify(value); 97 | } 98 | 99 | protected decode(input: string): T { 100 | return JSON.parse(input); 101 | } 102 | 103 | protected isString(value: unknown): value is string { 104 | return typeof value === "string"; 105 | } 106 | 107 | protected isNil(value: unknown): value is null | undefined { 108 | return value == null; 109 | } 110 | 111 | protected isCollectionNameRequest( 112 | request: NonNullable 113 | ): request is T { 114 | return "CollectionName" in request; 115 | } 116 | } 117 | -------------------------------------------------------------------------------- /src/services/vikingdb/collection/backend.ts: -------------------------------------------------------------------------------- 1 | import type { BackendField } from "../types"; 2 | 3 | export interface BackendCreateCollectionRequest { 4 | collection_name: string; 5 | collection_aliases?: string[]; 6 | description?: string; 7 | primary_key: string; 8 | fields: BackendField[]; 9 | } 10 | 11 | export interface BackendCollectionInfo { 12 | collection_name: string; 13 | description?: string; 14 | collection_aliases?: string[]; 15 | primary_key: string | string[]; 16 | fields: BackendField[]; 17 | stat: { 18 | data_number: number; 19 | }; 20 | index_names?: string[]; 21 | index_num: number; 22 | create_time: string; 23 | update_time: string; 24 | update_person: string; 25 | } 26 | 27 | export interface BackendGetCollectionInfoRequest { 28 | collection_name?: string; 29 | collection_alias?: string; 30 | } 31 | 32 | export type BackendUpdateCollectionRequest = Omit; 33 | export interface BackendDropCollectionRequest { 34 | collection_name?: string; 35 | collection_alias?: string; 36 | } 37 | -------------------------------------------------------------------------------- /src/services/vikingdb/collection/pathname.ts: -------------------------------------------------------------------------------- 1 | export enum Pathname { 2 | CreateCollection = "/api/collection/create", 3 | ListCollections = "/api/collection/list", 4 | GetCollectionInfo = "/api/collection/info", 5 | UpdateCollection = "/api/collection/update", 6 | DropCollection = "/api/collection/drop", 7 | } 8 | -------------------------------------------------------------------------------- /src/services/vikingdb/collection/types.ts: -------------------------------------------------------------------------------- 1 | import { VikingdbResponse } from "../types"; 2 | import type { FieldInfo } from "../types"; 3 | 4 | export type VectorizeMap = { 5 | text_field?: string; 6 | image_field?: string; 7 | dim?: number; 8 | model_name?: string; 9 | model_version?: string; 10 | }; 11 | export interface CollectionVectorize { 12 | dense?: VectorizeMap; 13 | sparse?: VectorizeMap; 14 | } 15 | 16 | export type Vectorize = CollectionVectorize | CollectionVectorize[]; 17 | export interface CreateCollectionRequest { 18 | CollectionName: string; 19 | Description?: string; 20 | CollectionAliases?: string[]; 21 | Fields: FieldInfo[]; 22 | Vectorize?: Vectorize; 23 | } 24 | /* CreateCollection end */ 25 | 26 | /* GetCollectionInfo start */ 27 | interface GetCollectionInfoByCollectionNameRequest { 28 | CollectionName: string; 29 | } 30 | 31 | interface GetCollectionInfoByCollectionAliasesRequest { 32 | CollectionAlias: string; 33 | } 34 | 35 | export type GetCollectionInfoRequest = 36 | | GetCollectionInfoByCollectionAliasesRequest 37 | | GetCollectionInfoByCollectionNameRequest; 38 | 39 | export interface Stat { 40 | DataNumber: number; 41 | } 42 | 43 | export interface CollectionInfo { 44 | CollectionName: string; 45 | Description?: string; 46 | CollectionAliases?: string[]; 47 | Fields: FieldInfo[]; 48 | Stat: Stat; 49 | IndexNames: string[]; 50 | IndexNumber: number; 51 | CreateTime: string; 52 | UpdateTime: string; 53 | UpdatePerson: string; 54 | } 55 | 56 | export class GetCollectionInfoResponse extends VikingdbResponse { 57 | constructor( 58 | public readonly CollectionInfo: CollectionInfo, 59 | OriginalRequest: string, 60 | LogId: string 61 | ) { 62 | super(OriginalRequest, LogId); 63 | } 64 | } 65 | /* GetCollectionInfo end */ 66 | 67 | /* ListCollections start */ 68 | export class ListCollectionsResponse extends VikingdbResponse { 69 | constructor( 70 | public readonly ListCollections: CollectionInfo[], 71 | OriginalRequest: string, 72 | LogId: string 73 | ) { 74 | super(OriginalRequest, LogId); 75 | } 76 | } 77 | /* ListCollections end */ 78 | 79 | /* UpdateCollection start */ 80 | export type UpdateCollectionRequest = CreateCollectionRequest; 81 | /* UpdateCollection end */ 82 | 83 | /* DropCollection start */ 84 | interface DropCollectionByCollectionNameRequest { 85 | CollectionName: string; 86 | } 87 | 88 | interface DropCollectionByCollectionAliasRequest { 89 | CollectionAlias: string; 90 | } 91 | 92 | export type DropCollectionRequest = 93 | | DropCollectionByCollectionNameRequest 94 | | DropCollectionByCollectionAliasRequest; 95 | /* DropCollection end */ 96 | -------------------------------------------------------------------------------- /src/services/vikingdb/custom/index.ts: -------------------------------------------------------------------------------- 1 | import { AbstractService } from "../abstractService"; 2 | import { CustomResponse, type Options } from "./types"; 3 | 4 | export class CustomService extends AbstractService { 5 | async fetch, R = void>({ 6 | pathname, 7 | data, 8 | ...rest 9 | }: Options): Promise> { 10 | const response = await this.request(pathname, data, rest); 11 | return new CustomResponse(response.data, response.original_request, response.request_id); 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /src/services/vikingdb/custom/types.ts: -------------------------------------------------------------------------------- 1 | import { type RequestOptions, VikingdbResponse } from "../types"; 2 | 3 | export class CustomResponse extends VikingdbResponse { 4 | constructor(public readonly Data: T, OriginalRequest: string, LogId: string) { 5 | super(OriginalRequest, LogId); 6 | } 7 | } 8 | 9 | export interface Options extends Omit { 10 | data: T; 11 | pathname: string; 12 | } 13 | -------------------------------------------------------------------------------- /src/services/vikingdb/data/backend.ts: -------------------------------------------------------------------------------- 1 | import type { PrimaryKeyFieldType, PrimaryKeys, ScalarFieldType2JsType } from "../types"; 2 | 3 | interface BackendUpsertDataCommonRequest { 4 | fields: Record[]; 5 | ttl?: number; 6 | async?: boolean; 7 | } 8 | 9 | interface BackendUpsertDataByCollectionNameRequest extends BackendUpsertDataCommonRequest { 10 | collection_name: string; 11 | } 12 | 13 | interface BackendUpsertDataByCollectionAliasRequest extends BackendUpsertDataCommonRequest { 14 | collection_alias: string; 15 | } 16 | 17 | export type BackendUpsertDataRequest = 18 | | BackendUpsertDataByCollectionNameRequest 19 | | BackendUpsertDataByCollectionAliasRequest; 20 | 21 | interface BackendDeleteSpecifyDataByCollectionNameRequest { 22 | collection_name: string; 23 | primary_keys: PrimaryKeys; 24 | } 25 | 26 | interface BackendDeleteAllDataByCollectionNameRequest { 27 | collection_name: string; 28 | del_all: true; 29 | } 30 | 31 | interface BackendDeleteSpecifyDataByCollectionAliasRequest { 32 | collection_alias: string; 33 | primary_keys: PrimaryKeys; 34 | } 35 | 36 | interface BackendDeleteAllDataByCollectionAliasRequest { 37 | collection_alias: string; 38 | del_all: true; 39 | } 40 | 41 | export type BackendDeleteDataRequest = 42 | | BackendDeleteSpecifyDataByCollectionNameRequest 43 | | BackendDeleteSpecifyDataByCollectionAliasRequest 44 | | BackendDeleteAllDataByCollectionNameRequest 45 | | BackendDeleteAllDataByCollectionAliasRequest; 46 | 47 | interface BackendFetchCollectionDataByCollectionNameRequest { 48 | collection_name: string; 49 | primary_keys: PrimaryKeys; 50 | } 51 | 52 | interface BackendFetchCollectionDataByCollectionAliasRequest { 53 | collection_alias: string; 54 | primary_keys: PrimaryKeys; 55 | } 56 | 57 | export type BackendFetchCollectionDataRequest = 58 | | BackendFetchCollectionDataByCollectionAliasRequest 59 | | BackendFetchCollectionDataByCollectionNameRequest; 60 | 61 | interface BackendFetchIndexDataCommonRequest { 62 | index_name: string; 63 | primary_keys: PrimaryKeys; 64 | partition?: ScalarFieldType2JsType[PrimaryKeyFieldType]; 65 | output_fields?: string[]; 66 | } 67 | 68 | interface BackendFetchIndexDataByCollectionNameRequest extends BackendFetchIndexDataCommonRequest { 69 | collection_name: string; 70 | } 71 | 72 | interface BackendFetchIndexDataByCollectionAliasRequest extends BackendFetchIndexDataCommonRequest { 73 | collection_alias: string; 74 | } 75 | 76 | export type BackendFetchIndexDataRequest = 77 | | BackendFetchIndexDataByCollectionNameRequest 78 | | BackendFetchIndexDataByCollectionAliasRequest; 79 | 80 | export interface BackendFetchIndexDataInfo> { 81 | fields: T[]; 82 | } 83 | 84 | /* UpdateData start */ 85 | interface BackendUpdateDataCommonRequest { 86 | fields: Record[]; 87 | ttl?: number; 88 | } 89 | 90 | interface BackendUpdateDataByCollectionNameRequest extends BackendUpdateDataCommonRequest { 91 | collection_name: string; 92 | } 93 | 94 | interface BackendUpdateDataByCollectionAliasRequest extends BackendUpdateDataCommonRequest { 95 | collection_alias: string; 96 | } 97 | 98 | export type BackendUpdateDataRequest = 99 | | BackendUpdateDataByCollectionNameRequest 100 | | BackendUpdateDataByCollectionAliasRequest; 101 | 102 | /* UpdateData end */ 103 | -------------------------------------------------------------------------------- /src/services/vikingdb/data/index.ts: -------------------------------------------------------------------------------- 1 | import { AbstractService } from "../abstractService"; 2 | import { 3 | type DeleteDataRequest, 4 | type FetchCollectionDataRequest, 5 | FetchCollectionDataResponse, 6 | type FetchIndexDataRequest, 7 | FetchIndexDataResponse, 8 | UpdateDataRequest, 9 | type UpsertDataRequest, 10 | } from "./types"; 11 | import { type GetPrimaryKeys, VikingdbResponse } from "../types"; 12 | import type { 13 | BackendDeleteDataRequest, 14 | BackendFetchCollectionDataRequest, 15 | BackendFetchIndexDataInfo, 16 | BackendFetchIndexDataRequest, 17 | BackendUpdateDataRequest, 18 | BackendUpsertDataRequest, 19 | } from "./backend"; 20 | import { Pathname } from "./pathname"; 21 | 22 | export class DataService extends AbstractService { 23 | async UpsertData({ 24 | Fields, 25 | TTL, 26 | Async = false, 27 | ...rest 28 | }: UpsertDataRequest): Promise { 29 | const request: BackendUpsertDataRequest = this.isCollectionNameRequest(rest) 30 | ? { 31 | collection_name: rest.CollectionName, 32 | fields: Fields, 33 | ttl: TTL, 34 | async: Async, 35 | } 36 | : { 37 | collection_alias: rest.CollectionAlias, 38 | fields: Fields, 39 | ttl: TTL, 40 | async: Async, 41 | }; 42 | const response = await this.request(Pathname.UpsertData, request); 43 | return new VikingdbResponse(response.original_request, response.request_id); 44 | } 45 | 46 | async DeleteData(request: DeleteDataRequest): Promise { 47 | let data: BackendDeleteDataRequest; 48 | const isDeleteAll = ( 49 | request: NonNullable 50 | ): request is T => "DeleteAll" in request; 51 | if (this.isCollectionNameRequest(request)) { 52 | if (isDeleteAll(request)) { 53 | data = { 54 | collection_name: request.CollectionName, 55 | del_all: request.DeleteAll, 56 | }; 57 | } else { 58 | data = { 59 | collection_name: request.CollectionName, 60 | primary_keys: request.PrimaryKeys, 61 | }; 62 | } 63 | } else { 64 | if (isDeleteAll(request)) { 65 | data = { 66 | collection_alias: request.CollectionAlias, 67 | del_all: request.DeleteAll, 68 | }; 69 | } else { 70 | data = { 71 | collection_alias: request.CollectionAlias, 72 | primary_keys: request.PrimaryKeys, 73 | }; 74 | } 75 | } 76 | const response = await this.request(Pathname.DeleteData, data); 77 | return new VikingdbResponse(response.original_request, response.request_id); 78 | } 79 | 80 | async UpdateData({ Fields, TTL, ...rest }: UpdateDataRequest): Promise { 81 | const request: BackendUpdateDataRequest = this.isCollectionNameRequest(rest) 82 | ? { 83 | collection_name: rest.CollectionName, 84 | fields: Fields, 85 | ttl: TTL, 86 | } 87 | : { 88 | collection_alias: rest.CollectionAlias, 89 | fields: Fields, 90 | ttl: TTL, 91 | }; 92 | const response = await this.request(Pathname.UpdateData, request); 93 | return new VikingdbResponse(response.original_request, response.request_id); 94 | } 95 | 96 | async FetchCollectionData< 97 | Data extends Record, 98 | PrimaryKey extends GetPrimaryKeys 99 | >({ 100 | PrimaryKeys, 101 | ...rest 102 | }: FetchCollectionDataRequest): Promise> { 103 | const request: BackendFetchCollectionDataRequest = this.isCollectionNameRequest(rest) 104 | ? { 105 | primary_keys: PrimaryKeys, 106 | collection_name: rest.CollectionName, 107 | } 108 | : { primary_keys: PrimaryKeys, collection_alias: rest.CollectionAlias }; 109 | const response = await this.request( 110 | Pathname.FetchCollectionData, 111 | request 112 | ); 113 | return new FetchCollectionDataResponse( 114 | response.data, 115 | response.original_request, 116 | response.request_id 117 | ); 118 | } 119 | 120 | async FetchIndexData, PrimaryKey extends GetPrimaryKeys>({ 121 | IndexName, 122 | PrimaryKeys, 123 | OutputFields, 124 | Partition, 125 | ...rest 126 | }: FetchIndexDataRequest): Promise> { 127 | let request: BackendFetchIndexDataRequest; 128 | if (this.isCollectionNameRequest(rest)) { 129 | request = { 130 | collection_name: rest.CollectionName, 131 | index_name: IndexName, 132 | partition: Partition, 133 | output_fields: OutputFields, 134 | primary_keys: PrimaryKeys, 135 | }; 136 | } else { 137 | request = { 138 | collection_alias: rest.CollectionAlias, 139 | index_name: IndexName, 140 | partition: Partition, 141 | output_fields: OutputFields, 142 | primary_keys: PrimaryKeys, 143 | }; 144 | } 145 | const response = await this.request< 146 | BackendFetchIndexDataRequest, 147 | BackendFetchIndexDataInfo[] 148 | >(Pathname.FetchIndexData, request); 149 | const data = response.data.map((item) => item.fields).flat(); 150 | return new FetchIndexDataResponse( 151 | data, 152 | response.original_request, 153 | response.request_id 154 | ); 155 | } 156 | } 157 | 158 | export * as data from "./types"; 159 | -------------------------------------------------------------------------------- /src/services/vikingdb/data/pathname.ts: -------------------------------------------------------------------------------- 1 | export enum Pathname { 2 | UpsertData = "/api/collection/upsert_data", 3 | FetchCollectionData = "/api/collection/fetch_data", 4 | DeleteData = "/api/collection/del_data", 5 | FetchIndexData = "/api/index/fetch_data", 6 | UpdateData = "/api/collection/update_data", 7 | } 8 | -------------------------------------------------------------------------------- /src/services/vikingdb/data/types.ts: -------------------------------------------------------------------------------- 1 | /* UpsertData start */ 2 | import { 3 | type GetPrimaryKeys, 4 | type PrimaryKeyFieldType, 5 | type PrimaryKeys, 6 | type ScalarFieldType2JsType, 7 | VikingdbResponse, 8 | } from "../types"; 9 | 10 | interface UpsertDataCommonRequest { 11 | Fields: Record[]; 12 | TTL?: number; 13 | Async?: boolean; 14 | } 15 | 16 | interface UpsertDataByCollectionNameRequest extends UpsertDataCommonRequest { 17 | CollectionName: string; 18 | } 19 | 20 | interface UpsertDataByCollectionAliasRequest extends UpsertDataCommonRequest { 21 | CollectionAlias: string; 22 | } 23 | 24 | export type UpsertDataRequest = 25 | | UpsertDataByCollectionNameRequest 26 | | UpsertDataByCollectionAliasRequest; 27 | /* UpsertData end */ 28 | 29 | /* DeleteData start */ 30 | interface DeleteSpecifyDataByCollectionNameRequest { 31 | CollectionName: string; 32 | PrimaryKeys: PrimaryKeys; 33 | } 34 | 35 | interface DeleteAllDataByCollectionNameRequest { 36 | CollectionName: string; 37 | DeleteAll: true; 38 | } 39 | 40 | interface DeleteSpecifyDataByCollectionAliasRequest { 41 | CollectionAlias: string; 42 | PrimaryKeys: PrimaryKeys; 43 | } 44 | 45 | interface DeleteAllDataByCollectionAliasRequest { 46 | CollectionAlias: string; 47 | DeleteAll: true; 48 | } 49 | 50 | export type DeleteDataRequest = 51 | | DeleteSpecifyDataByCollectionNameRequest 52 | | DeleteSpecifyDataByCollectionAliasRequest 53 | | DeleteAllDataByCollectionNameRequest 54 | | DeleteAllDataByCollectionAliasRequest; 55 | /* DeleteData end */ 56 | 57 | /* FetchCollectionData start */ 58 | interface FetchCollectionDataByCollectionNameRequest { 59 | CollectionName: string; 60 | PrimaryKeys: PrimaryKeys; 61 | } 62 | 63 | interface FetchCollectionDataByCollectionAliasRequest { 64 | CollectionAlias: string; 65 | PrimaryKeys: PrimaryKeys; 66 | } 67 | 68 | export type FetchCollectionDataRequest = 69 | | FetchCollectionDataByCollectionAliasRequest 70 | | FetchCollectionDataByCollectionNameRequest; 71 | 72 | export type FetchDataInfo< 73 | Data extends Record, 74 | PrimaryKey extends GetPrimaryKeys 75 | > = Data | { [Key in PrimaryKey]: ScalarFieldType2JsType[Data[PrimaryKey]] }; 76 | 77 | export class FetchCollectionDataResponse< 78 | Data extends Record, 79 | PrimaryKey extends GetPrimaryKeys 80 | > extends VikingdbResponse { 81 | constructor( 82 | public readonly Data: FetchDataInfo[], 83 | OriginalRequest: string, 84 | LogId: string 85 | ) { 86 | super(OriginalRequest, LogId); 87 | } 88 | } 89 | /* FetchCollectionData start */ 90 | 91 | /* FetchIndexData start */ 92 | interface FetchIndexDataCommonRequest { 93 | IndexName: string; 94 | PrimaryKeys: PrimaryKeys; 95 | /** 96 | * 子索引对应的字段 97 | * 98 | * 类型和 `partition_by` 对齐 99 | */ 100 | Partition?: ScalarFieldType2JsType[PrimaryKeyFieldType]; 101 | /** 102 | * 不传时返回所有标量字段 103 | * 104 | * 传空数组不返回 `fields` 字段 105 | */ 106 | OutputFields?: string[]; 107 | } 108 | 109 | interface FetchIndexDataByCollectionNameRequest extends FetchIndexDataCommonRequest { 110 | CollectionName: string; 111 | } 112 | 113 | interface FetchIndexDataByCollectionAliasRequest extends FetchIndexDataCommonRequest { 114 | CollectionAlias: string; 115 | } 116 | 117 | export type FetchIndexDataRequest = 118 | | FetchIndexDataByCollectionNameRequest 119 | | FetchIndexDataByCollectionAliasRequest; 120 | 121 | export class FetchIndexDataResponse< 122 | Data extends Record, 123 | PrimaryKey extends GetPrimaryKeys 124 | > extends VikingdbResponse { 125 | constructor( 126 | public readonly Data: FetchDataInfo[], 127 | OriginalRequest: string, 128 | LogId: string 129 | ) { 130 | super(OriginalRequest, LogId); 131 | } 132 | } 133 | /* FetchIndexData end */ 134 | 135 | /* UpdateData start */ 136 | interface UpdateDataByCollectionNameRequest extends UpsertDataCommonRequest { 137 | CollectionName: string; 138 | } 139 | 140 | interface UpdateDataByCollectionAliasRequest extends UpsertDataCommonRequest { 141 | CollectionAlias: string; 142 | } 143 | 144 | export type UpdateDataRequest = 145 | | UpdateDataByCollectionNameRequest 146 | | UpdateDataByCollectionAliasRequest; 147 | 148 | /* UpdateData end */ 149 | -------------------------------------------------------------------------------- /src/services/vikingdb/embedding/backend.ts: -------------------------------------------------------------------------------- 1 | /** @link https://www.volcengine.com/docs/84313/1254554 */ 2 | export type ModelName = 3 | | "bge-large-zh" 4 | | "bge-m3" 5 | | "bge-large-zh-and-m3" 6 | | "bge-visualized-m3" 7 | | "doubao-embedding" 8 | | "doubao-embedding-and-m3"; 9 | 10 | export enum DataType { 11 | Text = "text", 12 | Image = "image", 13 | TextImage = "text-image", 14 | } 15 | 16 | interface BackendTextDataParams { 17 | data_type: DataType.Text; 18 | text: string; 19 | } 20 | 21 | interface BackendImageDataParams { 22 | data_type: DataType.Image; 23 | image: string; 24 | } 25 | 26 | interface BackendTextImageDataParams { 27 | data_type: DataType.TextImage; 28 | text: string; 29 | image: string; 30 | } 31 | 32 | type BackendDataParams = 33 | | BackendTextDataParams 34 | | BackendImageDataParams 35 | | BackendTextImageDataParams; 36 | 37 | export interface BackendEmbeddingRequest { 38 | model: { 39 | model_name: ModelName; 40 | params?: { 41 | return_token_usage?: boolean; 42 | return_dense?: boolean; 43 | return_sparse?: boolean; 44 | }; 45 | }; 46 | data: BackendDataParams[]; 47 | } 48 | 49 | export interface BackendEmbeddingResult { 50 | sentence_dense_embedding?: number[][]; 51 | sentence_sparse_embedding?: Record[]; 52 | token_usage?: { 53 | prompt_tokens: number; 54 | completion_tokens?: number; 55 | total_tokens?: number; 56 | }; 57 | } 58 | -------------------------------------------------------------------------------- /src/services/vikingdb/embedding/index.ts: -------------------------------------------------------------------------------- 1 | import { AbstractService } from "../abstractService"; 2 | import { 3 | type AllModelParams, 4 | type DataParams, 5 | EmbeddingResponse, 6 | type EmbeddingResult, 7 | type ModelParams, 8 | } from "./types"; 9 | import { Pathname } from "./pathname"; 10 | import { type BackendEmbeddingRequest, type BackendEmbeddingResult, DataType } from "./backend"; 11 | 12 | export class EmbeddingService extends AbstractService { 13 | async Embedding( 14 | modelParams: ModelParams, 15 | dataParams: DataParams[] 16 | ): Promise>; 17 | async Embedding( 18 | modelParams: ModelParams<"ReturnDense">, 19 | dataParams: DataParams[] 20 | ): Promise>; 21 | async Embedding( 22 | modelParams: ModelParams<"ReturnSparse">, 23 | dataParams: DataParams[] 24 | ): Promise>; 25 | async Embedding( 26 | modelParams: ModelParams<"ReturnTokenUsage">, 27 | dataParams: DataParams[] 28 | ): Promise>; 29 | async Embedding( 30 | modelParams: ModelParams<"ReturnDense" | "ReturnSparse">, 31 | dataParams: DataParams[] 32 | ): Promise>; 33 | async Embedding( 34 | modelParams: ModelParams<"ReturnDense" | "ReturnTokenUsage">, 35 | dataParams: DataParams[] 36 | ): Promise>; 37 | async Embedding( 38 | modelParams: ModelParams<"ReturnSparse" | "ReturnTokenUsage">, 39 | dataParams: DataParams[] 40 | ): Promise>; 41 | async Embedding( 42 | modelParams: ModelParams<"ReturnDense" | "ReturnSparse" | "ReturnTokenUsage">, 43 | dataParams: DataParams[] 44 | ): Promise< 45 | EmbeddingResponse<"SentenceDenseEmbedding" | "SentenceSparseEmbedding" | "TokenUsage"> 46 | >; 47 | async Embedding( 48 | { ModelName, ReturnTokenUsage, ReturnSparse, ReturnDense }: AllModelParams, 49 | dataParams: DataParams[] 50 | ): Promise> { 51 | const request: BackendEmbeddingRequest = { 52 | model: { 53 | model_name: ModelName, 54 | params: { 55 | return_dense: ReturnDense, 56 | return_sparse: ReturnSparse, 57 | return_token_usage: ReturnTokenUsage, 58 | }, 59 | }, 60 | data: dataParams.map((item) => { 61 | if (item.DataType === DataType.Text) { 62 | return { 63 | data_type: item.DataType, 64 | text: item.Text, 65 | }; 66 | } 67 | if (item.DataType === DataType.Image) { 68 | return { 69 | data_type: item.DataType, 70 | image: item.Image, 71 | }; 72 | } 73 | return { 74 | data_type: item.DataType, 75 | text: item.Text, 76 | image: item.Image, 77 | }; 78 | }), 79 | }; 80 | const response = await this.request( 81 | Pathname.Embedding, 82 | request 83 | ); 84 | const { sentence_dense_embedding, sentence_sparse_embedding, token_usage } = response.data; 85 | const result: EmbeddingResult = {}; 86 | if (ReturnDense && sentence_dense_embedding) { 87 | result.SentenceDenseEmbedding = sentence_dense_embedding; 88 | } 89 | if (ReturnSparse && sentence_sparse_embedding) { 90 | result.SentenceSparseEmbedding = sentence_sparse_embedding; 91 | } 92 | if (ReturnTokenUsage && token_usage) { 93 | result.TokenUsage = { 94 | TotalTokens: token_usage.total_tokens, 95 | CompletionTokens: token_usage.completion_tokens, 96 | PromptTokens: token_usage.prompt_tokens, 97 | }; 98 | } 99 | return new EmbeddingResponse(result, response.original_request, response.request_id); 100 | } 101 | } 102 | 103 | export * as embedding from "./types"; 104 | -------------------------------------------------------------------------------- /src/services/vikingdb/embedding/pathname.ts: -------------------------------------------------------------------------------- 1 | export enum Pathname { 2 | Embedding = "/api/data/embedding/version/2", 3 | } 4 | -------------------------------------------------------------------------------- /src/services/vikingdb/embedding/types.ts: -------------------------------------------------------------------------------- 1 | import type { DataType, ModelName } from "./backend"; 2 | import { VikingdbResponse } from "../types"; 3 | 4 | export { DataType } from "./backend"; 5 | 6 | /* Embedding start */ 7 | export interface AllModelParams { 8 | ModelName: ModelName; 9 | /** 10 | * 返回请求消耗的 token 数 11 | * @default false 12 | */ 13 | ReturnTokenUsage?: boolean; 14 | /** 15 | * 返回稠密向量 16 | * @default true 17 | */ 18 | ReturnDense?: boolean; 19 | /** 20 | * 返回稀疏向量,需要模型支持,否则报错 21 | */ 22 | ReturnSparse?: boolean; 23 | } 24 | 25 | export type ModelParams> = Pick< 26 | Required, 27 | Key 28 | > & 29 | Pick; 30 | 31 | interface TextDataParams { 32 | DataType: DataType.Text; 33 | Text: string; 34 | } 35 | 36 | interface ImageDataParams { 37 | DataType: DataType.Image; 38 | /** 传入 base64 编码 */ 39 | Image: string; 40 | } 41 | 42 | interface TextImageDataParams { 43 | DataType: DataType.TextImage; 44 | Text: string; 45 | /** 传入 base64 编码 */ 46 | Image: string; 47 | } 48 | 49 | export type DataParams = TextDataParams | ImageDataParams | TextImageDataParams; 50 | 51 | export interface EmbeddingResult { 52 | SentenceDenseEmbedding?: number[][]; 53 | SentenceSparseEmbedding?: Record[]; 54 | TokenUsage?: { 55 | PromptTokens: number; 56 | CompletionTokens?: number; 57 | TotalTokens?: number; 58 | }; 59 | } 60 | 61 | export class EmbeddingResponse extends VikingdbResponse { 62 | constructor( 63 | public Result: Pick, Key>, 64 | OriginalRequest: string, 65 | LogId: string 66 | ) { 67 | super(OriginalRequest, LogId); 68 | } 69 | } 70 | /* Embedding end */ 71 | -------------------------------------------------------------------------------- /src/services/vikingdb/index.ts: -------------------------------------------------------------------------------- 1 | import type { VikingdbRegion } from "./types"; 2 | import { CollectionService } from "./collection"; 3 | import { IndexService } from "./index/index"; 4 | import { DataService } from "./data"; 5 | import { EmbeddingService } from "./embedding"; 6 | import { SearchService } from "./search"; 7 | import { CustomService } from "./custom"; 8 | import { TaskService } from "./task"; 9 | 10 | interface ModuleService { 11 | collection: CollectionService; 12 | index: IndexService; 13 | data: DataService; 14 | embedding: EmbeddingService; 15 | search: SearchService; 16 | custom: CustomService; 17 | task: TaskService; 18 | } 19 | 20 | interface Options { 21 | ak: string; 22 | sk: string; 23 | /** 24 | * 请求后端 region 25 | * @default cn-beijing 26 | */ 27 | region?: VikingdbRegion; 28 | /** 29 | * 如果是进行角色扮演请求,需要先通过 AssumeRole 获取临时的 aksk 和 sessionToken 30 | * @example 31 | * import { sts, vikingdb } from '@volcengine/volc-sdk-nodejs' 32 | * 33 | * const stsService = new sts.StsService({ 34 | * RoleTrn: 'trn:iam::{accountId}:role/{roleName}', 35 | * RoleSessionName: 'TempSessionName', 36 | * }) 37 | * const { Result } = await stsService.AssumeRole() 38 | * if (!Result.Credentials) { 39 | * return 40 | * } 41 | * const vikingdbService = new vikingdb.VikingdbService({ 42 | * ak: Result.Credentials.AccessKeyId, 43 | * sk: Result.Credentials.SecretAccessKey, 44 | * sessionToken: Result.Credentials.SessionToken 45 | * }) 46 | * @link https://www.volcengine.com/docs/6257/86374 47 | */ 48 | sessionToken?: string; 49 | } 50 | 51 | /** 52 | * @example 53 | * import { vikingdb } from '@volcengine/volc-sdk-nodejs' 54 | * const service = new vikingdb.VikingdbService({ ak, sk, region }) 55 | * await service.collection.ListCollections() 56 | */ 57 | export class VikingdbService implements ModuleService { 58 | readonly collection: CollectionService; 59 | readonly index: IndexService; 60 | readonly data: DataService; 61 | readonly embedding: EmbeddingService; 62 | readonly search: SearchService; 63 | readonly custom: CustomService; 64 | readonly task: TaskService; 65 | 66 | constructor({ ak, sk, region = "cn-beijing", sessionToken }: Options) { 67 | this.collection = new CollectionService(ak, sk, region, sessionToken); 68 | this.index = new IndexService(ak, sk, region, sessionToken); 69 | this.data = new DataService(ak, sk, region, sessionToken); 70 | this.embedding = new EmbeddingService(ak, sk, region, sessionToken); 71 | this.search = new SearchService(ak, sk, region, sessionToken); 72 | this.custom = new CustomService(ak, sk, region, sessionToken); 73 | this.task = new TaskService(ak, sk, region, sessionToken); 74 | } 75 | } 76 | 77 | export { collection } from "./collection"; 78 | export { index } from "./index/index"; 79 | export { data } from "./data"; 80 | export { embedding } from "./embedding"; 81 | export { search } from "./search"; 82 | export { task } from "./task"; 83 | export { 84 | VikingdbResponse, 85 | VikingdbErrorCode, 86 | VikingdbError, 87 | VikingdbRequestError, 88 | FieldType, 89 | } from "./types"; 90 | -------------------------------------------------------------------------------- /src/services/vikingdb/index/backend.ts: -------------------------------------------------------------------------------- 1 | import type { BackendField } from "../types"; 2 | 3 | export interface BackendDropIndexRequest { 4 | collection_name: string; 5 | index_name: string; 6 | } 7 | 8 | export type BackendGetIndexInfoRequest = BackendDropIndexRequest; 9 | 10 | export enum ShardPolicy { 11 | Custom = "custom", 12 | Auto = "auto", 13 | } 14 | 15 | export enum IndexType { 16 | Hnsw = "hnsw", 17 | HnswHybrid = "hnsw_hybrid", 18 | Flat = "flat", 19 | Ivf = "ivf", 20 | Diskann = "diskann", 21 | } 22 | 23 | export enum Distance { 24 | Ip = "ip", 25 | l2 = "l2", 26 | Cosine = "cosine", 27 | } 28 | 29 | export enum Quant { 30 | Int8 = "int8", 31 | Float = "float", 32 | Fix16 = "fix16", 33 | PQ = "pq", 34 | } 35 | 36 | export type IndexStatus = "INIT" | "CHANGING" | "READY"; 37 | 38 | interface HnswVector1 { 39 | index_type: IndexType.Hnsw; 40 | distance: Exclude; 41 | quant: Exclude; 42 | hnsw_m?: number; 43 | hnsw_cef?: number; 44 | hnsw_sef?: number; 45 | } 46 | 47 | interface HnswVector2 { 48 | index_type: IndexType.Hnsw; 49 | distance: Distance.l2; 50 | quant: Exclude; 51 | hnsw_m?: number; 52 | hnsw_cef?: number; 53 | hnsw_sef?: number; 54 | } 55 | 56 | export type BackendHnswVector = HnswVector1 | HnswVector2; 57 | 58 | interface HnswHybridVector1 { 59 | index_type: IndexType.HnswHybrid; 60 | distance: Exclude; 61 | quant: Exclude; 62 | } 63 | 64 | interface HnswHybridVector2 { 65 | index_type: IndexType.HnswHybrid; 66 | distance: Distance.l2; 67 | quant: Exclude; 68 | } 69 | 70 | export type BackendHnswHybridVector = HnswHybridVector1 | HnswHybridVector2; 71 | 72 | interface FlatVector1 { 73 | index_type: IndexType.Flat; 74 | distance: Exclude; 75 | quant: Exclude; 76 | } 77 | 78 | interface FlatVector2 { 79 | index_type: IndexType.Flat; 80 | distance: Distance.l2; 81 | quant: Exclude; 82 | } 83 | 84 | export type BackendFlatVector = FlatVector1 | FlatVector2; 85 | 86 | export interface BackendDiskannVector { 87 | index_type: IndexType.Diskann; 88 | distance: Distance; 89 | quant: Exclude; 90 | diskann_m?: number; 91 | diskann_cef?: number; 92 | cache_ratio?: number; 93 | pq_code_ratio?: number; 94 | } 95 | 96 | export interface BackendIvfVector { 97 | index_type: IndexType.Ivf; 98 | distance: Exclude; 99 | quant: Quant.PQ; 100 | } 101 | 102 | export type BackendVectorIndex = 103 | | BackendHnswVector 104 | | BackendHnswHybridVector 105 | | BackendFlatVector 106 | | BackendDiskannVector 107 | | BackendIvfVector; 108 | 109 | export interface BackendIndexInfo { 110 | collection_name: string; 111 | index_name: string; 112 | cpu_quota: number; 113 | description?: string; 114 | shard_policy: ShardPolicy; 115 | shard_count: number; 116 | partition_by?: string; 117 | partitions?: string[]; 118 | vector_index?: BackendVectorIndex; 119 | scalar_index?: BackendField[]; 120 | status: IndexStatus; 121 | index_cost: { 122 | cpu_core: number; 123 | mem_gb: string; 124 | }; 125 | create_time: string; 126 | update_time: string; 127 | update_person: string; 128 | } 129 | 130 | export interface BackendListIndexesRequest { 131 | collection_name: string; 132 | } 133 | 134 | export interface BackendCreateIndexRequest 135 | extends Pick< 136 | BackendIndexInfo, 137 | | "collection_name" 138 | | "index_name" 139 | | "description" 140 | | "shard_policy" 141 | | "partition_by" 142 | | "vector_index" 143 | > { 144 | cpu_quota?: number; 145 | shard_count?: number; 146 | scalar_index?: string[]; 147 | } 148 | 149 | export interface BackendUpdateIndexRequest 150 | extends Omit { 151 | shard_policy?: ShardPolicy; 152 | } 153 | -------------------------------------------------------------------------------- /src/services/vikingdb/index/pathname.ts: -------------------------------------------------------------------------------- 1 | export enum Pathname { 2 | DropIndex = "/api/index/drop", 3 | GetIndexInfo = "/api/index/info", 4 | ListIndexes = "/api/index/list", 5 | CreateIndex = "/api/index/create", 6 | UpdateIndex = "/api/index/update", 7 | } 8 | -------------------------------------------------------------------------------- /src/services/vikingdb/index/types.ts: -------------------------------------------------------------------------------- 1 | /* DropIndex start */ 2 | import { type ScalarFieldInfo, type ScalarFieldType, VikingdbResponse } from "../types"; 3 | import { Distance, type IndexStatus, IndexType, Quant, ShardPolicy } from "./backend"; 4 | 5 | export { Distance, IndexType, Quant, ShardPolicy } from "./backend"; 6 | 7 | export interface DropIndexRequest { 8 | CollectionName: string; 9 | IndexName: string; 10 | } 11 | /* DropIndex end */ 12 | 13 | /* GetIndexInfo start */ 14 | export type GetIndexInfoRequest = DropIndexRequest; 15 | 16 | interface HnswVector1 { 17 | IndexType: IndexType.Hnsw; 18 | Distance: Exclude; 19 | Quant: Exclude; 20 | HnswM?: number; 21 | HnswCef?: number; 22 | HnswSef?: number; 23 | } 24 | 25 | interface HnswVector2 { 26 | IndexType: IndexType.Hnsw; 27 | Distance: Distance.l2; 28 | Quant: Exclude; 29 | HnswM?: number; 30 | HnswCef?: number; 31 | HnswSef?: number; 32 | } 33 | 34 | export type HnswVector = HnswVector1 | HnswVector2; 35 | 36 | interface HnswHybridVector1 { 37 | IndexType: IndexType.HnswHybrid; 38 | Distance: Exclude; 39 | Quant: Exclude; 40 | } 41 | 42 | interface HnswHybridVector2 { 43 | IndexType: IndexType.HnswHybrid; 44 | Distance: Distance.l2; 45 | Quant: Exclude; 46 | } 47 | 48 | export type HnswHybridVector = HnswHybridVector1 | HnswHybridVector2; 49 | 50 | interface FlatVector1 { 51 | IndexType: IndexType.Flat; 52 | Distance: Exclude; 53 | Quant: Exclude; 54 | } 55 | 56 | interface FlatVector2 { 57 | IndexType: IndexType.Flat; 58 | Distance: Distance.l2; 59 | Quant: Exclude; 60 | } 61 | 62 | export type FlatVector = FlatVector1 | FlatVector2; 63 | 64 | export interface DiskannVector { 65 | IndexType: IndexType.Diskann; 66 | Distance: Distance; 67 | Quant: Exclude; 68 | DiskannM?: number; 69 | DiskannCef?: number; 70 | CacheRatio?: number; 71 | PqCodeRatio?: number; 72 | } 73 | 74 | export interface IvfVector { 75 | IndexType: IndexType.Ivf; 76 | Distance: Exclude; 77 | Quant: Quant.PQ; 78 | } 79 | 80 | export type VectorIndex = HnswVector | HnswHybridVector | FlatVector | DiskannVector | IvfVector; 81 | 82 | export interface IndexInfo { 83 | CollectionName: string; 84 | IndexName: string; 85 | CpuQuota: number; 86 | Description?: string; 87 | ShardPolicy: ShardPolicy; 88 | ShardCount: number; 89 | PartitionBy?: string; 90 | Partitions?: string[]; 91 | VectorIndex?: VectorIndex; 92 | ScalarIndex?: ScalarFieldInfo[]; 93 | Status: IndexStatus; 94 | IndexCost: { 95 | CpuCore: number; 96 | MemoryGb: string; 97 | }; 98 | CreateTime: string; 99 | UpdateTime: string; 100 | UpdatePerson: string; 101 | } 102 | 103 | export class GetIndexInfoResponse extends VikingdbResponse { 104 | constructor(public readonly IndexInfo: IndexInfo, OriginalRequest: string, LogId: string) { 105 | super(OriginalRequest, LogId); 106 | } 107 | } 108 | /* GetIndexInfo end */ 109 | 110 | /* ListIndexes start */ 111 | export interface ListIndexesRequest { 112 | CollectionName: string; 113 | } 114 | export class ListIndexesResponse extends VikingdbResponse { 115 | constructor(public readonly ListIndexes: IndexInfo[], OriginalRequest: string, LogId: string) { 116 | super(OriginalRequest, LogId); 117 | } 118 | } 119 | /* ListIndexes end */ 120 | 121 | /* CreateIndex start */ 122 | export type ShardConfig = 123 | | { 124 | ShardPolicy: ShardPolicy.Custom; 125 | ShardCount: number; 126 | } 127 | | { 128 | ShardPolicy: ShardPolicy.Auto; 129 | }; 130 | 131 | export interface CreateIndexRequest { 132 | CollectionName: string; 133 | IndexName: string; 134 | Description?: string; 135 | CpuQuota?: number; 136 | ShardConfig: ShardConfig; 137 | VectorIndex?: VectorIndex; 138 | PartitionBy?: string; 139 | /** 标量过滤字段 */ 140 | ScalarIndexes?: string[]; 141 | } 142 | /* CreateIndex end */ 143 | 144 | /* UpdateIndex start */ 145 | export interface UpdateIndexRequest 146 | extends Omit { 147 | ShardConfig?: ShardConfig; 148 | } 149 | /* UpdateIndex end */ 150 | -------------------------------------------------------------------------------- /src/services/vikingdb/search/backend.ts: -------------------------------------------------------------------------------- 1 | export enum SearchOperation { 2 | Must = "must", 3 | MustNot = "must_not", 4 | Range = "range", 5 | RangeOut = "range_out", 6 | /** 地理距离筛选 */ 7 | GeographicalRange = "georange", 8 | And = "and", 9 | Or = "or", 10 | } 11 | 12 | export interface BackendMustTypeCondition { 13 | op: Extract; 14 | field: string; 15 | conds: Array; 16 | } 17 | 18 | export interface BackendRangeTypeCondition { 19 | op: Extract; 20 | field: string | [string, string]; 21 | gt?: number; 22 | lt?: number; 23 | gte?: number; 24 | lte?: number; 25 | center?: [number, number]; 26 | radius?: number; 27 | } 28 | 29 | export interface BackendGeographicalRangeTypeCondition { 30 | op: SearchOperation.GeographicalRange; 31 | field: [string, string]; 32 | center: [number, number]; 33 | radius: number; 34 | } 35 | 36 | export interface BackendLogicTypeCondition { 37 | op: Extract; 38 | // eslint-disable-next-line no-use-before-define 39 | conds: BackendFilter[]; 40 | } 41 | 42 | export type BackendFilter = 43 | | BackendMustTypeCondition 44 | | BackendRangeTypeCondition 45 | | BackendGeographicalRangeTypeCondition 46 | | BackendLogicTypeCondition; 47 | 48 | export interface BackendSearchCommonRequest { 49 | index_name: string; 50 | search: { 51 | limit?: number; 52 | partition?: unknown; 53 | order_by_vector?: { 54 | vectors?: number[][]; 55 | primary_keys?: Array; 56 | sparse_vectors?: Record[]; 57 | }; 58 | dense_weight?: number; 59 | order_by_raw?: { 60 | text: string; 61 | }; 62 | filter?: BackendFilter; 63 | output_fields?: string[]; 64 | order_by_scalar?: { 65 | order: "asc" | "desc"; 66 | field_name: string; 67 | }; 68 | primary_key_in?: Array; 69 | primary_key_not_in?: Array; 70 | }; 71 | } 72 | 73 | interface BackendSearchByCollectionNameRequest extends BackendSearchCommonRequest { 74 | collection_name: string; 75 | } 76 | 77 | interface BackendSearchByCollectionAliasRequest extends BackendSearchCommonRequest { 78 | collection_alias: string; 79 | } 80 | 81 | export type BackendSearchRequest = 82 | | BackendSearchByCollectionNameRequest 83 | | BackendSearchByCollectionAliasRequest; 84 | 85 | export type BackendSearchData> = { 86 | score: number; 87 | fields?: Data; 88 | [key: string]: unknown; 89 | }[][]; 90 | 91 | export interface BackendSearchAggCommonRequest { 92 | index_name: string; 93 | search?: { 94 | partition?: unknown; 95 | filter?: BackendFilter; 96 | }; 97 | agg: { 98 | op: string; 99 | field?: string; 100 | cond?: Record; 101 | }; 102 | } 103 | 104 | interface BackendSearchAggByCollectionNameRequest extends BackendSearchAggCommonRequest { 105 | collection_name: string; 106 | } 107 | 108 | interface BackendSearchAggByCollectionAliasRequest extends BackendSearchAggCommonRequest { 109 | collection_alias: string; 110 | } 111 | 112 | export type BackendSearchAggRequest = 113 | | BackendSearchAggByCollectionNameRequest 114 | | BackendSearchAggByCollectionAliasRequest; 115 | 116 | export type BackendSearchAggResponse = { 117 | agg_op: string; 118 | group_by_field?: string; 119 | agg_result?: Record; 120 | }; 121 | -------------------------------------------------------------------------------- /src/services/vikingdb/search/pathname.ts: -------------------------------------------------------------------------------- 1 | export enum Pathname { 2 | Search = "/api/index/search", 3 | SearchAgg = "/api/index/search/agg", 4 | } 5 | -------------------------------------------------------------------------------- /src/services/vikingdb/search/types.ts: -------------------------------------------------------------------------------- 1 | import type { BackendFilter, BackendSearchAggResponse, SearchOperation } from "./backend"; 2 | import { VikingdbResponse } from "../types"; 3 | 4 | export { SearchOperation } from "./backend"; 5 | 6 | /** 支持字段类型为 int64、bool、string、list、list */ 7 | export interface MustTypeCondition { 8 | Operation: Extract; 9 | FieldName: string; 10 | Conditions: Array; 11 | } 12 | 13 | /** 支持字段类型为 int64、float32 */ 14 | export interface NumberRangeTypeCondition { 15 | Operation: Extract; 16 | FieldName: string; 17 | GreatThen?: number; 18 | LessThen?: number; 19 | GreatThenEqual?: number; 20 | LessThenEqual?: number; 21 | } 22 | 23 | export interface AreaRangeTypeCondition { 24 | Operation: Extract; 25 | /** 横坐标、纵坐标 */ 26 | FieldNames: [string, string]; 27 | /** 横坐标、纵坐标 */ 28 | Center: [number, number]; 29 | /** 半径 */ 30 | Radius: number; 31 | } 32 | 33 | export interface GeographicalRangeTypeCondition { 34 | Operation: SearchOperation.GeographicalRange; 35 | /** 经度、纬度 */ 36 | FieldNames: [string, string]; 37 | /** 经度值、纬度值 */ 38 | Center: [number, number]; 39 | /** 半径 */ 40 | Radius: number; 41 | } 42 | 43 | export interface LogicTypeCondition { 44 | Operation: Extract; 45 | // eslint-disable-next-line no-use-before-define 46 | Conditions: Filter[]; 47 | } 48 | 49 | export type Filter = 50 | | MustTypeCondition 51 | | NumberRangeTypeCondition 52 | | AreaRangeTypeCondition 53 | | GeographicalRangeTypeCondition 54 | | LogicTypeCondition; 55 | 56 | interface SearchCommonRequest { 57 | IndexName: string; 58 | Limit: number; 59 | DenseWeight?: number; 60 | /** 61 | * 不传时返回所有标量字段,不返回向量字段 62 | * 63 | * 为空时不返回字段 64 | * 65 | * 格式错误 sdk 报错 66 | */ 67 | OutputFields?: string[]; 68 | /** 69 | * 子索引名称,类型与索引配置中的 `PartitionBy` 的类型一致 70 | */ 71 | Partition?: string | number; 72 | Filter?: Filter; 73 | } 74 | 75 | /** 76 | * `score` 为检索排名 77 | * 78 | * `fields` 为这条数据的键值对 79 | * 80 | * 拓展字段中可能还会有其它内部字段,如: 81 | * - 主键字段,key 为定义的字段名 82 | */ 83 | interface SearchData> { 84 | Score: number; 85 | Fields?: Data; 86 | [key: string]: unknown; 87 | } 88 | 89 | export class SearchResponse> extends VikingdbResponse { 90 | constructor(public Data: SearchData[][], OriginalRequest: string, LogId: string) { 91 | super(OriginalRequest, LogId); 92 | } 93 | } 94 | 95 | /* SearchByVector start */ 96 | interface SearchByVectorCommonRequest extends SearchCommonRequest { 97 | DenseVectors: number[][]; 98 | /** 当索引为混合检索时 */ 99 | SparseVectors?: Record[]; 100 | PrimaryKeyIn?: Array; 101 | PrimaryKeyNotIn?: Array; 102 | } 103 | 104 | interface SearchByVectorByCollectionNameRequest extends SearchByVectorCommonRequest { 105 | CollectionName: string; 106 | } 107 | 108 | interface SearchByVectorByCollectionAliasRequest extends SearchByVectorCommonRequest { 109 | CollectionAlias: string; 110 | } 111 | 112 | export type SearchByVectorRequest = 113 | | SearchByVectorByCollectionNameRequest 114 | | SearchByVectorByCollectionAliasRequest; 115 | /* SearchByVector end */ 116 | 117 | /* SearchByPrimaryKey start */ 118 | interface SearchByPrimaryKeyCommonRequest extends SearchCommonRequest { 119 | PrimaryKeys: Array; 120 | } 121 | 122 | interface SearchByPrimaryKeyByCollectionNameRequest extends SearchByPrimaryKeyCommonRequest { 123 | CollectionName: string; 124 | } 125 | 126 | interface SearchByPrimaryKeyByCollectionAliasRequest extends SearchByPrimaryKeyCommonRequest { 127 | CollectionAlias: string; 128 | } 129 | 130 | export type SearchByPrimaryKeyRequest = 131 | | SearchByPrimaryKeyByCollectionNameRequest 132 | | SearchByPrimaryKeyByCollectionAliasRequest; 133 | /* SearchByPrimaryKey end */ 134 | 135 | /* SearchByText start */ 136 | interface SearchByTextCommonRequest extends SearchCommonRequest { 137 | Text: string; 138 | } 139 | 140 | interface SearchByTextByCollectionNameRequest extends SearchByTextCommonRequest { 141 | CollectionName: string; 142 | } 143 | 144 | interface SearchByTextByCollectionAliasRequest extends SearchByTextCommonRequest { 145 | CollectionAlias: string; 146 | } 147 | 148 | export type SearchByTextRequest = 149 | | SearchByTextByCollectionNameRequest 150 | | SearchByTextByCollectionAliasRequest; 151 | /* SearchByText end */ 152 | 153 | /* SearchByScalar start */ 154 | interface SearchByScalarCommonRequest extends Omit { 155 | ScalarConfig?: { 156 | Order: "asc" | "desc"; 157 | FieldName: string; 158 | }; 159 | } 160 | 161 | interface SearchByScalarByCollectionNameRequest extends SearchByScalarCommonRequest { 162 | CollectionName: string; 163 | } 164 | 165 | interface SearchByScalarByCollectionAliasRequest extends SearchByScalarCommonRequest { 166 | CollectionAlias: string; 167 | } 168 | 169 | export type SearchByScalarRequest = 170 | | SearchByScalarByCollectionNameRequest 171 | | SearchByScalarByCollectionAliasRequest; 172 | /* SearchByScalar end */ 173 | 174 | /* SearchAgg start*/ 175 | 176 | interface SearchAggCommonRequest extends SearchCommonRequest { 177 | Search: { 178 | partition?: unknown; 179 | filter?: BackendFilter; 180 | }; 181 | Agg: { 182 | op: string; 183 | field?: string; 184 | cond?: Record; 185 | }; 186 | } 187 | interface SearchAggByCollectionNameRequest extends SearchAggCommonRequest { 188 | CollectionName: string; 189 | } 190 | 191 | interface SearchAggByCollectionAliasRequest extends SearchAggCommonRequest { 192 | CollectionAlias: string; 193 | } 194 | 195 | export type SearchAggRequest = SearchAggByCollectionNameRequest | SearchAggByCollectionAliasRequest; 196 | 197 | export class SearchAggResponse extends VikingdbResponse { 198 | constructor(public Data: BackendSearchAggResponse, OriginalRequest: string, LogId: string) { 199 | super(OriginalRequest, LogId); 200 | } 201 | } 202 | /* SearchAgg end*/ 203 | -------------------------------------------------------------------------------- /src/services/vikingdb/task/backend.ts: -------------------------------------------------------------------------------- 1 | /* CreateTask start */ 2 | export interface CommonTaskParamsCommon { 3 | collection_name: string; 4 | filter?: Record; 5 | } 6 | 7 | export interface DeleteTaskParams extends CommonTaskParamsCommon { 8 | need_confirm?: boolean; 9 | } 10 | 11 | export interface ExportTaskParams extends CommonTaskParamsCommon { 12 | tos_path: string; 13 | field_type: "parquet" | "json"; 14 | export_all: boolean; 15 | } 16 | 17 | export type TaskParams = DeleteTaskParams | ExportTaskParams; 18 | export interface BackendCreateTaskRequest { 19 | task_type: string; 20 | task_params: TaskParams; 21 | } 22 | 23 | export interface BackendCreateTaskData { 24 | task_id: string; 25 | } 26 | 27 | /* CreateTask end */ 28 | 29 | /* UpdateTask start */ 30 | export interface BackendUpdateTaskRequest { 31 | task_id: string; 32 | task_status: string; 33 | } 34 | /* UpdateTask end */ 35 | 36 | /* GetTaskInfo start */ 37 | export interface BackendGetTaskInfoRequest { 38 | task_id: string; 39 | } 40 | 41 | export interface ProcessInfo { 42 | sampled_data: Array; 43 | sampled_tipmestamp: number; 44 | err_msg: string; 45 | process_step: string; 46 | task_progress: number; 47 | total_data_count: number; 48 | total_delete_count: number; 49 | total_filter_count: number; 50 | } 51 | export type TaskStatus = "init" | "queued" | "running" | "done" | "fail" | "confirm" | "confirmed"; 52 | 53 | export interface BackendGetTaskInfoData { 54 | process_info: { 55 | task_id: string; 56 | task_status: TaskStatus; 57 | task_type: string; 58 | task_params: TaskParams; 59 | update_person: string; 60 | update_time: number; 61 | create_time: number; 62 | process_info: ProcessInfo; 63 | }; 64 | } 65 | /* GetTaskInfo end */ 66 | -------------------------------------------------------------------------------- /src/services/vikingdb/task/index.ts: -------------------------------------------------------------------------------- 1 | import { AbstractService } from "../abstractService"; 2 | import { VikingdbResponse } from "../types"; 3 | import { 4 | BackendCreateTaskData, 5 | BackendCreateTaskRequest, 6 | BackendGetTaskInfoData, 7 | BackendGetTaskInfoRequest, 8 | BackendUpdateTaskRequest, 9 | } from "./backend"; 10 | import { Pathname } from "./pathname"; 11 | import { 12 | CreateTaskRequest, 13 | CreateTaskResponse, 14 | GetTaskInfoRequest, 15 | GetTaskInfoResponse, 16 | UpdateTaskRequest, 17 | } from "./types"; 18 | 19 | export class TaskService extends AbstractService { 20 | async CreateTask({ TaskType, TaskParams }: CreateTaskRequest): Promise { 21 | const response = await this.request( 22 | Pathname.CreateTask, 23 | { 24 | task_type: TaskType, 25 | task_params: TaskParams, 26 | } 27 | ); 28 | return new CreateTaskResponse(response.data, response.original_request, response.request_id); 29 | } 30 | async UpdateTask({ TaskType, TaskStatus }: UpdateTaskRequest): Promise { 31 | const response = await this.request(Pathname.UpdateTask, { 32 | task_id: TaskType, 33 | task_status: TaskStatus, 34 | }); 35 | return new VikingdbResponse(response.original_request, response.request_id); 36 | } 37 | async GetTaskInfo({ TaskId }: GetTaskInfoRequest): Promise { 38 | const response = await this.request( 39 | Pathname.GetTaskInfo, 40 | { 41 | task_id: TaskId, 42 | } 43 | ); 44 | return new GetTaskInfoResponse(response.data, response.original_request, response.request_id); 45 | } 46 | } 47 | 48 | export * as task from "./types"; 49 | -------------------------------------------------------------------------------- /src/services/vikingdb/task/pathname.ts: -------------------------------------------------------------------------------- 1 | export enum Pathname { 2 | CreateTask = "/api/task/create", 3 | UpdateTask = "/api/task/update", 4 | GetTaskInfo = "/api/task/info", 5 | } 6 | -------------------------------------------------------------------------------- /src/services/vikingdb/task/types.ts: -------------------------------------------------------------------------------- 1 | import { type RequestOptions, VikingdbResponse } from "../types"; 2 | import { BackendCreateTaskData, BackendGetTaskInfoData, TaskParams } from "./backend"; 3 | 4 | export class TaskResponse extends VikingdbResponse { 5 | constructor(public readonly Data: T, OriginalRequest: string, LogId: string) { 6 | super(OriginalRequest, LogId); 7 | } 8 | } 9 | 10 | export interface Options extends Omit { 11 | data: T; 12 | pathname: string; 13 | } 14 | 15 | export interface CreateTaskRequest { 16 | TaskType: string; 17 | TaskParams: TaskParams; 18 | } 19 | 20 | export class CreateTaskResponse extends VikingdbResponse { 21 | constructor(public Data: BackendCreateTaskData, OriginalRequest: string, LogId: string) { 22 | super(OriginalRequest, LogId); 23 | } 24 | } 25 | 26 | export interface UpdateTaskRequest { 27 | TaskType: string; 28 | TaskStatus: string; 29 | } 30 | 31 | export interface GetTaskInfoRequest { 32 | TaskId: string; 33 | } 34 | 35 | export class GetTaskInfoResponse extends VikingdbResponse { 36 | constructor(public Data: BackendGetTaskInfoData, OriginalRequest: string, LogId: string) { 37 | super(OriginalRequest, LogId); 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /src/services/vikingdb/types.ts: -------------------------------------------------------------------------------- 1 | export type VikingdbRegion = "cn-beijing" | "cn-shanghai"; 2 | 3 | export class VikingdbResponse { 4 | constructor( 5 | /** @type string 原始请求 body string */ 6 | public readonly OriginalRequest: string, 7 | /** @type string 日志 ID */ 8 | public readonly LogId: string 9 | ) {} 10 | } 11 | 12 | export enum VikingdbErrorCode { 13 | ErrUnauthorized = 1000001, 14 | ErrNoPermission, 15 | ErrInvalidRequest, 16 | ErrCollectionExist, 17 | ErrCollectionNotExist, 18 | ErrOperationNotAllowed, 19 | ErrIndexExist, 20 | ErrIndexNotExist, 21 | ErrInitTbaseReader, 22 | ErrQueryOpFailed, 23 | ErrDataNotFound, 24 | ErrInitTbaseWriter, 25 | ErrDelOpFailed, 26 | ErrUpsertOpFailed, 27 | ErrTokenMismatch, 28 | ErrInvalidQueryVec, 29 | ErrInvalidPrimaryKey, 30 | ErrInvalidPartition, 31 | ErrInvalidScalarCond, 32 | ErrInvalidProxyService, 33 | ErrIndexRecall, 34 | ErrIndexFetchData, 35 | ErrIndexNotReady, 36 | ErrAPINotImplemented, 37 | ErrCalcEmbeddingFailed, 38 | ErrListEmbeddingModels, 39 | ErrInternal = 1000028, 40 | ErrInvalidRerank = 1000030, 41 | ErrUserNoOrder = 1000032, 42 | ErrUserOverdue, 43 | ErrSdk = 9999999, 44 | } 45 | 46 | export class VikingdbError extends Error { 47 | constructor( 48 | /** @type number 后端错误码 */ 49 | public readonly Code: VikingdbErrorCode, 50 | /** @type string 后端错误信息 */ 51 | public readonly Message: string 52 | ) { 53 | super(`[${Code}]: ${Message}`); 54 | } 55 | } 56 | 57 | export class VikingdbRequestError extends VikingdbError { 58 | constructor( 59 | /** @type number 后端错误码 */ 60 | Code: VikingdbErrorCode, 61 | /** @type string 后端错误信息 */ 62 | Message: string, 63 | public readonly OriginalRequest: string, 64 | /** @type string 请求日志 ID */ 65 | public readonly LogId: string 66 | ) { 67 | super(Code, Message); 68 | } 69 | } 70 | 71 | /* CreateCollection start */ 72 | export enum FieldType { 73 | Int64 = "int64", 74 | Float32 = "float32", 75 | String = "string", 76 | Boolean = "bool", 77 | ListString = "list", 78 | ListInt64 = "list", 79 | /** 稠密向量 */ 80 | DenseVector = "vector", 81 | /** 稀疏向量 */ 82 | SparseVector = "sparse_vector", 83 | Text = "text", 84 | } 85 | /** 标量字段类型 */ 86 | export type ScalarFieldType = Exclude< 87 | FieldType, 88 | FieldType.DenseVector | FieldType.SparseVector | FieldType.Text 89 | >; 90 | 91 | export interface ScalarFieldType2JsType { 92 | [FieldType.Int64]: number; 93 | [FieldType.Float32]: number; 94 | [FieldType.String]: string; 95 | [FieldType.Boolean]: boolean; 96 | [FieldType.ListString]: string[]; 97 | [FieldType.ListInt64]: Array; 98 | } 99 | 100 | /** 主键字段类型 */ 101 | export type PrimaryKeyFieldType = Extract; 102 | 103 | /** 标量字段信息 */ 104 | export interface ScalarFieldInfo< 105 | Type extends ScalarFieldType, 106 | Value extends ScalarFieldType2JsType[Type] = any 107 | > { 108 | FieldName: string; 109 | FieldType: Type; 110 | DefaultValue?: Value; 111 | } 112 | 113 | /** 主键字段信息 */ 114 | export interface PrimaryKeyFieldInfo 115 | extends Omit, "DefaultValue"> { 116 | IsPrimary: true; 117 | } 118 | 119 | /** 稠密向量字段信息 */ 120 | export interface DenseVectorFieldInfo { 121 | FieldName: string; 122 | FieldType: FieldType.DenseVector; 123 | /** 向量维度,需要 4 的倍数 */ 124 | Dim: number; 125 | } 126 | 127 | /** 稀疏向量字段信息 */ 128 | export interface SparseVectorFieldInfo { 129 | FieldName: string; 130 | FieldType: FieldType.SparseVector; 131 | } 132 | 133 | export type PipelineName = 134 | | "text_split_bge_large_zh" 135 | | "text_bge_large_zh" 136 | | "text_split_bge_m3" 137 | | "text_bge_m3" 138 | | "text_split_bge_large_and_m3" 139 | | "text_bge_large_and_m3" 140 | | "text_doubao_embedding" 141 | | "text_split_doubao_embedding" 142 | | "text_doubao_embedding_and_m3" 143 | | "text_split_doubao_embedding_and_m3"; 144 | 145 | /** 文本字段信息 */ 146 | export interface TextFieldInfo { 147 | FieldName: string; 148 | FieldType: FieldType.Text; 149 | PipelineName?: PipelineName; 150 | } 151 | 152 | export type FieldInfo = 153 | | ScalarFieldInfo 154 | | PrimaryKeyFieldInfo 155 | | DenseVectorFieldInfo 156 | | SparseVectorFieldInfo 157 | | TextFieldInfo; 158 | 159 | export interface BackendField { 160 | field_name: string; 161 | field_type: string; 162 | default_val?: any; 163 | dim?: number; 164 | pipeline_name?: PipelineName; 165 | } 166 | 167 | export type IsNever = [T] extends [never] ? true : false; 168 | 169 | export type IsUnion = IsNever extends true 170 | ? false 171 | : T extends B 172 | ? [B] extends [T] 173 | ? false 174 | : true 175 | : never; 176 | 177 | export type IsPrimaryKey< 178 | Data extends Record, 179 | PrimaryKey extends keyof Data 180 | > = IsUnion extends true 181 | ? false 182 | : Data[PrimaryKey] extends ScalarFieldType2JsType[PrimaryKeyFieldType] 183 | ? true 184 | : false; 185 | 186 | export type GetPrimaryKeys> = { 187 | [K in keyof T]: IsPrimaryKey extends true ? K : never; 188 | }[keyof T]; 189 | 190 | export type PrimaryKeys = Array; 191 | 192 | export interface RequestOptions { 193 | headers?: any; 194 | timeout?: number; 195 | } 196 | -------------------------------------------------------------------------------- /src/services/vod/constants.ts: -------------------------------------------------------------------------------- 1 | export const VALID_CATEGORY_LIST = ["video", "audio", "image", "dynamic_img", "subtitle", "font"]; 2 | 3 | export const VALID_TYPE_LIST = ["media", "image", "object"]; 4 | 5 | export const MinChunkSize = 20 * 1024 * 1024; 6 | export const LargeFileSize = 1024 * 1024 * 1024; 7 | -------------------------------------------------------------------------------- /src/services/vod/demo.js: -------------------------------------------------------------------------------- 1 | import { vodOpenapi } from "@volcengine/openapi"; 2 | 3 | export async function main(AccessKeyId, SecretKey, SessionToken) { 4 | // 使用默认的service实例 也可以创建一个新实例 const vodOpenapiService = new vodOpenapi.VodService(); 5 | const vodOpenapiService = vodOpenapi.defaultService; 6 | // 强烈建议不要把 AccessKey ID 和 AccessKey Secret 保存到工程代码里,否则可能导致 AccessKey 泄露,威胁您账号下所有资源的安全。 7 | // 本示例通过从环境变量中读取 AccessKey ID 和 AccessKey Secret,来实现 API 访问的身份验证。运行代码示例前,请配置环境变量 VOLC_ACCESSKEY 和 VOLC_SECRETKEY 8 | // vodOpenapiService.setAccessKeyId(AccessKeyId); 9 | // vodOpenapiService.setSecretKey(SecretKey); 10 | 11 | if (SessionToken) { 12 | // 使用sts请求时 设置SessionToken 13 | vodOpenapiService.setSessionToken(SessionToken); 14 | } 15 | 16 | // 获取播放信息 17 | await vodOpenapiService.GetPlayInfo({ 18 | Vid: "your video id", 19 | }); 20 | 21 | // 获取上传token 22 | await vodOpenapiService.GetUploadToken(); 23 | } 24 | -------------------------------------------------------------------------------- /src/typings.d.ts: -------------------------------------------------------------------------------- 1 | declare module "*.json"; 2 | -------------------------------------------------------------------------------- /test/acep.test.js: -------------------------------------------------------------------------------- 1 | import { Service } from "../lib"; 2 | import { getListPodResultReponseSchemaValidate } from "./schema/acep"; 3 | const defaultConfig = { 4 | serviceName: "ACEP", 5 | defaultVersion: "2020-10-25", 6 | }; 7 | const ACEPService = new Service(defaultConfig); 8 | 9 | test("edit:listPodEditResult", async () => { 10 | const response = await ACEPService.fetchOpenAPI({ 11 | Action: "ListPod", 12 | Version: "2020-10-25", 13 | query: { 14 | product_id: '1426095758716702720', 15 | } 16 | }); 17 | const validateResult = getListPodResultReponseSchemaValidate(response); 18 | expect(validateResult).toBe(true); 19 | }); 20 | -------------------------------------------------------------------------------- /test/billing.test.js: -------------------------------------------------------------------------------- 1 | import { Service } from "../lib"; 2 | import { 3 | listBillReponseSchemaValidate, 4 | listBillDetailReponseSchemaValidate, 5 | listBillOverviewByProdReponseSchemaValidate, 6 | } from "./schema/billing"; 7 | 8 | test("billing:ListBill", async () => { 9 | const billingService = new Service({ 10 | accessKeyId: "", 11 | secretKey: "", 12 | }); 13 | 14 | // 查询账单 15 | const ListBillResponse = await billingService.fetchOpenAPI({ 16 | Action: "ListBill", 17 | Version: "2022-01-01", 18 | query: { 19 | BillPeriod: "2022-01", 20 | Limit: "10", 21 | Offset: "0", 22 | Product: "", 23 | BillingMode: "", 24 | BillCategoryParent: "", 25 | PayStatus: "", 26 | IgnoreZero: "0", 27 | NeedRecordNum: "1", 28 | }, 29 | }); 30 | const validateListBillResult = listBillReponseSchemaValidate(ListBillResponse); 31 | expect(validateListBillResult).toBe(true); 32 | 33 | // 查询账单明细 34 | const ListBillDetailresponse = await billingService.fetchOpenAPI({ 35 | Action: "ListBillDetail", 36 | Version: "2022-01-01", 37 | query: { 38 | BillPeriod: "2022-01", 39 | Limit: "10", 40 | Offset: "0", 41 | GroupTerm: "0", 42 | GroupPeriod: "2", 43 | Product: "", 44 | BillingMode: "", 45 | BillCategory: "", 46 | InstanceNo: "", 47 | IgnoreZero: "0", 48 | NeedRecordNum: "1", 49 | }, 50 | }); 51 | const validateListBillDetailResult = listBillDetailReponseSchemaValidate(ListBillDetailresponse); 52 | expect(validateListBillDetailResult).toBe(true); 53 | 54 | // 查询账单总览-产品汇总 55 | const ListBillOverviewByProdResponse = await billingService.fetchOpenAPI({ 56 | Action: "ListBillOverviewByProd", 57 | Version: "2022-01-01", 58 | query: { 59 | BillPeriod: "2022-01", 60 | Limit: "10", 61 | Offset: "0", 62 | Product: "", 63 | BillingMode: "", 64 | BillCategoryParent: "", 65 | IgnoreZero: "0", 66 | NeedRecordNum: "1", 67 | }, 68 | }); 69 | const validateListBillOverviewByProdResult = listBillOverviewByProdReponseSchemaValidate( 70 | ListBillOverviewByProdResponse 71 | ); 72 | expect(validateListBillOverviewByProdResult).toBe(true); 73 | }); 74 | -------------------------------------------------------------------------------- /test/edit.test.js: -------------------------------------------------------------------------------- 1 | import { Service } from "../lib"; 2 | import { getDirectEditResultReponseSchemaValidate } from "./schema/edit"; 3 | 4 | const defaultConfig = { 5 | serviceName: "edit", 6 | defaultVersion: "2018-01-01", 7 | }; 8 | const editService = new Service(defaultConfig); 9 | 10 | test("edit:GetDirectEditResult", async () => { 11 | const response = await editService.fetchOpenAPI({ 12 | Action: "GetDirectEditResult", 13 | Version: "2018-01-01", 14 | method: 'POST', 15 | headers: { 16 | "content-type": "application-json", 17 | }, 18 | data: { 19 | ReqIds: ['979a0b0ca97c45b2b06e61b522b0cd7e'], 20 | } 21 | }); 22 | const validateResult = getDirectEditResultReponseSchemaValidate(response); 23 | expect(validateResult).toBe(true); 24 | }); 25 | -------------------------------------------------------------------------------- /test/iam.test.js: -------------------------------------------------------------------------------- 1 | import { Service } from "../lib"; 2 | import { listUserReponseSchemaValidate } from "./schema/iam"; 3 | 4 | const defaultConfig = { 5 | serviceName: "iam", 6 | defaultVersion: "2018-01-01", 7 | }; 8 | const iamService = new Service(defaultConfig); 9 | 10 | test("iam:ListUsers", async () => { 11 | const response = await iamService.fetchOpenAPI({ 12 | Action: "ListUsers", 13 | Version: "2018-01-01", 14 | }); 15 | const validateResult = listUserReponseSchemaValidate(response); 16 | expect(validateResult).toBe(true); 17 | }); 18 | -------------------------------------------------------------------------------- /test/imagex.test.js: -------------------------------------------------------------------------------- 1 | import { Service, imagex } from "../lib"; 2 | import { 3 | previewImageUploadFileReponseSchemaValidate, 4 | uploadImagesReponseSchemaValidate, 5 | } from "./schema/imagex"; 6 | import path from "path"; 7 | import { readFile } from "fs/promises"; 8 | import axios from "axios"; 9 | 10 | function atob(content) { 11 | const buff = Buffer.from(content, "base64"); 12 | return buff.toString(); 13 | } 14 | 15 | const defaultConfig = { 16 | serviceName: "imagex", 17 | defaultVersion: "2018-08-01", 18 | }; 19 | const imagexService = new Service(defaultConfig); 20 | 21 | test("imagex:PreviewImageUploadFile", async () => { 22 | const response = await imagexService.fetchOpenAPI({ 23 | Action: "PreviewImageUploadFile", 24 | Version: "2018-08-01", 25 | query: { 26 | ServiceId: "7zcoejbqou", 27 | StoreUri: "tos-cn-i-7zcoejbqou/732c6acc5637408a96bb67d59bf0de85", 28 | }, 29 | }); 30 | const validateResult = previewImageUploadFileReponseSchemaValidate(response); 31 | expect(validateResult).toBe(true); 32 | }); 33 | 34 | test("imagex:UploadImages", async () => { 35 | const imagexService = imagex.defaultService; 36 | const response = await imagexService.UploadImages({ 37 | serviceId: "7zcoejbqou", 38 | files: [path.resolve(__dirname, "imagex_test_pic.png")], 39 | fileKeys: ["sdk_test_1"], 40 | }); 41 | const validateResult = uploadImagesReponseSchemaValidate(response); 42 | expect(validateResult).toBe(true); 43 | }); 44 | 45 | test("imagex:GetUploadAuthToken", async () => { 46 | const protocal = "https:"; 47 | const host = "open.volcengineapi.com"; 48 | 49 | const imagexService = imagex.defaultService; 50 | 51 | imagexService.setAccessKeyId("testAk"); 52 | imagexService.setSecretKey("testSk"); 53 | 54 | const base64String = imagexService.GetUploadAuthToken({ 55 | ServiceId: "your imagex service id", 56 | // 默认900 (15min) 57 | "X-Expires": "60", 58 | }); 59 | 60 | const imageBlob = await readFile(path.resolve(__dirname, "./imagex_test_pic.png")); 61 | 62 | const tokens = JSON.parse(atob(base64String)); 63 | 64 | const { ApplyUploadToken, CommitUploadToken } = tokens; 65 | 66 | const { 67 | data: { 68 | Result: { 69 | UploadAddress: { 70 | UploadHosts: [UploadHost], 71 | StoreInfos, 72 | SessionKey, 73 | }, 74 | }, 75 | }, 76 | } = await axios.get(`${protocal}//${host}?${ApplyUploadToken}`); 77 | 78 | await imagexService.DoUpload([imageBlob], UploadHost, StoreInfos); 79 | 80 | const { 81 | data: { Result: CommitUploadRes }, 82 | } = await axios.post(`${protocal}//${host}?${CommitUploadToken}`, { SessionKey }); 83 | 84 | return CommitUploadRes; 85 | }); 86 | -------------------------------------------------------------------------------- /test/imagex_test_pic.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/volcengine/volc-sdk-nodejs/677e35e1c1d1bb892f0c66256edad03a7d3949bc/test/imagex_test_pic.png -------------------------------------------------------------------------------- /test/live.test.js: -------------------------------------------------------------------------------- 1 | import { liveOpenapi } from "../lib"; 2 | import { GetCasterPlayerUserTokenSchemaValidate } from "./schema/live"; 3 | 4 | test("live:GetCasterPlayerUserToken", async () => { 5 | const liveCasterService = new liveOpenapi.liveCasterService({ 6 | accessKeyId: "test", 7 | secretKey: "test", 8 | }); 9 | const response = liveCasterService.GetCasterPlayerUserToken(); 10 | const validateResult = GetCasterPlayerUserTokenSchemaValidate(response); 11 | expect(validateResult).toBe(true); 12 | }); 13 | -------------------------------------------------------------------------------- /test/livesaas.test.js: -------------------------------------------------------------------------------- 1 | import { livesaasOpenapi } from "../lib"; 2 | import { GetLivesaasUploadUserTokenSchemaValidate } from "./schema/livesaas"; 3 | 4 | test("live:GetLivesaasUploadUserToken", async () => { 5 | const livesaasService = new livesaasOpenapi.LivesaasService({ 6 | accessKeyId: "test", 7 | secretKey: "test", 8 | }); 9 | const response = livesaasService.GetLivesaasUploadUserToken(); 10 | const validateResult = GetLivesaasUploadUserTokenSchemaValidate(response); 11 | expect(validateResult).toBe(true); 12 | }); 13 | -------------------------------------------------------------------------------- /test/maas.test.js: -------------------------------------------------------------------------------- 1 | import { maas } from "../lib"; 2 | import { 3 | ChatMaasSchemaValidate, 4 | TokenizationMaasSchemaValidate, 5 | ClassificationMaasSchemaValidate, 6 | EmbeddingsMaasSchemaValidate, 7 | ChatV2MaasSchemaValidate, 8 | TokenizationV2MaasSchemaValidate, 9 | ClassificationV2MaasSchemaValidate, 10 | EmbeddingsV2MaasSchemaValidate, 11 | } from "./schema/maas"; 12 | 13 | const maasService = new maas.MaasService({ 14 | host: "maas-api.ml-platform-cn-beijing.volces.com", 15 | region: "cn-beijing", 16 | }); 17 | 18 | const maasServiceV2 = new maas.MaasServiceV2({ 19 | host: "maas-api.ml-platform-cn-beijing.volces.com", 20 | region: "cn-beijing", 21 | }); 22 | 23 | // 从环境变量设置 ak & sk 24 | maasService.setAccessKeyId(process.env.VOLC_ACCESSKEY); 25 | maasService.setSecretKey(process.env.VOLC_SECRETKEY); 26 | 27 | maasServiceV2.setAccessKeyId(process.env.VOLC_ACCESSKEY); 28 | maasServiceV2.setSecretKey(process.env.VOLC_SECRETKEY); 29 | 30 | const chatParams = { 31 | model: { 32 | name: "chatglm-130b", 33 | }, 34 | messages: [ 35 | { 36 | role: "user", 37 | content: "天为什么这么蓝?", 38 | }, 39 | { 40 | role: "assistant", 41 | content: "因为有你", 42 | }, 43 | { 44 | role: "user", 45 | content: "花儿为什么这么香?", 46 | }, 47 | ], 48 | parameters: { 49 | max_new_tokens: 1000, 50 | temperature: 1, 51 | }, 52 | }; 53 | 54 | const chatV2Params = { 55 | parameters: { 56 | max_new_tokens: 1000, 57 | min_new_tokens: 1, 58 | temperature: 0.7, 59 | top_p: 0.9, 60 | top_k: 0, 61 | max_prompt_tokens: 4000, 62 | }, 63 | messages: [ 64 | { 65 | role: "user", 66 | content: "天为什么这么蓝?", 67 | }, 68 | { 69 | role: "assistant", 70 | content: "因为有你", 71 | }, 72 | { 73 | role: "user", 74 | content: "花儿为什么这么香?", 75 | }, 76 | ], 77 | }; 78 | 79 | const tokenizationParams = { 80 | model: { 81 | name: "skylark2-pro-4k", 82 | version: "1.0", 83 | }, 84 | text: "天空为什么这么蓝?", 85 | }; 86 | 87 | const tokenizationV2Params = { 88 | text: "花儿为什么这么香?", 89 | }; 90 | 91 | const classificationParams = { 92 | model: { 93 | name: "skylark2-pro-4k", 94 | version: "1.0", 95 | }, 96 | query: "中国的第一个经济特区是?", 97 | labels: ["北京", "珠海", "深圳", "厦门", "上海"], 98 | }; 99 | 100 | const classificationV2Params = { 101 | query: "花儿为什么这么香?", 102 | labels: ["陈述句", "疑问句", "肯定句"], 103 | }; 104 | 105 | const embeddingsParams = { 106 | model: { 107 | name: "bge-large-zh", 108 | }, 109 | input: ["天很蓝", "海很深"], 110 | }; 111 | 112 | const embeddingsV2Params = { 113 | input: ["天很蓝", "海很深"], 114 | }; 115 | 116 | const endpointId = "mse-20231201150750-qqzgd"; 117 | const vectorModelendpointId = "mse-20231114152400-l7rb8"; 118 | 119 | test("maas:Chat", async () => { 120 | const resp = await maasService.Chat({ ...chatParams }); 121 | const validateResult = ChatMaasSchemaValidate(resp); 122 | expect(validateResult).toBe(true); 123 | }); 124 | 125 | test("maas:ChatV2", async () => { 126 | const resp = await maasServiceV2.Chat(endpointId, chatV2Params); 127 | process.stdout.write(JSON.stringify(resp)); 128 | const validateResult = ChatV2MaasSchemaValidate(resp); 129 | expect(validateResult).toBe(true); 130 | }); 131 | 132 | test("maas:StreamChat", async () => { 133 | const streamGenerator = await maasService.StreamChat({ ...chatParams }); 134 | for await (const value of streamGenerator) { 135 | process.stdout.write(JSON.stringify(value)); 136 | } 137 | }); 138 | 139 | test("maas:StreamChatV2", async () => { 140 | const streamGenerator = await maasServiceV2.StreamChat(endpointId, chatV2Params); 141 | for await (const value of streamGenerator) { 142 | process.stdout.write(JSON.stringify(value)); 143 | } 144 | }); 145 | 146 | test("maas:Tokenization", async () => { 147 | const resp = await maasService.Tokenization({ ...tokenizationParams }); 148 | process.stdout.write(JSON.stringify(resp)); 149 | const validateResult = TokenizationMaasSchemaValidate(resp); 150 | expect(validateResult).toBe(true); 151 | }); 152 | 153 | test("maas:TokenizationV2", async () => { 154 | const resp = await maasServiceV2.Tokenization(endpointId, tokenizationV2Params); 155 | process.stdout.write(JSON.stringify(resp)); 156 | const validateResult = TokenizationV2MaasSchemaValidate(resp); 157 | expect(validateResult).toBe(true); 158 | }); 159 | 160 | test("maas:Classification", async () => { 161 | const resp = await maasService.Classification({ ...classificationParams }); 162 | process.stdout.write(JSON.stringify(resp)); 163 | const validateResult = ClassificationMaasSchemaValidate(resp); 164 | expect(validateResult).toBe(true); 165 | }); 166 | 167 | test("maas:ClassificationV2", async () => { 168 | const resp = await maasServiceV2.Classification(endpointId, classificationV2Params); 169 | process.stdout.write(JSON.stringify(resp)); 170 | const validateResult = ClassificationV2MaasSchemaValidate(resp); 171 | expect(validateResult).toBe(true); 172 | }); 173 | 174 | test("maas:Embeddings", async () => { 175 | const resp = await maasService.Embeddings({ ...embeddingsParams }); 176 | const validateResult = EmbeddingsMaasSchemaValidate(resp); 177 | expect(validateResult).toBe(true); 178 | }); 179 | 180 | test("maas:EmbeddingsV2", async () => { 181 | const resp = await maasServiceV2.Embeddings(vectorModelendpointId, embeddingsV2Params); 182 | const validateResult = EmbeddingsV2MaasSchemaValidate(resp); 183 | expect(validateResult).toBe(true); 184 | }); 185 | -------------------------------------------------------------------------------- /test/rocketmq.test.js: -------------------------------------------------------------------------------- 1 | const { Client } = require("../lib/services/rocketmq"); 2 | 3 | const instanceId = process.env.MQ_INSTANCE_ID; 4 | const endpoint = process.env.MQ_ENDPOINT; 5 | const accessKey = process.env.MQ_ACCESS_KEY; 6 | const secretKey = process.env.MQ_SECRET_KEY; 7 | 8 | const topic = process.env.MQ_TOPIC; 9 | const group = process.env.MQ_GROUP; 10 | 11 | const client = new Client({ 12 | instanceId, 13 | endpoint, 14 | accessKey, 15 | secretKey, 16 | }); 17 | 18 | describe("RocketMQ producer test", () => { 19 | test("连接并关闭", async () => { 20 | const producer = client.createProducer(); 21 | await producer.connect(); 22 | await producer.close(); 23 | }); 24 | }); 25 | -------------------------------------------------------------------------------- /test/rtc.test.js: -------------------------------------------------------------------------------- 1 | import { rtcOpenapi } from "../lib"; 2 | import { GetRecordTaskParamsSchemaValidate, StopRecordParamsSchemaValidate, StartRecordParamsSchemaValidate } from "./schema/rtc"; 3 | 4 | const rtcOpenapiService = rtcOpenapi.defaultService; 5 | 6 | test("rtc:StartRecordParams", async () => { 7 | const response = await rtcOpenapiService.StartRecordParams({ 8 | AppId : "Your_AppId", 9 | BusinessId : "Your_BusinessId", 10 | RoomId : "Your_RoomId", 11 | TaskId: "Your_TaskId", 12 | RecordMode: 0, 13 | FileFormatConfig: { 14 | FileFormat: ["HLS", "FLV"] 15 | }, 16 | FileNameConfig: { 17 | Prefix: ["directory1", "directory2"], 18 | Pattern: "" 19 | }, 20 | StorageConfig: { 21 | Type: 0, 22 | TosConfig: { 23 | UserAccountId: "Your_UserAccountId", 24 | Region: "Your_Region", 25 | Bucket: "Your_Bucket" 26 | } 27 | } 28 | }); 29 | const validateResult = StartRecordParamsSchemaValidate(response); 30 | expect(validateResult).toBe(true); 31 | }); 32 | 33 | test("rtc:StopRecord", async () => { 34 | const response = await rtcOpenapiService.StopRecord({ 35 | AppId : "Your_AppId", 36 | RoomId : "Your_RoomId", 37 | TaskId: "Your_TaskId" 38 | }); 39 | const validateResult = StopRecordParamsSchemaValidate(response); 40 | expect(validateResult).toBe(true); 41 | }); 42 | 43 | 44 | test("rtc:GetRecordTask", async () => { 45 | const response = await rtcOpenapiService.GetRecordTask({ 46 | AppId : "Your_AppId", 47 | RoomId : "Your_RoomId", 48 | TaskId: "Your_TaskId" 49 | }); 50 | const validateResult = GetRecordTaskParamsSchemaValidate(response); 51 | expect(validateResult).toBe(true); 52 | }); 53 | -------------------------------------------------------------------------------- /test/schema/acep.js: -------------------------------------------------------------------------------- 1 | import Ajv from "ajv"; 2 | import { createResponseSchema } from "./response"; 3 | const ajv = new Ajv(); 4 | 5 | export const getListPodResultReponseSchemaValidate = ajv.compile( 6 | createResponseSchema({ 7 | type: "object", 8 | properties: { 9 | row: { 10 | type: "array", 11 | items: { 12 | type: "object", 13 | properties: { 14 | pod_id:{ 15 | type: "string", 16 | }, 17 | } 18 | } 19 | }, 20 | total: { 21 | type: "number", 22 | } 23 | } 24 | }) 25 | ); 26 | -------------------------------------------------------------------------------- /test/schema/edit.js: -------------------------------------------------------------------------------- 1 | import Ajv from "ajv"; 2 | import { createResponseSchema } from "./response"; 3 | const ajv = new Ajv(); 4 | 5 | export const getDirectEditResultReponseSchemaValidate = ajv.compile( 6 | createResponseSchema({ 7 | type: "array", 8 | items: { 9 | type: "object", 10 | properties: { 11 | ReqId: { 12 | type: "string", 13 | }, 14 | EditParam: { 15 | type: "object", 16 | }, 17 | CallbackUri: { 18 | type: "string", 19 | }, 20 | CallbackArgs: { 21 | type: "string", 22 | }, 23 | Priority: { 24 | type: "number", 25 | }, 26 | Status: { 27 | type: "string", 28 | }, 29 | Message: { 30 | type: "string", 31 | }, 32 | OutputVid: { 33 | type: "string", 34 | }, 35 | SubVid: { 36 | type: "array", 37 | items: { type: "string" } 38 | }, 39 | TaskId: { 40 | type: "string", 41 | }, 42 | }, 43 | }, 44 | }) 45 | ); 46 | -------------------------------------------------------------------------------- /test/schema/iam.js: -------------------------------------------------------------------------------- 1 | import Ajv from "ajv"; 2 | import { createResponseSchema } from "./response"; 3 | const ajv = new Ajv(); 4 | 5 | export const listUserReponseSchemaValidate = ajv.compile( 6 | createResponseSchema({ 7 | type: "object", 8 | properties: { 9 | Limit: { 10 | type: "number", 11 | }, 12 | Offset: { 13 | type: "number", 14 | }, 15 | Total: { 16 | type: "number", 17 | }, 18 | UserMetadata: { 19 | type: "array", 20 | items: { 21 | type: "object", 22 | properties: { 23 | UserName: { 24 | type: "string", 25 | }, 26 | Trn: { 27 | type: "string", 28 | }, 29 | DisplayName: { 30 | type: "string", 31 | }, 32 | }, 33 | }, 34 | }, 35 | }, 36 | required: ["Limit", "Offset", "Total", "UserMetadata"], 37 | }) 38 | ); 39 | -------------------------------------------------------------------------------- /test/schema/imagex.js: -------------------------------------------------------------------------------- 1 | import Ajv from "ajv"; 2 | import { createResponseSchema } from "./response"; 3 | const ajv = new Ajv(); 4 | 5 | export const previewImageUploadFileReponseSchemaValidate = ajv.compile( 6 | createResponseSchema({ 7 | type: "object", 8 | properties: { 9 | ServiceId: { 10 | type: "string", 11 | }, 12 | FileName: { 13 | type: "string", 14 | }, 15 | StoreUri: { 16 | type: "string", 17 | }, 18 | ImageURL: { 19 | type: "string", 20 | }, 21 | ImageFormat: { 22 | type: "string", 23 | }, 24 | ImageSize: { 25 | type: "number", 26 | }, 27 | ImageWidth: { 28 | type: "number", 29 | }, 30 | ImageHeight: { 31 | type: "number", 32 | }, 33 | ImageFrames: { 34 | type: "number", 35 | }, 36 | ImageDuration: { 37 | type: "number", 38 | }, 39 | }, 40 | required: ["ServiceId", "FileName", "StoreUri", "ImageURL", "ImageFormat", "ImageSize", "ImageWidth", "ImageHeight"], 41 | }) 42 | ); 43 | 44 | export const uploadImagesReponseSchemaValidate = ajv.compile( 45 | createResponseSchema({ 46 | type: 'object', 47 | properties: { 48 | Results: { 49 | type: 'array', 50 | items: { 51 | type: 'object', 52 | properties: { 53 | Uri: { 54 | type: 'string', 55 | } 56 | }, 57 | required: ['Uri'], 58 | } 59 | }, 60 | RequestId: { 61 | type: 'string', 62 | }, 63 | PluginResult: { 64 | type: 'array', 65 | items: { 66 | type: 'object', 67 | properties: { 68 | FileName: { 69 | type: 'string', 70 | }, 71 | ImageUri: { 72 | type: "string", 73 | }, 74 | ImageFormat: { 75 | type: "string", 76 | }, 77 | ImageSize: { 78 | type: "number", 79 | }, 80 | ImageWidth: { 81 | type: "number", 82 | }, 83 | ImageHeight: { 84 | type: "number", 85 | }, 86 | ImageMd5: { 87 | type: "string", 88 | }, 89 | FrameCnt: { 90 | type: "number", 91 | }, 92 | Duration: { 93 | type: "number", 94 | }, 95 | }, 96 | required: ['FileName', 'ImageUri', 'ImageFormat', 'ImageSize', 'ImageWidth', 'ImageHeight', 'ImageMd5'], 97 | } 98 | } 99 | }, 100 | required: ['Results', 'RequestId', 'PluginResult'], 101 | }) 102 | ); 103 | -------------------------------------------------------------------------------- /test/schema/live.js: -------------------------------------------------------------------------------- 1 | import Ajv from "ajv"; 2 | const ajv = new Ajv(); 3 | 4 | export const GetCasterPlayerUserTokenSchemaValidate = ajv.compile({ 5 | type: "object", 6 | properties: { 7 | AccessKeyId: { 8 | type: "string", 9 | }, 10 | SecretAccessKey: { 11 | type: "string", 12 | }, 13 | CurrentTime: { 14 | type: "string", 15 | }, 16 | ExpiredTime: { 17 | type: "string", 18 | }, 19 | SessionToken: { 20 | type: "string", 21 | }, 22 | }, 23 | required: ["AccessKeyId", "SecretAccessKey", "CurrentTime", "ExpiredTime", "SessionToken"], 24 | }); 25 | -------------------------------------------------------------------------------- /test/schema/livesaas.js: -------------------------------------------------------------------------------- 1 | import Ajv from "ajv"; 2 | const ajv = new Ajv(); 3 | 4 | export const GetLivesaasUploadUserTokenSchemaValidate = ajv.compile({ 5 | type: "object", 6 | properties: { 7 | AccessKeyId: { 8 | type: "string", 9 | }, 10 | SecretAccessKey: { 11 | type: "string", 12 | }, 13 | CurrentTime: { 14 | type: "string", 15 | }, 16 | ExpiredTime: { 17 | type: "string", 18 | }, 19 | SessionToken: { 20 | type: "string", 21 | }, 22 | }, 23 | required: ["AccessKeyId", "SecretAccessKey", "CurrentTime", "ExpiredTime", "SessionToken"], 24 | }); 25 | -------------------------------------------------------------------------------- /test/schema/response.js: -------------------------------------------------------------------------------- 1 | import Ajv from "ajv"; 2 | import merge from "lodash.merge"; 3 | const ajv = new Ajv(); 4 | 5 | const responseErrorSchema = { 6 | additionalProperties: true, 7 | properties: { 8 | ResponseMetadata: { 9 | additionalProperties: true, 10 | properties: { 11 | RequestId: { 12 | type: "string", 13 | }, 14 | Service: { 15 | type: "string", 16 | }, 17 | Error: { 18 | properties: { 19 | Code: { 20 | type: "string", 21 | }, 22 | Message: { 23 | type: "string", 24 | }, 25 | CodeN: { 26 | type: "number", 27 | }, 28 | }, 29 | type: "object", 30 | }, 31 | }, 32 | type: "object", 33 | required: ["RequestId", "Service"], 34 | }, 35 | }, 36 | required: ["ResponseMetadata"], 37 | type: "object", 38 | }; 39 | export const responseErrorSchemaValidate = ajv.compile(responseErrorSchema); 40 | export const reponseSchema = { 41 | type: "object", 42 | properties: { 43 | ResponseMetadata: { 44 | type: "object", 45 | properties: { 46 | RequestId: { 47 | type: "string", 48 | }, 49 | Service: { 50 | type: "string", 51 | }, 52 | }, 53 | required: ["RequestId", "Service"], 54 | }, 55 | Result: { 56 | type: "object", 57 | }, 58 | }, 59 | required: ["ResponseMetadata"], 60 | }; 61 | export function createResponseSchema(resultSchema) { 62 | return merge({}, reponseSchema, { 63 | type: "object", 64 | properties: { 65 | Result: resultSchema, 66 | }, 67 | required: ["ResponseMetadata", "Result"], 68 | }); 69 | } 70 | 71 | export const reponseSchemaValidate = ajv.compile(reponseSchema); 72 | -------------------------------------------------------------------------------- /test/schema/rtc.js: -------------------------------------------------------------------------------- 1 | import Ajv from "ajv"; 2 | import { createResponseSchema } from "./response"; 3 | const ajv = new Ajv(); 4 | 5 | export const ListRoomsReponseSchemaValidate = ajv.compile( 6 | createResponseSchema({ 7 | type: "object", 8 | properties: { 9 | Total: { 10 | type: "number", 11 | }, 12 | ActiveNum: { 13 | type: "number", 14 | }, 15 | InactiveNum: { 16 | type: "number", 17 | }, 18 | Offset: { 19 | type: "number", 20 | }, 21 | Limit: { 22 | type: "number", 23 | }, 24 | Rooms: { 25 | type: "array", 26 | items: { 27 | type: "object", 28 | properties: { 29 | RoomId: { 30 | type: "string", 31 | }, 32 | AppId: { 33 | type: "string", 34 | }, 35 | UserNum: { 36 | type: "number", 37 | }, 38 | StreamNum: { 39 | type: "number", 40 | }, 41 | State: { 42 | type: "number", 43 | }, 44 | CreatedAt: { 45 | type: "string", 46 | }, 47 | UpdatedAt: { 48 | type: "string", 49 | }, 50 | }, 51 | }, 52 | }, 53 | }, 54 | required: ["Total", "ActiveNum", "InactiveNum", "Offset", "Limit", "Rooms"], 55 | }) 56 | ); 57 | 58 | export const ListIndicatorsReponseSchemaValidate = ajv.compile( 59 | createResponseSchema({ 60 | type: "object", 61 | properties: { 62 | Indicators: { 63 | type: "array", 64 | items: { 65 | type: "object", 66 | properties: { 67 | Name: { 68 | type: "string", 69 | }, 70 | Unit: { 71 | type: "string", 72 | }, 73 | Data: { 74 | type: "array", 75 | items: { 76 | type: "object", 77 | properties: { 78 | TimeStamp: { 79 | type: "string", 80 | }, 81 | Value: { 82 | type: "number", 83 | }, 84 | }, 85 | }, 86 | }, 87 | }, 88 | }, 89 | }, 90 | }, 91 | required: ["Indicators"], 92 | }) 93 | ); 94 | 95 | export const StartRecordParamsSchemaValidate = ajv.compile( 96 | createResponseSchema({ 97 | type: "string", 98 | }) 99 | ); 100 | export const StopRecordParamsSchemaValidate = ajv.compile( 101 | createResponseSchema({ 102 | type: "string", 103 | }) 104 | ); 105 | 106 | export const GetRecordTaskParamsSchemaValidate = ajv.compile( 107 | createResponseSchema({ 108 | type: "object", 109 | properties: { 110 | StartTime: { 111 | type: "number", 112 | }, 113 | EndTime: { 114 | type: "number", 115 | }, 116 | Status: { 117 | type: "number", 118 | }, 119 | StopReason: { 120 | type: "string", 121 | }, 122 | RecordFileList: { 123 | type: "array", 124 | items: { 125 | type: "object", 126 | properties: { 127 | Vid: { 128 | type: "string", 129 | }, 130 | Duration: { 131 | type: "number", 132 | }, 133 | Size: { 134 | type: "number", 135 | }, 136 | StreamList: { 137 | type: "array", 138 | items: { 139 | type: "object", 140 | properties: { 141 | UserId: { 142 | type: "string", 143 | }, 144 | StreamType: { 145 | type: "number", 146 | }, 147 | } 148 | } 149 | }, 150 | }, 151 | }, 152 | }, 153 | }, 154 | required: ["StartTime", "EndTime", "Status", "StopReason", "RecordFileList"], 155 | }) 156 | ); -------------------------------------------------------------------------------- /test/schema/sms.js: -------------------------------------------------------------------------------- 1 | import Ajv from "ajv"; 2 | import { createResponseSchema } from "./response"; 3 | const ajv = new Ajv(); 4 | 5 | export const SendSmsResponseSchemaValidate = ajv.compile( 6 | createResponseSchema({ 7 | type: "object", 8 | properties: { 9 | ResponseMetadata: { 10 | type: "object", 11 | properties: { 12 | RequestId: { 13 | type: "string", 14 | }, 15 | Service: { 16 | type: "string", 17 | }, 18 | Region: { 19 | type: "string", 20 | }, 21 | Action: { 22 | type: "string", 23 | }, 24 | Version: { 25 | type: "string", 26 | }, 27 | Error: { 28 | type: "object", 29 | properties: { 30 | CodeN: { 31 | type: "number", 32 | }, 33 | Code: { 34 | type: "string", 35 | }, 36 | Message: { 37 | type: "string", 38 | }, 39 | }, 40 | required: ["Code", "Message"], 41 | }, 42 | }, 43 | required: ["RequestId", "Service", "Region", "Action", "Version"], 44 | }, 45 | Result: { 46 | type: "array", 47 | properties: { 48 | MessageID: { 49 | type: "string", 50 | }, 51 | }, 52 | required: ["MessageID"], 53 | }, 54 | }, 55 | required: ["ResponseMetadata", "Result"], 56 | }) 57 | ); 58 | -------------------------------------------------------------------------------- /test/schema/vod/index.js: -------------------------------------------------------------------------------- 1 | import Ajv from "ajv"; 2 | import { createResponseSchema } from "../response"; 3 | import { jsonSchema } from "./schema"; 4 | 5 | const ajv = new Ajv(); 6 | const suffix = "SchemaValidate"; 7 | 8 | // 修改媒资信息 VodUpdateMediaInfoRequest 9 | // 修改媒资发布状态 VodUpdateMediaPublishStatusRequest 10 | // 修改字幕信息 VodUpdateSubtitleInfoRequest 11 | // 上述 3 个接口的响应无 Result 字段 12 | const genSchemaValidateFunc = () => { 13 | const res = {}; 14 | Object.keys(jsonSchema).forEach((key) => { 15 | // 过滤掉请求类型 16 | if (!key.includes("Request")) { 17 | res[key + suffix] = ajv.compile(createResponseSchema(jsonSchema[key])); 18 | } 19 | }); 20 | return res; 21 | }; 22 | 23 | export const allSchemaValidateFuncs = genSchemaValidateFunc(); 24 | -------------------------------------------------------------------------------- /test/service.test.js: -------------------------------------------------------------------------------- 1 | import Service from "../lib/base/service"; 2 | import { reponseSchemaValidate } from "./schema/response"; 3 | import _get from "lodash.get"; 4 | 5 | const defaultConfig = { 6 | serviceName: "iam", 7 | defaultVersion: "2018-01-01", 8 | }; 9 | const iamService = new Service(defaultConfig); 10 | 11 | test("get open api", async () => { 12 | const response = await iamService.createAPI("ListUsers", { 13 | method: "GET", 14 | })({ 15 | Limit: 5, 16 | }); 17 | const validateResult = reponseSchemaValidate(response); 18 | expect(validateResult).toBe(true); 19 | expect(_get(response, "ResponseMetadata.Error")).toBe(undefined); 20 | expect(_get(response, "Result.Limit")).toBe(5); 21 | }); 22 | test("post json open api", async () => { 23 | const response = await iamService.createAPI("ListUsers", { 24 | method: "POST", 25 | contentType: "json", 26 | })({ 27 | Limit: 5, 28 | }); 29 | const validateResult = reponseSchemaValidate(response); 30 | expect(validateResult).toBe(true); 31 | expect(_get(response, "ResponseMetadata.Error")).toBe(undefined); 32 | }); 33 | 34 | test("post urlencode open api", async () => { 35 | const response = await iamService.createAPI("ListUsers", { 36 | method: "POST", 37 | contentType: "urlencode", 38 | })({ 39 | Limit: 5, 40 | }); 41 | const validateResult = reponseSchemaValidate(response); 42 | expect(validateResult).toBe(true); 43 | expect(_get(response, "ResponseMetadata.Error")).toBe(undefined); 44 | }); 45 | 46 | test("post form-data open api", async () => { 47 | const response = await iamService.createAPI("ListUsers", { 48 | method: "POST", 49 | contentType: "form-data", 50 | })({ 51 | Limit: 5, 52 | }); 53 | const validateResult = reponseSchemaValidate(response); 54 | expect(validateResult).toBe(true); 55 | expect(_get(response, "ResponseMetadata.Error")).toBe(undefined); 56 | }); 57 | 58 | test("default params check without accessKeyId", async () => { 59 | const service = new Service({ 60 | serviceName: "iam", 61 | }); 62 | service.setAccessKeyId(""); 63 | service.setSecretKey(""); 64 | let error; 65 | try { 66 | await service.fetchOpenAPI({ 67 | Action: "ListUsers", 68 | Version: "2018-01-01", 69 | }); 70 | } catch (e) { 71 | error = e; 72 | } 73 | expect(error).toBeInstanceOf(Error); 74 | }); 75 | -------------------------------------------------------------------------------- /test/sign.test.ts: -------------------------------------------------------------------------------- 1 | import Signer from "../src/base/sign"; 2 | import { RequestObj, Credentials } from "../src/base/types"; 3 | const { VOLC_ACCESSKEY = "", VOLC_SECRETKEY = "", TEST_SIGNER = "" } = process.env; 4 | 5 | if (TEST_SIGNER) { 6 | const date = new Date(1662609419724); 7 | describe("getSignUrl", () => { 8 | const caseTable: { 9 | name: string; 10 | requestObj: RequestObj; 11 | serviceName: string; 12 | credentials: Credentials; 13 | expected: string; 14 | }[] = [ 15 | { 16 | name: "result", 17 | requestObj: { 18 | method: "POST", 19 | region: "cn-north-1", 20 | params: { 21 | Action: "AssumeRole", 22 | Version: "2018-01-01", 23 | RoleTrn: "trn:iam::2000001050:role/STSRole", 24 | RoleSessionName: "test", 25 | }, 26 | }, 27 | serviceName: "sts", 28 | credentials: { 29 | accessKeyId: VOLC_ACCESSKEY, 30 | secretKey: VOLC_SECRETKEY, 31 | }, 32 | expected: `Action=AssumeRole&RoleSessionName=test&RoleTrn=trn%3Aiam%3A%3A2000001050%3Arole%2FSTSRole&Version=2018-01-01&X-Algorithm=HMAC-SHA256&X-Credential=akfsrq251-9xaf44f-xxaff-fadbaa%2F20220908%2Fcn-north-1%2Fsts%2Frequest&X-Date=20220908T035659Z&X-NotSignBody=&X-SignedHeaders=&X-SignedQueries=Action%3BRoleSessionName%3BRoleTrn%3BVersion%3BX-Algorithm%3BX-Credential%3BX-Date%3BX-NotSignBody%3BX-SignedHeaders&X-Signature=`, 33 | }, 34 | ]; 35 | 36 | for (const c of caseTable) { 37 | it(c.name, function () { 38 | const signer = new Signer(c.requestObj, c.serviceName); 39 | const queryString = signer.getSignUrl(c.credentials, date); 40 | const queryStrWithoutSig = queryString.replace(/X-Signature=[^&]+/, "X-Signature="); 41 | expect(queryStrWithoutSig).toEqual(c.expected); 42 | }); 43 | } 44 | }); 45 | } 46 | -------------------------------------------------------------------------------- /test/sms.test.js: -------------------------------------------------------------------------------- 1 | import { sms } from "../lib"; 2 | import { SendSmsResponseSchemaValidate } from "./schema/sms"; 3 | 4 | const accessKey = "xxx"; 5 | const secretKey = "xxx"; 6 | 7 | test("sms:Send", async () => { 8 | const smsService = sms.defaultService; 9 | smsService.setAccessKeyId(accessKey); 10 | smsService.setSecretKey(secretKey); 11 | const response = await smsService.Send({ 12 | SmsAccount: "7384ed01", 13 | Sign: "xxxx", 14 | TemplateID: "SPT_1baef3f6", 15 | PhoneNumbers: "186110xxxx", 16 | TemplateParam: JSON.stringify({ content: "Hello World" }), 17 | Tag: "tag", 18 | }); 19 | const validateResult = SendSmsResponseSchemaValidate(response); 20 | expect(validateResult).toBe(true); 21 | }); 22 | 23 | test("sms:BatchSend", async () => { 24 | const smsService = sms.defaultService; 25 | smsService.setAccessKeyId(accessKey); 26 | smsService.setSecretKey(secretKey); 27 | const response = await smsService.BatchSend({ 28 | SmsAccount: "7384ed01", 29 | Sign: "xxxx", 30 | TemplateID: "SPT_1baef3f6", 31 | Tag: "tag", 32 | Messages: [ 33 | { 34 | PhoneNumber: "186110xxx", 35 | TemplateParam: JSON.stringify({ content: "Hello World" }), 36 | }, 37 | ], 38 | }); 39 | const validateResult = SendSmsResponseSchemaValidate(response); 40 | expect(validateResult).toBe(true); 41 | }); 42 | -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "baseUrl": ".", 4 | "outDir": "lib", 5 | "module": "commonjs", 6 | "target": "es2017", 7 | "lib": ["es6", "dom", "es2017"], 8 | "sourceMap": true, 9 | "allowJs": false, 10 | "moduleResolution": "node", 11 | "rootDir": "src", 12 | "forceConsistentCasingInFileNames": true, 13 | "noImplicitReturns": true, 14 | "noImplicitThis": true, 15 | "noImplicitAny": false, 16 | "strictNullChecks": true, 17 | "suppressImplicitAnyIndexErrors": true, 18 | "noUnusedLocals": true, 19 | "importHelpers": false, 20 | "esModuleInterop": true, 21 | "declaration": true, 22 | "downlevelIteration": true, 23 | "resolveJsonModule": false, 24 | "types": ["jest", "node"] 25 | }, 26 | "include": [ 27 | "src/**/*" 28 | ], 29 | "exclude": ["node_modules", "lib", "test", "**/demo.ts"] 30 | } 31 | --------------------------------------------------------------------------------