@skystate/core
@skystate/core is the framework-agnostic SkyState client. It loads public state, stores SkyState auth tokens through a pluggable storage adapter, and reads or writes user state after login.
Basic Example
ts
import { createSkyStateClient } from '@skystate/core';
const client = createSkyStateClient({
account: 'acc_example',
project: 'my-app',
environment: 'production',
});
await client.init();
const banner = client.publicState.get('banner', { enabled: false });
client.setAuthTokens({ idToken, refreshToken });
const theme = client.userState.get('theme', 'dark');
client.userState.set('theme', 'light');Installation
bash
npm install @skystate/coreCreating A Client
ts
import { createSkyStateClient } from '@skystate/core';
const client = createSkyStateClient({
apiUrl: 'https://api.skystate.io',
account: 'acc_example',
project: 'my-app',
environment: 'production',
});
await client.init();account, project, and environment are required. apiUrl defaults to https://api.skystate.io.
createSkyStateClient(options)
ts
function createSkyStateClient(options: SkyStateClientOptions): SkyStateClient| Option | Type | Required | Description |
|---|---|---|---|
account | string | Yes | Account route identifier, for example acc_example. |
project | string | Yes | Project identifier. |
environment | string | Yes | development, staging, or production. |
apiUrl | string | No | SkyState API base URL. Defaults to https://api.skystate.io. |
fetch | typeof globalThis.fetch | No | Custom fetch implementation. |
storage | AuthTokenStorage | No | Custom token storage adapter. |
Public State
Public state is read during init() and is available without end-user auth. Use it for application config, feature flags, public settings, and client-visible catalog or inventory values.
ts
const banner = client.publicState.get('banner', { enabled: false });Keys are top-level state keys. They are not nested paths.
client.publicState.get(key, fallback?)
ts
get(key: string, fallback?: unknown): unknown| Parameter | Description |
|---|---|
key | Top-level public-state key. |
fallback | Value returned when public state is not ready, when the key is absent, or when the stored value is null. |
Returns the current value for key, or fallback when no value is available.
Auth
The core client does not open browser windows. Pass tokens from your hosted auth flow into the client:
ts
client.setAuthTokens({
idToken,
refreshToken,
});clearAuthTokens() clears the local session only. logout() signs the user out through SkyState and resets local user state.
Auth methods
| Method | Signature | Description |
|---|---|---|
setAuthTokens | (tokens: { idToken: string; refreshToken: string }) => void | Attaches hosted-auth tokens to the client. |
clearAuthTokens | (error?: AuthError) => void | Clears local auth state. |
logout | () => Promise<void> | Signs out through SkyState and clears local auth state. |
User State
User state requires an authenticated end-user bearer scoped to the same account, project, and environment.
ts
const theme = client.userState.get('theme', 'dark');
client.userState.set('theme', 'light');
const unsubscribe = client.userState.subscribe('theme', () => {
console.log(client.userState.get('theme'));
});Writes update local subscribers immediately and are persisted by the SDK. Temporary network, sign-in renewal, concurrent update, validation, and permission issues are reported through the user-state status surface.
Keys are top-level state keys such as theme, profile, or preferences. Keys must be non-empty and cannot contain / or ~.
API
| Method | Signature | Description |
|---|---|---|
get | (key: string, fallback?: unknown) => unknown | Reads the current user-state value for a key. |
set | (key: string, value: unknown) => void | Writes a user-state value. |
subscribe | (key: string, listener: () => void) => () => void | Subscribes to changes for a key. Returns an unsubscribe function. |
draft | <T>(key: string, fallback?: T) => UserStateDraftHandle<T> | Creates a draft handle for edit-then-save UI. |
client.userState.get(key, fallback?)
ts
const theme = client.userState.get('theme', 'dark');| Parameter | Description |
|---|---|
key | Top-level user-state key. |
fallback | Value returned when user state is not ready, when the key is absent, or when the committed value is null. |
Returns the current value for key, or fallback when no value is available.
client.userState.set(key, value)
ts
client.userState.set('theme', 'light');| Parameter | Description |
|---|---|
key | Top-level user-state key. |
value | JSON-serializable value to save for the signed-in user. |
Returns void. The local value updates immediately; save errors are reported through user-state status and client subscribers.
client.userState.subscribe(key, listener)
ts
const unsubscribe = client.userState.subscribe('theme', () => {
console.log(client.userState.get('theme', 'dark'));
});
unsubscribe();| Parameter | Description |
|---|---|
key | Top-level user-state key. |
listener | Callback invoked when the key's visible value changes. |
Returns a function that unsubscribes the listener.
client.userState.draft(key, fallback?)
Creates a local draft handle for staged edits:
ts
const profile = client.userState.draft('profile', { displayName: '' });
profile.set((current) => ({ ...current, displayName: 'Ada' }));
profile.push();Use profile.push() to save the drafted value, or profile.discard() to drop local form edits.
| Draft member | Type | Description |
|---|---|---|
get() | () => T | Drafted value if present, otherwise committed value or fallback. |
committed() | () => T | Committed value, ignoring local draft edits. |
hasDraft() | () => boolean | Whether a local draft value exists. |
getDraft() | `() => T | undefined` |
set(value) | `(value: T | ((displayValue: T) => T)) => void` |
push() | () => void | Saves the current draft value. |
discard() | () => void | Drops the local draft value. |
subscribe(listener) | (listener: () => void) => () => void | Subscribes to draft or committed-value changes. |
dispose() | () => void | Releases handle-local subscriptions. |
Snapshot And Lifecycle
Use client.getSnapshot() and client.subscribe() when building an integration layer:
ts
const unsubscribe = client.subscribe(() => {
const snapshot = client.getSnapshot();
console.log(snapshot.publicState.status, snapshot.auth.status, snapshot.userState.status);
});The snapshot contains lifecycle, publicState, auth, and userState subtrees.
Value-Only Metadata Contract
SDK v1 intentionally returns application values and subsystem status only. Use the console, CLI, or REST API when you need inspection, audit, or history metadata.
Exports
| Export | Description |
|---|---|
createSkyStateClient(options) | Create a framework-agnostic client. |
SkyStateClient, SkyStateClientOptions | Client interface and construction options. |
ClientSnapshot, ClientLifecycle | Client lifecycle and combined snapshot types. |
PublicStateSnapshot, AuthSnapshot, UserStateSnapshot | Public, auth, and user-state snapshot types. |
PublicStateAccessor, UserStateAccessor, UserStateDraftHandle | Accessor and draft-handle types. |
AuthError | Auth error type. |
SkyStateError, SkyStateErrorCode | Typed error with code, message, optional HTTP status, and the error-code union. |
decodeJwtPayload() | Decode JWT payloads for inspection. |
createMemoryStorage() / createLocalStorage() / AuthTokenStorage | Auth token storage adapters and interface. |
buildStorageKey() | Build the SDK auth storage key for an account/project/environment. |
toJsonPointer() / resolvePointer() | Lower-level JSON Pointer helpers. Normal state accessors take top-level keys. |
INITIAL_SNAPSHOT | The initial unauthenticated client snapshot. |
assertNever() | Exhaustiveness helper for TypeScript discriminated unions. |
RefreshOutcome | Token-refresh outcome type used by advanced integrations. |