@pi-r/azure 0.6.7 → 0.7.1
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 +3 -6
- package/client/index.js +22 -19
- package/download/index.js +26 -10
- package/package.json +6 -6
- package/types/index.d.ts +24 -0
- package/upload/index.js +79 -17
package/README.md
CHANGED
|
@@ -1,10 +1,7 @@
|
|
|
1
|
-
|
|
1
|
+
### @pi-r/azure
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
https://e-mc.readthedocs.io/en/latest/cloud/azure.html
|
|
4
4
|
|
|
5
|
-
|
|
6
|
-
- [squared](https://squared.readthedocs.io)
|
|
7
|
-
|
|
8
|
-
## LICENSE
|
|
5
|
+
### LICENSE
|
|
9
6
|
|
|
10
7
|
MIT
|
package/client/index.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
-
exports.executeBatchQuery = exports.executeQuery = exports.deleteObjectsV2 = exports.deleteObjects = exports.setBucketWebsite = exports.createBucketV2 = exports.createBucket = exports.createDatabaseClient = exports.createStorageClient = exports.validateDatabase = exports.validateStorage = void 0;
|
|
2
|
+
exports.CLOUD_DOWNLOAD_CHUNK = exports.CLOUD_UPLOAD_CHUNK = exports.CLOUD_UPLOAD_STREAM = exports.executeBatchQuery = exports.executeQuery = exports.deleteObjectsV2 = exports.deleteObjects = exports.setBucketWebsite = exports.createBucketV2 = exports.createBucket = exports.createDatabaseClient = exports.createStorageClient = exports.validateDatabase = exports.validateStorage = void 0;
|
|
3
3
|
const path = require("path");
|
|
4
4
|
const storage = require("@azure/storage-blob");
|
|
5
5
|
const cosmos = require("@azure/cosmos");
|
|
@@ -20,11 +20,10 @@ function validateDatabase(credential, data) {
|
|
|
20
20
|
}
|
|
21
21
|
exports.validateDatabase = validateDatabase;
|
|
22
22
|
function createStorageClient(credential) {
|
|
23
|
-
var _a, _b;
|
|
24
23
|
let { accountName, accountKey, connectionString, sharedAccessSignature } = credential;
|
|
25
24
|
if (connectionString) {
|
|
26
25
|
if (!accountName) {
|
|
27
|
-
credential.accountName =
|
|
26
|
+
credential.accountName = /AccountName=([^;]+);/.exec(connectionString)?.[1];
|
|
28
27
|
}
|
|
29
28
|
return storage.BlobServiceClient.fromConnectionString(connectionString);
|
|
30
29
|
}
|
|
@@ -36,7 +35,7 @@ function createStorageClient(credential) {
|
|
|
36
35
|
}
|
|
37
36
|
}
|
|
38
37
|
else {
|
|
39
|
-
credential.accountName
|
|
38
|
+
credential.accountName ||= /^https:\/\/([a-z\d]+)\./.exec(sharedAccessSignature)?.[1];
|
|
40
39
|
}
|
|
41
40
|
return new storage.BlobServiceClient(sharedAccessSignature);
|
|
42
41
|
}
|
|
@@ -69,7 +68,7 @@ async function createBucketV2(credential, bucket, access, options, service = 'az
|
|
|
69
68
|
break;
|
|
70
69
|
}
|
|
71
70
|
const containerClient = createStorageClient.call(this, credential).getContainerClient(bucket);
|
|
72
|
-
const setAccessPolicy = async () => containerClient.setAccessPolicy(access).catch(err => this.formatMessage(64, service, ["Unable to configure container", bucket], err, { ...Cloud.LOG_CLOUD_WARN }));
|
|
71
|
+
const setAccessPolicy = async () => containerClient.setAccessPolicy(access).catch((err) => this.formatMessage(64, service, ["Unable to configure container", bucket], err, { ...Cloud.LOG_CLOUD_WARN }));
|
|
73
72
|
if (await containerClient.exists().catch(() => false)) {
|
|
74
73
|
if (access) {
|
|
75
74
|
await setAccessPolicy();
|
|
@@ -120,15 +119,15 @@ async function setBucketWebsite(credential, bucket, options, service = 'azure')
|
|
|
120
119
|
.then(response => {
|
|
121
120
|
const { requestId, errorCode } = response;
|
|
122
121
|
if (errorCode) {
|
|
123
|
-
this.formatMessage(64, service, ["Bucket configured" + ' with errors', bucket], (0, types_1.errorMessage)("Error code", errorCode), { ...Cloud.LOG_CLOUD_WARN });
|
|
122
|
+
this.formatMessage(64, service, ["Bucket website configured" + ' with errors', bucket], (0, types_1.errorMessage)("Error code", errorCode), { ...Cloud.LOG_CLOUD_WARN });
|
|
124
123
|
}
|
|
125
124
|
else {
|
|
126
|
-
this.formatMessage(64, service, ["Bucket configured", bucket], requestId, { ...Cloud.LOG_CLOUD_COMMAND });
|
|
125
|
+
this.formatMessage(64, service, ["Bucket website configured", bucket], requestId, { ...Cloud.LOG_CLOUD_COMMAND });
|
|
127
126
|
}
|
|
128
127
|
return true;
|
|
129
128
|
})
|
|
130
|
-
.catch(err => {
|
|
131
|
-
this.formatFail(64, service, ["Unable to
|
|
129
|
+
.catch((err) => {
|
|
130
|
+
this.formatFail(64, service, ["Unable to set bucket website", bucket], err, { ...Cloud.LOG_CLOUD_FAIL, fatal: false });
|
|
132
131
|
return false;
|
|
133
132
|
});
|
|
134
133
|
}
|
|
@@ -144,11 +143,12 @@ async function deleteObjectsV2(credential, bucket, recursive = true, service = '
|
|
|
144
143
|
const tasks = [];
|
|
145
144
|
let fileCount = 0;
|
|
146
145
|
for await (const blob of containerClient.listBlobsFlat({ includeUncommitedBlobs: true })) {
|
|
147
|
-
if (recursive
|
|
148
|
-
|
|
149
|
-
--fileCount;
|
|
150
|
-
}));
|
|
146
|
+
if (!recursive && blob.name.includes('/')) {
|
|
147
|
+
continue;
|
|
151
148
|
}
|
|
149
|
+
tasks.push(containerClient.deleteBlob(blob.name, { versionId: blob.versionId }).catch(() => {
|
|
150
|
+
--fileCount;
|
|
151
|
+
}));
|
|
152
152
|
}
|
|
153
153
|
fileCount = tasks.length;
|
|
154
154
|
return this.allSettled(tasks, ["Unable to delete blob", bucket], 64).then(() => {
|
|
@@ -172,10 +172,10 @@ async function executeBatchQuery(credential, batch, sessionKey) {
|
|
|
172
172
|
const cacheValue = { value: this.valueOfKey(credential, 'cache'), sessionKey };
|
|
173
173
|
let client;
|
|
174
174
|
const createClient = (name, table) => {
|
|
175
|
-
client
|
|
175
|
+
client ||= createDatabaseClient.call(this, credential);
|
|
176
176
|
return client.database(name).container(table);
|
|
177
177
|
};
|
|
178
|
-
const closeClient = () => client
|
|
178
|
+
const closeClient = () => client?.dispose();
|
|
179
179
|
for (let i = 0; i < length; ++i) {
|
|
180
180
|
const item = batch[i];
|
|
181
181
|
const { service, name, table, id, query, storedProcedureId, partitionKey = null, params, limit = 0, update, ignoreCache } = item;
|
|
@@ -193,7 +193,7 @@ async function executeBatchQuery(credential, batch, sessionKey) {
|
|
|
193
193
|
let rows, queryString = caching && ignoreCache !== true ? name + '_' + table + '_' : '';
|
|
194
194
|
if (storedProcedureId && params) {
|
|
195
195
|
const { options } = item;
|
|
196
|
-
if (queryString && (rows = getCache(queryString += Cloud.asString(partitionKey, true) + '_' + storedProcedureId + Cloud.asString(params, true) + Cloud.asString(options, true)))) {
|
|
196
|
+
if (queryString && (rows = getCache(queryString += (partitionKey ? Cloud.asString(partitionKey, true) : '') + '_' + storedProcedureId + '_' + Cloud.asString(params, true) + Cloud.asString(options, true)))) {
|
|
197
197
|
result[i] = rows;
|
|
198
198
|
continue;
|
|
199
199
|
}
|
|
@@ -205,7 +205,7 @@ async function executeBatchQuery(credential, batch, sessionKey) {
|
|
|
205
205
|
else if (id) {
|
|
206
206
|
const { options } = item;
|
|
207
207
|
if (queryString) {
|
|
208
|
-
queryString += Cloud.asString(partitionKey, true) + '_' + id + Cloud.asString(options, true);
|
|
208
|
+
queryString += (partitionKey ? Cloud.asString(partitionKey, true) : '') + '_' + id + '_' + Cloud.asString(options, true);
|
|
209
209
|
if (!update && (rows = getCache(queryString))) {
|
|
210
210
|
result[i] = rows;
|
|
211
211
|
continue;
|
|
@@ -220,10 +220,10 @@ async function executeBatchQuery(credential, batch, sessionKey) {
|
|
|
220
220
|
else {
|
|
221
221
|
let { options } = item;
|
|
222
222
|
if (partitionKey) {
|
|
223
|
-
(options
|
|
223
|
+
(options ||= {}).partitionKey = partitionKey;
|
|
224
224
|
}
|
|
225
225
|
if (limit > 0) {
|
|
226
|
-
(options
|
|
226
|
+
(options ||= {}).maxItemCount = limit;
|
|
227
227
|
}
|
|
228
228
|
if (query || (0, types_1.isPlainObject)(options)) {
|
|
229
229
|
if (queryString && (rows = getCache(queryString += (query ? Cloud.asString(query, true) : '') + Cloud.asString(options, true)))) {
|
|
@@ -244,3 +244,6 @@ async function executeBatchQuery(credential, batch, sessionKey) {
|
|
|
244
244
|
return result;
|
|
245
245
|
}
|
|
246
246
|
exports.executeBatchQuery = executeBatchQuery;
|
|
247
|
+
exports.CLOUD_UPLOAD_STREAM = true;
|
|
248
|
+
exports.CLOUD_UPLOAD_CHUNK = true;
|
|
249
|
+
exports.CLOUD_DOWNLOAD_CHUNK = true;
|
package/download/index.js
CHANGED
|
@@ -1,26 +1,42 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
const types_1 = require("@e-mc/types");
|
|
3
|
-
const
|
|
3
|
+
const path = require("path");
|
|
4
4
|
const Cloud = require("@e-mc/cloud");
|
|
5
5
|
const client_1 = require("@pi-r/azure");
|
|
6
6
|
module.exports = function download(credential, service = 'azure') {
|
|
7
7
|
const blobServiceClient = client_1.createStorageClient.call(this, credential);
|
|
8
8
|
return (data, callback) => {
|
|
9
9
|
const { bucket: Bucket, download: target } = data;
|
|
10
|
-
const Key = target.filename;
|
|
10
|
+
const Key = target.keyname || target.filename;
|
|
11
11
|
if (!Bucket || !Key) {
|
|
12
12
|
callback((0, types_1.errorValue)('Missing property', !Bucket ? 'Container' : 'Name'));
|
|
13
13
|
return;
|
|
14
14
|
}
|
|
15
|
-
|
|
16
|
-
const
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
15
|
+
let tempDir;
|
|
16
|
+
const downloadResponse = (err, url) => {
|
|
17
|
+
callback(err, url);
|
|
18
|
+
if (tempDir) {
|
|
19
|
+
queueMicrotask(() => Cloud.removeDir(tempDir));
|
|
20
|
+
}
|
|
21
|
+
};
|
|
22
|
+
const { flags = 0 } = target;
|
|
23
|
+
const containerClient = blobServiceClient.getContainerClient(Bucket);
|
|
24
|
+
const blobClient = containerClient.getBlockBlobClient(Key);
|
|
25
|
+
const blockSize = (flags & 4) && (0, types_1.alignSize)(target.chunkSize, 1024) || 0;
|
|
26
|
+
let diskClient, destination;
|
|
27
|
+
if (blockSize >= 2097152000 && (tempDir = this.getTempDir({ uuidDir: true }))) {
|
|
28
|
+
diskClient = blobClient.downloadToFile(destination = path.join(tempDir, path.basename(target.filename || Key)), 0, undefined, { snapshot: target.versionId, abortSignal: this.signal });
|
|
29
|
+
}
|
|
30
|
+
(diskClient || blobClient.downloadToBuffer(0, 0, { ...target.options, blockSize, concurrency: blockSize > 0 ? target.chunkLimit : undefined, abortSignal: this.signal }))
|
|
31
|
+
.then((value) => {
|
|
32
|
+
downloadResponse(null, diskClient && destination || value);
|
|
20
33
|
const deleteObject = target.deleteObject;
|
|
21
34
|
if (deleteObject) {
|
|
22
|
-
|
|
23
|
-
|
|
35
|
+
const location = Cloud.joinPath(Bucket, Key);
|
|
36
|
+
containerClient.delete((0, types_1.isPlainObject)(deleteObject) ? (deleteObject.abortSignal = this.signal, deleteObject) : { abortSignal: this.signal })
|
|
37
|
+
.then(() => {
|
|
38
|
+
this.formatMessage(64, service, "Delete success", location, { ...Cloud.LOG_CLOUD_DELETE });
|
|
39
|
+
})
|
|
24
40
|
.catch((err) => {
|
|
25
41
|
if (!(err instanceof Error && err.code === 'BlobNotFound')) {
|
|
26
42
|
this.formatFail(64, service, ["Delete failed", location], err, { ...Cloud.LOG_CLOUD_FAIL, fatal: !!target.active });
|
|
@@ -28,6 +44,6 @@ module.exports = function download(credential, service = 'azure') {
|
|
|
28
44
|
});
|
|
29
45
|
}
|
|
30
46
|
})
|
|
31
|
-
.catch(err =>
|
|
47
|
+
.catch((err) => downloadResponse(err));
|
|
32
48
|
};
|
|
33
49
|
};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@pi-r/azure",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.7.1",
|
|
4
4
|
"description": "Azure cloud functions for E-mc.",
|
|
5
5
|
"main": "client/index.js",
|
|
6
6
|
"publishConfig": {
|
|
@@ -20,11 +20,11 @@
|
|
|
20
20
|
"license": "MIT",
|
|
21
21
|
"homepage": "https://github.com/anpham6/pi-r#readme",
|
|
22
22
|
"dependencies": {
|
|
23
|
-
"@e-mc/cloud": "^0.
|
|
24
|
-
"@e-mc/module": "^0.
|
|
25
|
-
"@e-mc/types": "^0.
|
|
23
|
+
"@e-mc/cloud": "^0.9.2",
|
|
24
|
+
"@e-mc/module": "^0.9.2",
|
|
25
|
+
"@e-mc/types": "^0.9.2",
|
|
26
26
|
"@azure/cosmos": "^4.0.0",
|
|
27
|
-
"@azure/identity": "^4.0
|
|
28
|
-
"@azure/storage-blob": "^12.
|
|
27
|
+
"@azure/identity": "^4.2.0",
|
|
28
|
+
"@azure/storage-blob": "^12.18.0"
|
|
29
29
|
}
|
|
30
30
|
}
|
package/types/index.d.ts
ADDED
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import type { CloudDatabase, CloudStorage } from '@e-mc/types/lib/cloud';
|
|
2
|
+
|
|
3
|
+
import type { CosmosClientOptions, FeedOptions, PartitionKey, PatchRequestBody, RequestOptions, SqlQuerySpec } from '@azure/cosmos';
|
|
4
|
+
|
|
5
|
+
export type AzureStorage = CloudStorage<AzureStorageCredential, "azure" | "az">;
|
|
6
|
+
|
|
7
|
+
export interface AzureStorageCredential {
|
|
8
|
+
accountName?: string;
|
|
9
|
+
accountKey?: string;
|
|
10
|
+
connectionString?: string;
|
|
11
|
+
sharedAccessSignature?: string;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
export interface AzureDatabaseQuery<T = FeedOptions | RequestOptions> extends CloudDatabase<string | SqlQuerySpec, T, PatchRequestBody, unknown[], AzureDatabaseCredential> {
|
|
15
|
+
source: "cloud";
|
|
16
|
+
service: "azure" | "az";
|
|
17
|
+
partitionKey?: PartitionKey;
|
|
18
|
+
storedProcedureId?: string;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
export interface AzureDatabaseCredential extends AuthValue, CosmosClientOptions {
|
|
22
|
+
tenantId?: string;
|
|
23
|
+
clientId?: string;
|
|
24
|
+
}
|
package/upload/index.js
CHANGED
|
@@ -1,19 +1,19 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
const path = require("path");
|
|
3
|
+
const fs = require("fs");
|
|
4
|
+
const stream = require("stream");
|
|
3
5
|
const util_1 = require("@e-mc/cloud/util");
|
|
4
6
|
const types_1 = require("@e-mc/types");
|
|
5
|
-
const Module = require("@e-mc/module");
|
|
6
7
|
const Cloud = require("@e-mc/cloud");
|
|
7
8
|
const client_1 = require("@pi-r/azure");
|
|
8
9
|
const BUCKET_SESSION = new Set();
|
|
9
10
|
const BUCKET_RESPONSE = {};
|
|
10
|
-
const getBucketKey = (credential, bucket, acl = '') =>
|
|
11
|
+
const getBucketKey = (credential, bucket, acl = '') => Cloud.asString(credential, true) + bucket + '_' + acl;
|
|
11
12
|
module.exports = function upload(credential, service = 'azure') {
|
|
12
13
|
const blobServiceClient = client_1.createStorageClient.call(this, credential);
|
|
13
14
|
return async (data, callback) => {
|
|
14
|
-
var _a, _b;
|
|
15
15
|
const { bucket, localUri } = data;
|
|
16
|
-
const { pathname = '', fileGroup, contentType, metadata, tags, endpoint, admin = {}, overwrite, options } = data.upload;
|
|
16
|
+
const { pathname = '', flags = 0, fileGroup, contentType, metadata, tags, endpoint, admin = {}, overwrite, options } = data.upload;
|
|
17
17
|
const containerClient = blobServiceClient.getContainerClient(bucket);
|
|
18
18
|
let filename = data.upload.filename || path.basename(localUri), bucketKey;
|
|
19
19
|
const cleanup = () => {
|
|
@@ -30,24 +30,31 @@ module.exports = function upload(credential, service = 'azure') {
|
|
|
30
30
|
const configBucket = admin.configBucket;
|
|
31
31
|
if (!BUCKET_SESSION.has(bucket)) {
|
|
32
32
|
const bucketAcl = admin.publicRead ? 'blob' : admin.acl;
|
|
33
|
-
const response = BUCKET_RESPONSE[
|
|
33
|
+
const response = BUCKET_RESPONSE[bucketKey = getBucketKey(credential, bucket, bucketAcl)] ||= client_1.createBucketV2.call(this, credential, bucket, bucketAcl, configBucket?.create);
|
|
34
34
|
if (!await response) {
|
|
35
35
|
errorResponse(null);
|
|
36
36
|
return;
|
|
37
37
|
}
|
|
38
38
|
BUCKET_SESSION.add(bucket);
|
|
39
39
|
}
|
|
40
|
-
let retentionPolicy = configBucket
|
|
40
|
+
let retentionPolicy = configBucket?.retentionPolicy;
|
|
41
41
|
if (retentionPolicy) {
|
|
42
42
|
if (!Array.isArray(retentionPolicy)) {
|
|
43
43
|
retentionPolicy = [retentionPolicy];
|
|
44
44
|
}
|
|
45
|
+
try {
|
|
46
|
+
if (this.hasCoerce(service, 'options')) {
|
|
47
|
+
retentionPolicy.forEach(policy => (0, types_1.coerceObject)(policy));
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
catch {
|
|
51
|
+
}
|
|
45
52
|
containerClient.setAccessPolicy('container', retentionPolicy)
|
|
46
53
|
.then(() => {
|
|
47
54
|
const { expiresOn, startsOn, permissions } = retentionPolicy[0].accessPolicy;
|
|
48
55
|
this.formatMessage(64, service, ["Bucket configured" + ' (retention policy)', bucket], expiresOn ? expiresOn.toLocaleString() + ' (expires)' : startsOn ? startsOn.toLocaleString() + ' (starts)' : permissions, { ...Cloud.LOG_CLOUD_COMMAND });
|
|
49
56
|
})
|
|
50
|
-
.catch(err => addLog(err));
|
|
57
|
+
.catch((err) => addLog(err));
|
|
51
58
|
}
|
|
52
59
|
if (!overwrite) {
|
|
53
60
|
try {
|
|
@@ -61,7 +68,7 @@ module.exports = function upload(credential, service = 'azure') {
|
|
|
61
68
|
break;
|
|
62
69
|
}
|
|
63
70
|
}
|
|
64
|
-
const name = pathname ?
|
|
71
|
+
const name = pathname ? Cloud.joinPath(pathname, filename) : filename;
|
|
65
72
|
for await (const blob of containerClient.listBlobsFlat({ includeUncommitedBlobs: true })) {
|
|
66
73
|
if (blob.name === name) {
|
|
67
74
|
exists = true;
|
|
@@ -78,14 +85,50 @@ module.exports = function upload(credential, service = 'azure') {
|
|
|
78
85
|
return;
|
|
79
86
|
}
|
|
80
87
|
}
|
|
88
|
+
const chunkSize = flags & 4 ? (0, types_1.alignSize)(data.upload.chunkSize, 1024) : 0;
|
|
89
|
+
const maxSingleShotSize = Math.max(chunkSize, 8388608);
|
|
81
90
|
const Key = [filename];
|
|
82
91
|
const Body = [data.buffer];
|
|
92
|
+
const Path = [];
|
|
93
|
+
const Stream = [];
|
|
83
94
|
const ContentType = [contentType];
|
|
95
|
+
const getChunkSize = () => chunkSize > 0 ? maxSingleShotSize : undefined;
|
|
96
|
+
if (Body[0].length === 0) {
|
|
97
|
+
try {
|
|
98
|
+
if (chunkSize > 0 && fs.statSync(localUri).size > maxSingleShotSize) {
|
|
99
|
+
Path[0] = localUri;
|
|
100
|
+
}
|
|
101
|
+
else if (flags & 2) {
|
|
102
|
+
Stream[0] = fs.createReadStream(localUri, { highWaterMark: getChunkSize(), signal: this.signal });
|
|
103
|
+
}
|
|
104
|
+
else {
|
|
105
|
+
Body[0] = fs.readFileSync(localUri);
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
catch (err) {
|
|
109
|
+
errorResponse(err);
|
|
110
|
+
return;
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
else if ((flags & 2) || chunkSize > 0) {
|
|
114
|
+
Stream[0] = stream.Readable.from(Body[0], { highWaterMark: getChunkSize() });
|
|
115
|
+
}
|
|
84
116
|
if (fileGroup) {
|
|
85
|
-
const [key, body, type] = (0, util_1.createKeyAndBody)(filename, fileGroup, addLog);
|
|
117
|
+
const [key, body, type] = (0, util_1.createKeyAndBody)(filename, fileGroup, chunkSize > 0 ? maxSingleShotSize : 0, addLog, flags);
|
|
86
118
|
Key.push(...key);
|
|
87
|
-
Body.push(...body);
|
|
88
119
|
ContentType.push(...type);
|
|
120
|
+
for (let i = 0; i < body.length; ++i) {
|
|
121
|
+
const item = body[i];
|
|
122
|
+
if (typeof item === 'string') {
|
|
123
|
+
Path[i + 1] = item;
|
|
124
|
+
}
|
|
125
|
+
else if (Buffer.isBuffer(item)) {
|
|
126
|
+
Body[i + 1] = item;
|
|
127
|
+
}
|
|
128
|
+
else {
|
|
129
|
+
Stream[i + 1] = item;
|
|
130
|
+
}
|
|
131
|
+
}
|
|
89
132
|
}
|
|
90
133
|
for (let i = 0; i < Key.length; ++i) {
|
|
91
134
|
const first = i === 0;
|
|
@@ -95,28 +138,47 @@ module.exports = function upload(credential, service = 'azure') {
|
|
|
95
138
|
}
|
|
96
139
|
return;
|
|
97
140
|
}
|
|
98
|
-
const blobName =
|
|
141
|
+
const blobName = Cloud.joinPath(pathname, Key[i]);
|
|
99
142
|
const params = { ...options, abortSignal: this.signal };
|
|
143
|
+
const headers = params.blobHTTPHeaders ||= {};
|
|
100
144
|
if (first) {
|
|
101
|
-
if ((0, types_1.
|
|
145
|
+
if ((0, types_1.isObject)(metadata)) {
|
|
102
146
|
params.metadata = metadata;
|
|
103
147
|
}
|
|
104
|
-
if ((0, types_1.
|
|
148
|
+
if ((0, types_1.isObject)(tags)) {
|
|
105
149
|
params.tags = tags;
|
|
106
150
|
}
|
|
151
|
+
headers.blobContentType ||= ContentType[i];
|
|
152
|
+
}
|
|
153
|
+
else {
|
|
154
|
+
headers.blobContentType = ContentType[i];
|
|
155
|
+
}
|
|
156
|
+
const blobClient = containerClient.getBlockBlobClient(blobName);
|
|
157
|
+
let uploadClient;
|
|
158
|
+
if (Stream[i]) {
|
|
159
|
+
uploadClient = blobClient.uploadStream(Stream[i], getChunkSize(), chunkSize > 0 ? data.upload.chunkLimit : undefined, params);
|
|
160
|
+
}
|
|
161
|
+
else if (Path[i]) {
|
|
162
|
+
params.maxSingleShotSize = maxSingleShotSize;
|
|
163
|
+
params.concurrency = data.upload.chunkLimit;
|
|
164
|
+
uploadClient = blobClient.uploadFile(Path[i], params);
|
|
165
|
+
}
|
|
166
|
+
else if (chunkSize > 0 && Body[i].byteLength > maxSingleShotSize) {
|
|
167
|
+
params.maxSingleShotSize = maxSingleShotSize;
|
|
168
|
+
params.concurrency = data.upload.chunkLimit;
|
|
169
|
+
uploadClient = blobClient.uploadData(Body[i], params);
|
|
107
170
|
}
|
|
108
|
-
(
|
|
109
|
-
containerClient.getBlockBlobClient(blobName).upload(Body[i], Body[i].byteLength, params)
|
|
171
|
+
(uploadClient || blobClient.upload(Body[i], Body[i].byteLength, params))
|
|
110
172
|
.then(result => {
|
|
111
173
|
let requestUrl = result._response.request.url;
|
|
112
|
-
const url = endpoint ?
|
|
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);
|
|
113
175
|
this.formatMessage(64, service, "Upload success", url, { ...Cloud.LOG_CLOUD_UPLOAD });
|
|
114
176
|
if (first) {
|
|
115
177
|
cleanup();
|
|
116
178
|
callback(null, url);
|
|
117
179
|
}
|
|
118
180
|
})
|
|
119
|
-
.catch(err => {
|
|
181
|
+
.catch((err) => {
|
|
120
182
|
if (first) {
|
|
121
183
|
errorResponse(err);
|
|
122
184
|
}
|