@itzworking/single-table 0.0.162 → 0.0.197

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 (168) hide show
  1. package/dist-cjs/dynamodb/dynamodb.js +17 -0
  2. package/{dist → dist-cjs}/errors/decorators-error.js +1 -1
  3. package/{dist → dist-cjs}/errors/generate-update-expression-error.js +1 -1
  4. package/{dist → dist-cjs}/errors/index-decorator-error.js +1 -1
  5. package/{dist → dist-cjs}/errors/key-composition-error.js +1 -1
  6. package/{dist → dist-cjs}/errors/single-table-error.js +1 -1
  7. package/{dist → dist-cjs}/errors/single-table-item-format-error.js +1 -1
  8. package/dist-cjs/single-table-item/single-table-item.js +261 -0
  9. package/dist-cjs/single-table-item/utils/validate-entity-annotations.js +20 -0
  10. package/{dist → dist-cjs}/single-table-repository/single-table-repository.js +0 -22
  11. package/dist-es/decorators/editable/editable.js +4 -0
  12. package/dist-es/decorators/editable/index.js +2 -0
  13. package/dist-es/decorators/editable/is-editable.js +4 -0
  14. package/dist-es/decorators/editable/symbol.js +1 -0
  15. package/dist-es/decorators/entity/entity.js +6 -0
  16. package/dist-es/decorators/entity/get-entity-name.js +4 -0
  17. package/dist-es/decorators/entity/index.js +2 -0
  18. package/dist-es/decorators/entity/symbol.js +1 -0
  19. package/dist-es/decorators/gsis/get-pk-composition.js +4 -0
  20. package/dist-es/decorators/gsis/get-sk-composition.js +4 -0
  21. package/dist-es/decorators/gsis/gsis.js +15 -0
  22. package/dist-es/decorators/gsis/index.js +3 -0
  23. package/dist-es/decorators/gsis/symbols.js +8 -0
  24. package/dist-es/decorators/gsis/types.js +1 -0
  25. package/dist-es/decorators/index.js +4 -0
  26. package/dist-es/dynamodb/delete-dynamodb-item.js +24 -0
  27. package/dist-es/dynamodb/dynamodb.js +14 -0
  28. package/dist-es/dynamodb/get-dynamodb-item.js +24 -0
  29. package/dist-es/dynamodb/index.js +7 -0
  30. package/dist-es/dynamodb/put-dynamodb-item.js +28 -0
  31. package/dist-es/dynamodb/query-all-dynamodb.js +19 -0
  32. package/dist-es/dynamodb/query-dynamodb.js +28 -0
  33. package/dist-es/dynamodb/update-dynamodb-item.js +24 -0
  34. package/dist-es/errors/decorators-error.js +10 -0
  35. package/dist-es/errors/generate-update-expression-error.js +10 -0
  36. package/dist-es/errors/index-decorator-error.js +10 -0
  37. package/dist-es/errors/index.js +5 -0
  38. package/dist-es/errors/key-composition-error.js +10 -0
  39. package/dist-es/errors/single-table-error.js +10 -0
  40. package/dist-es/errors/single-table-item-format-error.js +10 -0
  41. package/dist-es/index.js +6 -0
  42. package/dist-es/single-table-item/index.js +1 -0
  43. package/dist-es/single-table-item/single-table-item.js +257 -0
  44. package/dist-es/single-table-item/utils/capitalize-first-letter.js +3 -0
  45. package/dist-es/single-table-item/utils/handle-composite-primary-key.js +33 -0
  46. package/dist-es/single-table-item/utils/index.js +3 -0
  47. package/dist-es/single-table-item/utils/validate-entity-annotations.js +16 -0
  48. package/dist-es/single-table-repository/index.js +2 -0
  49. package/dist-es/single-table-repository/single-table-repository.js +189 -0
  50. package/dist-es/single-table-repository/types.js +1 -0
  51. package/dist-es/types.js +1 -0
  52. package/{dist → dist-types}/decorators/editable/editable.d.ts +0 -1
  53. package/{dist → dist-types}/decorators/editable/index.d.ts +0 -1
  54. package/{dist → dist-types}/decorators/editable/is-editable.d.ts +0 -1
  55. package/{dist → dist-types}/decorators/editable/symbol.d.ts +0 -1
  56. package/{dist → dist-types}/decorators/entity/entity.d.ts +0 -1
  57. package/{dist → dist-types}/decorators/entity/get-entity-name.d.ts +0 -1
  58. package/{dist → dist-types}/decorators/entity/index.d.ts +0 -1
  59. package/{dist → dist-types}/decorators/entity/symbol.d.ts +0 -1
  60. package/{dist → dist-types}/decorators/gsis/get-pk-composition.d.ts +0 -1
  61. package/{dist → dist-types}/decorators/gsis/get-sk-composition.d.ts +0 -1
  62. package/{dist → dist-types}/decorators/gsis/gsis.d.ts +0 -1
  63. package/{dist → dist-types}/decorators/gsis/index.d.ts +0 -1
  64. package/{dist → dist-types}/decorators/gsis/symbols.d.ts +0 -1
  65. package/{dist → dist-types}/decorators/gsis/types.d.ts +0 -1
  66. package/{dist → dist-types}/decorators/index.d.ts +0 -1
  67. package/{dist → dist-types}/dynamodb/delete-dynamodb-item.d.ts +0 -1
  68. package/{dist → dist-types}/dynamodb/dynamodb.d.ts +0 -1
  69. package/{dist → dist-types}/dynamodb/get-dynamodb-item.d.ts +0 -1
  70. package/{dist → dist-types}/dynamodb/index.d.ts +0 -1
  71. package/{dist → dist-types}/dynamodb/put-dynamodb-item.d.ts +0 -1
  72. package/{dist → dist-types}/dynamodb/query-all-dynamodb.d.ts +0 -1
  73. package/{dist → dist-types}/dynamodb/query-dynamodb.d.ts +0 -1
  74. package/{dist → dist-types}/dynamodb/update-dynamodb-item.d.ts +0 -1
  75. package/{dist → dist-types}/errors/decorators-error.d.ts +0 -1
  76. package/{dist → dist-types}/errors/generate-update-expression-error.d.ts +0 -1
  77. package/{dist → dist-types}/errors/index-decorator-error.d.ts +0 -1
  78. package/{dist → dist-types}/errors/index.d.ts +0 -1
  79. package/{dist → dist-types}/errors/key-composition-error.d.ts +0 -1
  80. package/{dist → dist-types}/errors/single-table-error.d.ts +0 -1
  81. package/{dist → dist-types}/errors/single-table-item-format-error.d.ts +0 -1
  82. package/{dist → dist-types}/index.d.ts +0 -1
  83. package/{dist → dist-types}/single-table-item/index.d.ts +0 -1
  84. package/{dist → dist-types}/single-table-item/single-table-item.d.ts +0 -1
  85. package/{dist → dist-types}/single-table-item/utils/capitalize-first-letter.d.ts +0 -1
  86. package/{dist → dist-types}/single-table-item/utils/handle-composite-primary-key.d.ts +0 -1
  87. package/{dist → dist-types}/single-table-item/utils/index.d.ts +0 -1
  88. package/{dist → dist-types}/single-table-item/utils/validate-entity-annotations.d.ts +0 -1
  89. package/{dist → dist-types}/single-table-repository/index.d.ts +0 -1
  90. package/{dist → dist-types}/single-table-repository/single-table-repository.d.ts +0 -1
  91. package/{dist → dist-types}/single-table-repository/types.d.ts +0 -1
  92. package/{dist → dist-types}/types.d.ts +0 -1
  93. package/package.json +26 -26
  94. package/dist/decorators/editable/editable.d.ts.map +0 -1
  95. package/dist/decorators/editable/index.d.ts.map +0 -1
  96. package/dist/decorators/editable/is-editable.d.ts.map +0 -1
  97. package/dist/decorators/editable/symbol.d.ts.map +0 -1
  98. package/dist/decorators/entity/entity.d.ts.map +0 -1
  99. package/dist/decorators/entity/get-entity-name.d.ts.map +0 -1
  100. package/dist/decorators/entity/index.d.ts.map +0 -1
  101. package/dist/decorators/entity/symbol.d.ts.map +0 -1
  102. package/dist/decorators/gsis/get-pk-composition.d.ts.map +0 -1
  103. package/dist/decorators/gsis/get-sk-composition.d.ts.map +0 -1
  104. package/dist/decorators/gsis/gsis.d.ts.map +0 -1
  105. package/dist/decorators/gsis/index.d.ts.map +0 -1
  106. package/dist/decorators/gsis/symbols.d.ts.map +0 -1
  107. package/dist/decorators/gsis/types.d.ts.map +0 -1
  108. package/dist/decorators/index.d.ts.map +0 -1
  109. package/dist/dynamodb/delete-dynamodb-item.d.ts.map +0 -1
  110. package/dist/dynamodb/dynamodb.d.ts.map +0 -1
  111. package/dist/dynamodb/dynamodb.js +0 -24
  112. package/dist/dynamodb/get-dynamodb-item.d.ts.map +0 -1
  113. package/dist/dynamodb/index.d.ts.map +0 -1
  114. package/dist/dynamodb/put-dynamodb-item.d.ts.map +0 -1
  115. package/dist/dynamodb/query-all-dynamodb.d.ts.map +0 -1
  116. package/dist/dynamodb/query-dynamodb.d.ts.map +0 -1
  117. package/dist/dynamodb/update-dynamodb-item.d.ts.map +0 -1
  118. package/dist/errors/decorators-error.d.ts.map +0 -1
  119. package/dist/errors/generate-update-expression-error.d.ts.map +0 -1
  120. package/dist/errors/index-decorator-error.d.ts.map +0 -1
  121. package/dist/errors/index.d.ts.map +0 -1
  122. package/dist/errors/key-composition-error.d.ts.map +0 -1
  123. package/dist/errors/single-table-error.d.ts.map +0 -1
  124. package/dist/errors/single-table-item-format-error.d.ts.map +0 -1
  125. package/dist/index.d.ts.map +0 -1
  126. package/dist/single-table-item/index.d.ts.map +0 -1
  127. package/dist/single-table-item/single-table-item.d.ts.map +0 -1
  128. package/dist/single-table-item/single-table-item.js +0 -281
  129. package/dist/single-table-item/utils/capitalize-first-letter.d.ts.map +0 -1
  130. package/dist/single-table-item/utils/handle-composite-primary-key.d.ts.map +0 -1
  131. package/dist/single-table-item/utils/index.d.ts.map +0 -1
  132. package/dist/single-table-item/utils/validate-entity-annotations.d.ts.map +0 -1
  133. package/dist/single-table-item/utils/validate-entity-annotations.js +0 -38
  134. package/dist/single-table-repository/index.d.ts.map +0 -1
  135. package/dist/single-table-repository/single-table-repository.d.ts.map +0 -1
  136. package/dist/single-table-repository/types.d.ts.map +0 -1
  137. package/dist/types.d.ts.map +0 -1
  138. /package/{dist → dist-cjs}/decorators/editable/editable.js +0 -0
  139. /package/{dist → dist-cjs}/decorators/editable/index.js +0 -0
  140. /package/{dist → dist-cjs}/decorators/editable/is-editable.js +0 -0
  141. /package/{dist → dist-cjs}/decorators/editable/symbol.js +0 -0
  142. /package/{dist → dist-cjs}/decorators/entity/entity.js +0 -0
  143. /package/{dist → dist-cjs}/decorators/entity/get-entity-name.js +0 -0
  144. /package/{dist → dist-cjs}/decorators/entity/index.js +0 -0
  145. /package/{dist → dist-cjs}/decorators/entity/symbol.js +0 -0
  146. /package/{dist → dist-cjs}/decorators/gsis/get-pk-composition.js +0 -0
  147. /package/{dist → dist-cjs}/decorators/gsis/get-sk-composition.js +0 -0
  148. /package/{dist → dist-cjs}/decorators/gsis/gsis.js +0 -0
  149. /package/{dist → dist-cjs}/decorators/gsis/index.js +0 -0
  150. /package/{dist → dist-cjs}/decorators/gsis/symbols.js +0 -0
  151. /package/{dist → dist-cjs}/decorators/gsis/types.js +0 -0
  152. /package/{dist → dist-cjs}/decorators/index.js +0 -0
  153. /package/{dist → dist-cjs}/dynamodb/delete-dynamodb-item.js +0 -0
  154. /package/{dist → dist-cjs}/dynamodb/get-dynamodb-item.js +0 -0
  155. /package/{dist → dist-cjs}/dynamodb/index.js +0 -0
  156. /package/{dist → dist-cjs}/dynamodb/put-dynamodb-item.js +0 -0
  157. /package/{dist → dist-cjs}/dynamodb/query-all-dynamodb.js +0 -0
  158. /package/{dist → dist-cjs}/dynamodb/query-dynamodb.js +0 -0
  159. /package/{dist → dist-cjs}/dynamodb/update-dynamodb-item.js +0 -0
  160. /package/{dist → dist-cjs}/errors/index.js +0 -0
  161. /package/{dist → dist-cjs}/index.js +0 -0
  162. /package/{dist → dist-cjs}/single-table-item/index.js +0 -0
  163. /package/{dist → dist-cjs}/single-table-item/utils/capitalize-first-letter.js +0 -0
  164. /package/{dist → dist-cjs}/single-table-item/utils/handle-composite-primary-key.js +0 -0
  165. /package/{dist → dist-cjs}/single-table-item/utils/index.js +0 -0
  166. /package/{dist → dist-cjs}/single-table-repository/index.js +0 -0
  167. /package/{dist → dist-cjs}/single-table-repository/types.js +0 -0
  168. /package/{dist → dist-cjs}/types.js +0 -0
