@cloudbase/storage 3.0.0 → 3.0.2

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.
@@ -0,0 +1,64 @@
1
+ /// <reference types="node" />
2
+ /// <reference types="node" />
3
+ export type FileBody = ArrayBuffer | ArrayBufferView | Blob | Buffer | File | FormData | NodeJS.ReadableStream | ReadableStream<Uint8Array> | URLSearchParams | string;
4
+ export type BucketType = 'STANDARD' | 'ANALYTICS';
5
+ export interface Bucket {
6
+ id: string;
7
+ type?: BucketType;
8
+ name: string;
9
+ owner: string;
10
+ file_size_limit?: number;
11
+ allowed_mime_types?: string[];
12
+ created_at: string;
13
+ updated_at: string;
14
+ public: boolean;
15
+ }
16
+ export interface FileObject {
17
+ name: string;
18
+ bucket_id: string;
19
+ owner: string;
20
+ id: string;
21
+ updated_at: string;
22
+ created_at: string;
23
+ last_accessed_at: string;
24
+ metadata: Record<string, any>;
25
+ buckets: Bucket;
26
+ }
27
+ export interface FileObjectV2 {
28
+ id: string;
29
+ version: string;
30
+ name: string;
31
+ bucket_id: string;
32
+ updated_at: string;
33
+ created_at: string;
34
+ last_accessed_at: string;
35
+ size?: number;
36
+ cache_control?: string;
37
+ content_type?: string;
38
+ etag?: string;
39
+ last_modified?: string;
40
+ metadata?: Record<string, any>;
41
+ }
42
+ export interface FileOptions {
43
+ cacheControl?: string;
44
+ contentType?: string;
45
+ upsert?: boolean;
46
+ duplex?: string;
47
+ metadata?: Record<string, any>;
48
+ headers?: Record<string, string>;
49
+ }
50
+ export interface DestinationOptions {
51
+ destinationBucket?: string;
52
+ }
53
+ export interface TransformOptions {
54
+ width?: number;
55
+ height?: number;
56
+ resize?: 'cover' | 'contain' | 'fill';
57
+ quality?: number;
58
+ format?: 'origin';
59
+ }
60
+ type CamelCase<S extends string> = S extends `${infer P1}_${infer P2}${infer P3}` ? `${Lowercase<P1>}${Uppercase<P2>}${CamelCase<P3>}` : S;
61
+ export type Camelize<T> = {
62
+ [K in keyof T as CamelCase<Extract<K, string>>]: T[K];
63
+ };
64
+ export {};
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidHlwZXMuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi9zcmMvc3VwYWJhc2UvdHlwZXMudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IiIsInNvdXJjZXNDb250ZW50IjpbImV4cG9ydCB0eXBlIEZpbGVCb2R5ID1cbiAgfCBBcnJheUJ1ZmZlclxuICB8IEFycmF5QnVmZmVyVmlld1xuICB8IEJsb2JcbiAgfCBCdWZmZXJcbiAgfCBGaWxlXG4gIHwgRm9ybURhdGFcbiAgfCBOb2RlSlMuUmVhZGFibGVTdHJlYW1cbiAgfCBSZWFkYWJsZVN0cmVhbTxVaW50OEFycmF5PlxuICB8IFVSTFNlYXJjaFBhcmFtc1xuICB8IHN0cmluZ1xuXG4vKipcbiAqIFR5cGUgb2Ygc3RvcmFnZSBidWNrZXRcbiAqIC0gU1RBTkRBUkQ6IFJlZ3VsYXIgZmlsZSBzdG9yYWdlIGJ1Y2tldHNcbiAqIC0gQU5BTFlUSUNTOiBJY2ViZXJnIHRhYmxlLWJhc2VkIGJ1Y2tldHMgZm9yIGFuYWx5dGljYWwgd29ya2xvYWRzXG4gKi9cbmV4cG9ydCB0eXBlIEJ1Y2tldFR5cGUgPSAnU1RBTkRBUkQnIHwgJ0FOQUxZVElDUydcblxuZXhwb3J0IGludGVyZmFjZSBCdWNrZXQge1xuICBpZDogc3RyaW5nXG4gIHR5cGU/OiBCdWNrZXRUeXBlXG4gIG5hbWU6IHN0cmluZ1xuICBvd25lcjogc3RyaW5nXG4gIGZpbGVfc2l6ZV9saW1pdD86IG51bWJlclxuICBhbGxvd2VkX21pbWVfdHlwZXM/OiBzdHJpbmdbXVxuICBjcmVhdGVkX2F0OiBzdHJpbmdcbiAgdXBkYXRlZF9hdDogc3RyaW5nXG4gIHB1YmxpYzogYm9vbGVhblxufVxuXG5leHBvcnQgaW50ZXJmYWNlIEZpbGVPYmplY3Qge1xuICBuYW1lOiBzdHJpbmdcbiAgYnVja2V0X2lkOiBzdHJpbmdcbiAgb3duZXI6IHN0cmluZ1xuICBpZDogc3RyaW5nXG4gIHVwZGF0ZWRfYXQ6IHN0cmluZ1xuICBjcmVhdGVkX2F0OiBzdHJpbmdcbiAgLyoqIEBkZXByZWNhdGVkICovXG4gIGxhc3RfYWNjZXNzZWRfYXQ6IHN0cmluZ1xuICBtZXRhZGF0YTogUmVjb3JkPHN0cmluZywgYW55PlxuICBidWNrZXRzOiBCdWNrZXRcbn1cblxuZXhwb3J0IGludGVyZmFjZSBGaWxlT2JqZWN0VjIge1xuICBpZDogc3RyaW5nXG4gIHZlcnNpb246IHN0cmluZ1xuICBuYW1lOiBzdHJpbmdcbiAgYnVja2V0X2lkOiBzdHJpbmdcbiAgdXBkYXRlZF9hdDogc3RyaW5nXG4gIGNyZWF0ZWRfYXQ6IHN0cmluZ1xuICAvKiogQGRlcHJlY2F0ZWQgKi9cbiAgbGFzdF9hY2Nlc3NlZF9hdDogc3RyaW5nXG4gIHNpemU/OiBudW1iZXJcbiAgY2FjaGVfY29udHJvbD86IHN0cmluZ1xuICBjb250ZW50X3R5cGU/OiBzdHJpbmdcbiAgZXRhZz86IHN0cmluZ1xuICBsYXN0X21vZGlmaWVkPzogc3RyaW5nXG4gIG1ldGFkYXRhPzogUmVjb3JkPHN0cmluZywgYW55PlxufVxuXG5leHBvcnQgaW50ZXJmYWNlIEZpbGVPcHRpb25zIHtcbiAgLyoqXG4gICAqIFRoZSBudW1iZXIgb2Ygc2Vjb25kcyB0aGUgYXNzZXQgaXMgY2FjaGVkIGluIHRoZSBicm93c2VyIGFuZCBpbiB0aGUgU3VwYWJhc2UgQ0ROLiBUaGlzIGlzIHNldCBpbiB0aGUgYENhY2hlLUNvbnRyb2w6IG1heC1hZ2U9PHNlY29uZHM+YCBoZWFkZXIuIERlZmF1bHRzIHRvIDM2MDAgc2Vjb25kcy5cbiAgICovXG4gIGNhY2hlQ29udHJvbD86IHN0cmluZ1xuICAvKipcbiAgICogdGhlIGBDb250ZW50LVR5cGVgIGhlYWRlciB2YWx1ZS4gU2hvdWxkIGJlIHNwZWNpZmllZCBpZiB1c2luZyBhIGBmaWxlQm9keWAgdGhhdCBpcyBuZWl0aGVyIGBCbG9iYCBub3IgYEZpbGVgIG5vciBgRm9ybURhdGFgLCBvdGhlcndpc2Ugd2lsbCBkZWZhdWx0IHRvIGB0ZXh0L3BsYWluO2NoYXJzZXQ9VVRGLThgLlxuICAgKi9cbiAgY29udGVudFR5cGU/OiBzdHJpbmdcbiAgLyoqXG4gICAqIFdoZW4gdXBzZXJ0IGlzIHNldCB0byB0cnVlLCB0aGUgZmlsZSBpcyBvdmVyd3JpdHRlbiBpZiBpdCBleGlzdHMuIFdoZW4gc2V0IHRvIGZhbHNlLCBhbiBlcnJvciBpcyB0aHJvd24gaWYgdGhlIG9iamVjdCBhbHJlYWR5IGV4aXN0cy4gRGVmYXVsdHMgdG8gdHJ1ZS5cbiAgICovXG4gIHVwc2VydD86IGJvb2xlYW5cbiAgLyoqXG4gICAqIFRoZSBkdXBsZXggb3B0aW9uIGlzIGEgc3RyaW5nIHBhcmFtZXRlciB0aGF0IGVuYWJsZXMgb3IgZGlzYWJsZXMgZHVwbGV4IHN0cmVhbWluZywgYWxsb3dpbmcgZm9yIGJvdGggcmVhZGluZyBhbmQgd3JpdGluZyBkYXRhIGluIHRoZSBzYW1lIHN0cmVhbS4gSXQgY2FuIGJlIHBhc3NlZCBhcyBhbiBvcHRpb24gdG8gdGhlIGZldGNoKCkgbWV0aG9kLlxuICAgKi9cbiAgZHVwbGV4Pzogc3RyaW5nXG5cbiAgLyoqXG4gICAqIFRoZSBtZXRhZGF0YSBvcHRpb24gaXMgYW4gb2JqZWN0IHRoYXQgYWxsb3dzIHlvdSB0byBzdG9yZSBhZGRpdGlvbmFsIGluZm9ybWF0aW9uIGFib3V0IHRoZSBmaWxlLiBUaGlzIGluZm9ybWF0aW9uIGNhbiBiZSB1c2VkIHRvIGZpbHRlciBhbmQgc2VhcmNoIGZvciBmaWxlcy4gVGhlIG1ldGFkYXRhIG9iamVjdCBjYW4gY29udGFpbiBhbnkga2V5LXZhbHVlIHBhaXJzIHlvdSB3YW50IHRvIHN0b3JlLlxuICAgKi9cbiAgbWV0YWRhdGE/OiBSZWNvcmQ8c3RyaW5nLCBhbnk+XG5cbiAgLyoqXG4gICAqIE9wdGlvbmFsbHkgYWRkIGV4dHJhIGhlYWRlcnNcbiAgICovXG4gIGhlYWRlcnM/OiBSZWNvcmQ8c3RyaW5nLCBzdHJpbmc+XG59XG5cbmV4cG9ydCBpbnRlcmZhY2UgRGVzdGluYXRpb25PcHRpb25zIHtcbiAgZGVzdGluYXRpb25CdWNrZXQ/OiBzdHJpbmdcbn1cblxuZXhwb3J0IGludGVyZmFjZSBUcmFuc2Zvcm1PcHRpb25zIHtcbiAgLyoqXG4gICAqIFRoZSB3aWR0aCBvZiB0aGUgaW1hZ2UgaW4gcGl4ZWxzLlxuICAgKi9cbiAgd2lkdGg/OiBudW1iZXJcbiAgLyoqXG4gICAqIFRoZSBoZWlnaHQgb2YgdGhlIGltYWdlIGluIHBpeGVscy5cbiAgICovXG4gIGhlaWdodD86IG51bWJlclxuICAvKipcbiAgICogVGhlIHJlc2l6ZSBtb2RlIGNhbiBiZSBjb3ZlciwgY29udGFpbiBvciBmaWxsLiBEZWZhdWx0cyB0byBjb3Zlci5cbiAgICogQ292ZXIgcmVzaXplcyB0aGUgaW1hZ2UgdG8gbWFpbnRhaW4gaXQncyBhc3BlY3QgcmF0aW8gd2hpbGUgZmlsbGluZyB0aGUgZW50aXJlIHdpZHRoIGFuZCBoZWlnaHQuXG4gICAqIENvbnRhaW4gcmVzaXplcyB0aGUgaW1hZ2UgdG8gbWFpbnRhaW4gaXQncyBhc3BlY3QgcmF0aW8gd2hpbGUgZml0dGluZyB0aGUgZW50aXJlIGltYWdlIHdpdGhpbiB0aGUgd2lkdGggYW5kIGhlaWdodC5cbiAgICogRmlsbCByZXNpemVzIHRoZSBpbWFnZSB0byBmaWxsIHRoZSBlbnRpcmUgd2lkdGggYW5kIGhlaWdodC4gSWYgdGhlIG9iamVjdCdzIGFzcGVjdCByYXRpbyBkb2VzIG5vdCBtYXRjaCB0aGUgd2lkdGggYW5kIGhlaWdodCwgdGhlIGltYWdlIHdpbGwgYmUgc3RyZXRjaGVkIHRvIGZpdC5cbiAgICovXG4gIHJlc2l6ZT86ICdjb3ZlcicgfCAnY29udGFpbicgfCAnZmlsbCdcbiAgLyoqXG4gICAqIFNldCB0aGUgcXVhbGl0eSBvZiB0aGUgcmV0dXJuZWQgaW1hZ2UuXG4gICAqIEEgbnVtYmVyIGZyb20gMjAgdG8gMTAwLCB3aXRoIDEwMCBiZWluZyB0aGUgaGlnaGVzdCBxdWFsaXR5LlxuICAgKiBEZWZhdWx0cyB0byA4MFxuICAgKi9cbiAgcXVhbGl0eT86IG51bWJlclxuICAvKipcbiAgICogU3BlY2lmeSB0aGUgZm9ybWF0IG9mIHRoZSBpbWFnZSByZXF1ZXN0ZWQuXG4gICAqXG4gICAqIFdoZW4gdXNpbmcgJ29yaWdpbicgd2UgZm9yY2UgdGhlIGZvcm1hdCB0byBiZSB0aGUgc2FtZSBhcyB0aGUgb3JpZ2luYWwgaW1hZ2UuXG4gICAqIFdoZW4gdGhpcyBvcHRpb24gaXMgbm90IHBhc3NlZCBpbiwgaW1hZ2VzIGFyZSBvcHRpbWl6ZWQgdG8gbW9kZXJuIGltYWdlIGZvcm1hdHMgbGlrZSBXZWJwLlxuICAgKi9cbiAgZm9ybWF0PzogJ29yaWdpbidcbn1cblxudHlwZSBDYW1lbENhc2U8UyBleHRlbmRzIHN0cmluZz4gPSBTIGV4dGVuZHMgYCR7aW5mZXIgUDF9XyR7aW5mZXIgUDJ9JHtpbmZlciBQM31gXG4gID8gYCR7TG93ZXJjYXNlPFAxPn0ke1VwcGVyY2FzZTxQMj59JHtDYW1lbENhc2U8UDM+fWBcbiAgOiBTXG5cbmV4cG9ydCB0eXBlIENhbWVsaXplPFQ+ID0ge1xuICBbSyBpbiBrZXlvZiBUIGFzIENhbWVsQ2FzZTxFeHRyYWN0PEssIHN0cmluZz4+XTogVFtLXVxufVxuIl19
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@cloudbase/storage",
3
- "version": "3.0.0",
3
+ "version": "3.0.2",
4
4
  "description": "cloudbase js sdk storage module",
