dyna-record 0.4.10 → 0.4.11
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 +4 -3
- package/dist/src/decorators/attributes/ObjectAttribute.d.ts +1 -1
- package/dist/src/decorators/attributes/ObjectAttribute.d.ts.map +1 -1
- package/dist/src/decorators/attributes/ObjectAttribute.js +9 -3
- package/dist/src/decorators/attributes/index.d.ts +1 -1
- package/dist/src/decorators/attributes/index.d.ts.map +1 -1
- package/dist/src/decorators/attributes/serializers.d.ts +48 -0
- package/dist/src/decorators/attributes/serializers.d.ts.map +1 -1
- package/dist/src/decorators/attributes/serializers.js +98 -0
- package/dist/src/decorators/attributes/types.d.ts +33 -10
- package/dist/src/decorators/attributes/types.d.ts.map +1 -1
- package/dist/src/operations/Update/types.d.ts +15 -1
- package/dist/src/operations/Update/types.d.ts.map +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -183,6 +183,7 @@ const addressSchema = {
|
|
|
183
183
|
zip: { type: "number", nullable: true },
|
|
184
184
|
tags: { type: "array", items: { type: "string" } },
|
|
185
185
|
category: { type: "enum", values: ["home", "work", "other"] },
|
|
186
|
+
createdDate: { type: "date" },
|
|
186
187
|
geo: {
|
|
187
188
|
type: "object",
|
|
188
189
|
fields: {
|
|
@@ -202,8 +203,8 @@ class Store extends MyTable {
|
|
|
202
203
|
}
|
|
203
204
|
```
|
|
204
205
|
|
|
205
|
-
- **Supported field types:** `"string"`, `"number"`, `"boolean"`, `"enum"` (via `values`), nested `"object"` (via `fields`), and `"array"` (via `items`)
|
|
206
|
-
- **Nullable fields:** Set `nullable: true` on individual fields within the schema to
|
|
206
|
+
- **Supported field types:** `"string"`, `"number"`, `"boolean"`, `"date"` (stored as ISO strings, exposed as `Date` objects), `"enum"` (via `values`), nested `"object"` (via `fields`), and `"array"` (via `items`)
|
|
207
|
+
- **Nullable fields:** Set `nullable: true` on individual fields within the schema to remove them
|
|
207
208
|
- **Nullable object attributes:** Set `nullable: true` on the decorator options to make the entire object optional
|
|
208
209
|
- **Alias support:** Use the `alias` option to map to a different DynamoDB attribute name
|
|
209
210
|
- **Storage:** Objects are stored as native DynamoDB Map types
|
|
@@ -221,7 +222,7 @@ const schema = {
|
|
|
221
222
|
// Top-level enum: inferred as "active" | "inactive"
|
|
222
223
|
status: { type: "enum", values: ["active", "inactive"] },
|
|
223
224
|
|
|
224
|
-
// Nullable enum: inferred as "home" | "work" | "other" |
|
|
225
|
+
// Nullable enum: inferred as "home" | "work" | "other" | undefined
|
|
225
226
|
category: { type: "enum", values: ["home", "work", "other"], nullable: true },
|
|
226
227
|
|
|
227
228
|
// Enum inside a nested object
|
|
@@ -40,7 +40,7 @@ export interface ObjectAttributeOptions<S extends ObjectSchema> extends Attribut
|
|
|
40
40
|
* - `"object"` — nested objects (arbitrarily deep)
|
|
41
41
|
* - `"array"` — lists of any field type
|
|
42
42
|
*
|
|
43
|
-
* All field types support `nullable: true` to
|
|
43
|
+
* All field types support `nullable: true` to remove them
|
|
44
44
|
*
|
|
45
45
|
* @template T The class type that the decorator is applied to
|
|
46
46
|
* @template S The ObjectSchema type used for validation and type inference
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ObjectAttribute.d.ts","sourceRoot":"","sources":["../../../../src/decorators/attributes/ObjectAttribute.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,UAAU,MAAM,kBAAkB,CAAC;AAE/C,OAAO,KAAK,EAAE,yBAAyB,EAAE,gBAAgB,EAAE,MAAM,UAAU,CAAC;AAC5E,OAAO,KAAK,EAAE,YAAY,EAAE,iBAAiB,EAAY,MAAM,SAAS,CAAC;
|
|
1
|
+
{"version":3,"file":"ObjectAttribute.d.ts","sourceRoot":"","sources":["../../../../src/decorators/attributes/ObjectAttribute.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,UAAU,MAAM,kBAAkB,CAAC;AAE/C,OAAO,KAAK,EAAE,yBAAyB,EAAE,gBAAgB,EAAE,MAAM,UAAU,CAAC;AAC5E,OAAO,KAAK,EAAE,YAAY,EAAE,iBAAiB,EAAY,MAAM,SAAS,CAAC;AAGzE;;;;;;;;;;;;;;;;GAgBG;AACH,MAAM,WAAW,sBAAsB,CAAC,CAAC,SAAS,YAAY,CAC5D,SAAQ,gBAAgB;IACxB;;;;OAIG;IACH,MAAM,EAAE,CAAC,CAAC;CACX;AAyED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAiEG;AACH,iBAAS,eAAe,CACtB,CAAC,SAAS,UAAU,EACpB,KAAK,CAAC,CAAC,SAAS,YAAY,EAC5B,CAAC,SAAS,sBAAsB,CAAC,CAAC,CAAC,EACnC,KAAK,EAAE,CAAC,YAEE,SAAS,WACR,yBAAyB,CAAC,CAAC,EAAE,iBAAiB,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,UAkBjE;AAED,eAAe,eAAe,CAAC"}
|
|
@@ -5,6 +5,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
5
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
6
|
const zod_1 = require("zod");
|
|
7
7
|
const metadata_1 = __importDefault(require("../../metadata"));
|
|
8
|
+
const serializers_1 = require("./serializers");
|
|
8
9
|
/**
|
|
9
10
|
* Converts an {@link ObjectSchema} to a Zod schema for runtime validation.
|
|
10
11
|
*
|
|
@@ -29,7 +30,7 @@ function objectSchemaToZod(schema) {
|
|
|
29
30
|
* - `"boolean"` → `z.boolean()`
|
|
30
31
|
* - `"enum"` → `z.enum(values)` for string literal validation
|
|
31
32
|
*
|
|
32
|
-
* When `nullable` is `true`, wraps the type with `.
|
|
33
|
+
* When `nullable` is `true`, wraps the type with `.optional().nullable()`.
|
|
33
34
|
*
|
|
34
35
|
* @param fieldDef The field definition to convert
|
|
35
36
|
* @returns A ZodType that validates values matching the field definition
|
|
@@ -52,6 +53,9 @@ function fieldDefToZod(fieldDef) {
|
|
|
52
53
|
case "boolean":
|
|
53
54
|
zodType = zod_1.z.boolean();
|
|
54
55
|
break;
|
|
56
|
+
case "date":
|
|
57
|
+
zodType = zod_1.z.date();
|
|
58
|
+
break;
|
|
55
59
|
case "enum":
|
|
56
60
|
zodType = zod_1.z.enum(fieldDef.values);
|
|
57
61
|
break;
|
|
@@ -62,7 +66,7 @@ function fieldDefToZod(fieldDef) {
|
|
|
62
66
|
}
|
|
63
67
|
}
|
|
64
68
|
if (fieldDef.nullable === true) {
|
|
65
|
-
zodType = zodType.
|
|
69
|
+
zodType = zodType.optional().nullable();
|
|
66
70
|
}
|
|
67
71
|
return zodType;
|
|
68
72
|
}
|
|
@@ -80,7 +84,7 @@ function fieldDefToZod(fieldDef) {
|
|
|
80
84
|
* - `"object"` — nested objects (arbitrarily deep)
|
|
81
85
|
* - `"array"` — lists of any field type
|
|
82
86
|
*
|
|
83
|
-
* All field types support `nullable: true` to
|
|
87
|
+
* All field types support `nullable: true` to remove them
|
|
84
88
|
*
|
|
85
89
|
* @template T The class type that the decorator is applied to
|
|
86
90
|
* @template S The ObjectSchema type used for validation and type inference
|
|
@@ -138,10 +142,12 @@ function ObjectAttribute(props) {
|
|
|
138
142
|
context.addInitializer(function () {
|
|
139
143
|
const { schema, ...restProps } = props;
|
|
140
144
|
const zodSchema = objectSchemaToZod(schema);
|
|
145
|
+
const serializers = (0, serializers_1.createObjectSerializer)(schema);
|
|
141
146
|
metadata_1.default.addEntityAttribute(this.constructor.name, {
|
|
142
147
|
attributeName: context.name.toString(),
|
|
143
148
|
nullable: props?.nullable,
|
|
144
149
|
type: zodSchema,
|
|
150
|
+
serializers,
|
|
145
151
|
...restProps
|
|
146
152
|
});
|
|
147
153
|
});
|
|
@@ -10,5 +10,5 @@ export { default as IdAttribute } from "./IdAttribute";
|
|
|
10
10
|
export { default as ObjectAttribute } from "./ObjectAttribute";
|
|
11
11
|
export type { ObjectAttributeOptions } from "./ObjectAttribute";
|
|
12
12
|
export * from "./serializers";
|
|
13
|
-
export type { ObjectSchema, InferObjectSchema, FieldDef, PrimitiveFieldDef, ObjectFieldDef, ArrayFieldDef, EnumFieldDef } from "./types";
|
|
13
|
+
export type { ObjectSchema, InferObjectSchema, FieldDef, PrimitiveFieldDef, ObjectFieldDef, ArrayFieldDef, EnumFieldDef, DateFieldDef } from "./types";
|
|
14
14
|
//# sourceMappingURL=index.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/decorators/attributes/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,IAAI,qBAAqB,EAAE,MAAM,yBAAyB,CAAC;AAC3E,OAAO,EAAE,OAAO,IAAI,gBAAgB,EAAE,MAAM,oBAAoB,CAAC;AACjE,OAAO,EAAE,OAAO,IAAI,mBAAmB,EAAE,MAAM,uBAAuB,CAAC;AACvE,OAAO,EAAE,OAAO,IAAI,aAAa,EAAE,MAAM,iBAAiB,CAAC;AAC3D,OAAO,EAAE,OAAO,IAAI,eAAe,EAAE,MAAM,mBAAmB,CAAC;AAC/D,OAAO,EAAE,OAAO,IAAI,gBAAgB,EAAE,MAAM,oBAAoB,CAAC;AACjE,OAAO,EAAE,OAAO,IAAI,eAAe,EAAE,MAAM,mBAAmB,CAAC;AAC/D,OAAO,EAAE,OAAO,IAAI,aAAa,EAAE,MAAM,iBAAiB,CAAC;AAC3D,OAAO,EAAE,OAAO,IAAI,WAAW,EAAE,MAAM,eAAe,CAAC;AACvD,OAAO,EAAE,OAAO,IAAI,eAAe,EAAE,MAAM,mBAAmB,CAAC;AAC/D,YAAY,EAAE,sBAAsB,EAAE,MAAM,mBAAmB,CAAC;AAChE,cAAc,eAAe,CAAC;AAC9B,YAAY,EACV,YAAY,EACZ,iBAAiB,EACjB,QAAQ,EACR,iBAAiB,EACjB,cAAc,EACd,aAAa,EACb,YAAY,EACb,MAAM,SAAS,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/decorators/attributes/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,IAAI,qBAAqB,EAAE,MAAM,yBAAyB,CAAC;AAC3E,OAAO,EAAE,OAAO,IAAI,gBAAgB,EAAE,MAAM,oBAAoB,CAAC;AACjE,OAAO,EAAE,OAAO,IAAI,mBAAmB,EAAE,MAAM,uBAAuB,CAAC;AACvE,OAAO,EAAE,OAAO,IAAI,aAAa,EAAE,MAAM,iBAAiB,CAAC;AAC3D,OAAO,EAAE,OAAO,IAAI,eAAe,EAAE,MAAM,mBAAmB,CAAC;AAC/D,OAAO,EAAE,OAAO,IAAI,gBAAgB,EAAE,MAAM,oBAAoB,CAAC;AACjE,OAAO,EAAE,OAAO,IAAI,eAAe,EAAE,MAAM,mBAAmB,CAAC;AAC/D,OAAO,EAAE,OAAO,IAAI,aAAa,EAAE,MAAM,iBAAiB,CAAC;AAC3D,OAAO,EAAE,OAAO,IAAI,WAAW,EAAE,MAAM,eAAe,CAAC;AACvD,OAAO,EAAE,OAAO,IAAI,eAAe,EAAE,MAAM,mBAAmB,CAAC;AAC/D,YAAY,EAAE,sBAAsB,EAAE,MAAM,mBAAmB,CAAC;AAChE,cAAc,eAAe,CAAC;AAC9B,YAAY,EACV,YAAY,EACZ,iBAAiB,EACjB,QAAQ,EACR,iBAAiB,EACjB,cAAc,EACd,aAAa,EACb,YAAY,EACZ,YAAY,EACb,MAAM,SAAS,CAAC"}
|
|
@@ -1,4 +1,6 @@
|
|
|
1
1
|
import type { NativeAttributeValue } from "@aws-sdk/util-dynamodb";
|
|
2
|
+
import type { ObjectSchema } from "./types";
|
|
3
|
+
import type { Serializers } from "../../metadata/types";
|
|
2
4
|
/**
|
|
3
5
|
* Provides serialization and deserialization functions for date attributes when interfacing with a DynamoDB table, enabling the conversion between the table's string-based date representation and JavaScript's `Date` object. DynamoDb dos not support Date types naturally, this utility allows for Date attributes to be serialized to an entity and stored as ISO strings in Dynamo.
|
|
4
6
|
*
|
|
@@ -10,4 +12,50 @@ export declare const dateSerializer: {
|
|
|
10
12
|
toEntityAttribute: (val: NativeAttributeValue) => any;
|
|
11
13
|
toTableAttribute: (val?: Date) => string | undefined;
|
|
12
14
|
};
|
|
15
|
+
/**
|
|
16
|
+
* Recursively walks an {@link ObjectSchema} and converts the entity value to its
|
|
17
|
+
* DynamoDB representation.
|
|
18
|
+
*
|
|
19
|
+
* - `"date"` fields are converted from `Date` objects to ISO 8601 strings.
|
|
20
|
+
* - `"object"` fields recurse into their nested schema.
|
|
21
|
+
* - `"array"` fields map each item through the same conversion.
|
|
22
|
+
* - `null` and `undefined` values are stripped from the result so that nullable
|
|
23
|
+
* fields set to `null` are removed from the stored object rather than persisted
|
|
24
|
+
* as `null` in DynamoDB.
|
|
25
|
+
* - All other field types pass through unchanged.
|
|
26
|
+
*
|
|
27
|
+
* @param schema The {@link ObjectSchema} describing the object shape
|
|
28
|
+
* @param value The entity-level object value to convert
|
|
29
|
+
* @returns A new object suitable for DynamoDB storage
|
|
30
|
+
*/
|
|
31
|
+
export declare function objectToTableItem(schema: ObjectSchema, value: Record<string, unknown>): Record<string, unknown>;
|
|
32
|
+
/**
|
|
33
|
+
* Recursively walks an {@link ObjectSchema} and converts a DynamoDB table item
|
|
34
|
+
* back to its entity representation.
|
|
35
|
+
*
|
|
36
|
+
* - `"date"` fields are converted from ISO 8601 strings to `Date` objects.
|
|
37
|
+
* - `"object"` fields recurse into their nested schema.
|
|
38
|
+
* - `"array"` fields map each item through the same conversion.
|
|
39
|
+
* - `null` and `undefined` values are stripped from the result so that absent
|
|
40
|
+
* fields are represented as `undefined` (omitted) on the entity, consistent
|
|
41
|
+
* with root-level nullable attribute behaviour.
|
|
42
|
+
* - All other field types pass through unchanged.
|
|
43
|
+
*
|
|
44
|
+
* @param schema The {@link ObjectSchema} describing the object shape
|
|
45
|
+
* @param value The DynamoDB table item to convert
|
|
46
|
+
* @returns A new object with entity-level types (e.g. `Date` instead of string)
|
|
47
|
+
*/
|
|
48
|
+
export declare function tableItemToObject(schema: ObjectSchema, value: Record<string, unknown>): Record<string, unknown>;
|
|
49
|
+
/**
|
|
50
|
+
* Creates a {@link Serializers} pair for an {@link ObjectSchema}.
|
|
51
|
+
*
|
|
52
|
+
* The returned serializers handle:
|
|
53
|
+
* - Converting `Date` fields to/from ISO 8601 strings for DynamoDB storage.
|
|
54
|
+
* - Stripping `null` and `undefined` values so that nullable fields set to
|
|
55
|
+
* `null` during updates are removed from the stored object.
|
|
56
|
+
*
|
|
57
|
+
* @param schema The {@link ObjectSchema} describing the object shape
|
|
58
|
+
* @returns A `Serializers` object with `toTableAttribute` and `toEntityAttribute` functions
|
|
59
|
+
*/
|
|
60
|
+
export declare function createObjectSerializer(schema: ObjectSchema): Serializers;
|
|
13
61
|
//# sourceMappingURL=serializers.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"serializers.d.ts","sourceRoot":"","sources":["../../../../src/decorators/attributes/serializers.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,wBAAwB,CAAC;
|
|
1
|
+
{"version":3,"file":"serializers.d.ts","sourceRoot":"","sources":["../../../../src/decorators/attributes/serializers.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,wBAAwB,CAAC;AACnE,OAAO,KAAK,EAAE,YAAY,EAAY,MAAM,SAAS,CAAC;AACtD,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,sBAAsB,CAAC;AAExD;;;;;;GAMG;AACH,eAAO,MAAM,cAAc;6BACA,oBAAoB;6BAMpB,IAAI;CAC9B,CAAC;AAEF;;;;;;;;;;;;;;;GAeG;AACH,wBAAgB,iBAAiB,CAC/B,MAAM,EAAE,YAAY,EACpB,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAC7B,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAUzB;AAiBD;;;;;;;;;;;;;;;GAeG;AACH,wBAAgB,iBAAiB,CAC/B,MAAM,EAAE,YAAY,EACpB,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAC7B,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAUzB;AAiBD;;;;;;;;;;GAUG;AACH,wBAAgB,sBAAsB,CAAC,MAAM,EAAE,YAAY,GAAG,WAAW,CAOxE"}
|
|
@@ -1,6 +1,9 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.dateSerializer = void 0;
|
|
4
|
+
exports.objectToTableItem = objectToTableItem;
|
|
5
|
+
exports.tableItemToObject = tableItemToObject;
|
|
6
|
+
exports.createObjectSerializer = createObjectSerializer;
|
|
4
7
|
/**
|
|
5
8
|
* Provides serialization and deserialization functions for date attributes when interfacing with a DynamoDB table, enabling the conversion between the table's string-based date representation and JavaScript's `Date` object. DynamoDb dos not support Date types naturally, this utility allows for Date attributes to be serialized to an entity and stored as ISO strings in Dynamo.
|
|
6
9
|
*
|
|
@@ -17,3 +20,98 @@ exports.dateSerializer = {
|
|
|
17
20
|
},
|
|
18
21
|
toTableAttribute: (val) => val?.toISOString() ?? undefined
|
|
19
22
|
};
|
|
23
|
+
/**
|
|
24
|
+
* Recursively walks an {@link ObjectSchema} and converts the entity value to its
|
|
25
|
+
* DynamoDB representation.
|
|
26
|
+
*
|
|
27
|
+
* - `"date"` fields are converted from `Date` objects to ISO 8601 strings.
|
|
28
|
+
* - `"object"` fields recurse into their nested schema.
|
|
29
|
+
* - `"array"` fields map each item through the same conversion.
|
|
30
|
+
* - `null` and `undefined` values are stripped from the result so that nullable
|
|
31
|
+
* fields set to `null` are removed from the stored object rather than persisted
|
|
32
|
+
* as `null` in DynamoDB.
|
|
33
|
+
* - All other field types pass through unchanged.
|
|
34
|
+
*
|
|
35
|
+
* @param schema The {@link ObjectSchema} describing the object shape
|
|
36
|
+
* @param value The entity-level object value to convert
|
|
37
|
+
* @returns A new object suitable for DynamoDB storage
|
|
38
|
+
*/
|
|
39
|
+
function objectToTableItem(schema, value) {
|
|
40
|
+
const result = {};
|
|
41
|
+
for (const [key, fieldDef] of Object.entries(schema)) {
|
|
42
|
+
const val = value[key];
|
|
43
|
+
if (val === undefined || val === null) {
|
|
44
|
+
continue;
|
|
45
|
+
}
|
|
46
|
+
result[key] = convertFieldToTableItem(fieldDef, val);
|
|
47
|
+
}
|
|
48
|
+
return result;
|
|
49
|
+
}
|
|
50
|
+
function convertFieldToTableItem(fieldDef, val) {
|
|
51
|
+
switch (fieldDef.type) {
|
|
52
|
+
case "date":
|
|
53
|
+
return val.toISOString();
|
|
54
|
+
case "object":
|
|
55
|
+
return objectToTableItem(fieldDef.fields, val);
|
|
56
|
+
case "array":
|
|
57
|
+
return val.map(item => convertFieldToTableItem(fieldDef.items, item));
|
|
58
|
+
default:
|
|
59
|
+
return val;
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
/**
|
|
63
|
+
* Recursively walks an {@link ObjectSchema} and converts a DynamoDB table item
|
|
64
|
+
* back to its entity representation.
|
|
65
|
+
*
|
|
66
|
+
* - `"date"` fields are converted from ISO 8601 strings to `Date` objects.
|
|
67
|
+
* - `"object"` fields recurse into their nested schema.
|
|
68
|
+
* - `"array"` fields map each item through the same conversion.
|
|
69
|
+
* - `null` and `undefined` values are stripped from the result so that absent
|
|
70
|
+
* fields are represented as `undefined` (omitted) on the entity, consistent
|
|
71
|
+
* with root-level nullable attribute behaviour.
|
|
72
|
+
* - All other field types pass through unchanged.
|
|
73
|
+
*
|
|
74
|
+
* @param schema The {@link ObjectSchema} describing the object shape
|
|
75
|
+
* @param value The DynamoDB table item to convert
|
|
76
|
+
* @returns A new object with entity-level types (e.g. `Date` instead of string)
|
|
77
|
+
*/
|
|
78
|
+
function tableItemToObject(schema, value) {
|
|
79
|
+
const result = {};
|
|
80
|
+
for (const [key, fieldDef] of Object.entries(schema)) {
|
|
81
|
+
const val = value[key];
|
|
82
|
+
if (val === undefined || val === null) {
|
|
83
|
+
continue;
|
|
84
|
+
}
|
|
85
|
+
result[key] = convertFieldToEntityValue(fieldDef, val);
|
|
86
|
+
}
|
|
87
|
+
return result;
|
|
88
|
+
}
|
|
89
|
+
function convertFieldToEntityValue(fieldDef, val) {
|
|
90
|
+
switch (fieldDef.type) {
|
|
91
|
+
case "date":
|
|
92
|
+
return new Date(val);
|
|
93
|
+
case "object":
|
|
94
|
+
return tableItemToObject(fieldDef.fields, val);
|
|
95
|
+
case "array":
|
|
96
|
+
return val.map(item => convertFieldToEntityValue(fieldDef.items, item));
|
|
97
|
+
default:
|
|
98
|
+
return val;
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
/**
|
|
102
|
+
* Creates a {@link Serializers} pair for an {@link ObjectSchema}.
|
|
103
|
+
*
|
|
104
|
+
* The returned serializers handle:
|
|
105
|
+
* - Converting `Date` fields to/from ISO 8601 strings for DynamoDB storage.
|
|
106
|
+
* - Stripping `null` and `undefined` values so that nullable fields set to
|
|
107
|
+
* `null` during updates are removed from the stored object.
|
|
108
|
+
*
|
|
109
|
+
* @param schema The {@link ObjectSchema} describing the object shape
|
|
110
|
+
* @returns A `Serializers` object with `toTableAttribute` and `toEntityAttribute` functions
|
|
111
|
+
*/
|
|
112
|
+
function createObjectSerializer(schema) {
|
|
113
|
+
return {
|
|
114
|
+
toTableAttribute: (val) => objectToTableItem(schema, val),
|
|
115
|
+
toEntityAttribute: (val) => tableItemToObject(schema, val)
|
|
116
|
+
};
|
|
117
|
+
}
|
|
@@ -8,16 +8,18 @@
|
|
|
8
8
|
* | `"string"` | `string` |
|
|
9
9
|
* | `"number"` | `number` |
|
|
10
10
|
* | `"boolean"` | `boolean` |
|
|
11
|
+
* | `"date"` | `Date` |
|
|
11
12
|
*/
|
|
12
13
|
export interface PrimitiveTypeMap {
|
|
13
14
|
string: string;
|
|
14
15
|
number: number;
|
|
15
16
|
boolean: boolean;
|
|
17
|
+
date: Date;
|
|
16
18
|
}
|
|
17
19
|
/**
|
|
18
20
|
* The allowed primitive type strings for object schema fields.
|
|
19
21
|
*
|
|
20
|
-
* Derived from the keys of {@link PrimitiveTypeMap}: `"string" | "number" | "boolean"`.
|
|
22
|
+
* Derived from the keys of {@link PrimitiveTypeMap}: `"string" | "number" | "boolean" | "date"`.
|
|
21
23
|
*/
|
|
22
24
|
export type PrimitiveFieldType = keyof PrimitiveTypeMap;
|
|
23
25
|
/**
|
|
@@ -35,7 +37,7 @@ export type PrimitiveFieldType = keyof PrimitiveTypeMap;
|
|
|
35
37
|
export interface PrimitiveFieldDef {
|
|
36
38
|
/** The primitive type — `"string"`, `"number"`, or `"boolean"`. */
|
|
37
39
|
type: PrimitiveFieldType;
|
|
38
|
-
/** When `true`, the field
|
|
40
|
+
/** When `true`, the field becomes optional (`T | undefined`). */
|
|
39
41
|
nullable?: boolean;
|
|
40
42
|
}
|
|
41
43
|
/**
|
|
@@ -61,7 +63,7 @@ export interface ObjectFieldDef {
|
|
|
61
63
|
type: "object";
|
|
62
64
|
/** The nested {@link ObjectSchema} describing the object's shape. */
|
|
63
65
|
fields: ObjectSchema;
|
|
64
|
-
/** When `true`, the field
|
|
66
|
+
/** When `true`, the field becomes optional. */
|
|
65
67
|
nullable?: boolean;
|
|
66
68
|
}
|
|
67
69
|
/**
|
|
@@ -83,7 +85,7 @@ export interface ArrayFieldDef {
|
|
|
83
85
|
type: "array";
|
|
84
86
|
/** A {@link FieldDef} describing the type of each array element. */
|
|
85
87
|
items: FieldDef;
|
|
86
|
-
/** When `true`, the field
|
|
88
|
+
/** When `true`, the field becomes optional. */
|
|
87
89
|
nullable?: boolean;
|
|
88
90
|
}
|
|
89
91
|
/**
|
|
@@ -120,7 +122,7 @@ export interface ArrayFieldDef {
|
|
|
120
122
|
* type T = InferObjectSchema<typeof schema>;
|
|
121
123
|
* // {
|
|
122
124
|
* // status: "active" | "inactive";
|
|
123
|
-
* // category?: "home" | "work" | "other"
|
|
125
|
+
* // category?: "home" | "work" | "other";
|
|
124
126
|
* // geo: { accuracy: "precise" | "approximate" };
|
|
125
127
|
* // roles: ("admin" | "user" | "guest")[];
|
|
126
128
|
* // }
|
|
@@ -138,7 +140,27 @@ export interface EnumFieldDef {
|
|
|
138
140
|
* Must contain at least one value (enforced by the `[string, ...string[]]` tuple type).
|
|
139
141
|
*/
|
|
140
142
|
values: readonly [string, ...string[]];
|
|
141
|
-
/** When `true`, the field
|
|
143
|
+
/** When `true`, the field becomes optional. */
|
|
144
|
+
nullable?: boolean;
|
|
145
|
+
}
|
|
146
|
+
/**
|
|
147
|
+
* A schema field definition for a date type.
|
|
148
|
+
*
|
|
149
|
+
* Date fields are stored as ISO 8601 strings in DynamoDB and exposed as
|
|
150
|
+
* JavaScript `Date` objects on entities, mirroring `@DateAttribute` behavior.
|
|
151
|
+
*
|
|
152
|
+
* @example
|
|
153
|
+
* ```typescript
|
|
154
|
+
* const schema = {
|
|
155
|
+
* createdDate: { type: "date" },
|
|
156
|
+
* deletedAt: { type: "date", nullable: true }
|
|
157
|
+
* } as const satisfies ObjectSchema;
|
|
158
|
+
* ```
|
|
159
|
+
*/
|
|
160
|
+
export interface DateFieldDef {
|
|
161
|
+
/** Must be `"date"` to indicate a date field. */
|
|
162
|
+
type: "date";
|
|
163
|
+
/** When `true`, the field becomes optional (`Date | undefined`). */
|
|
142
164
|
nullable?: boolean;
|
|
143
165
|
}
|
|
144
166
|
/**
|
|
@@ -146,13 +168,14 @@ export interface EnumFieldDef {
|
|
|
146
168
|
*
|
|
147
169
|
* This is the union of all supported field types:
|
|
148
170
|
* - {@link PrimitiveFieldDef} — `"string"`, `"number"`, `"boolean"`
|
|
171
|
+
* - {@link DateFieldDef} — dates stored as ISO strings, exposed as `Date` objects
|
|
149
172
|
* - {@link ObjectFieldDef} — nested objects via `fields`
|
|
150
173
|
* - {@link ArrayFieldDef} — arrays/lists via `items`
|
|
151
174
|
* - {@link EnumFieldDef} — string literal enums via `values`
|
|
152
175
|
*
|
|
153
176
|
* Each variant is discriminated by the `type` property.
|
|
154
177
|
*/
|
|
155
|
-
export type FieldDef = PrimitiveFieldDef | ObjectFieldDef | ArrayFieldDef | EnumFieldDef;
|
|
178
|
+
export type FieldDef = PrimitiveFieldDef | DateFieldDef | ObjectFieldDef | ArrayFieldDef | EnumFieldDef;
|
|
156
179
|
/**
|
|
157
180
|
* Declarative schema for describing the shape of an object attribute.
|
|
158
181
|
*
|
|
@@ -193,7 +216,7 @@ export type InferFieldDef<F extends FieldDef> = F extends ArrayFieldDef ? Array<
|
|
|
193
216
|
* - Enum fields become a union of their `values` (`values[number]`)
|
|
194
217
|
* - Nested object fields recurse through `InferObjectSchema`
|
|
195
218
|
* - Array fields become `T[]` where `T` is inferred from `items`
|
|
196
|
-
* - Fields with `nullable: true` become optional
|
|
219
|
+
* - Fields with `nullable: true` become optional (`T | undefined`)
|
|
197
220
|
*
|
|
198
221
|
* @example
|
|
199
222
|
* ```typescript
|
|
@@ -211,13 +234,13 @@ export type InferFieldDef<F extends FieldDef> = F extends ArrayFieldDef ? Array<
|
|
|
211
234
|
* // status: "active" | "inactive";
|
|
212
235
|
* // tags: string[];
|
|
213
236
|
* // geo: { lat: number; lng: number };
|
|
214
|
-
* // age?: number
|
|
237
|
+
* // age?: number;
|
|
215
238
|
* // }
|
|
216
239
|
* ```
|
|
217
240
|
*/
|
|
218
241
|
export type InferObjectSchema<S extends ObjectSchema> = {
|
|
219
242
|
[K in keyof S as S[K]["nullable"] extends true ? never : K]: InferFieldDef<S[K]>;
|
|
220
243
|
} & {
|
|
221
|
-
[K in keyof S as S[K]["nullable"] extends true ? K : never]?: InferFieldDef<S[K]
|
|
244
|
+
[K in keyof S as S[K]["nullable"] extends true ? K : never]?: InferFieldDef<S[K]>;
|
|
222
245
|
};
|
|
223
246
|
//# sourceMappingURL=types.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../../src/decorators/attributes/types.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../../src/decorators/attributes/types.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AACH,MAAM,WAAW,gBAAgB;IAC/B,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,EAAE,OAAO,CAAC;IACjB,IAAI,EAAE,IAAI,CAAC;CACZ;AAED;;;;GAIG;AACH,MAAM,MAAM,kBAAkB,GAAG,MAAM,gBAAgB,CAAC;AAExD;;;;;;;;;;;GAWG;AACH,MAAM,WAAW,iBAAiB;IAChC,mEAAmE;IACnE,IAAI,EAAE,kBAAkB,CAAC;IACzB,iEAAiE;IACjE,QAAQ,CAAC,EAAE,OAAO,CAAC;CACpB;AAED;;;;;;;;;;;;;;;;;GAiBG;AACH,MAAM,WAAW,cAAc;IAC7B,4DAA4D;IAC5D,IAAI,EAAE,QAAQ,CAAC;IACf,qEAAqE;IACrE,MAAM,EAAE,YAAY,CAAC;IACrB,+CAA+C;IAC/C,QAAQ,CAAC,EAAE,OAAO,CAAC;CACpB;AAED;;;;;;;;;;;;;GAaG;AACH,MAAM,WAAW,aAAa;IAC5B,wDAAwD;IACxD,IAAI,EAAE,OAAO,CAAC;IACd,oEAAoE;IACpE,KAAK,EAAE,QAAQ,CAAC;IAChB,+CAA+C;IAC/C,QAAQ,CAAC,EAAE,OAAO,CAAC;CACpB;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAuCG;AACH,MAAM,WAAW,YAAY;IAC3B,kDAAkD;IAClD,IAAI,EAAE,MAAM,CAAC;IACb;;;;;;;OAOG;IACH,MAAM,EAAE,SAAS,CAAC,MAAM,EAAE,GAAG,MAAM,EAAE,CAAC,CAAC;IACvC,+CAA+C;IAC/C,QAAQ,CAAC,EAAE,OAAO,CAAC;CACpB;AAED;;;;;;;;;;;;;GAaG;AACH,MAAM,WAAW,YAAY;IAC3B,iDAAiD;IACjD,IAAI,EAAE,MAAM,CAAC;IACb,oEAAoE;IACpE,QAAQ,CAAC,EAAE,OAAO,CAAC;CACpB;AAED;;;;;;;;;;;GAWG;AACH,MAAM,MAAM,QAAQ,GAChB,iBAAiB,GACjB,YAAY,GACZ,cAAc,GACd,aAAa,GACb,YAAY,CAAC;AAEjB;;;;;;;;;;;;;;;;;;;GAmBG;AACH,MAAM,MAAM,YAAY,GAAG,MAAM,CAAC,MAAM,EAAE,QAAQ,CAAC,CAAC;AAEpD;;;;;;;;;;GAUG;AACH,MAAM,MAAM,aAAa,CAAC,CAAC,SAAS,QAAQ,IAAI,CAAC,SAAS,aAAa,GACnE,KAAK,CAAC,aAAa,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,GAChC,CAAC,SAAS,cAAc,GACtB,iBAAiB,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,GAC9B,CAAC,SAAS,YAAY,GACpB,CAAC,CAAC,QAAQ,CAAC,CAAC,MAAM,CAAC,GACnB,CAAC,SAAS,iBAAiB,GACzB,gBAAgB,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,GAC3B,KAAK,CAAC;AAEhB;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4BG;AACH,MAAM,MAAM,iBAAiB,CAAC,CAAC,SAAS,YAAY,IAAI;KACrD,CAAC,IAAI,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,UAAU,CAAC,SAAS,IAAI,GAAG,KAAK,GAAG,CAAC,GAAG,aAAa,CACxE,CAAC,CAAC,CAAC,CAAC,CACL;CACF,GAAG;KACD,CAAC,IAAI,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,UAAU,CAAC,SAAS,IAAI,GAAG,CAAC,GAAG,KAAK,CAAC,CAAC,EAAE,aAAa,CACzE,CAAC,CAAC,CAAC,CAAC,CACL;CACF,CAAC"}
|
|
@@ -9,14 +9,28 @@ import type { EntityDefinedAttributes } from "../types";
|
|
|
9
9
|
type NullableProperties<T> = {
|
|
10
10
|
[K in keyof T]: undefined extends T[K] ? K : never;
|
|
11
11
|
}[keyof T];
|
|
12
|
+
/**
|
|
13
|
+
* Recursively resolves the value type for `AllowNullForNullable`.
|
|
14
|
+
*
|
|
15
|
+
* For plain object types (not `Date`, arrays, primitives, or functions),
|
|
16
|
+
* recurses via {@link AllowNullForNullable} so that nullable fields within
|
|
17
|
+
* object schemas (e.g. `@ObjectAttribute`) also receive `| null` during updates.
|
|
18
|
+
*
|
|
19
|
+
* Primitives, `Date`, arrays, and functions pass through unchanged.
|
|
20
|
+
*/
|
|
21
|
+
type AllowNullForNullableValue<T> = T extends Date | readonly unknown[] | string | number | boolean | null | undefined | ((...args: unknown[]) => unknown) ? T : T extends Record<string, unknown> ? AllowNullForNullable<T> : T;
|
|
12
22
|
/**
|
|
13
23
|
* Transforms a type `T` by allowing `null` as an additional type for its nullable properties.
|
|
14
24
|
*
|
|
25
|
+
* Recurses into plain object values (e.g. object schema attributes) so that
|
|
26
|
+
* nullable fields at any depth receive `| null`, matching root-level nullable
|
|
27
|
+
* attribute behavior during updates.
|
|
28
|
+
*
|
|
15
29
|
* @typeParam T - The type whose properties are to be transformed.
|
|
16
30
|
* @returns A new type with properties of `T` where each nullable property is also allowed to be `null`.
|
|
17
31
|
*/
|
|
18
32
|
type AllowNullForNullable<T> = {
|
|
19
|
-
[K in keyof T]: K extends NullableProperties<T> ? T[K] | null : T[K]
|
|
33
|
+
[K in keyof T]: K extends NullableProperties<T> ? AllowNullForNullableValue<NonNullable<T[K]>> | null | undefined : AllowNullForNullableValue<T[K]>;
|
|
20
34
|
};
|
|
21
35
|
/**
|
|
22
36
|
* Attributes of an entity to update. Not all properties are required. Setting a nullable property to null will remove the attribute from the item
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../../src/operations/Update/types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,UAAU,MAAM,kBAAkB,CAAC;AAC/C,OAAO,KAAK,EAAE,uBAAuB,EAAE,MAAM,UAAU,CAAC;AAExD;;;;;GAKG;AACH,KAAK,kBAAkB,CAAC,CAAC,IAAI;KAC1B,CAAC,IAAI,MAAM,CAAC,GAAG,SAAS,SAAS,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,GAAG,KAAK;CACnD,CAAC,MAAM,CAAC,CAAC,CAAC;AAEX
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../../src/operations/Update/types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,UAAU,MAAM,kBAAkB,CAAC;AAC/C,OAAO,KAAK,EAAE,uBAAuB,EAAE,MAAM,UAAU,CAAC;AAExD;;;;;GAKG;AACH,KAAK,kBAAkB,CAAC,CAAC,IAAI;KAC1B,CAAC,IAAI,MAAM,CAAC,GAAG,SAAS,SAAS,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,GAAG,KAAK;CACnD,CAAC,MAAM,CAAC,CAAC,CAAC;AAEX;;;;;;;;GAQG;AACH,KAAK,yBAAyB,CAAC,CAAC,IAAI,CAAC,SACjC,IAAI,GACJ,SAAS,OAAO,EAAE,GAClB,MAAM,GACN,MAAM,GACN,OAAO,GACP,IAAI,GACJ,SAAS,GACT,CAAC,CAAC,GAAG,IAAI,EAAE,OAAO,EAAE,KAAK,OAAO,CAAC,GACjC,CAAC,GACD,CAAC,SAAS,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAC/B,oBAAoB,CAAC,CAAC,CAAC,GACvB,CAAC,CAAC;AAER;;;;;;;;;GASG;AACH,KAAK,oBAAoB,CAAC,CAAC,IAAI;KAC5B,CAAC,IAAI,MAAM,CAAC,GAAG,CAAC,SAAS,kBAAkB,CAAC,CAAC,CAAC,GAC3C,yBAAyB,CAAC,WAAW,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,IAAI,GAAG,SAAS,GAC/D,yBAAyB,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;CACpC,CAAC;AAEF;;;;;;;;GAQG;AACH,MAAM,MAAM,aAAa,CAAC,CAAC,SAAS,UAAU,IAAI,OAAO,CACvD,oBAAoB,CAAC,uBAAuB,CAAC,CAAC,CAAC,CAAC,CACjD,CAAC;AAEF;;GAEG;AACH,MAAM,WAAW,sBAAsB;IACrC;;;;;OAKG;IACH,yBAAyB,CAAC,EAAE,OAAO,CAAC;CACrC;AAED;;GAEG;AACH,MAAM,MAAM,iBAAiB,CAAC,CAAC,SAAS,UAAU,IAAI,IAAI,CACxD,OAAO,CAAC,CAAC,CAAC,EACV,WAAW,CACZ,CAAC"}
|