@edgespark/client

中文文档
1.0.4发布于 2026/03/18MITTypeScriptESM + CJS近 30 天下载 3076

边缘spark 伞客户端: auth UI/APIs 外加 HTTP 公用.

中文使用文档
文档目录29 节
  1. 安装
  2. 快速启动
  3. 管理登录 UI
  4. 集装箱需求
  5. 基本用途
  6. 反应示例
  7. 自定义标签
  8. 自定义样式
  9. 自定义用户界面
  10. 签名
  11. 注册
  12. 获取用户信息
  13. 签出
  14. 忘记密码/ 重置密码
  15. 收听 Auth 状态更改
  16. API 模块
  17. 生命周期和最佳做法
  18. 在渲染前检查登录状态
  19. 在目标页面上获取用户信息
  20. 在Login vs 获得会议对 AuthState Change 上
  21. 反应最佳做法
  22. 清理
  23. API 参考
  24. createEdgeSpark(options)
  25. client.auth
  26. client.api
  27. LoginUIOptions
  28. RedirectOptions
  29. 构建

@ dedgespark/ 客户端

EdgeSpark BaaS的浏览器SDK - 一个软件包中的认证+API客户端.

安装

npm i @edgespark/client

说明: 此SDK只使用浏览器. 它不支持节点.js或SSR环境.

快速启动

import { createEdgeSpark } from "@edgespark/client";
import "@edgespark/client/styles.css";

const client = createEdgeSpark({ baseUrl: "https://api.example.com" });

// Option 1: Use managed login UI (recommended)
await client.auth.renderAuthUI(document.getElementById("auth")!, {
  redirectTo: "/dashboard",
  onLogin: (user) => console.log("Logged in!", user.email),
});

// Option 2: Build custom UI with direct API calls
await client.auth.signIn.email({ email, password });
const session = await client.auth.getSession();

// API requests (auth token auto-injected)
const res = await client.api.fetch("/api/users");

管理登录 UI

renderAuthUI 提供完整的外框认证流程 :

流动说明
签名电子邮件/密码登录、 OAuth( Google等), 匿名临时账户
注册电子邮件/密码登记(自动处理电子邮件核查)
忘记密码发送重置代码 输入代码 设置新密码
电子邮件验证注册后发送校验邮件, 支持再发送

集装箱需求

管理下的登录UI对这些容器尺寸进行了优化:

尺寸数值页:1
最大宽度420px匹配 --edgespark-auth-card-width
最小宽度320px移动设备
响应width: 100%; max-width: 420px建议
<div id="auth" style="width: 100%; max-width: 420px; margin: 0 auto;"></div>

基本用途

import { createEdgeSpark } from "@edgespark/client";
import "@edgespark/client/styles.css";  // Required

const client = createEdgeSpark({ baseUrl: "https://api.example.com" });

// Check if already logged in
const session = await client.auth.getSession();
if (session.data?.user) {
  window.location.href = "/dashboard";
} else {
  // Render login UI
  await client.auth.renderAuthUI(document.getElementById("auth")!, {
    redirectTo: "/dashboard",
    onError: (error) => console.error("Auth error:", error),
  });
}

反应示例

import { useRef, useEffect } from "react";
import { createEdgeSpark } from "@edgespark/client";
import "@edgespark/client/styles.css";

// Create client outside component (singleton)
const client = createEdgeSpark({ baseUrl: "https://api.example.com" });

export function AuthPage() {
  const ref = useRef<HTMLDivElement>(null);

  useEffect(() => {
    if (!ref.current) return;

    // Check login status first
    client.auth.getSession().then((session) => {
      if (session.data?.user) {
        window.location.href = "/dashboard";
        return;
      }
      client.auth.renderAuthUI(ref.current!, {
        redirectTo: "/dashboard",
      });
    });
  }, []);

  return <div ref={ref} />;
}

// Dashboard page - get user info here
export function DashboardPage() {
  const [user, setUser] = useState(null);

  useEffect(() => {
    client.auth.getSession().then((session) => {
      if (!session.data?.user) {
        window.location.href = "/login";
        return;
      }
      setUser(session.data.user);
    });
  }, []);

  if (!user) return <div>Loading...</div>;
  return <div>Welcome, {user.name}!</div>;
}

自定义标签

覆盖默认标签通过 labels 参数( 部分覆盖支持) :

