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 +137 -0
- package/dist/src/decorators/attributes/ObjectAttribute.d.ts +97 -0
- package/dist/src/decorators/attributes/ObjectAttribute.d.ts.map +1 -0
- package/dist/src/decorators/attributes/ObjectAttribute.js +151 -0
- package/dist/src/decorators/attributes/index.d.ts +3 -0
- package/dist/src/decorators/attributes/index.d.ts.map +1 -1
- package/dist/src/decorators/attributes/index.js +3 -1
- package/dist/src/decorators/attributes/serializers.d.ts +2 -2
- package/dist/src/decorators/attributes/serializers.d.ts.map +1 -1
- package/dist/src/decorators/attributes/types.d.ts +223 -0
- package/dist/src/decorators/attributes/types.d.ts.map +1 -0
- package/dist/src/decorators/attributes/types.js +2 -0
- package/dist/src/metadata/types.d.ts +3 -3
- package/dist/src/metadata/types.d.ts.map +1 -1
- package/dist/src/query-utils/QueryBuilder.d.ts +24 -5
- package/dist/src/query-utils/QueryBuilder.d.ts.map +1 -1
- package/dist/src/query-utils/QueryBuilder.js +63 -18
- package/dist/src/query-utils/types.d.ts +31 -8
- package/dist/src/query-utils/types.d.ts.map +1 -1
- package/dist/src/types.d.ts +2 -2
- package/dist/src/types.d.ts.map +1 -1
- package/dist/src/utils.d.ts.map +1 -1
- package/package.json +1 -1
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 {
|
|
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:
|
|
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,
|
|
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"}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type {
|
|
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:
|
|
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) =>
|
|
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,
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../src/metadata/types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,wBAAwB,CAAC;AACnE,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,oBAAoB,KAAK,GAAG,CAAC;AAEpE;;GAEG;AACH,MAAM,MAAM,eAAe,GAAG,CAAC,KAAK,EAAE,GAAG,KAAK,oBAAoB,CAAC;AAEnE;;;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"}
|
|
@@ -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
|
-
*
|
|
33
|
-
*
|
|
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
|
-
*
|
|
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,
|
|
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
|
|
74
|
-
obj
|
|
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
|
-
*
|
|
94
|
-
*
|
|
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
|
-
*
|
|
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
|
|
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
|
|
151
|
-
values[
|
|
152
|
-
return acc.concat(`:${
|
|
152
|
+
const placeholder = `${resolved.placeholderKey}${++this.#attrCounter}`;
|
|
153
|
+
values[placeholder] = val;
|
|
154
|
+
return acc.concat(`:${placeholder}`);
|
|
153
155
|
}, []);
|
|
154
|
-
condition =
|
|
156
|
+
condition = `${resolved.expressionPath} IN (${mappings.join()})`;
|
|
155
157
|
}
|
|
156
158
|
else if (this.isBeginsWithFilter(value)) {
|
|
157
|
-
const
|
|
158
|
-
condition = `begins_with(
|
|
159
|
-
values = { [
|
|
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
|
|
163
|
-
condition =
|
|
164
|
-
values = { [
|
|
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
|
|
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,
|
|
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,
|
|
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",
|
|
24
|
+
export type BeginsWithFilter = Record<"$beginsWith", NativeAttributeValue>;
|
|
25
25
|
/**
|
|
26
|
-
*
|
|
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
|
-
*
|
|
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 |
|
|
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 |
|
|
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,
|
|
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"}
|
package/dist/src/types.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { type
|
|
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,
|
|
43
|
+
export type DynamoTableItem = Record<string, NativeAttributeValue>;
|
|
44
44
|
/**
|
|
45
45
|
* A utility type for objects with string keys and string values.
|
|
46
46
|
*/
|
package/dist/src/types.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/types.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,
|
|
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"}
|
package/dist/src/utils.d.ts.map
CHANGED
|
@@ -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;
|
|
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"}
|