@pi-r/azure 0.6.0 → 0.6.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -1,5 +1,7 @@
1
1
  ### @pi-r/azure
2
2
 
3
+ https://e-mc.readthedocs.io/en/latest/cloud/azure.html
4
+
3
5
  ### LICENSE
4
6
 
5
7
  MIT
package/client/index.js CHANGED
@@ -7,42 +7,51 @@ const cosmos = require("@azure/cosmos");
7
7
  const identity = require("@azure/identity");
8
8
  const types_1 = require("@e-mc/types");
9
9
  const util_1 = require("@e-mc/cloud/util");
10
- const Module = require("@e-mc/module");
11
10
  const Cloud = require("@e-mc/cloud");
12
11
  function validateStorage(credential) {
13
12
  const env = process.env;
14
- if (credential.accountName && credential.accountKey || credential.connectionString || credential.sharedAccessSignature || env.AZURE_TENANT_ID && env.AZURE_CLIENT_ID && env.AZURE_CLIENT_SECRET && (credential.accountName || env.AZURE_STORAGE_ACCOUNT)) {
13
+ if (credential.accountName && credential.accountKey || credential.connectionString || credential.sharedAccessSignature || env.AZURE_TENANT_ID && env.AZURE_CLIENT_ID && env.AZURE_CLIENT_SECRET) {
15
14
  return true;
16
15
  }
17
- return Module.enabled("process.env.apply" /* KEY_NAME.PROCESS_ENV_APPLY */) && !!((credential.connectionString = env.AZURE_STORAGE_CONNECTION_STRING) || (credential.sharedAccessSignature = env.AZURE_STORAGE_SAS_TOKEN) || (credential.accountName = env.AZURE_STORAGE_ACCOUNT) && (credential.accountKey = env.AZURE_STORAGE_KEY));
16
+ return Cloud.enabled("process.env.apply" /* KEY_NAME.PROCESS_ENV_APPLY */) && !!((credential.connectionString = env.AZURE_STORAGE_CONNECTION_STRING) || (credential.sharedAccessSignature = env.AZURE_STORAGE_SAS_TOKEN) || (credential.accountName = env.AZURE_STORAGE_ACCOUNT) && (credential.accountKey = env.AZURE_STORAGE_KEY));
18
17
  }
19
18
  exports.validateStorage = validateStorage;
20
19
  function validateDatabase(credential, data) {
21
- return !!(data.name && data.table && (credential.endpoint && credential.key || Module.enabled("process.env.apply" /* KEY_NAME.PROCESS_ENV_APPLY */) && (credential.endpoint = process.env.AZURE_COSMOS_ENDPOINT) && (credential.key = process.env.AZURE_COSMOS_KEY)));
20
+ return !!(data.name && data.table && (credential.endpoint && credential.key || credential.username && credential.password && (credential.tenantId && credential.clientId || (credential.tenantId = process.env.AZURE_TENANT_ID) && (credential.clientId = process.env.AZURE_CLIENT_ID)) || Cloud.enabled("process.env.apply" /* KEY_NAME.PROCESS_ENV_APPLY */) && (credential.endpoint = process.env.AZURE_COSMOS_ENDPOINT) && (credential.key = process.env.AZURE_COSMOS_KEY)));
22
21
  }
23
22
  exports.validateDatabase = validateDatabase;
24
23
  function createStorageClient(credential) {
25
- const { BlobServiceClient, StorageSharedKeyCredential } = storage;
26
- const { accountName, accountKey, connectionString, sharedAccessSignature } = credential;
24
+ let { accountName, accountKey, connectionString, sharedAccessSignature } = credential;
27
25
  if (connectionString) {
28
- credential.accountName || (credential.accountName = /AccountName=([^;]+);/.exec(connectionString)?.[1]);
29
- return BlobServiceClient.fromConnectionString(connectionString);
26
+ if (!accountName) {
27
+ credential.accountName = /AccountName=([^;]+);/.exec(connectionString)?.[1];
28
+ }
29
+ return storage.BlobServiceClient.fromConnectionString(connectionString);
30
30
  }
31
+ const url = `https://${accountName || process.env.AZURE_STORAGE_ACCOUNT}.blob.core.windows.net`;
31
32
  if (sharedAccessSignature) {
32
- credential.accountName || (credential.accountName = /^https:\/\/([a-z\d]+)\./.exec(sharedAccessSignature)?.[1]);
33
- return new BlobServiceClient(sharedAccessSignature);
34
- }
35
- let azureCredential;
36
- if (accountName && accountKey) {
37
- azureCredential = new StorageSharedKeyCredential(accountName, accountKey);
38
- }
39
- else {
40
- azureCredential = new identity.DefaultAzureCredential();
33
+ if (accountName) {
34
+ if (!Cloud.isURL(sharedAccessSignature)) {
35
+ sharedAccessSignature = url + (!sharedAccessSignature.startsWith('?') ? '?' : '') + sharedAccessSignature;
36
+ }
37
+ }
38
+ else {
39
+ credential.accountName || (credential.accountName = /^https:\/\/([a-z\d]+)\./.exec(sharedAccessSignature)?.[1]);
40
+ }
41
+ return new storage.BlobServiceClient(sharedAccessSignature);
41
42
  }
42
- return new BlobServiceClient(`https://${accountName || process.env.AZURE_STORAGE_ACCOUNT}.blob.core.windows.net`, azureCredential);
43
+ return new storage.BlobServiceClient(url, accountName && accountKey ? new storage.StorageSharedKeyCredential(accountName, accountKey) : new identity.DefaultAzureCredential());
43
44
  }
44
45
  exports.createStorageClient = createStorageClient;
45
46
  function createDatabaseClient(credential) {
47
+ if (credential.username && credential.password && credential.tenantId && credential.clientId) {
48
+ credential.aadCredentials = new identity.UsernamePasswordCredential(credential.username, credential.password, credential.tenantId, credential.clientId);
49
+ credential = { ...credential };
50
+ delete credential.username;
51
+ delete credential.password;
52
+ delete credential.tenantId;
53
+ delete credential.clientId;
54
+ }
46
55
  return new cosmos.CosmosClient(credential);
47
56
  }
48
57
  exports.createDatabaseClient = createDatabaseClient;
@@ -102,14 +111,20 @@ async function setBucketWebsite(credential, bucket, options, service = 'azure')
102
111
  staticWebsite.indexDocument = path.basename(indexPage);
103
112
  }
