@lotics/app-sdk 0.87.3 → 0.87.4

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/docs/mutations.md CHANGED
@@ -321,7 +321,8 @@ await update_records({
321
321
 
322
322
  `set` still writes every key it carries — `null` in `set` **clears** the field; `null`/absent in
323
323
  `set_skip_null` **skips** it. The full write surface (`set`, `set_skip_null`, the surgical
324
- `add_to`/`remove_from`/`replace` ops, `field_edits`, and the exact value shape per field type)
324
+ `add_to`/`remove_from`/`replace` ops, `increment`, `field_edits`, and the exact value shape per
325
+ field type)
325
326
  is [workflows](./workflows.md#writing-records).
326
327
 
327
328
  ## Refetch after a mutation
@@ -446,7 +447,9 @@ Why a full-form snapshot save is a bug, not a style choice — three independent
446
447
  append is the system's rather than a person's — an upload settling, a workflow attaching a
447
448
  generated document — name the ITEMS with `add_to` / `remove_from`
448
449
  ([workflows](./workflows.md#writing-records)) and the write path resolves them against the
449
- record as it stands.
450
+ record as it stands. A running total is the scalar form of the same defect: two writers both
451
+ read 100, both subtract 10, both write 90, and one sale is gone with no error anywhere. Name
452
+ the DELTA with `increment`.
450
453
 
451
454
  ```tsx
452
455
  // load: snapshot the editable fields from the row
package/docs/workflows.md CHANGED
@@ -482,31 +482,38 @@ differ from `<` / `>` (code-unit order) and from the database's collation.
482
482
 
483
483
  ## Writing records
484
484
 
485
- `update_records` carries four composable surfaces. A field may appear in **at most one** of them.
485
+ `update_records` carries five composable surfaces. A field may appear in **at most one** of them.
486
486
 
487
487
  | Surface | Shape | Effect |
488
488
  |---|---|---|
489
489
  | `set` | `{ fld_x: value }` | write the whole value. `null` **clears** the field |
490
490
  | `set_skip_null` | `{ fld_x: value }` | same shape, but `null`/`undefined` entries are **dropped** — absent means "leave unchanged" |
491
491
  | `add_to` / `remove_from` / `replace` | `{ fld_x: [items] }` | surgical edits on multi-value fields (files, multi select, multi member, record links) |
492
- | `field_edits` | `[{ field, op, value }]` | the same surgical ops with the field named by a **string expression** the only way to target a field chosen at run time |
493
-
494
- `add_to` / `remove_from` are RELATIVE: the server resolves them against the record as it stands
495
- when the write lands, inside the lock it already takes. Two runs appending to one field at the
496
- same time therefore each keep their item which reading the field and writing the whole array
497
- back through `set` does not, since both fold onto the array they read and the later write drops
498
- the earlier, both reporting success. Parallel runs are ordinary (a trigger firing twice, an agent
499
- emitting two calls in one step), so reach for the ops rather than a read-modify-write whenever
500
- the workflow is ADDING to a field rather than stating it.
492
+ | `increment` | `{ fld_x: delta }` | move a **number** field by a signed amount. Negative decrements; there is no separate decrement op |
493
+ | `field_edits` | `[{ field, op, value }]` | the multi-value ops with the field named by a **string expression** — the only way to target a field chosen at run time. `increment` has no value-form: its payload is a scalar, not an item list |
494
+
495
+ `add_to`, `remove_from` and `increment` are RELATIVE: the server resolves them against the record
496
+ as it stands when the write lands, inside the lock it already takes. Two runs changing one field at
497
+ the same time therefore each keep their effect which reading the field and writing the result back
498
+ through `set` does not, since both fold onto the value they read and the later write drops the
499
+ earlier, both reporting success. On a stock count that is a sale that vanishes. Parallel runs are
500
+ ordinary (a trigger firing twice, an agent emitting two calls in one step), so reach for the ops
501
+ rather than a read-modify-write whenever the workflow is CHANGING a field by an amount rather than
502
+ stating its value.
503
+
504
+ `increment` counts an empty or unset field as 0, so a first decrement leaves a negative — oversold,
505
+ and visibly so. It is rejected on formula, rollup, lookup and autonumber fields: those come from
506
+ their own definition, so change what they aggregate instead.
501
507
 
502
508
  Inside `set` and `create_records.records`: `null` clears (persisted), `undefined` or an omitted
503
509
  key preserves. So passing a possibly-null read straight through is safe. Use
504
510
  `coalesce(x, fallback)` only when you want a real fallback, never to "strip" null.
505
511
 
506
512
  `set_skip_null` is what turns a bag of optional workflow inputs into a diff-write without a guard
507
- per field; naming the same field in both `set` and `set_skip_null` is an error, and an
508
- all-dropped `set_skip_null` with no other surface is a no-op (no records touched, no
509
- `before_update` hooks). Why diffs and not snapshots, plus locked records and the
513
+ per field; naming the same field in both `set` and `set_skip_null` is an error. A call whose
514
+ surfaces all resolve to nothing — an all-dropped `set_skip_null`, an op object with no entries
515
+ is a no-op: no records touched, no `before_update` hooks. So a conditionally-built op object needs
516
+ no guard around the call. Why diffs and not snapshots, plus locked records and the
510
517
  `request_locked_record_change` path: [mutations](./mutations.md#diff-before-update--send-only-what-changed).
511
518
 
512
519
  **A `null` optional input is a CLEAR, and `set_skip_null` drops it.** The caller has three states
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lotics/app-sdk",
3
- "version": "0.87.3",
3
+ "version": "0.87.4",
4
4
  "description": "Runtime SDK for Lotics custom-code apps \u2014 typed hooks, postMessage bridge, mount entry point",
5
5
  "type": "module",
6
6
  "exports": {