@monorise/core 1.0.2 → 1.0.4-0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/mock/monorise/chapter.d.ts +1 -1
- package/dist/mock/monorise/course.d.ts +1 -1
- package/dist/mock/monorise/learning-journey-config.d.ts +1 -1
- package/dist/mock/monorise/module.d.ts +1 -1
- package/dist/mock/monorise/organization.d.ts +1 -1
- package/dist/services/entity.service.d.ts +2 -2
- package/dist/services/entity.service.d.ts.map +1 -1
- package/package.json +4 -1
- package/configs/service.config.ts +0 -14
- package/constants/table.ts +0 -3
- package/controllers/entity/create-entity.controller.ts +0 -51
- package/controllers/entity/delete-entity.controller.ts +0 -35
- package/controllers/entity/entity.http +0 -62
- package/controllers/entity/get-entity.controller.ts +0 -33
- package/controllers/entity/list-entities.controller.ts +0 -69
- package/controllers/entity/update-entity.controller.ts +0 -56
- package/controllers/entity/upsert-entity.controller.ts +0 -97
- package/controllers/mutual/create-mutual.controller.ts +0 -89
- package/controllers/mutual/delete-mutual.controller.ts +0 -40
- package/controllers/mutual/get-mutual.controller.ts +0 -38
- package/controllers/mutual/list-entities-by-entity.controller.ts +0 -76
- package/controllers/mutual/mutual.http +0 -88
- package/controllers/mutual/update-mutual.controller.ts +0 -50
- package/controllers/setupRoutes.ts +0 -73
- package/controllers/tag/list-tags.controller.ts +0 -57
- package/data/DbUtils.ts +0 -40
- package/data/Entity.ts +0 -499
- package/data/EventUtils.ts +0 -47
- package/data/FileObject.ts +0 -16
- package/data/Mutual.ts +0 -779
- package/data/ProjectionExpression.ts +0 -8
- package/data/Tag.ts +0 -470
- package/data/abstract/Item.base.ts +0 -19
- package/data/abstract/Repository.base.ts +0 -92
- package/errors/api-error.ts +0 -39
- package/errors/extendable-error.ts +0 -35
- package/errors/standard-error.ts +0 -29
- package/helpers/dependencies.ts +0 -10
- package/helpers/event.ts +0 -85
- package/helpers/fromLastKeyQuery.ts +0 -11
- package/helpers/sleep.ts +0 -1
- package/helpers/toLastKeyResponse.ts +0 -11
- package/index.ts +0 -23
- package/middlewares/entity-type-check.ts +0 -20
- package/middlewares/mutual-type-check.ts +0 -26
- package/mock/entity.ts +0 -12
- package/mock/monorise/admin.ts +0 -35
- package/mock/monorise/chapter.ts +0 -94
- package/mock/monorise/course.ts +0 -149
- package/mock/monorise/index.ts +0 -143
- package/mock/monorise/learner.ts +0 -66
- package/mock/monorise/learning-activity.ts +0 -62
- package/mock/monorise/learning-journey-config.ts +0 -34
- package/mock/monorise/module.ts +0 -108
- package/mock/monorise/organization.ts +0 -63
- package/mock/monorise/reference.ts +0 -28
- package/mock/monorise/video.ts +0 -36
- package/processors/create-entity-processor.ts +0 -55
- package/processors/mutual-processor.ts +0 -262
- package/processors/prejoin-processor.ts +0 -264
- package/processors/replication-processor.ts +0 -261
- package/processors/tag-processor.ts +0 -174
- package/services/DependencyContainer.ts +0 -208
- package/services/entity-service-lifecycle.ts +0 -41
- package/services/entity.service.ts +0 -201
- package/services/mutual.service.ts +0 -285
- package/tsconfig.json +0 -116
- package/types/entity.type.ts +0 -62
- package/types/event.ts +0 -84
package/data/Entity.ts
DELETED
|
@@ -1,499 +0,0 @@
|
|
|
1
|
-
import {
|
|
2
|
-
type AttributeValue,
|
|
3
|
-
ConditionalCheckFailedException,
|
|
4
|
-
type DynamoDB,
|
|
5
|
-
type QueryCommandInput,
|
|
6
|
-
type TransactWriteItem,
|
|
7
|
-
type UpdateItemCommandInput,
|
|
8
|
-
} from '@aws-sdk/client-dynamodb';
|
|
9
|
-
import { marshall, unmarshall } from '@aws-sdk/util-dynamodb';
|
|
10
|
-
import type { EntitySchemaMap, Entity as EntityType } from '@monorise/base';
|
|
11
|
-
import { ulid } from 'ulid';
|
|
12
|
-
import {
|
|
13
|
-
EmailAuthEnabledEntities,
|
|
14
|
-
EntityConfig,
|
|
15
|
-
} from '#/lambda-layer/monorise';
|
|
16
|
-
import { StandardError } from '../errors/standard-error';
|
|
17
|
-
import type { ProjectionExpressionValues } from './ProjectionExpression';
|
|
18
|
-
import { Item } from './abstract/Item.base';
|
|
19
|
-
import { Repository } from './abstract/Repository.base';
|
|
20
|
-
|
|
21
|
-
export class Entity<T extends EntityType> extends Item {
|
|
22
|
-
public fullId: string;
|
|
23
|
-
|
|
24
|
-
constructor(
|
|
25
|
-
public entityType: T,
|
|
26
|
-
public entityId?: string,
|
|
27
|
-
public data: Partial<EntitySchemaMap[T]> = {},
|
|
28
|
-
private _createdAt?: Date,
|
|
29
|
-
private _updatedAt?: Date,
|
|
30
|
-
) {
|
|
31
|
-
super();
|
|
32
|
-
this.fullId = this.pk;
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
static fromItem<T extends EntityType>(
|
|
36
|
-
item?: Record<string, AttributeValue>,
|
|
37
|
-
): Entity<T> {
|
|
38
|
-
if (!item)
|
|
39
|
-
throw new StandardError('ENTITY_IS_UNDEFINED', 'Entity item empty');
|
|
40
|
-
|
|
41
|
-
const parsedItem = unmarshall(item);
|
|
42
|
-
|
|
43
|
-
return new Entity<T>(
|
|
44
|
-
parsedItem.entityType,
|
|
45
|
-
parsedItem.entityId,
|
|
46
|
-
parsedItem.data,
|
|
47
|
-
parsedItem.createdAt ? new Date(parsedItem.createdAt) : undefined,
|
|
48
|
-
parsedItem.updatedAt ? new Date(parsedItem.updatedAt) : undefined,
|
|
49
|
-
);
|
|
50
|
-
}
|
|
51
|
-
|
|
52
|
-
get pk(): string {
|
|
53
|
-
return `${this.entityType}#${this.entityId}`;
|
|
54
|
-
}
|
|
55
|
-
|
|
56
|
-
get sk(): string {
|
|
57
|
-
return '#METADATA#';
|
|
58
|
-
}
|
|
59
|
-
|
|
60
|
-
get listActionKey(): string {
|
|
61
|
-
return `LIST#${this.entityType}`;
|
|
62
|
-
}
|
|
63
|
-
|
|
64
|
-
get emailKeys(): Record<string, AttributeValue> {
|
|
65
|
-
return {
|
|
66
|
-
PK: {
|
|
67
|
-
S: `EMAIL#${(this.data as Partial<EntitySchemaMap[T]> & { email: string }).email}`,
|
|
68
|
-
},
|
|
69
|
-
SK: {
|
|
70
|
-
S: `${this.entityType}#${this.entityId}`,
|
|
71
|
-
},
|
|
72
|
-
};
|
|
73
|
-
}
|
|
74
|
-
|
|
75
|
-
get createdAt(): string | undefined {
|
|
76
|
-
return this._createdAt?.toISOString();
|
|
77
|
-
}
|
|
78
|
-
|
|
79
|
-
get updatedAt(): string | undefined {
|
|
80
|
-
return this._updatedAt?.toISOString();
|
|
81
|
-
}
|
|
82
|
-
|
|
83
|
-
toItem(): Record<string, AttributeValue> {
|
|
84
|
-
return {
|
|
85
|
-
...marshall(this.toJSON(), { removeUndefinedValues: true }),
|
|
86
|
-
...this.keys(),
|
|
87
|
-
};
|
|
88
|
-
}
|
|
89
|
-
|
|
90
|
-
toJSON(): Record<string, unknown> {
|
|
91
|
-
return {
|
|
92
|
-
entityType: this.entityType,
|
|
93
|
-
entityId: this.entityId,
|
|
94
|
-
data: this.data,
|
|
95
|
-
createdAt: this.createdAt,
|
|
96
|
-
updatedAt: this.updatedAt,
|
|
97
|
-
};
|
|
98
|
-
}
|
|
99
|
-
}
|
|
100
|
-
|
|
101
|
-
export class EntityRepository extends Repository {
|
|
102
|
-
constructor(
|
|
103
|
-
private readonly TABLE_NAME: string,
|
|
104
|
-
private readonly dynamodbClient: DynamoDB,
|
|
105
|
-
) {
|
|
106
|
-
super();
|
|
107
|
-
}
|
|
108
|
-
|
|
109
|
-
async listEntities<T extends EntityType>({
|
|
110
|
-
entityType,
|
|
111
|
-
limit, // if this is not set, it will return all items
|
|
112
|
-
between,
|
|
113
|
-
options = {},
|
|
114
|
-
}: {
|
|
115
|
-
entityType: T;
|
|
116
|
-
limit?: number;
|
|
117
|
-
between?: {
|
|
118
|
-
start: string;
|
|
119
|
-
end: string;
|
|
120
|
-
};
|
|
121
|
-
options?: {
|
|
122
|
-
lastKey?: Record<string, AttributeValue>;
|
|
123
|
-
ProjectionExpression?: ProjectionExpressionValues;
|
|
124
|
-
};
|
|
125
|
-
}): Promise<{
|
|
126
|
-
items: Entity<T>[];
|
|
127
|
-
totalCount?: number;
|
|
128
|
-
lastKey?: Record<string, AttributeValue>;
|
|
129
|
-
}> {
|
|
130
|
-
const entity = new Entity(entityType);
|
|
131
|
-
// when query for records that SK are between provided start and end
|
|
132
|
-
const expression: Pick<
|
|
133
|
-
QueryCommandInput,
|
|
134
|
-
| 'KeyConditionExpression'
|
|
135
|
-
| 'ExpressionAttributeNames'
|
|
136
|
-
| 'ExpressionAttributeValues'
|
|
137
|
-
> = between
|
|
138
|
-
? {
|
|
139
|
-
KeyConditionExpression:
|
|
140
|
-
'#PK = :PK and #SK between :SKStart and :SKEnd',
|
|
141
|
-
ExpressionAttributeNames: {
|
|
142
|
-
'#PK': 'PK',
|
|
143
|
-
'#SK': 'SK',
|
|
144
|
-
},
|
|
145
|
-
ExpressionAttributeValues: {
|
|
146
|
-
':PK': {
|
|
147
|
-
S: entity.listActionKey,
|
|
148
|
-
},
|
|
149
|
-
':SKStart': {
|
|
150
|
-
S: `${entityType}#${between.start}`,
|
|
151
|
-
},
|
|
152
|
-
':SKEnd': {
|
|
153
|
-
S: `${entityType}#${between.end}`,
|
|
154
|
-
},
|
|
155
|
-
},
|
|
156
|
-
}
|
|
157
|
-
: {
|
|
158
|
-
KeyConditionExpression: '#PK = :PK',
|
|
159
|
-
ExpressionAttributeNames: {
|
|
160
|
-
'#PK': 'PK',
|
|
161
|
-
},
|
|
162
|
-
ExpressionAttributeValues: {
|
|
163
|
-
':PK': {
|
|
164
|
-
S: entity.listActionKey,
|
|
165
|
-
},
|
|
166
|
-
},
|
|
167
|
-
};
|
|
168
|
-
|
|
169
|
-
const defaultListQuery: QueryCommandInput = {
|
|
170
|
-
TableName: this.TABLE_NAME,
|
|
171
|
-
Limit: limit,
|
|
172
|
-
ScanIndexForward: false,
|
|
173
|
-
ProjectionExpression: options?.ProjectionExpression,
|
|
174
|
-
...expression,
|
|
175
|
-
};
|
|
176
|
-
|
|
177
|
-
let lastKey = options.lastKey;
|
|
178
|
-
let items: Record<string, AttributeValue>[] = [];
|
|
179
|
-
let remainingCount = limit ?? 0;
|
|
180
|
-
do {
|
|
181
|
-
const resp = await this.dynamodbClient.query({
|
|
182
|
-
...defaultListQuery,
|
|
183
|
-
...(remainingCount && { Limit: remainingCount }),
|
|
184
|
-
...(lastKey && {
|
|
185
|
-
ExclusiveStartKey: lastKey,
|
|
186
|
-
}),
|
|
187
|
-
});
|
|
188
|
-
items = items.concat(resp.Items ?? []);
|
|
189
|
-
|
|
190
|
-
lastKey = resp.LastEvaluatedKey;
|
|
191
|
-
|
|
192
|
-
if (limit) {
|
|
193
|
-
remainingCount = remainingCount - (resp.Items?.length ?? 0);
|
|
194
|
-
}
|
|
195
|
-
} while (
|
|
196
|
-
// limit is given, haven't reach limit, and there are still items to retrieve
|
|
197
|
-
(limit && remainingCount && lastKey) ||
|
|
198
|
-
// no limit is given and there are still items to retrieve
|
|
199
|
-
(!limit && lastKey)
|
|
200
|
-
);
|
|
201
|
-
|
|
202
|
-
return {
|
|
203
|
-
items: (items || []).map(Entity.fromItem<T>),
|
|
204
|
-
totalCount: items.length,
|
|
205
|
-
lastKey,
|
|
206
|
-
};
|
|
207
|
-
}
|
|
208
|
-
|
|
209
|
-
async getEntity<T extends EntityType>(
|
|
210
|
-
entityType: T,
|
|
211
|
-
entityId: string,
|
|
212
|
-
): Promise<Entity<T>> {
|
|
213
|
-
const entity = new Entity(entityType, entityId);
|
|
214
|
-
const resp = await this.dynamodbClient.getItem({
|
|
215
|
-
TableName: this.TABLE_NAME,
|
|
216
|
-
Key: entity.keys(),
|
|
217
|
-
});
|
|
218
|
-
|
|
219
|
-
return Entity.fromItem(resp.Item);
|
|
220
|
-
}
|
|
221
|
-
|
|
222
|
-
async getEntityByEmail<T extends EntityType>(
|
|
223
|
-
entityType: T,
|
|
224
|
-
email: string,
|
|
225
|
-
): Promise<Entity<T>> {
|
|
226
|
-
const resp = await this.dynamodbClient.query({
|
|
227
|
-
TableName: this.TABLE_NAME,
|
|
228
|
-
KeyConditionExpression: '#PK = :PK and begins_with(#SK, :SK)',
|
|
229
|
-
ExpressionAttributeNames: {
|
|
230
|
-
'#PK': 'PK',
|
|
231
|
-
'#SK': 'SK',
|
|
232
|
-
},
|
|
233
|
-
ExpressionAttributeValues: {
|
|
234
|
-
':PK': { S: `EMAIL#${email}` },
|
|
235
|
-
':SK': { S: entityType as unknown as string },
|
|
236
|
-
},
|
|
237
|
-
});
|
|
238
|
-
|
|
239
|
-
return Entity.fromItem(resp.Items?.[0]);
|
|
240
|
-
}
|
|
241
|
-
|
|
242
|
-
async getEmailAvailability<T extends EntityType>(
|
|
243
|
-
entityType: T,
|
|
244
|
-
email: string,
|
|
245
|
-
): Promise<void> {
|
|
246
|
-
const resp = await this.dynamodbClient.query({
|
|
247
|
-
TableName: this.TABLE_NAME,
|
|
248
|
-
KeyConditionExpression: '#PK = :PK and begins_with(#SK, :SK)',
|
|
249
|
-
ExpressionAttributeNames: {
|
|
250
|
-
'#PK': 'PK',
|
|
251
|
-
'#SK': 'SK',
|
|
252
|
-
},
|
|
253
|
-
ExpressionAttributeValues: {
|
|
254
|
-
':PK': { S: `EMAIL#${email}` },
|
|
255
|
-
':SK': { S: entityType as unknown as string },
|
|
256
|
-
},
|
|
257
|
-
});
|
|
258
|
-
|
|
259
|
-
if (resp.Items?.[0]) {
|
|
260
|
-
throw new StandardError('EMAIL_EXISTS', 'Email already exists');
|
|
261
|
-
}
|
|
262
|
-
|
|
263
|
-
return;
|
|
264
|
-
}
|
|
265
|
-
|
|
266
|
-
createEntityTransactItems<T extends EntityType>(
|
|
267
|
-
entity: Entity<T>,
|
|
268
|
-
opts?: {
|
|
269
|
-
mutualId?: string;
|
|
270
|
-
},
|
|
271
|
-
): TransactWriteItem[] {
|
|
272
|
-
const TransactItems: TransactWriteItem[] = [
|
|
273
|
-
{
|
|
274
|
-
Put: {
|
|
275
|
-
TableName: this.TABLE_NAME,
|
|
276
|
-
ConditionExpression: 'attribute_not_exists(PK)',
|
|
277
|
-
Item: {
|
|
278
|
-
...entity.toItem(),
|
|
279
|
-
...(opts?.mutualId && {
|
|
280
|
-
R2PK: { S: opts.mutualId },
|
|
281
|
-
R2SK: { S: entity.pk },
|
|
282
|
-
}),
|
|
283
|
-
},
|
|
284
|
-
},
|
|
285
|
-
},
|
|
286
|
-
{
|
|
287
|
-
Put: {
|
|
288
|
-
TableName: this.TABLE_NAME,
|
|
289
|
-
ConditionExpression: 'attribute_not_exists(PK)',
|
|
290
|
-
Item: {
|
|
291
|
-
...entity.toItem(),
|
|
292
|
-
PK: { S: entity.listActionKey },
|
|
293
|
-
SK: entity.keys().PK,
|
|
294
|
-
R1PK: entity.keys().PK,
|
|
295
|
-
R1SK: { S: entity.listActionKey },
|
|
296
|
-
},
|
|
297
|
-
},
|
|
298
|
-
},
|
|
299
|
-
];
|
|
300
|
-
|
|
301
|
-
// currently when detected it's an account, create email record
|
|
302
|
-
// TODO: Future improvement, if we introduce multiple ways to register/login,
|
|
303
|
-
// here we should also check if entity has the respective auth method defined
|
|
304
|
-
// in the config file
|
|
305
|
-
if (EmailAuthEnabledEntities.includes(entity.entityType)) {
|
|
306
|
-
TransactItems.push({
|
|
307
|
-
Put: {
|
|
308
|
-
TableName: this.TABLE_NAME,
|
|
309
|
-
ConditionExpression: 'attribute_not_exists(PK)',
|
|
310
|
-
Item: {
|
|
311
|
-
...entity.toItem(),
|
|
312
|
-
...entity.emailKeys,
|
|
313
|
-
R1PK: entity.emailKeys.SK,
|
|
314
|
-
R1SK: entity.emailKeys.PK,
|
|
315
|
-
},
|
|
316
|
-
},
|
|
317
|
-
});
|
|
318
|
-
}
|
|
319
|
-
|
|
320
|
-
return TransactItems;
|
|
321
|
-
}
|
|
322
|
-
|
|
323
|
-
async createEntity<T extends EntityType>(
|
|
324
|
-
entityType: T,
|
|
325
|
-
entityPayload: EntitySchemaMap[T],
|
|
326
|
-
entityId?: string,
|
|
327
|
-
opts?: {
|
|
328
|
-
createAndUpdateDatetime?: Date;
|
|
329
|
-
mutualId?: string;
|
|
330
|
-
},
|
|
331
|
-
): Promise<Entity<T>> {
|
|
332
|
-
const currentDatetime = opts?.createAndUpdateDatetime ?? new Date();
|
|
333
|
-
const entity = new Entity<T>(
|
|
334
|
-
entityType,
|
|
335
|
-
entityId || ulid(),
|
|
336
|
-
entityPayload,
|
|
337
|
-
currentDatetime,
|
|
338
|
-
currentDatetime,
|
|
339
|
-
);
|
|
340
|
-
const TransactItems = this.createEntityTransactItems<T>(entity, {
|
|
341
|
-
mutualId: opts?.mutualId,
|
|
342
|
-
});
|
|
343
|
-
|
|
344
|
-
await this.dynamodbClient.transactWriteItems({ TransactItems });
|
|
345
|
-
|
|
346
|
-
return entity;
|
|
347
|
-
}
|
|
348
|
-
|
|
349
|
-
async upsertEntity<T extends EntityType>(
|
|
350
|
-
entityType: T,
|
|
351
|
-
entityId: string,
|
|
352
|
-
payload: Partial<EntitySchemaMap[T]>,
|
|
353
|
-
): Promise<Entity<T>> {
|
|
354
|
-
const toUpdateExpressions = this.toUpdate({
|
|
355
|
-
entityType,
|
|
356
|
-
entityId,
|
|
357
|
-
data: payload,
|
|
358
|
-
});
|
|
359
|
-
const params: UpdateItemCommandInput = {
|
|
360
|
-
TableName: this.TABLE_NAME,
|
|
361
|
-
ReturnValues: 'ALL_NEW',
|
|
362
|
-
Key: new Entity(entityType, entityId).keys(),
|
|
363
|
-
UpdateExpression: toUpdateExpressions.UpdateExpression,
|
|
364
|
-
ExpressionAttributeNames: {
|
|
365
|
-
...toUpdateExpressions.ExpressionAttributeNames,
|
|
366
|
-
},
|
|
367
|
-
ExpressionAttributeValues: {
|
|
368
|
-
...toUpdateExpressions.ExpressionAttributeValues,
|
|
369
|
-
},
|
|
370
|
-
};
|
|
371
|
-
|
|
372
|
-
const resp = await this.dynamodbClient.updateItem(params);
|
|
373
|
-
const updatedEntity = Entity.fromItem<T>(resp.Attributes);
|
|
374
|
-
return updatedEntity;
|
|
375
|
-
}
|
|
376
|
-
|
|
377
|
-
async updateEntity<T extends EntityType>(
|
|
378
|
-
entityType: T,
|
|
379
|
-
entityId: string,
|
|
380
|
-
toUpdate: {
|
|
381
|
-
data: Partial<EntitySchemaMap[T]>;
|
|
382
|
-
updatedAt?: string;
|
|
383
|
-
},
|
|
384
|
-
opts?: {
|
|
385
|
-
ConditionExpression: string;
|
|
386
|
-
ExpressionAttributeNames: Record<string, string>;
|
|
387
|
-
ExpressionAttributeValues: Record<string, AttributeValue>;
|
|
388
|
-
},
|
|
389
|
-
): Promise<Entity<T>> {
|
|
390
|
-
try {
|
|
391
|
-
const currentDatetime = new Date().toISOString();
|
|
392
|
-
const toUpdateExpressions = this.toUpdate({
|
|
393
|
-
updatedAt: currentDatetime,
|
|
394
|
-
...toUpdate,
|
|
395
|
-
});
|
|
396
|
-
const params: UpdateItemCommandInput = {
|
|
397
|
-
TableName: this.TABLE_NAME,
|
|
398
|
-
ReturnValues: 'ALL_NEW',
|
|
399
|
-
Key: new Entity(entityType, entityId).keys(),
|
|
400
|
-
ConditionExpression:
|
|
401
|
-
opts?.ConditionExpression || 'attribute_exists(PK)',
|
|
402
|
-
UpdateExpression: toUpdateExpressions.UpdateExpression,
|
|
403
|
-
ExpressionAttributeNames: {
|
|
404
|
-
...toUpdateExpressions.ExpressionAttributeNames,
|
|
405
|
-
...opts?.ExpressionAttributeNames,
|
|
406
|
-
},
|
|
407
|
-
ExpressionAttributeValues: {
|
|
408
|
-
...toUpdateExpressions.ExpressionAttributeValues,
|
|
409
|
-
...opts?.ExpressionAttributeValues,
|
|
410
|
-
},
|
|
411
|
-
};
|
|
412
|
-
|
|
413
|
-
const resp = await this.dynamodbClient.updateItem(params);
|
|
414
|
-
const updatedEntity = Entity.fromItem<T>(resp.Attributes);
|
|
415
|
-
return updatedEntity;
|
|
416
|
-
} catch (err) {
|
|
417
|
-
if (err instanceof ConditionalCheckFailedException) {
|
|
418
|
-
throw new StandardError('ENTITY_NOT_FOUND', 'Entity not found', err, {
|
|
419
|
-
entityId,
|
|
420
|
-
toUpdate,
|
|
421
|
-
});
|
|
422
|
-
}
|
|
423
|
-
|
|
424
|
-
throw err;
|
|
425
|
-
}
|
|
426
|
-
}
|
|
427
|
-
|
|
428
|
-
async deleteEntity<T extends EntityType>(
|
|
429
|
-
entityType: T,
|
|
430
|
-
entityId: string,
|
|
431
|
-
): Promise<void> {
|
|
432
|
-
try {
|
|
433
|
-
const entity = new Entity(entityType, entityId);
|
|
434
|
-
|
|
435
|
-
await this.dynamodbClient.deleteItem({
|
|
436
|
-
TableName: this.TABLE_NAME,
|
|
437
|
-
Key: entity.keys(),
|
|
438
|
-
ConditionExpression: 'attribute_exists(PK)',
|
|
439
|
-
});
|
|
440
|
-
} catch (err) {
|
|
441
|
-
if (err instanceof ConditionalCheckFailedException) {
|
|
442
|
-
throw new StandardError('ENTITY_NOT_FOUND', 'Entity not found', err, {
|
|
443
|
-
entityId,
|
|
444
|
-
});
|
|
445
|
-
}
|
|
446
|
-
|
|
447
|
-
throw err;
|
|
448
|
-
}
|
|
449
|
-
}
|
|
450
|
-
|
|
451
|
-
async queryEntities<T extends EntityType>(
|
|
452
|
-
entityType: T,
|
|
453
|
-
query: string,
|
|
454
|
-
): Promise<{
|
|
455
|
-
items: Entity<T>[];
|
|
456
|
-
totalCount?: number;
|
|
457
|
-
filteredCount?: number;
|
|
458
|
-
}> {
|
|
459
|
-
const results: { items: Entity<T>[]; totalCount: number } = {
|
|
460
|
-
items: [],
|
|
461
|
-
totalCount: 0,
|
|
462
|
-
};
|
|
463
|
-
// let regex be empty if its invalid (eg. +)
|
|
464
|
-
let queryRegex = /(?:)/;
|
|
465
|
-
try {
|
|
466
|
-
queryRegex = new RegExp(query.toLowerCase());
|
|
467
|
-
} catch (err) {
|
|
468
|
-
return results;
|
|
469
|
-
}
|
|
470
|
-
|
|
471
|
-
const listResults = await this.listEntities<T>({
|
|
472
|
-
entityType,
|
|
473
|
-
});
|
|
474
|
-
results.items.push(...listResults.items);
|
|
475
|
-
results.totalCount += listResults.totalCount || 0;
|
|
476
|
-
|
|
477
|
-
const filteredItems: Entity<T>[] = [];
|
|
478
|
-
|
|
479
|
-
const { searchableFields } = EntityConfig[entityType];
|
|
480
|
-
|
|
481
|
-
for (const item of results.items) {
|
|
482
|
-
const searchTerm = (searchableFields ?? [])
|
|
483
|
-
.map((field) =>
|
|
484
|
-
(item.data as Record<string, any>)[field]?.toLowerCase(),
|
|
485
|
-
)
|
|
486
|
-
.join(' ');
|
|
487
|
-
const isMatched = queryRegex.test(searchTerm);
|
|
488
|
-
if (isMatched) {
|
|
489
|
-
filteredItems.push(item);
|
|
490
|
-
}
|
|
491
|
-
}
|
|
492
|
-
|
|
493
|
-
return {
|
|
494
|
-
items: filteredItems,
|
|
495
|
-
totalCount: results.totalCount,
|
|
496
|
-
filteredCount: filteredItems.length,
|
|
497
|
-
};
|
|
498
|
-
}
|
|
499
|
-
}
|
package/data/EventUtils.ts
DELETED
|
@@ -1,47 +0,0 @@
|
|
|
1
|
-
import type { Entity as EntityType } from '@monorise/base';
|
|
2
|
-
import { EntityConfig } from '#/lambda-layer/monorise';
|
|
3
|
-
import type { publishEvent as publishEventType } from '../helpers/event';
|
|
4
|
-
import { EVENT } from '../types/event';
|
|
5
|
-
import type { Entity } from './Entity';
|
|
6
|
-
|
|
7
|
-
type PublishEventProps<T extends EntityType> = {
|
|
8
|
-
entity: Entity<T>;
|
|
9
|
-
mutualPayload: Record<string, any>;
|
|
10
|
-
};
|
|
11
|
-
|
|
12
|
-
export class EventUtils {
|
|
13
|
-
constructor(private publishEvent: typeof publishEventType) {}
|
|
14
|
-
|
|
15
|
-
// Always when create entity, this must be called following, to make sure mutual data processor will be called
|
|
16
|
-
publishCreateMutualsEvent = async <T extends EntityType>({
|
|
17
|
-
entity,
|
|
18
|
-
mutualPayload,
|
|
19
|
-
}: PublishEventProps<T>) => {
|
|
20
|
-
const publishEventPromises = [];
|
|
21
|
-
for (const [fieldKey, config] of Object.entries(
|
|
22
|
-
EntityConfig[entity.entityType].mutual?.mutualFields || {},
|
|
23
|
-
)) {
|
|
24
|
-
const toMutualIds = config.toMutualIds;
|
|
25
|
-
const mutualPayloadByFieldKey = mutualPayload[fieldKey];
|
|
26
|
-
if (!mutualPayloadByFieldKey) continue;
|
|
27
|
-
|
|
28
|
-
publishEventPromises.push(
|
|
29
|
-
this.publishEvent({
|
|
30
|
-
event: EVENT.CORE.ENTITY_MUTUAL_TO_CREATE,
|
|
31
|
-
payload: {
|
|
32
|
-
byEntityType: entity.entityType,
|
|
33
|
-
byEntityId: entity.entityId,
|
|
34
|
-
entityType: config.entityType,
|
|
35
|
-
field: fieldKey,
|
|
36
|
-
mutualIds: toMutualIds
|
|
37
|
-
? toMutualIds(mutualPayloadByFieldKey)
|
|
38
|
-
: mutualPayloadByFieldKey,
|
|
39
|
-
customContext: toMutualIds ? mutualPayloadByFieldKey : {},
|
|
40
|
-
publishedAt: entity.updatedAt || new Date().toISOString(),
|
|
41
|
-
},
|
|
42
|
-
}),
|
|
43
|
-
);
|
|
44
|
-
}
|
|
45
|
-
await Promise.allSettled(publishEventPromises);
|
|
46
|
-
};
|
|
47
|
-
}
|
package/data/FileObject.ts
DELETED
|
@@ -1,16 +0,0 @@
|
|
|
1
|
-
import { z } from 'zod';
|
|
2
|
-
|
|
3
|
-
export const fileObjectSchema = z.object({
|
|
4
|
-
name: z.string(),
|
|
5
|
-
url: z.string(),
|
|
6
|
-
});
|
|
7
|
-
|
|
8
|
-
export const fileSchema = z.object({
|
|
9
|
-
uid: z.string(),
|
|
10
|
-
name: z.string(),
|
|
11
|
-
regular: fileObjectSchema,
|
|
12
|
-
thumbnail: fileObjectSchema.optional(),
|
|
13
|
-
jobId: z.string().optional(),
|
|
14
|
-
});
|
|
15
|
-
|
|
16
|
-
export type File = z.infer<typeof fileSchema>;
|