New Research: Supply Chain Attack on Axios Pulls Malicious Dependency from npm.Details
Socket
Book a DemoSign in
Socket

@cloudbase/cloud-api

Package Overview
Dependencies
Maintainers
11
Versions
41
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@cloudbase/cloud-api - npm Package Compare versions

Comparing version
0.3.1
to
0.3.2
+2
-2
.eslintrc.js
module.exports = {
extends: ['alloy', 'alloy/typescript'],
rules: {
semi: ['error'],
indent: ['error', 4],
semi: ['error', 'never'],
complexity: ['error', { max: 40 }],

@@ -26,2 +26,2 @@ 'no-useless-constructor': 'off',

]
}
};

@@ -8,4 +8,3 @@ module.exports = {

useTabs: false,
// 行尾需要有分号
semi: false,
semi: true,
// 使用单引号

@@ -30,2 +29,2 @@ singleQuote: true,

endOfLine: 'lf'
}
};

@@ -17,2 +17,2 @@ module.exports = {

coverageReporters: ['json', 'lcov', 'clover', 'text-summary']
}
};

@@ -111,4 +111,19 @@ "use strict";

}
async request(action, data = {}, method = 'POST') {
async request(actionOrOptions, assignData = {}, assignMethod = 'POST') {
var _a;
let action;
let data;
let method;
let region;
if (typeof actionOrOptions === 'string') {
action = actionOrOptions;
data = assignData;
method = assignMethod;
}
else {
action = actionOrOptions === null || actionOrOptions === void 0 ? void 0 : actionOrOptions.action;
data = (actionOrOptions === null || actionOrOptions === void 0 ? void 0 : actionOrOptions.data) || {};
method = (actionOrOptions === null || actionOrOptions === void 0 ? void 0 : actionOrOptions.method) || 'POST';
region = actionOrOptions === null || actionOrOptions === void 0 ? void 0 : actionOrOptions.region;
}
this.action = action;

@@ -132,3 +147,3 @@ this.data = deepRemoveVoid(Object.assign(Object.assign({}, data), this.baseParams));

try {
const data = await this.requestWithSign();
const data = await this.requestWithSign(region);
if (data.Response.Error) {

@@ -160,3 +175,3 @@ const tcError = new error_1.CloudBaseError(data.Response.Error.Message, {

}
async requestWithSign() {
async requestWithSign(region) {
const timestamp = Math.floor(Date.now() / 1000);

@@ -183,3 +198,3 @@ const { method, timeout, data } = this;

'X-TC-Action': this.action,
'X-TC-Region': this.region,
'X-TC-Region': region || this.region,
'X-TC-Timestamp': timestamp,

@@ -186,0 +201,0 @@ 'X-TC-Version': this.version

{
"name": "@cloudbase/cloud-api",
"version": "0.3.1",
"version": "0.3.2",
"description": "The cloud api request package.",

@@ -5,0 +5,0 @@ "main": "lib/index.js",

interface Options {
exit?: number
original?: Error | undefined
code?: string | number
requestId?: string
action?: string
type?: string
exit?: number;
original?: Error | undefined;
code?: string | number;
requestId?: string;
action?: string;
type?: string;
}
export class CloudBaseError extends Error {
readonly exit: number
readonly message: string
readonly name = 'CloudBaseError'
readonly original: Error | undefined
readonly code: string | number
readonly requestId: string
readonly action: string
readonly type: string
readonly exit: number;
readonly message: string;
readonly name = 'CloudBaseError';
readonly original: Error | undefined;
readonly code: string | number;
readonly requestId: string;
readonly action: string;
readonly type: string;
constructor(message: string, options: Options = {}) {
super()
const { code = '', action = '', original = null, requestId = '', type } = options
this.message = `[${action}]\nRequestId:${requestId}\n${message}`
this.original = original
this.code = code
this.requestId = requestId
this.action = action
this.type = type
super();
const { code = '', action = '', original = null, requestId = '', type } = options;
this.message = `[${action}]\nRequestId:${requestId}\n${message}`;
this.original = original;
this.code = code;
this.requestId = requestId;
this.action = action;
this.type = type;
}
}
+141
-141

@@ -1,10 +0,10 @@

import crypto from 'crypto'
import { URL } from 'url'
import QueryString from 'query-string'
import crypto from 'crypto';
import { URL } from 'url';
import QueryString from 'query-string';
import { fetch as _fetch, fetchStream as _fetchStream, nodeFetch as _nodeFetch } from './request'
import { CloudBaseError } from './error'
import { fetch as _fetch, fetchStream as _fetchStream, nodeFetch as _nodeFetch } from './request';
import { CloudBaseError } from './error';
function isObject(x) {
return typeof x === 'object' && !Array.isArray(x) && x !== null
return typeof x === 'object' && !Array.isArray(x) && x !== null;
}

@@ -15,38 +15,38 @@

if (Array.isArray(obj)) {
return obj.map(deepRemoveVoid)
return obj.map(deepRemoveVoid);
} else if (isObject(obj)) {
let result = {}
let result = {};
for (const key in obj) {
if (Object.prototype.hasOwnProperty.call(obj, key)) {
const value = obj[key]
const value = obj[key];
if (typeof value !== 'undefined' && value !== null) {
result[key] = deepRemoveVoid(value)
result[key] = deepRemoveVoid(value);
}
}
}
return result
return result;
} else {
return obj
return obj;
}
}
type HexBase64Latin1Encoding = 'latin1' | 'hex' | 'base64'
type HexBase64Latin1Encoding = 'latin1' | 'hex' | 'base64';
function sha256(message: string, secret: string, encoding?: HexBase64Latin1Encoding) {
const hmac = crypto.createHmac('sha256', secret)
return hmac.update(message).digest(encoding)
const hmac = crypto.createHmac('sha256', secret);
return hmac.update(message).digest(encoding);
}
function getHash(message: string): string {
const hash = crypto.createHash('sha256')
return hash.update(message).digest('hex')
const hash = crypto.createHash('sha256');
return hash.update(message).digest('hex');
}
function getDate(timestamp: number): string {
const date = new Date(timestamp * 1000)
const year = date.getUTCFullYear()
const month = ('0' + (date.getUTCMonth() + 1)).slice(-2)
const date = new Date(timestamp * 1000);
const year = date.getUTCFullYear();
const month = ('0' + (date.getUTCMonth() + 1)).slice(-2);
// UTC 日期,非本地时间
const day = ('0' + date.getUTCDate()).slice(-2)
return `${year}-${month}-${day}`
const day = ('0' + date.getUTCDate()).slice(-2);
return `${year}-${month}-${day}`;
}

@@ -61,69 +61,69 @@

ssl: '2019-12-05'
}
};
export interface ServiceOptions {
service: string
version?: string
proxy?: string
timeout?: number
region?: string
baseParams?: Record<string, any>
credential?: Credential
getCredential?: () => Promise<Credential> | Credential
service: string;
version?: string;
proxy?: string;
timeout?: number;
region?: string;
baseParams?: Record<string, any>;
credential?: Credential;
getCredential?: () => Promise<Credential> | Credential;
}
export interface Credential {
secretId: string
secretKey: string
token?: string
secretId: string;
secretKey: string;
token?: string;
}
export interface RequestOptions {
action: string
data?: Record<string, any>
method?: 'POST' | 'GET'
region?: string
action: string;
data?: Record<string, any>;
method?: 'POST' | 'GET';
region?: string;
}
export const fetch = _fetch
export const fetchStream = _fetchStream
export const nodeFetch = _nodeFetch
export const fetch = _fetch;
export const fetchStream = _fetchStream;
export const nodeFetch = _nodeFetch;
export class CloudApiService {
// 缓存请求实例
static serviceCacheMap: Record<string, CloudApiService> = {}
static serviceCacheMap: Record<string, CloudApiService> = {};
static getInstance(options: ServiceOptions) {
const { service } = options
const { service } = options;
if (CloudApiService.serviceCacheMap?.[service]) {
return CloudApiService.serviceCacheMap[service]
return CloudApiService.serviceCacheMap[service];
}
const apiService = new CloudApiService(options)
const apiService = new CloudApiService(options);
// 预防 serviceCacheMap 被置空导致的错误
CloudApiService.serviceCacheMap = {
...CloudApiService.serviceCacheMap
}
CloudApiService.serviceCacheMap[service] = apiService
return apiService
};
CloudApiService.serviceCacheMap[service] = apiService;
return apiService;
}
service: string
version: string
proxy: string
timeout: number
region: string
credential: Credential
baseParams: Record<string, any>
getCredential: () => Promise<Credential> | Credential
service: string;
version: string;
proxy: string;
timeout: number;
region: string;
credential: Credential;
baseParams: Record<string, any>;
getCredential: () => Promise<Credential> | Credential;
url: string
host: string
action: string
method: 'POST' | 'GET'
data: Record<string, any>
payload: Record<string, any>
url: string;
host: string;
action: string;
method: 'POST' | 'GET';
data: Record<string, any>;
payload: Record<string, any>;
constructor(options: ServiceOptions) {
if (!options) {
throw new CloudBaseError('Options cloud not be empty!')
throw new CloudBaseError('Options cloud not be empty!');
}

@@ -139,23 +139,23 @@ const {

timeout = 60000
} = options
} = options;
this.service = service
this.timeout = timeout
this.service = service;
this.timeout = timeout;
if (this.service === 'tcb' && process.env.CLOUDBASE_TCB_CLOUDAPI_PROXY) {
this.proxy = process.env.CLOUDBASE_TCB_CLOUDAPI_PROXY
this.proxy = process.env.CLOUDBASE_TCB_CLOUDAPI_PROXY;
} else {
this.proxy = proxy
this.proxy = proxy;
}
if (this.service === 'tcb' && process.env.CLOUDBASE_TCB_CLOUDAPI_REGION) {
this.region = process.env.CLOUDBASE_TCB_CLOUDAPI_REGION
this.region = process.env.CLOUDBASE_TCB_CLOUDAPI_REGION;
} else {
this.region = region || process.env.TENCENTCLOUD_REGION || 'ap-shanghai'
this.region = region || process.env.TENCENTCLOUD_REGION || 'ap-shanghai';
}
this.credential = credential
this.baseParams = baseParams || {}
this.getCredential = getCredential
this.version = ServiceVersionMap[service] || version
this.credential = credential;
this.baseParams = baseParams || {};
this.getCredential = getCredential;
this.version = ServiceVersionMap[service] || version;
}

@@ -167,12 +167,12 @@

flexdb: 'https://flexdb.tencentcloudapi.com'
}
};
if (this.service === 'tcb' && process.env.CLOUDBASE_TCB_CLOUDAPI_HOST) {
return `http://${process.env.CLOUDBASE_TCB_CLOUDAPI_HOST}`
return `http://${process.env.CLOUDBASE_TCB_CLOUDAPI_HOST}`;
}
if (urlMap[this.service]) {
return urlMap[this.service]
return urlMap[this.service];
} else {
return `https://${this.service}.tencentcloudapi.com`
return `https://${this.service}.tencentcloudapi.com`;
}

@@ -182,4 +182,4 @@ }

// overload
async request(options: RequestOptions)
async request(action: string, data?: Record<string, any>, method?: 'POST' | 'GET')
async request(options: RequestOptions);
async request(action: string, data?: Record<string, any>, method?: 'POST' | 'GET');

@@ -192,42 +192,42 @@ async request(

// 增加 region 参数,兼容之前的入参形式
let action
let data
let method
let region
let action;
let data;
let method;
let region;
if (typeof actionOrOptions === 'string') {
action = actionOrOptions
data = assignData
method = assignMethod
action = actionOrOptions;
data = assignData;
method = assignMethod;
} else {
action = actionOrOptions?.action
data = actionOrOptions?.data || {}
method = actionOrOptions?.method || 'POST'
region = actionOrOptions?.region
action = actionOrOptions?.action;
data = actionOrOptions?.data || {};
method = actionOrOptions?.method || 'POST';
region = actionOrOptions?.region;
}
this.action = action
this.data = deepRemoveVoid({ ...data, ...this.baseParams })
this.method = method
this.action = action;
this.data = deepRemoveVoid({ ...data, ...this.baseParams });
this.method = method;
this.url = this.baseUrl
this.url = this.baseUrl;
if (!this.credential?.secretId) {
if (!this.getCredential) {
throw new CloudBaseError('You must provide credential info!')
throw new CloudBaseError('You must provide credential info!');
}
if (typeof this.getCredential !== 'function') {
throw new CloudBaseError('The getCredential option must be a function!')
throw new CloudBaseError('The getCredential option must be a function!');
}
const credential = await this.getCredential()
const credential = await this.getCredential();
if (!credential) {
throw new CloudBaseError('Calling getCredential function get no credential info!')
throw new CloudBaseError('Calling getCredential function get no credential info!');
}
this.credential = credential
this.credential = credential;
}
try {
const data: Record<string, any> = await this.requestWithSign(region)
const data: Record<string, any> = await this.requestWithSign(region);

@@ -240,6 +240,6 @@ if (data.Response.Error) {

original: data.Response.Error
})
throw tcError
});
throw tcError;
} else {
return data.Response
return data.Response;
}

