sa2kit 3.2.1 → 3.2.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../../src/common/auth/server/plugins/dev-otp.ts","../../../../src/common/auth/server/create-auth.ts","../../../../src/common/auth/server/handler/next.ts","../../../../src/common/auth/server/handler/hono.ts","../../../../src/common/auth/server/session.ts"],"names":["phoneNumber","session","user"],"mappings":"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","file":"index.mjs","sourcesContent":["/**\n * 开发 / 测试环境 OTP 输出(禁止生产依赖)\n */\nexport function createDevOtpLogger(enabled: boolean) {\n if (!enabled || process.env.NODE_ENV === 'production') {\n return undefined;\n }\n return (channel: 'sms' | 'email', target: string, code: string) => {\n console.info(`[sa2kit/auth][dev-otp][${channel}] ${target} => ${code}`);\n };\n}\n\nexport const defaultPhoneValidator = (phoneNumber: string) => /^1\\d{10}$/.test(phoneNumber);\n\nexport const defaultTempEmailFromPhone = (phoneNumber: string) =>\n `${phoneNumber.replace(/\\D/g, '')}@phone.sa2kit.local`;\n","/**\n * Better Auth 服务端工厂(sa2kit 3.0 SSOT)\n */\nimport { betterAuth } from 'better-auth';\nimport { drizzleAdapter } from '@better-auth/drizzle-adapter';\nimport { emailOTP } from 'better-auth/plugins';\nimport { phoneNumber } from 'better-auth/plugins';\nimport { bearer } from 'better-auth/plugins';\nimport { authDrizzleSchema } from '../schema';\nimport type { Sa2kitAuthConfig, Sa2kitAuthInstance } from './types';\nimport {\n createDevOtpLogger,\n defaultPhoneValidator,\n defaultTempEmailFromPhone,\n} from './plugins/dev-otp';\n\nexport type { Sa2kitAuthInstance } from './types';\n\nexport function createSa2kitAuth(config: Sa2kitAuthConfig): Sa2kitAuthInstance {\n if (!config.secret || config.secret.length < 32) {\n throw new Error('createSa2kitAuth: secret 至少 32 字符');\n }\n\n const devLog = createDevOtpLogger(config.logOtpInDev ?? process.env.NODE_ENV !== 'production');\n const phoneValidator = config.phoneNumberValidator ?? defaultPhoneValidator;\n\n const auth = betterAuth({\n appName: 'sa2kit',\n baseURL: config.baseURL,\n basePath: config.basePath ?? '/api/auth',\n secret: config.secret,\n trustedOrigins: config.trustedOrigins,\n database: drizzleAdapter(config.db as never, {\n provider: 'pg',\n schema: authDrizzleSchema,\n }),\n emailAndPassword: {\n enabled: true,\n },\n user: {\n additionalFields: {\n role: {\n type: 'string',\n required: false,\n defaultValue: 'USER',\n input: false,\n },\n },\n },\n plugins: [\n bearer(),\n emailOTP({\n async sendVerificationOTP({ email, otp, type }) {\n devLog?.('email', `${email} (${type})`, otp);\n if (config.email?.sendVerificationOTP) {\n await config.email.sendVerificationOTP(email, otp, type);\n }\n },\n }),\n phoneNumber({\n allowedAttempts: 5,\n phoneNumberValidator: phoneValidator,\n async sendOTP({ phoneNumber: phone, code }) {\n devLog?.('sms', phone, code);\n if (config.sms?.sendOTP) {\n void config.sms.sendOTP(phone, code);\n }\n },\n signUpOnVerification: {\n getTempEmail: defaultTempEmailFromPhone,\n getTempName: (phone) => phone,\n },\n }),\n ],\n }) as unknown as Sa2kitAuthInstance;\n\n return auth;\n}\n","/**\n * Next.js App Router handler 挂载\n */\nimport { toNextJsHandler } from 'better-auth/next-js';\nimport type { Sa2kitAuthInstance } from '../create-auth';\n\nexport function mountNextAuthHandler(auth: Sa2kitAuthInstance) {\n return toNextJsHandler(auth);\n}\n","/**\n * Hono / 通用 fetch handler\n */\nimport type { Sa2kitAuthInstance } from '../create-auth';\n\nexport function mountAuthHandler(auth: Sa2kitAuthInstance) {\n return (request: Request) => auth.handler(request);\n}\n\nexport function createAuthRouteHandlers(auth: Sa2kitAuthInstance) {\n const handler = mountAuthHandler(auth);\n return {\n GET: handler,\n POST: handler,\n PUT: handler,\n PATCH: handler,\n DELETE: handler,\n };\n}\n","/**\n * 从 Request 解析 Better Auth session(替代自研 JWT validateApiAuth)\n */\nimport type { Sa2kitAuthInstance } from './types';\n\nexport type SessionUser = {\n id: string;\n email: string;\n name: string;\n role?: string;\n phoneNumber?: string | null;\n};\n\nexport async function getSessionUser(\n auth: Sa2kitAuthInstance,\n request: Request,\n): Promise<SessionUser | null> {\n const session = await auth.api.getSession({ headers: request.headers });\n if (!session?.user) return null;\n\n const user = session.user as SessionUser & { role?: string };\n return {\n id: user.id,\n email: user.email,\n name: user.name,\n role: user.role,\n phoneNumber: (user as { phoneNumber?: string | null }).phoneNumber ?? null,\n };\n}\n\nexport type SessionUserNumeric = Omit<SessionUser, 'id'> & { id: number };\n\n/** 兼容 numeric id 消费方(legacy calendar 等) */\nexport async function getSessionUserNumeric(\n auth: Sa2kitAuthInstance,\n request: Request,\n): Promise<SessionUserNumeric | null> {\n const user = await getSessionUser(auth, request);\n if (!user) return null;\n const numericId = Number.parseInt(user.id, 10);\n if (Number.isNaN(numericId)) return null;\n const { id: _id, ...rest } = user;\n return { ...rest, id: numericId };\n}\n\nexport function createSessionValidator(auth: Sa2kitAuthInstance) {\n return {\n getSessionUser: (request: Request) => getSessionUser(auth, request),\n getSessionUserNumeric: (request: Request) => getSessionUserNumeric(auth, request),\n };\n}\n"]}
1
+ {"version":3,"sources":["../../../../src/common/auth/server/plugins/dev-otp.ts","../../../../src/common/auth/server/credential-password.ts","../../../../src/common/auth/server/phone-signup-intent.ts","../../../../src/common/auth/server/create-auth.ts","../../../../src/common/auth/server/env/auth-env-catalog.ts","../../../../src/common/auth/server/sms/providers/aliyun-pnvs.ts","../../../../src/common/auth/server/sms/providers/console.ts","../../../../src/common/auth/server/sms/create-sms-provider-from-env.ts","../../../../src/common/auth/server/env/resolve-auth-env.ts","../../../../src/common/auth/server/env/check-auth-env.ts","../../../../src/common/auth/server/create-auth-from-env.ts","../../../../src/common/auth/server/handler/next.ts","../../../../src/common/auth/server/handler/hono.ts","../../../../src/common/auth/server/session.ts"],"names":["phoneNumber","user","readEnv","session"],"mappings":"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","file":"index.mjs","sourcesContent":["/**\n * 开发 / 测试环境 OTP 输出(禁止生产依赖)\n */\nexport function createDevOtpLogger(enabled: boolean) {\n if (!enabled || process.env.NODE_ENV === 'production') {\n return undefined;\n }\n return (channel: 'sms' | 'email', target: string, code: string) => {\n console.info(`[sa2kit/auth][dev-otp][${channel}] ${target} => ${code}`);\n };\n}\n\nexport const defaultPhoneValidator = (phoneNumber: string) => /^1\\d{10}$/.test(phoneNumber);\n\nexport const defaultTempEmailFromPhone = (phoneNumber: string) =>\n `${phoneNumber.replace(/\\D/g, '')}@phone.sa2kit.local`;\n","import { and, eq } from 'drizzle-orm';\nimport { hashPassword } from 'better-auth/crypto';\nimport { account } from '../schema/account';\n\ntype AuthDb = {\n select: (...args: unknown[]) => {\n from: (...args: unknown[]) => {\n where: (...args: unknown[]) => {\n limit: (...args: unknown[]) => Promise<Array<{ id: string }>>;\n };\n };\n };\n update: (...args: unknown[]) => {\n set: (...args: unknown[]) => {\n where: (...args: unknown[]) => Promise<unknown>;\n };\n };\n insert: (...args: unknown[]) => {\n values: (...args: unknown[]) => Promise<unknown>;\n };\n};\n\nfunction createId(): string {\n return globalThis.crypto?.randomUUID?.() ?? `acc_${Date.now()}_${Math.random().toString(36).slice(2)}`;\n}\n\n/** 为手机号注册用户写入 credential 密码,供「手机+密码」登录 */\nexport async function upsertCredentialPassword(\n db: unknown,\n userId: string,\n plainPassword: string,\n): Promise<void> {\n const database = db as AuthDb;\n const now = new Date();\n const passwordHash = await hashPassword(plainPassword);\n\n const existing = await database\n .select({ id: account.id })\n .from(account)\n .where(and(eq(account.userId, userId), eq(account.providerId, 'credential')))\n .limit(1);\n\n if (existing[0]) {\n await database\n .update(account)\n .set({ password: passwordHash, updatedAt: now })\n .where(eq(account.id, existing[0].id));\n return;\n }\n\n await database.insert(account).values({\n id: createId(),\n accountId: userId,\n providerId: 'credential',\n userId,\n password: passwordHash,\n createdAt: now,\n updatedAt: now,\n });\n}\n","import { defaultPhoneValidator } from './plugins/dev-otp';\n\ntype PendingEntry = {\n password: string;\n expiresAt: number;\n};\n\nconst pendingByPhone = new Map<string, PendingEntry>();\nconst TTL_MS = 5 * 60 * 1000;\n\nfunction normalizePhone(phoneNumber: string): string {\n return phoneNumber.replace(/\\D/g, '');\n}\n\nexport function stashPhoneSignupPassword(phoneNumber: string, password: string): void {\n pendingByPhone.set(normalizePhone(phoneNumber), {\n password,\n expiresAt: Date.now() + TTL_MS,\n });\n}\n\nexport function consumePhoneSignupPassword(phoneNumber: string): string | undefined {\n const key = normalizePhone(phoneNumber);\n const entry = pendingByPhone.get(key);\n pendingByPhone.delete(key);\n if (!entry) return undefined;\n if (entry.expiresAt < Date.now()) return undefined;\n return entry.password;\n}\n\nexport async function handlePhoneSignupIntentRequest(request: Request): Promise<Response> {\n if (request.method !== 'POST') {\n return new Response('Method Not Allowed', { status: 405 });\n }\n\n let body: { phoneNumber?: string; password?: string };\n try {\n body = (await request.json()) as { phoneNumber?: string; password?: string };\n } catch {\n return Response.json({ error: 'invalid_json' }, { status: 400 });\n }\n\n const phoneNumber = String(body.phoneNumber ?? '').trim();\n const password = String(body.password ?? '');\n\n if (!defaultPhoneValidator(phoneNumber)) {\n return Response.json({ error: 'invalid_phone' }, { status: 400 });\n }\n if (password.length < 6) {\n return Response.json({ error: 'invalid_password' }, { status: 400 });\n }\n\n stashPhoneSignupPassword(phoneNumber, password);\n return Response.json({ ok: true });\n}\n","/**\n * Better Auth 服务端工厂(sa2kit 3.0 SSOT)\n */\nimport { betterAuth } from 'better-auth';\nimport { drizzleAdapter } from '@better-auth/drizzle-adapter';\nimport { emailOTP } from 'better-auth/plugins';\nimport { phoneNumber } from 'better-auth/plugins';\nimport { bearer } from 'better-auth/plugins';\nimport { authDrizzleSchema } from '../schema';\nimport type { Sa2kitAuthConfig, Sa2kitAuthInstance } from './types';\nimport {\n createDevOtpLogger,\n defaultPhoneValidator,\n defaultTempEmailFromPhone,\n} from './plugins/dev-otp';\nimport { upsertCredentialPassword } from './credential-password';\nimport { consumePhoneSignupPassword } from './phone-signup-intent';\n\nexport type { Sa2kitAuthInstance } from './types';\n\nexport function createSa2kitAuth(config: Sa2kitAuthConfig): Sa2kitAuthInstance {\n if (!config.secret || config.secret.length < 32) {\n throw new Error('createSa2kitAuth: secret 至少 32 字符');\n }\n\n const devLog = createDevOtpLogger(config.logOtpInDev ?? process.env.NODE_ENV !== 'production');\n const phoneValidator = config.phoneNumberValidator ?? defaultPhoneValidator;\n\n const auth = betterAuth({\n appName: 'sa2kit',\n baseURL: config.baseURL,\n basePath: config.basePath ?? '/api/auth',\n secret: config.secret,\n trustedOrigins: config.trustedOrigins,\n database: drizzleAdapter(config.db as never, {\n provider: 'pg',\n schema: authDrizzleSchema,\n }),\n emailAndPassword: {\n enabled: true,\n },\n user: {\n additionalFields: {\n role: {\n type: 'string',\n required: false,\n defaultValue: 'USER',\n input: false,\n },\n },\n },\n plugins: [\n bearer(),\n emailOTP({\n async sendVerificationOTP({ email, otp, type }) {\n devLog?.('email', `${email} (${type})`, otp);\n if (config.email?.sendVerificationOTP) {\n await config.email.sendVerificationOTP(email, otp, type);\n }\n },\n }),\n phoneNumber({\n allowedAttempts: 5,\n phoneNumberValidator: phoneValidator,\n async sendOTP({ phoneNumber: phone, code }) {\n devLog?.('sms', phone, code);\n if (config.sms?.sendOTP) {\n await config.sms.sendOTP(phone, code);\n }\n },\n async callbackOnVerification({ phoneNumber: phone, user }) {\n const pendingPassword = consumePhoneSignupPassword(phone);\n if (pendingPassword && user?.id) {\n await upsertCredentialPassword(config.db, String(user.id), pendingPassword);\n }\n },\n signUpOnVerification: {\n getTempEmail: defaultTempEmailFromPhone,\n getTempName: (phone) => phone,\n },\n }),\n ],\n }) as unknown as Sa2kitAuthInstance;\n\n return auth;\n}\n","export type AuthEnvPlacement = 'env_file' | 'github_secret' | 'runtime_env' | 'database';\n\nexport type AuthEnvVarDefinition = {\n key: string;\n featureId: string;\n required: boolean;\n placement: AuthEnvPlacement[];\n description: string;\n example?: string;\n secret?: boolean;\n};\n\nexport type AuthFeatureDefinition = {\n id: string;\n name: string;\n description: string;\n envKeys: string[];\n};\n\nexport const AUTH_FEATURES: AuthFeatureDefinition[] = [\n {\n id: 'core',\n name: '核心认证',\n description: 'Better Auth 服务端基础能力(会话、Cookie、API 路由)',\n envKeys: ['BETTER_AUTH_SECRET', 'BETTER_AUTH_URL'],\n },\n {\n id: 'client',\n name: 'Web 客户端',\n description: '浏览器端 AuthProvider / 登录弹窗请求正确 origin',\n envKeys: ['NEXT_PUBLIC_APP_URL'],\n },\n {\n id: 'trusted_origins',\n name: '跨域信任源',\n description: '多域名 / 预览环境 CORS 与 Cookie',\n envKeys: ['BETTER_AUTH_TRUSTED_ORIGINS'],\n },\n {\n id: 'sms_phone_otp',\n name: '手机短信 OTP',\n description: '手机号注册 / 登录 / 找回密码的短信验证码',\n envKeys: [\n 'SA2KIT_SMS_PROVIDER',\n 'ALIYUN_SMS_ACCESS_KEY_ID',\n 'ALIYUN_SMS_ACCESS_KEY_SECRET',\n 'ALIYUN_SMS_SIGN_NAME',\n 'ALIYUN_SMS_TEMPLATE_CODE',\n 'ALIYUN_SMS_COUNTRY_CODE',\n 'ALIYUN_SMS_CODE_VALID_MINUTES',\n 'ALIYUN_SMS_ENDPOINT',\n ],\n },\n {\n id: 'email_otp',\n name: '邮箱 OTP',\n description: '邮箱验证码(需在 createSa2kitAuth 传入 email.sendVerificationOTP)',\n envKeys: ['SA2KIT_EMAIL_PROVIDER'],\n },\n {\n id: 'database',\n name: '数据库',\n description: 'Drizzle + PostgreSQL 持久化 user/session(由宿主项目配置)',\n envKeys: ['DATABASE_URL'],\n },\n];\n\nexport const AUTH_ENV_CATALOG: AuthEnvVarDefinition[] = [\n {\n key: 'BETTER_AUTH_SECRET',\n featureId: 'core',\n required: true,\n placement: ['env_file', 'github_secret', 'runtime_env'],\n description: 'Better Auth 签名密钥,至少 32 字符。可兼容读取 NEXTAUTH_SECRET。',\n example: 'openssl rand -base64 32',\n secret: true,\n },\n {\n key: 'BETTER_AUTH_URL',\n featureId: 'core',\n required: true,\n placement: ['env_file', 'github_secret', 'runtime_env'],\n description: '对外可访问的站点 URL(含协议与端口)。可回退 NEXT_PUBLIC_APP_URL / NEXTAUTH_URL。',\n example: 'https://example.com',\n },\n {\n key: 'NEXT_PUBLIC_APP_URL',\n featureId: 'client',\n required: true,\n placement: ['env_file', 'github_secret', 'runtime_env'],\n description: '浏览器端 auth client 的 baseURL。',\n example: 'https://example.com',\n },\n {\n key: 'BETTER_AUTH_TRUSTED_ORIGINS',\n featureId: 'trusted_origins',\n required: false,\n placement: ['env_file', 'github_secret', 'runtime_env'],\n description: '逗号分隔的可信 origin 列表,用于预览域 / 多域名部署。',\n example: 'https://example.com,https://www.example.com',\n },\n {\n key: 'SA2KIT_SMS_PROVIDER',\n featureId: 'sms_phone_otp',\n required: false,\n placement: ['env_file', 'github_secret', 'runtime_env'],\n description: '短信 provider:console(开发日志)| aliyun-pnvs(生产)| none。开发默认 console,生产未配置则无法发短信。',\n example: 'aliyun-pnvs',\n },\n {\n key: 'ALIYUN_SMS_ACCESS_KEY_ID',\n featureId: 'sms_phone_otp',\n required: false,\n placement: ['env_file', 'github_secret', 'runtime_env'],\n description: '阿里云 RAM AccessKey ID(短信认证 SendSmsVerifyCode)。',\n secret: true,\n },\n {\n key: 'ALIYUN_SMS_ACCESS_KEY_SECRET',\n featureId: 'sms_phone_otp',\n required: false,\n placement: ['env_file', 'github_secret', 'runtime_env'],\n description: '阿里云 RAM AccessKey Secret。',\n secret: true,\n },\n {\n key: 'ALIYUN_SMS_SIGN_NAME',\n featureId: 'sms_phone_otp',\n required: false,\n placement: ['env_file', 'github_secret', 'runtime_env'],\n description: '短信认证控制台赠送/申请的签名名称。',\n example: '速通互联验证码',\n },\n {\n key: 'ALIYUN_SMS_TEMPLATE_CODE',\n featureId: 'sms_phone_otp',\n required: false,\n placement: ['env_file', 'github_secret', 'runtime_env'],\n description: '短信认证控制台赠送/申请的模板 CODE。',\n example: '100001',\n },\n {\n key: 'ALIYUN_SMS_COUNTRY_CODE',\n featureId: 'sms_phone_otp',\n required: false,\n placement: ['env_file', 'runtime_env'],\n description: '国家码,默认 86(中国大陆)。',\n example: '86',\n },\n {\n key: 'ALIYUN_SMS_CODE_VALID_MINUTES',\n featureId: 'sms_phone_otp',\n required: false,\n placement: ['env_file', 'runtime_env'],\n description: '短信模板中展示的有效分钟数,默认 5(与 Better Auth OTP 有效期独立)。',\n example: '5',\n },\n {\n key: 'ALIYUN_SMS_ENDPOINT',\n featureId: 'sms_phone_otp',\n required: false,\n placement: ['env_file', 'runtime_env'],\n description: '可选,默认 https://dypnsapi.aliyuncs.com',\n },\n {\n key: 'SA2KIT_EMAIL_PROVIDER',\n featureId: 'email_otp',\n required: false,\n placement: ['env_file', 'github_secret', 'runtime_env'],\n description: '邮箱 OTP 由宿主实现 config.email.sendVerificationOTP;此变量仅用于 env 检查提示。',\n example: 'resend | smtp | console',\n },\n {\n key: 'DATABASE_URL',\n featureId: 'database',\n required: true,\n placement: ['env_file', 'github_secret', 'runtime_env', 'database'],\n description: 'PostgreSQL 连接串(宿主项目 Drizzle 使用,非 sa2kit 直接读取)。',\n secret: true,\n },\n {\n key: 'SA2KIT_AUTH_LOG_OTP',\n featureId: 'sms_phone_otp',\n required: false,\n placement: ['env_file', 'runtime_env'],\n description: '设为 1 时在非生产环境将 OTP 打印到服务端日志;生产环境忽略。设为 0 可关闭开发日志。',\n example: '1',\n },\n];\n\nexport const AUTH_ENV_ALIASES: Record<string, string[]> = {\n BETTER_AUTH_SECRET: ['NEXTAUTH_SECRET'],\n BETTER_AUTH_URL: ['NEXT_PUBLIC_APP_URL', 'NEXTAUTH_URL'],\n};\n","import type { AliyunPnvsSmsConfig, Sa2kitSmsProvider } from '../types';\n\ntype PopCoreClient = {\n request(\n action: string,\n params: Record<string, string>,\n options?: { method?: string },\n ): Promise<{ Code?: string; Success?: boolean; Message?: string }>;\n};\n\nasync function loadPopCore(): Promise<new (config: Record<string, string>) => PopCoreClient> {\n try {\n const mod = await import('@alicloud/pop-core');\n return (mod.default ?? mod) as unknown as new (config: Record<string, string>) => PopCoreClient;\n } catch {\n throw new Error(\n '启用 SA2KIT_SMS_PROVIDER=aliyun-pnvs 需要安装 @alicloud/pop-core:pnpm add @alicloud/pop-core',\n );\n }\n}\n\nexport function createAliyunPnvsSmsProvider(config: AliyunPnvsSmsConfig): Sa2kitSmsProvider {\n return {\n async sendOTP(phoneNumber, code) {\n const Core = await loadPopCore();\n const client = new Core({\n accessKeyId: config.accessKeyId,\n accessKeySecret: config.accessKeySecret,\n endpoint: config.endpoint ?? 'https://dypnsapi.aliyuncs.com',\n apiVersion: '2017-05-25',\n });\n\n const minutes = String(config.codeValidMinutes ?? 5);\n const result = await client.request(\n 'SendSmsVerifyCode',\n {\n PhoneNumber: phoneNumber,\n CountryCode: config.countryCode ?? '86',\n SignName: config.signName,\n TemplateCode: config.templateCode,\n TemplateParam: JSON.stringify({ code, min: minutes }),\n },\n { method: 'POST' },\n );\n\n if (result.Code !== 'OK' && result.Success !== true) {\n throw new Error(\n `阿里云短信认证发送失败: ${result.Message ?? result.Code ?? 'unknown error'}`,\n );\n }\n },\n };\n}\n","import type { Sa2kitSmsProvider } from '../types';\n\nexport function createConsoleSmsProvider(): Sa2kitSmsProvider {\n return {\n async sendOTP(phoneNumber, code) {\n console.info(`[sa2kit/auth][sms][console] ${phoneNumber} => ${code}`);\n },\n };\n}\n","import { createAliyunPnvsSmsProvider } from './providers/aliyun-pnvs';\nimport { createConsoleSmsProvider } from './providers/console';\nimport type { Sa2kitSmsProvider, Sa2kitSmsProviderId } from './types';\n\nfunction readEnv(key: string): string | undefined {\n const value = process.env[key];\n return value && value.trim().length > 0 ? value.trim() : undefined;\n}\n\nexport function resolveSmsProviderId(\n explicit?: Sa2kitSmsProviderId,\n): Sa2kitSmsProviderId | undefined {\n if (explicit) return explicit;\n const fromEnv = readEnv('SA2KIT_SMS_PROVIDER') as Sa2kitSmsProviderId | undefined;\n if (fromEnv) return fromEnv;\n if (process.env.NODE_ENV !== 'production') return 'console';\n return undefined;\n}\n\nexport function createSmsProviderFromEnv(options?: {\n providerId?: Sa2kitSmsProviderId;\n}): Sa2kitSmsProvider | undefined {\n const providerId = resolveSmsProviderId(options?.providerId);\n if (!providerId || providerId === 'none') return undefined;\n\n if (providerId === 'console') {\n return createConsoleSmsProvider();\n }\n\n if (providerId === 'aliyun-pnvs') {\n const accessKeyId = readEnv('ALIYUN_SMS_ACCESS_KEY_ID');\n const accessKeySecret = readEnv('ALIYUN_SMS_ACCESS_KEY_SECRET');\n const signName = readEnv('ALIYUN_SMS_SIGN_NAME');\n const templateCode = readEnv('ALIYUN_SMS_TEMPLATE_CODE');\n\n if (!accessKeyId || !accessKeySecret || !signName || !templateCode) {\n throw new Error(\n 'SA2KIT_SMS_PROVIDER=aliyun-pnvs 需要 ALIYUN_SMS_ACCESS_KEY_ID、ALIYUN_SMS_ACCESS_KEY_SECRET、ALIYUN_SMS_SIGN_NAME、ALIYUN_SMS_TEMPLATE_CODE',\n );\n }\n\n const codeValidMinutes = Number.parseInt(readEnv('ALIYUN_SMS_CODE_VALID_MINUTES') ?? '5', 10);\n\n return createAliyunPnvsSmsProvider({\n accessKeyId,\n accessKeySecret,\n signName,\n templateCode,\n countryCode: readEnv('ALIYUN_SMS_COUNTRY_CODE') ?? '86',\n codeValidMinutes: Number.isFinite(codeValidMinutes) ? codeValidMinutes : 5,\n endpoint: readEnv('ALIYUN_SMS_ENDPOINT'),\n });\n }\n\n throw new Error(`未知的 SA2KIT_SMS_PROVIDER: ${providerId}`);\n}\n","import type { Sa2kitAuthConfig } from '../types';\nimport { AUTH_ENV_ALIASES } from './auth-env-catalog';\nimport { createSmsProviderFromEnv, resolveSmsProviderId } from '../sms/create-sms-provider-from-env';\n\nfunction readEnv(key: string): string | undefined {\n const value = process.env[key];\n return value && value.trim().length > 0 ? value.trim() : undefined;\n}\n\nfunction readEnvWithAliases(key: string): string | undefined {\n const direct = readEnv(key);\n if (direct) return direct;\n for (const alias of AUTH_ENV_ALIASES[key] ?? []) {\n const value = readEnv(alias);\n if (value) return value;\n }\n return undefined;\n}\n\nfunction parseTrustedOrigins(baseURL: string): string[] {\n const fromEnv = readEnv('BETTER_AUTH_TRUSTED_ORIGINS');\n const defaults = [baseURL, 'http://localhost:3000', 'http://127.0.0.1:3000'];\n const extra = fromEnv\n ? fromEnv\n .split(',')\n .map((item) => item.trim())\n .filter(Boolean)\n : [];\n return [...defaults, ...extra].filter((origin, index, list) => list.indexOf(origin) === index);\n}\n\nexport type ResolveAuthEnvInput = Partial<Sa2kitAuthConfig> & Pick<Sa2kitAuthConfig, 'db'>;\n\nexport type ResolvedAuthEnv = {\n config: Sa2kitAuthConfig;\n envSnapshot: Record<string, string | undefined>;\n};\n\nexport function resolveAuthEnv(input: ResolveAuthEnvInput): ResolvedAuthEnv {\n const baseURL =\n input.baseURL ??\n readEnvWithAliases('BETTER_AUTH_URL') ??\n readEnv('NEXT_PUBLIC_APP_URL') ??\n 'http://localhost:3000';\n\n const secret =\n input.secret ??\n readEnvWithAliases('BETTER_AUTH_SECRET') ??\n (process.env.NODE_ENV !== 'production' ? 'dev-better-auth-secret-min-32-chars!!' : undefined);\n\n if (!secret || secret.length < 32) {\n throw new Error('BETTER_AUTH_SECRET 至少 32 字符(或开发环境使用默认 dev secret)');\n }\n\n const smsProvider = createSmsProviderFromEnv();\n const sms = input.sms ?? (smsProvider ? { sendOTP: smsProvider.sendOTP.bind(smsProvider) } : undefined);\n\n const config: Sa2kitAuthConfig = {\n db: input.db,\n baseURL,\n secret,\n trustedOrigins: input.trustedOrigins ?? parseTrustedOrigins(baseURL),\n basePath: input.basePath,\n sms,\n email: input.email,\n phoneNumberValidator: input.phoneNumberValidator,\n logOtpInDev:\n input.logOtpInDev ??\n (process.env.SA2KIT_AUTH_LOG_OTP === '1' || process.env.NODE_ENV !== 'production'),\n };\n\n const envSnapshot: Record<string, string | undefined> = {\n BETTER_AUTH_SECRET: readEnvWithAliases('BETTER_AUTH_SECRET') ? '[set]' : undefined,\n BETTER_AUTH_URL: readEnvWithAliases('BETTER_AUTH_URL'),\n NEXT_PUBLIC_APP_URL: readEnv('NEXT_PUBLIC_APP_URL'),\n BETTER_AUTH_TRUSTED_ORIGINS: readEnv('BETTER_AUTH_TRUSTED_ORIGINS'),\n SA2KIT_SMS_PROVIDER: String(resolveSmsProviderId() ?? ''),\n ALIYUN_SMS_ACCESS_KEY_ID: readEnv('ALIYUN_SMS_ACCESS_KEY_ID') ? '[set]' : undefined,\n ALIYUN_SMS_ACCESS_KEY_SECRET: readEnv('ALIYUN_SMS_ACCESS_KEY_SECRET') ? '[set]' : undefined,\n ALIYUN_SMS_SIGN_NAME: readEnv('ALIYUN_SMS_SIGN_NAME'),\n ALIYUN_SMS_TEMPLATE_CODE: readEnv('ALIYUN_SMS_TEMPLATE_CODE'),\n SA2KIT_EMAIL_PROVIDER: readEnv('SA2KIT_EMAIL_PROVIDER'),\n DATABASE_URL: readEnv('DATABASE_URL') ? '[set]' : undefined,\n NODE_ENV: process.env.NODE_ENV,\n };\n\n return { config, envSnapshot };\n}\n","import {\n AUTH_ENV_CATALOG,\n AUTH_FEATURES,\n type AuthEnvVarDefinition,\n type AuthFeatureDefinition,\n} from './auth-env-catalog';\n\nexport type AuthEnvIssueLevel = 'error' | 'warning' | 'info';\n\nexport type AuthEnvIssue = {\n level: AuthEnvIssueLevel;\n featureId: string;\n featureName: string;\n message: string;\n missingKeys?: string[];\n hints?: string[];\n};\n\nexport type AuthEnvReport = {\n ok: boolean;\n issues: AuthEnvIssue[];\n enabledFeatures: string[];\n disabledFeatures: string[];\n};\n\nfunction isSet(snapshot: Record<string, string | undefined>, key: string): boolean {\n const value = snapshot[key];\n return value !== undefined && value !== '[unset]' && value.length > 0;\n}\n\nfunction featureById(id: string): AuthFeatureDefinition {\n return AUTH_FEATURES.find((f) => f.id === id)!;\n}\n\nfunction varsForFeature(featureId: string): AuthEnvVarDefinition[] {\n return AUTH_ENV_CATALOG.filter((item) => item.featureId === featureId);\n}\n\nexport function checkAuthEnv(\n envSnapshot: Record<string, string | undefined>,\n): AuthEnvReport {\n const issues: AuthEnvIssue[] = [];\n const enabledFeatures: string[] = [];\n const disabledFeatures: string[] = [];\n\n const checkRequiredFeature = (featureId: string, productionOnly = false) => {\n const feature = featureById(featureId);\n const requiredVars = varsForFeature(featureId).filter((item) => item.required);\n const missing = requiredVars.filter((item) => !isSet(envSnapshot, item.key)).map((item) => item.key);\n\n if (missing.length === 0) {\n enabledFeatures.push(featureId);\n return;\n }\n\n if (productionOnly && envSnapshot.NODE_ENV !== 'production') {\n disabledFeatures.push(featureId);\n issues.push({\n level: 'info',\n featureId,\n featureName: feature.name,\n message: `开发环境可暂缺:${missing.join(', ')}`,\n missingKeys: missing,\n });\n return;\n }\n\n disabledFeatures.push(featureId);\n issues.push({\n level: 'error',\n featureId,\n featureName: feature.name,\n message: `缺少必需环境变量:${missing.join(', ')}`,\n missingKeys: missing,\n });\n };\n\n checkRequiredFeature('core');\n checkRequiredFeature('client', true);\n checkRequiredFeature('database', true);\n\n // SMS\n const smsFeature = featureById('sms_phone_otp');\n const smsProvider = envSnapshot.SA2KIT_SMS_PROVIDER;\n if (smsProvider === 'aliyun-pnvs') {\n const aliyunKeys = [\n 'ALIYUN_SMS_ACCESS_KEY_ID',\n 'ALIYUN_SMS_ACCESS_KEY_SECRET',\n 'ALIYUN_SMS_SIGN_NAME',\n 'ALIYUN_SMS_TEMPLATE_CODE',\n ];\n const missing = aliyunKeys.filter((key) => !isSet(envSnapshot, key));\n if (missing.length === 0) {\n enabledFeatures.push('sms_phone_otp');\n } else {\n disabledFeatures.push('sms_phone_otp');\n issues.push({\n level: 'error',\n featureId: 'sms_phone_otp',\n featureName: smsFeature.name,\n message: `SA2KIT_SMS_PROVIDER=aliyun-pnvs 但缺少:${missing.join(', ')}`,\n missingKeys: missing,\n hints: ['在 GitHub Secrets 或 .env.production 中配置 ALIYUN_SMS_*'],\n });\n }\n } else if (smsProvider === 'console') {\n enabledFeatures.push('sms_phone_otp');\n if (envSnapshot.NODE_ENV === 'production') {\n issues.push({\n level: 'warning',\n featureId: 'sms_phone_otp',\n featureName: smsFeature.name,\n message: '生产环境仍在使用 SA2KIT_SMS_PROVIDER=console,验证码仅输出到日志,用户收不到短信。',\n hints: ['生产请改为 aliyun-pnvs 并配置 ALIYUN_SMS_*'],\n });\n }\n } else {\n disabledFeatures.push('sms_phone_otp');\n issues.push({\n level: envSnapshot.NODE_ENV === 'production' ? 'warning' : 'info',\n featureId: 'sms_phone_otp',\n featureName: smsFeature.name,\n message:\n envSnapshot.NODE_ENV === 'production'\n ? '未配置短信 provider,手机号 OTP 无法送达(用户收不到验证码)。'\n : '未配置短信 provider;开发环境可设置 SA2KIT_SMS_PROVIDER=console 并在服务端日志查看 OTP。',\n hints: [\n '开发:SA2KIT_SMS_PROVIDER=console',\n '生产:SA2KIT_SMS_PROVIDER=aliyun-pnvs + ALIYUN_SMS_*',\n ],\n });\n }\n\n // Email OTP\n if (isSet(envSnapshot, 'SA2KIT_EMAIL_PROVIDER')) {\n enabledFeatures.push('email_otp');\n } else {\n disabledFeatures.push('email_otp');\n issues.push({\n level: 'info',\n featureId: 'email_otp',\n featureName: featureById('email_otp').name,\n message: '未声明 SA2KIT_EMAIL_PROVIDER;若需邮箱验证码请在 createSa2kitAuth 配置 email.sendVerificationOTP。',\n });\n }\n\n // Trusted origins optional\n if (isSet(envSnapshot, 'BETTER_AUTH_TRUSTED_ORIGINS')) {\n enabledFeatures.push('trusted_origins');\n } else {\n disabledFeatures.push('trusted_origins');\n issues.push({\n level: 'info',\n featureId: 'trusted_origins',\n featureName: featureById('trusted_origins').name,\n message: '未设置 BETTER_AUTH_TRUSTED_ORIGINS,仅使用 baseURL + localhost 默认值。',\n });\n }\n\n const ok = !issues.some((issue) => issue.level === 'error');\n return { ok, issues, enabledFeatures, disabledFeatures };\n}\n\nlet loggedOnce = false;\n\nexport function logAuthEnvReport(report: AuthEnvReport, options?: { force?: boolean }): void {\n if (loggedOnce && !options?.force) return;\n loggedOnce = true;\n\n const lines: string[] = ['[sa2kit/auth] 环境配置检查'];\n for (const issue of report.issues) {\n const prefix =\n issue.level === 'error' ? '✗' : issue.level === 'warning' ? '⚠' : '○';\n lines.push(`${prefix} ${issue.featureName}: ${issue.message}`);\n if (issue.hints?.length) {\n for (const hint of issue.hints) {\n lines.push(` → ${hint}`);\n }\n }\n }\n if (report.issues.length === 0) {\n lines.push('✓ 所有已启用能力的环境变量均已就绪');\n }\n lines.push(` 已启用: ${report.enabledFeatures.join(', ') || '无'}`);\n console.info(lines.join('\\n'));\n}\n\nexport function formatAuthEnvSetupMarkdown(report?: AuthEnvReport): string {\n const lines: string[] = [\n '# sa2kit Auth 环境变量',\n '',\n '完整说明见 sa2kit 文档:`docs/auth-env.md`',\n '',\n '## 功能 ↔ 环境变量',\n '',\n ];\n\n for (const feature of AUTH_FEATURES) {\n lines.push(`### ${feature.name} (\\`${feature.id}\\`)`);\n lines.push('');\n lines.push(feature.description);\n lines.push('');\n const vars = varsForFeature(feature.id);\n lines.push('| 变量 | 必需 | 存放位置 | 说明 |');\n lines.push('|------|------|----------|------|');\n for (const item of vars) {\n lines.push(\n `| \\`${item.key}\\` | ${item.required ? '是' : '否'} | ${item.placement.join(', ')} | ${item.description} |`,\n );\n }\n lines.push('');\n }\n\n if (report) {\n lines.push('## 当前检查结果');\n lines.push('');\n for (const issue of report.issues) {\n lines.push(`- **${issue.featureName}** (${issue.level}): ${issue.message}`);\n }\n }\n\n return lines.join('\\n');\n}\n\nexport function checkAuthEnvFromProcessEnv(\n extraSnapshot?: Record<string, string | undefined>,\n): AuthEnvReport {\n const snapshot: Record<string, string | undefined> = {\n BETTER_AUTH_SECRET: process.env.BETTER_AUTH_SECRET || process.env.NEXTAUTH_SECRET ? '[set]' : undefined,\n BETTER_AUTH_URL: process.env.BETTER_AUTH_URL ?? process.env.NEXT_PUBLIC_APP_URL,\n NEXT_PUBLIC_APP_URL: process.env.NEXT_PUBLIC_APP_URL,\n BETTER_AUTH_TRUSTED_ORIGINS: process.env.BETTER_AUTH_TRUSTED_ORIGINS,\n SA2KIT_SMS_PROVIDER: process.env.SA2KIT_SMS_PROVIDER ?? (process.env.NODE_ENV !== 'production' ? 'console' : undefined),\n ALIYUN_SMS_ACCESS_KEY_ID: process.env.ALIYUN_SMS_ACCESS_KEY_ID ? '[set]' : undefined,\n ALIYUN_SMS_ACCESS_KEY_SECRET: process.env.ALIYUN_SMS_ACCESS_KEY_SECRET ? '[set]' : undefined,\n ALIYUN_SMS_SIGN_NAME: process.env.ALIYUN_SMS_SIGN_NAME,\n ALIYUN_SMS_TEMPLATE_CODE: process.env.ALIYUN_SMS_TEMPLATE_CODE,\n SA2KIT_EMAIL_PROVIDER: process.env.SA2KIT_EMAIL_PROVIDER,\n DATABASE_URL: process.env.DATABASE_URL ? '[set]' : undefined,\n NODE_ENV: process.env.NODE_ENV,\n ...extraSnapshot,\n };\n return checkAuthEnv(snapshot);\n}\n","import { createSa2kitAuth, type Sa2kitAuthInstance } from './create-auth';\nimport {\n checkAuthEnv,\n logAuthEnvReport,\n resolveAuthEnv,\n type ResolveAuthEnvInput,\n} from './env';\n\nexport function createSa2kitAuthFromEnv(\n input: ResolveAuthEnvInput,\n options?: { logEnvReport?: boolean },\n): Sa2kitAuthInstance {\n const resolved = resolveAuthEnv(input);\n const report = checkAuthEnv(resolved.envSnapshot);\n if (options?.logEnvReport !== false) {\n logAuthEnvReport(report);\n }\n return createSa2kitAuth(resolved.config);\n}\n","/**\n * Next.js App Router handler 挂载\n */\nimport { toNextJsHandler } from 'better-auth/next-js';\nimport type { Sa2kitAuthInstance } from '../create-auth';\n\nexport function mountNextAuthHandler(auth: Sa2kitAuthInstance) {\n return toNextJsHandler(auth);\n}\n","/**\n * Hono / 通用 fetch handler\n */\nimport type { Sa2kitAuthInstance } from '../create-auth';\n\nexport function mountAuthHandler(auth: Sa2kitAuthInstance) {\n return (request: Request) => auth.handler(request);\n}\n\nexport function createAuthRouteHandlers(auth: Sa2kitAuthInstance) {\n const handler = mountAuthHandler(auth);\n return {\n GET: handler,\n POST: handler,\n PUT: handler,\n PATCH: handler,\n DELETE: handler,\n };\n}\n","/**\n * 从 Request 解析 Better Auth session(替代自研 JWT validateApiAuth)\n */\nimport type { Sa2kitAuthInstance } from './types';\n\nexport type SessionUser = {\n id: string;\n email: string;\n name: string;\n role?: string;\n phoneNumber?: string | null;\n};\n\nexport async function getSessionUser(\n auth: Sa2kitAuthInstance,\n request: Request,\n): Promise<SessionUser | null> {\n const session = await auth.api.getSession({ headers: request.headers });\n if (!session?.user) return null;\n\n const user = session.user as SessionUser & { role?: string };\n return {\n id: user.id,\n email: user.email,\n name: user.name,\n role: user.role,\n phoneNumber: (user as { phoneNumber?: string | null }).phoneNumber ?? null,\n };\n}\n\nexport type SessionUserNumeric = Omit<SessionUser, 'id'> & { id: number };\n\n/** 兼容 numeric id 消费方(legacy calendar 等) */\nexport async function getSessionUserNumeric(\n auth: Sa2kitAuthInstance,\n request: Request,\n): Promise<SessionUserNumeric | null> {\n const user = await getSessionUser(auth, request);\n if (!user) return null;\n const numericId = Number.parseInt(user.id, 10);\n if (Number.isNaN(numericId)) return null;\n const { id: _id, ...rest } = user;\n return { ...rest, id: numericId };\n}\n\nexport function createSessionValidator(auth: Sa2kitAuthInstance) {\n return {\n getSessionUser: (request: Request) => getSessionUser(auth, request),\n getSessionUserNumeric: (request: Request) => getSessionUserNumeric(auth, request),\n };\n}\n"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "sa2kit",
3
- "version": "3.2.1",
3
+ "version": "3.2.2",
4
4
  "description": "SA2Kit 2.0 — common API 稳定;business 实验田模块逐步迁出 profile-v1",
5
5
  "keywords": [
6
6
  "react",
@@ -565,6 +565,7 @@
565
565
  "snapshot:exports": "node scripts/snapshot-exports.mjs",
566
566
  "smoke:exports": "node scripts/smoke-exports.mjs",
567
567
  "verify:publish-artifact": "node scripts/verify-publish-artifact.mjs",
568
+ "auth:env-check": "pnpm run build:common && node scripts/check-auth-env.mjs",
568
569
  "smoke:file-api": "vitest run tests/ossFile/uploadGetUrl.integration.test.ts tests/ossFile/bootstrap.test.ts",
569
570
  "prepare": "node scripts/prepare.mjs",
570
571
  "prepublishOnly": "pnpm run build && pnpm run verify:publish-artifact && pnpm run test",
@@ -613,6 +614,9 @@
613
614
  },
614
615
  "ws": {
615
616
  "optional": true
617
+ },
618
+ "@alicloud/pop-core": {
619
+ "optional": true
616
620
  }
617
621
  },
618
622
  "devDependencies": {
@@ -655,6 +659,9 @@
655
659
  "vitest": "^1.2.0",
656
660
  "ws": "^8.19.0"
657
661
  },
662
+ "optionalDependencies": {
663
+ "@alicloud/pop-core": "^1.7.12"
664
+ },
658
665
  "engines": {
659
666
  "node": ">=18.0.0"
660
667
  },