104
113
  if ((0, types_1.isString)(indexPath)) {
105
- staticWebsite.defaultIndexDocumentPath = Module.joinPath(bucket, indexPath);
114
+ staticWebsite.defaultIndexDocumentPath = Cloud.joinPath(bucket, indexPath);
106
115
  }
107
116
  if ((0, types_1.isString)(errorPath)) {
108
- staticWebsite.errorDocument404Path = Module.joinPath(bucket, errorPath);
117
+ staticWebsite.errorDocument404Path = Cloud.joinPath(bucket, errorPath);
109
118
  }
110
119
  return createStorageClient.call(this, credential).setProperties({ staticWebsite })
111
- .then(() => {
112
- this.formatMessage(64 /* LOG_TYPE.CLOUD */, service, ["Bucket configured" /* VAL_CLOUD.CONFIGURE_BUCKET */, bucket], options, { ...Cloud.LOG_CLOUD_COMMAND });
120
+ .then(response => {
121
+ const { requestId, errorCode } = response;
122
+ if (errorCode) {
123
+ this.formatMessage(64 /* LOG_TYPE.CLOUD */, service, ["Bucket configured" /* VAL_CLOUD.CONFIGURE_BUCKET */ + ' with errors', bucket], (0, types_1.errorMessage)("Error code" /* ERR_MESSAGE.ERROR_CODE */, errorCode), { ...Cloud.LOG_CLOUD_WARN });
124
+ }
125
+ else {
126
+ this.formatMessage(64 /* LOG_TYPE.CLOUD */, service, ["Bucket configured" /* VAL_CLOUD.CONFIGURE_BUCKET */, bucket], requestId, { ...Cloud.LOG_CLOUD_COMMAND });
127
+ }
113
128
  return true;
114
129
  })
115
130
  .catch(err => {
@@ -129,15 +144,15 @@ async function deleteObjectsV2(credential, bucket, recursive = true, service = '
129
144
  const tasks = [];
130
145
  let fileCount = 0;
131
146
  for await (const blob of containerClient.listBlobsFlat({ includeUncommitedBlobs: true })) {
132
- if (!recursive && blob.name.includes('/')) {
133
- continue;
147
+ if (recursive || !blob.name.includes('/')) {
148
+ tasks.push(containerClient.deleteBlob(blob.name, { versionId: blob.versionId }).catch(() => {
149
+ --fileCount;
150
+ }));
134
151
  }
135
- tasks.push(containerClient.deleteBlob(blob.name, { versionId: blob.versionId }).catch(() => { --fileCount; }));
136
152
  }
137
153
  fileCount = tasks.length;
138
154
  return this.allSettled(tasks, ["Unable to delete blob" /* ERR_AZURE.DELETE_BLOB */, bucket], 64 /* LOG_TYPE.CLOUD */).then(() => {
139
- const files = fileCount + ' files';
140
- this.formatMessage(64 /* LOG_TYPE.CLOUD */, service, [`Container emptied (${recursive ? 'recursive' : files})`, bucket], recursive ? files : '', { ...Cloud.LOG_CLOUD_COMMAND });
155
+ this.formatMessage(64 /* LOG_TYPE.CLOUD */, service, ['Container emptied' + (recursive ? ' (recursive)' : ''), bucket], fileCount + ' files', { ...Cloud.LOG_CLOUD_COMMAND });
141
156
  });
142
157
  }
143
158
  catch (err) {
@@ -157,7 +172,7 @@ async function executeBatchQuery(credential, batch, sessionKey) {
157
172
  const cacheValue = { value: this.valueOfKey(credential, 'cache'), sessionKey };
158
173
  let client;
159
174
  const createClient = (name, table) => {
160
- client || (client = createDatabaseClient.call(this, length === 1 ? credential : { ...credential }));
175
+ client || (client = createDatabaseClient.call(this, credential));
161
176
  return client.database(name).container(table);
162
177
  };
163
178
  const closeClient = () => client?.dispose();
@@ -168,17 +183,17 @@ async function executeBatchQuery(credential, batch, sessionKey) {
168
183
  closeClient();
169
184
  throw (0, util_1.formatError)(item, name ? "Missing database table" /* ERR_DB.TABLE */ : "Missing database name" /* ERR_DB.NAME */);
170
185
  }
171
- const renewCache = ignoreCache === 0;
172
186
  const getCache = (value) => {
173
187
  if (ignoreCache !== 1) {
174
- cacheValue.renewCache = renewCache;
188
+ cacheValue.renewCache = ignoreCache === 0;
175
189
  return this.getQueryResult(service, credential, value, cacheValue);
176
190
  }
177
191
  };
178
- let rows, queryString = caching && ignoreCache !== true || ignoreCache === false || ignoreCache === 1 || renewCache ? name + '_' + table + '_' : '';
192
+ cacheValue.exclusiveOf = Array.isArray(ignoreCache) ? ignoreCache : undefined;
193
+ let rows, queryString = caching && ignoreCache !== true ? name + '_' + table + '_' : '';
179
194
  if (storedProcedureId && params) {
180
195
  const { options } = item;
181
- if (queryString && (rows = getCache(queryString += Module.asString(partitionKey, true) + '_' + storedProcedureId + Module.asString(params, true) + Module.asString(options, true)))) {
196
+ if (queryString && (rows = getCache(queryString += Cloud.asString(partitionKey, true) + '_' + storedProcedureId + Cloud.asString(params, true) + Cloud.asString(options, true)))) {
182
197
  result[i] = rows;
183
198
  continue;
184
199
  }
@@ -190,7 +205,7 @@ async function executeBatchQuery(credential, batch, sessionKey) {
190
205
  else if (id) {
191
206
  const { options } = item;
192
207
  if (queryString) {
193
- queryString += Module.asString(partitionKey, true) + '_' + id + Module.asString(options, true);
208
+ queryString += Cloud.asString(partitionKey, true) + '_' + id + Cloud.asString(options, true);
194
209
  if (!update && (rows = getCache(queryString))) {
195
210
  result[i] = rows;
196
211
  continue;
@@ -202,20 +217,26 @@ async function executeBatchQuery(credential, batch, sessionKey) {
202
217
  rows = [resource];
203
218
  }
204
219
  }
205
- else if (query) {
220
+ else {
206
221
  let { options } = item;
222
+ if (partitionKey) {
223
+ (options || (options = {})).partitionKey = partitionKey;
224
+ }
207
225
  if (limit > 0) {
208
226
  (options || (options = {})).maxItemCount = limit;
209
227
  }
210
- if (queryString && (rows = getCache(queryString += Module.asString(query, true) + Module.asString(options, true)))) {
211
- result[i] = rows;
212
- continue;
228
+ if (query || (0, types_1.isPlainObject)(options)) {
229
+ if (queryString && (rows = getCache(queryString += (query ? Cloud.asString(query, true) : '') + Cloud.asString(options, true)))) {
230
+ result[i] = rows;
231
+ continue;
232
+ }
233
+ const items = createClient(name, table).items;
234
+ ({ resources: rows } = await (query ? items.query(query, options).fetchAll() : items.readAll(options).fetchAll()));
235
+ }
236
+ else {
237
+ closeClient();
238
+ throw (0, util_1.formatError)(item, "Missing database query" /* ERR_DB.QUERY */);
213
239
  }
214
- rows = (await createClient(name, table).items.query(query, options).fetchAll()).resources;
215
- }
216
- else {
217
- closeClient();
218
- throw (0, util_1.formatError)(item, "Missing database query" /* ERR_DB.QUERY */);
219
240
  }
220
241
  result[i] = this.setQueryResult(service, credential, queryString, rows, cacheValue);
221
242
  }
package/download/index.js CHANGED
@@ -20,7 +20,7 @@ function download(credential, service = 'azure') {
20
20
  callback(null, value);
21
21
  const deleteObject = target.deleteObject;
22
22
  if (deleteObject) {
23
- blobClient.delete((0, types_1.isPlainObject)(deleteObject) && (deleteObject.abortSignal = this.signal) ? deleteObject : undefined)
23
+ blobClient.delete((0, types_1.isPlainObject)(deleteObject) ? (deleteObject.abortSignal = this.signal, deleteObject) : { abortSignal: this.signal })
24
24
  .then(() => this.formatMessage(64 /* LOG_TYPE.CLOUD */, service, "Delete success" /* VAL_CLOUD.DELETE_FILE */, location, { ...Cloud.LOG_CLOUD_DELETE }))
25
25
  .catch((err) => {
26
26
  if (!(err instanceof Error && err.code === 'BlobNotFound')) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@pi-r/azure",
3
- "version": "0.6.0",
3
+ "version": "0.6.2",
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.8.0",
24
- "@e-mc/module": "^0.8.0",
25
- "@e-mc/types": "^0.8.0",
23
+ "@e-mc/cloud": "^0.8.2",
24
+ "@e-mc/module": "^0.8.2",
25
+ "@e-mc/types": "^0.8.2",
26
26
  "@azure/cosmos": "^4.0.0",
27
- "@azure/identity": "^4.0.0",
27
+ "@azure/identity": "^4.0.1",
28
28
  "@azure/storage-blob": "^12.17.0"
29
29
  }
30
30
  }
package/upload/index.js CHANGED
@@ -1,7 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  const path = require("path");
4
- const fs = require("fs");
5
4
  const util_1 = require("@e-mc/cloud/util");
6
5
  const types_1 = require("@e-mc/types");
7
6
  const Module = require("@e-mc/module");
@@ -84,15 +83,10 @@ function upload(credential, service = 'azure') {
84
83
  const Body = [data.buffer];
85
84
  const ContentType = [contentType];
86
85
  if (fileGroup) {
87
- for (const [content, ext, localFile] of fileGroup) {
88
- try {
89
- Body.push(typeof content === 'string' ? fs.readFileSync(content) : content);
90
- Key.push(ext === '.map' && localFile ? path.basename(localFile) : filename + ext);
91
- }
92
- catch (err) {
93
- addLog(err);
94
- }
95
- }
86
+ const [key, body, type] = (0, util_1.createKeyAndBody)(filename, fileGroup, addLog);
87
+ Key.push(...key);
88
+ Body.push(...body);
89
+ ContentType.push(...type);
96
90
  }
97
91
  for (let i = 0; i < Key.length; ++i) {
98
92
  const first = i === 0;