@pi-r/aws-v3 0.10.3 → 0.11.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/client/index.js CHANGED
@@ -12,6 +12,7 @@ exports.setBucketWebsite = setBucketWebsite;
12
12
  exports.deleteObjects = deleteObjects;
13
13
  exports.deleteObjectsV2 = deleteObjectsV2;
14
14
  exports.deleteObjectsV3 = deleteObjectsV3;
15
+ exports.copyObject = copyObject;
15
16
  exports.executeQuery = executeQuery;
16
17
  exports.executeBatchQuery = executeBatchQuery;
17
18
  const S3 = require("@aws-sdk/client-s3");
@@ -40,16 +41,16 @@ async function setCannedAcl(instance, client, Bucket, ACL, service = "aws-v3", r
40
41
  }
41
42
  return client.send(new instance.PutBucketPolicyCommand({ Bucket, Policy }))
42
43
  .then(() => {
43
- this.formatMessage(64, service, ['Grant ' + ACL, Bucket], '', { ...recursive ? Cloud.LOG_CLOUD_DELAYED : Cloud.LOG_CLOUD_COMMAND });
44
+ this.formatMessage(64, service, ['Grant ' + ACL, Bucket], '', Cloud.optionsLogMessage(recursive ? 'DELAYED' : 'COMMAND'));
44
45
  })
45
46
  .catch((err) => {
46
47
  if (!recursive && err instanceof Error) {
47
48
  if (err.name === 'OperationAborted') {
48
49
  setTimeout(async () => setCannedAcl.call(this, instance, client, Bucket, ACL, service, true), 60000);
49
- this.formatMessage(64, service, [`Grant ${ACL} (delayed)`, err.Endpoint || Bucket], err, { ...Cloud.LOG_CLOUD_DELAYED });
50
+ this.formatMessage(64, service, [`Grant ${ACL} (delayed)`, err.Endpoint || Bucket], err, Cloud.optionsLogMessage('DELAYED'));
50
51
  }
51
52
  else {
52
- this.formatMessage(64, service, ['Unable to grant ' + ACL, err.Endpoint || Bucket], err, { ...Cloud.LOG_CLOUD_WARN });
53
+ this.formatMessage(64, service, ['Unable to grant ' + ACL, err.Endpoint || Bucket], err, Cloud.optionsLogMessage('WARN'));
53
54
  }
54
55
  }
55
56
  });
@@ -177,7 +178,7 @@ async function createBucketV2(credential, Bucket, ACL, options, service = "aws-v
177
178
  }
178
179
  return client.send(new AWS.CreateBucketCommand(input))
179
180
  .then(async () => {
180
- this.formatMessage(64, service, ["Bucket created", Bucket], '', { ...Cloud.LOG_CLOUD_COMMAND });
181
+ this.formatMessage(64, service, ["Bucket created", Bucket], '', Cloud.optionsLogMessage('COMMAND'));
181
182
  if (ACL) {
182
183
  await setCannedAcl.call(this, AWS, client, Bucket, ACL, service);
183
184
  }
@@ -192,7 +193,7 @@ async function createBucketV2(credential, Bucket, ACL, options, service = "aws-v
192
193
  }
193
194
  return true;
194
195
  default:
195
- this.formatFail(64, service, ["Unable to create bucket", Bucket], err, { ...Cloud.LOG_CLOUD_FAIL });
196
+ this.formatFail(64, service, ["Unable to create bucket", Bucket], err, Cloud.optionsLogMessage('FAIL'));
196
197
  return false;
197
198
  }
198
199
  });
