@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.
@@ -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
- .pipe((0, nodejs_lib_1.transformMapSync)(f => this.normalizeFilename(f.name, fullPaths)));
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 js_lib_1.SKIP;
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 (0, nodejs_lib_1._pipeline)([
148
- this.storage.bucket(fromBucket).getFilesStream({
149
- prefix: fromPrefix,
150
- }),
151
- (0, nodejs_lib_1.writableForEach)(async (file) => {
152
- const { name } = file;
153
- const newName = toPrefix + name.slice(fromPrefix.length);
154
- await file.move(this.storage.bucket(toBucket || fromBucket).file(newName));
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
- .pipe((0, nodejs_lib_1.transformMapSimple)(({ filePath, content }) => [
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 (0, nodejs_lib_1.readableToArray)(storage.getFileNamesStream(bucketName, { prefix: TEST_FOLDER }));
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 (0, nodejs_lib_1.readableToArray)(storage.getFileNamesStream(bucketName, { prefix: TEST_FOLDER }));
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
@@ -35,7 +35,7 @@
35
35
  "engines": {
36
36
  "node": ">=18.12.0"
37
37
  },
38
- "version": "1.9.0",
38
+ "version": "1.9.2",
39
39
  "description": "CommonStorage implementation based on Google Cloud Storage",
40
40
  "author": "Natural Cycles Team",
41
41
  "license": "MIT"
@@ -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 this.storage
118
- .bucket(bucketName)
119
- .getFilesStream({
111
+ return (
112
+ this.storage.bucket(bucketName).getFilesStream({
120
113
  prefix,
121
114
  maxResults: opt.limit || undefined,
122
- })
123
- .pipe(transformMapSync<File, string>(f => this.normalizeFilename(f.name, fullPaths)))
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 this.storage
130
- .bucket(bucketName)
131
- .getFilesStream({
126
+ return (
127
+ this.storage.bucket(bucketName).getFilesStream({
132
128
  prefix,
133
129
  maxResults: opt.limit || undefined,
134
- })
135
- .pipe(
136
- transformMap<File, FileEntry>(async f => {
137
- const filePath = this.normalizeFilename(f.name, fullPaths)
138
- if (filePath === SKIP) return SKIP
139
-
140
- const [content] = await f.download()
141
- return { filePath, content }
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 _pipeline([
228
- this.storage.bucket(fromBucket).getFilesStream({
226
+ await this.storage
227
+ .bucket(fromBucket)
228
+ .getFilesStream({
229
229
  prefix: fromPrefix,
230
- }),
231
- writableForEach<File>(async file => {
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, transformMapSimple } from '@naturalcycles/nodejs-lib'
4
- import { CommonStorage, FileEntry } from './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
- .pipe(
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 readableToArray(
73
- storage.getFileNamesStream(bucketName, { prefix: TEST_FOLDER }),
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 readableToArray(
103
- storage.getFileNamesStream(bucketName, { prefix: TEST_FOLDER }),
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> = {}