@ftschopp/dynatable-core 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 (197) hide show
  1. package/CHANGELOG.md +62 -0
  2. package/README.md +17 -0
  3. package/dist/builders/batch-get/create-batch-get-builder.d.ts +18 -0
  4. package/dist/builders/batch-get/create-batch-get-builder.d.ts.map +1 -0
  5. package/dist/builders/batch-get/create-batch-get-builder.js +71 -0
  6. package/dist/builders/batch-get/index.d.ts +3 -0
  7. package/dist/builders/batch-get/index.d.ts.map +1 -0
  8. package/dist/builders/batch-get/index.js +18 -0
  9. package/dist/builders/batch-get/types.d.ts +25 -0
  10. package/dist/builders/batch-get/types.d.ts.map +1 -0
  11. package/dist/builders/batch-get/types.js +2 -0
  12. package/dist/builders/batch-write/create-batch-write-builder.d.ts +12 -0
  13. package/dist/builders/batch-write/create-batch-write-builder.d.ts.map +1 -0
  14. package/dist/builders/batch-write/create-batch-write-builder.js +35 -0
  15. package/dist/builders/batch-write/index.d.ts +3 -0
  16. package/dist/builders/batch-write/index.d.ts.map +1 -0
  17. package/dist/builders/batch-write/index.js +18 -0
  18. package/dist/builders/batch-write/types.d.ts +30 -0
  19. package/dist/builders/batch-write/types.d.ts.map +1 -0
  20. package/dist/builders/batch-write/types.js +2 -0
  21. package/dist/builders/delete/create-delete-builder.d.ts +9 -0
  22. package/dist/builders/delete/create-delete-builder.d.ts.map +1 -0
  23. package/dist/builders/delete/create-delete-builder.js +72 -0
  24. package/dist/builders/delete/index.d.ts +3 -0
  25. package/dist/builders/delete/index.d.ts.map +1 -0
  26. package/dist/builders/delete/index.js +18 -0
  27. package/dist/builders/delete/types.d.ts +11 -0
  28. package/dist/builders/delete/types.d.ts.map +1 -0
  29. package/dist/builders/delete/types.js +2 -0
  30. package/dist/builders/get/create-get-builder.d.ts +12 -0
  31. package/dist/builders/get/create-get-builder.d.ts.map +1 -0
  32. package/dist/builders/get/create-get-builder.js +95 -0
  33. package/dist/builders/get/index.d.ts +3 -0
  34. package/dist/builders/get/index.d.ts.map +1 -0
  35. package/dist/builders/get/index.js +18 -0
  36. package/dist/builders/get/types.d.ts +28 -0
  37. package/dist/builders/get/types.d.ts.map +1 -0
  38. package/dist/builders/get/types.js +2 -0
  39. package/dist/builders/index.d.ts +12 -0
  40. package/dist/builders/index.d.ts.map +1 -0
  41. package/dist/builders/index.js +29 -0
  42. package/dist/builders/put/create-put-builder.d.ts +9 -0
  43. package/dist/builders/put/create-put-builder.d.ts.map +1 -0
  44. package/dist/builders/put/create-put-builder.js +104 -0
  45. package/dist/builders/put/index.d.ts +3 -0
  46. package/dist/builders/put/index.d.ts.map +1 -0
  47. package/dist/builders/put/index.js +18 -0
  48. package/dist/builders/put/types.d.ts +17 -0
  49. package/dist/builders/put/types.d.ts.map +1 -0
  50. package/dist/builders/put/types.js +2 -0
  51. package/dist/builders/query/create-query-builder.d.ts +9 -0
  52. package/dist/builders/query/create-query-builder.d.ts.map +1 -0
  53. package/dist/builders/query/create-query-builder.js +283 -0
  54. package/dist/builders/query/index.d.ts +3 -0
  55. package/dist/builders/query/index.d.ts.map +1 -0
  56. package/dist/builders/query/index.js +18 -0
  57. package/dist/builders/query/types.d.ts +79 -0
  58. package/dist/builders/query/types.d.ts.map +1 -0
  59. package/dist/builders/query/types.js +2 -0
  60. package/dist/builders/scan/create-scan-builder.d.ts +12 -0
  61. package/dist/builders/scan/create-scan-builder.d.ts.map +1 -0
  62. package/dist/builders/scan/create-scan-builder.js +103 -0
  63. package/dist/builders/scan/index.d.ts +3 -0
  64. package/dist/builders/scan/index.d.ts.map +1 -0
  65. package/dist/builders/scan/index.js +18 -0
  66. package/dist/builders/scan/types.d.ts +43 -0
  67. package/dist/builders/scan/types.d.ts.map +1 -0
  68. package/dist/builders/scan/types.js +2 -0
  69. package/dist/builders/shared/conditions.d.ts +18 -0
  70. package/dist/builders/shared/conditions.d.ts.map +1 -0
  71. package/dist/builders/shared/conditions.js +48 -0
  72. package/dist/builders/shared/index.d.ts +4 -0
  73. package/dist/builders/shared/index.d.ts.map +1 -0
  74. package/dist/builders/shared/index.js +19 -0
  75. package/dist/builders/shared/operators.d.ts +12 -0
  76. package/dist/builders/shared/operators.d.ts.map +1 -0
  77. package/dist/builders/shared/operators.js +197 -0
  78. package/dist/builders/shared/types.d.ts +77 -0
  79. package/dist/builders/shared/types.d.ts.map +1 -0
  80. package/dist/builders/shared/types.js +6 -0
  81. package/dist/builders/transact-get/create-transact-get-builder.d.ts +18 -0
  82. package/dist/builders/transact-get/create-transact-get-builder.d.ts.map +1 -0
  83. package/dist/builders/transact-get/create-transact-get-builder.js +60 -0
  84. package/dist/builders/transact-get/index.d.ts +3 -0
  85. package/dist/builders/transact-get/index.d.ts.map +1 -0
  86. package/dist/builders/transact-get/index.js +18 -0
  87. package/dist/builders/transact-get/types.d.ts +28 -0
  88. package/dist/builders/transact-get/types.d.ts.map +1 -0
  89. package/dist/builders/transact-get/types.js +2 -0
  90. package/dist/builders/transact-write/create-transact-write-builder.d.ts +18 -0
  91. package/dist/builders/transact-write/create-transact-write-builder.d.ts.map +1 -0
  92. package/dist/builders/transact-write/create-transact-write-builder.js +97 -0
  93. package/dist/builders/transact-write/index.d.ts +3 -0
  94. package/dist/builders/transact-write/index.d.ts.map +1 -0
  95. package/dist/builders/transact-write/index.js +18 -0
  96. package/dist/builders/transact-write/types.d.ts +34 -0
  97. package/dist/builders/transact-write/types.d.ts.map +1 -0
  98. package/dist/builders/transact-write/types.js +2 -0
  99. package/dist/builders/update/create-update-builder.d.ts +14 -0
  100. package/dist/builders/update/create-update-builder.d.ts.map +1 -0
  101. package/dist/builders/update/create-update-builder.js +180 -0
  102. package/dist/builders/update/index.d.ts +3 -0
  103. package/dist/builders/update/index.d.ts.map +1 -0
  104. package/dist/builders/update/index.js +18 -0
  105. package/dist/builders/update/types.d.ts +35 -0
  106. package/dist/builders/update/types.d.ts.map +1 -0
  107. package/dist/builders/update/types.js +2 -0
  108. package/dist/core/types.d.ts +224 -0
  109. package/dist/core/types.d.ts.map +1 -0
  110. package/dist/core/types.js +3 -0
  111. package/dist/entity.d.ts +73 -0
  112. package/dist/entity.d.ts.map +1 -0
  113. package/dist/entity.js +161 -0
  114. package/dist/index.d.ts +4 -0
  115. package/dist/index.d.ts.map +1 -0
  116. package/dist/index.js +20 -0
  117. package/dist/table.d.ts +70 -0
  118. package/dist/table.d.ts.map +1 -0
  119. package/dist/table.js +69 -0
  120. package/dist/utils/dynamodb-logger.d.ts +118 -0
  121. package/dist/utils/dynamodb-logger.d.ts.map +1 -0
  122. package/dist/utils/dynamodb-logger.js +125 -0
  123. package/dist/utils/model-utils.d.ts +24 -0
  124. package/dist/utils/model-utils.d.ts.map +1 -0
  125. package/dist/utils/model-utils.js +88 -0
  126. package/dist/utils/zod-utils.d.ts +13 -0
  127. package/dist/utils/zod-utils.d.ts.map +1 -0
  128. package/dist/utils/zod-utils.js +35 -0
  129. package/eslint.config.mjs +4 -0
  130. package/jest.config.js +11 -0
  131. package/package.json +36 -0
  132. package/src/builders/README.md +272 -0
  133. package/src/builders/batch-get/README.md +98 -0
  134. package/src/builders/batch-get/create-batch-get-builder.test.ts +165 -0
  135. package/src/builders/batch-get/create-batch-get-builder.ts +106 -0
  136. package/src/builders/batch-get/index.ts +2 -0
  137. package/src/builders/batch-get/types.ts +29 -0
  138. package/src/builders/batch-write/README.md +204 -0
  139. package/src/builders/batch-write/create-batch-write-builder.test.ts +173 -0
  140. package/src/builders/batch-write/create-batch-write-builder.ts +49 -0
  141. package/src/builders/batch-write/index.ts +2 -0
  142. package/src/builders/batch-write/types.ts +33 -0
  143. package/src/builders/delete/create-delete-builder.test.ts +294 -0
  144. package/src/builders/delete/create-delete-builder.ts +100 -0
  145. package/src/builders/delete/index.ts +2 -0
  146. package/src/builders/delete/types.ts +11 -0
  147. package/src/builders/get/create-get-builder.test.ts +272 -0
  148. package/src/builders/get/create-get-builder.ts +140 -0
  149. package/src/builders/get/index.ts +2 -0
  150. package/src/builders/get/types.ts +30 -0
  151. package/src/builders/index.ts +14 -0
  152. package/src/builders/put/create-put-builder.test.ts +213 -0
  153. package/src/builders/put/create-put-builder.ts +151 -0
  154. package/src/builders/put/index.ts +2 -0
  155. package/src/builders/put/types.ts +18 -0
  156. package/src/builders/query/create-query-builder.test.ts +230 -0
  157. package/src/builders/query/create-query-builder.ts +353 -0
  158. package/src/builders/query/index.ts +2 -0
  159. package/src/builders/query/types.ts +95 -0
  160. package/src/builders/scan/create-scan-builder.test.ts +260 -0
  161. package/src/builders/scan/create-scan-builder.ts +217 -0
  162. package/src/builders/scan/index.ts +2 -0
  163. package/src/builders/scan/types.ts +49 -0
  164. package/src/builders/shared/conditions.ts +58 -0
  165. package/src/builders/shared/index.ts +3 -0
  166. package/src/builders/shared/operators.test.ts +270 -0
  167. package/src/builders/shared/operators.ts +200 -0
  168. package/src/builders/shared/types.ts +100 -0
  169. package/src/builders/transact-get/README.md +167 -0
  170. package/src/builders/transact-get/create-transact-get-builder.test.ts +239 -0
  171. package/src/builders/transact-get/create-transact-get-builder.ts +67 -0
  172. package/src/builders/transact-get/index.ts +2 -0
  173. package/src/builders/transact-get/types.ts +31 -0
  174. package/src/builders/transact-write/README.md +166 -0
  175. package/src/builders/transact-write/create-transact-write-builder.test.ts +288 -0
  176. package/src/builders/transact-write/create-transact-write-builder.ts +118 -0
  177. package/src/builders/transact-write/index.ts +2 -0
  178. package/src/builders/transact-write/types.ts +33 -0
  179. package/src/builders/update/create-update-builder.test.ts +333 -0
  180. package/src/builders/update/create-update-builder.ts +284 -0
  181. package/src/builders/update/index.ts +2 -0
  182. package/src/builders/update/types.ts +42 -0
  183. package/src/core/types.test.ts +506 -0
  184. package/src/core/types.ts +290 -0
  185. package/src/entity.ts +337 -0
  186. package/src/index.ts +22 -0
  187. package/src/table.ts +109 -0
  188. package/src/utils/dynamodb-logger.test.ts +246 -0
  189. package/src/utils/dynamodb-logger.ts +175 -0
  190. package/src/utils/model-utils.test.ts +232 -0
  191. package/src/utils/model-utils.ts +101 -0
  192. package/src/utils/zod-utils.test.ts +272 -0
  193. package/src/utils/zod-utils.ts +36 -0
  194. package/tests/integration/instagram-clone.integration.test.ts +966 -0
  195. package/tests/integration/pagination-timestamps.integration.test.ts +375 -0
  196. package/tests/integration/transactions.integration.test.ts +529 -0
  197. package/tsconfig.json +12 -0
