npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@saleandwin/auth

v2.2.0

Published

Authentication center for framework-ts projects with OAuth, email, and password support

Readme

@saleandwin/auth

企业级认证中心模块,为 framework-ts 项目提供完整的用户认证和授权解决方案。支持游客登录和角色权限管理。

✨ 特性

🔐 多种认证方式

  • 邮箱密码登录 - 传统的用户名密码认证
  • Magic Link - 无密码邮箱链接登录
  • OAuth 登录 - 支持 Google、GitHub、Microsoft、Discord、Twitter
  • 游客登录 - 无需注册的临时用户体验 🆕

🛡️ 安全可靠

  • 密码加密 - bcrypt 哈希算法
  • JWT 令牌 - 安全的访问控制
  • 会话管理 - 自动过期和刷新机制
  • 输入验证 - Zod 严格类型验证
  • 速率限制 - 防暴力破解保护

👥 角色权限系统 🆕

  • 等级制权限 - 基于数字等级的简单权限控制
  • 预设角色 - 游客、用户、管理员、超级管理员
  • 灵活分配 - 支持角色过期时间设置
  • 权限检查 - 角色名称和等级双重检查

📧 邮件集成

  • Resend 集成 - 专业的邮件发送服务
  • 邮箱验证 - 自动发送验证码
  • Magic Link - 一键登录链接
  • 响应式模板 - 美观的 HTML 邮件模板

💾 数据库优化

  • Cloudflare D1 - 边缘数据库优化
  • 类型安全 - 完整的 TypeScript 支持
  • 高性能查询 - 优化的 SQL 语句
  • 自动清理 - 过期数据自动清理

Architecture

The library follows a clean architecture pattern:

Handler -> Service -> Table
  • Handler: HTTP request handling for Next.js routes
  • Service: Business logic, validation, and data processing
  • Table: Database access layer with prepared statements

📦 安装

npm install @saleandwin/auth
# 或
pnpm add @saleandwin/auth
# 或
yarn add @saleandwin/auth

🚀 快速开始

1. 基础配置

import { AuthHandler, type AuthConfig, type AuthEnv } from '@saleandwin/auth';

// 在 Cloudflare Workers 中
export default {
  async fetch(request: Request, env: AuthEnv, ctx: ExecutionContext): Promise<Response> {
    const config: AuthConfig = {
      jwt_secret: env.JWT_SECRET,
      jwt_expires_in: '7d',
      session_duration: 7 * 24 * 60 * 60, // 7天
      magic_link_duration: 30 * 60, // 30分钟
      verification_code_duration: 10 * 60, // 10分钟
      password_reset_duration: 60 * 60, // 1小时
      oauth_providers: {
        google: {
          client_id: env.GOOGLE_CLIENT_ID,
          client_secret: env.GOOGLE_CLIENT_SECRET,
          redirect_uri: 'https://yourapp.com/auth/callback/google'
        }
      },
      email: {
        api_key: env.RESEND_API_KEY,
        from_email: '[email protected]',
        from_name: 'Your App'
      }
    };

    // 注入环境变量(包含 DB)
    const authHandler = AuthHandler.createInstance(config, env);

    // 处理请求...
  }
};

2. 数据库设置

# 使用 Cloudflare D1 CLI
wrangler d1 execute your-database --file=./node_modules/@saleandwin/auth/migrations.sql

# 或直接执行 SQL
cat ./node_modules/@saleandwin/auth/migrations.sql | sqlite3 your-database.db

3. 环境变量

# 必需配置
AUTH_JWT_SECRET=your-super-secret-jwt-key-at-least-32-characters
RESEND_API_KEY=re_your_resend_api_key
[email protected]
FROM_NAME=Your App Name

# OAuth 配置(可选)
GOOGLE_CLIENT_ID=your-google-client-id
GOOGLE_CLIENT_SECRET=your-google-client-secret
GITHUB_CLIENT_ID=your-github-client-id
GITHUB_CLIENT_SECRET=your-github-client-secret

4. 用户注册

const result = await authHandler.handleRegister({
  email: '[email protected]',
  name: 'John Doe',
  password: 'SecurePassword123'
});

if (result.success) {
  console.log('注册成功:', result.user);
  console.log('访问令牌:', result.access_token);
} else {
  console.error('注册失败:', result.error);
}

5. 用户登录

const result = await authHandler.handleLogin({
  email: '[email protected]',
  password: 'SecurePassword123'
});

if (result.success) {
  console.log('登录成功:', result.user);
  console.log('访问令牌:', result.access_token);
} else {
  console.error('登录失败:', result.error);
}

6. 游客登录 🆕

