@monorise/core 0.1.1 → 0.1.3
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/base/utils/index.js +2 -9
- package/dist/base/utils/index.js.map +1 -1
- package/dist/core/controllers/entity/create-entity.controller.js +39 -32
- package/dist/core/controllers/entity/create-entity.controller.js.map +1 -1
- package/dist/core/controllers/entity/delete-entity.controller.js +26 -20
- package/dist/core/controllers/entity/delete-entity.controller.js.map +1 -1
- package/dist/core/controllers/entity/get-entity-by-unique-field-value.controller.js +25 -17
- package/dist/core/controllers/entity/get-entity-by-unique-field-value.controller.js.map +1 -1
- package/dist/core/controllers/entity/get-entity.controller.js +25 -17
- package/dist/core/controllers/entity/get-entity.controller.js.map +1 -1
- package/dist/core/controllers/entity/list-entities.controller.js +39 -36
- package/dist/core/controllers/entity/list-entities.controller.js.map +1 -1
- package/dist/core/controllers/entity/update-entity.controller.js +40 -33
- package/dist/core/controllers/entity/update-entity.controller.js.map +1 -1
- package/dist/core/controllers/entity/upsert-entity.controller.js +64 -59
- package/dist/core/controllers/entity/upsert-entity.controller.js.map +1 -1
- package/dist/core/controllers/mutual/create-mutual.controller.js +42 -38
- package/dist/core/controllers/mutual/create-mutual.controller.js.map +1 -1
- package/dist/core/controllers/mutual/delete-mutual.controller.js +28 -22
- package/dist/core/controllers/mutual/delete-mutual.controller.js.map +1 -1
- package/dist/core/controllers/mutual/get-mutual.controller.js +25 -17
- package/dist/core/controllers/mutual/get-mutual.controller.js.map +1 -1
- package/dist/core/controllers/mutual/list-entities-by-entity.controller.js +52 -44
- package/dist/core/controllers/mutual/list-entities-by-entity.controller.js.map +1 -1
- package/dist/core/controllers/mutual/update-mutual.controller.js +38 -32
- package/dist/core/controllers/mutual/update-mutual.controller.js.map +1 -1
- package/dist/core/controllers/tag/list-tags.controller.js +39 -31
- package/dist/core/controllers/tag/list-tags.controller.js.map +1 -1
- package/dist/core/data/DbUtils.js +23 -12
- package/dist/core/data/DbUtils.js.map +1 -1
- package/dist/core/data/Entity.js +298 -334
- package/dist/core/data/Entity.js.map +1 -1
- package/dist/core/data/EventUtils.js +35 -27
- package/dist/core/data/EventUtils.js.map +1 -1
- package/dist/core/data/Mutual.js +282 -342
- package/dist/core/data/Mutual.js.map +1 -1
- package/dist/core/data/Tag.js +225 -228
- package/dist/core/data/Tag.js.map +1 -1
- package/dist/core/data/abstract/Repository.base.js +4 -7
- package/dist/core/data/abstract/Repository.base.js.map +1 -1
- package/dist/core/errors/extendable-error.js +0 -7
- package/dist/core/errors/extendable-error.js.map +1 -1
- package/dist/core/errors/standard-error.js +0 -3
- package/dist/core/errors/standard-error.js.map +1 -1
- package/dist/core/helpers/event.js +35 -34
- package/dist/core/helpers/event.js.map +1 -1
- package/dist/core/helpers/test/test-utils.js +60 -58
- package/dist/core/helpers/test/test-utils.js.map +1 -1
- package/dist/core/index.js +0 -8
- package/dist/core/index.js.map +1 -1
- package/dist/core/processors/create-entity-processor.js +12 -3
- package/dist/core/processors/create-entity-processor.js.map +1 -1
- package/dist/core/processors/mutual-processor.js +33 -23
- package/dist/core/processors/mutual-processor.js.map +1 -1
- package/dist/core/processors/prejoin-processor.js +117 -105
- package/dist/core/processors/prejoin-processor.js.map +1 -1
- package/dist/core/processors/replication-processor.js +27 -26
- package/dist/core/processors/replication-processor.js.map +1 -1
- package/dist/core/processors/tag-processor.js +47 -35
- package/dist/core/processors/tag-processor.js.map +1 -1
- package/dist/core/services/DependencyContainer.js +0 -4
- package/dist/core/services/DependencyContainer.js.map +1 -1
- package/dist/core/services/entity-service-lifecycle.js +29 -20
- package/dist/core/services/entity-service-lifecycle.js.map +1 -1
- package/dist/core/services/entity.service.js +95 -92
- package/dist/core/services/entity.service.js.map +1 -1
- package/dist/core/services/mutual.service.js +117 -113
- package/dist/core/services/mutual.service.js.map +1 -1
- package/package.json +1 -1
package/dist/core/data/Entity.js
CHANGED
|
@@ -1,3 +1,12 @@
|
|
|
1
|
+
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
2
|
+
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
3
|
+
return new (P || (P = Promise))(function (resolve, reject) {
|
|
4
|
+
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
5
|
+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
6
|
+
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
7
|
+
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
8
|
+
});
|
|
9
|
+
};
|
|
1
10
|
import { ConditionalCheckFailedException, } from '@aws-sdk/client-dynamodb';
|
|
2
11
|
import { marshall, unmarshall } from '@aws-sdk/util-dynamodb';
|
|
3
12
|
import { ulid } from 'ulid';
|
|
@@ -5,12 +14,6 @@ import { StandardError } from '../errors/standard-error';
|
|
|
5
14
|
import { Item } from './abstract/Item.base';
|
|
6
15
|
import { Repository } from './abstract/Repository.base';
|
|
7
16
|
export class Entity extends Item {
|
|
8
|
-
entityType;
|
|
9
|
-
entityId;
|
|
10
|
-
data;
|
|
11
|
-
_createdAt;
|
|
12
|
-
_updatedAt;
|
|
13
|
-
fullId;
|
|
14
17
|
constructor(entityType, entityId, data = {}, _createdAt, _updatedAt) {
|
|
15
18
|
super();
|
|
16
19
|
this.entityType = entityType;
|
|
@@ -46,16 +49,15 @@ export class Entity extends Item {
|
|
|
46
49
|
};
|
|
47
50
|
}
|
|
48
51
|
get createdAt() {
|
|
49
|
-
|
|
52
|
+
var _a;
|
|
53
|
+
return (_a = this._createdAt) === null || _a === void 0 ? void 0 : _a.toISOString();
|
|
50
54
|
}
|
|
51
55
|
get updatedAt() {
|
|
52
|
-
|
|
56
|
+
var _a;
|
|
57
|
+
return (_a = this._updatedAt) === null || _a === void 0 ? void 0 : _a.toISOString();
|
|
53
58
|
}
|
|
54
59
|
toItem() {
|
|
55
|
-
return {
|
|
56
|
-
...marshall(this.toJSON(), { removeUndefinedValues: true }),
|
|
57
|
-
...this.keys(),
|
|
58
|
-
};
|
|
60
|
+
return Object.assign(Object.assign({}, marshall(this.toJSON(), { removeUndefinedValues: true })), this.keys());
|
|
59
61
|
}
|
|
60
62
|
toJSON() {
|
|
61
63
|
return {
|
|
@@ -68,10 +70,6 @@ export class Entity extends Item {
|
|
|
68
70
|
}
|
|
69
71
|
}
|
|
70
72
|
export class EntityRepository extends Repository {
|
|
71
|
-
EntityConfig;
|
|
72
|
-
TABLE_NAME;
|
|
73
|
-
dynamodbClient;
|
|
74
|
-
EmailAuthEnabledEntities;
|
|
75
73
|
constructor(EntityConfig, TABLE_NAME, dynamodbClient, EmailAuthEnabledEntities) {
|
|
76
74
|
super();
|
|
77
75
|
this.EntityConfig = EntityConfig;
|
|
@@ -79,147 +77,154 @@ export class EntityRepository extends Repository {
|
|
|
79
77
|
this.dynamodbClient = dynamodbClient;
|
|
80
78
|
this.EmailAuthEnabledEntities = EmailAuthEnabledEntities;
|
|
81
79
|
}
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
80
|
+
listEntities(_a) {
|
|
81
|
+
return __awaiter(this, arguments, void 0, function* ({ entityType, limit, // if this is not set, it will return all items
|
|
82
|
+
between, options = {}, }) {
|
|
83
|
+
var _b, _c, _d;
|
|
84
|
+
const entity = new Entity(entityType);
|
|
85
|
+
// when query for records that SK are between provided start and end
|
|
86
|
+
const expression = between
|
|
87
|
+
? {
|
|
88
|
+
KeyConditionExpression: '#PK = :PK and #SK between :SKStart and :SKEnd',
|
|
89
|
+
ExpressionAttributeNames: {
|
|
90
|
+
'#PK': 'PK',
|
|
91
|
+
'#SK': 'SK',
|
|
92
|
+
},
|
|
93
|
+
ExpressionAttributeValues: {
|
|
94
|
+
':PK': {
|
|
95
|
+
S: entity.listActionKey,
|
|
96
|
+
},
|
|
97
|
+
':SKStart': {
|
|
98
|
+
S: `${entityType}#${between.start}`,
|
|
99
|
+
},
|
|
100
|
+
':SKEnd': {
|
|
101
|
+
S: `${entityType}#${between.end}`,
|
|
102
|
+
},
|
|
103
|
+
},
|
|
104
|
+
}
|
|
105
|
+
: {
|
|
106
|
+
KeyConditionExpression: '#PK = :PK',
|
|
107
|
+
ExpressionAttributeNames: {
|
|
108
|
+
'#PK': 'PK',
|
|
109
|
+
},
|
|
110
|
+
ExpressionAttributeValues: {
|
|
111
|
+
':PK': {
|
|
112
|
+
S: entity.listActionKey,
|
|
113
|
+
},
|
|
114
|
+
},
|
|
115
|
+
};
|
|
116
|
+
const defaultListQuery = Object.assign({ TableName: this.TABLE_NAME, Limit: limit, ScanIndexForward: false, ProjectionExpression: options === null || options === void 0 ? void 0 : options.ProjectionExpression }, expression);
|
|
117
|
+
let lastKey = options.lastKey;
|
|
118
|
+
let items = [];
|
|
119
|
+
let remainingCount = limit !== null && limit !== void 0 ? limit : 0;
|
|
120
|
+
do {
|
|
121
|
+
const resp = yield this.dynamodbClient.query(Object.assign(Object.assign(Object.assign({}, defaultListQuery), (remainingCount && { Limit: remainingCount })), (lastKey && {
|
|
122
|
+
ExclusiveStartKey: lastKey,
|
|
123
|
+
})));
|
|
124
|
+
items = items.concat((_b = resp.Items) !== null && _b !== void 0 ? _b : []);
|
|
125
|
+
lastKey = resp.LastEvaluatedKey;
|
|
126
|
+
if (limit) {
|
|
127
|
+
remainingCount = remainingCount - ((_d = (_c = resp.Items) === null || _c === void 0 ? void 0 : _c.length) !== null && _d !== void 0 ? _d : 0);
|
|
128
|
+
}
|
|
129
|
+
} while (
|
|
130
|
+
// limit is given, haven't reach limit, and there are still items to retrieve
|
|
131
|
+
(limit && remainingCount && lastKey) ||
|
|
132
|
+
// no limit is given and there are still items to retrieve
|
|
133
|
+
(!limit && lastKey));
|
|
134
|
+
return {
|
|
135
|
+
items: (items || []).map((Entity.fromItem)),
|
|
136
|
+
totalCount: items.length,
|
|
137
|
+
lastKey,
|
|
138
|
+
};
|
|
139
|
+
});
|
|
140
|
+
}
|
|
141
|
+
getEntity(entityType, entityId) {
|
|
142
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
143
|
+
const entity = new Entity(entityType, entityId);
|
|
144
|
+
const resp = yield this.dynamodbClient.getItem({
|
|
145
|
+
TableName: this.TABLE_NAME,
|
|
146
|
+
Key: entity.keys(),
|
|
147
|
+
});
|
|
148
|
+
return Entity.fromItem(resp.Item);
|
|
149
|
+
});
|
|
150
|
+
}
|
|
151
|
+
getEntityByEmail(entityType, email) {
|
|
152
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
153
|
+
var _a;
|
|
154
|
+
const resp = yield this.dynamodbClient.query({
|
|
155
|
+
TableName: this.TABLE_NAME,
|
|
156
|
+
KeyConditionExpression: '#PK = :PK and begins_with(#SK, :SK)',
|
|
89
157
|
ExpressionAttributeNames: {
|
|
90
158
|
'#PK': 'PK',
|
|
91
159
|
'#SK': 'SK',
|
|
92
160
|
},
|
|
93
161
|
ExpressionAttributeValues: {
|
|
94
|
-
':PK': {
|
|
95
|
-
|
|
96
|
-
},
|
|
97
|
-
':SKStart': {
|
|
98
|
-
S: `${entityType}#${between.start}`,
|
|
99
|
-
},
|
|
100
|
-
':SKEnd': {
|
|
101
|
-
S: `${entityType}#${between.end}`,
|
|
102
|
-
},
|
|
162
|
+
':PK': { S: `EMAIL#${email}` },
|
|
163
|
+
':SK': { S: entityType },
|
|
103
164
|
},
|
|
104
|
-
}
|
|
105
|
-
:
|
|
106
|
-
|
|
165
|
+
});
|
|
166
|
+
return Entity.fromItem((_a = resp.Items) === null || _a === void 0 ? void 0 : _a[0]);
|
|
167
|
+
});
|
|
168
|
+
}
|
|
169
|
+
getEmailAvailability(entityType, email) {
|
|
170
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
171
|
+
var _a;
|
|
172
|
+
const resp = yield this.dynamodbClient.query({
|
|
173
|
+
TableName: this.TABLE_NAME,
|
|
174
|
+
KeyConditionExpression: '#PK = :PK and begins_with(#SK, :SK)',
|
|
107
175
|
ExpressionAttributeNames: {
|
|
108
176
|
'#PK': 'PK',
|
|
177
|
+
'#SK': 'SK',
|
|
109
178
|
},
|
|
110
179
|
ExpressionAttributeValues: {
|
|
111
|
-
':PK': {
|
|
112
|
-
|
|
113
|
-
},
|
|
180
|
+
':PK': { S: `EMAIL#${email}` },
|
|
181
|
+
':SK': { S: entityType },
|
|
114
182
|
},
|
|
115
|
-
};
|
|
116
|
-
const defaultListQuery = {
|
|
117
|
-
TableName: this.TABLE_NAME,
|
|
118
|
-
Limit: limit,
|
|
119
|
-
ScanIndexForward: false,
|
|
120
|
-
ProjectionExpression: options?.ProjectionExpression,
|
|
121
|
-
...expression,
|
|
122
|
-
};
|
|
123
|
-
let lastKey = options.lastKey;
|
|
124
|
-
let items = [];
|
|
125
|
-
let remainingCount = limit ?? 0;
|
|
126
|
-
do {
|
|
127
|
-
const resp = await this.dynamodbClient.query({
|
|
128
|
-
...defaultListQuery,
|
|
129
|
-
...(remainingCount && { Limit: remainingCount }),
|
|
130
|
-
...(lastKey && {
|
|
131
|
-
ExclusiveStartKey: lastKey,
|
|
132
|
-
}),
|
|
133
183
|
});
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
if (limit) {
|
|
137
|
-
remainingCount = remainingCount - (resp.Items?.length ?? 0);
|
|
184
|
+
if ((_a = resp.Items) === null || _a === void 0 ? void 0 : _a[0]) {
|
|
185
|
+
throw new StandardError('EMAIL_EXISTS', 'Email already exists');
|
|
138
186
|
}
|
|
139
|
-
|
|
140
|
-
// limit is given, haven't reach limit, and there are still items to retrieve
|
|
141
|
-
(limit && remainingCount && lastKey) ||
|
|
142
|
-
// no limit is given and there are still items to retrieve
|
|
143
|
-
(!limit && lastKey));
|
|
144
|
-
return {
|
|
145
|
-
items: (items || []).map((Entity.fromItem)),
|
|
146
|
-
totalCount: items.length,
|
|
147
|
-
lastKey,
|
|
148
|
-
};
|
|
149
|
-
}
|
|
150
|
-
async getEntity(entityType, entityId) {
|
|
151
|
-
const entity = new Entity(entityType, entityId);
|
|
152
|
-
const resp = await this.dynamodbClient.getItem({
|
|
153
|
-
TableName: this.TABLE_NAME,
|
|
154
|
-
Key: entity.keys(),
|
|
187
|
+
return;
|
|
155
188
|
});
|
|
156
|
-
return Entity.fromItem(resp.Item);
|
|
157
189
|
}
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
'#PK
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
const resp = await this.dynamodbClient.query({
|
|
175
|
-
TableName: this.TABLE_NAME,
|
|
176
|
-
KeyConditionExpression: '#PK = :PK and begins_with(#SK, :SK)',
|
|
177
|
-
ExpressionAttributeNames: {
|
|
178
|
-
'#PK': 'PK',
|
|
179
|
-
'#SK': 'SK',
|
|
180
|
-
},
|
|
181
|
-
ExpressionAttributeValues: {
|
|
182
|
-
':PK': { S: `EMAIL#${email}` },
|
|
183
|
-
':SK': { S: entityType },
|
|
184
|
-
},
|
|
185
|
-
});
|
|
186
|
-
if (resp.Items?.[0]) {
|
|
187
|
-
throw new StandardError('EMAIL_EXISTS', 'Email already exists');
|
|
188
|
-
}
|
|
189
|
-
return;
|
|
190
|
-
}
|
|
191
|
-
async getEntityByUniqueField(entityType, fieldName, value) {
|
|
192
|
-
const resp = await this.dynamodbClient.query({
|
|
193
|
-
TableName: this.TABLE_NAME,
|
|
194
|
-
KeyConditionExpression: '#PK = :PK and begins_with(#SK, :SK)',
|
|
195
|
-
ExpressionAttributeNames: {
|
|
196
|
-
'#PK': 'PK',
|
|
197
|
-
'#SK': 'SK',
|
|
198
|
-
},
|
|
199
|
-
ExpressionAttributeValues: {
|
|
200
|
-
':PK': { S: `UNIQUE#${fieldName}#${value}` },
|
|
201
|
-
':SK': { S: entityType },
|
|
202
|
-
},
|
|
190
|
+
getEntityByUniqueField(entityType, fieldName, value) {
|
|
191
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
192
|
+
var _a;
|
|
193
|
+
const resp = yield this.dynamodbClient.query({
|
|
194
|
+
TableName: this.TABLE_NAME,
|
|
195
|
+
KeyConditionExpression: '#PK = :PK and begins_with(#SK, :SK)',
|
|
196
|
+
ExpressionAttributeNames: {
|
|
197
|
+
'#PK': 'PK',
|
|
198
|
+
'#SK': 'SK',
|
|
199
|
+
},
|
|
200
|
+
ExpressionAttributeValues: {
|
|
201
|
+
':PK': { S: `UNIQUE#${fieldName}#${value}` },
|
|
202
|
+
':SK': { S: entityType },
|
|
203
|
+
},
|
|
204
|
+
});
|
|
205
|
+
return Entity.fromItem((_a = resp.Items) === null || _a === void 0 ? void 0 : _a[0]);
|
|
203
206
|
});
|
|
204
|
-
return Entity.fromItem(resp.Items?.[0]);
|
|
205
207
|
}
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
'#PK
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
208
|
+
getUniqueFieldValueAvailability(entityType, fieldName, value) {
|
|
209
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
210
|
+
var _a;
|
|
211
|
+
const resp = yield this.dynamodbClient.query({
|
|
212
|
+
TableName: this.TABLE_NAME,
|
|
213
|
+
KeyConditionExpression: '#PK = :PK and begins_with(#SK, :SK)',
|
|
214
|
+
ExpressionAttributeNames: {
|
|
215
|
+
'#PK': 'PK',
|
|
216
|
+
'#SK': 'SK',
|
|
217
|
+
},
|
|
218
|
+
ExpressionAttributeValues: {
|
|
219
|
+
':PK': { S: `UNIQUE#${fieldName}#${value}` },
|
|
220
|
+
':SK': { S: entityType },
|
|
221
|
+
},
|
|
222
|
+
});
|
|
223
|
+
if ((_a = resp.Items) === null || _a === void 0 ? void 0 : _a[0]) {
|
|
224
|
+
throw new StandardError('UNIQUE_VALUE_EXISTS', `${fieldName} '${value}' already exists`);
|
|
225
|
+
}
|
|
226
|
+
return;
|
|
218
227
|
});
|
|
219
|
-
if (resp.Items?.[0]) {
|
|
220
|
-
throw new StandardError('UNIQUE_VALUE_EXISTS', `${fieldName} '${value}' already exists`);
|
|
221
|
-
}
|
|
222
|
-
return;
|
|
223
228
|
}
|
|
224
229
|
createEntityTransactItems(entity, opts) {
|
|
225
230
|
const TransactItems = [
|
|
@@ -227,26 +232,17 @@ export class EntityRepository extends Repository {
|
|
|
227
232
|
Put: {
|
|
228
233
|
TableName: this.TABLE_NAME,
|
|
229
234
|
ConditionExpression: 'attribute_not_exists(PK)',
|
|
230
|
-
Item: {
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
R2SK: { S: entity.pk },
|
|
235
|
-
}),
|
|
236
|
-
},
|
|
235
|
+
Item: Object.assign(Object.assign({}, entity.toItem()), ((opts === null || opts === void 0 ? void 0 : opts.mutualId) && {
|
|
236
|
+
R2PK: { S: opts.mutualId },
|
|
237
|
+
R2SK: { S: entity.pk },
|
|
238
|
+
})),
|
|
237
239
|
},
|
|
238
240
|
},
|
|
239
241
|
{
|
|
240
242
|
Put: {
|
|
241
243
|
TableName: this.TABLE_NAME,
|
|
242
244
|
ConditionExpression: 'attribute_not_exists(PK)',
|
|
243
|
-
Item: {
|
|
244
|
-
...entity.toItem(),
|
|
245
|
-
PK: { S: entity.listActionKey },
|
|
246
|
-
SK: entity.keys().PK,
|
|
247
|
-
R1PK: entity.keys().PK,
|
|
248
|
-
R1SK: { S: entity.listActionKey },
|
|
249
|
-
},
|
|
245
|
+
Item: Object.assign(Object.assign({}, entity.toItem()), { PK: { S: entity.listActionKey }, SK: entity.keys().PK, R1PK: entity.keys().PK, R1SK: { S: entity.listActionKey } }),
|
|
250
246
|
},
|
|
251
247
|
},
|
|
252
248
|
];
|
|
@@ -259,12 +255,7 @@ export class EntityRepository extends Repository {
|
|
|
259
255
|
Put: {
|
|
260
256
|
TableName: this.TABLE_NAME,
|
|
261
257
|
ConditionExpression: 'attribute_not_exists(PK)',
|
|
262
|
-
Item: {
|
|
263
|
-
...entity.toItem(),
|
|
264
|
-
...entity.emailKeys,
|
|
265
|
-
R1PK: entity.emailKeys.SK,
|
|
266
|
-
R1SK: entity.emailKeys.PK,
|
|
267
|
-
},
|
|
258
|
+
Item: Object.assign(Object.assign(Object.assign({}, entity.toItem()), entity.emailKeys), { R1PK: entity.emailKeys.SK, R1SK: entity.emailKeys.PK }),
|
|
268
259
|
},
|
|
269
260
|
});
|
|
270
261
|
}
|
|
@@ -273,76 +264,65 @@ export class EntityRepository extends Repository {
|
|
|
273
264
|
Put: {
|
|
274
265
|
TableName: this.TABLE_NAME,
|
|
275
266
|
ConditionExpression: 'attribute_not_exists(PK)',
|
|
276
|
-
Item: {
|
|
277
|
-
...entity.toItem(),
|
|
278
|
-
PK: {
|
|
267
|
+
Item: Object.assign(Object.assign({}, entity.toItem()), { PK: {
|
|
279
268
|
S: `UNIQUE#${field}#${entity.data[field]}`,
|
|
280
|
-
},
|
|
281
|
-
SK: { S: entity.entityType },
|
|
282
|
-
R1PK: entity.keys().PK,
|
|
283
|
-
R1SK: entity.keys().SK,
|
|
284
|
-
},
|
|
269
|
+
}, SK: { S: entity.entityType }, R1PK: entity.keys().PK, R1SK: entity.keys().SK }),
|
|
285
270
|
},
|
|
286
271
|
});
|
|
287
272
|
}
|
|
288
273
|
return TransactItems;
|
|
289
274
|
}
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
275
|
+
createEntity(entityType, entityPayload, entityId, opts) {
|
|
276
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
277
|
+
var _a;
|
|
278
|
+
const currentDatetime = (_a = opts === null || opts === void 0 ? void 0 : opts.createAndUpdateDatetime) !== null && _a !== void 0 ? _a : new Date();
|
|
279
|
+
const entity = new Entity(entityType, entityId || ulid(), entityPayload, currentDatetime, currentDatetime);
|
|
280
|
+
const uniqueFields = (this.EntityConfig[entityType].uniqueFields ||
|
|
281
|
+
[]);
|
|
282
|
+
const hasUniqueFields = Object.keys(entityPayload).some((field) => uniqueFields.includes(field));
|
|
283
|
+
let uniqueFieldValues = {};
|
|
284
|
+
if (hasUniqueFields) {
|
|
285
|
+
for (const field of uniqueFields) {
|
|
286
|
+
if (typeof entityPayload[field] !== 'string') {
|
|
287
|
+
throw new StandardError('INVALID_UNIQUE_VALUE_TYPE', `Invalid type. ${field} is not a 'string'.`);
|
|
288
|
+
}
|
|
301
289
|
}
|
|
290
|
+
uniqueFieldValues = uniqueFields.reduce((acc, field) => (Object.assign(Object.assign({}, acc), { [field]: entityPayload[field] })), {});
|
|
302
291
|
}
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
})
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
mutualId: opts?.mutualId,
|
|
310
|
-
uniqueFieldValues,
|
|
292
|
+
const TransactItems = this.createEntityTransactItems(entity, {
|
|
293
|
+
mutualId: opts === null || opts === void 0 ? void 0 : opts.mutualId,
|
|
294
|
+
uniqueFieldValues,
|
|
295
|
+
});
|
|
296
|
+
yield this.dynamodbClient.transactWriteItems({ TransactItems });
|
|
297
|
+
return entity;
|
|
311
298
|
});
|
|
312
|
-
await this.dynamodbClient.transactWriteItems({ TransactItems });
|
|
313
|
-
return entity;
|
|
314
299
|
}
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
300
|
+
upsertEntity(entityType, entityId, payload) {
|
|
301
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
302
|
+
const currentDatetime = new Date().toISOString();
|
|
303
|
+
const toUpdateExpressions = this.toUpdate({
|
|
304
|
+
entityType,
|
|
305
|
+
entityId,
|
|
306
|
+
data: payload,
|
|
307
|
+
updatedAt: currentDatetime,
|
|
308
|
+
});
|
|
309
|
+
const params = {
|
|
310
|
+
TableName: this.TABLE_NAME,
|
|
311
|
+
ReturnValues: 'ALL_NEW',
|
|
312
|
+
Key: new Entity(entityType, entityId).keys(),
|
|
313
|
+
UpdateExpression: toUpdateExpressions.UpdateExpression,
|
|
314
|
+
ExpressionAttributeNames: Object.assign({}, toUpdateExpressions.ExpressionAttributeNames),
|
|
315
|
+
ExpressionAttributeValues: Object.assign({}, toUpdateExpressions.ExpressionAttributeValues),
|
|
316
|
+
};
|
|
317
|
+
const resp = yield this.dynamodbClient.updateItem(params);
|
|
318
|
+
const updatedEntity = Entity.fromItem(resp.Attributes);
|
|
319
|
+
return updatedEntity;
|
|
322
320
|
});
|
|
323
|
-
const params = {
|
|
324
|
-
TableName: this.TABLE_NAME,
|
|
325
|
-
ReturnValues: 'ALL_NEW',
|
|
326
|
-
Key: new Entity(entityType, entityId).keys(),
|
|
327
|
-
UpdateExpression: toUpdateExpressions.UpdateExpression,
|
|
328
|
-
ExpressionAttributeNames: {
|
|
329
|
-
...toUpdateExpressions.ExpressionAttributeNames,
|
|
330
|
-
},
|
|
331
|
-
ExpressionAttributeValues: {
|
|
332
|
-
...toUpdateExpressions.ExpressionAttributeValues,
|
|
333
|
-
},
|
|
334
|
-
};
|
|
335
|
-
const resp = await this.dynamodbClient.updateItem(params);
|
|
336
|
-
const updatedEntity = Entity.fromItem(resp.Attributes);
|
|
337
|
-
return updatedEntity;
|
|
338
321
|
}
|
|
339
322
|
updateEntityTransactItems(entity, updateParams, previousUniqueFieldValues, previousEntity) {
|
|
340
323
|
const transactItems = [
|
|
341
324
|
{
|
|
342
|
-
Update: {
|
|
343
|
-
...updateParams,
|
|
344
|
-
UpdateExpression: updateParams.UpdateExpression,
|
|
345
|
-
},
|
|
325
|
+
Update: Object.assign(Object.assign({}, updateParams), { UpdateExpression: updateParams.UpdateExpression }),
|
|
346
326
|
},
|
|
347
327
|
];
|
|
348
328
|
for (const field in previousUniqueFieldValues) {
|
|
@@ -358,142 +338,126 @@ export class EntityRepository extends Repository {
|
|
|
358
338
|
Put: {
|
|
359
339
|
TableName: this.TABLE_NAME,
|
|
360
340
|
ConditionExpression: 'attribute_not_exists(PK)',
|
|
361
|
-
Item: {
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
M: {
|
|
365
|
-
...previousEntity.toItem().data.M,
|
|
366
|
-
...entity.toItem().data.M,
|
|
367
|
-
},
|
|
368
|
-
},
|
|
369
|
-
PK: {
|
|
341
|
+
Item: Object.assign(Object.assign({}, entity.toItem()), { data: {
|
|
342
|
+
M: Object.assign(Object.assign({}, previousEntity.toItem().data.M), entity.toItem().data.M),
|
|
343
|
+
}, PK: {
|
|
370
344
|
S: `UNIQUE#${field}#${entity.data[field]}`,
|
|
371
|
-
},
|
|
372
|
-
SK: { S: entity.entityType },
|
|
373
|
-
R1PK: entity.keys().PK,
|
|
374
|
-
R1SK: entity.keys().SK,
|
|
375
|
-
},
|
|
345
|
+
}, SK: { S: entity.entityType }, R1PK: entity.keys().PK, R1SK: entity.keys().SK }),
|
|
376
346
|
},
|
|
377
347
|
});
|
|
378
348
|
}
|
|
379
349
|
return transactItems;
|
|
380
350
|
}
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
updatedAt: currentDatetime,
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
}), {});
|
|
419
|
-
for (const field in previousUniqueFieldValues) {
|
|
420
|
-
if (typeof toUpdate.data[field] !==
|
|
421
|
-
'string') {
|
|
422
|
-
throw new StandardError('INVALID_UNIQUE_VALUE_TYPE', `Invalid type. ${field} is not a 'string'.`);
|
|
351
|
+
updateEntity(entityType, entityId, toUpdate, opts) {
|
|
352
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
353
|
+
try {
|
|
354
|
+
const currentDatetime = new Date().toISOString();
|
|
355
|
+
const toUpdateExpressions = this.toUpdate(Object.assign({ updatedAt: currentDatetime }, toUpdate));
|
|
356
|
+
const params = {
|
|
357
|
+
TableName: this.TABLE_NAME,
|
|
358
|
+
ReturnValues: 'ALL_NEW',
|
|
359
|
+
Key: new Entity(entityType, entityId).keys(),
|
|
360
|
+
ConditionExpression: (opts === null || opts === void 0 ? void 0 : opts.ConditionExpression) || 'attribute_exists(PK)',
|
|
361
|
+
UpdateExpression: toUpdateExpressions.UpdateExpression,
|
|
362
|
+
ExpressionAttributeNames: Object.assign(Object.assign({}, toUpdateExpressions.ExpressionAttributeNames), opts === null || opts === void 0 ? void 0 : opts.ExpressionAttributeNames),
|
|
363
|
+
ExpressionAttributeValues: Object.assign(Object.assign({}, toUpdateExpressions.ExpressionAttributeValues), opts === null || opts === void 0 ? void 0 : opts.ExpressionAttributeValues),
|
|
364
|
+
};
|
|
365
|
+
const entity = new Entity(entityType, entityId, toUpdate.data);
|
|
366
|
+
const uniqueFields = (this.EntityConfig[entityType].uniqueFields ||
|
|
367
|
+
[]);
|
|
368
|
+
const hasUniqueFields = Object.keys(toUpdate.data).some((field) => uniqueFields.includes(field));
|
|
369
|
+
let updatedUniqueFields = [];
|
|
370
|
+
let previousUniqueFieldValues = {};
|
|
371
|
+
let previousEntity;
|
|
372
|
+
if (hasUniqueFields) {
|
|
373
|
+
previousEntity = yield this.getEntity(entityType, entityId);
|
|
374
|
+
// check if any of the unique fields has changed
|
|
375
|
+
updatedUniqueFields = uniqueFields.filter((field) => toUpdate.data[field] !==
|
|
376
|
+
previousEntity.data[field]);
|
|
377
|
+
previousUniqueFieldValues = updatedUniqueFields.reduce((acc, field) => (Object.assign(Object.assign({}, acc), { [field]: previousEntity.data[field] })), {});
|
|
378
|
+
for (const field in previousUniqueFieldValues) {
|
|
379
|
+
if (typeof toUpdate.data[field] !==
|
|
380
|
+
'string') {
|
|
381
|
+
throw new StandardError('INVALID_UNIQUE_VALUE_TYPE', `Invalid type. ${field} is not a 'string'.`);
|
|
382
|
+
}
|
|
383
|
+
}
|
|
384
|
+
if (updatedUniqueFields.length > 0) {
|
|
385
|
+
const TransactItems = this.updateEntityTransactItems(entity, params, previousUniqueFieldValues, previousEntity);
|
|
386
|
+
yield this.dynamodbClient.transactWriteItems({ TransactItems });
|
|
387
|
+
return yield this.getEntity(entityType, entityId);
|
|
423
388
|
}
|
|
424
389
|
}
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
390
|
+
const resp = yield this.dynamodbClient.updateItem(params);
|
|
391
|
+
const updatedEntity = Entity.fromItem(resp.Attributes);
|
|
392
|
+
return updatedEntity;
|
|
393
|
+
}
|
|
394
|
+
catch (err) {
|
|
395
|
+
if (err instanceof ConditionalCheckFailedException) {
|
|
396
|
+
throw new StandardError('ENTITY_NOT_FOUND', 'Entity not found', err, {
|
|
397
|
+
entityId,
|
|
398
|
+
toUpdate,
|
|
399
|
+
});
|
|
429
400
|
}
|
|
401
|
+
throw err;
|
|
430
402
|
}
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
403
|
+
});
|
|
404
|
+
}
|
|
405
|
+
deleteEntity(entityType, entityId) {
|
|
406
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
407
|
+
try {
|
|
408
|
+
const entity = new Entity(entityType, entityId);
|
|
409
|
+
yield this.dynamodbClient.deleteItem({
|
|
410
|
+
TableName: this.TABLE_NAME,
|
|
411
|
+
Key: entity.keys(),
|
|
412
|
+
ConditionExpression: 'attribute_exists(PK)',
|
|
440
413
|
});
|
|
441
414
|
}
|
|
442
|
-
|
|
443
|
-
|
|
415
|
+
catch (err) {
|
|
416
|
+
if (err instanceof ConditionalCheckFailedException) {
|
|
417
|
+
throw new StandardError('ENTITY_NOT_FOUND', 'Entity not found', err, {
|
|
418
|
+
entityId,
|
|
419
|
+
});
|
|
420
|
+
}
|
|
421
|
+
throw err;
|
|
422
|
+
}
|
|
423
|
+
});
|
|
444
424
|
}
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
const
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
425
|
+
queryEntities(entityType, query) {
|
|
426
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
427
|
+
const results = {
|
|
428
|
+
items: [],
|
|
429
|
+
totalCount: 0,
|
|
430
|
+
};
|
|
431
|
+
// let regex be empty if its invalid (eg. +)
|
|
432
|
+
let queryRegex = /(?:)/;
|
|
433
|
+
try {
|
|
434
|
+
queryRegex = new RegExp(query.toLowerCase());
|
|
435
|
+
}
|
|
436
|
+
catch (err) {
|
|
437
|
+
return results;
|
|
438
|
+
}
|
|
439
|
+
const listResults = yield this.listEntities({
|
|
440
|
+
entityType,
|
|
452
441
|
});
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
442
|
+
results.items.push(...listResults.items);
|
|
443
|
+
results.totalCount += listResults.totalCount || 0;
|
|
444
|
+
const filteredItems = [];
|
|
445
|
+
const { searchableFields } = this.EntityConfig[entityType];
|
|
446
|
+
for (const item of results.items) {
|
|
447
|
+
const searchTerm = (searchableFields !== null && searchableFields !== void 0 ? searchableFields : [])
|
|
448
|
+
.map((field) => { var _a; return (_a = item.data[field]) === null || _a === void 0 ? void 0 : _a.toLowerCase(); })
|
|
449
|
+
.join(' ');
|
|
450
|
+
const isMatched = queryRegex.test(searchTerm);
|
|
451
|
+
if (isMatched) {
|
|
452
|
+
filteredItems.push(item);
|
|
453
|
+
}
|
|
459
454
|
}
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
items: [],
|
|
466
|
-
totalCount: 0,
|
|
467
|
-
};
|
|
468
|
-
// let regex be empty if its invalid (eg. +)
|
|
469
|
-
let queryRegex = /(?:)/;
|
|
470
|
-
try {
|
|
471
|
-
queryRegex = new RegExp(query.toLowerCase());
|
|
472
|
-
}
|
|
473
|
-
catch (err) {
|
|
474
|
-
return results;
|
|
475
|
-
}
|
|
476
|
-
const listResults = await this.listEntities({
|
|
477
|
-
entityType,
|
|
455
|
+
return {
|
|
456
|
+
items: filteredItems,
|
|
457
|
+
totalCount: results.totalCount,
|
|
458
|
+
filteredCount: filteredItems.length,
|
|
459
|
+
};
|
|
478
460
|
});
|
|
479
|
-
results.items.push(...listResults.items);
|
|
480
|
-
results.totalCount += listResults.totalCount || 0;
|
|
481
|
-
const filteredItems = [];
|
|
482
|
-
const { searchableFields } = this.EntityConfig[entityType];
|
|
483
|
-
for (const item of results.items) {
|
|
484
|
-
const searchTerm = (searchableFields ?? [])
|
|
485
|
-
.map((field) => item.data[field]?.toLowerCase())
|
|
486
|
-
.join(' ');
|
|
487
|
-
const isMatched = queryRegex.test(searchTerm);
|
|
488
|
-
if (isMatched) {
|
|
489
|
-
filteredItems.push(item);
|
|
490
|
-
}
|
|
491
|
-
}
|
|
492
|
-
return {
|
|
493
|
-
items: filteredItems,
|
|
494
|
-
totalCount: results.totalCount,
|
|
495
|
-
filteredCount: filteredItems.length,
|
|
496
|
-
};
|
|
497
461
|
}
|
|
498
462
|
}
|
|
499
463
|
//# sourceMappingURL=Entity.js.map
|