await client.auth.renderAuthUI(container, {
  labels: {
    // Common labels
    common: {
      continueButton: "Continue",
      backButton: "Back",
      unknownError: "Something went wrong, please try again",
    },
    // Sign in page
    signIn: {
      title: "Welcome Back",
      subtitle: "Sign in to continue",
      emailPlaceholder: "Enter your email",
      passwordPlaceholder: "Enter your password",
      loginButton: "Sign In",
      forgotPassword: "Forgot password?",
      signUpPrompt: "Don't have an account?",
      toggleToSignUp: "Sign up now",
      guestPrompt: "Not ready to sign up?",
      guestLinkText: "Continue with temporary account",
    },
    // Sign up page
    signUp: {
      title: "Create Account",
      subtitle: "Sign up to get started",
      emailPlaceholder: "Enter your email",
      passwordPlaceholder: "Enter your password",
      confirmPasswordPlaceholder: "Confirm your password",
      signUpButton: "Sign Up",
      toggleToSignIn: "Already have an account?",
      toggleToSignInLink: "Sign in now",
    },
    // Verification code page
    verifyCode: {
      title: "Enter Verification Code",
      sentTo: "Code sent to",
      resendCode: "Resend",
      resendCountdown: "Resend in {seconds}s",  // {seconds} is a placeholder
    },
    // Reset password
    resetPassword: {
      title: "Reset Password",
      subtitle: "Enter your email to receive a reset code",
      sendResetButton: "Send Reset Code",
      backToSignIn: "Back to sign in",
    },
    // Set new password
    setNewPassword: {
      title: "Set New Password",
      subtitle: "Code sent to",
      newPasswordLabel: "New password",
      confirmPasswordLabel: "Confirm password",
      setPasswordButton: "Set Password",
    },
    // OAuth buttons
    oauth: {
      googleBtnName: "Continue with Google",
      githubBtnName: "Continue with GitHub",
    },
    // Error messages (override backend error codes)
    errors: {
      INVALID_EMAIL_OR_PASSWORD: "Invalid email or password",
      INVALID_EMAIL: "Invalid email format",
      PASSWORD_MISMATCH: "Passwords do not match",
      PASSWORD_TOO_SHORT: "Password is too short",
      USER_ALREADY_EXISTS: "This email is already registered",
      EMAIL_NOT_VERIFIED: "Email not verified, please check your inbox",
      INVALID_OTP: "Invalid verification code",
      OTP_EXPIRED: "Verification code has expired",
      TOO_MANY_ATTEMPTS: "Too many attempts, please try again later",
    },
    // Success page
    success: {
      title: "Success!",
      continueButton: "Continue",
    },
    // iframe OAuth modal (for preview page limitations)
    iframeModal: {
      titleTemplate: "Sign in with {provider}",  // {provider} is a placeholder
      messageTemplate: "Due to preview limitations, {provider} sign-in must be completed in a new tab.",
      actionButton: "Open in New Tab",
    },
  },
});

自定义样式

所有样式都标注在下面 [data-edgespark-auth]。通过 CSS 变量导入 CSS并覆盖:

/* In your CSS file */
[data-edgespark-auth] {
  /* Colors */
  --edgespark-auth-color-primary: rgba(0, 0, 0, 0.95);
  --edgespark-auth-color-secondary: rgba(0, 0, 0, 0.65);
  --edgespark-auth-color-tertiary: rgba(0, 0, 0, 0.45);
  --edgespark-auth-color-text: rgba(0, 0, 0, 0.95);
  --edgespark-auth-color-text-inverse: #ffffff;
  --edgespark-auth-color-error: #dc2626;
  --edgespark-auth-color-border: rgba(0, 0, 0, 0.12);
  --edgespark-auth-color-bg: #ffffff;
  --edgespark-auth-color-bg-secondary: rgba(0, 0, 0, 0.05);
  --edgespark-auth-color-bg-link: #0077ff;

  /* Typography */
  --edgespark-auth-font-family: 'Roboto Flex', -apple-system, sans-serif;
  --edgespark-auth-font-size-title: 32px;
  --edgespark-auth-font-size-body: 14px;
  --edgespark-auth-font-size-small: 12px;

  /* Sizing & Border Radius */
  --edgespark-auth-radius-card: 30px;
  --edgespark-auth-radius-input: 12px;
  --edgespark-auth-radius-button: 999px;
  --edgespark-auth-spacing: 16px;
  --edgespark-auth-input-height: 48px;
  --edgespark-auth-button-height: 48px;
  --edgespark-auth-card-width: 420px;
}

