@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.
- package/dist-cjs/dynamodb/dynamodb.js +17 -0
- package/{dist → dist-cjs}/errors/decorators-error.js +1 -1
- package/{dist → dist-cjs}/errors/generate-update-expression-error.js +1 -1
- package/{dist → dist-cjs}/errors/index-decorator-error.js +1 -1
- package/{dist → dist-cjs}/errors/key-composition-error.js +1 -1
- package/{dist → dist-cjs}/errors/single-table-error.js +1 -1
- package/{dist → dist-cjs}/errors/single-table-item-format-error.js +1 -1
- package/dist-cjs/single-table-item/single-table-item.js +261 -0
- package/dist-cjs/single-table-item/utils/validate-entity-annotations.js +20 -0
- package/{dist → dist-cjs}/single-table-repository/single-table-repository.js +0 -22
- package/dist-es/decorators/editable/editable.js +4 -0
- package/dist-es/decorators/editable/index.js +2 -0
- package/dist-es/decorators/editable/is-editable.js +4 -0
- package/dist-es/decorators/editable/symbol.js +1 -0
- package/dist-es/decorators/entity/entity.js +6 -0
- package/dist-es/decorators/entity/get-entity-name.js +4 -0
- package/dist-es/decorators/entity/index.js +2 -0
- package/dist-es/decorators/entity/symbol.js +1 -0
- package/dist-es/decorators/gsis/get-pk-composition.js +4 -0
- package/dist-es/decorators/gsis/get-sk-composition.js +4 -0
- package/dist-es/decorators/gsis/gsis.js +15 -0
- package/dist-es/decorators/gsis/index.js +3 -0
- package/dist-es/decorators/gsis/symbols.js +8 -0
- package/dist-es/decorators/gsis/types.js +1 -0
- package/dist-es/decorators/index.js +4 -0
- package/dist-es/dynamodb/delete-dynamodb-item.js +24 -0
- package/dist-es/dynamodb/dynamodb.js +14 -0
- package/dist-es/dynamodb/get-dynamodb-item.js +24 -0
- package/dist-es/dynamodb/index.js +7 -0
- package/dist-es/dynamodb/put-dynamodb-item.js +28 -0
- package/dist-es/dynamodb/query-all-dynamodb.js +19 -0
- package/dist-es/dynamodb/query-dynamodb.js +28 -0
- package/dist-es/dynamodb/update-dynamodb-item.js +24 -0
- package/dist-es/errors/decorators-error.js +10 -0
- package/dist-es/errors/generate-update-expression-error.js +10 -0
- package/dist-es/errors/index-decorator-error.js +10 -0
- package/dist-es/errors/index.js +5 -0
- package/dist-es/errors/key-composition-error.js +10 -0
- package/dist-es/errors/single-table-error.js +10 -0
- package/dist-es/errors/single-table-item-format-error.js +10 -0
- package/dist-es/index.js +6 -0
- package/dist-es/single-table-item/index.js +1 -0
- package/dist-es/single-table-item/single-table-item.js +257 -0
- package/dist-es/single-table-item/utils/capitalize-first-letter.js +3 -0
- package/dist-es/single-table-item/utils/handle-composite-primary-key.js +33 -0
- package/dist-es/single-table-item/utils/index.js +3 -0
- package/dist-es/single-table-item/utils/validate-entity-annotations.js +16 -0
- package/dist-es/single-table-repository/index.js +2 -0
- package/dist-es/single-table-repository/single-table-repository.js +189 -0
- package/dist-es/single-table-repository/types.js +1 -0
- package/dist-es/types.js +1 -0
- package/{dist → dist-types}/decorators/editable/editable.d.ts +0 -1
- package/{dist → dist-types}/decorators/editable/index.d.ts +0 -1
- package/{dist → dist-types}/decorators/editable/is-editable.d.ts +0 -1
- package/{dist → dist-types}/decorators/editable/symbol.d.ts +0 -1
- package/{dist → dist-types}/decorators/entity/entity.d.ts +0 -1
- package/{dist → dist-types}/decorators/entity/get-entity-name.d.ts +0 -1
- package/{dist → dist-types}/decorators/entity/index.d.ts +0 -1
- package/{dist → dist-types}/decorators/entity/symbol.d.ts +0 -1
- package/{dist → dist-types}/decorators/gsis/get-pk-composition.d.ts +0 -1
- package/{dist → dist-types}/decorators/gsis/get-sk-composition.d.ts +0 -1
- package/{dist → dist-types}/decorators/gsis/gsis.d.ts +0 -1
- package/{dist → dist-types}/decorators/gsis/index.d.ts +0 -1
- package/{dist → dist-types}/decorators/gsis/symbols.d.ts +0 -1
- package/{dist → dist-types}/decorators/gsis/types.d.ts +0 -1
- package/{dist → dist-types}/decorators/index.d.ts +0 -1
- package/{dist → dist-types}/dynamodb/delete-dynamodb-item.d.ts +0 -1
- package/{dist → dist-types}/dynamodb/dynamodb.d.ts +0 -1
- package/{dist → dist-types}/dynamodb/get-dynamodb-item.d.ts +0 -1
- package/{dist → dist-types}/dynamodb/index.d.ts +0 -1
- package/{dist → dist-types}/dynamodb/put-dynamodb-item.d.ts +0 -1
- package/{dist → dist-types}/dynamodb/query-all-dynamodb.d.ts +0 -1
- package/{dist → dist-types}/dynamodb/query-dynamodb.d.ts +0 -1
- package/{dist → dist-types}/dynamodb/update-dynamodb-item.d.ts +0 -1
- package/{dist → dist-types}/errors/decorators-error.d.ts +0 -1
- package/{dist → dist-types}/errors/generate-update-expression-error.d.ts +0 -1
- package/{dist → dist-types}/errors/index-decorator-error.d.ts +0 -1
- package/{dist → dist-types}/errors/index.d.ts +0 -1
- package/{dist → dist-types}/errors/key-composition-error.d.ts +0 -1
- package/{dist → dist-types}/errors/single-table-error.d.ts +0 -1
- package/{dist → dist-types}/errors/single-table-item-format-error.d.ts +0 -1
- package/{dist → dist-types}/index.d.ts +0 -1
- package/{dist → dist-types}/single-table-item/index.d.ts +0 -1
- package/{dist → dist-types}/single-table-item/single-table-item.d.ts +0 -1
- package/{dist → dist-types}/single-table-item/utils/capitalize-first-letter.d.ts +0 -1
- package/{dist → dist-types}/single-table-item/utils/handle-composite-primary-key.d.ts +0 -1
- package/{dist → dist-types}/single-table-item/utils/index.d.ts +0 -1
- package/{dist → dist-types}/single-table-item/utils/validate-entity-annotations.d.ts +0 -1
- package/{dist → dist-types}/single-table-repository/index.d.ts +0 -1
- package/{dist → dist-types}/single-table-repository/single-table-repository.d.ts +0 -1
- package/{dist → dist-types}/single-table-repository/types.d.ts +0 -1
- package/{dist → dist-types}/types.d.ts +0 -1
- package/package.json +26 -26
- package/dist/decorators/editable/editable.d.ts.map +0 -1
- package/dist/decorators/editable/index.d.ts.map +0 -1
- package/dist/decorators/editable/is-editable.d.ts.map +0 -1
- package/dist/decorators/editable/symbol.d.ts.map +0 -1
- package/dist/decorators/entity/entity.d.ts.map +0 -1
- package/dist/decorators/entity/get-entity-name.d.ts.map +0 -1
- package/dist/decorators/entity/index.d.ts.map +0 -1
- package/dist/decorators/entity/symbol.d.ts.map +0 -1
- package/dist/decorators/gsis/get-pk-composition.d.ts.map +0 -1
- package/dist/decorators/gsis/get-sk-composition.d.ts.map +0 -1
- package/dist/decorators/gsis/gsis.d.ts.map +0 -1
- package/dist/decorators/gsis/index.d.ts.map +0 -1
- package/dist/decorators/gsis/symbols.d.ts.map +0 -1
- package/dist/decorators/gsis/types.d.ts.map +0 -1
- package/dist/decorators/index.d.ts.map +0 -1
- package/dist/dynamodb/delete-dynamodb-item.d.ts.map +0 -1
- package/dist/dynamodb/dynamodb.d.ts.map +0 -1
- package/dist/dynamodb/dynamodb.js +0 -24
- package/dist/dynamodb/get-dynamodb-item.d.ts.map +0 -1
- package/dist/dynamodb/index.d.ts.map +0 -1
- package/dist/dynamodb/put-dynamodb-item.d.ts.map +0 -1
- package/dist/dynamodb/query-all-dynamodb.d.ts.map +0 -1
- package/dist/dynamodb/query-dynamodb.d.ts.map +0 -1
- package/dist/dynamodb/update-dynamodb-item.d.ts.map +0 -1
- package/dist/errors/decorators-error.d.ts.map +0 -1
- package/dist/errors/generate-update-expression-error.d.ts.map +0 -1
- package/dist/errors/index-decorator-error.d.ts.map +0 -1
- package/dist/errors/index.d.ts.map +0 -1
- package/dist/errors/key-composition-error.d.ts.map +0 -1
- package/dist/errors/single-table-error.d.ts.map +0 -1
- package/dist/errors/single-table-item-format-error.d.ts.map +0 -1
- package/dist/index.d.ts.map +0 -1
- package/dist/single-table-item/index.d.ts.map +0 -1
- package/dist/single-table-item/single-table-item.d.ts.map +0 -1
- package/dist/single-table-item/single-table-item.js +0 -281
- package/dist/single-table-item/utils/capitalize-first-letter.d.ts.map +0 -1
- package/dist/single-table-item/utils/handle-composite-primary-key.d.ts.map +0 -1
- package/dist/single-table-item/utils/index.d.ts.map +0 -1
- package/dist/single-table-item/utils/validate-entity-annotations.d.ts.map +0 -1
- package/dist/single-table-item/utils/validate-entity-annotations.js +0 -38
- package/dist/single-table-repository/index.d.ts.map +0 -1
- package/dist/single-table-repository/single-table-repository.d.ts.map +0 -1
- package/dist/single-table-repository/types.d.ts.map +0 -1
- package/dist/types.d.ts.map +0 -1
- /package/{dist → dist-cjs}/decorators/editable/editable.js +0 -0
- /package/{dist → dist-cjs}/decorators/editable/index.js +0 -0
- /package/{dist → dist-cjs}/decorators/editable/is-editable.js +0 -0
- /package/{dist → dist-cjs}/decorators/editable/symbol.js +0 -0
- /package/{dist → dist-cjs}/decorators/entity/entity.js +0 -0
- /package/{dist → dist-cjs}/decorators/entity/get-entity-name.js +0 -0
- /package/{dist → dist-cjs}/decorators/entity/index.js +0 -0
- /package/{dist → dist-cjs}/decorators/entity/symbol.js +0 -0
- /package/{dist → dist-cjs}/decorators/gsis/get-pk-composition.js +0 -0
- /package/{dist → dist-cjs}/decorators/gsis/get-sk-composition.js +0 -0
- /package/{dist → dist-cjs}/decorators/gsis/gsis.js +0 -0
- /package/{dist → dist-cjs}/decorators/gsis/index.js +0 -0
- /package/{dist → dist-cjs}/decorators/gsis/symbols.js +0 -0
- /package/{dist → dist-cjs}/decorators/gsis/types.js +0 -0
- /package/{dist → dist-cjs}/decorators/index.js +0 -0
- /package/{dist → dist-cjs}/dynamodb/delete-dynamodb-item.js +0 -0
- /package/{dist → dist-cjs}/dynamodb/get-dynamodb-item.js +0 -0
- /package/{dist → dist-cjs}/dynamodb/index.js +0 -0
- /package/{dist → dist-cjs}/dynamodb/put-dynamodb-item.js +0 -0
- /package/{dist → dist-cjs}/dynamodb/query-all-dynamodb.js +0 -0
- /package/{dist → dist-cjs}/dynamodb/query-dynamodb.js +0 -0
- /package/{dist → dist-cjs}/dynamodb/update-dynamodb-item.js +0 -0
- /package/{dist → dist-cjs}/errors/index.js +0 -0
- /package/{dist → dist-cjs}/index.js +0 -0
- /package/{dist → dist-cjs}/single-table-item/index.js +0 -0
- /package/{dist → dist-cjs}/single-table-item/utils/capitalize-first-letter.js +0 -0
- /package/{dist → dist-cjs}/single-table-item/utils/handle-composite-primary-key.js +0 -0
- /package/{dist → dist-cjs}/single-table-item/utils/index.js +0 -0
- /package/{dist → dist-cjs}/single-table-repository/index.js +0 -0
- /package/{dist → dist-cjs}/single-table-repository/types.js +0 -0
- /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,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
|
+
}
|
package/dist-es/index.js
ADDED
|
@@ -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,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,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,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 {};
|
package/dist-es/types.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -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
|