@@ -0,0 +1,10 @@
1
+ import { SingleTableError } from "./single-table-error";
2
+ export class DecoratorsError extends SingleTableError {
3
+ constructor(message) {
4
+ super({
5
+ message,
6
+ });
7
+ this.name = "DecoratorsError";
8
+ Object.setPrototypeOf(this, new.target.prototype);
9
+ }
10
+ }
@@ -0,0 +1,10 @@
1
+ import { SingleTableError } from "./single-table-error";
2
+ export class GenerateUpdateExpressionError extends SingleTableError {
3
+ constructor(message) {
4
+ super({
5
+ message,
6
+ });
7
+ this.name = "GenerateUpdateExpressionError";
8
+ Object.setPrototypeOf(this, new.target.prototype);
9
+ }
10
+ }
@@ -0,0 +1,10 @@
1
+ import { SingleTableError } from "./single-table-error";
2
+ export class IndexDecoratorError extends SingleTableError {
3
+ constructor(message) {
4
+ super({
5
+ message,
6
+ });
7
+ this.name = "IndexDecoratorError";
8
+ Object.setPrototypeOf(this, new.target.prototype);
9
+ }
10
+ }
@@ -0,0 +1,5 @@
1
+ export * from "./decorators-error";
2
+ export * from "./generate-update-expression-error";
3
+ export * from "./index-decorator-error";
4
+ export * from "./single-table-error";
5
+ export * from "./single-table-item-format-error";
@@ -0,0 +1,10 @@
1
+ import { SingleTableError } from "./single-table-error";
2
+ export class KeyCompositionError extends SingleTableError {
3
+ constructor(message) {
4
+ super({
5
+ message,
6
+ });
7
+ this.name = "KeyCompositionError";
8
+ Object.setPrototypeOf(this, new.target.prototype);
9
+ }
10
+ }
@@ -0,0 +1,10 @@
1
+ export class SingleTableError extends Error {
2
+ statusCode;
3
+ constructor(props) {
4
+ super(JSON.stringify({ props }));
5
+ const { statusCode = 500 } = props;
6
+ this.name = "SingleTableError";
7
+ this.statusCode = statusCode;
8
+ Object.setPrototypeOf(this, new.target.prototype);
9
+ }
10
+ }
@@ -0,0 +1,10 @@
1
+ import { SingleTableError } from "./single-table-error";
2
+ export class SingleTableItemFormatError extends SingleTableError {
3
+ constructor(message) {
4
+ super({
5
+ message,
6
+ });
7
+ this.name = "SingleTableItemFormatError";
8
+ Object.setPrototypeOf(this, new.target.prototype);
9
+ }
10
+ }
@@ -0,0 +1,6 @@
1
+ export * from "./types";
2
+ export * from "./decorators";
3
+ export * from "./dynamodb";
4
+ export * from "./errors";
5
+ export * from "./single-table-item";
6
+ export * from "./single-table-repository";
@@ -0,0 +1 @@
1
+ export * from "./single-table-item";
@@ -0,0 +1,257 @@
1
+ import { __decorate } from "tslib";
2
+ import { v4 as uuid } from "uuid";
3
+ import { Editable, getEntityName, getPKComposition, getSKComposition, isEditable, } from "../decorators";
4
+ import { capitalizeFirstLetter, handleCompositePrimaryKey, validateEntityAnnotations, } from "./utils";
5
+ import { GenerateUpdateExpressionError, IndexDecoratorError, SingleTableItemFormatError, } from "../errors";
6
+ import { Attribute, AttributeType, DecoratedClass, listAttributes, } from "@itzworking/decorated-class";
7
+ export class SingleTableItem extends DecoratedClass {
8
+ id;
9
+ createdAt;
10
+ updatedAt;
11
+ createdBy;
12
+ updatedBy;
13
+ deletedBy;
14
+ deletedAt;
15
+ constructor(props = {}) {
16
+ super(props);
17
+ validateEntityAnnotations(this);
18
+ if (!props?.id) {
19
+ this.generateId();
20
+ }
21
+ if (!props?.createdAt) {
22
+ this.createdAt = new Date();
23
+ }
24
+ if (!props?.updatedAt) {
25
+ this.updatedAt = new Date();
26
+ }
27
+ }
28
+ generateId() {
29
+ this.id = uuid();
30
+ return this.id;
31
+ }
32
+ type() {
33
+ return getEntityName(this);
34
+ }
35
+ pk() {
36
+ const keys = getPKComposition(this);
37
+ if (!keys?.length) {
38
+ throw new IndexDecoratorError(`@Entity("${this.type()}") @Index: PK is not defined`);
39
+ }
40
+ return handleCompositePrimaryKey(this, keys);
41
+ }
42
+ sk() {
43
+ const keys = getSKComposition(this);
44
+ if (!keys?.length) {
45
+ throw new IndexDecoratorError(`@Entity("${this.type()}") @Index: SK is not defined`);
46
+ }
47
+ return handleCompositePrimaryKey(this, keys);
48
+ }
49
+ key() {
50
+ return {
51
+ PK: this.pk(),
52
+ SK: this.sk(),
53
+ };
54
+ }
55
+ gsi1pk() {
56
+ return handleCompositePrimaryKey(this, getPKComposition(this, "GSI1"));
57
+ }
58
+ gsi1sk() {
59
+ return handleCompositePrimaryKey(this, getSKComposition(this, "GSI1"));
60
+ }
61
+ gsi2pk() {
62
+ return handleCompositePrimaryKey(this, getPKComposition(this, "GSI2"));
63
+ }
64
+ gsi2sk() {
65
+ return handleCompositePrimaryKey(this, getSKComposition(this, "GSI2"));
66
+ }
67
+ gsi3pk() {
68
+ return handleCompositePrimaryKey(this, getPKComposition(this, "GSI3"));
69
+ }
70
+ gsi3sk() {
71
+ return handleCompositePrimaryKey(this, getSKComposition(this, "GSI3"));
72
+ }
73
+ gsi4pk() {
74
+ return handleCompositePrimaryKey(this, getPKComposition(this, "GSI4"));
75
+ }
76
+ gsi4sk() {
77
+ return handleCompositePrimaryKey(this, getSKComposition(this, "GSI4"));
78
+ }
79
+ gsi5pk() {
80
+ return handleCompositePrimaryKey(this, getPKComposition(this, "GSI5"));
81
+ }
82
+ gsi5sk() {
83
+ return handleCompositePrimaryKey(this, getSKComposition(this, "GSI5"));
84
+ }
85
+ generateUpdateExpression(attributes = []) {
86
+ const attributesToUpdate = [];
87
+ const entityAttributes = listAttributes(this);
88
+ if (attributes?.length) {
89
+ for (const attribute of attributes) {
90
+ if (entityAttributes.find((ef) => ef.attributeName === attribute)) {
91
+ attributesToUpdate.push(attribute);
92
+ }
93
+ else {
94
+ throw new GenerateUpdateExpressionError(`@Entity("${this.type()}"): ${attribute} is not an @Attribute`);
95
+ }
96
+ }
97
+ }
98
+ else {
99
+ for (const attribute of entityAttributes) {
100
+ if (!isEditable(this, attribute.attributeName)) {
101
+ continue;
102
+ }
103
+ attributesToUpdate.push(attribute.attributeName);
104
+ }
105
+ }
106
+ if (attributesToUpdate.length === 0) {
107
+ throw new GenerateUpdateExpressionError(`@Entity("${this.type()}"): attributesToUpdate is empty; attributes = ${attributes}`);
108
+ }
109
+ else {
110
+ const indexComposition = {
111
+ PK: getPKComposition(this),
112
+ SK: getSKComposition(this),
113
+ };
114
+ const indexPkSkAttributes = [
115
+ ...(indexComposition.PK || []),
116
+ ...(indexComposition.SK || []),
117
+ ];
118
+ const notAllowedAttributes = indexPkSkAttributes.filter((attribute) => attributesToUpdate.includes(attribute));
119
+ if (notAllowedAttributes.length > 0) {
120
+ throw new GenerateUpdateExpressionError(`@Entity("${this.type()}"): cannot update @Index notAllowedAttributes = ${notAllowedAttributes}`);
121
+ }
122
+ }
123
+ const attributeValues = {};
124
+ const attributeNames = {};
125
+ const namesAndValues = [];
126
+ const attributesToRemove = [];
127
+ const gsis = {
128
+ GSI1: {
129
+ PK: getPKComposition(this, "GSI1"),
130
+ SK: getSKComposition(this, "GSI1"),
131
+ },
132
+ GSI2: {
133
+ PK: getPKComposition(this, "GSI2"),
134
+ SK: getSKComposition(this, "GSI2"),
135
+ },
136
+ GSI3: {
137
+ PK: getPKComposition(this, "GSI3"),
138
+ SK: getSKComposition(this, "GSI3"),
139
+ },
140
+ GSI4: {
141
+ PK: getPKComposition(this, "GSI4"),
142
+ SK: getSKComposition(this, "GSI4"),
143
+ },
144
+ GSI5: {
145
+ PK: getPKComposition(this, "GSI5"),
146
+ SK: getSKComposition(this, "GSI5"),
147
+ },
148
+ };
149
+ for (const [gsiKey, gsiComposition] of Object.entries(gsis)) {
150
+ for (const [gsiAttributeKey, gsiAttributeComposition] of Object.entries(gsiComposition)) {
151
+ if (gsiAttributeComposition?.some((key) => attributesToUpdate.includes(key))) {
152
+ attributeNames[`#key${gsiKey}${gsiAttributeKey}`] = `${gsiKey}${gsiAttributeKey}`;
153
+ attributeValues[`:value${gsiKey}${gsiAttributeKey}`] = this[`${gsiKey}${gsiAttributeKey}`.toLowerCase()]();
154
+ namesAndValues.push(`#key${gsiKey}${gsiAttributeKey} = :value${gsiKey}${gsiAttributeKey}`);
155
+ }
156
+ }
157
+ }
158
+ for (const key of attributesToUpdate) {
159
+ const keyToUse = capitalizeFirstLetter(key);
160
+ const value = this[key];
161
+ attributeNames[`#key${keyToUse}`] = key;
162
+ if (value === undefined) {
163
+ attributesToRemove.push(`#key${keyToUse}`);
164
+ }
165
+ else {
166
+ attributeValues[`:value${keyToUse}`] =
167
+ value instanceof Date ? value.toISOString() : value;
168
+ namesAndValues.push(`#key${keyToUse} = :value${keyToUse}`);
169
+ }
170
+ }
171
+ return {
172
+ UpdateExpression: ((namesAndValues.length ? `SET ${namesAndValues.join(", ")} ` : "") +
173
+ (attributesToRemove.length
174
+ ? `REMOVE ${attributesToRemove.join(", ")}`
175
+ : "")).trim(),
176
+ ExpressionAttributeNames: attributeNames,
177
+ ExpressionAttributeValues: attributeValues,
178
+ };
179
+ }
180
+ toSingleTableItem() {
181
+ const result = {
182
+ type: this.type(),
183
+ ...this.key(),
184
+ };
185
+ if (this.gsi1pk() && this.gsi1sk()) {
186
+ result.GSI1PK = this.gsi1pk();
187
+ result.GSI1SK = this.gsi1sk();
188
+ }
189
+ if (this.gsi2pk() && this.gsi2sk()) {
190
+ result.GSI2PK = this.gsi2pk();
191
+ result.GSI2SK = this.gsi2sk();
192
+ }
193
+ if (this.gsi3pk() && this.gsi3sk()) {
194
+ result.GSI3PK = this.gsi3pk();
195
+ result.GSI3SK = this.gsi3sk();
196
+ }
197
+ if (this.gsi4pk() && this.gsi4sk()) {
198
+ result.GSI4PK = this.gsi4pk();
199
+ result.GSI4SK = this.gsi4sk();
200
+ }
201
+ if (this.gsi5pk() && this.gsi5sk()) {
202
+ result.GSI5PK = this.gsi5pk();
203
+ result.GSI5SK = this.gsi5sk();
204
+ }
205
+ const attributes = listAttributes(this);
206
+ const reservedKeys = [
207
+ "type",
208
+ "PK",
209
+ "SK",
210
+ "GSI1PK",
211
+ "GSI1SK",
212
+ "GSI2PK",
213
+ "GSI2SK",
214
+ "GSI3PK",
215
+ "GSI3SK",
216
+ "GSI4PK",
217
+ "GSI4SK",
218
+ "GSI5PK",
219
+ "GSI5SK",
220
+ ];
221
+ const reservedKeysInUse = reservedKeys.filter((reservedKey) => attributes.find((f) => f.attributeName === reservedKey));
222
+ if (reservedKeysInUse.length > 0) {
223
+ throw new SingleTableItemFormatError(`@Entity("${this.type()}"): cannot use reserved keys in attributes = ${reservedKeysInUse}`);
224
+ }
225
+ for (const attribute of attributes) {
226
+ const value = this[attribute.attributeName];
227
+ if (value !== undefined) {
228
+ result[attribute.attributeName] =
229
+ value instanceof Date ? value.toISOString() : value;
230
+ }
231
+ }
232
+ return result;
233
+ }
234
+ }
235
+ __decorate([
236
+ Attribute(AttributeType.String)
237
+ ], SingleTableItem.prototype, "id", void 0);
238
+ __decorate([
239
+ Attribute(AttributeType.Date)
240
+ ], SingleTableItem.prototype, "createdAt", void 0);
241
+ __decorate([
242
+ Editable,
243
+ Attribute(AttributeType.Date)
244
+ ], SingleTableItem.prototype, "updatedAt", void 0);
245
+ __decorate([
246
+ Attribute(AttributeType.String)
247
+ ], SingleTableItem.prototype, "createdBy", void 0);
248
+ __decorate([
249
+ Editable,
250
+ Attribute(AttributeType.String)
251
+ ], SingleTableItem.prototype, "updatedBy", void 0);
252
+ __decorate([
253
+ Attribute(AttributeType.String)
254
+ ], SingleTableItem.prototype, "deletedBy", void 0);
255
+ __decorate([
256
+ Attribute(AttributeType.Date)
257
+ ], SingleTableItem.prototype, "deletedAt", void 0);
@@ -0,0 +1,3 @@
1
+ export const capitalizeFirstLetter = (s) => {
2
+ return s.charAt(0).toUpperCase() + s.slice(1);
3
+ };
@@ -0,0 +1,33 @@
1
+ import { AttributeType, listAttributes, PrimitiveType, } from "@itzworking/decorated-class";
2
+ import { KeyCompositionError } from "../../errors/key-composition-error";
3
+ const isPrimitiveType = (type) => {
4
+ return Object.values(PrimitiveType).includes(type);
5
+ };
6
+ export const handleCompositePrimaryKey = (target, keys) => {
7
+ if (!keys?.length) {
8
+ return "";
9
+ }
10
+ const entityAttributes = listAttributes(target);
11
+ const result = [];
12
+ for (const key of keys) {
13
+ const entityAttribute = entityAttributes.find((attDef) => attDef.attributeName === key);
14
+ if (entityAttribute) {
15
+ if (!isPrimitiveType(entityAttribute?.attributeType)) {
16
+ throw new KeyCompositionError(`Composite primary key must all be primitive type - @Entity("${target.type()}"): ${key}`);
17
+ }
18
+ if (target[key] === undefined) {
19
+ result.push("null");
20
+ }
21
+ else if (entityAttribute.attributeType === AttributeType.Date) {
22
+ result.push(target[key].toISOString());
23
+ }
24
+ else {
25
+ result.push(target[key]);
26
+ }
27
+ }
28
+ else {
29
+ result.push(key);
30
+ }
31
+ }
32
+ return result.join("#");
33
+ };
@@ -0,0 +1,3 @@
1
+ export * from "./capitalize-first-letter";
2
+ export * from "./handle-composite-primary-key";
3
+ export * from "./validate-entity-annotations";
@@ -0,0 +1,16 @@
1
+ import { DecoratorsError } from "../../errors";
2
+ export const validateEntityAnnotations = (entity) => {
3
+ const errors = [];
4
+ if (!entity.type()) {
5
+ errors.push("missing @Entity annotation on SingleTableItem class");
6
+ }
7
+ try {
8
+ entity.key();
9
+ }
10
+ catch (e) {
11
+ errors.push("missing @Index annotation on SingleTableItem class");
12
+ }
13
+ if (errors.length) {
14
+ throw new DecoratorsError(errors.join(","));
15
+ }
16
+ };
@@ -0,0 +1,2 @@
1
+ export * from "./single-table-repository";
2
+ export * from "./types";
@@ -0,0 +1,189 @@
1
+ import { deleteDynamodbItem, getDynamodbItem, putDynamodbItem, queryAllDynamodb, queryDynamodb, updateDynamodbItem, } from "../dynamodb";
2
+ import { getContext, NotFoundError } from "@itzworking/powertools";
3
+ export class SingleTableRepository {
4
+ tableName = process.env.MAIN_TABLE_NAME || process.env.MAIN_TABLE_TABLE_NAME || "";
5
+ getUserId() {
6
+ try {
7
+ return getContext().user?.id || "unknown";
8
+ }
9
+ catch (e) {
10
+ return "unknown";
11
+ }
12
+ }
13
+ async insert(entity, options) {
14
+ const now = new Date();
15
+ entity.createdAt = now;
16
+ entity.updatedAt = now;
17
+ const userId = this.getUserId();
18
+ entity.createdBy = userId;
19
+ entity.updatedBy = userId;
20
+ let retryLimit = options?.override ? 1 : 3;
21
+ while (retryLimit > 0) {
22
+ try {
23
+ await putDynamodbItem({
24
+ TableName: this.tableName || "",
25
+ Item: entity.toSingleTableItem(),
26
+ ConditionExpression: options?.override
27
+ ? undefined
28
+ : "attribute_not_exists(PK) AND attribute_not_exists(SK)",
29
+ ...options?.input,
30
+ });
31
+ retryLimit = 0;
32
+ }
33
+ catch (error) {
34
+ if (error.name === "ConditionalCheckFailedException" &&
35
+ retryLimit > 1) {
36
+ entity.generateId();
37
+ retryLimit--;
38
+ }
39
+ else {
40
+ throw error;
41
+ }
42
+ }
43
+ }
44
+ return entity;
45
+ }
46
+ async get(entity, options) {
47
+ const { Item: item } = await getDynamodbItem({
48
+ TableName: this.tableName || "",
49
+ Key: entity.key(),
50
+ ...options?.input,
51
+ });
52
+ if (!item) {
53
+ throw new NotFoundError(`Item not found: ${JSON.stringify(entity.key())}`);
54
+ }
55
+ const EntityClass = Object.getPrototypeOf(entity).constructor;
56
+ return new EntityClass(item);
57
+ }
58
+ async update(entity, options) {
59
+ if (options?.attributes?.length) {
60
+ if (!options.attributes.includes("updatedAt")) {
61
+ options.attributes.push("updatedAt");
62
+ }
63
+ if (!options.attributes.includes("updatedBy")) {
64
+ options.attributes.push("updatedBy");
65
+ }
66
+ }
67
+ entity.updatedAt = new Date();
68
+ entity.updatedBy = this.getUserId();
69
+ const dynamodbResponse = await updateDynamodbItem({
70
+ TableName: this.tableName || "",
71
+ Key: entity.key(),
72
+ ReturnValues: "ALL_NEW",
73
+ ...entity.generateUpdateExpression((options?.attributes || [])),
74
+ ...options?.input,
75
+ });
76
+ const EntityClass = Object.getPrototypeOf(entity).constructor;
77
+ return new EntityClass(dynamodbResponse?.Attributes ?? entity);
78
+ }
79
+ async delete(entity, options) {
80
+ entity.deletedAt = new Date();
81
+ entity.deletedBy = this.getUserId();
82
+ await updateDynamodbItem({
83
+ TableName: options?.input?.TableName || this.tableName || "",
84
+ Key: options?.input?.Key || entity.key(),
85
+ ReturnValues: "NONE",
86
+ ...entity.generateUpdateExpression(["deletedAt", "deletedBy"]),
87
+ });
88
+ await deleteDynamodbItem({
89
+ TableName: this.tableName || "",
90
+ Key: entity.key(),
91
+ ...options?.input,
92
+ });
93
+ }
94
+ async query(entity, options) {
95
+ return this.queryMultipleEntityTypes(entity, {
96
+ ...options,
97
+ entityClasses: [entity.constructor],
98
+ });
99
+ }
100
+ async queryMultipleEntityTypes(entity, options) {
101
+ if (options.sortKey && Object.keys(options.sortKey).length > 1) {
102
+ throw new Error("Only one sort key condition is allowed");
103
+ }
104
+ const typeAndConstructor = {};
105
+ for (const entityClass of options.entityClasses) {
106
+ typeAndConstructor[new entityClass().type()] = entityClass;
107
+ }
108
+ const index = options.index || "";
109
+ let KeyConditionExpression = "#pk = :pk";
110
+ const ExpressionAttributeNames = {
111
+ "#pk": `${index}PK`,
112
+ };
113
+ const ExpressionAttributeValues = {
114
+ ":pk": `${entity[`${index.toLowerCase()}pk`]()}`,
115
+ };
116
+ if (options.sortKey && Object.keys(options.sortKey).length > 0) {
117
+ ExpressionAttributeNames["#sk"] = `${index}SK`;
118
+ if (options.sortKey.equalTo !== undefined) {
119
+ KeyConditionExpression += " and #sk = :sk";
120
+ ExpressionAttributeValues[":sk"] = options.sortKey.equalTo;
121
+ }
122
+ else if (options.sortKey.lessThanOrEqualTo !== undefined) {
123
+ KeyConditionExpression += " and #sk <= :sk";
124
+ ExpressionAttributeValues[":sk"] = options.sortKey.lessThanOrEqualTo;
125
+ }
126
+ else if (options.sortKey.lessThan !== undefined) {
127
+ KeyConditionExpression += " and #sk < :sk";
128
+ ExpressionAttributeValues[":sk"] = options.sortKey.lessThan;
129
+ }
130
+ else if (options.sortKey.greaterThanOrEqualTo !== undefined) {
131
+ KeyConditionExpression += " and #sk >= :sk";
132
+ ExpressionAttributeValues[":sk"] = options.sortKey.greaterThanOrEqualTo;
133
+ }
134
+ else if (options.sortKey.greaterThan !== undefined) {
135
+ KeyConditionExpression += " and #sk > :sk";
136
+ ExpressionAttributeValues[":sk"] = options.sortKey.greaterThan;
137
+ }
138
+ else if (options.sortKey.between !== undefined &&
139
+ options.sortKey.between.length === 2) {
140
+ KeyConditionExpression += " and #sk between :sk1 and :sk2";
141
+ ExpressionAttributeValues[":sk"] = options.sortKey.between[0];
142
+ ExpressionAttributeValues[":sk2"] = options.sortKey.between[1];
143
+ }
144
+ else if (options.sortKey.beginsWith !== undefined) {
145
+ KeyConditionExpression += " and begins_with(#sk, :sk)";
146
+ ExpressionAttributeValues[":sk"] = options.sortKey.beginsWith;
147
+ }
148
+ else {
149
+ throw new Error("Invalid sort key condition");
150
+ }
151
+ }
152
+ const response = {
153
+ items: [],
154
+ };
155
+ let dynamodbItems;
156
+ if (options?.queryAll) {
157
+ dynamodbItems = await queryAllDynamodb({
158
+ TableName: this.tableName || "",
159
+ IndexName: options.index,
160
+ KeyConditionExpression,
161
+ ExpressionAttributeNames,
162
+ ExpressionAttributeValues,
163
+ ...options?.input,
164
+ });
165
+ }
166
+ else {
167
+ const { Items, LastEvaluatedKey } = await queryDynamodb({
168
+ TableName: this.tableName || "",
169
+ IndexName: options.index,
170
+ KeyConditionExpression,
171
+ ExpressionAttributeNames,
172
+ ExpressionAttributeValues,
173
+ ...options?.input,
174
+ });
175
+ if (LastEvaluatedKey) {
176
+ response.lastEvaluatedKey = LastEvaluatedKey;
177
+ }
178
+ dynamodbItems = Items || [];
179
+ }
180
+ for (const dynamodbItem of dynamodbItems) {
181
+ const entityClass = typeAndConstructor[dynamodbItem.type];
182
+ if (!entityClass) {
183
+ throw new Error(`Entity class not found for type ${dynamodbItem.type}`);
184
+ }
185
+ response.items.push(new entityClass(dynamodbItem));
186
+ }
187
+ return response;
188
+ }
189
+ }
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1 @@
1
+ export {};
@@ -1,4 +1,3 @@
1
1
  export declare const Editable: (target: any, context: string | (ClassFieldDecoratorContext & {
2
2
  name: string;
3
3
  })) => void;
