effect-dynamodb 0.1.0
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/LICENSE +21 -0
- package/README.md +69 -0
- package/dist/Aggregate.d.ts +210 -0
- package/dist/Aggregate.d.ts.map +1 -0
- package/dist/Aggregate.js +1169 -0
- package/dist/Aggregate.js.map +1 -0
- package/dist/Batch.d.ts +62 -0
- package/dist/Batch.d.ts.map +1 -0
- package/dist/Batch.js +218 -0
- package/dist/Batch.js.map +1 -0
- package/dist/Collection.d.ts +58 -0
- package/dist/Collection.d.ts.map +1 -0
- package/dist/Collection.js +195 -0
- package/dist/Collection.js.map +1 -0
- package/dist/Collections.d.ts +121 -0
- package/dist/Collections.d.ts.map +1 -0
- package/dist/Collections.js +121 -0
- package/dist/Collections.js.map +1 -0
- package/dist/DynamoClient.d.ts +317 -0
- package/dist/DynamoClient.d.ts.map +1 -0
- package/dist/DynamoClient.js +653 -0
- package/dist/DynamoClient.js.map +1 -0
- package/dist/DynamoModel.d.ts +278 -0
- package/dist/DynamoModel.d.ts.map +1 -0
- package/dist/DynamoModel.js +453 -0
- package/dist/DynamoModel.js.map +1 -0
- package/dist/DynamoSchema.d.ts +137 -0
- package/dist/DynamoSchema.d.ts.map +1 -0
- package/dist/DynamoSchema.js +188 -0
- package/dist/DynamoSchema.js.map +1 -0
- package/dist/Entity.d.ts +628 -0
- package/dist/Entity.d.ts.map +1 -0
- package/dist/Entity.js +2371 -0
- package/dist/Entity.js.map +1 -0
- package/dist/Errors.d.ts +227 -0
- package/dist/Errors.d.ts.map +1 -0
- package/dist/Errors.js +93 -0
- package/dist/Errors.js.map +1 -0
- package/dist/EventStore.d.ts +208 -0
- package/dist/EventStore.d.ts.map +1 -0
- package/dist/EventStore.js +333 -0
- package/dist/EventStore.js.map +1 -0
- package/dist/Expression.d.ts +50 -0
- package/dist/Expression.d.ts.map +1 -0
- package/dist/Expression.js +170 -0
- package/dist/Expression.js.map +1 -0
- package/dist/KeyComposer.d.ts +125 -0
- package/dist/KeyComposer.d.ts.map +1 -0
- package/dist/KeyComposer.js +257 -0
- package/dist/KeyComposer.js.map +1 -0
- package/dist/Marshaller.d.ts +30 -0
- package/dist/Marshaller.d.ts.map +1 -0
- package/dist/Marshaller.js +115 -0
- package/dist/Marshaller.js.map +1 -0
- package/dist/Projection.d.ts +28 -0
- package/dist/Projection.d.ts.map +1 -0
- package/dist/Projection.js +39 -0
- package/dist/Projection.js.map +1 -0
- package/dist/Query.d.ts +214 -0
- package/dist/Query.d.ts.map +1 -0
- package/dist/Query.js +397 -0
- package/dist/Query.js.map +1 -0
- package/dist/Table.d.ts +178 -0
- package/dist/Table.d.ts.map +1 -0
- package/dist/Table.js +211 -0
- package/dist/Table.js.map +1 -0
- package/dist/Transaction.d.ts +79 -0
- package/dist/Transaction.d.ts.map +1 -0
- package/dist/Transaction.js +215 -0
- package/dist/Transaction.js.map +1 -0
- package/dist/_AggregateCursor.d.ts +44 -0
- package/dist/_AggregateCursor.d.ts.map +1 -0
- package/dist/_AggregateCursor.js +18 -0
- package/dist/_AggregateCursor.js.map +1 -0
- package/dist/_AggregateEdges.d.ts +77 -0
- package/dist/_AggregateEdges.d.ts.map +1 -0
- package/dist/_AggregateEdges.js +41 -0
- package/dist/_AggregateEdges.js.map +1 -0
- package/dist/_AggregateSchemas.d.ts +69 -0
- package/dist/_AggregateSchemas.d.ts.map +1 -0
- package/dist/_AggregateSchemas.js +194 -0
- package/dist/_AggregateSchemas.js.map +1 -0
- package/dist/_AggregateTypes.d.ts +94 -0
- package/dist/_AggregateTypes.d.ts.map +1 -0
- package/dist/_AggregateTypes.js +7 -0
- package/dist/_AggregateTypes.js.map +1 -0
- package/dist/_EntityCombinators.d.ts +155 -0
- package/dist/_EntityCombinators.d.ts.map +1 -0
- package/dist/_EntityCombinators.js +158 -0
- package/dist/_EntityCombinators.js.map +1 -0
- package/dist/_EntityConfig.d.ts +100 -0
- package/dist/_EntityConfig.d.ts.map +1 -0
- package/dist/_EntityConfig.js +7 -0
- package/dist/_EntityConfig.js.map +1 -0
- package/dist/_EntityOps.d.ts +205 -0
- package/dist/_EntityOps.d.ts.map +1 -0
- package/dist/_EntityOps.js +137 -0
- package/dist/_EntityOps.js.map +1 -0
- package/dist/_EntitySchemas.d.ts +57 -0
- package/dist/_EntitySchemas.d.ts.map +1 -0
- package/dist/_EntitySchemas.js +298 -0
- package/dist/_EntitySchemas.js.map +1 -0
- package/dist/_EntityTypes.d.ts +81 -0
- package/dist/_EntityTypes.d.ts.map +1 -0
- package/dist/_EntityTypes.js +7 -0
- package/dist/_EntityTypes.js.map +1 -0
- package/dist/_sparse_check.d.ts +2 -0
- package/dist/_sparse_check.d.ts.map +1 -0
- package/dist/_sparse_check.js +193 -0
- package/dist/_sparse_check.js.map +1 -0
- package/dist/index.d.ts +35 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +20 -0
- package/dist/index.js.map +1 -0
- package/dist/internal/AggregateCursor.d.ts +44 -0
- package/dist/internal/AggregateCursor.d.ts.map +1 -0
- package/dist/internal/AggregateCursor.js +18 -0
- package/dist/internal/AggregateCursor.js.map +1 -0
- package/dist/internal/AggregateEdges.d.ts +77 -0
- package/dist/internal/AggregateEdges.d.ts.map +1 -0
- package/dist/internal/AggregateEdges.js +41 -0
- package/dist/internal/AggregateEdges.js.map +1 -0
- package/dist/internal/AggregateSchemas.d.ts +69 -0
- package/dist/internal/AggregateSchemas.d.ts.map +1 -0
- package/dist/internal/AggregateSchemas.js +193 -0
- package/dist/internal/AggregateSchemas.js.map +1 -0
- package/dist/internal/AggregateTypes.d.ts +94 -0
- package/dist/internal/AggregateTypes.d.ts.map +1 -0
- package/dist/internal/AggregateTypes.js +7 -0
- package/dist/internal/AggregateTypes.js.map +1 -0
- package/dist/internal/BoundQuery.d.ts +107 -0
- package/dist/internal/BoundQuery.d.ts.map +1 -0
- package/dist/internal/BoundQuery.js +111 -0
- package/dist/internal/BoundQuery.js.map +1 -0
- package/dist/internal/EntityCombinators.d.ts +173 -0
- package/dist/internal/EntityCombinators.d.ts.map +1 -0
- package/dist/internal/EntityCombinators.js +183 -0
- package/dist/internal/EntityCombinators.js.map +1 -0
- package/dist/internal/EntityConfig.d.ts +100 -0
- package/dist/internal/EntityConfig.d.ts.map +1 -0
- package/dist/internal/EntityConfig.js +7 -0
- package/dist/internal/EntityConfig.js.map +1 -0
- package/dist/internal/EntityOps.d.ts +268 -0
- package/dist/internal/EntityOps.d.ts.map +1 -0
- package/dist/internal/EntityOps.js +153 -0
- package/dist/internal/EntityOps.js.map +1 -0
- package/dist/internal/EntitySchemas.d.ts +57 -0
- package/dist/internal/EntitySchemas.d.ts.map +1 -0
- package/dist/internal/EntitySchemas.js +299 -0
- package/dist/internal/EntitySchemas.js.map +1 -0
- package/dist/internal/EntityTypes.d.ts +128 -0
- package/dist/internal/EntityTypes.d.ts.map +1 -0
- package/dist/internal/EntityTypes.js +7 -0
- package/dist/internal/EntityTypes.js.map +1 -0
- package/dist/internal/Expr.d.ts +141 -0
- package/dist/internal/Expr.d.ts.map +1 -0
- package/dist/internal/Expr.js +332 -0
- package/dist/internal/Expr.js.map +1 -0
- package/dist/internal/PathBuilder.d.ts +88 -0
- package/dist/internal/PathBuilder.d.ts.map +1 -0
- package/dist/internal/PathBuilder.js +100 -0
- package/dist/internal/PathBuilder.js.map +1 -0
- package/dist/internal/TransactableOps.d.ts +25 -0
- package/dist/internal/TransactableOps.d.ts.map +1 -0
- package/dist/internal/TransactableOps.js +58 -0
- package/dist/internal/TransactableOps.js.map +1 -0
- package/dist/internal/sparse_check.d.ts +2 -0
- package/dist/internal/sparse_check.d.ts.map +1 -0
- package/dist/internal/sparse_check.js +196 -0
- package/dist/internal/sparse_check.js.map +1 -0
- package/package.json +71 -0
|
@@ -0,0 +1,170 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Expression — Type-safe builders for DynamoDB expressions.
|
|
3
|
+
*
|
|
4
|
+
* Produces expression strings with attribute name/value placeholders,
|
|
5
|
+
* matching the shape used by DynamoDB query/put/update/delete operations.
|
|
6
|
+
*
|
|
7
|
+
* Three builder types:
|
|
8
|
+
* - condition: For conditional puts/deletes (ConditionExpression)
|
|
9
|
+
* - filter: For query result filtering (FilterExpression)
|
|
10
|
+
* - update: For update operations (UpdateExpression)
|
|
11
|
+
*/
|
|
12
|
+
import { toAttributeValue } from "./Marshaller.js";
|
|
13
|
+
// Counter for unique placeholder names within a build
|
|
14
|
+
let _counter = 0;
|
|
15
|
+
const nextPlaceholder = () => `v${_counter++}`;
|
|
16
|
+
const resetCounter = () => {
|
|
17
|
+
_counter = 0;
|
|
18
|
+
};
|
|
19
|
+
const buildComparisonClauses = (op, attrs, names, values) => {
|
|
20
|
+
const clauses = [];
|
|
21
|
+
for (const [attr, val] of Object.entries(attrs)) {
|
|
22
|
+
const nameKey = `#${attr}`;
|
|
23
|
+
const valKey = `:${nextPlaceholder()}`;
|
|
24
|
+
names[nameKey] = attr;
|
|
25
|
+
values[valKey] = toAttributeValue(val);
|
|
26
|
+
clauses.push(`${nameKey} ${op} ${valKey}`);
|
|
27
|
+
}
|
|
28
|
+
return clauses;
|
|
29
|
+
};
|
|
30
|
+
const buildFromInput = (input) => {
|
|
31
|
+
resetCounter();
|
|
32
|
+
const names = {};
|
|
33
|
+
const values = {};
|
|
34
|
+
const clauses = [];
|
|
35
|
+
if (input.eq) {
|
|
36
|
+
clauses.push(...buildComparisonClauses("=", input.eq, names, values));
|
|
37
|
+
}
|
|
38
|
+
if (input.ne) {
|
|
39
|
+
clauses.push(...buildComparisonClauses("<>", input.ne, names, values));
|
|
40
|
+
}
|
|
41
|
+
if (input.lt) {
|
|
42
|
+
clauses.push(...buildComparisonClauses("<", input.lt, names, values));
|
|
43
|
+
}
|
|
44
|
+
if (input.le) {
|
|
45
|
+
clauses.push(...buildComparisonClauses("<=", input.le, names, values));
|
|
46
|
+
}
|
|
47
|
+
if (input.gt) {
|
|
48
|
+
clauses.push(...buildComparisonClauses(">", input.gt, names, values));
|
|
49
|
+
}
|
|
50
|
+
if (input.ge) {
|
|
51
|
+
clauses.push(...buildComparisonClauses(">=", input.ge, names, values));
|
|
52
|
+
}
|
|
53
|
+
if (input.between) {
|
|
54
|
+
for (const [attr, [low, high]] of Object.entries(input.between)) {
|
|
55
|
+
const nameKey = `#${attr}`;
|
|
56
|
+
const lowKey = `:${nextPlaceholder()}`;
|
|
57
|
+
const highKey = `:${nextPlaceholder()}`;
|
|
58
|
+
names[nameKey] = attr;
|
|
59
|
+
values[lowKey] = toAttributeValue(low);
|
|
60
|
+
values[highKey] = toAttributeValue(high);
|
|
61
|
+
clauses.push(`${nameKey} BETWEEN ${lowKey} AND ${highKey}`);
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
if (input.beginsWith) {
|
|
65
|
+
for (const [attr, prefix] of Object.entries(input.beginsWith)) {
|
|
66
|
+
const nameKey = `#${attr}`;
|
|
67
|
+
const valKey = `:${nextPlaceholder()}`;
|
|
68
|
+
names[nameKey] = attr;
|
|
69
|
+
values[valKey] = toAttributeValue(prefix);
|
|
70
|
+
clauses.push(`begins_with(${nameKey}, ${valKey})`);
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
if (input.attributeExists) {
|
|
74
|
+
const attrs = Array.isArray(input.attributeExists)
|
|
75
|
+
? input.attributeExists
|
|
76
|
+
: [input.attributeExists];
|
|
77
|
+
for (const attr of attrs) {
|
|
78
|
+
const nameKey = `#${attr}`;
|
|
79
|
+
names[nameKey] = attr;
|
|
80
|
+
clauses.push(`attribute_exists(${nameKey})`);
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
if (input.attributeNotExists) {
|
|
84
|
+
const attrs = Array.isArray(input.attributeNotExists)
|
|
85
|
+
? input.attributeNotExists
|
|
86
|
+
: [input.attributeNotExists];
|
|
87
|
+
for (const attr of attrs) {
|
|
88
|
+
const nameKey = `#${attr}`;
|
|
89
|
+
names[nameKey] = attr;
|
|
90
|
+
clauses.push(`attribute_not_exists(${nameKey})`);
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
return {
|
|
94
|
+
expression: clauses.join(" AND "),
|
|
95
|
+
names,
|
|
96
|
+
values,
|
|
97
|
+
};
|
|
98
|
+
};
|
|
99
|
+
/**
|
|
100
|
+
* Build a ConditionExpression for conditional puts/deletes.
|
|
101
|
+
* All clauses are ANDed together.
|
|
102
|
+
*/
|
|
103
|
+
export const condition = (input) => buildFromInput(input);
|
|
104
|
+
/**
|
|
105
|
+
* Build a FilterExpression for query result filtering.
|
|
106
|
+
* Same syntax as condition expressions.
|
|
107
|
+
*/
|
|
108
|
+
export const filter = (input) => buildFromInput(input);
|
|
109
|
+
/**
|
|
110
|
+
* Build an UpdateExpression with SET, REMOVE, ADD, DELETE clauses.
|
|
111
|
+
*/
|
|
112
|
+
export const update = (input) => {
|
|
113
|
+
resetCounter();
|
|
114
|
+
const names = {};
|
|
115
|
+
const values = {};
|
|
116
|
+
const parts = [];
|
|
117
|
+
if (input.set) {
|
|
118
|
+
const setClauses = [];
|
|
119
|
+
for (const [attr, val] of Object.entries(input.set)) {
|
|
120
|
+
const nameKey = `#${attr}`;
|
|
121
|
+
const valKey = `:${nextPlaceholder()}`;
|
|
122
|
+
names[nameKey] = attr;
|
|
123
|
+
values[valKey] = toAttributeValue(val);
|
|
124
|
+
setClauses.push(`${nameKey} = ${valKey}`);
|
|
125
|
+
}
|
|
126
|
+
if (setClauses.length > 0) {
|
|
127
|
+
parts.push(`SET ${setClauses.join(", ")}`);
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
if (input.remove && input.remove.length > 0) {
|
|
131
|
+
const removeClauses = input.remove.map((attr) => {
|
|
132
|
+
const nameKey = `#${attr}`;
|
|
133
|
+
names[nameKey] = attr;
|
|
134
|
+
return nameKey;
|
|
135
|
+
});
|
|
136
|
+
parts.push(`REMOVE ${removeClauses.join(", ")}`);
|
|
137
|
+
}
|
|
138
|
+
if (input.add) {
|
|
139
|
+
const addClauses = [];
|
|
140
|
+
for (const [attr, val] of Object.entries(input.add)) {
|
|
141
|
+
const nameKey = `#${attr}`;
|
|
142
|
+
const valKey = `:${nextPlaceholder()}`;
|
|
143
|
+
names[nameKey] = attr;
|
|
144
|
+
values[valKey] = toAttributeValue(val);
|
|
145
|
+
addClauses.push(`${nameKey} ${valKey}`);
|
|
146
|
+
}
|
|
147
|
+
if (addClauses.length > 0) {
|
|
148
|
+
parts.push(`ADD ${addClauses.join(", ")}`);
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
if (input.delete) {
|
|
152
|
+
const deleteClauses = [];
|
|
153
|
+
for (const [attr, val] of Object.entries(input.delete)) {
|
|
154
|
+
const nameKey = `#${attr}`;
|
|
155
|
+
const valKey = `:${nextPlaceholder()}`;
|
|
156
|
+
names[nameKey] = attr;
|
|
157
|
+
values[valKey] = toAttributeValue(val);
|
|
158
|
+
deleteClauses.push(`${nameKey} ${valKey}`);
|
|
159
|
+
}
|
|
160
|
+
if (deleteClauses.length > 0) {
|
|
161
|
+
parts.push(`DELETE ${deleteClauses.join(", ")}`);
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
return {
|
|
165
|
+
expression: parts.join(" "),
|
|
166
|
+
names,
|
|
167
|
+
values,
|
|
168
|
+
};
|
|
169
|
+
};
|
|
170
|
+
//# sourceMappingURL=Expression.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Expression.js","sourceRoot":"","sources":["../src/Expression.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,125 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* KeyComposer — Composite key composition for DynamoDB keys.
|
|
3
|
+
*
|
|
4
|
+
* v2 uses attribute-list composition (composite: ["userId"]) instead of
|
|
5
|
+
* template strings ("USER#${userId}"). The DynamoSchema module handles
|
|
6
|
+
* the key format; KeyComposer extracts attribute values and delegates.
|
|
7
|
+
*/
|
|
8
|
+
import type * as DynamoSchema from "./DynamoSchema.js";
|
|
9
|
+
/** Index key part definition (pk or sk of an index) */
|
|
10
|
+
export interface KeyPart {
|
|
11
|
+
readonly field: string;
|
|
12
|
+
readonly composite: ReadonlyArray<string>;
|
|
13
|
+
}
|
|
14
|
+
/** Index definition for primary or secondary index (internal format) */
|
|
15
|
+
export interface IndexDefinition {
|
|
16
|
+
readonly index?: string | undefined;
|
|
17
|
+
readonly collection?: string | ReadonlyArray<string> | undefined;
|
|
18
|
+
readonly type?: "isolated" | "clustered" | undefined;
|
|
19
|
+
readonly pk: KeyPart;
|
|
20
|
+
readonly sk: KeyPart;
|
|
21
|
+
readonly casing?: DynamoSchema.Casing | undefined;
|
|
22
|
+
}
|
|
23
|
+
/** GSI definition as specified on Entity.make() indexes config.
|
|
24
|
+
* Mirrors the primaryKey structure with an added `name` for the physical GSI. */
|
|
25
|
+
export interface GsiConfig {
|
|
26
|
+
/** Physical GSI name (e.g., `"gsi1"`). */
|
|
27
|
+
readonly name: string;
|
|
28
|
+
/** Optional collection name. String for single, array for sub-collections. */
|
|
29
|
+
readonly collection?: string | ReadonlyArray<string> | undefined;
|
|
30
|
+
/** SK ordering mode. `"isolated"` (default) puts entity type before composites; `"clustered"` puts entity type after composites (required for sub-collections). */
|
|
31
|
+
readonly type?: "isolated" | "clustered" | undefined;
|
|
32
|
+
/** Partition key: physical field name + composite attributes. */
|
|
33
|
+
readonly pk: KeyPart;
|
|
34
|
+
/** Sort key: physical field name + composite attributes. */
|
|
35
|
+
readonly sk: KeyPart;
|
|
36
|
+
}
|
|
37
|
+
/** Normalize a GsiConfig (entity input) to an IndexDefinition (internal format). */
|
|
38
|
+
export declare const normalizeGsiConfig: (config: GsiConfig) => IndexDefinition;
|
|
39
|
+
/**
|
|
40
|
+
* Extract composite attribute values from an entity record.
|
|
41
|
+
*
|
|
42
|
+
* Given composite: ["tenantId", "email"] and record: { tenantId: "t-1", email: "a@b.com" }
|
|
43
|
+
* Returns: ["t-1", "a@b.com"]
|
|
44
|
+
*/
|
|
45
|
+
export declare const extractComposites: (composite: ReadonlyArray<string>, record: Record<string, unknown>) => ReadonlyArray<string>;
|
|
46
|
+
/**
|
|
47
|
+
* Non-throwing variant of extractComposites. Returns undefined when any
|
|
48
|
+
* composite attribute is missing or null. Used for sparse GSI support —
|
|
49
|
+
* if a GSI's composites aren't all present, the index is simply skipped.
|
|
50
|
+
*/
|
|
51
|
+
export declare const tryExtractComposites: (composite: ReadonlyArray<string>, record: Record<string, unknown>) => ReadonlyArray<string> | undefined;
|
|
52
|
+
/**
|
|
53
|
+
* Serialize a value for use in a composite key.
|
|
54
|
+
*
|
|
55
|
+
* Numeric values are zero-padded for correct lexicographic sort order:
|
|
56
|
+
* - number → 16-digit zero-padded string (covers Number.MAX_SAFE_INTEGER)
|
|
57
|
+
* - bigint → 38-digit zero-padded string (covers DynamoDB's max precision)
|
|
58
|
+
*
|
|
59
|
+
* DateTime values are formatted as ISO strings for correct sort order:
|
|
60
|
+
* - DateTime.Zoned → ISO string with offset (preserves timezone info)
|
|
61
|
+
* - DateTime.Utc → ISO string
|
|
62
|
+
* - Date → ISO string
|
|
63
|
+
*/
|
|
64
|
+
export declare const serializeValue: (value: unknown) => string;
|
|
65
|
+
/**
|
|
66
|
+
* Compose a partition key for an entity index.
|
|
67
|
+
*
|
|
68
|
+
* For non-collection indexes: `$schema#v<version>#entityType#attr1#attr2`
|
|
69
|
+
* For collection indexes: `$schema#v<version>#collectionName#attr1#attr2`
|
|
70
|
+
*/
|
|
71
|
+
export declare const composePk: (schema: DynamoSchema.DynamoSchema, entityType: string, index: IndexDefinition, record: Record<string, unknown>) => string;
|
|
72
|
+
/**
|
|
73
|
+
* Compose a sort key for an entity index.
|
|
74
|
+
*
|
|
75
|
+
* For isolated indexes: `$schema#v<version>#entityType_version#attr1#attr2`
|
|
76
|
+
* For clustered indexes: `$schema#v<version>#collectionName#entityType_version#attr1#attr2`
|
|
77
|
+
* For non-collection indexes: `$schema#v<version>#entityType#attr1#attr2`
|
|
78
|
+
*/
|
|
79
|
+
export declare const composeSk: (schema: DynamoSchema.DynamoSchema, entityType: string, entityVersion: number, index: IndexDefinition, record: Record<string, unknown>) => string;
|
|
80
|
+
/**
|
|
81
|
+
* Compose all key attributes for a single index.
|
|
82
|
+
* Returns a record mapping field names to composed key values.
|
|
83
|
+
*/
|
|
84
|
+
export declare const composeIndexKeys: (schema: DynamoSchema.DynamoSchema, entityType: string, entityVersion: number, index: IndexDefinition, record: Record<string, unknown>) => Record<string, string>;
|
|
85
|
+
/**
|
|
86
|
+
* Non-throwing variant of composeIndexKeys. Returns undefined if any composite
|
|
87
|
+
* attribute is missing. Used for sparse GSI support.
|
|
88
|
+
*/
|
|
89
|
+
export declare const tryComposeIndexKeys: (schema: DynamoSchema.DynamoSchema, entityType: string, entityVersion: number, index: IndexDefinition, record: Record<string, unknown>) => Record<string, string> | undefined;
|
|
90
|
+
/**
|
|
91
|
+
* Compose keys for all indexes of an entity.
|
|
92
|
+
* Returns a flat record of all key field -> value mappings.
|
|
93
|
+
*/
|
|
94
|
+
export declare const composeAllKeys: (schema: DynamoSchema.DynamoSchema, entityType: string, entityVersion: number, indexes: Record<string, IndexDefinition>, record: Record<string, unknown>) => Record<string, string>;
|
|
95
|
+
/**
|
|
96
|
+
* Compose GSI keys for indexes whose composites appear in an update payload.
|
|
97
|
+
* For each non-primary index, checks if ANY of its composite attributes are in
|
|
98
|
+
* the update payload. If so, composes the full GSI keys using values merged from
|
|
99
|
+
* keyRecord (primary key composites) and updatePayload.
|
|
100
|
+
*
|
|
101
|
+
* Used by Entity.update to recompose GSI keys when the update touches GSI composites.
|
|
102
|
+
* Callers should filter out indexes whose composites are targeted by REMOVE operations
|
|
103
|
+
* before calling — otherwise `extractComposites` will throw on the missing values.
|
|
104
|
+
*/
|
|
105
|
+
export declare const composeGsiKeysForUpdate: (schema: DynamoSchema.DynamoSchema, entityType: string, entityVersion: number, indexes: Record<string, IndexDefinition>, updatePayload: Record<string, unknown>, keyRecord: Record<string, unknown>) => Record<string, string>;
|
|
106
|
+
/**
|
|
107
|
+
* Thrown when an update provides some but not all composite attributes for a GSI.
|
|
108
|
+
* Caught by Entity.update and converted to a tagged `ValidationError`.
|
|
109
|
+
*/
|
|
110
|
+
export declare class PartialGsiCompositeError extends Error {
|
|
111
|
+
readonly indexName: string;
|
|
112
|
+
readonly provided: ReadonlyArray<string>;
|
|
113
|
+
readonly missing: ReadonlyArray<string>;
|
|
114
|
+
readonly required: ReadonlyArray<string>;
|
|
115
|
+
constructor(indexName: string, provided: ReadonlyArray<string>, missing: ReadonlyArray<string>, required: ReadonlyArray<string>);
|
|
116
|
+
}
|
|
117
|
+
/**
|
|
118
|
+
* Compose a partial sort key prefix for query operations.
|
|
119
|
+
* Used when not all SK composite attributes are provided.
|
|
120
|
+
*
|
|
121
|
+
* For example, if SK composite is ["department", "hireDate"] and only "department"
|
|
122
|
+
* is provided, this generates a begins_with prefix.
|
|
123
|
+
*/
|
|
124
|
+
export declare const composeSortKeyPrefix: (schema: DynamoSchema.DynamoSchema, entityType: string, entityVersion: number, index: IndexDefinition, record: Record<string, unknown>) => string;
|
|
125
|
+
//# sourceMappingURL=KeyComposer.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"KeyComposer.d.ts","sourceRoot":"","sources":["../src/KeyComposer.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,257 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* KeyComposer — Composite key composition for DynamoDB keys.
|
|
3
|
+
*
|
|
4
|
+
* v2 uses attribute-list composition (composite: ["userId"]) instead of
|
|
5
|
+
* template strings ("USER#${userId}"). The DynamoSchema module handles
|
|
6
|
+
* the key format; KeyComposer extracts attribute values and delegates.
|
|
7
|
+
*/
|
|
8
|
+
import { DateTime } from "effect";
|
|
9
|
+
import { composeClusteredSortKey, composeCollectionKey, composeIsolatedSortKey, composeKey, } from "./DynamoSchema.js";
|
|
10
|
+
/** Normalize a GsiConfig (entity input) to an IndexDefinition (internal format). */
|
|
11
|
+
export const normalizeGsiConfig = (config) => {
|
|
12
|
+
// Detect old format and give helpful migration error
|
|
13
|
+
if ("index" in config && typeof config.index === "object") {
|
|
14
|
+
throw new Error(`[EDD-9003] GsiConfig uses old format with "index" property. ` +
|
|
15
|
+
`Migrate to: { name: "gsi1", pk: { field: "gsi1pk", composite: [...] }, sk: { field: "gsi1sk", composite: [...] } }`);
|
|
16
|
+
}
|
|
17
|
+
if (!config.name || !config.pk || !config.sk) {
|
|
18
|
+
throw new Error(`[EDD-9003] Invalid GsiConfig: requires name, pk: { field, composite }, sk: { field, composite }`);
|
|
19
|
+
}
|
|
20
|
+
return {
|
|
21
|
+
index: config.name,
|
|
22
|
+
collection: config.collection,
|
|
23
|
+
type: config.type ?? "isolated",
|
|
24
|
+
pk: { field: config.pk.field, composite: [...config.pk.composite] },
|
|
25
|
+
sk: { field: config.sk.field, composite: [...config.sk.composite] },
|
|
26
|
+
};
|
|
27
|
+
};
|
|
28
|
+
/**
|
|
29
|
+
* Extract composite attribute values from an entity record.
|
|
30
|
+
*
|
|
31
|
+
* Given composite: ["tenantId", "email"] and record: { tenantId: "t-1", email: "a@b.com" }
|
|
32
|
+
* Returns: ["t-1", "a@b.com"]
|
|
33
|
+
*/
|
|
34
|
+
export const extractComposites = (composite, record) => composite.map((attr) => {
|
|
35
|
+
const value = record[attr];
|
|
36
|
+
if (value === undefined || value === null) {
|
|
37
|
+
throw new Error(`Missing composite attribute "${attr}" in record`);
|
|
38
|
+
}
|
|
39
|
+
return serializeValue(value);
|
|
40
|
+
});
|
|
41
|
+
/**
|
|
42
|
+
* Non-throwing variant of extractComposites. Returns undefined when any
|
|
43
|
+
* composite attribute is missing or null. Used for sparse GSI support —
|
|
44
|
+
* if a GSI's composites aren't all present, the index is simply skipped.
|
|
45
|
+
*/
|
|
46
|
+
export const tryExtractComposites = (composite, record) => {
|
|
47
|
+
const values = [];
|
|
48
|
+
for (const attr of composite) {
|
|
49
|
+
const value = record[attr];
|
|
50
|
+
if (value === undefined || value === null)
|
|
51
|
+
return undefined;
|
|
52
|
+
values.push(serializeValue(value));
|
|
53
|
+
}
|
|
54
|
+
return values;
|
|
55
|
+
};
|
|
56
|
+
/**
|
|
57
|
+
* Serialize a value for use in a composite key.
|
|
58
|
+
*
|
|
59
|
+
* Numeric values are zero-padded for correct lexicographic sort order:
|
|
60
|
+
* - number → 16-digit zero-padded string (covers Number.MAX_SAFE_INTEGER)
|
|
61
|
+
* - bigint → 38-digit zero-padded string (covers DynamoDB's max precision)
|
|
62
|
+
*
|
|
63
|
+
* DateTime values are formatted as ISO strings for correct sort order:
|
|
64
|
+
* - DateTime.Zoned → ISO string with offset (preserves timezone info)
|
|
65
|
+
* - DateTime.Utc → ISO string
|
|
66
|
+
* - Date → ISO string
|
|
67
|
+
*/
|
|
68
|
+
export const serializeValue = (value) => {
|
|
69
|
+
if (typeof value === "string")
|
|
70
|
+
return value;
|
|
71
|
+
if (typeof value === "number")
|
|
72
|
+
return String(value).padStart(16, "0");
|
|
73
|
+
if (typeof value === "bigint")
|
|
74
|
+
return String(value).padStart(38, "0");
|
|
75
|
+
if (typeof value === "boolean")
|
|
76
|
+
return value ? "true" : "false";
|
|
77
|
+
// DateTime types → ISO string (Zoned normalized to UTC for sort order)
|
|
78
|
+
if (typeof value === "object" && value !== null && DateTime.isDateTime(value)) {
|
|
79
|
+
return DateTime.formatIso(value);
|
|
80
|
+
}
|
|
81
|
+
// Native Date
|
|
82
|
+
if (value instanceof Date)
|
|
83
|
+
return value.toISOString();
|
|
84
|
+
return String(value);
|
|
85
|
+
};
|
|
86
|
+
/**
|
|
87
|
+
* Compose a partition key for an entity index.
|
|
88
|
+
*
|
|
89
|
+
* For non-collection indexes: `$schema#v<version>#entityType#attr1#attr2`
|
|
90
|
+
* For collection indexes: `$schema#v<version>#collectionName#attr1#attr2`
|
|
91
|
+
*/
|
|
92
|
+
export const composePk = (schema, entityType, index, record) => {
|
|
93
|
+
const composites = extractComposites(index.pk.composite, record);
|
|
94
|
+
const names = [...index.pk.composite];
|
|
95
|
+
const collection = index.collection;
|
|
96
|
+
if (collection !== undefined) {
|
|
97
|
+
// Collection index — PK uses collection name
|
|
98
|
+
const collectionName = Array.isArray(collection) ? collection[0] : collection;
|
|
99
|
+
return composeCollectionKey(schema, collectionName, composites, { casing: index.casing, names });
|
|
100
|
+
}
|
|
101
|
+
// Regular entity index — PK uses entity type
|
|
102
|
+
return composeKey(schema, entityType, composites, { casing: index.casing, names });
|
|
103
|
+
};
|
|
104
|
+
/**
|
|
105
|
+
* Compose a sort key for an entity index.
|
|
106
|
+
*
|
|
107
|
+
* For isolated indexes: `$schema#v<version>#entityType_version#attr1#attr2`
|
|
108
|
+
* For clustered indexes: `$schema#v<version>#collectionName#entityType_version#attr1#attr2`
|
|
109
|
+
* For non-collection indexes: `$schema#v<version>#entityType#attr1#attr2`
|
|
110
|
+
*/
|
|
111
|
+
export const composeSk = (schema, entityType, entityVersion, index, record) => {
|
|
112
|
+
const composites = extractComposites(index.sk.composite, record);
|
|
113
|
+
const names = [...index.sk.composite];
|
|
114
|
+
const collection = index.collection;
|
|
115
|
+
const collectionType = index.type ?? "isolated";
|
|
116
|
+
if (collection !== undefined) {
|
|
117
|
+
if (collectionType === "clustered") {
|
|
118
|
+
// For sub-collections (collection: ["parent", "child"]) the FULL hierarchy
|
|
119
|
+
// is written into the SK so a begins_with query at any level matches.
|
|
120
|
+
return composeClusteredSortKey(schema, collection, entityType, entityVersion, composites, {
|
|
121
|
+
casing: index.casing,
|
|
122
|
+
names,
|
|
123
|
+
});
|
|
124
|
+
}
|
|
125
|
+
// Isolated
|
|
126
|
+
return composeIsolatedSortKey(schema, entityType, entityVersion, composites, {
|
|
127
|
+
casing: index.casing,
|
|
128
|
+
names,
|
|
129
|
+
});
|
|
130
|
+
}
|
|
131
|
+
// Non-collection — simple entity key
|
|
132
|
+
return composeKey(schema, entityType, composites, { casing: index.casing, names });
|
|
133
|
+
};
|
|
134
|
+
/**
|
|
135
|
+
* Compose all key attributes for a single index.
|
|
136
|
+
* Returns a record mapping field names to composed key values.
|
|
137
|
+
*/
|
|
138
|
+
export const composeIndexKeys = (schema, entityType, entityVersion, index, record) => ({
|
|
139
|
+
[index.pk.field]: composePk(schema, entityType, index, record),
|
|
140
|
+
[index.sk.field]: composeSk(schema, entityType, entityVersion, index, record),
|
|
141
|
+
});
|
|
142
|
+
/**
|
|
143
|
+
* Non-throwing variant of composeIndexKeys. Returns undefined if any composite
|
|
144
|
+
* attribute is missing. Used for sparse GSI support.
|
|
145
|
+
*/
|
|
146
|
+
export const tryComposeIndexKeys = (schema, entityType, entityVersion, index, record) => {
|
|
147
|
+
if (tryExtractComposites(index.pk.composite, record) === undefined)
|
|
148
|
+
return undefined;
|
|
149
|
+
if (tryExtractComposites(index.sk.composite, record) === undefined)
|
|
150
|
+
return undefined;
|
|
151
|
+
return composeIndexKeys(schema, entityType, entityVersion, index, record);
|
|
152
|
+
};
|
|
153
|
+
/**
|
|
154
|
+
* Compose keys for all indexes of an entity.
|
|
155
|
+
* Returns a flat record of all key field -> value mappings.
|
|
156
|
+
*/
|
|
157
|
+
export const composeAllKeys = (schema, entityType, entityVersion, indexes, record) => {
|
|
158
|
+
const result = {};
|
|
159
|
+
for (const [indexName, index] of Object.entries(indexes)) {
|
|
160
|
+
if (indexName === "primary") {
|
|
161
|
+
// Primary index always required — throws on missing composites
|
|
162
|
+
Object.assign(result, composeIndexKeys(schema, entityType, entityVersion, index, record));
|
|
163
|
+
}
|
|
164
|
+
else {
|
|
165
|
+
// GSI — sparse-aware: skip if any composite is missing
|
|
166
|
+
const keys = tryComposeIndexKeys(schema, entityType, entityVersion, index, record);
|
|
167
|
+
if (keys !== undefined)
|
|
168
|
+
Object.assign(result, keys);
|
|
169
|
+
}
|
|
170
|
+
}
|
|
171
|
+
return result;
|
|
172
|
+
};
|
|
173
|
+
/**
|
|
174
|
+
* Compose GSI keys for indexes whose composites appear in an update payload.
|
|
175
|
+
* For each non-primary index, checks if ANY of its composite attributes are in
|
|
176
|
+
* the update payload. If so, composes the full GSI keys using values merged from
|
|
177
|
+
* keyRecord (primary key composites) and updatePayload.
|
|
178
|
+
*
|
|
179
|
+
* Used by Entity.update to recompose GSI keys when the update touches GSI composites.
|
|
180
|
+
* Callers should filter out indexes whose composites are targeted by REMOVE operations
|
|
181
|
+
* before calling — otherwise `extractComposites` will throw on the missing values.
|
|
182
|
+
*/
|
|
183
|
+
export const composeGsiKeysForUpdate = (schema, entityType, entityVersion, indexes, updatePayload, keyRecord) => {
|
|
184
|
+
const result = {};
|
|
185
|
+
for (const [indexName, index] of Object.entries(indexes)) {
|
|
186
|
+
if (indexName === "primary")
|
|
187
|
+
continue;
|
|
188
|
+
const allComposites = [...index.pk.composite, ...index.sk.composite];
|
|
189
|
+
const touchedComposites = allComposites.filter((attr) => attr in updatePayload);
|
|
190
|
+
if (touchedComposites.length > 0) {
|
|
191
|
+
const merged = { ...keyRecord, ...updatePayload };
|
|
192
|
+
const missingComposites = allComposites.filter((attr) => merged[attr] === undefined || merged[attr] === null);
|
|
193
|
+
if (missingComposites.length > 0) {
|
|
194
|
+
throw new PartialGsiCompositeError(indexName, touchedComposites, missingComposites, allComposites);
|
|
195
|
+
}
|
|
196
|
+
Object.assign(result, composeIndexKeys(schema, entityType, entityVersion, index, merged));
|
|
197
|
+
}
|
|
198
|
+
}
|
|
199
|
+
return result;
|
|
200
|
+
};
|
|
201
|
+
/**
|
|
202
|
+
* Thrown when an update provides some but not all composite attributes for a GSI.
|
|
203
|
+
* Caught by Entity.update and converted to a tagged `ValidationError`.
|
|
204
|
+
*/
|
|
205
|
+
export class PartialGsiCompositeError extends Error {
|
|
206
|
+
indexName;
|
|
207
|
+
provided;
|
|
208
|
+
missing;
|
|
209
|
+
required;
|
|
210
|
+
constructor(indexName, provided, missing, required) {
|
|
211
|
+
super(`Partial GSI composite update on index "${indexName}": ` +
|
|
212
|
+
`provided [${provided.join(", ")}] but missing [${missing.join(", ")}]. ` +
|
|
213
|
+
`When updating any composite for a GSI, all composites must be provided: [${required.join(", ")}]`);
|
|
214
|
+
this.name = "PartialGsiCompositeError";
|
|
215
|
+
this.indexName = indexName;
|
|
216
|
+
this.provided = provided;
|
|
217
|
+
this.missing = missing;
|
|
218
|
+
this.required = required;
|
|
219
|
+
}
|
|
220
|
+
}
|
|
221
|
+
/**
|
|
222
|
+
* Compose a partial sort key prefix for query operations.
|
|
223
|
+
* Used when not all SK composite attributes are provided.
|
|
224
|
+
*
|
|
225
|
+
* For example, if SK composite is ["department", "hireDate"] and only "department"
|
|
226
|
+
* is provided, this generates a begins_with prefix.
|
|
227
|
+
*/
|
|
228
|
+
export const composeSortKeyPrefix = (schema, entityType, entityVersion, index, record) => {
|
|
229
|
+
// Collect available composites and their names (stop at first missing)
|
|
230
|
+
const available = [];
|
|
231
|
+
const names = [];
|
|
232
|
+
for (const attr of index.sk.composite) {
|
|
233
|
+
const value = record[attr];
|
|
234
|
+
if (value === undefined || value === null)
|
|
235
|
+
break;
|
|
236
|
+
available.push(serializeValue(value));
|
|
237
|
+
names.push(attr);
|
|
238
|
+
}
|
|
239
|
+
const collection = index.collection;
|
|
240
|
+
const collectionType = index.type ?? "isolated";
|
|
241
|
+
if (collection !== undefined) {
|
|
242
|
+
if (collectionType === "clustered") {
|
|
243
|
+
// For sub-collections, pass the full hierarchy so the SK prefix matches
|
|
244
|
+
// the same hierarchy written by composeSk during put.
|
|
245
|
+
return composeClusteredSortKey(schema, collection, entityType, entityVersion, available, {
|
|
246
|
+
casing: index.casing,
|
|
247
|
+
names,
|
|
248
|
+
});
|
|
249
|
+
}
|
|
250
|
+
return composeIsolatedSortKey(schema, entityType, entityVersion, available, {
|
|
251
|
+
casing: index.casing,
|
|
252
|
+
names,
|
|
253
|
+
});
|
|
254
|
+
}
|
|
255
|
+
return composeKey(schema, entityType, available, { casing: index.casing, names });
|
|
256
|
+
};
|
|
257
|
+
//# sourceMappingURL=KeyComposer.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"KeyComposer.js","sourceRoot":"","sources":["../src/KeyComposer.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Marshaller — Thin wrapper around @aws-sdk/util-dynamodb for converting
|
|
3
|
+
* between JS objects and DynamoDB attribute maps, plus date-aware serialization
|
|
4
|
+
* for DynamoEncoding-annotated fields.
|
|
5
|
+
*/
|
|
6
|
+
import type { AttributeValue } from "@aws-sdk/client-dynamodb";
|
|
7
|
+
import { DateTime } from "effect";
|
|
8
|
+
import type { DynamoEncoding } from "./DynamoModel.js";
|
|
9
|
+
/** Marshall a JS object to a DynamoDB attribute map */
|
|
10
|
+
export declare const toAttributeMap: (item: Record<string, unknown>) => Record<string, AttributeValue>;
|
|
11
|
+
/** Unmarshall a DynamoDB attribute map to a JS object */
|
|
12
|
+
export declare const fromAttributeMap: (item: Record<string, AttributeValue>) => Record<string, unknown>;
|
|
13
|
+
/** Marshall a single value to a DynamoDB attribute value */
|
|
14
|
+
export declare const toAttributeValue: (value: unknown) => AttributeValue;
|
|
15
|
+
/** Unmarshall a single DynamoDB attribute value */
|
|
16
|
+
export declare const fromAttributeValue: (value: AttributeValue) => unknown;
|
|
17
|
+
/**
|
|
18
|
+
* Convert a domain date value to the storage primitive based on DynamoEncoding.
|
|
19
|
+
*
|
|
20
|
+
* Domain types supported:
|
|
21
|
+
* - `DateTime.Utc` → ISO string, epoch ms, or epoch seconds
|
|
22
|
+
* - `DateTime.Zoned` → extended ISO string (only "string" storage)
|
|
23
|
+
* - `Date` → ISO string, epoch ms, or epoch seconds
|
|
24
|
+
*/
|
|
25
|
+
export declare const serializeDateForDynamo: (value: unknown, encoding: DynamoEncoding) => string | number;
|
|
26
|
+
/**
|
|
27
|
+
* Convert a DynamoDB storage primitive back to the domain value based on DynamoEncoding.
|
|
28
|
+
*/
|
|
29
|
+
export declare const deserializeDateFromDynamo: (stored: unknown, encoding: DynamoEncoding) => DateTime.Utc | DateTime.Zoned | Date;
|
|
30
|
+
//# sourceMappingURL=Marshaller.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Marshaller.d.ts","sourceRoot":"","sources":["../src/Marshaller.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,0BAA0B,CAAA;AAE9D,OAAO,EAAE,QAAQ,EAAE,MAAM,QAAQ,CAAA;AACjC,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,kBAAkB,CAAA;AAEtD,uDAAuD;AACvD,eAAO,MAAM,cAAc,GAAI,MAAM,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,KAAG,MAAM,CAAC,MAAM,EAAE,cAAc,CACV,CAAA;AAElF,yDAAyD;AACzD,eAAO,MAAM,gBAAgB,GAAI,MAAM,MAAM,CAAC,MAAM,EAAE,cAAc,CAAC,KAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAC5E,CAAA;AAElB,4DAA4D;AAC5D,eAAO,MAAM,gBAAgB,GAAI,OAAO,OAAO,KAAG,cAA2C,CAAA;AAE7F,mDAAmD;AACnD,eAAO,MAAM,kBAAkB,GAAI,OAAO,cAAc,KAAG,OAAqC,CAAA;AAMhG;;;;;;;GAOG;AACH,eAAO,MAAM,sBAAsB,GACjC,OAAO,OAAO,EACd,UAAU,cAAc,KACvB,MAAM,GAAG,MAyBX,CAAA;AAED;;GAEG;AACH,eAAO,MAAM,yBAAyB,GACpC,QAAQ,OAAO,EACf,UAAU,cAAc,KACvB,QAAQ,CAAC,GAAG,GAAG,QAAQ,CAAC,KAAK,GAAG,IAsElC,CAAA"}
|