dyna-record 0.3.6 → 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/README.md +12 -10
- package/dist/src/decorators/attributes/ForeignKeyAttribute.d.ts +10 -6
- package/dist/src/decorators/attributes/ForeignKeyAttribute.d.ts.map +1 -1
- package/dist/src/decorators/attributes/ForeignKeyAttribute.js +11 -5
- package/dist/src/decorators/relationships/BelongsTo.d.ts +3 -2
- package/dist/src/decorators/relationships/BelongsTo.d.ts.map +1 -1
- package/dist/src/decorators/relationships/types.d.ts +10 -5
- package/dist/src/decorators/relationships/types.d.ts.map +1 -1
- package/dist/src/metadata/AttributeMetadata.d.ts +4 -0
- package/dist/src/metadata/AttributeMetadata.d.ts.map +1 -1
- package/dist/src/metadata/AttributeMetadata.js +3 -0
- package/dist/src/metadata/EntityMetadata.d.ts +11 -1
- package/dist/src/metadata/EntityMetadata.d.ts.map +1 -1
- package/dist/src/metadata/EntityMetadata.js +17 -0
- package/dist/src/metadata/types.d.ts +13 -1
- package/dist/src/metadata/types.d.ts.map +1 -1
- package/dist/src/metadata/utils.d.ts +7 -1
- package/dist/src/metadata/utils.d.ts.map +1 -1
- package/dist/src/metadata/utils.js +9 -1
- package/dist/src/operations/Create/Create.d.ts +7 -0
- package/dist/src/operations/Create/Create.d.ts.map +1 -1
- package/dist/src/operations/Create/Create.js +27 -0
- package/dist/src/operations/Update/Update.d.ts +6 -0
- package/dist/src/operations/Update/Update.d.ts.map +1 -1
- package/dist/src/operations/Update/Update.js +28 -0
- package/dist/src/types.d.ts +13 -3
- package/dist/src/types.d.ts.map +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -172,6 +172,8 @@ Define foreign keys in order to support [@BelongsTo](https://dyna-record.com/fun
|
|
|
172
172
|
- The [alias](https://dyna-record.com/interfaces/AttributeOptions.html#alias) option allows you to specify the attribute name as it appears in the DynamoDB table, different from your class property name.
|
|
173
173
|
- Set nullable foreign key attributes as optional for optimal type safety
|
|
174
174
|
- Attempting to remove an entity from a non-nullable foreign key will result in a [NullConstrainViolationError](https://dyna-record.com/classes/NullConstraintViolationError.html)
|
|
175
|
+
- Always provide the referenced entity class to `@ForeignKeyAttribute` (for example `@ForeignKeyAttribute(() => Customer)`); this allows DynaRecord to enforce referential integrity even when no relationship decorator is defined.
|
|
176
|
+
- `Create` and `Update` automatically add DynamoDB condition checks for standalone foreign keys (those without a relationship decorator) to ensure the referenced entity exists, enabling referential integrity even when no denormalised access pattern is required.
|
|
175
177
|
|
|
176
178
|
```typescript
|
|
177
179
|
import {
|
|
@@ -184,8 +186,8 @@ import {
|
|
|
184
186
|
|
|
185
187
|
@Entity
|
|
186
188
|
class Assignment extends MyTable {
|
|
187
|
-
@ForeignKeyAttribute()
|
|
188
|
-
public readonly courseId: ForeignKey
|
|
189
|
+
@ForeignKeyAttribute(() => Course)
|
|
190
|
+
public readonly courseId: ForeignKey<Course>;
|
|
189
191
|
|
|
190
192
|
@BelongsTo(() => Course, { foreignKey: "courseId" })
|
|
191
193
|
public readonly course: Course;
|
|
@@ -193,8 +195,8 @@ class Assignment extends MyTable {
|
|
|
193
195
|
|
|
194
196
|
@Entity
|
|
195
197
|
class Course extends MyTable {
|
|
196
|
-
@ForeignKeyAttribute({ nullable: true })
|
|
197
|
-
public readonly teacherId?: NullableForeignKey
|
|
198
|
+
@ForeignKeyAttribute(() => Teacher, { nullable: true })
|
|
199
|
+
public readonly teacherId?: NullableForeignKey<Teacher>; // Set as optional
|
|
198
200
|
|
|
199
201
|
@BelongsTo(() => Teacher, { foreignKey: "teacherId" })
|
|
200
202
|
public readonly teacher?: Teacher; // Set as optional because its linked through NullableForeignKey
|
|
@@ -232,8 +234,8 @@ class Assignment extends MyTable {
|
|
|
232
234
|
|
|
233
235
|
@Entity
|
|
234
236
|
class Grade extends MyTable {
|
|
235
|
-
@ForeignKeyAttribute()
|
|
236
|
-
public readonly assignmentId: ForeignKey
|
|
237
|
+
@ForeignKeyAttribute(() => Assignment)
|
|
238
|
+
public readonly assignmentId: ForeignKey<Assignment>;
|
|
237
239
|
|
|
238
240
|
// 'assignmentId' Must be defined on self as ForeignKey or NullableForeignKey
|
|
239
241
|
@BelongsTo(() => Assignment, { foreignKey: "assignmentId" })
|
|
@@ -257,8 +259,8 @@ class Teacher extends MyTable {
|
|
|
257
259
|
|
|
258
260
|
@Entity
|
|
259
261
|
class Course extends MyTable {
|
|
260
|
-
@ForeignKeyAttribute({ nullable: true })
|
|
261
|
-
public readonly teacherId?: NullableForeignKey
|
|
262
|
+
@ForeignKeyAttribute(() => Teacher, { nullable: true })
|
|
263
|
+
public readonly teacherId?: NullableForeignKey<Teacher>; // Mark as optional
|
|
262
264
|
|
|
263
265
|
// 'teacherId' Must be defined on self as ForeignKey or NullableForeignKey
|
|
264
266
|
@BelongsTo(() => Teacher, { foreignKey: "teacherId" })
|
|
@@ -282,8 +284,8 @@ class Teacher extends MyTable {
|
|
|
282
284
|
|
|
283
285
|
@Entity
|
|
284
286
|
class Course extends MyTable {
|
|
285
|
-
@ForeignKeyAttribute({ nullable: true })
|
|
286
|
-
public readonly teacherId?: NullableForeignKey
|
|
287
|
+
@ForeignKeyAttribute(() => Teacher, { nullable: true })
|
|
288
|
+
public readonly teacherId?: NullableForeignKey<Teacher>; // Mark as optional
|
|
287
289
|
}
|
|
288
290
|
```
|
|
289
291
|
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type DynaRecord from "../../DynaRecord";
|
|
2
|
-
import type { ForeignKey, NullableForeignKey } from "../../types";
|
|
2
|
+
import type { EntityClass, ForeignKey, NullableForeignKey } from "../../types";
|
|
3
3
|
import type { AttributeDecoratorContext, AttributeOptions } from "../types";
|
|
4
4
|
/**
|
|
5
5
|
* A decorator for annotating class fields as foreign keys within the context of a single-table design entity, aimed at establishing and managing relationships between different entities in a relational manner. This decorator enables the clear and explicit declaration of foreign key relationships, contributing to the ORM's ability to navigate and resolve these associations efficiently.
|
|
@@ -8,21 +8,25 @@ import type { AttributeDecoratorContext, AttributeOptions } from "../types";
|
|
|
8
8
|
*
|
|
9
9
|
* Does not allow property to be optional.
|
|
10
10
|
*
|
|
11
|
+
* Supplying the target entity enables DynaRecord to enforce referential integrity for the foreign key even when no relationship decorators are defined (for example when a foreign key is used purely for validation without denormalising related records).
|
|
12
|
+
*
|
|
11
13
|
* @template T The entity the decorator is applied to.
|
|
14
|
+
* @template K The entity that the foreign key references.
|
|
15
|
+
* @param getTarget A function returning the constructor for the entity referenced by the foreign key. This allows deferred resolution to avoid circular dependency issues.
|
|
12
16
|
* @param props An optional object of {@link AttributeOptions}, including configuration options such as metadata attributes. These options allow for additional customization of the foreign key attribute, including aliasing and metadata tagging.
|
|
13
17
|
* @returns A class field decorator function that targets and initializes the class's prototype to register the foreign key with the ORM's metadata system. This registration is crucial for enabling the ORM to correctly interpret and manage the relationships between entities.
|
|
14
18
|
*
|
|
15
19
|
* Usage example:
|
|
16
20
|
* ```typescript
|
|
17
21
|
* class Order extends TableClass {
|
|
18
|
-
* @ForeignKeyAttribute({ alias: 'UserID' })
|
|
19
|
-
* public userId: ForeignKey
|
|
22
|
+
* @ForeignKeyAttribute(() => User, { alias: 'UserID' })
|
|
23
|
+
* public userId: ForeignKey<User>; // Foreign key to the User entity. Cannot be optional.
|
|
20
24
|
*
|
|
21
25
|
* @BelongsTo(() => User, { foreignKey: "userId" })
|
|
22
26
|
* public readonly user: User; // Cannot be optional
|
|
23
27
|
*
|
|
24
|
-
* @ForeignKeyAttribute({ alias: 'ProfileId', nullable: true })
|
|
25
|
-
* public profileId?: NullableForeignKey
|
|
28
|
+
* @ForeignKeyAttribute(() => Profile, { alias: 'ProfileId', nullable: true })
|
|
29
|
+
* public profileId?: NullableForeignKey<Profile>; // Set to optional. Nullable foreign key to another entity (e.g., UserProfile)
|
|
26
30
|
*
|
|
27
31
|
* @BelongsTo(() => Profile, { foreignKey: "profileId" })
|
|
28
32
|
* public readonly profile?: Profile; // Set to optional because its linked via a NullableForeignKey
|
|
@@ -31,6 +35,6 @@ import type { AttributeDecoratorContext, AttributeOptions } from "../types";
|
|
|
31
35
|
*
|
|
32
36
|
* Here, `@ForeignKeyAttribute` decorates `userId` of `Order`, designating it as a foreign key that references the `User` entity. This decoration not only clarifies the nature of the relationship but also empowers the ORM to enforce relational integrity and facilitate entity association operations.
|
|
33
37
|
*/
|
|
34
|
-
declare function ForeignKeyAttribute<T extends DynaRecord, P extends AttributeOptions>(props?: P): (_value: undefined, context: AttributeDecoratorContext<T, P["nullable"] extends true ? NullableForeignKey : ForeignKey
|
|
38
|
+
declare function ForeignKeyAttribute<TargetEntity extends DynaRecord, T extends DynaRecord, P extends AttributeOptions>(getTarget: () => EntityClass<TargetEntity>, props?: P): (_value: undefined, context: AttributeDecoratorContext<T, P["nullable"] extends true ? NullableForeignKey<TargetEntity> : ForeignKey<TargetEntity>, P>) => void;
|
|
35
39
|
export default ForeignKeyAttribute;
|
|
36
40
|
//# sourceMappingURL=ForeignKeyAttribute.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ForeignKeyAttribute.d.ts","sourceRoot":"","sources":["../../../../src/decorators/attributes/ForeignKeyAttribute.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,UAAU,MAAM,kBAAkB,CAAC;AAE/C,OAAO,KAAK,EAAE,UAAU,EAAE,kBAAkB,EAAE,MAAM,aAAa,CAAC;
|
|
1
|
+
{"version":3,"file":"ForeignKeyAttribute.d.ts","sourceRoot":"","sources":["../../../../src/decorators/attributes/ForeignKeyAttribute.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,UAAU,MAAM,kBAAkB,CAAC;AAE/C,OAAO,KAAK,EAAE,WAAW,EAAE,UAAU,EAAE,kBAAkB,EAAE,MAAM,aAAa,CAAC;AAC/E,OAAO,KAAK,EAAE,yBAAyB,EAAE,gBAAgB,EAAE,MAAM,UAAU,CAAC;AAE5E;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAiCG;AACH,iBAAS,mBAAmB,CAC1B,YAAY,SAAS,UAAU,EAC/B,CAAC,SAAS,UAAU,EACpB,CAAC,SAAS,gBAAgB,EAC1B,SAAS,EAAE,MAAM,WAAW,CAAC,YAAY,CAAC,EAAE,KAAK,CAAC,EAAE,CAAC,YAE3C,SAAS,WACR,yBAAyB,CAChC,CAAC,EACD,CAAC,CAAC,UAAU,CAAC,SAAS,IAAI,GACtB,kBAAkB,CAAC,YAAY,CAAC,GAChC,UAAU,CAAC,YAAY,CAAC,EAC5B,CAAC,CACF,UAgBJ;AAED,eAAe,mBAAmB,CAAC"}
|
|
@@ -12,21 +12,25 @@ const metadata_1 = __importDefault(require("../../metadata"));
|
|
|
12
12
|
*
|
|
13
13
|
* Does not allow property to be optional.
|
|
14
14
|
*
|
|
15
|
+
* Supplying the target entity enables DynaRecord to enforce referential integrity for the foreign key even when no relationship decorators are defined (for example when a foreign key is used purely for validation without denormalising related records).
|
|
16
|
+
*
|
|
15
17
|
* @template T The entity the decorator is applied to.
|
|
18
|
+
* @template K The entity that the foreign key references.
|
|
19
|
+
* @param getTarget A function returning the constructor for the entity referenced by the foreign key. This allows deferred resolution to avoid circular dependency issues.
|
|
16
20
|
* @param props An optional object of {@link AttributeOptions}, including configuration options such as metadata attributes. These options allow for additional customization of the foreign key attribute, including aliasing and metadata tagging.
|
|
17
21
|
* @returns A class field decorator function that targets and initializes the class's prototype to register the foreign key with the ORM's metadata system. This registration is crucial for enabling the ORM to correctly interpret and manage the relationships between entities.
|
|
18
22
|
*
|
|
19
23
|
* Usage example:
|
|
20
24
|
* ```typescript
|
|
21
25
|
* class Order extends TableClass {
|
|
22
|
-
* @ForeignKeyAttribute({ alias: 'UserID' })
|
|
23
|
-
* public userId: ForeignKey
|
|
26
|
+
* @ForeignKeyAttribute(() => User, { alias: 'UserID' })
|
|
27
|
+
* public userId: ForeignKey<User>; // Foreign key to the User entity. Cannot be optional.
|
|
24
28
|
*
|
|
25
29
|
* @BelongsTo(() => User, { foreignKey: "userId" })
|
|
26
30
|
* public readonly user: User; // Cannot be optional
|
|
27
31
|
*
|
|
28
|
-
* @ForeignKeyAttribute({ alias: 'ProfileId', nullable: true })
|
|
29
|
-
* public profileId?: NullableForeignKey
|
|
32
|
+
* @ForeignKeyAttribute(() => Profile, { alias: 'ProfileId', nullable: true })
|
|
33
|
+
* public profileId?: NullableForeignKey<Profile>; // Set to optional. Nullable foreign key to another entity (e.g., UserProfile)
|
|
30
34
|
*
|
|
31
35
|
* @BelongsTo(() => Profile, { foreignKey: "profileId" })
|
|
32
36
|
* public readonly profile?: Profile; // Set to optional because its linked via a NullableForeignKey
|
|
@@ -35,14 +39,16 @@ const metadata_1 = __importDefault(require("../../metadata"));
|
|
|
35
39
|
*
|
|
36
40
|
* Here, `@ForeignKeyAttribute` decorates `userId` of `Order`, designating it as a foreign key that references the `User` entity. This decoration not only clarifies the nature of the relationship but also empowers the ORM to enforce relational integrity and facilitate entity association operations.
|
|
37
41
|
*/
|
|
38
|
-
function ForeignKeyAttribute(props) {
|
|
42
|
+
function ForeignKeyAttribute(getTarget, props) {
|
|
39
43
|
return function (_value, context) {
|
|
40
44
|
if (context.kind === "field") {
|
|
41
45
|
context.addInitializer(function () {
|
|
46
|
+
const targetEntity = getTarget();
|
|
42
47
|
metadata_1.default.addEntityAttribute(this.constructor.name, {
|
|
43
48
|
attributeName: context.name.toString(),
|
|
44
49
|
nullable: props?.nullable,
|
|
45
50
|
type: zod_1.z.string(),
|
|
51
|
+
foreignKeyTarget: targetEntity,
|
|
46
52
|
...props
|
|
47
53
|
});
|
|
48
54
|
});
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import type DynaRecord from "../../DynaRecord";
|
|
2
2
|
import type { EntityClass } from "../../types";
|
|
3
|
-
import type { BelongsToField, BelongsToProps } from "./types";
|
|
3
|
+
import type { BelongsToField, BelongsToProps, BelongsToTarget } from "./types";
|
|
4
|
+
import type { ForeignEntityAttribute } from "../types";
|
|
4
5
|
/**
|
|
5
6
|
* A decorator for defining a "BelongsTo" relationship between entities in a single-table design using DynaRecord. This relationship indicates that the decorated field is a reference to another entity, effectively establishing a parent-child linkage. The decorator dynamically enforces the presence or optionality of this reference based on the nature of the foreign key, enhancing type safety and relationship integrity within the ORM model.
|
|
6
7
|
*
|
|
@@ -29,6 +30,6 @@ import type { BelongsToField, BelongsToProps } from "./types";
|
|
|
29
30
|
* ```
|
|
30
31
|
* In this example, `@BelongsTo` decorates the `user` field of the `Order` entity, establishing a "BelongsTo" relationship with the `User` entity via the `userId` foreign key. This decoration signifies that each `Order` instance is related to a specific `User` instance.
|
|
31
32
|
*/
|
|
32
|
-
declare function BelongsTo<
|
|
33
|
+
declare function BelongsTo<Source extends DynaRecord, FK extends ForeignEntityAttribute<Source>>(getTarget: () => EntityClass<BelongsToTarget<Source, FK>>, props: BelongsToProps<Source, FK>): (_value: undefined, context: ClassFieldDecoratorContext<Source, BelongsToField<Source, FK>>) => void;
|
|
33
34
|
export default BelongsTo;
|
|
34
35
|
//# sourceMappingURL=BelongsTo.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"BelongsTo.d.ts","sourceRoot":"","sources":["../../../../src/decorators/relationships/BelongsTo.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,UAAU,MAAM,kBAAkB,CAAC;AAC/C,OAAO,KAAK,EAAE,WAAW,EAAsB,MAAM,aAAa,CAAC;AACnE,OAAO,KAAK,EAAE,cAAc,EAAE,cAAc,EAAE,MAAM,SAAS,CAAC;
|
|
1
|
+
{"version":3,"file":"BelongsTo.d.ts","sourceRoot":"","sources":["../../../../src/decorators/relationships/BelongsTo.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,UAAU,MAAM,kBAAkB,CAAC;AAC/C,OAAO,KAAK,EAAE,WAAW,EAAsB,MAAM,aAAa,CAAC;AACnE,OAAO,KAAK,EAAE,cAAc,EAAE,cAAc,EAAE,eAAe,EAAE,MAAM,SAAS,CAAC;AAC/E,OAAO,KAAK,EAAE,sBAAsB,EAAE,MAAM,UAAU,CAAC;AAEvD;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2BG;AACH,iBAAS,SAAS,CAChB,MAAM,SAAS,UAAU,EACzB,EAAE,SAAS,sBAAsB,CAAC,MAAM,CAAC,EAEzC,SAAS,EAAE,MAAM,WAAW,CAAC,eAAe,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC,EACzD,KAAK,EAAE,cAAc,CAAC,MAAM,EAAE,EAAE,CAAC,YAGvB,SAAS,WACR,0BAA0B,CAAC,MAAM,EAAE,cAAc,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC,UAa1E;AAED,eAAe,SAAS,CAAC"}
|
|
@@ -1,11 +1,16 @@
|
|
|
1
1
|
import type DynaRecord from "../../DynaRecord";
|
|
2
|
-
import type { NullableForeignKey, Optional } from "../../types";
|
|
2
|
+
import type { ForeignKey, NullableForeignKey, Optional } from "../../types";
|
|
3
3
|
import type { ForeignEntityAttribute } from "../types";
|
|
4
|
-
|
|
5
|
-
|
|
4
|
+
type NullableForeignKeyBrand<T extends DynaRecord> = NonNullable<NullableForeignKey<T>>;
|
|
5
|
+
type NormalizedForeignKey<Value> = NonNullable<Value>;
|
|
6
|
+
type ExtractForeignKeyTarget<Value> = NormalizedForeignKey<Value> extends ForeignKey<infer Target> ? Target : NormalizedForeignKey<Value> extends NullableForeignKeyBrand<infer Target> ? Target : never;
|
|
7
|
+
export interface BelongsToProps<T extends DynaRecord, FK extends ForeignEntityAttribute<T>> {
|
|
8
|
+
foreignKey: FK;
|
|
6
9
|
}
|
|
10
|
+
export type BelongsToTarget<T extends DynaRecord, FK extends ForeignEntityAttribute<T>> = FK extends keyof T ? ExtractForeignKeyTarget<T[FK]> : never;
|
|
7
11
|
/**
|
|
8
|
-
* If the relationship is linked by a NullableForeignKey then it allows the field to be optional, otherwise it ensures that
|
|
12
|
+
* If the relationship is linked by a NullableForeignKey then it allows the field to be optional, otherwise it ensures that it is not optional
|
|
9
13
|
*/
|
|
10
|
-
export type BelongsToField<T extends DynaRecord,
|
|
14
|
+
export type BelongsToField<T extends DynaRecord, FK extends ForeignEntityAttribute<T>> = FK extends keyof T ? BelongsToTarget<T, FK> extends never ? never : undefined extends T[FK] ? Optional<BelongsToTarget<T, FK>> : BelongsToTarget<T, FK> : never;
|
|
15
|
+
export {};
|
|
11
16
|
//# sourceMappingURL=types.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../../src/decorators/relationships/types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,UAAU,MAAM,kBAAkB,CAAC;AAC/C,OAAO,KAAK,EAAE,kBAAkB,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAC;
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../../src/decorators/relationships/types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,UAAU,MAAM,kBAAkB,CAAC;AAC/C,OAAO,KAAK,EAAE,UAAU,EAAE,kBAAkB,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAC;AAC5E,OAAO,KAAK,EAAE,sBAAsB,EAAE,MAAM,UAAU,CAAC;AAEvD,KAAK,uBAAuB,CAAC,CAAC,SAAS,UAAU,IAAI,WAAW,CAC9D,kBAAkB,CAAC,CAAC,CAAC,CACtB,CAAC;AAEF,KAAK,oBAAoB,CAAC,KAAK,IAAI,WAAW,CAAC,KAAK,CAAC,CAAC;AAEtD,KAAK,uBAAuB,CAAC,KAAK,IAChC,oBAAoB,CAAC,KAAK,CAAC,SAAS,UAAU,CAAC,MAAM,MAAM,CAAC,GACxD,MAAM,GACN,oBAAoB,CAAC,KAAK,CAAC,SAAS,uBAAuB,CAAC,MAAM,MAAM,CAAC,GACvE,MAAM,GACN,KAAK,CAAC;AAEd,MAAM,WAAW,cAAc,CAC7B,CAAC,SAAS,UAAU,EACpB,EAAE,SAAS,sBAAsB,CAAC,CAAC,CAAC;IAEpC,UAAU,EAAE,EAAE,CAAC;CAChB;AAED,MAAM,MAAM,eAAe,CACzB,CAAC,SAAS,UAAU,EACpB,EAAE,SAAS,sBAAsB,CAAC,CAAC,CAAC,IAClC,EAAE,SAAS,MAAM,CAAC,GAAG,uBAAuB,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,GAAG,KAAK,CAAC;AAEhE;;GAEG;AACH,MAAM,MAAM,cAAc,CACxB,CAAC,SAAS,UAAU,EACpB,EAAE,SAAS,sBAAsB,CAAC,CAAC,CAAC,IAClC,EAAE,SAAS,MAAM,CAAC,GAClB,eAAe,CAAC,CAAC,EAAE,EAAE,CAAC,SAAS,KAAK,GAClC,KAAK,GACL,SAAS,SAAS,CAAC,CAAC,EAAE,CAAC,GACrB,QAAQ,CAAC,eAAe,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,GAChC,eAAe,CAAC,CAAC,EAAE,EAAE,CAAC,GAC1B,KAAK,CAAC"}
|
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
import { type ZodType } from "zod";
|
|
2
|
+
import type DynaRecord from "../DynaRecord";
|
|
2
3
|
import type { AttributeMetadataOptions, Serializers } from "./types";
|
|
4
|
+
import type { EntityClass } from "../types";
|
|
3
5
|
/**
|
|
4
6
|
* Represents the metadata for an attribute of an entity, including its name, alias (if any), nullability, and serialization strategies.
|
|
5
7
|
*
|
|
@@ -10,6 +12,7 @@ import type { AttributeMetadataOptions, Serializers } from "./types";
|
|
|
10
12
|
* @property {boolean} nullable - Indicates whether the attribute can be `null`, defining the attribute's nullability constraint within the database.
|
|
11
13
|
* @property {Serializers | undefined} serializers - Optional serialization strategies for converting the attribute between its database representation and its entity representation. This is particularly useful for custom data types not natively supported by DynamoDB.
|
|
12
14
|
* @property {ZodType} type - Zod validator to run on the attribute
|
|
15
|
+
* @property {EntityClass | undefined} foreignKeyTarget - When present, identifies the entity referenced by a foreign key attribute, enabling referential integrity enforcement.
|
|
13
16
|
*
|
|
14
17
|
* @param {AttributeMetadataOptions} options - Configuration options for the attribute metadata, including the attribute's name, optional alias, nullability, and serialization strategies.
|
|
15
18
|
*/
|
|
@@ -19,6 +22,7 @@ declare class AttributeMetadata {
|
|
|
19
22
|
readonly nullable: boolean;
|
|
20
23
|
readonly serializers?: Serializers;
|
|
21
24
|
readonly type: ZodType;
|
|
25
|
+
readonly foreignKeyTarget?: EntityClass<DynaRecord>;
|
|
22
26
|
constructor(options: AttributeMetadataOptions);
|
|
23
27
|
}
|
|
24
28
|
export default AttributeMetadata;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"AttributeMetadata.d.ts","sourceRoot":"","sources":["../../../src/metadata/AttributeMetadata.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,OAAO,EAAE,MAAM,KAAK,CAAC;AACnC,OAAO,KAAK,EAAE,wBAAwB,EAAE,WAAW,EAAE,MAAM,SAAS,CAAC;
|
|
1
|
+
{"version":3,"file":"AttributeMetadata.d.ts","sourceRoot":"","sources":["../../../src/metadata/AttributeMetadata.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,OAAO,EAAE,MAAM,KAAK,CAAC;AACnC,OAAO,KAAK,UAAU,MAAM,eAAe,CAAC;AAC5C,OAAO,KAAK,EAAE,wBAAwB,EAAE,WAAW,EAAE,MAAM,SAAS,CAAC;AACrE,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,UAAU,CAAC;AAE5C;;;;;;;;;;;;;GAaG;AACH,cAAM,iBAAiB;IACrB,SAAgB,IAAI,EAAE,MAAM,CAAC;IAC7B,SAAgB,KAAK,EAAE,MAAM,CAAC;IAC9B,SAAgB,QAAQ,EAAE,OAAO,CAAC;IAClC,SAAgB,WAAW,CAAC,EAAE,WAAW,CAAC;IAC1C,SAAgB,IAAI,EAAE,OAAO,CAAC;IAC9B,SAAgB,gBAAgB,CAAC,EAAE,WAAW,CAAC,UAAU,CAAC,CAAC;gBAE/C,OAAO,EAAE,wBAAwB;CAa9C;AAED,eAAe,iBAAiB,CAAC"}
|
|
@@ -10,6 +10,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
10
10
|
* @property {boolean} nullable - Indicates whether the attribute can be `null`, defining the attribute's nullability constraint within the database.
|
|
11
11
|
* @property {Serializers | undefined} serializers - Optional serialization strategies for converting the attribute between its database representation and its entity representation. This is particularly useful for custom data types not natively supported by DynamoDB.
|
|
12
12
|
* @property {ZodType} type - Zod validator to run on the attribute
|
|
13
|
+
* @property {EntityClass | undefined} foreignKeyTarget - When present, identifies the entity referenced by a foreign key attribute, enabling referential integrity enforcement.
|
|
13
14
|
*
|
|
14
15
|
* @param {AttributeMetadataOptions} options - Configuration options for the attribute metadata, including the attribute's name, optional alias, nullability, and serialization strategies.
|
|
15
16
|
*/
|
|
@@ -19,11 +20,13 @@ class AttributeMetadata {
|
|
|
19
20
|
nullable;
|
|
20
21
|
serializers;
|
|
21
22
|
type;
|
|
23
|
+
foreignKeyTarget;
|
|
22
24
|
constructor(options) {
|
|
23
25
|
this.name = options.attributeName;
|
|
24
26
|
this.alias = options.alias ?? options.attributeName;
|
|
25
27
|
this.nullable = options.nullable ?? false;
|
|
26
28
|
this.serializers = options.serializers;
|
|
29
|
+
this.foreignKeyTarget = options.foreignKeyTarget;
|
|
27
30
|
if (options.nullable === true) {
|
|
28
31
|
this.type = options.type.optional().nullable();
|
|
29
32
|
}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { BelongsToRelationship, HasRelationships, AttributeMetadata, AttributeMetadataStorage, RelationshipMetadataStorage, RelationshipMetadata, OwnedByRelationship, BelongsToOrOwnedByRelationship } from ".";
|
|
1
|
+
import type { BelongsToRelationship, HasRelationships, AttributeMetadata, AttributeMetadataStorage, RelationshipMetadataStorage, RelationshipMetadata, OwnedByRelationship, BelongsToOrOwnedByRelationship, ForeignKeyAttributeMetadata } from ".";
|
|
2
2
|
import type DynaRecord from "../DynaRecord";
|
|
3
3
|
import { type EntityDefinedAttributes } from "../operations";
|
|
4
4
|
type EntityClass = new (...args: any) => DynaRecord;
|
|
@@ -83,6 +83,16 @@ declare class EntityMetadata {
|
|
|
83
83
|
* Returns the "Has" relationship metadata for the entity (EX: "HasMany")
|
|
84
84
|
*/
|
|
85
85
|
get hasRelationships(): HasRelationships;
|
|
86
|
+
/**
|
|
87
|
+
* Returns attribute metadata for attributes that reference a foreign entity via {@link ForeignKeyAttribute}.
|
|
88
|
+
* The returned metadata guarantees a non-null {@link ForeignKeyAttributeMetadata.foreignKeyTarget}.
|
|
89
|
+
*/
|
|
90
|
+
get foreignKeyAttributes(): ForeignKeyAttributeMetadata[];
|
|
91
|
+
/**
|
|
92
|
+
* Returns foreign key attributes that are not linked through a relationship decorator.
|
|
93
|
+
* These attributes rely on standalone referential integrity checks during create and update operations.
|
|
94
|
+
*/
|
|
95
|
+
get standaloneForeignKeyAttributes(): ForeignKeyAttributeMetadata[];
|
|
86
96
|
}
|
|
87
97
|
export default EntityMetadata;
|
|
88
98
|
//# sourceMappingURL=EntityMetadata.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"EntityMetadata.d.ts","sourceRoot":"","sources":["../../../src/metadata/EntityMetadata.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EACV,qBAAqB,EACrB,gBAAgB,EAChB,iBAAiB,EACjB,wBAAwB,EACxB,2BAA2B,EAC3B,oBAAoB,EACpB,mBAAmB,EACnB,8BAA8B,
|
|
1
|
+
{"version":3,"file":"EntityMetadata.d.ts","sourceRoot":"","sources":["../../../src/metadata/EntityMetadata.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EACV,qBAAqB,EACrB,gBAAgB,EAChB,iBAAiB,EACjB,wBAAwB,EACxB,2BAA2B,EAC3B,oBAAoB,EACpB,mBAAmB,EACnB,8BAA8B,EAC9B,2BAA2B,EAC5B,MAAM,GAAG,CAAC;AACX,OAAO,KAAK,UAAU,MAAM,eAAe,CAAC;AAE5C,OAAO,EAAE,KAAK,uBAAuB,EAAE,MAAM,eAAe,CAAC;AAY7D,KAAK,WAAW,GAAG,KAAK,GAAG,IAAI,EAAE,GAAG,KAAK,UAAU,CAAC;AAEpD;;;;;;;;;;;GAWG;AACH,cAAM,cAAc;;IAClB;;OAEG;IACH,SAAgB,cAAc,EAAE,MAAM,CAAC;IACvC;;OAEG;IACH,SAAgB,UAAU,EAAE,wBAAwB,CAAC;IACrD;;OAEG;IACH,SAAgB,eAAe,EAAE,wBAAwB,CAAC;IAE1D;;OAEG;IACH,SAAgB,aAAa,EAAE,2BAA2B,CAAC;IAE3D,SAAgB,WAAW,EAAE,WAAW,CAAC;IAEzC;;OAEG;IACI,OAAO,EAAE,MAAM,CAAC;gBAiBX,WAAW,EAAE,WAAW,EAAE,cAAc,EAAE,MAAM;IAS5D;;;OAGG;IACI,YAAY,CAAC,QAAQ,EAAE,iBAAiB,GAAG,IAAI;IAOtD;;;;;OAKG;IACI,+BAA+B,CACpC,UAAU,EAAE,uBAAuB,CAAC,UAAU,CAAC,GAC9C,uBAAuB,CAAC,UAAU,CAAC;IAatC;;;;;;OAMG;IACI,sCAAsC,CAC3C,UAAU,EAAE,OAAO,CAAC,uBAAuB,CAAC,UAAU,CAAC,CAAC,GACvD,OAAO,CAAC,uBAAuB,CAAC,UAAU,CAAC,CAAC;IA0B/C;;;OAGG;IACH,OAAO,CAAC,oBAAoB;IAM5B;;OAEG;IACH,IAAW,gBAAgB,IAAI,oBAAoB,EAAE,CAEpD;IAED;;OAEG;IACH,IAAW,sBAAsB,IAAI,qBAAqB,EAAE,CAI3D;IAED;;OAEG;IACH,IAAW,oBAAoB,IAAI,mBAAmB,EAAE,CAIvD;IAED;;OAEG;IACH,IAAW,+BAA+B,IAAI,8BAA8B,EAAE,CAE7E;IAED;;OAEG;IACH,IAAW,gBAAgB,IAAI,gBAAgB,CAO9C;IAED;;;OAGG;IACH,IAAW,oBAAoB,IAAI,2BAA2B,EAAE,CAE/D;IAED;;;OAGG;IACH,IAAW,8BAA8B,IAAI,2BAA2B,EAAE,CAUzE;CACF;AAED,eAAe,cAAc,CAAC"}
|
|
@@ -159,5 +159,22 @@ class EntityMetadata {
|
|
|
159
159
|
(0, utils_1.isHasManyRelationship)(relMeta) ||
|
|
160
160
|
(0, utils_1.isHasAndBelongsToManyRelationship)(relMeta));
|
|
161
161
|
}
|
|
162
|
+
/**
|
|
163
|
+
* Returns attribute metadata for attributes that reference a foreign entity via {@link ForeignKeyAttribute}.
|
|
164
|
+
* The returned metadata guarantees a non-null {@link ForeignKeyAttributeMetadata.foreignKeyTarget}.
|
|
165
|
+
*/
|
|
166
|
+
get foreignKeyAttributes() {
|
|
167
|
+
return Object.values(this.attributes).filter(utils_1.isForeignKeyAttributeMetadata);
|
|
168
|
+
}
|
|
169
|
+
/**
|
|
170
|
+
* Returns foreign key attributes that are not linked through a relationship decorator.
|
|
171
|
+
* These attributes rely on standalone referential integrity checks during create and update operations.
|
|
172
|
+
*/
|
|
173
|
+
get standaloneForeignKeyAttributes() {
|
|
174
|
+
const associatedForeignKeys = new Set(Object.values(this.relationships)
|
|
175
|
+
.filter(utils_1.isRelationshipMetadataWithForeignKey)
|
|
176
|
+
.map(rel => rel.foreignKey.toString()));
|
|
177
|
+
return this.foreignKeyAttributes.filter(attr => !associatedForeignKeys.has(attr.name));
|
|
178
|
+
}
|
|
162
179
|
}
|
|
163
180
|
exports.default = EntityMetadata;
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import type { NativeScalarAttributeValue } from "@aws-sdk/util-dynamodb";
|
|
2
2
|
import type { AttributeMetadata, BelongsToRelationship, EntityMetadata, JoinTableMetadata, OwnedByRelationship, RelationshipMetadata, TableMetadata } from ".";
|
|
3
3
|
import type DynaRecord from "../DynaRecord";
|
|
4
|
-
import type { MakeOptional } from "../types";
|
|
4
|
+
import type { EntityClass, MakeOptional } from "../types";
|
|
5
5
|
import type { ZodType } from "zod";
|
|
6
6
|
/**
|
|
7
7
|
* Represents relationship metadata that includes a foreign key reference to another entity.
|
|
@@ -94,9 +94,21 @@ export interface AttributeMetadataOptions {
|
|
|
94
94
|
alias?: string;
|
|
95
95
|
nullable?: boolean;
|
|
96
96
|
serializers?: Serializers;
|
|
97
|
+
/**
|
|
98
|
+
* When the attribute represents a foreign key, this references the target entity class.
|
|
99
|
+
* Used to enforce referential integrity even when a relationship decorator is not present.
|
|
100
|
+
*/
|
|
101
|
+
foreignKeyTarget?: EntityClass<DynaRecord>;
|
|
97
102
|
}
|
|
98
103
|
/**
|
|
99
104
|
* A relationship that is either BelongsTo (bi-directional to parent) or OwnedBy (uni directional to parent)
|
|
100
105
|
*/
|
|
101
106
|
export type BelongsToOrOwnedByRelationship = BelongsToRelationship | OwnedByRelationship;
|
|
107
|
+
/**
|
|
108
|
+
* Attribute metadata for foreign key attributes where {@link AttributeMetadata.foreignKeyTarget} is guaranteed.
|
|
109
|
+
* Provides the target entity class so operations can enforce referential integrity even when no relationship metadata exists.
|
|
110
|
+
*/
|
|
111
|
+
export interface ForeignKeyAttributeMetadata extends AttributeMetadata {
|
|
112
|
+
foreignKeyTarget: NonNullable<AttributeMetadata["foreignKeyTarget"]>;
|
|
113
|
+
}
|
|
102
114
|
//# sourceMappingURL=types.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../src/metadata/types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,0BAA0B,EAAE,MAAM,wBAAwB,CAAC;AACzE,OAAO,KAAK,EACV,iBAAiB,EACjB,qBAAqB,EACrB,cAAc,EACd,iBAAiB,EACjB,mBAAmB,EACnB,oBAAoB,EACpB,aAAa,EACd,MAAM,GAAG,CAAC;AACX,OAAO,KAAK,UAAU,MAAM,eAAe,CAAC;AAC5C,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,UAAU,CAAC;
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../src/metadata/types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,0BAA0B,EAAE,MAAM,wBAAwB,CAAC;AACzE,OAAO,KAAK,EACV,iBAAiB,EACjB,qBAAqB,EACrB,cAAc,EACd,iBAAiB,EACjB,mBAAmB,EACnB,oBAAoB,EACpB,aAAa,EACd,MAAM,GAAG,CAAC;AACX,OAAO,KAAK,UAAU,MAAM,eAAe,CAAC;AAC5C,OAAO,KAAK,EAAE,WAAW,EAAE,YAAY,EAAE,MAAM,UAAU,CAAC;AAC1D,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,KAAK,CAAC;AAEnC;;GAEG;AACH,MAAM,MAAM,kCAAkC,GAAG,OAAO,CACtD,oBAAoB,EACpB;IAAE,UAAU,EAAE,MAAM,UAAU,CAAA;CAAE,CACjC,CAAC;AAEF;;GAEG;AACH,MAAM,MAAM,wBAAwB,GAAG,MAAM,CAAC,MAAM,EAAE,iBAAiB,CAAC,CAAC;AAEzE;;GAEG;AACH,MAAM,MAAM,2BAA2B,GAAG,MAAM,CAAC,MAAM,EAAE,oBAAoB,CAAC,CAAC;AAE/E;;GAEG;AACH,MAAM,MAAM,oBAAoB,GAAG,MAAM,CAAC,MAAM,EAAE,aAAa,CAAC,CAAC;AAEjE;;GAEG;AACH,MAAM,MAAM,qBAAqB,GAAG,MAAM,CAAC,MAAM,EAAE,cAAc,CAAC,CAAC;AAEnE;;GAEG;AACH,MAAM,MAAM,wBAAwB,GAAG,MAAM,CAAC,MAAM,EAAE,iBAAiB,EAAE,CAAC,CAAC;AAE3E;;GAEG;AACH,MAAM,MAAM,iBAAiB,GAAG,WAAW,GAAG,WAAW,CAAC;AAE1D;;GAEG;AACH,MAAM,MAAM,aAAa,GAAG;KACzB,CAAC,IAAI,MAAM,UAAU,GAAG,UAAU,CAAC,CAAC,CAAC,SAAS,CAAC,GAAG,IAAI,EAAE,GAAG,EAAE,KAAK,GAAG,GAClE,KAAK,GACL,CAAC;CACN,CAAC,MAAM,UAAU,CAAC,CAAC;AAEpB;;GAEG;AACH,MAAM,MAAM,kBAAkB,GAAG,MAAM,CACrC,aAAa,EACb,IAAI,CAAC,iBAAiB,EAAE,OAAO,CAAC,CACjC,CAAC;AAEF;;;;;;;GAOG;AACH,MAAM,MAAM,oBAAoB,GAAG,IAAI,CAAC,aAAa,EAAE,MAAM,CAAC,GAC5D,OAAO,CAAC,IAAI,CAAC,aAAa,EAAE,WAAW,CAAC,CAAC,GAAG;IAC1C,aAAa,CAAC,EAAE,OAAO,CAAC,kBAAkB,CAAC,CAAC;CAC7C,CAAC;AAEJ;;GAEG;AACH,MAAM,MAAM,4BAA4B,GAAG,YAAY,CACrD,IAAI,CAAC,wBAAwB,EAAE,UAAU,CAAC,EAC1C,OAAO,CACR,CAAC;AAEF;;GAEG;AACH,MAAM,MAAM,gBAAgB,GAAG,CAAC,KAAK,EAAE,0BAA0B,KAAK,GAAG,CAAC;AAE1E;;GAEG;AACH,MAAM,MAAM,eAAe,GAAG,CAAC,KAAK,EAAE,GAAG,KAAK,0BAA0B,CAAC;AAEzE;;;GAGG;AACH,MAAM,WAAW,WAAW;IAC1B;;OAEG;IACH,iBAAiB,EAAE,gBAAgB,CAAC;IACpC;;OAEG;IACH,gBAAgB,EAAE,eAAe,CAAC;CACnC;AAED;;;;;;;GAOG;AACH,MAAM,WAAW,wBAAwB;IACvC,aAAa,EAAE,MAAM,CAAC;IACtB,IAAI,EAAE,OAAO,CAAC;IACd,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,WAAW,CAAC,EAAE,WAAW,CAAC;IAC1B;;;OAGG;IACH,gBAAgB,CAAC,EAAE,WAAW,CAAC,UAAU,CAAC,CAAC;CAC5C;AAED;;GAEG;AACH,MAAM,MAAM,8BAA8B,GACtC,qBAAqB,GACrB,mBAAmB,CAAC;AAExB;;;GAGG;AACH,MAAM,WAAW,2BAA4B,SAAQ,iBAAiB;IACpE,gBAAgB,EAAE,WAAW,CAAC,iBAAiB,CAAC,kBAAkB,CAAC,CAAC,CAAC;CACtE"}
|
|
@@ -1,7 +1,8 @@
|
|
|
1
|
-
import type { RelationshipMetadata, HasManyRelationship, BelongsToRelationship, HasOneRelationship, HasAndBelongsToManyRelationship, OwnedByRelationship } from ".";
|
|
1
|
+
import type { RelationshipMetadata, HasManyRelationship, BelongsToRelationship, HasOneRelationship, HasAndBelongsToManyRelationship, OwnedByRelationship, ForeignKeyAttributeMetadata } from ".";
|
|
2
2
|
import type DynaRecord from "../DynaRecord";
|
|
3
3
|
import type { BelongsToOrOwnedByRelationship, RelationshipMetadataWithForeignKey } from "./types";
|
|
4
4
|
import type { EntityClass } from "../types";
|
|
5
|
+
import type AttributeMetadata from "./AttributeMetadata";
|
|
5
6
|
/**
|
|
6
7
|
* Type guard to check if the relationship is a HasMany
|
|
7
8
|
*/
|
|
@@ -28,6 +29,11 @@ export declare const isOwnedByRelationship: (rel: RelationshipMetadata) => rel i
|
|
|
28
29
|
* @returns
|
|
29
30
|
*/
|
|
30
31
|
export declare const isRelationshipMetadataWithForeignKey: (rel: RelationshipMetadata) => rel is RelationshipMetadataWithForeignKey;
|
|
32
|
+
/**
|
|
33
|
+
* Type guard that checks whether attribute metadata represents a foreign key.
|
|
34
|
+
* Returns {@link ForeignKeyAttributeMetadata} with a guaranteed target entity.
|
|
35
|
+
*/
|
|
36
|
+
export declare const isForeignKeyAttributeMetadata: (attr: AttributeMetadata) => attr is ForeignKeyAttributeMetadata;
|
|
31
37
|
/**
|
|
32
38
|
* Returns true if an "Entity" BelongsTo the provided relationship as a HasOne
|
|
33
39
|
* @param Entity
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"utils.d.ts","sourceRoot":"","sources":["../../../src/metadata/utils.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EACV,oBAAoB,EACpB,mBAAmB,EACnB,qBAAqB,EACrB,kBAAkB,EAClB,+BAA+B,EAC/B,mBAAmB,
|
|
1
|
+
{"version":3,"file":"utils.d.ts","sourceRoot":"","sources":["../../../src/metadata/utils.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EACV,oBAAoB,EACpB,mBAAmB,EACnB,qBAAqB,EACrB,kBAAkB,EAClB,+BAA+B,EAC/B,mBAAmB,EACnB,2BAA2B,EAC5B,MAAM,GAAG,CAAC;AACX,OAAO,KAAK,UAAU,MAAM,eAAe,CAAC;AAC5C,OAAO,KAAK,EACV,8BAA8B,EAC9B,kCAAkC,EACnC,MAAM,SAAS,CAAC;AACjB,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,UAAU,CAAC;AAC5C,OAAO,KAAK,iBAAiB,MAAM,qBAAqB,CAAC;AAEzD;;GAEG;AACH,eAAO,MAAM,qBAAqB,QAC3B,oBAAoB,KACxB,GAAG,IAAI,mBAET,CAAC;AAEF;;GAEG;AACH,eAAO,MAAM,uBAAuB,QAC7B,oBAAoB,KACxB,GAAG,IAAI,qBAET,CAAC;AAEF;;GAEG;AACH,eAAO,MAAM,oBAAoB,QAC1B,oBAAoB,KACxB,GAAG,IAAI,kBAET,CAAC;AAEF;;GAEG;AACH,eAAO,MAAM,iCAAiC,QACvC,oBAAoB,KACxB,GAAG,IAAI,+BAET,CAAC;AAEF;;GAEG;AACH,eAAO,MAAM,qBAAqB,QAC3B,oBAAoB,KACxB,GAAG,IAAI,mBAET,CAAC;AAEF;;;;GAIG;AACH,eAAO,MAAM,oCAAoC,QAC1C,oBAAoB,KACxB,GAAG,IAAI,kCAET,CAAC;AAEF;;;GAGG;AACH,eAAO,MAAM,6BAA6B,SAClC,iBAAiB,KACtB,IAAI,IAAI,2BAEV,CAAC;AAEF;;;;;GAKG;AACH,eAAO,MAAM,6BAA6B,GAAI,CAAC,SAAS,UAAU,UACxD,WAAW,CAAC,CAAC,CAAC,OACjB,8BAA8B,KAClC,OAMF,CAAC;AAEF;;;;;;GAMG;AACH,eAAO,MAAM,8BAA8B,GAAI,CAAC,SAAS,UAAU,UACzD,WAAW,CAAC,CAAC,CAAC,OACjB,8BAA8B,KAClC,OAMF,CAAC"}
|
|
@@ -3,7 +3,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
3
3
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
4
|
};
|
|
5
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
-
exports.doesEntityBelongToRelAsHasMany = exports.doesEntityBelongToRelAsHasOne = exports.isRelationshipMetadataWithForeignKey = exports.isOwnedByRelationship = exports.isHasAndBelongsToManyRelationship = exports.isHasOneRelationship = exports.isBelongsToRelationship = exports.isHasManyRelationship = void 0;
|
|
6
|
+
exports.doesEntityBelongToRelAsHasMany = exports.doesEntityBelongToRelAsHasOne = exports.isForeignKeyAttributeMetadata = exports.isRelationshipMetadataWithForeignKey = exports.isOwnedByRelationship = exports.isHasAndBelongsToManyRelationship = exports.isHasOneRelationship = exports.isBelongsToRelationship = exports.isHasManyRelationship = void 0;
|
|
7
7
|
const _1 = __importDefault(require("./"));
|
|
8
8
|
/**
|
|
9
9
|
* Type guard to check if the relationship is a HasMany
|
|
@@ -49,6 +49,14 @@ const isRelationshipMetadataWithForeignKey = (rel) => {
|
|
|
49
49
|
return "foreignKey" in rel;
|
|
50
50
|
};
|
|
51
51
|
exports.isRelationshipMetadataWithForeignKey = isRelationshipMetadataWithForeignKey;
|
|
52
|
+
/**
|
|
53
|
+
* Type guard that checks whether attribute metadata represents a foreign key.
|
|
54
|
+
* Returns {@link ForeignKeyAttributeMetadata} with a guaranteed target entity.
|
|
55
|
+
*/
|
|
56
|
+
const isForeignKeyAttributeMetadata = (attr) => {
|
|
57
|
+
return attr.foreignKeyTarget !== undefined;
|
|
58
|
+
};
|
|
59
|
+
exports.isForeignKeyAttributeMetadata = isForeignKeyAttributeMetadata;
|
|
52
60
|
/**
|
|
53
61
|
* Returns true if an "Entity" BelongsTo the provided relationship as a HasOne
|
|
54
62
|
* @param Entity
|
|
@@ -78,6 +78,13 @@ declare class Create<T extends DynaRecord> extends OperationBase<T> {
|
|
|
78
78
|
* @private
|
|
79
79
|
*/
|
|
80
80
|
private buildBelongsToTransactions;
|
|
81
|
+
/**
|
|
82
|
+
* Adds DynamoDB condition checks for foreign keys that are not associated with a relationship decorator.
|
|
83
|
+
* Ensures referenced entities exist even when denormalised access patterns are not defined.
|
|
84
|
+
*
|
|
85
|
+
* @param entityData - Attributes being persisted for the new entity.
|
|
86
|
+
*/
|
|
87
|
+
private buildStandaloneForeignKeyConditionChecks;
|
|
81
88
|
/**
|
|
82
89
|
* Retrieves the DynamoDB items for all entities that the new entity references via "BelongsTo" relationships.
|
|
83
90
|
*
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Create.d.ts","sourceRoot":"","sources":["../../../../src/operations/Create/Create.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,UAAU,MAAM,kBAAkB,CAAC;AAE/C,OAAO,KAAK,EAAmB,WAAW,EAAE,MAAM,aAAa,CAAC;AAOhE,OAAO,aAAa,MAAM,kBAAkB,CAAC;AAE7C,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,SAAS,CAAC;AAC7C,OAAO,EAGL,KAAK,oBAAoB,EAC1B,MAAM,UAAU,CAAC;AAIlB;;;;;;;;;;;;;;;;;GAiBG;AACH,cAAM,MAAM,CAAC,CAAC,SAAS,UAAU,CAAE,SAAQ,aAAa,CAAC,CAAC,CAAC;;gBAG7C,MAAM,EAAE,WAAW,CAAC,CAAC,CAAC;IAKlC;;;;;;;;;;;;;;;;OAgBG;IACU,GAAG,CACd,UAAU,EAAE,aAAa,CAAC,CAAC,CAAC,GAC3B,OAAO,CAAC,oBAAoB,CAAC,CAAC,CAAC,CAAC;
|
|
1
|
+
{"version":3,"file":"Create.d.ts","sourceRoot":"","sources":["../../../../src/operations/Create/Create.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,UAAU,MAAM,kBAAkB,CAAC;AAE/C,OAAO,KAAK,EAAmB,WAAW,EAAE,MAAM,aAAa,CAAC;AAOhE,OAAO,aAAa,MAAM,kBAAkB,CAAC;AAE7C,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,SAAS,CAAC;AAC7C,OAAO,EAGL,KAAK,oBAAoB,EAC1B,MAAM,UAAU,CAAC;AAIlB;;;;;;;;;;;;;;;;;GAiBG;AACH,cAAM,MAAM,CAAC,CAAC,SAAS,UAAU,CAAE,SAAQ,aAAa,CAAC,CAAC,CAAC;;gBAG7C,MAAM,EAAE,WAAW,CAAC,CAAC,CAAC;IAKlC;;;;;;;;;;;;;;;;OAgBG;IACU,GAAG,CACd,UAAU,EAAE,aAAa,CAAC,CAAC,CAAC,GAC3B,OAAO,CAAC,oBAAoB,CAAC,CAAC,CAAC,CAAC;IA6BnC;;;;;;;;;;;OAWG;IACH,OAAO,CAAC,uBAAuB;IA8B/B;;;;;;;;;OASG;IACH,OAAO,CAAC,uBAAuB;IAiB/B;;;;;;;;;;OAUG;IACH,OAAO,CAAC,0BAA0B;IAkClC;;;;;OAKG;IACH,OAAO,CAAC,wCAAwC;IA8BhD;;;;;;;;;;;OAWG;YACW,sBAAsB;IAmCpC;;;;;;;;;;OAUG;IACH,OAAO,CAAC,2CAA2C;IAmBnD;;;;;;;;;;;OAWG;IACH,OAAO,CAAC,uCAAuC;CA0BhD;AAED,eAAe,MAAM,CAAC"}
|
|
@@ -57,6 +57,7 @@ class Create extends OperationBase_1.default {
|
|
|
57
57
|
const tableItem = (0, utils_1.entityToTableItem)(this.EntityClass, entityData);
|
|
58
58
|
this.buildPutItemTransaction(tableItem, entityData.id);
|
|
59
59
|
this.buildBelongsToTransactions(entityData, tableItem);
|
|
60
|
+
this.buildStandaloneForeignKeyConditionChecks(entityData);
|
|
60
61
|
// Attempt to fetch all belongs-to entities to properly create reverse denormalization links
|
|
61
62
|
const belongsToTableItems = await this.getBelongsToTableItems(entityData);
|
|
62
63
|
// If there are any belongs-to relationships, add the inverse link records into the new entity's partition
|
|
@@ -145,6 +146,32 @@ class Create extends OperationBase_1.default {
|
|
|
145
146
|
}
|
|
146
147
|
}
|
|
147
148
|
}
|
|
149
|
+
/**
|
|
150
|
+
* Adds DynamoDB condition checks for foreign keys that are not associated with a relationship decorator.
|
|
151
|
+
* Ensures referenced entities exist even when denormalised access patterns are not defined.
|
|
152
|
+
*
|
|
153
|
+
* @param entityData - Attributes being persisted for the new entity.
|
|
154
|
+
*/
|
|
155
|
+
buildStandaloneForeignKeyConditionChecks(entityData) {
|
|
156
|
+
const standaloneForeignKeys = this.entityMetadata.standaloneForeignKeyAttributes;
|
|
157
|
+
for (const attrMeta of standaloneForeignKeys) {
|
|
158
|
+
const target = attrMeta.foreignKeyTarget;
|
|
159
|
+
const foreignKeyValue = entityData[attrMeta.name];
|
|
160
|
+
if (!(0, utils_1.isString)(foreignKeyValue))
|
|
161
|
+
continue;
|
|
162
|
+
const foreignKey = foreignKeyValue;
|
|
163
|
+
const errMsg = `${target.name} with ID '${foreignKey}' does not exist`;
|
|
164
|
+
const conditionCheck = {
|
|
165
|
+
TableName: this.tableMetadata.name,
|
|
166
|
+
Key: {
|
|
167
|
+
[this.partitionKeyAlias]: target.partitionKeyValue(foreignKey),
|
|
168
|
+
[this.sortKeyAlias]: target.name
|
|
169
|
+
},
|
|
170
|
+
ConditionExpression: `attribute_exists(${this.partitionKeyAlias})`
|
|
171
|
+
};
|
|
172
|
+
this.#transactionBuilder.addConditionCheck(conditionCheck, errMsg);
|
|
173
|
+
}
|
|
174
|
+
}
|
|
148
175
|
/**
|
|
149
176
|
* Retrieves the DynamoDB items for all entities that the new entity references via "BelongsTo" relationships.
|
|
150
177
|
*
|
|
@@ -46,6 +46,12 @@ declare class Update<T extends DynaRecord> extends OperationBase<T> {
|
|
|
46
46
|
* @returns
|
|
47
47
|
*/
|
|
48
48
|
private getBelongsToRelMetaAndKeyForUpdatedKeys;
|
|
49
|
+
/**
|
|
50
|
+
* Adds condition checks for standalone foreign keys present in the update payload to ensure the referenced records exist.
|
|
51
|
+
*
|
|
52
|
+
* @param attributes - Partial entity attributes supplied to the update call.
|
|
53
|
+
*/
|
|
54
|
+
private addStandaloneForeignKeyConditionChecks;
|
|
49
55
|
/**
|
|
50
56
|
* Pre-fetches the target entity and any related entities from the database. This is done using a strong read operation to ensure consistency.
|
|
51
57
|
*
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Update.d.ts","sourceRoot":"","sources":["../../../../src/operations/Update/Update.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,UAAU,MAAM,kBAAkB,CAAC;AAC/C,OAAO,EAGL,oBAAoB,EACrB,MAAM,oBAAoB,CAAC;
|
|
1
|
+
{"version":3,"file":"Update.d.ts","sourceRoot":"","sources":["../../../../src/operations/Update/Update.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,UAAU,MAAM,kBAAkB,CAAC;AAC/C,OAAO,EAGL,oBAAoB,EACrB,MAAM,oBAAoB,CAAC;AAmB5B,OAAO,aAAa,MAAM,kBAAkB,CAAC;AAC7C,OAAO,KAAK,EAAE,iBAAiB,EAAE,aAAa,EAAE,MAAM,SAAS,CAAC;AAChE,OAAO,KAAK,EAAmB,WAAW,EAAgB,MAAM,aAAa,CAAC;AA4D9E;;;;;;;;;;;;;;;;;GAiBG;AACH,cAAM,MAAM,CAAC,CAAC,SAAS,UAAU,CAAE,SAAQ,aAAa,CAAC,CAAC,CAAC;IACzD,SAAS,CAAC,QAAQ,CAAC,kBAAkB,EAAE,oBAAoB,CAAC;gBAG1D,MAAM,EAAE,WAAW,CAAC,CAAC,CAAC,EACtB,kBAAkB,CAAC,EAAE,oBAAoB;IAO3C;;;;;;;;;;;;;OAaG;IACU,GAAG,CACd,EAAE,EAAE,MAAM,EACV,UAAU,EAAE,aAAa,CAAC,UAAU,CAAC,GACpC,OAAO,CAAC,iBAAiB,CAAC,CAAC,CAAC,CAAC;cA6ChB,iBAAiB,IAAI,OAAO,CAAC,IAAI,CAAC;IAIlD;;;;OAIG;IACH,OAAO,CAAC,uCAAuC;IAY/C;;;;OAIG;IACH,OAAO,CAAC,sCAAsC;IAgC9C;;;;;;;;;;;;;;;OAeG;YACW,QAAQ;IAsDtB;;;;;;OAMG;IACH,OAAO,CAAC,qBAAqB;IA4B7B;;;;;;;;;;;;OAYG;IACH,OAAO,CAAC,mBAAmB;IAY3B;;;;;;;;;;OAUG;IACH,OAAO,CAAC,0BAA0B;IAyBlC;;;;;;;;;;;;OAYG;IACH,OAAO,CAAC,0BAA0B;IAuDlC;;;;;;;;;;;;OAYG;IACH,OAAO,CAAC,iCAAiC;IAuBzC;;;;;;;;;;OAUG;IACH,OAAO,CAAC,8BAA8B;IA+BtC;;;;OAIG;IACH,OAAO,CAAC,0BAA0B;IAkBlC;;;;;OAKG;IACH,OAAO,CAAC,mCAAmC;IAsB3C;;;;;;;;OAQG;IACH,OAAO,CAAC,sCAAsC;IAqC9C;;;;;;;;;;OAUG;IACH,OAAO,CAAC,6BAA6B;IAuCrC;;;;;;;OAOG;IACH,OAAO,CAAC,4BAA4B;IA6BpC;;;;;;;;;;OAUG;IACH,OAAO,CAAC,6BAA6B;IAwBrC;;;;;;OAMG;IACH,OAAO,CAAC,gCAAgC;IAgBxC;;;OAGG;IACH,OAAO,CAAC,iCAAiC;CAU1C;AAED,eAAe,MAAM,CAAC"}
|
|
@@ -54,6 +54,7 @@ class Update extends OperationBase_1.default {
|
|
|
54
54
|
const entityAttrs = entityMeta.parseRawEntityDefinedAttributesPartial(attributes);
|
|
55
55
|
const { updatedAttrs, expression } = this.buildUpdateMetadata(entityAttrs);
|
|
56
56
|
this.buildUpdateItemTransaction(id, expression);
|
|
57
|
+
this.addStandaloneForeignKeyConditionChecks(entityAttrs);
|
|
57
58
|
// Only need to prefetch if the entity has relationships
|
|
58
59
|
if (entityMeta.allRelationships.length > 0) {
|
|
59
60
|
const belongsToRelMetaBeingUpdated = this.getBelongsToRelMetaAndKeyForUpdatedKeys(entityAttrs);
|
|
@@ -86,6 +87,33 @@ class Update extends OperationBase_1.default {
|
|
|
86
87
|
return acc;
|
|
87
88
|
}, []);
|
|
88
89
|
}
|
|
90
|
+
/**
|
|
91
|
+
* Adds condition checks for standalone foreign keys present in the update payload to ensure the referenced records exist.
|
|
92
|
+
*
|
|
93
|
+
* @param attributes - Partial entity attributes supplied to the update call.
|
|
94
|
+
*/
|
|
95
|
+
addStandaloneForeignKeyConditionChecks(attributes) {
|
|
96
|
+
const standaloneForeignKeys = this.entityMetadata.standaloneForeignKeyAttributes;
|
|
97
|
+
for (const attrMeta of standaloneForeignKeys) {
|
|
98
|
+
const target = attrMeta.foreignKeyTarget;
|
|
99
|
+
if (!(0, utils_1.isKeyOfObject)(attributes, attrMeta.name))
|
|
100
|
+
continue;
|
|
101
|
+
const foreignKeyValue = attributes[attrMeta.name];
|
|
102
|
+
if (!(0, utils_1.isString)(foreignKeyValue))
|
|
103
|
+
continue;
|
|
104
|
+
const foreignKey = foreignKeyValue;
|
|
105
|
+
const errMsg = `${target.name} with ID '${foreignKey}' does not exist`;
|
|
106
|
+
const conditionCheck = {
|
|
107
|
+
TableName: this.tableMetadata.name,
|
|
108
|
+
Key: {
|
|
109
|
+
[this.partitionKeyAlias]: target.partitionKeyValue(foreignKey),
|
|
110
|
+
[this.sortKeyAlias]: target.name
|
|
111
|
+
},
|
|
112
|
+
ConditionExpression: `attribute_exists(${this.partitionKeyAlias})`
|
|
113
|
+
};
|
|
114
|
+
this.transactionBuilder.addConditionCheck(conditionCheck, errMsg);
|
|
115
|
+
}
|
|
116
|
+
}
|
|
89
117
|
/**
|
|
90
118
|
* Pre-fetches the target entity and any related entities from the database. This is done using a strong read operation to ensure consistency.
|
|
91
119
|
*
|
package/dist/src/types.d.ts
CHANGED
|
@@ -16,13 +16,23 @@ export type SortKey = Brand<string, "SortKey">;
|
|
|
16
16
|
*/
|
|
17
17
|
export type PartitionKey = Brand<string, "PartitionKey">;
|
|
18
18
|
/**
|
|
19
|
-
* A branded string type to represent foreign keys in DynamoDB tables
|
|
19
|
+
* A branded string type to represent foreign keys in DynamoDB tables.
|
|
20
|
+
*
|
|
21
|
+
* @typeParam T - The entity that the foreign key references. Defaults to {@link DynaRecord}.
|
|
20
22
|
*/
|
|
21
|
-
export type ForeignKey = Brand<string,
|
|
23
|
+
export type ForeignKey<T extends DynaRecord = DynaRecord> = Brand<string, {
|
|
24
|
+
kind: "ForeignKey";
|
|
25
|
+
entity: T;
|
|
26
|
+
}>;
|
|
22
27
|
/**
|
|
23
28
|
* A branded string type to represent nullable foreign keys in DynamoDB tables, which can also be undefined.
|
|
29
|
+
*
|
|
30
|
+
* @typeParam T - The entity that the foreign key references. Defaults to {@link DynaRecord}.
|
|
24
31
|
*/
|
|
25
|
-
export type NullableForeignKey = Optional<Brand<string,
|
|
32
|
+
export type NullableForeignKey<T extends DynaRecord = DynaRecord> = Optional<Brand<string, {
|
|
33
|
+
kind: "NullableForeignKey";
|
|
34
|
+
entity: T;
|
|
35
|
+
}>>;
|
|
26
36
|
/**
|
|
27
37
|
* Represents a foreign key property on an entity within a DynaRecord model
|
|
28
38
|
*/
|
package/dist/src/types.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/types.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,0BAA0B,EAAE,MAAM,wBAAwB,CAAC;AACzE,OAAO,KAAK,EAAE,qBAAqB,EAAE,oBAAoB,EAAE,MAAM,YAAY,CAAC;AAC9E,OAAO,KAAK,UAAU,MAAM,cAAc,CAAC;AAE3C;;GAEG;AACH,MAAM,MAAM,KAAK,CAAC,CAAC,EAAE,CAAC,IAAI,CAAC,GAAG;IAAE,OAAO,EAAE,CAAC,CAAA;CAAE,CAAC;AAE7C;;GAEG;AACH,MAAM,MAAM,OAAO,GAAG,KAAK,CAAC,MAAM,EAAE,SAAS,CAAC,CAAC;AAE/C;;GAEG;AACH,MAAM,MAAM,YAAY,GAAG,KAAK,CAAC,MAAM,EAAE,cAAc,CAAC,CAAC;AAEzD
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/types.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,0BAA0B,EAAE,MAAM,wBAAwB,CAAC;AACzE,OAAO,KAAK,EAAE,qBAAqB,EAAE,oBAAoB,EAAE,MAAM,YAAY,CAAC;AAC9E,OAAO,KAAK,UAAU,MAAM,cAAc,CAAC;AAE3C;;GAEG;AACH,MAAM,MAAM,KAAK,CAAC,CAAC,EAAE,CAAC,IAAI,CAAC,GAAG;IAAE,OAAO,EAAE,CAAC,CAAA;CAAE,CAAC;AAE7C;;GAEG;AACH,MAAM,MAAM,OAAO,GAAG,KAAK,CAAC,MAAM,EAAE,SAAS,CAAC,CAAC;AAE/C;;GAEG;AACH,MAAM,MAAM,YAAY,GAAG,KAAK,CAAC,MAAM,EAAE,cAAc,CAAC,CAAC;AAEzD;;;;GAIG;AACH,MAAM,MAAM,UAAU,CAAC,CAAC,SAAS,UAAU,GAAG,UAAU,IAAI,KAAK,CAC/D,MAAM,EACN;IAAE,IAAI,EAAE,YAAY,CAAC;IAAC,MAAM,EAAE,CAAC,CAAA;CAAE,CAClC,CAAC;AAEF;;;;GAIG;AACH,MAAM,MAAM,kBAAkB,CAAC,CAAC,SAAS,UAAU,GAAG,UAAU,IAAI,QAAQ,CAC1E,KAAK,CAAC,MAAM,EAAE;IAAE,IAAI,EAAE,oBAAoB,CAAC;IAAC,MAAM,EAAE,CAAC,CAAA;CAAE,CAAC,CACzD,CAAC;AAEF;;GAEG;AACH,MAAM,MAAM,kBAAkB,GAAG,MAAM,UAAU,GAAG,UAAU,CAAC;AAE/D;;GAEG;AACH,MAAM,MAAM,eAAe,GAAG,MAAM,CAAC,MAAM,EAAE,0BAA0B,CAAC,CAAC;AAEzE;;GAEG;AACH,MAAM,MAAM,SAAS,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;AAE/C;;GAEG;AACH,MAAM,MAAM,QAAQ,CAAC,CAAC,IAAI,CAAC,GAAG,SAAS,CAAC;AAExC;;GAEG;AACH,MAAM,MAAM,QAAQ,CAAC,CAAC,IAAI,CAAC,GAAG,IAAI,CAAC;AAEnC;;GAEG;AACH,MAAM,MAAM,kBAAkB,GAAG,MAAM,CAAC,MAAM,EAAE,oBAAoB,CAAC,CAAC;AAEtE;;GAEG;AACH,MAAM,WAAW,mBAAmB;IAClC,eAAe,EAAE,kBAAkB,CAAC;IACpC,sBAAsB,EAAE,qBAAqB,EAAE,CAAC;CACjD;AAED;;GAEG;AACH,MAAM,MAAM,YAAY,CAAC,CAAC,EAAE,CAAC,SAAS,MAAM,CAAC,IAAI,IAAI,CAAC,CAAC,EAAE,CAAC,CAAC,GACzD,OAAO,CAAC,IAAI,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC;AAEtB;;GAEG;AACH,MAAM,MAAM,WAAW,CAAC,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC,GAAG,OAAO,UAAU,CAAC;AAE/D;;GAEG;AACH,MAAM,MAAM,YAAY,CAAC,CAAC,EAAE,CAAC,SAAS,MAAM,CAAC,IAAI,IAAI,CAAC,CAAC,EAAE,CAAC,CAAC,GAAG;KAC3D,CAAC,IAAI,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC;CACjB,CAAC"}
|