@ftschopp/dynatable-core 2.2.1 → 2.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +7 -0
- package/README.md +14 -0
- package/dist/builders/update/create-update-builder.d.ts.map +1 -1
- package/dist/builders/update/create-update-builder.js +27 -0
- package/dist/builders/update/types.d.ts +22 -0
- package/dist/builders/update/types.d.ts.map +1 -1
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,3 +1,10 @@
|
|
|
1
|
+
# @ftschopp/dynatable-core [2.3.0](https://github.com/ftschopp/dynatable/compare/@ftschopp/dynatable-core@2.2.1...@ftschopp/dynatable-core@2.3.0) (2026-06-03)
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
### Features
|
|
5
|
+
|
|
6
|
+
* **core:** add setDefined to UpdateBuilder ([#58](https://github.com/ftschopp/dynatable/issues/58)) ([851c0dc](https://github.com/ftschopp/dynatable/commit/851c0dc8ab6c6eed0555c874c6230d8997530808)), closes [#56](https://github.com/ftschopp/dynatable/issues/56) [#57](https://github.com/ftschopp/dynatable/issues/57)
|
|
7
|
+
|
|
1
8
|
## @ftschopp/dynatable-core [2.2.1](https://github.com/ftschopp/dynatable/compare/@ftschopp/dynatable-core@2.2.0...@ftschopp/dynatable-core@2.2.1) (2026-06-03)
|
|
2
9
|
|
|
3
10
|
|
package/README.md
CHANGED
|
@@ -272,6 +272,20 @@ await table.entities.User.update({ username: 'alice' })
|
|
|
272
272
|
// to clear an attribute, or filter `undefined` out of your payload before
|
|
273
273
|
// calling `.set()`. `null` is allowed — it writes the DynamoDB `NULL` type.
|
|
274
274
|
|
|
275
|
+
// UPSERT via setDefined - sync from an external system where undefined
|
|
276
|
+
// means "this attribute no longer applies". Defined values go to SET,
|
|
277
|
+
// undefined keys go to REMOVE. Internally composes `.set()` + `.remove()`,
|
|
278
|
+
// so all guards (PK template, GSI templates, dedup, GSI key recomputation)
|
|
279
|
+
// apply identically.
|
|
280
|
+
await table.entities.User.update({ username: 'alice' })
|
|
281
|
+
.setDefined({
|
|
282
|
+
name: tamsRecord.name, // SET
|
|
283
|
+
email: tamsRecord.email, // may be undefined → REMOVE
|
|
284
|
+
lastSeenAt: new Date().toISOString(),
|
|
285
|
+
})
|
|
286
|
+
.setIfNotExists('createdAt', new Date().toISOString())
|
|
287
|
+
.execute();
|
|
288
|
+
|
|
275
289
|
// DELETE - Remove item
|
|
276
290
|
await table.entities.User.delete({ username: 'alice' })
|
|
277
291
|
.returning('ALL_OLD')
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"create-update-builder.d.ts","sourceRoot":"","sources":["../../../src/builders/update/create-update-builder.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,cAAc,EAAE,MAAM,0BAA0B,CAAC;AAE1D,OAAO,EAAgC,SAAS,EAA4B,MAAM,WAAW,CAAC;AAC9F,OAAO,EAAE,aAAa,EAAE,YAAY,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AACpE,OAAO,EAAE,cAAc,EAAE,MAAM,6BAA6B,CAAC;AAkE7D;;;;;;;;GAQG;AACH,wBAAgB,mBAAmB,CAAC,KAAK,EACvC,SAAS,EAAE,MAAM,EACjB,GAAG,EAAE,OAAO,CAAC,KAAK,CAAC,EACnB,MAAM,EAAE,cAAc,EACtB,cAAc,GAAE,SAAS,EAAO,EAChC,aAAa,GAAE;IACb,GAAG,EAAE,YAAY,EAAE,CAAC;IACpB,MAAM,EAAE,YAAY,EAAE,CAAC;IACvB,GAAG,EAAE,YAAY,EAAE,CAAC;IACpB,MAAM,EAAE,YAAY,EAAE,CAAC;CACuB,EAChD,UAAU,GAAE,MAAM,GAAG,SAAS,GAAG,SAAS,GAAG,aAAa,GAAG,aAAsB,EACnF,YAAY,SAAI,EAChB,gBAAgB,UAAQ,EACxB,MAAM,CAAC,EAAE,cAAc,EACvB,YAAY,CAAC,EAAE,YAAY,EAC3B,SAAS,GAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAM,EACnC,gBAAgB,CAAC,EAAE,SAAS,GAAG,OAAO,GAAG,MAAM,EAO/C,oBAAoB,GAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAM,GAC7C,aAAa,CAAC,KAAK,CAAC,
|
|
1
|
+
{"version":3,"file":"create-update-builder.d.ts","sourceRoot":"","sources":["../../../src/builders/update/create-update-builder.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,cAAc,EAAE,MAAM,0BAA0B,CAAC;AAE1D,OAAO,EAAgC,SAAS,EAA4B,MAAM,WAAW,CAAC;AAC9F,OAAO,EAAE,aAAa,EAAE,YAAY,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AACpE,OAAO,EAAE,cAAc,EAAE,MAAM,6BAA6B,CAAC;AAkE7D;;;;;;;;GAQG;AACH,wBAAgB,mBAAmB,CAAC,KAAK,EACvC,SAAS,EAAE,MAAM,EACjB,GAAG,EAAE,OAAO,CAAC,KAAK,CAAC,EACnB,MAAM,EAAE,cAAc,EACtB,cAAc,GAAE,SAAS,EAAO,EAChC,aAAa,GAAE;IACb,GAAG,EAAE,YAAY,EAAE,CAAC;IACpB,MAAM,EAAE,YAAY,EAAE,CAAC;IACvB,GAAG,EAAE,YAAY,EAAE,CAAC;IACpB,MAAM,EAAE,YAAY,EAAE,CAAC;CACuB,EAChD,UAAU,GAAE,MAAM,GAAG,SAAS,GAAG,SAAS,GAAG,aAAa,GAAG,aAAsB,EACnF,YAAY,SAAI,EAChB,gBAAgB,UAAQ,EACxB,MAAM,CAAC,EAAE,cAAc,EACvB,YAAY,CAAC,EAAE,YAAY,EAC3B,SAAS,GAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAM,EACnC,gBAAgB,CAAC,EAAE,SAAS,GAAG,OAAO,GAAG,MAAM,EAO/C,oBAAoB,GAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAM,GAC7C,aAAa,CAAC,KAAK,CAAC,CA6lBtB"}
|
|
@@ -162,6 +162,33 @@ setIfNotExistsInputs = {}) {
|
|
|
162
162
|
};
|
|
163
163
|
return createUpdateBuilder(tableName, key, client, conditions, { ...updateActions, set: [...updateActions.set, action] }, returnMode, valueCounter, enableTimestamps, logger, indexContext, setInputs, consumedCapacity, { ...setIfNotExistsInputs, [attrName]: value });
|
|
164
164
|
},
|
|
165
|
+
setDefined(updates) {
|
|
166
|
+
// Split the payload, then route through the public `.set()` and
|
|
167
|
+
// `.remove()` paths so all of their guards apply unchanged: PK
|
|
168
|
+
// template immutability, GSI template guard 2 (which will reject
|
|
169
|
+
// any `undefined` targeting a GSI-template field), dedup, and the
|
|
170
|
+
// index-key recomputation triggered by `setInputs`. Composing the
|
|
171
|
+
// builder instead of re-emitting actions keeps the surface area
|
|
172
|
+
// of this method as close to zero as possible.
|
|
173
|
+
const defined = {};
|
|
174
|
+
const toRemove = [];
|
|
175
|
+
for (const [attr, val] of Object.entries(updates)) {
|
|
176
|
+
if (val === undefined) {
|
|
177
|
+
toRemove.push(attr);
|
|
178
|
+
}
|
|
179
|
+
else {
|
|
180
|
+
defined[attr] = val;
|
|
181
|
+
}
|
|
182
|
+
}
|
|
183
|
+
let next = build();
|
|
184
|
+
if (Object.keys(defined).length > 0) {
|
|
185
|
+
next = next.set(defined);
|
|
186
|
+
}
|
|
187
|
+
for (const attr of toRemove) {
|
|
188
|
+
next = next.remove(attr);
|
|
189
|
+
}
|
|
190
|
+
return next;
|
|
191
|
+
},
|
|
165
192
|
remove(attr) {
|
|
166
193
|
const attrName = normalizeAttr(attr);
|
|
167
194
|
const action = {
|
|
@@ -59,6 +59,28 @@ export interface UpdateBuilder<Model> extends Omit<OperationBuilder<Model>, 'dbP
|
|
|
59
59
|
*/
|
|
60
60
|
setIfNotExists(attr: keyof Model | AttrRef, value: any): UpdateBuilder<Model>;
|
|
61
61
|
setIfNotExists(updates: Partial<Model>): UpdateBuilder<Model>;
|
|
62
|
+
/**
|
|
63
|
+
* Upsert helper: writes attributes whose value is defined with SET, and
|
|
64
|
+
* removes attributes whose value is `undefined`. Equivalent to splitting
|
|
65
|
+
* the payload between `.set()` and `.remove()` at the call site, but
|
|
66
|
+
* makes the intent explicit at the API.
|
|
67
|
+
*
|
|
68
|
+
* Typical use case: syncing from an external system where a missing field
|
|
69
|
+
* in the source payload means "this attribute no longer applies" rather
|
|
70
|
+
* than "leave the existing value alone" — the latter is what `.set()`
|
|
71
|
+
* with `undefined` would imply, and it's a destructive footgun the strict
|
|
72
|
+
* `.set()` rightly rejects.
|
|
73
|
+
*
|
|
74
|
+
* Internally routes through `.set()` and `.remove()`, so every existing
|
|
75
|
+
* guard (primary-key template, secondary-index templates, dedup,
|
|
76
|
+
* GSI-key recomputation) applies identically — including the rejection
|
|
77
|
+
* of `.remove()` on fields used in a GSI template, which will surface as
|
|
78
|
+
* an error here whenever an `undefined` targets such a field.
|
|
79
|
+
*
|
|
80
|
+
* `null` is treated as a defined value and writes the DynamoDB `NULL`
|
|
81
|
+
* type — only `undefined` triggers the REMOVE branch.
|
|
82
|
+
*/
|
|
83
|
+
setDefined(updates: Partial<Model>): UpdateBuilder<Model>;
|
|
62
84
|
/**
|
|
63
85
|
* Removes an attribute from the item
|
|
64
86
|
*/
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../src/builders/update/types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,uBAAuB,CAAC;AAChE,OAAO,EAAE,eAAe,EAAE,MAAM,cAAc,CAAC;AAC/C,OAAO,EAAE,gBAAgB,EAAE,OAAO,EAAE,WAAW,EAAE,SAAS,EAAE,SAAS,EAAE,MAAM,WAAW,CAAC;AAEzF;;GAEG;AACH,MAAM,MAAM,YAAY,GAAG;IACzB,UAAU,EAAE,MAAM,CAAC;IACnB,KAAK,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAC/B,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;CAC9B,CAAC;AAEF;;;;;;;GAOG;AACH,MAAM,MAAM,YAAY,GAAG;IACzB,KAAK,EAAE,eAAe,CAAC;IACvB,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;CAC9B,CAAC;AAEF;;GAEG;AACH,MAAM,WAAW,aAAa,CAAC,KAAK,CAAE,SAAQ,IAAI,CAAC,gBAAgB,CAAC,KAAK,CAAC,EAAE,UAAU,GAAG,OAAO,CAAC;IAC/F;;;;;;;;OAQG;IACH,KAAK,CAAC,EAAE,EAAE,CAAC,IAAI,EAAE,WAAW,CAAC,KAAK,CAAC,EAAE,EAAE,EAAE,SAAS,KAAK,SAAS,GAAG,aAAa,CAAC,KAAK,CAAC,CAAC;IAExF;;OAEG;IACH,GAAG,CAAC,IAAI,EAAE,MAAM,KAAK,GAAG,OAAO,EAAE,KAAK,EAAE,GAAG,GAAG,aAAa,CAAC,KAAK,CAAC,CAAC;IACnE,GAAG,CAAC,OAAO,EAAE,OAAO,CAAC,KAAK,CAAC,GAAG,aAAa,CAAC,KAAK,CAAC,CAAC;IAEnD;;;;;;;;;;;;;;;;OAgBG;IACH,cAAc,CAAC,IAAI,EAAE,MAAM,KAAK,GAAG,OAAO,EAAE,KAAK,EAAE,GAAG,GAAG,aAAa,CAAC,KAAK,CAAC,CAAC;IAC9E,cAAc,CAAC,OAAO,EAAE,OAAO,CAAC,KAAK,CAAC,GAAG,aAAa,CAAC,KAAK,CAAC,CAAC;IAE9D;;OAEG;IACH,MAAM,CAAC,IAAI,EAAE,MAAM,KAAK,GAAG,OAAO,GAAG,aAAa,CAAC,KAAK,CAAC,CAAC;IAE1D;;OAEG;IACH,GAAG,CAAC,IAAI,EAAE,MAAM,KAAK,GAAG,OAAO,EAAE,KAAK,EAAE,GAAG,GAAG,aAAa,CAAC,KAAK,CAAC,CAAC;IAEnE;;OAEG;IACH,MAAM,CAAC,IAAI,EAAE,MAAM,KAAK,GAAG,OAAO,EAAE,KAAK,EAAE,GAAG,GAAG,aAAa,CAAC,KAAK,CAAC,CAAC;IAEtE;;OAEG;IACH,SAAS,CACP,IAAI,EAAE,MAAM,GAAG,SAAS,GAAG,SAAS,GAAG,aAAa,GAAG,aAAa,GACnE,aAAa,CAAC,KAAK,CAAC,CAAC;IAExB;;;;;;;;OAQG;IACH,sBAAsB,CAAC,IAAI,EAAE,SAAS,GAAG,OAAO,GAAG,MAAM,GAAG,aAAa,CAAC,KAAK,CAAC,CAAC;IAEjF;;OAEG;IACH,QAAQ,IAAI,kBAAkB,CAAC;CAChC"}
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../src/builders/update/types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,uBAAuB,CAAC;AAChE,OAAO,EAAE,eAAe,EAAE,MAAM,cAAc,CAAC;AAC/C,OAAO,EAAE,gBAAgB,EAAE,OAAO,EAAE,WAAW,EAAE,SAAS,EAAE,SAAS,EAAE,MAAM,WAAW,CAAC;AAEzF;;GAEG;AACH,MAAM,MAAM,YAAY,GAAG;IACzB,UAAU,EAAE,MAAM,CAAC;IACnB,KAAK,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAC/B,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;CAC9B,CAAC;AAEF;;;;;;;GAOG;AACH,MAAM,MAAM,YAAY,GAAG;IACzB,KAAK,EAAE,eAAe,CAAC;IACvB,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;CAC9B,CAAC;AAEF;;GAEG;AACH,MAAM,WAAW,aAAa,CAAC,KAAK,CAAE,SAAQ,IAAI,CAAC,gBAAgB,CAAC,KAAK,CAAC,EAAE,UAAU,GAAG,OAAO,CAAC;IAC/F;;;;;;;;OAQG;IACH,KAAK,CAAC,EAAE,EAAE,CAAC,IAAI,EAAE,WAAW,CAAC,KAAK,CAAC,EAAE,EAAE,EAAE,SAAS,KAAK,SAAS,GAAG,aAAa,CAAC,KAAK,CAAC,CAAC;IAExF;;OAEG;IACH,GAAG,CAAC,IAAI,EAAE,MAAM,KAAK,GAAG,OAAO,EAAE,KAAK,EAAE,GAAG,GAAG,aAAa,CAAC,KAAK,CAAC,CAAC;IACnE,GAAG,CAAC,OAAO,EAAE,OAAO,CAAC,KAAK,CAAC,GAAG,aAAa,CAAC,KAAK,CAAC,CAAC;IAEnD;;;;;;;;;;;;;;;;OAgBG;IACH,cAAc,CAAC,IAAI,EAAE,MAAM,KAAK,GAAG,OAAO,EAAE,KAAK,EAAE,GAAG,GAAG,aAAa,CAAC,KAAK,CAAC,CAAC;IAC9E,cAAc,CAAC,OAAO,EAAE,OAAO,CAAC,KAAK,CAAC,GAAG,aAAa,CAAC,KAAK,CAAC,CAAC;IAE9D;;;;;;;;;;;;;;;;;;;;OAoBG;IACH,UAAU,CAAC,OAAO,EAAE,OAAO,CAAC,KAAK,CAAC,GAAG,aAAa,CAAC,KAAK,CAAC,CAAC;IAE1D;;OAEG;IACH,MAAM,CAAC,IAAI,EAAE,MAAM,KAAK,GAAG,OAAO,GAAG,aAAa,CAAC,KAAK,CAAC,CAAC;IAE1D;;OAEG;IACH,GAAG,CAAC,IAAI,EAAE,MAAM,KAAK,GAAG,OAAO,EAAE,KAAK,EAAE,GAAG,GAAG,aAAa,CAAC,KAAK,CAAC,CAAC;IAEnE;;OAEG;IACH,MAAM,CAAC,IAAI,EAAE,MAAM,KAAK,GAAG,OAAO,EAAE,KAAK,EAAE,GAAG,GAAG,aAAa,CAAC,KAAK,CAAC,CAAC;IAEtE;;OAEG;IACH,SAAS,CACP,IAAI,EAAE,MAAM,GAAG,SAAS,GAAG,SAAS,GAAG,aAAa,GAAG,aAAa,GACnE,aAAa,CAAC,KAAK,CAAC,CAAC;IAExB;;;;;;;;OAQG;IACH,sBAAsB,CAAC,IAAI,EAAE,SAAS,GAAG,OAAO,GAAG,MAAM,GAAG,aAAa,CAAC,KAAK,CAAC,CAAC;IAEjF;;OAEG;IACH,QAAQ,IAAI,kBAAkB,CAAC;CAChC"}
|