@baadal-sdk/dapi 0.31.6 → 1.0.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.
Files changed (51) hide show
  1. package/README.md +62 -2
  2. package/dist/index.d.ts +674 -0
  3. package/dist/index.js +1118 -0
  4. package/dist/index.js.map +1 -0
  5. package/package.json +44 -106
  6. package/LICENSE.txt +0 -21
  7. package/dist/cjs/index.js +0 -3
  8. package/dist/cjs/index.js.LICENSE.txt +0 -1
  9. package/dist/cjs/index.js.map +0 -1
  10. package/dist/cjs/package.json +0 -3
  11. package/dist/esm/index.js +0 -3
  12. package/dist/esm/index.js.LICENSE.txt +0 -1
  13. package/dist/esm/index.js.map +0 -1
  14. package/dist/esm/package.json +0 -3
  15. package/dist/types/aws/client.d.ts +0 -13
  16. package/dist/types/aws/client.d.ts.map +0 -1
  17. package/dist/types/aws/db.d.ts +0 -291
  18. package/dist/types/aws/db.d.ts.map +0 -1
  19. package/dist/types/aws/index.d.ts +0 -12
  20. package/dist/types/aws/index.d.ts.map +0 -1
  21. package/dist/types/aws/s3.d.ts +0 -90
  22. package/dist/types/aws/s3.d.ts.map +0 -1
  23. package/dist/types/common/common.model.d.ts +0 -4
  24. package/dist/types/common/common.model.d.ts.map +0 -1
  25. package/dist/types/common/const.d.ts +0 -4
  26. package/dist/types/common/const.d.ts.map +0 -1
  27. package/dist/types/common/error.d.ts +0 -4
  28. package/dist/types/common/error.d.ts.map +0 -1
  29. package/dist/types/common/logger.d.ts +0 -29
  30. package/dist/types/common/logger.d.ts.map +0 -1
  31. package/dist/types/fs/index.d.ts +0 -102
  32. package/dist/types/fs/index.d.ts.map +0 -1
  33. package/dist/types/gh/index.d.ts +0 -22
  34. package/dist/types/gh/index.d.ts.map +0 -1
  35. package/dist/types/index.d.ts +0 -13
  36. package/dist/types/index.d.ts.map +0 -1
  37. package/dist/types/utils/index.d.ts +0 -6
  38. package/dist/types/utils/index.d.ts.map +0 -1
  39. package/src/aws/client.ts +0 -18
  40. package/src/aws/db.ts +0 -764
  41. package/src/aws/index.ts +0 -33
  42. package/src/aws/s3.ts +0 -476
  43. package/src/common/common.model.ts +0 -3
  44. package/src/common/const.ts +0 -3
  45. package/src/common/error.ts +0 -12
  46. package/src/common/logger.ts +0 -18
  47. package/src/fs/index.ts +0 -316
  48. package/src/gh/index.ts +0 -60
  49. package/src/index.ts +0 -8
  50. package/src/typings/index.d.ts +0 -0
  51. package/src/utils/index.ts +0 -39
