@baadal-sdk/dapi 0.22.0 → 0.23.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.
@@ -0,0 +1,13 @@
1
+ /**
2
+ * Partition key vs Composite primary key:
3
+ * Ref: https://aws.amazon.com/premiumsupport/knowledge-center/primary-key-dynamodb-table/
4
+ */
5
+ import { StringIndexable } from '../common/common.model';
6
+ export declare const init: (region: string) => void;
7
+ export declare const writeItemForce: <T = any>(table: string, data: T, key?: string) => Promise<T | null>;
8
+ export declare const writeItem: (table: string, data: StringIndexable) => Promise<true | null>;
9
+ export declare const updateItem: (table: string, key: StringIndexable, update: string, attr: StringIndexable, attrNames?: StringIndexable<any> | undefined) => Promise<true | null>;
10
+ export declare const readItem: <T = any>(table: string, key: StringIndexable, projection?: string) => Promise<T | null>;
11
+ export declare const queryItems: (table: string, indexName: string, cond: string, attr: StringIndexable, projection?: string, desc?: boolean) => Promise<StringIndexable<any>[] | null>;
12
+ export declare const scanItems: (table: string, projection?: string) => Promise<StringIndexable<any>[] | null>;
13
+ //# sourceMappingURL=db.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"db.d.ts","sourceRoot":"","sources":["../../../src/aws/db.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAkBH,OAAO,EAAE,eAAe,EAAE,MAAM,wBAAwB,CAAC;AAWzD,eAAO,MAAM,IAAI,WAAY,MAAM,SAKlC,CAAC;AAiCF,eAAO,MAAM,cAAc,mBAA0B,MAAM,6CAE1D,CAAC;AAEF,eAAO,MAAM,SAAS,UAAiB,MAAM,QAAQ,eAAe,yBAiBnE,CAAC;AAEF,eAAO,MAAM,UAAU,UACd,MAAM,OACR,eAAe,UACZ,MAAM,QACR,eAAe,uEAyBtB,CAAC;AAEF,eAAO,MAAM,QAAQ,mBAA0B,MAAM,OAAO,eAAe,2CA0B1E,CAAC;AAEF,eAAO,MAAM,UAAU,UACd,MAAM,aACF,MAAM,QACX,MAAM,QACN,eAAe,gFAuCtB,CAAC;AAEF,eAAO,MAAM,SAAS,UAAiB,MAAM,gEA6B5C,CAAC"}
@@ -0,0 +1,11 @@
1
+ declare const db: {
2
+ writeItemForce: <T = any>(table: string, data: T, key?: string) => Promise<T | null>;
3
+ writeItem: (table: string, data: import("../common/common.model").StringIndexable<any>) => Promise<true | null>;
4
+ updateItem: (table: string, key: import("../common/common.model").StringIndexable<any>, update: string, attr: import("../common/common.model").StringIndexable<any>, attrNames?: import("../common/common.model").StringIndexable<any> | undefined) => Promise<true | null>;
5
+ readItem: <T_1 = any>(table: string, key: import("../common/common.model").StringIndexable<any>, projection?: string) => Promise<T_1 | null>;
6
+ queryItems: (table: string, indexName: string, cond: string, attr: import("../common/common.model").StringIndexable<any>, projection?: string, desc?: boolean) => Promise<import("../common/common.model").StringIndexable<any>[] | null>;
7
+ scanItems: (table: string, projection?: string) => Promise<import("../common/common.model").StringIndexable<any>[] | null>;
8
+ };
9
+ declare const init: (region: string) => void;
10
+ export { db, init };
11
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/aws/index.ts"],"names":[],"mappings":"AAEA,QAAA,MAAyB,EAAE;;;;;;;CAAU,CAAC;AAEtC,QAAA,MAAM,IAAI,WAAY,MAAM,SAO3B,CAAC;AAEF,OAAO,EAAE,EAAE,EAAE,IAAI,EAAE,CAAC"}
@@ -0,0 +1,4 @@
1
+ export interface StringIndexable<T = any> {
2
+ [key: string]: T;
3
+ }
4
+ //# sourceMappingURL=common.model.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"common.model.d.ts","sourceRoot":"","sources":["../../../src/common/common.model.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,eAAe,CAAC,CAAC,GAAG,GAAG;IACtC,CAAC,GAAG,EAAE,MAAM,GAAG,CAAC,CAAC;CAClB"}
@@ -1,7 +1,9 @@
1
1
  import * as fs from './fs';
