Bknd调试Skill bknd-debugging

此技能用于诊断和解决Bknd框架的常见问题,包括使用CLI工具调试、分析HTTP错误代码、检查日志和系统故障排除。关键词:Bknd、调试、CLI命令、HTTP错误、故障排除、日志分析、后端开发。

后端开发 0 次安装 0 次浏览 更新于 3/8/2026

name: bknd-debugging description: 用于排查Bknd问题、调试错误、修复常见问题或诊断为何某事不工作。覆盖CLI调试命令、错误代码、日志、常见问题和解决方案。

调试常见问题

使用CLI工具、错误分析和系统故障排除来诊断和修复Bknd常见问题。

先决条件

  • Bknd项目在本地设置完成
  • 终端/命令行访问权限
  • 对HTTP状态码有基本理解

何时使用UI模式

  • 在管理面板(/admin)中检查数据
  • 可视化验证实体模式
  • 手动测试CRUD操作
  • 检查用户/角色配置

何时使用代码模式

  • 运行调试CLI命令
  • 分析API响应错误
  • 检查路由注册
  • 检查配置路径
  • 查看服务器日志

CLI调试命令

显示所有注册的路由

npx bknd debug routes

输出显示每个HTTP端点:

  • API路由(/api/data/*/api/auth/*/api/media/*
  • 管理路由(/admin/*
  • 自定义Flow HTTP触发器
  • 插件路由

使用时机:端点返回404,验证自定义路由是否注册。

显示内部路径

npx bknd debug paths

输出:

[PATHS] {
  rootpath: '/path/to/bknd',
  distPath: '/path/to/dist',
  relativeDistPath: './dist',
  cwd: '/your/project',
  dir: '/path/to/cli',
  resolvedPkg: '/path/to/package.json'
}

使用时机:配置文件未加载,路径解析问题。

CLI帮助

npx bknd --help
npx bknd run --help
npx bknd types --help

HTTP错误代码

代码 含义 常见原因
400 错误请求 无效JSON、缺少必需字段、验证错误
401 未授权 缺少/无效/过期的令牌
403 禁止访问 有效令牌但权限不足
404 未找到 错误端点、实体不存在、记录未找到
409 冲突 重复唯一字段、用户已存在
413 负载过大 文件上传超过body_max_size
500 服务器错误 未处理的异常、数据库错误

常见问题与解决方案

配置文件未加载

症状: “配置文件无法解析”错误

诊断:

# 检查配置是否存在
ls bknd.config.*

# 检查当前目录
pwd

# 检查Bknd看到的路径
npx bknd debug paths

解决方案:

# 确保正确扩展名
mv bknd.config.js bknd.config.ts

# 显式指定
npx bknd run -c ./bknd.config.ts

# 检查支持的扩展名:.ts、.js、.mjs、.cjs、.json

数据库未持久化

症状: 服务器重启后数据消失

诊断:

# 检查是否使用内存模式
# 在启动输出中查找“使用内存模式”
npx bknd run

# 检查数据库文件
ls *.db

解决方案:

# 使用基于文件的数据库
npx bknd run --db-url "file:data.db"

# 不要使用内存模式
npx bknd run --memory  # 数据会丢失!

# 在配置中验证:
# connection: { url: "file:data.db" }  ✓
# connection: { url: ":memory:" }      ✗

端口已被占用

症状: EADDRINUSE: 地址已被使用

诊断:

# 查找使用端口的进程
lsof -i :3000

# 或在Windows上
netstat -ano | findstr :3000

解决方案:

# 使用不同端口
npx bknd run --port 3001

# 终止现有进程
kill -9 <PID>

# 或在Windows上
taskkill /PID <PID> /F

身份验证不起作用

症状: 401错误、令牌未持久化、用户始终为null

诊断:

# 测试登录端点
curl -X POST http://localhost:3000/api/auth/password/login \
  -H "Content-Type: application/json" \
  -d '{"email":"test@example.com","password":"password"}'

# 检查身份验证配置
# 在响应错误中查找“策略”

解决方案:

  1. 身份验证未启用:
export default {
  app: {
    auth: { enabled: true },  // 必需!
  }
}
  1. 错误策略路径:
# 密码身份验证端点:
POST /api/auth/password/login    # ✓
POST /api/auth/login             # ✗ 404
  1. JWT密钥未设置(生产环境):
auth: {
  jwt: {
    secret: process.env.JWT_SECRET,  // 生产环境必需
  }
}
  1. Cookie未设置(CORS):
auth: {
  cookie: {
    secure: false,     // 仅对HTTPS设置为true
    sameSite: "lax",   // 不要设为“strict”以支持OAuth
  }
}
  1. 令牌未持久化(前端):
const api = new Api({
  host: "http://localhost:3000",
  storage: localStorage,  // 令牌持久化必需
});

权限被拒绝(403)

症状: 有效令牌但403禁止访问

诊断:

# 检查用户的角色
curl http://localhost:3000/api/auth/me \
  -H "Authorization: Bearer <token>"

# 检查配置中的角色权限

解决方案:

  1. 防护未启用:
export default {
  app: {
    auth: {
      guard: { enabled: true },  // 权限必需
    }
  }
}
  1. 无默认角色(匿名访问):
auth: {
  guard: {
    roles: {
      anonymous: {
        is_default: true,  // 允许未身份验证访问
        permissions: ["data.entity.read"],
      }
    }
  }
}
  1. 角色缺少权限:
roles: {
  user: {
    permissions: [
      "data.entity.read",
      "data.entity.create",  // 如果需要则添加
    ]
  }
}
  1. 需要实体特定权限:
permissions: [
  { permission: "data.entity.read", entity: "posts" },
]

实体/记录未找到(404)

症状: 数据端点返回404

诊断:

# 列出所有实体
curl http://localhost:3000/api/data

# 检查实体名称(区分大小写)
curl http://localhost:3000/api/data/Posts    # ✗
curl http://localhost:3000/api/data/posts    # ✓

# 验证路由
npx bknd debug routes | grep data

解决方案:

  1. 模式未同步:
# 重启服务器以同步模式
npx bknd run
  1. 实体名称大小写不匹配:
// 模式定义小写
entity("posts", { ... })

// API调用必须完全匹配
api.data.readMany("posts");     // ✓
api.data.readMany("Posts");     // ✗ 404
  1. 记录不存在:
const result = await api.data.readOne("posts", 999);
if (!result.ok) {
  console.log("未找到:", result.status);  // 404
}

使用em()时的类型错误

症状: 使用模式对象时的TypeScript错误

问题: em()返回模式定义,而非可查询的EntityManager。

// 错误 - 这会失败
const schema = em({
  posts: entity("posts", { title: text() }),
});
schema.repo("posts").find();  // ✗ 错误!

// 正确 - 使用SDK进行查询
const api = new Api({ url: "http://localhost:3000" });
await api.data.readMany("posts");  // ✓

对于直接数据库访问(仅服务器端):

const app = new App(config);
await app.build();
const posts = await app.em.repo("posts").findMany();  // ✓

模式同步问题

症状: 实体在代码中但不在数据库中,或反之

诊断:

# 检查管理面板 -> 模式视图
# 或直接查询
curl http://localhost:3000/api/system/schema

解决方案:

  1. 重启服务器 - 模式在启动时同步:
npx bknd run
  1. 强制同步(可能丢失数据):
options: {
  sync: {
    force: true,  // 危险!可能删除表
  }
}
  1. 检查模式 - 数据库模式忽略代码模式:
// 代码模式(默认) - 模式来自代码
mode: "code"

// 混合模式 - 合并代码和数据库
mode: "hybrid"

文件上传失败

症状: 413错误,上传静默失败

诊断:

# 检查文件大小
ls -la myfile.jpg

# 测试上传
curl -X POST http://localhost:3000/api/media/upload \
  -H "Authorization: Bearer <token>" \
  -F "file=@myfile.jpg"

解决方案:

  1. 文件过大:
media: {
  body_max_size: 10 * 1024 * 1024,  // 10MB
}
  1. 存储未配置:
media: {
  adapter: {
    type: "s3",
    // ... S3配置
  }
}
  1. 本地存储(仅开发):
import { registerLocalMediaAdapter } from "bknd/adapter/node";
const local = registerLocalMediaAdapter();

export default {
  app: {
    media: { adapter: local }
  }
}

CORS错误

症状: 浏览器控制台中的“Access-Control-Allow-Origin”错误

诊断:

# 检查CORS头部
curl -I http://localhost:3000/api/data/posts \
  -H "Origin: http://localhost:5173"

解决方案:

export default {
  app: {
    server: {
      cors: {
        origin: ["http://localhost:5173", "https://myapp.com"],
        credentials: true,  // 用于Cookie
      }
    }
  }
}

用于开发(允许所有):

server: {
  cors: {
    origin: "*",
  }
}

无头环境崩溃

症状: 无显示服务器上的spawn xdg-open ENOENT

解决方案:

npx bknd run --no-open

Windows ESM错误

症状: Windows上的ERR_UNSUPPORTED_ESM_URL_SCHEME

解决方案:

  1. 使用Node.js 18+
  2. 确保package.json中有"type": "module"
  3. 配置使用.mjs扩展名

TypeScript类型未更新

症状: IDE显示旧类型,自动完成错误

解决方案:

# 重新生成类型
npx bknd types

# 重启TypeScript服务器(VS Code)
# Cmd/Ctrl + Shift + P -> "TypeScript: Restart TS Server"

# 清除缓存
rm -rf node_modules/.cache

调试脚本模式

创建一个调试助手以进行系统故障排除:

// debug.ts
import { Api } from "bknd/client";

async function debug() {
  const api = new Api({ host: "http://localhost:3000" });

  // 1. 检查服务器健康状态
  console.log("=== 健康检查 ===");
  const entities = await fetch("http://localhost:3000/api/data");
  console.log("状态:", entities.status);
  console.log("实体:", await entities.json());

  // 2. 检查身份验证
  console.log("
=== 身份验证检查 ===");
  const me = await api.auth.me();
  console.log("身份验证状态:", me.ok ? "已验证" : "未验证");
  if (me.data) console.log("用户:", me.data);

  // 3. 检查模式
  console.log("
=== 模式检查 ===");
  const schema = await fetch("http://localhost:3000/api/system/schema");
  console.log("模式:", await schema.json());

  // 4. 测试实体访问
  console.log("
=== 实体访问 ===");
  const posts = await api.data.readMany("posts", { limit: 1 });
  console.log("帖子访问:", posts.ok ? "成功" : `失败(${posts.status})`);
}

debug().catch(console.error);

运行:

npx tsx debug.ts

日志模式

服务器端日志

// 在种子函数或插件中
options: {
  seed: async (ctx) => {
    console.log("[SEED] 启动中...");
    console.log("[SEED] 实体:", Object.keys(ctx.em.entities));

    try {
      await ctx.em.mutator("posts").insertOne({ title: "测试" });
      console.log("[SEED] 创建帖子");
    } catch (e) {
      console.error("[SEED] 错误:", e);
    }
  }
}

API响应日志

const api = new Api({
  host: "http://localhost:3000",
  verbose: true,  // 记录所有请求/响应
});

// 或手动日志
const result = await api.data.readMany("posts");
console.log("请求结果:", {
  ok: result.ok,
  status: result.status,
  data: result.data,
  error: result.error,
});

带日志的自定义Fetcher

const api = new Api({
  host: "http://localhost:3000",
  fetcher: async (url, options) => {
    console.log("→", options?.method || "GET", url);
    const start = Date.now();
    const response = await fetch(url, options);
    console.log("←", response.status, `(${Date.now() - start}ms)`);
    return response;
  },
});

Flow/任务调试

HTTP触发器错误

同步模式在响应中返回错误:

{
  "success": false,
  "errors": [
    {
      "task": "fetchUser",
      "error": "Failed to fetch user: 404 Not Found",
      "timestamp": "2024-01-15T10:30:00Z"
    }
  ]
}

任务错误处理

import { Task, Condition } from "bknd/flows";

const flow = new Flow("myFlow", [
  mainTask,
  errorTask.connect(mainTask, Condition.error()),  // 处理错误
]);

验证清单

调试时按顺序检查这些:

  1. 服务器在运行吗?

    curl http://localhost:3000/api/data
    
  2. 配置加载了吗?

    • 在启动日志中检查“从…使用配置”
  3. 模式同步了吗?

    • 检查管理面板或/api/system/schema
  4. 身份验证启用了吗?(如果需要)

    • 检查配置中的auth: { enabled: true }
  5. 权限设置了吗?(如果403)

    • 检查guard: { enabled: true }和角色
  6. CORS配置了吗?(如果浏览器错误)

    • 检查server: { cors: {...} }

应该做与不应该做

应该做:

  • 首先检查服务器日志
  • 使用npx bknd debug routes处理404
  • 验证实体名称完全匹配(区分大小写)
  • 在调试前端之前用curl测试
  • 在Api中使用verbose: true进行请求日志
  • 模式更改后重启服务器

不应该做:

  • 假设em()返回可查询的EntityManager
  • 在无头服务器上忘记--no-open
  • 使用:memory:数据库处理持久数据
  • 在响应中跳过检查HTTP状态码
  • 调试前端问题时忽略CORS
  • 在生产环境中使用sync: { force: true }

相关技能

  • bknd-local-setup - 初始项目设置
  • bknd-env-config - 环境变量配置
  • bknd-setup-auth - 身份验证配置
  • bknd-assign-permissions - 权限故障排除
  • bknd-api-discovery - 探索可用端点