const result = await authHandler.handleGuestLogin({
  device_id: 'device_123', // 可选
  session_duration: 86400   // 可选,默认24小时
});

if (result.success) {
  console.log('游客登录成功:', result.user);
  console.log('用户类型:', result.user.user_type); // 'guest'
}

7. 角色权限检查 🆕

// 检查用户是否有特定角色
const hasRole = await authHandler.handleCheckRole(userId, 'admin');
console.log('是否为管理员:', hasRole.data.has_role);

// 检查用户角色等级
const hasLevel = await authHandler.handleCheckRoleLevel(userId, 80);
console.log('是否达到管理员等级:', hasLevel.data.has_min_level);

📚 完整 API 文档

AuthHandler 方法

👤 用户管理

// 用户注册
handleRegister(data: CreateUserRequest): Promise<AuthResponse>

// 用户登录
handleLogin(data: LoginRequest, clientInfo?: ClientInfo): Promise<AuthResponse>

// 游客登录 🆕
handleGuestLogin(data: GuestLoginRequest): Promise<AuthResponse>

// 用户登出
handleLogout(sessionId: string): Promise<AuthResponse>

// 更新用户信息
handleUpdateUser(userId: string, data: UpdateUserRequest): Promise<AuthResponse>

// 修改密码
handleChangePassword(userId: string, data: ChangePasswordRequest): Promise<AuthResponse>

🎫 会话管理

// 验证会话
handleValidateSession(token: string): Promise<AuthResponse>

// 刷新会话
handleRefreshSession(refreshToken: string): Promise<AuthResponse>

✨ Magic Link

// 发送 Magic Link
handleSendMagicLink(data: MagicLinkRequest): Promise<AuthResponse>

// 验证 Magic Link
handleVerifyMagicLink(token: string): Promise<AuthResponse>

🔗 OAuth

// OAuth 登录
handleOAuthLogin(data: OAuthLoginRequest, clientInfo?: ClientInfo): Promise<AuthResponse>

👥 角色权限 🆕

// 检查用户角色
handleCheckRole(userId: string, roleName: string): Promise<AuthResponse>

// 检查角色等级
handleCheckRoleLevel(userId: string, minLevel: number): Promise<AuthResponse>

数据类型

用户类型

interface User {
  id: string;
  email?: string;           // 游客用户可以没有邮箱
  email_verified: boolean;
  name?: string;
  avatar_url?: string;
  user_type: 'user' | 'guest'; // 🆕 用户类型
  is_active: boolean;
  created_at: string;
  updated_at: string;
  last_login_at?: string;
  login_count: number;
  expires_at?: string;      // 🆕 游客用户过期时间
}

角色类型 🆕

interface Role {
  id: string;
  name: string;           // 'super_admin', 'admin', 'user', 'guest'
  display_name: string;   // '超级管理员', '管理员', '注册用户', '游客用户'
  description?: string;
  level: number;          // 权限等级:100, 80, 50, 10
  is_system: boolean;     // 是否为系统角色
  is_active: boolean;
  created_at: string;
  updated_at: string;
}

请求类型

// 游客登录请求 🆕
interface GuestLoginRequest {
  device_id?: string;      // 设备标识
  session_duration?: number; // 会话持续时间(秒)
}

// 游客升级请求 🆕
interface GuestUpgradeRequest {
  email: string;
  name?: string;
  password?: string;
}

// 角色分配请求 🆕
interface AssignRoleRequest {
  user_id: string;
  role_ids: string[];
  expires_at?: string;
}

🗄️ 数据库设置

1. 运行迁移脚本

# 使用 Cloudflare D1 CLI
wrangler d1 execute your-database --file=./node_modules/@saleandwin/auth/migrations.sql

# 或直接执行 SQL
cat ./node_modules/@saleandwin/auth/migrations.sql | sqlite3 your-database.db

2. 数据库表结构

核心表

  • users - 用户表(支持游客用户)
  • sessions - 会话表
  • oauth_accounts - OAuth 账户表
  • email_verifications - 邮箱验证表

角色权限表 🆕

  • roles - 角色表(预设4个系统角色)
  • user_roles - 用户角色关联表

预设角色

| 角色名 | 显示名称 | 等级 | 描述 | |--------|----------|------|------| | super_admin | 超级管理员 | 100 | 拥有最高权限 | | admin | 管理员 | 80 | 系统管理权限 | | user | 注册用户 | 50 | 普通用户权限 | | guest | 游客用户 | 10 | 基础浏览权限 |

⚙️ 配置选项

interface AuthConfig {
  // 必需配置
  jwt_secret: string;

