@cloudbase/storage 2.23.4-alpha.0 → 2.24.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/dist/cjs/index.js +51 -712
- package/dist/cjs/storage.d.ts +53 -0
- package/dist/cjs/storage.js +718 -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 +141 -0
- package/dist/cjs/supabase/index.js +689 -0
- package/dist/cjs/supabase/types.d.ts +64 -0
- package/dist/cjs/supabase/types.js +3 -0
- package/dist/esm/index.js +51 -712
- package/dist/esm/storage.d.ts +53 -0
- package/dist/esm/storage.js +715 -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 +141 -0
- package/dist/esm/supabase/index.js +686 -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 +56 -650
- package/src/storage.ts +698 -0
- package/src/supabase/errors.ts +43 -0
- package/src/supabase/index.ts +730 -0
- package/src/supabase/types.ts +132 -0
package/src/index.ts
CHANGED
|
@@ -1,680 +1,87 @@
|
|
|
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
|
-
const { isArray, isString, isPalinObject, execCallback } = utils
|
|
29
|
-
const { catchErrorsDecorator } = helpers
|
|
30
|
-
|
|
31
|
-
const COMPONENT_NAME = 'storage'
|
|
32
|
-
|
|
33
|
-
function basename(path) {
|
|
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
|
-
},
|
|
8
|
+
const component: ICloudbaseComponent = {
|
|
9
|
+
name: COMPONENT_NAME,
|
|
10
|
+
entity() {
|
|
11
|
+
const context: ICloudbaseContext = {
|
|
12
|
+
config: this.config,
|
|
13
|
+
request: this.request,
|
|
126
14
|
}
|
|
127
|
-
|
|
128
|
-
return
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
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
|
-
},
|
|
15
|
+
const storage = new CloudbaseStorage(context)
|
|
16
|
+
return {
|
|
17
|
+
uploadFile: storage.uploadFile.bind(storage),
|
|
18
|
+
deleteFile: storage.deleteFile.bind(storage),
|
|
19
|
+
getTempFileURL: storage.getTempFileURL.bind(storage),
|
|
20
|
+
downloadFile: storage.downloadFile.bind(storage),
|
|
21
|
+
getUploadMetadata: storage.getUploadMetadata.bind(storage),
|
|
22
|
+
copyFile: storage.copyFile.bind(storage),
|
|
23
|
+
getFileInfo: storage.getFileInfo.bind(storage),
|
|
24
|
+
isGateWay: storage.isGateWay.bind(storage),
|
|
159
25
|
}
|
|
160
|
-
|
|
161
|
-
return res
|
|
162
26
|
},
|
|
163
27
|
}
|
|
164
28
|
|
|
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
|
-
}
|
|
215
|
-
|
|
216
|
-
let metaData: ICloudbaseFileMetaDataRes = {} as any
|
|
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
|
|
357
|
-
|
|
358
|
-
if (!fileList || !isArray(fileList) || fileList.length === 0) {
|
|
359
|
-
throw new Error(JSON.stringify({
|
|
360
|
-
code: ERRORS.INVALID_PARAMS,
|
|
361
|
-
msg: `[${COMPONENT_NAME}.deleteFile] fileList must not be empty`,
|
|
362
|
-
}),)
|
|
363
|
-
}
|
|
364
|
-
|
|
365
|
-
for (const fileId of fileList) {
|
|
366
|
-
if (!fileId || !isString(fileId)) {
|
|
367
|
-
throw new Error(JSON.stringify({
|
|
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
|
-
}
|
|
29
|
+
const supabaseComponent: ICloudbaseComponent = {
|
|
30
|
+
name: `${COMPONENT_NAME}/supabase`,
|
|
31
|
+
IIFE: true,
|
|
32
|
+
entity() {
|
|
33
|
+
// 在 IIFE 中,this 是 Cloudbase 类(构造函数),不是实例
|
|
34
|
+
// 所以我们需要使用 getter 来延迟获取实例的 config 和 request
|
|
390
35
|
|
|
391
|
-
|
|
392
|
-
|
|
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
|
|
36
|
+
// 使用 WeakMap 缓存每个实例的 storage 对象
|
|
37
|
+
const storageCache = new WeakMap<any, SupabaseFileAPILikeStorage>()
|
|
419
38
|
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
}),)
|
|
425
|
-
}
|
|
39
|
+
// 定义 storage 属性的 getter,每个实例只创建一次
|
|
40
|
+
Object.defineProperty(this.prototype, 'storage', {
|
|
41
|
+
get() {
|
|
42
|
+
// 这里的 this 是 cloudbase 实例
|
|
426
43
|
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
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
|
-
}),)
|
|
44
|
+
// 如果已经创建过,直接返回缓存的实例
|
|
45
|
+
if (storageCache.has(this)) {
|
|
46
|
+
return storageCache.get(this)
|
|
438
47
|
}
|
|
439
48
|
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
49
|
+
// 创建动态 context,从当前实例获取 config 和 request
|
|
50
|
+
// eslint-disable-next-line @typescript-eslint/no-this-alias
|
|
51
|
+
const instance = this
|
|
52
|
+
// eslint-disable-next-line @typescript-eslint/consistent-type-assertions
|
|
53
|
+
const context = new Proxy<ICloudbaseContext>({} as ICloudbaseContext, {
|
|
54
|
+
get: (_target, prop) => {
|
|
55
|
+
if (prop === 'config') {
|
|
56
|
+
return instance.config
|
|
57
|
+
}
|
|
58
|
+
if (prop === 'request') {
|
|
59
|
+
return instance.request
|
|
60
|
+
}
|
|
61
|
+
return undefined
|
|
62
|
+
},
|
|
447
63
|
})
|
|
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
64
|
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
|
|
545
|
-
|
|
546
|
-
}
|
|
547
|
-
|
|
548
|
-
|
|
549
|
-
const convertedFileList = []
|
|
550
|
-
|
|
551
|
-
for (const file of fileList) {
|
|
552
|
-
const { srcPath, dstPath } = file
|
|
553
|
-
if (!srcPath || !dstPath || typeof srcPath !== 'string' || typeof dstPath !== 'string') {
|
|
554
|
-
throw new Error(JSON.stringify({
|
|
555
|
-
code: ERRORS.INVALID_PARAMS,
|
|
556
|
-
msg: `[${COMPONENT_NAME}.copyFile] srcPath and dstPath may not be empty`,
|
|
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,
|
|
65
|
+
// 创建新的 storage 实例并缓存
|
|
66
|
+
const storage = new SupabaseFileAPILikeStorage(context)
|
|
67
|
+
storageCache.set(this, storage)
|
|
68
|
+
return storage
|
|
69
|
+
},
|
|
70
|
+
configurable: true,
|
|
71
|
+
enumerable: true,
|
|
597
72
|
})
|
|
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
73
|
},
|
|
669
74
|
}
|
|
670
75
|
|
|
671
76
|
try {
|
|
672
77
|
cloudbase.registerComponent(component)
|
|
78
|
+
cloudbase.registerComponent(supabaseComponent)
|
|
673
79
|
} catch (e) {}
|
|
674
80
|
|
|
675
81
|
export function registerStorage(app: Pick<ICloudbase, 'registerComponent'>) {
|
|
676
82
|
try {
|
|
677
83
|
app.registerComponent(component)
|
|
84
|
+
app.registerComponent(supabaseComponent)
|
|
678
85
|
} catch (e) {
|
|
679
86
|
console.warn(e)
|
|
680
87
|
}
|
|
@@ -683,4 +90,3 @@ export function registerStorage(app: Pick<ICloudbase, 'registerComponent'>) {
|
|
|
683
90
|
try {
|
|
684
91
|
(window as any).registerStorage = registerStorage
|
|
685
92
|
} catch (e) {}
|
|
686
|
-
|