Packages for building browser apps on the ConfigHub API:
@confighub/react-auth— a React provider and hooks that run the browser-direct auth flow (OIDC PKCE + RFC 8693 token exchange) and hand back a client pre-wired with the token.@confighub/api— a typed, framework-agnostic client (openapi-fetch). No Redux, no React, no required provider. Reach for this by default.@confighub/rtk-query— an RTK Query client (generated hooks, cache tags) for apps already on Redux Toolkit.
@confighub/api and @confighub/rtk-query are parallel, independent clients: same
version-pegged spec, same getToken auth seam, different generator, no shared code.
Pick one. The only contract between the auth package and a client is getToken(): the
client accepts a token source; the auth layer provides one (via useConfigHub() for the
plain client, or getAccessToken for RTK Query).
examples/space-browser is a full app built on both packages — it logs you in and
browses your spaces and units. Nothing is published to npm; the example uses the
packages straight from this repo, so cloning and running is all it takes.
Prerequisites: Node 18+, and cub logged in to a
ConfigHub instance with browser auth enabled (hub.confighub.com works).
-
Clone and install:
git clone git@github.com:confighub/js-sdk.git cd js-sdk npm install -
Register your app to get a
client_id(it registers in whatever org yourcubis currently logged into; aclient_idis public, not a secret):cub oauthclient create my-tryout --redirect-uri http://localhost:5173/ -
Configure the example — copy the template and paste in your
client_id:cp examples/space-browser/.env.example examples/space-browser/.env # edit examples/space-browser/.env: set VITE_OAUTH_CLIENT_ID # (VITE_CONFIGHUB_BASE_URL defaults to https://hub.confighub.com) -
Run it:
npm run example # vite dev server on http://localhost:5173Open http://localhost:5173, click Log in, and — if you belong to more than one org — pick the same org your
cubis logged into (the app can only sign you in for the org that owns itsclient_id).
When you're done, remove the throwaway client: cub oauthclient delete my-tryout.
import { ConfigHubAuthProvider, useAuth, useConfigHub } from '@confighub/react-auth';
function Root() {
return (
<ConfigHubAuthProvider baseUrl="https://hub.confighub.com" clientId={CLIENT_ID}>
<App />
</ConfigHubAuthProvider>
);
}
function App() {
const { status, user, login } = useAuth();
const api = useConfigHub();
if (status !== 'authenticated') return <button onClick={login}>Log in</button>;
// `api` is a typed client (see below); calls are fully typed against the pinned spec:
// await api.GET('/me')
// await api.GET('/space/{space_id}/unit', { params: { path: { space_id } } })
return <div>signed in as org {user!.organizationId}</div>;
}clientId comes from registering the app: cub oauthclient create <name> --redirect-uri <origin>. The issuer and endpoints are discovered at runtime from
{baseUrl}/api/info, so the same build runs against any ConfigHub instance.
import { createConfigHubClient } from '@confighub/api';
const api = createConfigHubClient({
baseUrl: 'https://hub.confighub.com',
getToken: () => myToken,
});
const { data, error } = await api.GET('/space/{space_id}/unit', {
params: { path: { space_id } },
});Unlike the Go SDK (confighub/sdk, a mirror of the monorepo), this repo is the home
of its own code. The one thing it pulls from ConfigHub is the OpenAPI spec, pinned to
a released server version in .spec-version.
npm run sync-spec # fetch the pinned spec, regenerate BOTH clients
One pegged spec drives both clients through their own generators: openapi-typescript
for @confighub/api, @rtk-query/codegen-openapi for @confighub/rtk-query. The
fetched root openapi.json and both generated files (packages/api/src/schema.d.ts,
packages/rtk-query/src/confighubApi.gen.ts) are committed, so a spec change is a
reviewable diff. Bumping the targeted server version is: edit .spec-version, run
npm run sync-spec, commit the regenerated files, and open a PR.
npm install
npm run sync-spec # generate the client types (needed once before build)
npm run build # tsup -> dual ESM/CJS + d.ts for all packages
npm run typecheck
npm run example # run examples/space-browser (plain client)
npm run example:rtk # run examples/space-browser-rtk (RTK Query)
Publishing is tag-driven (matching the main codebase). The git tag is the source of truth for the version; CI sets each package to that version and publishes all three to npm with provenance.
git tag v0.2.0
git push origin v0.2.0 # triggers .github/workflows/release.yml
Use a v*.*.* semver tag. The package.json versions in the repo are placeholders that
CI overwrites at publish time, so they don't need bumping by hand.
| Concern | Standard |
|---|---|
Bearer token on /api |
OAuth 2.0 Bearer (RFC 6750) |
| Browser login | OIDC Core + PKCE (RFC 7636) |
| Mint a ConfigHub token from an IdP token | OAuth 2.0 Token Exchange (RFC 8693) |
| Issuer / endpoint discovery | OIDC Discovery / AS Metadata (RFC 8414) |
| Per-app registration (Cloud) | Dynamic Client Registration (RFC 7591) |