Skip to content

Conversation

@TechQuery
Copy link
Member

@TechQuery TechQuery commented Dec 28, 2025

PR-43 PR-43 PR-43 Powered by Pull Request Badge

  1. [add] Markdown export & Document copy API of Lark documents
  2. [add] JWT parser & verifier middlewares
  3. [optimize] update Upstream packages
  4. [migrate] upgrade Lark notification to Interactive Card

Summary by CodeRabbit

发行说明

  • 新功能

    • 新增文档复制功能
    • 新增Markdown内容下载支持
    • 实施JWT令牌认证机制
  • 改进

    • 优化API错误处理和响应机制
    • 简化文件处理逻辑,提升性能

✏️ Tip: You can customize this high-level summary in your review settings.

[add] JWT parser & verifier middlewares
[optimize] update Upstream packages
@coderabbitai
Copy link

coderabbitai bot commented Dec 28, 2025

📝 Walkthrough

功能概览

本次提交新增两个 Lark 文档 API 端点(复制、Markdown 下载)并重构核心 API 中间件,引入 JWT 认证工具,改进错误处理机制,优化前置物质解析逻辑,约涉及 4 个文件的新增与修改。

变更汇总

队列 / 文件 变更概述
新增 API 端点
pages/api/Lark/document/copy/[...slug].ts
POST 端点处理文档复制请求,通过 lark.copyFile 执行操作,禁用默认 body 解析器,强制 JWT 验证
新增 API 端点
pages/api/Lark/document/markdown/[...slug].ts
GET 端点提供 Markdown 内容下载,返回 text/markdown 格式响应,同样受 JWT 保护
错误处理增强
pages/api/Lark/file/[id]/[name].ts
上游响应失败时尝试 JSON 解析,降级到原文本响应;成功路径简化为三元条件赋值
核心中间件重构
pages/api/core.ts
新增 JWTContext 类型与 parseJWTverifyJWT 中间件;替换 YAML 前置物质解析为原生 parse();重构 pageListOf 文件遍历逻辑,优化路径计算与目录处理

代码审查工作量评估

🎯 3 (中等复杂度) | ⏱️ ~20 分钟

关键审查点:

  • JWT 中间件的秘钥配置与 Cookie 字段映射正确性
  • 新端点的类型约束完整性(参数类型、响应类型)
  • pageListOf 重构后的路径计算逻辑是否保持与原有行为一致
  • 前置物质解析降级的 YAML → 原生 parse 兼容性
  • 错误响应的 JSON 降级到文本的容错策略是否覆盖所有边界情况

新路由添,双端欲就,

JWT守关,中间件妙。

前物解析轻,路径智更明,

错误处理稳,API 心舒坦。✨

Pre-merge checks and finishing touches

❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. You can run @coderabbitai generate docstrings to improve docstring coverage.
✅ Passed checks (2 passed)
Check name Status Explanation
Title check ✅ Passed 标题准确概括了拉克文档的两个主要新功能:Markdown 导出和文档复制 API,与变更集的核心内容相符。
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch Lark-document-API

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@dosubot
Copy link

dosubot bot commented Dec 28, 2025

Related Documentation

Checked 10 published document(s) in 1 knowledge base(s). No updates required.

How did I do? Any feedback?  Join Discord

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

🧹 Nitpick comments (1)
pages/api/core.ts (1)

108-109: ReDoS 风险较低,但建议使用字符串方法替代正则

静态分析工具标记了从变量构造正则表达式的潜在 ReDoS 风险。虽然在当前场景下 prefix 是受控的(默认为 'pages'),但使用字符串方法更安全且性能更好。

🔎 建议使用 startsWith + slice 替代正则
-    const path = `${parentPath}/${name}`.replace(new RegExp(`^${prefix}`), '');
+    const fullPath = `${parentPath}/${name}`;
+    const path = fullPath.startsWith(prefix) ? fullPath.slice(prefix.length) : fullPath;
📜 Review details

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 41801f8 and 4825d1a.