@@ -205,12 +206,12 @@ async function setBucketPolicy(credential, Bucket, options, service = "aws-v3",
205
206
  options.Bucket = Bucket;
206
207
  return (block ? client.send(new AWS.PutPublicAccessBlockCommand(options)) : policy ? client.send(new AWS.PutBucketPolicyCommand(options)) : client.send(new AWS.PutBucketAclCommand(options)))
207
208
  .then(() => {
208
- this.formatMessage(64, service, [block ? "Bucket configured" : policy ? "Bucket policy configured" : "Bucket ACL configured", Bucket], '', { ...Cloud.LOG_CLOUD_COMMAND });
209
+ this.formatMessage(64, service, [block ? "Bucket configured" : policy ? "Bucket policy configured" : "Bucket ACL configured", Bucket], '', Cloud.optionsLogMessage('COMMAND'));
209
210
  return true;
210
211
  })
211
212
  .catch((err) => {
212
213
  if (!isNoSuchBucket(err)) {
213
- this.formatFail(64, service, ["Unable to update bucket policy", Bucket], err, { ...Cloud.LOG_CLOUD_FAIL, fatal: false });
214
+ this.formatFail(64, service, ["Unable to update bucket policy", Bucket], err, Cloud.optionsLogMessage('FAIL', { fatal: false }));
214
215
  }
215
216
  return false;
216
217
  });
@@ -232,12 +233,12 @@ async function setBucketTagging(credential, Bucket, options, service = "aws-v3",
232
233
  }
233
234
  return client.send(command)
234
235
  .then(() => {
235
- this.formatMessage(64, service, [message, Bucket], null, { ...Cloud.LOG_CLOUD_COMMAND });
236
+ this.formatMessage(64, service, [message, Bucket], null, Cloud.optionsLogMessage('COMMAND'));
236
237
  return true;
237
238
  })
238
239
  .catch((err) => {
239
240
  if (!isNoSuchBucket(err)) {
240
- this.formatFail(64, service, ["Unable to update bucket tagging", Bucket], err, { ...Cloud.LOG_CLOUD_FAIL, fatal: false });
241
+ this.formatFail(64, service, ["Unable to update bucket tagging", Bucket], err, Cloud.optionsLogMessage('FAIL', { fatal: false }));
241
242
  }
242
243
  return false;
243
244
  });
@@ -254,12 +255,12 @@ async function setBucketWebsite(credential, Bucket, options, service = "aws-v3",
254
255
  }
255
256
  return client.send(new AWS.PutBucketWebsiteCommand({ Bucket, WebsiteConfiguration }))
256
257
  .then(() => {
257
- this.formatMessage(64, service, ["Bucket website configured", Bucket], WebsiteConfiguration, { ...Cloud.LOG_CLOUD_COMMAND });
258
+ this.formatMessage(64, service, ["Bucket website configured", Bucket], WebsiteConfiguration, Cloud.optionsLogMessage('COMMAND'));
258
259
  return true;
259
260
  })
260
261
  .catch((err) => {
261
262
  if (!isNoSuchBucket(err)) {
262
- this.formatFail(64, service, ["Unable to set bucket website", Bucket], err, { ...Cloud.LOG_CLOUD_FAIL, fatal: false });
263
+ this.formatFail(64, service, ["Unable to set bucket website", Bucket], err, Cloud.optionsLogMessage('FAIL', { fatal: false }));
263
264
  }
264
265
  return false;
265
266
  });
@@ -277,7 +278,7 @@ async function deleteObjectsV3(credential, Bucket, options = {}, service = "aws-
277
278
  recursive = options.recursive;
278
279
  delete options.recursive;
279
280
  }
280
- options.Bucket ||= Bucket;
281
+ options.Bucket = Bucket;
281
282
  const [client, AWS] = createStorageClient.call(this, credential, service, sdk);
282
283
  return client.send(new AWS.ListObjectsCommand(options))
283
284
  .then(async ({ Contents }) => {
@@ -290,22 +291,37 @@ async function deleteObjectsV3(credential, Bucket, options = {}, service = "aws-
290
291
  .then(data => {
291
292
  if ((0, types_1.isArray)(data.Deleted)) {
292
293
  const files = data.Deleted.length + ' files';
293
- this.formatMessage(64, service, ["Bucket emptied" + ` (${recursive ? 'recursive' : files})`, Bucket], recursive ? files : '', { ...Cloud.LOG_CLOUD_COMMAND });
294
+ this.formatMessage(64, service, ["Bucket emptied" + ` (${recursive ? 'recursive' : files})`, Bucket], recursive ? files : '', Cloud.optionsLogMessage('COMMAND'));
294
295
  }
295
296
  })
296
297
  .catch((err) => {
297
- this.formatFail(64, service, ["Unable to empty bucket", Bucket], err, { ...Cloud.LOG_CLOUD_FAIL, fatal: false });
298
+ this.formatFail(64, service, ["Unable to empty bucket", Bucket], err, Cloud.optionsLogMessage('FAIL', { fatal: false }));
298
299
  });
299
300
  }
300
301
  })
301
302
  .catch((err) => {
302
303
  if (!isNoSuchBucket(err)) {
303
- this.formatFail(64, service, ["Unable to list bucket", Bucket], err, { ...Cloud.LOG_CLOUD_FAIL, fatal: false });
304
+ this.formatFail(64, service, ["Unable to list bucket", Bucket], err, Cloud.optionsLogMessage('FAIL', { fatal: false }));
304
305
  }
305
306
  });
306
307
  }
