dyna-record 0.3.6 → 0.4.1
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 +56 -10
- package/dist/src/DynaRecord.d.ts +39 -7
- package/dist/src/DynaRecord.d.ts.map +1 -1
- package/dist/src/DynaRecord.js +36 -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 +14 -3
- package/dist/src/operations/Create/Create.d.ts.map +1 -1
- package/dist/src/operations/Create/Create.js +42 -5
- package/dist/src/operations/Create/types.d.ts +12 -0
- package/dist/src/operations/Create/types.d.ts.map +1 -1
- package/dist/src/operations/Update/Update.d.ts +17 -2
- package/dist/src/operations/Update/Update.d.ts.map +1 -1
- package/dist/src/operations/Update/Update.js +52 -9
- package/dist/src/operations/Update/types.d.ts +12 -0
- package/dist/src/operations/Update/types.d.ts.map +1 -1
- package/dist/src/relationships/JoinTable.d.ts +17 -1
- package/dist/src/relationships/JoinTable.d.ts.map +1 -1
- package/dist/src/relationships/JoinTable.js +16 -9
- 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
|
|
|
@@ -355,6 +357,25 @@ const grade: Grade = await Grade.create({
|
|
|
355
357
|
});
|
|
356
358
|
```
|
|
357
359
|
|
|
360
|
+
#### Skipping Referential Integrity Checks
|
|
361
|
+
|
|
362
|
+
By default, when creating entities with foreign key references, dyna-record performs condition checks to ensure that referenced entities exist. This prevents creating entities with invalid foreign key references. However, in high-contention or high-throughput systems where the same foreign key may be referenced in parallel operations, these condition checks can fail due to transaction conflicts. In scenarios such as bulk imports or when you've already verified the references, you may want to skip these checks to prevent such failures.
|
|
363
|
+
|
|
364
|
+
To skip referential integrity checks, pass an options object as the second parameter with `referentialIntegrityCheck: false`:
|
|
365
|
+
|
|
366
|
+
```typescript
|
|
367
|
+
const grade: Grade = await Grade.create(
|
|
368
|
+
{
|
|
369
|
+
gradeValue: "A+",
|
|
370
|
+
assignmentId: "123",
|
|
371
|
+
studentId: "456"
|
|
372
|
+
},
|
|
373
|
+
{ referentialIntegrityCheck: false }
|
|
374
|
+
);
|
|
375
|
+
```
|
|
376
|
+
|
|
377
|
+
**Note:** When `referentialIntegrityCheck` is set to `false`, the condition checks that verify foreign key references exist are skipped. This means you can create entities even if the referenced entities don't exist, which may lead to data integrity issues. Use this option with caution.
|
|
378
|
+
|
|
358
379
|
#### Error handling
|
|
359
380
|
|
|
360
381
|
The method is designed to throw errors under various conditions, such as transaction cancellation due to failed conditional checks. For instance, if you attempt to create a `Grade` for an `Assignment` that already has one, the method throws a [TransactionWriteFailedError](https://dyna-record.com/classes/TransactionWriteFailedError.html).
|
|
@@ -547,6 +568,31 @@ const updatedInstance = await petInstance.update({
|
|
|
547
568
|
});
|
|
548
569
|
```
|
|
549
570
|
|
|
571
|
+
#### Skipping Referential Integrity Checks
|
|
572
|
+
|
|
573
|
+
By default, when updating entities with foreign key references, dyna-record performs condition checks to ensure that referenced entities exist. This prevents updating entities with invalid foreign key references. However, in high-contention or high-throughput systems where the same foreign key may be referenced in parallel operations, these condition checks can fail due to transaction conflicts. In scenarios such as bulk updates or when you've already verified the references, you may want to skip these checks to prevent such failures.
|
|
574
|
+
|
|
575
|
+
To skip referential integrity checks, pass an options object as the third parameter with `referentialIntegrityCheck: false`:
|
|
576
|
+
|
|
577
|
+
```typescript
|
|
578
|
+
await PaymentMethod.update(
|
|
579
|
+
"123",
|
|
580
|
+
{ customerId: "456" },
|
|
581
|
+
{ referentialIntegrityCheck: false }
|
|
582
|
+
);
|
|
583
|
+
```
|
|
584
|
+
|
|
585
|
+
For instance methods:
|
|
586
|
+
|
|
587
|
+
```typescript
|
|
588
|
+
const updatedInstance = await paymentMethodInstance.update(
|
|
589
|
+
{ customerId: "456" },
|
|
590
|
+
{ referentialIntegrityCheck: false }
|
|
591
|
+
);
|
|
592
|
+
```
|
|
593
|
+
|
|
594
|
+
**Note:** When `referentialIntegrityCheck` is set to `false`, the condition checks that verify foreign key references exist are skipped. This means you can update entities even if the referenced entities don't exist, which may lead to data integrity issues. Use this option with caution.
|
|
595
|
+
|
|
550
596
|
### Delete
|
|
551
597
|
|
|
552
598
|
[Docs](https://dyna-record.com/classes/default.html#delete)
|
package/dist/src/DynaRecord.d.ts
CHANGED
|
@@ -181,24 +181,36 @@ declare abstract class DynaRecord implements DynaRecordBase {
|
|
|
181
181
|
*/
|
|
182
182
|
static query<T extends DynaRecord>(this: EntityClass<T>, key: IndexKeyConditions<T>, options: OptionsWithIndex): Promise<QueryResults<T>>;
|
|
183
183
|
/**
|
|
184
|
-
* Create an entity. If foreign keys are included in the attributes then links will be
|
|
184
|
+
* Create an entity. If foreign keys are included in the attributes then links will be denormalized accordingly
|
|
185
185
|
* @param attributes - Attributes of the model to create
|
|
186
|
+
* @param options - Optional operation options including referentialIntegrityCheck flag
|
|
186
187
|
* @returns The new Entity
|
|
187
188
|
*
|
|
189
|
+
* @example Basic usage
|
|
188
190
|
* ```typescript
|
|
189
191
|
* const newUser = await User.create({ name: "Alice", email: "alice@example.com", profileId: "123" });
|
|
190
192
|
* ```
|
|
193
|
+
*
|
|
194
|
+
* @example With referential integrity check disabled
|
|
195
|
+
* ```typescript
|
|
196
|
+
* const newUser = await User.create(
|
|
197
|
+
* { name: "Alice", email: "alice@example.com", profileId: "123" },
|
|
198
|
+
* { referentialIntegrityCheck: false }
|
|
199
|
+
* );
|
|
200
|
+
* ```
|
|
191
201
|
*/
|
|
192
|
-
static create<T extends DynaRecord>(this: EntityClass<T>, attributes: CreateOptions<T
|
|
202
|
+
static create<T extends DynaRecord>(this: EntityClass<T>, attributes: CreateOptions<T>, options?: {
|
|
203
|
+
referentialIntegrityCheck?: boolean;
|
|
204
|
+
}): Promise<ReturnType<Create<T>["run"]>>;
|
|
193
205
|
/**
|
|
194
|
-
* Update an entity. If foreign keys are included in the
|
|
206
|
+
* Update an entity. If foreign keys are included in the attributes then:
|
|
195
207
|
* - Manages associated relationship links as needed
|
|
196
208
|
* - If the entity already had a foreign key relationship, then denormalized records will be deleted from each partition
|
|
197
209
|
* - If the foreign key is not nullable then a {@link NullConstraintViolationError} is thrown.
|
|
198
210
|
* - Validation errors will be thrown if the attribute being removed is not nullable
|
|
199
211
|
* @param id - The id of the entity to update
|
|
200
212
|
* @param attributes - Attributes to update
|
|
201
|
-
*
|
|
213
|
+
* @param options - Optional operation options including referentialIntegrityCheck flag
|
|
202
214
|
*
|
|
203
215
|
* @example Updating an entity.
|
|
204
216
|
* ```typescript
|
|
@@ -209,12 +221,22 @@ declare abstract class DynaRecord implements DynaRecordBase {
|
|
|
209
221
|
* ```typescript
|
|
210
222
|
* await User.update("userId", { email: "newemail@example.com", someKey: null });
|
|
211
223
|
* ```
|
|
224
|
+
*
|
|
225
|
+
* @example With referential integrity check disabled
|
|
226
|
+
* ```typescript
|
|
227
|
+
* await User.update(
|
|
228
|
+
* "userId",
|
|
229
|
+
* { email: "newemail@example.com", profileId: 789 },
|
|
230
|
+
* { referentialIntegrityCheck: false }
|
|
231
|
+
* );
|
|
232
|
+
* ```
|
|
212
233
|
*/
|
|
213
|
-
static update<T extends DynaRecord>(this: EntityClass<T>, id: string, attributes: UpdateOptions<T
|
|
234
|
+
static update<T extends DynaRecord>(this: EntityClass<T>, id: string, attributes: UpdateOptions<T>, options?: {
|
|
235
|
+
referentialIntegrityCheck?: boolean;
|
|
236
|
+
}): Promise<void>;
|
|
214
237
|
/**
|
|
215
238
|
* Same as the static `update` method but on an instance. Returns the full updated instance
|
|
216
239
|
*
|
|
217
|
-
*
|
|
218
240
|
* @example Updating an entity.
|
|
219
241
|
* ```typescript
|
|
220
242
|
* const updatedInstance = await instance.update({ email: "newemail@example.com", profileId: 789 });
|
|
@@ -224,8 +246,18 @@ declare abstract class DynaRecord implements DynaRecordBase {
|
|
|
224
246
|
* ```typescript
|
|
225
247
|
* const updatedInstance = await instance.update({ email: "newemail@example.com", someKey: null });
|
|
226
248
|
* ```
|
|
249
|
+
*
|
|
250
|
+
* @example With referential integrity check disabled
|
|
251
|
+
* ```typescript
|
|
252
|
+
* const updatedInstance = await instance.update(
|
|
253
|
+
* { email: "newemail@example.com", profileId: 789 },
|
|
254
|
+
* { referentialIntegrityCheck: false }
|
|
255
|
+
* );
|
|
256
|
+
* ```
|
|
227
257
|
*/
|
|
228
|
-
update<T extends this>(attributes: UpdateOptions<T
|
|
258
|
+
update<T extends this>(attributes: UpdateOptions<T>, options?: {
|
|
259
|
+
referentialIntegrityCheck?: boolean;
|
|
260
|
+
}): Promise<EntityAttributesInstance<T>>;
|
|
229
261
|
/**
|
|
230
262
|
* Delete an entity by ID
|
|
231
263
|
* - Delete all denormalized records
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"DynaRecord.d.ts","sourceRoot":"","sources":["../../src/DynaRecord.ts"],"names":[],"mappings":"AAEA,OAAO,EAEL,KAAK,eAAe,EACpB,KAAK,mBAAmB,EAExB,KAAK,mBAAmB,EACxB,KAAK,YAAY,EACjB,MAAM,EACN,KAAK,aAAa,EAElB,KAAK,aAAa,EAGlB,KAAK,wBAAwB,EAC7B,KAAK,oBAAoB,EACzB,KAAK,kBAAkB,EACvB,KAAK,mBAAmB,EACxB,KAAK,gBAAgB,EAEtB,MAAM,cAAc,CAAC;AACtB,OAAO,KAAK,EAAE,eAAe,EAAE,WAAW,EAAE,QAAQ,EAAE,MAAM,SAAS,CAAC;AAGtE,UAAU,cAAc;IACtB,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;IACb,SAAS,EAAE,IAAI,CAAC;IAChB,SAAS,EAAE,IAAI,CAAC;CACjB;AAED;;;;;;;;;;;;;;;;;;;;;;GAsBG;AACH,uBAAe,UAAW,YAAW,cAAc;IACjD;;OAEG;IACH,SACgB,EAAE,EAAE,MAAM,CAAC;IAE3B;;OAEG;IACH,SACgB,IAAI,EAAE,MAAM,CAAC;IAE7B;;OAEG;IACH,SACgB,SAAS,EAAE,IAAI,CAAC;IAEhC;;OAEG;IACH,SACgB,SAAS,EAAE,IAAI,CAAC;IAEhC;;;;;;;;;;;;;;;;;;;;;;OAsBG;WAEiB,QAAQ,CAAC,CAAC,SAAS,UAAU,EAC/C,IAAI,EAAE,WAAW,CAAC,CAAC,CAAC,EACpB,EAAE,EAAE,MAAM,EACV,OAAO,CAAC,EAAE,SAAS,GAClB,OAAO,CAAC,QAAQ,CAAC,wBAAwB,CAAC,CAAC,CAAC,CAAC,CAAC;WAG7B,QAAQ,CAC1B,CAAC,SAAS,UAAU,EACpB,GAAG,SAAS,oBAAoB,CAAC,CAAC,CAAC,GAAG,EAAE,EAExC,IAAI,EAAE,WAAW,CAAC,CAAC,CAAC,EACpB,EAAE,EAAE,MAAM,EACV,OAAO,EAAE,eAAe,CAAC,CAAC,EAAE,GAAG,CAAC,GAC/B,OAAO,CAAC,QAAQ,CAAC,mBAAmB,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC,CAAC;IAgBjD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;OAmCG;WACiB,KAAK,CAAC,CAAC,SAAS,UAAU,EAC5C,IAAI,EAAE,WAAW,CAAC,CAAC,CAAC,EACpB,GAAG,EAAE,MAAM,EACX,OAAO,CAAC,EAAE,mBAAmB,GAC5B,OAAO,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC;IAE3B;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;OAqDG;WACiB,KAAK,CAAC,CAAC,SAAS,UAAU,EAC5C,IAAI,EAAE,WAAW,CAAC,CAAC,CAAC,EACpB,GAAG,EAAE,mBAAmB,CAAC,CAAC,CAAC,EAC3B,OAAO,CAAC,EAAE,mBAAmB,GAC5B,OAAO,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC;IAE3B;;;;;;;;;;;;;;;OAeG;WACiB,KAAK,CAAC,CAAC,SAAS,UAAU,EAC5C,IAAI,EAAE,WAAW,CAAC,CAAC,CAAC,EACpB,GAAG,EAAE,kBAAkB,CAAC,CAAC,CAAC,EAC1B,OAAO,EAAE,gBAAgB,GACxB,OAAO,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC;IAW3B
|
|
1
|
+
{"version":3,"file":"DynaRecord.d.ts","sourceRoot":"","sources":["../../src/DynaRecord.ts"],"names":[],"mappings":"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"}
|
package/dist/src/DynaRecord.js
CHANGED
|
@@ -145,27 +145,37 @@ let DynaRecord = (() => {
|
|
|
145
145
|
return await op.run(key, options);
|
|
146
146
|
}
|
|
147
147
|
/**
|
|
148
|
-
* Create an entity. If foreign keys are included in the attributes then links will be
|
|
148
|
+
* Create an entity. If foreign keys are included in the attributes then links will be denormalized accordingly
|
|
149
149
|
* @param attributes - Attributes of the model to create
|
|
150
|
+
* @param options - Optional operation options including referentialIntegrityCheck flag
|
|
150
151
|
* @returns The new Entity
|
|
151
152
|
*
|
|
153
|
+
* @example Basic usage
|
|
152
154
|
* ```typescript
|
|
153
155
|
* const newUser = await User.create({ name: "Alice", email: "alice@example.com", profileId: "123" });
|
|
154
156
|
* ```
|
|
157
|
+
*
|
|
158
|
+
* @example With referential integrity check disabled
|
|
159
|
+
* ```typescript
|
|
160
|
+
* const newUser = await User.create(
|
|
161
|
+
* { name: "Alice", email: "alice@example.com", profileId: "123" },
|
|
162
|
+
* { referentialIntegrityCheck: false }
|
|
163
|
+
* );
|
|
164
|
+
* ```
|
|
155
165
|
*/
|
|
156
|
-
static async create(attributes) {
|
|
166
|
+
static async create(attributes, options) {
|
|
157
167
|
const op = new operations_1.Create(this);
|
|
158
|
-
return await op.run(attributes);
|
|
168
|
+
return await op.run(attributes, options);
|
|
159
169
|
}
|
|
160
170
|
/**
|
|
161
|
-
* Update an entity. If foreign keys are included in the
|
|
171
|
+
* Update an entity. If foreign keys are included in the attributes then:
|
|
162
172
|
* - Manages associated relationship links as needed
|
|
163
173
|
* - If the entity already had a foreign key relationship, then denormalized records will be deleted from each partition
|
|
164
174
|
* - If the foreign key is not nullable then a {@link NullConstraintViolationError} is thrown.
|
|
165
175
|
* - Validation errors will be thrown if the attribute being removed is not nullable
|
|
166
176
|
* @param id - The id of the entity to update
|
|
167
177
|
* @param attributes - Attributes to update
|
|
168
|
-
*
|
|
178
|
+
* @param options - Optional operation options including referentialIntegrityCheck flag
|
|
169
179
|
*
|
|
170
180
|
* @example Updating an entity.
|
|
171
181
|
* ```typescript
|
|
@@ -176,15 +186,23 @@ let DynaRecord = (() => {
|
|
|
176
186
|
* ```typescript
|
|
177
187
|
* await User.update("userId", { email: "newemail@example.com", someKey: null });
|
|
178
188
|
* ```
|
|
189
|
+
*
|
|
190
|
+
* @example With referential integrity check disabled
|
|
191
|
+
* ```typescript
|
|
192
|
+
* await User.update(
|
|
193
|
+
* "userId",
|
|
194
|
+
* { email: "newemail@example.com", profileId: 789 },
|
|
195
|
+
* { referentialIntegrityCheck: false }
|
|
196
|
+
* );
|
|
197
|
+
* ```
|
|
179
198
|
*/
|
|
180
|
-
static async update(id, attributes) {
|
|
199
|
+
static async update(id, attributes, options) {
|
|
181
200
|
const op = new operations_1.Update(this);
|
|
182
|
-
await op.run(id, attributes);
|
|
201
|
+
await op.run(id, attributes, options);
|
|
183
202
|
}
|
|
184
203
|
/**
|
|
185
204
|
* Same as the static `update` method but on an instance. Returns the full updated instance
|
|
186
205
|
*
|
|
187
|
-
*
|
|
188
206
|
* @example Updating an entity.
|
|
189
207
|
* ```typescript
|
|
190
208
|
* const updatedInstance = await instance.update({ email: "newemail@example.com", profileId: 789 });
|
|
@@ -194,11 +212,19 @@ let DynaRecord = (() => {
|
|
|
194
212
|
* ```typescript
|
|
195
213
|
* const updatedInstance = await instance.update({ email: "newemail@example.com", someKey: null });
|
|
196
214
|
* ```
|
|
215
|
+
*
|
|
216
|
+
* @example With referential integrity check disabled
|
|
217
|
+
* ```typescript
|
|
218
|
+
* const updatedInstance = await instance.update(
|
|
219
|
+
* { email: "newemail@example.com", profileId: 789 },
|
|
220
|
+
* { referentialIntegrityCheck: false }
|
|
221
|
+
* );
|
|
222
|
+
* ```
|
|
197
223
|
*/
|
|
198
|
-
async update(attributes) {
|
|
224
|
+
async update(attributes, options) {
|
|
199
225
|
const InstanceClass = this.constructor;
|
|
200
226
|
const op = new operations_1.Update(InstanceClass);
|
|
201
|
-
const updatedAttributes = await op.run(this.id, attributes);
|
|
227
|
+
const updatedAttributes = await op.run(this.id, attributes, options);
|
|
202
228
|
const clone = structuredClone(this);
|
|
203
229
|
// Update the current instance with new attributes
|
|
204
230
|
Object.assign(clone, updatedAttributes);
|
|
@@ -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
|