graphddb 0.9.0 → 0.9.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/dist/cdc/index.d.ts +4 -4
- package/dist/cdc/index.js +3 -3
- package/dist/{chunk-KOIJ4SNO.js → chunk-7OCXY4R6.js} +1 -1
- package/dist/{chunk-ZNU7OI5I.js → chunk-GWWRXIHF.js} +19 -4
- package/dist/{chunk-XZTA4VJH.js → chunk-HLFNCKFV.js} +84 -6
- package/dist/{chunk-SSVG6NQK.js → chunk-MBJ4JVRM.js} +28 -12
- package/dist/{chunk-NWTEUWJD.js → chunk-PHXUFAY2.js} +2 -2
- package/dist/{chunk-YGQ2NO6J.js → chunk-VECUS35D.js} +2 -2
- package/dist/cli.js +5 -5
- package/dist/index.d.ts +4 -4
- package/dist/index.js +3 -3
- package/dist/internal/index.d.ts +5 -5
- package/dist/internal/index.js +4 -4
- package/dist/{key-Dne-a20Q.d.ts → key-CWytoEaE.d.ts} +54 -1
- package/dist/linter/index.d.ts +5 -5
- package/dist/{linter-Cr1Hnw7n.d.ts → linter-jEwmZotm.d.ts} +1 -1
- package/dist/{prepared-artifact-BXkARxwO.d.ts → prepared-artifact-CwH5ezFq.d.ts} +3 -3
- package/dist/spec/index.d.ts +8 -8
- package/dist/spec/index.js +5 -5
- package/dist/testing/index.d.ts +2 -2
- package/dist/testing/index.js +32 -5
- package/dist/transform/index.d.ts +1 -1
- package/dist/transform/index.js +1 -1
- package/dist/{types-CfxzTEFL.d.ts → types-CgXS-4Ox.d.ts} +37 -8
- package/dist/{types-BnFsTZwl.d.ts → types-nk5okD7d.d.ts} +1 -1
- package/package.json +1 -1
package/dist/cdc/index.d.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import { w as CdcEmulatorOptions, x as ChangeHandler, y as Unsubscribe, F as FaultSpec, z as ConcurrentRecomputeRef, v as ChangeEvent, A as EventLog, G as ReplayOptions, H as ShardId, I as MaintainTrigger, E as EffectPath, g as ProjectionMap, j as MembershipPredicate } from '../key-
|
|
2
|
-
export { J as BatchResult, K as CdcMode, L as ChangeBatch, N as ChangeEventName, O as ClockMode, V as StartingPosition, X as StreamViewType, Y as SubscribeHandler, Z as SubscribeHandlers, _ as buildSubscribeHandler } from '../key-
|
|
3
|
-
import { E as EntityMetadata } from '../types-
|
|
4
|
-
import '../types-
|
|
1
|
+
import { w as CdcEmulatorOptions, x as ChangeHandler, y as Unsubscribe, F as FaultSpec, z as ConcurrentRecomputeRef, v as ChangeEvent, A as EventLog, G as ReplayOptions, H as ShardId, I as MaintainTrigger, E as EffectPath, g as ProjectionMap, j as MembershipPredicate } from '../key-CWytoEaE.js';
|
|
2
|
+
export { J as BatchResult, K as CdcMode, L as ChangeBatch, N as ChangeEventName, O as ClockMode, V as StartingPosition, X as StreamViewType, Y as SubscribeHandler, Z as SubscribeHandlers, _ as buildSubscribeHandler } from '../key-CWytoEaE.js';
|
|
3
|
+
import { E as EntityMetadata } from '../types-nk5okD7d.js';
|
|
4
|
+
import '../types-CgXS-4Ox.js';
|
|
5
5
|
import 'behavior-contracts';
|
|
6
6
|
|
|
7
7
|
/**
|
package/dist/cdc/index.js
CHANGED
|
@@ -8,12 +8,12 @@ import {
|
|
|
8
8
|
createMaintenanceDrainHandler,
|
|
9
9
|
hashString,
|
|
10
10
|
shardIdFor
|
|
11
|
-
} from "../chunk-
|
|
11
|
+
} from "../chunk-VECUS35D.js";
|
|
12
12
|
import {
|
|
13
13
|
buildSubscribeHandler,
|
|
14
14
|
parseChange
|
|
15
|
-
} from "../chunk-
|
|
16
|
-
import "../chunk-
|
|
15
|
+
} from "../chunk-7OCXY4R6.js";
|
|
16
|
+
import "../chunk-GWWRXIHF.js";
|
|
17
17
|
import "../chunk-XTWXMOHD.js";
|
|
18
18
|
export {
|
|
19
19
|
CdcEmulator,
|
|
@@ -2070,9 +2070,21 @@ function buildUpdateInput(modelClass, entity, changes, options) {
|
|
|
2070
2070
|
const embeddedFieldNames = new Set(
|
|
2071
2071
|
meta.embeddedFields.map((e) => e.propertyName)
|
|
2072
2072
|
);
|
|
2073
|
-
const
|
|
2074
|
-
const
|
|
2075
|
-
const
|
|
2073
|
+
const addEntries = Object.entries(options?.add ?? {});
|
|
2074
|
+
const addNames = {};
|
|
2075
|
+
const addValues = {};
|
|
2076
|
+
const addClauses = [];
|
|
2077
|
+
addEntries.forEach(([field, delta], i) => {
|
|
2078
|
+
const nameKey = `#add${i}`;
|
|
2079
|
+
const valueKey = `:add${i}`;
|
|
2080
|
+
addNames[nameKey] = field;
|
|
2081
|
+
addValues[valueKey] = delta;
|
|
2082
|
+
addClauses.push(`${nameKey} ${valueKey}`);
|
|
2083
|
+
});
|
|
2084
|
+
const hasChanges = Object.keys(serializedChanges).length > 0;
|
|
2085
|
+
const updateResult = hasChanges || addClauses.length === 0 ? buildUpdateExpression(serializedChanges, embeddedFieldNames) : { expression: "", names: {}, values: {} };
|
|
2086
|
+
const names = { ...updateResult.names, ...addNames };
|
|
2087
|
+
const values = { ...updateResult.values, ...addValues };
|
|
2076
2088
|
const gsiSetClauses = buildGsiRederiveSets(
|
|
2077
2089
|
modelClass,
|
|
2078
2090
|
meta,
|
|
@@ -2090,13 +2102,16 @@ function buildUpdateInput(modelClass, entity, changes, options) {
|
|
|
2090
2102
|
Object.assign(names, condResult.names);
|
|
2091
2103
|
Object.assign(values, condResult.values);
|
|
2092
2104
|
}
|
|
2105
|
+
const setPortion = appendSetClauses(updateResult.expression, gsiSetClauses);
|
|
2106
|
+
const addPortion = addClauses.length > 0 ? `ADD ${addClauses.join(", ")}` : "";
|
|
2107
|
+
const updateExpression = [setPortion, addPortion].filter((s) => s !== "").join(" ");
|
|
2093
2108
|
const updateInput = {
|
|
2094
2109
|
TableName: tableName,
|
|
2095
2110
|
Key: {
|
|
2096
2111
|
PK: pk,
|
|
2097
2112
|
SK: sk
|
|
2098
2113
|
},
|
|
2099
|
-
UpdateExpression:
|
|
2114
|
+
UpdateExpression: updateExpression,
|
|
2100
2115
|
ExpressionAttributeNames: names
|
|
2101
2116
|
};
|
|
2102
2117
|
if (Object.keys(values).length > 0) {
|
|
@@ -17,7 +17,7 @@ import {
|
|
|
17
17
|
normalizeTopLevelSelect,
|
|
18
18
|
parseChange,
|
|
19
19
|
validateInlineSnapshotSelect
|
|
20
|
-
} from "./chunk-
|
|
20
|
+
} from "./chunk-7OCXY4R6.js";
|
|
21
21
|
import {
|
|
22
22
|
EXPR_VERSION,
|
|
23
23
|
MARKER_ROW_ENTITY,
|
|
@@ -61,7 +61,7 @@ import {
|
|
|
61
61
|
serializeFieldValue,
|
|
62
62
|
serializeRawCondition,
|
|
63
63
|
skTemplate
|
|
64
|
-
} from "./chunk-
|
|
64
|
+
} from "./chunk-GWWRXIHF.js";
|
|
65
65
|
import {
|
|
66
66
|
TableMapping,
|
|
67
67
|
createColumnMap,
|
|
@@ -2520,7 +2520,12 @@ function renderWrite(op, key, params, contextLabel) {
|
|
|
2520
2520
|
return { ...base, item: renderRecord(op.item, key, params, `${contextLabel} item`) };
|
|
2521
2521
|
}
|
|
2522
2522
|
if (op.operation === "update") {
|
|
2523
|
-
|
|
2523
|
+
const add = op.add !== void 0 && Object.keys(op.add).length > 0 ? renderRecord(op.add, key, params, `${contextLabel} add`) : void 0;
|
|
2524
|
+
return {
|
|
2525
|
+
...base,
|
|
2526
|
+
changes: renderRecord(op.changes, key, params, `${contextLabel} changes`),
|
|
2527
|
+
...add !== void 0 ? { add } : {}
|
|
2528
|
+
};
|
|
2524
2529
|
}
|
|
2525
2530
|
return base;
|
|
2526
2531
|
}
|
|
@@ -2534,11 +2539,34 @@ async function executeSingleWrite(w, retry) {
|
|
|
2534
2539
|
return;
|
|
2535
2540
|
}
|
|
2536
2541
|
if (w.operation === "update") {
|
|
2542
|
+
if (w.add !== void 0) {
|
|
2543
|
+
const primaryOptions = { ...options ?? {}, add: w.add };
|
|
2544
|
+
if (w.condition === void 0) {
|
|
2545
|
+
await executeUpdate(w.modelClass, w.key, w.changes ?? {}, primaryOptions);
|
|
2546
|
+
return;
|
|
2547
|
+
}
|
|
2548
|
+
try {
|
|
2549
|
+
await executeUpdate(w.modelClass, w.key, w.changes ?? {}, primaryOptions);
|
|
2550
|
+
} catch (e) {
|
|
2551
|
+
if (!isConditionalCheckFailure(e)) throw e;
|
|
2552
|
+
const fallbackOptions = {
|
|
2553
|
+
add: w.add,
|
|
2554
|
+
...retry !== void 0 ? { retry } : {}
|
|
2555
|
+
};
|
|
2556
|
+
await executeUpdate(w.modelClass, w.key, {}, fallbackOptions);
|
|
2557
|
+
}
|
|
2558
|
+
return;
|
|
2559
|
+
}
|
|
2537
2560
|
await executeUpdate(w.modelClass, w.key, w.changes ?? {}, options);
|
|
2538
2561
|
return;
|
|
2539
2562
|
}
|
|
2540
2563
|
await executeDelete(w.modelClass, w.key, options);
|
|
2541
2564
|
}
|
|
2565
|
+
function isConditionalCheckFailure(e) {
|
|
2566
|
+
if (e === null || typeof e !== "object") return false;
|
|
2567
|
+
const name = e.name;
|
|
2568
|
+
return name === "ConditionalCheckFailedException" || name === "ConditionalCheckFailed";
|
|
2569
|
+
}
|
|
2542
2570
|
function renderConditionCheck(check, key, params, contextLabel) {
|
|
2543
2571
|
const modelClass = check.entity.modelClass;
|
|
2544
2572
|
const referencedKey = {};
|
|
@@ -4428,8 +4456,17 @@ function isConcreteLiteral(value) {
|
|
|
4428
4456
|
const t = typeof value;
|
|
4429
4457
|
return value === null || value instanceof Date || t === "string" || t === "number" || t === "boolean";
|
|
4430
4458
|
}
|
|
4431
|
-
function makeFragment(intent, entity, input, use, condition) {
|
|
4459
|
+
function makeFragment(intent, entity, input, use, condition, add) {
|
|
4432
4460
|
const checked = assertFaithfulInput(input ?? {}, intent, entity.name);
|
|
4461
|
+
let checkedAdd;
|
|
4462
|
+
if (add !== void 0 && Object.keys(add).length > 0) {
|
|
4463
|
+
if (intent !== "update") {
|
|
4464
|
+
throw new Error(
|
|
4465
|
+
`mutation: the '${intent}' fragment on '${entity.name}' declares \`add\`, but an atomic \`ADD\` (issue #301) is only valid on an \`update\` fragment.`
|
|
4466
|
+
);
|
|
4467
|
+
}
|
|
4468
|
+
checkedAdd = assertFaithfulInput(add, intent, entity.name);
|
|
4469
|
+
}
|
|
4433
4470
|
if (use !== void 0 && !isEntityWritesDefinition(use)) {
|
|
4434
4471
|
throw new Error(
|
|
4435
4472
|
`mutation: the '${intent}' fragment on '${entity.name}' was given a \`use:\` that is not an \`entityWrites(...)\` save contract. \`use:\` takes the WHOLE \`writes\` set (an \`entityWrites(...)\` value), never a single lifecycle (e.g. \`Model.writes.create\`) \u2014 the fragment's intent already selects the lifecycle.`
|
|
@@ -4441,6 +4478,7 @@ function makeFragment(intent, entity, input, use, condition) {
|
|
|
4441
4478
|
intent,
|
|
4442
4479
|
entity,
|
|
4443
4480
|
input: checked,
|
|
4481
|
+
...checkedAdd !== void 0 ? { add: checkedAdd } : {},
|
|
4444
4482
|
...use !== void 0 ? { use } : {},
|
|
4445
4483
|
...checkedCondition !== void 0 ? { condition: checkedCondition } : {}
|
|
4446
4484
|
};
|
|
@@ -4536,7 +4574,8 @@ function mutation(nameOrBody, maybeBody) {
|
|
|
4536
4574
|
const { intent, entity } = resolveDescriptorTarget(descriptor, alias);
|
|
4537
4575
|
const merged = mergeBindings(descriptor, intent, alias);
|
|
4538
4576
|
const resolved = resolveAliasRefs(merged, aliasToIndex, alias);
|
|
4539
|
-
|
|
4577
|
+
const add = descriptor.add !== void 0 ? resolveAliasRefs(descriptor.add, aliasToIndex, alias) : void 0;
|
|
4578
|
+
return makeFragment(intent, entity, resolved, descriptor.use, descriptor.condition, add);
|
|
4540
4579
|
});
|
|
4541
4580
|
return { [COMMAND_PLAN_BRAND]: true, name, fragments };
|
|
4542
4581
|
}
|
|
@@ -5007,6 +5046,35 @@ function writeDescriptorToPlan(name, d) {
|
|
|
5007
5046
|
const model = resolveDescriptorModel(d[intent], name);
|
|
5008
5047
|
const keyFieldNames = Object.keys(d.key);
|
|
5009
5048
|
const inputFieldNames = d.input !== void 0 ? Object.keys(d.input) : [];
|
|
5049
|
+
const addFieldNames = d.add !== void 0 ? Object.keys(d.add) : [];
|
|
5050
|
+
if (addFieldNames.length > 0) {
|
|
5051
|
+
if (intent !== "update") {
|
|
5052
|
+
throw new Error(
|
|
5053
|
+
`publishCommand: method '${name}' declares \`add\` on a '${intent}' descriptor, but an atomic \`ADD\` (issue #301) is only valid on an \`update\` (a standalone UpdateItem). A create / upsert / remove cannot carry \`add\`.`
|
|
5054
|
+
);
|
|
5055
|
+
}
|
|
5056
|
+
if (d.add === null || typeof d.add !== "object") {
|
|
5057
|
+
throw new Error(`publishCommand: method '${name}' has a non-object \`add\`.`);
|
|
5058
|
+
}
|
|
5059
|
+
for (const field of addFieldNames) {
|
|
5060
|
+
const v = d.add[field];
|
|
5061
|
+
if (!isParam(v) || v.kind !== "number") {
|
|
5062
|
+
throw new Error(
|
|
5063
|
+
`publishCommand: method '${name}' binds \`add.${field}\` to a non-\`param.number()\` value. An atomic \`ADD\` delta (issue #301) is a caller \`param.number()\` \u2014 a compile-time constant or a non-numeric param is not a valid atomic increment.`
|
|
5064
|
+
);
|
|
5065
|
+
}
|
|
5066
|
+
if (keyFieldNames.includes(field)) {
|
|
5067
|
+
throw new Error(
|
|
5068
|
+
`publishCommand: method '${name}' binds field '${field}' in both \`key\` and \`add\`. A primary-key field cannot be atomically incremented \u2014 it belongs in \`key\` only.`
|
|
5069
|
+
);
|
|
5070
|
+
}
|
|
5071
|
+
if (inputFieldNames.includes(field)) {
|
|
5072
|
+
throw new Error(
|
|
5073
|
+
`publishCommand: method '${name}' binds field '${field}' in both \`input\` (SET) and \`add\` (ADD). A field is either overwritten (\`input\`) or atomically incremented (\`add\`), never both.`
|
|
5074
|
+
);
|
|
5075
|
+
}
|
|
5076
|
+
}
|
|
5077
|
+
}
|
|
5010
5078
|
const plan2 = mutation(name, ($) => {
|
|
5011
5079
|
const keyRefs = (fields) => {
|
|
5012
5080
|
const out = {};
|
|
@@ -5024,7 +5092,10 @@ function writeDescriptorToPlan(name, d) {
|
|
|
5024
5092
|
const descriptor = {
|
|
5025
5093
|
[intent]: (() => model),
|
|
5026
5094
|
key: keyRefs(keyFieldNames),
|
|
5027
|
-
...inputFieldNames.length > 0 ? { input: inputRefs(d.input) } : {}
|
|
5095
|
+
...inputFieldNames.length > 0 ? { input: inputRefs(d.input) } : {},
|
|
5096
|
+
// #301: `add` deltas are always `param.number()` (validated above), so each binds
|
|
5097
|
+
// to a same-named `$.field` placeholder — the runtime resolves the caller delta.
|
|
5098
|
+
...addFieldNames.length > 0 ? { add: keyRefs(addFieldNames) } : {}
|
|
5028
5099
|
};
|
|
5029
5100
|
return { [name]: descriptor };
|
|
5030
5101
|
});
|
|
@@ -5798,6 +5869,12 @@ function compileFragment(fragment, index = 0, resolveEntityRef = null, maintenan
|
|
|
5798
5869
|
if (keyFieldSet.has(field)) continue;
|
|
5799
5870
|
changes[field] = renderInputLeaf(leaf, false, index, field, resolveEntityRef);
|
|
5800
5871
|
}
|
|
5872
|
+
const add = {};
|
|
5873
|
+
if (fragment.add !== void 0) {
|
|
5874
|
+
for (const [field, leaf] of Object.entries(fragment.add)) {
|
|
5875
|
+
add[field] = renderInputLeaf(leaf, false, index, field, resolveEntityRef);
|
|
5876
|
+
}
|
|
5877
|
+
}
|
|
5801
5878
|
op = {
|
|
5802
5879
|
__isContractMethodOp: true,
|
|
5803
5880
|
entity: fragment.entity,
|
|
@@ -5805,6 +5882,7 @@ function compileFragment(fragment, index = 0, resolveEntityRef = null, maintenan
|
|
|
5805
5882
|
keys: wholeKeysSentinel(),
|
|
5806
5883
|
keyFields,
|
|
5807
5884
|
...fragment.intent === "update" ? { changes } : {},
|
|
5885
|
+
...fragment.intent === "update" && Object.keys(add).length > 0 ? { add } : {},
|
|
5808
5886
|
// #242: a conditioned update / remove — the write is a CAS-style gate (the
|
|
5809
5887
|
// row must satisfy the condition or the write is rejected, not silently
|
|
5810
5888
|
// committed). Absent → an unconditional update / remove (unchanged).
|
|
@@ -2,7 +2,7 @@ import {
|
|
|
2
2
|
PREPARED_FORMAT_VERSION,
|
|
3
3
|
buildManifest,
|
|
4
4
|
entityFingerprint
|
|
5
|
-
} from "./chunk-
|
|
5
|
+
} from "./chunk-PHXUFAY2.js";
|
|
6
6
|
import {
|
|
7
7
|
analyzeWriteRoute,
|
|
8
8
|
assertBundleSerializable,
|
|
@@ -21,12 +21,12 @@ import {
|
|
|
21
21
|
isContractKeyRef,
|
|
22
22
|
isContractParamRef,
|
|
23
23
|
isQueryModelContract
|
|
24
|
-
} from "./chunk-
|
|
24
|
+
} from "./chunk-HLFNCKFV.js";
|
|
25
25
|
import {
|
|
26
26
|
detectRelationFields,
|
|
27
27
|
isInlineSnapshotSpec,
|
|
28
28
|
normalizeSelectSpec
|
|
29
|
-
} from "./chunk-
|
|
29
|
+
} from "./chunk-7OCXY4R6.js";
|
|
30
30
|
import {
|
|
31
31
|
EXPR_VERSION,
|
|
32
32
|
MARKER_ROW_ENTITY,
|
|
@@ -46,7 +46,7 @@ import {
|
|
|
46
46
|
isRawCondition,
|
|
47
47
|
param,
|
|
48
48
|
resolveModelClass
|
|
49
|
-
} from "./chunk-
|
|
49
|
+
} from "./chunk-GWWRXIHF.js";
|
|
50
50
|
import {
|
|
51
51
|
TableMapping,
|
|
52
52
|
isColumn,
|
|
@@ -232,6 +232,7 @@ function opToDefinition(contractName, methodName, op) {
|
|
|
232
232
|
}
|
|
233
233
|
const select = op.select !== void 0 ? assertBooleanProjection(op.select, `${contractName}.${methodName} select`) : void 0;
|
|
234
234
|
const changes = op.changes !== void 0 ? convertStructure(op.changes, place, `${contractName}.${methodName} changes`) : void 0;
|
|
235
|
+
const add = op.add !== void 0 ? convertStructure(op.add, place, `${contractName}.${methodName} add`) : void 0;
|
|
235
236
|
const condition = op.condition !== void 0 ? convertCondition(op.condition, place, `${contractName}.${methodName} condition`) : void 0;
|
|
236
237
|
return {
|
|
237
238
|
__isOperationDefinition: true,
|
|
@@ -240,6 +241,7 @@ function opToDefinition(contractName, methodName, op) {
|
|
|
240
241
|
key,
|
|
241
242
|
select,
|
|
242
243
|
changes,
|
|
244
|
+
...add !== void 0 ? { add } : {},
|
|
243
245
|
...condition !== void 0 ? { condition } : {},
|
|
244
246
|
// #154: the use-case description captured on the recorded op (from the
|
|
245
247
|
// descriptor's `description`) flows into the flattened `queries[op]` /
|
|
@@ -584,6 +586,14 @@ function toElementTemplate(template, keyParams) {
|
|
|
584
586
|
);
|
|
585
587
|
}
|
|
586
588
|
function toElementRecord(record, keyParams) {
|
|
589
|
+
const out = {};
|
|
590
|
+
for (const field of Object.keys(record)) {
|
|
591
|
+
const value = record[field];
|
|
592
|
+
out[field] = typeof value === "string" ? toElementTemplate(value, keyParams) : value;
|
|
593
|
+
}
|
|
594
|
+
return out;
|
|
595
|
+
}
|
|
596
|
+
function toElementKeyRecord(record, keyParams) {
|
|
587
597
|
const out = {};
|
|
588
598
|
for (const field of Object.keys(record)) {
|
|
589
599
|
out[field] = toElementTemplate(record[field], keyParams);
|
|
@@ -636,7 +646,7 @@ function synthesizeBatchTransaction(commandSpec, op) {
|
|
|
636
646
|
tableName: commandSpec.tableName,
|
|
637
647
|
entity: commandSpec.entity,
|
|
638
648
|
...commandSpec.item !== void 0 ? { item: toElementRecord(commandSpec.item, keyParams) } : {},
|
|
639
|
-
...commandSpec.keyCondition !== void 0 ? { keyCondition:
|
|
649
|
+
...commandSpec.keyCondition !== void 0 ? { keyCondition: toElementKeyRecord(commandSpec.keyCondition, keyParams) } : {},
|
|
640
650
|
...commandSpec.changes !== void 0 ? { changes: toElementRecord(commandSpec.changes, keyParams) } : {},
|
|
641
651
|
...condition !== void 0 ? { condition } : {},
|
|
642
652
|
forEach: { source: "keys" }
|
|
@@ -829,8 +839,9 @@ function buildDerivedUpdateItems(derivedUpdates) {
|
|
|
829
839
|
tableName,
|
|
830
840
|
entity: update.entity.name,
|
|
831
841
|
keyCondition,
|
|
832
|
-
// The delta is a compile-time constant → a
|
|
833
|
-
|
|
842
|
+
// The delta is a compile-time constant → a TYPED numeric literal (no param),
|
|
843
|
+
// carried verbatim so it marshals as `N`, not a stringified `S "1"` (#299).
|
|
844
|
+
add: { [update.attribute]: update.amount }
|
|
834
845
|
});
|
|
835
846
|
collectTemplateParams(keyCondition, metadata, params);
|
|
836
847
|
}
|
|
@@ -890,7 +901,8 @@ function buildMaintainWriteItems(maintainWrites) {
|
|
|
890
901
|
...maintain.kind === "counter" && maintain.counter !== void 0 && maintain.counter.op === "count" ? {
|
|
891
902
|
counter: {
|
|
892
903
|
attribute: maintain.counter.attribute,
|
|
893
|
-
delta
|
|
904
|
+
// TYPED numeric delta (#299): carried verbatim so it marshals as `N`.
|
|
905
|
+
delta: maintain.counter.delta
|
|
894
906
|
}
|
|
895
907
|
} : {}
|
|
896
908
|
};
|
|
@@ -1713,7 +1725,7 @@ function conditionPorts(condition, ports) {
|
|
|
1713
1725
|
return;
|
|
1714
1726
|
case "equals": {
|
|
1715
1727
|
for (const field of Object.keys(condition.fields).sort()) {
|
|
1716
|
-
ports[`condition.equals.${field}`] =
|
|
1728
|
+
ports[`condition.equals.${field}`] = lowerTransactionValue(condition.fields[field]);
|
|
1717
1729
|
}
|
|
1718
1730
|
return;
|
|
1719
1731
|
}
|
|
@@ -1882,11 +1894,12 @@ function paramSpecs(params) {
|
|
|
1882
1894
|
function metaFor(def) {
|
|
1883
1895
|
return MetadataRegistry.get(def.entity.modelClass);
|
|
1884
1896
|
}
|
|
1885
|
-
function
|
|
1897
|
+
function templateValueLeaf(key, value) {
|
|
1886
1898
|
if (isContractParamRef(value)) return value.token;
|
|
1887
1899
|
if (isContractKeyFieldRef(value)) return `{${value.field}}`;
|
|
1888
1900
|
if (isParam(value)) return `{${key}}`;
|
|
1889
1901
|
if (value instanceof Date) return value.toISOString();
|
|
1902
|
+
if (typeof value === "number" || typeof value === "boolean") return value;
|
|
1890
1903
|
return String(value);
|
|
1891
1904
|
}
|
|
1892
1905
|
function keyFieldNames(key) {
|
|
@@ -2220,6 +2233,8 @@ function buildCommandSpec(def) {
|
|
|
2220
2233
|
...description
|
|
2221
2234
|
};
|
|
2222
2235
|
}
|
|
2236
|
+
const addStructure = def.add;
|
|
2237
|
+
const add = addStructure !== void 0 && Object.keys(addStructure).length > 0 ? { add: templateRecord(addStructure) } : {};
|
|
2223
2238
|
return {
|
|
2224
2239
|
type: "UpdateItem",
|
|
2225
2240
|
tableName,
|
|
@@ -2227,6 +2242,7 @@ function buildCommandSpec(def) {
|
|
|
2227
2242
|
params,
|
|
2228
2243
|
keyCondition: writeKeyCondition(metadata, def.key, entity),
|
|
2229
2244
|
changes: templateRecord(def.changes),
|
|
2245
|
+
...add,
|
|
2230
2246
|
...condition ? { condition } : {},
|
|
2231
2247
|
...description
|
|
2232
2248
|
};
|
|
@@ -2253,7 +2269,7 @@ function writeKeyCondition(metadata, key, entity) {
|
|
|
2253
2269
|
function templateRecord(structure) {
|
|
2254
2270
|
const out = {};
|
|
2255
2271
|
for (const key of Object.keys(structure).sort()) {
|
|
2256
|
-
out[key] =
|
|
2272
|
+
out[key] = templateValueLeaf(key, structure[key]);
|
|
2257
2273
|
}
|
|
2258
2274
|
return out;
|
|
2259
2275
|
}
|
|
@@ -2261,7 +2277,7 @@ function extractCondition(def) {
|
|
|
2261
2277
|
return conditionInputToSpec(
|
|
2262
2278
|
def.condition,
|
|
2263
2279
|
`Command on '${def.entity.name}'`,
|
|
2264
|
-
(field, value) =>
|
|
2280
|
+
(field, value) => templateValueLeaf(field, value),
|
|
2265
2281
|
(value, name) => conditionTreeLeaf(value, name),
|
|
2266
2282
|
// A raw `cond` value slot (issue #114-B): a contract param / key ref carries
|
|
2267
2283
|
// its own name; a plain `param.*` falls through to the positional default.
|
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
import {
|
|
2
2
|
evaluateKey
|
|
3
|
-
} from "./chunk-
|
|
3
|
+
} from "./chunk-HLFNCKFV.js";
|
|
4
4
|
import {
|
|
5
5
|
SPEC_VERSION_KEY_EXPR
|
|
6
6
|
} from "./chunk-WOFRHRXY.js";
|
|
7
7
|
import {
|
|
8
8
|
MetadataRegistry
|
|
9
|
-
} from "./chunk-
|
|
9
|
+
} from "./chunk-GWWRXIHF.js";
|
|
10
10
|
import {
|
|
11
11
|
TableMapping
|
|
12
12
|
} from "./chunk-XTWXMOHD.js";
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import {
|
|
2
2
|
buildMaintenanceGraph
|
|
3
|
-
} from "./chunk-
|
|
3
|
+
} from "./chunk-7OCXY4R6.js";
|
|
4
4
|
import {
|
|
5
5
|
ChangeCaptureRegistry,
|
|
6
6
|
ClientManager,
|
|
@@ -9,7 +9,7 @@ import {
|
|
|
9
9
|
buildDeleteInput,
|
|
10
10
|
buildPutInput,
|
|
11
11
|
resolveModelClass
|
|
12
|
-
} from "./chunk-
|
|
12
|
+
} from "./chunk-GWWRXIHF.js";
|
|
13
13
|
|
|
14
14
|
// src/cdc/prng.ts
|
|
15
15
|
var SeededRandom = class {
|
package/dist/cli.js
CHANGED
|
@@ -4,16 +4,16 @@ import {
|
|
|
4
4
|
buildOperations,
|
|
5
5
|
portableIrDocument,
|
|
6
6
|
renderKeyExprToTemplate
|
|
7
|
-
} from "./chunk-
|
|
7
|
+
} from "./chunk-MBJ4JVRM.js";
|
|
8
8
|
import {
|
|
9
9
|
buildManifest
|
|
10
|
-
} from "./chunk-
|
|
11
|
-
import "./chunk-
|
|
12
|
-
import "./chunk-
|
|
10
|
+
} from "./chunk-PHXUFAY2.js";
|
|
11
|
+
import "./chunk-HLFNCKFV.js";
|
|
12
|
+
import "./chunk-7OCXY4R6.js";
|
|
13
13
|
import "./chunk-WOFRHRXY.js";
|
|
14
14
|
import {
|
|
15
15
|
MetadataRegistry
|
|
16
|
-
} from "./chunk-
|
|
16
|
+
} from "./chunk-GWWRXIHF.js";
|
|
17
17
|
import {
|
|
18
18
|
createDefaultLinter
|
|
19
19
|
} from "./chunk-XTWXMOHD.js";
|
package/dist/index.d.ts
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
|
-
import { ak as SelectableOf, al as PrimaryKeyOf, e as ProjectionTransform, f as MaintainEvent, j as MembershipPredicate, h as MaintainConsistency, i as MaintainUpdateMode, am as MembershipPredicateOp, an as publishQuery, ao as publishCommand, D as DDBModel, ap as RetryPolicy, aq as Middleware } from './key-
|
|
2
|
-
export { ar as CdcModelRegistry, as as CdcSubscribeHandlers, at as Change, au as Column, av as ColumnMap, aw as CondSlot, ax as CtxBase, ay as CtxModel, az as FilterInput, aA as GsiDefinitionMarker, aB as GsiOptions, aC as InlineSnapshotSpec, aD as Item, aE as KeyDefinitionMarker, aF as KeySegment, aG as KeySlot, aH as KeyStructure, M as ModelStatic, aI as MutateAuthoringOptions, aJ as ParamDescriptor, aK as ParamStructure, aL as PartialQueryKeyOf, aM as PersistCtx, aN as PersistOrigin, aO as QueryKeyOf, aP as QueryResult, aQ as RawCondition, aR as ReadOpCtx, aS as ReadOpKind, aT as ReadParams, aU as ReadRequestCtx, aV as ReadRequestKind, aW as RelationBuilder, aX as RelationSelect, aY as RelationSpec, aZ as RequestContext, a_ as SegmentSpec, d as SegmentedKey, a$ as SelectBuilder, b0 as SelectOf, b1 as UniqueQueryKeyOf, b2 as Updatable, b3 as WriteCtx, b4 as WriteInput, b5 as WriteKind, b6 as WriteMiddleware, b7 as cond, b8 as entityWrites, b9 as getEntityWrites, ba as gsi, bb as identity, bc as k, bd as key, be as mutate, bf as preview, bg as when } from './key-
|
|
1
|
+
import { ak as SelectableOf, al as PrimaryKeyOf, e as ProjectionTransform, f as MaintainEvent, j as MembershipPredicate, h as MaintainConsistency, i as MaintainUpdateMode, am as MembershipPredicateOp, an as publishQuery, ao as publishCommand, D as DDBModel, ap as RetryPolicy, aq as Middleware } from './key-CWytoEaE.js';
|
|
2
|
+
export { ar as CdcModelRegistry, as as CdcSubscribeHandlers, at as Change, au as Column, av as ColumnMap, aw as CondSlot, ax as CtxBase, ay as CtxModel, az as FilterInput, aA as GsiDefinitionMarker, aB as GsiOptions, aC as InlineSnapshotSpec, aD as Item, aE as KeyDefinitionMarker, aF as KeySegment, aG as KeySlot, aH as KeyStructure, M as ModelStatic, aI as MutateAuthoringOptions, aJ as ParamDescriptor, aK as ParamStructure, aL as PartialQueryKeyOf, aM as PersistCtx, aN as PersistOrigin, aO as QueryKeyOf, aP as QueryResult, aQ as RawCondition, aR as ReadOpCtx, aS as ReadOpKind, aT as ReadParams, aU as ReadRequestCtx, aV as ReadRequestKind, aW as RelationBuilder, aX as RelationSelect, aY as RelationSpec, aZ as RequestContext, a_ as SegmentSpec, d as SegmentedKey, a$ as SelectBuilder, b0 as SelectOf, b1 as UniqueQueryKeyOf, b2 as Updatable, b3 as WriteCtx, b4 as WriteInput, b5 as WriteKind, b6 as WriteMiddleware, b7 as cond, b8 as entityWrites, b9 as getEntityWrites, ba as gsi, bb as identity, bc as k, bd as key, be as mutate, bf as preview, bg as when } from './key-CWytoEaE.js';
|
|
3
3
|
import * as _aws_sdk_client_dynamodb from '@aws-sdk/client-dynamodb';
|
|
4
4
|
import { p as publishBehaviors } from './behaviors-DDltNivc.js';
|
|
5
5
|
export { b as BehaviorComponentFns, a as BehaviorMethodSpec, B as BehaviorModelContract, P as PublishBehaviorsOptions, c as behaviorComponents, i as isBehaviorModelContract } from './behaviors-DDltNivc.js';
|
|
6
|
-
import { M as ModelKind, F as FieldOptions, D as DynamoType, R as RelationOptions, A as AggregateOptions, a as AggregateValue } from './types-
|
|
7
|
-
export { a0 as LiteralParam, a1 as MapParam, a2 as NumberParam, a3 as Param, a4 as ParamKind, a5 as StringParam, a6 as param } from './types-
|
|
6
|
+
import { M as ModelKind, F as FieldOptions, D as DynamoType, R as RelationOptions, A as AggregateOptions, a as AggregateValue } from './types-nk5okD7d.js';
|
|
7
|
+
export { a0 as LiteralParam, a1 as MapParam, a2 as NumberParam, a3 as Param, a4 as ParamKind, a5 as StringParam, a6 as param } from './types-CgXS-4Ox.js';
|
|
8
8
|
import 'behavior-contracts';
|
|
9
9
|
|
|
10
10
|
/**
|
package/dist/index.js
CHANGED
|
@@ -3,13 +3,13 @@ import {
|
|
|
3
3
|
mutate,
|
|
4
4
|
publishCommand,
|
|
5
5
|
publishQuery
|
|
6
|
-
} from "./chunk-
|
|
6
|
+
} from "./chunk-HLFNCKFV.js";
|
|
7
7
|
import {
|
|
8
8
|
entityWrites,
|
|
9
9
|
getEntityWrites,
|
|
10
10
|
identity,
|
|
11
11
|
preview
|
|
12
|
-
} from "./chunk-
|
|
12
|
+
} from "./chunk-7OCXY4R6.js";
|
|
13
13
|
import {
|
|
14
14
|
when
|
|
15
15
|
} from "./chunk-WOFRHRXY.js";
|
|
@@ -22,7 +22,7 @@ import {
|
|
|
22
22
|
deriveContractEffect,
|
|
23
23
|
gsi,
|
|
24
24
|
param
|
|
25
|
-
} from "./chunk-
|
|
25
|
+
} from "./chunk-GWWRXIHF.js";
|
|
26
26
|
import {
|
|
27
27
|
TableMapping,
|
|
28
28
|
k,
|
package/dist/internal/index.d.ts
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
import { P as PreparedWriteOpSpec, a as PreparedPlanDocument } from '../prepared-artifact-
|
|
2
|
-
export { b as PreparedBindSpec, c as PreparedPlanSpec, d as PreparedReadRouteSpec } from '../prepared-artifact-
|
|
3
|
-
import { M as Manifest } from '../types-
|
|
4
|
-
import { M as ModelStatic, D as DDBModel, S as Slot, P as PreparedWriteExecOptions, C as CommandReturn, a as ParallelOpResult, b as PreparedBody, c as PreparedStatement } from '../key-
|
|
5
|
-
import '../types-
|
|
1
|
+
import { P as PreparedWriteOpSpec, a as PreparedPlanDocument } from '../prepared-artifact-CwH5ezFq.js';
|
|
2
|
+
export { b as PreparedBindSpec, c as PreparedPlanSpec, d as PreparedReadRouteSpec } from '../prepared-artifact-CwH5ezFq.js';
|
|
3
|
+
import { M as Manifest } from '../types-CgXS-4Ox.js';
|
|
4
|
+
import { M as ModelStatic, D as DDBModel, S as Slot, P as PreparedWriteExecOptions, C as CommandReturn, a as ParallelOpResult, b as PreparedBody, c as PreparedStatement } from '../key-CWytoEaE.js';
|
|
5
|
+
import '../types-nk5okD7d.js';
|
|
6
6
|
import 'behavior-contracts';
|
|
7
7
|
|
|
8
8
|
/**
|
package/dist/internal/index.js
CHANGED
|
@@ -2,15 +2,15 @@ import {
|
|
|
2
2
|
PREPARED_FORMAT_VERSION,
|
|
3
3
|
buildManifestEntity,
|
|
4
4
|
entityFingerprint
|
|
5
|
-
} from "../chunk-
|
|
5
|
+
} from "../chunk-PHXUFAY2.js";
|
|
6
6
|
import {
|
|
7
7
|
LOGICAL_EFFECT_CATEGORIES,
|
|
8
8
|
PreparedReadStatement,
|
|
9
9
|
executeLogicalParallelWrites,
|
|
10
10
|
executeLogicalWriteOps,
|
|
11
11
|
serializeEffectParams
|
|
12
|
-
} from "../chunk-
|
|
13
|
-
import "../chunk-
|
|
12
|
+
} from "../chunk-HLFNCKFV.js";
|
|
13
|
+
import "../chunk-7OCXY4R6.js";
|
|
14
14
|
import {
|
|
15
15
|
MARKER_ROW_ENTITY,
|
|
16
16
|
SPEC_VERSION_KEY_EXPR,
|
|
@@ -21,7 +21,7 @@ import {
|
|
|
21
21
|
buildConditionExpression,
|
|
22
22
|
execItemKeySignature,
|
|
23
23
|
resolveConditionTree
|
|
24
|
-
} from "../chunk-
|
|
24
|
+
} from "../chunk-GWWRXIHF.js";
|
|
25
25
|
import {
|
|
26
26
|
TableMapping
|
|
27
27
|
} from "../chunk-XTWXMOHD.js";
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { a3 as Param, E as ExpressionSpec, a4 as ParamKind, T as TransactionSpec, Y as TransactionItemSpec } from './types-
|
|
1
|
+
import { a3 as Param, E as ExpressionSpec, a4 as ParamKind, T as TransactionSpec, Y as TransactionItemSpec } from './types-CgXS-4Ox.js';
|
|
2
2
|
|
|
3
3
|
/**
|
|
4
4
|
* CDC emulator types (issue #72). These types are **cdc-module-owned**; core
|
|
@@ -1653,6 +1653,13 @@ interface OperationDefinition<T extends DDBModel, Op extends OperationKind, K, S
|
|
|
1653
1653
|
readonly select: S;
|
|
1654
1654
|
/** The parameterized changes for `update`; `undefined` otherwise. */
|
|
1655
1655
|
readonly changes: Ch;
|
|
1656
|
+
/**
|
|
1657
|
+
* The parameterized atomic-`ADD` record for a standalone `update` (issue #301):
|
|
1658
|
+
* field name → a `param.number()` caller-delta leaf. Distinct from {@link changes}
|
|
1659
|
+
* (a SET) — each entry serializes to `CommandSpec.add` (`ADD #field :delta`).
|
|
1660
|
+
* `undefined` unless the command declared `add`.
|
|
1661
|
+
*/
|
|
1662
|
+
readonly add?: Readonly<Record<string, unknown>>;
|
|
1656
1663
|
/**
|
|
1657
1664
|
* The declarative write condition for `put` / `update` / `delete`; `undefined`
|
|
1658
1665
|
* when no condition is attached or for reads (issue #46).
|
|
@@ -2512,6 +2519,16 @@ interface MutationFragment {
|
|
|
2512
2519
|
readonly intent: MutationIntent;
|
|
2513
2520
|
readonly entity: EntityRef;
|
|
2514
2521
|
readonly input: FragmentInput;
|
|
2522
|
+
/**
|
|
2523
|
+
* Atomic-**`ADD`** field binding on the self row (issue #301): model field name →
|
|
2524
|
+
* a {@link MutationInputRef} (`$.field`, a `param.number()` caller delta). Distinct
|
|
2525
|
+
* from {@link input} (a `SET`): the compiler ({@link
|
|
2526
|
+
* import('../spec/mutation-command.js').compileFragment}) lowers each leaf onto the
|
|
2527
|
+
* command spec's `add` record (an `ADD #field :delta`), so the runtime issues an
|
|
2528
|
+
* atomic increment (no read, concurrency-safe). Absent when the fragment declares no
|
|
2529
|
+
* `add`. Present only on an `update` fragment.
|
|
2530
|
+
*/
|
|
2531
|
+
readonly add?: FragmentInput;
|
|
2515
2532
|
readonly use?: EntityWritesDefinition;
|
|
2516
2533
|
/**
|
|
2517
2534
|
* The declarative write **condition** (gate) authored on the descriptor (issue
|
|
@@ -2581,6 +2598,16 @@ interface WriteDescriptor {
|
|
|
2581
2598
|
readonly key: DescriptorBinding;
|
|
2582
2599
|
/** The non-key field binding; optional (a `remove` writes no fields). */
|
|
2583
2600
|
readonly input?: DescriptorBinding;
|
|
2601
|
+
/**
|
|
2602
|
+
* Optional atomic-**`ADD`** binding on the self row (issue #301) — `{ field: $.field }`
|
|
2603
|
+
* whose leaves are `$.field` input refs bound from `param.number()` caller deltas.
|
|
2604
|
+
* Distinct from `input` (a `SET`): an `add` field lowers to a `TransactionValueLeaf`
|
|
2605
|
+
* on the compiled command spec's `add` record (an `ADD #field :delta`), NOT to a
|
|
2606
|
+
* `changes` SET. Legal only on an `update` fragment. When present alongside a
|
|
2607
|
+
* `condition`, the runtime applies the ADD unconditionally (two-stage: ADD+SET under
|
|
2608
|
+
* the condition, fallback ADD-only on ConditionalCheckFailed).
|
|
2609
|
+
*/
|
|
2610
|
+
readonly add?: DescriptorBinding;
|
|
2584
2611
|
/**
|
|
2585
2612
|
* Optional declarative write gate — the #114-A condition subset (issue #242,
|
|
2586
2613
|
* Phase 2). Compiled, serialized, and evaluated at runtime; see the interface doc.
|
|
@@ -3038,6 +3065,13 @@ interface ContractMethodOp<Op extends OperationKind = OperationKind> {
|
|
|
3038
3065
|
readonly select?: Readonly<Record<string, unknown>>;
|
|
3039
3066
|
/** The changes structure for `update`; `undefined` otherwise. */
|
|
3040
3067
|
readonly changes?: Readonly<Record<string, unknown>>;
|
|
3068
|
+
/**
|
|
3069
|
+
* The atomic-`ADD` structure for `update` (issue #301): model field name → a
|
|
3070
|
+
* `param.number()` caller-delta leaf (a `{token}` template). Distinct from
|
|
3071
|
+
* {@link changes} (a SET): each entry lowers to `ADD #field :delta`. Present only on
|
|
3072
|
+
* a standalone `update` command that declared `add`; `undefined` otherwise.
|
|
3073
|
+
*/
|
|
3074
|
+
readonly add?: Readonly<Record<string, unknown>>;
|
|
3041
3075
|
/** The item structure for `put`; `undefined` otherwise. */
|
|
3042
3076
|
readonly item?: Readonly<Record<string, unknown>>;
|
|
3043
3077
|
/** The optional declarative write condition for writes. */
|
|
@@ -3679,6 +3713,25 @@ interface PublicWriteDescriptor {
|
|
|
3679
3713
|
readonly upsert?: ModelRef;
|
|
3680
3714
|
readonly key: Readonly<Record<string, unknown>>;
|
|
3681
3715
|
readonly input?: Readonly<Record<string, unknown>>;
|
|
3716
|
+
/**
|
|
3717
|
+
* Atomic **`ADD`** deltas on the SELF row (issue #301) — `{ field: param.number() }`
|
|
3718
|
+
* declaring an `ADD #field :delta` with a **caller-param** delta. Distinct from
|
|
3719
|
+
* `input` (a `SET` that overwrites): `add` is an atomic server-side increment that
|
|
3720
|
+
* needs no prior read and is concurrency-safe (the aggregate-tree `mark`'s
|
|
3721
|
+
* `version++`). Legal only on an `update` intent, with each value a
|
|
3722
|
+
* `param.number()`. An `add` field may NOT also appear in `input` (a field is either
|
|
3723
|
+
* SET or ADD, not both) nor be a primary-key field (a key cannot be incremented).
|
|
3724
|
+
*
|
|
3725
|
+
* **Two-stage semantics**: when an `update` carries BOTH `add` and a `condition`, the
|
|
3726
|
+
* `add` is UNCONDITIONAL (it must always apply — the mark's `version++` must always
|
|
3727
|
+
* happen) while `input` (SET) is gated by `condition`. Because DynamoDB rejects the
|
|
3728
|
+
* ENTIRE `UpdateItem` when the `ConditionExpression` fails, the RUNTIME performs a
|
|
3729
|
+
* transparent two-stage: `ADD + SET` under the condition (1 write, the common path);
|
|
3730
|
+
* on `ConditionalCheckFailedException`, a fallback `ADD`-only write (no SET, no
|
|
3731
|
+
* condition — the `version` still increments). read=0, retry=0. The author does NOT
|
|
3732
|
+
* write the fallback — it is derived from `add` + `condition` presence.
|
|
3733
|
+
*/
|
|
3734
|
+
readonly add?: Readonly<Record<string, unknown>>;
|
|
3682
3735
|
readonly condition?: Readonly<Record<string, unknown>> | RawCondition<any, any>;
|
|
3683
3736
|
readonly result?: {
|
|
3684
3737
|
readonly select?: Readonly<Record<string, boolean>>;
|
package/dist/linter/index.d.ts
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
import { L as Linter, a as LintRule } from '../linter-
|
|
2
|
-
export { b as LintResult } from '../linter-
|
|
3
|
-
import '../types-
|
|
4
|
-
import '../key-
|
|
5
|
-
import '../types-
|
|
1
|
+
import { L as Linter, a as LintRule } from '../linter-jEwmZotm.js';
|
|
2
|
+
export { b as LintResult } from '../linter-jEwmZotm.js';
|
|
3
|
+
import '../types-nk5okD7d.js';
|
|
4
|
+
import '../key-CWytoEaE.js';
|
|
5
|
+
import '../types-CgXS-4Ox.js';
|
|
6
6
|
import 'behavior-contracts';
|
|
7
7
|
|
|
8
8
|
/**
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { E as EntityMetadata } from './types-
|
|
2
|
-
import { C as ContractSpec, Q as QuerySpec, a as CommandSpec, T as TransactionSpec, b as ContextSpec, S as SPEC_VERSION_KEY_EXPR, P as ParamSpec } from './types-
|
|
3
|
-
import { Q as QueryModelContract, k as QueryMethodSpec, l as CommandModelContract, m as CommandMethodSpec } from './key-
|
|
1
|
+
import { E as EntityMetadata } from './types-nk5okD7d.js';
|
|
2
|
+
import { C as ContractSpec, Q as QuerySpec, a as CommandSpec, T as TransactionSpec, b as ContextSpec, S as SPEC_VERSION_KEY_EXPR, P as ParamSpec } from './types-CgXS-4Ox.js';
|
|
3
|
+
import { Q as QueryModelContract, k as QueryMethodSpec, l as CommandModelContract, m as CommandMethodSpec } from './key-CWytoEaE.js';
|
|
4
4
|
|
|
5
5
|
/**
|
|
6
6
|
* Contract-layer serialization (issue #59, CQRS Contract layer, Epic #57;
|
package/dist/spec/index.d.ts
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
|
-
import { $ as AnyOperationDefinition, a0 as TransactionDefinition, b as PreparedBody } from '../key-
|
|
2
|
-
export { a1 as CompiledFragment, a2 as CompiledMutationPlan, a3 as DerivedConditionCheck, a4 as DerivedEdgeWrite, a5 as DerivedIdempotencyGuard, a6 as DerivedMaintainOutbox, a7 as DerivedMaintainWrite, a8 as DerivedOutboxEvent, a9 as DerivedUniqueGuard, aa as DerivedUpdate, ab as EntityRefResolver, ac as MAX_TRANSACT_COMPOSE_ITEMS, ad as assertNoCrossFragmentMaintainCollision, ae as compileFragment, af as compileMutationPlan, ag as compileSingleFragmentPlan, ah as resetMaintenanceGraphCache, ai as resolveLifecycle, aj as resolveMaintainers } from '../key-
|
|
3
|
-
import { M as MetadataRegistry } from '../linter-
|
|
1
|
+
import { $ as AnyOperationDefinition, a0 as TransactionDefinition, b as PreparedBody } from '../key-CWytoEaE.js';
|
|
2
|
+
export { a1 as CompiledFragment, a2 as CompiledMutationPlan, a3 as DerivedConditionCheck, a4 as DerivedEdgeWrite, a5 as DerivedIdempotencyGuard, a6 as DerivedMaintainOutbox, a7 as DerivedMaintainWrite, a8 as DerivedOutboxEvent, a9 as DerivedUniqueGuard, aa as DerivedUpdate, ab as EntityRefResolver, ac as MAX_TRANSACT_COMPOSE_ITEMS, ad as assertNoCrossFragmentMaintainCollision, ae as compileFragment, af as compileMutationPlan, ag as compileSingleFragmentPlan, ah as resetMaintenanceGraphCache, ai as resolveLifecycle, aj as resolveMaintainers } from '../key-CWytoEaE.js';
|
|
3
|
+
import { M as MetadataRegistry } from '../linter-jEwmZotm.js';
|
|
4
4
|
import { B as BehaviorModelContract } from '../behaviors-DDltNivc.js';
|
|
5
5
|
export { a as BehaviorMethodSpec } from '../behaviors-DDltNivc.js';
|
|
6
|
-
import { C as ContractMap, e as ContextOwnershipMap, c as PreparedPlanSpec, a as PreparedPlanDocument } from '../prepared-artifact-
|
|
7
|
-
export { A as AnyModelContract, B as BuiltContracts, f as ContextOwnership, g as PREPARED_FORMAT_VERSION, h as PreparedBindMap, b as PreparedBindSpec, d as PreparedReadRouteSpec, P as PreparedWriteOpSpec, i as buildContexts, j as buildContracts, k as canonicalJson, l as entityFingerprint, p as planFingerprint } from '../prepared-artifact-
|
|
8
|
-
import { O as OperationsDocument, Q as QuerySpec, M as Manifest, T as TransactionSpec, C as ContractSpec, B as BridgeBundle, c as ConditionSpec, E as ExpressionSpec, a as CommandSpec, d as SpecVersion } from '../types-
|
|
9
|
-
export { e as CommandContractMethodSpec, f as CommandResolutionTarget, g as ComposeSpec, h as CompositionPlanSpec, b as ContextSpec, i as ContractCardinality, j as ContractCommandResult, k as ContractInputArity, l as ContractKeySpec, m as ContractKind, n as ContractResolution, o as EXPR_VERSION, p as ExecutionPlanSpec, q as ExpressionArrNode, r as ExpressionFloatNode, s as ExpressionIntNode, t as ExpressionNode, u as ExpressionObjNode, v as ExpressionOpNode, w as ExpressionOperator, x as ExpressionRefNode, y as ExpressionRefOptNode, z as ExpressionScalar, F as FilterSpec, A as ManifestEntity, D as ManifestField, G as ManifestFieldType, H as ManifestGsi, I as ManifestKey, J as ManifestRelation, K as ManifestTable, L as OperationSpec, P as ParamSpec, N as QueryContractMethodSpec, R as RangeConditionSpec, U as ReadOperationType, V as SPEC_VERSION, S as SPEC_VERSION_KEY_EXPR, W as SPEC_VERSION_SCP, X as SPEC_VERSION_SUPPORTED, Y as TransactionItemSpec, Z as TransactionItemType, _ as WhenSpec, $ as WriteOperationType } from '../types-
|
|
6
|
+
import { C as ContractMap, e as ContextOwnershipMap, c as PreparedPlanSpec, a as PreparedPlanDocument } from '../prepared-artifact-CwH5ezFq.js';
|
|
7
|
+
export { A as AnyModelContract, B as BuiltContracts, f as ContextOwnership, g as PREPARED_FORMAT_VERSION, h as PreparedBindMap, b as PreparedBindSpec, d as PreparedReadRouteSpec, P as PreparedWriteOpSpec, i as buildContexts, j as buildContracts, k as canonicalJson, l as entityFingerprint, p as planFingerprint } from '../prepared-artifact-CwH5ezFq.js';
|
|
8
|
+
import { O as OperationsDocument, Q as QuerySpec, M as Manifest, T as TransactionSpec, C as ContractSpec, B as BridgeBundle, c as ConditionSpec, E as ExpressionSpec, a as CommandSpec, d as SpecVersion } from '../types-CgXS-4Ox.js';
|
|
9
|
+
export { e as CommandContractMethodSpec, f as CommandResolutionTarget, g as ComposeSpec, h as CompositionPlanSpec, b as ContextSpec, i as ContractCardinality, j as ContractCommandResult, k as ContractInputArity, l as ContractKeySpec, m as ContractKind, n as ContractResolution, o as EXPR_VERSION, p as ExecutionPlanSpec, q as ExpressionArrNode, r as ExpressionFloatNode, s as ExpressionIntNode, t as ExpressionNode, u as ExpressionObjNode, v as ExpressionOpNode, w as ExpressionOperator, x as ExpressionRefNode, y as ExpressionRefOptNode, z as ExpressionScalar, F as FilterSpec, A as ManifestEntity, D as ManifestField, G as ManifestFieldType, H as ManifestGsi, I as ManifestKey, J as ManifestRelation, K as ManifestTable, L as OperationSpec, P as ParamSpec, N as QueryContractMethodSpec, R as RangeConditionSpec, U as ReadOperationType, V as SPEC_VERSION, S as SPEC_VERSION_KEY_EXPR, W as SPEC_VERSION_SCP, X as SPEC_VERSION_SUPPORTED, Y as TransactionItemSpec, Z as TransactionItemType, _ as WhenSpec, $ as WriteOperationType } from '../types-CgXS-4Ox.js';
|
|
10
10
|
import { Component, ComponentGraphIR } from 'behavior-contracts';
|
|
11
|
-
import '../types-
|
|
11
|
+
import '../types-nk5okD7d.js';
|
|
12
12
|
|
|
13
13
|
/**
|
|
14
14
|
* Static parameterized operation-spec generation (issue #42, Phase 0b).
|
package/dist/spec/index.js
CHANGED
|
@@ -14,14 +14,14 @@ import {
|
|
|
14
14
|
collectContractN1Violations,
|
|
15
15
|
compilePreparedPlan,
|
|
16
16
|
portableIrDocument
|
|
17
|
-
} from "../chunk-
|
|
17
|
+
} from "../chunk-MBJ4JVRM.js";
|
|
18
18
|
import {
|
|
19
19
|
PREPARED_FORMAT_VERSION,
|
|
20
20
|
buildManifest,
|
|
21
21
|
canonicalJson,
|
|
22
22
|
entityFingerprint,
|
|
23
23
|
planFingerprint
|
|
24
|
-
} from "../chunk-
|
|
24
|
+
} from "../chunk-PHXUFAY2.js";
|
|
25
25
|
import {
|
|
26
26
|
MAX_TRANSACT_COMPOSE_ITEMS,
|
|
27
27
|
assertBundleSerializable,
|
|
@@ -36,8 +36,8 @@ import {
|
|
|
36
36
|
resetMaintenanceGraphCache,
|
|
37
37
|
resolveLifecycle,
|
|
38
38
|
resolveMaintainers
|
|
39
|
-
} from "../chunk-
|
|
40
|
-
import "../chunk-
|
|
39
|
+
} from "../chunk-HLFNCKFV.js";
|
|
40
|
+
import "../chunk-7OCXY4R6.js";
|
|
41
41
|
import {
|
|
42
42
|
EXPR_VERSION,
|
|
43
43
|
SPEC_VERSION,
|
|
@@ -47,7 +47,7 @@ import {
|
|
|
47
47
|
canonicalizeExpressionSpec,
|
|
48
48
|
operationsSpecVersion
|
|
49
49
|
} from "../chunk-WOFRHRXY.js";
|
|
50
|
-
import "../chunk-
|
|
50
|
+
import "../chunk-GWWRXIHF.js";
|
|
51
51
|
import "../chunk-XTWXMOHD.js";
|
|
52
52
|
export {
|
|
53
53
|
EXPR_VERSION,
|
package/dist/testing/index.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { n as Executor, o as DynamoDBOperation, R as ReadExecOptions, p as ExecutorResult, B as BatchGetExecInput, q as PutInput, W as WriteExecOptions, r as WriteResult, U as UpdateInput, s as DeleteInput, t as BatchWriteExecItem, u as BatchExecOptions, T as TransactWriteExecItem, M as ModelStatic, D as DDBModel, v as ChangeEvent } from '../key-
|
|
2
|
-
import '../types-
|
|
1
|
+
import { n as Executor, o as DynamoDBOperation, R as ReadExecOptions, p as ExecutorResult, B as BatchGetExecInput, q as PutInput, W as WriteExecOptions, r as WriteResult, U as UpdateInput, s as DeleteInput, t as BatchWriteExecItem, u as BatchExecOptions, T as TransactWriteExecItem, M as ModelStatic, D as DDBModel, v as ChangeEvent } from '../key-CWytoEaE.js';
|
|
2
|
+
import '../types-CgXS-4Ox.js';
|
|
3
3
|
import 'behavior-contracts';
|
|
4
4
|
|
|
5
5
|
/**
|
package/dist/testing/index.js
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
import {
|
|
2
2
|
createCdcEmulator
|
|
3
|
-
} from "../chunk-
|
|
4
|
-
import "../chunk-
|
|
3
|
+
} from "../chunk-VECUS35D.js";
|
|
4
|
+
import "../chunk-7OCXY4R6.js";
|
|
5
5
|
import {
|
|
6
6
|
ClientManager,
|
|
7
7
|
MetadataRegistry,
|
|
8
8
|
resolveModelClass
|
|
9
|
-
} from "../chunk-
|
|
9
|
+
} from "../chunk-GWWRXIHF.js";
|
|
10
10
|
import {
|
|
11
11
|
TableMapping
|
|
12
12
|
} from "../chunk-XTWXMOHD.js";
|
|
@@ -470,8 +470,9 @@ function removePath(target, segments) {
|
|
|
470
470
|
delete cursor[segments[segments.length - 1]];
|
|
471
471
|
}
|
|
472
472
|
function applyUpdateExpression(item, expression, clauses) {
|
|
473
|
-
const setMatch = /SET\s+(.*?)(?:\s+REMOVE\s+|$)/.exec(expression);
|
|
474
|
-
const removeMatch = /REMOVE\s+(
|
|
473
|
+
const setMatch = /SET\s+(.*?)(?:\s+REMOVE\s+|\s+ADD\s+|$)/.exec(expression);
|
|
474
|
+
const removeMatch = /REMOVE\s+(.*?)(?:\s+ADD\s+|$)/.exec(expression);
|
|
475
|
+
const addMatch = /ADD\s+(.*)$/.exec(expression);
|
|
475
476
|
if (setMatch && setMatch[1].trim().length > 0) {
|
|
476
477
|
const assignments = splitTopLevel(setMatch[1]);
|
|
477
478
|
for (const assignment of assignments) {
|
|
@@ -496,6 +497,32 @@ function applyUpdateExpression(item, expression, clauses) {
|
|
|
496
497
|
removePath(item, resolvePath(trimmed, clauses.names));
|
|
497
498
|
}
|
|
498
499
|
}
|
|
500
|
+
if (addMatch && addMatch[1].trim().length > 0) {
|
|
501
|
+
const clausesList = splitTopLevel(addMatch[1]);
|
|
502
|
+
for (const clause of clausesList) {
|
|
503
|
+
const trimmed = clause.trim();
|
|
504
|
+
if (trimmed.length === 0) continue;
|
|
505
|
+
const sp = trimmed.indexOf(" ");
|
|
506
|
+
if (sp < 0) {
|
|
507
|
+
throw new Error(`memory update: malformed ADD clause '${trimmed}'`);
|
|
508
|
+
}
|
|
509
|
+
const pathExpr = trimmed.slice(0, sp).trim();
|
|
510
|
+
const valueAlias = trimmed.slice(sp + 1).trim();
|
|
511
|
+
if (!(valueAlias in clauses.values)) {
|
|
512
|
+
throw new Error(`memory update: unbound value alias '${valueAlias}'`);
|
|
513
|
+
}
|
|
514
|
+
const delta = clauses.values[valueAlias];
|
|
515
|
+
if (typeof delta !== "number") {
|
|
516
|
+
throw new Error(
|
|
517
|
+
`memory update: ADD delta for '${pathExpr}' is not numeric (${typeof delta})`
|
|
518
|
+
);
|
|
519
|
+
}
|
|
520
|
+
const segments = resolvePath(pathExpr, clauses.names);
|
|
521
|
+
const current = segments.length === 1 ? item[segments[0]] : void 0;
|
|
522
|
+
const base = typeof current === "number" ? current : 0;
|
|
523
|
+
setPath(item, segments, base + delta);
|
|
524
|
+
}
|
|
525
|
+
}
|
|
499
526
|
}
|
|
500
527
|
function splitTopLevel(clause) {
|
|
501
528
|
const parts = [];
|
package/dist/transform/index.js
CHANGED
|
@@ -721,7 +721,9 @@ type WriteOperationType = 'PutItem' | 'UpdateItem' | 'DeleteItem';
|
|
|
721
721
|
* - `{ kind: 'attributeNotExists'; field }` → `attribute_not_exists(<field>)` — the
|
|
722
722
|
* named attribute must be absent (field-level uniqueness / first-write guard).
|
|
723
723
|
* - `{ kind: 'equals'; fields }` → `#f = :v AND …` field equality (each value a
|
|
724
|
-
* `{param}` / literal
|
|
724
|
+
* `{param}` string template or a typed literal — a `number` / `boolean` literal
|
|
725
|
+
* is carried verbatim so it compares as `N` / `BOOL`, not a stringified `S`,
|
|
726
|
+
* issue #299).
|
|
725
727
|
* - `{ kind: 'expr'; declarative }` → the full declarative operator tree (issue
|
|
726
728
|
* #114-A): comparison (`gt`/`ge`/`lt`/`le`/`ne`), `between`, `in`,
|
|
727
729
|
* `begins_with`/`contains`/`notContains`, `attributeType`, and the logical
|
|
@@ -743,7 +745,7 @@ type ConditionSpec = {
|
|
|
743
745
|
readonly field: string;
|
|
744
746
|
} | {
|
|
745
747
|
readonly kind: 'equals';
|
|
746
|
-
readonly fields: Readonly<Record<string,
|
|
748
|
+
readonly fields: Readonly<Record<string, TransactionValueLeaf>>;
|
|
747
749
|
} | {
|
|
748
750
|
readonly kind: 'expr';
|
|
749
751
|
readonly declarative: unknown;
|
|
@@ -792,10 +794,33 @@ interface CommandSpec {
|
|
|
792
794
|
* Absent for `PutItem` (the whole item is built from `item`).
|
|
793
795
|
*/
|
|
794
796
|
readonly keyCondition?: Readonly<Record<string, string>>;
|
|
795
|
-
/**
|
|
796
|
-
|
|
797
|
-
|
|
798
|
-
|
|
797
|
+
/**
|
|
798
|
+
* The full item template for `PutItem` (field name → template / typed literal).
|
|
799
|
+
* A string value is a template ({@link TransactionValueLeaf}); a `number` /
|
|
800
|
+
* `boolean` is a typed literal carried verbatim so it lands as `N` / `BOOL`
|
|
801
|
+
* rather than a stringified `S` (issue #299, mirroring the transaction #245).
|
|
802
|
+
*/
|
|
803
|
+
readonly item?: Readonly<Record<string, TransactionValueLeaf>>;
|
|
804
|
+
/**
|
|
805
|
+
* Field-level changes for `UpdateItem` (field name → template / typed literal).
|
|
806
|
+
* A string value is a template; a `number` / `boolean` is a typed literal
|
|
807
|
+
* carried verbatim (issue #299).
|
|
808
|
+
*/
|
|
809
|
+
readonly changes?: Readonly<Record<string, TransactionValueLeaf>>;
|
|
810
|
+
/**
|
|
811
|
+
* Atomic-`ADD` deltas for a standalone `UpdateItem` (issue #301): field name →
|
|
812
|
+
* template / typed literal. Distinct from {@link changes} (a SET): each entry emits
|
|
813
|
+
* `ADD #field :delta` — an atomic, read-free, concurrency-safe increment (the
|
|
814
|
+
* aggregate-tree `mark`'s `version++`). The delta rides as a `{token}` template
|
|
815
|
+
* resolved from a caller `param.number()`. When present together with
|
|
816
|
+
* {@link condition}, the ADD is UNCONDITIONAL and the runtime executes a transparent
|
|
817
|
+
* TWO-STAGE write: `ADD + SET` under the condition (1 write); on
|
|
818
|
+
* `ConditionalCheckFailedException`, a fallback `ADD`-only write (no SET, no
|
|
819
|
+
* condition — the counter still increments). read=0, retry=0. Absent unless the
|
|
820
|
+
* command declared `add`, so a command with no `add` serializes byte-identically to
|
|
821
|
+
* the pre-#301 spec.
|
|
822
|
+
*/
|
|
823
|
+
readonly add?: Readonly<Record<string, TransactionValueLeaf>>;
|
|
799
824
|
/** Optional write condition (subset). */
|
|
800
825
|
readonly condition?: ConditionSpec;
|
|
801
826
|
/**
|
|
@@ -1023,8 +1048,12 @@ interface MaintainItemSpec {
|
|
|
1023
1048
|
interface MaintainCounterSpec {
|
|
1024
1049
|
/** The target attribute the counter increments (e.g. `postCount`). */
|
|
1025
1050
|
readonly attribute: string;
|
|
1026
|
-
/**
|
|
1027
|
-
|
|
1051
|
+
/**
|
|
1052
|
+
* The signed `ADD` delta. A compile-time constant delta is carried as a typed
|
|
1053
|
+
* `number` (`1` / `-1`) so it marshals as `N` (issue #299); a `{param}` numeric
|
|
1054
|
+
* template rides as a string. (Pre-#299 a constant was stringified to `"1"`.)
|
|
1055
|
+
*/
|
|
1056
|
+
readonly delta: TransactionValueLeaf;
|
|
1028
1057
|
}
|
|
1029
1058
|
/** A declarative transaction definition's full execution spec. */
|
|
1030
1059
|
interface TransactionSpec {
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { d as SegmentedKey, e as ProjectionTransform, f as MaintainEvent, g as ProjectionMap, h as MaintainConsistency, i as MaintainUpdateMode, E as EffectPath, j as MembershipPredicate } from './key-
|
|
1
|
+
import { d as SegmentedKey, e as ProjectionTransform, f as MaintainEvent, g as ProjectionMap, h as MaintainConsistency, i as MaintainUpdateMode, E as EffectPath, j as MembershipPredicate } from './key-CWytoEaE.js';
|
|
2
2
|
|
|
3
3
|
type DynamoType = 'S' | 'N' | 'BOOL' | 'B' | 'SS' | 'NS' | 'L' | 'M';
|
|
4
4
|
interface FieldOptions {
|