@naturalcycles/cloud-storage-lib 1.9.0 → 1.9.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.
package/dist/cloudStorage.js
CHANGED
|
@@ -4,7 +4,6 @@ exports.CloudStorage = exports.Storage = void 0;
|
|
|
4
4
|
const storage_1 = require("@google-cloud/storage");
|
|
5
5
|
Object.defineProperty(exports, "Storage", { enumerable: true, get: function () { return storage_1.Storage; } });
|
|
6
6
|
const js_lib_1 = require("@naturalcycles/js-lib");
|
|
7
|
-
const nodejs_lib_1 = require("@naturalcycles/nodejs-lib");
|
|
8
7
|
/**
|
|
9
8
|
* CloudStorage implementation of CommonStorage API.
|
|
10
9
|
*
|
|
@@ -68,29 +67,30 @@ class CloudStorage {
|
|
|
68
67
|
}
|
|
69
68
|
getFileNamesStream(bucketName, opt = {}) {
|
|
70
69
|
const { prefix, fullPaths = true } = opt;
|
|
71
|
-
return this.storage
|
|
72
|
-
.bucket(bucketName)
|
|
73
|
-
.getFilesStream({
|
|
70
|
+
return this.storage.bucket(bucketName).getFilesStream({
|
|
74
71
|
prefix,
|
|
75
72
|
maxResults: opt.limit || undefined,
|
|
76
|
-
})
|
|
77
|
-
|
|
73
|
+
}).flatMap(f => {
|
|
74
|
+
const r = this.normalizeFilename(f.name, fullPaths);
|
|
75
|
+
if (r === js_lib_1.SKIP)
|
|
76
|
+
return [];
|
|
77
|
+
return [r];
|
|
78
|
+
});
|
|
78
79
|
}
|
|
79
80
|
getFilesStream(bucketName, opt = {}) {
|
|
80
81
|
const { prefix, fullPaths = true } = opt;
|
|
81
|
-
return this.storage
|
|
82
|
-
.bucket(bucketName)
|
|
83
|
-
.getFilesStream({
|
|
82
|
+
return this.storage.bucket(bucketName).getFilesStream({
|
|
84
83
|
prefix,
|
|
85
84
|
maxResults: opt.limit || undefined,
|
|
86
|
-
})
|
|
87
|
-
.pipe((0, nodejs_lib_1.transformMap)(async (f) => {
|
|
85
|
+
}).flatMap(async (f) => {
|
|
88
86
|
const filePath = this.normalizeFilename(f.name, fullPaths);
|
|
89
87
|
if (filePath === js_lib_1.SKIP)
|
|
90
|
-
return
|
|
88
|
+
return [];
|
|
91
89
|
const [content] = await f.download();
|
|
92
|
-
return { filePath, content };
|
|
93
|
-
}
|
|
90
|
+
return [{ filePath, content }];
|
|
91
|
+
}, {
|
|
92
|
+
concurrency: 16,
|
|
93
|
+
});
|
|
94
94
|
}
|
|
95
95
|
async getFile(bucketName, filePath) {
|
|
96
96
|
const [buf] = await this.storage
|
|
@@ -144,16 +144,16 @@ class CloudStorage {
|
|
|
144
144
|
async movePath(fromBucket, fromPrefix, toPrefix, toBucket) {
|
|
145
145
|
(0, js_lib_1._assert)(fromPrefix.endsWith('/'), 'fromPrefix should end with `/`');
|
|
146
146
|
(0, js_lib_1._assert)(toPrefix.endsWith('/'), 'toPrefix should end with `/`');
|
|
147
|
-
await
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
147
|
+
await this.storage
|
|
148
|
+
.bucket(fromBucket)
|
|
149
|
+
.getFilesStream({
|
|
150
|
+
prefix: fromPrefix,
|
|
151
|
+
})
|
|
152
|
+
.forEach(async (file) => {
|
|
153
|
+
const { name } = file;
|
|
154
|
+
const newName = toPrefix + name.slice(fromPrefix.length);
|
|
155
|
+
await file.move(this.storage.bucket(toBucket || fromBucket).file(newName));
|
|
156
|
+
});
|
|
157
157
|
}
|
|
158
158
|
async combine(bucketName, filePaths, toPath, toBucket) {
|
|
159
159
|
// todo: if (filePaths.length > 32) - use recursive algorithm
|
|
@@ -2,7 +2,6 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.CommonStorageKeyValueDB = void 0;
|
|
4
4
|
const js_lib_1 = require("@naturalcycles/js-lib");
|
|
5
|
-
const nodejs_lib_1 = require("@naturalcycles/nodejs-lib");
|
|
6
5
|
/**
|
|
7
6
|
* CommonKeyValueDB, backed up by a CommonStorage implementation.
|
|
8
7
|
*
|
|
@@ -66,18 +65,13 @@ class CommonStorageKeyValueDB {
|
|
|
66
65
|
}
|
|
67
66
|
streamValues(table, limit) {
|
|
68
67
|
const { bucketName, prefix } = this.getBucketAndPrefix(table);
|
|
69
|
-
return this.cfg.storage
|
|
70
|
-
.getFilesStream(bucketName, { prefix, limit })
|
|
71
|
-
.pipe((0, nodejs_lib_1.transformMapSimple)(f => f.content));
|
|
68
|
+
return this.cfg.storage.getFilesStream(bucketName, { prefix, limit }).map(f => f.content);
|
|
72
69
|
}
|
|
73
70
|
streamEntries(table, limit) {
|
|
74
71
|
const { bucketName, prefix } = this.getBucketAndPrefix(table);
|
|
75
72
|
return this.cfg.storage
|
|
76
73
|
.getFilesStream(bucketName, { prefix, limit, fullPaths: false })
|
|
77
|
-
.
|
|
78
|
-
filePath,
|
|
79
|
-
content,
|
|
80
|
-
]));
|
|
74
|
+
.map(f => [f.filePath, f.content]);
|
|
81
75
|
}
|
|
82
76
|
async count(table) {
|
|
83
77
|
const { bucketName, prefix } = this.getBucketAndPrefix(table);
|
|
@@ -2,7 +2,6 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.runCommonStorageTest = void 0;
|
|
4
4
|
const js_lib_1 = require("@naturalcycles/js-lib");
|
|
5
|
-
const nodejs_lib_1 = require("@naturalcycles/nodejs-lib");
|
|
6
5
|
const TEST_FOLDER = 'test/subdir';
|
|
7
6
|
const TEST_ITEMS = (0, js_lib_1._range)(10).map(n => ({
|
|
8
7
|
id: `id_${n + 1}`,
|
|
@@ -56,7 +55,9 @@ function runCommonStorageTest(storage, bucketName) {
|
|
|
56
55
|
expect(fileNames).toEqual([]);
|
|
57
56
|
});
|
|
58
57
|
test(`streamFileNames on ${TEST_FOLDER} should return empty`, async () => {
|
|
59
|
-
const fileNames = await
|
|
58
|
+
const fileNames = await storage
|
|
59
|
+
.getFileNamesStream(bucketName, { prefix: TEST_FOLDER })
|
|
60
|
+
.toArray();
|
|
60
61
|
expect(fileNames).toEqual([]);
|
|
61
62
|
});
|
|
62
63
|
test(`exists should return empty array`, async () => {
|
|
@@ -76,7 +77,9 @@ function runCommonStorageTest(storage, bucketName) {
|
|
|
76
77
|
expect(fileNamesShort.sort()).toEqual(TEST_FILES.map(f => (0, js_lib_1._substringAfterLast)(f.filePath, '/')).sort());
|
|
77
78
|
const fileNames = await storage.getFileNames(bucketName, { prefix: TEST_FOLDER });
|
|
78
79
|
expect(fileNames.sort()).toEqual(TEST_FILES.map(f => f.filePath).sort());
|
|
79
|
-
const streamedFileNames = await
|
|
80
|
+
const streamedFileNames = await storage
|
|
81
|
+
.getFileNamesStream(bucketName, { prefix: TEST_FOLDER })
|
|
82
|
+
.toArray();
|
|
80
83
|
expect(streamedFileNames.sort()).toEqual(TEST_FILES.map(f => f.filePath).sort());
|
|
81
84
|
const filesMap = {};
|
|
82
85
|
await (0, js_lib_1.pMap)(fileNames, async (filePath) => {
|
package/package.json
CHANGED
package/src/cloudStorage.ts
CHANGED
|
@@ -8,13 +8,7 @@ import {
|
|
|
8
8
|
pMap,
|
|
9
9
|
SKIP,
|
|
10
10
|
} from '@naturalcycles/js-lib'
|
|
11
|
-
import {
|
|
12
|
-
_pipeline,
|
|
13
|
-
ReadableTyped,
|
|
14
|
-
transformMap,
|
|
15
|
-
transformMapSync,
|
|
16
|
-
writableForEach,
|
|
17
|
-
} from '@naturalcycles/nodejs-lib'
|
|
11
|
+
import { ReadableTyped } from '@naturalcycles/nodejs-lib'
|
|
18
12
|
import { CommonStorage, CommonStorageGetOptions, FileEntry } from './commonStorage'
|
|
19
13
|
import { GCPServiceAccount } from './model'
|
|
20
14
|
|
|
@@ -114,33 +108,38 @@ export class CloudStorage implements CommonStorage {
|
|
|
114
108
|
getFileNamesStream(bucketName: string, opt: CommonStorageGetOptions = {}): ReadableTyped<string> {
|
|
115
109
|
const { prefix, fullPaths = true } = opt
|
|
116
110
|
|
|
117
|
-
return
|
|
118
|
-
.bucket(bucketName)
|
|
119
|
-
.getFilesStream({
|
|
111
|
+
return (
|
|
112
|
+
this.storage.bucket(bucketName).getFilesStream({
|
|
120
113
|
prefix,
|
|
121
114
|
maxResults: opt.limit || undefined,
|
|
122
|
-
})
|
|
123
|
-
|
|
115
|
+
}) as ReadableTyped<File>
|
|
116
|
+
).flatMap(f => {
|
|
117
|
+
const r = this.normalizeFilename(f.name, fullPaths)
|
|
118
|
+
if (r === SKIP) return []
|
|
119
|
+
return [r]
|
|
120
|
+
})
|
|
124
121
|
}
|
|
125
122
|
|
|
126
123
|
getFilesStream(bucketName: string, opt: CommonStorageGetOptions = {}): ReadableTyped<FileEntry> {
|
|
127
124
|
const { prefix, fullPaths = true } = opt
|
|
128
125
|
|
|
129
|
-
return
|
|
130
|
-
.bucket(bucketName)
|
|
131
|
-
.getFilesStream({
|
|
126
|
+
return (
|
|
127
|
+
this.storage.bucket(bucketName).getFilesStream({
|
|
132
128
|
prefix,
|
|
133
129
|
maxResults: opt.limit || undefined,
|
|
134
|
-
})
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
130
|
+
}) as ReadableTyped<File>
|
|
131
|
+
).flatMap(
|
|
132
|
+
async f => {
|
|
133
|
+
const filePath = this.normalizeFilename(f.name, fullPaths)
|
|
134
|
+
if (filePath === SKIP) return []
|
|
135
|
+
|
|
136
|
+
const [content] = await f.download()
|
|
137
|
+
return [{ filePath, content }] as FileEntry[]
|
|
138
|
+
},
|
|
139
|
+
{
|
|
140
|
+
concurrency: 16,
|
|
141
|
+
},
|
|
142
|
+
)
|
|
144
143
|
}
|
|
145
144
|
|
|
146
145
|
async getFile(bucketName: string, filePath: string): Promise<Buffer | null> {
|
|
@@ -224,16 +223,16 @@ export class CloudStorage implements CommonStorage {
|
|
|
224
223
|
_assert(fromPrefix.endsWith('/'), 'fromPrefix should end with `/`')
|
|
225
224
|
_assert(toPrefix.endsWith('/'), 'toPrefix should end with `/`')
|
|
226
225
|
|
|
227
|
-
await
|
|
228
|
-
|
|
226
|
+
await this.storage
|
|
227
|
+
.bucket(fromBucket)
|
|
228
|
+
.getFilesStream({
|
|
229
229
|
prefix: fromPrefix,
|
|
230
|
-
})
|
|
231
|
-
|
|
230
|
+
})
|
|
231
|
+
.forEach(async file => {
|
|
232
232
|
const { name } = file
|
|
233
233
|
const newName = toPrefix + name.slice(fromPrefix.length)
|
|
234
234
|
await file.move(this.storage.bucket(toBucket || fromBucket).file(newName))
|
|
235
|
-
})
|
|
236
|
-
])
|
|
235
|
+
})
|
|
237
236
|
}
|
|
238
237
|
|
|
239
238
|
async combine(
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { CommonDBCreateOptions, CommonKeyValueDB, KeyValueDBTuple } from '@naturalcycles/db-lib'
|
|
2
2
|
import { pMap, StringMap } from '@naturalcycles/js-lib'
|
|
3
|
-
import { ReadableTyped
|
|
4
|
-
import { CommonStorage
|
|
3
|
+
import { ReadableTyped } from '@naturalcycles/nodejs-lib'
|
|
4
|
+
import { CommonStorage } from './commonStorage'
|
|
5
5
|
|
|
6
6
|
export interface CommonStorageKeyValueDBCfg {
|
|
7
7
|
storage: CommonStorage
|
|
@@ -84,9 +84,7 @@ export class CommonStorageKeyValueDB implements CommonKeyValueDB {
|
|
|
84
84
|
streamValues(table: string, limit?: number): ReadableTyped<Buffer> {
|
|
85
85
|
const { bucketName, prefix } = this.getBucketAndPrefix(table)
|
|
86
86
|
|
|
87
|
-
return this.cfg.storage
|
|
88
|
-
.getFilesStream(bucketName, { prefix, limit })
|
|
89
|
-
.pipe(transformMapSimple<FileEntry, Buffer>(f => f.content))
|
|
87
|
+
return this.cfg.storage.getFilesStream(bucketName, { prefix, limit }).map(f => f.content)
|
|
90
88
|
}
|
|
91
89
|
|
|
92
90
|
streamEntries(table: string, limit?: number): ReadableTyped<KeyValueDBTuple> {
|
|
@@ -94,12 +92,7 @@ export class CommonStorageKeyValueDB implements CommonKeyValueDB {
|
|
|
94
92
|
|
|
95
93
|
return this.cfg.storage
|
|
96
94
|
.getFilesStream(bucketName, { prefix, limit, fullPaths: false })
|
|
97
|
-
.
|
|
98
|
-
transformMapSimple<FileEntry, KeyValueDBTuple>(({ filePath, content }) => [
|
|
99
|
-
filePath,
|
|
100
|
-
content,
|
|
101
|
-
]),
|
|
102
|
-
)
|
|
95
|
+
.map(f => [f.filePath, f.content] satisfies KeyValueDBTuple)
|
|
103
96
|
}
|
|
104
97
|
|
|
105
98
|
async count(table: string): Promise<number> {
|
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
import { _range, _substringAfterLast, pMap, StringMap } from '@naturalcycles/js-lib'
|
|
2
|
-
import { readableToArray } from '@naturalcycles/nodejs-lib'
|
|
3
2
|
import { CommonStorage, FileEntry } from '../commonStorage'
|
|
4
3
|
|
|
5
4
|
const TEST_FOLDER = 'test/subdir'
|
|
@@ -69,9 +68,9 @@ export function runCommonStorageTest(storage: CommonStorage, bucketName: string)
|
|
|
69
68
|
})
|
|
70
69
|
|
|
71
70
|
test(`streamFileNames on ${TEST_FOLDER} should return empty`, async () => {
|
|
72
|
-
const fileNames = await
|
|
73
|
-
|
|
74
|
-
|
|
71
|
+
const fileNames = await storage
|
|
72
|
+
.getFileNamesStream(bucketName, { prefix: TEST_FOLDER })
|
|
73
|
+
.toArray()
|
|
75
74
|
expect(fileNames).toEqual([])
|
|
76
75
|
})
|
|
77
76
|
|
|
@@ -99,9 +98,9 @@ export function runCommonStorageTest(storage: CommonStorage, bucketName: string)
|
|
|
99
98
|
const fileNames = await storage.getFileNames(bucketName, { prefix: TEST_FOLDER })
|
|
100
99
|
expect(fileNames.sort()).toEqual(TEST_FILES.map(f => f.filePath).sort())
|
|
101
100
|
|
|
102
|
-
const streamedFileNames = await
|
|
103
|
-
|
|
104
|
-
|
|
101
|
+
const streamedFileNames = await storage
|
|
102
|
+
.getFileNamesStream(bucketName, { prefix: TEST_FOLDER })
|
|
103
|
+
.toArray()
|
|
105
104
|
expect(streamedFileNames.sort()).toEqual(TEST_FILES.map(f => f.filePath).sort())
|
|
106
105
|
|
|
107
106
|
const filesMap: StringMap<Buffer> = {}
|