betterddb 0.6.1 → 0.6.4

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 (48) hide show
  1. package/.eslintrc.cjs +41 -0
  2. package/lib/betterddb.js +26 -18
  3. package/lib/builders/batch-get-builder.js +6 -2
  4. package/lib/builders/create-builder.js +14 -6
  5. package/lib/builders/delete-builder.js +8 -5
  6. package/lib/builders/get-builder.js +11 -6
  7. package/lib/builders/query-builder.js +38 -31
  8. package/lib/builders/scan-builder.js +17 -11
  9. package/lib/builders/update-builder.js +21 -16
  10. package/lib/operator.js +10 -10
  11. package/lib/{betterddb.d.ts → types/betterddb.d.ts} +10 -9
  12. package/lib/types/betterddb.d.ts.map +1 -0
  13. package/lib/{builders → types/builders}/batch-get-builder.d.ts +2 -1
  14. package/lib/types/builders/batch-get-builder.d.ts.map +1 -0
  15. package/lib/{builders → types/builders}/create-builder.d.ts +3 -2
  16. package/lib/types/builders/create-builder.d.ts.map +1 -0
  17. package/lib/{builders → types/builders}/delete-builder.d.ts +3 -2
  18. package/lib/types/builders/delete-builder.d.ts.map +1 -0
  19. package/lib/{builders → types/builders}/get-builder.d.ts +3 -2
  20. package/lib/types/builders/get-builder.d.ts.map +1 -0
  21. package/lib/{builders → types/builders}/query-builder.d.ts +4 -3
  22. package/lib/types/builders/query-builder.d.ts.map +1 -0
  23. package/lib/{builders → types/builders}/scan-builder.d.ts +4 -3
  24. package/lib/types/builders/scan-builder.d.ts.map +1 -0
  25. package/lib/{builders → types/builders}/update-builder.d.ts +3 -2
  26. package/lib/types/builders/update-builder.d.ts.map +1 -0
  27. package/lib/types/index.d.ts +2 -0
  28. package/lib/types/index.d.ts.map +1 -0
  29. package/lib/types/operator.d.ts +3 -0
  30. package/lib/types/operator.d.ts.map +1 -0
  31. package/lib/types/{paginated-result.d.ts → types/paginated-result.d.ts} +1 -0
  32. package/lib/types/types/paginated-result.d.ts.map +1 -0
  33. package/package.json +15 -5
  34. package/prettier.config.js +6 -0
  35. package/src/betterddb.ts +39 -35
  36. package/src/builders/batch-get-builder.ts +11 -6
  37. package/src/builders/create-builder.ts +42 -27
  38. package/src/builders/delete-builder.ts +28 -17
  39. package/src/builders/get-builder.ts +26 -19
  40. package/src/builders/query-builder.ts +64 -44
  41. package/src/builders/scan-builder.ts +18 -14
  42. package/src/builders/update-builder.ts +49 -28
  43. package/src/index.ts +1 -1
  44. package/src/operator.ts +21 -21
  45. package/src/types/paginated-result.ts +1 -1
  46. package/tsconfig.json +25 -11
  47. package/lib/index.d.ts +0 -1
  48. package/lib/operator.d.ts +0 -2
package/.eslintrc.cjs ADDED
@@ -0,0 +1,41 @@
1
+ /** @type {import("eslint").Linter.Config} */
2
+ const config = {
3
+ "parser": "@typescript-eslint/parser",
4
+ "parserOptions": {
5
+ "project": true
6
+ },
7
+ "plugins": [
8
+ "@typescript-eslint"
9
+ ],
10
+ "extends": [
11
+ "plugin:@typescript-eslint/recommended-type-checked",
12
+ "plugin:@typescript-eslint/stylistic-type-checked"
13
+ ],
14
+ "rules": {
15
+ "@typescript-eslint/array-type": "off",
16
+ "@typescript-eslint/consistent-type-definitions": "off",
17
+ "@typescript-eslint/consistent-type-imports": [
18
+ "warn",
19
+ {
20
+ "prefer": "type-imports",
21
+ "fixStyle": "inline-type-imports"
22
+ }
23
+ ],
24
+ "@typescript-eslint/no-unused-vars": [
25
+ "warn",
26
+ {
27
+ "argsIgnorePattern": "^_"
28
+ }
29
+ ],
30
+ "@typescript-eslint/require-await": "off",
31
+ "@typescript-eslint/no-misused-promises": [
32
+ "error",
33
+ {
34
+ "checksVoidReturn": {
35
+ "attributes": false
36
+ }
37
+ }
38
+ ]
39
+ }
40
+ }
41
+ module.exports = config;
package/lib/betterddb.js CHANGED
@@ -12,15 +12,21 @@ const batch_get_builder_1 = require("./builders/batch-get-builder");
12
12
  * BetterDDB is a definition-based DynamoDB wrapper library.
