@cloudbase/utilities 2.5.7-beta.0 → 2.5.20-beta.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.eslintignore +2 -0
- package/.eslintrc.js +15 -0
- package/dist/{adapters → cjs/adapters}/index.js +1 -1
- package/dist/cjs/adapters/platforms/web.js +213 -0
- package/dist/cjs/constants/common.js +24 -0
- package/dist/cjs/constants/errors.js +12 -0
- package/dist/{constants → cjs/constants}/index.js +1 -1
- package/dist/cjs/helpers/decorators.js +238 -0
- package/dist/{helpers → cjs/helpers}/index.js +1 -1
- package/dist/{index.js → cjs/index.js} +1 -1
- package/dist/cjs/libs/cache.js +259 -0
- package/dist/cjs/libs/events.js +104 -0
- package/dist/cjs/libs/util.js +221 -0
- package/dist/esm/adapters/index.d.ts +13 -0
- package/dist/esm/adapters/index.js +27 -0
- package/dist/esm/adapters/platforms/web.d.ts +15 -0
- package/dist/esm/adapters/platforms/web.js +209 -0
- package/dist/esm/constants/common.d.ts +6 -0
- package/dist/esm/constants/common.js +17 -0
- package/dist/esm/constants/errors.d.ts +8 -0
- package/dist/esm/constants/errors.js +9 -0
- package/dist/esm/constants/index.d.ts +3 -0
- package/dist/esm/constants/index.js +4 -0
- package/dist/esm/helpers/decorators.d.ts +11 -0
- package/dist/esm/helpers/decorators.js +234 -0
- package/dist/esm/helpers/index.d.ts +1 -0
- package/dist/esm/helpers/index.js +2 -0
- package/dist/esm/index.d.ts +11 -0
- package/dist/esm/index.js +12 -0
- package/dist/esm/libs/cache.d.ts +17 -0
- package/dist/esm/libs/cache.js +256 -0
- package/dist/esm/libs/events.d.ts +27 -0
- package/dist/esm/libs/events.js +98 -0
- package/dist/esm/libs/util.d.ts +35 -0
- package/dist/esm/libs/util.js +194 -0
- package/package.json +6 -16
- package/src/adapters/index.ts +28 -0
- package/src/adapters/platforms/web.ts +182 -0
- package/src/constants/common.ts +21 -0
- package/src/constants/errors.ts +8 -0
- package/src/constants/index.ts +4 -0
- package/src/global.d.ts +3 -0
- package/src/helpers/decorators.ts +228 -0
- package/src/helpers/index.ts +1 -0
- package/src/index.ts +22 -0
- package/src/libs/cache.ts +192 -0
- package/src/libs/events.ts +154 -0
- package/src/libs/util.ts +216 -0
- package/tsconfig.esm.json +16 -0
- package/tsconfig.json +21 -0
- package/dist/adapters/platforms/web.js +0 -213
- package/dist/constants/common.js +0 -24
- package/dist/constants/errors.js +0 -12
- package/dist/helpers/decorators.js +0 -238
- package/dist/libs/cache.js +0 -259
- package/dist/libs/events.js +0 -104
- package/dist/libs/util.js +0 -221
- /package/dist/{adapters → cjs/adapters}/index.d.ts +0 -0
- /package/dist/{adapters → cjs/adapters}/platforms/web.d.ts +0 -0
- /package/dist/{constants → cjs/constants}/common.d.ts +0 -0
- /package/dist/{constants → cjs/constants}/errors.d.ts +0 -0
- /package/dist/{constants → cjs/constants}/index.d.ts +0 -0
- /package/dist/{helpers → cjs/helpers}/decorators.d.ts +0 -0
- /package/dist/{helpers → cjs/helpers}/index.d.ts +0 -0
- /package/dist/{index.d.ts → cjs/index.d.ts} +0 -0
- /package/dist/{libs → cjs/libs}/cache.d.ts +0 -0
- /package/dist/{libs → cjs/libs}/events.d.ts +0 -0
- /package/dist/{libs → cjs/libs}/util.d.ts +0 -0
package/src/global.d.ts
ADDED
|
@@ -0,0 +1,228 @@
|
|
|
1
|
+
import { printGroupLog } from '../libs/util'
|
|
2
|
+
import { IS_DEBUG_MODE } from '../constants'
|
|
3
|
+
|
|
4
|
+
interface ICatchErrorsDecoratorOptions {
|
|
5
|
+
mode?: 'sync' | 'async';
|
|
6
|
+
customInfo?: {
|
|
7
|
+
className?: string;
|
|
8
|
+
methodName?: string;
|
|
9
|
+
};
|
|
10
|
+
title?: string;
|
|
11
|
+
messages?: string[];
|
|
12
|
+
}
|
|
13
|
+
// firefox的stack格式与chrome不同
|
|
14
|
+
let isFirefox = false
|
|
15
|
+
if (typeof navigator !== 'undefined' && navigator.userAgent) {
|
|
16
|
+
isFirefox = navigator.userAgent.indexOf('Firefox') !== -1
|
|
17
|
+
}
|
|
18
|
+
/**
|
|
19
|
+
* decorate在stack中一般都特定的规范
|
|
20
|
+
*/
|
|
21
|
+
const REG_STACK_DECORATE = isFirefox
|
|
22
|
+
? /(\.js\/)?__decorate(\$\d+)?<@.*\d$/
|
|
23
|
+
: /(\/\w+\.js\.)?__decorate(\$\d+)?\s*\(.*\)$/
|
|
24
|
+
const REG_STACK_LINK = /https?:\/\/.+:\d*\/.*\.js:\d+:\d+/
|
|
25
|
+
/**
|
|
26
|
+
* debug模式强化日志信息
|
|
27
|
+
* @param options
|
|
28
|
+
*/
|
|
29
|
+
export function catchErrorsDecorator(options: ICatchErrorsDecoratorOptions) {
|
|
30
|
+
const { mode = 'async', customInfo = {}, title, messages = [] } = options
|
|
31
|
+
|
|
32
|
+
return function (
|
|
33
|
+
target: any,
|
|
34
|
+
methodName: string,
|
|
35
|
+
descriptor: TypedPropertyDescriptor<Function>
|
|
36
|
+
) {
|
|
37
|
+
// 生产环境禁用
|
|
38
|
+
if (!IS_DEBUG_MODE) {
|
|
39
|
+
return
|
|
40
|
+
}
|
|
41
|
+
const className = customInfo.className || target.constructor.name
|
|
42
|
+
const fnName = customInfo.methodName || methodName
|
|
43
|
+
const fn = descriptor.value
|
|
44
|
+
|
|
45
|
+
// 被decorator装饰的源码link
|
|
46
|
+
// 在descriptor.value外部此处创建的stack层次可触达源码
|
|
47
|
+
// 而descriptor.value内部有可能由于stack太深无法触达
|
|
48
|
+
const sourceLink = getSourceLink(new Error())
|
|
49
|
+
|
|
50
|
+
if (mode === 'sync') {
|
|
51
|
+
descriptor.value = function (...args: any[]) {
|
|
52
|
+
// 此处的stack作用主要是为了获取被decorator装饰的源码class和method名称
|
|
53
|
+
const innerErr: any = getRewritedError({
|
|
54
|
+
err: new Error(),
|
|
55
|
+
className,
|
|
56
|
+
methodName: fnName,
|
|
57
|
+
sourceLink,
|
|
58
|
+
})
|
|
59
|
+
try {
|
|
60
|
+
return fn.apply(this, args)
|
|
61
|
+
} catch (err) {
|
|
62
|
+
let failErr = err
|
|
63
|
+
const { message: errMsg, error, error_description: errorDescription } = err
|
|
64
|
+
const logs: any = {
|
|
65
|
+
title: title || `${className}.${fnName} failed`,
|
|
66
|
+
content: [{
|
|
67
|
+
type: 'error',
|
|
68
|
+
body: err,
|
|
69
|
+
}],
|
|
70
|
+
}
|
|
71
|
+
// 只特殊处理SDK业务逻辑抛出的错误-JSON string
|
|
72
|
+
if (errMsg && /^\{.*\}$/.test(errMsg)) {
|
|
73
|
+
const msg = JSON.parse(errMsg)
|
|
74
|
+
logs.subtitle = errMsg
|
|
75
|
+
if (msg.code) {
|
|
76
|
+
if (innerErr) {
|
|
77
|
+
innerErr.code = msg.code
|
|
78
|
+
innerErr.msg = msg.msg
|
|
79
|
+
} else {
|
|
80
|
+
err.code = msg.code
|
|
81
|
+
err.message = msg.msg
|
|
82
|
+
}
|
|
83
|
+
failErr = innerErr || err
|
|
84
|
+
logs.content = messages.map(msg => ({
|
|
85
|
+
type: 'info',
|
|
86
|
+
body: msg,
|
|
87
|
+
}))
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
// oauth 错误特殊处理
|
|
92
|
+
if (error && errorDescription) {
|
|
93
|
+
logs.subtitle = errorDescription
|
|
94
|
+
if (innerErr) {
|
|
95
|
+
innerErr.code = error
|
|
96
|
+
innerErr.msg = errorDescription
|
|
97
|
+
} else {
|
|
98
|
+
err.code = error
|
|
99
|
+
err.message = errorDescription
|
|
100
|
+
}
|
|
101
|
+
failErr = innerErr || err
|
|
102
|
+
logs.content = messages.map(msg => ({
|
|
103
|
+
type: 'info',
|
|
104
|
+
body: msg,
|
|
105
|
+
}))
|
|
106
|
+
}
|
|
107
|
+
printGroupLog(logs)
|
|
108
|
+
throw failErr
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
} else {
|
|
112
|
+
descriptor.value = async function (...args: any[]) {
|
|
113
|
+
const innerErr: any = getRewritedError({
|
|
114
|
+
err: new Error(),
|
|
115
|
+
className,
|
|
116
|
+
methodName: fnName,
|
|
117
|
+
sourceLink,
|
|
118
|
+
})
|
|
119
|
+
|
|
120
|
+
try {
|
|
121
|
+
return await fn.apply(this, args)
|
|
122
|
+
} catch (err) {
|
|
123
|
+
let failErr = err
|
|
124
|
+
const { message: errMsg, error, error_description: errorDescription } = err
|
|
125
|
+
const logs: any = {
|
|
126
|
+
title: title || `${className}.${fnName} failed`,
|
|
127
|
+
content: [{
|
|
128
|
+
type: 'error',
|
|
129
|
+
body: err,
|
|
130
|
+
}],
|
|
131
|
+
}
|
|
132
|
+
// 只特殊处理SDK业务逻辑抛出的错误-JSON string
|
|
133
|
+
if (errMsg && /^\{.*\}$/.test(errMsg)) {
|
|
134
|
+
const msg = JSON.parse(errMsg)
|
|
135
|
+
logs.subtitle = msg
|
|
136
|
+
if (msg.code) {
|
|
137
|
+
if (innerErr) {
|
|
138
|
+
innerErr.code = msg.code
|
|
139
|
+
innerErr.message = msg.msg
|
|
140
|
+
} else {
|
|
141
|
+
err.code = msg.code
|
|
142
|
+
err.message = msg.msg
|
|
143
|
+
}
|
|
144
|
+
failErr = innerErr || err
|
|
145
|
+
logs.content = messages.map(msg => ({
|
|
146
|
+
type: 'info',
|
|
147
|
+
body: msg,
|
|
148
|
+
}))
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
// oauth 错误特殊处理
|
|
153
|
+
if (error && errorDescription) {
|
|
154
|
+
logs.subtitle = errorDescription
|
|
155
|
+
if (innerErr) {
|
|
156
|
+
innerErr.code = error
|
|
157
|
+
innerErr.msg = errorDescription
|
|
158
|
+
} else {
|
|
159
|
+
err.code = error
|
|
160
|
+
err.message = errorDescription
|
|
161
|
+
}
|
|
162
|
+
failErr = innerErr || err
|
|
163
|
+
logs.content = messages.map(msg => ({
|
|
164
|
+
type: 'info',
|
|
165
|
+
body: msg,
|
|
166
|
+
}))
|
|
167
|
+
}
|
|
168
|
+
printGroupLog(logs)
|
|
169
|
+
throw failErr
|
|
170
|
+
}
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
}
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
/**
|
|
177
|
+
* 在原始堆栈中查找装饰器条目并返回源码链接link
|
|
178
|
+
* @param err
|
|
179
|
+
*/
|
|
180
|
+
function getSourceLink(err: Error) {
|
|
181
|
+
let sourceLink = ''
|
|
182
|
+
const outterErrStacks = err.stack.split('\n')
|
|
183
|
+
const indexOfDecorator = outterErrStacks.findIndex(str => REG_STACK_DECORATE.test(str))
|
|
184
|
+
|
|
185
|
+
if (indexOfDecorator !== -1) {
|
|
186
|
+
const match = REG_STACK_LINK.exec(outterErrStacks[indexOfDecorator + 1] || '')
|
|
187
|
+
|
|
188
|
+
sourceLink = match ? match[0] : ''
|
|
189
|
+
}
|
|
190
|
+
return sourceLink
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
/**
|
|
194
|
+
* 在原始堆栈中查找装饰器条目,剔除其后的无用堆栈,并将链接替换为源码link
|
|
195
|
+
* @param options
|
|
196
|
+
*/
|
|
197
|
+
function getRewritedError(options: {
|
|
198
|
+
err: Error;
|
|
199
|
+
className: string;
|
|
200
|
+
methodName: string;
|
|
201
|
+
sourceLink: string;
|
|
202
|
+
}) {
|
|
203
|
+
const { err, className, methodName, sourceLink } = options
|
|
204
|
+
// 找不到源码link返回null,后续逻辑将打印原堆栈信息
|
|
205
|
+
if (!sourceLink) {
|
|
206
|
+
return null
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
const innerErrStack = err.stack.split('\n')
|
|
210
|
+
const REG_STACK_INNER_METHOD = isFirefox
|
|
211
|
+
? /^catchErrorsDecorator\/<\/descriptor.value@.*\d$/
|
|
212
|
+
: new RegExp(`${className}\\.descriptor.value\\s*\\[as\\s${methodName}\\]\\s*\\(.*\\)$`)
|
|
213
|
+
const REG_STACK_INNER_METHOD_WITHOUT_LINK = isFirefox
|
|
214
|
+
? /^catchErrorsDecorator\/<\/descriptor.value/
|
|
215
|
+
: new RegExp(`${className}\\.descriptor.value\\s*\\[as\\s${methodName}\\]`)
|
|
216
|
+
const indexOfSource = innerErrStack.findIndex(str => REG_STACK_INNER_METHOD.test(str))
|
|
217
|
+
let innerErr: Error
|
|
218
|
+
if (indexOfSource !== -1) {
|
|
219
|
+
// @ts-ignore
|
|
220
|
+
const realErrStack = innerErrStack.filter((v, i) => i > indexOfSource)
|
|
221
|
+
realErrStack.unshift(innerErrStack[indexOfSource]
|
|
222
|
+
.replace(REG_STACK_INNER_METHOD_WITHOUT_LINK, `${className}.${methodName}`)
|
|
223
|
+
.replace(REG_STACK_LINK, sourceLink))
|
|
224
|
+
innerErr = new Error()
|
|
225
|
+
innerErr.stack = `${isFirefox ? '@debugger' : 'Error'}\n${realErrStack.join('\n')}`
|
|
226
|
+
}
|
|
227
|
+
return innerErr
|
|
228
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from './decorators'
|
package/src/index.ts
ADDED
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import * as constants from './constants'
|
|
2
|
+
import * as adapters from './adapters'
|
|
3
|
+
import * as cache from './libs/cache'
|
|
4
|
+
import * as events from './libs/events'
|
|
5
|
+
import * as utils from './libs/util'
|
|
6
|
+
import * as helpers from './helpers'
|
|
7
|
+
|
|
8
|
+
import jwtDecode from 'jwt-decode'
|
|
9
|
+
|
|
10
|
+
const jwt = {
|
|
11
|
+
decode: jwtDecode,
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
export {
|
|
15
|
+
constants,
|
|
16
|
+
adapters,
|
|
17
|
+
cache,
|
|
18
|
+
events,
|
|
19
|
+
utils,
|
|
20
|
+
helpers,
|
|
21
|
+
jwt,
|
|
22
|
+
}
|
|
@@ -0,0 +1,192 @@
|
|
|
1
|
+
import { StorageInterface, AbstractStorage, SDKAdapterInterface } from '@cloudbase/adapter-interface'
|
|
2
|
+
import { ICloudbaseCache, ICacheConfig } from '@cloudbase/types/cache'
|
|
3
|
+
import { KV, Persistence, ICloudbasePlatformInfo } from '@cloudbase/types'
|
|
4
|
+
import { printWarn } from './util'
|
|
5
|
+
import { ERRORS, getSdkName } from '../constants'
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* persitence=none时登录态保存在内存中
|
|
9
|
+
*/
|
|
10
|
+
class TcbCacheObject extends AbstractStorage {
|
|
11
|
+
private readonly root: any;
|
|
12
|
+
constructor(root: any) {
|
|
13
|
+
super()
|
|
14
|
+
this.root = root
|
|
15
|
+
if (!root.tcbCacheObject) {
|
|
16
|
+
root.tcbCacheObject = {}
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
public setItem(key: string, value: any) {
|
|
20
|
+
this.root.tcbCacheObject[key] = value
|
|
21
|
+
}
|
|
22
|
+
public getItem(key: string) {
|
|
23
|
+
return this.root.tcbCacheObject[key]
|
|
24
|
+
}
|
|
25
|
+
public removeItem(key: string) {
|
|
26
|
+
delete this.root.tcbCacheObject[key]
|
|
27
|
+
}
|
|
28
|
+
public clear() {
|
|
29
|
+
delete this.root.tcbCacheObject
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
/**
|
|
33
|
+
* 工厂函数
|
|
34
|
+
*/
|
|
35
|
+
function createStorage(persistence: Persistence, adapter: SDKAdapterInterface): StorageInterface {
|
|
36
|
+
switch (persistence) {
|
|
37
|
+
case 'local':
|
|
38
|
+
if (!adapter.localStorage) {
|
|
39
|
+
printWarn(ERRORS.INVALID_PARAMS, 'localStorage is not supported on current platform')
|
|
40
|
+
// 不支持localstorage的平台降级为none
|
|
41
|
+
return new TcbCacheObject(adapter.root)
|
|
42
|
+
}
|
|
43
|
+
return adapter.localStorage
|
|
44
|
+
case 'none':
|
|
45
|
+
return new TcbCacheObject(adapter.root)
|
|
46
|
+
default:
|
|
47
|
+
if (!adapter.localStorage) {
|
|
48
|
+
printWarn(ERRORS.INVALID_PARAMS, 'localStorage is not supported on current platform')
|
|
49
|
+
// 不支持localstorage的平台降级为none
|
|
50
|
+
return new TcbCacheObject(adapter.root)
|
|
51
|
+
}
|
|
52
|
+
return adapter.localStorage
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
export class CloudbaseCache implements ICloudbaseCache {
|
|
57
|
+
public keys: KV<string> = {};
|
|
58
|
+
|
|
59
|
+
private persistenceTag: Persistence;
|
|
60
|
+
private platformInfo: ICloudbasePlatformInfo;
|
|
61
|
+
private storage: StorageInterface;
|
|
62
|
+
|
|
63
|
+
constructor(config: ICacheConfig) {
|
|
64
|
+
const { persistence, platformInfo = {}, keys = {} } = config
|
|
65
|
+
this.platformInfo = platformInfo
|
|
66
|
+
if (!this.storage) {
|
|
67
|
+
this.persistenceTag = this.platformInfo.adapter.primaryStorage || persistence
|
|
68
|
+
this.storage = createStorage(this.persistenceTag, this.platformInfo.adapter)
|
|
69
|
+
this.keys = keys
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
/**
|
|
73
|
+
* @getter storage模式-同步/异步
|
|
74
|
+
*/
|
|
75
|
+
get mode() {
|
|
76
|
+
return this.storage.mode || 'sync'
|
|
77
|
+
}
|
|
78
|
+
get persistence(): Persistence {
|
|
79
|
+
return this.persistenceTag
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
public setStore(key: string, value: any, version?: any) {
|
|
83
|
+
if (this.mode === 'async') {
|
|
84
|
+
printWarn(ERRORS.INVALID_OPERATION, 'current platform\'s storage is asynchronous, please use setStoreAsync insteed')
|
|
85
|
+
return
|
|
86
|
+
}
|
|
87
|
+
if (!this.storage) {
|
|
88
|
+
return
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
try {
|
|
92
|
+
const val = {
|
|
93
|
+
version: version || 'localCachev1',
|
|
94
|
+
content: value,
|
|
95
|
+
}
|
|
96
|
+
this.storage.setItem(key, JSON.stringify(val))
|
|
97
|
+
} catch (e) {
|
|
98
|
+
throw new Error(JSON.stringify({
|
|
99
|
+
code: ERRORS.OPERATION_FAIL,
|
|
100
|
+
msg: `[${getSdkName()}][${ERRORS.OPERATION_FAIL}]setStore failed`,
|
|
101
|
+
info: e,
|
|
102
|
+
}))
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
return
|
|
106
|
+
}
|
|
107
|
+
public async setStoreAsync(key: string, value: any, version?: any) {
|
|
108
|
+
if (!this.storage) {
|
|
109
|
+
return
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
try {
|
|
113
|
+
const val = {
|
|
114
|
+
version: version || 'localCachev1',
|
|
115
|
+
content: value,
|
|
116
|
+
}
|
|
117
|
+
await this.storage.setItem(key, JSON.stringify(val))
|
|
118
|
+
} catch (e) {
|
|
119
|
+
return
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
return
|
|
123
|
+
}
|
|
124
|
+
public getStore(key: string, version?: string) {
|
|
125
|
+
if (this.mode === 'async') {
|
|
126
|
+
printWarn(ERRORS.INVALID_OPERATION, 'current platform\'s storage is asynchronous, please use getStoreAsync insteed')
|
|
127
|
+
return
|
|
128
|
+
}
|
|
129
|
+
try {
|
|
130
|
+
// 测试用例使用
|
|
131
|
+
if (typeof process !== 'undefined' && process.env?.tcb_token) {
|
|
132
|
+
return process.env.tcb_token
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
if (!this.storage) {
|
|
136
|
+
return ''
|
|
137
|
+
}
|
|
138
|
+
} catch (e) {
|
|
139
|
+
return ''
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
version = version || 'localCachev1'
|
|
143
|
+
|
|
144
|
+
const content = this.storage.getItem(key)
|
|
145
|
+
if (!content) {
|
|
146
|
+
return ''
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
if (content.indexOf(version) >= 0) {
|
|
150
|
+
const d = JSON.parse(content)
|
|
151
|
+
return d.content
|
|
152
|
+
}
|
|
153
|
+
return ''
|
|
154
|
+
}
|
|
155
|
+
public async getStoreAsync(key: string, version?: string) {
|
|
156
|
+
try {
|
|
157
|
+
// 测试用例使用
|
|
158
|
+
if (typeof process !== 'undefined' && process.env?.tcb_token) {
|
|
159
|
+
return process.env.tcb_token
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
if (!this.storage) {
|
|
163
|
+
return ''
|
|
164
|
+
}
|
|
165
|
+
} catch (e) {
|
|
166
|
+
return ''
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
version = version || 'localCachev1'
|
|
170
|
+
|
|
171
|
+
const content = await this.storage.getItem(key)
|
|
172
|
+
if (!content) {
|
|
173
|
+
return ''
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
if (content.indexOf(version) >= 0) {
|
|
177
|
+
const d = JSON.parse(content)
|
|
178
|
+
return d.content
|
|
179
|
+
}
|
|
180
|
+
return ''
|
|
181
|
+
}
|
|
182
|
+
public removeStore(key: string) {
|
|
183
|
+
if (this.mode === 'async') {
|
|
184
|
+
printWarn(ERRORS.INVALID_OPERATION, 'current platform\'s storage is asynchronous, please use removeStoreAsync insteed')
|
|
185
|
+
return
|
|
186
|
+
}
|
|
187
|
+
this.storage.removeItem(key)
|
|
188
|
+
}
|
|
189
|
+
public async removeStoreAsync(key: string) {
|
|
190
|
+
await this.storage.removeItem(key)
|
|
191
|
+
}
|
|
192
|
+
}
|
|
@@ -0,0 +1,154 @@
|
|
|
1
|
+
import { isString, isInstanceOf } from './util'
|
|
2
|
+
import { Listeners, ICloudbaseEventEmitter } from '@cloudbase/types/events'
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* @private
|
|
7
|
+
* @function _addEventListener - 添加监听
|
|
8
|
+
* @param {string} name - event名称
|
|
9
|
+
* @param {Function} listener - 响应函数
|
|
10
|
+
* @param {Listeners} listeners - 已存响应函数集合
|
|
11
|
+
*/
|
|
12
|
+
function customeAddEventListener(name: string, listener: Function, listeners: Listeners) {
|
|
13
|
+
listeners[name] = listeners[name] || []
|
|
14
|
+
listeners[name].push(listener)
|
|
15
|
+
}
|
|
16
|
+
/**
|
|
17
|
+
* @private
|
|
18
|
+
* @function _removeEventListener - 移除监听
|
|
19
|
+
* @param {string} name - event名称
|
|
20
|
+
* @param {Function} listener - 响应函数
|
|
21
|
+
* @param {Listeners} listeners - 已存响应函数集合
|
|
22
|
+
*/
|
|
23
|
+
function customRemoveEventListener(name: string, listener: Function, listeners: Listeners) {
|
|
24
|
+
if (listeners?.[name]) {
|
|
25
|
+
const index = listeners[name].indexOf(listener)
|
|
26
|
+
if (index !== -1) {
|
|
27
|
+
listeners[name].splice(index, 1)
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
interface IEvent {
|
|
32
|
+
name: string;
|
|
33
|
+
target: any;
|
|
34
|
+
data: any;
|
|
35
|
+
}
|
|
36
|
+
/**
|
|
37
|
+
* 自定义事件
|
|
38
|
+
* @class CloudbaseEvent
|
|
39
|
+
* @param {string} name - 类型
|
|
40
|
+
* @param {any} data - 数据
|
|
41
|
+
*/
|
|
42
|
+
export class CloudbaseEvent implements IEvent {
|
|
43
|
+
public readonly name: string;
|
|
44
|
+
public target: any;
|
|
45
|
+
public data: any;
|
|
46
|
+
|
|
47
|
+
constructor(name: string, data: any) {
|
|
48
|
+
this.data = data || null
|
|
49
|
+
this.name = name
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
/**
|
|
53
|
+
* 自定义错误事件
|
|
54
|
+
* @class IErrorEvent
|
|
55
|
+
* @extends CloudbaseEvent
|
|
56
|
+
* @param {Error} error - 错误信息对象
|
|
57
|
+
* @param {any} data - 数据
|
|
58
|
+
*/
|
|
59
|
+
export class IErrorEvent extends CloudbaseEvent {
|
|
60
|
+
public readonly error: Error;
|
|
61
|
+
constructor(error: Error, data?: any) {
|
|
62
|
+
super('error', { error, data })
|
|
63
|
+
this.error = error
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
/**
|
|
68
|
+
* @class CloudbaseEventEmitter
|
|
69
|
+
*/
|
|
70
|
+
export class CloudbaseEventEmitter implements ICloudbaseEventEmitter {
|
|
71
|
+
/**
|
|
72
|
+
* @private
|
|
73
|
+
* @readonly
|
|
74
|
+
* @property {Listeners} listeners - 响应函数集合
|
|
75
|
+
* @default `{}`
|
|
76
|
+
*/
|
|
77
|
+
private readonly listeners: Listeners = {};
|
|
78
|
+
|
|
79
|
+
/**
|
|
80
|
+
* @public
|
|
81
|
+
* @method on - 添加监听
|
|
82
|
+
* @param {string} name - event名称
|
|
83
|
+
* @param {Function} listener - 响应函数
|
|
84
|
+
* @return `this`
|
|
85
|
+
*/
|
|
86
|
+
public on(name: string, listener: Function): this {
|
|
87
|
+
customeAddEventListener(name, listener, this.listeners)
|
|
88
|
+
return this
|
|
89
|
+
}
|
|
90
|
+
/**
|
|
91
|
+
* @public
|
|
92
|
+
* @method off - 移除监听
|
|
93
|
+
* @param {string} name - event名称
|
|
94
|
+
* @param {Function} listener - 响应函数
|
|
95
|
+
* @return `this`
|
|
96
|
+
*/
|
|
97
|
+
public off(name: string, listener: Function): this {
|
|
98
|
+
customRemoveEventListener(name, listener, this.listeners)
|
|
99
|
+
return this
|
|
100
|
+
}
|
|
101
|
+
/**
|
|
102
|
+
* @public
|
|
103
|
+
* @method fire - 触发事件
|
|
104
|
+
* @param {string|CloudbaseEvent} event - event
|
|
105
|
+
* @return `this`
|
|
106
|
+
*/
|
|
107
|
+
public fire(event: string | CloudbaseEvent, data?: any): this {
|
|
108
|
+
// 打印错误信息
|
|
109
|
+
if (isInstanceOf(event, IErrorEvent)) {
|
|
110
|
+
console.error((event as IErrorEvent).error)
|
|
111
|
+
return this
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
const ev: CloudbaseEvent = isString(event) ? new CloudbaseEvent(event as string, data || {}) : event as CloudbaseEvent
|
|
115
|
+
|
|
116
|
+
const { name } = ev
|
|
117
|
+
|
|
118
|
+
if (this.listens(name)) {
|
|
119
|
+
ev.target = this
|
|
120
|
+
|
|
121
|
+
const handlers = this.listeners[name] ? [...this.listeners[name]] : []
|
|
122
|
+
for (const fn of handlers) {
|
|
123
|
+
fn.call(this, ev)
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
return this
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
/**
|
|
131
|
+
* @private
|
|
132
|
+
* @method listens - 判断是否监听了name事件
|
|
133
|
+
* @param {string} name - event名称
|
|
134
|
+
* @return `boolean`
|
|
135
|
+
*/
|
|
136
|
+
private listens(name: string): boolean {
|
|
137
|
+
return this.listeners[name] && this.listeners[name].length > 0
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
|
|
142
|
+
const eventEmitter = new CloudbaseEventEmitter()
|
|
143
|
+
|
|
144
|
+
export function addEventListener(event: string, callback: Function) {
|
|
145
|
+
eventEmitter.on(event, callback)
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
export function activateEvent(event: string, data: any = {}) {
|
|
149
|
+
eventEmitter.fire(event, data)
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
export function removeEventListener(event: string, callback: Function) {
|
|
153
|
+
eventEmitter.off(event, callback)
|
|
154
|
+
}
|