2
- export { fs };
2
+ import * as aws from './aws';
3
+ export { fs, aws };
3
4
  declare const _default: {
4
5
  fs: typeof fs;
6
+ aws: typeof aws;
5
7
  };
6
8
  export default _default;
7
9
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,MAAM,CAAC;AAG3B,OAAO,EAAE,EAAE,EAAE,CAAC;;;;AACd,wBAAsB"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,MAAM,CAAC;AAC3B,OAAO,KAAK,GAAG,MAAM,OAAO,CAAC;AAG7B,OAAO,EAAE,EAAE,EAAE,GAAG,EAAE,CAAC;;;;;AACnB,wBAA2B"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@baadal-sdk/dapi",
3
- "version": "0.22.0",
3
+ "version": "0.23.0",
4
4
  "description": "Dead-simple API wrappers",
5
5
  "main": "dist/cjs/index.js",
6
6
  "module": "dist/esm/index.js",
@@ -20,7 +20,7 @@
20
20
  "author": "Abhishek Raj <abhi@raj.me>",
21
21
  "license": "MIT",
22
22
  "engines": {
23
- "node": ">=12.5.0"
23
+ "node": ">=14.10.0"
24
24
  },
25
25
  "scripts": {
26
26
  "build": "npm run verify && bash tasks/build.sh",
@@ -68,11 +68,15 @@
68
68
  "ts-node": "10.2.1",
69
69
  "typescript": "4.4.3",
70
70
  "webpack": "5.53.0",
71
- "webpack-cli": "4.8.0"
71
+ "webpack-cli": "4.8.0",
72
+ "webpack-node-externals": "3.0.0"
72
73
  },
73
74
  "dependencies": {
74
- "core-js": "3.18.0",
75
- "rimraf": "3.0.2"
75
+ "@aws-sdk/client-dynamodb": "^3.34.0",
76
+ "@aws-sdk/lib-dynamodb": "^3.34.0",
77
+ "core-js": "^3.18.0",
78
+ "rimraf": "^3.0.2",
79
+ "short-uuid": "^4.2.0"
76
80
  },