  // 会话配置
  session_duration?: number;        // 会话持续时间(秒)
  max_login_attempts?: number;      // 最大登录尝试次数
  lockout_duration?: number;        // 锁定持续时间(秒)

  // 验证配置
  password_reset_duration?: number;     // 密码重置有效期
  email_verification_duration?: number; // 邮箱验证有效期
  magic_link_duration?: number;         // Magic Link 有效期

  // OAuth 配置
  oauth?: {
    google?: OAuthProviderConfig;
    github?: OAuthProviderConfig;
    microsoft?: OAuthProviderConfig;
    discord?: OAuthProviderConfig;
    twitter?: OAuthProviderConfig;
  };

  // 邮件配置
  email?: {
    resend_api_key: string;
    from_email: string;
    from_name?: string;
  };
}

interface OAuthProviderConfig {
  client_id: string;
  client_secret: string;
  redirect_uri: string;
  scope?: string;
}

"password": "SecurePassword123", "remember_me": false }


### Get Current User
```http
GET /api/auth/me
Authorization: Bearer <access_token>

Update User Profile

PUT /api/auth/me
Authorization: Bearer <access_token>
Content-Type: application/json

{
  "name": "Updated Name",
  "avatar_url": "https://example.com/avatar.jpg"
}

Send Email Verification

POST /api/auth/send-verification
Content-Type: application/json

{
  "email": "[email protected]"
}

Verify Email

POST /api/auth/verify-email
Content-Type: application/json

{
  "code": "123456"
}

Send Magic Link

POST /api/auth/magic-link
Content-Type: application/json

{
  "email": "[email protected]",
  "redirect_uri": "https://yourapp.com/dashboard"
}

Change Password

POST /api/auth/change-password
Authorization: Bearer <access_token>
Content-Type: application/json

{
  "current_password": "OldPassword123",
  "new_password": "NewPassword123"
}

Logout

POST /api/auth/logout
Authorization: Bearer <access_token>

🔧 Next.js 集成示例

API 路由示例

// app/api/auth/register/route.ts
import { AuthHandler } from '@saleandwin/auth';
import { NextRequest, NextResponse } from 'next/server';
import { authConfig } from '@/lib/auth-config';

export async function POST(request: NextRequest) {
  try {
    const authHandler = await AuthHandler.createInstance(authConfig);
    const data = await request.json();

    const result = await authHandler.handleRegister(data);

    if (result.success) {
      return NextResponse.json(result, { status: 201 });
    } else {
      return NextResponse.json(result, { status: 400 });
    }
  } catch (error) {
    return NextResponse.json(
      { success: false, error: '服务器内部错误' },
      { status: 500 }
    );
  }
}

中间件权限控制

// middleware.ts
import { NextRequest, NextResponse } from 'next/server';
import { AuthHandler } from '@saleandwin/auth';

export async function middleware(request: NextRequest) {
  // 检查管理员路由权限
  if (request.nextUrl.pathname.startsWith('/dashboard/admin')) {
    const token = request.cookies.get('auth-token')?.value;
    if (!token) return NextResponse.redirect(new URL('/login', request.url));

    const authHandler = await AuthHandler.createInstance(authConfig);
    const roleCheck = await authHandler.handleCheckRoleLevel(userId, 80);

    if (!roleCheck.data?.has_min_level) {
      return NextResponse.redirect(new URL('/dashboard', request.url));
    }
  }

  return NextResponse.next();
}

📖 使用示例

详细的使用示例请查看 examples/ 目录:

🛡️ 安全最佳实践

  1. 密码安全: 使用强密码策略,密码使用 bcrypt 加密
  2. 会话管理: 定期刷新令牌,设置合理的过期时间
  3. 输入验证: 所有输入都经过 Zod 验证
  4. 错误处理: 不暴露敏感信息的错误消息
  5. 速率限制: 实施登录尝试限制和锁定机制
  6. HTTPS: 生产环境必须使用 HTTPS
  7. 环境变量: 敏感配置使用环境变量存储

🔄 错误处理

所有 API 方法都返回统一的响应格式:

interface AuthResponse {
  success: boolean;
  user?: User;
  session?: SessionInfo;
  access_token?: string;
  refresh_token?: string;
  expires_in?: number;
  message?: string;
  error?: string;
  data?: any; // 通用数据字段
}

🚀 开发

# 安装依赖
pnpm install

# 运行测试
pnpm test

# 构建
pnpm build

# 类型检查
pnpm type-check

📄 许可证

MIT

🤝 贡献

欢迎提交 Issue 和 Pull Request!

📞 支持

如有问题,请通过以下方式联系: