Files
stuffbox-sdk/README.md
T
cyph3rasi bb04d47a29 Release automatic callback setup in SDK 0.2.0
Hop-State: A_06FPARPGMNVEAN3XBVH0QD8
Hop-Proposal: R_06FPARNXMP3DGP5VQGGX4Z8
Hop-Task: T_06FPAR9KH2V5ED7V65JEN00
Hop-Attempt: AT_06FPAR9KH3NZ1CV8RGPJDSG
2026-07-15 03:46:42 -07:00

150 lines
4.6 KiB
Markdown

# `@gnosyslabs/stuffbox-sdk`
The official TypeScript SDK for connecting applications to Stuffbox, a user-owned media library. The package includes a framework-neutral client, shared API types, PKCE helpers, typed errors, and optional React upload helpers.
## Install
```sh
npm install @gnosyslabs/stuffbox-sdk
```
The core entry point has no runtime dependencies. If you use `@gnosyslabs/stuffbox-sdk/react`, install React 18.2 or React 19 in your application.
## Connect a user
Run the connection flow on your server. Access and refresh tokens must not be embedded in browser JavaScript.
```ts
import {
StuffboxClient,
createPkcePair,
generateState,
} from "@gnosyslabs/stuffbox-sdk";
const stuffbox = new StuffboxClient({ baseUrl: "https://stuffbox.xyz" });
const pkce = await createPkcePair();
const state = generateState();
const savedClientId = await loadStuffboxClientId();
const connection = await stuffbox.createConnectionRequest({
...(savedClientId ? { clientId: savedClientId } : {}),
callbackUrl: "https://yourapp.example/api/stuffbox/callback",
codeChallenge: pkce.challenge,
scopes: ["assets:read"],
state,
});
// No dashboard registration is needed. Persist the returned identity and
// pending PKCE state before redirecting the user's browser.
await saveStuffboxClientId(connection.clientId);
await savePendingConnection({
clientId: connection.clientId,
callbackUrl: connection.callbackUrl,
codeVerifier: pkce.verifier,
state,
});
redirect(connection.authorizationUrl);
```
After the exact callback, compare the returned state with the persisted value and exchange the one-time code:
```ts
const pending = await loadPendingConnection();
const tokens = await stuffbox.exchangeAuthorizationCode({
clientId: pending.clientId,
code: callbackCode,
codeVerifier: pending.codeVerifier,
redirectUri: pending.callbackUrl,
});
```
Stuffbox creates or reuses an identity for the exact callback automatically. Pass the returned `clientId` on later connections when available. The client ID is public routing information, not a secret.
## Read a user's media library
```ts
const media = new StuffboxClient({
baseUrl: "https://stuffbox.xyz",
accessToken: () => loadCurrentAccessToken(),
});
let cursor: string | undefined;
do {
const page = await media.listAssets({
limit: 50,
...(cursor ? { cursor } : {}),
});
addToMediaPicker(page.items);
cursor = page.nextCursor;
} while (cursor);
```
Request only the permissions your feature uses: `assets:read`, `assets:write`, and `assets:delete`.
## React uploads
The optional React entry point exports `useStuffboxUpload`, `uploadFile`, and their types:
```tsx
import { useStuffboxUpload, type UploadTransport } from "@gnosyslabs/stuffbox-sdk/react";
const transport: UploadTransport = {
async createUpload(input, options) {
const response = await fetch("/api/stuffbox/uploads", {
method: "POST",
headers: { "content-type": "application/json" },
body: JSON.stringify(input),
signal: options?.signal,
});
if (!response.ok) throw new Error("Could not create upload");
return response.json();
},
async completeUpload(uploadId, input, options) {
const response = await fetch(`/api/stuffbox/uploads/${uploadId}/complete`, {
method: "POST",
headers: { "content-type": "application/json" },
body: JSON.stringify(input ?? {}),
signal: options?.signal,
});
if (!response.ok) throw new Error("Could not complete upload");
return response.json();
},
};
export function UploadButton() {
const { state, upload, abort } = useStuffboxUpload(transport);
return (
<div>
<input
type="file"
onChange={(event) => {
const file = event.currentTarget.files?.[0];
if (file) void upload(file);
}}
/>
{state.status === "uploading" && (
<button type="button" onClick={abort}>
Cancel {Math.round(state.progress.percent)}%
</button>
)}
</div>
);
}
```
The browser should call same-origin endpoints owned by your application. Those endpoints call Stuffbox with the user's access token and return only the short-lived upload session or completed asset. File bytes then travel directly from the browser to object storage.
## Documentation
- [Developer guide](https://stuffbox.xyz/developers)
- [Protocol reference](docs/protocol.md)
- [Integration examples](examples)
- [Source and issues](https://githop.xyz/GnosysLabs/stuffbox-sdk)
## License
MIT © Gnosys Labs. The Stuffbox service implementation is proprietary and is not included in this package or its public source repository.