---
title: "@vonvon-kit/solid"
description: "基于 @vonvon-kit/core 的 SolidJS context provider、基于 signal 的认证原语和无样式组件。"
locale: "zh-Hans"
---

> Documentation Index
> Fetch the relevant documentation index at: https://vonvon.id/zh-hans/sdks/llms.txt
> Use this file to discover all available pages before exploring further.

# @vonvon-kit/solid

## 状态

Registry 状态:UNPUBLISHED。此 SDK 只能从仓库源码 checkout 安装；不要使用外部 package registry。

包状态为 **当前包**。SolidJS context provider、基于 signal 的原语和无样式组件已实现。在真实生产基础设施上的 IdP 往返验证仍待人工核实。

## Provider 配置

使用 `VonvonProvider` 包裹你的应用。它会创建 `VonvonClient`，在挂载时调用 `client.load()` 获取当前会话，并通过 `onCleanup` 进行清理。

```tsx
import { VonvonProvider } from '@vonvon-kit/solid'

export function App() {
  return (
<VonvonProvider
  mode="oidc"
  issuer="https://vonvon.id"
  clientId="client_abc123"
  redirectUri="https://app.example.com/auth/callback"
>
  <Routes />
</VonvonProvider>
  )
}
```

## 认证原语

每个原语返回响应式 `Accessor<T>`（getter 函数）。在 JSX 或 `createEffect` 中调用以追踪变更。

```tsx
import { createAuth, createUser, createOrganization, createSession } from '@vonvon-kit/solid'
import { Show } from 'solid-js'

function Profile() {
  const auth = createAuth()
  // auth.isLoaded()  -- Accessor<boolean>
  // auth.isSignedIn() -- Accessor<boolean>
  // auth.userId()    -- Accessor<string | null>
  // auth.getToken()  -- () => Promise<Result<string, VonvonError>>
  // auth.signOut()   -- (options?) => Promise<Result<null, VonvonError>>

  return (
<Show when={auth.isLoaded()} fallback={<p>Loading...</p>}>
  <Show when={auth.isSignedIn()} fallback={<p>Not signed in</p>}>
    <p>Signed in as {auth.userId()}</p>
    <button onClick={() => void auth.signOut()}>Sign out</button>
  </Show>
</Show>
  )
}
```

## createOrganization 和 createSession

```tsx
const org = createOrganization()
// org() is CreateOrganizationReturn
if (org().isSignedIn) {
  console.log(org().organization?.name, org().membership?.role)
  const activated = await org().setActive('org_new_id')
  if (!activated.ok) throw new Error(activated.error.message)
}

const session = createSession()
if (session().isSignedIn) {
  const token = await session().getToken()
  if (!token.ok) throw new Error(token.error.message)
  // use token.value for backend requests
}
```

## 无样式组件

```tsx
import { SignInButton, SignOutButton, Protect } from '@vonvon-kit/solid'

// Navigates to /sign-in by default
<SignInButton signInUrl="/auth/sign-in" redirectUrl="/dashboard">
  Log in
</SignInButton>

// Signs out all sessions; pass sessionId to target one
<SignOutButton redirectUrl="/home">Log out</SignOutButton>

// Role and permission gate
<Protect role="admin" fallback={<p>Admins only</p>}>
  <Settings />
</Protect>

<Protect permission="org:member:write" fallback={null}>
  <InviteForm />
</Protect>
```

## 导出的 API

| 导出 | 类型 | 用途 |
| --- | --- | --- |
| `VonvonProvider` | 组件 | 创建 VonvonClient，挂载时调用 load()，通过 onCleanup 清理 |
| `createAuth` | 原语 | isLoaded、isSignedIn、userId、sessionId、session、getToken、signOut（均为 Accessor） |
| `createUser` | 原语 | 封装 isLoaded / isSignedIn / user 判别联合的访问器 |
| `createOrganization` | 原语 | 返回活跃组织的 organization、membership 和 setActive 的访问器 |
| `createSession` | 原语 | 返回活跃会话的 session 和 getToken 的访问器 |
| `SignInButton` | 组件 | 点击时跳转到登录 URL 的无样式按钮 |
| `SignOutButton` | 组件 | 点击时调用 signOut 的无样式按钮 |
| `Protect` | 组件 | 带回退 prop 的角色与权限门控 |

## Token 存储

- Vonvon Worker 在 `HttpOnly` cookie 中保留不透明的刷新凭据。它不是 JWT，SDK 永远不会从 JavaScript 读取它或将其存储在 `localStorage` 中。
- `getToken()` 返回短期 JWT（60 秒），仅由 `@vonvon-kit/core` 中的 `TokenManager` 缓存在内存中。

Source: https://vonvon.id/zh-hans/sdks/solid/index.mdx