自定义用户界面

如果管理下的UI不能满足你的需要,就打电话 client.auth API直接构建自己的UI.

client.auth 是基于 好一点了 客户端并支持所有更好的自动方法.

签名

// Email/password sign in
const result = await client.auth.signIn.email({
  email: "[email protected]",
  password: "password",
});

if (result.error) {
  console.error("Sign in failed:", result.error.message);
} else {
  console.log("Sign in successful:", result.data);
}

// OAuth sign in (redirects to third-party page)
await client.auth.signIn.social({
  provider: "google",
  callbackURL: "/dashboard",  // Redirect after success
});

// Anonymous temporary account (requires backend support)
await client.auth.signIn.anonymous();

注册

const result = await client.auth.signUp.email({
  name: "John Doe",
  email: "[email protected]",
  password: "password",
  callbackURL: "/verify-email",  // Link destination in verification email
});

if (result.error) {
  console.error("Sign up failed:", result.error.message);
}

获取用户信息

// Get current logged-in user's session
const session = await client.auth.getSession();

if (session.data) {
  console.log("User info:", session.data.user);
  console.log("Session:", session.data.session);
} else {
  console.log("Not logged in");
}

签出

await client.auth.signOut();

忘记密码/ 重置密码

// 1. Send reset code to email
await client.auth.forgetPassword.emailOtp({
  email: "[email protected]",
});

// 2. Set new password with verification code
const result = await client.auth.emailOtp.resetPassword({
  email: "[email protected]",
  otp: "123456",
  password: "newpassword",
});

if (result.error) {
  console.error("Reset failed:", result.error.message);
}

收听 Auth 状态更改

// Listen to auth state changes (login/logout/token refresh)
const unsubscribe = client.auth.onAuthStateChange(() => {
  // Get latest session when state changes
  client.auth.getSession().then((session) => {
    if (session?.data?.user) {
      console.log("Logged in", session.data.user);
    } else {
      console.log("Logged out");
    }
  });
});

// Unsubscribe
unsubscribe();

API 模块

client.api.fetch 实值 fetch 带有自动注入的认证符号 :

// GET
const res = await client.api.fetch("/api/users");
const users = await res.json();

// POST
const res = await client.api.fetch("/api/posts", {
  method: "POST",
  headers: { "Content-Type": "application/json" },
  body: JSON.stringify({ title: "Hello" }),
});

安全说明: Token 仅为同源请求注入(域名与 baseUrl) (中文(简体) ). 跨源请求不会自动包含符号 .


生命周期和最佳做法

在渲染前检查登录状态

总是在渲染登录用户前检查用户是否已经登录 :

const session = await client.auth.getSession();
if (session.data?.user) {
  // Already logged in, redirect to dashboard
  window.location.href = "/dashboard";
  return;
}

// Not logged in, render login UI
await client.auth.renderAuthUI(container, {
  redirectTo: "/dashboard",
});

在目标页面上获取用户信息

重定向后, 使用 getSession() 目标页面上 - 这是 建议 获取用户信息的方法 :

// /dashboard page
const session = await client.auth.getSession();
if (!session.data?.user) {
  window.location.href = "/login";
  return;
}
console.log("Welcome", session.data.user.name);

在Login vs 获得会议对 AuthState Change 上

API 密码使用大小写页:1
getSession()建议: 获取当前用户信息到处都行,同声
onLogin快速同步操作( 分析、 日志)未呼叫 OAuth; 重新定向前起火
onAuthStateChange高级:实时认证监测需要手动取消订阅; 在任何符号更改上起火

反应最佳做法

// ✅ Create client outside component (singleton)
const client = createEdgeSpark({ baseUrl: "..." });

function AuthPage() {
  const ref = useRef<HTMLDivElement>(null);

  useEffect(() => {
    if (!ref.current) return;

    // Check if already logged in
    client.auth.getSession().then((session) => {
      if (session.data?.user) {
        window.location.href = "/dashboard";
        return;
      }
      // Render login UI
      client.auth.renderAuthUI(ref.current!, {
      redirectTo: "/dashboard",
      });
    });

    // No need to destroy - renderAuthUI auto-cleans previous UI
  }, []);

  return <div ref={ref} />;
}