⛔ Files ignored due to path filters (2)
  • package.json is excluded by none and included by none
  • pnpm-lock.yaml is excluded by !**/pnpm-lock.yaml, !pnpm-lock.yaml and included by none
📒 Files selected for processing (4)
  • pages/api/Lark/document/copy/[...slug].ts
  • pages/api/Lark/document/markdown/[...slug].ts
  • pages/api/Lark/file/[id]/[name].ts
  • pages/api/core.ts
🧰 Additional context used
📓 Path-based instructions (3)
{models,pages/api}/**/*.ts

📄 CodeRabbit inference engine (.github/copilot-instructions.md)

Import and use the configured githubClient from models/Base.ts; do not create new GitHub API instances

Files:

  • pages/api/Lark/document/copy/[...slug].ts
  • pages/api/Lark/file/[id]/[name].ts
  • pages/api/Lark/document/markdown/[...slug].ts
  • pages/api/core.ts
{models,pages/api}/**/*.{ts,tsx}

📄 CodeRabbit inference engine (.github/copilot-instructions.md)

Decode Base64 GitHub content using atob(item.content) when processing responses

Files:

  • pages/api/Lark/document/copy/[...slug].ts
  • pages/api/Lark/file/[id]/[name].ts
  • pages/api/Lark/document/markdown/[...slug].ts
  • pages/api/core.ts
**/*.{ts,tsx}

📄 CodeRabbit inference engine (.github/copilot-instructions.md)

**/*.{ts,tsx}: Use optional chaining and modern ECMAScript features
Let TypeScript infer types when possible to avoid verbose annotations
Import from established sources (e.g., ContentModel from mobx-github, utilities from web-utility) rather than reimplementing
Use minimal exports and avoid unnecessary custom implementations

Files:

  • pages/api/Lark/document/copy/[...slug].ts
  • pages/api/Lark/file/[id]/[name].ts
  • pages/api/Lark/document/markdown/[...slug].ts
  • pages/api/core.ts
🧬 Code graph analysis (1)
pages/api/core.ts (1)
models/configuration.ts (2)
  • process (9-9)
  • LarkAppMeta (27-31)
🪛 ast-grep (0.40.3)
pages/api/core.ts

[warning] 108-108: Regular expression constructed from variable input detected. This can lead to Regular Expression Denial of Service (ReDoS) attacks if the variable contains malicious patterns. Use libraries like 'recheck' to validate regex safety or use static patterns.
Context: new RegExp(^${prefix})
Note: [CWE-1333] Inefficient Regular Expression Complexity [REFERENCES]
- https://owasp.org/www-community/attacks/Regular_expression_Denial_of_Service_-_ReDoS
- https://cwe.mitre.org/data/definitions/1333.html

(regexp-from-variable)

⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
  • GitHub Check: Build-and-Deploy
🔇 Additional comments (7)
pages/api/core.ts (3)

19-29: JWT 中间件配置清晰,结构合理

parseJWT(带 passthrough: true)和 verifyJWT 的分离设计很好:

  • parseJWT 用于可选认证场景,即使 Token 无效也会继续执行
  • verifyJWT 用于强制认证场景

TypeScript 类型 JWTContext 正确地使用了联合类型来表示两种可能的状态。


111-127: pageListOf 重构逻辑清晰

重构后的逻辑更加简洁:

  • 只处理 MDX 文件并附加 meta
  • 目录只在有子项时才 yield
  • 使用 Array.fromAsync 替代手动收集

整体结构和可读性有明显提升。


102-102: parentPath 与项目 Node.js 版本完全兼容

项目已升级至 Node.js 22,Dirent.parentPath 属性(Node.js 18.17.0+ 支持)在当前版本完全兼容,无需调整。

pages/api/Lark/file/[id]/[name].ts (2)

33-37: 错误响应处理改进合理

先尝试解析 JSON,失败时回退到纯文本,这种处理方式更加健壮。能够正确处理 Lark API 返回的各种错误格式。


