@naturalcycles/cloud-storage-lib 1.7.0 → 1.9.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/cloudStorage.d.ts +3 -0
- package/dist/cloudStorage.js +25 -4
- package/dist/commonStorage.d.ts +21 -0
- package/dist/inMemoryCommonStorage.d.ts +5 -1
- package/dist/inMemoryCommonStorage.js +24 -1
- package/package.json +1 -1
- package/src/cloudStorage.ts +41 -4
- package/src/commonStorage.ts +30 -0
- package/src/inMemoryCommonStorage.ts +52 -3
package/dist/cloudStorage.d.ts
CHANGED
|
@@ -38,6 +38,7 @@ export declare class CloudStorage implements CommonStorage {
|
|
|
38
38
|
static createFromStorageOptions(storageOptions?: StorageOptions): CloudStorage;
|
|
39
39
|
ping(bucketName?: string): Promise<void>;
|
|
40
40
|
deletePath(bucketName: string, prefix: string): Promise<void>;
|
|
41
|
+
deletePaths(bucketName: string, prefixes: string[]): Promise<void>;
|
|
41
42
|
fileExists(bucketName: string, filePath: string): Promise<boolean>;
|
|
42
43
|
getFileNames(bucketName: string, opt?: CommonStorageGetOptions): Promise<string[]>;
|
|
43
44
|
getFileNamesStream(bucketName: string, opt?: CommonStorageGetOptions): ReadableTyped<string>;
|
|
@@ -50,11 +51,13 @@ export declare class CloudStorage implements CommonStorage {
|
|
|
50
51
|
getFileReadStream(bucketName: string, filePath: string): Readable;
|
|
51
52
|
saveFile(bucketName: string, filePath: string, content: Buffer): Promise<void>;
|
|
52
53
|
getFileWriteStream(bucketName: string, filePath: string): Writable;
|
|
54
|
+
uploadFile(localFilePath: string, bucketName: string, bucketFilePath: string): Promise<void>;
|
|
53
55
|
setFileVisibility(bucketName: string, filePath: string, isPublic: boolean): Promise<void>;
|
|
54
56
|
getFileVisibility(bucketName: string, filePath: string): Promise<boolean>;
|
|
55
57
|
copyFile(fromBucket: string, fromPath: string, toPath: string, toBucket?: string): Promise<void>;
|
|
56
58
|
moveFile(fromBucket: string, fromPath: string, toPath: string, toBucket?: string): Promise<void>;
|
|
57
59
|
movePath(fromBucket: string, fromPrefix: string, toPrefix: string, toBucket?: string): Promise<void>;
|
|
60
|
+
combine(bucketName: string, filePaths: string[], toPath: string, toBucket?: string): Promise<void>;
|
|
58
61
|
/**
|
|
59
62
|
* Acquires a "signed url", which allows bearer to use it to download ('read') the file.
|
|
60
63
|
*
|
package/dist/cloudStorage.js
CHANGED
|
@@ -38,10 +38,16 @@ class CloudStorage {
|
|
|
38
38
|
await this.storage.bucket(bucketName || 'non-existing-for-sure').exists();
|
|
39
39
|
}
|
|
40
40
|
async deletePath(bucketName, prefix) {
|
|
41
|
-
await this.
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
41
|
+
await this.deletePaths(bucketName, [prefix]);
|
|
42
|
+
}
|
|
43
|
+
async deletePaths(bucketName, prefixes) {
|
|
44
|
+
const bucket = this.storage.bucket(bucketName);
|
|
45
|
+
await (0, js_lib_1.pMap)(prefixes, async (prefix) => {
|
|
46
|
+
await bucket.deleteFiles({
|
|
47
|
+
prefix,
|
|
48
|
+
// to keep going in case error occurs, similar to THROW_AGGREGATED
|
|
49
|
+
force: true,
|
|
50
|
+
});
|
|
45
51
|
});
|
|
46
52
|
}
|
|
47
53
|
async fileExists(bucketName, filePath) {
|
|
@@ -111,6 +117,11 @@ class CloudStorage {
|
|
|
111
117
|
getFileWriteStream(bucketName, filePath) {
|
|
112
118
|
return this.storage.bucket(bucketName).file(filePath).createWriteStream();
|
|
113
119
|
}
|
|
120
|
+
async uploadFile(localFilePath, bucketName, bucketFilePath) {
|
|
121
|
+
await this.storage.bucket(bucketName).upload(localFilePath, {
|
|
122
|
+
destination: bucketFilePath,
|
|
123
|
+
});
|
|
124
|
+
}
|
|
114
125
|
async setFileVisibility(bucketName, filePath, isPublic) {
|
|
115
126
|
await this.storage.bucket(bucketName).file(filePath)[isPublic ? 'makePublic' : 'makePrivate']();
|
|
116
127
|
}
|
|
@@ -144,6 +155,15 @@ class CloudStorage {
|
|
|
144
155
|
}),
|
|
145
156
|
]);
|
|
146
157
|
}
|
|
158
|
+
async combine(bucketName, filePaths, toPath, toBucket) {
|
|
159
|
+
// todo: if (filePaths.length > 32) - use recursive algorithm
|
|
160
|
+
(0, js_lib_1._assert)(filePaths.length <= 32, 'combine supports up to 32 input files');
|
|
161
|
+
await this.storage
|
|
162
|
+
.bucket(bucketName)
|
|
163
|
+
.combine(filePaths, this.storage.bucket(toBucket || bucketName).file(toPath));
|
|
164
|
+
// Delete original files
|
|
165
|
+
await this.deletePaths(bucketName, filePaths);
|
|
166
|
+
}
|
|
147
167
|
/**
|
|
148
168
|
* Acquires a "signed url", which allows bearer to use it to download ('read') the file.
|
|
149
169
|
*
|
|
@@ -157,6 +177,7 @@ class CloudStorage {
|
|
|
157
177
|
.file(filePath)
|
|
158
178
|
.getSignedUrl({
|
|
159
179
|
action: 'read',
|
|
180
|
+
version: 'v4',
|
|
160
181
|
expires: (0, js_lib_1.localTime)(expires).unixMillis(),
|
|
161
182
|
});
|
|
162
183
|
return url;
|
package/dist/commonStorage.d.ts
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
/// <reference types="node" />
|
|
2
2
|
/// <reference types="node" />
|
|
3
3
|
import { Readable, Writable } from 'node:stream';
|
|
4
|
+
import { LocalTimeInput } from '@naturalcycles/js-lib';
|
|
4
5
|
import { ReadableTyped } from '@naturalcycles/nodejs-lib';
|
|
5
6
|
export interface FileEntry {
|
|
6
7
|
filePath: string;
|
|
@@ -54,6 +55,7 @@ export interface CommonStorage {
|
|
|
54
55
|
* Should recursively delete all files in a folder, if path is a folder.
|
|
55
56
|
*/
|
|
56
57
|
deletePath: (bucketName: string, prefix: string) => Promise<void>;
|
|
58
|
+
deletePaths: (bucketName: string, prefixes: string[]) => Promise<void>;
|
|
57
59
|
/**
|
|
58
60
|
* Returns an array of strings which are file paths.
|
|
59
61
|
* Files that are not found by the path are not present in the map.
|
|
@@ -70,6 +72,10 @@ export interface CommonStorage {
|
|
|
70
72
|
getFilesStream: (bucketName: string, opt?: CommonStorageGetOptions) => ReadableTyped<FileEntry>;
|
|
71
73
|
getFileReadStream: (bucketName: string, filePath: string) => Readable;
|
|
72
74
|
getFileWriteStream: (bucketName: string, filePath: string) => Writable;
|
|
75
|
+
/**
|
|
76
|
+
* Upload local file to the bucket (by streaming it).
|
|
77
|
+
*/
|
|
78
|
+
uploadFile: (localFilePath: string, bucketName: string, bucketFilePath: string) => Promise<void>;
|
|
73
79
|
setFileVisibility: (bucketName: string, filePath: string, isPublic: boolean) => Promise<void>;
|
|
74
80
|
getFileVisibility: (bucketName: string, filePath: string) => Promise<boolean>;
|
|
75
81
|
copyFile: (fromBucket: string, fromPath: string, toPath: string, toBucket?: string) => Promise<void>;
|
|
@@ -81,4 +87,19 @@ export interface CommonStorage {
|
|
|
81
87
|
* otherwise some folder that starts with the same prefix will be included.
|
|
82
88
|
*/
|
|
83
89
|
movePath: (fromBucket: string, fromPrefix: string, toPrefix: string, toBucket?: string) => Promise<void>;
|
|
90
|
+
/**
|
|
91
|
+
* Combine (compose) multiple input files into a single output file.
|
|
92
|
+
* Should support unlimited number of input files, using recursive algorithm if necessary.
|
|
93
|
+
*
|
|
94
|
+
* After the output file is created, all input files should be deleted.
|
|
95
|
+
*
|
|
96
|
+
* @experimental
|
|
97
|
+
*/
|
|
98
|
+
combine: (bucketName: string, filePaths: string[], toPath: string, toBucket?: string) => Promise<void>;
|
|
99
|
+
/**
|
|
100
|
+
* Acquire a "signed url", which allows bearer to use it to download ('read') the file.
|
|
101
|
+
*
|
|
102
|
+
* @experimental
|
|
103
|
+
*/
|
|
104
|
+
getSignedUrl: (bucketName: string, filePath: string, expires: LocalTimeInput) => Promise<string>;
|
|
84
105
|
}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
/// <reference types="node" />
|
|
2
2
|
/// <reference types="node" />
|
|
3
3
|
import { Readable, Writable } from 'node:stream';
|
|
4
|
-
import { StringMap } from '@naturalcycles/js-lib';
|
|
4
|
+
import { LocalTimeInput, StringMap } from '@naturalcycles/js-lib';
|
|
5
5
|
import { ReadableTyped } from '@naturalcycles/nodejs-lib';
|
|
6
6
|
import { CommonStorage, CommonStorageGetOptions, FileEntry } from './commonStorage';
|
|
7
7
|
export declare class InMemoryCommonStorage implements CommonStorage {
|
|
@@ -17,14 +17,18 @@ export declare class InMemoryCommonStorage implements CommonStorage {
|
|
|
17
17
|
getFile(bucketName: string, filePath: string): Promise<Buffer | null>;
|
|
18
18
|
saveFile(bucketName: string, filePath: string, content: Buffer): Promise<void>;
|
|
19
19
|
deletePath(bucketName: string, prefix: string): Promise<void>;
|
|
20
|
+
deletePaths(bucketName: string, prefixes: string[]): Promise<void>;
|
|
20
21
|
getFileNames(bucketName: string, opt?: CommonStorageGetOptions): Promise<string[]>;
|
|
21
22
|
getFileNamesStream(bucketName: string, opt?: CommonStorageGetOptions): ReadableTyped<string>;
|
|
22
23
|
getFilesStream(bucketName: string, opt?: CommonStorageGetOptions): ReadableTyped<FileEntry>;
|
|
23
24
|
getFileReadStream(bucketName: string, filePath: string): Readable;
|
|
24
25
|
getFileWriteStream(_bucketName: string, _filePath: string): Writable;
|
|
26
|
+
uploadFile(localFilePath: string, bucketName: string, bucketFilePath: string): Promise<void>;
|
|
25
27
|
setFileVisibility(bucketName: string, filePath: string, isPublic: boolean): Promise<void>;
|
|
26
28
|
getFileVisibility(bucketName: string, filePath: string): Promise<boolean>;
|
|
27
29
|
copyFile(fromBucket: string, fromPath: string, toPath: string, toBucket?: string): Promise<void>;
|
|
28
30
|
moveFile(fromBucket: string, fromPath: string, toPath: string, toBucket?: string): Promise<void>;
|
|
29
31
|
movePath(fromBucket: string, fromPrefix: string, toPrefix: string, toBucket?: string): Promise<void>;
|
|
32
|
+
combine(bucketName: string, filePaths: string[], toPath: string, toBucket?: string): Promise<void>;
|
|
33
|
+
getSignedUrl(bucketName: string, filePath: string, expires: LocalTimeInput): Promise<string>;
|
|
30
34
|
}
|
|
@@ -3,6 +3,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
3
3
|
exports.InMemoryCommonStorage = void 0;
|
|
4
4
|
const node_stream_1 = require("node:stream");
|
|
5
5
|
const js_lib_1 = require("@naturalcycles/js-lib");
|
|
6
|
+
const nodejs_lib_1 = require("@naturalcycles/nodejs-lib");
|
|
6
7
|
class InMemoryCommonStorage {
|
|
7
8
|
constructor() {
|
|
8
9
|
/**
|
|
@@ -29,8 +30,11 @@ class InMemoryCommonStorage {
|
|
|
29
30
|
this.data[bucketName][filePath] = content;
|
|
30
31
|
}
|
|
31
32
|
async deletePath(bucketName, prefix) {
|
|
33
|
+
await this.deletePaths(bucketName, [prefix]);
|
|
34
|
+
}
|
|
35
|
+
async deletePaths(bucketName, prefixes) {
|
|
32
36
|
Object.keys(this.data[bucketName] || {}).forEach(filePath => {
|
|
33
|
-
if (filePath.startsWith(prefix)) {
|
|
37
|
+
if (prefixes.some(prefix => filePath.startsWith(prefix))) {
|
|
34
38
|
delete this.data[bucketName][filePath];
|
|
35
39
|
}
|
|
36
40
|
});
|
|
@@ -65,6 +69,10 @@ class InMemoryCommonStorage {
|
|
|
65
69
|
getFileWriteStream(_bucketName, _filePath) {
|
|
66
70
|
throw new Error('Method not implemented.');
|
|
67
71
|
}
|
|
72
|
+
async uploadFile(localFilePath, bucketName, bucketFilePath) {
|
|
73
|
+
this.data[bucketName] ||= {};
|
|
74
|
+
this.data[bucketName][bucketFilePath] = await nodejs_lib_1.fs2.readBufferAsync(localFilePath);
|
|
75
|
+
}
|
|
68
76
|
async setFileVisibility(bucketName, filePath, isPublic) {
|
|
69
77
|
this.publicMap[bucketName] ||= {};
|
|
70
78
|
this.publicMap[bucketName][filePath] = isPublic;
|
|
@@ -96,5 +104,20 @@ class InMemoryCommonStorage {
|
|
|
96
104
|
delete this.data[fromBucket][filePath];
|
|
97
105
|
});
|
|
98
106
|
}
|
|
107
|
+
async combine(bucketName, filePaths, toPath, toBucket) {
|
|
108
|
+
if (!this.data[bucketName])
|
|
109
|
+
return;
|
|
110
|
+
const tob = toBucket || bucketName;
|
|
111
|
+
this.data[tob] ||= {};
|
|
112
|
+
this.data[tob][toPath] = Buffer.concat(filePaths.map(p => this.data[bucketName][p]).filter(js_lib_1._isTruthy));
|
|
113
|
+
// delete source files
|
|
114
|
+
filePaths.forEach(p => delete this.data[bucketName][p]);
|
|
115
|
+
}
|
|
116
|
+
async getSignedUrl(bucketName, filePath, expires) {
|
|
117
|
+
const buf = this.data[bucketName]?.[filePath];
|
|
118
|
+
(0, js_lib_1._assert)(buf, `getSignedUrl file not found: ${bucketName}/${filePath}`);
|
|
119
|
+
const signature = (0, nodejs_lib_1.md5)(buf);
|
|
120
|
+
return `https://testurl.com/${bucketName}/${filePath}?expires=${(0, js_lib_1.localTime)(expires).unix()}&signature=${signature}`;
|
|
121
|
+
}
|
|
99
122
|
}
|
|
100
123
|
exports.InMemoryCommonStorage = InMemoryCommonStorage;
|
package/package.json
CHANGED
package/src/cloudStorage.ts
CHANGED
|
@@ -5,6 +5,7 @@ import {
|
|
|
5
5
|
_substringAfterLast,
|
|
6
6
|
localTime,
|
|
7
7
|
LocalTimeInput,
|
|
8
|
+
pMap,
|
|
8
9
|
SKIP,
|
|
9
10
|
} from '@naturalcycles/js-lib'
|
|
10
11
|
import {
|
|
@@ -75,10 +76,18 @@ export class CloudStorage implements CommonStorage {
|
|
|
75
76
|
}
|
|
76
77
|
|
|
77
78
|
async deletePath(bucketName: string, prefix: string): Promise<void> {
|
|
78
|
-
await this.
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
79
|
+
await this.deletePaths(bucketName, [prefix])
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
async deletePaths(bucketName: string, prefixes: string[]): Promise<void> {
|
|
83
|
+
const bucket = this.storage.bucket(bucketName)
|
|
84
|
+
|
|
85
|
+
await pMap(prefixes, async prefix => {
|
|
86
|
+
await bucket.deleteFiles({
|
|
87
|
+
prefix,
|
|
88
|
+
// to keep going in case error occurs, similar to THROW_AGGREGATED
|
|
89
|
+
force: true,
|
|
90
|
+
})
|
|
82
91
|
})
|
|
83
92
|
}
|
|
84
93
|
|
|
@@ -163,6 +172,16 @@ export class CloudStorage implements CommonStorage {
|
|
|
163
172
|
return this.storage.bucket(bucketName).file(filePath).createWriteStream()
|
|
164
173
|
}
|
|
165
174
|
|
|
175
|
+
async uploadFile(
|
|
176
|
+
localFilePath: string,
|
|
177
|
+
bucketName: string,
|
|
178
|
+
bucketFilePath: string,
|
|
179
|
+
): Promise<void> {
|
|
180
|
+
await this.storage.bucket(bucketName).upload(localFilePath, {
|
|
181
|
+
destination: bucketFilePath,
|
|
182
|
+
})
|
|
183
|
+
}
|
|
184
|
+
|
|
166
185
|
async setFileVisibility(bucketName: string, filePath: string, isPublic: boolean): Promise<void> {
|
|
167
186
|
await this.storage.bucket(bucketName).file(filePath)[isPublic ? 'makePublic' : 'makePrivate']()
|
|
168
187
|
}
|
|
@@ -217,6 +236,23 @@ export class CloudStorage implements CommonStorage {
|
|
|
217
236
|
])
|
|
218
237
|
}
|
|
219
238
|
|
|
239
|
+
async combine(
|
|
240
|
+
bucketName: string,
|
|
241
|
+
filePaths: string[],
|
|
242
|
+
toPath: string,
|
|
243
|
+
toBucket?: string,
|
|
244
|
+
): Promise<void> {
|
|
245
|
+
// todo: if (filePaths.length > 32) - use recursive algorithm
|
|
246
|
+
_assert(filePaths.length <= 32, 'combine supports up to 32 input files')
|
|
247
|
+
|
|
248
|
+
await this.storage
|
|
249
|
+
.bucket(bucketName)
|
|
250
|
+
.combine(filePaths, this.storage.bucket(toBucket || bucketName).file(toPath))
|
|
251
|
+
|
|
252
|
+
// Delete original files
|
|
253
|
+
await this.deletePaths(bucketName, filePaths)
|
|
254
|
+
}
|
|
255
|
+
|
|
220
256
|
/**
|
|
221
257
|
* Acquires a "signed url", which allows bearer to use it to download ('read') the file.
|
|
222
258
|
*
|
|
@@ -234,6 +270,7 @@ export class CloudStorage implements CommonStorage {
|
|
|
234
270
|
.file(filePath)
|
|
235
271
|
.getSignedUrl({
|
|
236
272
|
action: 'read',
|
|
273
|
+
version: 'v4',
|
|
237
274
|
expires: localTime(expires).unixMillis(),
|
|
238
275
|
})
|
|
239
276
|
|
package/src/commonStorage.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { Readable, Writable } from 'node:stream'
|
|
2
|
+
import { LocalTimeInput } from '@naturalcycles/js-lib'
|
|
2
3
|
import { ReadableTyped } from '@naturalcycles/nodejs-lib'
|
|
3
4
|
|
|
4
5
|
export interface FileEntry {
|
|
@@ -66,6 +67,8 @@ export interface CommonStorage {
|
|
|
66
67
|
*/
|
|
67
68
|
deletePath: (bucketName: string, prefix: string) => Promise<void>
|
|
68
69
|
|
|
70
|
+
deletePaths: (bucketName: string, prefixes: string[]) => Promise<void>
|
|
71
|
+
|
|
69
72
|
/**
|
|
70
73
|
* Returns an array of strings which are file paths.
|
|
71
74
|
* Files that are not found by the path are not present in the map.
|
|
@@ -87,6 +90,11 @@ export interface CommonStorage {
|
|
|
87
90
|
|
|
88
91
|
getFileWriteStream: (bucketName: string, filePath: string) => Writable
|
|
89
92
|
|
|
93
|
+
/**
|
|
94
|
+
* Upload local file to the bucket (by streaming it).
|
|
95
|
+
*/
|
|
96
|
+
uploadFile: (localFilePath: string, bucketName: string, bucketFilePath: string) => Promise<void>
|
|
97
|
+
|
|
90
98
|
setFileVisibility: (bucketName: string, filePath: string, isPublic: boolean) => Promise<void>
|
|
91
99
|
|
|
92
100
|
getFileVisibility: (bucketName: string, filePath: string) => Promise<boolean>
|
|
@@ -117,4 +125,26 @@ export interface CommonStorage {
|
|
|
117
125
|
toPrefix: string,
|
|
118
126
|
toBucket?: string,
|
|
119
127
|
) => Promise<void>
|
|
128
|
+
|
|
129
|
+
/**
|
|
130
|
+
* Combine (compose) multiple input files into a single output file.
|
|
131
|
+
* Should support unlimited number of input files, using recursive algorithm if necessary.
|
|
132
|
+
*
|
|
133
|
+
* After the output file is created, all input files should be deleted.
|
|
134
|
+
*
|
|
135
|
+
* @experimental
|
|
136
|
+
*/
|
|
137
|
+
combine: (
|
|
138
|
+
bucketName: string,
|
|
139
|
+
filePaths: string[],
|
|
140
|
+
toPath: string,
|
|
141
|
+
toBucket?: string,
|
|
142
|
+
) => Promise<void>
|
|
143
|
+
|
|
144
|
+
/**
|
|
145
|
+
* Acquire a "signed url", which allows bearer to use it to download ('read') the file.
|
|
146
|
+
*
|
|
147
|
+
* @experimental
|
|
148
|
+
*/
|
|
149
|
+
getSignedUrl: (bucketName: string, filePath: string, expires: LocalTimeInput) => Promise<string>
|
|
120
150
|
}
|
|
@@ -1,6 +1,14 @@
|
|
|
1
1
|
import { Readable, Writable } from 'node:stream'
|
|
2
|
-
import {
|
|
3
|
-
|
|
2
|
+
import {
|
|
3
|
+
_assert,
|
|
4
|
+
_isTruthy,
|
|
5
|
+
_stringMapEntries,
|
|
6
|
+
_substringAfterLast,
|
|
7
|
+
localTime,
|
|
8
|
+
LocalTimeInput,
|
|
9
|
+
StringMap,
|
|
10
|
+
} from '@naturalcycles/js-lib'
|
|
11
|
+
import { fs2, md5, ReadableTyped } from '@naturalcycles/nodejs-lib'
|
|
4
12
|
import { CommonStorage, CommonStorageGetOptions, FileEntry } from './commonStorage'
|
|
5
13
|
|
|
6
14
|
export class InMemoryCommonStorage implements CommonStorage {
|
|
@@ -35,8 +43,12 @@ export class InMemoryCommonStorage implements CommonStorage {
|
|
|
35
43
|
}
|
|
36
44
|
|
|
37
45
|
async deletePath(bucketName: string, prefix: string): Promise<void> {
|
|
46
|
+
await this.deletePaths(bucketName, [prefix])
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
async deletePaths(bucketName: string, prefixes: string[]): Promise<void> {
|
|
38
50
|
Object.keys(this.data[bucketName] || {}).forEach(filePath => {
|
|
39
|
-
if (filePath.startsWith(prefix)) {
|
|
51
|
+
if (prefixes.some(prefix => filePath.startsWith(prefix))) {
|
|
40
52
|
delete this.data[bucketName]![filePath]
|
|
41
53
|
}
|
|
42
54
|
})
|
|
@@ -83,6 +95,15 @@ export class InMemoryCommonStorage implements CommonStorage {
|
|
|
83
95
|
throw new Error('Method not implemented.')
|
|
84
96
|
}
|
|
85
97
|
|
|
98
|
+
async uploadFile(
|
|
99
|
+
localFilePath: string,
|
|
100
|
+
bucketName: string,
|
|
101
|
+
bucketFilePath: string,
|
|
102
|
+
): Promise<void> {
|
|
103
|
+
this.data[bucketName] ||= {}
|
|
104
|
+
this.data[bucketName]![bucketFilePath] = await fs2.readBufferAsync(localFilePath)
|
|
105
|
+
}
|
|
106
|
+
|
|
86
107
|
async setFileVisibility(bucketName: string, filePath: string, isPublic: boolean): Promise<void> {
|
|
87
108
|
this.publicMap[bucketName] ||= {}
|
|
88
109
|
this.publicMap[bucketName]![filePath] = isPublic
|
|
@@ -133,4 +154,32 @@ export class InMemoryCommonStorage implements CommonStorage {
|
|
|
133
154
|
delete this.data[fromBucket]![filePath]
|
|
134
155
|
})
|
|
135
156
|
}
|
|
157
|
+
|
|
158
|
+
async combine(
|
|
159
|
+
bucketName: string,
|
|
160
|
+
filePaths: string[],
|
|
161
|
+
toPath: string,
|
|
162
|
+
toBucket?: string,
|
|
163
|
+
): Promise<void> {
|
|
164
|
+
if (!this.data[bucketName]) return
|
|
165
|
+
const tob = toBucket || bucketName
|
|
166
|
+
this.data[tob] ||= {}
|
|
167
|
+
this.data[tob]![toPath] = Buffer.concat(
|
|
168
|
+
filePaths.map(p => this.data[bucketName]![p]).filter(_isTruthy),
|
|
169
|
+
)
|
|
170
|
+
|
|
171
|
+
// delete source files
|
|
172
|
+
filePaths.forEach(p => delete this.data[bucketName]![p])
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
async getSignedUrl(
|
|
176
|
+
bucketName: string,
|
|
177
|
+
filePath: string,
|
|
178
|
+
expires: LocalTimeInput,
|
|
179
|
+
): Promise<string> {
|
|
180
|
+
const buf = this.data[bucketName]?.[filePath]
|
|
181
|
+
_assert(buf, `getSignedUrl file not found: ${bucketName}/${filePath}`)
|
|
182
|
+
const signature = md5(buf)
|
|
183
|
+
return `https://testurl.com/${bucketName}/${filePath}?expires=${localTime(expires).unix()}&signature=${signature}`
|
|
184
|
+
}
|
|
136
185
|
}
|