graphddb 0.3.0 → 0.3.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/index.js CHANGED
@@ -2,8 +2,6 @@ import {
2
2
  BatchGetResult,
3
3
  DDBModel,
4
4
  EDGE_WRITES_MARKER,
5
- ENTITY_WRITES_MARKER,
6
- LIFECYCLE_CONTRACT_MARKER,
7
5
  MARKER_ROW_ENTITY,
8
6
  OLD_VALUE_NAMESPACE,
9
7
  RELATION_TRAVERSAL_CONCURRENCY,
@@ -16,7 +14,6 @@ import {
16
14
  buildBridgeBundle,
17
15
  buildContexts,
18
16
  buildContracts,
19
- buildMaintenanceGraph,
20
17
  buildManifest,
21
18
  buildOperations,
22
19
  buildProjection,
@@ -42,7 +39,6 @@ import {
42
39
  detectRelationFields,
43
40
  edgeWrites,
44
41
  encodeCursor,
45
- entityWrites,
46
42
  evaluateFilter,
47
43
  execute,
48
44
  executeBatchGet,
@@ -54,10 +50,8 @@ import {
54
50
  executeQuery,
55
51
  from,
56
52
  getEdgeWrites,
57
- getEntityWrites,
58
53
  getImplicitKeyFields,
59
54
  hydrate,
60
- identity,
61
55
  isCommandModelContract,
62
56
  isCommandPlan,
63
57
  isContractComposeNode,
@@ -66,23 +60,17 @@ import {
66
60
  isContractKeyRef,
67
61
  isContractParamRef,
68
62
  isEdgeWritesDefinition,
69
- isEntityWritesDefinition,
70
- isLifecycleContract,
71
- isMaintainTrigger,
72
63
  isMutationFragment,
73
64
  isMutationInputRef,
74
65
  isPlannedCommandMethod,
75
66
  isQueryModelContract,
76
67
  isSelectBuilder,
77
68
  isTransactionRef,
78
- lifecyclePhaseForIntent,
79
- maintainTrigger,
80
69
  mapWithConcurrency,
81
70
  mintContractKeyFieldRef,
82
71
  mintContractParamRef,
83
72
  mutation,
84
73
  plan,
85
- preview,
86
74
  publicCommandModel,
87
75
  publicQueryModel,
88
76
  query,
@@ -91,11 +79,23 @@ import {
91
79
  validateDepth,
92
80
  when,
93
81
  wholeKeysSentinel
94
- } from "./chunk-QEOFIXTN.js";
82
+ } from "./chunk-VST3WOK3.js";
95
83
  import {
96
84
  CdcEmulator,
97
- createCdcEmulator
98
- } from "./chunk-QQNP43JL.js";
85
+ InMemoryProjectionSink,
86
+ MAINT_OUTBOX_PK_PREFIX,
87
+ MaintenanceDrain,
88
+ ProjectionSinkDrain,
89
+ compareDesc,
90
+ createCdcEmulator,
91
+ createMaintenanceDrain,
92
+ createMaintenanceDrainHandler,
93
+ createProjectionSinkDrain,
94
+ createProjectionSinkHandler,
95
+ orderAndTrimCollection,
96
+ pathField,
97
+ projectFrom
98
+ } from "./chunk-PNIZS37E.js";
99
99
  import {
100
100
  BATCH_GET_MAX_KEYS,
101
101
  BATCH_WRITE_MAX_ITEMS,
@@ -103,15 +103,19 @@ import {
103
103
  DEFAULT_MAX_ATTEMPTS,
104
104
  DEFAULT_RETRY_POLICY,
105
105
  DynamoExecutor,
106
+ ENTITY_WRITES_MARKER,
107
+ LIFECYCLE_CONTRACT_MARKER,
106
108
  Linter,
107
109
  MAX_TRANSACT_ITEMS,
108
110
  MetadataRegistry,
109
111
  RetryingExecutor,
110
112
  TableMapping,
111
113
  TransactionContext,
114
+ ViewRegistry,
112
115
  attachModelClass,
113
116
  buildConditionExpression,
114
117
  buildDeleteInput,
118
+ buildMaintenanceGraph,
115
119
  buildPutInput,
116
120
  buildUpdateExpression,
117
121
  buildUpdateInput,
@@ -120,31 +124,49 @@ import {
120
124
  commitTransaction,
121
125
  cond,
122
126
  createDefaultLinter,
127
+ defineProjection,
128
+ defineProjections,
129
+ defineVersioned,
130
+ defineView,
131
+ defineViews,
132
+ entityWrites,
123
133
  execItemKeySignature,
124
134
  executeDelete,
125
135
  executePut,
126
136
  executeTransaction,
127
137
  executeUpdate,
138
+ getEntityWrites,
128
139
  gsi,
129
140
  gsiAmbiguityRule,
141
+ identity,
130
142
  isColumn,
143
+ isEntityWritesDefinition,
131
144
  isKeySegment,
145
+ isLifecycleContract,
146
+ isMaintainTrigger,
132
147
  isParam,
148
+ isProjectionDefinition,
133
149
  isRawCondition,
134
150
  isRetryableError,
135
151
  isRetryableTransactionCancellation,
152
+ isViewDefinition,
136
153
  k,
137
154
  key,
155
+ lifecyclePhaseForIntent,
156
+ maintainTrigger,
138
157
  missingGsiRule,
139
158
  noScanRule,
140
159
  param,
160
+ preview,
141
161
  relationDepthRule,
142
162
  requireLimitRule,
143
163
  resolveConditionTree,
144
164
  resolveKey,
145
165
  resolveModelClass,
146
- serializeFieldValue
147
- } from "./chunk-6AIAHP3A.js";
166
+ segmentFieldNames,
167
+ serializeFieldValue,
168
+ whenMember
169
+ } from "./chunk-YIXXTGZ6.js";
148
170
 
149
171
  // src/metadata/prefix.ts
150
172
  function derivePrefix(customPrefix, className) {
@@ -955,6 +977,360 @@ var queryBoundaryRule = {
955
977
  }
956
978
  };
957
979
 
980
+ // src/relation/maintenance-rebuild.ts
981
+ function toClass(m) {
982
+ try {
983
+ return resolveModelClass(m);
984
+ } catch {
985
+ return m;
986
+ }
987
+ }
988
+ var MaintenanceRebuilder = class {
989
+ graph;
990
+ constructor(opts = {}) {
991
+ const classes = (opts.models ?? []).map(toClass);
992
+ const views = opts.views ?? [];
993
+ const allClasses = [...classes, ...views.map((v) => v.viewClass)];
994
+ const scoped = allClasses.length > 0 ? new Map(allClasses.map((c) => [c, MetadataRegistry.get(c)])) : void 0;
995
+ this.graph = buildMaintenanceGraph(scoped, views);
996
+ }
997
+ /**
998
+ * Re-derive the materialized value for one owner row × maintainer from the source
999
+ * rows and report whether it differs from what the owner row currently stores. Does
1000
+ * NOT write anything (a read-only drift probe).
1001
+ *
1002
+ * @param owner The owner model class declaring the maintainer.
1003
+ * @param relationProperty The relation / `@aggregate` property the value lives under.
1004
+ * @param ownerKeyInput The owner row's key input (e.g. `{ threadId: 't1' }`).
1005
+ */
1006
+ async detectDrift(owner, relationProperty, ownerKeyInput) {
1007
+ const { item, ownerMeta, ownerKey } = this.resolve(owner, relationProperty);
1008
+ const expected = await this.recompute(item, ownerMeta, ownerKeyInput);
1009
+ const ownerRow = await this.readOwnerRow(ownerMeta, ownerKey(ownerKeyInput));
1010
+ const actual = this.actualValue(item.effect, ownerRow);
1011
+ const ownerAbsentAndEmpty = ownerRow === void 0 && isEmptyMaintained(item.effect, expected);
1012
+ return {
1013
+ relationProperty,
1014
+ ownerEntity: item.ownerEntity,
1015
+ ownerKey: ownerKey(ownerKeyInput),
1016
+ kind: item.effect.kind,
1017
+ drifted: !ownerAbsentAndEmpty && !deepEqual(normalize(expected), normalize(actual)),
1018
+ expected,
1019
+ actual
1020
+ };
1021
+ }
1022
+ /**
1023
+ * Re-derive the materialized value for one owner row × maintainer from the source
1024
+ * rows and WRITE the absolute re-derived value onto the owner row when it drifts (or
1025
+ * always, when `force`). Returns the drift verdict plus whether a repair write ran.
1026
+ *
1027
+ * @param options.force Write even when no drift is detected (default: write only on drift).
1028
+ */
1029
+ async rebuild(owner, relationProperty, ownerKeyInput, options = {}) {
1030
+ const report = await this.detectDrift(owner, relationProperty, ownerKeyInput);
1031
+ if (!report.drifted && options.force !== true) {
1032
+ return { ...report, repaired: false };
1033
+ }
1034
+ const { item, ownerMeta } = this.resolve(owner, relationProperty);
1035
+ await this.writeValue(item.effect, ownerMeta, report.ownerKey, report.expected);
1036
+ return { ...report, repaired: true };
1037
+ }
1038
+ /** Resolve an owner model + property to its {@link MaintainItem} + owner-key builder. */
1039
+ resolve(owner, relationProperty) {
1040
+ const ownerClass = toClass(owner);
1041
+ const ownerMeta = MetadataRegistry.get(ownerClass);
1042
+ const item = this.graph.items.find(
1043
+ (i) => i.relationProperty === relationProperty && (i.ownerClass === ownerClass || i.ownerClass.name === ownerClass.name)
1044
+ );
1045
+ if (item === void 0) {
1046
+ throw new Error(
1047
+ `Maintenance rebuild: no maintainer found for property '${relationProperty}' on '${ownerClass.name}'. The rebuilder repairs declared \`maintainedOn\` maintainers (snapshot / collection / counter); '${relationProperty}' declares none, or its model is not in this rebuilder's scope.`
1048
+ );
1049
+ }
1050
+ const ownerKey = (input) => {
1051
+ const { Key } = buildDeleteInput(
1052
+ ownerClass,
1053
+ input
1054
+ );
1055
+ return Key;
1056
+ };
1057
+ return { item, ownerMeta, ownerKey };
1058
+ }
1059
+ /**
1060
+ * Scan every source row bound to this owner row and re-derive the maintained value:
1061
+ *
1062
+ * - **collection** — project each source row, order + trim by the SAME read-side
1063
+ * rules (`orderBy` / `orderDir` / `maxItems`) the drain uses, return the list;
1064
+ * - **snapshot** — project the single bound source row (or `undefined` when none);
1065
+ * - **counter `count`** — the COUNT of source rows (absolute, not an ADD);
1066
+ * - **counter `max`** — the maximum source value of the tracked field.
1067
+ */
1068
+ async recompute(item, _ownerMeta, ownerKeyInput) {
1069
+ const effect = item.effect;
1070
+ if (effect.kind === "membership") {
1071
+ throw new Error(
1072
+ `Maintenance rebuild: sparse-view membership maintainer '${item.relationProperty}' on '${item.ownerEntity}' is not yet supported by the rebuild planner (#133 follow-up). A membership row appears/disappears per source row by predicate; rebuild it by re-running the source events through the drain.`
1073
+ );
1074
+ }
1075
+ const sources = await this.scanSourceRows(item, ownerKeyInput);
1076
+ if (effect.kind === "collection") {
1077
+ return this.recomputeCollection(effect, sources);
1078
+ }
1079
+ if (effect.kind === "snapshot") {
1080
+ return this.recomputeSnapshot(effect, sources);
1081
+ }
1082
+ return this.recomputeCounter(effect, sources);
1083
+ }
1084
+ /**
1085
+ * The source rows bound to one owner row. The maintenance key binding is
1086
+ * `{ ownerField: '$.entity.<sourceField>' }` (the destination owner-key field ← the
1087
+ * source row's field). INVERTED for a rebuild: the owner row supplies the value, and
1088
+ * the source partition is queried for rows whose `<sourceField>` matches — exactly the
1089
+ * set the live `hasMany` / `@aggregate` read aggregates. Queries the source via the
1090
+ * same {@link plan} the read planner uses (a partition Query), paginating fully.
1091
+ */
1092
+ async scanSourceRows(item, ownerKeyInput) {
1093
+ const sourceMeta = MetadataRegistry.get(item.sourceClass);
1094
+ const queryKey = {};
1095
+ for (const [ownerField, srcPath] of Object.entries(item.effect.keys)) {
1096
+ const sourceField = pathField(srcPath);
1097
+ queryKey[sourceField] = ownerKeyInput[ownerField];
1098
+ }
1099
+ const executor = ClientManager.getExecutor();
1100
+ const rows = [];
1101
+ let after;
1102
+ do {
1103
+ const execPlan = plan(sourceMeta, {
1104
+ key: queryKey,
1105
+ // Select all declared source fields so every projection / value source path
1106
+ // and the sort-key leaf is present on the scanned row.
1107
+ select: selectAll(sourceMeta),
1108
+ consistentRead: false,
1109
+ ...after ? { after } : {}
1110
+ });
1111
+ const op = execPlan.operations[0];
1112
+ const res = await executor.execute(op);
1113
+ for (const it of res.items) rows.push(it);
1114
+ after = res.lastEvaluatedKey;
1115
+ } while (after !== void 0);
1116
+ return rows;
1117
+ }
1118
+ /** Re-derive a bounded collection: project, then order + trim by the read-side rules. */
1119
+ recomputeCollection(effect, sources) {
1120
+ if (effect.collection.orderBy === void 0 && effect.collection.maxItems !== void 0) {
1121
+ throw new Error(
1122
+ `Maintenance rebuild: relation '${effect.collection.field}' maintains an UNORDERED bounded collection (\`maxItems: ${effect.collection.maxItems}\` with no \`read.order\`). Its trimmed contents depend on stream ARRIVAL order, which the source rows do not record, so the value cannot be faithfully rebuilt from source \u2014 a rebuild would keep a different subset than the drain converged to. Declare a \`read.order\` on the relation so the maintained collection orders by the source's sort-key field (then the rebuild and the drain agree), or rebuild it unbounded.`
1123
+ );
1124
+ }
1125
+ const projected = sources.map((row) => projectFrom(effect.project, row));
1126
+ return orderAndTrimCollection(projected, effect.collection);
1127
+ }
1128
+ /**
1129
+ * Re-derive a single-row snapshot. A snapshot mirrors ONE source row (a `belongsTo` /
1130
+ * `hasOne`, normally 1:1). In the unusual case where MORE THAN ONE source row binds, the
1131
+ * live single-value read takes the FIRST row in the source's natural query order
1132
+ * (`ScanIndexForward`, default ASC = the smallest sort-key leaf), so re-derive the same
1133
+ * row — {@link pickFirst} — for a verdict consistent with the live read. Returns
1134
+ * `undefined` when no source row is bound (the snapshot should be absent).
1135
+ */
1136
+ recomputeSnapshot(effect, sources) {
1137
+ if (sources.length === 0) return void 0;
1138
+ const chosen = sources.length === 1 ? sources[0] : pickFirst(sources, this.sourceMetaOf(effect));
1139
+ return projectFrom(effect.project, chosen);
1140
+ }
1141
+ /** The source entity metadata a maintain effect projects from (its relation target). */
1142
+ sourceMetaOf(effect) {
1143
+ const item = this.graph.items.find((i) => i.effect === effect);
1144
+ return item ? MetadataRegistry.get(item.sourceClass) : void 0;
1145
+ }
1146
+ /** Re-derive a counter: the absolute COUNT of source rows, or the MAX of the tracked field. */
1147
+ recomputeCounter(effect, sources) {
1148
+ if (effect.value.op === "count") {
1149
+ return sources.length;
1150
+ }
1151
+ const field2 = effect.value.field;
1152
+ let best;
1153
+ for (const row of sources) {
1154
+ const v = row[field2];
1155
+ if (v === void 0 || v === null) continue;
1156
+ if (best === void 0 || compareDesc(v, best) < 0) best = v;
1157
+ }
1158
+ return best;
1159
+ }
1160
+ /** Read the owner row (consistent) for the drift comparison / actual value. */
1161
+ async readOwnerRow(ownerMeta, ownerKey) {
1162
+ const res = await ClientManager.getExecutor().execute({
1163
+ type: "GetItem",
1164
+ tableName: TableMapping.resolve(ownerMeta.tableName),
1165
+ keyCondition: ownerKey,
1166
+ consistentRead: true
1167
+ });
1168
+ return res.items[0];
1169
+ }
1170
+ /** The value currently stored on the owner row for this maintainer. */
1171
+ actualValue(effect, ownerRow) {
1172
+ if (ownerRow === void 0) return void 0;
1173
+ if (effect.kind === "collection") {
1174
+ return ownerRow[effect.collection.field];
1175
+ }
1176
+ if (effect.kind === "counter") {
1177
+ return ownerRow[effect.attribute];
1178
+ }
1179
+ const out = {};
1180
+ let anyPresent = false;
1181
+ for (const attr of Object.keys(effect.project)) {
1182
+ if (Object.prototype.hasOwnProperty.call(ownerRow, attr)) {
1183
+ out[attr] = ownerRow[attr];
1184
+ anyPresent = true;
1185
+ }
1186
+ }
1187
+ return anyPresent ? out : void 0;
1188
+ }
1189
+ /** Write the re-derived ABSOLUTE value onto the owner row (the repair). */
1190
+ async writeValue(effect, ownerMeta, ownerKey, expected) {
1191
+ const TableName = TableMapping.resolve(ownerMeta.tableName);
1192
+ const executor = ClientManager.getExecutor();
1193
+ if (effect.kind === "collection") {
1194
+ await executor.update({
1195
+ TableName,
1196
+ Key: ownerKey,
1197
+ UpdateExpression: "SET #c = :list",
1198
+ ExpressionAttributeNames: { "#c": effect.collection.field },
1199
+ ExpressionAttributeValues: { ":list": expected ?? [] }
1200
+ });
1201
+ return;
1202
+ }
1203
+ if (effect.kind === "counter") {
1204
+ if (expected === void 0 || expected === null) {
1205
+ if (effect.value.op === "count") {
1206
+ await executor.update({
1207
+ TableName,
1208
+ Key: ownerKey,
1209
+ UpdateExpression: "SET #a = :v",
1210
+ ExpressionAttributeNames: { "#a": effect.attribute },
1211
+ ExpressionAttributeValues: { ":v": 0 }
1212
+ });
1213
+ } else {
1214
+ await executor.update({
1215
+ TableName,
1216
+ Key: ownerKey,
1217
+ UpdateExpression: "REMOVE #a",
1218
+ ExpressionAttributeNames: { "#a": effect.attribute }
1219
+ });
1220
+ }
1221
+ return;
1222
+ }
1223
+ await executor.update({
1224
+ TableName,
1225
+ Key: ownerKey,
1226
+ UpdateExpression: "SET #a = :v",
1227
+ ExpressionAttributeNames: { "#a": effect.attribute },
1228
+ ExpressionAttributeValues: { ":v": expected }
1229
+ });
1230
+ return;
1231
+ }
1232
+ if (expected === void 0) {
1233
+ const names2 = {};
1234
+ const removes = [];
1235
+ let i2 = 0;
1236
+ for (const attr of Object.keys(effect.project)) {
1237
+ names2[`#m${i2}`] = attr;
1238
+ removes.push(`#m${i2}`);
1239
+ i2 += 1;
1240
+ }
1241
+ if (removes.length === 0) return;
1242
+ await executor.update({
1243
+ TableName,
1244
+ Key: ownerKey,
1245
+ UpdateExpression: `REMOVE ${removes.join(", ")}`,
1246
+ ExpressionAttributeNames: names2
1247
+ });
1248
+ return;
1249
+ }
1250
+ const projection = expected;
1251
+ const names = {};
1252
+ const values = {};
1253
+ const sets = [];
1254
+ let i = 0;
1255
+ for (const [attr, value] of Object.entries(projection)) {
1256
+ names[`#m${i}`] = attr;
1257
+ values[`:m${i}`] = value;
1258
+ sets.push(`#m${i} = :m${i}`);
1259
+ i += 1;
1260
+ }
1261
+ if (sets.length === 0) return;
1262
+ await executor.update({
1263
+ TableName,
1264
+ Key: ownerKey,
1265
+ UpdateExpression: `SET ${sets.join(", ")}`,
1266
+ ExpressionAttributeNames: names,
1267
+ ExpressionAttributeValues: values
1268
+ });
1269
+ }
1270
+ };
1271
+ function selectAll(meta) {
1272
+ const select = {};
1273
+ for (const f of meta.fields) select[f.propertyName] = true;
1274
+ return select;
1275
+ }
1276
+ function pickFirst(sources, sourceMeta) {
1277
+ const skFields = sourceMeta?.primaryKey ? segmentFieldNames(sourceMeta.primaryKey.segmented.skSegments) : [];
1278
+ const orderField = skFields[skFields.length - 1];
1279
+ if (orderField === void 0) return sources[0];
1280
+ return [...sources].sort((a, b) => compareDesc(b[orderField], a[orderField]))[0];
1281
+ }
1282
+ function normalize(value) {
1283
+ if (value === void 0 || value === null) return void 0;
1284
+ if (typeof value === "number") return value;
1285
+ if (typeof value === "string" && /^-?\d+$/.test(value)) {
1286
+ const n = Number(value);
1287
+ if (Number.isSafeInteger(n)) return n;
1288
+ }
1289
+ if (Array.isArray(value)) return value.map(normalize);
1290
+ if (typeof value === "object") {
1291
+ const out = {};
1292
+ for (const [k2, v] of Object.entries(value)) {
1293
+ const nv = normalize(v);
1294
+ if (nv === void 0) continue;
1295
+ out[k2] = nv;
1296
+ }
1297
+ return out;
1298
+ }
1299
+ return value;
1300
+ }
1301
+ function isEmptyMaintained(effect, expected) {
1302
+ if (effect.kind === "collection") {
1303
+ return Array.isArray(expected) && expected.length === 0;
1304
+ }
1305
+ if (effect.kind === "counter") {
1306
+ return effect.value.op === "count" ? expected === 0 : expected === void 0 || expected === null;
1307
+ }
1308
+ return expected === void 0;
1309
+ }
1310
+ function deepEqual(a, b) {
1311
+ if (a === b) return true;
1312
+ if (a === void 0 || b === void 0 || a === null || b === null) return a === b;
1313
+ if (Array.isArray(a) && Array.isArray(b)) {
1314
+ if (a.length !== b.length) return false;
1315
+ return a.every((v, i) => deepEqual(v, b[i]));
1316
+ }
1317
+ if (typeof a === "object" && typeof b === "object") {
1318
+ const ka = Object.keys(a);
1319
+ const kb = Object.keys(b);
1320
+ if (ka.length !== kb.length) return false;
1321
+ return ka.every(
1322
+ (k2) => deepEqual(
1323
+ a[k2],
1324
+ b[k2]
1325
+ )
1326
+ );
1327
+ }
1328
+ return false;
1329
+ }
1330
+ function createMaintenanceRebuilder(opts = {}) {
1331
+ return new MaintenanceRebuilder(opts);
1332
+ }
1333
+
958
1334
  // src/define/define.ts
959
1335
  function collectParams(structure, out = {}) {
960
1336
  if (structure === null || typeof structure !== "object") return out;
@@ -1170,15 +1546,21 @@ export {
1170
1546
  DynamoExecutor,
1171
1547
  EDGE_WRITES_MARKER,
1172
1548
  ENTITY_WRITES_MARKER,
1549
+ InMemoryProjectionSink,
1173
1550
  LIFECYCLE_CONTRACT_MARKER,
1174
1551
  Linter,
1552
+ MAINT_OUTBOX_PK_PREFIX,
1175
1553
  MAX_TRANSACT_ITEMS,
1554
+ MaintenanceDrain,
1555
+ MaintenanceRebuilder,
1176
1556
  MetadataRegistry,
1177
1557
  OLD_VALUE_NAMESPACE,
1558
+ ProjectionSinkDrain,
1178
1559
  RetryingExecutor,
1179
1560
  SPEC_VERSION,
1180
1561
  TableMapping,
1181
1562
  TransactionContext,
1563
+ ViewRegistry,
1182
1564
  aggregate,
1183
1565
  assertBundleSerializable,
1184
1566
  assertContractBoundaries,
@@ -1215,6 +1597,11 @@ export {
1215
1597
  count,
1216
1598
  createCdcEmulator,
1217
1599
  createDefaultLinter,
1600
+ createMaintenanceDrain,
1601
+ createMaintenanceDrainHandler,
1602
+ createMaintenanceRebuilder,
1603
+ createProjectionSinkDrain,
1604
+ createProjectionSinkHandler,
1218
1605
  datetime,
1219
1606
  decodeCursor,
1220
1607
  decodePerKeyCursor,
@@ -1222,12 +1609,17 @@ export {
1222
1609
  defineDelete,
1223
1610
  defineList,
1224
1611
  definePlan,
1612
+ defineProjection,
1613
+ defineProjections,
1225
1614
  definePut,
1226
1615
  defineQueries,
1227
1616
  defineQuery,
1228
1617
  defineTransaction,
1229
1618
  defineTransactions,
1230
1619
  defineUpdate,
1620
+ defineVersioned,
1621
+ defineView,
1622
+ defineViews,
1231
1623
  deriveEdgeWriteItems,
1232
1624
  deriveEdgeWriteItemsFor,
1233
1625
  deriveModelEdgeWriteItems,
@@ -1283,11 +1675,13 @@ export {
1283
1675
  isMutationInputRef,
1284
1676
  isParam,
1285
1677
  isPlannedCommandMethod,
1678
+ isProjectionDefinition,
1286
1679
  isQueryModelContract,
1287
1680
  isRetryableError,
1288
1681
  isRetryableTransactionCancellation,
1289
1682
  isSelectBuilder,
1290
1683
  isTransactionRef,
1684
+ isViewDefinition,
1291
1685
  k,
1292
1686
  key,
1293
1687
  lifecyclePhaseForIntent,
@@ -1323,5 +1717,6 @@ export {
1323
1717
  validateDepth,
1324
1718
  validateGsiAmbiguity,
1325
1719
  when,
1720
+ whenMember,
1326
1721
  wholeKeysSentinel
1327
1722
  };
@@ -1,4 +1,4 @@
1
- import { E as Executor, D as DynamoDBOperation, R as ReadExecOptions, a as ExecutorResult, B as BatchGetExecInput, P as PutInput, W as WriteExecOptions, b as WriteResult, U as UpdateInput, c as DeleteInput, d as BatchWriteExecItem, e as BatchExecOptions, T as TransactWriteExecItem, M as ModelStatic, f as DDBModel, C as ChangeEvent } from '../types-xJRn5qkv.js';
1
+ import { E as Executor, D as DynamoDBOperation, R as ReadExecOptions, a as ExecutorResult, B as BatchGetExecInput, P as PutInput, W as WriteExecOptions, b as WriteResult, U as UpdateInput, c as DeleteInput, d as BatchWriteExecItem, e as BatchExecOptions, T as TransactWriteExecItem, M as ModelStatic, f as DDBModel, C as ChangeEvent } from '../types-DuJ08bgc.js';
2
2
  import '@aws-sdk/client-dynamodb';
3
3
 
4
4
  /**
@@ -1,12 +1,12 @@
1
1
  import {
2
2
  createCdcEmulator
3
- } from "../chunk-QQNP43JL.js";
3
+ } from "../chunk-PNIZS37E.js";
4
4
  import {
5
5
  ClientManager,
6
6
  MetadataRegistry,
7
7
  TableMapping,
8
8
  resolveModelClass
9
- } from "../chunk-6AIAHP3A.js";
9
+ } from "../chunk-YIXXTGZ6.js";
10
10
 
11
11
  // src/memory/memory-store.ts
12
12
  function deepClone(value) {