@cloudbase/storage 2.23.4-alpha.0 → 2.24.1
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/dist/cjs/index.js +45 -712
- package/dist/cjs/storage.d.ts +49 -0
- package/dist/cjs/storage.js +701 -0
- package/dist/cjs/supabase/errors.d.ts +20 -0
- package/dist/cjs/supabase/errors.js +65 -0
- package/dist/cjs/supabase/index.d.ts +145 -0
- package/dist/cjs/supabase/index.js +706 -0
- package/dist/cjs/supabase/types.d.ts +64 -0
- package/dist/cjs/supabase/types.js +3 -0
- package/dist/esm/index.js +45 -712
- package/dist/esm/storage.d.ts +49 -0
- package/dist/esm/storage.js +698 -0
- package/dist/esm/supabase/errors.d.ts +20 -0
- package/dist/esm/supabase/errors.js +61 -0
- package/dist/esm/supabase/index.d.ts +145 -0
- package/dist/esm/supabase/index.js +703 -0
- package/dist/esm/supabase/types.d.ts +64 -0
- package/dist/esm/supabase/types.js +2 -0
- package/package.json +4 -4
- package/src/index.ts +52 -652
- package/src/storage.ts +683 -0
- package/src/supabase/errors.ts +43 -0
- package/src/supabase/index.ts +746 -0
- package/src/supabase/types.ts +132 -0
package/src/index.ts
CHANGED
|
@@ -1,680 +1,81 @@
|
|
|
1
|
-
import { constants, utils, helpers } from '@cloudbase/utilities'
|
|
2
1
|
import { ICloudbase } from '@cloudbase/types'
|
|
3
2
|
import { ICloudbaseComponent } from '@cloudbase/types/component'
|
|
4
|
-
import {
|
|
5
|
-
|
|
6
|
-
ICloudbaseFileInfo,
|
|
7
|
-
ICloudbaseUploadFileParams,
|
|
8
|
-
ICloudbaseUploadFileResult,
|
|
9
|
-
ICloudbaseGetUploadMetadataParams,
|
|
10
|
-
ICloudbaseDeleteFileParams,
|
|
11
|
-
ICloudbaseDeleteFileResult,
|
|
12
|
-
ICloudbaseGetTempFileURLResult,
|
|
13
|
-
ICloudbaseGetTempFileURLParams,
|
|
14
|
-
ICloudbaseDownloadFileResult,
|
|
15
|
-
ICloudbaseDownloadFileParams,
|
|
16
|
-
ICloudbaseCopyFileParams,
|
|
17
|
-
ICloudbaseCopyFileResult,
|
|
18
|
-
} from '@cloudbase/types/storage'
|
|
3
|
+
import { CloudbaseStorage, COMPONENT_NAME, ICloudbaseContext } from './storage'
|
|
4
|
+
import { SupabaseFileAPILikeStorage } from './supabase'
|
|
19
5
|
|
|
20
6
|
declare const cloudbase: ICloudbase
|
|
21
7
|
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
const lastSlashIndex = path.lastIndexOf('/')
|
|
35
|
-
if (lastSlashIndex === -1) return path
|
|
36
|
-
return path.slice(lastSlashIndex + 1)
|
|
37
|
-
}
|
|
38
|
-
|
|
39
|
-
const storageGateWay = {
|
|
40
|
-
getUploadInfo: async (
|
|
41
|
-
request,
|
|
42
|
-
params: { path: string; headers?: Record<string, string> },
|
|
43
|
-
customReqOpts: ICloudbaseUploadFileParams['customReqOpts'],
|
|
44
|
-
) => {
|
|
45
|
-
let res = await request.gateWay(
|
|
46
|
-
{
|
|
47
|
-
path: 'storages',
|
|
48
|
-
name: 'get-objects-upload-info',
|
|
49
|
-
data: [
|
|
50
|
-
{
|
|
51
|
-
objectId: params.path,
|
|
52
|
-
...(params.headers ? { signedHeader: params.headers } : {}),
|
|
53
|
-
},
|
|
54
|
-
],
|
|
55
|
-
},
|
|
56
|
-
customReqOpts,
|
|
57
|
-
)
|
|
58
|
-
const data = res.data?.[0] || {}
|
|
59
|
-
|
|
60
|
-
res = {
|
|
61
|
-
...res,
|
|
62
|
-
data: {
|
|
63
|
-
...(data.code ? { ...data } : {}),
|
|
64
|
-
authorization: data.authorization,
|
|
65
|
-
token: data.token,
|
|
66
|
-
url: data.uploadUrl,
|
|
67
|
-
fileId: data.cloudObjectId,
|
|
68
|
-
cosFileId: data.cloudObjectMeta,
|
|
69
|
-
download_url: data.downloadUrl,
|
|
70
|
-
},
|
|
71
|
-
}
|
|
72
|
-
|
|
73
|
-
return res
|
|
74
|
-
},
|
|
75
|
-
getDownLoadInfo: async (
|
|
76
|
-
request,
|
|
77
|
-
params: { convertedFileList: Array<{ fileid: string }> },
|
|
78
|
-
customReqOpts: ICloudbaseUploadFileParams['customReqOpts'],
|
|
79
|
-
) => {
|
|
80
|
-
let res = await request.gateWay(
|
|
81
|
-
{
|
|
82
|
-
path: 'storages',
|
|
83
|
-
name: 'get-objects-download-info',
|
|
84
|
-
data: params.convertedFileList.map((v: any) => ({ cloudObjectId: v.fileid })),
|
|
85
|
-
},
|
|
86
|
-
customReqOpts,
|
|
87
|
-
)
|
|
88
|
-
res = {
|
|
89
|
-
...res,
|
|
90
|
-
data: {
|
|
91
|
-
download_list: res.data?.map(v => ({
|
|
92
|
-
code: v.code || 'SUCCESS',
|
|
93
|
-
message: v.message,
|
|
94
|
-
fileid: v.cloudObjectId,
|
|
95
|
-
download_url: v.downloadUrl,
|
|
96
|
-
fileID: v.cloudObjectId,
|
|
97
|
-
tempFileURL: v.downloadUrl,
|
|
98
|
-
})),
|
|
99
|
-
},
|
|
100
|
-
}
|
|
101
|
-
|
|
102
|
-
return res
|
|
103
|
-
},
|
|
104
|
-
delete: async (
|
|
105
|
-
request,
|
|
106
|
-
params: { fileList: Array<string> },
|
|
107
|
-
customReqOpts: ICloudbaseUploadFileParams['customReqOpts'],
|
|
108
|
-
) => {
|
|
109
|
-
let res = await request.gateWay(
|
|
110
|
-
{
|
|
111
|
-
path: 'storages',
|
|
112
|
-
name: 'delete-objects',
|
|
113
|
-
data: params.fileList.map(v => ({ cloudObjectId: v })),
|
|
114
|
-
},
|
|
115
|
-
customReqOpts,
|
|
116
|
-
)
|
|
117
|
-
res = {
|
|
118
|
-
...res,
|
|
119
|
-
data: {
|
|
120
|
-
delete_list: res.data?.map(v => ({
|
|
121
|
-
code: v.code || 'SUCCESS',
|
|
122
|
-
fileID: v.cloudObjectId,
|
|
123
|
-
message: v.message,
|
|
124
|
-
})),
|
|
125
|
-
},
|
|
126
|
-
}
|
|
127
|
-
|
|
128
|
-
return res
|
|
129
|
-
},
|
|
130
|
-
copyFile: async (
|
|
131
|
-
request,
|
|
132
|
-
params: {
|
|
133
|
-
convertedFileList: Array<{ src_path: string; dst_path: string; overwrite: boolean; remove_original: boolean }>
|
|
134
|
-
},
|
|
135
|
-
customReqOpts: ICloudbaseUploadFileParams['customReqOpts'],
|
|
136
|
-
) => {
|
|
137
|
-
let res = await request.gateWay(
|
|
138
|
-
{
|
|
139
|
-
path: 'storages',
|
|
140
|
-
name: 'copy-objects',
|
|
141
|
-
data: params.convertedFileList.map((v: any) => ({
|
|
142
|
-
srcPath: v.src_path,
|
|
143
|
-
dstPath: v.dst_path,
|
|
144
|
-
overwrite: v.overwrite,
|
|
145
|
-
removeOriginal: v.remove_original,
|
|
146
|
-
})),
|
|
147
|
-
},
|
|
148
|
-
customReqOpts,
|
|
149
|
-
)
|
|
150
|
-
res = {
|
|
151
|
-
...res,
|
|
152
|
-
data: {
|
|
153
|
-
copy_list: res.data?.map(v => ({
|
|
154
|
-
code: v.code || 'SUCCESS',
|
|
155
|
-
fileID: v.cloudObjectId,
|
|
156
|
-
message: v.message,
|
|
157
|
-
})),
|
|
158
|
-
},
|
|
159
|
-
}
|
|
160
|
-
|
|
161
|
-
return res
|
|
8
|
+
const storage = new CloudbaseStorage()
|
|
9
|
+
const component: ICloudbaseComponent = {
|
|
10
|
+
name: COMPONENT_NAME,
|
|
11
|
+
entity: {
|
|
12
|
+
uploadFile: storage.uploadFile,
|
|
13
|
+
deleteFile: storage.deleteFile,
|
|
14
|
+
getTempFileURL: storage.getTempFileURL,
|
|
15
|
+
downloadFile: storage.downloadFile,
|
|
16
|
+
getUploadMetadata: storage.getUploadMetadata,
|
|
17
|
+
copyFile: storage.copyFile,
|
|
18
|
+
getFileInfo: storage.getFileInfo,
|
|
19
|
+
isGateWay: storage.isGateWay,
|
|
162
20
|
},
|
|
163
21
|
}
|
|
164
22
|
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
return endPointMode === 'GATEWAY'
|
|
172
|
-
}
|
|
173
|
-
|
|
174
|
-
@catchErrorsDecorator({
|
|
175
|
-
customInfo: {
|
|
176
|
-
className: 'Cloudbase',
|
|
177
|
-
methodName: 'uploadFile',
|
|
178
|
-
},
|
|
179
|
-
title: '上传文件失败',
|
|
180
|
-
messages: [
|
|
181
|
-
'请确认以下各项:',
|
|
182
|
-
' 1 - 调用 uploadFile() 的语法或参数是否正确',
|
|
183
|
-
' 2 - 当前域名是否在安全域名列表中:https://console.cloud.tencent.com/tcb/env/safety',
|
|
184
|
-
' 3 - 云存储安全规则是否限制了当前登录状态访问',
|
|
185
|
-
`如果问题依然存在,建议到官方问答社区提问或寻找帮助:${COMMUNITY_SITE_URL}`,
|
|
186
|
-
],
|
|
187
|
-
})
|
|
188
|
-
public async uploadFile(
|
|
189
|
-
params: ICloudbaseUploadFileParams,
|
|
190
|
-
callback?: Function,
|
|
191
|
-
): Promise<ICloudbaseUploadFileResult> {
|
|
192
|
-
const { cloudPath, filePath, onUploadProgress, method = 'put', headers = {}, fileContent } = params
|
|
193
|
-
if (!isString(cloudPath) || (!filePath && !fileContent)) {
|
|
194
|
-
throw new Error(JSON.stringify({
|
|
195
|
-
code: ERRORS.INVALID_PARAMS,
|
|
196
|
-
msg: `[${COMPONENT_NAME}.uploadFile] invalid params`,
|
|
197
|
-
}),)
|
|
198
|
-
}
|
|
199
|
-
const uploadMethod = { put: EUploadMethod.put, post: EUploadMethod.post }[method.toLocaleLowerCase()] || EUploadMethod.put
|
|
200
|
-
|
|
201
|
-
const action = 'storage.getUploadMetadata'
|
|
202
|
-
// @ts-ignore
|
|
203
|
-
const { request } = this
|
|
204
|
-
const metaDataParam: {
|
|
205
|
-
path: string
|
|
206
|
-
method: EUploadMethod
|
|
207
|
-
headers?: Record<any, any>
|
|
208
|
-
} = {
|
|
209
|
-
path: cloudPath,
|
|
210
|
-
method: uploadMethod,
|
|
211
|
-
}
|
|
212
|
-
if (uploadMethod === EUploadMethod.put) {
|
|
213
|
-
metaDataParam.headers = headers
|
|
214
|
-
}
|
|
23
|
+
const supabaseComponent: ICloudbaseComponent = {
|
|
24
|
+
name: `${COMPONENT_NAME}/supabase`,
|
|
25
|
+
IIFE: true,
|
|
26
|
+
entity() {
|
|
27
|
+
// 在 IIFE 中,this 是 Cloudbase 类(构造函数),不是实例
|
|
28
|
+
// 所以我们需要使用 getter 来延迟获取实例的 config 和 request
|
|
215
29
|
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
if (this.isGateWay()) {
|
|
219
|
-
metaData = await storageGateWay.getUploadInfo(request, metaDataParam, params.customReqOpts)
|
|
220
|
-
} else {
|
|
221
|
-
metaData = await request.send(action, metaDataParam, params.customReqOpts)
|
|
222
|
-
}
|
|
223
|
-
|
|
224
|
-
const {
|
|
225
|
-
data: { url, authorization, token, fileId, cosFileId, download_url: downloadUrl },
|
|
226
|
-
requestId,
|
|
227
|
-
} = metaData
|
|
228
|
-
|
|
229
|
-
if (metaData.data?.code) {
|
|
230
|
-
return execCallback(
|
|
231
|
-
callback,
|
|
232
|
-
new Error(`[${getSdkName()}][${ERRORS.OPERATION_FAIL}][${COMPONENT_NAME}]:${metaData.data}`),
|
|
233
|
-
)
|
|
234
|
-
}
|
|
235
|
-
|
|
236
|
-
const commonParams = {
|
|
237
|
-
url,
|
|
238
|
-
file: filePath,
|
|
239
|
-
name: cloudPath,
|
|
240
|
-
onUploadProgress,
|
|
241
|
-
fileContent,
|
|
242
|
-
fileId,
|
|
243
|
-
requestId,
|
|
244
|
-
}
|
|
245
|
-
|
|
246
|
-
const putParams = {
|
|
247
|
-
...commonParams,
|
|
248
|
-
method: EUploadMethod.put,
|
|
249
|
-
headers: {
|
|
250
|
-
...headers,
|
|
251
|
-
authorization,
|
|
252
|
-
'x-cos-meta-fileid': cosFileId,
|
|
253
|
-
'x-cos-security-token': token,
|
|
254
|
-
},
|
|
255
|
-
}
|
|
256
|
-
|
|
257
|
-
const postParams = {
|
|
258
|
-
...commonParams,
|
|
259
|
-
method: EUploadMethod.post,
|
|
260
|
-
data: {
|
|
261
|
-
key: cloudPath,
|
|
262
|
-
signature: authorization,
|
|
263
|
-
'x-cos-meta-fileid': cosFileId,
|
|
264
|
-
success_action_status: '201',
|
|
265
|
-
'x-cos-security-token': token,
|
|
266
|
-
},
|
|
267
|
-
}
|
|
268
|
-
|
|
269
|
-
const uploadConfig = {
|
|
270
|
-
[EUploadMethod.put]: {
|
|
271
|
-
params: putParams,
|
|
272
|
-
isSuccess: (code: number) => code >= 200 && code < 300,
|
|
273
|
-
},
|
|
274
|
-
[EUploadMethod.post]: {
|
|
275
|
-
params: postParams,
|
|
276
|
-
isSuccess: (code: number) => code === 201,
|
|
277
|
-
},
|
|
278
|
-
}
|
|
279
|
-
|
|
280
|
-
const res = await request.upload(uploadConfig[uploadMethod].params)
|
|
281
|
-
|
|
282
|
-
if (uploadConfig[uploadMethod].isSuccess(res.statusCode)) {
|
|
283
|
-
return execCallback(callback, null, {
|
|
284
|
-
fileID: fileId,
|
|
285
|
-
download_url: downloadUrl,
|
|
286
|
-
requestId,
|
|
287
|
-
})
|
|
288
|
-
}
|
|
289
|
-
return execCallback(
|
|
290
|
-
callback,
|
|
291
|
-
new Error(`[${getSdkName()}][${ERRORS.OPERATION_FAIL}][${COMPONENT_NAME}]:${res.data}`),
|
|
292
|
-
)
|
|
293
|
-
}
|
|
294
|
-
@catchErrorsDecorator({
|
|
295
|
-
customInfo: {
|
|
296
|
-
className: 'Cloudbase',
|
|
297
|
-
methodName: 'getUploadMetadata',
|
|
298
|
-
},
|
|
299
|
-
title: '获取上传元信息失败',
|
|
300
|
-
messages: [
|
|
301
|
-
'请确认以下各项:',
|
|
302
|
-
' 1 - 调用 getUploadMetadata() 的语法或参数是否正确',
|
|
303
|
-
' 2 - 当前域名是否在安全域名列表中:https://console.cloud.tencent.com/tcb/env/safety',
|
|
304
|
-
' 3 - 云存储安全规则是否限制了当前登录状态访问',
|
|
305
|
-
`如果问题依然存在,建议到官方问答社区提问或寻找帮助:${COMMUNITY_SITE_URL}`,
|
|
306
|
-
],
|
|
307
|
-
})
|
|
308
|
-
public async getUploadMetadata(params: ICloudbaseGetUploadMetadataParams, callback?: Function): Promise<any> {
|
|
309
|
-
const { cloudPath } = params
|
|
310
|
-
if (!isString(cloudPath)) {
|
|
311
|
-
throw new Error(JSON.stringify({
|
|
312
|
-
code: ERRORS.INVALID_PARAMS,
|
|
313
|
-
msg: `[${COMPONENT_NAME}.getUploadMetadata] invalid cloudPath`,
|
|
314
|
-
}),)
|
|
315
|
-
}
|
|
316
|
-
// @ts-ignore
|
|
317
|
-
const { request } = this
|
|
318
|
-
const action = 'storage.getUploadMetadata'
|
|
319
|
-
|
|
320
|
-
try {
|
|
321
|
-
let metaData: any = {}
|
|
322
|
-
if (this.isGateWay()) {
|
|
323
|
-
metaData = await storageGateWay.getUploadInfo(request, { path: cloudPath }, params.customReqOpts)
|
|
324
|
-
} else {
|
|
325
|
-
metaData = await request.send(
|
|
326
|
-
action,
|
|
327
|
-
{
|
|
328
|
-
path: cloudPath,
|
|
329
|
-
},
|
|
330
|
-
params.customReqOpts,
|
|
331
|
-
)
|
|
332
|
-
}
|
|
333
|
-
return execCallback(callback, null, metaData)
|
|
334
|
-
} catch (err) {
|
|
335
|
-
return execCallback(callback, err)
|
|
336
|
-
}
|
|
337
|
-
}
|
|
338
|
-
@catchErrorsDecorator({
|
|
339
|
-
customInfo: {
|
|
340
|
-
className: 'Cloudbase',
|
|
341
|
-
methodName: 'deleteFile',
|
|
342
|
-
},
|
|
343
|
-
title: '删除文件失败',
|
|
344
|
-
messages: [
|
|
345
|
-
'请确认以下各项:',
|
|
346
|
-
' 1 - 调用 deleteFile() 的语法或参数是否正确',
|
|
347
|
-
' 2 - 当前域名是否在安全域名列表中:https://console.cloud.tencent.com/tcb/env/safety',
|
|
348
|
-
' 3 - 云存储安全规则是否限制了当前登录状态访问',
|
|
349
|
-
`如果问题依然存在,建议到官方问答社区提问或寻找帮助:${COMMUNITY_SITE_URL}`,
|
|
350
|
-
],
|
|
351
|
-
})
|
|
352
|
-
public async deleteFile(
|
|
353
|
-
params: ICloudbaseDeleteFileParams,
|
|
354
|
-
callback?: Function,
|
|
355
|
-
): Promise<ICloudbaseDeleteFileResult> {
|
|
356
|
-
const { fileList } = params
|
|
30
|
+
// 使用 WeakMap 缓存每个实例的 storage 对象
|
|
31
|
+
const storageCache = new WeakMap<any, SupabaseFileAPILikeStorage>()
|
|
357
32
|
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
}),)
|
|
363
|
-
}
|
|
33
|
+
// 定义 storage 属性的 getter,每个实例只创建一次
|
|
34
|
+
Object.defineProperty(this.prototype, 'storage', {
|
|
35
|
+
get() {
|
|
36
|
+
// 这里的 this 是 cloudbase 实例
|
|
364
37
|
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
code: ERRORS.INVALID_PARAMS,
|
|
369
|
-
msg: `[${COMPONENT_NAME}.deleteFile] fileID must be string`,
|
|
370
|
-
}),)
|
|
371
|
-
}
|
|
372
|
-
}
|
|
373
|
-
|
|
374
|
-
const action = 'storage.batchDeleteFile'
|
|
375
|
-
// @ts-ignore
|
|
376
|
-
const { request } = this
|
|
377
|
-
let res: any = {}
|
|
378
|
-
|
|
379
|
-
if (this.isGateWay()) {
|
|
380
|
-
res = await storageGateWay.delete(request, { fileList }, params.customReqOpts)
|
|
381
|
-
} else {
|
|
382
|
-
res = await request.send(
|
|
383
|
-
action,
|
|
384
|
-
{
|
|
385
|
-
fileid_list: fileList,
|
|
386
|
-
},
|
|
387
|
-
params.customReqOpts,
|
|
388
|
-
)
|
|
389
|
-
}
|
|
390
|
-
|
|
391
|
-
if (res.code) {
|
|
392
|
-
return execCallback(callback, null, res)
|
|
393
|
-
}
|
|
394
|
-
const data = {
|
|
395
|
-
fileList: res.data.delete_list,
|
|
396
|
-
requestId: res.requestId,
|
|
397
|
-
}
|
|
398
|
-
return execCallback(callback, null, data)
|
|
399
|
-
}
|
|
400
|
-
@catchErrorsDecorator({
|
|
401
|
-
customInfo: {
|
|
402
|
-
className: 'Cloudbase',
|
|
403
|
-
methodName: 'getTempFileURL',
|
|
404
|
-
},
|
|
405
|
-
title: '获取文件下载链接',
|
|
406
|
-
messages: [
|
|
407
|
-
'请确认以下各项:',
|
|
408
|
-
' 1 - 调用 getTempFileURL() 的语法或参数是否正确',
|
|
409
|
-
' 2 - 当前域名是否在安全域名列表中:https://console.cloud.tencent.com/tcb/env/safety',
|
|
410
|
-
' 3 - 云存储安全规则是否限制了当前登录状态访问',
|
|
411
|
-
`如果问题依然存在,建议到官方问答社区提问或寻找帮助:${COMMUNITY_SITE_URL}`,
|
|
412
|
-
],
|
|
413
|
-
})
|
|
414
|
-
public async getTempFileURL(
|
|
415
|
-
params: ICloudbaseGetTempFileURLParams,
|
|
416
|
-
callback?: Function,
|
|
417
|
-
): Promise<ICloudbaseGetTempFileURLResult> {
|
|
418
|
-
const { fileList } = params
|
|
419
|
-
|
|
420
|
-
if (!fileList || !isArray(fileList) || fileList.length === 0) {
|
|
421
|
-
throw new Error(JSON.stringify({
|
|
422
|
-
code: ERRORS.INVALID_PARAMS,
|
|
423
|
-
msg: `[${COMPONENT_NAME}.getTempFileURL] fileList must not be empty`,
|
|
424
|
-
}),)
|
|
425
|
-
}
|
|
426
|
-
|
|
427
|
-
const convertedFileList = []
|
|
428
|
-
for (const file of fileList) {
|
|
429
|
-
if (isPalinObject(file)) {
|
|
430
|
-
if (
|
|
431
|
-
!Object.prototype.hasOwnProperty.call(file, 'fileID')
|
|
432
|
-
|| !Object.prototype.hasOwnProperty.call(file, 'maxAge')
|
|
433
|
-
) {
|
|
434
|
-
throw new Error(JSON.stringify({
|
|
435
|
-
code: ERRORS.INVALID_PARAMS,
|
|
436
|
-
msg: `[${COMPONENT_NAME}.getTempFileURL] file info must include fileID and maxAge`,
|
|
437
|
-
}),)
|
|
38
|
+
// 如果已经创建过,直接返回缓存的实例
|
|
39
|
+
if (storageCache.has(this)) {
|
|
40
|
+
return storageCache.get(this)
|
|
438
41
|
}
|
|
439
42
|
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
43
|
+
// 创建动态 context,从当前实例获取 config 和 request
|
|
44
|
+
// eslint-disable-next-line @typescript-eslint/no-this-alias
|
|
45
|
+
const instance = this
|
|
46
|
+
// eslint-disable-next-line @typescript-eslint/consistent-type-assertions
|
|
47
|
+
const context = new Proxy<ICloudbaseContext>({} as ICloudbaseContext, {
|
|
48
|
+
get: (_target, prop) => {
|
|
49
|
+
if (prop === 'config') {
|
|
50
|
+
return instance.config
|
|
51
|
+
}
|
|
52
|
+
if (prop === 'request') {
|
|
53
|
+
return instance.request
|
|
54
|
+
}
|
|
55
|
+
return undefined
|
|
56
|
+
},
|
|
447
57
|
})
|
|
448
|
-
} else {
|
|
449
|
-
throw new Error(JSON.stringify({
|
|
450
|
-
code: ERRORS.INVALID_PARAMS,
|
|
451
|
-
msg: `[${COMPONENT_NAME}.getTempFileURL] invalid fileList`,
|
|
452
|
-
}),)
|
|
453
|
-
}
|
|
454
|
-
}
|
|
455
|
-
|
|
456
|
-
const action = 'storage.batchGetDownloadUrl'
|
|
457
|
-
// @ts-ignore
|
|
458
|
-
const { request } = this
|
|
459
|
-
let res: any = {}
|
|
460
|
-
|
|
461
|
-
if (this.isGateWay()) {
|
|
462
|
-
res = await storageGateWay.getDownLoadInfo(request, { convertedFileList }, params.customReqOpts)
|
|
463
|
-
} else {
|
|
464
|
-
res = await request.send(action, { file_list: convertedFileList }, params.customReqOpts)
|
|
465
|
-
}
|
|
466
|
-
|
|
467
|
-
if (res.code) {
|
|
468
|
-
return execCallback(callback, null, res)
|
|
469
|
-
}
|
|
470
|
-
|
|
471
|
-
return execCallback(callback, null, {
|
|
472
|
-
fileList: res.data.download_list,
|
|
473
|
-
requestId: res.requestId,
|
|
474
|
-
})
|
|
475
|
-
}
|
|
476
|
-
@catchErrorsDecorator({
|
|
477
|
-
customInfo: {
|
|
478
|
-
className: 'Cloudbase',
|
|
479
|
-
methodName: 'downloadFile',
|
|
480
|
-
},
|
|
481
|
-
title: '下载文件失败',
|
|
482
|
-
messages: [
|
|
483
|
-
'请确认以下各项:',
|
|
484
|
-
' 1 - 调用 downloadFile() 的语法或参数是否正确',
|
|
485
|
-
' 2 - 当前域名是否在安全域名列表中:https://console.cloud.tencent.com/tcb/env/safety',
|
|
486
|
-
' 3 - 云存储安全规则是否限制了当前登录状态访问',
|
|
487
|
-
`如果问题依然存在,建议到官方问答社区提问或寻找帮助:${COMMUNITY_SITE_URL}`,
|
|
488
|
-
],
|
|
489
|
-
})
|
|
490
|
-
public async downloadFile(
|
|
491
|
-
params: ICloudbaseDownloadFileParams,
|
|
492
|
-
callback?: Function,
|
|
493
|
-
): Promise<ICloudbaseDownloadFileResult> {
|
|
494
|
-
const { fileID } = params
|
|
495
|
-
if (!isString(fileID)) {
|
|
496
|
-
throw new Error(JSON.stringify({
|
|
497
|
-
code: ERRORS.INVALID_PARAMS,
|
|
498
|
-
msg: `[${COMPONENT_NAME}.getTempFileURL] fileID must be string`,
|
|
499
|
-
}),)
|
|
500
|
-
}
|
|
501
|
-
|
|
502
|
-
const tmpUrlRes = await this.getTempFileURL.call(this, {
|
|
503
|
-
fileList: [
|
|
504
|
-
{
|
|
505
|
-
fileID,
|
|
506
|
-
maxAge: 600,
|
|
507
|
-
},
|
|
508
|
-
],
|
|
509
|
-
customReqOpts: params.customReqOpts,
|
|
510
|
-
})
|
|
511
|
-
|
|
512
|
-
const res = tmpUrlRes.fileList[0]
|
|
513
|
-
|
|
514
|
-
if (res.code !== 'SUCCESS') {
|
|
515
|
-
return execCallback(callback, res)
|
|
516
|
-
}
|
|
517
|
-
// @ts-ignore
|
|
518
|
-
const { request } = this
|
|
519
|
-
|
|
520
|
-
const tmpUrl = encodeURI(res.download_url)
|
|
521
|
-
|
|
522
|
-
const result = await request.download({ url: tmpUrl, tempFilePath: params.tempFilePath })
|
|
523
|
-
return execCallback(callback, null, result)
|
|
524
|
-
}
|
|
525
|
-
@catchErrorsDecorator({
|
|
526
|
-
customInfo: {
|
|
527
|
-
className: 'Cloudbase',
|
|
528
|
-
methodName: 'copyFile',
|
|
529
|
-
},
|
|
530
|
-
title: '批量复制文件',
|
|
531
|
-
messages: [
|
|
532
|
-
'请确认以下各项:',
|
|
533
|
-
' 1 - 调用 copyFile() 的语法或参数是否正确',
|
|
534
|
-
' 2 - 当前域名是否在安全域名列表中:https://console.cloud.tencent.com/tcb/env/safety',
|
|
535
|
-
' 3 - 云存储安全规则是否限制了当前登录状态访问',
|
|
536
|
-
`如果问题依然存在,建议到官方问答社区提问或寻找帮助:${COMMUNITY_SITE_URL}`,
|
|
537
|
-
],
|
|
538
|
-
})
|
|
539
|
-
public async copyFile(params: ICloudbaseCopyFileParams, callback?: Function): Promise<ICloudbaseCopyFileResult> {
|
|
540
|
-
const { fileList } = params
|
|
541
|
-
|
|
542
|
-
if (!fileList || !isArray(fileList) || fileList.length === 0) {
|
|
543
|
-
throw new Error(JSON.stringify({
|
|
544
|
-
code: ERRORS.INVALID_PARAMS,
|
|
545
|
-
msg: `[${COMPONENT_NAME}.copyFile] fileList must not be empty`,
|
|
546
|
-
}),)
|
|
547
|
-
}
|
|
548
|
-
|
|
549
|
-
const convertedFileList = []
|
|
550
58
|
|
|
551
|
-
|
|
552
|
-
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
|
|
558
|
-
}
|
|
559
|
-
if (srcPath === dstPath) {
|
|
560
|
-
throw new Error(JSON.stringify({
|
|
561
|
-
code: ERRORS.INVALID_PARAMS,
|
|
562
|
-
msg: `[${COMPONENT_NAME}.copyFile] srcPath and dstPath can not be the same`,
|
|
563
|
-
}),)
|
|
564
|
-
}
|
|
565
|
-
if (basename(srcPath) !== basename(dstPath)) {
|
|
566
|
-
throw new Error(JSON.stringify({
|
|
567
|
-
code: ERRORS.INVALID_PARAMS,
|
|
568
|
-
msg: `[${COMPONENT_NAME}.copyFile] srcPath and dstPath file name must be the same`,
|
|
569
|
-
}),)
|
|
570
|
-
}
|
|
571
|
-
convertedFileList.push({
|
|
572
|
-
src_path: srcPath,
|
|
573
|
-
dst_path: dstPath,
|
|
574
|
-
overwrite: file.overwrite,
|
|
575
|
-
remove_original: file.removeOriginal,
|
|
576
|
-
})
|
|
577
|
-
}
|
|
578
|
-
|
|
579
|
-
const action = 'storage.batchCopyFile'
|
|
580
|
-
// @ts-ignore
|
|
581
|
-
const { request } = this
|
|
582
|
-
let res: any = {}
|
|
583
|
-
|
|
584
|
-
if (this.isGateWay()) {
|
|
585
|
-
res = await storageGateWay.copyFile(request, { convertedFileList }, params.customReqOpts)
|
|
586
|
-
} else {
|
|
587
|
-
res = await request.send(action, { file_list: convertedFileList }, params.customReqOpts)
|
|
588
|
-
}
|
|
589
|
-
|
|
590
|
-
if (res.code) {
|
|
591
|
-
return execCallback(callback, null, res)
|
|
592
|
-
}
|
|
593
|
-
|
|
594
|
-
return execCallback(callback, null, {
|
|
595
|
-
fileList: res.data.copy_list,
|
|
596
|
-
requestId: res.requestId,
|
|
59
|
+
// 创建新的 storage 实例并缓存
|
|
60
|
+
const storage = new SupabaseFileAPILikeStorage(context)
|
|
61
|
+
storageCache.set(this, storage)
|
|
62
|
+
return storage
|
|
63
|
+
},
|
|
64
|
+
configurable: true,
|
|
65
|
+
enumerable: true,
|
|
597
66
|
})
|
|
598
|
-
}
|
|
599
|
-
|
|
600
|
-
public async getFileInfo(params: ICloudbaseGetTempFileURLParams): Promise<ICloudbaseGetTempFileURLResult> {
|
|
601
|
-
const fileInfo = await this.getTempFileURL(params)
|
|
602
|
-
|
|
603
|
-
if (fileInfo?.fileList && fileInfo?.fileList?.length > 0) {
|
|
604
|
-
const fileList = await Promise.all(fileInfo.fileList.map(async (item: ICloudbaseGetTempFileURLResult['fileList'][0]) => {
|
|
605
|
-
if (item.code !== 'SUCCESS') {
|
|
606
|
-
return {
|
|
607
|
-
code: item.code,
|
|
608
|
-
fileID: item.fileID,
|
|
609
|
-
tempFileURL: item.tempFileURL,
|
|
610
|
-
}
|
|
611
|
-
}
|
|
612
|
-
|
|
613
|
-
try {
|
|
614
|
-
// @ts-ignore
|
|
615
|
-
const { request } = this
|
|
616
|
-
const res = await request.fetch({ url: item.tempFileURL, method: 'HEAD' })
|
|
617
|
-
|
|
618
|
-
// eslint-disable-next-line radix
|
|
619
|
-
const fileSize = parseInt(res.headers['content-length']) || 0
|
|
620
|
-
const contentType = res.headers['content-type'] || ''
|
|
621
|
-
|
|
622
|
-
const fileInfo = {
|
|
623
|
-
code: item.code,
|
|
624
|
-
fileID: item.fileID,
|
|
625
|
-
tempFileURL: item.tempFileURL,
|
|
626
|
-
cloudId: item.fileID,
|
|
627
|
-
fileName: item.fileID.split('/').pop(),
|
|
628
|
-
contentType,
|
|
629
|
-
mime: contentType.split(';')[0].trim(),
|
|
630
|
-
size: fileSize,
|
|
631
|
-
}
|
|
632
|
-
|
|
633
|
-
return fileInfo
|
|
634
|
-
} catch (e) {
|
|
635
|
-
return {
|
|
636
|
-
code: 'FETCH_FILE_INFO_ERROR',
|
|
637
|
-
fileID: item.fileID,
|
|
638
|
-
tempFileURL: item.tempFileURL,
|
|
639
|
-
}
|
|
640
|
-
}
|
|
641
|
-
}),)
|
|
642
|
-
|
|
643
|
-
return {
|
|
644
|
-
fileList,
|
|
645
|
-
requestId: fileInfo.requestId,
|
|
646
|
-
}
|
|
647
|
-
}
|
|
648
|
-
|
|
649
|
-
return {
|
|
650
|
-
fileList: [],
|
|
651
|
-
requestId: fileInfo.requestId,
|
|
652
|
-
}
|
|
653
|
-
}
|
|
654
|
-
}
|
|
655
|
-
|
|
656
|
-
const cloudbaseStorage = new CloudbaseStorage()
|
|
657
|
-
const component: ICloudbaseComponent = {
|
|
658
|
-
name: COMPONENT_NAME,
|
|
659
|
-
entity: {
|
|
660
|
-
uploadFile: cloudbaseStorage.uploadFile,
|
|
661
|
-
deleteFile: cloudbaseStorage.deleteFile,
|
|
662
|
-
getTempFileURL: cloudbaseStorage.getTempFileURL,
|
|
663
|
-
downloadFile: cloudbaseStorage.downloadFile,
|
|
664
|
-
getUploadMetadata: cloudbaseStorage.getUploadMetadata,
|
|
665
|
-
copyFile: cloudbaseStorage.copyFile,
|
|
666
|
-
getFileInfo: cloudbaseStorage.getFileInfo,
|
|
667
|
-
isGateWay: cloudbaseStorage.isGateWay,
|
|
668
67
|
},
|
|
669
68
|
}
|
|
670
69
|
|
|
671
70
|
try {
|
|
672
71
|
cloudbase.registerComponent(component)
|
|
72
|
+
cloudbase.registerComponent(supabaseComponent)
|
|
673
73
|
} catch (e) {}
|
|
674
74
|
|
|
675
75
|
export function registerStorage(app: Pick<ICloudbase, 'registerComponent'>) {
|
|
676
76
|
try {
|
|
677
77
|
app.registerComponent(component)
|
|
78
|
+
app.registerComponent(supabaseComponent)
|
|
678
79
|
} catch (e) {
|
|
679
80
|
console.warn(e)
|
|
680
81
|
}
|
|
@@ -683,4 +84,3 @@ export function registerStorage(app: Pick<ICloudbase, 'registerComponent'>) {
|
|
|
683
84
|
try {
|
|
684
85
|
(window as any).registerStorage = registerStorage
|
|
685
86
|
} catch (e) {}
|
|
686
|
-
|