- 后端
- 认证鉴权
- 前端
【免费下载链接】hanko
Modern authentication, on your terms. Open source alternative to Auth0, Clerk, WorkOS, Stytch.
@teamhanko/hanko-frontend-sdk是 Hanko 官方提供、专为浏览器环境设计的 TypeScript 客户端库,它封装了 Hanko API 的会话管理、用户信息拉取与事件通知能力,并提供基于状态机模型的 FlowAPI,让开发者可以不依赖现成 UI 组件、自由构建自定义登录与个人资料前端。读完本文,你将掌握 SDK 的安装接入、实例选项、会话生命周期事件监听、会话/用户管理方法,以及从零驱动 FlowAPI 完成认证流程(含自动步进、Passkey 自动填充、状态缓存与错误处理)的完整实战方案。
安装
SDK 以 npm 包形式发布,包名为@teamhanko/hanko-frontend-sdk(当前仓库版本为 3.0.0,见 frontend/frontend-sdk/package.json),支持主流的包管理器:
# npm npm install @teamhanko/hanko-frontend-sdk # yarn yarn add @teamhanko/hanko-frontend-sdk # pnpm pnpm install @teamhanko/hanko-frontend-sdk该包仅面向浏览器运行(package.json 中明确注明 "It is meant for use in browsers only"),其产物支持多种模块格式:dist/sdk.cjs(CommonJS)、dist/sdk.modern.js(ESM)以及dist/sdk.umd.js(UMD),分别通过exports、module与unpkg字段对外暴露。
快速接入:模块导入与 CDN 两种方式
作为 ES 模块导入
import { Hanko } from "@teamhanko/hanko-frontend-sdk" const hanko = new Hanko("http://localhost:3000")构造函数第一个参数是 Hanko API 实例的地址(即 backend 服务的 URL)。
通过 CDN 的 script 标签使用
<script src="https://cdn.jsdelivr.net/npm/@teamhanko/hanko-frontend-sdk/dist/sdk.umd.js"></script> <script> const hanko = new hankoFrontendSdk.Hanko("http://localhost:3000") ... </script>UMD 构建会把全部导出挂载到全局命名空间hankoFrontendSdk下,适合无构建工具的场景。SDK 的入口文件 frontend/frontend-sdk/src/index.ts 集中导出了Hanko主类、各子客户端(HttpClient、SessionClient、UserClient)、Relay、WebAuthn 工具函数、DTO 类型(Email、Identity、SessionCheckResponse、Claims)、全部错误类型以及 FlowAPI 相关的类型。
实例选项(Options)
创建Hanko实例时可以传入第二个可选参数来定制行为。以下默认值直接对应 Hanko.ts 构造函数中的实现:
const defaultOptions = { timeout: 13000, // The timeout (in ms) for the HTTP requests. cookieName: "hanko", // The cookie name under which the session token is set. localStorageKey: "hanko", // The prefix / name of the localStorage keys. sessionCheckInterval: 30000, // Interval (in ms) for session validity checks. Must be greater than 3000 (3s). sessionCheckChannelName: "hanko-session-check" // The broadcast channel name for inter-tab communication }; const hanko = new Hanko("http://localhost:3000", defaultOptions);在源码的HankoOptions接口(frontend/frontend-sdk/src/Hanko.ts)中,还定义了 README 之外的可选字段,可供深度定制:
| 选项 | 类型 | 默认值 | 说明 |
|---|---|---|---|
timeout | number | 13000 | HTTP 请求超时时间(毫秒) |
cookieName | string | "hanko" | SDK 写入会话 token 的 cookie 名 |
cookieDomain | string | 当前页面域名 | cookie 生效的域名 |
cookieSameSite | CookieSameSite | "lax" | 跨站请求时 cookie 的发送策略 |
localStorageKey | string | "hanko" | localStorage 键名前缀 |
lang | string | — | 向 API 传递的首选语言(见下文"邮件翻译") |
sessionCheckInterval | number | 30000 | 会话有效性轮询间隔(毫秒),必须大于 3000,否则强制设为 3000 |
sessionCheckChannelName | string | "hanko-session-check" | 跨标签页通信的 BroadcastChannel 名称 |
sessionTokenLocation | "cookie" \| "sessionStorage" | — | 会话 token 的存储位置 |
其中sessionCheckInterval的最小值约束在 Relay.ts 中实现:若传入值小于 3000 会被直接钳制为 3000。而sessionCheckChannelName在sessionTokenLocation为"sessionStorage"时,会以该值为前缀生成随机通道名并持久化到sessionStorage,用于区分不同标签页间的会话同步(见 Relay.ts)。
会话事件(Session Events)
SDK 基于浏览器原生CustomEvent派发自定义事件。Hanko继承自Listener基类(frontend/frontend-sdk/src/lib/events/Listener.ts),所有onXxx方法都返回一个CleanupFunc移除函数,调用它即可注销监听器。事件绑定通用模式如下:
// Controls the optional `once` parameter. When set to `true` the callback function will be called only once. const once = false; const removeEventListener = hanko.onSessionCreated((eventDetail) => { // Your code... }, once);hanko-session-created
在会话创建、且用户完成所有附加步骤(如 passkey 注册或密码恢复)后触发;当用户在其他浏览器窗口登录时,当前窗口也会触发。该事件可用于获取 JWT 的 claims:
hanko.onSessionCreated((sessionDetail) => { // A new JWT has been issued. console.info("Session created", sessionDetail.claims); })从源码看,SessionDetail包含claims(JWT 声明对象)与已废弃的expirationSeconds字段(frontend/frontend-sdk/src/lib/events/CustomEvents.ts)。该事件在success状态的 auto-step 中被派发:SDK 从成功载荷中取出 claims,计算剩余有效期后调用dispatchSessionCreatedEvent(frontend/frontend-sdk/src/lib/flow-api/auto-steps.ts),并同时通过 BroadcastChannel 广播给其他标签页。
hanko-session-expired
会话过期、或用户在另一个窗口登出/删除账号导致会话被移除时触发:
hanko.onSessionExpired(() => { // You can redirect the user to a login page or show the `<hanko-auth>` element, or to prompt the user to log in again. console.info("Session expired"); })hanko-user-logged-out
用户主动登出时触发。同一时刻,其他浏览器窗口会触发hanko-session-expired:
hanko.onUserLoggedOut(() => { // You can redirect the user to a login page or show the `<hanko-auth>` element. console.info("User logged out"); })hanko-user-deleted
用户删除账号时触发。其他浏览器窗口同样会同步触发hanko-session-expired:
hanko.onUserDeleted(() => { // You can redirect the user to a login page or show the `<hanko-auth>` element. console.info("User has been deleted"); })userDeleted事件由account_deleted状态的 auto-step 派发(frontend/frontend-sdk/src/lib/flow-api/auto-steps.ts)。事件名称常量集中在 frontend/frontend-sdk/src/lib/events/CustomEvents.ts 中定义。此外onSessionCreated与onSessionExpired在 Listener.ts 中默认开启了节流(throttle,默认 1 秒),防止多个 SDK 实例同时触发同一事件时回调被重复执行。
会话管理(Session Management)
SDK 提供一组用于管理用户会话与获取用户信息的方法,均由 Hanko.ts 中的Hanko类直接暴露。
获取用户对象(getCurrentUser)
拉取当前用户的完整资料:
- 返回值:一个
User对象,包含:user_id:用户的唯一字符串标识;passkeys:已注册 passkey 数组(WebauthnCredential[],可选);security_keys:已注册安全密钥数组(WebauthnCredential[],可选);mfa_config:MFA 配置对象({ auth_app_set_up, totp_enabled, security_keys_enabled },可选);emails:邮箱对象数组(如{ id: string, address: string, is_verified: boolean, is_primary: boolean, identities?: Identity[] },可选);username:用户名对象(如{ id: string, username: string, created_at: string, updated_at: string },可选);metadata:自定义元数据对象({ public_metadata?, unsafe_metadata? },可选);identities:关联的第三方身份数组(如{ id: string, provider: string, identity_id?: string },可选);created_at/updated_at:ISO 8601 格式的创建与最后更新时间戳;name、given_name、family_name、picture:通过第三方提供商注册时填充的可选资料字段。
- 错误:
UnauthorizedError(会话无效或过期)、TechnicalError(服务端或网络问题)。
try { const user = await hanko.getCurrentUser(); console.log("User profile:", user); // Example output: // { // user_id: "123e4567-e89b-12d3-a456-426614174000", // passkeys: [{ // id: "d6df75e0-8a2b-4c6d-9b6e-1a2b3c4d5e6f", // name: "MacBook Touch ID", // public_key: "...", // attestation_type: "none", // aaguid: "08987058-cadc-4b81-b6e1-30de50dcbe96", // created_at: "2025-01-01T10:00:00Z", // transports: "internal", // backup_eligible: "true", // backup_state: "true" // }], // security_keys: [], // mfa_config: { auth_app_set_up: false, totp_enabled: false, security_keys_enabled: false }, // emails: [{ // id: "f2882293-3c39-451d-a7cb-4cf3375e0c66", // address: "user@example.com", // is_verified: true, // is_primary: true, // identities: [] // }], // username: { // id: "a1b2c3d4-3c39-451d-a7cb-4cf3375e0c66", // username: "johndoe", // created_at: "2025-01-01T10:00:00Z", // updated_at: "2025-01-01T10:00:00Z" // }, // metadata: { public_metadata: {}, unsafe_metadata: {} }, // identities: [], // created_at: "2025-01-01T10:00:00Z", // updated_at: "2025-04-01T12:00:00Z", // name: "John Doe", // given_name: "John", // family_name: "Doe" // } } catch (error) { console.error("Failed to fetch user profile:", error); // Handle UnauthorizedError or TechnicalError }校验会话(validateSession)
检查当前会话的有效性:
- 返回值:一个
SessionCheckResponse对象(结构定义见 frontend/frontend-sdk/src/lib/Dto.ts),包含:is_valid:布尔值,会话是否有效;expiration_time:会话过期时间(ISO 8601,可选);user_id:会话所属用户 ID(可选);idle_expires_at:配置了空闲超时后,会话因无活动而过期的时间(可选);claims:会话声明对象(可选),包括:subject:用户 ID 或会话标识;session_id:唯一会话标识;expiration:会话过期时间戳(ISO 8601);email:邮箱详情对象(如{ address: string, is_primary: boolean, is_verified: boolean },可选);username:用户名(可选);issued_at、audience、issuer:会话 token 的元数据(可选);- 自定义声明(由应用定义)。
- 错误:
TechnicalError(服务端或网络问题)。
try { const sessionStatus = await hanko.validateSession(); console.log("Session status:", sessionStatus); // Example output: // { // is_valid: true, // expiration_time: "2025-04-25T12:00:00Z", // user_id: "123e4567-e89b-12d3-a456-426614174000", // idle_expires_at: "2025-04-25T11:00:00Z", // claims: { // subject: "123e4567-e89b-12d3-a456-426614174000", // session_id: "789abc", // expiration: "2025-04-25T12:00:00Z", // email: { address: "user@example.com", is_primary: true, is_verified: true }, // custom_field: "value" // } // } } catch (error) { console.error("Failed to validate session:", error); // Handle TechnicalError }Claims的完整类型定义在 frontend/frontend-sdk/src/lib/Dto.ts:包含subject、issued_at、expiration、audience、issuer、email、username、session_id等标准声明,并通过泛型参数支持扩展自定义声明。
获取会话 Token(getSessionToken)
从认证 cookie 中读取当前会话 token:
- 返回值:包含 JWT 会话 token 的字符串,或
null(无会话时)。 - 注意:该方法不会抛错;请通过判断
null来处理无会话的情况。
const token = hanko.getSessionToken(); console.log("Session token:", token); // Example output: "eyJhbGciOiJIUzI1NiIs..."其底层实现直接读取认证 cookie(Hanko.ts 调用cookie.getAuthCookie())。
登出用户(logout)
注销当前会话,使会话失效:
- 返回值:登出成功后 resolve(无值)的 Promise,失败则抛错。
- 错误:
TechnicalError(服务端或网络问题)。 - 注意:若当前不存在会话,该方法也会正常 resolve,不会报错。
try { await hanko.logout(); console.log("User logged out"); } catch (error) { console.error("Failed to fetch user logout:", error); // Handle TechnicalError }邮件翻译的语言配置
如果使用Hanko主客户端,可以在实例化时通过lang选项向 Hanko API 传递首选语言,用于决定外出邮件的语言(如登录验证码、安全通知等邮件)。
- 若通过 Hanko 发送邮件,
lang应与 Hanko 支持的语言之一匹配(如"bn"、"de"、"en"、"fr"、"it"、"nl"、"pt-BR"、"zh",与仓库 mail/locales 目录下的本地化文件对应)。 - 若关闭了 Hanko 的邮件投递、改用
email.send事件的 webhook,则lang的值会体现在 webhook 请求所携带 token 的 JWT 载荷中的 "Language" 声明里。
源码层面,语言是通过自定义请求头X-Language传给 Hanko API 的;此外 Hanko.ts 还提供了setLang(lang)方法,可在运行时动态更新底层客户端的语言设置。
自定义会话声明的类型安全
Hanko 后端允许在签发的会话 JWT 中加入自定义声明(会话 JWT 模板的说明见 backend/README.md)。为了让 IDE 具备自动补全并保持自定义声明的类型安全,可以按以下步骤操作:
- 在项目中创建 TypeScript 声明文件(
*.d.ts,或直接修改现有声明文件); - 从 Frontend SDK 导入
Claims类型; - 声明一个扩展
Claims的自定义类型; - 将自定义声明添加到该类型中:
import type { Claims } from "@teamhanko/hanko-frontend-sdk" // 2. // import type { Claims } from "@teamhanko/elements" // alternatively, if you use Hanko Elements, which // re-exports most SDK types type CustomClaims = Claims<{ // 3. custom_claim?: string // 4. }>;- 在访问声明时使用自定义类型,例如事件回调中的会话详情,或会话校验接口返回的 claims:
import type { CustomClaims } from "..."; // path to your type declaration file hanko.onSessionCreated((sessionDetail) => { const claims = sessionDetail.claims as CustomClaims; console.info("My custom claim:", claims.custom_claim); });import type { CustomClaims } from "..."; // path to your type declaration file async function session() { const session = await hanko.validateSession(); const claims = session.claims as CustomClaims; console.info("My custom claim:", claims.custom_claim); };底层机制上,Claims<TCustomClaims>是一个泛型交叉类型:标准声明字段与TCustomClaims(约束为Record<string, unknown>)取交集(frontend/frontend-sdk/src/lib/Dto.ts),因此自定义类型只需声明新增字段即可获得完整推导。
FlowAPI:用自定义前端驱动认证流程
FlowAPI 是 SDK 提供的 TypeScript 接口,用于管理 Hanko 的认证与个人资料流程,支持开发完全自定义的前端。它在 State.ts 中实现,负责状态转换、动作执行、输入校验与事件派发,并内置自动步进(auto-stepping)与 passkey 自动填充(autofill)支持。
核心概念:一个流程(Flow)是一个自包含的状态机,SDK 支持"login"、"registration"、"profile"、"token_exchange"四种顶层流程(frontend/frontend-sdk/src/lib/flow-api/types/flow.ts)。每个流程由若干状态(State)组成,全部 26 个可能的状态名定义在 frontend/frontend-sdk/src/lib/flow-api/types/state.ts,例如login_init、login_password、passcode_confirmation、success、error等;每个状态下的可用动作(Action)及其输入(Input)、**载荷(Payload)**类型,分别定义在 action.ts、input.ts 与types/payload.ts中。
初始化一个新流程
使用Hanko实例上的createState方法开启一个新的认证或个人资料流程。选项可控制事件派发与自动步进行为:
const state = await hanko.createState("login", { dispatchAfterStateChangeEvent: true, excludeAutoSteps: [], loadFromCache: true, cacheKey: "hanko-flow-state", });参数说明
- flowName:流程名,如
"login"、"register"或"profile"(注意源码中的合法取值实际为"login" | "registration" | "profile" | "token_exchange",见 flow.ts)。 - options:
dispatchAfterStateChangeEvent:boolean— 状态变更后是否派发 onAfterStateChange 事件(默认true);excludeAutoSteps:AutoStepExclusion— 要跳过的自动步进状态名数组,或传"all"跳过全部自动步进(默认null);loadFromCache:boolean— 是否尝试从 localStorage 加载缓存的状态(默认true);cacheKey:string— localStorage 缓存的键名(默认"hanko-flow-state")。
其底层逻辑(State.ts)为:若loadFromCache为真且能在cacheKey下解析出有效缓存,则反序列化恢复;否则向服务端POST /{flowName}拉取初始状态。
理解 State 对象
state对象代表流程中的当前步骤,包含以下属性与方法:
name:StateName— 当前状态名(如"login_init"、"login_password"、"success");flowName:FlowName— 流程名(如"login");error:Error | undefined— 动作或请求失败时的错误对象(如输入非法、网络错误);payload:Payloads[StateName] | undefined— API 返回的该状态特有数据;actions:ActionMap<StateName>— 将动作名映射到Action实例的对象;csrfToken:string— 用于安全请求的 CSRF token;status:number— 上一次响应的 HTTP 状态码;invokedAction:ActionInfo | undefined— 本状态上最近一次被运行的动作信息(如有);previousAction:ActionInfo | undefined— 引导进入当前状态的动作信息(如有);isCached:boolean— 该状态是否从 localStorage 加载;cacheKey:string— 用于 localStorage 缓存的键;excludeAutoSteps:AutoStepExclusion— 被排除在自动步进之外的状态名数组。
以上字段与 State.ts 中的类定义一一对应。此外,若当前状态支持自动步进或 passkey 自动填充,还会提供autoStep与passkeyAutofillActivation方法(见下文)。
动作可用性(Action Availability)
后端配置或用户状态/属性可能启用或禁用某些动作。通过访问动作的enabled属性即可判断:
if (state.actions.example_action.enabled) { await state.actions.example_action.run(); } else { console.log("Action is disabled"); }实现上,State.buildActionMap用Proxy包装动作映射:访问一个后端未返回的动作名时,会返回一个enabled = false的禁用动作占位(href 为空、描述为 "Disabled action",见 State.ts 与Action.createDisabled),保证类型安全的同时不会让代码崩溃。
访问动作输入(Accessing Action Inputs)
state.actions中的每个动作都有inputs属性,描述其期望的输入字段。每个输入字段的结构由 input.ts 中的Input<TValue>接口定义:包含name、type(如string、boolean)、value、min_length、max_length、required、hidden、error(上次提交失败的校验错误)以及allowed_values(受限取值列表)。
console.log(state.actions.continue_with_login_identifier.inputs); // Example output: // { // identifier: { name: "identifier", type: "string", required: false }, // email: { name: "email", type: "string", required: false }, // username: { // name: "username", // type: "string", // required: true, // min_length: 3, // max_length: 20 // } // }运行动作(Running an Action)
动作负责将流程推进到新状态。使用动作的run方法,传入输入值与可选配置:
带类型收窄的基础示例
if (state.name === "login_init") { const newState = await state.actions.continue_with_login_identifier.run({ username: "user1", }); // Triggers `onBeforeStateChange` and `onAfterStateChange` events // `newState` is the next state in the flow (e.g., "login_password") }补充说明
- 类型收窄:通过判断
state.name来确保该状态存在对应动作、且输入合法。 - 事件:默认情况下,
run会在执行动作前触发onBeforeStateChange,在新状态加载后触发onAfterStateChange。 - 校验错误:若动作因输入非法失败(格式或长度不符),
newState.error会被设为"invalid_form_data",且具体错误会挂到对应输入字段上(见下方"错误处理")。
动作执行的内部流程(State.ts):先校验动作是否启用(禁用或已调用过会抛错),记录invokedAction,派发onBeforeStateChange,将输入默认值与用户提交值合并为{ input_data, csrf_token }请求体,提交到动作的href,随后清理 localStorage 缓存,最后以新响应初始化下一个状态。
事件处理器(Event Handlers)
SDK 通过 Hanko 实例派发事件以追踪状态变更,对应监听方法在 Listener.ts 中定义。
onBeforeStateChange
在动作执行前触发,适合展示加载态:
hanko.onBeforeStateChange(({ state }) => { console.log("Action loading:", state.invokedAction); });onAfterStateChange
在新状态加载后触发,适合渲染 UI 或处理状态特有逻辑:
hanko.onAfterStateChange(({ state }) => { console.log("Action load finished:", state.invokedAction); switch (state.name) { case "login_init": state.passkeyAutofillActivation(); // Special handler for passkey autofill; requires an <input> field on the page with `autocomplete="username webauthn"` (e.g., <input type="text" name="username" autocomplete="username webauthn" />) so the browser can suggest and autofill passkeys when the user interacts with it. break; case "login_password": // Render password input UI if (state.error) { console.log("Error:", state.error); // e.g., "invalid_form_data" } break; case "error": // Handle network errors or 5xx responses console.error("Flow error:", state.error); break; } });控制 afterStateChange 事件
可以关闭自动派发的onAfterStateChange事件,在自定义逻辑完成后手动派发:
if (state.name === "login_init") { const newState = await state.actions.continue_with_login_identifier.run( { username: "user1" }, { dispatchAfterStateChangeEvent: false }, // Disable automatic dispatch ); // Only `onBeforeStateChange` is triggered here await doSomething(); // Your custom async logic newState.dispatchAfterStateChangeEvent(); // Manually trigger the event }State构造时若dispatchAfterStateChangeEvent为真会在初始化时自动派发;Action.run的config同样支持该选项(State.ts)。dispatchAfterStateChangeEvent()方法本身通过hanko.relay派发hanko-after-state-change事件(State.ts)。
自动步进(Auto-Steps)
自动步进会在特定状态自动推进流程,减少手动干预。
支持自动步进的状态
preflightlogin_passkeyonboarding_verify_passkey_attestationwebauthn_credential_verificationthirdpartysuccessaccount_deleted
这些状态与 auto-steps.ts 和 flow.ts 中的映射一致,各自动步进的行为如下:
preflight:自动上报客户端 WebAuthn 能力(webauthn_available、webauthn_conditional_mediation_available、webauthn_platform_authenticator_available),执行register_client_capabilities动作;login_passkey:自动发起 WebAuthn 断言并提交webauthn_verify_assertion_response,失败时回退并保留服务端错误;onboarding_verify_passkey_attestation/webauthn_credential_verification:自动创建 WebAuthn 凭证并提交 attestation 响应(InvalidStateError会被翻译为"凭证已存在"错误);thirdparty:自动处理 OAuth 回调——从 URL 读取hanko_token并调用exchange_token(配合 PKCE code_verifier),处理error参数与access_denied映射,无 token 时保存状态并跳转到redirect_url;success:派发hanko-session-created事件并清理缓存;account_deleted:派发hanko-user-deleted事件并清理缓存。
禁用自动步进
通过excludeAutoSteps指定要跳过的状态:
const state = await hanko.createState("login", { excludeAutoSteps: ["success"], // Skip auto-step for "success" });createState的初始化流程会循环执行自动步进,直到到达无自动步进的状态或命中被排除的状态(State.ts)。
手动执行自动步进
hanko.onAfterStateChange(({ state }) => { if (state.name === "success") { console.log("Flow completed"); await state.autoStep(); } });错误处理(Error Handling)
输入错误
动作因输入非法失败时:
if (state.name === "login_password" && state.error === "invalid_form_data") { const passwordError = state.actions.password_login.inputs.password.error; console.log("Password error:", passwordError); }具体错误的错误码类型定义在 frontend/frontend-sdk/src/lib/flow-api/types/flowError.ts 中;服务端返回的每个输入字段校验错误会被解析并挂载到对应Input.error上。
网络 / API 错误
网络问题或5xx响应会使流程进入error状态,详情在state.error中:
if (state.name === "error") { console.error("Flow error:", state.error); }当请求失败时,State.fetchState会捕获异常并构造一个名为error、status: 0的错误状态(State.ts),保证流程不会在 HTTP 层直接中断。
缓存流程状态(Caching Flow State)
使用localStorage持久化与恢复流程状态,适合刷新页面后继续未完成的流程。
保存状态
state.saveToLocalStorage(); // Stores under `state.cacheKey` (default: "hanko-flow-state")注意:一旦在保存的状态上调用动作,localStorage 中的该条目会被自动移除(见 State.ts 中run对removeFromLocalStorage的调用)。
加载状态
const state = await hanko.createState("login", { loadFromCache: true, // Attempts to load from `cacheKey` cacheKey: "hanko-flow-state", });清除状态
state.removeFromLocalStorage(); // Deletes from `state.cacheKey`高级序列化
用于自定义持久化机制:
import { State } from "@teamhanko/hanko-frontend-sdk"; const serialized = state.serialize(); // Returns a `SerializedState` object // Store `serialized` in your storage system // Later, deserialize it const recoveredState = await State.deserialize(hanko, serialized, { cacheKey: "custom-key", });serialize()会把状态(含flow_name、name、error、payload、csrf_token、status、previous_action与动作映射)转成可存储的普通对象,State.deserialize则将其恢复为可用状态(State.ts、State.ts)。这允许与任意存储系统集成。
测试与源码参考
FlowAPI 与各子系统的行为在仓库测试中有充分覆盖,可作为理解与二次开发的参考:
- frontend/frontend-sdk/tests/lib/flow-api/State.spec.ts:状态创建、动作执行、缓存与反序列化;
- frontend/frontend-sdk/tests/lib/flow-api/auto-steps.spec.ts:自动步进行为;
- frontend/frontend-sdk/tests/lib/client/HttpClient.spec.ts、frontend/frontend-sdk/tests/lib/client/UserClient.spec.ts:HTTP 客户端与用户接口;
- frontend/frontend-sdk/tests/lib/events/Dispatcher.spec.ts、frontend/frontend-sdk/tests/lib/events/Listener.spec.ts:事件派发与监听。
许可证
hanko-frontend-sdk以 MIT License 授权发布。
- 后端
- 认证鉴权
- 前端
【免费下载链接】hanko
Modern authentication, on your terms. Open source alternative to Auth0, Clerk, WorkOS, Stytch.
相关推荐
openJiuwen DeepSearch人机协同:自然语言反馈与交互式修订完整指南
openJiuwen DeepSearch人机协同:自然语言反馈与交互式修订完整指南 openJiuwen DeepSearch 是一款知识增强的深度搜索与研究
人工智能大模型AI AgentRAG深度研究搜索引擎后端代码智能体GoCD与Netlify Identity集成:前端认证部署完整指南
GoCD与Netlify Identity集成:前端认证部署完整指南 GoCD是一个开源的持续集成和持续部署工具,可以帮助开发团队自动化软件开发和运维流程。通过
CI/CDDevOps后端任务调度jeecg-boot前端表单验证:VeeValidate集成与自定义校验规则完整指南
jeecg boot前端表单验证:VeeValidate集成与自定义校验规则完整指南 你是否在开发企业级管理系统时遇到过表单验证的困扰?jeecg boot作为
低代码后端前端AI 应用大模型RAG工作流自动化
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考