5
5
  "main": "dist/cjs/index.js",
6
6
  "module": "dist/esm/index.js",
@@ -27,8 +27,8 @@
27
27
  "author": "",
28
28
  "license": "Apache-2.0",
29
29
  "dependencies": {
30
- "@cloudbase/types": "3.0.0",
31
- "@cloudbase/utilities": "3.0.0"
30
+ "@cloudbase/types": "3.0.2",
31
+ "@cloudbase/utilities": "3.0.2"
32
32
  },
33
- "gitHead": "a70e7266db7be901d909b1fa63c1651e2a7943e4"
33
+ "gitHead": "56b879a3e173e64e44ca36c1260b3fc66d0e822a"
34
34
  }
package/src/index.ts CHANGED
@@ -1,358 +1,86 @@
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
- ICloudbaseFileMetaDataRes,
6
- ICloudbaseFileInfo,
7
- ICloudbaseUploadFileParams,
8
- ICloudbaseUploadFileResult,
9
- ICloudbaseGetUploadMetadataParams,
10
- ICloudbaseDeleteFileParams,
11
- ICloudbaseDeleteFileResult,
12
- ICloudbaseGetTempFileURLResult,
13
- ICloudbaseGetTempFileURLParams,
14
- ICloudbaseDownloadFileResult,
15
- ICloudbaseDownloadFileParams,
16
- } from '@cloudbase/types/storage'
3
+ import { CloudbaseStorage, COMPONENT_NAME, ICloudbaseContext } from './storage'
4
+ import { SupabaseFileAPILikeStorage } from './supabase'
17
5
 