4
- //# sourceMappingURL=editable.d.ts.map
@@ -1,3 +1,2 @@
1
1
  export * from "./editable";
2
2
  export * from "./is-editable";
3
- //# sourceMappingURL=index.d.ts.map
@@ -1,2 +1 @@
1
1
  export declare const isEditable: (target: any, propertyKey: string) => boolean;
2
- //# sourceMappingURL=is-editable.d.ts.map
@@ -1,2 +1 @@
1
1
  export declare const symbol: unique symbol;
2
- //# sourceMappingURL=symbol.d.ts.map
@@ -1,4 +1,3 @@
1
1
  export declare const Entity: (name: string) => <C extends {
2
2
  new (...args: any[]): any;
3
3
  }>(constructor: C, ctx?: ClassDecoratorContext) => void;
4
- //# sourceMappingURL=entity.d.ts.map
@@ -1,2 +1 @@
1
1
  export declare const getEntityName: (target: any) => any;
2
- //# sourceMappingURL=get-entity-name.d.ts.map
@@ -1,3 +1,2 @@
1
1
  export * from "./entity";
2
2
  export * from "./get-entity-name";
3
- //# sourceMappingURL=index.d.ts.map
@@ -1,2 +1 @@
1
1
  export declare const symbol: unique symbol;
2
- //# sourceMappingURL=symbol.d.ts.map
@@ -1,3 +1,2 @@
1
1
  import { symbols } from "./symbols";
2
2
  export declare const getPKComposition: (target: any, name?: keyof typeof symbols) => string[];
3
- //# sourceMappingURL=get-pk-composition.d.ts.map
@@ -1,3 +1,2 @@
1
1
  import { symbols } from "./symbols";
2
2
  export declare const getSKComposition: (target: any, name?: keyof typeof symbols) => string[];
3
- //# sourceMappingURL=get-sk-composition.d.ts.map
@@ -17,4 +17,3 @@ export declare const GSI4: <T>(keyComposition: CompositePrimaryKeyComposition<T>
17
17
  export declare const GSI5: <T>(keyComposition: CompositePrimaryKeyComposition<T>) => (constructor: {
18
18
  new (...args: any[]): T;
19
19
  }, context?: ClassDecoratorContext) => void;
20
- //# sourceMappingURL=gsis.d.ts.map
@@ -1,4 +1,3 @@
1
1
  export * from "./gsis";
2
2
  export * from "./get-pk-composition";
3
3
  export * from "./get-sk-composition";
4
- //# sourceMappingURL=index.d.ts.map