package/src/aws/db.ts DELETED
@@ -1,764 +0,0 @@
1
- /**
2
- * Examples:
3
- * Ref: https://docs.aws.amazon.com/sdk-for-javascript/v3/developer-guide/dynamodb-examples.html
4
- *
5
- * Partition key vs Composite primary key:
6
- * Ref: https://aws.amazon.com/premiumsupport/knowledge-center/primary-key-dynamodb-table/
7
- */
8
-
9
- import { DynamoDBClient } from '@aws-sdk/client-dynamodb';
10
- import {
11
- DynamoDBDocumentClient,
12
- GetCommand,
13
- GetCommandInput,
14
- BatchGetCommand,
15
- BatchGetCommandInput,
16
- PutCommand,
17
- PutCommandInput,
18
- BatchWriteCommand,
19
- BatchWriteCommandInput,
20
- UpdateCommand,
21
- UpdateCommandInput,
22
- QueryCommand,
23
- QueryCommandInput,
24
- ScanCommand,
25
- ScanCommandInput,
26
- DeleteCommand,
27
- DeleteCommandInput,
28
- } from '@aws-sdk/lib-dynamodb';
29
- import short from 'short-uuid';
30
- import { chunkifyArray } from '@baadal-sdk/utils';
31
-
32
- import { dbClient } from './client';
33
- import { StringIndexable } from '../common/common.model';
34
- import { CustomError } from '../common/error';
35
- import { warn, error } from '../common/logger';
36
- import { BATCH_SIZE, CHUNK_SIZE, MAX_RETRY_ATTEMPTS } from '../common/const';
37
-
38
- const DynamoDBError = (msg: string) => new CustomError(msg, { name: 'DynamoDBError' });
39
-
40
- /** @internal */
41
- export const init = (region: string) => {
42
- // Ref: https://docs.aws.amazon.com/AWSJavaScriptSDK/v3/latest/modules/_aws_sdk_lib_dynamodb.html#configuration
43
- if (!dbClient.client) {
44
- const dydbClient = new DynamoDBClient({ region }); // may also pass `credentials`
45
- dbClient.client = DynamoDBDocumentClient.from(dydbClient);
46
- dbClient.id = short.uuid();
47
- return true;
48
- }
49
- return false;
50
- };
51
-
52
- /** @internal */
53
- export const status = () => dbClient.id;
54
-
55
- const tryInit = (silent = false) => {
56
- if (dbClient.client) return;
57
- const region = process.env.AWS_REGION || '';
58
- if (region) {
59
- if (init(region)) {
60
- // console.log('Auto-initialization of DynamoDB successful');
61
- return;
62
- }
63
- }
64
- if (!silent) {
65
- // throw DynamoDBError('DynamoDB is possibly uninitialized!');
66
- throw DynamoDBError('Could not auto-initialize DynamoDB!');
67
- }
68
- };
69
-
70
- // auto-initialize on load
71
- tryInit(true);
72
-
73
- const writeItemForceHelper = async <T = any>(
74
- table: string,
75
- item: T,
76
- key: string,
77
- i: number,
78
- imax?: number
79
- ): Promise<T | null> => {
80
- if (!dbClient.client) tryInit();
81
- if (!dbClient.client) return null;
82
- if (!table || !item) return null;
83
-
84
- if (!(item as any)[key]) {
85
- (item as any)[key] = short.uuid();
86
- }
87
- const cmdParams: PutCommandInput = { TableName: table, Item: item, ConditionExpression: `attribute_not_exists(${key})` };
88
- const command = new PutCommand(cmdParams);
89
- const numberOfAttempts = imax ?? MAX_RETRY_ATTEMPTS;
90
-
91
- try {
92
- await dbClient.client.send(command);
93
- } catch (err: any) {
94
- if (err.name === 'ConditionalCheckFailedException') {
95
- if (i < numberOfAttempts - 1) {
96
- (item as any)[key] = short.uuid(); // new primary key
97
- const ret: T | null = await writeItemForceHelper(table, item, key, i + 1, imax);
98
- return ret;
99
- }
100
- console.error('PutCommandInput:', cmdParams);
101
- if (numberOfAttempts === 1) {
102
- error(`[ERROR] An item with the same key(${(item as any)[key]}) already exists!`);
103
- } else {
104
- error('[ERROR] Maximum attempts overflow!');
105
- }
106
- }
107
- return null;
108
- }
109
-
110
- return item;
111
- };
112
-
113
- export interface WriteItemForceInput<T = any> {
114
- table: string;
115
- item: T;
116
- key?: string;
117
- }
118
-
119
- export type WriteItemUniqueInput<T = any> = WriteItemForceInput<T>;
120
-
121
- /**
122
- * Write an item to a DynamoDB table, retry in case of key conflict
123
- * @param input input command object
124
- * @returns the created item, null in case of error
125
- *
126
- * ```js
127
- * writeItemForce({
128
- * table: 'lesson_list',
129
- * item: { title: 'My Lesson' },
130
- * key: 'id',
131
- * });
132
- *
133
- * interface WriteItemForceInput<T = any> {
134
- * table: string;
135
- * item: T;
136
- * key?: string; // default: `id`
137
- * }
138
- * ```
139
- */
140
- export const writeItemForce = async <T = any>(input: WriteItemForceInput<T>): Promise<T | null> => {
141
- const key = input.key || 'id';
142
- return writeItemForceHelper<T>(input.table, input.item, key, 0);
143
- };
144
-
145
- /**
146
- * Write an item (uniquely) to a DynamoDB table.
147
- * Unlike `writeItemForce`, it does not retry in case of key conflict
148
- * Unlike `writeItem`, it does not overwrite an item with the same key (if it exists)
149
- * @param input input command object
150
- * @returns the created item, null in case of error or key conflict (i.e., if item with same key already exists)
151
- *
152
- * ```js
153
- * writeItemUnique({
154
- * table: 'lesson_list',
155
- * item: { id: 'id_001', title: 'My Lesson' },
156
- * key: 'id',
157
- * });
158
- *
159
- * interface WriteItemUniqueInput<T = any> {
160
- * table: string;
161
- * item: T;
162
- * key?: string; // default: `id`
163
- * }
164
- * ```
165
- */
166
- export const writeItemUnique = async <T = any>(input: WriteItemUniqueInput<T>): Promise<T | null> => {
167
- const key = input.key || 'id';
168
- return writeItemForceHelper<T>(input.table, input.item, key, 0, 1);
169
- };
170
-
171
- export interface WriteItemInput {
172
- table: string;
173
- item: StringIndexable;
174
- }
175
-
176
- /**
177
- * Write an item to a DynamoDB table
178
- * @param input input command object
179
- * @returns true if successful, null in case of error
180
- *
181
- * ```js
182
- * writeItem({
183
- * table: 'lesson_list',
184
- * item: { id: 'id_001', title: 'My Lesson' },
185
- * });
186
- *
187
- * interface WriteItemInput {
188
- * table: string;
189
- * item: StringIndexable;
190
- * }
191
- * ```
192
- */
193
- export const writeItem = async (input: WriteItemInput) => {
194
- if (!dbClient.client) tryInit();
195
- if (!dbClient.client) return null;
196
- if (!input.table || !input.item) return null;
197
-
198
- const cmdParams: PutCommandInput = { TableName: input.table, Item: input.item };
199
- const command = new PutCommand(cmdParams);
200
-
201
- try {
202
- await dbClient.client.send(command);
203
- } catch (err) {
204
- console.error('PutCommandInput:', cmdParams);
205
- console.error(err);
206
- return null;
207
- // throw err;
208
- }
209
-
210
- return true;
211
- };
212
-
213
- // Ref: https://docs.aws.amazon.com/sdk-for-javascript/v3/developer-guide/dynamodb-example-table-read-write-batch.html
214
- const batchWriteItems = async (table: string, items: StringIndexable[]) => {
215
- if (!dbClient.client) tryInit();
216
- if (!dbClient.client) return null;
217
- if (!table || !items || !Array.isArray(items)) return null;
218
- if (!items.length) return true;
219
-
220
- const reqList = items.map(item => ({ PutRequest: { Item: item } }));
221
- const cmdParams: BatchWriteCommandInput = {
222
- RequestItems: {
223
- [table]: reqList,
224
- },
225
- };
226
-
227
- const command = new BatchWriteCommand(cmdParams);
228
-
229
- try {
230
- await dbClient.client.send(command);
231
- } catch (err) {
232
- console.error('BatchWriteCommandInput:', cmdParams);
233
- console.error(err);
234
- return null;
235
- // throw err;
236
- }
237
-
238
- return true;
239
- };
240
-
241
- export interface WriteItemsAllInput {
242
- table: string;
243
- items: StringIndexable[];
244
- }
245
-
246
- /**
247
- * Write a list of items to a DynamoDB table
248
- * @param input input command object
249
- * @returns true if successful, null in case of error
250
- *
251
- * ```js
252
- * writeItemsAll({
253
- * table: 'lesson_list',
254
- * items: [{ id: 'id_001', title: 'My Lesson' }, { id: 'id_002', title: 'My Lesson 2' }],
255
- * });
256
- *
257
- * interface WriteItemInput {
258
- * table: string;
259
- * items: StringIndexable[];
260
- * }
261
- * ```
262
- */
263
- export const writeItemsAll = async (input: WriteItemsAllInput) => {
264
- if (!dbClient.client) tryInit();
265
- if (!dbClient.client) return null;
266
- if (!input.table || !input.items || !Array.isArray(input.items)) return null;
267
- if (!input.items.length) return true;
268
-
269
- let errFlag = false;
270
-
271
- const batchedItems = chunkifyArray(input.items, BATCH_SIZE);
272
- const chunkedItems = chunkifyArray(batchedItems, CHUNK_SIZE);
273
-
274
- for (let i = 0; i < chunkedItems.length; i += 1) {
275
- const bchunks = chunkedItems[i];
276
-
277
- const brlist = bchunks.map(iItems => batchWriteItems(input.table, iItems));
278
- const bslist = await Promise.all(brlist); // eslint-disable-line no-await-in-loop
279
-
280
- const isSuccess = bslist.every(e => e === true);
281
- if (!isSuccess) errFlag = true;
282
- }
283
-
284
- return errFlag ? null : true;
285
- };
286
-
287
- export interface UpdateItemInput {
288
- table: string;
289
- key: StringIndexable;
290
- update: string;
291
- attr: StringIndexable;
292
- attrNames?: StringIndexable;
293
- }
294
-
295
- /**
296
- * Update an item in DynamoDB table
297
- * @param input input command object
298
- * @returns true if successful, null in case of error
299
- *
300
- * ```js
301
- * updateItem({
302
- * table: 'lesson_list',
303
- * key: { id: 'id_001' },
304
- * update: 'SET status = :status, #rev = 10',
305
- * attr: { ':status': 'completed' },
306
- * attrNames: { '#rev': 'revision' },
307
- * });
308
- *
309
- * interface UpdateItemInput {
310
- * table: string;
311
- * key: StringIndexable;
312
- * update: string;
313
- * attr: StringIndexable;
314
- * attrNames?: StringIndexable;
315
- * }
316
- * ```
317
- */
318
- export const updateItem = async (input: UpdateItemInput) => {
319
- if (!dbClient.client) tryInit();
320
- if (!dbClient.client) return null;
321
- if (!input.table || !input.key || !input.update || !input.attr) return null;
322
-
323
- let cmdParams: UpdateCommandInput = {
324
- TableName: input.table,
325
- Key: input.key,
326
- UpdateExpression: input.update,
327
- ExpressionAttributeValues: input.attr,
328
- };
329
- if (input.attrNames) cmdParams = { ...cmdParams, ExpressionAttributeNames: input.attrNames };
330
- const command = new UpdateCommand(cmdParams);
331
-
332
- try {
333
- await dbClient.client.send(command);
334
- } catch (err) {
335
- console.error('UpdateCommandInput:', cmdParams);
336
- console.error(err);
337
- return null;
338
- // throw err;
339
- }
340
-
341
- return true;
342
- };
343
-
344
- export interface ReadItemInput {
345
- table: string;
346
- key: StringIndexable;
347
- projection?: string;
348
- attrNames?: StringIndexable;
349
- loud?: boolean;
350
- }
351
-
352
- /**
353
- * Read an item from DynamoDB table
354
- * @param input input command object
355
- * @returns item contents, null in case of error
356
- *
357
- * ```js
358
- * readItem({
359
- * table: 'lesson_list',
360
- * key: { id: 'id_001' },
361
- * projection: 'id, lesson, status',
362
- * });
363
- *
364
- * interface ReadItemInput {
365
- * table: string;
366
- * key: StringIndexable;
367
- * projection?: string;
368
- * attrNames?: StringIndexable;
369
- * }
370
- * ```
371
- */
372
- export const readItem = async <T = any>(input: ReadItemInput) => {
373
- if (!dbClient.client) tryInit();
374
- if (!dbClient.client) return null;
375
- if (!input.table || !input.key) return null;
376
-
377
- let contents: T | null = null;
378
- let cmdParams: GetCommandInput = { TableName: input.table, Key: input.key };
379
-
380
- // Ref: https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/Expressions.ProjectionExpressions.html
381
- if (input.projection) cmdParams = { ...cmdParams, ProjectionExpression: input.projection };
382
- if (input.attrNames) cmdParams = { ...cmdParams, ExpressionAttributeNames: input.attrNames };
383
-
384
- const command = new GetCommand(cmdParams);
385
-
386
- try {
387
- const results = await dbClient.client.send(command);
388
- const item = results.Item;
389
-
390
- if (item) {
391
- contents = item as T;
392
- }
393
- } catch (err) {
394
- console.error('GetCommandInput:', cmdParams);
395
- console.error(err);
396
- if (input.loud) {
397
- throw err;
398
- } else {
399
- return null;
400
- }
401
- }
402
-
403
- return contents;
404
- };
405
-
406
- // Ref: https://docs.aws.amazon.com/sdk-for-javascript/v3/developer-guide/dynamodb-example-table-read-write-batch.html
407
- const batchReadItems = async <T = any>(
408
- table: string,
409
- keys: StringIndexable[],
410
- projection?: string,
411
- attrNames?: StringIndexable
412
- ) => {
413
- if (!dbClient.client) tryInit();
414
- if (!dbClient.client) return null;
415
- if (!table || !keys || !Array.isArray(keys)) return null;
416
- if (!keys.length) return [];
417
-
418
- let contents: StringIndexable<T>[] = [];
419
-
420
- let reqParams: any = { Keys: keys };
421
- if (projection) reqParams = { ...reqParams, ProjectionExpression: projection };
422
- if (attrNames) reqParams = { ...reqParams, ExpressionAttributeNames: attrNames };
423
-
424
- const cmdParams: BatchGetCommandInput = {
425
- RequestItems: {
426
- [table]: reqParams,
427
- },
428
- };
429
-
430
- const command = new BatchGetCommand(cmdParams);
431
-
432
- try {
433
- const results = await dbClient.client.send(command);
434
- const items = results.Responses;
435
-
436
- if (items && items[table]) {
437
- contents = items[table];
438
- }
439
- } catch (err) {
440
- console.error('BatchGetCommandInput:', cmdParams);
441
- console.error(err);
442
- return null;
443
- // throw err;
444
- }
445
-
446
- return contents;
447
- };
448
-
449
- export interface ReadItemsAllInput {
450
- table: string;
451
- keys: StringIndexable[];
452
- projection?: string;
453
- attrNames?: StringIndexable;
454
- }
455
-
456
- /**
457
- * Read a list of items from DynamoDB table
458
- * Note: ordering of items in result may not be same as that in `keys`
459
- * @param input input command object
460
- * @returns list of contents for items, null in case of error
461
- *
462
- * ```js
463
- * readItemsAll({
464
- * table: 'lesson_list',
465
- * keys: [{ id: 'id_001' }, { id: 'id_002' }],
466
- * projection: 'id, lesson, status',
467
- * });
468
- *
469
- * interface ReadItemsAllInput {
470
- * table: string;
471
- * keys: StringIndexable[];
472
- * projection?: string;
473
- * attrNames?: StringIndexable;
474
- * }
475
- * ```
476
- */
477
- export const readItemsAll = async <T = any>(input: ReadItemsAllInput) => {
478
- if (!dbClient.client) tryInit();
479
- if (!dbClient.client) return null;
480
- if (!input.table || !input.keys || !Array.isArray(input.keys)) return null;
481
- if (!input.keys.length) return [];
482
-
483
- let contents: StringIndexable<T>[] = [];
484
- let errFlag = false;
485
-
486
- const batchedKeys = chunkifyArray(input.keys, BATCH_SIZE);
487
- const chunkedKeys = chunkifyArray(batchedKeys, CHUNK_SIZE);
488
-
489
- for (let i = 0; i < chunkedKeys.length; i += 1) {
490
- const bchunks = chunkedKeys[i];
491
-
492
- const brlist = bchunks.map(ikeys => batchReadItems(input.table, ikeys, input.projection, input.attrNames));
493
- const bslist = await Promise.all(brlist); // eslint-disable-line no-await-in-loop
494
-
495
- const icontents = bslist.flat();
496
- const isError = icontents.find(e => e === null) === null;
497
- if (isError) {
498
- errFlag = true;
499
- return null;
500
- }
501
- if (!errFlag) {
502
- contents = contents.concat(icontents as StringIndexable[]);
503
- }
504
- }
505
-
506
- return contents;
507
- };
508
-
509
- export interface QueryItemsInput {
510
- table: string;
511
- indexName?: string;
512
- cond: string;
513
- attr: StringIndexable;
514
- attrNames?: StringIndexable;
515
- projection?: string;
516
- desc?: boolean;
517
- }
518
-
519
- /**
520
- * Query items from a DynamoDB table based on some condition
521
- * @param input input command object
522
- * @returns query results array, null in case of error
523
- *
524
- * ```js
525
- * dbQueryItems({
526
- * table: 'lesson_list',
527
- * indexName: 'status-revision-index',
528
- * cond: 'status = :comp AND #rev >= :rev',
529
- * attr: { ':comp': 'completed', ':rev': 9 },
530
- * attrNames: { '#rev': 'revision' },
531
- * projection: 'id, lesson, status, revision',
532
- * });
533
- *
534
- * interface QueryItemsInput {
535
- * table: string;
536
- * indexName?: string;
537
- * cond: string;
538
- * attr: StringIndexable;
539
- * attrNames?: StringIndexable;
540
- * projection?: string;
541
- * desc?: boolean;
542
- * }
543
- * ```
544
- */
545
- export const queryItems = async (input: QueryItemsInput) => {
546
- if (!dbClient.client) tryInit();
547
- if (!dbClient.client) return null;
548
- if (!input.table || !input.cond || !input.attr) return null;
549
-
550
- let contents: StringIndexable[] = [];
551
- const desc = input.desc || false;
552
-
553
- // Ref: https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/Query.html
554
- // Ref: https://docs.aws.amazon.com/amazondynamodb/latest/APIReference/API_Query.html
555
- // Ref: https://docs.aws.amazon.com/sdk-for-javascript/v3/developer-guide/dynamodb-example-query-scan.html
556
- // Ref: https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/SQLtoNoSQL.Indexes.QueryAndScan.html#SQLtoNoSQL.Indexes.QueryAndScan.DynamoDB
557
- let cmdParams: QueryCommandInput = {
558
- TableName: input.table,
559
- KeyConditionExpression: input.cond,
560
- ExpressionAttributeValues: input.attr,
561
- // FilterExpression: "contains (category_id, :cid)",
562
- };
563
-
564
- if (input.indexName) cmdParams = { ...cmdParams, IndexName: input.indexName };
565
- if (input.attrNames) cmdParams = { ...cmdParams, ExpressionAttributeNames: input.attrNames };
566
- if (input.projection) cmdParams = { ...cmdParams, ProjectionExpression: input.projection };
567
- if (desc) cmdParams = { ...cmdParams, ScanIndexForward: false };
568
-
569
- const command = new QueryCommand(cmdParams);
570
-
571
- try {
572
- const results = await dbClient.client.send(command);
573
- const items = results.Items;
574
-
575
- if (items) {
576
- contents = items;
577
- }
578
- } catch (err) {
579
- console.error('QueryCommandInput:', command.input);
580
- console.error(err);
581
- return null;
582
- // throw err;
583
- }
584
-
585
- return contents;
586
- };
587
-
588
- export interface ScanItemsInput {
589
- table: string;
590
- projection?: string;
591
- }
592
-
593
- /**
594
- * Scan all items in a DynamoDB table
595
- * Note: avoid using this method in favour of `queryItems` method due to performance reasons
596
- * @param input input command object
597
- * @returns results of the scan query, null in case of error
598
- *
599
- * ```js
600
- * scanItems({
601
- * table: 'lesson_list',
602
- * projection: 'id, status',
603
- * });
604
- *
605
- * interface ScanItemsInput {
606
- * table: string;
607
- * projection?: string;
608
- * }
609
- * ```
610
- */
611
- export const scanItems = async (input: ScanItemsInput) => {
612
- if (!dbClient.client) tryInit();
613
- if (!dbClient.client) return null;
614
- if (!input.table) return null;
615
-
616
- let contents: StringIndexable[] = [];
617
-
618
- // Ref: https://docs.aws.amazon.com/sdk-for-javascript/v3/developer-guide/dynamodb-example-query-scan.html
619
- let cmdParams: ScanCommandInput = {
620
- TableName: input.table,
621
- };
622
-
623
- if (input.projection) cmdParams = { ...cmdParams, ProjectionExpression: input.projection };
624
-
625
- const command = new ScanCommand(cmdParams);
626
-
627
- try {
628
- const results = await dbClient.client.send(command);
629
- const items = results.Items;
630
-
631
- // Ref: https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/Scan.html#Scan.Pagination
632
- if (results.LastEvaluatedKey) {
633
- warn('[scanItems] Partial results obtained! Consider pagination.');
634
- }
635
-
636
- if (items) {
637
- contents = items;
638
- }
639
- } catch (err) {
640
- console.error('ScanCommandInput:', cmdParams);
641
- console.error(err);
642
- return null;
643
- // throw err;
644
- }
645
-
646
- return contents;
647
- };
648
-
649
- export interface DeleteItemInput {
650
- table: string;
651
- key: StringIndexable;
652
- }
653
-
654
- /**
655
- * Delete an item in a DynamoDB table
656
- * @param input input command object
657
- * @returns true if successful, null in case of error
658
- *
659
- * ```js
660
- * deleteItem({
661
- * table: 'lesson_list',
662
- * key: { id: 'id_001' },
663
- * });
664
- *
665
- * interface DeleteItemInput {
666
- * table: string;
667
- * key: StringIndexable;
668
- * }
669
- * ```
670
- */
671
- export const deleteItem = async (input: DeleteItemInput) => {
672
- if (!dbClient.client) tryInit();
673
- if (!dbClient.client) return null;
674
- if (!input.table || !input.key) return null;
675
-
676
- const cmdParams: DeleteCommandInput = { TableName: input.table, Key: input.key };
677
- const command = new DeleteCommand(cmdParams);
678
-
679
- try {
680
- await dbClient.client.send(command);
681
- } catch (err) {
682
- console.error('DeleteCommandInput:', cmdParams);
683
- console.error(err);
684
- return null;
685
- // throw err;
686
- }
687
-
688
- return true;
689
- };
690
-
691
- // Ref: https://docs.aws.amazon.com/sdk-for-javascript/v3/developer-guide/dynamodb-example-table-read-write-batch.html
692
- // Ref: https://docs.aws.amazon.com/AWSJavaScriptSDK/v3/latest/clients/client-dynamodb/interfaces/batchwriteitemcommandinput.html#requestitems
693
- const batchDeleteItems = async (table: string, keys: StringIndexable[]) => {
694
- if (!dbClient.client) tryInit();
695
- if (!dbClient.client) return null;
696
- if (!table || !keys || !Array.isArray(keys)) return null;
697
- if (!keys.length) return true;
698
-
699
- const reqList = keys.map(key => ({ DeleteRequest: { Key: key } }));
700
- const cmdParams: BatchWriteCommandInput = {
701
- RequestItems: {
702
- [table]: reqList,
703
- },
704
- };
705
-
706
- const command = new BatchWriteCommand(cmdParams);
707
-
708
- try {
709
- await dbClient.client.send(command);
710
- } catch (err) {
711
- console.error('BatchWriteCommandInput:', cmdParams);
712
- console.error(err);
713
- return null;
714
- // throw err;
715
- }
716
-
717
- return true;
718
- };
719
-
720
- export interface DeleteItemsAllInput {
721
- table: string;
722
- keys: StringIndexable[];
723
- }
724
-
725
- /**
726
- * Delete a list of items in a DynamoDB table
727
- * @param input input command object
728
- * @returns true if successful, null in case of error
729
- *
730
- * ```js
731
- * deleteItemsAll({
732
- * table: 'lesson_list',
733
- * keys: [{ id: 'id_001' }, { id: 'id_002' }],
734
- * });
735
- *
736
- * interface DeleteItemsAllInput {
737
- * table: string;
738
- * keys: StringIndexable[];
739
- * }
740
- * ```
741
- */
742
- export const deleteItemsAll = async (input: DeleteItemsAllInput) => {
743
- if (!dbClient.client) tryInit();
744
- if (!dbClient.client) return null;
745
- if (!input.table || !input.keys || !Array.isArray(input.keys)) return null;
746
- if (!input.keys.length) return true;
747
-
748
- let errFlag = false;
749
-
750
- const batchedItems = chunkifyArray(input.keys, BATCH_SIZE);
751
- const chunkedItems = chunkifyArray(batchedItems, CHUNK_SIZE);
752
-
753
- for (let i = 0; i < chunkedItems.length; i += 1) {
754
- const bchunks = chunkedItems[i];
755
-
756
- const brlist = bchunks.map(ikeys => batchDeleteItems(input.table, ikeys));
757
- const bslist = await Promise.all(brlist); // eslint-disable-line no-await-in-loop
758
-
759
- const isSuccess = bslist.every(e => e === true);
760
- if (!isSuccess) errFlag = true;
761
- }
762
-
763
- return errFlag ? null : true;
764
- };