dyna-record 0.4.9 → 0.4.10

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 CHANGED
@@ -20,6 +20,7 @@ Note: ACID compliant according to DynamoDB [limitations](https://docs.aws.amazon
20
20
  - [Create](#create)
21
21
  - [FindById](#findbyid)
22
22
  - [Query](#query)
23
+ - [Filtering on Object Attributes](#filtering-on-object-attributes)
23
24
  - [Update](#update)
24
25
  - [Delete](#delete)
25
26
  - [Type Safety Features](#type-safety-features)
@@ -144,6 +145,7 @@ Use the attribute decorators below to define attributes on a model. The decorato
144
145
  - [@DateAttribute](https://dyna-record.com/functions/DateAttribute.html)
145
146
  - [@EnumAttribute](https://dyna-record.com/functions/EnumAttribute.html)
146
147
  - [@IdAttribute](https://dyna-record.com/functions/IdAttribute.html)
148
+ - [@ObjectAttribute](https://dyna-record.com/functions/ObjectAttribute.html)
147
149
 
148
150
  - 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.
149
151
  - Set nullable attributes as optional for optimal type safety
@@ -165,6 +167,78 @@ class Student extends MyTable {
165
167
  }
166
168
  ```
167
169
 
170
+ #### @ObjectAttribute
171
+
172
+ Use `@ObjectAttribute` to define structured, typed object attributes on an entity. Objects are validated at runtime and stored as native DynamoDB Map types.
173
+
174
+ Define the shape using an `ObjectSchema` and derive the TypeScript type with `InferObjectSchema`:
175
+
176
+ ```typescript
177
+ import { Entity, ObjectAttribute } from "dyna-record";
178
+ import type { ObjectSchema, InferObjectSchema } from "dyna-record";
179
+
180
+ const addressSchema = {
181
+ street: { type: "string" },
182
+ city: { type: "string" },
183
+ zip: { type: "number", nullable: true },
184
+ tags: { type: "array", items: { type: "string" } },
185
+ category: { type: "enum", values: ["home", "work", "other"] },
186
+ geo: {
187
+ type: "object",
188
+ fields: {
189
+ lat: { type: "number" },
190
+ lng: { type: "number" }
191
+ }
192
+ }
193
+ } as const satisfies ObjectSchema;
194
+
195
+ @Entity
196
+ class Store extends MyTable {
197
+ @ObjectAttribute({ alias: "Address", schema: addressSchema })
198
+ public readonly address: InferObjectSchema<typeof addressSchema>;
199
+
200
+ @ObjectAttribute({ alias: "Metadata", schema: metaSchema, nullable: true })
201
+ public readonly metadata?: InferObjectSchema<typeof metaSchema>;
202
+ }
203
+ ```
204
+
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 allow `null` values
207
+ - **Nullable object attributes:** Set `nullable: true` on the decorator options to make the entire object optional
208
+ - **Alias support:** Use the `alias` option to map to a different DynamoDB attribute name
209
+ - **Storage:** Objects are stored as native DynamoDB Map types
210
+ - **Updates:** Updates replace the entire object (not a partial merge)
211
+ - **Filtering:** Object attributes support dot-path filtering in queries — see [Filtering on Object Attributes](#filtering-on-object-attributes)
212
+
213
+ ##### Enum fields
214
+
215
+ Use `{ type: "enum", values: [...] }` to define a field that only accepts specific string values. The TypeScript type is inferred as a union of the provided values, and invalid values are rejected at runtime via Zod validation.
216
+
217
+ Enum fields can appear at any nesting level — top-level, inside nested objects, or as array items:
218
+
219
+ ```typescript
220
+ const schema = {
221
+ // Top-level enum: inferred as "active" | "inactive"
222
+ status: { type: "enum", values: ["active", "inactive"] },
223
+
224
+ // Nullable enum: inferred as "home" | "work" | "other" | null | undefined
225
+ category: { type: "enum", values: ["home", "work", "other"], nullable: true },
226
+
227
+ // Enum inside a nested object
228
+ geo: {
229
+ type: "object",
230
+ fields: {
231
+ accuracy: { type: "enum", values: ["precise", "approximate"] }
232
+ }
233
+ },
234
+
235
+ // Array of enum values: inferred as ("admin" | "user")[]
236
+ roles: { type: "array", items: { type: "enum", values: ["admin", "user"] } }
237
+ } as const satisfies ObjectSchema;
238
+ ```
239
+
240
+ The schema must be declared with `as const satisfies ObjectSchema` so TypeScript preserves the literal string values for type inference. At runtime, providing an invalid value (e.g., `status: "unknown"`) throws a `ValidationError`.
241
+
168
242
  ### Foreign Keys
169
243
 
170
244
  Define foreign keys in order to support [@BelongsTo](https://dyna-record.com/functions/BelongsTo.html) relationships. A foreign key is required for [@HasOne](https://dyna-record.com/functions/HasOne.html) and [@HasMany](https://dyna-record.com/functions/HasMany.html) relationships.
@@ -496,6 +570,69 @@ const result = await Course.query(
496
570
  );
497
571
  ```
498
572
 
573
+ #### Filtering on Object Attributes
574
+
575
+ When using `@ObjectAttribute`, you can filter on nested Map fields using **dot-path notation** and check List membership using the **`$contains`** operator.
576
+
577
+ ##### Dot-path filtering on nested fields
578
+
579
+ Use dot notation to filter on fields within an `@ObjectAttribute`. All standard filter operators work with dot-paths: equality, `$beginsWith`, and `IN` (array of values).
580
+
581
+ ```typescript
582
+ // Equality on a nested field
583
+ const result = await Store.query("123", {
584
+ filter: { "address.city": "Springfield" }
585
+ });
586
+
587
+ // $beginsWith on a nested field
588
+ const result = await Store.query("123", {
589
+ filter: { "address.street": { $beginsWith: "123" } }
590
+ });
591
+
592
+ // IN on a nested field
593
+ const result = await Store.query("123", {
594
+ filter: { "address.city": ["Springfield", "Shelbyville"] }
595
+ });
596
+
597
+ // Deeply nested fields
598
+ const result = await Store.query("123", {
599
+ filter: { "address.geo.lat": 40 }
600
+ });
601
+ ```
602
+
603
+ ##### `$contains` operator
604
+
605
+ Use `$contains` to check if a List attribute contains a specific element, or if a string attribute contains a substring. Works on both top-level attributes and nested fields via dot-path.
606
+
607
+ ```typescript
608
+ // Check if a List contains an element
609
+ const result = await Store.query("123", {
610
+ filter: { "address.tags": { $contains: "home" } }
611
+ });
612
+
613
+ // Check if a top-level string contains a substring
614
+ const result = await Store.query("123", {
615
+ filter: { name: { $contains: "john" } }
616
+ });
617
+ ```
618
+
619
+ ##### Combining dot-path and `$contains` with AND/OR
620
+
621
+ Dot-path filters and `$contains` work with all existing AND/OR filter combinations.
622
+
623
+ ```typescript
624
+ const result = await Store.query("123", {
625
+ filter: {
626
+ "address.city": "Springfield",
627
+ "address.geo.lat": 40,
628
+ $or: [
629
+ { "address.tags": { $contains: "home" } },
630
+ { name: { $beginsWith: "Main" } }
631
+ ]
632
+ }
633
+ });
634
+ ```
635
+
499
636
  ### Querying on an index
500
637
 
501
638
  For querying based on secondary indexes, you can specify the index name in the options.
@@ -0,0 +1,97 @@
1
+ import type DynaRecord from "../../DynaRecord";
2
+ import type { AttributeDecoratorContext, AttributeOptions } from "../types";
3
+ import type { ObjectSchema, InferObjectSchema } from "./types";
4
+ /**
5
+ * Options for the `@ObjectAttribute` decorator.
6
+ * Extends {@link AttributeOptions} with a required `schema` field describing the object shape.
7
+ *
8
+ * The schema supports all {@link FieldDef} types: primitives, enums, nested objects, and arrays.
9
+ *
10
+ * @template S The specific ObjectSchema type used for type inference
11
+ *
12
+ * @example
13
+ * ```typescript
14
+ * @ObjectAttribute({ alias: "Address", schema: addressSchema })
15
+ * public readonly address: InferObjectSchema<typeof addressSchema>;
16
+ *
17
+ * @ObjectAttribute({ alias: "Meta", schema: metaSchema, nullable: true })
18
+ * public readonly meta?: InferObjectSchema<typeof metaSchema>;
19
+ * ```
20
+ */
21
+ export interface ObjectAttributeOptions<S extends ObjectSchema> extends AttributeOptions {
22
+ /**
23
+ * The {@link ObjectSchema} defining the structure of the object attribute.
24
+ *
25
+ * Must be declared with `as const satisfies ObjectSchema` for accurate type inference.
26
+ */
27
+ schema: S;
28
+ }
29
+ /**
30
+ * A decorator for marking class fields as structured object attributes within the context of a single-table design entity.
31
+ *
32
+ * Objects are stored as native DynamoDB Map types and validated at runtime against the provided schema.
33
+ * The TypeScript type is inferred from the schema using {@link InferObjectSchema}.
34
+ *
35
+ * Can be set to nullable via decorator props.
36
+ *
37
+ * **Supported field types within the schema:**
38
+ * - `"string"`, `"number"`, `"boolean"` — primitives
39
+ * - `"enum"` — string literal unions, validated at runtime via `z.enum()`
40
+ * - `"object"` — nested objects (arbitrarily deep)
41
+ * - `"array"` — lists of any field type
42
+ *
43
+ * All field types support `nullable: true` to allow `null` values.
44
+ *
45
+ * @template T The class type that the decorator is applied to
46
+ * @template S The ObjectSchema type used for validation and type inference
47
+ * @template K The inferred TypeScript type from the schema
48
+ * @template P The decorator options type
49
+ * @param props An {@link ObjectAttributeOptions} object providing the `schema` and optional `alias` and `nullable` configuration.
50
+ * @returns A class field decorator function
51
+ *
52
+ * Usage example:
53
+ * ```typescript
54
+ * const addressSchema = {
55
+ * street: { type: "string" },
56
+ * city: { type: "string" },
57
+ * zip: { type: "number", nullable: true },
58
+ * category: { type: "enum", values: ["home", "work", "other"] },
59
+ * geo: {
60
+ * type: "object",
61
+ * fields: {
62
+ * lat: { type: "number" },
63
+ * lng: { type: "number" },
64
+ * accuracy: { type: "enum", values: ["precise", "approximate"] }
65
+ * }
66
+ * }
67
+ * } as const satisfies ObjectSchema;
68
+ *
69
+ * class MyEntity extends MyTable {
70
+ * @ObjectAttribute({ alias: 'Address', schema: addressSchema })
71
+ * public address: InferObjectSchema<typeof addressSchema>;
72
+ *
73
+ * @ObjectAttribute({ alias: 'Meta', schema: metaSchema, nullable: true })
74
+ * public meta?: InferObjectSchema<typeof metaSchema>;
75
+ * }
76
+ *
77
+ * // TypeScript infers:
78
+ * // address.category → "home" | "work" | "other"
79
+ * // address.geo.accuracy → "precise" | "approximate"
80
+ * ```
81
+ *
82
+ * Object attributes support filtering in queries using dot-path notation for nested fields
83
+ * and the {@link ContainsFilter | $contains} operator for List membership checks.
84
+ *
85
+ * ```typescript
86
+ * await MyEntity.query("123", {
87
+ * filter: { "address.city": "Springfield" }
88
+ * });
89
+ *
90
+ * await MyEntity.query("123", {
91
+ * filter: { "address.tags": { $contains: "home" } }
92
+ * });
93
+ * ```
94
+ */
95
+ declare function ObjectAttribute<T extends DynaRecord, const S extends ObjectSchema, P extends ObjectAttributeOptions<S>>(props: P): (_value: undefined, context: AttributeDecoratorContext<T, InferObjectSchema<S>, P>) => void;
96
+ export default ObjectAttribute;
97
+ //# sourceMappingURL=ObjectAttribute.d.ts.map
@@ -0,0 +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;AAEzE;;;;;;;;;;;;;;;;GAgBG;AACH,MAAM,WAAW,sBAAsB,CAAC,CAAC,SAAS,YAAY,CAC5D,SAAQ,gBAAgB;IACxB;;;;OAIG;IACH,MAAM,EAAE,CAAC,CAAC;CACX;AAsED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;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,UAgBjE;AAED,eAAe,eAAe,CAAC"}
@@ -0,0 +1,151 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ const zod_1 = require("zod");
7
+ const metadata_1 = __importDefault(require("../../metadata"));
8
+ /**
9
+ * Converts an {@link ObjectSchema} to a Zod schema for runtime validation.
10
+ *
11
+ * @param schema The object schema definition
12
+ * @returns A ZodType that validates objects matching the schema
13
+ */
14
+ function objectSchemaToZod(schema) {
15
+ const shape = {};
16
+ for (const [key, fieldDef] of Object.entries(schema)) {
17
+ shape[key] = fieldDefToZod(fieldDef);
18
+ }
19
+ return zod_1.z.object(shape);
20
+ }
21
+ /**
22
+ * Converts a single {@link FieldDef} to the corresponding Zod type for runtime validation.
23
+ *
24
+ * Handles all field types:
25
+ * - `"object"` → recursively builds a `z.object()` via {@link objectSchemaToZod}
26
+ * - `"array"` → `z.array()` wrapping a recursive call for the `items` type
27
+ * - `"string"` → `z.string()`
28
+ * - `"number"` → `z.number()`
29
+ * - `"boolean"` → `z.boolean()`
30
+ * - `"enum"` → `z.enum(values)` for string literal validation
31
+ *
32
+ * When `nullable` is `true`, wraps the type with `.nullable().optional()`.
33
+ *
34
+ * @param fieldDef The field definition to convert
35
+ * @returns A ZodType that validates values matching the field definition
36
+ */
37
+ function fieldDefToZod(fieldDef) {
38
+ let zodType;
39
+ switch (fieldDef.type) {
40
+ case "object":
41
+ zodType = objectSchemaToZod(fieldDef.fields);
42
+ break;
43
+ case "array":
44
+ zodType = zod_1.z.array(fieldDefToZod(fieldDef.items));
45
+ break;
46
+ case "string":
47
+ zodType = zod_1.z.string();
48
+ break;
49
+ case "number":
50
+ zodType = zod_1.z.number();
51
+ break;
52
+ case "boolean":
53
+ zodType = zod_1.z.boolean();
54
+ break;
55
+ case "enum":
56
+ zodType = zod_1.z.enum(fieldDef.values);
57
+ break;
58
+ default: {
59
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars
60
+ const _exhaustiveCheck = fieldDef;
61
+ throw new Error("Unsupported field type");
62
+ }
63
+ }
64
+ if (fieldDef.nullable === true) {
65
+ zodType = zodType.nullable().optional();
66
+ }
67
+ return zodType;
68
+ }
69
+ /**
70
+ * A decorator for marking class fields as structured object attributes within the context of a single-table design entity.
71
+ *
72
+ * Objects are stored as native DynamoDB Map types and validated at runtime against the provided schema.
73
+ * The TypeScript type is inferred from the schema using {@link InferObjectSchema}.
74
+ *
75
+ * Can be set to nullable via decorator props.
76
+ *
77
+ * **Supported field types within the schema:**
78
+ * - `"string"`, `"number"`, `"boolean"` — primitives
79
+ * - `"enum"` — string literal unions, validated at runtime via `z.enum()`
80
+ * - `"object"` — nested objects (arbitrarily deep)
81
+ * - `"array"` — lists of any field type
82
+ *
83
+ * All field types support `nullable: true` to allow `null` values.
84
+ *
85
+ * @template T The class type that the decorator is applied to
86
+ * @template S The ObjectSchema type used for validation and type inference
87
+ * @template K The inferred TypeScript type from the schema
88
+ * @template P The decorator options type
89
+ * @param props An {@link ObjectAttributeOptions} object providing the `schema` and optional `alias` and `nullable` configuration.
90
+ * @returns A class field decorator function
91
+ *
92
+ * Usage example:
93
+ * ```typescript
94
+ * const addressSchema = {
95
+ * street: { type: "string" },
96
+ * city: { type: "string" },
97
+ * zip: { type: "number", nullable: true },
98
+ * category: { type: "enum", values: ["home", "work", "other"] },
99
+ * geo: {
100
+ * type: "object",
101
+ * fields: {
102
+ * lat: { type: "number" },
103
+ * lng: { type: "number" },
104
+ * accuracy: { type: "enum", values: ["precise", "approximate"] }
105
+ * }
106
+ * }
107
+ * } as const satisfies ObjectSchema;
108
+ *
109
+ * class MyEntity extends MyTable {
110
+ * @ObjectAttribute({ alias: 'Address', schema: addressSchema })
111
+ * public address: InferObjectSchema<typeof addressSchema>;
112
+ *
113
+ * @ObjectAttribute({ alias: 'Meta', schema: metaSchema, nullable: true })
114
+ * public meta?: InferObjectSchema<typeof metaSchema>;
115
+ * }
116
+ *
117
+ * // TypeScript infers:
118
+ * // address.category → "home" | "work" | "other"
119
+ * // address.geo.accuracy → "precise" | "approximate"
120
+ * ```
121
+ *
122
+ * Object attributes support filtering in queries using dot-path notation for nested fields
123
+ * and the {@link ContainsFilter | $contains} operator for List membership checks.
124
+ *
125
+ * ```typescript
126
+ * await MyEntity.query("123", {
127
+ * filter: { "address.city": "Springfield" }
128
+ * });
129
+ *
130
+ * await MyEntity.query("123", {
131
+ * filter: { "address.tags": { $contains: "home" } }
132
+ * });
133
+ * ```
134
+ */
135
+ function ObjectAttribute(props) {
136
+ return function (_value, context) {
137
+ if (context.kind === "field") {
138
+ context.addInitializer(function () {
139
+ const { schema, ...restProps } = props;
140
+ const zodSchema = objectSchemaToZod(schema);
141
+ metadata_1.default.addEntityAttribute(this.constructor.name, {
142
+ attributeName: context.name.toString(),
143
+ nullable: props?.nullable,
144
+ type: zodSchema,
145
+ ...restProps
146
+ });
147
+ });
148
+ }
149
+ };
150
+ }
151
+ exports.default = ObjectAttribute;
@@ -7,5 +7,8 @@ export { default as BooleanAttribute } from "./BooleanAttribute";
7
7
  export { default as NumberAttribute } from "./NumberAttribute";
8
8
  export { default as EnumAttribute } from "./EnumAttribute";
9
9
  export { default as IdAttribute } from "./IdAttribute";
10
+ export { default as ObjectAttribute } from "./ObjectAttribute";
11
+ export type { ObjectAttributeOptions } from "./ObjectAttribute";
10
12
  export * from "./serializers";
13
+ export type { ObjectSchema, InferObjectSchema, FieldDef, PrimitiveFieldDef, ObjectFieldDef, ArrayFieldDef, EnumFieldDef } from "./types";
11
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,cAAc,eAAe,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,EACb,MAAM,SAAS,CAAC"}
@@ -17,7 +17,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
17
17
  return (mod && mod.__esModule) ? mod : { "default": mod };
18
18
  };
19
19
  Object.defineProperty(exports, "__esModule", { value: true });
20
- exports.IdAttribute = exports.EnumAttribute = exports.NumberAttribute = exports.BooleanAttribute = exports.StringAttribute = exports.DateAttribute = exports.ForeignKeyAttribute = exports.SortKeyAttribute = exports.PartitionKeyAttribute = void 0;
20
+ exports.ObjectAttribute = exports.IdAttribute = exports.EnumAttribute = exports.NumberAttribute = exports.BooleanAttribute = exports.StringAttribute = exports.DateAttribute = exports.ForeignKeyAttribute = exports.SortKeyAttribute = exports.PartitionKeyAttribute = void 0;
21
21
  var PartitionKeyAttribute_1 = require("./PartitionKeyAttribute");
22
22
  Object.defineProperty(exports, "PartitionKeyAttribute", { enumerable: true, get: function () { return __importDefault(PartitionKeyAttribute_1).default; } });
23
23
  var SortKeyAttribute_1 = require("./SortKeyAttribute");
@@ -36,4 +36,6 @@ var EnumAttribute_1 = require("./EnumAttribute");
36
36
  Object.defineProperty(exports, "EnumAttribute", { enumerable: true, get: function () { return __importDefault(EnumAttribute_1).default; } });
37
37
  var IdAttribute_1 = require("./IdAttribute");
38
38
  Object.defineProperty(exports, "IdAttribute", { enumerable: true, get: function () { return __importDefault(IdAttribute_1).default; } });
39
+ var ObjectAttribute_1 = require("./ObjectAttribute");
40
+ Object.defineProperty(exports, "ObjectAttribute", { enumerable: true, get: function () { return __importDefault(ObjectAttribute_1).default; } });
39
41
  __exportStar(require("./serializers"), exports);
@@ -1,4 +1,4 @@
1
- import type { NativeScalarAttributeValue } from "@aws-sdk/util-dynamodb";
1
+ import type { NativeAttributeValue } from "@aws-sdk/util-dynamodb";
2
2
  /**
3
3
  * 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
4
  *
@@ -7,7 +7,7 @@ import type { NativeScalarAttributeValue } from "@aws-sdk/util-dynamodb";
7
7
  *
8
8
  */
9
9
  export declare const dateSerializer: {
10
- toEntityAttribute: (val: NativeScalarAttributeValue) => number | bigint | boolean | import("@aws-sdk/util-dynamodb").NumberValue | ArrayBuffer | Blob | DataView<ArrayBufferLike> | Date | null | undefined;
10
+ toEntityAttribute: (val: NativeAttributeValue) => any;
11
11
  toTableAttribute: (val?: Date) => string | undefined;
12
12
  };
13
13
  //# 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,0BAA0B,EAAE,MAAM,wBAAwB,CAAC;AAEzE;;;;;;GAMG;AACH,eAAO,MAAM,cAAc;6BACA,0BAA0B;6BAM1B,IAAI;CAC9B,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;AAEnE;;;;;;GAMG;AACH,eAAO,MAAM,cAAc;6BACA,oBAAoB;6BAMpB,IAAI;CAC9B,CAAC"}
@@ -0,0 +1,223 @@
1
+ /**
2
+ * Maps schema type strings to their corresponding TypeScript types.
3
+ *
4
+ * Used by {@link InferFieldDef} to resolve primitive field types at the type level.
5
+ *
6
+ * | Schema type | TypeScript type |
7
+ * |-------------|-----------------|
8
+ * | `"string"` | `string` |
9
+ * | `"number"` | `number` |
10
+ * | `"boolean"` | `boolean` |
11
+ */
12
+ export interface PrimitiveTypeMap {
13
+ string: string;
14
+ number: number;
15
+ boolean: boolean;
16
+ }
17
+ /**
18
+ * The allowed primitive type strings for object schema fields.
19
+ *
20
+ * Derived from the keys of {@link PrimitiveTypeMap}: `"string" | "number" | "boolean"`.
21
+ */
22
+ export type PrimitiveFieldType = keyof PrimitiveTypeMap;
23
+ /**
24
+ * A schema field definition for a primitive type (`"string"`, `"number"`, or `"boolean"`).
25
+ *
26
+ * @example
27
+ * ```typescript
28
+ * const schema = {
29
+ * name: { type: "string" },
30
+ * age: { type: "number", nullable: true },
31
+ * active: { type: "boolean" }
32
+ * } as const satisfies ObjectSchema;
33
+ * ```
34
+ */
35
+ export interface PrimitiveFieldDef {
36
+ /** The primitive type — `"string"`, `"number"`, or `"boolean"`. */
37
+ type: PrimitiveFieldType;
38
+ /** When `true`, the field accepts `null` and becomes optional (`T | null | undefined`). */
39
+ nullable?: boolean;
40
+ }
41
+ /**
42
+ * A schema field definition for a nested object type.
43
+ *
44
+ * The `fields` property is itself an {@link ObjectSchema}, enabling arbitrarily deep nesting.
45
+ *
46
+ * @example
47
+ * ```typescript
48
+ * const schema = {
49
+ * geo: {
50
+ * type: "object",
51
+ * fields: {
52
+ * lat: { type: "number" },
53
+ * lng: { type: "number" }
54
+ * }
55
+ * }
56
+ * } as const satisfies ObjectSchema;
57
+ * ```
58
+ */
59
+ export interface ObjectFieldDef {
60
+ /** Must be `"object"` to indicate a nested object field. */
61
+ type: "object";
62
+ /** The nested {@link ObjectSchema} describing the object's shape. */
63
+ fields: ObjectSchema;
64
+ /** When `true`, the field accepts `null` and becomes optional. */
65
+ nullable?: boolean;
66
+ }
67
+ /**
68
+ * A schema field definition for an array/list type.
69
+ *
70
+ * The `items` property describes the element type — primitives, enums, objects, or nested arrays.
71
+ * Inferred as `Array<InferFieldDef<items>>`.
72
+ *
73
+ * @example
74
+ * ```typescript
75
+ * const schema = {
76
+ * tags: { type: "array", items: { type: "string" } },
77
+ * matrix: { type: "array", items: { type: "array", items: { type: "number" } } }
78
+ * } as const satisfies ObjectSchema;
79
+ * ```
80
+ */
81
+ export interface ArrayFieldDef {
82
+ /** Must be `"array"` to indicate a list/array field. */
83
+ type: "array";
84
+ /** A {@link FieldDef} describing the type of each array element. */
85
+ items: FieldDef;
86
+ /** When `true`, the field accepts `null` and becomes optional. */
87
+ nullable?: boolean;
88
+ }
89
+ /**
90
+ * A schema field definition for an enum type.
91
+ *
92
+ * The `values` tuple defines the allowed string literals, used for both
93
+ * TypeScript type inference (`values[number]` → string literal union) and
94
+ * Zod runtime validation (`z.enum(values)`).
95
+ *
96
+ * Enum fields can appear at any nesting level: top-level, inside nested objects,
97
+ * or as array items.
98
+ *
99
+ * @example
100
+ * ```typescript
101
+ * const schema = {
102
+ * // Top-level enum
103
+ * status: { type: "enum", values: ["active", "inactive"] },
104
+ *
105
+ * // Nullable enum
106
+ * category: { type: "enum", values: ["home", "work", "other"], nullable: true },
107
+ *
108
+ * // Enum inside a nested object
109
+ * geo: {
110
+ * type: "object",
111
+ * fields: {
112
+ * accuracy: { type: "enum", values: ["precise", "approximate"] }
113
+ * }
114
+ * },
115
+ *
116
+ * // Array of enum values
117
+ * roles: { type: "array", items: { type: "enum", values: ["admin", "user", "guest"] } }
118
+ * } as const satisfies ObjectSchema;
119
+ *
120
+ * type T = InferObjectSchema<typeof schema>;
121
+ * // {
122
+ * // status: "active" | "inactive";
123
+ * // category?: "home" | "work" | "other" | null;
124
+ * // geo: { accuracy: "precise" | "approximate" };
125
+ * // roles: ("admin" | "user" | "guest")[];
126
+ * // }
127
+ * ```
128
+ */
129
+ export interface EnumFieldDef {
130
+ /** Must be `"enum"` to indicate an enum field. */
131
+ type: "enum";
132
+ /**
133
+ * A non-empty readonly tuple of allowed string values.
134
+ *
135
+ * At the type level, `values[number]` produces the union of allowed string literals.
136
+ * At runtime, this is passed to `z.enum()` for validation.
137
+ *
138
+ * Must contain at least one value (enforced by the `[string, ...string[]]` tuple type).
139
+ */
140
+ values: readonly [string, ...string[]];
141
+ /** When `true`, the field accepts `null` and becomes optional. */
142
+ nullable?: boolean;
143
+ }
144
+ /**
145
+ * A field definition within an {@link ObjectSchema}.
146
+ *
147
+ * This is the union of all supported field types:
148
+ * - {@link PrimitiveFieldDef} — `"string"`, `"number"`, `"boolean"`
149
+ * - {@link ObjectFieldDef} — nested objects via `fields`
150
+ * - {@link ArrayFieldDef} — arrays/lists via `items`
151
+ * - {@link EnumFieldDef} — string literal enums via `values`
152
+ *
153
+ * Each variant is discriminated by the `type` property.
154
+ */
155
+ export type FieldDef = PrimitiveFieldDef | ObjectFieldDef | ArrayFieldDef | EnumFieldDef;
156
+ /**
157
+ * Declarative schema for describing the shape of an object attribute.
158
+ *
159
+ * Used with `@ObjectAttribute` to provide both runtime validation (via Zod) and
160
+ * compile-time TypeScript type inference (via {@link InferObjectSchema}).
161
+ *
162
+ * Each key maps to a {@link FieldDef} describing the field's type, nesting, and nullability.
163
+ *
164
+ * **Important:** Always declare schemas with `as const satisfies ObjectSchema` to preserve
165
+ * literal types for accurate type inference.
166
+ *
167
+ * @example
168
+ * ```typescript
169
+ * const mySchema = {
170
+ * name: { type: "string" },
171
+ * score: { type: "number" },
172
+ * status: { type: "enum", values: ["active", "inactive"] }
173
+ * } as const satisfies ObjectSchema;
174
+ * ```
175
+ */
176
+ export type ObjectSchema = Record<string, FieldDef>;
177
+ /**
178
+ * Infers the TypeScript type of a single {@link FieldDef}.
179
+ *
180
+ * Used internally by {@link InferObjectSchema} and for recursive array item inference.
181
+ *
182
+ * Resolution order:
183
+ * 1. {@link ArrayFieldDef} → `Array<InferFieldDef<items>>`
184
+ * 2. {@link ObjectFieldDef} → `InferObjectSchema<fields>`
185
+ * 3. {@link EnumFieldDef} → `values[number]` (string literal union)
186
+ * 4. {@link PrimitiveFieldDef} → `PrimitiveTypeMap[type]`
187
+ */
188
+ export type InferFieldDef<F extends FieldDef> = F extends ArrayFieldDef ? Array<InferFieldDef<F["items"]>> : F extends ObjectFieldDef ? InferObjectSchema<F["fields"]> : F extends EnumFieldDef ? F["values"][number] : F extends PrimitiveFieldDef ? PrimitiveTypeMap[F["type"]] : never;
189
+ /**
190
+ * Infers the TypeScript type from an {@link ObjectSchema} definition.
191
+ *
192
+ * - Primitive fields map to their TS equivalents via {@link PrimitiveTypeMap}
193
+ * - Enum fields become a union of their `values` (`values[number]`)
194
+ * - Nested object fields recurse through `InferObjectSchema`
195
+ * - Array fields become `T[]` where `T` is inferred from `items`
196
+ * - Fields with `nullable: true` become optional and accept `null` (`T | null | undefined`)
197
+ *
198
+ * @example
199
+ * ```typescript
200
+ * const schema = {
201
+ * name: { type: "string" },
202
+ * age: { type: "number", nullable: true },
203
+ * status: { type: "enum", values: ["active", "inactive"] },
204
+ * tags: { type: "array", items: { type: "string" } },
205
+ * geo: { type: "object", fields: { lat: { type: "number" }, lng: { type: "number" } } }
206
+ * } as const satisfies ObjectSchema;
207
+ *
208
+ * type MyType = InferObjectSchema<typeof schema>;
209
+ * // {
210
+ * // name: string;
211
+ * // status: "active" | "inactive";
212
+ * // tags: string[];
213
+ * // geo: { lat: number; lng: number };
214
+ * // age?: number | null;
215
+ * // }
216
+ * ```
217
+ */
218
+ export type InferObjectSchema<S extends ObjectSchema> = {
219
+ [K in keyof S as S[K]["nullable"] extends true ? never : K]: InferFieldDef<S[K]>;
220
+ } & {
221
+ [K in keyof S as S[K]["nullable"] extends true ? K : never]?: InferFieldDef<S[K]> | null;
222
+ };
223
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../../src/decorators/attributes/types.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AACH,MAAM,WAAW,gBAAgB;IAC/B,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,EAAE,OAAO,CAAC;CAClB;AAED;;;;GAIG;AACH,MAAM,MAAM,kBAAkB,GAAG,MAAM,gBAAgB,CAAC;AAExD;;;;;;;;;;;GAWG;AACH,MAAM,WAAW,iBAAiB;IAChC,mEAAmE;IACnE,IAAI,EAAE,kBAAkB,CAAC;IACzB,2FAA2F;IAC3F,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,kEAAkE;IAClE,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,kEAAkE;IAClE,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,kEAAkE;IAClE,QAAQ,CAAC,EAAE,OAAO,CAAC;CACpB;AAED;;;;;;;;;;GAUG;AACH,MAAM,MAAM,QAAQ,GAChB,iBAAiB,GACjB,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,GAAG,IAAI;CACT,CAAC"}
@@ -0,0 +1,2 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
@@ -1,4 +1,4 @@
1
- import type { NativeScalarAttributeValue } from "@aws-sdk/util-dynamodb";
1
+ import type { NativeAttributeValue } 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
4
  import type { EntityClass, MakeOptional } from "../types";
@@ -61,11 +61,11 @@ export type KeysAttributeMetadataOptions = MakeOptional<Omit<AttributeMetadataOp
61
61
  /**
62
62
  * Function that takes a attribute from a Dynamo table item, and serialize it to a non-Dynamo native type (EX: Date)
63
63
  */
64
- export type EntitySerializer = (param: NativeScalarAttributeValue) => any;
64
+ export type EntitySerializer = (param: NativeAttributeValue) => any;
65
65
  /**
66
66
  * Function that takes a attribute from an Entity which is not a native Dynamo type and serializes it a type that is supported by Dynamo
67
67
  */
68
- export type TableSerializer = (param: any) => NativeScalarAttributeValue;
68
+ export type TableSerializer = (param: any) => NativeAttributeValue;
69
69
  /**
70
70
  * Functions for serializing attribute types that are not native to Dynamo from table item -> entity and entity -> table item
71
71
  * EX: See DateAttribute decorator
@@ -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,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
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../src/metadata/types.ts"],"names":[],"mappings":"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"}
@@ -3,7 +3,7 @@ import type { QueryCommandProps } from "./types";
3
3
  /**
4
4
  * Constructs and formats a DynamoDB query command based on provided key conditions and query options. This class simplifies the creation of complex DynamoDB queries by abstracting the underlying AWS SDK query command structure, particularly handling the construction of key condition expressions, filter expressions, and expression attribute names and values.
5
5
  *
6
- * Utilizing metadata about the entity and its attributes, `QueryBuilder` generates the necessary DynamoDB expressions to perform precise queries, including support for conditional operators like '=', 'begins_with', and 'IN', as well as logical 'AND' and 'OR' operations.
6
+ * Utilizing metadata about the entity and its attributes, `QueryBuilder` generates the necessary DynamoDB expressions to perform precise queries, including support for conditional operators like '=', 'begins_with', 'contains', and 'IN', as well as logical 'AND' and 'OR' operations. Supports dot-path notation for filtering on nested Map attributes.
7
7
  */
8
8
  declare class QueryBuilder {
9
9
  #private;
@@ -29,8 +29,8 @@ declare class QueryBuilder {
29
29
  * Creates the filters
30
30
  *
31
31
  * Supports 'AND' and 'OR'
32
- * Currently only works for '=', 'begins_with' or 'IN' operands
33
- * Does not support operations like 'contains' etc yet
32
+ * Supports '=', 'begins_with', 'contains', and 'IN' operands
33
+ * Supports dot-path notation for nested Map attributes (e.g., 'address.city')
34
34
  *
35
35
  * @param filter
36
36
  * @returns
@@ -49,12 +49,25 @@ declare class QueryBuilder {
49
49
  */
50
50
  private andFilter;
51
51
  /**
52
- * Creates an AND condition
53
- * @param attr
52
+ * Creates an AND condition.
53
+ * Supports equality, begins_with, contains, and IN operators.
54
+ * Supports dot-path notation for nested Map attributes.
55
+ * @param attr - The attribute key, optionally using dot notation for nested paths
54
56
  * @param value
55
57
  * @returns
56
58
  */
57
59
  private andCondition;
60
+ /**
61
+ * Resolves an attribute key (potentially a dot-path) into its DynamoDB expression components.
62
+ *
63
+ * For simple keys (e.g., "name"), resolves via metadata alias.
64
+ * For dot-paths (e.g., "address.city"), resolves the first segment via metadata alias
65
+ * and uses remaining segments as literal Map sub-keys.
66
+ *
67
+ * @param key - The attribute key, optionally using dot notation
68
+ * @returns The resolved expression path, attribute names, and placeholder key
69
+ */
70
+ private resolveAttrPath;
58
71
  /**
59
72
  * Builds an OR filter
60
73
  * @param filter
@@ -73,6 +86,12 @@ declare class QueryBuilder {
73
86
  * @returns
74
87
  */
75
88
  private isBeginsWithFilter;
89
+ /**
90
+ * Type guard to check if its a ContainsFilter
91
+ * @param filter
92
+ * @returns
93
+ */
94
+ private isContainsFilter;
76
95
  /**
77
96
  * Type guard to check if its a AndOrFilter
78
97
  * @param filter
@@ -1 +1 @@
1
- {"version":3,"file":"QueryBuilder.d.ts","sourceRoot":"","sources":["../../../src/query-utils/QueryBuilder.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,iBAAiB,EAAE,MAAM,uBAAuB,CAAC;AAO/D,OAAO,KAAK,EASV,iBAAiB,EAClB,MAAM,SAAS,CAAC;AAGjB;;;;GAIG;AACH,cAAM,YAAY;;gBASJ,KAAK,EAAE,iBAAiB;IAmBpC;;;OAGG;IACI,KAAK,IAAI,iBAAiB;IAwBjC;;;;;OAKG;IACH,OAAO,CAAC,8BAA8B;IAetC;;;OAGG;IACH,OAAO,CAAC,wBAAwB;IAgChC;;;;;;;;;OASG;IACH,OAAO,CAAC,YAAY;IAWpB;;;;OAIG;IACH,OAAO,CAAC,WAAW;IASnB;;;;OAIG;IACH,OAAO,CAAC,SAAS;IAejB;;;;;OAKG;IACH,OAAO,CAAC,YAAY;IAyBpB;;;;OAIG;IACH,OAAO,CAAC,QAAQ;IAehB;;;;OAIG;IACH,OAAO,CAAC,WAAW;IAanB;;;;OAIG;IACH,OAAO,CAAC,kBAAkB;IAI1B;;;;OAIG;IACH,OAAO,CAAC,aAAa;IAIrB;;;;OAIG;IACH,OAAO,CAAC,UAAU;CAGnB;AAED,eAAe,YAAY,CAAC"}
1
+ {"version":3,"file":"QueryBuilder.d.ts","sourceRoot":"","sources":["../../../src/query-utils/QueryBuilder.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,iBAAiB,EAAE,MAAM,uBAAuB,CAAC;AAO/D,OAAO,KAAK,EAUV,iBAAiB,EAClB,MAAM,SAAS,CAAC;AAgBjB;;;;GAIG;AACH,cAAM,YAAY;;gBASJ,KAAK,EAAE,iBAAiB;IAmBpC;;;OAGG;IACI,KAAK,IAAI,iBAAiB;IAwBjC;;;;;OAKG;IACH,OAAO,CAAC,8BAA8B;IAetC;;;OAGG;IACH,OAAO,CAAC,wBAAwB;IAgChC;;;;;;;;;OASG;IACH,OAAO,CAAC,YAAY;IAWpB;;;;OAIG;IACH,OAAO,CAAC,WAAW;IASnB;;;;OAIG;IACH,OAAO,CAAC,SAAS;IAejB;;;;;;;OAOG;IACH,OAAO,CAAC,YAAY;IA6BpB;;;;;;;;;OASG;IACH,OAAO,CAAC,eAAe;IA0BvB;;;;OAIG;IACH,OAAO,CAAC,QAAQ;IAehB;;;;OAIG;IACH,OAAO,CAAC,WAAW;IAanB;;;;OAIG;IACH,OAAO,CAAC,kBAAkB;IAI1B;;;;OAIG;IACH,OAAO,CAAC,gBAAgB;IAIxB;;;;OAIG;IACH,OAAO,CAAC,aAAa;IAIrB;;;;OAIG;IACH,OAAO,CAAC,UAAU;CAGnB;AAED,eAAe,YAAY,CAAC"}
@@ -8,7 +8,7 @@ const utils_1 = require("../operations/utils");
8
8
  /**
9
9
  * Constructs and formats a DynamoDB query command based on provided key conditions and query options. This class simplifies the creation of complex DynamoDB queries by abstracting the underlying AWS SDK query command structure, particularly handling the construction of key condition expressions, filter expressions, and expression attribute names and values.
10
10
  *
11
- * Utilizing metadata about the entity and its attributes, `QueryBuilder` generates the necessary DynamoDB expressions to perform precise queries, including support for conditional operators like '=', 'begins_with', and 'IN', as well as logical 'AND' and 'OR' operations.
11
+ * Utilizing metadata about the entity and its attributes, `QueryBuilder` generates the necessary DynamoDB expressions to perform precise queries, including support for conditional operators like '=', 'begins_with', 'contains', and 'IN', as well as logical 'AND' and 'OR' operations. Supports dot-path notation for filtering on nested Map attributes.
12
12
  */
13
13
  class QueryBuilder {
14
14
  #props;
@@ -70,8 +70,8 @@ class QueryBuilder {
70
70
  expressionAttributeNames() {
71
71
  const { filter } = this.#props.options ?? {};
72
72
  const accumulator = (obj, key) => {
73
- const tableKey = this.#attributeMetadata[key].alias;
74
- obj[`#${tableKey}`] = tableKey;
73
+ const resolved = this.resolveAttrPath(key);
74
+ Object.assign(obj, resolved.names);
75
75
  return obj;
76
76
  };
77
77
  let expressionAttributeNames = Object.keys(this.#props.key).reduce((acc, key) => accumulator(acc, key), {});
@@ -90,8 +90,8 @@ class QueryBuilder {
90
90
  * Creates the filters
91
91
  *
92
92
  * Supports 'AND' and 'OR'
93
- * Currently only works for '=', 'begins_with' or 'IN' operands
94
- * Does not support operations like 'contains' etc yet
93
+ * Supports '=', 'begins_with', 'contains', and 'IN' operands
94
+ * Supports dot-path notation for nested Map attributes (e.g., 'address.city')
95
95
  *
96
96
  * @param filter
97
97
  * @returns
@@ -136,35 +136,72 @@ class QueryBuilder {
136
136
  return params;
137
137
  }
138
138
  /**
139
- * Creates an AND condition
140
- * @param attr
139
+ * Creates an AND condition.
140
+ * Supports equality, begins_with, contains, and IN operators.
141
+ * Supports dot-path notation for nested Map attributes.
142
+ * @param attr - The attribute key, optionally using dot notation for nested paths
141
143
  * @param value
142
144
  * @returns
143
145
  */
144
146
  andCondition(attr, value) {
145
- const tableKey = this.#attributeMetadata[attr].alias;
147
+ const resolved = this.resolveAttrPath(attr);
146
148
  let condition;
147
149
  let values = {};
148
150
  if (Array.isArray(value)) {
149
151
  const mappings = value.reduce((acc, val) => {
150
- const attr = `${tableKey}${++this.#attrCounter}`;
151
- values[attr] = val;
152
- return acc.concat(`:${attr}`);
152
+ const placeholder = `${resolved.placeholderKey}${++this.#attrCounter}`;
153
+ values[placeholder] = val;
154
+ return acc.concat(`:${placeholder}`);
153
155
  }, []);
154
- condition = `#${tableKey} IN (${mappings.join()})`;
156
+ condition = `${resolved.expressionPath} IN (${mappings.join()})`;
155
157
  }
156
158
  else if (this.isBeginsWithFilter(value)) {
157
- const attr = `${tableKey}${++this.#attrCounter}`;
158
- condition = `begins_with(#${tableKey}, :${attr})`;
159
- values = { [`${attr}`]: value.$beginsWith };
159
+ const placeholder = `${resolved.placeholderKey}${++this.#attrCounter}`;
160
+ condition = `begins_with(${resolved.expressionPath}, :${placeholder})`;
161
+ values = { [placeholder]: value.$beginsWith };
162
+ }
163
+ else if (this.isContainsFilter(value)) {
164
+ const placeholder = `${resolved.placeholderKey}${++this.#attrCounter}`;
165
+ condition = `contains(${resolved.expressionPath}, :${placeholder})`;
166
+ values = { [placeholder]: value.$contains };
160
167
  }
161
168
  else {
162
- const attr = `${tableKey}${++this.#attrCounter}`;
163
- condition = `#${tableKey} = :${attr}`;
164
- values = { [`${attr}`]: value };
169
+ const placeholder = `${resolved.placeholderKey}${++this.#attrCounter}`;
170
+ condition = `${resolved.expressionPath} = :${placeholder}`;
171
+ values = { [placeholder]: value };
165
172
  }
166
173
  return { expression: `${condition} AND `, values };
167
174
  }
175
+ /**
176
+ * Resolves an attribute key (potentially a dot-path) into its DynamoDB expression components.
177
+ *
178
+ * For simple keys (e.g., "name"), resolves via metadata alias.
179
+ * For dot-paths (e.g., "address.city"), resolves the first segment via metadata alias
180
+ * and uses remaining segments as literal Map sub-keys.
181
+ *
182
+ * @param key - The attribute key, optionally using dot notation
183
+ * @returns The resolved expression path, attribute names, and placeholder key
184
+ */
185
+ resolveAttrPath(key) {
186
+ const segments = key.split(".");
187
+ const topLevelKey = segments[0];
188
+ const tableKey = this.#attributeMetadata[topLevelKey].alias;
189
+ const names = { [`#${tableKey}`]: tableKey };
190
+ if (segments.length === 1) {
191
+ return {
192
+ expressionPath: `#${tableKey}`,
193
+ names,
194
+ placeholderKey: tableKey
195
+ };
196
+ }
197
+ const subSegments = segments.slice(1);
198
+ for (const segment of subSegments) {
199
+ names[`#${segment}`] = segment;
200
+ }
201
+ const expressionPath = `#${tableKey}.${subSegments.map(s => `#${s}`).join(".")}`;
202
+ const placeholderKey = `${tableKey}${subSegments.join("")}`;
203
+ return { expressionPath, names, placeholderKey };
204
+ }
168
205
  /**
169
206
  * Builds an OR filter
170
207
  * @param filter
@@ -203,6 +240,14 @@ class QueryBuilder {
203
240
  isBeginsWithFilter(filter) {
204
241
  return filter.$beginsWith !== undefined;
205
242
  }
243
+ /**
244
+ * Type guard to check if its a ContainsFilter
245
+ * @param filter
246
+ * @returns
247
+ */
248
+ isContainsFilter(filter) {
249
+ return filter.$contains !== undefined;
250
+ }
206
251
  /**
207
252
  * Type guard to check if its a AndOrFilter
208
253
  * @param filter
@@ -1,5 +1,5 @@
1
1
  import { type QueryCommandInput } from "@aws-sdk/lib-dynamodb";
2
- import { type NativeScalarAttributeValue } from "@aws-sdk/util-dynamodb";
2
+ import { type NativeAttributeValue } from "@aws-sdk/util-dynamodb";
3
3
  /**
4
4
  * Represents conditions used to specify the partition key and sort key (if applicable) for querying items in DynamoDB.
5
5
  *
@@ -9,11 +9,11 @@ export type KeyConditions = Omit<QueryCommandInput["KeyConditions"], "undefined"
9
9
  /**
10
10
  * Defines the structure for a filter expression used in querying items, including the expression string and a record of values associated with the expression placeholders.
11
11
  *
12
- * @property {Record<string, NativeScalarAttributeValue>} values - A mapping of placeholder tokens in the filter expression to their actual values.
12
+ * @property {Record<string, NativeAttributeValue>} values - A mapping of placeholder tokens in the filter expression to their actual values.
13
13
  * @property {string} expression - The filter expression string, using DynamoDB's expression syntax.
14
14
  */
15
15
  export interface FilterExpression {
16
- values: Record<string, NativeScalarAttributeValue>;
16
+ values: Record<string, NativeAttributeValue>;
17
17
  expression: string;
18
18
  }
19
19
  /**
@@ -21,13 +21,36 @@ export interface FilterExpression {
21
21
  *
22
22
  * @type {BeginsWithFilter} - A record with "$beginsWith" key pointing to the prefix value.
23
23
  */
24
- export type BeginsWithFilter = Record<"$beginsWith", NativeScalarAttributeValue>;
24
+ export type BeginsWithFilter = Record<"$beginsWith", NativeAttributeValue>;
25
25
  /**
26
- * Defines possible types of values that can be used in a filter condition, including begins with, exact value, or an array for "IN" conditions.
26
+ * Represents a filter condition specifying that a list contains a given element, or a string contains a given substring.
27
+ * Maps to the DynamoDB `contains()` function.
27
28
  *
28
- * @type {FilterTypes} - A union of `BeginsWithFilter`, a single scalar value, or an array of scalar values.
29
+ * Works with both top-level attributes and nested `@ObjectAttribute` fields via dot-path notation.
30
+ *
31
+ * @type {ContainsFilter} - A record with "$contains" key pointing to the value to check for.
32
+ *
33
+ * @example
34
+ * ```typescript
35
+ * // Check if a List attribute contains an element
36
+ * filter: { tags: { $contains: "vip" } }
37
+ *
38
+ * // Check on a nested List via dot-path
39
+ * filter: { "address.tags": { $contains: "home" } }
40
+ *
41
+ * // Check if a string attribute contains a substring
42
+ * filter: { name: { $contains: "john" } }
43
+ * ```
44
+ */
45
+ export type ContainsFilter = Record<"$contains", NativeAttributeValue>;
46
+ /**
47
+ * Defines possible types of values that can be used in a filter condition, including begins with, contains, exact value, or an array for "IN" conditions.
48
+ *
49
+ * Filter keys support dot-path notation for nested `@ObjectAttribute` Map fields (e.g., `"address.city"`).
50
+ *
51
+ * @type {FilterTypes} - A union of `BeginsWithFilter`, `ContainsFilter`, a single scalar value, or an array of scalar values.
29
52
  */
30
- export type FilterTypes = BeginsWithFilter | NativeScalarAttributeValue | NativeScalarAttributeValue[];
53
+ export type FilterTypes = BeginsWithFilter | ContainsFilter | NativeAttributeValue | NativeAttributeValue[];
31
54
  /**
32
55
  * Represents a filter condition using an AND logical operator. All items in this record will be queried with "AND"
33
56
  *
@@ -63,7 +86,7 @@ export type AndOrFilter = FilterParams & OrFilter;
63
86
  *
64
87
  * @type {SortKeyCondition} - A `BeginsWithFilter` or a single scalar value, used for sort key conditions in queries.
65
88
  */
66
- export type SortKeyCondition = BeginsWithFilter | NativeScalarAttributeValue;
89
+ export type SortKeyCondition = BeginsWithFilter | NativeAttributeValue;
67
90
  /**
68
91
  * Specifies additional options for querying items, including optional consistent read, index name and filter conditions.
69
92
  *
@@ -1 +1 @@
1
- {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../src/query-utils/types.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,iBAAiB,EAAE,MAAM,uBAAuB,CAAC;AAC/D,OAAO,EAAE,KAAK,0BAA0B,EAAE,MAAM,wBAAwB,CAAC;AAEzE;;;;GAIG;AACH,MAAM,MAAM,aAAa,GAAG,IAAI,CAC9B,iBAAiB,CAAC,eAAe,CAAC,EAClC,WAAW,CACZ,CAAC;AAEF;;;;;GAKG;AACH,MAAM,WAAW,gBAAgB;IAC/B,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,0BAA0B,CAAC,CAAC;IACnD,UAAU,EAAE,MAAM,CAAC;CACpB;AAED;;;;GAIG;AACH,MAAM,MAAM,gBAAgB,GAAG,MAAM,CACnC,aAAa,EACb,0BAA0B,CAC3B,CAAC;AAEF;;;;GAIG;AACH,MAAM,MAAM,WAAW,GACnB,gBAAgB,GAChB,0BAA0B,GAC1B,0BAA0B,EAAE,CAAC;AAEjC;;;;GAIG;AACH,MAAM,MAAM,SAAS,GAAG,MAAM,CAAC,MAAM,EAAE,WAAW,CAAC,CAAC;AAEpD;;;;GAIG;AACH,MAAM,MAAM,QAAQ,GAAG,MAAM,CAAC,KAAK,EAAE,SAAS,EAAE,CAAC,CAAC;AAElD;;;;GAIG;AACH,MAAM,MAAM,UAAU,GAAG,IAAI,CAAC,QAAQ,EAAE,KAAK,CAAC,GAAG,OAAO,CAAC,IAAI,CAAC,QAAQ,EAAE,KAAK,CAAC,CAAC,CAAC;AAEhF;;;;GAIG;AACH,MAAM,MAAM,YAAY,GAAG,CAAC,SAAS,GAAG,QAAQ,CAAC,GAAG,UAAU,CAAC;AAE/D;;;;GAIG;AACH,MAAM,MAAM,WAAW,GAAG,YAAY,GAAG,QAAQ,CAAC;AAElD;;;;GAIG;AACH,MAAM,MAAM,gBAAgB,GAAG,gBAAgB,GAAG,0BAA0B,CAAC;AAE7E;;;;;;;GAOG;AACH,MAAM,MAAM,YAAY,GACpB;IACE,SAAS,EAAE,MAAM,CAAC;IAClB,MAAM,CAAC,EAAE,YAAY,CAAC;IACtB,cAAc,CAAC,EAAE,KAAK,CAAC;CACxB,GACD;IACE,SAAS,CAAC,EAAE,SAAS,CAAC;IACtB,MAAM,CAAC,EAAE,YAAY,CAAC;IACtB,cAAc,CAAC,EAAE,OAAO,CAAC;CAC1B,CAAC;AAEN;;;;;;GAMG;AACH,MAAM,WAAW,iBAAiB;IAChC,eAAe,EAAE,MAAM,CAAC;IACxB,GAAG,EAAE,aAAa,CAAC;IACnB,OAAO,CAAC,EAAE,YAAY,CAAC;CACxB"}
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../src/query-utils/types.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,iBAAiB,EAAE,MAAM,uBAAuB,CAAC;AAC/D,OAAO,EAAE,KAAK,oBAAoB,EAAE,MAAM,wBAAwB,CAAC;AAEnE;;;;GAIG;AACH,MAAM,MAAM,aAAa,GAAG,IAAI,CAC9B,iBAAiB,CAAC,eAAe,CAAC,EAClC,WAAW,CACZ,CAAC;AAEF;;;;;GAKG;AACH,MAAM,WAAW,gBAAgB;IAC/B,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,oBAAoB,CAAC,CAAC;IAC7C,UAAU,EAAE,MAAM,CAAC;CACpB;AAED;;;;GAIG;AACH,MAAM,MAAM,gBAAgB,GAAG,MAAM,CAAC,aAAa,EAAE,oBAAoB,CAAC,CAAC;AAE3E;;;;;;;;;;;;;;;;;;;GAmBG;AACH,MAAM,MAAM,cAAc,GAAG,MAAM,CAAC,WAAW,EAAE,oBAAoB,CAAC,CAAC;AAEvE;;;;;;GAMG;AACH,MAAM,MAAM,WAAW,GACnB,gBAAgB,GAChB,cAAc,GACd,oBAAoB,GACpB,oBAAoB,EAAE,CAAC;AAE3B;;;;GAIG;AACH,MAAM,MAAM,SAAS,GAAG,MAAM,CAAC,MAAM,EAAE,WAAW,CAAC,CAAC;AAEpD;;;;GAIG;AACH,MAAM,MAAM,QAAQ,GAAG,MAAM,CAAC,KAAK,EAAE,SAAS,EAAE,CAAC,CAAC;AAElD;;;;GAIG;AACH,MAAM,MAAM,UAAU,GAAG,IAAI,CAAC,QAAQ,EAAE,KAAK,CAAC,GAAG,OAAO,CAAC,IAAI,CAAC,QAAQ,EAAE,KAAK,CAAC,CAAC,CAAC;AAEhF;;;;GAIG;AACH,MAAM,MAAM,YAAY,GAAG,CAAC,SAAS,GAAG,QAAQ,CAAC,GAAG,UAAU,CAAC;AAE/D;;;;GAIG;AACH,MAAM,MAAM,WAAW,GAAG,YAAY,GAAG,QAAQ,CAAC;AAElD;;;;GAIG;AACH,MAAM,MAAM,gBAAgB,GAAG,gBAAgB,GAAG,oBAAoB,CAAC;AAEvE;;;;;;;GAOG;AACH,MAAM,MAAM,YAAY,GACpB;IACE,SAAS,EAAE,MAAM,CAAC;IAClB,MAAM,CAAC,EAAE,YAAY,CAAC;IACtB,cAAc,CAAC,EAAE,KAAK,CAAC;CACxB,GACD;IACE,SAAS,CAAC,EAAE,SAAS,CAAC;IACtB,MAAM,CAAC,EAAE,YAAY,CAAC;IACtB,cAAc,CAAC,EAAE,OAAO,CAAC;CAC1B,CAAC;AAEN;;;;;;GAMG;AACH,MAAM,WAAW,iBAAiB;IAChC,eAAe,EAAE,MAAM,CAAC;IACxB,GAAG,EAAE,aAAa,CAAC;IACnB,OAAO,CAAC,EAAE,YAAY,CAAC;CACxB"}
@@ -1,4 +1,4 @@
1
- import { type NativeScalarAttributeValue } from "@aws-sdk/util-dynamodb";
1
+ import { type NativeAttributeValue } from "@aws-sdk/util-dynamodb";
2
2
  import type { BelongsToRelationship, RelationshipMetadata } from "./metadata";
3
3
  import type DynaRecord from "./DynaRecord";
4
4
  /**
@@ -40,7 +40,7 @@ export type ForeignKeyProperty = keyof DynaRecord & ForeignKey;
40
40
  /**
41
41
  * Defines a general type for items stored in a DynamoDB table, using string keys and native scalar attribute values.
42
42
  */
43
- export type DynamoTableItem = Record<string, NativeScalarAttributeValue>;
43
+ export type DynamoTableItem = Record<string, NativeAttributeValue>;
44
44
  /**
45
45
  * A utility type for objects with string keys and string values.
46
46
  */
@@ -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;;;;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"}
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/types.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,oBAAoB,EAAE,MAAM,wBAAwB,CAAC;AACnE,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,oBAAoB,CAAC,CAAC;AAEnE;;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"}
@@ -1 +1 @@
1
- {"version":3,"file":"utils.d.ts","sourceRoot":"","sources":["../../src/utils.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,UAAU,MAAM,cAAc,CAAC;AAC3C,OAAO,KAAK,EAAE,eAAe,EAAE,QAAQ,EAAE,MAAM,SAAS,CAAC;AAGzD,OAAO,EAAE,KAAK,oBAAoB,EAAE,MAAM,cAAc,CAAC;AAEzD;;;;;GAKG;AACH,eAAO,MAAM,iBAAiB,GAAI,CAAC,SAAS,UAAU,eACvC,UAAU,CAAC,cACZ,OAAO,CAAC,UAAU,CAAC,KAC9B,eAqBF,CAAC;AAEF;;;;;GAKG;AACH,eAAO,MAAM,iBAAiB,GAAI,CAAC,SAAS,UAAU,eACvC,UAAU,CAAC,aACb,eAAe,KACzB,CAuBF,CAAC;AAEF;;GAEG;AACH,eAAO,MAAM,cAAc,GAAI,CAAC,SAAS,UAAU,eACpC,UAAU,CAAC,cACZ,oBAAoB,CAAC,CAAC,CAAC,KAClC,CAUF,CAAC;AAEF;;GAEG;AACH,eAAO,MAAM,aAAa,WAChB,UAAU,OACb,MAAM,KACV,GAAG,IAAI,MAAM,UAEf,CAAC;AAEF;;;;;GAKG;AACH,eAAO,MAAM,aAAa,GAAI,CAAC,UACrB,OAAO,CAAC,UAAU,CAAC,OACtB,GAAG,KACP,GAAG,IAAI,MAAM,CAEf,CAAC;AAEF;;;;;GAKG;AACH,eAAO,MAAM,UAAU,GAAI,CAAC,SAAS,CAAC,EAAE,QAAQ,MAAM,KAAG,CAAC,EAAE,EAI3D,CAAC;AAEF;;;;;GAKG;AACH,eAAO,MAAM,QAAQ,UAAW,GAAG,KAAG,KAAK,IAAI,MAE9C,CAAC;AAEF;;;;;;;;;;;;;;;;;GAiBG;AACH,eAAO,MAAM,UAAU,GACrB,OAAO,SAAS,oBAAoB,CAAC,UAAU,CAAC,EAChD,IAAI,SAAS,MAAM,OAAO,EAC1B,MAAM,UAEE,OAAO,OACV,IAAI,SACF,MAAM,KACZ,IAEF,CAAC;AAEF;;;;GAIG;AACH,eAAO,MAAM,gBAAgB,QAAS,OAAO,KAAG,GAAG,IAAI,QAAQ,CAAC,MAAM,CAErE,CAAC"}
1
+ {"version":3,"file":"utils.d.ts","sourceRoot":"","sources":["../../src/utils.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,UAAU,MAAM,cAAc,CAAC;AAC3C,OAAO,KAAK,EAAE,eAAe,EAAE,QAAQ,EAAE,MAAM,SAAS,CAAC;AAEzD,OAAO,EAAE,KAAK,oBAAoB,EAAE,MAAM,cAAc,CAAC;AAEzD;;;;;GAKG;AACH,eAAO,MAAM,iBAAiB,GAAI,CAAC,SAAS,UAAU,eACvC,UAAU,CAAC,cACZ,OAAO,CAAC,UAAU,CAAC,KAC9B,eAqBF,CAAC;AAEF;;;;;GAKG;AACH,eAAO,MAAM,iBAAiB,GAAI,CAAC,SAAS,UAAU,eACvC,UAAU,CAAC,aACb,eAAe,KACzB,CAuBF,CAAC;AAEF;;GAEG;AACH,eAAO,MAAM,cAAc,GAAI,CAAC,SAAS,UAAU,eACpC,UAAU,CAAC,cACZ,oBAAoB,CAAC,CAAC,CAAC,KAClC,CAUF,CAAC;AAEF;;GAEG;AACH,eAAO,MAAM,aAAa,WAChB,UAAU,OACb,MAAM,KACV,GAAG,IAAI,MAAM,UAEf,CAAC;AAEF;;;;;GAKG;AACH,eAAO,MAAM,aAAa,GAAI,CAAC,UACrB,OAAO,CAAC,UAAU,CAAC,OACtB,GAAG,KACP,GAAG,IAAI,MAAM,CAEf,CAAC;AAEF;;;;;GAKG;AACH,eAAO,MAAM,UAAU,GAAI,CAAC,SAAS,CAAC,EAAE,QAAQ,MAAM,KAAG,CAAC,EAAE,EAI3D,CAAC;AAEF;;;;;GAKG;AACH,eAAO,MAAM,QAAQ,UAAW,GAAG,KAAG,KAAK,IAAI,MAE9C,CAAC;AAEF;;;;;;;;;;;;;;;;;GAiBG;AACH,eAAO,MAAM,UAAU,GACrB,OAAO,SAAS,oBAAoB,CAAC,UAAU,CAAC,EAChD,IAAI,SAAS,MAAM,OAAO,EAC1B,MAAM,UAEE,OAAO,OACV,IAAI,SACF,MAAM,KACZ,IAEF,CAAC;AAEF;;;;GAIG;AACH,eAAO,MAAM,gBAAgB,QAAS,OAAO,KAAG,GAAG,IAAI,QAAQ,CAAC,MAAM,CAErE,CAAC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "dyna-record",
3
- "version": "0.4.9",
3
+ "version": "0.4.10",
4
4
  "description": "Typescript Data Modeler and ORM for Dynamo",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",