50-51: 响应体赋值简化清晰

使用三元表达式统一处理 GET 和 HEAD 请求,代码更简洁。@ts-expect-error 用于 Web Stream 与 Node.js Stream 的类型兼容性是合理的临时方案。

pages/api/Lark/document/markdown/[...slug].ts (1)

8-15: 新路由结构清晰,中间件使用正确

路由正确使用了 safeAPIverifyJWT 中间件进行错误处理和认证保护。Content-Type 设置正确包含了 charset。

建议可选:对 type 参数进行校验,确保只接受合法的文档类型(如 'docx''wiki' 等)。

🔎 可选:添加类型校验
 router.get('/:type/:id', safeAPI, verifyJWT, async context => {
   const { type, id } = context.params;
+
+  const validTypes = ['docx', 'wiki', 'sheet', 'bitable'];
+  if (!validTypes.includes(type)) {
+    context.status = 400;
+    context.body = { message: `Invalid document type: ${type}` };
+    return;
+  }

   const markdown = await lark.downloadMarkdown(`${type}/${id}`);
pages/api/Lark/document/copy/[...slug].ts (1)

7-7: bodyParser 禁用配置正确

由于使用 Koa 中间件处理请求体,正确禁用了 Next.js 默认的 body parser。

Comment on lines +11 to +16
router.post('/:type/:id', safeAPI, verifyJWT, async (context: Context) => {
const { type, id } = context.params,
{ name, parentToken } = Reflect.get(context.request, 'body');

context.body = await lark.copyFile(`${type as 'wiki'}/${id}`, name, parentToken);
});
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

类型安全问题:建议改进请求体访问方式

使用 Reflect.get(context.request, 'body') 绕过类型检查不是最佳实践。另外,type as 'wiki' 的强制类型断言可能导致运行时错误。

🔎 建议:添加类型定义和输入校验
+interface CopyRequestBody {
+  name: string;
+  parentToken: string;
+}
+
+type DocumentType = 'wiki' | 'docx';
+
 router.post('/:type/:id', safeAPI, verifyJWT, async (context: Context) => {
-  const { type, id } = context.params,
-    { name, parentToken } = Reflect.get(context.request, 'body');
+  const { type, id } = context.params;
+  const body = (context.request as any).body as CopyRequestBody;
+
+  if (!body?.name || !body?.parentToken) {
+    context.status = 400;
+    context.body = { message: 'Missing required fields: name, parentToken' };
+    return;
+  }
+
+  const validTypes: DocumentType[] = ['wiki', 'docx'];
+  if (!validTypes.includes(type as DocumentType)) {
+    context.status = 400;
+    context.body = { message: `Invalid document type: ${type}` };
+    return;
+  }

-  context.body = await lark.copyFile(`${type as 'wiki'}/${id}`, name, parentToken);
+  context.body = await lark.copyFile(`${type}/${id}`, body.name, body.parentToken);
 });
🤖 Prompt for AI Agents
In pages/api/Lark/document/copy/[...slug].ts around lines 11 to 16, the handler
uses Reflect.get(context.request, 'body') and a forced assertion type as 'wiki',
which bypasses type safety and can cause runtime errors; replace this with a
strongly typed request body interface (e.g., interface CopyRequest { name:
string; parentToken?: string }), parse and validate the body using the
framework's request body API into that type, validate required fields (name) and
that context.params.type is one of the allowed values (e.g., 'wiki') before
calling lark.copyFile, and return a 4xx error if validation fails instead of
using a blind type assertion.

@TechQuery TechQuery added the feature New feature or request label Dec 29, 2025
@TechQuery TechQuery merged commit 250884f into main Dec 29, 2025
5 of 6 checks passed
@TechQuery TechQuery deleted the Lark-document-API branch December 29, 2025 00:06
@github-project-automation github-project-automation bot moved this from Ready to Done in 官网项目群 Dec 29, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

feature New feature or request

Projects

Status: Done

Development

Successfully merging this pull request may close these issues.

2 participants