77
81
  "peerDependencies": {
78
82
  "react": ">=16.8.6",
package/src/aws/db.ts ADDED
@@ -0,0 +1,244 @@
1
+ /**
2
+ * Partition key vs Composite primary key:
3
+ * Ref: https://aws.amazon.com/premiumsupport/knowledge-center/primary-key-dynamodb-table/
4
+ */
5
+
6
+ import { DynamoDBClient } from '@aws-sdk/client-dynamodb';
7
+ import {
8
+ DynamoDBDocumentClient,
9
+ GetCommand,
10
+ GetCommandInput,
11
+ PutCommand,
12
+ PutCommandInput,
13
+ UpdateCommand,
14
+ UpdateCommandInput,
15
+ QueryCommand,
16
+ QueryCommandInput,
17
+ ScanCommand,
18
+ ScanCommandInput,
19
+ } from '@aws-sdk/lib-dynamodb';
20
+ import short from 'short-uuid';
21
+
22
+ import { StringIndexable } from '../common/common.model';
23
+ import { CustomError } from '../common/error';
24
+
25
+ let dbDocClient: DynamoDBDocumentClient | null = null;
26
+
27
+ const DynamoDBError = (msg: string) => new CustomError(msg, { name: 'DynamoDBError' });
28
+
29
+ const initializationError = () => {
30
+ throw DynamoDBError('DynamoDB is possibly uninitialized!');
31
+ };
32
+
33
+ export const init = (region: string) => {
34
+ const dbClient = new DynamoDBClient({ region });
35
+
36
+ // Ref: https://docs.aws.amazon.com/AWSJavaScriptSDK/v3/latest/modules/_aws_sdk_lib_dynamodb.html#configuration
37
+ dbDocClient = DynamoDBDocumentClient.from(dbClient);
38
+ };
39
+
40
+ const writeItemForceHelper = async <T = any>(table: string, data: T, key: string, i: number): Promise<T | null> => {
41
+ if (!dbDocClient) return initializationError();
42
+ if (!table || !data) return null;
43
+
44
+ if (!(data as any)[key]) {
45
+ (data as any)[key] = short.uuid();
46
+ }
47
+ const cmdParams: PutCommandInput = { TableName: table, Item: data, ConditionExpression: `attribute_not_exists(${key})` };
48
+ const command = new PutCommand(cmdParams);
49
+ const numberOfAttempts = 3;
50
+
51
+ try {
52
+ await dbDocClient.send(command);
53
+ } catch (err: any) {
54
+ // console.error('PutCommandInput:', cmdParams);
55
+ // console.error(err);
56
+ if (err.name === 'ConditionalCheckFailedException') {
57
+ if (i < numberOfAttempts - 1) {
58
+ (data as any)[key] = short.uuid(); // new primary key
59
+ const ret: T | null = await writeItemForceHelper(table, data, key, i + 1);
60
+ return ret;
61
+ }
62
+ console.error('PutCommandInput:', cmdParams);
63
+ console.error('[ERROR] Maximum attempts overflow!');
64
+ }
65
+ return null;
66
+ }
67
+
68
+ return data;
69
+ };
70
+
71
+ export const writeItemForce = async <T = any>(table: string, data: T, key = 'id'): Promise<T | null> => {
72
+ return writeItemForceHelper<T>(table, data, key, 0);
73
+ };
74
+
75
+ export const writeItem = async (table: string, data: StringIndexable) => {
76
+ if (!dbDocClient) return initializationError();
77
+ if (!table || !data) return null;
78
+
79
+ const cmdParams: PutCommandInput = { TableName: table, Item: data };
80
+ const command = new PutCommand(cmdParams);
81
+
82
+ try {
83
+ await dbDocClient.send(command);
84
+ } catch (err) {
85
+ console.error('PutCommandInput:', cmdParams);
86
+ console.error(err);
87
+ return null;
88
+ // throw err;
89
+ }
90
+
91
+ return true;
92
+ };
93
+
94
+ export const updateItem = async (
95
+ table: string,
96
+ key: StringIndexable,
97
+ update: string,
98
+ attr: StringIndexable,
99
+ attrNames?: StringIndexable
100
+ ) => {
101
+ if (!dbDocClient) return initializationError();
102
+ if (!table || !key || !update || !attr) return null;
103
+
104
+ let cmdParams: UpdateCommandInput = {
105
+ TableName: table,
106
+ Key: key,
107
+ UpdateExpression: update,
108
+ ExpressionAttributeValues: attr,
109
+ };
110
+ if (attrNames) cmdParams = { ...cmdParams, ExpressionAttributeNames: attrNames };
111
+ const command = new UpdateCommand(cmdParams);
112
+
113
+ try {
114
+ await dbDocClient.send(command);
115
+ } catch (err) {
116
+ console.error('UpdateCommandInput:', cmdParams);
117
+ console.error(err);
118
+ return null;
119
+ // throw err;
120
+ }
121
+
122
+ return true;
123
+ };
124
+
125
+ export const readItem = async <T = any>(table: string, key: StringIndexable, projection = '') => {
126
+ if (!dbDocClient) return initializationError();
127
+ if (!table || !key) return null;
128
+
129
+ let contents: T | null = null;
130
+ let cmdParams: GetCommandInput = { TableName: table, Key: key };
131
+
132
+ // Ref: https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/Expressions.ProjectionExpressions.html
133
+ if (projection) cmdParams = { ...cmdParams, ProjectionExpression: projection };
134
+
135
+ const command = new GetCommand(cmdParams);
136
+
137
+ try {
138
+ const results = await dbDocClient.send(command);
139
+ const item = results.Item;
140
+
141
+ if (item) {
142
+ contents = item as T;
143
+ }
144
+ } catch (err) {
145
+ console.error('GetCommandInput:', cmdParams);
146
+ console.error(err);
147
+ // throw err;
148
+ }
149
+
150
+ return contents;
151
+ };
152
+
153
+ export const queryItems = async (
154
+ table: string,
155
+ indexName: string,
156
+ cond: string,
157
+ attr: StringIndexable,
158
+ projection = '',
159
+ desc = false
160
+ ) => {
161
+ if (!dbDocClient) return initializationError();
162
+ if (!table || !cond || !attr) return null;
163
+
164
+ let contents: StringIndexable[] | null = null;
165
+
166
+ // Ref: https://docs.aws.amazon.com/amazondynamodb/latest/APIReference/API_Query.html
167
+ // Ref: https://docs.aws.amazon.com/sdk-for-javascript/v3/developer-guide/dynamodb-example-query-scan.html
168
+ // Ref: https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/SQLtoNoSQL.Indexes.QueryAndScan.html#SQLtoNoSQL.Indexes.QueryAndScan.DynamoDB
169
+ let cmdParams: QueryCommandInput = {
170
+ TableName: table,
171
+ KeyConditionExpression: cond,
172
+ ExpressionAttributeValues: attr,
173
+ // FilterExpression: "contains (category_id, :cid)",
174
+ };
175
+
176
+ if (indexName) cmdParams = { ...cmdParams, IndexName: indexName };
177
+ if (projection) cmdParams = { ...cmdParams, ProjectionExpression: projection };
178
+ if (desc) cmdParams = { ...cmdParams, ScanIndexForward: false };
179
+
180
+ const command = new QueryCommand(cmdParams);
181
+
182
+ try {
183
+ const results = await dbDocClient.send(command);
184
+ const items = results.Items;
185
+
186
+ if (items) {
187
+ contents = items;
188
+ }
189
+ } catch (err) {
190
+ console.error('QueryCommandInput:', command.input);
191
+ console.error(err);
192
+ // throw err;
193
+ }
194
+
195
+ return contents;
196
+ };
197
+
198
+ export const scanItems = async (table: string, projection = '') => {
199
+ if (!dbDocClient) return initializationError();
200
+ if (!table) return null;
201
+
202
+ let contents: StringIndexable[] | null = null;
203
+
204
+ // Ref: https://docs.aws.amazon.com/sdk-for-javascript/v3/developer-guide/dynamodb-example-query-scan.html
205
+ let cmdParams: ScanCommandInput = {
206
+ TableName: table,
207
+ };
208
+
209
+ if (projection) cmdParams = { ...cmdParams, ProjectionExpression: projection };
210
+
211
+ const command = new ScanCommand(cmdParams);
212
+
213
+ try {
214
+ const results = await dbDocClient.send(command);
215
+ const items = results.Items;
216
+
217
+ if (items) {
218
+ contents = items;
219
+ }
220
+ } catch (err) {
221
+ console.error('ScanCommandInput:', cmdParams);
222
+ console.error(err);
223
+ // throw err;
224
+ }
225
+
226
+ return contents;
227
+ };
228
+
229
+ // ----------------
230
+
231
+ // await dbWriteItem('lesson_list', { id: 'id_001', title: 'My Lesson' });
232
+
233
+ // const contents = await dbReadItem('lesson_list', { id: 'id_001' });
234
+ // console.log(contents);
235
+
236
+ // await dbUpdateItem(
237
+ // 'lesson_list',
238
+ // { id: 'id_001' },
239
+ // 'set #a = :a, #b = :b',
240
+ // { ':a': 'abhi@raj.me', ':b': 'Abhishek Raj' },
241
+ // { '#a': 'email', '#b': 'name' }
242
+ // );
243
+
244
+ // ----------------
@@ -0,0 +1,14 @@
1
+ import * as dbAll from './db';
2
+
3
+ const { init: dbInit, ...db } = dbAll;
4
+
5
+ const init = (region: string) => {
6
+ if (!region) {
7
+ console.warn(`[WARN] AWS initialization error! Missing region: ${region}`);
8
+ return;
9
+ }
10
+
11
+ dbInit(region);
12
+ };
13
+
14
+ export { db, init }; // named exports
@@ -0,0 +1,3 @@
1
+ export interface StringIndexable<T = any> {
2
+ [key: string]: T;
3
+ }
package/src/index.ts CHANGED
@@ -1,5 +1,6 @@
1
1
  import * as fs from './fs';
2
+ import * as aws from './aws';
2
3
 
3
4
  // Ref: https://stackoverflow.com/a/41283945
4
- export { fs }; // named exports
5
- export default { fs }; // default export
5
+ export { fs, aws }; // named exports
6
+ export default { fs, aws }; // default export