@pi-r/azure 0.11.3 → 0.12.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/client/index.js +49 -45
- package/download/index.js +16 -14
- package/package.json +4 -4
- package/upload/index.js +23 -21
package/client/index.js
CHANGED
|
@@ -1,25 +1,12 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
exports.deleteObjects = deleteObjects;
|
|
11
|
-
exports.deleteObjectsV2 = deleteObjectsV2;
|
|
12
|
-
exports.deleteObjectsV3 = deleteObjectsV3;
|
|
13
|
-
exports.copyObject = copyObject;
|
|
14
|
-
exports.executeQuery = executeQuery;
|
|
15
|
-
exports.executeBatchQuery = executeBatchQuery;
|
|
16
|
-
const path = require("node:path");
|
|
17
|
-
const storage = require("@azure/storage-blob");
|
|
18
|
-
const cosmos = require("@azure/cosmos");
|
|
19
|
-
const identity = require("@azure/identity");
|
|
20
|
-
const Cloud = require("@e-mc/cloud");
|
|
21
|
-
const types_1 = require("@e-mc/types");
|
|
22
|
-
const util_1 = require("@e-mc/cloud/util");
|
|
2
|
+
|
|
3
|
+
const path = require('node:path');
|
|
4
|
+
const { AnonymousCredential, BlobServiceClient, StorageSharedKeyCredential } = require('@azure/storage-blob');
|
|
5
|
+
const { CosmosClient } = require('@azure/cosmos');
|
|
6
|
+
const { DefaultAzureCredential, EnvironmentCredential, UsernamePasswordCredential } = require('@azure/identity');
|
|
7
|
+
const Cloud = require('@e-mc/cloud');
|
|
8
|
+
const { errorMessage, isErrorCode, isString } = require('@e-mc/types');
|
|
9
|
+
const { formatError } = require('@e-mc/cloud/util');
|
|
23
10
|
function isEnvironmentCredential() {
|
|
24
11
|
const env = process.env;
|
|
25
12
|
return !!(env.AZURE_TENANT_ID && env.AZURE_CLIENT_ID && (env.AZURE_CLIENT_SECRET || env.AZURE_CLIENT_CERTIFICATE_PATH));
|
|
@@ -40,7 +27,7 @@ function createStorageClient(credential) {
|
|
|
40
27
|
if (!accountName) {
|
|
41
28
|
credential.accountName = /AccountName=([^;]+);/.exec(connectionString)?.[1];
|
|
42
29
|
}
|
|
43
|
-
return
|
|
30
|
+
return BlobServiceClient.fromConnectionString(connectionString, credential.clientOptions);
|
|
44
31
|
}
|
|
45
32
|
if (accountSas && !accountSas.startsWith('?')) {
|
|
46
33
|
accountSas = '?' + accountSas;
|
|
@@ -55,26 +42,26 @@ function createStorageClient(credential) {
|
|
|
55
42
|
else {
|
|
56
43
|
credential.accountName ||= /^https:\/\/([a-z\d]+)\./.exec(sharedAccessSignature)?.[1];
|
|
57
44
|
}
|
|
58
|
-
return new
|
|
45
|
+
return new BlobServiceClient(sharedAccessSignature);
|
|
59
46
|
}
|
|
60
47
|
let serviceCredential;
|
|
61
48
|
if (accountName && accountSas) {
|
|
62
|
-
serviceCredential = new
|
|
49
|
+
serviceCredential = new AnonymousCredential();
|
|
63
50
|
}
|
|
64
51
|
else if (accountName && accountKey) {
|
|
65
|
-
serviceCredential = new
|
|
52
|
+
serviceCredential = new StorageSharedKeyCredential(accountName, accountKey);
|
|
66
53
|
}
|
|
67
54
|
else if (isEnvironmentCredential()) {
|
|
68
|
-
serviceCredential = new
|
|
55
|
+
serviceCredential = new EnvironmentCredential();
|
|
69
56
|
}
|
|
70
57
|
else {
|
|
71
|
-
serviceCredential = new
|
|
58
|
+
serviceCredential = new DefaultAzureCredential(credential.defaultAzureOptions);
|
|
72
59
|
}
|
|
73
|
-
return new
|
|
60
|
+
return new BlobServiceClient(url, serviceCredential, credential.clientOptions);
|
|
74
61
|
}
|
|
75
62
|
function createDatabaseClient(credential) {
|
|
76
63
|
if (credential.username && credential.password && credential.tenantId && credential.clientId) {
|
|
77
|
-
credential.aadCredentials = new
|
|
64
|
+
credential.aadCredentials = new UsernamePasswordCredential(credential.username, credential.password, credential.tenantId, credential.clientId);
|
|
78
65
|
credential = { ...credential };
|
|
79
66
|
delete credential.username;
|
|
80
67
|
delete credential.password;
|
|
@@ -82,9 +69,9 @@ function createDatabaseClient(credential) {
|
|
|
82
69
|
delete credential.clientId;
|
|
83
70
|
}
|
|
84
71
|
else if (isEnvironmentCredential()) {
|
|
85
|
-
credential.aadCredentials = new
|
|
72
|
+
credential.aadCredentials = new EnvironmentCredential();
|
|
86
73
|
}
|
|
87
|
-
return new
|
|
74
|
+
return new CosmosClient(credential);
|
|
88
75
|
}
|
|
89
76
|
async function createBucket(credential, bucket, publicRead, service = "azure") {
|
|
90
77
|
return createBucketV2.call(this, credential, bucket, publicRead ? 'blob' : 'container', undefined, service);
|
|
@@ -119,7 +106,7 @@ async function createBucketV2(credential, bucket, access, options, service = "az
|
|
|
119
106
|
.then(response => {
|
|
120
107
|
const { requestId, errorCode } = response;
|
|
121
108
|
if (errorCode) {
|
|
122
|
-
this.formatMessage(64, service, ['Container created with errors', bucket],
|
|
109
|
+
this.formatMessage(64, service, ['Container created with errors', bucket], errorMessage("Error code", errorCode), Cloud.optionsLogMessage('WARN'));
|
|
123
110
|
}
|
|
124
111
|
else {
|
|
125
112
|
this.formatMessage(64, service, ['Container created', bucket], requestId, Cloud.optionsLogMessage('COMMAND'));
|
|
@@ -127,7 +114,7 @@ async function createBucketV2(credential, bucket, access, options, service = "az
|
|
|
127
114
|
return true;
|
|
128
115
|
})
|
|
129
116
|
.catch(async (err) => {
|
|
130
|
-
if (
|
|
117
|
+
if (isErrorCode(err, 'ContainerAlreadyExists')) {
|
|
131
118
|
if (access) {
|
|
132
119
|
await setAccessPolicy();
|
|
133
120
|
}
|
|
@@ -140,20 +127,20 @@ async function createBucketV2(credential, bucket, access, options, service = "az
|
|
|
140
127
|
async function setBucketWebsite(credential, bucket, options, service = "azure") {
|
|
141
128
|
const staticWebsite = { enabled: true };
|
|
142
129
|
const { indexPage, indexPath, errorPath } = options;
|
|
143
|
-
if (
|
|
130
|
+
if (isString(indexPage)) {
|
|
144
131
|
staticWebsite.indexDocument = path.basename(indexPage);
|
|
145
132
|
}
|
|
146
|
-
if (
|
|
133
|
+
if (isString(indexPath)) {
|
|
147
134
|
staticWebsite.defaultIndexDocumentPath = Cloud.joinPath(bucket, indexPath);
|
|
148
135
|
}
|
|
149
|
-
if (
|
|
136
|
+
if (isString(errorPath)) {
|
|
150
137
|
staticWebsite.errorDocument404Path = Cloud.joinPath(bucket, errorPath);
|
|
151
138
|
}
|
|
152
139
|
return createStorageClient(credential).setProperties({ staticWebsite })
|
|
153
140
|
.then(response => {
|
|
154
141
|
const { requestId, errorCode } = response;
|
|
155
142
|
if (errorCode) {
|
|
156
|
-
this.formatMessage(64, service, ["Bucket website configured" + ' with errors', bucket],
|
|
143
|
+
this.formatMessage(64, service, ["Bucket website configured" + ' with errors', bucket], errorMessage("Error code", errorCode), Cloud.optionsLogMessage('WARN'));
|
|
157
144
|
}
|
|
158
145
|
else {
|
|
159
146
|
this.formatMessage(64, service, ["Bucket website configured", bucket], requestId, Cloud.optionsLogMessage('COMMAND'));
|
|
@@ -165,8 +152,8 @@ async function setBucketWebsite(credential, bucket, options, service = "azure")
|
|
|
165
152
|
return false;
|
|
166
153
|
});
|
|
167
154
|
}
|
|
168
|
-
async function deleteObjects(credential, bucket,
|
|
169
|
-
return
|
|
155
|
+
async function deleteObjects(credential, bucket, options, service) {
|
|
156
|
+
return deleteObjectsV3.call(this, credential, bucket, options, service);
|
|
170
157
|
}
|
|
171
158
|
async function deleteObjectsV2(credential, bucket, recursive = true, service) {
|
|
172
159
|
return deleteObjectsV3.call(this, credential, bucket, { recursive }, service);
|
|
@@ -210,7 +197,7 @@ async function copyObject(credential, bucketSource, keySource, bucket, key, opti
|
|
|
210
197
|
return poller.pollUntilDone()
|
|
211
198
|
.then(response => {
|
|
212
199
|
if (response.errorCode) {
|
|
213
|
-
this.formatMessage(64, service, ["Copy success" + ' with errors', bucket],
|
|
200
|
+
this.formatMessage(64, service, ["Copy success" + ' with errors', bucket], errorMessage("Error code", response.errorCode, bucketSource), Cloud.optionsLogMessage('WARN'));
|
|
214
201
|
}
|
|
215
202
|
else {
|
|
216
203
|
this.formatMessage(64, service, ["Copy success", bucket], bucketSource + '/' + keySource, Cloud.optionsLogMessage('COMMAND'));
|
|
@@ -243,7 +230,7 @@ async function executeBatchQuery(credential, batch, sessionKey) {
|
|
|
243
230
|
const { service, name, table, id, query, storedProcedureId, partitionKey = null, params, limit = 0, ignoreCache } = item;
|
|
244
231
|
if (!name || !table) {
|
|
245
232
|
closeClient();
|
|
246
|
-
throw
|
|
233
|
+
throw formatError(item, name ? "Missing database table" : "Missing database name");
|
|
247
234
|
}
|
|
248
235
|
cacheValue.exclusiveOf = Array.isArray(ignoreCache) ? ignoreCache : undefined;
|
|
249
236
|
let rows, queryString = caching && ignoreCache !== true ? name + '_' + table + '_' : '';
|
|
@@ -306,7 +293,7 @@ async function executeBatchQuery(credential, batch, sessionKey) {
|
|
|
306
293
|
}
|
|
307
294
|
else {
|
|
308
295
|
closeClient();
|
|
309
|
-
throw
|
|
296
|
+
throw formatError(item, "Missing database query");
|
|
310
297
|
}
|
|
311
298
|
}
|
|
312
299
|
result[i] = this.setQueryResult(service, credential, queryString, rows, cacheValue);
|
|
@@ -314,6 +301,23 @@ async function executeBatchQuery(credential, batch, sessionKey) {
|
|
|
314
301
|
closeClient();
|
|
315
302
|
return result;
|
|
316
303
|
}
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
304
|
+
const CLOUD_UPLOAD_STREAM = true;
|
|
305
|
+
const CLOUD_UPLOAD_CHUNK = true;
|
|
306
|
+
const CLOUD_DOWNLOAD_CHUNK = true;
|
|
307
|
+
|
|
308
|
+
exports.CLOUD_DOWNLOAD_CHUNK = CLOUD_DOWNLOAD_CHUNK;
|
|
309
|
+
exports.CLOUD_UPLOAD_CHUNK = CLOUD_UPLOAD_CHUNK;
|
|
310
|
+
exports.CLOUD_UPLOAD_STREAM = CLOUD_UPLOAD_STREAM;
|
|
311
|
+
exports.copyObject = copyObject;
|
|
312
|
+
exports.createBucket = createBucket;
|
|
313
|
+
exports.createBucketV2 = createBucketV2;
|
|
314
|
+
exports.createDatabaseClient = createDatabaseClient;
|
|
315
|
+
exports.createStorageClient = createStorageClient;
|
|
316
|
+
exports.deleteObjects = deleteObjects;
|
|
317
|
+
exports.deleteObjectsV2 = deleteObjectsV2;
|
|
318
|
+
exports.deleteObjectsV3 = deleteObjectsV3;
|
|
319
|
+
exports.executeBatchQuery = executeBatchQuery;
|
|
320
|
+
exports.executeQuery = executeQuery;
|
|
321
|
+
exports.setBucketWebsite = setBucketWebsite;
|
|
322
|
+
exports.validateDatabase = validateDatabase;
|
|
323
|
+
exports.validateStorage = validateStorage;
|
package/download/index.js
CHANGED
|
@@ -1,23 +1,24 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
-
|
|
3
|
-
const
|
|
4
|
-
const
|
|
5
|
-
const
|
|
6
|
-
const
|
|
2
|
+
|
|
3
|
+
const path = require('node:path');
|
|
4
|
+
const Cloud = require('@e-mc/cloud');
|
|
5
|
+
const { alignSize, errorValue, getTempDir, isErrorCode, isPlainObject } = require('@e-mc/types');
|
|
6
|
+
const { createErrorHandler, intoArray } = require('@e-mc/cloud/util');
|
|
7
|
+
const { copyObject, createStorageClient } = require('@pi-r/azure');
|
|
7
8
|
function download(credential, service = "azure") {
|
|
8
|
-
const blobServiceClient =
|
|
9
|
+
const blobServiceClient = createStorageClient(credential);
|
|
9
10
|
return (data, callback) => {
|
|
10
11
|
const { bucket, download: target } = data;
|
|
11
12
|
const key = target.keyname || target.filename;
|
|
12
13
|
if (!bucket || !key) {
|
|
13
|
-
callback(
|
|
14
|
+
callback(errorValue('Missing property', !bucket ? 'Container' : 'Name'));
|
|
14
15
|
return;
|
|
15
16
|
}
|
|
16
17
|
const { flags = 0 } = target;
|
|
17
18
|
const containerClient = blobServiceClient.getContainerClient(bucket);
|
|
18
19
|
const blobClient = containerClient.getBlockBlobClient(key);
|
|
19
|
-
const blockSize = (flags & 4) &&
|
|
20
|
-
const tempDir = blockSize >= 2097152000 ?
|
|
20
|
+
const blockSize = (flags & 4) && alignSize(target.chunkSize, 1024) || 0;
|
|
21
|
+
const tempDir = blockSize >= 2097152000 ? getTempDir(true, service) : null;
|
|
21
22
|
let diskClient, destination;
|
|
22
23
|
if (tempDir) {
|
|
23
24
|
destination = path.join(tempDir, path.basename(target.filename || key));
|
|
@@ -29,26 +30,26 @@ function download(credential, service = "azure") {
|
|
|
29
30
|
diskClient
|
|
30
31
|
.then(async (value) => {
|
|
31
32
|
callback(null, destination || value);
|
|
32
|
-
const copyTo =
|
|
33
|
+
const copyTo = intoArray(target.copyObject);
|
|
33
34
|
if (copyTo) {
|
|
34
35
|
const tasks = [];
|
|
35
36
|
for (const { bucket: bucketName, pathname, filename, options } of copyTo) {
|
|
36
37
|
const keyObject = filename ? Cloud.joinPath(pathname, filename, true) : key;
|
|
37
|
-
tasks.push(
|
|
38
|
+
tasks.push(copyObject
|
|
38
39
|
.call(this, credential, bucket, key, bucketName, keyObject, options)
|
|
39
|
-
.catch(
|
|
40
|
+
.catch(createErrorHandler(this, service, bucket)));
|
|
40
41
|
}
|
|
41
42
|
await Promise.all(tasks);
|
|
42
43
|
}
|
|
43
44
|
const deleteObject = target.deleteObject;
|
|
44
45
|
if (deleteObject) {
|
|
45
46
|
const location = Cloud.joinPath(bucket, key);
|
|
46
|
-
containerClient.delete(
|
|
47
|
+
containerClient.delete(isPlainObject(deleteObject) ? { ...deleteObject, abortSignal: this.signal } : { abortSignal: this.signal })
|
|
47
48
|
.then(() => {
|
|
48
49
|
this.formatMessage(64, service, "Delete success", location, Cloud.optionsLogMessage('DELETE'));
|
|
49
50
|
})
|
|
50
51
|
.catch((err) => {
|
|
51
|
-
if (!
|
|
52
|
+
if (!isErrorCode(err, 'BlobNotFound')) {
|
|
52
53
|
this.formatFail(64, service, ["Delete failed", location], err, Cloud.optionsLogMessage('FAIL', { fatal: !!target.active }));
|
|
53
54
|
}
|
|
54
55
|
});
|
|
@@ -57,4 +58,5 @@ function download(credential, service = "azure") {
|
|
|
57
58
|
.catch(callback);
|
|
58
59
|
};
|
|
59
60
|
}
|
|
61
|
+
|
|
60
62
|
module.exports = download;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@pi-r/azure",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.12.0",
|
|
4
4
|
"description": "Azure cloud functions for E-mc.",
|
|
5
5
|
"main": "client/index.js",
|
|
6
6
|
"publishConfig": {
|
|
@@ -19,9 +19,9 @@
|
|
|
19
19
|
"license": "MIT",
|
|
20
20
|
"homepage": "https://github.com/anpham6/pi-r#readme",
|
|
21
21
|
"dependencies": {
|
|
22
|
-
"@e-mc/cloud": "^0.
|
|
23
|
-
"@e-mc/module": "^0.
|
|
24
|
-
"@e-mc/types": "^0.
|
|
22
|
+
"@e-mc/cloud": "^0.14.0",
|
|
23
|
+
"@e-mc/module": "^0.14.0",
|
|
24
|
+
"@e-mc/types": "^0.14.0",
|
|
25
25
|
"@azure/cosmos": "^4.9.3",
|
|
26
26
|
"@azure/identity": "*",
|
|
27
27
|
"@azure/storage-blob": "^12.31.0"
|
package/upload/index.js
CHANGED
|
@@ -1,19 +1,20 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
-
|
|
3
|
-
const
|
|
4
|
-
const
|
|
5
|
-
const
|
|
6
|
-
const
|
|
7
|
-
const
|
|
8
|
-
const
|
|
2
|
+
|
|
3
|
+
const path = require('node:path');
|
|
4
|
+
const fs = require('node:fs');
|
|
5
|
+
const stream = require('node:stream');
|
|
6
|
+
const Cloud = require('@e-mc/cloud');
|
|
7
|
+
const { alignSize, coerceObject, createAbortError, isObject } = require('@e-mc/types');
|
|
8
|
+
const { createErrorHandler, createKeyAndBody, generateFilename, intoArray } = require('@e-mc/cloud/util');
|
|
9
|
+
const { copyObject, createBucketV2, createStorageClient } = require('@pi-r/azure');
|
|
9
10
|
const BUCKET_SESSION = new Set();
|
|
10
11
|
const BUCKET_RESPONSE = {};
|
|
11
12
|
const getBucketKey = (credential, bucket, acl = '') => Cloud.asString(credential, true) + bucket + '_' + acl;
|
|
12
13
|
function upload(credential, service = "azure") {
|
|
13
|
-
const blobServiceClient =
|
|
14
|
+
const blobServiceClient = createStorageClient(credential);
|
|
14
15
|
return async (data, callback) => {
|
|
15
16
|
const { bucket, localUri } = data;
|
|
16
|
-
const { pathname, flags = 0, fileGroup, contentType, metadata, tags, endpoint, admin = {}, overwrite, options } = data.upload;
|
|
17
|
+
const { pathname, flags = 0, fileGroup, descendantsGroup, contentType, metadata, tags, endpoint, admin = {}, overwrite, options } = data.upload;
|
|
17
18
|
const containerClient = blobServiceClient.getContainerClient(bucket);
|
|
18
19
|
let filename = data.upload.filename || path.basename(localUri), bucketKey;
|
|
19
20
|
const complete = (err, url) => {
|
|
@@ -23,23 +24,23 @@ function upload(credential, service = "azure") {
|
|
|
23
24
|
}
|
|
24
25
|
callback(err, url);
|
|
25
26
|
};
|
|
26
|
-
const addLog =
|
|
27
|
+
const addLog = createErrorHandler(this, bucket, service);
|
|
27
28
|
const configBucket = admin.configBucket;
|
|
28
29
|
if (!BUCKET_SESSION.has(bucket)) {
|
|
29
30
|
const bucketAcl = admin.publicRead ? 'blob' : admin.acl;
|
|
30
|
-
const response = BUCKET_RESPONSE[bucketKey = getBucketKey(credential, bucket, bucketAcl)] ||=
|
|
31
|
+
const response = BUCKET_RESPONSE[bucketKey = getBucketKey(credential, bucket, bucketAcl)] ||= createBucketV2.call(this, credential, bucket, bucketAcl, configBucket?.create);
|
|
31
32
|
if (!await response) {
|
|
32
33
|
complete(null);
|
|
33
34
|
return;
|
|
34
35
|
}
|
|
35
36
|
BUCKET_SESSION.add(bucket);
|
|
36
37
|
}
|
|
37
|
-
const retentionPolicy =
|
|
38
|
+
const retentionPolicy = intoArray(configBucket?.retentionPolicy);
|
|
38
39
|
if (retentionPolicy) {
|
|
39
40
|
try {
|
|
40
41
|
if (this.hasCoerce(service, 'options')) {
|
|
41
42
|
for (const policy of retentionPolicy) {
|
|
42
|
-
|
|
43
|
+
coerceObject(policy);
|
|
43
44
|
}
|
|
44
45
|
}
|
|
45
46
|
}
|
|
@@ -55,7 +56,7 @@ function upload(credential, service = "azure") {
|
|
|
55
56
|
if (!overwrite) {
|
|
56
57
|
try {
|
|
57
58
|
const current = filename;
|
|
58
|
-
const next =
|
|
59
|
+
const next = generateFilename(filename);
|
|
59
60
|
let i = 0, exists = false;
|
|
60
61
|
do {
|
|
61
62
|
if (i > 0) {
|
|
@@ -81,7 +82,7 @@ function upload(credential, service = "azure") {
|
|
|
81
82
|
return;
|
|
82
83
|
}
|
|
83
84
|
}
|
|
84
|
-
const chunkSize = flags & 4 ?
|
|
85
|
+
const chunkSize = flags & 4 ? alignSize(data.upload.chunkSize, 1024) : 0;
|
|
85
86
|
const maxSingleShotSize = Math.max(chunkSize, 8388608);
|
|
86
87
|
const Key = [filename];
|
|
87
88
|
const Body = [data.buffer];
|
|
@@ -110,7 +111,7 @@ function upload(credential, service = "azure") {
|
|
|
110
111
|
Stream[0] = stream.Readable.from(Body[0], { highWaterMark: getChunkSize() });
|
|
111
112
|
}
|
|
112
113
|
if (fileGroup) {
|
|
113
|
-
const [key, body, type] =
|
|
114
|
+
const [key, body, type] = createKeyAndBody(filename, fileGroup, { errorCallback: addLog, descendantsGroup, flags, chunkSize: chunkSize > 0 ? maxSingleShotSize : 0 });
|
|
114
115
|
Key.push(...key);
|
|
115
116
|
ContentType.push(...type);
|
|
116
117
|
for (let i = 0; i < body.length; ++i) {
|
|
@@ -130,7 +131,7 @@ function upload(credential, service = "azure") {
|
|
|
130
131
|
const first = i === 0;
|
|
131
132
|
if (this.aborted) {
|
|
132
133
|
if (first) {
|
|
133
|
-
complete(
|
|
134
|
+
complete(createAbortError());
|
|
134
135
|
}
|
|
135
136
|
return;
|
|
136
137
|
}
|
|
@@ -138,10 +139,10 @@ function upload(credential, service = "azure") {
|
|
|
138
139
|
const params = { ...options, abortSignal: this.signal };
|
|
139
140
|
const headers = params.blobHTTPHeaders ||= {};
|
|
140
141
|
if (first) {
|
|
141
|
-
if (
|
|
142
|
+
if (isObject(metadata)) {
|
|
142
143
|
params.metadata = metadata;
|
|
143
144
|
}
|
|
144
|
-
if (
|
|
145
|
+
if (isObject(tags)) {
|
|
145
146
|
params.tags = tags;
|
|
146
147
|
}
|
|
147
148
|
headers.blobContentType ||= ContentType[i];
|
|
@@ -173,12 +174,12 @@ function upload(credential, service = "azure") {
|
|
|
173
174
|
const url = endpoint ? Cloud.joinPath(endpoint, blobName) : Cloud.isFile(requestUrl = decodeURIComponent(requestUrl), 'http/s') ? requestUrl : Cloud.joinPath(`https://${credential.accountName}.blob.core.windows.net`, bucket, blobName);
|
|
174
175
|
this.formatMessage(64, service, "Upload success", url, Cloud.optionsLogMessage('UPLOAD'));
|
|
175
176
|
if (first) {
|
|
176
|
-
const copyTo =
|
|
177
|
+
const copyTo = intoArray(data.upload.copyObject);
|
|
177
178
|
if (copyTo) {
|
|
178
179
|
const tasks = [];
|
|
179
180
|
for (const { bucket: bucketName, pathname: pathObject = pathname, filename: fileObject, options: copyOptions } of copyTo) {
|
|
180
181
|
const keyObject = fileObject ? Cloud.joinPath(pathObject, fileObject, true) : blobName;
|
|
181
|
-
tasks.push(
|
|
182
|
+
tasks.push(copyObject
|
|
182
183
|
.call(this, credential, bucket, blobName, bucketName, keyObject, copyOptions)
|
|
183
184
|
.catch(addLog));
|
|
184
185
|
}
|
|
@@ -198,4 +199,5 @@ function upload(credential, service = "azure") {
|
|
|
198
199
|
}
|
|
199
200
|
};
|
|
200
201
|
}
|
|
202
|
+
|
|
201
203
|
module.exports = upload;
|