@barelyacompany/locko-react-sdk
v1.0.0
Published
React SDK for Locko — secrets and config management
Downloads
24
Maintainers
Readme
@barelyacompany/locko-react-sdk
React and Node.js SDK for Locko — secrets and config management.
Works in both React (client-side hooks) and Next.js / Node.js (async server-side functions). The same API key works in both environments.
Installation
npm install @barelyacompany/locko-react-sdkReact 17+ is a peer dependency. It is not required for server-side usage.
Import paths
The package exposes two subpath entry points to keep environments separated:
| Import path | Use in | Exports |
|-------------|--------|---------|
| @barelyacompany/locko-react-sdk/client | React components, Next.js "use client" files | LockoProvider, useConfig, useSecrets, useVariables, useLocko |
| @barelyacompany/locko-react-sdk/server | Next.js server components, API routes, Node.js | getConfig, getSecrets, getVariables, applyToEnv, createClient, LockoApiError |
The root import (@barelyacompany/locko-react-sdk) re-exports everything and is suitable for plain React apps or when you need both in the same module.
API keys
| Prefix | Scope | Extra requirement |
|--------|-------|-------------------|
| lk_ | Single service | None |
| lko_ | Org-wide | Must pass serviceSlug |
React (client-side)
Wrap your app with LockoProvider once, then read config anywhere via hooks.
import { LockoProvider } from '@barelyacompany/locko-react-sdk/client';
export default function App() {
return (
<LockoProvider apiKey={process.env.REACT_APP_LOCKO_KEY!}>
<MyApp />
</LockoProvider>
);
}For org keys, pass serviceSlug:
<LockoProvider apiKey="lko_..." serviceSlug="my-service">
<MyApp />
</LockoProvider>useConfig
Returns all entries (variables + secrets) as a flat key-value map. Returns {} while loading or on error.
import { useConfig } from '@barelyacompany/locko-react-sdk/client';
function Dashboard() {
const config = useConfig();
return <p>{config.FEATURE_FLAG}</p>;
}useVariables
Returns only non-secret entries. Returns {} while loading or on error.
import { useVariables } from '@barelyacompany/locko-react-sdk/client';
function Settings() {
const variables = useVariables();
return <p>API URL: {variables.API_BASE_URL}</p>;
}useSecrets
Returns only secret entries. Returns {} while loading or on error.
import { useSecrets } from '@barelyacompany/locko-react-sdk/client';
function PaymentForm() {
const secrets = useSecrets();
// use secrets.STRIPE_PUBLISHABLE_KEY, etc.
}useLocko
Low-level hook — exposes raw entries, metadata, loading state, and errors.
import { useLocko } from '@barelyacompany/locko-react-sdk/client';
function StatusBadge() {
const { loading, error, entries, metadata } = useLocko();
if (loading) return <span>Loading config…</span>;
if (error) return <span>Config error: {error.message}</span>;
return <span>{entries?.length} entries loaded from {metadata?.environment}</span>;
}Next.js / Node.js (server-side)
Standalone async functions — no provider or React required. Call them in server components, getServerSideProps, API routes, middleware, or any Node.js process.
getConfig
Fetches all entries (variables + secrets).
import { getConfig } from '@barelyacompany/locko-react-sdk/server';
// Next.js server component
export default async function Page() {
const { config, metadata } = await getConfig(process.env.LOCKO_API_KEY!);
return <p>Env: {metadata.environment} — {Object.keys(config).length} entries</p>;
}// getServerSideProps
export async function getServerSideProps() {
const { config } = await getConfig(process.env.LOCKO_API_KEY!);
return { props: { apiUrl: config.API_BASE_URL } };
}getSecrets
Fetches only secret entries.
import { getSecrets } from '@barelyacompany/locko-react-sdk/server';
const { secrets, metadata } = await getSecrets(process.env.LOCKO_API_KEY!);
console.log(secrets.DATABASE_URL);getVariables
Fetches only non-secret entries.
import { getVariables } from '@barelyacompany/locko-react-sdk/server';
const { variables, metadata } = await getVariables(process.env.LOCKO_API_KEY!);
console.log(variables.FEATURE_FLAG_NEW_UI);Options
All three server functions accept the same options as LockoProvider:
const { config } = await getConfig('lko_...', {
serviceSlug: 'my-service', // required for lko_ keys
baseUrl: 'https://...', // override API base URL
timeoutMs: 5000, // default 3000
debug: true, // logs request details to console
});applyToEnv
Writes config entries into an env-like target. Defaults to process.env on Node.js.
import { createClient, applyToEnv } from '@barelyacompany/locko-react-sdk/server';
const client = createClient(process.env.LOCKO_API_KEY!);
const { entries } = await client.fetchWithTimeout();
applyToEnv(entries); // overwrites existing keys (default)
applyToEnv(entries, { overwrite: false }); // only fills keys not already setFor browser environments where process.env is not writable at runtime, pass a custom target:
import { createClient, applyToEnv } from '@barelyacompany/locko-react-sdk/server';
const { entries } = await createClient(process.env.LOCKO_API_KEY!).fetchWithTimeout();
const runtimeEnv: Record<string, string | undefined> = {};
applyToEnv(entries, { target: runtimeEnv });Error handling
Both hooks and server functions surface LockoApiError for HTTP errors.
import { getConfig, LockoApiError } from '@barelyacompany/locko-react-sdk/server';
try {
const { config } = await getConfig(process.env.LOCKO_API_KEY!);
} catch (err) {
if (err instanceof LockoApiError) {
console.error(`Locko API error ${err.statusCode}:`, err.message);
}
}In React, read the error field from useLocko() or wrap LockoProvider in an error boundary.
Debug logging
Pass debug: true to any function or provider to log request and response details to the console. Alternatively, set the LOCKO_DEBUG environment variable to "1" or "true" without changing code:
LOCKO_DEBUG=1 node server.jsErrors are always logged regardless of the debug flag.
Testing
npm test # unit, integration, and export surface tests
npm run test:e2e # E2E tests against the live API (requires env vars)
npm run test:watch # watch mode
npm run test:coverage # with coverage reportE2E tests require the following env vars (set in .env or shell):
LOCKO_API_KEY=lk_...
LOCKO_BASE_URL=https://api-locko.barelyacompany.com
LOCKO_SERVICE_SLUG=my-service # only for lko_ keysE2E tests auto-skip when the env vars are not set, so npm test is always safe to run without them.
API reference
Provider
| Export | Description |
|--------|-------------|
| LockoProvider | React context provider — fetches config on mount |
| LockoContext | Raw React context — use with useContext if needed |
LockoProvider props:
| Prop | Type | Required | Default |
|------|------|----------|---------|
| apiKey | string | Yes | — |
| serviceSlug | string | For lko_ keys | — |
| baseUrl | string | No | https://api-locko.barelyacompany.com |
| timeoutMs | number | No | 3000 |
| debug | boolean | No | false |
React hooks
All hooks must be used inside a LockoProvider. They return {} (or the empty equivalent) while loading and on error.
| Hook | Returns | Notes |
|------|---------|-------|
| useLocko() | { entries, metadata, loading, error } | Raw context value |
| useConfig() | Record<string, string> | All entries |
| useSecrets() | Record<string, string> | is_secret === true only |
| useVariables() | Record<string, string> | is_secret === false only |
Server functions
| Function | Returns | Notes |
|----------|---------|-------|
| getConfig(apiKey, opts?) | Promise<{ config, metadata }> | All entries |
| getSecrets(apiKey, opts?) | Promise<{ secrets, metadata }> | Secrets only |
| getVariables(apiKey, opts?) | Promise<{ variables, metadata }> | Variables only |
Utilities
| Export | Description |
|--------|-------------|
| applyToEnv(entries, opts?) | Write entries into process.env or a custom target |
| createClient(apiKey, opts?) | Create a raw LockoClient for manual fetching |
| LockoApiError | Error class — has .statusCode: number |
| VERSION | Current SDK version string |
