@e-mc/cloud 0.13.10 → 0.14.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/README.md +8 -8
- package/index.js +108 -103
- package/package.json +4 -4
- package/types/index.d.ts +3 -2
- package/util.d.ts +3 -3
- package/util.js +26 -26
package/README.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# @e-mc/cloud
|
|
2
2
|
|
|
3
|
-
* NodeJS
|
|
3
|
+
* NodeJS 20 (Minimum 18)
|
|
4
4
|
* ES2022
|
|
5
5
|
|
|
6
6
|
## General Usage
|
|
@@ -9,7 +9,7 @@
|
|
|
9
9
|
|
|
10
10
|
## Interface
|
|
11
11
|
|
|
12
|
-
* [View Source](https://www.unpkg.com/@e-mc/types@0.
|
|
12
|
+
* [View Source](https://www.unpkg.com/@e-mc/types@0.14.0/lib/index.d.ts)
|
|
13
13
|
|
|
14
14
|
```typescript
|
|
15
15
|
import type { IFileManager, IHost, IScopeOrigin } from "./index";
|
|
@@ -180,12 +180,12 @@ const rows = await instance.getDatabaseRows({ service: "aws-v3", credential: "ma
|
|
|
180
180
|
|
|
181
181
|
## References
|
|
182
182
|
|
|
183
|
-
- https://www.unpkg.com/@e-mc/types@0.
|
|
184
|
-
- https://www.unpkg.com/@e-mc/types@0.
|
|
185
|
-
- https://www.unpkg.com/@e-mc/types@0.
|
|
186
|
-
- https://www.unpkg.com/@e-mc/types@0.
|
|
187
|
-
- https://www.unpkg.com/@e-mc/types@0.
|
|
188
|
-
- https://www.unpkg.com/@e-mc/types@0.
|
|
183
|
+
- https://www.unpkg.com/@e-mc/types@0.14.0/lib/asset.d.ts
|
|
184
|
+
- https://www.unpkg.com/@e-mc/types@0.14.0/lib/cloud.d.ts
|
|
185
|
+
- https://www.unpkg.com/@e-mc/types@0.14.0/lib/core.d.ts
|
|
186
|
+
- https://www.unpkg.com/@e-mc/types@0.14.0/lib/db.d.ts
|
|
187
|
+
- https://www.unpkg.com/@e-mc/types@0.14.0/lib/logger.d.ts
|
|
188
|
+
- https://www.unpkg.com/@e-mc/types@0.14.0/lib/settings.d.ts
|
|
189
189
|
|
|
190
190
|
## LICENSE
|
|
191
191
|
|
package/index.js
CHANGED
|
@@ -1,9 +1,11 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
const
|
|
5
|
-
const
|
|
6
|
-
const
|
|
2
|
+
|
|
3
|
+
var _a;
|
|
4
|
+
const path = require('node:path');
|
|
5
|
+
const fs = require('node:fs');
|
|
6
|
+
const { randomUUID } = require('node:crypto');
|
|
7
|
+
const { IMPORT_MAP, alignSize, coerceObject, createAbortError, errorMessage, errorValue, formatSize, ignoreFlag, isArray, isError, isErrorCode, isObject, isPlainObject, isString } = require('@e-mc/types');
|
|
8
|
+
const { ClientDb } = require('@e-mc/core');
|
|
7
9
|
const kCloud = Symbol.for('cloud:constructor');
|
|
8
10
|
const SERVICE_CLIENT = new Map();
|
|
9
11
|
const SERVICE_UPLOAD = Object.create(null);
|
|
@@ -12,19 +14,19 @@ function setUploadFilename(upload, filename) {
|
|
|
12
14
|
filename = Cloud.toPosix(filename.replace(/^\.*[\\/]+/, ''));
|
|
13
15
|
const index = filename.lastIndexOf('/');
|
|
14
16
|
if (index !== -1) {
|
|
15
|
-
const directory = filename.
|
|
17
|
+
const directory = filename.slice(0, index + 1);
|
|
16
18
|
upload.pathname = upload.pathname ? Cloud.joinPath(upload.pathname, directory) : directory;
|
|
17
|
-
filename = filename.
|
|
19
|
+
filename = filename.slice(index + 1);
|
|
18
20
|
}
|
|
19
21
|
return upload.filename = filename;
|
|
20
22
|
}
|
|
21
|
-
function
|
|
23
|
+
function fromSameBucket({ upload, service, bucket }, other) {
|
|
22
24
|
const endpoint = upload.endpoint;
|
|
23
25
|
return (service && other.service || endpoint && endpoint === other.upload.endpoint) && bucket === other.bucket;
|
|
24
26
|
}
|
|
25
27
|
function getFiles(file, data) {
|
|
26
28
|
const localUri = file.localUri;
|
|
27
|
-
const grouped = [localUri &&
|
|
29
|
+
const grouped = [localUri && ClientDb.isPath(localUri, true) ? localUri : ''];
|
|
28
30
|
if (data.all) {
|
|
29
31
|
if (file.descendants) {
|
|
30
32
|
grouped.push(...file.descendants);
|
|
@@ -43,19 +45,16 @@ function renameTrailing(map, item, folder, value) {
|
|
|
43
45
|
const location = folder + value;
|
|
44
46
|
map[location] ||= 1;
|
|
45
47
|
const index = value.indexOf('.');
|
|
46
|
-
item.filename = (index !== -1 ? value.
|
|
48
|
+
item.filename = (index !== -1 ? value.slice(0, index) : value) + '_' + map[location]++ + (index !== -1 ? value.slice(index) : '');
|
|
47
49
|
}
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
const errorObject = (err, service, value) => err instanceof Error ? err : typeof err === 'string' ? new Error(err) : (0, types_1.errorMessage)(service, value);
|
|
52
|
-
const assignFilename = (value) => crypto.randomUUID() + (path.extname(value) || '');
|
|
53
|
-
class Cloud extends core_1.ClientDb {
|
|
50
|
+
const errorObject = (err, service, value) => isError(err) ? err : typeof err === 'string' ? new Error(err) : errorMessage(service, value);
|
|
51
|
+
const assignFilename = (value) => randomUUID() + (path.extname(value) || '');
|
|
52
|
+
class Cloud extends ClientDb {
|
|
54
53
|
static [kCloud] = true;
|
|
55
54
|
static STORE_RESULT_PARTITION_SIZE = 16;
|
|
56
55
|
static STORE_RESULT_PARTITION_MULT = 2;
|
|
57
|
-
static LOG_CLOUD_SUCCESS =
|
|
58
|
-
static LOG_CLOUD_FAIL =
|
|
56
|
+
static LOG_CLOUD_SUCCESS = ClientDb.LOG_STYLE_SUCCESS;
|
|
57
|
+
static LOG_CLOUD_FAIL = ClientDb.LOG_STYLE_FAIL;
|
|
59
58
|
static LOG_CLOUD_COMMAND = Object.freeze({ titleColor: 'blue' });
|
|
60
59
|
static LOG_CLOUD_WARN = Object.freeze({ titleColor: 'yellow' });
|
|
61
60
|
static LOG_CLOUD_UPLOAD = Object.freeze({ titleColor: 'green' });
|
|
@@ -87,11 +86,11 @@ class Cloud extends core_1.ClientDb {
|
|
|
87
86
|
}
|
|
88
87
|
static async finalize(instance) {
|
|
89
88
|
if (instance.aborted) {
|
|
90
|
-
return
|
|
89
|
+
return createAbortError(true);
|
|
91
90
|
}
|
|
92
|
-
|
|
91
|
+
_a.sanitizeAssets(this.assets);
|
|
93
92
|
const localStorage = new Map();
|
|
94
|
-
const bucketGroup =
|
|
93
|
+
const bucketGroup = randomUUID();
|
|
95
94
|
const state = { host: this, instance, bucketGroup, localStorage };
|
|
96
95
|
const bucketDelete = {};
|
|
97
96
|
const bucketPolicy = {};
|
|
@@ -100,17 +99,17 @@ class Cloud extends core_1.ClientDb {
|
|
|
100
99
|
const startTime = process.hrtime.bigint();
|
|
101
100
|
let tasks = [], downloadMap;
|
|
102
101
|
if (await instance.commit()) {
|
|
103
|
-
instance.writeTimeElapsed(instance.moduleName, "Transactions were committed", startTime,
|
|
102
|
+
instance.writeTimeElapsed(instance.moduleName, "Transactions were committed", startTime, _a.optionsLogMessage('SUCCESS'));
|
|
104
103
|
}
|
|
105
104
|
for (const { instance: document } of this.Document) {
|
|
106
105
|
document.cloudInit?.(state);
|
|
107
106
|
}
|
|
108
107
|
for (const item of this.assets) {
|
|
109
108
|
const cloudStorage = item.cloudStorage;
|
|
110
|
-
if (
|
|
109
|
+
if (isArray(cloudStorage) && !ignoreFlag(item)) {
|
|
111
110
|
if (item.invalid) {
|
|
112
111
|
for (const storage of cloudStorage) {
|
|
113
|
-
instance.formatMessage(64, storage.service, ["Upload failed", storage.bucket],
|
|
112
|
+
instance.formatMessage(64, storage.service, ["Upload failed", storage.bucket], errorValue("File not found", item.uri || item.filename || "Unknown"), _a.optionsLogMessage('WARN'));
|
|
114
113
|
}
|
|
115
114
|
continue;
|
|
116
115
|
}
|
|
@@ -137,7 +136,7 @@ class Cloud extends core_1.ClientDb {
|
|
|
137
136
|
const service = bucketDelete[name] ||= {};
|
|
138
137
|
const items = service[bucket];
|
|
139
138
|
if (!items) {
|
|
140
|
-
let options =
|
|
139
|
+
let options = isObject(admin.emptyBucket) ? admin.emptyBucket : undefined;
|
|
141
140
|
if (typeof admin.recursive === 'boolean') {
|
|
142
141
|
(options ||= {}).recursive = admin.recursive;
|
|
143
142
|
}
|
|
@@ -165,7 +164,7 @@ class Cloud extends core_1.ClientDb {
|
|
|
165
164
|
if (tasks.length > 0) {
|
|
166
165
|
await instance.allSettled(tasks, ["Compress files", instance.moduleName]);
|
|
167
166
|
if (instance.aborted) {
|
|
168
|
-
return
|
|
167
|
+
return createAbortError(true);
|
|
169
168
|
}
|
|
170
169
|
tasks = [];
|
|
171
170
|
}
|
|
@@ -181,20 +180,20 @@ class Cloud extends core_1.ClientDb {
|
|
|
181
180
|
if (tasks.length > 0) {
|
|
182
181
|
await instance.allSettled(tasks, ["Empty bucket", instance.moduleName]);
|
|
183
182
|
if (instance.aborted) {
|
|
184
|
-
return
|
|
183
|
+
return createAbortError(true);
|
|
185
184
|
}
|
|
186
185
|
tasks = [];
|
|
187
186
|
}
|
|
188
187
|
if (rawFiles.length > 0) {
|
|
189
188
|
const options = { preferBuffer: process.env.EMC_CLOUD_UPLOAD_BUFFER === 'true' };
|
|
190
189
|
for (const item of rawFiles) {
|
|
191
|
-
tasks.push(...
|
|
190
|
+
tasks.push(..._a.uploadAsset(state, item, options));
|
|
192
191
|
}
|
|
193
192
|
}
|
|
194
193
|
if (tasks.length > 0) {
|
|
195
194
|
await instance.allSettled(tasks, ["Upload raw assets", instance.moduleName]);
|
|
196
195
|
if (instance.aborted) {
|
|
197
|
-
return
|
|
196
|
+
return createAbortError(true);
|
|
198
197
|
}
|
|
199
198
|
tasks = [];
|
|
200
199
|
}
|
|
@@ -219,7 +218,7 @@ class Cloud extends core_1.ClientDb {
|
|
|
219
218
|
if (tasks.length > 0) {
|
|
220
219
|
await instance.allSettled(tasks, ["Configure bucket", instance.moduleName]);
|
|
221
220
|
if (instance.aborted) {
|
|
222
|
-
return
|
|
221
|
+
return createAbortError(true);
|
|
223
222
|
}
|
|
224
223
|
tasks = [];
|
|
225
224
|
}
|
|
@@ -229,7 +228,7 @@ class Cloud extends core_1.ClientDb {
|
|
|
229
228
|
document.writeFail(["Handled rejection", document.moduleName], err, { type: 64, startTime });
|
|
230
229
|
});
|
|
231
230
|
if (document.aborted) {
|
|
232
|
-
return
|
|
231
|
+
return createAbortError(true);
|
|
233
232
|
}
|
|
234
233
|
}
|
|
235
234
|
}
|
|
@@ -244,7 +243,7 @@ class Cloud extends core_1.ClientDb {
|
|
|
244
243
|
}
|
|
245
244
|
for (const item of this.assets) {
|
|
246
245
|
const cloudStorage = item.cloudStorage;
|
|
247
|
-
if (
|
|
246
|
+
if (isArray(cloudStorage) && !ignoreFlag(item)) {
|
|
248
247
|
for (const data of cloudStorage) {
|
|
249
248
|
if (!instance.hasStorage('download', data)) {
|
|
250
249
|
continue;
|
|
@@ -258,8 +257,8 @@ class Cloud extends core_1.ClientDb {
|
|
|
258
257
|
let active = download.active, downloadUri;
|
|
259
258
|
if (pathname && path.isAbsolute(pathname)) {
|
|
260
259
|
downloadUri = path.join(pathname, filename);
|
|
261
|
-
if (!
|
|
262
|
-
instance.writeFail(["Unable to download file", filename],
|
|
260
|
+
if (!_a.isPath(downloadUri) && !this.canWrite(pathname)) {
|
|
261
|
+
instance.writeFail(["Unable to download file", filename], errorValue("Unsupported access", pathname), { type: 64, fatal: !!active, startTime });
|
|
263
262
|
continue;
|
|
264
263
|
}
|
|
265
264
|
}
|
|
@@ -267,14 +266,14 @@ class Cloud extends core_1.ClientDb {
|
|
|
267
266
|
downloadUri = pathname ? path.join(this.baseDirectory, pathname.replace(/^([A-Z]:)?[\\/]+/i, ''), filename) : path.join(data.admin?.preservePath && localUri ? path.dirname(localUri) : this.baseDirectory, filename);
|
|
268
267
|
}
|
|
269
268
|
const destDir = path.dirname(downloadUri);
|
|
270
|
-
if (
|
|
269
|
+
if (_a.isPath(downloadUri)) {
|
|
271
270
|
if (!active && !overwrite) {
|
|
272
271
|
continue;
|
|
273
272
|
}
|
|
274
273
|
active = true;
|
|
275
274
|
}
|
|
276
|
-
else if (!
|
|
277
|
-
instance.writeFail(["Unable to create directory", filename],
|
|
275
|
+
else if (!_a.createDir(destDir)) {
|
|
276
|
+
instance.writeFail(["Unable to create directory", filename], errorValue("Path is not a directory", destDir), { type: 64, fatal: !!active, startTime });
|
|
278
277
|
continue;
|
|
279
278
|
}
|
|
280
279
|
else if (active) {
|
|
@@ -294,7 +293,7 @@ class Cloud extends core_1.ClientDb {
|
|
|
294
293
|
}
|
|
295
294
|
pending = new Set([downloadUri]);
|
|
296
295
|
download.admin = data.admin;
|
|
297
|
-
download.flags = SERVICE_CLIENT.get(service).CLOUD_DOWNLOAD_CHUNK &&
|
|
296
|
+
download.flags = SERVICE_CLIENT.get(service).CLOUD_DOWNLOAD_CHUNK && alignSize(download.chunkSize) > 0 ? 4 : 0;
|
|
298
297
|
const task = instance.downloadObject(service, instance.getCredential(data), data.bucket, download, async (value) => {
|
|
299
298
|
if (instance.aborted || !value) {
|
|
300
299
|
return;
|
|
@@ -318,11 +317,11 @@ class Cloud extends core_1.ClientDb {
|
|
|
318
317
|
this.addDownload(size = value.length);
|
|
319
318
|
}
|
|
320
319
|
this.add(destUri);
|
|
321
|
-
this.formatMessage(64, service, ["Download success",
|
|
320
|
+
this.formatMessage(64, service, ["Download success", formatSize(size)], destUri, _a.optionsLogMessage('DOWNLOAD'));
|
|
322
321
|
result ||= destUri;
|
|
323
322
|
}
|
|
324
323
|
catch (err) {
|
|
325
|
-
if (!copy &&
|
|
324
|
+
if (!copy && isErrorCode(err, 'EXDEV')) {
|
|
326
325
|
copy = true;
|
|
327
326
|
--i;
|
|
328
327
|
}
|
|
@@ -349,7 +348,7 @@ class Cloud extends core_1.ClientDb {
|
|
|
349
348
|
}
|
|
350
349
|
static uploadAsset(state, file, contentType, ignoreProcess) {
|
|
351
350
|
let preferBuffer;
|
|
352
|
-
if (
|
|
351
|
+
if (isObject(contentType)) {
|
|
353
352
|
({ contentType, ignoreProcess, preferBuffer } = contentType);
|
|
354
353
|
}
|
|
355
354
|
else if (typeof contentType === 'boolean') {
|
|
@@ -375,7 +374,7 @@ class Cloud extends core_1.ClientDb {
|
|
|
375
374
|
if (client.CLOUD_UPLOAD_STREAM && upload.minStreamSize !== -1) {
|
|
376
375
|
flags |= 2;
|
|
377
376
|
}
|
|
378
|
-
if (client.CLOUD_UPLOAD_CHUNK &&
|
|
377
|
+
if (client.CLOUD_UPLOAD_CHUNK && alignSize(upload.chunkSize) > 0) {
|
|
379
378
|
flags |= 4;
|
|
380
379
|
}
|
|
381
380
|
}
|
|
@@ -385,13 +384,13 @@ class Cloud extends core_1.ClientDb {
|
|
|
385
384
|
const task = new Promise(resolve => {
|
|
386
385
|
const { service, bucket = state.bucketGroup, admin } = storage;
|
|
387
386
|
const credential = instance.getCredential(storage, true);
|
|
388
|
-
const minStreamSize =
|
|
387
|
+
const minStreamSize = alignSize(upload.minStreamSize);
|
|
389
388
|
const uploading = [];
|
|
390
389
|
getFiles(file, upload).forEach(async (group, index) => {
|
|
391
390
|
let fileGroup;
|
|
392
391
|
if (index === 0) {
|
|
393
392
|
if (!group[0]) {
|
|
394
|
-
instance.writeFail("Unable to read file",
|
|
393
|
+
instance.writeFail("Unable to read file", errorValue("File not found", service), { type: 64, fatal: true });
|
|
395
394
|
return;
|
|
396
395
|
}
|
|
397
396
|
if (group.length > 1) {
|
|
@@ -419,7 +418,7 @@ class Cloud extends core_1.ClientDb {
|
|
|
419
418
|
const localUri = group[i];
|
|
420
419
|
const exists = index === 0 || this.isPath(localUri, true);
|
|
421
420
|
if (!exists || !instance.canRead(localUri, { ownPermissionOnly: true })) {
|
|
422
|
-
instance.writeFail(["Unable to read file", path.basename(localUri)],
|
|
421
|
+
instance.writeFail(["Unable to read file", path.basename(localUri)], errorValue(!exists ? "File not found" : "Not permitted to read file", localUri), { type: 64, fatal: i === 0 && index === 0 });
|
|
423
422
|
continue;
|
|
424
423
|
}
|
|
425
424
|
let buffer, filename;
|
|
@@ -483,7 +482,7 @@ class Cloud extends core_1.ClientDb {
|
|
|
483
482
|
const storage = [];
|
|
484
483
|
for (const item of assets) {
|
|
485
484
|
const cloudStorage = item.cloudStorage;
|
|
486
|
-
if (
|
|
485
|
+
if (isArray(cloudStorage) && !ignoreFlag(item)) {
|
|
487
486
|
for (const data of cloudStorage) {
|
|
488
487
|
const upload = data.upload;
|
|
489
488
|
if (upload) {
|
|
@@ -516,7 +515,7 @@ class Cloud extends core_1.ClientDb {
|
|
|
516
515
|
if (current !== previous) {
|
|
517
516
|
for (const other of previous.cloudStorage) {
|
|
518
517
|
const leading = other.upload;
|
|
519
|
-
if (leading &&
|
|
518
|
+
if (leading && fromSameBucket(data, other)) {
|
|
520
519
|
const leadingFolder = leading.pathname || '';
|
|
521
520
|
if (basename && basename === leading.filename && leadingFolder === trailingFolder) {
|
|
522
521
|
renameTrailing(nameIndex, trailing, trailingFolder, basename);
|
|
@@ -558,7 +557,7 @@ class Cloud extends core_1.ClientDb {
|
|
|
558
557
|
}
|
|
559
558
|
async createBucket(service, credential, bucket, acl, options) {
|
|
560
559
|
if (this.aborted) {
|
|
561
|
-
return
|
|
560
|
+
return createAbortError(true);
|
|
562
561
|
}
|
|
563
562
|
const client = this.getClient(service);
|
|
564
563
|
try {
|
|
@@ -576,14 +575,14 @@ class Cloud extends core_1.ClientDb {
|
|
|
576
575
|
}
|
|
577
576
|
}
|
|
578
577
|
catch (err) {
|
|
579
|
-
this.formatMessage(64, service, ["Unable to create bucket", bucket], err,
|
|
578
|
+
this.formatMessage(64, service, ["Unable to create bucket", bucket], err, _a.optionsLogMessage('WARN'));
|
|
580
579
|
throw err;
|
|
581
580
|
}
|
|
582
|
-
throw
|
|
581
|
+
throw errorMessage(service, "Create bucket not supported");
|
|
583
582
|
}
|
|
584
583
|
async setBucketPolicy(service, credential, bucket, options) {
|
|
585
584
|
if (this.aborted) {
|
|
586
|
-
return
|
|
585
|
+
return createAbortError(true);
|
|
587
586
|
}
|
|
588
587
|
const handler = this.getClient(service).setBucketPolicy?.bind(this);
|
|
589
588
|
if (handler) {
|
|
@@ -591,15 +590,15 @@ class Cloud extends core_1.ClientDb {
|
|
|
591
590
|
return handler.call(this, credential, bucket, options);
|
|
592
591
|
}
|
|
593
592
|
catch (err) {
|
|
594
|
-
this.formatMessage(64, service, ["Unable to update bucket policy", bucket], err,
|
|
593
|
+
this.formatMessage(64, service, ["Unable to update bucket policy", bucket], err, _a.optionsLogMessage('WARN'));
|
|
595
594
|
throw err;
|
|
596
595
|
}
|
|
597
596
|
}
|
|
598
|
-
throw
|
|
597
|
+
throw errorMessage(service, "Bucket policy not supported");
|
|
599
598
|
}
|
|
600
599
|
async setBucketTagging(service, credential, bucket, options) {
|
|
601
600
|
if (this.aborted) {
|
|
602
|
-
return
|
|
601
|
+
return createAbortError(true);
|
|
603
602
|
}
|
|
604
603
|
const handler = this.getClient(service).setBucketTagging?.bind(this);
|
|
605
604
|
if (handler) {
|
|
@@ -607,15 +606,15 @@ class Cloud extends core_1.ClientDb {
|
|
|
607
606
|
return handler.call(this, credential, bucket, options);
|
|
608
607
|
}
|
|
609
608
|
catch (err) {
|
|
610
|
-
this.formatMessage(64, service, ["Unable to update bucket tagging", bucket], err,
|
|
609
|
+
this.formatMessage(64, service, ["Unable to update bucket tagging", bucket], err, _a.optionsLogMessage('WARN'));
|
|
611
610
|
throw err;
|
|
612
611
|
}
|
|
613
612
|
}
|
|
614
|
-
throw
|
|
613
|
+
throw errorMessage(service, "Bucket tagging not supported");
|
|
615
614
|
}
|
|
616
615
|
async setBucketWebsite(service, credential, bucket, options) {
|
|
617
616
|
if (this.aborted) {
|
|
618
|
-
return
|
|
617
|
+
return createAbortError(true);
|
|
619
618
|
}
|
|
620
619
|
const handler = this.getClient(service).setBucketWebsite?.bind(this);
|
|
621
620
|
if (handler) {
|
|
@@ -623,53 +622,53 @@ class Cloud extends core_1.ClientDb {
|
|
|
623
622
|
return handler.call(this, credential, bucket, options);
|
|
624
623
|
}
|
|
625
624
|
catch (err) {
|
|
626
|
-
this.formatMessage(64, service, ["Unable to configure bucket", bucket], err,
|
|
625
|
+
this.formatMessage(64, service, ["Unable to configure bucket", bucket], err, _a.optionsLogMessage('WARN'));
|
|
627
626
|
throw err;
|
|
628
627
|
}
|
|
629
628
|
}
|
|
630
|
-
throw
|
|
629
|
+
throw errorMessage(service, "Set bucket website not supported");
|
|
631
630
|
}
|
|
632
631
|
async deleteObjects(service, credential, bucket, options = true) {
|
|
633
632
|
if (this.aborted) {
|
|
634
|
-
return
|
|
633
|
+
return createAbortError(true);
|
|
635
634
|
}
|
|
636
635
|
const client = this.getClient(service);
|
|
637
636
|
const handlerV3 = client.deleteObjectsV3?.bind(this);
|
|
638
637
|
if (handlerV3) {
|
|
639
638
|
return handlerV3.call(this, credential, bucket, typeof options === 'boolean' ? { recursive: options } : options, service).catch((err) => {
|
|
640
|
-
errorResponse(
|
|
639
|
+
this.#errorResponse(service, bucket, err);
|
|
640
|
+
});
|
|
641
|
+
}
|
|
642
|
+
const handlerV1 = client.deleteObjects?.bind(this);
|
|
643
|
+
if (handlerV1) {
|
|
644
|
+
return handlerV1.call(this, credential, bucket, typeof options === 'boolean' ? { recursive: options } : options, service).catch((err) => {
|
|
645
|
+
this.#errorResponse(service, bucket, err);
|
|
641
646
|
});
|
|
642
647
|
}
|
|
643
|
-
const recursive =
|
|
648
|
+
const recursive = isObject(options) ? options.recursive : options;
|
|
644
649
|
const handlerV2 = client.deleteObjectsV2?.bind(this);
|
|
645
650
|
if (handlerV2) {
|
|
646
651
|
return handlerV2.call(this, credential, bucket, recursive ?? true, service).catch((err) => {
|
|
647
|
-
errorResponse(
|
|
652
|
+
this.#errorResponse(service, bucket, err);
|
|
648
653
|
});
|
|
649
654
|
}
|
|
650
|
-
|
|
651
|
-
if (handlerV1) {
|
|
652
|
-
return handlerV1.call(this, credential, bucket, service, undefined, recursive).catch((err) => {
|
|
653
|
-
errorResponse(this, service, bucket, err);
|
|
654
|
-
});
|
|
655
|
-
}
|
|
656
|
-
throw (0, types_1.errorMessage)(service, "Delete objects not supported");
|
|
655
|
+
throw errorMessage(service, "Delete objects not supported");
|
|
657
656
|
}
|
|
658
657
|
async copyObject(service, credential, bucketSource, keySource, bucket, key, options) {
|
|
659
658
|
if (this.aborted) {
|
|
660
|
-
return
|
|
659
|
+
return createAbortError(true);
|
|
661
660
|
}
|
|
662
661
|
const handler = this.getClient(service).copyObject?.bind(this);
|
|
663
662
|
if (handler) {
|
|
664
663
|
return handler.call(this, credential, bucketSource, keySource, bucket, key, options, service).catch((err) => {
|
|
665
|
-
errorResponse(
|
|
664
|
+
this.#errorResponse(service, bucket, err);
|
|
666
665
|
});
|
|
667
666
|
}
|
|
668
|
-
throw
|
|
667
|
+
throw errorMessage(service, "Copy object not supported");
|
|
669
668
|
}
|
|
670
669
|
async uploadObject(service, credential, bucket, upload, localUri, beforeResolve) {
|
|
671
670
|
if (this.aborted) {
|
|
672
|
-
return
|
|
671
|
+
return createAbortError(true);
|
|
673
672
|
}
|
|
674
673
|
try {
|
|
675
674
|
const handler = this.getUploadHandler(service, credential).bind(this);
|
|
@@ -679,7 +678,7 @@ class Cloud extends core_1.ClientDb {
|
|
|
679
678
|
if (err) {
|
|
680
679
|
reject(errorObject(err, service, "Upload failed"));
|
|
681
680
|
}
|
|
682
|
-
else if (
|
|
681
|
+
else if (isString(value)) {
|
|
683
682
|
if (beforeResolve) {
|
|
684
683
|
await beforeResolve(value);
|
|
685
684
|
}
|
|
@@ -688,21 +687,21 @@ class Cloud extends core_1.ClientDb {
|
|
|
688
687
|
resolve(value);
|
|
689
688
|
}
|
|
690
689
|
else {
|
|
691
|
-
reject(
|
|
690
|
+
reject(errorMessage(service, "Upload failed"));
|
|
692
691
|
}
|
|
693
692
|
});
|
|
694
693
|
});
|
|
695
694
|
}
|
|
696
695
|
catch (err) {
|
|
697
|
-
this.formatMessage(64, service, ["Upload function not supported", bucket], localUri,
|
|
696
|
+
this.formatMessage(64, service, ["Upload function not supported", bucket], localUri, _a.optionsLogMessage('WARN'));
|
|
698
697
|
throw err;
|
|
699
698
|
}
|
|
700
699
|
}
|
|
701
700
|
async downloadObject(service, credential, bucket, download, beforeResolve) {
|
|
702
701
|
if (this.aborted) {
|
|
703
|
-
return
|
|
702
|
+
return createAbortError(true);
|
|
704
703
|
}
|
|
705
|
-
if ((service === 'gcp' || service === 'gcloud') &&
|
|
704
|
+
if ((service === 'gcp' || service === 'gcloud') && isPlainObject(credential)) {
|
|
706
705
|
credential.storageBucket ||= bucket;
|
|
707
706
|
}
|
|
708
707
|
try {
|
|
@@ -715,30 +714,30 @@ class Cloud extends core_1.ClientDb {
|
|
|
715
714
|
else if (value) {
|
|
716
715
|
if (beforeResolve) {
|
|
717
716
|
const output = await beforeResolve(value);
|
|
718
|
-
if (
|
|
717
|
+
if (isString(output)) {
|
|
719
718
|
value = output;
|
|
720
719
|
}
|
|
721
720
|
}
|
|
722
|
-
if (
|
|
721
|
+
if (isString(value) && path.isAbsolute(value)) {
|
|
723
722
|
this.addLog(4, 'downloadObject: ' + bucket, service, value);
|
|
724
723
|
this.downloaded.push(value);
|
|
725
724
|
}
|
|
726
725
|
resolve(value);
|
|
727
726
|
}
|
|
728
727
|
else {
|
|
729
|
-
reject(
|
|
728
|
+
reject(errorMessage(service, "Download failed"));
|
|
730
729
|
}
|
|
731
730
|
});
|
|
732
731
|
});
|
|
733
732
|
}
|
|
734
733
|
catch (err) {
|
|
735
|
-
this.formatMessage(64, service, ["Download function not supported", bucket],
|
|
734
|
+
this.formatMessage(64, service, ["Download function not supported", bucket], _a.joinPath(download.pathname, download.filename), _a.optionsLogMessage('WARN'));
|
|
736
735
|
throw err;
|
|
737
736
|
}
|
|
738
737
|
}
|
|
739
738
|
async getDatabaseRows(item, ignoreErrors, sessionKey) {
|
|
740
739
|
if (this.aborted) {
|
|
741
|
-
return
|
|
740
|
+
return createAbortError(true);
|
|
742
741
|
}
|
|
743
742
|
if (typeof ignoreErrors === 'string') {
|
|
744
743
|
sessionKey = ignoreErrors;
|
|
@@ -750,7 +749,7 @@ class Cloud extends core_1.ClientDb {
|
|
|
750
749
|
if (client?.executeQuery) {
|
|
751
750
|
const credential = this.getCredential(item);
|
|
752
751
|
if (item.options && this.hasCoerce(service, 'options', credential)) {
|
|
753
|
-
|
|
752
|
+
coerceObject(item.options);
|
|
754
753
|
}
|
|
755
754
|
if (ignoreErrors) {
|
|
756
755
|
return client.executeQuery.call(this, credential, item, sessionKey);
|
|
@@ -759,17 +758,17 @@ class Cloud extends core_1.ClientDb {
|
|
|
759
758
|
return await client.executeQuery.call(this, credential, item, sessionKey);
|
|
760
759
|
}
|
|
761
760
|
catch (err) {
|
|
762
|
-
this.formatFail(64, service, "Unable to execute query", err,
|
|
761
|
+
this.formatFail(64, service, "Unable to execute query", err, _a.optionsLogMessage('FAIL'));
|
|
763
762
|
throw err;
|
|
764
763
|
}
|
|
765
764
|
}
|
|
766
|
-
throw
|
|
765
|
+
throw errorMessage(service, "Execute query not supported");
|
|
767
766
|
}
|
|
768
|
-
throw
|
|
767
|
+
throw errorMessage(service, "Invalid credentials");
|
|
769
768
|
}
|
|
770
769
|
async getDatabaseBatchRows(batch, ignoreErrors, sessionKey) {
|
|
771
770
|
if (this.aborted) {
|
|
772
|
-
return
|
|
771
|
+
return createAbortError(true);
|
|
773
772
|
}
|
|
774
773
|
if (typeof ignoreErrors === 'string') {
|
|
775
774
|
sessionKey = ignoreErrors;
|
|
@@ -784,7 +783,7 @@ class Cloud extends core_1.ClientDb {
|
|
|
784
783
|
if (this.hasCoerce(service, 'options', credential)) {
|
|
785
784
|
for (const item of batch) {
|
|
786
785
|
if (item.options) {
|
|
787
|
-
|
|
786
|
+
coerceObject(item.options);
|
|
788
787
|
}
|
|
789
788
|
}
|
|
790
789
|
}
|
|
@@ -795,28 +794,28 @@ class Cloud extends core_1.ClientDb {
|
|
|
795
794
|
return await client.executeBatchQuery.call(this, credential, batch, sessionKey);
|
|
796
795
|
}
|
|
797
796
|
catch (err) {
|
|
798
|
-
this.formatFail(64, service, "Unable to execute query", err,
|
|
797
|
+
this.formatFail(64, service, "Unable to execute query", err, _a.optionsLogMessage('FAIL'));
|
|
799
798
|
throw err;
|
|
800
799
|
}
|
|
801
800
|
}
|
|
802
|
-
throw
|
|
801
|
+
throw errorMessage(service, "Execute query not supported");
|
|
803
802
|
}
|
|
804
|
-
throw
|
|
803
|
+
throw errorMessage(service, "Invalid credentials");
|
|
805
804
|
}
|
|
806
805
|
getCredential(item, unused) {
|
|
807
806
|
const service = item.service;
|
|
808
807
|
let credential = item.credential, stored = false;
|
|
809
808
|
if (typeof credential === 'string') {
|
|
810
809
|
const settings = this.getSettings(service);
|
|
811
|
-
if (
|
|
810
|
+
if (isPlainObject(settings)) {
|
|
812
811
|
credential = settings[credential];
|
|
813
812
|
stored = true;
|
|
814
813
|
}
|
|
815
814
|
}
|
|
816
|
-
if (
|
|
815
|
+
if (isPlainObject(credential)) {
|
|
817
816
|
item.credential = credential;
|
|
818
817
|
if (this.settingsOf(service, 'coerce', 'credential') === true) {
|
|
819
|
-
|
|
818
|
+
coerceObject(credential, stored);
|
|
820
819
|
}
|
|
821
820
|
return unused ? credential : { ...credential };
|
|
822
821
|
}
|
|
@@ -826,7 +825,7 @@ class Cloud extends core_1.ClientDb {
|
|
|
826
825
|
return this.module[service];
|
|
827
826
|
}
|
|
828
827
|
getStorage(action, data) {
|
|
829
|
-
if (
|
|
828
|
+
if (isArray(data)) {
|
|
830
829
|
for (const item of data) {
|
|
831
830
|
const service = this.hasStorage(action, item);
|
|
832
831
|
if (service && service.active) {
|
|
@@ -861,7 +860,7 @@ class Cloud extends core_1.ClientDb {
|
|
|
861
860
|
}
|
|
862
861
|
}
|
|
863
862
|
catch (err) {
|
|
864
|
-
this.formatFail(64, data.service, "Cloud provider not found", err,
|
|
863
|
+
this.formatFail(64, data.service, "Cloud provider not found", err, _a.optionsLogMessage('FAIL'));
|
|
865
864
|
}
|
|
866
865
|
return false;
|
|
867
866
|
}
|
|
@@ -874,7 +873,7 @@ class Cloud extends core_1.ClientDb {
|
|
|
874
873
|
resolveService(service, folder) {
|
|
875
874
|
let result;
|
|
876
875
|
if (!service.startsWith('@')) {
|
|
877
|
-
result = this.settings.imports?.[service] ||
|
|
876
|
+
result = this.settings.imports?.[service] || IMPORT_MAP[service];
|
|
878
877
|
}
|
|
879
878
|
else {
|
|
880
879
|
folder ||= 'client';
|
|
@@ -883,11 +882,11 @@ class Cloud extends core_1.ClientDb {
|
|
|
883
882
|
}
|
|
884
883
|
settingsOf(service, name, component) {
|
|
885
884
|
const result = this.settings[service]?.[name];
|
|
886
|
-
return component ?
|
|
885
|
+
return component ? isObject(result) ? result[component] : undefined : result;
|
|
887
886
|
}
|
|
888
887
|
async commit() {
|
|
889
888
|
if (this.aborted) {
|
|
890
|
-
return
|
|
889
|
+
return createAbortError(true);
|
|
891
890
|
}
|
|
892
891
|
const items = this.pending.filter(item => !item.document).map(async (data) => {
|
|
893
892
|
data.ignoreCache ??= true;
|
|
@@ -907,9 +906,15 @@ class Cloud extends core_1.ClientDb {
|
|
|
907
906
|
return client;
|
|
908
907
|
}
|
|
909
908
|
}
|
|
910
|
-
catch {
|
|
909
|
+
catch (err) {
|
|
910
|
+
this.addLog(3, err, service);
|
|
911
911
|
}
|
|
912
|
-
throw service ?
|
|
912
|
+
throw service ? errorMessage(service, "Cloud provider not found") : errorValue("Cloud provider not found");
|
|
913
|
+
}
|
|
914
|
+
#errorResponse(service, bucket, err) {
|
|
915
|
+
this.formatMessage(64, service, ["Unable to empty bucket", bucket], err, _a.optionsLogMessage('WARN'));
|
|
913
916
|
}
|
|
914
917
|
}
|
|
918
|
+
_a = Cloud;
|
|
919
|
+
|
|
915
920
|
module.exports = Cloud;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@e-mc/cloud",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.14.0",
|
|
4
4
|
"description": "Cloud constructor for E-mc.",
|
|
5
5
|
"main": "index.js",
|
|
6
6
|
"types": "index.d.ts",
|
|
@@ -19,9 +19,9 @@
|
|
|
19
19
|
"license": "BSD-3-Clause",
|
|
20
20
|
"homepage": "https://github.com/anpham6/e-mc#readme",
|
|
21
21
|
"dependencies": {
|
|
22
|
-
"@e-mc/core": "0.
|
|
23
|
-
"@e-mc/db": "0.
|
|
24
|
-
"@e-mc/types": "0.
|
|
22
|
+
"@e-mc/core": "0.14.0",
|
|
23
|
+
"@e-mc/db": "0.14.0",
|
|
24
|
+
"@e-mc/types": "0.14.0",
|
|
25
25
|
"mime-types": "^3.0.2"
|
|
26
26
|
}
|
|
27
27
|
}
|
package/types/index.d.ts
CHANGED
|
@@ -18,10 +18,11 @@ export interface ICloudServiceClient<T extends CloudDatabase = CloudDatabase, U
|
|
|
18
18
|
setBucketPolicy?(this: IModule, credential: U, bucket: string, options: unknown, service?: string, sdk?: string): Promise<boolean>;
|
|
19
19
|
setBucketTagging?(this: IModule, credential: U, bucket: string, options: unknown, service?: string, sdk?: string): Promise<boolean>;
|
|
20
20
|
setBucketWebsite?(this: IModule, credential: U, bucket: string, options: BucketWebsiteOptions, service?: string, sdk?: string): Promise<boolean>;
|
|
21
|
-
|
|
22
|
-
deleteObjects?(this: IModule, credential: U, bucket: string,
|
|
21
|
+
copyObject?(this: IModule, credential: U, bucketSource: string, keySource: string, bucket: string, key: string, options?: unknown, service?: string, sdk?: string): Promise<void>;
|
|
22
|
+
deleteObjects?(this: IModule, credential: U, bucket: string, options?: DeleteObjectsOptions, service?: string, sdk?: string): Promise<void>;
|
|
23
23
|
/** @deprecated */
|
|
24
24
|
deleteObjectsV2?(this: IModule, credential: U, bucket: string, recursive?: boolean, service?: string, sdk?: string): Promise<void>;
|
|
25
|
+
/** @deprecated */
|
|
25
26
|
deleteObjectsV3?(this: IModule, credential: U, bucket: string, options?: DeleteObjectsOptions, service?: string, sdk?: string): Promise<void>;
|
|
26
27
|
copyObject?(this: IModule, credential: U, bucketSource: string, keySource: string, bucket: string, key: string, options?: unknown, service?: string, sdk?: string): Promise<void>;
|
|
27
28
|
executeQuery?(this: ICloud, credential: V, data: T, sessionKey?: string): Promise<QueryResult>;
|
package/util.d.ts
CHANGED
|
@@ -6,7 +6,7 @@ import type { Readable } from 'node:stream';
|
|
|
6
6
|
|
|
7
7
|
declare namespace util {
|
|
8
8
|
interface CreateKeyAndBodyOptions {
|
|
9
|
-
errorCallback?:
|
|
9
|
+
errorCallback?: FunctionReturn<void>;
|
|
10
10
|
descendantsGroup?: string[];
|
|
11
11
|
flags?: number;
|
|
12
12
|
chunkSize?: number;
|
|
@@ -15,9 +15,9 @@ declare namespace util {
|
|
|
15
15
|
|
|
16
16
|
function readableAsBuffer(from: Readable): Promise<Buffer | null>;
|
|
17
17
|
function createKeyAndBody<T = Buffer>(filename: string, items: UploadContent[], options: CreateKeyAndBodyOptions): [string[], T[], string[]];
|
|
18
|
-
function createKeyAndBody<T = Buffer>(filename: string, items: UploadContent[], errorCallback:
|
|
18
|
+
function createKeyAndBody<T = Buffer>(filename: string, items: UploadContent[], errorCallback: FunctionReturn<void>, flags?: number): [string[], T[], string[]];
|
|
19
19
|
/** @deprecated options */
|
|
20
|
-
function createKeyAndBody<T = Buffer>(filename: string, items: UploadContent[], chunkSize?: number | string |
|
|
20
|
+
function createKeyAndBody<T = Buffer>(filename: string, items: UploadContent[], chunkSize?: number | string | FunctionReturn<void>, errorCallback?: FunctionReturn<void> | number, flags?: number, descendantsGroup?: string[]): [string[], T[], string[]];
|
|
21
21
|
function createErrorHandler(instance: IModule, service: string, bucket: string): (err: unknown) => void;
|
|
22
22
|
function generateFilename(filename: string): (i: number) => [string, boolean];
|
|
23
23
|
function getBasicAuth(auth: AuthValue): string;
|
package/util.js
CHANGED
|
@@ -1,19 +1,11 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
const path = require("node:path");
|
|
10
|
-
const fs = require("node:fs");
|
|
11
|
-
const stream = require("node:stream");
|
|
12
|
-
const mime = require("mime-types");
|
|
13
|
-
const types_1 = require("@e-mc/types");
|
|
14
|
-
const util_1 = require("@e-mc/db/util");
|
|
15
|
-
Object.defineProperty(exports, "getBasicAuth", { enumerable: true, get: function () { return util_1.getBasicAuth; } });
|
|
16
|
-
Object.defineProperty(exports, "hasBasicAuth", { enumerable: true, get: function () { return util_1.hasBasicAuth; } });
|
|
2
|
+
|
|
3
|
+
const path = require('node:path');
|
|
4
|
+
const fs = require('node:fs');
|
|
5
|
+
const stream = require('node:stream');
|
|
6
|
+
const mime = require('mime-types');
|
|
7
|
+
const { errorMessage, incrementUUID, isObject, isPlainObject } = require('@e-mc/types');
|
|
8
|
+
const { getBasicAuth, hasBasicAuth } = require('@e-mc/db/util');
|
|
17
9
|
async function readableAsBuffer(from) {
|
|
18
10
|
return new Promise((resolve, reject) => {
|
|
19
11
|
let result = null;
|
|
@@ -30,10 +22,10 @@ async function readableAsBuffer(from) {
|
|
|
30
22
|
.read();
|
|
31
23
|
});
|
|
32
24
|
}
|
|
33
|
-
function createKeyAndBody(filename, items, chunkSize = 0, errorCallback, flags = 0, descendantsGroup
|
|
25
|
+
function createKeyAndBody(filename, items, chunkSize = 0, errorCallback, flags = 0, descendantsGroup) {
|
|
34
26
|
let mimeType;
|
|
35
|
-
if (
|
|
36
|
-
({ errorCallback, mimeType, chunkSize = 0, flags = 0
|
|
27
|
+
if (isPlainObject(chunkSize)) {
|
|
28
|
+
({ errorCallback, mimeType, descendantsGroup, chunkSize = 0, flags = 0 } = chunkSize);
|
|
37
29
|
}
|
|
38
30
|
else {
|
|
39
31
|
switch (typeof chunkSize) {
|
|
@@ -110,10 +102,9 @@ function createKeyAndBody(filename, items, chunkSize = 0, errorCallback, flags =
|
|
|
110
102
|
}
|
|
111
103
|
if (target) {
|
|
112
104
|
const output = filename + ext;
|
|
113
|
-
|
|
114
|
-
key.push(descendant && localFile ? path.basename(localFile) : output);
|
|
105
|
+
key.push(Array.isArray(descendantsGroup) && descendantsGroup.includes(ext) && localFile ? path.basename(localFile) : output);
|
|
115
106
|
body.push(target);
|
|
116
|
-
type.push(
|
|
107
|
+
type.push(type.length === 0 && mimeType ? mimeType : mime.lookup(output) || "application/octet-stream");
|
|
117
108
|
}
|
|
118
109
|
}
|
|
119
110
|
catch (err) {
|
|
@@ -140,20 +131,29 @@ function generateFilename(filename) {
|
|
|
140
131
|
const type = /\.[a-z0-9]+\.[a-z0-9]+$/i.exec(filename);
|
|
141
132
|
const j = type ? type.index : filename.lastIndexOf('.');
|
|
142
133
|
if (j !== -1) {
|
|
143
|
-
const match = /^(.+)_(\d+)$/.exec(basename = filename.
|
|
134
|
+
const match = /^(.+)_(\d+)$/.exec(basename = filename.slice(0, j));
|
|
144
135
|
if (match) {
|
|
145
136
|
basename = match[1];
|
|
146
137
|
i = parseInt(match[2]) + 1;
|
|
147
138
|
}
|
|
148
|
-
suffix = filename.
|
|
139
|
+
suffix = filename.slice(j);
|
|
149
140
|
}
|
|
150
141
|
}
|
|
151
|
-
return basename && suffix ? [basename + `_${i}` + suffix, true] : [
|
|
142
|
+
return basename && suffix ? [basename + `_${i}` + suffix, true] : [incrementUUID() + path.extname(filename), false];
|
|
152
143
|
};
|
|
153
144
|
}
|
|
154
145
|
function formatError(title, value, hint) {
|
|
155
|
-
if (
|
|
146
|
+
if (isObject(title)) {
|
|
156
147
|
title = title.service;
|
|
157
148
|
}
|
|
158
|
-
return
|
|
149
|
+
return errorMessage(typeof title === 'string' ? title : '', value, hint);
|
|
159
150
|
}
|
|
151
|
+
|
|
152
|
+
exports.createErrorHandler = createErrorHandler;
|
|
153
|
+
exports.createKeyAndBody = createKeyAndBody;
|
|
154
|
+
exports.formatError = formatError;
|
|
155
|
+
exports.generateFilename = generateFilename;
|
|
156
|
+
exports.getBasicAuth = getBasicAuth;
|
|
157
|
+
exports.hasBasicAuth = hasBasicAuth;
|
|
158
|
+
exports.intoArray = intoArray;
|
|
159
|
+
exports.readableAsBuffer = readableAsBuffer;
|