@moicky/dynamodb 1.2.3 → 1.3.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.
@@ -1,4 +1,20 @@
1
1
  import { DynamoDBClient } from "@aws-sdk/client-dynamodb";
2
+ import * as ops from "../operations";
3
+ interface OperationArguments {
4
+ deleteItem?: Parameters<typeof ops.deleteItem>[1];
5
+ deleteItems?: Parameters<typeof ops.deleteItems>[1];
6
+ getItem?: Parameters<typeof ops.getItem>[1];
7
+ getItems?: Parameters<typeof ops.getItems>[1];
8
+ getAllItems?: Parameters<typeof ops.getAllItems>[0];
9
+ putItem?: Parameters<typeof ops.putItem>[1];
10
+ putItems?: Parameters<typeof ops.putItems>[1];
11
+ query?: Parameters<typeof ops.query>[2];
12
+ queryItems?: Parameters<typeof ops.queryItems>[2];
13
+ queryAllItems?: Parameters<typeof ops.queryAllItems>[2];
14
+ updateItem?: Parameters<typeof ops.updateItem>[2];
15
+ removeAttributes?: Parameters<typeof ops.removeAttributes>[2];
16
+ }
17
+ type Operation = keyof OperationArguments;
2
18
  declare interface KeySchema {
3
19
  hash: string;
4
20
  range?: string;
@@ -18,13 +34,18 @@ declare class DynamoDBConfig {
18
34
  getTableSchema(tableName?: string): KeySchema;
19
35
  getDefaultTableSchema(): KeySchema;
20
36
  validateSchema(schema: KeySchemaCollection): boolean;
37
+ initDefaults(newDefaults: OperationArguments): void;
38
+ withDefaults<T extends Operation>(args: OperationArguments[T], operation: T): OperationArguments[T];
21
39
  destroy(): void;
22
40
  }
23
41
  declare const config: DynamoDBConfig;
24
42
  export declare const client: DynamoDBClient;
43
+ export declare const initSchema: (schema: KeySchemaCollection) => KeySchemaCollection;
25
44
  export declare const getDefaultTable: () => string;
26
- export declare const getTableSchema: (tableName?: string) => KeySchema;
27
45
  export declare const getDefaultTableSchema: () => KeySchema;
28
- export declare const initSchema: (schema: KeySchemaCollection) => KeySchemaCollection;
46
+ export declare const validateSchema: (schema: KeySchemaCollection) => boolean;
47
+ export declare const getTableSchema: (tableName?: string) => KeySchema;
48
+ export declare const initDefaults: (newDefaults: OperationArguments) => void;
49
+ export declare const withDefaults: <T extends keyof OperationArguments>(args: OperationArguments[T], operation: T) => OperationArguments[T];
29
50
  export declare const destroy: () => void;
30
51
  export default config;
@@ -1,22 +1,24 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.destroy = exports.initSchema = exports.getDefaultTableSchema = exports.getTableSchema = exports.getDefaultTable = exports.client = void 0;
3
+ exports.destroy = exports.withDefaults = exports.initDefaults = exports.getTableSchema = exports.validateSchema = exports.getDefaultTableSchema = exports.getDefaultTable = exports.initSchema = exports.client = void 0;
4
4
  const client_dynamodb_1 = require("@aws-sdk/client-dynamodb");
5
5
  class DynamoDBConfig {
6
6
  client;
7
7
  tablesSchema = {};
8
8
  #initialized = false;
9
+ #defaults = {};
9
10
  constructor({ region } = {}) {
10
11
  this.client = new client_dynamodb_1.DynamoDBClient({
11
12
  region: region || process.env.AWS_REGION || "eu-central-1",
12
13
  });
13
14
  const defaultTable = process.env.DYNAMODB_TABLE;
14
15
  if (defaultTable) {
15
- this.tablesSchema[defaultTable] = {
16
- hash: "PK",
17
- range: "SK",
18
- };
19
- this.#initialized = true;
16
+ this.initSchema({
17
+ [defaultTable]: {
18
+ hash: "PK",
19
+ range: "SK",
20
+ },
21
+ });
20
22
  }
21
23
  }
22
24
  initSchema(schema) {
@@ -38,8 +40,7 @@ class DynamoDBConfig {
38
40
  if (!this.#initialized) {
39
41
  throw new Error("Schema not initialized");
40
42
  }
41
- const table = Object.keys(this.tablesSchema)[0];
42
- return table;
43
+ return Object.keys(this.tablesSchema)[0];
43
44
  }
44
45
  getTableSchema(tableName) {
45
46
  if (!this.#initialized) {
@@ -64,15 +65,30 @@ class DynamoDBConfig {
64
65
  });
65
66
  return true;
66
67
  }
68
+ initDefaults(newDefaults) {
69
+ this.#defaults = { ...newDefaults };
70
+ }
71
+ withDefaults(args, operation) {
72
+ return {
73
+ ...this.#defaults[operation],
74
+ ...args,
75
+ };
76
+ }
67
77
  destroy() {
68
78
  this.client.destroy();
69
79
  }
70
80
  }
71
81
  const config = new DynamoDBConfig();
82
+ const bind = (fn) => {
83
+ return fn.bind(config);
84
+ };
72
85
  exports.client = config.client;
73
- exports.getDefaultTable = config.getDefaultTable.bind(config);
74
- exports.getTableSchema = config.getTableSchema.bind(config);
75
- exports.getDefaultTableSchema = config.getDefaultTableSchema.bind(config);
76
- exports.initSchema = config.initSchema.bind(config);
77
- exports.destroy = config.destroy.bind(config);
86
+ exports.initSchema = bind(config.initSchema);
87
+ exports.getDefaultTable = bind(config.getDefaultTable);
88
+ exports.getDefaultTableSchema = bind(config.getDefaultTableSchema);
89
+ exports.validateSchema = bind(config.validateSchema);
90
+ exports.getTableSchema = bind(config.getTableSchema);
91
+ exports.initDefaults = bind(config.initDefaults);
92
+ exports.withDefaults = bind(config.withDefaults);
93
+ exports.destroy = bind(config.destroy);
78
94
  exports.default = config;
@@ -5,6 +5,3 @@ export declare function splitEvery<T>(items: T[], limit?: number): T[][];
5
5
  export declare function getAttributeValues(key: any, attributesToGet?: string[]): Record<string, any>;
6
6
  export declare function getAttributeNames(key: any, attributesToGet?: string[]): Record<string, string>;
7
7
  export declare function getAttributesFromExpression(expression: string, prefix?: string): string[];
8
- export declare function handleAliases(aliases: {
9
- [attr: string]: string[];
10
- }, args?: Record<string, any>): Record<string, any>;
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.handleAliases = exports.getAttributesFromExpression = exports.getAttributeNames = exports.getAttributeValues = exports.splitEvery = exports.stripKey = void 0;
3
+ exports.getAttributesFromExpression = exports.getAttributeNames = exports.getAttributeValues = exports.splitEvery = exports.stripKey = void 0;
4
4
  const util_dynamodb_1 = require("@aws-sdk/util-dynamodb");
5
5
  const client_1 = require("../lib/client");
6
6
  // Since dynamo only accepts key atrtributes which are described in table schema
@@ -42,15 +42,3 @@ function getAttributesFromExpression(expression, prefix = "#") {
42
42
  ?.map((attr) => attr.slice(1)) || []);
43
43
  }
44
44
  exports.getAttributesFromExpression = getAttributesFromExpression;
45
- function handleAliases(aliases, args = {}) {
46
- Object.keys(aliases).forEach((key) => {
47
- aliases[key].forEach((alias) => {
48
- if (args[alias]) {
49
- args[key] = args[alias];
50
- delete args[alias];
51
- }
52
- });
53
- });
54
- return args;
55
- }
56
- exports.handleAliases = handleAliases;
@@ -7,12 +7,13 @@ const helpers_1 = require("../lib/helpers");
7
7
  async function deleteItem(key, args = {}) {
8
8
  return client_1.client.send(new client_dynamodb_1.DeleteItemCommand({
9
9
  Key: (0, helpers_1.stripKey)(key, args),
10
- ...args,
10
+ ...(0, client_1.withDefaults)(args, "deleteItem"),
11
11
  TableName: args?.TableName || (0, client_1.getDefaultTable)(),
12
12
  }));
13
13
  }
14
14
  exports.deleteItem = deleteItem;
15
15
  async function deleteItems(keys, args = {}, retry = 0) {
16
+ args = (0, client_1.withDefaults)(args, "deleteItems");
16
17
  const uniqueKeys = Object.values(keys.reduce((acc, key) => {
17
18
  const strippedKey = (0, helpers_1.stripKey)(key, args);
18
19
  const keyString = JSON.stringify(strippedKey);
@@ -6,6 +6,7 @@ const util_dynamodb_1 = require("@aws-sdk/util-dynamodb");
6
6
  const client_1 = require("../lib/client");
7
7
  const helpers_1 = require("../lib/helpers");
8
8
  async function getItem(key, args = {}) {
9
+ args = (0, client_1.withDefaults)(args, "getItem");
9
10
  return client_1.client
10
11
  .send(new client_dynamodb_1.GetItemCommand({
11
12
  Key: (0, helpers_1.stripKey)(key, args),
@@ -16,6 +17,7 @@ async function getItem(key, args = {}) {
16
17
  }
17
18
  exports.getItem = getItem;
18
19
  async function getItems(keys, args = {}, retry = 0) {
20
+ args = (0, client_1.withDefaults)(args, "getItems");
19
21
  // creates batches of 100 items each and performs batchGet on every batch.
20
22
  // also retries up to 3 times if there are unprocessed items (due to size limit of 16MB)
21
23
  // returns items in same order as keys (not sorted by default when using batchGet)
@@ -69,6 +71,7 @@ async function getItems(keys, args = {}, retry = 0) {
69
71
  }
70
72
  exports.getItems = getItems;
71
73
  async function getAllItems(args = {}) {
74
+ args = (0, client_1.withDefaults)(args, "getAllItems");
72
75
  return client_1.client
73
76
  .send(new client_dynamodb_1.ScanCommand({
74
77
  ...args,
@@ -6,6 +6,7 @@ const util_dynamodb_1 = require("@aws-sdk/util-dynamodb");
6
6
  const client_1 = require("../lib/client");
7
7
  const helpers_1 = require("../lib/helpers");
8
8
  async function putItem(data, args = {}) {
9
+ args = (0, client_1.withDefaults)(args, "putItem");
9
10
  if (!Object.keys(data).includes("createdAt")) {
10
11
  data.createdAt = Date.now();
11
12
  }
@@ -19,6 +20,7 @@ async function putItem(data, args = {}) {
19
20
  }
20
21
  exports.putItem = putItem;
21
22
  async function putItems(items, args = {}) {
23
+ args = (0, client_1.withDefaults)(args, "putItems");
22
24
  return new Promise(async (resolve, reject) => {
23
25
  const now = Date.now();
24
26
  const batches = (0, helpers_1.splitEvery)(items.map((item) => ({
@@ -1,9 +1,4 @@
1
- import { QueryCommandInput as _QueryCommandInput, QueryCommandOutput } from "@aws-sdk/client-dynamodb";
2
- type QueryCommandInput = {
3
- GSI: _QueryCommandInput["IndexName"];
4
- Index: _QueryCommandInput["IndexName"];
5
- } & _QueryCommandInput;
1
+ import { QueryCommandInput, QueryCommandOutput } from "@aws-sdk/client-dynamodb";
6
2
  export declare function query(keyCondition: string, key: any, args?: Partial<QueryCommandInput>): Promise<QueryCommandOutput>;
7
3
  export declare function queryItems(keyCondition: string, key: any, args?: Partial<QueryCommandInput>): Promise<Record<string, any>[]>;
8
4
  export declare function queryAllItems(keyCondition: string, key: any, args?: Partial<QueryCommandInput>): Promise<Record<string, any>[]>;
9
- export {};
@@ -5,11 +5,7 @@ const client_dynamodb_1 = require("@aws-sdk/client-dynamodb");
5
5
  const util_dynamodb_1 = require("@aws-sdk/util-dynamodb");
6
6
  const client_1 = require("../lib/client");
7
7
  const helpers_1 = require("../lib/helpers");
8
- const aliases = {
9
- IndexName: ["GSI", "Index"],
10
- };
11
- async function query(keyCondition, key, args = {}) {
12
- args = (0, helpers_1.handleAliases)(aliases, args);
8
+ async function _query(keyCondition, key, args = {}) {
13
9
  return client_1.client.send(new client_dynamodb_1.QueryCommand({
14
10
  KeyConditionExpression: keyCondition,
15
11
  ExpressionAttributeValues: (0, helpers_1.getAttributeValues)(key, [
@@ -24,16 +20,23 @@ async function query(keyCondition, key, args = {}) {
24
20
  TableName: args?.TableName || (0, client_1.getDefaultTable)(),
25
21
  }));
26
22
  }
23
+ async function query(keyCondition, key, args) {
24
+ return _query(keyCondition, key, (0, client_1.withDefaults)(args, "query"));
25
+ }
27
26
  exports.query = query;
28
27
  async function queryItems(keyCondition, key, args = {}) {
29
- return query(keyCondition, key, args).then((res) => (res?.Items || []).map((item) => item && (0, util_dynamodb_1.unmarshall)(item)));
28
+ args = (0, client_1.withDefaults)(args, "queryItems");
29
+ return _query(keyCondition, key, args).then((res) => (res?.Items || [])
30
+ .map((item) => item && (0, util_dynamodb_1.unmarshall)(item))
31
+ .filter((item) => item));
30
32
  }
31
33
  exports.queryItems = queryItems;
32
34
  async function queryAllItems(keyCondition, key, args = {}) {
33
- let data = await query(keyCondition, key, args);
35
+ args = (0, client_1.withDefaults)(args, "queryAllItems");
36
+ let data = await _query(keyCondition, key, args);
34
37
  while (data.LastEvaluatedKey) {
35
38
  if (data.LastEvaluatedKey) {
36
- let helper = await query(keyCondition, key, {
39
+ let helper = await _query(keyCondition, key, {
37
40
  ...args,
38
41
  ExclusiveStartKey: data.LastEvaluatedKey,
39
42
  });
@@ -43,6 +46,8 @@ async function queryAllItems(keyCondition, key, args = {}) {
43
46
  data && (data.LastEvaluatedKey = helper.LastEvaluatedKey);
44
47
  }
45
48
  }
46
- return (data?.Items || []).map((item) => item && (0, util_dynamodb_1.unmarshall)(item));
49
+ return (data?.Items || [])
50
+ .map((item) => item && (0, util_dynamodb_1.unmarshall)(item))
51
+ .filter((item) => item);
47
52
  }
48
53
  exports.queryAllItems = queryAllItems;
@@ -6,6 +6,7 @@ const util_dynamodb_1 = require("@aws-sdk/util-dynamodb");
6
6
  const client_1 = require("../lib/client");
7
7
  const helpers_1 = require("../lib/helpers");
8
8
  async function updateItem(key, data, args = {}) {
9
+ args = (0, client_1.withDefaults)(args, "updateItem");
9
10
  if (!Object.keys(data).includes("updatedAt")) {
10
11
  data.updatedAt = Date.now();
11
12
  }
@@ -32,6 +33,7 @@ async function updateItem(key, data, args = {}) {
32
33
  }
33
34
  exports.updateItem = updateItem;
34
35
  async function removeAttributes(key, attributes, args = {}) {
36
+ args = (0, client_1.withDefaults)(args, "removeAttributes");
35
37
  const UpdateExpression = "REMOVE " + attributes.map((att) => `#${att}`).join(", ");
36
38
  return client_1.client.send(new client_dynamodb_1.UpdateItemCommand({
37
39
  Key: (0, helpers_1.stripKey)(key, args),
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@moicky/dynamodb",
3
- "version": "1.2.3",
3
+ "version": "1.3.0",
4
4
  "main": "dist/index.js",
5
5
  "types": "dist/index.d.ts",
6
6
  "description": "Contains a collection of convenience functions for working with AWS DynamoDB",
@@ -24,14 +24,15 @@
24
24
  },
25
25
  "dependencies": {
26
26
  "@aws-sdk/client-dynamodb": "^3.338.0",
27
- "@aws-sdk/util-dynamodb": "^3.338.0"
27
+ "@aws-sdk/util-dynamodb": "^3.338.0",
28
+ "aws-crt": "^1.15.20"
28
29
  },
29
30
  "devDependencies": {
30
31
  "@types/jest": "^29.5.1",
31
32
  "@types/node": "^20.2.4",
32
33
  "dotenv": "^16.0.3",
33
- "typescript": "^5.0.4",
34
- "jest": "^29.5.0"
34
+ "jest": "^29.5.0",
35
+ "typescript": "^5.0.4"
35
36
  },
36
37
  "keywords": [
37
38
  "dynamodb-helpers",