graphddb 0.2.0 → 0.2.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +68 -3
- package/dist/{chunk-F27INYI2.js → chunk-4B4MUPUJ.js} +232 -96
- package/dist/{chunk-347U24SB.js → chunk-PWV7JDMR.js} +353 -37
- package/dist/{chunk-UNRQ5YJT.js → chunk-SBNP62H7.js} +1 -1
- package/dist/cli.js +2 -2
- package/dist/index.d.ts +5 -19
- package/dist/index.js +113 -7
- package/dist/testing/index.d.ts +1 -1
- package/dist/testing/index.js +2 -2
- package/dist/{types-D6qLpw2M.d.ts → types-DPJ4tPjX.d.ts} +215 -122
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -28,7 +28,7 @@ import {
|
|
|
28
28
|
compileFragment,
|
|
29
29
|
compileMutationPlan,
|
|
30
30
|
compileSingleFragmentPlan,
|
|
31
|
-
|
|
31
|
+
conditionParamName,
|
|
32
32
|
contractOfMethodSpec,
|
|
33
33
|
decodeCursor,
|
|
34
34
|
definePlan,
|
|
@@ -68,7 +68,6 @@ import {
|
|
|
68
68
|
isLifecycleContract,
|
|
69
69
|
isMutationFragment,
|
|
70
70
|
isMutationInputRef,
|
|
71
|
-
isParam,
|
|
72
71
|
isPlannedCommandMethod,
|
|
73
72
|
isQueryModelContract,
|
|
74
73
|
isSelectBuilder,
|
|
@@ -78,7 +77,6 @@ import {
|
|
|
78
77
|
mintContractKeyFieldRef,
|
|
79
78
|
mintContractParamRef,
|
|
80
79
|
mutation,
|
|
81
|
-
param,
|
|
82
80
|
plan,
|
|
83
81
|
publicCommandModel,
|
|
84
82
|
publicQueryModel,
|
|
@@ -88,11 +86,11 @@ import {
|
|
|
88
86
|
validateDepth,
|
|
89
87
|
when,
|
|
90
88
|
wholeKeysSentinel
|
|
91
|
-
} from "./chunk-
|
|
89
|
+
} from "./chunk-4B4MUPUJ.js";
|
|
92
90
|
import {
|
|
93
91
|
CdcEmulator,
|
|
94
92
|
createCdcEmulator
|
|
95
|
-
} from "./chunk-
|
|
93
|
+
} from "./chunk-SBNP62H7.js";
|
|
96
94
|
import {
|
|
97
95
|
BATCH_GET_MAX_KEYS,
|
|
98
96
|
BATCH_WRITE_MAX_ITEMS,
|
|
@@ -110,7 +108,9 @@ import {
|
|
|
110
108
|
buildUpdateExpression,
|
|
111
109
|
buildUpdateInput,
|
|
112
110
|
collapseSameKeyItems,
|
|
111
|
+
collectRawConditionParams,
|
|
113
112
|
commitTransaction,
|
|
113
|
+
cond,
|
|
114
114
|
createDefaultLinter,
|
|
115
115
|
execItemKeySignature,
|
|
116
116
|
executeDelete,
|
|
@@ -121,16 +121,20 @@ import {
|
|
|
121
121
|
gsiAmbiguityRule,
|
|
122
122
|
isColumn,
|
|
123
123
|
isKeySegment,
|
|
124
|
+
isParam,
|
|
125
|
+
isRawCondition,
|
|
124
126
|
k,
|
|
125
127
|
key,
|
|
126
128
|
missingGsiRule,
|
|
127
129
|
noScanRule,
|
|
130
|
+
param,
|
|
128
131
|
relationDepthRule,
|
|
129
132
|
requireLimitRule,
|
|
133
|
+
resolveConditionTree,
|
|
130
134
|
resolveKey,
|
|
131
135
|
resolveModelClass,
|
|
132
136
|
serializeFieldValue
|
|
133
|
-
} from "./chunk-
|
|
137
|
+
} from "./chunk-PWV7JDMR.js";
|
|
134
138
|
|
|
135
139
|
// src/metadata/prefix.ts
|
|
136
140
|
function derivePrefix(customPrefix, className) {
|
|
@@ -413,6 +417,12 @@ function whenHolds(when2, params, element) {
|
|
|
413
417
|
const right = resolveTemplate(when2.right, params, element);
|
|
414
418
|
return when2.op === "eq" ? left === right : left !== right;
|
|
415
419
|
}
|
|
420
|
+
function resolveRawConditionValue(val, params, element) {
|
|
421
|
+
if (val !== null && typeof val === "object" && typeof val.$param === "string") {
|
|
422
|
+
return resolveValue(`{${val.$param}}`, params, element);
|
|
423
|
+
}
|
|
424
|
+
return val;
|
|
425
|
+
}
|
|
416
426
|
function applyCondition(condition, target, params, element) {
|
|
417
427
|
if (!condition) return;
|
|
418
428
|
const names = target.ExpressionAttributeNames ??= {};
|
|
@@ -428,6 +438,25 @@ function applyCondition(condition, target, params, element) {
|
|
|
428
438
|
return;
|
|
429
439
|
}
|
|
430
440
|
const values = target.ExpressionAttributeValues ??= {};
|
|
441
|
+
if (condition.kind === "raw") {
|
|
442
|
+
Object.assign(names, condition.names);
|
|
443
|
+
for (const [alias, val] of Object.entries(condition.values)) {
|
|
444
|
+
values[alias] = resolveRawConditionValue(val, params, element);
|
|
445
|
+
}
|
|
446
|
+
target.ConditionExpression = condition.expression;
|
|
447
|
+
return;
|
|
448
|
+
}
|
|
449
|
+
if (condition.kind === "expr") {
|
|
450
|
+
const concrete = resolveConditionTree(
|
|
451
|
+
condition.declarative,
|
|
452
|
+
(name) => resolveValue(`{${name}}`, params, element)
|
|
453
|
+
);
|
|
454
|
+
const compiled = buildConditionExpression(concrete);
|
|
455
|
+
Object.assign(names, compiled.names);
|
|
456
|
+
Object.assign(values, compiled.values);
|
|
457
|
+
target.ConditionExpression = compiled.expression;
|
|
458
|
+
return;
|
|
459
|
+
}
|
|
431
460
|
const clauses = [];
|
|
432
461
|
let i = 0;
|
|
433
462
|
for (const [field2, tmpl] of Object.entries(condition.fields)) {
|
|
@@ -832,11 +861,88 @@ function entityRef(model2) {
|
|
|
832
861
|
}
|
|
833
862
|
function collectConditionParams(condition, out) {
|
|
834
863
|
if (condition === void 0) return;
|
|
864
|
+
if (isRawCondition(condition)) {
|
|
865
|
+
for (const { name, param: param2 } of collectRawConditionParams(condition)) {
|
|
866
|
+
out[name] = descriptorFromParam(name, param2, out[name]);
|
|
867
|
+
}
|
|
868
|
+
return;
|
|
869
|
+
}
|
|
835
870
|
const obj = condition;
|
|
836
871
|
if (obj.notExists === true) return;
|
|
837
872
|
if (typeof obj.attributeExists === "string") return;
|
|
838
873
|
if (typeof obj.attributeNotExists === "string") return;
|
|
839
|
-
|
|
874
|
+
collectConditionTreeParams(obj, out);
|
|
875
|
+
}
|
|
876
|
+
var SINGLE_OPERAND_OPS = /* @__PURE__ */ new Set([
|
|
877
|
+
"eq",
|
|
878
|
+
"ne",
|
|
879
|
+
"gt",
|
|
880
|
+
"ge",
|
|
881
|
+
"lt",
|
|
882
|
+
"le",
|
|
883
|
+
"beginsWith",
|
|
884
|
+
"contains",
|
|
885
|
+
"notContains",
|
|
886
|
+
"attributeType",
|
|
887
|
+
"size"
|
|
888
|
+
]);
|
|
889
|
+
function collectConditionTreeParams(obj, out) {
|
|
890
|
+
for (const [key2, value] of Object.entries(obj)) {
|
|
891
|
+
if (value === void 0) continue;
|
|
892
|
+
if (key2 === "and" || key2 === "or") {
|
|
893
|
+
for (const sub of value) {
|
|
894
|
+
if (isRawCondition(sub)) {
|
|
895
|
+
for (const { name, param: param2 } of collectRawConditionParams(sub)) {
|
|
896
|
+
out[name] = descriptorFromParam(name, param2, out[name]);
|
|
897
|
+
}
|
|
898
|
+
continue;
|
|
899
|
+
}
|
|
900
|
+
collectConditionTreeParams(sub, out);
|
|
901
|
+
}
|
|
902
|
+
continue;
|
|
903
|
+
}
|
|
904
|
+
if (key2 === "not") {
|
|
905
|
+
if (isRawCondition(value)) {
|
|
906
|
+
for (const { name, param: param2 } of collectRawConditionParams(value)) {
|
|
907
|
+
out[name] = descriptorFromParam(name, param2, out[name]);
|
|
908
|
+
}
|
|
909
|
+
continue;
|
|
910
|
+
}
|
|
911
|
+
collectConditionTreeParams(value, out);
|
|
912
|
+
continue;
|
|
913
|
+
}
|
|
914
|
+
if (isParam(value)) {
|
|
915
|
+
out[key2] = descriptorFromParam(key2, value, out[key2]);
|
|
916
|
+
continue;
|
|
917
|
+
}
|
|
918
|
+
if (value === null || typeof value !== "object" || value instanceof Date) {
|
|
919
|
+
continue;
|
|
920
|
+
}
|
|
921
|
+
const ops = value;
|
|
922
|
+
for (const [op, opVal] of Object.entries(ops)) {
|
|
923
|
+
if (op === "between") {
|
|
924
|
+
const [lo, hi] = opVal;
|
|
925
|
+
if (isParam(lo)) {
|
|
926
|
+
const n = conditionParamName(key2, op, 0);
|
|
927
|
+
out[n] = descriptorFromParam(n, lo, out[n]);
|
|
928
|
+
}
|
|
929
|
+
if (isParam(hi)) {
|
|
930
|
+
const n = conditionParamName(key2, op, 1);
|
|
931
|
+
out[n] = descriptorFromParam(n, hi, out[n]);
|
|
932
|
+
}
|
|
933
|
+
} else if (op === "in") {
|
|
934
|
+
opVal.forEach((v, i) => {
|
|
935
|
+
if (isParam(v)) {
|
|
936
|
+
const n = conditionParamName(key2, op, i);
|
|
937
|
+
out[n] = descriptorFromParam(n, v, out[n]);
|
|
938
|
+
}
|
|
939
|
+
});
|
|
940
|
+
} else if (SINGLE_OPERAND_OPS.has(op) && isParam(opVal)) {
|
|
941
|
+
const n = conditionParamName(key2, op);
|
|
942
|
+
out[n] = descriptorFromParam(n, opVal, out[n]);
|
|
943
|
+
}
|
|
944
|
+
}
|
|
945
|
+
}
|
|
840
946
|
}
|
|
841
947
|
function makeDefinition(model2, operation, key2, select, changes, condition) {
|
|
842
948
|
const params = collectParams(key2);
|
package/dist/testing/index.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { E as Executor, D as DynamoDBOperation, a as ExecutorResult, B as BatchGetExecInput, P as PutInput, W as WriteExecOptions, b as WriteResult, U as UpdateInput, c as DeleteInput, d as BatchWriteExecItem, T as TransactWriteExecItem, M as ModelStatic, e as DDBModel, C as ChangeEvent } from '../types-
|
|
1
|
+
import { E as Executor, D as DynamoDBOperation, a as ExecutorResult, B as BatchGetExecInput, P as PutInput, W as WriteExecOptions, b as WriteResult, U as UpdateInput, c as DeleteInput, d as BatchWriteExecItem, T as TransactWriteExecItem, M as ModelStatic, e as DDBModel, C as ChangeEvent } from '../types-DPJ4tPjX.js';
|
|
2
2
|
import '@aws-sdk/client-dynamodb';
|
|
3
3
|
|
|
4
4
|
/**
|
package/dist/testing/index.js
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
import {
|
|
2
2
|
createCdcEmulator
|
|
3
|
-
} from "../chunk-
|
|
3
|
+
} from "../chunk-SBNP62H7.js";
|
|
4
4
|
import {
|
|
5
5
|
ClientManager,
|
|
6
6
|
MetadataRegistry,
|
|
7
7
|
TableMapping,
|
|
8
8
|
resolveModelClass
|
|
9
|
-
} from "../chunk-
|
|
9
|
+
} from "../chunk-PWV7JDMR.js";
|
|
10
10
|
|
|
11
11
|
// src/memory/memory-store.ts
|
|
12
12
|
function deepClone(value) {
|
|
@@ -52,6 +52,113 @@ type ResolvedKey = {
|
|
|
52
52
|
inputFieldNames: string[];
|
|
53
53
|
};
|
|
54
54
|
|
|
55
|
+
/**
|
|
56
|
+
* Parameter placeholders for the parameterized query / command definition DSL
|
|
57
|
+
* (issue #41, Python-bridge Phase 0a).
|
|
58
|
+
*
|
|
59
|
+
* A `Param<T>` is a **branded placeholder** standing in for a value that is not
|
|
60
|
+
* known at definition time but is supplied later (at execution, e.g. from
|
|
61
|
+
* Python). It carries:
|
|
62
|
+
*
|
|
63
|
+
* - the **TypeScript value type** `T` it represents (`string`, `number`, or a
|
|
64
|
+
* string-literal union), preserved through the IR and the inferred return
|
|
65
|
+
* types of `defineQueries` / `defineCommands`; and
|
|
66
|
+
* - a **runtime descriptor** (`kind` + optional `literals`) that the static
|
|
67
|
+
* planner (#42) and the code generator read to emit `operations.json`.
|
|
68
|
+
*
|
|
69
|
+
* Placeholders are created with `param.string()`, `param.number()`, and
|
|
70
|
+
* `param.literal(...)`. They are *only* legal at value positions inside a
|
|
71
|
+
* parameterized key / changes structure passed to the `define*` entry points —
|
|
72
|
+
* never to the live `Model.query` / `Model.putItem` runtime API, whose types remain
|
|
73
|
+
* uncontaminated by params.
|
|
74
|
+
*/
|
|
75
|
+
/** Brand tag preventing a plain object from structurally matching a {@link Param}. */
|
|
76
|
+
declare const PARAM_BRAND: unique symbol;
|
|
77
|
+
/** Runtime discriminant for a parameter placeholder. */
|
|
78
|
+
type ParamKind = 'string' | 'number' | 'literal' | 'array';
|
|
79
|
+
/**
|
|
80
|
+
* A branded parameter placeholder representing a value of TypeScript type `T`
|
|
81
|
+
* that is bound at execution time rather than definition time.
|
|
82
|
+
*
|
|
83
|
+
* The brand (`[PARAM_BRAND]: T`) keeps `Param<string>` and `Param<number>`
|
|
84
|
+
* distinct and prevents a bare value from being mistaken for a placeholder.
|
|
85
|
+
*
|
|
86
|
+
* @typeParam T - The value type this placeholder stands in for.
|
|
87
|
+
*/
|
|
88
|
+
interface Param<out T> {
|
|
89
|
+
/** @internal Type brand carrying the represented value type. */
|
|
90
|
+
readonly [PARAM_BRAND]: T;
|
|
91
|
+
/** Runtime discriminant: `'string'` | `'number'` | `'literal'` | `'array'`. */
|
|
92
|
+
readonly kind: ParamKind;
|
|
93
|
+
/**
|
|
94
|
+
* For `param.literal(...)`, the allowed literal values (preserved at runtime
|
|
95
|
+
* for the generator). `undefined` for `string` / `number`.
|
|
96
|
+
*/
|
|
97
|
+
readonly literals?: readonly T[];
|
|
98
|
+
/**
|
|
99
|
+
* For `param.array({...})`, the descriptor of each element's fields. Lets the
|
|
100
|
+
* transaction planner (#46) type `forEach` element references and emit the
|
|
101
|
+
* `{item.<field>}` templates. `undefined` for scalar params.
|
|
102
|
+
*/
|
|
103
|
+
readonly element?: Readonly<Record<string, Param<unknown>>>;
|
|
104
|
+
}
|
|
105
|
+
/** A `Param` whose represented value type is `string`. */
|
|
106
|
+
type StringParam = Param<string>;
|
|
107
|
+
/** A `Param` whose represented value type is `number`. */
|
|
108
|
+
type NumberParam = Param<number>;
|
|
109
|
+
/** A `Param` whose represented value type is the literal union `L`. */
|
|
110
|
+
type LiteralParam<L extends string | number> = Param<L>;
|
|
111
|
+
/** The element-field descriptor shape accepted by {@link param.array}. */
|
|
112
|
+
type ArrayElementShape = Record<string, Param<unknown>>;
|
|
113
|
+
/**
|
|
114
|
+
* The TypeScript element type implied by an {@link ArrayElementShape} `E`: each
|
|
115
|
+
* field carries the value type its placeholder represents.
|
|
116
|
+
*/
|
|
117
|
+
type ElementOf<E extends ArrayElementShape> = {
|
|
118
|
+
[K in keyof E]: E[K] extends Param<infer V> ? V : never;
|
|
119
|
+
};
|
|
120
|
+
/** A `Param` standing in for an **array** whose elements have shape `E`. */
|
|
121
|
+
type ArrayParam<E extends ArrayElementShape> = Param<ElementOf<E>[]> & {
|
|
122
|
+
readonly element: E;
|
|
123
|
+
};
|
|
124
|
+
/** Allowed scalar value types a placeholder may stand in for. */
|
|
125
|
+
type ParamValue = string | number;
|
|
126
|
+
/**
|
|
127
|
+
* Placeholder factory. Each call returns a branded {@link Param} carrying both
|
|
128
|
+
* the TypeScript value type and a runtime descriptor.
|
|
129
|
+
*/
|
|
130
|
+
declare const param: {
|
|
131
|
+
/** A placeholder for a `string` value. */
|
|
132
|
+
readonly string: () => StringParam;
|
|
133
|
+
/** A placeholder for a `number` value. */
|
|
134
|
+
readonly number: () => NumberParam;
|
|
135
|
+
/**
|
|
136
|
+
* A placeholder constrained to one of the given literal values. The value
|
|
137
|
+
* type of the resulting {@link Param} is the **union of the literals**, so it
|
|
138
|
+
* is preserved precisely in the IR and the inferred definition types.
|
|
139
|
+
*
|
|
140
|
+
* @example
|
|
141
|
+
* ```ts
|
|
142
|
+
* param.literal('active', 'disabled'); // Param<'active' | 'disabled'>
|
|
143
|
+
* ```
|
|
144
|
+
*/
|
|
145
|
+
readonly literal: <const L extends readonly [ParamValue, ...ParamValue[]]>(...values: L) => LiteralParam<L[number]>;
|
|
146
|
+
/**
|
|
147
|
+
* A placeholder for an **array** parameter whose elements have the given field
|
|
148
|
+
* shape. Used by `defineTransaction`'s `tx.forEach(p.<arrayParam>, …)` to bind
|
|
149
|
+
* each element's fields to `{item.<field>}` templates.
|
|
150
|
+
*
|
|
151
|
+
* @example
|
|
152
|
+
* ```ts
|
|
153
|
+
* param.array({ userId: param.string(), role: param.string() });
|
|
154
|
+
* // Param<{ userId: string; role: string }[]>
|
|
155
|
+
* ```
|
|
156
|
+
*/
|
|
157
|
+
readonly array: <const E extends ArrayElementShape>(element: E) => ArrayParam<E>;
|
|
158
|
+
};
|
|
159
|
+
/** Runtime type guard: is `value` a parameter placeholder? */
|
|
160
|
+
declare function isParam(value: unknown): value is Param<unknown>;
|
|
161
|
+
|
|
55
162
|
/**
|
|
56
163
|
* Internal brand identifying a {@link RawCondition} produced by {@link cond}.
|
|
57
164
|
*/
|
|
@@ -85,7 +192,7 @@ interface RawCondition<M = unknown> {
|
|
|
85
192
|
* @typeParam M - The owning model brand. Constrains all columns to one model,
|
|
86
193
|
* so passing another model's column is a compile error.
|
|
87
194
|
*/
|
|
88
|
-
type CondSlot<M> = Column<any, M> | string | number | boolean | Date
|
|
195
|
+
type CondSlot<M> = Column<any, M> | string | number | boolean | Date | Param<unknown>;
|
|
89
196
|
/**
|
|
90
197
|
* Raw DynamoDB condition escape hatch.
|
|
91
198
|
*
|
|
@@ -197,6 +304,35 @@ type FilterInput<T> = ({
|
|
|
197
304
|
or?: readonly (FilterInput<T> | RawCondition<T>)[];
|
|
198
305
|
not?: FilterInput<T> | RawCondition<T>;
|
|
199
306
|
}) | RawCondition<T>;
|
|
307
|
+
/**
|
|
308
|
+
* A type-safe **write condition** for `putItem` / `updateItem` / `deleteItem`
|
|
309
|
+
* and a transaction item (issue #114-A). Structurally the declarative operator
|
|
310
|
+
* subset of {@link FilterInput} — the same per-field-type operator constraints
|
|
311
|
+
* (e.g. `beginsWith` on a numeric field is a compile error) — plus the legacy
|
|
312
|
+
* existence primitives (`{ notExists }` / `{ attributeExists }` /
|
|
313
|
+
* `{ attributeNotExists }`). The raw `cond` escape hatch (issue #114-B) is also
|
|
314
|
+
* accepted — as a whole condition or as a member of an `and` / `or` / `not`
|
|
315
|
+
* group — for conditions the declarative subset cannot express; its
|
|
316
|
+
* `Model.col.<field>` brand must match the write target model `T`
|
|
317
|
+
* (injection-free / refactor-safe), exactly as on the read side.
|
|
318
|
+
*/
|
|
319
|
+
type WriteCondition<T> = ({
|
|
320
|
+
[K in ScalarKeys<T>]?: FieldFilter<T[K]>;
|
|
321
|
+
} & {
|
|
322
|
+
/** Legacy whole-row guard: `attribute_not_exists(PK)`. */
|
|
323
|
+
notExists?: true;
|
|
324
|
+
/** `attribute_exists(<field>)` — the named attribute must be present. */
|
|
325
|
+
attributeExists?: string;
|
|
326
|
+
/** `attribute_not_exists(<field>)` — the named attribute must be absent. */
|
|
327
|
+
attributeNotExists?: string;
|
|
328
|
+
and?: readonly (WriteCondition<T> | RawCondition<T>)[];
|
|
329
|
+
or?: readonly (WriteCondition<T> | RawCondition<T>)[];
|
|
330
|
+
not?: WriteCondition<T> | RawCondition<T>;
|
|
331
|
+
}) | RawCondition<T>;
|
|
332
|
+
/** Options carrying an optional type-safe write {@link WriteCondition}. */
|
|
333
|
+
interface WriteOptions<T> {
|
|
334
|
+
readonly condition?: WriteCondition<T>;
|
|
335
|
+
}
|
|
200
336
|
|
|
201
337
|
/**
|
|
202
338
|
* Internal brand symbol identifying a compiled select builder at runtime.
|
|
@@ -700,7 +836,7 @@ interface ModelStatic<T extends DDBModel, C = unknown> {
|
|
|
700
836
|
consistentRead?: boolean;
|
|
701
837
|
filter?: FilterInput<T>;
|
|
702
838
|
}): ExecutionPlan;
|
|
703
|
-
putItem(item: EntityInput<T>, options?:
|
|
839
|
+
putItem(item: EntityInput<T>, options?: WriteOptions<T>): Promise<void>;
|
|
704
840
|
/**
|
|
705
841
|
* Update an item identified by its **explicit base-table primary key**
|
|
706
842
|
* (`PrimaryKeyOf<C>`). This is the canonical form — it requires the key input
|
|
@@ -708,7 +844,7 @@ interface ModelStatic<T extends DDBModel, C = unknown> {
|
|
|
708
844
|
*
|
|
709
845
|
* @example `await User.updateItem({ userId: 'alice' }, { status: 'disabled' });`
|
|
710
846
|
*/
|
|
711
|
-
updateItem(key: UpdateExplicitKey<C>, changes: Partial<T>, options?:
|
|
847
|
+
updateItem(key: UpdateExplicitKey<C>, changes: Partial<T>, options?: WriteOptions<T>): Promise<void>;
|
|
712
848
|
/**
|
|
713
849
|
* Update an item using an **updatable** entity obtained from
|
|
714
850
|
* `query(..., { updatable: true })` / `list(..., { updatable: true })`. The
|
|
@@ -719,18 +855,18 @@ interface ModelStatic<T extends DDBModel, C = unknown> {
|
|
|
719
855
|
* brand (rejected here at compile time) and the hidden key (rejected at
|
|
720
856
|
* runtime), preventing an accidental wrong-item update.
|
|
721
857
|
*/
|
|
722
|
-
updateItem(entity: Partial<T> & Updatable, changes: Partial<T>, options?:
|
|
723
|
-
deleteItem(key: DeleteKey<C>, options?:
|
|
858
|
+
updateItem(entity: Partial<T> & Updatable, changes: Partial<T>, options?: WriteOptions<T>): Promise<void>;
|
|
859
|
+
deleteItem(key: DeleteKey<C>, options?: WriteOptions<T>): Promise<void>;
|
|
724
860
|
}
|
|
725
861
|
|
|
726
|
-
interface PutOptions {
|
|
727
|
-
condition?:
|
|
862
|
+
interface PutOptions<T = unknown> {
|
|
863
|
+
condition?: WriteCondition<T>;
|
|
728
864
|
}
|
|
729
|
-
interface UpdateOptions {
|
|
730
|
-
condition?:
|
|
865
|
+
interface UpdateOptions<T = unknown> {
|
|
866
|
+
condition?: WriteCondition<T>;
|
|
731
867
|
}
|
|
732
|
-
interface DeleteOptions {
|
|
733
|
-
condition?:
|
|
868
|
+
interface DeleteOptions<T = unknown> {
|
|
869
|
+
condition?: WriteCondition<T>;
|
|
734
870
|
}
|
|
735
871
|
|
|
736
872
|
interface PutInput {
|
|
@@ -949,113 +1085,6 @@ declare class BatchGetResult {
|
|
|
949
1085
|
declare function executeBatchGet(requests: BatchGetRequest[]): Promise<BatchGetResult>;
|
|
950
1086
|
declare function executeBatchWrite(requests: BatchWriteRequest[]): Promise<void>;
|
|
951
1087
|
|
|
952
|
-
/**
|
|
953
|
-
* Parameter placeholders for the parameterized query / command definition DSL
|
|
954
|
-
* (issue #41, Python-bridge Phase 0a).
|
|
955
|
-
*
|
|
956
|
-
* A `Param<T>` is a **branded placeholder** standing in for a value that is not
|
|
957
|
-
* known at definition time but is supplied later (at execution, e.g. from
|
|
958
|
-
* Python). It carries:
|
|
959
|
-
*
|
|
960
|
-
* - the **TypeScript value type** `T` it represents (`string`, `number`, or a
|
|
961
|
-
* string-literal union), preserved through the IR and the inferred return
|
|
962
|
-
* types of `defineQueries` / `defineCommands`; and
|
|
963
|
-
* - a **runtime descriptor** (`kind` + optional `literals`) that the static
|
|
964
|
-
* planner (#42) and the code generator read to emit `operations.json`.
|
|
965
|
-
*
|
|
966
|
-
* Placeholders are created with `param.string()`, `param.number()`, and
|
|
967
|
-
* `param.literal(...)`. They are *only* legal at value positions inside a
|
|
968
|
-
* parameterized key / changes structure passed to the `define*` entry points —
|
|
969
|
-
* never to the live `Model.query` / `Model.putItem` runtime API, whose types remain
|
|
970
|
-
* uncontaminated by params.
|
|
971
|
-
*/
|
|
972
|
-
/** Brand tag preventing a plain object from structurally matching a {@link Param}. */
|
|
973
|
-
declare const PARAM_BRAND: unique symbol;
|
|
974
|
-
/** Runtime discriminant for a parameter placeholder. */
|
|
975
|
-
type ParamKind = 'string' | 'number' | 'literal' | 'array';
|
|
976
|
-
/**
|
|
977
|
-
* A branded parameter placeholder representing a value of TypeScript type `T`
|
|
978
|
-
* that is bound at execution time rather than definition time.
|
|
979
|
-
*
|
|
980
|
-
* The brand (`[PARAM_BRAND]: T`) keeps `Param<string>` and `Param<number>`
|
|
981
|
-
* distinct and prevents a bare value from being mistaken for a placeholder.
|
|
982
|
-
*
|
|
983
|
-
* @typeParam T - The value type this placeholder stands in for.
|
|
984
|
-
*/
|
|
985
|
-
interface Param<out T> {
|
|
986
|
-
/** @internal Type brand carrying the represented value type. */
|
|
987
|
-
readonly [PARAM_BRAND]: T;
|
|
988
|
-
/** Runtime discriminant: `'string'` | `'number'` | `'literal'` | `'array'`. */
|
|
989
|
-
readonly kind: ParamKind;
|
|
990
|
-
/**
|
|
991
|
-
* For `param.literal(...)`, the allowed literal values (preserved at runtime
|
|
992
|
-
* for the generator). `undefined` for `string` / `number`.
|
|
993
|
-
*/
|
|
994
|
-
readonly literals?: readonly T[];
|
|
995
|
-
/**
|
|
996
|
-
* For `param.array({...})`, the descriptor of each element's fields. Lets the
|
|
997
|
-
* transaction planner (#46) type `forEach` element references and emit the
|
|
998
|
-
* `{item.<field>}` templates. `undefined` for scalar params.
|
|
999
|
-
*/
|
|
1000
|
-
readonly element?: Readonly<Record<string, Param<unknown>>>;
|
|
1001
|
-
}
|
|
1002
|
-
/** A `Param` whose represented value type is `string`. */
|
|
1003
|
-
type StringParam = Param<string>;
|
|
1004
|
-
/** A `Param` whose represented value type is `number`. */
|
|
1005
|
-
type NumberParam = Param<number>;
|
|
1006
|
-
/** A `Param` whose represented value type is the literal union `L`. */
|
|
1007
|
-
type LiteralParam<L extends string | number> = Param<L>;
|
|
1008
|
-
/** The element-field descriptor shape accepted by {@link param.array}. */
|
|
1009
|
-
type ArrayElementShape = Record<string, Param<unknown>>;
|
|
1010
|
-
/**
|
|
1011
|
-
* The TypeScript element type implied by an {@link ArrayElementShape} `E`: each
|
|
1012
|
-
* field carries the value type its placeholder represents.
|
|
1013
|
-
*/
|
|
1014
|
-
type ElementOf<E extends ArrayElementShape> = {
|
|
1015
|
-
[K in keyof E]: E[K] extends Param<infer V> ? V : never;
|
|
1016
|
-
};
|
|
1017
|
-
/** A `Param` standing in for an **array** whose elements have shape `E`. */
|
|
1018
|
-
type ArrayParam<E extends ArrayElementShape> = Param<ElementOf<E>[]> & {
|
|
1019
|
-
readonly element: E;
|
|
1020
|
-
};
|
|
1021
|
-
/** Allowed scalar value types a placeholder may stand in for. */
|
|
1022
|
-
type ParamValue = string | number;
|
|
1023
|
-
/**
|
|
1024
|
-
* Placeholder factory. Each call returns a branded {@link Param} carrying both
|
|
1025
|
-
* the TypeScript value type and a runtime descriptor.
|
|
1026
|
-
*/
|
|
1027
|
-
declare const param: {
|
|
1028
|
-
/** A placeholder for a `string` value. */
|
|
1029
|
-
readonly string: () => StringParam;
|
|
1030
|
-
/** A placeholder for a `number` value. */
|
|
1031
|
-
readonly number: () => NumberParam;
|
|
1032
|
-
/**
|
|
1033
|
-
* A placeholder constrained to one of the given literal values. The value
|
|
1034
|
-
* type of the resulting {@link Param} is the **union of the literals**, so it
|
|
1035
|
-
* is preserved precisely in the IR and the inferred definition types.
|
|
1036
|
-
*
|
|
1037
|
-
* @example
|
|
1038
|
-
* ```ts
|
|
1039
|
-
* param.literal('active', 'disabled'); // Param<'active' | 'disabled'>
|
|
1040
|
-
* ```
|
|
1041
|
-
*/
|
|
1042
|
-
readonly literal: <const L extends readonly [ParamValue, ...ParamValue[]]>(...values: L) => LiteralParam<L[number]>;
|
|
1043
|
-
/**
|
|
1044
|
-
* A placeholder for an **array** parameter whose elements have the given field
|
|
1045
|
-
* shape. Used by `defineTransaction`'s `tx.forEach(p.<arrayParam>, …)` to bind
|
|
1046
|
-
* each element's fields to `{item.<field>}` templates.
|
|
1047
|
-
*
|
|
1048
|
-
* @example
|
|
1049
|
-
* ```ts
|
|
1050
|
-
* param.array({ userId: param.string(), role: param.string() });
|
|
1051
|
-
* // Param<{ userId: string; role: string }[]>
|
|
1052
|
-
* ```
|
|
1053
|
-
*/
|
|
1054
|
-
readonly array: <const E extends ArrayElementShape>(element: E) => ArrayParam<E>;
|
|
1055
|
-
};
|
|
1056
|
-
/** Runtime type guard: is `value` a parameter placeholder? */
|
|
1057
|
-
declare function isParam(value: unknown): value is Param<unknown>;
|
|
1058
|
-
|
|
1059
1088
|
/**
|
|
1060
1089
|
* Intermediate representation (IR) produced by the parameterized definition DSL
|
|
1061
1090
|
* (issue #41). This is the **in-memory, typed** representation consumed by the
|
|
@@ -1092,18 +1121,48 @@ type OperationKind = 'query' | 'list' | 'put' | 'update' | 'delete';
|
|
|
1092
1121
|
* - `{ field: value, … }` → field equality (`#f = :v AND …`). Each value may be
|
|
1093
1122
|
* a concrete literal **or** a {@link Param} placeholder (bound at execution).
|
|
1094
1123
|
*
|
|
1095
|
-
* The forms are mutually exclusive: `notExists` / `attributeExists` /
|
|
1124
|
+
* The existence forms are mutually exclusive: `notExists` / `attributeExists` /
|
|
1096
1125
|
* `attributeNotExists` are single-primitive conditions and ignore any sibling
|
|
1097
1126
|
* fields. (When more than one would be present the most specific is taken in the
|
|
1098
1127
|
* order `notExists` → `attributeExists` → `attributeNotExists`.)
|
|
1099
|
-
|
|
1128
|
+
*
|
|
1129
|
+
* Beyond bare equality, a field value may be a declarative **operator object**
|
|
1130
|
+
* (issue #114-A) — `{ gt }`, `{ between }`, `{ in }`, `{ beginsWith }`, … —
|
|
1131
|
+
* mirroring the read-side `FilterInput`, and the reserved `and` / `or` (arrays)
|
|
1132
|
+
* / `not` (single nested condition) keys express logical groups. Each operand
|
|
1133
|
+
* value may be a concrete literal or a {@link Param} placeholder.
|
|
1134
|
+
*/
|
|
1135
|
+
type ConditionLeaf = Param<unknown> | string | number | boolean | Date;
|
|
1136
|
+
/** A declarative operator object on one condition field (subset of FilterInput). */
|
|
1137
|
+
interface ConditionOperatorObject {
|
|
1138
|
+
readonly eq?: ConditionLeaf;
|
|
1139
|
+
readonly ne?: ConditionLeaf;
|
|
1140
|
+
readonly gt?: ConditionLeaf;
|
|
1141
|
+
readonly ge?: ConditionLeaf;
|
|
1142
|
+
readonly lt?: ConditionLeaf;
|
|
1143
|
+
readonly le?: ConditionLeaf;
|
|
1144
|
+
readonly between?: readonly [ConditionLeaf, ConditionLeaf];
|
|
1145
|
+
readonly in?: readonly ConditionLeaf[];
|
|
1146
|
+
readonly beginsWith?: ConditionLeaf;
|
|
1147
|
+
readonly contains?: ConditionLeaf;
|
|
1148
|
+
readonly notContains?: ConditionLeaf;
|
|
1149
|
+
readonly attributeExists?: boolean;
|
|
1150
|
+
readonly attributeType?: string;
|
|
1151
|
+
}
|
|
1100
1152
|
type ConditionInput = {
|
|
1101
1153
|
readonly notExists: true;
|
|
1102
1154
|
} | {
|
|
1103
1155
|
readonly attributeExists: string;
|
|
1104
1156
|
} | {
|
|
1105
1157
|
readonly attributeNotExists: string;
|
|
1106
|
-
} |
|
|
1158
|
+
} | RawCondition | ConditionTree;
|
|
1159
|
+
/** A recursive declarative condition tree (field clauses + logical groups). */
|
|
1160
|
+
interface ConditionTree {
|
|
1161
|
+
readonly and?: readonly ConditionInput[];
|
|
1162
|
+
readonly or?: readonly ConditionInput[];
|
|
1163
|
+
readonly not?: ConditionInput;
|
|
1164
|
+
readonly [field: string]: ConditionLeaf | ConditionOperatorObject | readonly ConditionInput[] | ConditionInput | undefined;
|
|
1165
|
+
}
|
|
1107
1166
|
/** Options accepted by the write `define*` entry points (issue #46). */
|
|
1108
1167
|
interface WriteDefinitionOptions {
|
|
1109
1168
|
/** Optional declarative write condition (subset). */
|
|
@@ -1954,6 +2013,16 @@ type WriteOperationType = 'PutItem' | 'UpdateItem' | 'DeleteItem';
|
|
|
1954
2013
|
* named attribute must be absent (field-level uniqueness / first-write guard).
|
|
1955
2014
|
* - `{ kind: 'equals'; fields }` → `#f = :v AND …` field equality (each value a
|
|
1956
2015
|
* `{param}` / literal template).
|
|
2016
|
+
* - `{ kind: 'expr'; declarative }` → the full declarative operator tree (issue
|
|
2017
|
+
* #114-A): comparison (`gt`/`ge`/`lt`/`le`/`ne`), `between`, `in`,
|
|
2018
|
+
* `begins_with`/`contains`/`notContains`, `attributeType`, and the logical
|
|
2019
|
+
* `and`/`or`/`not` groups, mirroring the read-side {@link FilterSpec}. The tree
|
|
2020
|
+
* is JSON-safe: each leaf value is either a native literal (string / number /
|
|
2021
|
+
* boolean) or a {@link ConditionParamLeaf} (`{ $param }`) marking a caller
|
|
2022
|
+
* param bound at execution time. The runtime resolves the param leaves against
|
|
2023
|
+
* the caller params, then compiles the tree to a DynamoDB `ConditionExpression`
|
|
2024
|
+
* with the SAME mechanics the filter compiler uses (so TS and Python emit an
|
|
2025
|
+
* identical expression / semantics).
|
|
1957
2026
|
*/
|
|
1958
2027
|
type ConditionSpec = {
|
|
1959
2028
|
readonly kind: 'notExists';
|
|
@@ -1966,6 +2035,30 @@ type ConditionSpec = {
|
|
|
1966
2035
|
} | {
|
|
1967
2036
|
readonly kind: 'equals';
|
|
1968
2037
|
readonly fields: Readonly<Record<string, string>>;
|
|
2038
|
+
} | {
|
|
2039
|
+
readonly kind: 'expr';
|
|
2040
|
+
readonly declarative: unknown;
|
|
2041
|
+
} | {
|
|
2042
|
+
/**
|
|
2043
|
+
* A raw DynamoDB condition produced by the `cond` escape hatch (issue
|
|
2044
|
+
* #114-B), for write conditions that the declarative operator subset
|
|
2045
|
+
* cannot express. It is **pre-compiled and deterministic**: the
|
|
2046
|
+
* `expression` is a finished DynamoDB `ConditionExpression` whose name
|
|
2047
|
+
* placeholders are stable `#cr_<field>` aliases (reused per distinct
|
|
2048
|
+
* column) and whose value placeholders are sequential `:cr0`, `:cr1`, …
|
|
2049
|
+
* (assigned in template order), so the serialized golden is stable. The
|
|
2050
|
+
* names map binds each `#cr_<field>` alias to its entity field; the values
|
|
2051
|
+
* map binds each `:crN` alias to either a native literal (an embedded
|
|
2052
|
+
* `cond` value — in-process the concrete value) or a {@link ConditionParamLeaf}
|
|
2053
|
+
* (`{ $param }`) marker bound from a caller param at execution time (the
|
|
2054
|
+
* public-contract slot). The runtime substitutes the param leaves, then
|
|
2055
|
+
* attaches `expression` / `names` / serialized `values` to the write —
|
|
2056
|
+
* TS and Python build the identical DynamoDB expression.
|
|
2057
|
+
*/
|
|
2058
|
+
readonly kind: 'raw';
|
|
2059
|
+
readonly expression: string;
|
|
2060
|
+
readonly names: Readonly<Record<string, string>>;
|
|
2061
|
+
readonly values: Readonly<Record<string, unknown>>;
|
|
1969
2062
|
};
|
|
1970
2063
|
interface CommandSpec {
|
|
1971
2064
|
readonly type: WriteOperationType;
|
|
@@ -4511,4 +4604,4 @@ interface CdcEmulatorOptions {
|
|
|
4511
4604
|
}
|
|
4512
4605
|
type ShardId = string;
|
|
4513
4606
|
|
|
4514
|
-
export { type
|
|
4607
|
+
export { type AnyOperationDefinition as $, type StrictSelectSpec as A, type BatchGetExecInput as B, type ChangeEvent as C, type DynamoDBOperation as D, type Executor as E, type FaultSpec as F, type EntityInput as G, type UniqueQueryKeyOf as H, type EntityRef as I, type ConditionInput as J, type QueryMethodSpec as K, type CommandModelContract as L, type ModelStatic as M, type CommandMethodSpec as N, type OperationDefinition as O, type PutInput as P, type QueryModelContract as Q, type RawCondition as R, type SelectableOf as S, type TransactWriteExecItem as T, type UpdateInput as U, type ContractSpec as V, type WriteExecOptions as W, type QuerySpec as X, type CommandSpec as Y, type ContextSpec as Z, type OperationsDocument as _, type ExecutorResult as a, type InProcessWriteDescriptor as a$, type BridgeBundle as a0, type ConditionSpec as a1, type BatchDeleteRequest as a2, type BatchGetRequest as a3, BatchGetResult as a4, type BatchPutRequest as a5, type BatchResult as a6, type BatchWriteRequest as a7, CONTRACT_RANGE_FANOUT_CONCURRENCY as a8, type CdcMode as a9, type ContractKeyInput as aA, type ContractKeyRef as aB, type ContractKeySpec as aC, type ContractKind as aD, type ContractMethodOp as aE, type ContractParamRef as aF, type ContractQueryParams as aG, type ContractResolution as aH, type DeleteOptions as aI, type DeriveEffect as aJ, type DerivedEdgeWrite as aK, type DerivedUpdate as aL, type DescriptorBinding as aM, ENTITY_WRITES_MARKER as aN, type EdgeEffect as aO, type EffectPath as aP, type EmitEffect as aQ, type EntityWritesDefinition as aR, type EntityWritesShape as aS, type ExecutableCommandContract as aT, type ExecutableQueryContract as aU, type FilterInput as aV, type FilterSpec as aW, type FragmentInput as aX, type GsiDefinitionMarker as aY, type GsiOptions as aZ, type IdempotencyEffect as a_, type ChangeBatch as aa, type ChangeEventName as ab, type ClockMode as ac, type Column as ad, type ColumnMap as ae, type CommandContractMethodSpec as af, type CommandInputShape as ag, type CommandMethod as ah, type CommandPlan as ai, type CommandResolutionTarget as aj, type CommandResultKind as ak, type CommandSelectShape as al, type CompiledFragment as am, type ComposeSpec as an, type CondSlot as ao, type ConditionCheckInput as ap, type Connection as aq, type ContractCallSignature as ar, type ContractCardinality as as, type ContractCommandParams as at, type ContractCommandResult as au, type ContractComposeNode as av, type ContractFromRef as aw, type ContractInputArity as ax, type ContractItem as ay, type ContractKeyFieldRef as az, type WriteResult as b, type UniqueEffect as b$, type InputArity as b0, type KeyDefinitionMarker as b1, type KeySegment as b2, type KeySlot as b3, type KeyStructure as b4, type KeyedResult as b5, LIFECYCLE_CONTRACT_MARKER as b6, type LifecycleContract as b7, type LifecycleEffects as b8, type LiteralParam as b9, type PutOptions as bA, type QueryContractMethodSpec as bB, type QueryEnvelopeResult as bC, type QueryKeyOf as bD, type QueryMethod as bE, type QueryResult as bF, type RangeConditionSpec as bG, type ReadEnvelope as bH, type ReadOperationType as bI, type ReadRouteDescriptor as bJ, type ReadRouteOptions as bK, type ReadRouteResult as bL, type RecordedCompose as bM, type RelationBuilder as bN, type RelationSelect as bO, type RelationSpec as bP, type RequiresEffect as bQ, type Resolution as bR, SPEC_VERSION as bS, type SegmentSpec as bT, type SelectBuilder as bU, type SelectOf as bV, type StartingPosition as bW, type StreamViewType as bX, type StringParam as bY, TransactionContext as bZ, type TransactionItemType as b_, type ManifestEntity as ba, type ManifestField as bb, type ManifestFieldType as bc, type ManifestGsi as bd, type ManifestKey as be, type ManifestRelation as bf, type ManifestTable as bg, type ModelRef as bh, type MutateMode as bi, type MutateOptions as bj, type MutateParallelResult as bk, type MutateTransactionResult as bl, type MutationBody as bm, type MutationDescriptorMap as bn, type MutationFragment as bo, type MutationInputProxy as bp, type MutationInputRef as bq, type MutationIntent as br, type NumberParam as bs, type OperationKind as bt, type OperationSpec as bu, type ParallelOpResult as bv, type ParamKind as bw, type ParamSpec as bx, type ParamStructure as by, type PlannedCommandMethod as bz, type DeleteInput as c, type Updatable as c0, type UpdateOptions as c1, type WhenSpec as c2, type WriteDescriptor as c3, type WriteEnvelope as c4, type WriteLifecyclePhase as c5, type WriteOperationType as c6, type WriteRecorder as c7, type WriteResultProjection as c8, attachModelClass as c9, isContractComposeNode as cA, isContractFromRef as cB, isContractKeyFieldRef as cC, isContractKeyRef as cD, isContractParamRef as cE, isEntityWritesDefinition as cF, isKeySegment as cG, isLifecycleContract as cH, isMutationFragment as cI, isMutationInputRef as cJ, isParam as cK, isPlannedCommandMethod as cL, isQueryModelContract as cM, k as cN, key as cO, lifecyclePhaseForIntent as cP, mintContractKeyFieldRef as cQ, mintContractParamRef as cR, mutation as cS, param as cT, publicCommandModel as cU, publicQueryModel as cV, query as cW, resolveLifecycle as cX, wholeKeysSentinel as cY, buildDeleteInput as ca, buildPutInput as cb, buildUpdateInput as cc, compileFragment as cd, compileMutationPlan as ce, compileSingleFragmentPlan as cf, cond as cg, contractOfMethodSpec as ch, definePlan as ci, entityWrites as cj, executeBatchGet as ck, executeBatchWrite as cl, executeCommandMethod as cm, executeDelete as cn, executeKeyedBatchGet as co, executePut as cp, executeQueryMethod as cq, executeRangeFanout as cr, executeTransaction as cs, executeUpdate as ct, from as cu, getEntityWrites as cv, gsi as cw, isColumn as cx, isCommandModelContract as cy, isCommandPlan as cz, type BatchWriteExecItem as d, DDBModel as e, type PrimaryKeyOf as f, type ExecutionPlanSpec as g, type SegmentedKey as h, type SelectBuilderSpec as i, type TransactionSpec as j, type Manifest as k, type ExecutionPlan as l, type ResolvedKey as m, type CdcEmulatorOptions as n, type ChangeHandler as o, type Unsubscribe as p, type ConcurrentRecomputeRef as q, type EventLog as r, type ReplayOptions as s, type ShardId as t, type TransactionItemSpec as u, type Param as v, type ParamDescriptor as w, type DefinitionMap as x, type WriteDefinitionOptions as y, type PartialQueryKeyOf as z };
|