308
+ async function copyObject(credential, BucketSource, KeySource, Bucket, Key, options = {}, service = "aws-v3", sdk = "@aws-sdk/client-s3") {
309
+ const [client, AWS] = createStorageClient.call(this, credential, service, sdk);
310
+ const index = Key.lastIndexOf('/');
311
+ if (index !== -1) {
312
+ await client.send(new AWS.PutObjectCommand({ Bucket, Key: Key.substring(0, index + 1), Body: Buffer.from(''), ContentLength: 0 })).catch(() => { });
313
+ }
314
+ const CopySource = BucketSource + '/' + KeySource;
315
+ return client.send(new AWS.CopyObjectCommand({ ...options, Bucket, Key, CopySource }))
316
+ .then(() => {
317
+ this.formatMessage(64, service, ["Copy success", Bucket], CopySource, Cloud.optionsLogMessage('COMMAND'));
318
+ })
319
+ .catch((err) => {
320
+ this.formatFail(64, service, ["Copy failed", Bucket + '/' + Key], err, Cloud.optionsLogMessage('FAIL', { fatal: false }));
321
+ });
322
+ }
307
323
  async function executeQuery(credential, data, sessionKey) {
308
- return (await executeBatchQuery.call(this, credential, [data], sessionKey))[0] || [];
324
+ return (await executeBatchQuery.call(this, credential, [data], sessionKey)).at(0) || [];
309
325
  }
