@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.
- package/dist/cjs/index.js +1 -1
- package/dist/cjs/index.js.map +1 -1
- package/dist/esm/index.js +1 -1
- package/dist/esm/index.js.map +1 -1
- package/dist/types/aws/db.d.ts +13 -0
- package/dist/types/aws/db.d.ts.map +1 -0
- package/dist/types/aws/index.d.ts +11 -0
- package/dist/types/aws/index.d.ts.map +1 -0
- package/dist/types/common/common.model.d.ts +4 -0
- package/dist/types/common/common.model.d.ts.map +1 -0
- package/dist/types/index.d.ts +3 -1
- package/dist/types/index.d.ts.map +1 -1
- package/package.json +9 -5
- package/src/aws/db.ts +244 -0
- package/src/aws/index.ts +14 -0
- package/src/common/common.model.ts +3 -0
- package/src/index.ts +3 -2
|
@@ -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 @@
|
|
|
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"}
|
package/dist/types/index.d.ts
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,MAAM,CAAC;
|
|
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.
|
|
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": ">=
|
|
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
|
-
"
|
|
75
|
-
"
|
|
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
|
+
// ----------------
|
package/src/aws/index.ts
ADDED
|
@@ -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
|
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
|