@@ -249,3 +249,3 @@ } catch (e) {

if (e.name === 'CloudBaseError') {
throw e
throw e;
} else {

@@ -256,3 +256,3 @@ throw new CloudBaseError(e.message, {

type: e.type
})
});
}

@@ -266,20 +266,20 @@ }

// await convertReadStreamToBuffer(data)
const timestamp = Math.floor(Date.now() / 1000)
const timestamp = Math.floor(Date.now() / 1000);
const { method, timeout, data } = this
const { method, timeout, data } = this;
if (method === 'GET') {
this.url += '?' + QueryString.stringify(data)
this.url += '?' + QueryString.stringify(data);
}
if (method === 'POST') {
this.payload = data
this.payload = data;
}
const { CLOUDBASE_TCB_CLOUDAPI_HOST } = process.env
const { CLOUDBASE_TCB_CLOUDAPI_HOST } = process.env;
if (this.service === 'tcb' && CLOUDBASE_TCB_CLOUDAPI_HOST) {
this.host = CLOUDBASE_TCB_CLOUDAPI_HOST
this.host = CLOUDBASE_TCB_CLOUDAPI_HOST;
} else {
this.host = new URL(this.url).host
this.host = new URL(this.url).host;
}

@@ -297,65 +297,65 @@

}
}
};
if (this.credential.token) {
config.headers['X-TC-Token'] = this.credential.token
config.headers['X-TC-Token'] = this.credential.token;
}
if (method === 'GET') {
config.headers['Content-Type'] = 'application/x-www-form-urlencoded'
config.headers['Content-Type'] = 'application/x-www-form-urlencoded';
}
if (method === 'POST') {
config.body = JSON.stringify(data)
config.headers['Content-Type'] = 'application/json'
config.body = JSON.stringify(data);
config.headers['Content-Type'] = 'application/json';
}
const sign = this.getRequestSign(timestamp)
const sign = this.getRequestSign(timestamp);
config.headers['Authorization'] = sign
config.headers['Authorization'] = sign;
return fetch(this.url, config, this.proxy)
return fetch(this.url, config, this.proxy);
}
getRequestSign(timestamp: number) {
const { method, url, service } = this
const { secretId, secretKey } = this.credential
const urlObj = new URL(url)
const { method, url, service } = this;
const { secretId, secretKey } = this.credential;
const urlObj = new URL(url);
// 通用头部
let headers = ''
const signedHeaders = 'content-type;host'
let headers = '';
const signedHeaders = 'content-type;host';
if (method === 'GET') {
headers = 'content-type:application/x-www-form-urlencoded\n'
headers = 'content-type:application/x-www-form-urlencoded\n';
}
if (method === 'POST') {
headers = 'content-type:application/json\n'
headers = 'content-type:application/json\n';
}
headers += `host:${this.host}\n`
headers += `host:${this.host}\n`;
const path = urlObj.pathname
const querystring = urlObj.search.slice(1)
const path = urlObj.pathname;
const querystring = urlObj.search.slice(1);
const payloadHash = this.payload ? getHash(JSON.stringify(this.payload)) : getHash('')
const payloadHash = this.payload ? getHash(JSON.stringify(this.payload)) : getHash('');
const canonicalRequest = `${method}\n${path}\n${querystring}\n${headers}\n${signedHeaders}\n${payloadHash}`
const canonicalRequest = `${method}\n${path}\n${querystring}\n${headers}\n${signedHeaders}\n${payloadHash}`;
const date = getDate(timestamp)
const date = getDate(timestamp);
const StringToSign = `TC3-HMAC-SHA256\n${timestamp}\n${date}/${service}/tc3_request\n${getHash(
canonicalRequest
)}`
)}`;
const kDate = sha256(date, `TC3${secretKey}`)
const kService = sha256(service, kDate)
const kSigning = sha256('tc3_request', kService)
const signature = sha256(StringToSign, kSigning, 'hex')
const kDate = sha256(date, `TC3${secretKey}`);
const kService = sha256(service, kDate);
const kSigning = sha256('tc3_request', kService);
const signature = sha256(StringToSign, kSigning, 'hex');
return `TC3-HMAC-SHA256 Credential=${secretId}/${date}/${service}/tc3_request, SignedHeaders=${signedHeaders}, Signature=${signature}`
return `TC3-HMAC-SHA256 Credential=${secretId}/${date}/${service}/tc3_request, SignedHeaders=${signedHeaders}, Signature=${signature}`;
}
clearCredentialCache() {
this.credential = null
this.credential = null;
}
}

@@ -1,6 +0,6 @@

import { URL } from 'url'
import _fetch, { RequestInit } from 'node-fetch'
import HttpsProxyAgent from 'https-proxy-agent'
import { URL } from 'url';
import _fetch, { RequestInit } from 'node-fetch';
import HttpsProxyAgent from 'https-proxy-agent';
export const nodeFetch = _fetch
export const nodeFetch = _fetch;

@@ -10,10 +10,10 @@ // 使用 fetch + 代理

if (proxy) {
config.agent = HttpsProxyAgent(proxy)
config.agent = HttpsProxyAgent(proxy);
}
// 解决中文编码问题
const escapeUrl = new URL(url).toString()
const escapeUrl = new URL(url).toString();
const res = await _fetch(escapeUrl, config)
return res.json()
const res = await _fetch(escapeUrl, config);
return res.json();
}

@@ -23,8 +23,8 @@

if (proxy) {
config.agent = HttpsProxyAgent(proxy)
config.agent = HttpsProxyAgent(proxy);
}
const escapeUrl = new URL(url).toString()
const escapeUrl = new URL(url).toString();
return _fetch(escapeUrl, config)
return _fetch(escapeUrl, config);
}

@@ -17,2 +17,8 @@ import { fetch as _fetch, fetchStream as _fetchStream } from './request';

}
export interface RequestOptions {
action: string;
data?: Record<string, any>;
method?: 'POST' | 'GET';
region?: string;
}
export declare const fetch: typeof _fetch;

@@ -40,6 +46,7 @@ export declare const fetchStream: typeof _fetchStream;

get baseUrl(): any;
request(action: string, data?: Record<string, any>, method?: 'POST' | 'GET'): Promise<any>;
requestWithSign(): Promise<any>;
request(options: RequestOptions): any;
request(action: string, data?: Record<string, any>, method?: 'POST' | 'GET'): any;
requestWithSign(region: any): Promise<any>;
getRequestSign(timestamp: number): string;
clearCredentialCache(): void;
}