@nivaro/sdk 0.1.24 → 0.1.26

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -1889,6 +1889,81 @@ When SLA rules, scheduled flows, or other time-tracking systems are active:
1889
1889
 
1890
1890
  ---
1891
1891
 
1892
+ ## SDK — Layout Editor
1893
+
1894
+ The layout editor saves through a bundle + ops model: read the layout as `{ layout, groups, placements, rev }`, send a batch of small ops with the `rev` you read, and get the new bundle back. A batch applies all or nothing. Every call below except the picker and scheduled-change tools is admin only.
1895
+
1896
+ ```typescript
1897
+ import {
1898
+ readLayoutBundle, submitLayoutOps,
1899
+ readLayoutOverview, explainLayout,
1900
+ createCollectionLayout, cloneLayout, readActiveLayout
1901
+ } from '@nivaro/sdk'
1902
+
1903
+ const bundle = await nivaro.request(readLayoutBundle(42))
1904
+
1905
+ try {
1906
+ const next = await nivaro.request(
1907
+ submitLayoutOps(42, {
1908
+ base_rev: bundle.rev,
1909
+ note: 'Move Status into the header',
1910
+ ops: [
1911
+ { op: 'move', from: { field: 'status', group_key: 'details' }, to_group_key: null, index: 0 },
1912
+ { op: 'update_placement', at: { field: 'owner', group_key: null }, patch: { col_span: 6 } },
1913
+ { op: 'layout_update', patch: { disable_clone: true } }
1914
+ ]
1915
+ })
1916
+ )
1917
+ } catch (err) {
1918
+ // 409 { error: 'stale', bundle }: the layout changed since base_rev. Re-apply on err.response.bundle.
1919
+ // 400 { error, op_index }: the op at op_index was refused; nothing was saved.
1920
+ }
1921
+ ```
1922
+
1923
+ The op union (`LayoutOp`), `LayoutBundle`, `PlacementPatch`, `GroupPatch` and `LayoutPatch` are exported as types, with `PLACEMENT_PATCH_KEYS`, `GROUP_PATCH_KEYS` and `LAYOUT_PATCH_KEYS` as runtime lists. A batch holds at most 500 ops.
1924
+
1925
+ #### Commands
1926
+
1927
+ | Command | Route | Notes |
1928
+ | --- | --- | --- |
1929
+ | readLayoutBundle(id) | GET /collection-layouts/:id/bundle | Returns the bundle itself (no `data` wrapper). |
1930
+ | submitLayoutOps(id, { ops, base_rev, note? }) | POST /collection-layouts/:id/ops | Returns the new bundle; 409 stale carries the current bundle, 400 carries `op_index`. |
1931
+ | readLayoutOverview(collection) | GET /collection-layouts/overview | Every layout, sectioned the way the active-layout resolution checks them, with references and warnings. |
1932
+ | explainLayout({ collection, item?, role_id?, slug? }) | GET /collection-layouts/explain | Which layout a record opens with, why, and each candidate's check. |
1933
+ | createCollectionLayout(collection, name, { slug?, layout_type?, seed_fields? }) | POST /collection-layouts | `seed_fields` starts the layout with one Main section holding every visible field. |
1934
+ | cloneLayout(id, name, { slug?, layout_type? }) | POST /collection-layouts/:id/clone | The copy starts hidden from the New menu (`create_hidden`); an admin opts it in. |
1935
+ | readActiveLayout(collection, { slug?, item? }) | GET /collection-layouts/active | Placements carry `col_span`; the result includes `ungrouped_sort`. |
1936
+ | updateCollectionLayout(id, patch) | PATCH /collection-layouts/:id | Any `LayoutPatch` setting. |
1937
+ | readLayoutVersion / diffLayoutVersion / restoreLayoutVersion | /collection-layouts/:id/versions/... | A restore snapshots the current state first, so it is reversible. |
1938
+ | projectFieldConfig(collection, placements) | POST /field-config/:collection/project | The field-config rows a draft would produce. A read; writes nothing. |
1939
+ | listInternalWidgetPlacements(widgetId) | GET /widgets-internal/:id/placements | The layouts that place a widget. |
1940
+
1941
+ #### Layout-gated record tools
1942
+
1943
+ Disabling a record in pickers and scheduling a change accept `layout`, the `?layout=` slug of the form the record was opened with. A non-admin may use them only when that form grants it (`allow_disable_pickers`, `allow_schedule`) and they may update the record. Scheduled changes for non-admins are limited to real, writable columns they may update; a read-only, computed or alias field is refused with 400.
1944
+
1945
+ ```typescript
1946
+ import { excludeFromPickers, includeInPickers, createScheduledChange } from '@nivaro/sdk'
1947
+
1948
+ await nivaro.request(excludeFromPickers({ collection: 'vendors', item_id: 17, layout: 'intake' }))
1949
+ await nivaro.request(includeInPickers({ collection: 'vendors', item_id: 17, layout: 'intake' }))
1950
+
1951
+ await nivaro.request(
1952
+ createScheduledChange({
1953
+ collection: 'vendors',
1954
+ item_id: '17',
1955
+ change_type: 'field_update',
1956
+ changes: { status: 'inactive' },
1957
+ scheduled_at: '2026-12-01T09:00:00Z',
1958
+ layout: 'intake'
1959
+ })
1960
+ )
1961
+ ```
1962
+
1963
+ > **Note:** Retired layout settings are no longer writable: `summary_show_all`, `allow_clone` (use `disable_clone`), `addendum_lock_fields` and `hide_actions_when_collapsed`. They stay optional and deprecated on the `CollectionLayout` read type.
1964
+
1965
+ ---
1966
+
1892
1967
  ## SDK — Schema Snapshots
1893
1968
 
1894
1969
  Capture point-in-time snapshots of your entire metadata registry (collections, fields, relations). Useful for version control, environment promotion, and disaster recovery.