@osdk/react 0.9.0-beta.1 → 0.9.0-beta.10
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/AGENTS.md +253 -0
- package/CHANGELOG.md +118 -0
- package/build/browser/intellisense.test.js +1 -1
- package/build/browser/intellisense.test.js.map +1 -1
- package/build/browser/new/makeExternalStore.js +2 -2
- package/build/browser/new/makeExternalStore.js.map +1 -1
- package/build/browser/new/platform-apis/admin/useCurrentFoundryUser.js +44 -0
- package/build/browser/new/platform-apis/admin/useCurrentFoundryUser.js.map +1 -0
- package/build/browser/new/platform-apis/admin/useFoundryUser.js +50 -0
- package/build/browser/new/platform-apis/admin/useFoundryUser.js.map +1 -0
- package/build/browser/new/platform-apis/admin/useFoundryUsersList.js +54 -0
- package/build/browser/new/platform-apis/admin/useFoundryUsersList.js.map +1 -0
- package/build/browser/new/useLinks.js +15 -8
- package/build/browser/new/useLinks.js.map +1 -1
- package/build/browser/new/useObjectSet.js +20 -4
- package/build/browser/new/useObjectSet.js.map +1 -1
- package/build/browser/new/useOsdkAction.js.map +1 -1
- package/build/browser/new/useOsdkAggregation.js +1 -1
- package/build/browser/new/useOsdkAggregation.js.map +1 -1
- package/build/browser/new/useOsdkFunction.js +101 -0
- package/build/browser/new/useOsdkFunction.js.map +1 -0
- package/build/browser/new/useOsdkObject.js +1 -1
- package/build/browser/new/useOsdkObject.js.map +1 -1
- package/build/browser/new/useOsdkObjects.js +4 -3
- package/build/browser/new/useOsdkObjects.js.map +1 -1
- package/build/browser/public/experimental.js +4 -0
- package/build/browser/public/experimental.js.map +1 -1
- package/build/browser/utils/usePlatformQuery.js +74 -0
- package/build/browser/utils/usePlatformQuery.js.map +1 -0
- package/build/cjs/{chunk-OVBG5VXE.cjs → chunk-V32JHU3O.cjs} +8 -3
- package/build/cjs/chunk-V32JHU3O.cjs.map +1 -0
- package/build/cjs/index.cjs +4 -4
- package/build/cjs/public/experimental.cjs +413 -67
- package/build/cjs/public/experimental.cjs.map +1 -1
- package/build/cjs/public/experimental.d.cts +279 -32
- package/build/esm/intellisense.test.js +1 -1
- package/build/esm/intellisense.test.js.map +1 -1
- package/build/esm/new/makeExternalStore.js +2 -2
- package/build/esm/new/makeExternalStore.js.map +1 -1
- package/build/esm/new/platform-apis/admin/useCurrentFoundryUser.js +44 -0
- package/build/esm/new/platform-apis/admin/useCurrentFoundryUser.js.map +1 -0
- package/build/esm/new/platform-apis/admin/useFoundryUser.js +50 -0
- package/build/esm/new/platform-apis/admin/useFoundryUser.js.map +1 -0
- package/build/esm/new/platform-apis/admin/useFoundryUsersList.js +54 -0
- package/build/esm/new/platform-apis/admin/useFoundryUsersList.js.map +1 -0
- package/build/esm/new/useLinks.js +15 -8
- package/build/esm/new/useLinks.js.map +1 -1
- package/build/esm/new/useObjectSet.js +20 -4
- package/build/esm/new/useObjectSet.js.map +1 -1
- package/build/esm/new/useOsdkAction.js.map +1 -1
- package/build/esm/new/useOsdkAggregation.js +1 -1
- package/build/esm/new/useOsdkAggregation.js.map +1 -1
- package/build/esm/new/useOsdkFunction.js +101 -0
- package/build/esm/new/useOsdkFunction.js.map +1 -0
- package/build/esm/new/useOsdkObject.js +1 -1
- package/build/esm/new/useOsdkObject.js.map +1 -1
- package/build/esm/new/useOsdkObjects.js +4 -3
- package/build/esm/new/useOsdkObjects.js.map +1 -1
- package/build/esm/public/experimental.js +4 -0
- package/build/esm/public/experimental.js.map +1 -1
- package/build/esm/utils/usePlatformQuery.js +74 -0
- package/build/esm/utils/usePlatformQuery.js.map +1 -0
- package/build/types/new/makeExternalStore.d.ts +1 -1
- package/build/types/new/makeExternalStore.d.ts.map +1 -1
- package/build/types/new/platform-apis/admin/useCurrentFoundryUser.d.ts +28 -0
- package/build/types/new/platform-apis/admin/useCurrentFoundryUser.d.ts.map +1 -0
- package/build/types/new/platform-apis/admin/useFoundryUser.d.ts +36 -0
- package/build/types/new/platform-apis/admin/useFoundryUser.d.ts.map +1 -0
- package/build/types/new/platform-apis/admin/useFoundryUsersList.d.ts +52 -0
- package/build/types/new/platform-apis/admin/useFoundryUsersList.d.ts.map +1 -0
- package/build/types/new/useLinks.d.ts +5 -5
- package/build/types/new/useLinks.d.ts.map +1 -1
- package/build/types/new/useObjectSet.d.ts +4 -0
- package/build/types/new/useObjectSet.d.ts.map +1 -1
- package/build/types/new/useOsdkAction.d.ts +3 -3
- package/build/types/new/useOsdkAction.d.ts.map +1 -1
- package/build/types/new/useOsdkAggregation.d.ts +10 -12
- package/build/types/new/useOsdkAggregation.d.ts.map +1 -1
- package/build/types/new/useOsdkFunction.d.ts +112 -0
- package/build/types/new/useOsdkFunction.d.ts.map +1 -0
- package/build/types/new/useOsdkObjects.d.ts +31 -13
- package/build/types/new/useOsdkObjects.d.ts.map +1 -1
- package/build/types/public/experimental.d.ts +5 -0
- package/build/types/public/experimental.d.ts.map +1 -1
- package/build/types/utils/usePlatformQuery.d.ts +25 -0
- package/build/types/utils/usePlatformQuery.d.ts.map +1 -0
- package/docs/actions.md +414 -0
- package/docs/advanced-queries.md +663 -0
- package/docs/cache-management.md +213 -0
- package/docs/getting-started.md +382 -0
- package/docs/platform-apis.md +203 -0
- package/docs/querying-data.md +648 -0
- package/package.json +8 -4
- package/build/browser/new/types.js +0 -2
- package/build/browser/new/types.js.map +0 -1
- package/build/cjs/chunk-OVBG5VXE.cjs.map +0 -1
- package/build/esm/new/types.js +0 -2
- package/build/esm/new/types.js.map +0 -1
- package/build/types/new/types.d.ts +0 -5
- package/build/types/new/types.d.ts.map +0 -1
|
@@ -0,0 +1,213 @@
|
|
|
1
|
+
---
|
|
2
|
+
sidebar_position: 5
|
|
3
|
+
---
|
|
4
|
+
|
|
5
|
+
# Cache Management
|
|
6
|
+
|
|
7
|
+
This guide covers how the OSDK React cache system works and how to manually control it.
|
|
8
|
+
|
|
9
|
+
## How the Cache Works
|
|
10
|
+
|
|
11
|
+
The `OsdkProvider2` creates an `ObservableClient` that maintains a normalized cache of all queries and their results.
|
|
12
|
+
|
|
13
|
+
### What Gets Cached
|
|
14
|
+
|
|
15
|
+
| Data Type | Cache Key Based On |
|
|
16
|
+
|-----------|-------------------|
|
|
17
|
+
| **Objects** | Object type + primary key |
|
|
18
|
+
| **Lists** | Object type + where clause + orderBy |
|
|
19
|
+
| **Links** | Source object + link name + filters |
|
|
20
|
+
| **Aggregations** | Object type + where clause + aggregate definition |
|
|
21
|
+
|
|
22
|
+
### Cache Sharing
|
|
23
|
+
|
|
24
|
+
- **Same query = same cache entry**: Two components calling `useOsdkObjects(Todo, { where: { isComplete: false } })` share the same cached result
|
|
25
|
+
- **Different filters = different entries**: `{ isComplete: false }` and `{ isComplete: true }` create separate cache entries
|
|
26
|
+
- **Derived properties create variants**: Adding `withProperties` creates a separate cache entry
|
|
27
|
+
|
|
28
|
+
### Object Normalization
|
|
29
|
+
|
|
30
|
+
Objects are stored once and shared across all queries that reference them:
|
|
31
|
+
|
|
32
|
+
```
|
|
33
|
+
useOsdkObjects(Todo) ─┐
|
|
34
|
+
├─► Todo:1 (single cached instance)
|
|
35
|
+
useOsdkObject(Todo, "1") ─┘
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
When `Todo:1` is updated, all queries referencing it see the change immediately.
|
|
39
|
+
|
|
40
|
+
## Automatic Cache Updates
|
|
41
|
+
|
|
42
|
+
### After Actions
|
|
43
|
+
|
|
44
|
+
When an action completes, the server response specifies which objects were affected:
|
|
45
|
+
|
|
46
|
+
- **Added objects**: Fetched and added to cache, relevant lists re-evaluated
|
|
47
|
+
- **Modified objects**: Re-fetched, all queries containing them updated
|
|
48
|
+
- **Deleted objects**: Removed from cache and all lists
|
|
49
|
+
|
|
50
|
+
### Optimistic Updates
|
|
51
|
+
|
|
52
|
+
With `$optimisticUpdate`:
|
|
53
|
+
|
|
54
|
+
1. Optimistic layer created with your changes
|
|
55
|
+
2. UI shows optimistic state (`isOptimistic: true`)
|
|
56
|
+
3. On success: Server data replaces optimistic layer
|
|
57
|
+
4. On failure: Optimistic layer removed, original state restored
|
|
58
|
+
|
|
59
|
+
### Real-time Updates
|
|
60
|
+
|
|
61
|
+
With `streamUpdates: true`, the cache receives WebSocket updates and applies them automatically.
|
|
62
|
+
|
|
63
|
+
## When Manual Invalidation is Needed
|
|
64
|
+
|
|
65
|
+
Automatic updates don't cover:
|
|
66
|
+
|
|
67
|
+
- Data changed by an external system or external cache
|
|
68
|
+
- Data modified outside OSDK (direct API calls, background jobs)
|
|
69
|
+
|
|
70
|
+
## Manual Cache Invalidation
|
|
71
|
+
|
|
72
|
+
The `ObservableClient` provides methods to manually invalidate cached data.
|
|
73
|
+
|
|
74
|
+
### Setup
|
|
75
|
+
|
|
76
|
+
To use invalidation methods, create an `ObservableClient` and pass it to `OsdkProvider2`:
|
|
77
|
+
|
|
78
|
+
```tsx
|
|
79
|
+
// client.ts
|
|
80
|
+
import { createClient } from "@osdk/client";
|
|
81
|
+
import {
|
|
82
|
+
createObservableClient,
|
|
83
|
+
type ObservableClient,
|
|
84
|
+
} from "@osdk/client/unstable-do-not-use";
|
|
85
|
+
|
|
86
|
+
const client = createClient(
|
|
87
|
+
"https://your-stack.palantirfoundry.com",
|
|
88
|
+
"your-ontology-rid",
|
|
89
|
+
authProvider,
|
|
90
|
+
);
|
|
91
|
+
|
|
92
|
+
// Create and export the observable client for invalidation
|
|
93
|
+
export const observableClient = createObservableClient(client);
|
|
94
|
+
export { client };
|
|
95
|
+
```
|
|
96
|
+
|
|
97
|
+
```tsx
|
|
98
|
+
// main.tsx
|
|
99
|
+
import { OsdkProvider2 } from "@osdk/react/experimental";
|
|
100
|
+
import { client, observableClient } from "./client";
|
|
101
|
+
|
|
102
|
+
ReactDOM.createRoot(document.getElementById("root")!).render(
|
|
103
|
+
<OsdkProvider2 client={client} observableClient={observableClient}>
|
|
104
|
+
<App />
|
|
105
|
+
</OsdkProvider2>,
|
|
106
|
+
);
|
|
107
|
+
```
|
|
108
|
+
|
|
109
|
+
### Invalidation Methods
|
|
110
|
+
|
|
111
|
+
#### Object Invalidation
|
|
112
|
+
|
|
113
|
+
| Method | Effect | Use Case |
|
|
114
|
+
|--------|--------|----------|
|
|
115
|
+
| `invalidateObjects([obj1, obj2])` | Re-fetches specific objects | You know exactly which objects are stale |
|
|
116
|
+
| `invalidateObjectType(Todo)` | Re-fetches all objects and lists of that type | External bulk update |
|
|
117
|
+
| `invalidateAll()` | Re-fetches everything | Last resort |
|
|
118
|
+
|
|
119
|
+
#### Function Invalidation
|
|
120
|
+
|
|
121
|
+
| Method | Effect | Use Case |
|
|
122
|
+
|--------|--------|----------|
|
|
123
|
+
| `invalidateFunction(queryDef, params)` | Re-fetches a specific function query | You know which function call is stale |
|
|
124
|
+
| `invalidateFunction(queryDef)` | Re-fetches ALL queries for that function | External change affecting all calls |
|
|
125
|
+
| `invalidateFunctionsByObject(apiName, pk)` | Re-fetches functions depending on a specific object | Object changed outside action flow |
|
|
126
|
+
|
|
127
|
+
### Usage
|
|
128
|
+
|
|
129
|
+
```tsx
|
|
130
|
+
import { Todo, getEmployeeMetrics } from "@my/osdk";
|
|
131
|
+
import { observableClient } from "./client";
|
|
132
|
+
|
|
133
|
+
// Invalidate specific objects
|
|
134
|
+
await observableClient.invalidateObjects([todo1, todo2]);
|
|
135
|
+
|
|
136
|
+
// Invalidate all data for a type
|
|
137
|
+
await observableClient.invalidateObjectType(Todo);
|
|
138
|
+
|
|
139
|
+
// Invalidate a specific function query
|
|
140
|
+
await observableClient.invalidateFunction(getEmployeeMetrics, { departmentId: "sales" });
|
|
141
|
+
|
|
142
|
+
// Invalidate ALL queries for a function
|
|
143
|
+
await observableClient.invalidateFunction(getEmployeeMetrics);
|
|
144
|
+
|
|
145
|
+
// Invalidate functions that depend on a specific object instance
|
|
146
|
+
// (functions called with dependsOnObjects containing this object)
|
|
147
|
+
await observableClient.invalidateFunctionsByObject("Employee", "emp-123");
|
|
148
|
+
|
|
149
|
+
// Invalidate everything (use sparingly)
|
|
150
|
+
await observableClient.invalidateAll();
|
|
151
|
+
```
|
|
152
|
+
|
|
153
|
+
### Type Isolation
|
|
154
|
+
|
|
155
|
+
`invalidateObjectType(Todo)` only affects Todo-related data:
|
|
156
|
+
|
|
157
|
+
- Re-fetches all Todo objects
|
|
158
|
+
- Re-fetches all Todo lists
|
|
159
|
+
- Re-fetches links where Todo is the source type
|
|
160
|
+
- Does NOT affect other object types, even if linked to Todos
|
|
161
|
+
|
|
162
|
+
### Function Invalidation Details
|
|
163
|
+
|
|
164
|
+
`invalidateFunctionsByObject(apiName, primaryKey)` invalidates function queries that were registered with `dependsOnObjects` containing the specified object:
|
|
165
|
+
|
|
166
|
+
```tsx
|
|
167
|
+
// If useOsdkFunction was called with:
|
|
168
|
+
const { data } = useOsdkFunction(getEmployeeReport, {
|
|
169
|
+
params: { employeeId: employee.$primaryKey },
|
|
170
|
+
dependsOnObjects: [employee],
|
|
171
|
+
});
|
|
172
|
+
|
|
173
|
+
// You can invalidate it by calling:
|
|
174
|
+
await observableClient.invalidateFunctionsByObject("Employee", employee.$primaryKey);
|
|
175
|
+
```
|
|
176
|
+
|
|
177
|
+
This is useful when you know a specific object has changed outside of the normal action flow.
|
|
178
|
+
|
|
179
|
+
## Cache with Optimistic Updates
|
|
180
|
+
|
|
181
|
+
```tsx
|
|
182
|
+
import { $Actions, Todo } from "@my/osdk";
|
|
183
|
+
import { useOsdkAction, useOsdkObject } from "@osdk/react/experimental";
|
|
184
|
+
|
|
185
|
+
function TodoView({ todo }: { todo: Todo.OsdkInstance }) {
|
|
186
|
+
const { isOptimistic } = useOsdkObject(todo);
|
|
187
|
+
const { applyAction } = useOsdkAction($Actions.completeTodo);
|
|
188
|
+
|
|
189
|
+
const handleComplete = () => {
|
|
190
|
+
applyAction({
|
|
191
|
+
todo,
|
|
192
|
+
isComplete: true,
|
|
193
|
+
$optimisticUpdate: (ou) => {
|
|
194
|
+
ou.updateObject(todo.$clone({ isComplete: true }));
|
|
195
|
+
},
|
|
196
|
+
});
|
|
197
|
+
};
|
|
198
|
+
|
|
199
|
+
return (
|
|
200
|
+
<div>
|
|
201
|
+
{todo.title}
|
|
202
|
+
{isOptimistic && " (Saving...)"}
|
|
203
|
+
<button onClick={handleComplete}>Complete</button>
|
|
204
|
+
</div>
|
|
205
|
+
);
|
|
206
|
+
}
|
|
207
|
+
```
|
|
208
|
+
|
|
209
|
+
## Best Practices
|
|
210
|
+
|
|
211
|
+
1. **Be specific**: Use `invalidateObjects` when you know what data specifically changed
|
|
212
|
+
2. **Use type-level invalidation**: `invalidateObjectType` for external bulk changes
|
|
213
|
+
3. **Avoid multiple sources of truth**: Coordinating side effects between multiple systems is tricky; we recommend solely using the OSDK React cache when possible for data loading
|
|
@@ -0,0 +1,382 @@
|
|
|
1
|
+
---
|
|
2
|
+
sidebar_position: 1
|
|
3
|
+
---
|
|
4
|
+
|
|
5
|
+
# Getting Started
|
|
6
|
+
|
|
7
|
+
This guide covers installation, setup, and your first OSDK React application.
|
|
8
|
+
|
|
9
|
+
:::info Beta Release
|
|
10
|
+
`@osdk/react` is currently in beta. While the package is suitable for production use, you may encounter minor bugs as we continue development. We welcome bug reports and feedback.
|
|
11
|
+
:::
|
|
12
|
+
|
|
13
|
+
## Installation
|
|
14
|
+
|
|
15
|
+
### 1. Install Beta Packages
|
|
16
|
+
|
|
17
|
+
Using `latest` doesn't always install actual latest versions for beta packages. Specify them explicitly.
|
|
18
|
+
|
|
19
|
+
:::warning Version Compatibility
|
|
20
|
+
All `@osdk/*` packages must use **compatible versions**. Mismatched versions (e.g., mixing an old `@osdk/client` with a newer `@osdk/react`) will cause TypeScript errors.
|
|
21
|
+
:::
|
|
22
|
+
|
|
23
|
+
```json
|
|
24
|
+
{
|
|
25
|
+
"dependencies": {
|
|
26
|
+
"@osdk/api": "^2.7.0-beta.8",
|
|
27
|
+
"@osdk/client": "^2.7.0-beta.8",
|
|
28
|
+
"@osdk/react": "^0.9.0-beta.5"
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
Or install via command line:
|
|
34
|
+
|
|
35
|
+
```bash
|
|
36
|
+
npm install @osdk/api @osdk/client @osdk/react
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
Check for newer versions on npm:
|
|
40
|
+
|
|
41
|
+
- [@osdk/react versions](https://www.npmjs.com/package/@osdk/react?activeTab=versions)
|
|
42
|
+
- [@osdk/client versions](https://www.npmjs.com/package/@osdk/client?activeTab=versions)
|
|
43
|
+
- [@osdk/api versions](https://www.npmjs.com/package/@osdk/api?activeTab=versions)
|
|
44
|
+
|
|
45
|
+
### 2. Generate Your SDK with Beta Features
|
|
46
|
+
|
|
47
|
+
If you haven't generated an SDK yet:
|
|
48
|
+
|
|
49
|
+
1. Open Developer Console for your Foundry
|
|
50
|
+
2. Click "SDK versions" tab (tag icon in left navbar)
|
|
51
|
+
3. Click "Settings" → enable beta features for TypeScript
|
|
52
|
+
4. Click "Generate new version" → check "npm" checkbox → select latest `-beta` generator
|
|
53
|
+
5. Add the generated SDK to your package.json:
|
|
54
|
+
|
|
55
|
+
```json
|
|
56
|
+
{
|
|
57
|
+
"dependencies": {
|
|
58
|
+
"@your-app/sdk": "^0.4.0"
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
## Provider Setup
|
|
64
|
+
|
|
65
|
+
### Stable vs Experimental
|
|
66
|
+
|
|
67
|
+
`@osdk/react` has two entry points:
|
|
68
|
+
|
|
69
|
+
| | `@osdk/react` | `@osdk/react/experimental` |
|
|
70
|
+
| ----------------- | --------------------------- | --------------------------------------------- |
|
|
71
|
+
| **Use when** | You only need client access | You want reactive data hooks (most apps) |
|
|
72
|
+
| **Features** | Client provider, metadata | Queries, actions, caching, optimistic updates |
|
|
73
|
+
| **API stability** | Stable | APIs may change between releases |
|
|
74
|
+
|
|
75
|
+
**We recommend starting with experimental.** The "experimental" label indicates the API surface may evolve, not that the features are unstable or buggy. Most applications benefit from the reactive hooks, automatic caching, and optimistic update support.
|
|
76
|
+
|
|
77
|
+
### Stable Features (`@osdk/react`)
|
|
78
|
+
|
|
79
|
+
For basic client access only:
|
|
80
|
+
|
|
81
|
+
```tsx
|
|
82
|
+
import { OsdkProvider } from "@osdk/react";
|
|
83
|
+
import client from "./client";
|
|
84
|
+
|
|
85
|
+
ReactDOM.createRoot(document.getElementById("root")!).render(
|
|
86
|
+
<OsdkProvider client={client}>
|
|
87
|
+
<App />
|
|
88
|
+
</OsdkProvider>,
|
|
89
|
+
);
|
|
90
|
+
```
|
|
91
|
+
|
|
92
|
+
Stable exports (use with `OsdkProvider`):
|
|
93
|
+
|
|
94
|
+
- `OsdkProvider` - Provider component for basic client access
|
|
95
|
+
- `useOsdkClient` - Access the OSDK client directly
|
|
96
|
+
- `useOsdkMetadata` - Fetch type metadata
|
|
97
|
+
|
|
98
|
+
:::note
|
|
99
|
+
`useOsdkClient` and `useOsdkMetadata` are available from both `@osdk/react` (stable) and `@osdk/react/experimental`. When using experimental features with `OsdkProvider2`, import from `@osdk/react/experimental` for consistency.
|
|
100
|
+
:::
|
|
101
|
+
|
|
102
|
+
### Experimental Features (`@osdk/react/experimental`)
|
|
103
|
+
|
|
104
|
+
For reactive data management, cache, and optimistic updates.
|
|
105
|
+
|
|
106
|
+
:::tip About Experimental Hooks
|
|
107
|
+
The hooks in `@osdk/react/experimental` are production-ready and recommended for new projects. They are labeled "experimental" because they represent a newer architecture that is under active development. Once stabilized, these hooks will be promoted to the main `@osdk/react` package.
|
|
108
|
+
:::
|
|
109
|
+
|
|
110
|
+
```tsx
|
|
111
|
+
import { OsdkProvider2 } from "@osdk/react/experimental";
|
|
112
|
+
import client from "./client";
|
|
113
|
+
|
|
114
|
+
ReactDOM.createRoot(document.getElementById("root")!).render(
|
|
115
|
+
<OsdkProvider2 client={client}>
|
|
116
|
+
<App />
|
|
117
|
+
</OsdkProvider2>,
|
|
118
|
+
);
|
|
119
|
+
```
|
|
120
|
+
|
|
121
|
+
**All experimental hooks require `OsdkProvider2` at your app root.**
|
|
122
|
+
|
|
123
|
+
Experimental exports:
|
|
124
|
+
|
|
125
|
+
- `OsdkProvider2` - Provider for experimental features
|
|
126
|
+
- `useOsdkObjects` - Query collections of objects
|
|
127
|
+
- `useOsdkObject` - Query single objects
|
|
128
|
+
- `useOsdkAction` - Execute and validate actions
|
|
129
|
+
- `useLinks` - Navigate object relationships
|
|
130
|
+
- `useObjectSet` - Advanced queries with set operations
|
|
131
|
+
- `useOsdkAggregation` - Server-side aggregations
|
|
132
|
+
- `useOsdkFunction` - Execute and observe OSDK functions
|
|
133
|
+
- `useDebouncedCallback` - Debounce callbacks
|
|
134
|
+
- `useOsdkClient` - Access the OSDK client
|
|
135
|
+
- `useOsdkMetadata` - Fetch type metadata (also available from stable)
|
|
136
|
+
|
|
137
|
+
## Quick Start Checklist
|
|
138
|
+
|
|
139
|
+
Before using experimental hooks:
|
|
140
|
+
|
|
141
|
+
- [ ] App wrapped in `<OsdkProvider2 client={client}>`
|
|
142
|
+
- [ ] OsdkProvider2 at app root (not nested inside components)
|
|
143
|
+
- [ ] Passing configured OSDK client to OsdkProvider2
|
|
144
|
+
- [ ] All components using experimental hooks inside the provider
|
|
145
|
+
|
|
146
|
+
## First Query
|
|
147
|
+
|
|
148
|
+
:::note About `@my/osdk`
|
|
149
|
+
Throughout this documentation, `@my/osdk` refers to **your generated SDK package**. This is created when you generate an SDK in Foundry Developer Console (step 2 above). Replace `@my/osdk` with your actual package name (e.g., `@your-app/sdk`).
|
|
150
|
+
:::
|
|
151
|
+
|
|
152
|
+
```tsx
|
|
153
|
+
import { Todo } from "@my/osdk";
|
|
154
|
+
import { useOsdkObjects } from "@osdk/react/experimental";
|
|
155
|
+
|
|
156
|
+
function TodoList() {
|
|
157
|
+
const { data, isLoading, error } = useOsdkObjects(Todo, {
|
|
158
|
+
where: { isComplete: false },
|
|
159
|
+
orderBy: { createdAt: "desc" },
|
|
160
|
+
});
|
|
161
|
+
|
|
162
|
+
if (!data && isLoading) {
|
|
163
|
+
return <div>Loading...</div>;
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
if (error) {
|
|
167
|
+
return <div>Error: {JSON.stringify(error)}</div>;
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
return (
|
|
171
|
+
<div>
|
|
172
|
+
{data?.map(todo => <div key={todo.$primaryKey}>{todo.title}</div>)}
|
|
173
|
+
</div>
|
|
174
|
+
);
|
|
175
|
+
}
|
|
176
|
+
```
|
|
177
|
+
|
|
178
|
+
See [Querying Data](/react/querying-data) for filtering, pagination, real-time updates, and more.
|
|
179
|
+
|
|
180
|
+
## First Action
|
|
181
|
+
|
|
182
|
+
```tsx
|
|
183
|
+
import { $Actions, Todo } from "@my/osdk";
|
|
184
|
+
import { useOsdkAction } from "@osdk/react/experimental";
|
|
185
|
+
|
|
186
|
+
function CompleteTodoButton({ todo }: { todo: Todo.OsdkInstance }) {
|
|
187
|
+
const { applyAction, isPending, error } = useOsdkAction(
|
|
188
|
+
$Actions.completeTodo,
|
|
189
|
+
);
|
|
190
|
+
|
|
191
|
+
const handleClick = () => {
|
|
192
|
+
applyAction({ todo, isComplete: true });
|
|
193
|
+
};
|
|
194
|
+
|
|
195
|
+
return (
|
|
196
|
+
<div>
|
|
197
|
+
<button onClick={handleClick} disabled={isPending}>
|
|
198
|
+
{isPending ? "Saving..." : "Complete"}
|
|
199
|
+
</button>
|
|
200
|
+
{error && <div>Error: {JSON.stringify(error)}</div>}
|
|
201
|
+
</div>
|
|
202
|
+
);
|
|
203
|
+
}
|
|
204
|
+
```
|
|
205
|
+
|
|
206
|
+
See [Actions](/react/actions) for validation, batch actions, and optimistic updates.
|
|
207
|
+
|
|
208
|
+
## Troubleshooting
|
|
209
|
+
|
|
210
|
+
### "Property 'store' is missing" with OsdkProvider2
|
|
211
|
+
|
|
212
|
+
This error occurs when your `@osdk/client` version is incompatible with `@osdk/react`. The versions must match.
|
|
213
|
+
|
|
214
|
+
**Fix:** Ensure all `@osdk/*` packages use compatible beta versions:
|
|
215
|
+
|
|
216
|
+
1. Go to **Developer Console** → **SDK versions** → **Settings**
|
|
217
|
+
2. Enable **beta features** for TypeScript
|
|
218
|
+
3. Generate a new SDK version with the latest beta generator
|
|
219
|
+
4. Check the **Installation instructions** for the compatible `@osdk/client` version
|
|
220
|
+
5. Update your package.json to use matching versions:
|
|
221
|
+
|
|
222
|
+
```json
|
|
223
|
+
{
|
|
224
|
+
"dependencies": {
|
|
225
|
+
"@osdk/api": "^2.7.0-beta.8",
|
|
226
|
+
"@osdk/client": "^2.7.0-beta.8",
|
|
227
|
+
"@osdk/react": "^0.9.0-beta.5"
|
|
228
|
+
}
|
|
229
|
+
}
|
|
230
|
+
```
|
|
231
|
+
|
|
232
|
+
### "Cannot read property 'observableClient' of undefined"
|
|
233
|
+
|
|
234
|
+
The component is outside `<OsdkProvider2>`. Move OsdkProvider2 higher in your component tree.
|
|
235
|
+
|
|
236
|
+
**Wrong:**
|
|
237
|
+
|
|
238
|
+
```tsx
|
|
239
|
+
function App() {
|
|
240
|
+
return <TodoList />; // No OsdkProvider2!
|
|
241
|
+
}
|
|
242
|
+
```
|
|
243
|
+
|
|
244
|
+
**Correct:**
|
|
245
|
+
|
|
246
|
+
```tsx
|
|
247
|
+
ReactDOM.createRoot(document.getElementById("root")!).render(
|
|
248
|
+
<OsdkProvider2 client={client}>
|
|
249
|
+
<TodoList />
|
|
250
|
+
</OsdkProvider2>,
|
|
251
|
+
);
|
|
252
|
+
```
|
|
253
|
+
|
|
254
|
+
### Only some components work with hooks
|
|
255
|
+
|
|
256
|
+
OsdkProvider2 is not at the root.
|
|
257
|
+
|
|
258
|
+
**Wrong:**
|
|
259
|
+
|
|
260
|
+
```tsx
|
|
261
|
+
function App() {
|
|
262
|
+
return (
|
|
263
|
+
<>
|
|
264
|
+
<Header /> {/* Can't use hooks */}
|
|
265
|
+
<OsdkProvider2 client={client}>
|
|
266
|
+
<Content /> {/* Only this can use hooks */}
|
|
267
|
+
</OsdkProvider2>
|
|
268
|
+
</>
|
|
269
|
+
);
|
|
270
|
+
}
|
|
271
|
+
```
|
|
272
|
+
|
|
273
|
+
**Correct:**
|
|
274
|
+
|
|
275
|
+
```tsx
|
|
276
|
+
ReactDOM.createRoot(document.getElementById("root")!).render(
|
|
277
|
+
<OsdkProvider2 client={client}>
|
|
278
|
+
<App /> {/* All components can use hooks */}
|
|
279
|
+
</OsdkProvider2>,
|
|
280
|
+
);
|
|
281
|
+
```
|
|
282
|
+
|
|
283
|
+
### Hooks return no data
|
|
284
|
+
|
|
285
|
+
Ensure you're passing the same client instance, not creating a new one:
|
|
286
|
+
|
|
287
|
+
**Wrong:**
|
|
288
|
+
|
|
289
|
+
```tsx
|
|
290
|
+
<OsdkProvider2 client={createNewClient()}> {/* New instance each render */}
|
|
291
|
+
```
|
|
292
|
+
|
|
293
|
+
**Correct:**
|
|
294
|
+
|
|
295
|
+
```tsx
|
|
296
|
+
import client from "./client"; // Created once
|
|
297
|
+
<OsdkProvider2 client={client}>
|
|
298
|
+
```
|
|
299
|
+
|
|
300
|
+
### "Hooks cannot be conditionally called"
|
|
301
|
+
|
|
302
|
+
Use the `enabled` option instead of conditional hook calls:
|
|
303
|
+
|
|
304
|
+
**Wrong:**
|
|
305
|
+
|
|
306
|
+
```tsx
|
|
307
|
+
if (shouldLoad) {
|
|
308
|
+
const { data } = useOsdkObjects(Todo); // Conditional hook!
|
|
309
|
+
}
|
|
310
|
+
```
|
|
311
|
+
|
|
312
|
+
**Correct:**
|
|
313
|
+
|
|
314
|
+
```tsx
|
|
315
|
+
const { data } = useOsdkObjects(Todo, {
|
|
316
|
+
enabled: shouldLoad,
|
|
317
|
+
});
|
|
318
|
+
```
|
|
319
|
+
|
|
320
|
+
## NPM Peer Dependency Issues
|
|
321
|
+
|
|
322
|
+
If NPM has trouble resolving peer dependencies with beta packages, add to package.json:
|
|
323
|
+
|
|
324
|
+
```json
|
|
325
|
+
{
|
|
326
|
+
"overrides": {
|
|
327
|
+
"@osdk/client": "$@osdk/client",
|
|
328
|
+
"@osdk/react": "$@osdk/react"
|
|
329
|
+
}
|
|
330
|
+
}
|
|
331
|
+
```
|
|
332
|
+
|
|
333
|
+
## FAQ
|
|
334
|
+
|
|
335
|
+
### When should I use `@osdk/react` vs React Query?
|
|
336
|
+
|
|
337
|
+
**Use `@osdk/react`** when your application primarily works with OSDK data:
|
|
338
|
+
|
|
339
|
+
- Querying Foundry objects and ontology data
|
|
340
|
+
- Executing actions on Foundry objects
|
|
341
|
+
- Taking advantage of automatic cache management for OSDK objects
|
|
342
|
+
- Real-time updates via WebSocket subscriptions
|
|
343
|
+
|
|
344
|
+
**Use React Query** when you need to make requests to third-party APIs or non-OSDK endpoints:
|
|
345
|
+
|
|
346
|
+
- External REST APIs
|
|
347
|
+
- GraphQL services not backed by Foundry
|
|
348
|
+
- Custom backend services
|
|
349
|
+
|
|
350
|
+
**You can use both together.** `@osdk/react` hooks work independently from React Query. For applications that mix OSDK data with external services, use `@osdk/react` for Foundry operations and React Query for external APIs.
|
|
351
|
+
|
|
352
|
+
```tsx
|
|
353
|
+
import { Todo } from "@my/osdk";
|
|
354
|
+
import { useOsdkObjects } from "@osdk/react/experimental";
|
|
355
|
+
import { useQuery } from "@tanstack/react-query";
|
|
356
|
+
|
|
357
|
+
function Dashboard() {
|
|
358
|
+
// Use @osdk/react for Foundry data
|
|
359
|
+
const { data: todos } = useOsdkObjects(Todo);
|
|
360
|
+
|
|
361
|
+
// Use React Query for external APIs
|
|
362
|
+
const { data: weatherData } = useQuery({
|
|
363
|
+
queryKey: ["weather"],
|
|
364
|
+
queryFn: () => fetch("https://api.weather.com/current").then(r => r.json()),
|
|
365
|
+
});
|
|
366
|
+
|
|
367
|
+
return (
|
|
368
|
+
<div>
|
|
369
|
+
<TodoList todos={todos} />
|
|
370
|
+
<WeatherWidget data={weatherData} />
|
|
371
|
+
</div>
|
|
372
|
+
);
|
|
373
|
+
}
|
|
374
|
+
```
|
|
375
|
+
|
|
376
|
+
## Next Steps
|
|
377
|
+
|
|
378
|
+
- [Querying Data](/react/querying-data) - useOsdkObjects, useOsdkObject, useLinks, pagination, real-time updates
|
|
379
|
+
- [Actions](/react/actions) - useOsdkAction, validation, optimistic updates, debouncing
|
|
380
|
+
- [Advanced Queries](/react/advanced-queries) - useObjectSet, derived properties, aggregations
|
|
381
|
+
- [Cache Management](/react/cache-management) - Cache behavior and manual invalidation
|
|
382
|
+
- [Platform APIs](/react/platform-apis) - useCurrentFoundryUser, useFoundryUser, useFoundryUsersList
|