310
326
  async function executeBatchQuery(credential, batch, sessionKey) {
311
327
  const length = batch.length;
@@ -400,7 +416,7 @@ async function executeBatchQuery(credential, batch, sessionKey) {
400
416
  const db = createClient()[0];
401
417
  if ((0, types_1.isString)(update) && /^(?:insert|delete|update)\s/i.test(update) && !update.includes('?')) {
402
418
  await db.send(new Lib.ExecuteStatementCommand({ Statement: update })).catch((err) => {
403
- this.formatFail(64, service, "Unable to execute query", err, { ...Cloud.LOG_CLOUD_FAIL, fatal: false });
419
+ this.formatFail(64, service, "Unable to execute query", err, Cloud.optionsLogMessage('FAIL', { fatal: false }));
404
420
  });
405
421
  }
406
422
  else {
package/download/index.js CHANGED
@@ -3,8 +3,8 @@ const Cloud = require("@e-mc/cloud");
3
3
  const types_1 = require("@e-mc/types");
4
4
  const util_1 = require("@e-mc/cloud/util");
5
5
  const client_1 = require("@pi-r/aws-v3");
6
- function download(config, service = "aws-v3", sdk = "@aws-sdk/client-s3") {
7
- const [client, AWS] = client_1.createStorageClient.call(this, config, service, sdk);
6
+ function download(credential, service = "aws-v3", sdk = "@aws-sdk/client-s3") {
7
+ const [client, AWS] = client_1.createStorageClient.call(this, credential, service, sdk);
8
8
  return (data, callback) => {
9
9
  const { bucket: Bucket, download: target } = data;
10
10
  const Key = target.keyname || target.filename;
@@ -12,21 +12,32 @@ function download(config, service = "aws-v3", sdk = "@aws-sdk/client-s3") {
12
12
  callback((0, types_1.errorValue)('Missing property', !Bucket ? 'Bucket' : 'Key'));
13
13
  return;
14
14
  }
15
- const location = Cloud.joinPath(Bucket, Key);
16
15
  client.send(new AWS.GetObjectCommand({ ...target.options, Bucket, Key, VersionId: target.versionId }), { abortSignal: this.signal })
17
16
  .then(result => {
18
17
  (0, util_1.readableAsBuffer)(result.Body)
19
- .then(buffer => {
18
+ .then(async (buffer) => {
20
19
  callback(null, buffer);
20
+ const copyTo = (0, util_1.intoArray)(target.copyObject);
21
+ if (copyTo) {
22
+ const tasks = [];
23
+ for (const { bucket, pathname, filename, options } of copyTo) {
24
+ const keyObject = filename ? Cloud.joinPath(pathname, filename, true) : Key;
25
+ tasks.push(client_1.copyObject
26
+ .call(this, credential, Bucket, Key, bucket, keyObject, options, service, sdk)
27
+ .catch((0, util_1.createErrorHandler)(this, service, Bucket)));
28
+ }
29
+ await Promise.all(tasks);
30
+ }
21
31
  const deleteObject = target.deleteObject;
22
32
  if (deleteObject) {
23
33
  const deleteOptions = (0, types_1.isPlainObject)(deleteObject) ? deleteObject : undefined;
34
+ const location = Cloud.joinPath(Bucket, Key);
24
35
  client.send(new AWS.DeleteObjectCommand({ ...deleteOptions, Bucket, Key, VersionId: target.versionId }))
25
36
  .then(() => {
26
- this.formatMessage(64, service, "Delete success", location, { ...Cloud.LOG_CLOUD_DELETE });
37
+ this.formatMessage(64, service, "Delete success", location, Cloud.optionsLogMessage('DELETE'));
27
38
  })
28
39
  .catch((err) => {
29
- this.formatFail(64, service, ["Delete failed", location], err, { ...Cloud.LOG_CLOUD_FAIL, fatal: !!target.active });
40
+ this.formatFail(64, service, ["Delete failed", location], err, Cloud.optionsLogMessage('FAIL', { fatal: !!target.active }));
30
41
  });
31
42
  }
32
43
  })
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@pi-r/aws-v3",
3
- "version": "0.10.3",
3
+ "version": "0.11.1",
4
4
  "description": "AWS cloud functions for E-mc.",
5
5
  "main": "client/index.js",
6
6
  "publishConfig": {
@@ -19,14 +19,14 @@
19
19
  "license": "MIT",
20
20
  "homepage": "https://github.com/anpham6/pi-r#readme",
21
21
  "dependencies": {
22
- "@e-mc/cloud": "^0.12.7",
23
- "@e-mc/module": "^0.12.7",
24
- "@e-mc/types": "^0.12.7",
25
- "@pi-r/aws-lib": "^0.10.3",
26
- "@aws-sdk/client-dynamodb": "^3.888.0",
27
- "@aws-sdk/client-s3": "^3.888.0",
22
+ "@e-mc/cloud": "^0.13.5",
23
+ "@e-mc/module": "^0.13.5",
24
+ "@e-mc/types": "^0.13.5",
25
+ "@pi-r/aws-lib": "^0.11.1",
26
+ "@aws-sdk/client-dynamodb": "^3.964.0",
27
+ "@aws-sdk/client-s3": "^3.964.0",
28
28
  "@aws-sdk/credential-providers": "*",
29
- "@aws-sdk/lib-dynamodb": "^3.888.0",
30
- "@aws-sdk/lib-storage": "^3.888.0"
29
+ "@aws-sdk/lib-dynamodb": "^3.964.0",
30
+ "@aws-sdk/lib-storage": "^3.964.0"
31
31
  }
32
32
  }
package/upload/index.js CHANGED
@@ -15,30 +15,22 @@ function upload(credential, service = "aws-v3", sdk = "@aws-sdk/client-s3") {
15
15
  const [client, AWS] = client_1.createStorageClient.call(this, credential, service, sdk);
16
16
  return async (data, callback) => {
17
17
  const { bucket: Bucket, localUri } = data;
18
- const { pathname = '', flags = 0, fileGroup, contentType, metadata, tags: Tags, endpoint, active, publicRead, acl, admin = {}, overwrite, options } = data.upload;
18
+ const { pathname, flags = 0, fileGroup, contentType, metadata, tags: Tags, endpoint, active, publicRead, acl, admin = {}, overwrite, options } = data.upload;
19
19
  let filename = data.upload.filename || path.basename(localUri), bucketKey;
20
- const cleanup = () => {
20
+ const complete = (err, url) => {
21
21
  BUCKET_SESSION.delete(service + Bucket);
22
22
  if (bucketKey) {
23
23
  delete BUCKET_RESPONSE[bucketKey];
24
24
  }
25
+ callback(err, url);
25
26
  };
26
- const errorResponse = (err) => {
27
- cleanup();
28
- callback(err);
29
- return false;
30
- };
31
- const addLog = (err) => {
32
- if (err instanceof Error) {
33
- this.addLog(this.statusType.WARN, err, service, Bucket);
34
- }
35
- };
27
+ const addLog = (0, util_1.createErrorHandler)(this, Bucket, service);
36
28
  const configBucket = admin.configBucket;
37
29
  if (!BUCKET_SESSION.has(service + Bucket)) {
38
30
  const bucketAcl = admin.publicRead ? "public-read" : admin.acl;
39
31
  const response = BUCKET_RESPONSE[bucketKey = (0, aws_lib_1.getBucketKey)(credential, Bucket, bucketAcl, service, sdk)] ||= client_1.createBucketV2.call(this, credential, Bucket, bucketAcl, configBucket?.create, service, sdk);
40
32
  if (!await response) {
41
- errorResponse(null);
33
+ complete(null);
42
34
  return;
43
35
  }
44
36
  BUCKET_SESSION.add(service + Bucket);
@@ -52,7 +44,7 @@ function upload(credential, service = "aws-v3", sdk = "@aws-sdk/client-s3") {
52
44
  if ((0, types_1.isPlainObject)(DefaultRetention)) {
53
45
  client.send(new AWS.PutObjectLockConfigurationCommand({ Bucket, ObjectLockConfiguration: { ObjectLockEnabled: 'Enabled', Rule: { DefaultRetention } }, ExpectedBucketOwner, RequestPayer: options?.RequestPayer }))
54
46
  .then(() => {
55
- this.formatMessage(64, service, ["Bucket configured" + ' (Retention Policy)', Bucket], (0, aws_lib_1.formatDefaultRetention)(DefaultRetention), { ...Cloud.LOG_CLOUD_COMMAND });
47
+ this.formatMessage(64, service, ["Bucket configured" + ' (Retention Policy)', Bucket], (0, aws_lib_1.formatDefaultRetention)(DefaultRetention), Cloud.optionsLogMessage('COMMAND'));
56
48
  })
57
49
  .catch(addLog);
58
50
  }
@@ -102,7 +94,7 @@ function upload(credential, service = "aws-v3", sdk = "@aws-sdk/client-s3") {
102
94
  break;
103
95
  }
104
96
  }
105
- exists = await client.send(new AWS.HeadObjectCommand({ Bucket, Key: pathname ? Cloud.joinPath(pathname, filename) : filename }))
97
+ exists = await client.send(new AWS.HeadObjectCommand({ Bucket, Key: Cloud.joinPath(pathname, filename, true) }))
106
98
  .then(() => true)
107
99
  .catch((err) => {
108
100
  if (err instanceof Error && err.name !== 'NotFound') {
@@ -113,11 +105,11 @@ function upload(credential, service = "aws-v3", sdk = "@aws-sdk/client-s3") {
113
105
  });
114
106
  } while (exists && ++i);
115
107
  if (i > 0) {
116
- this.formatMessage(64, service, ["File renamed", current], filename, { ...Cloud.LOG_CLOUD_WARN });
108
+ this.formatMessage(64, service, ["File renamed", current], filename, Cloud.optionsLogMessage('WARN'));
117
109
  }
118
110
  }
119
111
  if (pathname) {
120
- await client.send(new AWS.PutObjectCommand({ Bucket, Key: pathname, Body: Buffer.from(''), ContentLength: 0 })).catch(() => { });
112
+ await client.send(new AWS.PutObjectCommand({ Bucket, Key: pathname.endsWith('/') ? pathname : pathname + '/', Body: Buffer.from(''), ContentLength: 0 })).catch(() => { });
121
113
  }
122
114
  const Key = [filename];
123
115
  const Body = [];
@@ -139,7 +131,7 @@ function upload(credential, service = "aws-v3", sdk = "@aws-sdk/client-s3") {
139
131
  }
140
132
  }
141
133
  catch (err) {
142
- errorResponse(err);
134
+ complete(err);
143
135
  return;
144
136
  }
145
137
  }
@@ -156,12 +148,12 @@ function upload(credential, service = "aws-v3", sdk = "@aws-sdk/client-s3") {
156
148
  const first = i === 0;
157
149
  if (this.aborted) {
158
150
  if (first) {
159
- errorResponse((0, types_1.createAbortError)());
151
+ complete((0, types_1.createAbortError)());
160
152
  }
161
153
  return;
162
154
  }
163
- const objectKey = Cloud.joinPath(pathname, Key[i]);
164
- const params = { ...options, Bucket, Key: pathname + Key[i], Body: Stream[i] || stream.Readable.from(Body[i]) };
155
+ const objectKey = Cloud.joinPath(pathname, Key[i], true);
156
+ const params = { ...options, Bucket, Key: objectKey, Body: Stream[i] || stream.Readable.from(Body[i]) };
165
157
  const readable = publicRead || active && publicRead !== false && !acl;
166
158
  let tags, length = -1;
167
159
  if (first) {
@@ -199,25 +191,35 @@ function upload(credential, service = "aws-v3", sdk = "@aws-sdk/client-s3") {
199
191
  new lib_storage_1.Upload({ client, params, tags, partSize: getPartSize(), queueSize: partSize > 0 ? data.upload.chunkLimit : undefined }).done()
200
192
  .then(() => {
201
193
  const url = endpoint ? Cloud.joinPath(endpoint, objectKey) : Cloud.joinPath(`https://${Bucket}.s3.${!credential.region || credential.region === "us-east-1" ? "us-east-1" + '.' : ''}amazonaws.com`, objectKey);
202
- this.formatMessage(64, service, "Upload success", url, { ...Cloud.LOG_CLOUD_UPLOAD });
194
+ this.formatMessage(64, service, "Upload success", url, Cloud.optionsLogMessage('UPLOAD'));
203
195
  if (first) {
204
196
  if (length === 0) {
205
197
  client.send(new AWS.DeleteObjectTaggingCommand({ Bucket, Key: params.Key, ExpectedBucketOwner: params.ExpectedBucketOwner }), (error) => {
206
198
  if (!error) {
207
- this.formatMessage(64, service, ["Tags deleted", Bucket], params.Key, { ...Cloud.LOG_CLOUD_COMMAND });
199
+ this.formatMessage(64, service, ["Tags deleted", Bucket], params.Key, Cloud.optionsLogMessage('COMMAND'));
208
200
  }
209
201
  else {
210
202
  addLog(error);
211
203
  }
212
204
  });
213
205
  }
214
- cleanup();
215
- callback(null, url);
206
+ const copyTo = (0, util_1.intoArray)(data.upload.copyObject);
207
+ if (copyTo) {
208
+ const tasks = [];
209
+ for (const { bucket: bucketName, pathname: pathObject = pathname, filename: fileObject, options: copyOptions } of copyTo) {
210
+ const keyObject = fileObject ? Cloud.joinPath(pathObject, fileObject, true) : objectKey;
211
+ tasks.push(client_1.copyObject
212
+ .call(this, credential, Bucket, objectKey, bucketName, keyObject, copyOptions, service, sdk)
213
+ .catch(addLog));
214
+ }
215
+ void Promise.all(tasks);
216
+ }
217
+ complete(null, url);
216
218
  }
217
219
  })
218
220
  .catch((err) => {
219
221
  if (first) {
220
- errorResponse(err);
222
+ complete(err);
221
223
  }
222
224
  else {
223
225
  addLog(err);