@pi-r/aws-v3 0.6.6 → 0.7.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 CHANGED
@@ -1,10 +1,7 @@
1
- # @pi-r/aws-v3
1
+ ### @pi-r/aws-v3
2
2
 
3
- ## Documentation
3
+ https://e-mc.readthedocs.io/en/latest/cloud/aws-v3.html
4
4
 
5
- - [E-mc](https://e-mc.readthedocs.io/en/latest/cloud/aws-v3.html)
6
- - [squared](https://squared.readthedocs.io)
7
-
8
- ## LICENSE
5
+ ### LICENSE
9
6
 
10
7
  MIT
package/client/index.js CHANGED
@@ -1,27 +1,26 @@
1
1
  "use strict";
2
- exports.executeBatchQuery = exports.executeQuery = exports.deleteObjectsV2 = exports.deleteObjects = exports.setBucketWebsite = exports.setBucketPolicy = exports.createBucketV2 = exports.createBucket = exports.validateDatabase = exports.validateStorage = exports.createDatabaseClient = exports.createStorageClient = void 0;
2
+ exports.CLOUD_UPLOAD_CHUNK = exports.CLOUD_UPLOAD_STREAM = exports.executeBatchQuery = exports.executeQuery = exports.deleteObjectsV2 = exports.deleteObjects = exports.setBucketWebsite = exports.setBucketTagging = exports.setBucketPolicy = exports.createBucketV2 = exports.createBucket = exports.validateDatabase = exports.validateStorage = exports.createDatabaseClient = exports.createStorageClient = void 0;
3
3
  const Lib = require("@aws-sdk/lib-dynamodb");
4
4
  const Client = require("@aws-sdk/client-dynamodb");
5
5
  const Providers = require("@aws-sdk/credential-providers");
6
- const aws_1 = require("@pi-r/aws");
6
+ const Cloud = require("@e-mc/cloud");
7
7
  const util_1 = require("@e-mc/cloud/util");
8
8
  const types_1 = require("@e-mc/types");
9
- const Module = require("@e-mc/module");
10
- const Cloud = require("@e-mc/cloud");
11
- async function setCannedAcl(S3, client, Bucket, ACL, service = 'aws-v3', recursive) {
9
+ const aws_lib_1 = require("@pi-r/aws-lib");
10
+ async function setCannedAcl(S3, client, Bucket, ACL, service = "aws-v3", recursive) {
12
11
  let Policy;
13
12
  switch (ACL) {
14
13
  case 1:
15
- Policy = (0, aws_1.getBucketPublicReadPolicy)(Bucket);
14
+ Policy = (0, aws_lib_1.getBucketPublicReadPolicy)(Bucket);
16
15
  break;
17
- case 'public-read-write':
18
- Policy = (0, aws_1.getPublicReadPolicy)(Bucket, false, true);
16
+ case "public-read-write":
17
+ Policy = (0, aws_lib_1.getPublicReadPolicy)(Bucket, false, true);
19
18
  break;
20
- case 'authenticated-read':
21
- Policy = (0, aws_1.getPublicReadPolicy)(Bucket, true);
19
+ case "authenticated-read":
20
+ Policy = (0, aws_lib_1.getPublicReadPolicy)(Bucket, true);
22
21
  break;
23
22
  default:
24
- Policy = (0, aws_1.getPrivatePolicy)(Bucket);
23
+ Policy = (0, aws_lib_1.getPrivatePolicy)(Bucket);
25
24
  break;
26
25
  }
27
26
  return client.send(new S3.PutBucketPolicyCommand({ Bucket, Policy }))
@@ -40,23 +39,6 @@ async function setCannedAcl(S3, client, Bucket, ACL, service = 'aws-v3', recursi
40
39
  }
41
40
  });
42
41
  }
43
- function sanitizeCredentials(credential) {
44
- const result = credential.credentials || (credential.credentials = {});
45
- for (const attr in credential) {
46
- switch (attr) {
47
- case 'accessKeyId':
48
- case 'secretAccessKey':
49
- case 'sessionToken':
50
- case 'expiration':
51
- if (typeof result !== 'function') {
52
- result[attr] = credential[attr];
53
- }
54
- delete credential[attr];
55
- break;
56
- }
57
- }
58
- return result;
59
- }
60
42
  function fromProvider(credential) {
61
43
  const from = credential.provider;
62
44
  let credentials = credential.credentials;
@@ -94,10 +76,10 @@ function fromProvider(credential) {
94
76
  else if ((0, types_1.isPlainObject)(from.sso)) {
95
77
  credentials = Providers.fromSSO(from.sso);
96
78
  }
97
- else if (from.env && (0, aws_1.isEnvDefined)()) {
79
+ else if (from.env && (0, aws_lib_1.isEnvDefined)()) {
98
80
  credentials = Providers.fromEnv();
99
81
  }
100
- else if (from.ini && (0, aws_1.isSharedCredentialsDefined)()) {
82
+ else if (from.ini && (0, aws_lib_1.isSharedCredentialsDefined)()) {
101
83
  credentials = Providers.fromIni();
102
84
  }
103
85
  if ((0, types_1.isPlainObject)(credentials)) {
@@ -123,9 +105,8 @@ function fromProvider(credential) {
123
105
  return credential;
124
106
  }
125
107
  const isNoSuchBucket = (err) => err instanceof Error && err.name === 'NoSuchBucket';
126
- function createStorageClient(credential, service = 'aws-v3', sdk = '@aws-sdk/client-s3') {
108
+ function createStorageClient(credential, service = "aws-v3", sdk = "@aws-sdk/client-s3") {
127
109
  try {
128
- sanitizeCredentials(credential);
129
110
  const AWS = require(sdk);
130
111
  return [new AWS.S3Client(fromProvider(credential)), AWS];
131
112
  }
@@ -140,25 +121,24 @@ function createDatabaseClient(credential) {
140
121
  }
141
122
  exports.createDatabaseClient = createDatabaseClient;
142
123
  function validateStorage(credential) {
143
- const credentials = sanitizeCredentials(credential);
144
- const profile = credential.profile;
145
- if (profile || !credentials && !credential.provider && (0, aws_1.isSharedCredentialsDefined)()) {
146
- credential.credentials = Providers.fromIni({ profile });
124
+ const credentials = credential.credentials;
125
+ if (!credentials && !credential.provider && (0, aws_lib_1.isSharedCredentialsDefined)()) {
126
+ credential.credentials = Providers.fromIni();
147
127
  return true;
148
128
  }
149
- return !!credentials && (typeof credentials === 'function' || (0, aws_1.isAccessDefined)(credentials)) || (0, types_1.isPlainObject)(credential.provider) || (0, aws_1.isEnvDefined)();
129
+ return !!credentials && ((0, aws_lib_1.isAccessDefined)(credentials) || typeof credentials === 'function') || (0, types_1.isPlainObject)(credential.provider) || (0, aws_lib_1.isEnvDefined)();
150
130
  }
151
131
  exports.validateStorage = validateStorage;
152
132
  function validateDatabase(credential, data) {
153
- return (0, aws_1.isDatabaseDefined)(credential, data) && validateStorage(credential);
133
+ return (0, aws_lib_1.isDatabaseDefined)(credential, data) && validateStorage(credential);
154
134
  }
155
135
  exports.validateDatabase = validateDatabase;
156
- async function createBucket(credential, Bucket, publicRead, service = 'aws-v3', sdk = '@aws-sdk/client-s3') {
157
- return createBucketV2.call(this, credential, Bucket, publicRead ? 'public-read' : undefined, undefined, service, sdk);
136
+ async function createBucket(credential, Bucket, publicRead, service = "aws-v3", sdk = "@aws-sdk/client-s3") {
137
+ return createBucketV2.call(this, credential, Bucket, publicRead ? "public-read" : undefined, undefined, service, sdk);
158
138
  }
159
139
  exports.createBucket = createBucket;
160
- async function createBucketV2(credential, Bucket, ACL, options, service = 'aws-v3', sdk = '@aws-sdk/client-s3') {
161
- ACL = ACL === 1 ? 1 : (0, aws_1.checkBucketCannedACL)(ACL);
140
+ async function createBucketV2(credential, Bucket, ACL, options, service = "aws-v3", sdk = "@aws-sdk/client-s3") {
141
+ ACL = ACL === 1 ? 1 : (0, aws_lib_1.checkBucketCannedACL)(ACL);
162
142
  const [client, AWS] = createStorageClient.call(this, credential, service, sdk);
163
143
  return client.send(new AWS.HeadBucketCommand({ Bucket }))
164
144
  .then(async () => {
@@ -170,8 +150,8 @@ async function createBucketV2(credential, Bucket, ACL, options, service = 'aws-v
170
150
  .catch(async () => {
171
151
  const input = { ...options, Bucket };
172
152
  const region = credential.region;
173
- if ((0, types_1.isString)(region) && region !== 'us-east-1') {
174
- input.CreateBucketConfiguration || (input.CreateBucketConfiguration = { LocationConstraint: region });
153
+ if ((0, types_1.isString)(region) && region !== "us-east-1") {
154
+ input.CreateBucketConfiguration ||= { LocationConstraint: region };
175
155
  }
176
156
  return client.send(new AWS.CreateBucketCommand(input))
177
157
  .then(async () => {
@@ -197,7 +177,7 @@ async function createBucketV2(credential, Bucket, ACL, options, service = 'aws-v
197
177
  });
198
178
  }
199
179
  exports.createBucketV2 = createBucketV2;
200
- async function setBucketPolicy(credential, Bucket, options, service = 'aws', sdk = 'aws-sdk/clients/s3') {
180
+ async function setBucketPolicy(credential, Bucket, options, service = "aws-v3", sdk = "@aws-sdk/client-s3") {
201
181
  const [client, AWS] = createStorageClient.call(this, credential, service, sdk);
202
182
  const block = 'PublicAccessBlockConfiguration' in options;
203
183
  const policy = !block && 'Policy' in options && !('ACL' in options);
@@ -207,7 +187,7 @@ async function setBucketPolicy(credential, Bucket, options, service = 'aws', sdk
207
187
  this.formatMessage(64, service, [block ? "Bucket configured" : policy ? "Bucket policy configured" : "Bucket ACL configured", Bucket], '', { ...Cloud.LOG_CLOUD_COMMAND });
208
188
  return true;
209
189
  })
210
- .catch(err => {
190
+ .catch((err) => {
211
191
  if (!isNoSuchBucket(err)) {
212
192
  this.formatFail(64, service, ["Unable to update bucket policy", Bucket], err, { ...Cloud.LOG_CLOUD_FAIL, fatal: false });
213
193
  }
@@ -215,7 +195,30 @@ async function setBucketPolicy(credential, Bucket, options, service = 'aws', sdk
215
195
  });
216
196
  }
217
197
  exports.setBucketPolicy = setBucketPolicy;
218
- async function setBucketWebsite(credential, Bucket, options, service = 'aws', sdk = 'aws-sdk/clients/s3') {
198
+ async function setBucketTagging(credential, Bucket, options, service = "aws-v3", sdk = "@aws-sdk/client-s3") {
199
+ if (!(0, types_1.isPlainObject)(options) || !Array.isArray(options.Tagging?.TagSet)) {
200
+ return false;
201
+ }
202
+ const [client, AWS] = createStorageClient.call(this, credential, service, sdk);
203
+ const deleting = options.Tagging.TagSet.length === 0;
204
+ const command = () => {
205
+ this.formatMessage(64, service, [deleting ? "Tags deleted" : "Tags created", Bucket], null, { ...Cloud.LOG_CLOUD_COMMAND });
206
+ return true;
207
+ };
208
+ const error = (err) => {
209
+ if (!isNoSuchBucket(err)) {
210
+ this.formatFail(64, service, ["Unable to update bucket tagging", Bucket], err, { ...Cloud.LOG_CLOUD_FAIL, fatal: false });
211
+ }
212
+ return false;
213
+ };
214
+ if (deleting) {
215
+ return client.send(new AWS.DeleteBucketTaggingCommand({ Bucket, ExpectedBucketOwner: options.ExpectedBucketOwner })).then(command).catch((err) => error(err));
216
+ }
217
+ options.Bucket = Bucket;
218
+ return client.send(new AWS.PutBucketTaggingCommand(options)).then(command).catch((err) => error(err));
219
+ }
220
+ exports.setBucketTagging = setBucketTagging;
221
+ async function setBucketWebsite(credential, Bucket, options, service = "aws-v3", sdk = "@aws-sdk/client-s3") {
219
222
  const [client, AWS] = createStorageClient.call(this, credential, service, sdk);
220
223
  const WebsiteConfiguration = {};
221
224
  const { indexPage: Suffix, errorPage: Key } = options;
@@ -227,22 +230,22 @@ async function setBucketWebsite(credential, Bucket, options, service = 'aws', sd
227
230
  }
228
231
  return client.send(new AWS.PutBucketWebsiteCommand({ Bucket, WebsiteConfiguration }))
229
232
  .then(() => {
230
- this.formatMessage(64, service, ["Bucket configured", Bucket], WebsiteConfiguration, { ...Cloud.LOG_CLOUD_COMMAND });
233
+ this.formatMessage(64, service, ["Bucket website configured", Bucket], WebsiteConfiguration, { ...Cloud.LOG_CLOUD_COMMAND });
231
234
  return true;
232
235
  })
233
- .catch(err => {
236
+ .catch((err) => {
234
237
  if (!isNoSuchBucket(err)) {
235
- this.formatFail(64, service, ["Unable to configure bucket", Bucket], err, { ...Cloud.LOG_CLOUD_FAIL, fatal: false });
238
+ this.formatFail(64, service, ["Unable to set bucket website", Bucket], err, { ...Cloud.LOG_CLOUD_FAIL, fatal: false });
236
239
  }
237
240
  return false;
238
241
  });
239
242
  }
240
243
  exports.setBucketWebsite = setBucketWebsite;
241
- async function deleteObjects(credential, Bucket, service, sdk) {
244
+ async function deleteObjects(credential, Bucket, service = "aws-v3", sdk = "@aws-sdk/client-s3") {
242
245
  return deleteObjectsV2.call(this, credential, Bucket, true, service, sdk);
243
246
  }
244
247
  exports.deleteObjects = deleteObjects;
245
- async function deleteObjectsV2(credential, Bucket, recursive = true, service = 'aws-v3', sdk = '@aws-sdk/client-s3') {
248
+ async function deleteObjectsV2(credential, Bucket, recursive = true, service = "aws-v3", sdk = "@aws-sdk/client-s3") {
246
249
  const [client, AWS] = createStorageClient.call(this, credential, service, sdk);
247
250
  return client.send(new AWS.ListObjectsCommand({ Bucket }))
248
251
  .then(async ({ Contents }) => {
@@ -259,12 +262,12 @@ async function deleteObjectsV2(credential, Bucket, recursive = true, service = '
259
262
  this.formatMessage(64, service, ["Bucket emptied" + ` (${recursive ? 'recursive' : files})`, Bucket], recursive ? files : '', { ...Cloud.LOG_CLOUD_COMMAND });
260
263
  }
261
264
  })
262
- .catch(err => {
265
+ .catch((err) => {
263
266
  this.formatFail(64, service, ["Unable to empty bucket", Bucket], err, { ...Cloud.LOG_CLOUD_FAIL, fatal: false });
264
267
  });
265
268
  }
266
269
  })
267
- .catch(err => {
270
+ .catch((err) => {
268
271
  if (!isNoSuchBucket(err)) {
269
272
  this.formatFail(64, service, ["Unable to list bucket", Bucket], err, { ...Cloud.LOG_CLOUD_FAIL, fatal: false });
270
273
  }
@@ -276,18 +279,17 @@ async function executeQuery(credential, data, sessionKey) {
276
279
  }
277
280
  exports.executeQuery = executeQuery;
278
281
  async function executeBatchQuery(credential, batch, sessionKey) {
279
- var _a;
280
282
  const length = batch.length;
281
283
  const result = new Array(length);
282
284
  const caching = length > 0 && this.hasCache(batch[0].service, sessionKey);
283
285
  const cacheValue = { value: this.valueOfKey(credential, 'cache'), sessionKey };
284
286
  let client;
285
- const createClient = () => client || (client = createDatabaseClient.call(this, credential));
287
+ const createClient = () => client ||= createDatabaseClient.call(this, credential);
286
288
  const closeClient = () => client?.[0].destroy();
287
- (0, aws_1.setDatabaseEndpoint)(credential);
289
+ (0, aws_lib_1.setDatabaseEndpoint)(credential);
288
290
  for (let i = 0; i < length; ++i) {
289
291
  const item = batch[i];
290
- let { service, table: TableName, id, query, partitionKey, key = partitionKey, limit = 0, update, ignoreCache } = item;
292
+ let { service, table: TableName, id, query, key, limit = 0, update, ignoreCache } = item;
291
293
  const useCache = caching && ignoreCache !== true;
292
294
  const getCache = (value) => {
293
295
  if (ignoreCache !== 1) {
@@ -303,7 +305,7 @@ async function executeBatchQuery(credential, batch, sessionKey) {
303
305
  throw (0, util_1.formatError)(item, "Missing database table");
304
306
  }
305
307
  if (useCache) {
306
- queryString = TableName + '_' + Module.asString(key, true) + (id !== undefined ? '_' + Module.asString(id, true) : '');
308
+ queryString = TableName + '_' + Cloud.asString(key, true) + (id !== undefined ? '_' + Cloud.asString(id, true) : '');
307
309
  if (!update && (rows = getCache(queryString))) {
308
310
  result[i] = rows;
309
311
  continue;
@@ -331,7 +333,7 @@ async function executeBatchQuery(credential, batch, sessionKey) {
331
333
  if (limit > 0) {
332
334
  query.Limit = limit;
333
335
  }
334
- if (useCache && (rows = getCache(queryString = Module.asString(query, true)))) {
336
+ if (useCache && (rows = getCache(queryString = Cloud.asString(query, true)))) {
335
337
  result[i] = rows;
336
338
  continue;
337
339
  }
@@ -346,14 +348,14 @@ async function executeBatchQuery(credential, batch, sessionKey) {
346
348
  if (!(0, types_1.isPlainObject)(params.RequestItems)) {
347
349
  params.RequestItems = {};
348
350
  }
349
- TableName || (TableName = Object.keys(params.RequestItems)[0]);
351
+ TableName ||= Object.keys(params.RequestItems)[0];
350
352
  if (!TableName) {
351
353
  throw (0, util_1.formatError)(item, "Missing database table");
352
354
  }
353
- const Item = (_a = params.RequestItems)[TableName] || (_a[TableName] = {});
355
+ const Item = params.RequestItems[TableName] ||= {};
354
356
  Item.Keys = query;
355
357
  params = { RequestItems: { [TableName]: Item } };
356
- if (useCache && (rows = getCache(queryString = Module.asString(params, true)))) {
358
+ if (useCache && (rows = getCache(queryString = Cloud.asString(params, true)))) {
357
359
  result[i] = rows;
358
360
  continue;
359
361
  }
@@ -371,7 +373,7 @@ async function executeBatchQuery(credential, batch, sessionKey) {
371
373
  else {
372
374
  params = { TableName };
373
375
  }
374
- if (useCache && (rows = getCache(queryString = Module.asString(params, true)))) {
376
+ if (useCache && (rows = getCache(queryString = Cloud.asString(params, true)))) {
375
377
  result[i] = rows;
376
378
  continue;
377
379
  }
@@ -391,3 +393,5 @@ async function executeBatchQuery(credential, batch, sessionKey) {
391
393
  return result;
392
394
  }
393
395
  exports.executeBatchQuery = executeBatchQuery;
396
+ exports.CLOUD_UPLOAD_STREAM = true;
397
+ exports.CLOUD_UPLOAD_CHUNK = true;
package/download/index.js CHANGED
@@ -1,33 +1,31 @@
1
1
  "use strict";
2
2
  const util_1 = require("@e-mc/cloud/util");
3
3
  const types_1 = require("@e-mc/types");
4
- const Module = require("@e-mc/module");
5
4
  const Cloud = require("@e-mc/cloud");
6
5
  const client_1 = require("@pi-r/aws-v3");
7
- module.exports = function download(config, service = 'aws-v3', sdk = '@aws-sdk/client-s3') {
6
+ module.exports = function download(config, service = "aws-v3", sdk = "@aws-sdk/client-s3") {
8
7
  const [client, AWS] = client_1.createStorageClient.call(this, config, service, sdk);
9
8
  return (data, callback) => {
10
9
  const { bucket: Bucket, download: target } = data;
11
- const Key = target.filename;
10
+ const Key = target.keyname || target.filename;
12
11
  if (!Bucket || !Key) {
13
12
  callback((0, types_1.errorValue)('Missing property', !Bucket ? 'Bucket' : 'Key'));
14
13
  return;
15
14
  }
16
- const location = Module.joinPath(Bucket, Key);
17
- let input = { Bucket, Key, VersionId: target.versionId };
18
- client.send(new AWS.GetObjectCommand(input), { abortSignal: this.signal })
15
+ const location = Cloud.joinPath(Bucket, Key);
16
+ client.send(new AWS.GetObjectCommand({ ...target.options, Bucket, Key, VersionId: target.versionId }), { abortSignal: this.signal })
19
17
  .then(result => {
20
- (0, util_1.readableAsBuffer)(result.Body).then(buffer => callback(null, buffer)).catch(err => callback(err));
21
- const deleteObject = target.deleteObject;
18
+ (0, util_1.readableAsBuffer)(result.Body).then(buffer => callback(null, buffer)).catch((err) => callback(err));
19
+ let deleteObject = target.deleteObject;
22
20
  if (deleteObject) {
23
- if ((0, types_1.isPlainObject)(deleteObject)) {
24
- input = Object.assign(deleteObject, input);
21
+ if (!(0, types_1.isPlainObject)(deleteObject)) {
22
+ deleteObject = undefined;
25
23
  }
26
- client.send(new AWS.DeleteObjectCommand(input))
24
+ client.send(new AWS.DeleteObjectCommand({ ...deleteObject, Bucket, Key, VersionId: target.versionId }))
27
25
  .then(() => this.formatMessage(64, service, "Delete success", location, { ...Cloud.LOG_CLOUD_DELETE }))
28
- .catch(err => this.formatFail(64, service, ["Delete failed", location], err, { ...Cloud.LOG_CLOUD_FAIL, fatal: !!target.active }));
26
+ .catch((err) => this.formatFail(64, service, ["Delete failed", location], err, { ...Cloud.LOG_CLOUD_FAIL, fatal: !!target.active }));
29
27
  }
30
28
  })
31
- .catch(err => callback(err));
29
+ .catch((err) => callback(err));
32
30
  };
33
31
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@pi-r/aws-v3",
3
- "version": "0.6.6",
3
+ "version": "0.7.0",
4
4
  "description": "AWS V3 cloud functions for E-mc.",
5
5
  "main": "client/index.js",
6
6
  "publishConfig": {
@@ -20,13 +20,14 @@
20
20
  "license": "MIT",
21
21
  "homepage": "https://github.com/anpham6/pi-r#readme",
22
22
  "dependencies": {
23
- "@e-mc/cloud": "^0.8.7",
24
- "@e-mc/module": "^0.8.7",
25
- "@e-mc/types": "^0.8.7",
26
- "@pi-r/aws": "^0.6.6",
27
- "@aws-sdk/client-dynamodb": "^3.540.0",
28
- "@aws-sdk/client-s3": "^3.540.0",
29
- "@aws-sdk/credential-providers": "^3.540.0",
30
- "@aws-sdk/lib-dynamodb": "^3.540.0"
23
+ "@e-mc/cloud": "^0.9.0",
24
+ "@e-mc/module": "^0.9.0",
25
+ "@e-mc/types": "^0.9.0",
26
+ "@pi-r/aws-lib": "^0.7.0",
27
+ "@aws-sdk/client-dynamodb": "^3.563.0",
28
+ "@aws-sdk/client-s3": "^3.563.0",
29
+ "@aws-sdk/credential-providers": "^3.563.0",
30
+ "@aws-sdk/lib-dynamodb": "^3.563.0",
31
+ "@aws-sdk/lib-storage": "^3.563.0"
31
32
  }
32
33
  }
@@ -0,0 +1,41 @@
1
+ import type { CloudDatabase, CloudStorage } from '@e-mc/types/lib/cloud';
2
+
3
+ import type { AwsAuthInputConfig } from '@aws-sdk/middleware-signing';
4
+ import type { DynamoDBClientConfig, QueryCommandInput, ScanCommandInput } from '@aws-sdk/client-dynamodb';
5
+ import type { BatchGetCommandInput, TranslateConfig, UpdateCommandInput } from '@aws-sdk/lib-dynamodb';
6
+ import type { NativeAttributeValue } from "@aws-sdk/util-dynamodb";
7
+ import type { S3ClientConfig } from '@aws-sdk/client-s3';
8
+
9
+ export interface AWSBaseCredential extends AwsAuthInputConfig {
10
+ provider?: {
11
+ http?: unknown;
12
+ ini?: unknown;
13
+ cognitoIdentity?: unknown;
14
+ cognitoIdentityPool?: unknown;
15
+ temporaryCredentials?: unknown;
16
+ webToken?: unknown;
17
+ containerMetadata?: unknown;
18
+ instanceMetadata?: unknown;
19
+ process?: unknown;
20
+ tokenFile?: unknown;
21
+ sso?: unknown;
22
+ env?: unknown;
23
+ nodeProviderChain?: unknown;
24
+ };
25
+ }
26
+
27
+ export type AWSStorage = CloudStorage<AWSStorageCredential, "aws-v3">;
28
+
29
+ export interface AWSStorageCredential extends S3ClientConfig, AWSBaseCredential {}
30
+
31
+ export interface AWSDatabaseQuery extends CloudDatabase<QueryCommandInput | ObjectMap<NativeAttributeValue>[], PlainObject, UpdateCommandInput, BatchGetCommandInput | ScanCommandInput> {
32
+ source: "cloud";
33
+ service: "aws-v3";
34
+ key?: string | AttributeKey;
35
+ }
36
+
37
+ export interface AWSDatabaseCredential extends Omit<DynamoDBClientConfig, "credentials">, AWSBaseCredential {
38
+ translateConfig?: TranslateConfig;
39
+ }
40
+
41
+ export type AttributeKey = Record<string, NativeAttributeValue>;
package/upload/index.js CHANGED
@@ -1,24 +1,24 @@
1
1
  "use strict";
2
2
  const path = require("path");
3
+ const fs = require("fs");
3
4
  const stream = require("stream");
5
+ const lib_storage_1 = require("@aws-sdk/lib-storage");
6
+ const Cloud = require("@e-mc/cloud");
4
7
  const util_1 = require("@e-mc/cloud/util");
5
- const aws_1 = require("@pi-r/aws");
6
8
  const types_1 = require("@e-mc/types");
7
- const Module = require("@e-mc/module");
8
- const Cloud = require("@e-mc/cloud");
9
+ const aws_lib_1 = require("@pi-r/aws-lib");
9
10
  const client_1 = require("@pi-r/aws-v3");
10
11
  const BUCKET_SESSION = new Set();
11
12
  const BUCKET_RESPONSE = {};
12
- module.exports = function upload(credential, service = 'aws-v3', sdk = '@aws-sdk/client-s3') {
13
+ module.exports = function upload(credential, service = "aws-v3", sdk = "@aws-sdk/client-s3") {
13
14
  const [client, AWS] = client_1.createStorageClient.call(this, credential, service, sdk);
14
15
  return async (data, callback) => {
15
- var _a;
16
16
  const { bucket: Bucket, localUri } = data;
17
- const { pathname = '', fileGroup, contentType, metadata, tags, endpoint, active, publicRead, acl, admin = {}, overwrite, options } = data.upload;
17
+ const { pathname = '', flags = 0, fileGroup, contentType, metadata, tags: Tags, endpoint, active, publicRead, acl, admin = {}, overwrite, options } = data.upload;
18
18
  let filename = data.upload.filename || path.basename(localUri), bucketKey;
19
19
  const cleanup = () => {
20
20
  BUCKET_SESSION.delete(service + Bucket);
21
- if (bucketKey && bucketKey in BUCKET_RESPONSE) {
21
+ if (bucketKey) {
22
22
  delete BUCKET_RESPONSE[bucketKey];
23
23
  }
24
24
  };
@@ -30,21 +30,49 @@ module.exports = function upload(credential, service = 'aws-v3', sdk = '@aws-sdk
30
30
  const addLog = (err) => err instanceof Error && this.addLog(this.statusType.WARN, err, service, Bucket);
31
31
  const configBucket = admin.configBucket;
32
32
  if (!BUCKET_SESSION.has(service + Bucket)) {
33
- const bucketAcl = admin.publicRead ? 'public-read' : admin.acl;
34
- const response = BUCKET_RESPONSE[_a = bucketKey = (0, aws_1.getBucketKey)(credential, Bucket, bucketAcl, service, sdk)] || (BUCKET_RESPONSE[_a] = client_1.createBucketV2.call(this, credential, Bucket, bucketAcl, configBucket?.create, service, sdk));
33
+ const bucketAcl = admin.publicRead ? "public-read" : admin.acl;
34
+ 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);
35
35
  if (!await response) {
36
36
  errorResponse(null);
37
37
  return;
38
38
  }
39
39
  BUCKET_SESSION.add(service + Bucket);
40
40
  }
41
- const DefaultRetention = configBucket?.retentionPolicy;
42
- if ((0, types_1.isPlainObject)(DefaultRetention)) {
43
- client.send(new AWS.PutObjectLockConfigurationCommand({ Bucket, ObjectLockConfiguration: { ObjectLockEnabled: 'Enabled', Rule: { DefaultRetention } }, ExpectedBucketOwner: options?.ExpectedBucketOwner, RequestPayer: options?.RequestPayer }))
44
- .then(() => {
45
- aws_1.writeMessageDefaultRetention.call(this, Bucket, DefaultRetention, service);
46
- })
47
- .catch(err => addLog(err));
41
+ if (configBucket) {
42
+ const { cors: CORSConfiguration, lifecycle: LifecycleConfiguration, retentionPolicy: DefaultRetention } = configBucket;
43
+ const ExpectedBucketOwner = options?.ExpectedBucketOwner;
44
+ const commandMessage = (feature, message) => this.formatMessage(64, service, ["Bucket configured" + ` (${feature})`, message || Bucket], ExpectedBucketOwner, { ...Cloud[message === 'delete' ? 'LOG_CLOUD_WARN' : 'LOG_CLOUD_COMMAND'] });
45
+ if ((0, types_1.isPlainObject)(DefaultRetention)) {
46
+ client.send(new AWS.PutObjectLockConfigurationCommand({ Bucket, ObjectLockConfiguration: { ObjectLockEnabled: 'Enabled', Rule: { DefaultRetention } }, ExpectedBucketOwner, RequestPayer: options?.RequestPayer }))
47
+ .then(() => {
48
+ this.formatMessage(64, service, ["Bucket configured" + ' (Retention Policy)', Bucket], (0, aws_lib_1.formatDefaultRetention)(DefaultRetention), { ...Cloud.LOG_CLOUD_COMMAND });
49
+ })
50
+ .catch((err) => addLog(err));
51
+ }
52
+ if (CORSConfiguration && Array.isArray(CORSConfiguration.CORSRules)) {
53
+ if (CORSConfiguration.CORSRules.length === 0) {
54
+ client.send(new AWS.DeleteBucketCorsCommand({ Bucket, ExpectedBucketOwner }))
55
+ .then(() => commandMessage('CORS', 'delete'))
56
+ .catch((err) => addLog(err));
57
+ }
58
+ else {
59
+ client.send(new AWS.PutBucketCorsCommand({ Bucket, CORSConfiguration, ExpectedBucketOwner }))
60
+ .then(() => commandMessage('CORS'))
61
+ .catch((err) => addLog(err));
62
+ }
63
+ }
64
+ if (LifecycleConfiguration && Array.isArray(LifecycleConfiguration.Rules)) {
65
+ if (LifecycleConfiguration.Rules.length === 0) {
66
+ client.send(new AWS.DeleteBucketLifecycleCommand({ Bucket, ExpectedBucketOwner }))
67
+ .then(() => commandMessage('Lifecycle', 'delete'))
68
+ .catch((err) => addLog(err));
69
+ }
70
+ else {
71
+ client.send(new AWS.PutBucketLifecycleConfigurationCommand({ Bucket, LifecycleConfiguration, ExpectedBucketOwner }))
72
+ .then(() => commandMessage('Lifecycle'))
73
+ .catch((err) => addLog(err));
74
+ }
75
+ }
48
76
  }
49
77
  if (!overwrite) {
50
78
  const current = filename;
@@ -57,9 +85,9 @@ module.exports = function upload(credential, service = 'aws-v3', sdk = '@aws-sdk
57
85
  break;
58
86
  }
59
87
  }
60
- exists = await client.send(new AWS.HeadObjectCommand({ Bucket, Key: pathname ? Module.joinPath(pathname, filename) : filename }))
88
+ exists = await client.send(new AWS.HeadObjectCommand({ Bucket, Key: pathname ? Cloud.joinPath(pathname, filename) : filename }))
61
89
  .then(() => true)
62
- .catch(err => {
90
+ .catch((err) => {
63
91
  if (err instanceof Error && err.name !== 'NotFound') {
64
92
  filename = (0, types_1.generateUUID)() + path.extname(current);
65
93
  return true;
@@ -75,13 +103,37 @@ module.exports = function upload(credential, service = 'aws-v3', sdk = '@aws-sdk
75
103
  await client.send(new AWS.PutObjectCommand({ Bucket, Key: pathname, Body: Buffer.from(''), ContentLength: 0 })).catch(() => { });
76
104
  }
77
105
  const Key = [filename];
78
- const Body = [data.buffer];
106
+ const Body = [];
107
+ const Stream = [];
79
108
  const ContentType = [contentType];
80
- if (fileGroup) {
81
- const [key, body, type] = (0, util_1.createKeyAndBody)(filename, fileGroup, addLog);
82
- Key.push(...key);
83
- Body.push(...body);
84
- ContentType.push(...type);
109
+ let partSize = 0;
110
+ const getPartSize = () => partSize > 0 ? Math.max(partSize, 5242880) : undefined;
111
+ if (flags & 2) {
112
+ if (flags & 4) {
113
+ partSize = (0, types_1.alignSize)(data.upload.chunkSize, 1024);
114
+ }
115
+ try {
116
+ Stream.push(data.buffer.length ? stream.Readable.from(data.buffer, { highWaterMark: getPartSize() }) : fs.createReadStream(localUri, { highWaterMark: getPartSize(), signal: this.signal }));
117
+ if (fileGroup) {
118
+ const [key, body, type] = (0, util_1.createKeyAndBody)(filename, fileGroup, 0, addLog, 2);
119
+ Key.push(...key);
120
+ Stream.push(...body);
121
+ ContentType.push(...type);
122
+ }
123
+ }
124
+ catch (err) {
125
+ errorResponse(err);
126
+ return;
127
+ }
128
+ }
129
+ else {
130
+ Body.push(data.buffer);
131
+ if (fileGroup) {
132
+ const [key, body, type] = (0, util_1.createKeyAndBody)(filename, fileGroup, 0, addLog);
133
+ Key.push(...key);
134
+ Body.push(...body);
135
+ ContentType.push(...type);
136
+ }
85
137
  }
86
138
  for (let i = 0; i < Key.length; ++i) {
87
139
  const first = i === 0;
@@ -91,81 +143,62 @@ module.exports = function upload(credential, service = 'aws-v3', sdk = '@aws-sdk
91
143
  }
92
144
  return;
93
145
  }
94
- const objectKey = Module.joinPath(pathname, Key[i]);
95
- let params;
96
- try {
97
- params = { ...options, Bucket, Key: pathname + Key[i], Body: stream.Readable.from(Body[i]) };
98
- const readable = publicRead || active && publicRead !== false && !acl;
99
- if (first) {
100
- params.ContentType || (params.ContentType = ContentType[i]);
146
+ const objectKey = Cloud.joinPath(pathname, Key[i]);
147
+ const params = { ...options, Bucket, Key: pathname + Key[i], Body: Stream[i] || stream.Readable.from(Body[i]) };
148
+ const readable = publicRead || active && publicRead !== false && !acl;
149
+ let tags, length = -1;
150
+ if (first) {
151
+ params.ContentType ||= ContentType[i];
152
+ if (readable) {
153
+ params.ACL = "public-read";
154
+ }
155
+ else if (acl) {
156
+ params.ACL = acl;
157
+ }
158
+ if (metadata) {
159
+ params.Metadata = metadata;
160
+ }
161
+ if ((0, types_1.isPlainObject)(Tags) && (length = Object.keys(Tags).length) > 0) {
162
+ tags = [];
163
+ for (const name in Tags) {
164
+ tags.push({ Key: name, Value: Tags[name] });
165
+ }
166
+ }
167
+ else if (Tags === false) {
168
+ length = 0;
169
+ }
170
+ }
171
+ else {
172
+ params.ContentType = ContentType[i];
173
+ if (!params.ACL) {
101
174
  if (readable) {
102
- params.ACL = 'public-read';
175
+ params.ACL = "public-read";
103
176
  }
104
177
  else if (acl) {
105
178
  params.ACL = acl;
106
179
  }
107
- if (metadata) {
108
- params.Metadata = metadata;
109
- }
110
180
  }
111
- else {
112
- params.ContentType = ContentType[i];
113
- if (!params.ACL) {
114
- if (readable) {
115
- params.ACL = 'public-read';
116
- }
117
- else if (acl) {
118
- params.ACL = acl;
119
- }
120
- }
121
- }
122
- }
123
- catch (err) {
124
- if (first) {
125
- errorResponse(err);
126
- return;
127
- }
128
- if (err instanceof Error) {
129
- this.addLog(this.statusType.WARN, err.message, service + ': ' + Bucket);
130
- }
131
- continue;
132
181
  }
133
- client.send(new AWS.PutObjectCommand(params), { abortSignal: this.signal })
182
+ new lib_storage_1.Upload({ client, params, tags, partSize: getPartSize(), queueSize: partSize > 0 ? data.upload.chunkLimit : undefined }).done()
134
183
  .then(() => {
135
- const url = endpoint ? Module.joinPath(endpoint, objectKey) : Module.joinPath(`https://${Bucket}.s3.${!credential.region || credential.region === 'us-east-1' ? 'us-east-1.' : ''}amazonaws.com`, objectKey);
184
+ 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);
136
185
  this.formatMessage(64, service, "Upload success", url, { ...Cloud.LOG_CLOUD_UPLOAD });
137
- if (!first) {
138
- return;
139
- }
140
- let length = -1;
141
- if ((0, types_1.isPlainObject)(tags) && (length = Object.keys(tags).length) > 0) {
142
- const TagSet = [];
143
- for (const name in tags) {
144
- TagSet.push({ Key: name, Value: tags[name] });
186
+ if (first) {
187
+ if (length === 0) {
188
+ client.send(new AWS.DeleteObjectTaggingCommand({ Bucket, Key: params.Key, ExpectedBucketOwner: params.ExpectedBucketOwner }), error => {
189
+ if (!error) {
190
+ this.formatMessage(64, service, ["Tags deleted", Bucket], params.Key, { ...Cloud.LOG_CLOUD_COMMAND });
191
+ }
192
+ else {
193
+ addLog(error);
194
+ }
195
+ });
145
196
  }
146
- client.send(new AWS.PutObjectTaggingCommand({ Bucket, Key: params.Key, ExpectedBucketOwner: params.ExpectedBucketOwner, Tagging: { TagSet }, RequestPayer: params.RequestPayer }), error => {
147
- if (!error) {
148
- this.formatMessage(64, service, ["Tags created", Bucket], params.Key, { ...Cloud.LOG_CLOUD_COMMAND });
149
- }
150
- else {
151
- addLog(error);
152
- }
153
- });
154
- }
155
- else if (tags === false || length === 0) {
156
- client.send(new AWS.DeleteObjectTaggingCommand({ Bucket, Key: params.Key, ExpectedBucketOwner: params.ExpectedBucketOwner }), error => {
157
- if (!error) {
158
- this.formatMessage(64, service, ["Tags deleted", Bucket], params.Key, { ...Cloud.LOG_CLOUD_COMMAND });
159
- }
160
- else {
161
- addLog(error);
162
- }
163
- });
164
- }
165
- cleanup();
166
- callback(null, url);
197
+ cleanup();
198
+ callback(null, url);
199
+ }
167
200
  })
168
- .catch(err => {
201
+ .catch((err) => {
169
202
  if (first) {
170
203
  errorResponse(err);
171
204
  }