@eredzik/foundry-react-query
v1.0.0
Published
tRPC-like TanStack Query wrapper for Foundry OSDK client in React apps
Downloads
122
Maintainers
Readme
@eredzik/foundry-react-query
A tRPC-style wrapper around TanStack Query for the Foundry OSDK client. Use your generated application SDK (e.g. @frontend-app-application/sdk) to get typed onto.actions.*.useMutation(), onto.queries.*.useQuery(), and custom hooks with full access to the client and object types.
Install
pnpm add @eredzik/foundry-react-query @osdk/client @tanstack/react-queryPeer dependencies: @osdk/client, @tanstack/react-query, react.
Setup
- Create your OSDK client (same instance you use with your generated SDK).
- Wrap your app in
FoundryQueryProvider. - Build the ontology once from your SDK (
$Actions,$Objects,$Queries) and useontoin components.
import { createClient } from "@osdk/client";
import { createPublicOauthClient } from "@osdk/oauth";
import { createFoundryOntology, FoundryQueryProvider } from "@eredzik/foundry-react-query";
import * as sdk from "@frontend-app-application/sdk";
const auth = createPublicOauthClient(clientId, foundryUrl, redirectUrl, { scopes });
const client = createClient(foundryUrl, ontologyRid, auth);
const onto = createFoundryOntology(sdk);
function App() {
return (
<FoundryQueryProvider client={client}>
<YourApp />
</FoundryQueryProvider>
);
}Your SDK must expose $Actions, $Objects, and $Queries (e.g. export * as $Actions from './ontology/actions.js').
Usage
Create onto once (e.g. next to your client) with createFoundryOntology(sdk). In components, use the following.
Actions (mutations)
import { onto } from "./onto";
function DeleteButton() {
const deleteTest = onto.actions.deleteTest.useMutation();
return (
<button
onClick={() =>
deleteTest.mutate({
Test: { $primaryKey: 1, $apiName: "Test" },
})
}
disabled={deleteTest.isPending}
>
{deleteTest.isPending ? "Deleting…" : "Delete"}
</button>
);
}Object sets (queries)
Object types from $Objects are on onto.queries. Pass optional fetch-page options as the first argument:
import { onto } from "./onto";
function TestList() {
const { data, isLoading, error } = onto.queries.Test.useQuery({ $pageSize: 20 });
const items = data?.data ?? [];
if (isLoading) return <div>Loading…</div>;
if (error) return <div>Error: {error.message}</div>;
return (
<ul>
{items.map((obj) => (
<li key={obj.$primaryKey}>{String(obj.primaryKey_)}</li>
))}
</ul>
);
}Ontology queries (queries)
If your SDK defines ontology queries in $Queries, they appear on onto.queries with the same name:
import { onto } from "./onto";
function MyQueryView() {
const { data } = onto.queries.myQuery.useQuery({ param: "value" });
// ...
}Custom hooks (onto.custom)
For logic that needs the raw client and all SDK exports (objects, actions, queries), use the custom hooks. The callback receives a typed client and your objects, actions, and queries.
Custom query
import { onto } from "./onto";
function CustomList() {
const { data } = onto.custom.useCustomQuery(
["customTests", 20],
async ({ client, objects }) => {
const page = await client(objects.Test).fetchPage({ $pageSize: 20 });
return page.data;
}
);
// ...
}Custom mutation
import { onto } from "./onto";
function CreateButton() {
const create = onto.custom.useCustomMutation(
({ client, actions }) => client(actions.createTest).applyAction({})
);
return (
<button onClick={() => create.mutate(undefined)} disabled={create.isPending}>
{create.isPending ? "Creating…" : "Create"}
</button>
);
}You can pass TanStack Query options as the last argument to both useCustomQuery and useCustomMutation (e.g. staleTime, onSuccess).
Imperative client
For one-off calls without hooks:
import { useFoundryClient } from "@eredzik/foundry-react-query";
function SomeComponent() {
const client = useFoundryClient();
// client($Actions.deleteTest).applyAction(...)
}API reference
| API | Description |
|-----|-------------|
| createFoundryOntology(sdk) | Builds onto from sdk.$Actions, sdk.$Objects, sdk.$Queries. Call once. |
| FoundryQueryProvider | Wraps the tree; provides the OSDK client and optional QueryClient. |
| useFoundryClient() | Returns the OSDK Client from context. |
| onto.actions.<name>.useMutation(options?) | Typed mutation for that action. |
| onto.queries.<objectType>.useQuery(fetchPageOptions?, queryOptions?) | Query for object set pages ($Objects). |
| onto.queries.<queryName>.useQuery(params?, queryOptions?) | Query for ontology functions ($Queries). |
| onto.custom.useCustomQuery(key, queryFn, options?) | Custom query with (ctx) => Promise<TData>; ctx has client, objects, actions, queries. |
| onto.custom.useCustomMutation(mutationFn, options?) | Custom mutation with (ctx, variables) => Promise<TData>. |
Low-level hooks (used by onto internally): useAction, useObjectSet, useOntologyQuery.
