dynamodb-expression-builder 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 +91 -0
- package/dist/index.cjs +1908 -0
- package/dist/index.d.cts +639 -0
- package/dist/index.d.ts +639 -0
- package/dist/index.js +1871 -0
- package/package.json +75 -0
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,639 @@
|
|
|
1
|
+
//#region src/operators.d.ts
|
|
2
|
+
/**
|
|
3
|
+
* Wire-format (uppercase) operator union. INLINED copy of the app's
|
|
4
|
+
* `WireFilterOperator` (`src/schemas/dynamodb-schemas.ts`).
|
|
5
|
+
*/
|
|
6
|
+
type WireFilterOperator = 'EQ' | 'NE' | 'GT' | 'GE' | 'LT' | 'LE' | 'CONTAINS' | 'BEGINS_WITH' | 'BETWEEN' | 'IN' | 'EXISTS' | 'NOT_EXISTS' | 'SIZE_EQ' | 'SIZE_NE' | 'SIZE_LT' | 'SIZE_LE' | 'SIZE_GT' | 'SIZE_GE' | 'TYPE_EQ' | 'TYPE_NE';
|
|
7
|
+
/**
|
|
8
|
+
* Data types the compat map reasons about. `L`/`M` are included even though the
|
|
9
|
+
* tool's Type selector doesn't expose them — they keep the compat table a
|
|
10
|
+
* faithful port of the app's (where indexed columns can report List/Map).
|
|
11
|
+
*/
|
|
12
|
+
type FilterDataType = 'S' | 'N' | 'B' | 'SS' | 'NS' | 'BS' | 'BOOL' | 'NULL' | 'L' | 'M';
|
|
13
|
+
/**
|
|
14
|
+
* Single source-of-truth row for an operator. One row per operator; consumers
|
|
15
|
+
* read the metadata they need (wire form, value-shape gates, key/scan type
|
|
16
|
+
* compatibility).
|
|
17
|
+
*/
|
|
18
|
+
type OperatorDef = {
|
|
19
|
+
readonly value: string;
|
|
20
|
+
readonly label: string;
|
|
21
|
+
readonly symbol: string;
|
|
22
|
+
readonly wireForm: WireFilterOperator;
|
|
23
|
+
/** false → no RHS value (`exists`, `not_exists`). */
|
|
24
|
+
readonly requiresValue: boolean;
|
|
25
|
+
/** true → needs a second RHS value (`between` only). */
|
|
26
|
+
readonly requiresValue2: boolean;
|
|
27
|
+
/** true → type field is optional / defaults to `S` (`exists`, `size_*`). */
|
|
28
|
+
readonly typeOptional: boolean;
|
|
29
|
+
/** Key-eligible types. `[]` → scan-only, rejected by KeyConditionExpression. */
|
|
30
|
+
readonly keyAllowedTypes: ReadonlyArray<'S' | 'N' | 'B'>;
|
|
31
|
+
/** Scan-eligible types. Non-empty. */
|
|
32
|
+
readonly scanAllowedTypes: readonly FilterDataType[];
|
|
33
|
+
};
|
|
34
|
+
declare const FILTER_OPERATORS: readonly [{
|
|
35
|
+
readonly value: "=";
|
|
36
|
+
readonly label: "Equals (=)";
|
|
37
|
+
readonly symbol: "=";
|
|
38
|
+
readonly wireForm: "EQ";
|
|
39
|
+
readonly requiresValue: true;
|
|
40
|
+
readonly requiresValue2: false;
|
|
41
|
+
readonly typeOptional: false;
|
|
42
|
+
readonly keyAllowedTypes: readonly ["S", "N", "B"];
|
|
43
|
+
readonly scanAllowedTypes: readonly ["S", "N", "B", "SS", "NS", "BS", "BOOL", "NULL", "L", "M"];
|
|
44
|
+
}, {
|
|
45
|
+
readonly value: "<>";
|
|
46
|
+
readonly label: "Not Equals (≠)";
|
|
47
|
+
readonly symbol: "≠";
|
|
48
|
+
readonly wireForm: "NE";
|
|
49
|
+
readonly requiresValue: true;
|
|
50
|
+
readonly requiresValue2: false;
|
|
51
|
+
readonly typeOptional: false;
|
|
52
|
+
readonly keyAllowedTypes: readonly [];
|
|
53
|
+
readonly scanAllowedTypes: readonly ["S", "N", "B", "SS", "NS", "BS", "BOOL", "NULL", "L", "M"];
|
|
54
|
+
}, {
|
|
55
|
+
readonly value: "<";
|
|
56
|
+
readonly label: "Less Than (<)";
|
|
57
|
+
readonly symbol: "<";
|
|
58
|
+
readonly wireForm: "LT";
|
|
59
|
+
readonly requiresValue: true;
|
|
60
|
+
readonly requiresValue2: false;
|
|
61
|
+
readonly typeOptional: false;
|
|
62
|
+
readonly keyAllowedTypes: readonly ["N"];
|
|
63
|
+
readonly scanAllowedTypes: readonly ["N"];
|
|
64
|
+
}, {
|
|
65
|
+
readonly value: "<=";
|
|
66
|
+
readonly label: "Less Than or Equal (≤)";
|
|
67
|
+
readonly symbol: "≤";
|
|
68
|
+
readonly wireForm: "LE";
|
|
69
|
+
readonly requiresValue: true;
|
|
70
|
+
readonly requiresValue2: false;
|
|
71
|
+
readonly typeOptional: false;
|
|
72
|
+
readonly keyAllowedTypes: readonly ["N"];
|
|
73
|
+
readonly scanAllowedTypes: readonly ["N"];
|
|
74
|
+
}, {
|
|
75
|
+
readonly value: ">";
|
|
76
|
+
readonly label: "Greater Than (>)";
|
|
77
|
+
readonly symbol: ">";
|
|
78
|
+
readonly wireForm: "GT";
|
|
79
|
+
readonly requiresValue: true;
|
|
80
|
+
readonly requiresValue2: false;
|
|
81
|
+
readonly typeOptional: false;
|
|
82
|
+
readonly keyAllowedTypes: readonly ["N"];
|
|
83
|
+
readonly scanAllowedTypes: readonly ["N"];
|
|
84
|
+
}, {
|
|
85
|
+
readonly value: ">=";
|
|
86
|
+
readonly label: "Greater Than or Equal (≥)";
|
|
87
|
+
readonly symbol: "≥";
|
|
88
|
+
readonly wireForm: "GE";
|
|
89
|
+
readonly requiresValue: true;
|
|
90
|
+
readonly requiresValue2: false;
|
|
91
|
+
readonly typeOptional: false;
|
|
92
|
+
readonly keyAllowedTypes: readonly ["N"];
|
|
93
|
+
readonly scanAllowedTypes: readonly ["N"];
|
|
94
|
+
}, {
|
|
95
|
+
readonly value: "contains";
|
|
96
|
+
readonly label: "Contains";
|
|
97
|
+
readonly symbol: "∋";
|
|
98
|
+
readonly wireForm: "CONTAINS";
|
|
99
|
+
readonly requiresValue: true;
|
|
100
|
+
readonly requiresValue2: false;
|
|
101
|
+
readonly typeOptional: false;
|
|
102
|
+
readonly keyAllowedTypes: readonly [];
|
|
103
|
+
readonly scanAllowedTypes: readonly ["S", "B", "SS", "NS", "BS", "L"];
|
|
104
|
+
}, {
|
|
105
|
+
readonly value: "begins_with";
|
|
106
|
+
readonly label: "Begins With";
|
|
107
|
+
readonly symbol: "^";
|
|
108
|
+
readonly wireForm: "BEGINS_WITH";
|
|
109
|
+
readonly requiresValue: true;
|
|
110
|
+
readonly requiresValue2: false;
|
|
111
|
+
readonly typeOptional: false;
|
|
112
|
+
readonly keyAllowedTypes: readonly ["S", "B"];
|
|
113
|
+
readonly scanAllowedTypes: readonly ["S", "B"];
|
|
114
|
+
}, {
|
|
115
|
+
readonly value: "between";
|
|
116
|
+
readonly label: "Between";
|
|
117
|
+
readonly symbol: "↔";
|
|
118
|
+
readonly wireForm: "BETWEEN";
|
|
119
|
+
readonly requiresValue: true;
|
|
120
|
+
readonly requiresValue2: true;
|
|
121
|
+
readonly typeOptional: false;
|
|
122
|
+
readonly keyAllowedTypes: readonly ["N"];
|
|
123
|
+
readonly scanAllowedTypes: readonly ["N"];
|
|
124
|
+
}, {
|
|
125
|
+
readonly value: "in";
|
|
126
|
+
readonly label: "In";
|
|
127
|
+
readonly symbol: "∈";
|
|
128
|
+
readonly wireForm: "IN";
|
|
129
|
+
readonly requiresValue: true;
|
|
130
|
+
readonly requiresValue2: false;
|
|
131
|
+
readonly typeOptional: false;
|
|
132
|
+
readonly keyAllowedTypes: readonly [];
|
|
133
|
+
readonly scanAllowedTypes: readonly ["S", "N"];
|
|
134
|
+
}, {
|
|
135
|
+
readonly value: "exists";
|
|
136
|
+
readonly label: "Attribute Exists";
|
|
137
|
+
readonly symbol: "∃";
|
|
138
|
+
readonly wireForm: "EXISTS";
|
|
139
|
+
readonly requiresValue: false;
|
|
140
|
+
readonly requiresValue2: false;
|
|
141
|
+
readonly typeOptional: true;
|
|
142
|
+
readonly keyAllowedTypes: readonly [];
|
|
143
|
+
readonly scanAllowedTypes: readonly ["S", "N", "B", "SS", "NS", "BS", "BOOL", "NULL", "L", "M"];
|
|
144
|
+
}, {
|
|
145
|
+
readonly value: "not_exists";
|
|
146
|
+
readonly label: "Attribute Not Exists";
|
|
147
|
+
readonly symbol: "∄";
|
|
148
|
+
readonly wireForm: "NOT_EXISTS";
|
|
149
|
+
readonly requiresValue: false;
|
|
150
|
+
readonly requiresValue2: false;
|
|
151
|
+
readonly typeOptional: true;
|
|
152
|
+
readonly keyAllowedTypes: readonly [];
|
|
153
|
+
readonly scanAllowedTypes: readonly ["S", "N", "B", "SS", "NS", "BS", "BOOL", "NULL", "L", "M"];
|
|
154
|
+
}, {
|
|
155
|
+
readonly value: "size_eq";
|
|
156
|
+
readonly label: "Size Equals";
|
|
157
|
+
readonly symbol: "size =";
|
|
158
|
+
readonly wireForm: "SIZE_EQ";
|
|
159
|
+
readonly requiresValue: true;
|
|
160
|
+
readonly requiresValue2: false;
|
|
161
|
+
readonly typeOptional: true;
|
|
162
|
+
readonly keyAllowedTypes: readonly [];
|
|
163
|
+
readonly scanAllowedTypes: readonly ["SS", "NS", "BS", "L", "M"];
|
|
164
|
+
}, {
|
|
165
|
+
readonly value: "size_ne";
|
|
166
|
+
readonly label: "Size Not Equals";
|
|
167
|
+
readonly symbol: "size ≠";
|
|
168
|
+
readonly wireForm: "SIZE_NE";
|
|
169
|
+
readonly requiresValue: true;
|
|
170
|
+
readonly requiresValue2: false;
|
|
171
|
+
readonly typeOptional: true;
|
|
172
|
+
readonly keyAllowedTypes: readonly [];
|
|
173
|
+
readonly scanAllowedTypes: readonly ["SS", "NS", "BS", "L", "M"];
|
|
174
|
+
}, {
|
|
175
|
+
readonly value: "size_lt";
|
|
176
|
+
readonly label: "Size Less Than";
|
|
177
|
+
readonly symbol: "size <";
|
|
178
|
+
readonly wireForm: "SIZE_LT";
|
|
179
|
+
readonly requiresValue: true;
|
|
180
|
+
readonly requiresValue2: false;
|
|
181
|
+
readonly typeOptional: true;
|
|
182
|
+
readonly keyAllowedTypes: readonly [];
|
|
183
|
+
readonly scanAllowedTypes: readonly ["SS", "NS", "BS", "L", "M"];
|
|
184
|
+
}, {
|
|
185
|
+
readonly value: "size_le";
|
|
186
|
+
readonly label: "Size Less Than or Equal";
|
|
187
|
+
readonly symbol: "size ≤";
|
|
188
|
+
readonly wireForm: "SIZE_LE";
|
|
189
|
+
readonly requiresValue: true;
|
|
190
|
+
readonly requiresValue2: false;
|
|
191
|
+
readonly typeOptional: true;
|
|
192
|
+
readonly keyAllowedTypes: readonly [];
|
|
193
|
+
readonly scanAllowedTypes: readonly ["SS", "NS", "BS", "L", "M"];
|
|
194
|
+
}, {
|
|
195
|
+
readonly value: "size_gt";
|
|
196
|
+
readonly label: "Size Greater Than";
|
|
197
|
+
readonly symbol: "size >";
|
|
198
|
+
readonly wireForm: "SIZE_GT";
|
|
199
|
+
readonly requiresValue: true;
|
|
200
|
+
readonly requiresValue2: false;
|
|
201
|
+
readonly typeOptional: true;
|
|
202
|
+
readonly keyAllowedTypes: readonly [];
|
|
203
|
+
readonly scanAllowedTypes: readonly ["SS", "NS", "BS", "L", "M"];
|
|
204
|
+
}, {
|
|
205
|
+
readonly value: "size_ge";
|
|
206
|
+
readonly label: "Size Greater Than or Equal";
|
|
207
|
+
readonly symbol: "size ≥";
|
|
208
|
+
readonly wireForm: "SIZE_GE";
|
|
209
|
+
readonly requiresValue: true;
|
|
210
|
+
readonly requiresValue2: false;
|
|
211
|
+
readonly typeOptional: true;
|
|
212
|
+
readonly keyAllowedTypes: readonly [];
|
|
213
|
+
readonly scanAllowedTypes: readonly ["SS", "NS", "BS", "L", "M"];
|
|
214
|
+
}, {
|
|
215
|
+
readonly value: "type_eq";
|
|
216
|
+
readonly label: "Type Equals";
|
|
217
|
+
readonly symbol: "type =";
|
|
218
|
+
readonly wireForm: "TYPE_EQ";
|
|
219
|
+
readonly requiresValue: true;
|
|
220
|
+
readonly requiresValue2: false;
|
|
221
|
+
readonly typeOptional: false;
|
|
222
|
+
readonly keyAllowedTypes: readonly [];
|
|
223
|
+
readonly scanAllowedTypes: readonly ["S", "N", "B", "SS", "NS", "BS", "BOOL", "NULL", "L", "M"];
|
|
224
|
+
}, {
|
|
225
|
+
readonly value: "type_ne";
|
|
226
|
+
readonly label: "Type Not Equals";
|
|
227
|
+
readonly symbol: "type ≠";
|
|
228
|
+
readonly wireForm: "TYPE_NE";
|
|
229
|
+
readonly requiresValue: true;
|
|
230
|
+
readonly requiresValue2: false;
|
|
231
|
+
readonly typeOptional: false;
|
|
232
|
+
readonly keyAllowedTypes: readonly [];
|
|
233
|
+
readonly scanAllowedTypes: readonly ["S", "N", "B", "SS", "NS", "BS", "BOOL", "NULL", "L", "M"];
|
|
234
|
+
}];
|
|
235
|
+
/** Tightened union of every operator's lowercase internal value. */
|
|
236
|
+
type OperatorValue = (typeof FILTER_OPERATORS)[number]['value'];
|
|
237
|
+
/**
|
|
238
|
+
* O(1) registry lookup. Loose-keyed (`Record<string, OperatorDef>`) so boundary
|
|
239
|
+
* callers must guard `if (!def)` — the runtime value is `undefined` for unknown
|
|
240
|
+
* keys.
|
|
241
|
+
*/
|
|
242
|
+
declare const OPERATOR_BY_VALUE: Readonly<Record<string, OperatorDef>>;
|
|
243
|
+
/** Key-eligible operators (KeyConditionExpression compatible). */
|
|
244
|
+
declare const KEY_OPERATORS: readonly OperatorDef[];
|
|
245
|
+
type FilterOperatorOption = (typeof FILTER_OPERATORS)[number];
|
|
246
|
+
/**
|
|
247
|
+
* Operators applicable to a scan value of the given type. Undefined type → full
|
|
248
|
+
* list. Filters/conditions use this.
|
|
249
|
+
*/
|
|
250
|
+
declare function getCompatibleFilterOperators(type: FilterDataType | undefined): readonly FilterOperatorOption[];
|
|
251
|
+
/**
|
|
252
|
+
* Key-eligible operators compatible with the given key type. Undefined → full
|
|
253
|
+
* key list. Range-key UI uses this (type-gated: N gets `<`/`between`, S/B get
|
|
254
|
+
* `begins_with`, all keys get `=`).
|
|
255
|
+
*/
|
|
256
|
+
declare function getCompatibleComparisonOperators(type: 'S' | 'N' | 'B' | undefined): readonly OperatorDef[];
|
|
257
|
+
//#endregion
|
|
258
|
+
//#region src/types.d.ts
|
|
259
|
+
/**
|
|
260
|
+
* Value type tags the tool exposes. Mirrors the app's filter Type selector
|
|
261
|
+
* minus `L`/`M` (no nested List/Map in v1 — see docs/plans/…expression-builder).
|
|
262
|
+
*/
|
|
263
|
+
type DdbScalarType = 'S' | 'N' | 'B' | 'BOOL' | 'SS' | 'NS' | 'BS' | 'NULL';
|
|
264
|
+
/** The set-typed tags, which carry members in `values` rather than `value`. */
|
|
265
|
+
declare const SET_TYPES: readonly ["SS", "NS", "BS"];
|
|
266
|
+
type SetType = (typeof SET_TYPES)[number];
|
|
267
|
+
declare function isSetType(type: DdbScalarType): type is SetType;
|
|
268
|
+
/**
|
|
269
|
+
* The scalar element type of a set tag (SS→S, NS→N, BS→B); identity for every
|
|
270
|
+
* scalar. `contains(path, operand)` takes a SCALAR operand even when `path` is a
|
|
271
|
+
* set (it tests membership), so the set-typed tag must marshal its ELEMENT type
|
|
272
|
+
* there — never `{SS:[…]}`, which DynamoDB rejects.
|
|
273
|
+
*/
|
|
274
|
+
declare function elementType(type: DdbScalarType): DdbScalarType;
|
|
275
|
+
/**
|
|
276
|
+
* A value carried with its DynamoDB type tag. `value` holds the scalar string
|
|
277
|
+
* representation (S text; N numeric string; B base64; BOOL `'true'`/`'false'`;
|
|
278
|
+
* NULL unused). `values` holds the members of a set type (SS/NS/BS). Exactly
|
|
279
|
+
* one is meaningful per `type`; emitters branch on the tag, not the runtime.
|
|
280
|
+
*/
|
|
281
|
+
interface TypedValue {
|
|
282
|
+
type: DdbScalarType;
|
|
283
|
+
value: string;
|
|
284
|
+
/** Members for set types (SS/NS/BS). Undefined for scalars. */
|
|
285
|
+
values?: string[];
|
|
286
|
+
}
|
|
287
|
+
/**
|
|
288
|
+
* Build a {@link TypedValue} from a tag + raw entry. Set types take an explicit
|
|
289
|
+
* member array (falling back to the single `value` as one member); scalars take
|
|
290
|
+
* the string; NULL ignores the payload.
|
|
291
|
+
*/
|
|
292
|
+
declare function makeTypedValue(type: DdbScalarType, value: string, values?: string[]): TypedValue;
|
|
293
|
+
/**
|
|
294
|
+
* A filter (Scan/Query) or condition (Update/Put/Delete) predicate row, as the
|
|
295
|
+
* bespoke UI emits it. `operator` is the lowercase internal value from
|
|
296
|
+
* `operators.ts` (`'='`, `'begins_with'`, …); the builder maps it to its wire
|
|
297
|
+
* form before compiling. `type` tags the RHS value(s).
|
|
298
|
+
*/
|
|
299
|
+
interface FilterRow {
|
|
300
|
+
field: string;
|
|
301
|
+
operator: OperatorValue;
|
|
302
|
+
type: DdbScalarType;
|
|
303
|
+
/** RHS scalar (unused for `exists`/`not_exists`; first bound for `between`). */
|
|
304
|
+
value: string;
|
|
305
|
+
/** Second bound for `between`. */
|
|
306
|
+
value2?: string;
|
|
307
|
+
/** Members for `in` (and set-typed single comparisons). */
|
|
308
|
+
values?: string[];
|
|
309
|
+
}
|
|
310
|
+
/** A primary-key attribute (GetItem/Delete Key map; Query hash key). */
|
|
311
|
+
interface KeyAttr {
|
|
312
|
+
field: string;
|
|
313
|
+
/** Keys are always scalar S/N/B, but typed as the full union for reuse. */
|
|
314
|
+
type: DdbScalarType;
|
|
315
|
+
value: string;
|
|
316
|
+
}
|
|
317
|
+
/** Query range-key condition (a key-eligible operator + value[s]). */
|
|
318
|
+
interface RangeKeyCondition {
|
|
319
|
+
field: string;
|
|
320
|
+
type: DdbScalarType;
|
|
321
|
+
operator: OperatorValue;
|
|
322
|
+
value: string;
|
|
323
|
+
/** Second bound for `between`. */
|
|
324
|
+
value2?: string;
|
|
325
|
+
}
|
|
326
|
+
/** A Put item attribute carrying its type tag. */
|
|
327
|
+
interface ItemAttr {
|
|
328
|
+
field: string;
|
|
329
|
+
type: DdbScalarType;
|
|
330
|
+
value: string;
|
|
331
|
+
/** Members for set types. */
|
|
332
|
+
values?: string[];
|
|
333
|
+
}
|
|
334
|
+
/** SET-clause idioms (the only action kind with sub-modes). */
|
|
335
|
+
type SetOperation = 'assign' | 'if_not_exists' | 'add' | 'subtract' | 'list_append' | 'list_prepend';
|
|
336
|
+
type UpdateActionKind = 'SET' | 'REMOVE' | 'ADD' | 'DELETE';
|
|
337
|
+
/**
|
|
338
|
+
* A single UpdateExpression action. `SET` carries a `setOp` idiom; `REMOVE`
|
|
339
|
+
* targets an attribute (optionally a list element via `index`); `ADD`/`DELETE`
|
|
340
|
+
* carry a number (ADD) or set (ADD/DELETE) value.
|
|
341
|
+
*/
|
|
342
|
+
interface UpdateAction {
|
|
343
|
+
kind: UpdateActionKind;
|
|
344
|
+
field: string;
|
|
345
|
+
/** SET only: which SET idiom. */
|
|
346
|
+
setOp?: SetOperation;
|
|
347
|
+
/** RHS value (SET except plain index removal; ADD; DELETE). */
|
|
348
|
+
value?: TypedValue;
|
|
349
|
+
/** List-element index for REMOVE (`#a[2]`). */
|
|
350
|
+
index?: number;
|
|
351
|
+
}
|
|
352
|
+
/** The six operations the builder supports. */
|
|
353
|
+
type DdbOperation = 'GetItem' | 'Query' | 'Scan' | 'Update' | 'Put' | 'Delete';
|
|
354
|
+
/**
|
|
355
|
+
* The whole builder state — one config covering every operation. Sub-parts are
|
|
356
|
+
* optional; `buildRequest` reads only the ones an operation uses (GetItem→key;
|
|
357
|
+
* Query→hashKey[+rangeKey][+filters]; Scan→filters; Update→key+updates[+conditions];
|
|
358
|
+
* Put→item[+conditions]; Delete→key[+conditions]). Serialised whole into the
|
|
359
|
+
* single `state` URL param.
|
|
360
|
+
*/
|
|
361
|
+
interface BuilderConfig {
|
|
362
|
+
operation: DdbOperation;
|
|
363
|
+
tableName: string;
|
|
364
|
+
indexName?: string;
|
|
365
|
+
/**
|
|
366
|
+
* Base-table PK/SK NAMES + TYPES only (never values). Lets a Scan or GSI-query
|
|
367
|
+
* emitter scaffold the table's REAL key schema instead of a `// TODO`
|
|
368
|
+
* placeholder — the request's own key belongs to the GSI (or is absent for a
|
|
369
|
+
* Scan), so the base schema must ride along separately. Absent when the base
|
|
370
|
+
* schema isn't known (the stateless expression tool, or table info not yet
|
|
371
|
+
* loaded); emitters fall back to the placeholder then.
|
|
372
|
+
*/
|
|
373
|
+
baseKeySchema?: {
|
|
374
|
+
hashKey: {
|
|
375
|
+
field: string;
|
|
376
|
+
type: DdbScalarType;
|
|
377
|
+
};
|
|
378
|
+
rangeKey?: {
|
|
379
|
+
field: string;
|
|
380
|
+
type: DdbScalarType;
|
|
381
|
+
};
|
|
382
|
+
};
|
|
383
|
+
/** Query hash key (EQ). */
|
|
384
|
+
hashKey?: KeyAttr;
|
|
385
|
+
/** Query range key condition. */
|
|
386
|
+
rangeKey?: RangeKeyCondition;
|
|
387
|
+
/** GetItem/Update/Delete exact primary key attrs (hash[+range]). */
|
|
388
|
+
key?: KeyAttr[];
|
|
389
|
+
/** Scan/Query filter predicates. */
|
|
390
|
+
filters?: FilterRow[];
|
|
391
|
+
/** Update/Put/Delete write conditions. */
|
|
392
|
+
conditions?: FilterRow[];
|
|
393
|
+
/** Update actions. */
|
|
394
|
+
updates?: UpdateAction[];
|
|
395
|
+
/** Put item attributes. */
|
|
396
|
+
item?: ItemAttr[];
|
|
397
|
+
/** GetItem/Query/Scan projected attribute names. */
|
|
398
|
+
projection?: string[];
|
|
399
|
+
/** Query/Scan `Limit` — max items EVALUATED per request (positive integer). */
|
|
400
|
+
limit?: number;
|
|
401
|
+
/**
|
|
402
|
+
* Query sort order. Only `false` (descending) is carried through — `true` is
|
|
403
|
+
* the DynamoDB default, and emitting it would just be noise in the snippet.
|
|
404
|
+
*/
|
|
405
|
+
scanIndexForward?: boolean;
|
|
406
|
+
/** GetItem/Query/Scan strongly-consistent read (only `true` is carried). */
|
|
407
|
+
consistentRead?: boolean;
|
|
408
|
+
/**
|
|
409
|
+
* Query/Scan resume point — the `LastEvaluatedKey` of a previous page, as
|
|
410
|
+
* typed key attrs (hash[+range]). Compiled into `ExclusiveStartKey`.
|
|
411
|
+
*/
|
|
412
|
+
exclusiveStartKey?: KeyAttr[];
|
|
413
|
+
}
|
|
414
|
+
/**
|
|
415
|
+
* The canonical, fully-resolved request every emitter formats. Expression
|
|
416
|
+
* strings reference `#`/`:` placeholders resolved by `names`/`typedValues`;
|
|
417
|
+
* empty maps are omitted. `key`/`item` are direct name→value maps (no
|
|
418
|
+
* placeholders). `config` is the raw model retained for PartiQL, which builds
|
|
419
|
+
* literals rather than placeholders.
|
|
420
|
+
*/
|
|
421
|
+
interface CanonicalRequest {
|
|
422
|
+
operation: DdbOperation;
|
|
423
|
+
tableName: string;
|
|
424
|
+
indexName?: string;
|
|
425
|
+
key?: Record<string, TypedValue>;
|
|
426
|
+
item?: Record<string, TypedValue>;
|
|
427
|
+
keyConditionExpression?: string;
|
|
428
|
+
filterExpression?: string;
|
|
429
|
+
updateExpression?: string;
|
|
430
|
+
conditionExpression?: string;
|
|
431
|
+
projectionExpression?: string;
|
|
432
|
+
names?: Record<string, string>;
|
|
433
|
+
typedValues?: Record<string, TypedValue>;
|
|
434
|
+
/** Query/Scan `Limit` (positive integer; present only when set). */
|
|
435
|
+
limit?: number;
|
|
436
|
+
/** Present ONLY as `false` (descending Query) — the default `true` is omitted. */
|
|
437
|
+
scanIndexForward?: boolean;
|
|
438
|
+
/** Present ONLY as `true` (strongly-consistent read). */
|
|
439
|
+
consistentRead?: boolean;
|
|
440
|
+
/** Query/Scan resume point (typed name→value map, like `key`). */
|
|
441
|
+
exclusiveStartKey?: Record<string, TypedValue>;
|
|
442
|
+
config: BuilderConfig;
|
|
443
|
+
}
|
|
444
|
+
//#endregion
|
|
445
|
+
//#region src/filter-expressions.d.ts
|
|
446
|
+
/** Namespacing prefix so filter and condition placeholders never collide. */
|
|
447
|
+
type PredicatePrefix = 'filter' | 'cond';
|
|
448
|
+
interface PredicateExpression {
|
|
449
|
+
expression: string;
|
|
450
|
+
names: Record<string, string>;
|
|
451
|
+
typedValues: Record<string, TypedValue>;
|
|
452
|
+
}
|
|
453
|
+
/**
|
|
454
|
+
* Compile a list of predicate rows into one `… AND …` expression plus the
|
|
455
|
+
* fresh names/typedValues maps it references. Returns null for an empty list.
|
|
456
|
+
* Callers (buildRequest) merge the maps; this function never mutates shared
|
|
457
|
+
* state.
|
|
458
|
+
*/
|
|
459
|
+
declare function buildFilterExpressions(rows: FilterRow[], prefix: PredicatePrefix): PredicateExpression | null;
|
|
460
|
+
//#endregion
|
|
461
|
+
//#region src/key-command.d.ts
|
|
462
|
+
interface KeyConditionResult {
|
|
463
|
+
expression: string;
|
|
464
|
+
names: Record<string, string>;
|
|
465
|
+
typedValues: Record<string, TypedValue>;
|
|
466
|
+
}
|
|
467
|
+
/**
|
|
468
|
+
* Build a Query KeyConditionExpression from a hash key (always EQ) plus an
|
|
469
|
+
* optional range-key condition. Captures value types.
|
|
470
|
+
*/
|
|
471
|
+
declare function buildKeyConditionExpression(hashKey: KeyAttr, rangeKey?: RangeKeyCondition): KeyConditionResult;
|
|
472
|
+
/**
|
|
473
|
+
* Build the plain typed Key map (GetItem/Update/Delete) — real attribute names
|
|
474
|
+
* mapped to typed values, no expression placeholders.
|
|
475
|
+
*/
|
|
476
|
+
declare function buildKeyMap(keys: KeyAttr[]): Record<string, TypedValue>;
|
|
477
|
+
//#endregion
|
|
478
|
+
//#region src/build-request.d.ts
|
|
479
|
+
/**
|
|
480
|
+
* Assemble a {@link CanonicalRequest} from a builder config. Pure: reads only the
|
|
481
|
+
* config sub-parts the operation uses, merges the sub-builders' maps, and omits
|
|
482
|
+
* any map that ended up empty. Throws (fail loud) when a required part is missing
|
|
483
|
+
* (a Query without a hash key) rather than emitting a malformed request.
|
|
484
|
+
*/
|
|
485
|
+
declare function buildRequest(config: BuilderConfig): CanonicalRequest;
|
|
486
|
+
//#endregion
|
|
487
|
+
//#region src/build-update-expression.d.ts
|
|
488
|
+
interface UpdateExpressionResult {
|
|
489
|
+
expression: string;
|
|
490
|
+
names: Record<string, string>;
|
|
491
|
+
typedValues: Record<string, TypedValue>;
|
|
492
|
+
}
|
|
493
|
+
/**
|
|
494
|
+
* Compile update actions into one UpdateExpression. Returns null for an empty
|
|
495
|
+
* list. Callers (buildRequest) merge the returned maps; this never mutates
|
|
496
|
+
* shared state. Actions are grouped by kind into the canonical
|
|
497
|
+
* `SET … REMOVE … ADD … DELETE …` order while preserving each action's input
|
|
498
|
+
* order within its clause.
|
|
499
|
+
*/
|
|
500
|
+
declare function buildUpdateExpression(actions: UpdateAction[]): UpdateExpressionResult | null;
|
|
501
|
+
//#endregion
|
|
502
|
+
//#region src/emit/marshal.d.ts
|
|
503
|
+
/** A single DynamoDB-JSON AttributeValue (the v1 scalar/set subset). */
|
|
504
|
+
type AttributeValue = {
|
|
505
|
+
S: string;
|
|
506
|
+
} | {
|
|
507
|
+
N: string;
|
|
508
|
+
} | {
|
|
509
|
+
B: string;
|
|
510
|
+
} | {
|
|
511
|
+
BOOL: boolean;
|
|
512
|
+
} | {
|
|
513
|
+
SS: string[];
|
|
514
|
+
} | {
|
|
515
|
+
NS: string[];
|
|
516
|
+
} | {
|
|
517
|
+
BS: string[];
|
|
518
|
+
} | {
|
|
519
|
+
NULL: true;
|
|
520
|
+
};
|
|
521
|
+
/** Build an AttributeValue from a value's type tag (not its runtime type). */
|
|
522
|
+
declare function typedValueToAv(tv: TypedValue): AttributeValue;
|
|
523
|
+
/** Marshal a whole placeholder/attr map (`:v`→typed, or name→typed) to AVs. */
|
|
524
|
+
declare function typedMapToAvMap(map: Record<string, TypedValue>): Record<string, AttributeValue>;
|
|
525
|
+
/**
|
|
526
|
+
* Does this request carry any binary (`B`/`BS`) value? The SDK v3 / boto3
|
|
527
|
+
* emitters use this to decide whether to emit binary-decoding (a `Uint8Array`
|
|
528
|
+
* expression / an `import base64`).
|
|
529
|
+
*/
|
|
530
|
+
declare function hasBinaryValue(request: CanonicalRequest): boolean;
|
|
531
|
+
//#endregion
|
|
532
|
+
//#region src/emit/sdk-v3.d.ts
|
|
533
|
+
/** Build the command params object (key order matches typical SDK usage). */
|
|
534
|
+
declare function buildSdkV3Params(request: CanonicalRequest): Record<string, unknown>;
|
|
535
|
+
/** Emit the `new <Op>Command({...})` source snippet for a canonical request. */
|
|
536
|
+
declare function emitSdkV3(request: CanonicalRequest): string;
|
|
537
|
+
/** The `@aws-sdk/client-dynamodb` command class name for an operation. */
|
|
538
|
+
declare function sdkV3CommandName(operation: DdbOperation): string;
|
|
539
|
+
/**
|
|
540
|
+
* Render an arbitrary params value as the same pretty-printed JS literal
|
|
541
|
+
* `emitSdkV3` embeds (B/BS members as `Uint8Array` expressions). Exported for
|
|
542
|
+
* the query-builder program emitter, which composes its own statements around
|
|
543
|
+
* the literal (client init + pagination loop) instead of a bare `new Command`.
|
|
544
|
+
*/
|
|
545
|
+
declare function renderJsValue(value: unknown, indent?: number): string;
|
|
546
|
+
//#endregion
|
|
547
|
+
//#region src/emit/cli.d.ts
|
|
548
|
+
/** Emit the multi-line `aws dynamodb <op>` command for a canonical request. */
|
|
549
|
+
declare function emitCli(request: CanonicalRequest): string;
|
|
550
|
+
//#endregion
|
|
551
|
+
//#region src/emit/boto3.d.ts
|
|
552
|
+
/**
|
|
553
|
+
* Render a params value as the same Python literal `emitBoto3` embeds
|
|
554
|
+
* (`True`/`False`/`None`, B/BS as `base64.b64decode(...)`). Exported for the
|
|
555
|
+
* query-builder program emitter, which renders a `params` dict for its
|
|
556
|
+
* LastEvaluatedKey pagination loop.
|
|
557
|
+
*/
|
|
558
|
+
declare function renderPyValue(value: unknown): string;
|
|
559
|
+
/** The low-level boto3 client method name for an operation. */
|
|
560
|
+
declare function boto3MethodName(operation: DdbOperation): string;
|
|
561
|
+
/** Emit the runnable boto3 snippet (client + method call) for a canonical request. */
|
|
562
|
+
declare function emitBoto3(request: CanonicalRequest): string;
|
|
563
|
+
//#endregion
|
|
564
|
+
//#region src/emit/partiql.d.ts
|
|
565
|
+
/** Either a finished statement or an honest reason PartiQL can't express it. */
|
|
566
|
+
type PartiqlResult = {
|
|
567
|
+
ok: true;
|
|
568
|
+
statement: string;
|
|
569
|
+
} | {
|
|
570
|
+
ok: false;
|
|
571
|
+
reason: string;
|
|
572
|
+
};
|
|
573
|
+
/**
|
|
574
|
+
* Emit a PartiQL statement for a canonical request, or an honest
|
|
575
|
+
* `{ ok: false, reason }` when the request has no faithful PartiQL form.
|
|
576
|
+
*/
|
|
577
|
+
declare function emitPartiql(request: CanonicalRequest): PartiqlResult;
|
|
578
|
+
//#endregion
|
|
579
|
+
//#region src/emit/java.d.ts
|
|
580
|
+
/** The model request class name for an operation (`QueryRequest`, …). */
|
|
581
|
+
declare function javaRequestClassName(operation: DdbOperation): string;
|
|
582
|
+
/** The `DynamoDbClient` method name for an operation (`query`, …). */
|
|
583
|
+
declare function javaClientMethodName(operation: DdbOperation): string;
|
|
584
|
+
/** Emit the bare `<Op>Request.builder()…build()` snippet for a canonical request. */
|
|
585
|
+
declare function emitJava(request: CanonicalRequest): string;
|
|
586
|
+
//#endregion
|
|
587
|
+
//#region src/emit/go.d.ts
|
|
588
|
+
/** The `dynamodb.<Op>Input` struct name for an operation. */
|
|
589
|
+
declare function goInputTypeName(operation: DdbOperation): string;
|
|
590
|
+
/** The `dynamodb.Client` method name for an operation. */
|
|
591
|
+
declare function goClientMethodName(operation: DdbOperation): string;
|
|
592
|
+
/** Emit the bare `&dynamodb.<Op>Input{…}` snippet for a canonical request. */
|
|
593
|
+
declare function emitGo(request: CanonicalRequest): string;
|
|
594
|
+
//#endregion
|
|
595
|
+
//#region src/emit/dotnet.d.ts
|
|
596
|
+
/** The model request class name for an operation (`QueryRequest`, …). */
|
|
597
|
+
declare function dotnetRequestClassName(operation: DdbOperation): string;
|
|
598
|
+
/** The async client method name for an operation (`QueryAsync`, …). */
|
|
599
|
+
declare function dotnetClientMethodName(operation: DdbOperation): string;
|
|
600
|
+
/** Emit the bare `new <Op>Request { … }` snippet for a canonical request. */
|
|
601
|
+
declare function emitDotnet(request: CanonicalRequest): string;
|
|
602
|
+
//#endregion
|
|
603
|
+
//#region src/emit/ddbtoolbox.d.ts
|
|
604
|
+
/**
|
|
605
|
+
* Emit the runnable dynamodb-toolbox program for a Query/Scan canonical request.
|
|
606
|
+
* `paginate` wraps the send in a `LastEvaluatedKey` loop (dynamodb-toolbox's
|
|
607
|
+
* `send()` returns `{ Items, LastEvaluatedKey }` and takes `exclusiveStartKey`).
|
|
608
|
+
*/
|
|
609
|
+
declare function emitDdbToolboxProgram(request: CanonicalRequest, paginate: boolean): string;
|
|
610
|
+
//#endregion
|
|
611
|
+
//#region src/program.d.ts
|
|
612
|
+
/**
|
|
613
|
+
* The query tool's whole state: a Query/Scan {@link BuilderConfig} plus the one
|
|
614
|
+
* PROGRAM-level knob the request itself doesn't carry — whether the emitted
|
|
615
|
+
* code loops on `LastEvaluatedKey` to fetch every page.
|
|
616
|
+
*/
|
|
617
|
+
interface QueryToolConfig extends BuilderConfig {
|
|
618
|
+
/** Emit the fetch-all-pages pagination loop (default: single request). */
|
|
619
|
+
paginate?: boolean;
|
|
620
|
+
}
|
|
621
|
+
type QueryProgramFormat = 'sdk' | 'cli' | 'boto3' | 'partiql' | 'java' | 'go' | 'dotnet' | 'ddbtoolbox';
|
|
622
|
+
/** A runnable program, or an honest reason the format can't express it. */
|
|
623
|
+
type ProgramResult = {
|
|
624
|
+
ok: true;
|
|
625
|
+
code: string;
|
|
626
|
+
} | {
|
|
627
|
+
ok: false;
|
|
628
|
+
reason: string;
|
|
629
|
+
};
|
|
630
|
+
/**
|
|
631
|
+
* Emit the runnable program for a Query/Scan config in the given format.
|
|
632
|
+
* Throws on a non-read operation (the widget never produces one — programmer
|
|
633
|
+
* error, mirroring `buildRequest`'s fail-loud posture) and propagates
|
|
634
|
+
* `buildRequest`'s build errors (e.g. a Query without a hash key) for the
|
|
635
|
+
* caller to surface as a note.
|
|
636
|
+
*/
|
|
637
|
+
declare function emitQueryProgram(config: QueryToolConfig, format: QueryProgramFormat): ProgramResult;
|
|
638
|
+
//#endregion
|
|
639
|
+
export { type AttributeValue, type BuilderConfig, type CanonicalRequest, type DdbOperation, type DdbScalarType, FILTER_OPERATORS, type FilterDataType, type FilterOperatorOption, type FilterRow, type ItemAttr, KEY_OPERATORS, type KeyAttr, type KeyConditionResult, OPERATOR_BY_VALUE, type OperatorDef, type OperatorValue, type PartiqlResult, type PredicateExpression, type PredicatePrefix, type ProgramResult, type QueryProgramFormat, type QueryToolConfig, type RangeKeyCondition, SET_TYPES, type SetOperation, type SetType, type TypedValue, type UpdateAction, type UpdateExpressionResult, type WireFilterOperator, boto3MethodName, buildFilterExpressions, buildKeyConditionExpression, buildKeyMap, buildRequest, buildSdkV3Params, buildUpdateExpression, dotnetClientMethodName, dotnetRequestClassName, elementType, emitBoto3, emitCli, emitDdbToolboxProgram, emitDotnet, emitGo, emitJava, emitPartiql, emitQueryProgram, emitSdkV3, getCompatibleComparisonOperators, getCompatibleFilterOperators, goClientMethodName, goInputTypeName, hasBinaryValue, isSetType, javaClientMethodName, javaRequestClassName, makeTypedValue, renderJsValue, renderPyValue, sdkV3CommandName, typedMapToAvMap, typedValueToAv };
|