18
6
  declare const cloudbase: ICloudbase
19
7
 
20
- enum EUploadMethod {
21
- put = 'put',
22
- post = 'post'
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,
20
+ },
23
21
  }
24
22
 
25
- const { getSdkName, ERRORS, COMMUNITY_SITE_URL } = constants
26
- const { isArray, isString, isPalinObject, execCallback } = utils
27
- const { catchErrorsDecorator } = helpers
28
-
29
- const COMPONENT_NAME = 'storage'
30
-
31
- class CloudbaseStorage {
32
- @catchErrorsDecorator({
33
- customInfo: {
34
- className: 'Cloudbase',
35
- methodName: 'uploadFile',
36
- },
37
- title: '上传文件失败',
38
- messages: [
39
- '请确认以下各项:',
40
- ' 1 - 调用 uploadFile() 的语法或参数是否正确',
41
- ' 2 - 当前域名是否在安全域名列表中:https://console.cloud.tencent.com/tcb/env/safety',
42
- ' 3 - 云存储安全规则是否限制了当前登录状态访问',
43
- `如果问题依然存在,建议到官方问答社区提问或寻找帮助:${COMMUNITY_SITE_URL}`,
44
- ],
45
- })
46
- public async uploadFile(
47
- params: ICloudbaseUploadFileParams,
48
- callback?: Function
49
- ): Promise<ICloudbaseUploadFileResult> {
50
- const { cloudPath, filePath, onUploadProgress, method = 'put', headers = {} } = params
51
- if (!isString(cloudPath) || !filePath) {
52
- throw new Error(JSON.stringify({
53
- code: ERRORS.INVALID_PARAMS,
54
- msg: `[${COMPONENT_NAME}.uploadFile] invalid params`,
55
- }))
56
- }
57
- const uploadMethod = { put: EUploadMethod.put, post: EUploadMethod.post }[method.toLocaleLowerCase()] || EUploadMethod.put
58
-
59
- const action = 'storage.getUploadMetadata'
60
- // @ts-ignore
61
- const { request } = this
62
- const metaDataParam = {
63
- path: cloudPath,
64
- method: uploadMethod,
65
- }
66
- if (uploadMethod === EUploadMethod.put) {
67
- /* eslint-disable-next-line */
68
- metaDataParam["headers"] = headers
69
- }
70
- const metaData: ICloudbaseFileMetaDataRes = await request.send(action, metaDataParam)
71
-
72
- const {
73
- data: { url, authorization, token, fileId, cosFileId, download_url: downloadUrl },
74
- requestId,
75
- } = metaData
76
-
77
- const commonParams = {
78
- url,
79
- file: filePath,
80
- name: cloudPath,
81
- onUploadProgress,
82
- }
83
-
84
- const putParams = {
85
- ...commonParams,
86
- method: EUploadMethod.put,
87
- headers: {
88
- ...headers,
89
- authorization,
90
- 'x-cos-meta-fileid': cosFileId,
91
- 'x-cos-security-token': token,
92
- },
93
- }
94
-
95
- const postParams = {
96
- ...commonParams,
97
- method: EUploadMethod.post,
98
- data: {
99
- key: cloudPath,
100
- signature: authorization,
101
- 'x-cos-meta-fileid': cosFileId,
102
- success_action_status: '201',
103
- 'x-cos-security-token': token,
104
- },
105
- }
106
-
107
- const uploadConfig = {
108
- [EUploadMethod.put]: {
109
- params: putParams,
110
- isSuccess: (code: number) => code >= 200 && code < 300,
111
- },
112
- [EUploadMethod.post]: {
113
- params: postParams,
114
- isSuccess: (code: number) => code === 201,
115
- },
116
- }
117
-
118
- const res = await request.upload(uploadConfig[uploadMethod].params)
119
-
120
- if (uploadConfig[uploadMethod].isSuccess(res.statusCode)) {
121
- return execCallback(callback, null, {
122
- fileID: fileId,
123
- download_url: downloadUrl,
124
- requestId,
125
- })
126
- }
127
- return execCallback(callback, new Error(`[${getSdkName()}][${ERRORS.OPERATION_FAIL}][${COMPONENT_NAME}]:${res.data}`))
128
- }
129
- @catchErrorsDecorator({
130
- customInfo: {
131
- className: 'Cloudbase',
132
- methodName: 'getUploadMetadata',
133
- },
134
- title: '获取上传元信息失败',
135
- messages: [
136
- '请确认以下各项:',
137
- ' 1 - 调用 getUploadMetadata() 的语法或参数是否正确',
138
- ' 2 - 当前域名是否在安全域名列表中:https://console.cloud.tencent.com/tcb/env/safety',
139
- ' 3 - 云存储安全规则是否限制了当前登录状态访问',
140
- `如果问题依然存在,建议到官方问答社区提问或寻找帮助:${COMMUNITY_SITE_URL}`,
141
- ],
142
- })
143
- public async getUploadMetadata(
144
- params: ICloudbaseGetUploadMetadataParams,
145
- callback?: Function
146
- ): Promise<any> {
147
- const { cloudPath } = params
148
- if (!isString(cloudPath)) {
149
- throw new Error(JSON.stringify({
150
- code: ERRORS.INVALID_PARAMS,
151
- msg: `[${COMPONENT_NAME}.getUploadMetadata] invalid cloudPath`,
152
- }))
153
- }
154
- // @ts-ignore
155
- const { request } = this
156
- const action = 'storage.getUploadMetadata'
157
-
158
- try {
159
- const metaData = await request.send(action, {
160
- path: cloudPath,
161
- })
162
- return execCallback(callback, null, metaData)
163
- } catch (err) {
164
- return execCallback(callback, err)
165
- }
166
- }
167
- @catchErrorsDecorator({
168
- customInfo: {
169
- className: 'Cloudbase',
170
- methodName: 'deleteFile',
171
- },
172
- title: '删除文件失败',
173
- messages: [
174
- '请确认以下各项:',
175
- ' 1 - 调用 deleteFile() 的语法或参数是否正确',
176
- ' 2 - 当前域名是否在安全域名列表中:https://console.cloud.tencent.com/tcb/env/safety',
177
- ' 3 - 云存储安全规则是否限制了当前登录状态访问',
178
- `如果问题依然存在,建议到官方问答社区提问或寻找帮助:${COMMUNITY_SITE_URL}`,
179
- ],
180
- })
181
- public async deleteFile(
182
- params: ICloudbaseDeleteFileParams,
183
- callback?: Function
184
- ): Promise<ICloudbaseDeleteFileResult> {
185
- const { fileList } = params
186
-
187
- if (!fileList || !isArray(fileList) || fileList.length === 0) {
188
- throw new Error(JSON.stringify({
189
- code: ERRORS.INVALID_PARAMS,
190
- msg: `[${COMPONENT_NAME}.deleteFile] fileList must not be empty`,
191
- }))
192
- }
193
-
194
- for (const fileId of fileList) {
195
- if (!fileId || !isString(fileId)) {
196
- throw new Error(JSON.stringify({
197
- code: ERRORS.INVALID_PARAMS,
198
- msg: `[${COMPONENT_NAME}.deleteFile] fileID must be string`,
199
- }))
200
- }
201
- }
23
+ const supabaseComponent: ICloudbaseComponent = {
24
+ name: `${COMPONENT_NAME}/supabase`,
25
+ IIFE: true,
26
+ entity() {
27
+ // IIFE 中,this 是 Cloudbase 类(构造函数),不是实例
28
+ // 所以我们需要使用 getter 来延迟获取实例的 config 和 request
202
29
 
203
- const action = 'storage.batchDeleteFile'
204
- // @ts-ignore
205
- const { request } = this
206
- const res = await request.send(action, {
207
- fileid_list: fileList,
208
- })
209
-
210
- if (res.code) {
211
- return execCallback(callback, null, res)
212
- }
213
- const data = {
214
- fileList: res.data.delete_list,
215
- requestId: res.requestId,
216
- }
217
- return execCallback(callback, null, data)
218
- }
219
- @catchErrorsDecorator({
220
- customInfo: {
221
- className: 'Cloudbase',
222
- methodName: 'getTempFileURL',
223
- },
224
- title: '获取文件下载链接',
225
- messages: [
226
- '请确认以下各项:',
227
- ' 1 - 调用 getTempFileURL() 的语法或参数是否正确',
228
- ' 2 - 当前域名是否在安全域名列表中:https://console.cloud.tencent.com/tcb/env/safety',
229
- ' 3 - 云存储安全规则是否限制了当前登录状态访问',
230
- `如果问题依然存在,建议到官方问答社区提问或寻找帮助:${COMMUNITY_SITE_URL}`,
231
- ],
232
- })
233
- public async getTempFileURL(
234
- params: ICloudbaseGetTempFileURLParams,
235
- callback?: Function
236
- ): Promise<ICloudbaseGetTempFileURLResult> {
237
- const { fileList } = params
30
+ // 使用 WeakMap 缓存每个实例的 storage 对象
31
+ const storageCache = new WeakMap<any, SupabaseFileAPILikeStorage>()
238
32
 
239
- if (!fileList || !isArray(fileList) || fileList.length === 0) {
240
- throw new Error(JSON.stringify({
241
- code: ERRORS.INVALID_PARAMS,
242
- msg: `[${COMPONENT_NAME}.getTempFileURL] fileList must not be empty`,
243
- }))
244
- }
33
+ // 定义 storage 属性的 getter,每个实例只创建一次
34
+ Object.defineProperty(this.prototype, 'storage', {
35
+ get() {
36
+ // 这里的 this cloudbase 实例
245
37
 
246
- const convertedFileList = []
247
- for (const file of fileList) {
248
- if (isPalinObject(file)) {
249
- if (!Object.prototype.hasOwnProperty.call(file, 'fileID')
250
- || !Object.prototype.hasOwnProperty.call(file, 'maxAge')) {
251
- throw new Error(JSON.stringify({
252
- code: ERRORS.INVALID_PARAMS,
253
- msg: `[${COMPONENT_NAME}.getTempFileURL] file info must include fileID and maxAge`,
254
- }))
38
+ // 如果已经创建过,直接返回缓存的实例
39
+ if (storageCache.has(this)) {
40
+ return storageCache.get(this)
255
41
  }
256
42
 
257
- convertedFileList.push({
258
- fileid: (file as ICloudbaseFileInfo).fileID,
259
- max_age: (file as ICloudbaseFileInfo).maxAge,
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
+ },
260
57
  })
261
- } else if (isString(file)) {
262
- convertedFileList.push({
263
- fileid: file,
264
- })
265
- } else {
266
- throw new Error(JSON.stringify({
267
- code: ERRORS.INVALID_PARAMS,
268
- msg: `[${COMPONENT_NAME}.getTempFileURL] invalid fileList`,
269
- }))
270
- }
271
- }
272
-
273
- const action = 'storage.batchGetDownloadUrl'
274
- // @ts-ignore
275
- const { request } = this
276
-
277
- const res = await request.send(action, { file_list: convertedFileList })
278
58
 
279
- if (res.code) {
280
- return execCallback(callback, null, res)
281
- }
282
-
283
- return execCallback(callback, null, {
284
- fileList: res.data.download_list,
285
- requestId: res.requestId,
286
- })
287
- }
288
- @catchErrorsDecorator({
289
- customInfo: {
290
- className: 'Cloudbase',
291
- methodName: 'downloadFile',
292
- },
293
- title: '下载文件失败',
294
- messages: [
295
- '请确认以下各项:',
296
- ' 1 - 调用 downloadFile() 的语法或参数是否正确',
297
- ' 2 - 当前域名是否在安全域名列表中:https://console.cloud.tencent.com/tcb/env/safety',
298
- ' 3 - 云存储安全规则是否限制了当前登录状态访问',
299
- `如果问题依然存在,建议到官方问答社区提问或寻找帮助:${COMMUNITY_SITE_URL}`,
300
- ],
301
- })
302
- public async downloadFile(
303
- params: ICloudbaseDownloadFileParams,
304
- callback?: Function
305
- ): Promise<ICloudbaseDownloadFileResult> {
306
- const { fileID } = params
307
- if (!isString(fileID)) {
308
- throw new Error(JSON.stringify({
309
- code: ERRORS.INVALID_PARAMS,
310
- msg: `[${COMPONENT_NAME}.getTempFileURL] fileID must be string`,
311
- }))
312
- }
313
-
314
- const tmpUrlRes = await this.getTempFileURL.call(this, {
315
- fileList: [{
316
- fileID,
317
- maxAge: 600,
318
- }],
59
+ // 创建新的 storage 实例并缓存
60
+ const storage = new SupabaseFileAPILikeStorage(context)
61
+ storageCache.set(this, storage)
62
+ return storage
63
+ },
64
+ configurable: true,
65
+ enumerable: true,
319
66
  })
320
-
321
- const res = tmpUrlRes.fileList[0]
322
-
323
- if (res.code !== 'SUCCESS') {
324
- return execCallback(callback, res)
325
- }
326
- // @ts-ignore
327
- const { request } = this
328
-
329
- const tmpUrl = encodeURI(res.download_url)
330
-
331
- const result = await request.download({ url: tmpUrl })
332
- return execCallback(callback, null, result)
333
- }
334
- }
335
-
336
- const cloudbaseStorage = new CloudbaseStorage()
337
- const component: ICloudbaseComponent = {
338
- name: COMPONENT_NAME,
339
- entity: {
340
- uploadFile: cloudbaseStorage.uploadFile,
341
- deleteFile: cloudbaseStorage.deleteFile,
342
- getTempFileURL: cloudbaseStorage.getTempFileURL,
343
- downloadFile: cloudbaseStorage.downloadFile,
344
- getUploadMetadata: cloudbaseStorage.getUploadMetadata,
345
67
  },
346
68
  }
347
69
 
348
70
  try {
349
71
  cloudbase.registerComponent(component)
350
- } catch (e) { }
72
+ cloudbase.registerComponent(supabaseComponent)
73
+ } catch (e) {}
351
74
 
352
75
  export function registerStorage(app: Pick<ICloudbase, 'registerComponent'>) {
353
76
  try {
354
77
  app.registerComponent(component)
78
+ app.registerComponent(supabaseComponent)
355
79
  } catch (e) {
356
80
  console.warn(e)
357
81
  }
358
82
  }
83
+
84
+ try {
85
+ (window as any).registerStorage = registerStorage
86
+ } catch (e) {}