@@ -0,0 +1,28 @@
1
+ import { ExecutableBuilder } from '../shared';
2
+ /**
3
+ * Builder for DynamoDB GetItem operations.
4
+ * Supports projection, consistent read, and inspection of the final parameters.
5
+ */
6
+ export interface GetBuilder<KeyInput, Model> extends ExecutableBuilder<Model | undefined> {
7
+ /**
8
+ * Adds a projection expression to only return specific attributes.
9
+ * Returns a new immutable builder.
10
+ */
11
+ select(attrs: (keyof Model)[]): GetBuilder<KeyInput, Model>;
12
+ /**
13
+ * Enables strongly consistent read (eventual consistency is default).
14
+ * Returns a new immutable builder.
15
+ */
16
+ consistentRead(): GetBuilder<KeyInput, Model>;
17
+ /**
18
+ * Configures the ReturnConsumedCapacity parameter.
19
+ * Returns a new immutable builder.
20
+ *
21
+ * @param mode - 'INDEXES' | 'TOTAL' | 'NONE'
22
+ * - INDEXES: Returns consumed capacity for table and indexes
23
+ * - TOTAL: Returns total consumed capacity
24
+ * - NONE: No consumed capacity data returned (default)
25
+ */
26
+ returnConsumedCapacity(mode: 'INDEXES' | 'TOTAL' | 'NONE'): GetBuilder<KeyInput, Model>;
27
+ }
28
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../src/builders/get/types.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,iBAAiB,EAAE,MAAM,WAAW,CAAC;AAE9C;;;GAGG;AACH,MAAM,WAAW,UAAU,CAAC,QAAQ,EAAE,KAAK,CAAE,SAAQ,iBAAiB,CAAC,KAAK,GAAG,SAAS,CAAC;IACvF;;;OAGG;IACH,MAAM,CAAC,KAAK,EAAE,CAAC,MAAM,KAAK,CAAC,EAAE,GAAG,UAAU,CAAC,QAAQ,EAAE,KAAK,CAAC,CAAC;IAE5D;;;OAGG;IACH,cAAc,IAAI,UAAU,CAAC,QAAQ,EAAE,KAAK,CAAC,CAAC;IAE9C;;;;;;;;OAQG;IACH,sBAAsB,CAAC,IAAI,EAAE,SAAS,GAAG,OAAO,GAAG,MAAM,GAAG,UAAU,CAAC,QAAQ,EAAE,KAAK,CAAC,CAAC;CACzF"}
@@ -0,0 +1,2 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
@@ -0,0 +1,12 @@
1
+ export * from './shared';
2
+ export * from './get';
3
+ export * from './put';
4
+ export * from './query';
5
+ export * from './scan';
6
+ export * from './update';
7
+ export * from './delete';
8
+ export * from './batch-get';
9
+ export * from './batch-write';
10
+ export * from './transact-write';
11
+ export * from './transact-get';
12
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/builders/index.ts"],"names":[],"mappings":"AACA,cAAc,UAAU,CAAC;AAGzB,cAAc,OAAO,CAAC;AACtB,cAAc,OAAO,CAAC;AACtB,cAAc,SAAS,CAAC;AACxB,cAAc,QAAQ,CAAC;AACvB,cAAc,UAAU,CAAC;AACzB,cAAc,UAAU,CAAC;AACzB,cAAc,aAAa,CAAC;AAC5B,cAAc,eAAe,CAAC;AAC9B,cAAc,kBAAkB,CAAC;AACjC,cAAc,gBAAgB,CAAC"}
@@ -0,0 +1,29 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __exportStar = (this && this.__exportStar) || function(m, exports) {
14
+ for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
15
+ };
16
+ Object.defineProperty(exports, "__esModule", { value: true });
17
+ // Shared utilities and types
18
+ __exportStar(require("./shared"), exports);
19
+ // Operation builders
20
+ __exportStar(require("./get"), exports);
21
+ __exportStar(require("./put"), exports);
22
+ __exportStar(require("./query"), exports);
23
+ __exportStar(require("./scan"), exports);
24
+ __exportStar(require("./update"), exports);
25
+ __exportStar(require("./delete"), exports);
26
+ __exportStar(require("./batch-get"), exports);
27
+ __exportStar(require("./batch-write"), exports);
28
+ __exportStar(require("./transact-write"), exports);
29
+ __exportStar(require("./transact-get"), exports);
@@ -0,0 +1,9 @@
1
+ import { DynamoDBClient } from '@aws-sdk/client-dynamodb';
2
+ import { Condition } from '../shared';
3
+ import { PutBuilder } from './types';
4
+ import { DynamoDBLogger } from '../../utils/dynamodb-logger';
5
+ /**
6
+ * Creates a PutBuilder for an item and table.
7
+ */
8
+ export declare function createPutBuilder<Model>(tableName: string, item: Model, client: DynamoDBClient, prevConditions?: Condition[], shouldCheckNotExists?: boolean, returnMode?: 'NONE' | 'ALL_OLD', enableTimestamps?: boolean, logger?: DynamoDBLogger): PutBuilder<Model>;
9
+ //# sourceMappingURL=create-put-builder.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"create-put-builder.d.ts","sourceRoot":"","sources":["../../../src/builders/put/create-put-builder.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,cAAc,EAAE,MAAM,0BAA0B,CAAC;AAE1D,OAAO,EAAgC,SAAS,EAAmB,MAAM,WAAW,CAAC;AACrF,OAAO,EAAE,UAAU,EAAE,MAAM,SAAS,CAAC;AACrC,OAAO,EAAE,cAAc,EAAE,MAAM,6BAA6B,CAAC;AAgB7D;;GAEG;AACH,wBAAgB,gBAAgB,CAAC,KAAK,EACpC,SAAS,EAAE,MAAM,EACjB,IAAI,EAAE,KAAK,EACX,MAAM,EAAE,cAAc,EACtB,cAAc,GAAE,SAAS,EAAO,EAChC,oBAAoB,UAAQ,EAC5B,UAAU,GAAE,MAAM,GAAG,SAAkB,EACvC,gBAAgB,UAAQ,EACxB,MAAM,CAAC,EAAE,cAAc,GACtB,UAAU,CAAC,KAAK,CAAC,CAqHnB"}
@@ -0,0 +1,104 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.createPutBuilder = createPutBuilder;
4
+ const lib_dynamodb_1 = require("@aws-sdk/lib-dynamodb");
5
+ const shared_1 = require("../shared");
6
+ /**
7
+ * Utility to infer if attribute exists in the item and returns condition.
8
+ */
9
+ function buildNotExistsConditions(item) {
10
+ // Check for common key names (both uppercase and lowercase)
11
+ const possibleKeys = ['PK', 'SK', 'pk', 'sk'];
12
+ const foundKeys = possibleKeys.filter((key) => key in item);
13
+ return foundKeys.map((key) => ({
14
+ expression: `attribute_not_exists(#${key})`,
15
+ names: { [`#${key}`]: key },
16
+ }));
17
+ }
18
+ /**
19
+ * Creates a PutBuilder for an item and table.
20
+ */
21
+ function createPutBuilder(tableName, item, client, prevConditions = [], shouldCheckNotExists = false, returnMode = 'NONE', enableTimestamps = false, logger) {
22
+ const conditions = [...prevConditions];
23
+ const build = () => ({
24
+ where(fn) {
25
+ const attrs = new Proxy({}, {
26
+ get(_, prop) {
27
+ return { name: prop };
28
+ },
29
+ });
30
+ // Create a scoped opBuilder for this operation to avoid global state
31
+ const opBuilder = (0, shared_1.createOpBuilder)();
32
+ const condition = fn(attrs, opBuilder);
33
+ return createPutBuilder(tableName, item, client, [...conditions, condition], shouldCheckNotExists, returnMode, enableTimestamps, logger);
34
+ },
35
+ ifNotExists() {
36
+ return createPutBuilder(tableName, item, client, conditions, true, returnMode, enableTimestamps, logger);
37
+ },
38
+ returning(mode) {
39
+ return createPutBuilder(tableName, item, client, conditions, shouldCheckNotExists, mode, enableTimestamps, logger);
40
+ },
41
+ dbParams() {
42
+ let finalConditions = [...conditions];
43
+ if (shouldCheckNotExists) {
44
+ finalConditions = [...finalConditions, ...buildNotExistsConditions(item)];
45
+ }
46
+ // Add timestamps if enabled
47
+ let finalItem = item;
48
+ if (enableTimestamps) {
49
+ const now = new Date().toISOString();
50
+ finalItem = {
51
+ ...item,
52
+ createdAt: now,
53
+ updatedAt: now,
54
+ };
55
+ }
56
+ // Build ConditionExpression from condition tree
57
+ let conditionExpression = '';
58
+ let expressionAttributeNames = {};
59
+ let expressionAttributeValues = {};
60
+ if (finalConditions.length > 0) {
61
+ // If there's only one condition, use it directly
62
+ // Otherwise, combine with AND
63
+ const combinedCondition = finalConditions.length === 1 && finalConditions[0]
64
+ ? finalConditions[0]
65
+ : {
66
+ expression: '',
67
+ operator: 'AND',
68
+ children: finalConditions,
69
+ };
70
+ const result = (0, shared_1.buildExpression)(combinedCondition);
71
+ conditionExpression = result.expression;
72
+ expressionAttributeNames = result.names;
73
+ expressionAttributeValues = result.values;
74
+ }
75
+ const extra = returnMode !== 'NONE' ? { ReturnValues: returnMode } : {};
76
+ return {
77
+ TableName: tableName,
78
+ Item: finalItem,
79
+ ...(conditionExpression && {
80
+ ConditionExpression: conditionExpression,
81
+ }),
82
+ ...(Object.keys(expressionAttributeNames).length && {
83
+ ExpressionAttributeNames: expressionAttributeNames,
84
+ }),
85
+ ...(Object.keys(expressionAttributeValues).length && {
86
+ ExpressionAttributeValues: expressionAttributeValues,
87
+ }),
88
+ ...extra,
89
+ };
90
+ },
91
+ async execute() {
92
+ const params = build().dbParams();
93
+ const response = await client.send(new lib_dynamodb_1.PutCommand(params));
94
+ logger?.log('PutCommand', params, response);
95
+ // Return the old item if returnMode is ALL_OLD and it was replaced
96
+ if (returnMode === 'ALL_OLD' && response.Attributes) {
97
+ return response.Attributes;
98
+ }
99
+ // For NONE mode or when no old item existed, return the new item with timestamps
100
+ return params.Item;
101
+ },
102
+ });
103
+ return build();
104
+ }
@@ -0,0 +1,3 @@
1
+ export * from './types';
2
+ export * from './create-put-builder';
3
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/builders/put/index.ts"],"names":[],"mappings":"AAAA,cAAc,SAAS,CAAC;AACxB,cAAc,sBAAsB,CAAC"}
@@ -0,0 +1,18 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __exportStar = (this && this.__exportStar) || function(m, exports) {
14
+ for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
15
+ };
16
+ Object.defineProperty(exports, "__esModule", { value: true });
17
+ __exportStar(require("./types"), exports);
18
+ __exportStar(require("./create-put-builder"), exports);
@@ -0,0 +1,17 @@
1
+ import { OperationBuilder } from '../shared';
2
+ /**
3
+ * Builder interface for DynamoDB PutItem operations
4
+ */
5
+ export interface PutBuilder<Model> extends OperationBuilder<Model> {
6
+ /**
7
+ * Adds a condition that the item must not exist (checks pk and sk)
8
+ */
9
+ ifNotExists(): PutBuilder<Model>;
10
+ /**
11
+ * Configures what values should be returned after the put operation.
12
+ * - NONE: Nothing is returned (default)
13
+ * - ALL_OLD: Returns the item as it was before being replaced (if it existed)
14
+ */
15
+ returning(mode: 'NONE' | 'ALL_OLD'): PutBuilder<Model>;
16
+ }
17
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../src/builders/put/types.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,gBAAgB,EAAE,MAAM,WAAW,CAAC;AAE7C;;GAEG;AACH,MAAM,WAAW,UAAU,CAAC,KAAK,CAAE,SAAQ,gBAAgB,CAAC,KAAK,CAAC;IAChE;;OAEG;IACH,WAAW,IAAI,UAAU,CAAC,KAAK,CAAC,CAAC;IAEjC;;;;OAIG;IACH,SAAS,CAAC,IAAI,EAAE,MAAM,GAAG,SAAS,GAAG,UAAU,CAAC,KAAK,CAAC,CAAC;CACxD"}
@@ -0,0 +1,2 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
@@ -0,0 +1,9 @@
1
+ import { DynamoDBClient } from '@aws-sdk/client-dynamodb';
2
+ import { QueryBuilder } from './types';
3
+ import { ModelDefinition } from '../../core/types';
4
+ import { DynamoDBLogger } from '../../utils/dynamodb-logger';
5
+ /**
6
+ * Creates a QueryBuilder for a table
7
+ */
8
+ export declare function createQueryBuilder<Model, M extends ModelDefinition = any>(tableName: string, client: DynamoDBClient, model?: M, logger?: DynamoDBLogger): QueryBuilder<Model, M>;
9
+ //# sourceMappingURL=create-query-builder.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"create-query-builder.d.ts","sourceRoot":"","sources":["../../../src/builders/query/create-query-builder.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,cAAc,EAAE,MAAM,0BAA0B,CAAC;AAK1D,OAAO,EAAE,YAAY,EAA8B,MAAM,SAAS,CAAC;AACnE,OAAO,EAAE,eAAe,EAAE,MAAM,kBAAkB,CAAC;AAEnD,OAAO,EAAE,cAAc,EAAE,MAAM,6BAA6B,CAAC;AAmT7D;;GAEG;AACH,wBAAgB,kBAAkB,CAAC,KAAK,EAAE,CAAC,SAAS,eAAe,GAAG,GAAG,EACvE,SAAS,EAAE,MAAM,EACjB,MAAM,EAAE,cAAc,EACtB,KAAK,CAAC,EAAE,CAAC,EACT,MAAM,CAAC,EAAE,cAAc,GACtB,YAAY,CAAC,KAAK,EAAE,CAAC,CAAC,CA4BxB"}
@@ -0,0 +1,283 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.createQueryBuilder = createQueryBuilder;
4
+ const lib_dynamodb_1 = require("@aws-sdk/lib-dynamodb");
5
+ const operators_1 = require("../shared/operators");
6
+ const conditions_1 = require("../shared/conditions");
7
+ const model_utils_1 = require("../../utils/model-utils");
8
+ /**
9
+ * Determines if a field is a key field (used in pk/sk templates)
10
+ */
11
+ function isKeyField(fieldName, model) {
12
+ if (!model?.key)
13
+ return false;
14
+ const keyEntries = Object.entries(model.key);
15
+ for (const [, keyDef] of keyEntries) {
16
+ const templateVars = (0, model_utils_1.extractTemplateVars)(keyDef.value);
17
+ if (templateVars.includes(fieldName)) {
18
+ return true;
19
+ }
20
+ }
21
+ return false;
22
+ }
23
+ /**
24
+ * Maps a model attribute name to its corresponding DynamoDB key name (PK/SK)
25
+ * Also returns the key template for value transformation
26
+ */
27
+ function getKeyNameForAttribute(fieldName, model) {
28
+ if (!model?.key)
29
+ return null;
30
+ for (const [keyName, keyDef] of Object.entries(model.key)) {
31
+ const templateVars = (0, model_utils_1.extractTemplateVars)(keyDef.value);
32
+ if (templateVars.includes(fieldName)) {
33
+ return { keyName, template: keyDef.value }; // Returns "PK" and "UP#${username}"
34
+ }
35
+ }
36
+ return null;
37
+ }
38
+ /**
39
+ * Apply key template to transform attribute value to key value
40
+ * e.g., applyKeyTemplate("UP#${username}", "username", "johndoe") -> "UP#johndoe"
41
+ */
42
+ function applyKeyTemplate(template, fieldName, fieldValue) {
43
+ return template.replace(`\${${fieldName}}`, fieldValue);
44
+ }
45
+ /**
46
+ * Separates a condition tree into key conditions and filter conditions
47
+ * Key conditions are rewritten to use actual DynamoDB key names (PK/SK)
48
+ */
49
+ function separateConditions(condition, model) {
50
+ const keyConditions = [];
51
+ const filterConditions = [];
52
+ function traverse(cond) {
53
+ // If it's a combinator
54
+ if (cond.operator && cond.children) {
55
+ // For KeyConditionExpression, we can only use AND at the top level
56
+ if (cond.operator === 'AND') {
57
+ cond.children.forEach((child) => {
58
+ // Check if this is a leaf condition or another combinator
59
+ if (child.children) {
60
+ // Nested combinator - goes to filter
61
+ filterConditions.push(child);
62
+ }
63
+ else {
64
+ traverse(child);
65
+ }
66
+ });
67
+ }
68
+ else {
69
+ // OR at any level must go to filter
70
+ filterConditions.push(cond);
71
+ }
72
+ return;
73
+ }
74
+ // It's a leaf condition - check if it's a key field
75
+ // Extract field name from the expression (e.g., "#username" -> "username")
76
+ const fieldMatch = cond.expression.match(/#(\w+)/);
77
+ if (fieldMatch && fieldMatch[1]) {
78
+ const fieldName = fieldMatch[1];
79
+ const keyInfo = getKeyNameForAttribute(fieldName, model);
80
+ if (keyInfo) {
81
+ // This is a key field - rewrite the condition to use the actual key name
82
+ // and apply the template to the value
83
+ // Find the value placeholder in the condition and transform it
84
+ const newValues = {};
85
+ if (cond.values) {
86
+ for (const [valuePlaceholder, value] of Object.entries(cond.values)) {
87
+ // Apply the key template to transform the value
88
+ const transformedValue = applyKeyTemplate(keyInfo.template, fieldName, value);
89
+ newValues[valuePlaceholder] = transformedValue;
90
+ }
91
+ }
92
+ const rewrittenCond = {
93
+ ...cond,
94
+ expression: cond.expression.replace(new RegExp(`#${fieldName}\\b`, 'g'), `#${keyInfo.keyName}`),
95
+ names: {
96
+ [`#${keyInfo.keyName}`]: keyInfo.keyName,
97
+ },
98
+ values: newValues,
99
+ };
100
+ keyConditions.push(rewrittenCond);
101
+ }
102
+ else {
103
+ filterConditions.push(cond);
104
+ }
105
+ }
106
+ else {
107
+ // Can't determine field, put in filter to be safe
108
+ filterConditions.push(cond);
109
+ }
110
+ }
111
+ traverse(condition);
112
+ return { keyConditions, filterConditions };
113
+ }
114
+ /**
115
+ * Builds a simple AND expression from multiple conditions
116
+ */
117
+ function buildSimpleAndExpression(conditions) {
118
+ if (conditions.length === 0) {
119
+ return { expression: '', names: {}, values: {} };
120
+ }
121
+ const expressions = [];
122
+ const names = {};
123
+ const values = {};
124
+ conditions.forEach((cond) => {
125
+ expressions.push(cond.expression);
126
+ Object.assign(names, cond.names || {});
127
+ Object.assign(values, cond.values || {});
128
+ });
129
+ return {
130
+ expression: expressions.join(' AND '),
131
+ names,
132
+ values,
133
+ };
134
+ }
135
+ /**
136
+ * Creates the query executor with all query methods
137
+ */
138
+ function createQueryExecutor(state) {
139
+ return {
140
+ limit(count) {
141
+ return createQueryExecutor({
142
+ ...state,
143
+ limitValue: count,
144
+ });
145
+ },
146
+ scanIndexForward(forward) {
147
+ return createQueryExecutor({
148
+ ...state,
149
+ scanForward: forward,
150
+ });
151
+ },
152
+ useIndex(indexName) {
153
+ return createQueryExecutor({
154
+ ...state,
155
+ indexName,
156
+ });
157
+ },
158
+ select(attrs) {
159
+ return createQueryExecutor({
160
+ ...state,
161
+ projection: attrs,
162
+ });
163
+ },
164
+ consistentRead() {
165
+ return createQueryExecutor({
166
+ ...state,
167
+ consistentReadEnabled: true,
168
+ });
169
+ },
170
+ startFrom(key) {
171
+ return createQueryExecutor({
172
+ ...state,
173
+ exclusiveStartKey: key,
174
+ });
175
+ },
176
+ dbParams() {
177
+ if (!state.condition) {
178
+ throw new Error('No where condition specified');
179
+ }
180
+ // Separate key conditions from filter conditions
181
+ const { keyConditions, filterConditions } = separateConditions(state.condition, state.model);
182
+ // Build KeyConditionExpression (simple AND)
183
+ const keyExpr = buildSimpleAndExpression(keyConditions);
184
+ // Build FilterExpression (can be complex with OR, NOT, etc.)
185
+ let filterExpr = { expression: '', names: {}, values: {} };
186
+ if (filterConditions.length > 0) {
187
+ if (filterConditions.length === 1 && filterConditions[0]) {
188
+ filterExpr = (0, conditions_1.buildExpression)(filterConditions[0]);
189
+ }
190
+ else {
191
+ // Multiple filter conditions - combine with AND
192
+ filterExpr = (0, conditions_1.buildExpression)({
193
+ expression: '',
194
+ operator: 'AND',
195
+ children: filterConditions,
196
+ });
197
+ }
198
+ }
199
+ // Merge attribute names and values from both expressions
200
+ const allNames = {
201
+ ...(keyExpr.names ?? {}),
202
+ ...(filterExpr.names ?? {}),
203
+ };
204
+ const allValues = {
205
+ ...(keyExpr.values ?? {}),
206
+ ...(filterExpr.values ?? {}),
207
+ };
208
+ return {
209
+ TableName: state.tableName,
210
+ ...(keyExpr.expression && {
211
+ KeyConditionExpression: keyExpr.expression,
212
+ }),
213
+ ...(filterExpr.expression && {
214
+ FilterExpression: filterExpr.expression,
215
+ }),
216
+ ...(Object.keys(allNames).length && {
217
+ ExpressionAttributeNames: allNames,
218
+ }),
219
+ ...(Object.keys(allValues).length && {
220
+ ExpressionAttributeValues: allValues,
221
+ }),
222
+ ...(state.indexName && { IndexName: state.indexName }),
223
+ ...(state.limitValue && { Limit: state.limitValue }),
224
+ ...(state.scanForward !== undefined && {
225
+ ScanIndexForward: state.scanForward,
226
+ }),
227
+ ...(state.projection &&
228
+ state.projection.length > 0 && {
229
+ ProjectionExpression: state.projection.join(', '),
230
+ }),
231
+ ...(state.consistentReadEnabled && { ConsistentRead: true }),
232
+ ...(state.exclusiveStartKey && {
233
+ ExclusiveStartKey: state.exclusiveStartKey,
234
+ }),
235
+ };
236
+ },
237
+ async execute() {
238
+ const params = this.dbParams();
239
+ const result = await state.client.send(new lib_dynamodb_1.QueryCommand(params));
240
+ state.logger?.log('QueryCommand', params, result);
241
+ return (result.Items ?? []);
242
+ },
243
+ async executeWithPagination() {
244
+ const params = this.dbParams();
245
+ const result = await state.client.send(new lib_dynamodb_1.QueryCommand(params));
246
+ state.logger?.log('QueryCommand', params, result);
247
+ return {
248
+ items: (result.Items ?? []),
249
+ lastEvaluatedKey: result.LastEvaluatedKey,
250
+ count: result.Count,
251
+ scannedCount: result.ScannedCount,
252
+ };
253
+ },
254
+ };
255
+ }
256
+ /**
257
+ * Creates a QueryBuilder for a table
258
+ */
259
+ function createQueryBuilder(tableName, client, model, logger) {
260
+ return {
261
+ where(fn) {
262
+ // Create attribute builder proxy
263
+ const attrProxy = new Proxy({}, {
264
+ get(_, prop) {
265
+ return { name: prop };
266
+ },
267
+ });
268
+ // Create a scoped opBuilder for this query to avoid global state
269
+ const opBuilder = (0, operators_1.createOpBuilder)();
270
+ // Call the user's function to get the condition tree
271
+ const condition = fn(attrProxy, opBuilder);
272
+ // Create initial state with the condition
273
+ const initialState = {
274
+ tableName,
275
+ client,
276
+ model,
277
+ condition,
278
+ logger,
279
+ };
280
+ return createQueryExecutor(initialState);
281
+ },
282
+ };
283
+ }
@@ -0,0 +1,3 @@
1
+ export * from './types';
2
+ export * from './create-query-builder';
3
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/builders/query/index.ts"],"names":[],"mappings":"AAAA,cAAc,SAAS,CAAC;AACxB,cAAc,wBAAwB,CAAC"}
@@ -0,0 +1,18 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __exportStar = (this && this.__exportStar) || function(m, exports) {
14
+ for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
15
+ };
16
+ Object.defineProperty(exports, "__esModule", { value: true });
17
+ __exportStar(require("./types"), exports);
18
+ __exportStar(require("./create-query-builder"), exports);
@@ -0,0 +1,79 @@
1
+ import { ExecutableBuilder, AttrBuilder, OpBuilder, Condition } from '../shared';
2
+ import { ModelDefinition } from '../../core/types';
3
+ /**
4
+ * Query result with pagination support
5
+ */
6
+ export interface QueryResult<Model> {
7
+ /**
8
+ * The items returned by the query
9
+ */
10
+ items: Model[];
11
+ /**
12
+ * The LastEvaluatedKey for pagination (if more results available)
13
+ */
14
+ lastEvaluatedKey?: Record<string, any>;
15
+ /**
16
+ * Number of items examined before applying filters
17
+ */
18
+ count?: number;
19
+ /**
20
+ * Number of items returned after applying filters
21
+ */
22
+ scannedCount?: number;
23
+ }
24
+ /**
25
+ * Query executor with additional query-specific options
26
+ */
27
+ export interface QueryExecutor<Model, M extends ModelDefinition = any> extends ExecutableBuilder<Model[]> {
28
+ /**
29
+ * Limit the number of items to return
30
+ */
31
+ limit(count: number): QueryExecutor<Model, M>;
32
+ /**
33
+ * Scan index forward (ascending) or backward (descending)
34
+ */
35
+ scanIndexForward(forward: boolean): QueryExecutor<Model, M>;
36
+ /**
37
+ * Use a secondary index
38
+ */
39
+ useIndex(indexName: string): QueryExecutor<Model, M>;
40
+ /**
41
+ * Select specific attributes to return
42
+ */
43
+ select(attrs: (keyof Model)[]): QueryExecutor<Model, M>;
44
+ /**
45
+ * Use consistent read
46
+ */
47
+ consistentRead(): QueryExecutor<Model, M>;
48
+ /**
49
+ * Start query from a specific key (for pagination)
50
+ */
51
+ startFrom(key: Record<string, any>): QueryExecutor<Model, M>;
52
+ /**
53
+ * Returns the raw DynamoDB query parameters
54
+ */
55
+ dbParams(): any;
56
+ /**
57
+ * Executes the query and returns matching items
58
+ */
59
+ execute(): Promise<Model[]>;
60
+ /**
61
+ * Executes the query and returns result with pagination metadata
62
+ */
63
+ executeWithPagination(): Promise<QueryResult<Model>>;
64
+ }
65
+ /**
66
+ * Main Query Builder interface with type-safe where clause
67
+ */
68
+ export interface QueryBuilder<Model, M extends ModelDefinition = any> {
69
+ /**
70
+ * Build a condition expression using attributes and operators
71
+ * Usage: .where((attr, op) => op.eq(attr.username, 'juanca'))
72
+ * Usage: .where((attr, op) => op.and(
73
+ * op.eq(attr.username, 'juanca'),
74
+ * op.gt(attr.age, 18)
75
+ * ))
76
+ */
77
+ where(fn: (attr: AttrBuilder<Model>, op: OpBuilder) => Condition): QueryExecutor<Model, M>;
78
+ }
79
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../src/builders/query/types.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,iBAAiB,EAAE,WAAW,EAAE,SAAS,EAAE,SAAS,EAAE,MAAM,WAAW,CAAC;AACjF,OAAO,EAAE,eAAe,EAAE,MAAM,kBAAkB,CAAC;AAEnD;;GAEG;AACH,MAAM,WAAW,WAAW,CAAC,KAAK;IAChC;;OAEG;IACH,KAAK,EAAE,KAAK,EAAE,CAAC;IAEf;;OAEG;IACH,gBAAgB,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;IAEvC;;OAEG;IACH,KAAK,CAAC,EAAE,MAAM,CAAC;IAEf;;OAEG;IACH,YAAY,CAAC,EAAE,MAAM,CAAC;CACvB;AAED;;GAEG;AACH,MAAM,WAAW,aAAa,CAAC,KAAK,EAAE,CAAC,SAAS,eAAe,GAAG,GAAG,CAAE,SAAQ,iBAAiB,CAC9F,KAAK,EAAE,CACR;IACC;;OAEG;IACH,KAAK,CAAC,KAAK,EAAE,MAAM,GAAG,aAAa,CAAC,KAAK,EAAE,CAAC,CAAC,CAAC;IAE9C;;OAEG;IACH,gBAAgB,CAAC,OAAO,EAAE,OAAO,GAAG,aAAa,CAAC,KAAK,EAAE,CAAC,CAAC,CAAC;IAE5D;;OAEG;IACH,QAAQ,CAAC,SAAS,EAAE,MAAM,GAAG,aAAa,CAAC,KAAK,EAAE,CAAC,CAAC,CAAC;IAErD;;OAEG;IACH,MAAM,CAAC,KAAK,EAAE,CAAC,MAAM,KAAK,CAAC,EAAE,GAAG,aAAa,CAAC,KAAK,EAAE,CAAC,CAAC,CAAC;IAExD;;OAEG;IACH,cAAc,IAAI,aAAa,CAAC,KAAK,EAAE,CAAC,CAAC,CAAC;IAE1C;;OAEG;IACH,SAAS,CAAC,GAAG,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,GAAG,aAAa,CAAC,KAAK,EAAE,CAAC,CAAC,CAAC;IAE7D;;OAEG;IACH,QAAQ,IAAI,GAAG,CAAC;IAEhB;;OAEG;IACH,OAAO,IAAI,OAAO,CAAC,KAAK,EAAE,CAAC,CAAC;IAE5B;;OAEG;IACH,qBAAqB,IAAI,OAAO,CAAC,WAAW,CAAC,KAAK,CAAC,CAAC,CAAC;CACtD;AAED;;GAEG;AACH,MAAM,WAAW,YAAY,CAAC,KAAK,EAAE,CAAC,SAAS,eAAe,GAAG,GAAG;IAClE;;;;;;;OAOG;IACH,KAAK,CAAC,EAAE,EAAE,CAAC,IAAI,EAAE,WAAW,CAAC,KAAK,CAAC,EAAE,EAAE,EAAE,SAAS,KAAK,SAAS,GAAG,aAAa,CAAC,KAAK,EAAE,CAAC,CAAC,CAAC;CAC5F"}