13
13
  */
14
14
  class BetterDDB {
15
+ schema;
16
+ tableName;
17
+ entityType;
18
+ client;
19
+ keys;
20
+ timestamps;
21
+ counter;
15
22
  constructor(options) {
16
- var _a, _b, _c;
17
23
  this.schema = options.schema;
18
24
  this.tableName = options.tableName;
19
- this.entityType = (_a = options.entityType) === null || _a === void 0 ? void 0 : _a.toUpperCase();
25
+ this.entityType = options.entityType?.toUpperCase();
20
26
  this.keys = options.keys;
21
27
  this.client = options.client;
22
- this.timestamps = (_b = options.timestamps) !== null && _b !== void 0 ? _b : false;
23
- this.counter = (_c = options.counter) !== null && _c !== void 0 ? _c : false;
28
+ this.timestamps = options.timestamps ?? false;
29
+ this.counter = options.counter ?? false;
24
30
  }
25
31
  getCounter() {
26
32
  return this.counter;
@@ -45,7 +51,9 @@ class BetterDDB {
45
51
  }
46
52
  // Helper: Retrieve the key value from a KeyDefinition.
47
53
  getKeyValue(def, rawKey) {
48
- if (typeof def === 'string' || typeof def === 'number' || typeof def === 'symbol') {
54
+ if (typeof def === "string" ||
55
+ typeof def === "number" ||
56
+ typeof def === "symbol") {
49
57
  return String(rawKey[def]);
50
58
  }
51
59
  else {
@@ -60,18 +68,18 @@ class BetterDDB {
60
68
  // For primary (partition) key:
61
69
  const pkConfig = this.keys.primary;
62
70
  keyObj[pkConfig.name] =
63
- (typeof pkConfig.definition === 'string' ||
64
- typeof pkConfig.definition === 'number' ||
65
- typeof pkConfig.definition === 'symbol')
71
+ typeof pkConfig.definition === "string" ||
72
+ typeof pkConfig.definition === "number" ||
73
+ typeof pkConfig.definition === "symbol"
66
74
  ? String(rawKey[pkConfig.definition])
67
75
  : pkConfig.definition.build(rawKey);
68
76
  // For sort key, if defined:
69
77
  if (this.keys.sort) {
70
78
  const skConfig = this.keys.sort;
71
79
  keyObj[skConfig.name] =
72
- (typeof skConfig.definition === 'string' ||
73
- typeof skConfig.definition === 'number' ||
74
- typeof skConfig.definition === 'symbol')
80
+ typeof skConfig.definition === "string" ||
81
+ typeof skConfig.definition === "number" ||
82
+ typeof skConfig.definition === "symbol"
75
83
  ? String(rawKey[skConfig.definition])
76
84
  : skConfig.definition.build(rawKey);
77
85
  }
@@ -88,18 +96,18 @@ class BetterDDB {
88
96
  // Compute primary index attribute.
89
97
  const primaryConfig = gsiConfig.primary;
90
98
  indexAttributes[primaryConfig.name] =
91
- (typeof primaryConfig.definition === 'string' ||
92
- typeof primaryConfig.definition === 'number' ||
93
- typeof primaryConfig.definition === 'symbol')
99
+ typeof primaryConfig.definition === "string" ||
100
+ typeof primaryConfig.definition === "number" ||
101
+ typeof primaryConfig.definition === "symbol"
94
102
  ? String(rawItem[primaryConfig.definition])
95
103
  : primaryConfig.definition.build(rawItem);
96
104
  // Compute sort index attribute if provided.
97
- if (gsiConfig.sort) {
105
+ if (gsiConfig?.sort) {
98
106
  const sortConfig = gsiConfig.sort;
99
107
  indexAttributes[sortConfig.name] =
100
- (typeof sortConfig.definition === 'string' ||
101
- typeof sortConfig.definition === 'number' ||
102
- typeof sortConfig.definition === 'symbol')
108
+ typeof sortConfig.definition === "string" ||
109
+ typeof sortConfig.definition === "number" ||
110
+ typeof sortConfig.definition === "symbol"
103
111
  ? String(rawItem[sortConfig.definition])
104
112
  : sortConfig.definition.build(rawItem);
105
113
  }
@@ -3,6 +3,8 @@ Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.BatchGetBuilder = void 0;
4
4
  const lib_dynamodb_1 = require("@aws-sdk/lib-dynamodb");
5
5
  class BatchGetBuilder {
6
+ parent;
7
+ keys;
6
8
  /**
7
9
  * @param parent - The BetterDDB instance for the table.
8
10
  * @param keys - An array of partial keys for the items you wish to retrieve.
@@ -30,7 +32,7 @@ class BatchGetBuilder {
30
32
  });
31
33
  const tableName = this.parent.getTableName();
32
34
  // Build an array of keys using the parent's key builder.
33
- const keysArray = deduplicatedKeys.map(key => this.parent.buildKey(key));
35
+ const keysArray = deduplicatedKeys.map((key) => this.parent.buildKey(key));
34
36
  // Construct the BatchGet parameters.
35
37
  const params = {
36
38
  RequestItems: {
@@ -39,7 +41,9 @@ class BatchGetBuilder {
39
41
  },
40
42
  },
41
43
  };
42
- const result = await this.parent.getClient().send(new lib_dynamodb_1.BatchGetCommand(params));
44
+ const result = await this.parent
45
+ .getClient()
46
+ .send(new lib_dynamodb_1.BatchGetCommand(params));
43
47
  const responses = result.Responses ? result.Responses[tableName] : [];
44
48
  if (!responses) {
45
49
  return [];
@@ -3,10 +3,12 @@ Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.CreateBuilder = void 0;
4
4
  const lib_dynamodb_1 = require("@aws-sdk/lib-dynamodb");
5
5
  class CreateBuilder {
6
+ parent;
7
+ item;
8
+ extraTransactItems = [];
6
9
  constructor(parent, item) {
7
10
  this.parent = parent;
8
11
  this.item = item;
9
- this.extraTransactItems = [];
10
12
  }
11
13
  async execute() {
12
14
  const validated = this.parent.getSchema().parse(this.item);
@@ -16,17 +18,20 @@ class CreateBuilder {
16
18
  // Combine with extra transaction items.
17
19
  const allItems = [...this.extraTransactItems, myTransactItem];
18
20
  await this.parent.getClient().send(new lib_dynamodb_1.TransactWriteCommand({
19
- TransactItems: allItems
21
+ TransactItems: allItems,
20
22
  }));
21
23
  // After transaction, retrieve the updated item.
22
24
  const result = await this.parent.get(this.item).execute();
23
25
  if (result === null) {
24
- throw new Error('Item not found after transaction create');
26
+ throw new Error("Item not found after transaction create");
25
27
  }
26
28
  return result;
27
29
  }
28
30
  else {
29
- let finalItem = { ...this.item, entityType: this.parent.getEntityType() };
31
+ let finalItem = {
32
+ ...this.item,
33
+ entityType: this.parent.getEntityType(),
34
+ };
30
35
  if (this.parent.getTimestamps()) {
31
36
  const now = new Date().toISOString();
32
37
  finalItem = { ...finalItem, createdAt: now, updatedAt: now };
@@ -39,7 +44,7 @@ class CreateBuilder {
39
44
  finalItem = { ...finalItem, ...indexAttributes };
40
45
  await this.parent.getClient().send(new lib_dynamodb_1.PutCommand({
41
46
  TableName: this.parent.getTableName(),
42
- Item: finalItem
47
+ Item: finalItem,
43
48
  }));
44
49
  return validated;
45
50
  }
@@ -55,7 +60,10 @@ class CreateBuilder {
55
60
  }
56
61
  toTransactPut() {
57
62
  const validated = this.parent.getSchema().parse(this.item);
58
- let finalItem = { ...this.item, entityType: this.parent.getEntityType() };
63
+ let finalItem = {
64
+ ...this.item,
65
+ entityType: this.parent.getEntityType(),
66
+ };
59
67
  if (this.parent.getTimestamps()) {
60
68
  const now = new Date().toISOString();
61
69
  finalItem = { ...finalItem, createdAt: now, updatedAt: now };
@@ -3,10 +3,13 @@ Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.DeleteBuilder = void 0;
4
4
  const lib_dynamodb_1 = require("@aws-sdk/lib-dynamodb");
5
5
  class DeleteBuilder {
6
+ parent;
7
+ key;
8
+ condition;
9
+ extraTransactItems = [];
6
10
  constructor(parent, key) {
7
11
  this.parent = parent;
8
12
  this.key = key;
9
- this.extraTransactItems = [];
10
13
  }
11
14
  /**
12
15
  * Specify a condition expression for the delete operation.
@@ -28,18 +31,18 @@ class DeleteBuilder {
28
31
  // Combine with extra transaction items.
29
32
  const allItems = [...this.extraTransactItems, myTransactItem];
30
33
  await this.parent.getClient().send(new lib_dynamodb_1.TransactWriteCommand({
31
- TransactItems: allItems
34
+ TransactItems: allItems,
32
35
  }));
33
36
  // After transaction, retrieve the updated item.
34
37
  const result = await this.parent.get(this.key).execute();
35
38
  if (result === null) {
36
- throw new Error('Item not found after transaction delete');
39
+ throw new Error("Item not found after transaction delete");
37
40
  }
38
41
  }
39
42
  else {
40
43
  const params = {
41
44
  TableName: this.parent.getTableName(),
42
- Key: this.parent.buildKey(this.key)
45
+ Key: this.parent.buildKey(this.key),
43
46
  };
44
47
  if (this.condition) {
45
48
  params.ConditionExpression = this.condition.expression;
@@ -60,7 +63,7 @@ class DeleteBuilder {
60
63
  toTransactDelete() {
61
64
  const deleteItem = {
62
65
  TableName: this.parent.getTableName(),
63
- Key: this.parent.buildKey(this.key)
66
+ Key: this.parent.buildKey(this.key),
64
67
  };
65
68
  if (this.condition) {
66
69
  deleteItem.ConditionExpression = this.condition.expression;
@@ -3,17 +3,22 @@ Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.GetBuilder = void 0;
4
4
  const lib_dynamodb_1 = require("@aws-sdk/lib-dynamodb");
5
5
  class GetBuilder {
6
+ parent;
7
+ key;
8
+ projectionExpression;
9
+ expressionAttributeNames = {};
10
+ extraTransactItems = [];
6
11
  constructor(parent, key) {
7
12
  this.parent = parent;
8
13
  this.key = key;
9
- this.expressionAttributeNames = {};
10
- this.extraTransactItems = [];
11
14
  }
12
15
  /**
13
16
  * Specify a projection by providing an array of attribute names.
14
17
  */
15
18
  withProjection(attributes) {
16
- this.projectionExpression = attributes.map(attr => `#${String(attr)}`).join(', ');
19
+ this.projectionExpression = attributes
20
+ .map((attr) => `#${String(attr)}`)
21
+ .join(", ");
17
22
  for (const attr of attributes) {
18
23
  this.expressionAttributeNames[`#${String(attr)}`] = String(attr);
19
24
  }
@@ -26,7 +31,7 @@ class GetBuilder {
26
31
  // Combine with extra transaction items.
27
32
  const allItems = [...this.extraTransactItems, myTransactItem];
28
33
  await this.parent.getClient().send(new lib_dynamodb_1.TransactGetCommand({
29
- TransactItems: allItems
34
+ TransactItems: allItems,
30
35
  }));
31
36
  // After transaction, retrieve the updated item.
32
37
  const result = await this.parent.get(this.key).execute();
@@ -35,7 +40,7 @@ class GetBuilder {
35
40
  else {
36
41
  const params = {
37
42
  TableName: this.parent.getTableName(),
38
- Key: this.parent.buildKey(this.key)
43
+ Key: this.parent.buildKey(this.key),
39
44
  };
40
45
  if (this.projectionExpression) {
41
46
  params.ProjectionExpression = this.projectionExpression;
@@ -59,7 +64,7 @@ class GetBuilder {
59
64
  toTransactGet() {
60
65
  const getItem = {
61
66
  TableName: this.parent.getTableName(),
62
- Key: this.parent.buildKey(this.key)
67
+ Key: this.parent.buildKey(this.key),
63
68
  };
64
69
  if (this.projectionExpression) {
65
70
  getItem.ProjectionExpression = this.projectionExpression;
@@ -4,32 +4,37 @@ exports.QueryBuilder = void 0;
4
4
  const lib_dynamodb_1 = require("@aws-sdk/lib-dynamodb");
5
5
  const operator_1 = require("../operator");
6
6
  class QueryBuilder {
7
+ parent;
8
+ key;
9
+ keyConditions = [];
10
+ filterConditions = [];
11
+ expressionAttributeNames = {};
12
+ expressionAttributeValues = {};
13
+ index;
14
+ limit;
15
+ lastKey;
16
+ ascending = true;
7
17
  constructor(parent, key) {
8
18
  this.parent = parent;
9
19
  this.key = key;
10
- this.keyConditions = [];
11
- this.filterConditions = [];
12
- this.expressionAttributeNames = {};
13
- this.expressionAttributeValues = {};
14
- this.ascending = true;
15
20
  const keys = this.parent.getKeys();
16
21
  let pkName = keys.primary.name;
17
22
  let builtKey = this.parent.buildKey(this.key);
18
- this.expressionAttributeNames['#pk'] = pkName;
19
- this.expressionAttributeValues[':pk_value'] = builtKey[pkName];
23
+ this.expressionAttributeNames["#pk"] = pkName;
24
+ this.expressionAttributeValues[":pk_value"] = builtKey[pkName];
20
25
  }
21
26
  usingIndex(indexName) {
22
27
  if (!this.parent.getKeys().gsis) {
23
- throw new Error('No global secondary indexes defined for this table');
28
+ throw new Error("No global secondary indexes defined for this table");
24
29
  }
25
30
  if (!(indexName in this.parent.getKeys().gsis)) {
26
- throw new Error('index does not exist');
31
+ throw new Error("index does not exist");
27
32
  }
28
33
  this.index = this.parent.getKeys().gsis[indexName];
29
34
  const pkName = this.index.primary.name;
30
35
  const builtKey = this.parent.buildIndexes(this.key);
31
- this.expressionAttributeNames['#pk'] = pkName;
32
- this.expressionAttributeValues[':pk_value'] = builtKey[pkName];
36
+ this.expressionAttributeNames["#pk"] = pkName;
37
+ this.expressionAttributeValues[":pk_value"] = builtKey[pkName];
33
38
  return this;
34
39
  }
35
40
  sortAscending() {
@@ -41,25 +46,24 @@ class QueryBuilder {
41
46
  return this;
42
47
  }
43
48
  where(operator, values) {
44
- var _a, _b;
45
49
  const keys = this.parent.getKeys();
46
50
  // Determine the sort key name from either the index or the primary keys.
47
- const sortKeyName = this.index ? (_a = this.index.sort) === null || _a === void 0 ? void 0 : _a.name : (_b = keys.sort) === null || _b === void 0 ? void 0 : _b.name;
51
+ const sortKeyName = this.index ? this.index.sort?.name : keys.sort?.name;
48
52
  if (!sortKeyName) {
49
- throw new Error('Sort key is not defined for this table/index.');
53
+ throw new Error("Sort key is not defined for this table/index.");
50
54
  }
51
- const nameKey = '#sk';
55
+ const nameKey = "#sk";
52
56
  this.expressionAttributeNames[nameKey] = sortKeyName;
53
57
  // Enforce that a complex sort key requires an object input.
54
- if (typeof values !== 'object' || values === null) {
58
+ if (typeof values !== "object" || values === null) {
55
59
  throw new Error(`For complex sort keys, please provide an object with all necessary properties.`);
56
60
  }
57
- if (operator === 'between') {
61
+ if (operator === "between") {
58
62
  if (!Array.isArray(values) || values.length !== 2) {
59
63
  throw new Error(`For 'between' operator, values must be a tuple of two objects`);
60
64
  }
61
- const valueKeyStart = ':sk_start';
62
- const valueKeyEnd = ':sk_end';
65
+ const valueKeyStart = ":sk_start";
66
+ const valueKeyEnd = ":sk_end";
63
67
  // Use the key definition's build function to build the key from the full object.
64
68
  this.expressionAttributeValues[valueKeyStart] = this.index
65
69
  ? this.parent.buildIndexes(values[0])[sortKeyName]
@@ -69,8 +73,8 @@ class QueryBuilder {
69
73
  : this.parent.buildKey(values[1])[sortKeyName];
70
74
  this.keyConditions.push(`${nameKey} BETWEEN ${valueKeyStart} AND ${valueKeyEnd}`);
71
75
  }
72
- else if (operator === 'begins_with') {
73
- const valueKey = ':sk_value';
76
+ else if (operator === "begins_with") {
77
+ const valueKey = ":sk_value";
74
78
  this.expressionAttributeValues[valueKey] = this.index
75
79
  ? this.parent.buildIndexes(values)[sortKeyName]
76
80
  : this.parent.buildKey(values)[sortKeyName];
@@ -78,7 +82,7 @@ class QueryBuilder {
78
82
  }
79
83
  else {
80
84
  // For eq, lt, lte, gt, gte:
81
- const valueKey = ':sk_value';
85
+ const valueKey = ":sk_value";
82
86
  this.expressionAttributeValues[valueKey] = this.index
83
87
  ? this.parent.buildIndexes(values)[sortKeyName]
84
88
  : this.parent.buildKey(values)[sortKeyName];
@@ -92,7 +96,7 @@ class QueryBuilder {
92
96
  const randomString = Math.random().toString(36).substring(2, 15);
93
97
  const placeholderName = `#attr_${attrStr}_${randomString}`;
94
98
  this.expressionAttributeNames[placeholderName] = attrStr;
95
- if (operator === 'between') {
99
+ if (operator === "between") {
96
100
  if (!Array.isArray(values) || values.length !== 2) {
97
101
  throw new Error("For 'between' operator, values must be a tuple of two items");
98
102
  }
@@ -102,7 +106,7 @@ class QueryBuilder {
102
106
  this.expressionAttributeValues[placeholderValueEnd] = values[1];
103
107
  this.filterConditions.push(`${placeholderName} BETWEEN ${placeholderValueStart} AND ${placeholderValueEnd}`);
104
108
  }
105
- else if (operator === 'begins_with' || operator === 'contains') {
109
+ else if (operator === "begins_with" || operator === "contains") {
106
110
  const placeholderValue = `:val_${attrStr}_${randomString}`;
107
111
  this.expressionAttributeValues[placeholderValue] = values;
108
112
  this.filterConditions.push(`${operator}(${placeholderName}, ${placeholderValue})`);
@@ -127,9 +131,8 @@ class QueryBuilder {
127
131
  * Executes the query and returns a Promise that resolves with an array of items.
128
132
  */
129
133
  async execute() {
130
- var _a, _b, _c;
131
134
  this.keyConditions.unshift(`#pk = :pk_value`);
132
- const keyConditionExpression = this.keyConditions.join(' AND ');
135
+ const keyConditionExpression = this.keyConditions.join(" AND ");
133
136
  const params = {
134
137
  TableName: this.parent.getTableName(),
135
138
  KeyConditionExpression: keyConditionExpression,
@@ -138,16 +141,20 @@ class QueryBuilder {
138
141
  ScanIndexForward: this.ascending,
139
142
  Limit: this.limit,
140
143
  ExclusiveStartKey: this.lastKey,
141
- IndexName: (_b = (_a = this.index) === null || _a === void 0 ? void 0 : _a.name) !== null && _b !== void 0 ? _b : undefined,
144
+ IndexName: this.index?.name ?? undefined,
142
145
  };
143
146
  if (this.parent.getEntityType()) {
144
147
  this.filterConditions.push(`#entity = :entity_value`);
145
- this.expressionAttributeNames['#entity'] = 'entityType';
146
- this.expressionAttributeValues[':entity_value'] = this.parent.getEntityType();
148
+ this.expressionAttributeNames["#entity"] = "entityType";
149
+ this.expressionAttributeValues[":entity_value"] =
150
+ this.parent.getEntityType();
147
151
  }
148
- params.FilterExpression = this.filterConditions.join(' AND ');
152
+ params.FilterExpression = this.filterConditions.join(" AND ");
149
153
  const result = await this.parent.getClient().send(new lib_dynamodb_1.QueryCommand(params));
150
- return { items: this.parent.getSchema().array().parse(result.Items), lastKey: (_c = result.LastEvaluatedKey) !== null && _c !== void 0 ? _c : undefined };
154
+ return {
155
+ items: this.parent.getSchema().array().parse(result.Items),
156
+ lastKey: result.LastEvaluatedKey ?? undefined,
157
+ };
151
158
  }
152
159
  }
153
160
  exports.QueryBuilder = QueryBuilder;
@@ -4,17 +4,20 @@ exports.ScanBuilder = void 0;
4
4
  const lib_dynamodb_1 = require("@aws-sdk/lib-dynamodb");
5
5
  const operator_1 = require("../operator");
6
6
  class ScanBuilder {
7
+ parent;
8
+ filters = [];
9
+ expressionAttributeNames = {};
10
+ expressionAttributeValues = {};
11
+ limit;
12
+ lastKey;
7
13
  constructor(parent) {
8
14
  this.parent = parent;
9
- this.filters = [];
10
- this.expressionAttributeNames = {};
11
- this.expressionAttributeValues = {};
12
15
  }
13
16
  where(attribute, operator, values) {
14
17
  const attrStr = String(attribute);
15
18
  const nameKey = `#attr_${attrStr}`;
16
19
  this.expressionAttributeNames[nameKey] = attrStr;
17
- if (operator === 'between') {
20
+ if (operator === "between") {
18
21
  if (!Array.isArray(values) || values.length !== 2) {
19
22
  throw new Error(`For 'between' operator, values must be a tuple of two items`);
20
23
  }
@@ -24,7 +27,7 @@ class ScanBuilder {
24
27
  this.expressionAttributeValues[valueKeyEnd] = values[1];
25
28
  this.filters.push(`${nameKey} BETWEEN ${valueKeyStart} AND ${valueKeyEnd}`);
26
29
  }
27
- else if (operator === 'begins_with' || operator === 'contains') {
30
+ else if (operator === "begins_with" || operator === "contains") {
28
31
  const valueKey = `:val_${attrStr}`;
29
32
  this.expressionAttributeValues[valueKey] = values;
30
33
  this.filters.push(`${operator}(${nameKey}, ${valueKey})`);
@@ -49,22 +52,25 @@ class ScanBuilder {
49
52
  * Executes the scan and returns a Promise that resolves with an array of items.
50
53
  */
51
54
  async execute() {
52
- var _a;
53
55
  const params = {
54
56
  TableName: this.parent.getTableName(),
55
57
  ExpressionAttributeNames: this.expressionAttributeNames,
56
58
  ExpressionAttributeValues: this.expressionAttributeValues,
57
59
  Limit: this.limit,
58
- ExclusiveStartKey: this.lastKey
60
+ ExclusiveStartKey: this.lastKey,
59
61
  };
60
62
  if (this.parent.getEntityType()) {
61
63
  this.filters.push(`#entity = :entity_value`);
62
- this.expressionAttributeNames['#entity'] = 'entityType';
63
- this.expressionAttributeValues[':entity_value'] = this.parent.getEntityType();
64
+ this.expressionAttributeNames["#entity"] = "entityType";
65
+ this.expressionAttributeValues[":entity_value"] =
66
+ this.parent.getEntityType();
64
67
  }
65
- params.FilterExpression = this.filters.join(' AND ');
68
+ params.FilterExpression = this.filters.join(" AND ");
66
69
  const result = await this.parent.getClient().send(new lib_dynamodb_1.ScanCommand(params));
67
- return { items: this.parent.getSchema().array().parse(result.Items), lastKey: (_a = result.LastEvaluatedKey) !== null && _a !== void 0 ? _a : undefined };
70
+ return {
71
+ items: this.parent.getSchema().array().parse(result.Items),
72
+ lastKey: result.LastEvaluatedKey ?? undefined,
73
+ };
68
74
  }
69
75
  }
70
76
  exports.ScanBuilder = ScanBuilder;
@@ -3,13 +3,16 @@ Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.UpdateBuilder = void 0;
4
4
  const lib_dynamodb_1 = require("@aws-sdk/lib-dynamodb");
5
5
  class UpdateBuilder {
6
+ parent;
7
+ key;
8
+ actions = {};
9
+ condition;
10
+ // When using transaction mode, we store extra transaction items.
11
+ extraTransactItems = [];
6
12
  // Reference to the parent BetterDDB instance and key.
7
13
  constructor(parent, key) {
8
14
  this.parent = parent;
9
15
  this.key = key;
10
- this.actions = {};
11
- // When using transaction mode, we store extra transaction items.
12
- this.extraTransactItems = [];
13
16
  }
14
17
  // Chainable methods:
15
18
  set(attrs) {
@@ -76,17 +79,17 @@ class UpdateBuilder {
76
79
  setParts.push(`${nameKey} = ${valueKey}`);
77
80
  }
78
81
  if (setParts.length > 0) {
79
- clauses.push(`SET ${setParts.join(', ')}`);
82
+ clauses.push(`SET ${setParts.join(", ")}`);
80
83
  }
81
84
  }
82
85
  // Build REMOVE clause.
83
86
  if (this.actions.remove && this.actions.remove.length > 0) {
84
- const removeParts = this.actions.remove.map(attr => {
87
+ const removeParts = this.actions.remove.map((attr) => {
85
88
  const nameKey = `#remove_${String(attr)}`;
86
89
  ExpressionAttributeNames[nameKey] = String(attr);
87
90
  return nameKey;
88
91
  });
89
- clauses.push(`REMOVE ${removeParts.join(', ')}`);
92
+ clauses.push(`REMOVE ${removeParts.join(", ")}`);
90
93
  }
91
94
  // Build ADD clause.
92
95
  if (this.actions.add) {
@@ -99,7 +102,7 @@ class UpdateBuilder {
99
102
  addParts.push(`${nameKey} ${valueKey}`);
100
103
  }
101
104
  if (addParts.length > 0) {
102
- clauses.push(`ADD ${addParts.join(', ')}`);
105
+ clauses.push(`ADD ${addParts.join(", ")}`);
103
106
  }
104
107
  }
105
108
  // Build DELETE clause.
@@ -113,7 +116,7 @@ class UpdateBuilder {
113
116
  deleteParts.push(`${nameKey} ${valueKey}`);
114
117
  }
115
118
  if (deleteParts.length > 0) {
116
- clauses.push(`DELETE ${deleteParts.join(', ')}`);
119
+ clauses.push(`DELETE ${deleteParts.join(", ")}`);
117
120
  }
118
121
  }
119
122
  // Merge any provided condition attribute values.
@@ -121,9 +124,9 @@ class UpdateBuilder {
121
124
  Object.assign(ExpressionAttributeValues, this.condition.attributeValues);
122
125
  }
123
126
  return {
124
- updateExpression: clauses.join(' '),
127
+ updateExpression: clauses.join(" "),
125
128
  attributeNames: ExpressionAttributeNames,
126
- attributeValues: ExpressionAttributeValues
129
+ attributeValues: ExpressionAttributeValues,
127
130
  };
128
131
  }
129
132
  /**
@@ -136,7 +139,7 @@ class UpdateBuilder {
136
139
  Key: this.parent.buildKey(this.key),
137
140
  UpdateExpression: updateExpression,
138
141
  ExpressionAttributeNames: attributeNames,
139
- ExpressionAttributeValues: attributeValues
142
+ ExpressionAttributeValues: attributeValues,
140
143
  };
141
144
  if (this.condition && this.condition.expression) {
142
145
  updateItem.ConditionExpression = this.condition.expression;
@@ -153,12 +156,12 @@ class UpdateBuilder {
153
156
  // Combine with extra transaction items.
154
157
  const allItems = [...this.extraTransactItems, myTransactItem];
155
158
  await this.parent.getClient().send(new lib_dynamodb_1.TransactWriteCommand({
156
- TransactItems: allItems
159
+ TransactItems: allItems,
157
160
  }));
158
161
  // After transaction, retrieve the updated item.
159
162
  const result = await this.parent.get(this.key).execute();
160
163
  if (result === null) {
161
- throw new Error('Item not found after transaction update');
164
+ throw new Error("Item not found after transaction update");
162
165
  }
163
166
  return result;
164
167
  }
@@ -171,14 +174,16 @@ class UpdateBuilder {
171
174
  UpdateExpression: updateExpression,
172
175
  ExpressionAttributeNames: attributeNames,
173
176
  ExpressionAttributeValues: attributeValues,
174
- ReturnValues: 'ALL_NEW'
177
+ ReturnValues: "ALL_NEW",
175
178
  };
176
179
  if (this.condition && this.condition.expression) {
177
180
  params.ConditionExpression = this.condition.expression;
178
181
  }
179
- const result = await this.parent.getClient().send(new lib_dynamodb_1.UpdateCommand(params));
182
+ const result = await this.parent
183
+ .getClient()
184
+ .send(new lib_dynamodb_1.UpdateCommand(params));
180
185
  if (!result.Attributes) {
181
- throw new Error('No attributes returned after update');
186
+ throw new Error("No attributes returned after update");
182
187
  }
183
188
  return this.parent.getSchema().parse(result.Attributes);
184
189
  }