Skip to content

@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/core

Creating 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
OptionTypeRequiredDescription
accountstringYesAccount route identifier, for example acc_example.
projectstringYesProject identifier.
environmentstringYesdevelopment, staging, or production.
apiUrlstringNoSkyState API base URL. Defaults to https://api.skystate.io.
fetchtypeof globalThis.fetchNoCustom fetch implementation.
storageAuthTokenStorageNoCustom 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
ParameterDescription
keyTop-level public-state key.
fallbackValue 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

MethodSignatureDescription
setAuthTokens(tokens: { idToken: string; refreshToken: string }) => voidAttaches hosted-auth tokens to the client.
clearAuthTokens(error?: AuthError) => voidClears 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

MethodSignatureDescription
get(key: string, fallback?: unknown) => unknownReads the current user-state value for a key.
set(key: string, value: unknown) => voidWrites a user-state value.
subscribe(key: string, listener: () => void) => () => voidSubscribes 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');
ParameterDescription
keyTop-level user-state key.
fallbackValue 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');
ParameterDescription
keyTop-level user-state key.
valueJSON-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();
ParameterDescription
keyTop-level user-state key.
listenerCallback 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 memberTypeDescription
get()() => TDrafted value if present, otherwise committed value or fallback.
committed()() => TCommitted value, ignoring local draft edits.
hasDraft()() => booleanWhether a local draft value exists.
getDraft()`() => Tundefined`
set(value)`(value: T((displayValue: T) => T)) => void`
push()() => voidSaves the current draft value.
discard()() => voidDrops the local draft value.
subscribe(listener)(listener: () => void) => () => voidSubscribes to draft or committed-value changes.
dispose()() => voidReleases 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

ExportDescription
createSkyStateClient(options)Create a framework-agnostic client.
SkyStateClient, SkyStateClientOptionsClient interface and construction options.
ClientSnapshot, ClientLifecycleClient lifecycle and combined snapshot types.
PublicStateSnapshot, AuthSnapshot, UserStateSnapshotPublic, auth, and user-state snapshot types.
PublicStateAccessor, UserStateAccessor, UserStateDraftHandleAccessor and draft-handle types.
AuthErrorAuth error type.
SkyStateError, SkyStateErrorCodeTyped error with code, message, optional HTTP status, and the error-code union.
decodeJwtPayload()Decode JWT payloads for inspection.
createMemoryStorage() / createLocalStorage() / AuthTokenStorageAuth 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_SNAPSHOTThe initial unauthenticated client snapshot.
assertNever()Exhaustiveness helper for TypeScript discriminated unions.
RefreshOutcomeToken-refresh outcome type used by advanced integrations.