@collective-intelligence/external-apps-client-sdk-react 0.0.0-stage → 0.1.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/README.md CHANGED
@@ -1,3 +1,141 @@
1
- # Temporary Holding Version
1
+ # `@collective-intelligence/external-apps-client-sdk-react`
2
2
 
3
- This version is a temporary placeholder for this package. An operational version to replace this has been submitted for review and is awaiting a staged release.
3
+ UI-minimal React bindings over the Promise Client SDK. The package has no private application UI dependencies.
4
+
5
+ `CollectiveIntelligenceProvider` owns a stable, request-isolated QueryClient. TanStack Query is a normal
6
+ SDK dependency; applications do not install it as a peer or configure a QueryClient for SDK CRUD.
7
+ React and React DOM remain peers.
8
+
9
+ Configure the provider's `entitySource` once, alongside its existing Promise `client`. `EntitySource`
10
+ exposes a stable `getSnapshot`, a `subscribe` function, and a typed `bind(contract)` function returning
11
+ the common Promise `EntityClient`. Authenticated snapshots identify the configured logical source,
12
+ application, user, and organization. Obtain those identities from the authenticated application
13
+ session; they are cache boundaries, not access grants. Return a new stable snapshot for every session
14
+ transition, notify subscribers immediately on logout, and bind clients to that snapshot's authority.
15
+ Backend authorization remains authoritative. `CollectiveIntelligenceLoginProvider` forwards the same
16
+ configuration; the entity source must subscribe to the application's CI-derived session lifecycle.
17
+
18
+ ```tsx
19
+ ;<CollectiveIntelligenceProvider client={appSdk} entitySource={entitySource}>
20
+ <Orders />
21
+ </CollectiveIntelligenceProvider>
22
+
23
+ // Import these hooks from /resources. Use the portable entity contract.
24
+ const rows = useEntityList(orderContract, query)
25
+ const record = useEntityRecord(orderContract, { id: selectedId })
26
+ const create = useEntityCreate(orderContract)
27
+ const update = useEntityUpdate(orderContract, { id: selectedId })
28
+ const remove = useEntityDelete(orderContract, { id: selectedId })
29
+
30
+ await update.submit({ value: draft, expectedRevision: editedRecord.revision })
31
+ // Only on an explicit user request to deliver the same action again:
32
+ await update.resubmit()
33
+ ```
34
+
35
+ Reads expose `data`, `loading`, `refreshing`, `error`, `authState`, effective binding `capabilities`,
36
+ and explicit `refresh`; list reads also expose `empty`. Equivalent requests share data across views.
37
+ Cache identity includes source/application/user/organization and resource/version/query, never view
38
+ namespaces or layout settings.
39
+
40
+ Writes expose `available`, record-scoped `pending`, `status`, `data`, `error`, `submitted`, `submit`,
41
+ and `resubmit`. Status distinguishes `conflict`, `rejected`, and `uncertain` from ordinary
42
+ `idle`/`pending`/`success`. Submission clones and freezes the draft and reviewed revision and generates
43
+ one operation key. A new submit creates a new action; resubmit preserves the previous action exactly.
44
+ Keep editable drafts in the form and use `submitted` for the retained action; a successful replay
45
+ does not overwrite a newer draft. Same-record update/delete calls serialize across hook instances;
46
+ different records and separate creates remain independent. Queued writes retain their original
47
+ revisions. Form unmount does not cancel a dispatched write. Source transitions clear protected reads
48
+ and reject stale queued actions before dispatch. Queries and mutations never automatically retry;
49
+ there is no persistence, reload recovery, or automatic revision rebasing.
50
+
51
+ The old public TanStack option factories and native-result resource hooks are no longer exported.
52
+ Use the deliberate entity hooks above. Existing generic slotted `Resource*` presentation remains
53
+ separate from common entity CRUD.
54
+
55
+ ## Declared entity views
56
+
57
+ Import `defineEntity`, `EntityTable`, `EntityList`, and `EntityForm` from
58
+ `@collective-intelligence/external-apps-client-sdk-react/resources`. Declare
59
+ presentation once alongside the portable contract:
60
+
61
+ ```tsx
62
+ const orders = defineEntity({
63
+ contract: orderContract,
64
+ config: {
65
+ fields: { number: { label: "Order number" } },
66
+ table: {
67
+ columns: ["number"],
68
+ variants: { compact: { columns: ["number"] } }
69
+ },
70
+ list: { title: "number" },
71
+ forms: {
72
+ create: { fields: ["number"] },
73
+ update: { fields: ["number"] }
74
+ }
75
+ }
76
+ })
77
+
78
+ // Inside the SDK provider and the host framework's NuqsAdapter:
79
+ <EntityTable entity={orders} namespace="orders-main" />
80
+ <EntityList entity={orders} namespace="orders-sidebar" />
81
+ <EntityTable entity={orders} viewState="memory" variant="compact" />
82
+ <EntityForm entity={orders} mode="update" record={selectedOrder} />
83
+ ```
84
+
85
+ The declaration contains labels, field/control/renderer keys and layouts, with
86
+ no JSX, credentials or storage configuration. Field names are inferred from
87
+ the contract; configured fields must also exist in its portable schema.
88
+ Views render public `ui-react` presentation and share authorized query data
89
+ when their normalized queries match.
90
+
91
+ URL-backed tables/lists require a stable, distinct namespace. Install the host
92
+ adapter once; the proven TanStack Start integration uses
93
+ `NuqsAdapter` from `nuqs/adapters/tanstack-router` inside the router root.
94
+ Nuqs 2.10.1 owns URL serialization and replace-history updates. Defaults are
95
+ omitted; unrelated keys, other namespaces and the hash are preserved. Invalid
96
+ owned values fall back to defaults. Search/filter/sort changes reset the page.
97
+ For custom controls, use `useEntityViewState(namespace, { contract, pageSize })`;
98
+ it exposes `state`, the normalized `query`, and setters for page, page size,
99
+ search, filters and sorting. `useMemoryEntityViewState` and
100
+ `viewState="memory"` need no URL adapter. View namespaces never enter data keys.
101
+
102
+ Forms infer scalar, enum, date, nullable and required settings from portable
103
+ schemas. Readonly schema fields cannot become writable through configuration
104
+ and are omitted from submissions. Richer values need a named control in the
105
+ form's `controls` registry; missing controls produce explicit feedback.
106
+ Custom controls receive the field metadata and return JSON wire values.
107
+ Named display renderers are supplied separately through `renderers`.
108
+
109
+ Pending writes disable overlapping saves. Conflict and unknown-outcome states
110
+ keep the local draft; **Resubmit** sends the captured original action, including
111
+ its key, values and revision. Successful resubmission also keeps newer edits.
112
+ An update form retains the revision its draft began editing when refreshed
113
+ record props arrive. Remount it intentionally (for example with a React `key`)
114
+ after the user chooses to discard the draft and edit a newer server revision.
115
+ Drafts and operation keys never enter the URL.
116
+
117
+ ## Workspace development
118
+
119
+ See the repository's [Effect demo](../../../demo/external-app-effect/README.md)
120
+ for the same declared Lead views configured against local Gateway, proxied CI,
121
+ and direct CI bindings.
122
+
123
+ Each package export declares an opt-in `ci-source` condition for workspace development. The local
124
+ TypeScript configuration enables it for the framework-neutral Client SDK, so either package's changes
125
+ are consumed without an intermediate rebuild. Release builds disable custom conditions; installed npm
126
+ consumers resolve generated `dist` JavaScript and declarations. Shared runtime chunks keep provider
127
+ contexts identical across the root and `/resources` entrypoints.
128
+
129
+ Run `bunx vitest run src`, `bun run type-check`, `bun run lint`, and `bun run test:pack`. The pack check
130
+ executes a real root-provider/resources-hook consumer without caller TanStack setup and removes its
131
+ temporary installation on success or failure.
132
+
133
+ ## Enum value compatibility
134
+
135
+ Repository-owned enum values use lower `snake_case`. Update gateway manifests,
136
+ request payloads and saved resource filters together with their consumers. For
137
+ example, resource filters use `starts_with` and `is_null`, lifecycle operation
138
+ values use `soft_delete` and `hard_delete`, and gateway principal kinds use
139
+ `detached_user` and `service_principal`. Public method and capability property
140
+ names such as `softDelete` remain unchanged. External HTTP, OAuth, JSON Schema
141
+ and provider values retain their required spelling at their adapter boundaries.