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.
Files changed (171) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +69 -0
  3. package/dist/Aggregate.d.ts +210 -0
  4. package/dist/Aggregate.d.ts.map +1 -0
  5. package/dist/Aggregate.js +1169 -0
  6. package/dist/Aggregate.js.map +1 -0
  7. package/dist/Batch.d.ts +62 -0
  8. package/dist/Batch.d.ts.map +1 -0
  9. package/dist/Batch.js +218 -0
  10. package/dist/Batch.js.map +1 -0
  11. package/dist/Collection.d.ts +58 -0
  12. package/dist/Collection.d.ts.map +1 -0
  13. package/dist/Collection.js +195 -0
  14. package/dist/Collection.js.map +1 -0
  15. package/dist/Collections.d.ts +121 -0
  16. package/dist/Collections.d.ts.map +1 -0
  17. package/dist/Collections.js +121 -0
  18. package/dist/Collections.js.map +1 -0
  19. package/dist/DynamoClient.d.ts +317 -0
  20. package/dist/DynamoClient.d.ts.map +1 -0
  21. package/dist/DynamoClient.js +653 -0
  22. package/dist/DynamoClient.js.map +1 -0
  23. package/dist/DynamoModel.d.ts +278 -0
  24. package/dist/DynamoModel.d.ts.map +1 -0
  25. package/dist/DynamoModel.js +453 -0
  26. package/dist/DynamoModel.js.map +1 -0
  27. package/dist/DynamoSchema.d.ts +137 -0
  28. package/dist/DynamoSchema.d.ts.map +1 -0
  29. package/dist/DynamoSchema.js +188 -0
  30. package/dist/DynamoSchema.js.map +1 -0
  31. package/dist/Entity.d.ts +628 -0
  32. package/dist/Entity.d.ts.map +1 -0
  33. package/dist/Entity.js +2371 -0
  34. package/dist/Entity.js.map +1 -0
  35. package/dist/Errors.d.ts +227 -0
  36. package/dist/Errors.d.ts.map +1 -0
  37. package/dist/Errors.js +93 -0
  38. package/dist/Errors.js.map +1 -0
  39. package/dist/EventStore.d.ts +208 -0
  40. package/dist/EventStore.d.ts.map +1 -0
  41. package/dist/EventStore.js +333 -0
  42. package/dist/EventStore.js.map +1 -0
  43. package/dist/Expression.d.ts +50 -0
  44. package/dist/Expression.d.ts.map +1 -0
  45. package/dist/Expression.js +170 -0
  46. package/dist/Expression.js.map +1 -0
  47. package/dist/KeyComposer.d.ts +125 -0
  48. package/dist/KeyComposer.d.ts.map +1 -0
  49. package/dist/KeyComposer.js +257 -0
  50. package/dist/KeyComposer.js.map +1 -0
  51. package/dist/Marshaller.d.ts +30 -0
  52. package/dist/Marshaller.d.ts.map +1 -0
  53. package/dist/Marshaller.js +115 -0
  54. package/dist/Marshaller.js.map +1 -0
  55. package/dist/Projection.d.ts +28 -0
  56. package/dist/Projection.d.ts.map +1 -0
  57. package/dist/Projection.js +39 -0
  58. package/dist/Projection.js.map +1 -0
  59. package/dist/Query.d.ts +214 -0
  60. package/dist/Query.d.ts.map +1 -0
  61. package/dist/Query.js +397 -0
  62. package/dist/Query.js.map +1 -0
  63. package/dist/Table.d.ts +178 -0
  64. package/dist/Table.d.ts.map +1 -0
  65. package/dist/Table.js +211 -0
  66. package/dist/Table.js.map +1 -0
  67. package/dist/Transaction.d.ts +79 -0
  68. package/dist/Transaction.d.ts.map +1 -0
  69. package/dist/Transaction.js +215 -0
  70. package/dist/Transaction.js.map +1 -0
  71. package/dist/_AggregateCursor.d.ts +44 -0
  72. package/dist/_AggregateCursor.d.ts.map +1 -0
  73. package/dist/_AggregateCursor.js +18 -0
  74. package/dist/_AggregateCursor.js.map +1 -0
  75. package/dist/_AggregateEdges.d.ts +77 -0
  76. package/dist/_AggregateEdges.d.ts.map +1 -0
  77. package/dist/_AggregateEdges.js +41 -0
  78. package/dist/_AggregateEdges.js.map +1 -0
  79. package/dist/_AggregateSchemas.d.ts +69 -0
  80. package/dist/_AggregateSchemas.d.ts.map +1 -0
  81. package/dist/_AggregateSchemas.js +194 -0
  82. package/dist/_AggregateSchemas.js.map +1 -0
  83. package/dist/_AggregateTypes.d.ts +94 -0
  84. package/dist/_AggregateTypes.d.ts.map +1 -0
  85. package/dist/_AggregateTypes.js +7 -0
  86. package/dist/_AggregateTypes.js.map +1 -0
  87. package/dist/_EntityCombinators.d.ts +155 -0
  88. package/dist/_EntityCombinators.d.ts.map +1 -0
  89. package/dist/_EntityCombinators.js +158 -0
  90. package/dist/_EntityCombinators.js.map +1 -0
  91. package/dist/_EntityConfig.d.ts +100 -0
  92. package/dist/_EntityConfig.d.ts.map +1 -0
  93. package/dist/_EntityConfig.js +7 -0
  94. package/dist/_EntityConfig.js.map +1 -0
  95. package/dist/_EntityOps.d.ts +205 -0
  96. package/dist/_EntityOps.d.ts.map +1 -0
  97. package/dist/_EntityOps.js +137 -0
  98. package/dist/_EntityOps.js.map +1 -0
  99. package/dist/_EntitySchemas.d.ts +57 -0
  100. package/dist/_EntitySchemas.d.ts.map +1 -0
  101. package/dist/_EntitySchemas.js +298 -0
  102. package/dist/_EntitySchemas.js.map +1 -0
  103. package/dist/_EntityTypes.d.ts +81 -0
  104. package/dist/_EntityTypes.d.ts.map +1 -0
  105. package/dist/_EntityTypes.js +7 -0
  106. package/dist/_EntityTypes.js.map +1 -0
  107. package/dist/_sparse_check.d.ts +2 -0
  108. package/dist/_sparse_check.d.ts.map +1 -0
  109. package/dist/_sparse_check.js +193 -0
  110. package/dist/_sparse_check.js.map +1 -0
  111. package/dist/index.d.ts +35 -0
  112. package/dist/index.d.ts.map +1 -0
  113. package/dist/index.js +20 -0
  114. package/dist/index.js.map +1 -0
  115. package/dist/internal/AggregateCursor.d.ts +44 -0
  116. package/dist/internal/AggregateCursor.d.ts.map +1 -0
  117. package/dist/internal/AggregateCursor.js +18 -0
  118. package/dist/internal/AggregateCursor.js.map +1 -0
  119. package/dist/internal/AggregateEdges.d.ts +77 -0
  120. package/dist/internal/AggregateEdges.d.ts.map +1 -0
  121. package/dist/internal/AggregateEdges.js +41 -0
  122. package/dist/internal/AggregateEdges.js.map +1 -0
  123. package/dist/internal/AggregateSchemas.d.ts +69 -0
  124. package/dist/internal/AggregateSchemas.d.ts.map +1 -0
  125. package/dist/internal/AggregateSchemas.js +193 -0
  126. package/dist/internal/AggregateSchemas.js.map +1 -0
  127. package/dist/internal/AggregateTypes.d.ts +94 -0
  128. package/dist/internal/AggregateTypes.d.ts.map +1 -0
  129. package/dist/internal/AggregateTypes.js +7 -0
  130. package/dist/internal/AggregateTypes.js.map +1 -0
  131. package/dist/internal/BoundQuery.d.ts +107 -0
  132. package/dist/internal/BoundQuery.d.ts.map +1 -0
  133. package/dist/internal/BoundQuery.js +111 -0
  134. package/dist/internal/BoundQuery.js.map +1 -0
  135. package/dist/internal/EntityCombinators.d.ts +173 -0
  136. package/dist/internal/EntityCombinators.d.ts.map +1 -0
  137. package/dist/internal/EntityCombinators.js +183 -0
  138. package/dist/internal/EntityCombinators.js.map +1 -0
  139. package/dist/internal/EntityConfig.d.ts +100 -0
  140. package/dist/internal/EntityConfig.d.ts.map +1 -0
  141. package/dist/internal/EntityConfig.js +7 -0
  142. package/dist/internal/EntityConfig.js.map +1 -0
  143. package/dist/internal/EntityOps.d.ts +268 -0
  144. package/dist/internal/EntityOps.d.ts.map +1 -0
  145. package/dist/internal/EntityOps.js +153 -0
  146. package/dist/internal/EntityOps.js.map +1 -0
  147. package/dist/internal/EntitySchemas.d.ts +57 -0
  148. package/dist/internal/EntitySchemas.d.ts.map +1 -0
  149. package/dist/internal/EntitySchemas.js +299 -0
  150. package/dist/internal/EntitySchemas.js.map +1 -0
  151. package/dist/internal/EntityTypes.d.ts +128 -0
  152. package/dist/internal/EntityTypes.d.ts.map +1 -0
  153. package/dist/internal/EntityTypes.js +7 -0
  154. package/dist/internal/EntityTypes.js.map +1 -0
  155. package/dist/internal/Expr.d.ts +141 -0
  156. package/dist/internal/Expr.d.ts.map +1 -0
  157. package/dist/internal/Expr.js +332 -0
  158. package/dist/internal/Expr.js.map +1 -0
  159. package/dist/internal/PathBuilder.d.ts +88 -0
  160. package/dist/internal/PathBuilder.d.ts.map +1 -0
  161. package/dist/internal/PathBuilder.js +100 -0
  162. package/dist/internal/PathBuilder.js.map +1 -0
  163. package/dist/internal/TransactableOps.d.ts +25 -0
  164. package/dist/internal/TransactableOps.d.ts.map +1 -0
  165. package/dist/internal/TransactableOps.js +58 -0
  166. package/dist/internal/TransactableOps.js.map +1 -0
  167. package/dist/internal/sparse_check.d.ts +2 -0
  168. package/dist/internal/sparse_check.d.ts.map +1 -0
  169. package/dist/internal/sparse_check.js +196 -0
  170. package/dist/internal/sparse_check.js.map +1 -0
  171. 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"}