@xlt-token/express 1.0.0

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.
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.mjs","names":["XltMode","XltMode","NotLoginException","NotPermissionException","NotRoleException","NotSafeException"],"sources":["../src/context.ts","../src/auth/resolve-route-auth-meta.ts","../src/auth/should-check-login.ts","../src/auth/run-auth.ts","../src/sync-state.ts","../src/middleware/xlt-middleware.ts","../src/middleware/ignore-auth.ts","../src/middleware/require-login.ts","../src/middleware/check-permission.ts","../src/middleware/check-role.ts","../src/middleware/check-safe.ts","../src/error/map-xlt-error.ts","../src/error/xlt-error-handler.ts"],"sourcesContent":["import type { Request, Response } from 'express';\nimport type { HttpContext } from '@xlt-token/core';\n\nexport interface ExpressLikeRequest {\n _xltState?: Record<string, unknown>;\n}\n\nexport interface ExpressLikeResponse {\n setHeader(name: string, value: string): void;\n cookie(name: string, value: string, options?: unknown): void;\n}\n\n/**\n * 将 Express `req` / `res` 适配为 core 的 `HttpContext`。\n *\n * `state` 复用挂在 `req._xltState` 上的请求级共享对象,使同一请求多次调用拿到同一引用。\n */\nexport function createExpressContext(req: Request, res: Response): HttpContext {\n const state = (req._xltState ??= {});\n\n return {\n headers: {\n get: (name) => (req.headers[name.toLowerCase()] as string) ?? null,\n },\n\n cookies: {\n get: (name) => (req.cookies?.[name] as string) ?? null,\n },\n\n query: {\n get: (name) => (req.query[name] as string) ?? null,\n },\n\n state,\n\n setHeader: (name, value) => {\n res.setHeader(name, value);\n },\n\n setCookie: (name, value, options) => {\n if (options) {\n res.cookie(name, value, options);\n } else {\n res.cookie(name, value);\n }\n },\n\n raw: <T = unknown>() => req as unknown as T,\n };\n}\n","import type { Request } from 'express';\nimport type { RouteAuthMeta, RouteAuthPolicy, XltMiddlewareOptions } from '../types.js';\n\nfunction matchPathPrefix(path: string, prefix: string): boolean {\n const pathname = path.split('?')[0] ?? path;\n return prefix === '/' || pathname === prefix || pathname.startsWith(`${prefix}/`);\n}\n\n/**\n * 解析当前请求命中的路由鉴权元数据。\n *\n * 在 `shouldCheckLogin` 和 `runAuth` 之前调用,使用 `req.originalUrl` 作为匹配目标,\n * 避免 Router 嵌套时 `req.path` 丢失挂载前缀。\n *\n * 当多条策略同时命中时,后声明的策略覆盖前者的简单字段,并合并权限/角色列表,\n * 因此用户可先声明 `/api` 默认策略,再声明 `/api/public` 例外。\n */\nexport function resolveRouteAuthMeta(\n req: Request,\n options: XltMiddlewareOptions = {},\n): RouteAuthMeta {\n const policies: RouteAuthPolicy[] = [\n ...(options.ignore ?? []).map((match) => ({ match, ignore: true })),\n ...(options.policies ?? []),\n ];\n\n return policies.reduce<RouteAuthMeta>((meta, policy) => {\n if (!matchPolicy(req, policy)) return meta;\n const { match: _match, methods: _methods, ...nextMeta } = policy;\n return mergeRouteAuthMeta(meta, nextMeta);\n }, {});\n}\n\n/** 判断单条策略是否命中当前请求。 */\nexport function matchPolicy(req: Request, policy: RouteAuthPolicy): boolean {\n if (policy.methods?.length) {\n const method = req.method.toUpperCase();\n const allowed = policy.methods.map((m) => m.toUpperCase());\n if (!allowed.includes(method)) return false;\n }\n\n const matchers = Array.isArray(policy.match) ? policy.match : [policy.match];\n return matchers.some((matcher) => {\n if (typeof matcher === 'function') return matcher(req);\n if (typeof matcher === 'string') {\n return matchPathPrefix(req.originalUrl, matcher);\n }\n return matcher.test(req.originalUrl);\n });\n}\n\n/**\n * 合并两段路由元数据:\n * - `ignore` / `requireLogin` / `safeBusiness` 等简单字段:后者覆盖前者\n * - `permissions` / `roles`:两者都存在时合并列表,mode 取后者\n */\nexport function mergeRouteAuthMeta(base: RouteAuthMeta, next: RouteAuthMeta): RouteAuthMeta {\n const merged: RouteAuthMeta = { ...base, ...next };\n\n if (base.permissions && next.permissions) {\n merged.permissions = {\n list: [...base.permissions.list, ...next.permissions.list],\n mode: next.permissions.mode,\n };\n }\n\n if (base.roles && next.roles) {\n merged.roles = {\n list: [...base.roles.list, ...next.roles.list],\n mode: next.roles.mode,\n };\n }\n\n return merged;\n}\n","import type { Request } from 'express';\nimport type { XltTokenConfig } from '@xlt-token/core';\n\n/**\n * 是否需要对当前请求执行登录校验。\n *\n * 与 NestJS `XltTokenGuard.requiresLogin` 行为一致:\n * - 黑名单模式(`defaultCheck === true`):除被 `ignore` 标记的路由外全部校验\n * - 白名单模式(`defaultCheck === false`):仅校验被 `requireLogin` 标记的路由\n *\n * 路由元数据由 `resolveRouteAuthMeta` 提前写入 `req._xltRouteMeta`。\n */\nexport function shouldCheckLogin(req: Request, config: XltTokenConfig): boolean {\n const meta = req._xltRouteMeta;\n\n if (config.defaultCheck) {\n return !meta?.ignore;\n }\n\n return meta?.requireLogin ?? false;\n}\n","import type { Request } from 'express';\nimport type { AuthResult, HttpContext, XltTokenContext } from '@xlt-token/core';\n\n/**\n * 编排登录 + 权限 + 角色 + 二级认证校验。\n *\n * 与 `XltTokenGuard.canActivate` 中的权限块逻辑等价:\n * `checkLogin` 失败时抛出 `NotLoginException`,权限/角色/safe 校验失败时分别抛出对应异常。\n */\nexport async function runAuth(\n xlt: XltTokenContext,\n httpCtx: HttpContext,\n req: Request,\n): Promise<AuthResult> {\n const result = await xlt.stpLogic.checkLogin(httpCtx);\n\n const meta = req._xltRouteMeta;\n\n if (meta?.permissions && xlt.stpPermLogic) {\n await xlt.stpPermLogic.checkPermission(\n result.loginId!,\n meta.permissions.list,\n meta.permissions.mode,\n );\n }\n\n if (meta?.roles && xlt.stpPermLogic) {\n await xlt.stpPermLogic.checkRole(result.loginId!, meta.roles.list, meta.roles.mode);\n }\n\n if (meta?.safeBusiness) {\n await xlt.stpLogic.checkSafe(result.token!, meta.safeBusiness);\n }\n\n return result;\n}\n","import type { Request } from 'express';\nimport type { HttpContext } from '@xlt-token/core';\n\n/**\n * 将鉴权成功后写入 `ctx.state` 的登录态同步到 Express `req` 上。\n *\n * core 在 `_resolveLoginId` 中写入 `ctx.state.stpLoginId` / `ctx.state.stpToken`,\n * 这里对应同步到 `req.stpLoginId` / `req.stpToken`(与 NestJS Guard 字段命名一致)。\n */\nexport function syncExpressAuthState(req: Request, ctx: HttpContext): void {\n const loginId = ctx.state.stpLoginId;\n const token = ctx.state.stpToken;\n\n if (loginId != null) {\n req.stpLoginId = String(loginId);\n }\n\n if (token != null) {\n req.stpToken = String(token);\n }\n}\n","import type { NextFunction, Request, RequestHandler, Response } from 'express';\nimport type { XltTokenContext } from '@xlt-token/core';\nimport type { XltMiddlewareOptions } from '../types.js';\nimport { createExpressContext } from '../context.js';\nimport { resolveRouteAuthMeta } from '../auth/resolve-route-auth-meta.js';\nimport { shouldCheckLogin } from '../auth/should-check-login.js';\nimport { runAuth } from '../auth/run-auth.js';\nimport { syncExpressAuthState } from '../sync-state.js';\n\nexport type { XltMiddlewareOptions } from '../types.js';\n\n/**\n * 全局登录校验中间件。\n *\n * 执行流程:\n * 1. `createExpressContext(req, res)`\n * 2. `resolveRouteAuthMeta` → 写入 `req._xltRouteMeta`\n * 3. `shouldCheckLogin` 判断是否需要校验,不需要则直接放行\n * 4. `runAuth`(登录 + 权限 + 角色 + safe),成功后 `syncExpressAuthState`\n * 5. 任意异常通过 `next(err)` 交给 `xltErrorHandler`\n */\nexport function xltMiddleware(\n xlt: XltTokenContext,\n options: XltMiddlewareOptions = {},\n): RequestHandler {\n return async (req: Request, res: Response, next: NextFunction) => {\n const httpCtx = createExpressContext(req, res);\n\n req._xltRouteMeta = {\n ...req._xltRouteMeta,\n ...resolveRouteAuthMeta(req, options),\n };\n\n if (!shouldCheckLogin(req, xlt.config)) return next();\n\n try {\n await runAuth(xlt, httpCtx, req);\n syncExpressAuthState(req, httpCtx);\n next();\n } catch (err) {\n next(err);\n }\n };\n}\n","import type { RequestHandler } from 'express';\n\n/**\n * 路由级 helper:标记当前路由忽略登录校验(黑名单模式下放行)。\n *\n * 仅写入 `req._xltRouteMeta`,因此必须在同一条 route chain 中位于 `xltMiddleware` 之前才有效。\n * 推荐主路径仍是 `xltMiddleware` 的 `ignore` / `policies` 选项。\n */\nexport function ignoreAuth(): RequestHandler {\n return (req, _res, next) => {\n req._xltRouteMeta = { ...req._xltRouteMeta, ignore: true };\n next();\n };\n}\n","import type { RequestHandler } from 'express';\n\n/**\n * 路由级 helper:标记当前路由需要登录(白名单模式下开启校验)。\n *\n * 仅写入 `req._xltRouteMeta`,必须位于 `xltMiddleware` 之前才生效。\n */\nexport function requireLogin(): RequestHandler {\n return (req, _res, next) => {\n req._xltRouteMeta = { ...req._xltRouteMeta, requireLogin: true };\n next();\n };\n}\n","import type { RequestHandler } from 'express';\nimport { XltMode } from '@xlt-token/core';\n\n/**\n * 路由级 helper:声明当前路由所需权限。\n *\n * 仅写入 `req._xltRouteMeta.permissions`,必须位于 `xltMiddleware` 之前才生效。\n */\nexport function checkPermission(\n permission: string | string[],\n mode: XltMode = XltMode.AND,\n): RequestHandler {\n return (req, _res, next) => {\n const list = Array.isArray(permission) ? permission : [permission];\n req._xltRouteMeta = {\n ...req._xltRouteMeta,\n permissions: { list, mode },\n };\n next();\n };\n}\n","import type { RequestHandler } from 'express';\nimport { XltMode } from '@xlt-token/core';\n\n/**\n * 路由级 helper:声明当前路由所需角色。\n *\n * 仅写入 `req._xltRouteMeta.roles`,必须位于 `xltMiddleware` 之前才生效。\n */\nexport function checkRole(role: string | string[], mode: XltMode = XltMode.AND): RequestHandler {\n return (req, _res, next) => {\n const list = Array.isArray(role) ? role : [role];\n req._xltRouteMeta = {\n ...req._xltRouteMeta,\n roles: { list, mode },\n };\n next();\n };\n}\n","import type { RequestHandler } from 'express';\n\n/**\n * 路由级 helper:声明当前路由需要二级认证安全窗口。\n *\n * 仅写入 `req._xltRouteMeta.safeBusiness`,必须位于 `xltMiddleware` 之前才生效。\n */\nexport function checkSafe(business: string): RequestHandler {\n return (req, _res, next) => {\n req._xltRouteMeta = { ...req._xltRouteMeta, safeBusiness: business };\n next();\n };\n}\n","import {\n NotLoginException,\n NotPermissionException,\n NotRoleException,\n NotSafeException,\n} from '@xlt-token/core';\n\nexport interface MappedXltError {\n status: number;\n body: Record<string, unknown>;\n}\n\n/**\n * 将 core 鉴权异常映射为 HTTP 状态码 + JSON body。\n * 非 xlt-token 异常返回 `null`,交由调用方继续向后传递。\n */\nexport function mapXltError(err: unknown): MappedXltError | null {\n if (err instanceof NotLoginException) {\n return {\n status: 401,\n body: {\n statusCode: 401,\n code: err.code,\n type: err.type,\n message: err.message,\n token: err.token,\n },\n };\n }\n\n if (err instanceof NotPermissionException) {\n return {\n status: 403,\n body: {\n statusCode: 403,\n code: err.code,\n permission: err.permission,\n mode: err.mode,\n message: err.message,\n },\n };\n }\n\n if (err instanceof NotRoleException) {\n return {\n status: 403,\n body: {\n statusCode: 403,\n code: err.code,\n role: err.role,\n mode: err.mode,\n message: err.message,\n },\n };\n }\n\n if (err instanceof NotSafeException) {\n return {\n status: 403,\n body: {\n statusCode: 403,\n code: err.code,\n business: err.business,\n message: err.message,\n },\n };\n }\n\n return null;\n}\n","import type { ErrorRequestHandler } from 'express';\nimport { mapXltError } from './map-xlt-error.js';\n\n/**\n * 四参数 Express 错误中间件,挂在路由链末尾,将 core 鉴权异常转为 401/403 JSON。\n * 非 xlt-token 异常透传给下一个错误处理器。\n *\n * @example\n * app.use(xltErrorHandler());\n */\nexport function xltErrorHandler(): ErrorRequestHandler {\n return (err, _req, res, next) => {\n const mapped = mapXltError(err);\n if (!mapped) {\n next(err);\n return;\n }\n res.status(mapped.status).json(mapped.body);\n };\n}\n"],"mappings":"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"}
package/package.json ADDED
@@ -0,0 +1,69 @@
1
+ {
2
+ "name": "@xlt-token/express",
3
+ "version": "1.0.0",
4
+ "description": "Express middleware adapter for xlt-token",
5
+ "keywords": [
6
+ "express",
7
+ "token",
8
+ "auth",
9
+ "session",
10
+ "xlt-token"
11
+ ],
12
+ "author": "xltorg",
13
+ "license": "MIT",
14
+ "repository": {
15
+ "type": "git",
16
+ "url": "git+https://github.com/xiaoLangtou/xlt-token.git",
17
+ "directory": "packages/express"
18
+ },
19
+ "bugs": {
20
+ "url": "https://github.com/xiaoLangtou/xlt-token/issues"
21
+ },
22
+ "homepage": "https://xiaolangtou.github.io/xlt-token/",
23
+ "publishConfig": {
24
+ "access": "public"
25
+ },
26
+ "type": "module",
27
+ "exports": {
28
+ ".": {
29
+ "import": "./dist/index.mjs",
30
+ "require": "./dist/index.cjs"
31
+ },
32
+ "./package.json": "./package.json"
33
+ },
34
+ "main": "./dist/index.cjs",
35
+ "module": "./dist/index.mjs",
36
+ "types": "./dist/index.d.cts",
37
+ "sideEffects": false,
38
+ "files": [
39
+ "dist",
40
+ "LICENSE",
41
+ "README.md"
42
+ ],
43
+ "scripts": {
44
+ "build": "tsdown",
45
+ "build:watch": "tsdown --watch",
46
+ "prepublishOnly": "pnpm run build",
47
+ "test": "vitest run",
48
+ "test:cov": "vitest run --coverage",
49
+ "test:e2e": "vitest run --config vitest.e2e.config.ts",
50
+ "test:e2e:cov": "vitest run --config vitest.e2e.config.ts --coverage"
51
+ },
52
+ "peerDependencies": {
53
+ "express": "^4.18.0 || ^5.0.0"
54
+ },
55
+ "dependencies": {
56
+ "@xlt-token/core": "workspace:*"
57
+ },
58
+ "devDependencies": {
59
+ "@types/express": "^4.17.21",
60
+ "@types/node": "^20.0.0",
61
+ "@types/supertest": "^7.2.0",
62
+ "@vitest/coverage-v8": "^2.1.9",
63
+ "express": "^4.22.0",
64
+ "supertest": "^7.2.2",
65
+ "tsdown": "^0.20.0",
66
+ "typescript": "^5.1.0",
67
+ "vitest": "^2.0.0"
68
+ }
69
+ }