@lafken/dynamo 0.14.2 → 0.14.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
|
@@ -27,6 +27,13 @@ interface IndexBase<T extends Function> {
|
|
|
27
27
|
*/
|
|
28
28
|
projection?: (keyof T['prototype'])[] | 'ALL';
|
|
29
29
|
}
|
|
30
|
+
/**
|
|
31
|
+
* Filter expression for a single DynamoDB attribute.
|
|
32
|
+
*
|
|
33
|
+
* Supports exact matches, `anything-but`, `exists`, `prefix`, and empty-string
|
|
34
|
+
* conditions. Values can be provided as a single value, an array of values,
|
|
35
|
+
* or null.
|
|
36
|
+
*/
|
|
30
37
|
type AttributeFilter<T> = {
|
|
31
38
|
[key in keyof T]?: (T[key] | {
|
|
32
39
|
'anything-but': T[key][];
|
|
@@ -359,18 +366,47 @@ export interface ExternalTableMetadata extends Omit<ExternalTableProps<any>, 'na
|
|
|
359
366
|
name: string;
|
|
360
367
|
}
|
|
361
368
|
export type TableMetadata = InternalTableMetadata | ExternalTableMetadata;
|
|
369
|
+
/**
|
|
370
|
+
* Base properties for a DynamoDB table field definition.
|
|
371
|
+
*/
|
|
362
372
|
export interface FieldProps {
|
|
373
|
+
/** The TypeScript constructor that determines the field's DynamoDB type. */
|
|
363
374
|
type?: StringConstructor | NumberConstructor | BooleanConstructor | [Function] | Function;
|
|
364
375
|
}
|
|
376
|
+
/**
|
|
377
|
+
* Resolved metadata for a DynamoDB table field after the `@Field`
|
|
378
|
+
* decorator is processed.
|
|
379
|
+
*/
|
|
365
380
|
export interface FieldMetadata {
|
|
381
|
+
/** Property name as declared on the class. */
|
|
366
382
|
name: string;
|
|
383
|
+
/** Resolved DynamoDB type (e.g. `'string'`, `'number'`, `'boolean'`). */
|
|
367
384
|
type: FieldTypes;
|
|
368
385
|
}
|
|
386
|
+
/**
|
|
387
|
+
* Map of property names to their resolved DynamoDB field metadata.
|
|
388
|
+
*/
|
|
369
389
|
export type FieldsMetadata = Record<string, FieldMetadata>;
|
|
390
|
+
/**
|
|
391
|
+
* Sentinel type used internally to mark DynamoDB partition key properties.
|
|
392
|
+
* Properties typed with `PrimaryPartition<T>` are recognized as partition
|
|
393
|
+
* key candidates during table metadata resolution.
|
|
394
|
+
*/
|
|
370
395
|
type Partition = {
|
|
371
396
|
__special: unknown;
|
|
372
397
|
};
|
|
398
|
+
/**
|
|
399
|
+
* Marks a type as a DynamoDB partition key candidate.
|
|
400
|
+
*
|
|
401
|
+
* @typeParam T - The type to mark as a partition key.
|
|
402
|
+
*/
|
|
373
403
|
export type PrimaryPartition<T = never> = T | (T & Partition);
|
|
404
|
+
/**
|
|
405
|
+
* Extracts only the partition key properties from a DynamoDB table class.
|
|
406
|
+
*
|
|
407
|
+
* Filters the keys of `T` to include only those whose type includes the
|
|
408
|
+
* {@link Partition} sentinel, giving the list of valid partition key fields.
|
|
409
|
+
*/
|
|
374
410
|
export type TablePartition<T> = {
|
|
375
411
|
[K in keyof T as [Extract<T[K], Partition>] extends [never] ? never : K]: T[K];
|
|
376
412
|
};
|
|
@@ -5,6 +5,25 @@ const client_dynamodb_1 = require("@aws-sdk/client-dynamodb");
|
|
|
5
5
|
const util_dynamodb_1 = require("@aws-sdk/util-dynamodb");
|
|
6
6
|
const base_1 = require("../base/base");
|
|
7
7
|
const update_utils_1 = require("./update.utils");
|
|
8
|
+
/**
|
|
9
|
+
* Recursively removes undefined values from an object.
|
|
10
|
+
* This prevents DynamoDB expression errors when undefined values
|
|
11
|
+
* are passed in setValues or replaceValues.
|
|
12
|
+
*/
|
|
13
|
+
function removeUndefinedValues(obj) {
|
|
14
|
+
const result = {};
|
|
15
|
+
for (const key in obj) {
|
|
16
|
+
if (obj[key] !== undefined) {
|
|
17
|
+
if (typeof obj[key] === 'object' && obj[key] !== null && !Array.isArray(obj[key])) {
|
|
18
|
+
result[key] = removeUndefinedValues(obj[key]);
|
|
19
|
+
}
|
|
20
|
+
else {
|
|
21
|
+
result[key] = obj[key];
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
return result;
|
|
26
|
+
}
|
|
8
27
|
class UpdateBuilder extends base_1.QueryBuilderBase {
|
|
9
28
|
queryOptions;
|
|
10
29
|
command;
|
|
@@ -30,17 +49,21 @@ class UpdateBuilder extends base_1.QueryBuilderBase {
|
|
|
30
49
|
}
|
|
31
50
|
prepare() {
|
|
32
51
|
const { removeValues = {}, replaceValues = {}, setValues = {}, condition, } = this.queryOptions.inputProps;
|
|
52
|
+
// Remove undefined values from setValues and replaceValues to prevent
|
|
53
|
+
// DynamoDB expression errors when undefined values are passed
|
|
54
|
+
const filteredSetValues = removeUndefinedValues(setValues);
|
|
55
|
+
const filteredReplaceValues = removeUndefinedValues(replaceValues);
|
|
33
56
|
if (Object.keys(removeValues).length > 0 &&
|
|
34
|
-
Object.keys(
|
|
35
|
-
Object.keys(
|
|
57
|
+
Object.keys(filteredReplaceValues).length > 0 &&
|
|
58
|
+
Object.keys(filteredSetValues).length > 0) {
|
|
36
59
|
throw new Error('You must assign a value to update');
|
|
37
60
|
}
|
|
38
61
|
let setExpression = '';
|
|
39
|
-
if (Object.keys(
|
|
40
|
-
setExpression = this.setValues(
|
|
62
|
+
if (Object.keys(filteredSetValues).length > 0) {
|
|
63
|
+
setExpression = this.setValues(filteredSetValues, true, [], this.expressionGroupCounter++);
|
|
41
64
|
}
|
|
42
|
-
if (Object.keys(
|
|
43
|
-
setExpression += `${setExpression ? ',' : ''} ${this.setValues(
|
|
65
|
+
if (Object.keys(filteredReplaceValues).length > 0) {
|
|
66
|
+
setExpression += `${setExpression ? ',' : ''} ${this.setValues(filteredReplaceValues, false, [], this.expressionGroupCounter++)}`;
|
|
44
67
|
}
|
|
45
68
|
const removeExpression = this.removeValues(removeValues);
|
|
46
69
|
const keyCondition = this.queryOptions.inputProps.keyCondition;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@lafken/dynamo",
|
|
3
|
-
"version": "0.14.
|
|
3
|
+
"version": "0.14.3",
|
|
4
4
|
"private": false,
|
|
5
5
|
"description": "Define DynamoDB tables using TypeScript decorators - type-safe, declarative infrastructure with Lafken",
|
|
6
6
|
"keywords": [
|
|
@@ -59,7 +59,7 @@
|
|
|
59
59
|
"@aws-sdk/client-dynamodb": "^3.1106.0",
|
|
60
60
|
"@aws-sdk/util-dynamodb": "^3.996.7",
|
|
61
61
|
"reflect-metadata": "^0.2.2",
|
|
62
|
-
"@lafken/resolver": "0.14.
|
|
62
|
+
"@lafken/resolver": "0.14.3"
|
|
63
63
|
},
|
|
64
64
|
"devDependencies": {
|
|
65
65
|
"@cdktn/provider-aws": "^25.0.0",
|
|
@@ -73,13 +73,13 @@
|
|
|
73
73
|
"typescript": "7.0.2",
|
|
74
74
|
"unplugin-swc": "^1.5.10",
|
|
75
75
|
"vitest": "^4.1.10",
|
|
76
|
-
"@lafken/common": "0.14.
|
|
76
|
+
"@lafken/common": "0.14.3"
|
|
77
77
|
},
|
|
78
78
|
"peerDependencies": {
|
|
79
79
|
"@cdktn/provider-aws": ">=23.0.0",
|
|
80
80
|
"cdktn": ">=0.22.0",
|
|
81
81
|
"constructs": ">=10.7.0",
|
|
82
|
-
"@lafken/common": "0.14.
|
|
82
|
+
"@lafken/common": "0.14.3"
|
|
83
83
|
},
|
|
84
84
|
"engines": {
|
|
85
85
|
"node": ">=20.19"
|