清理

// Destroy client (cleanup UI, event listeners, etc.)
client.destroy();

// Also clear locally stored token
client.destroy({ clearToken: true });

说明: 只有电话 destroy() 当整个应用程序卸载时, 而不是组件卸载时.


API 参考

createEdgeSpark(options)

创建 EdgeSpark 客户端. 初始化为同步.

选项类型说明
baseUrlstring后端 URL( 需要)
fetchCredentialsRequestCredentials获取证书模式, 默认 "include"

client.auth

认证客户端基于更好的事实。 主要方法:

方法说明
signIn.email({ email, password })电子邮件/密码符号
signIn.social({ provider, callbackURL })代理签名
signIn.anonymous()匿名签名
signUp.email({ name, email, password })电子邮件注册
signOut()签字
getSession()获取当前会话/用户信息
forgetPassword.emailOtp({ email })发送密码重置代码
emailOtp.resetPassword({ email, otp, password })用代码重置密码
renderAuthUI(container, options)Render 管理登录 UI
onAuthStateChange(listener)听值变化

client.api

方法说明
fetch(path, options?)用认证符号获取

LoginUIOptions

备选方案 renderAuthUI数字 :

选项类型说明
redirectTostring登录后重定向 URL (简单模式)
redirectsRedirectOptions精细重定向配置( 覆盖) redirectTo(中文(简体) )
labelsPartial<ExtendedLabels>自定义标签
onLogin(user) => void可选: 用于快速同步操作, 如分析( 不呼叫 OAuth)
onError(error) => void回调错误

RedirectOptions

interface RedirectOptions {
  oauth?: {
    success?: string;   // OAuth login success
    newUser?: string;   // OAuth first-time signup
    error?: string;     // OAuth error
  };
  emailPassword?: string;     // Email/password login success
  emailVerification?: string; // Email verification link destination
  anonymous?: string;         // Anonymous login success
}

构建

npm run build      # Build
npm run dev        # Run example (examples/dev)

版本与发布记录

@edgespark/client 共发布 32 个版本,首次发布于 2025/12/04;过去 12 个月发布了 32 个版本。

版本发布日期距今
1.0.4latest2026/03/187 个月前
1.0.32026/01/0610 个月前
1.0.22025/12/1710 个月前
1.0.12025/12/1610 个月前
1.0.02025/12/1610 个月前
0.0.272025/12/1610 个月前

其他发布通道:beta → 0.0.2。

关于 @edgespark/client 的常见问题

@edgespark/client 是什么?

边缘spark 伞客户端: auth UI/APIs 外加 HTTP 公用.

如何安装 @edgespark/client?

在项目目录运行 npm install @edgespark/client,或使用 pnpm add / yarn add / bun add。

@edgespark/client 支持 TypeScript 吗?

支持。包内自带 TypeScript 类型声明(package.json 声明了 types 入口),安装后即可获得类型提示,无需再安装 @types 包。

@edgespark/client 支持 ESM 还是 CommonJS?

同时提供 ES Module 与 CommonJS 入口,import 和 require() 都可以使用,打包工具会自动选择合适的版本。

@edgespark/client 需要什么版本的 Node.js?

package.json 的 engines 字段要求 Node.js >=18。版本不符时 npm 默认只给出警告,开启 engine-strict 后会拒绝安装。

@edgespark/client 可以商用吗?

@edgespark/client 使用 MIT 许可。宽松许可:允许商业使用、修改和再分发,通常只需在分发时保留原版权与许可声明。以上为概括,不构成法律意见,请以许可原文为准。

@edgespark/client 的下载量有多少?

根据 npm 官方下载统计,@edgespark/client 在 2026/10/13 – 2026/11/11 这 30 天内被下载 3,076 次,日均约 103 次。下载量会把 CI 构建、镜像同步和作为其他包依赖的安装一并计入,适合横向比较热度,不能直接等同于使用人数。

@edgespark/client 还在维护吗?

最新版本 1.0.4 发布于 2026/03/18(7 个月前);至今共发布 32 个版本,其中过去 12 个月发布了 32 个;首次发布于 2025/12/04。发布频率只是参考信号:功能稳定的工具可能很少需要更新,建议结合源码仓库的 issue 和提交记录判断。