{"_id":"@aqcq/express-reply","_rev":"10-ce06399120e810a1ac241b52373f095d","name":"@aqcq/express-reply","dist-tags":{"latest":"0.2.1"},"versions":{"0.0.1":{"name":"@aqcq/express-reply","version":"0.0.1","keywords":["aqcq","express","reply","middleware","express-reply"],"license":"MIT","_id":"@aqcq/express-reply@0.0.1","maintainers":[{"name":"penghuteng","email":"penghuteng@hotmail.com"}],"dist":{"shasum":"b4f4d101dfc628cb4bcf55ebda91086bf985e58c","tarball":"https://registry.npmjs.org/@aqcq/express-reply/-/express-reply-0.0.1.tgz","fileCount":9,"integrity":"sha512-RGFCZPPJjgIYO9hWx7+OIzEwqAafnGFcMWQI+WxE1TLz4ftjs/mpU+fGoZt38DAEoGjqeuAMfQNGLA2DSAHDfA==","signatures":[{"sig":"MEUCIQD/cqKgKpobsB6t8Ui4pmyVQc4pRNjgzKKqX0p1ftJVFgIgGxyeRmLQDf9DzRvMHbYqLPC/QzanzSBXLqfEYMIsXDs=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":35865},"main":"dist/index.js","types":"dist/index.d.ts","module":"dist/index.mjs","exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.mjs","require":"./dist/index.js"}},"gitHead":"a59948a1521f1491c2021c9ac88786cef5725d0e","scripts":{"build":"tsup src/index.ts --format cjs,esm --dts --clean && cp src/types.d.ts dist/types.d.ts"},"_npmUser":{"name":"penghuteng","email":"penghuteng@hotmail.com"},"_npmVersion":"10.9.2","description":"Express Reply middleware","directories":{},"_nodeVersion":"22.13.0","dependencies":{"express":"^5.1.0"},"publishConfig":{"access":"public","registry":"https://registry.npmjs.org"},"_hasShrinkwrap":false,"devDependencies":{"tsup":"^8.5.0","@types/express":"^5.0.2"},"_npmOperationalInternal":{"tmp":"tmp/express-reply_0.0.1_1749021998129_0.6085008268306142","host":"s3://npm-registry-packages-npm-production"}},"0.0.3":{"name":"@aqcq/express-reply","version":"0.0.3","keywords":["aqcq","express","reply","middleware","express-reply"],"license":"MIT","_id":"@aqcq/express-reply@0.0.3","maintainers":[{"name":"penghuteng","email":"penghuteng@hotmail.com"}],"dist":{"shasum":"a8be5d083ec4586528f8ac8658283531c3e87b7d","tarball":"https://registry.npmjs.org/@aqcq/express-reply/-/express-reply-0.0.3.tgz","fileCount":8,"integrity":"sha512-59JSd1dlqLHk+cntZlU2ENpqTCu/4xx32BMICw7ho7htv8Qs2wP7fTySwvzpRs3h52IBtkWGRfG7myhqv4v/Xw==","signatures":[{"sig":"MEUCIQDtMapHgDTcD2u0YfHtHJ18aP4WKW3dYDOoeX8c8MhcGgIgCelyHUthPRgHjn20+30K8WxmYKENXh4/mxv/ksuGnaw=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":36402},"main":"dist/index.js","types":"dist/index.d.ts","module":"dist/index.mjs","exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.mjs","require":"./dist/index.js"}},"gitHead":"435fc5002090c86ad456f6194b7844c8578115dc","scripts":{"build":"tsup src/index.ts --format cjs,esm --dts --clean"},"_npmUser":{"name":"penghuteng","email":"penghuteng@hotmail.com"},"_npmVersion":"10.9.2","description":"Express Reply middleware","directories":{},"_nodeVersion":"22.13.0","dependencies":{"express":"^5.1.0"},"publishConfig":{"access":"public","registry":"https://registry.npmjs.org"},"_hasShrinkwrap":false,"devDependencies":{"tsup":"^8.5.0","@types/express":"^5.0.2"},"_npmOperationalInternal":{"tmp":"tmp/express-reply_0.0.3_1749022964366_0.07627969237278953","host":"s3://npm-registry-packages-npm-production"}},"0.1.0":{"name":"@aqcq/express-reply","version":"0.1.0","keywords":["aqcq","express","reply","middleware","express-reply"],"license":"MIT","_id":"@aqcq/express-reply@0.1.0","maintainers":[{"name":"penghuteng","email":"penghuteng@hotmail.com"}],"dist":{"shasum":"e4acd19a1694d298b96340af01ca981c65d06087","tarball":"https://registry.npmjs.org/@aqcq/express-reply/-/express-reply-0.1.0.tgz","fileCount":8,"integrity":"sha512-Cyu49YJJ0hRTMUMAn6SQCW8U1A2aDKbL90v+8RFUNMXer8FXv0llqV86Y6NIU+Y9zAZwMBGy6BtP+3BGD8fPQA==","signatures":[{"sig":"MEUCIGcu+0MmQ8rABdmh56bjFjsKNYiJ8/4zhOTLuu3a/oF4AiEA8qi3ze+tQ3BDvWyOQNnHz7QHttXJc7qRrezf6DUJmK0=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":36402},"main":"dist/index.js","types":"dist/index.d.ts","module":"dist/index.mjs","exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.mjs","require":"./dist/index.js"}},"gitHead":"0d972ac728d7d38594fc94dabdff5e9715a3c0e5","scripts":{"build":"tsup src/index.ts --format cjs,esm --dts --clean"},"_npmUser":{"name":"penghuteng","email":"penghuteng@hotmail.com"},"_npmVersion":"10.9.2","description":"Express Reply middleware","directories":{},"_nodeVersion":"22.13.0","dependencies":{"express":"^5.1.0"},"publishConfig":{"access":"public","registry":"https://registry.npmjs.org"},"_hasShrinkwrap":false,"devDependencies":{"tsup":"^8.5.0","@types/express":"^5.0.2"},"_npmOperationalInternal":{"tmp":"tmp/express-reply_0.1.0_1749181186448_0.3145840752725846","host":"s3://npm-registry-packages-npm-production"}},"0.1.1":{"name":"@aqcq/express-reply","version":"0.1.1","keywords":["aqcq","express","reply","middleware","express-reply"],"license":"MIT","_id":"@aqcq/express-reply@0.1.1","maintainers":[{"name":"penghuteng","email":"penghuteng@hotmail.com"}],"dist":{"shasum":"716ae918494c4fc0e575bece02013e9464da322f","tarball":"https://registry.npmjs.org/@aqcq/express-reply/-/express-reply-0.1.1.tgz","fileCount":8,"integrity":"sha512-42B50LtskzQnEr0k5b89XZAucmIvuGdNW/mfKSLIOAcesIA5EaL6/imS7VFjGL00nQWKSGjXjNAoRNVKaRrJgg==","signatures":[{"sig":"MEQCIBSU+PC0nOOh1XEH4tjomEx/O1dP+H1gUorpgW07IZnLAiBfg2Z/nCQj2cZX6F9JjOzMgxePjRvVuMCCgMrAWUe7Sw==","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":36993},"main":"dist/index.js","types":"dist/index.d.ts","module":"dist/index.mjs","exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.mjs","require":"./dist/index.js"}},"gitHead":"40ce8747c5ec5bb5b55a26b5276922a7cf12699b","scripts":{"build":"tsup src/index.ts --format cjs,esm --dts --clean"},"_npmUser":{"name":"penghuteng","email":"penghuteng@hotmail.com"},"_npmVersion":"10.9.2","description":"Express Reply middleware","directories":{},"_nodeVersion":"22.13.0","dependencies":{"express":"^5.1.0"},"publishConfig":{"access":"public","registry":"https://registry.npmjs.org"},"_hasShrinkwrap":false,"devDependencies":{"tsup":"^8.5.0","@types/express":"^5.0.2"},"_npmOperationalInternal":{"tmp":"tmp/express-reply_0.1.1_1749182786911_0.37053545121336784","host":"s3://npm-registry-packages-npm-production"}},"0.1.2":{"name":"@aqcq/express-reply","version":"0.1.2","keywords":["aqcq","express","reply","middleware","express-reply"],"license":"MIT","_id":"@aqcq/express-reply@0.1.2","maintainers":[{"name":"penghuteng","email":"penghuteng@hotmail.com"}],"dist":{"shasum":"ebf6047616382410e72862c0e95943f4b6fa7f1b","tarball":"https://registry.npmjs.org/@aqcq/express-reply/-/express-reply-0.1.2.tgz","fileCount":8,"integrity":"sha512-ewqflVICRSMLCG+OnZrDXTYC62g5a+d71Rlqzu0vvyM/X+JzIv6C0HvgEm55PcTCfYHcqsHFBWytEG9yjjXaFw==","signatures":[{"sig":"MEUCIQC8io+dXC3WRmq7qrkepKtTS/dYCWO2kl68wCod5EYxrwIgXtjrC2WGRS/PFV9HbmRPkf1nDdl3/T5y/NhxtrdeSWI=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":45955},"main":"dist/index.js","types":"dist/index.d.ts","module":"dist/index.mjs","exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.mjs","require":"./dist/index.js"}},"gitHead":"40ce8747c5ec5bb5b55a26b5276922a7cf12699b","scripts":{"build":"tsup src/index.ts --format cjs,esm --dts --clean"},"_npmUser":{"name":"penghuteng","email":"penghuteng@hotmail.com"},"_npmVersion":"10.9.2","description":"Express Reply middleware","directories":{},"_nodeVersion":"22.13.0","dependencies":{"express":"^5.1.0"},"publishConfig":{"access":"public","registry":"https://registry.npmjs.org"},"_hasShrinkwrap":false,"devDependencies":{"tsup":"^8.5.0","@types/express":"^5.0.2"},"_npmOperationalInternal":{"tmp":"tmp/express-reply_0.1.2_1749191566337_0.055448420778527074","host":"s3://npm-registry-packages-npm-production"}},"0.1.3":{"name":"@aqcq/express-reply","version":"0.1.3","keywords":["aqcq","express","reply","middleware","express-reply"],"license":"MIT","_id":"@aqcq/express-reply@0.1.3","maintainers":[{"name":"penghuteng","email":"penghuteng@hotmail.com"}],"dist":{"shasum":"a20a34be8b73017d7842bad2865e384b344ef00e","tarball":"https://registry.npmjs.org/@aqcq/express-reply/-/express-reply-0.1.3.tgz","fileCount":8,"integrity":"sha512-UccXgrwsaSwYPpPZauw438SvEL2aG5tGRTdehYrbQUTwpO/UJQA0xYQdwY5Sx0I7bhUvzKHTpLwgtbyX+tVowQ==","signatures":[{"sig":"MEUCIEeoxXyz9m3UDTWvnxe/itjdtNFzhO+AXXE+u24T4bWpAiEAx1wl3W7CZNBiDuIM7WIPfP0mH/tuqCPVy8DsDMDq3kE=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":58060},"main":"dist/index.js","types":"dist/index.d.ts","module":"dist/index.mjs","exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.mjs","require":"./dist/index.js"}},"gitHead":"45b08a929ede21bf5193c37e20655999ca37ff03","scripts":{"build":"tsup src/index.ts --format cjs,esm --dts --clean","prepublishOnly":"yarn build"},"_npmUser":{"name":"penghuteng","email":"penghuteng@hotmail.com"},"_npmVersion":"10.9.2","description":"Express Reply middleware","directories":{},"_nodeVersion":"22.13.0","dependencies":{"express":"^5.1.0"},"publishConfig":{"access":"public","registry":"https://registry.npmjs.org"},"_hasShrinkwrap":false,"devDependencies":{"tsup":"^8.5.0","@types/express":"^5.0.2"},"_npmOperationalInternal":{"tmp":"tmp/express-reply_0.1.3_1749437973339_0.22567822611647226","host":"s3://npm-registry-packages-npm-production"}},"0.2.0":{"name":"@aqcq/express-reply","version":"0.2.0","keywords":["aqcq","express","reply","middleware","express-reply"],"license":"MIT","_id":"@aqcq/express-reply@0.2.0","maintainers":[{"name":"penghuteng","email":"penghuteng@hotmail.com"}],"dist":{"shasum":"c28d3726780756bd284fcc68b9d3698ad76ac4c2","tarball":"https://registry.npmjs.org/@aqcq/express-reply/-/express-reply-0.2.0.tgz","fileCount":8,"integrity":"sha512-diDfEO5SN1/Zkk/p2AVNj4HRxW4a2IbWASSQrqycBhX3Nl/W+5ANiThTGzEm1Cchv7X3jerFdJgA59G79BUzZQ==","signatures":[{"sig":"MEQCIE8RzzyGixy8Vr3r7W9EqSKb5blP66zexAW/sqrDqgF0AiBxHCZv2KlXcAxZe0R15bFwuIU6Q4U2QMnD8Avbh+3GnA==","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":59970},"main":"dist/index.js","types":"dist/index.d.ts","module":"dist/index.mjs","exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.mjs","require":"./dist/index.js"}},"gitHead":"a1d03f87cebddc46f9d846cca2f874e4a66f28ce","scripts":{"build":"tsup src/index.ts --format cjs,esm --dts --clean","prepublishOnly":"yarn build"},"_npmUser":{"name":"penghuteng","email":"penghuteng@hotmail.com"},"_npmVersion":"10.9.2","description":"Express Reply middleware","directories":{},"_nodeVersion":"22.13.0","dependencies":{"express":"^5.1.0"},"publishConfig":{"access":"public","registry":"https://registry.npmjs.org"},"_hasShrinkwrap":false,"devDependencies":{"tsup":"^8.5.0","@types/express":"^5.0.2"},"_npmOperationalInternal":{"tmp":"tmp/express-reply_0.2.0_1749460855107_0.5539301642251928","host":"s3://npm-registry-packages-npm-production"}},"0.2.1":{"name":"@aqcq/express-reply","description":"Express Reply middleware","version":"0.2.1","main":"dist/index.js","module":"dist/index.mjs","types":"dist/index.d.ts","exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.mjs","require":"./dist/index.js"}},"license":"MIT","keywords":["aqcq","express","reply","middleware","express-reply"],"scripts":{"build":"tsup src/index.ts --format cjs,esm --dts --clean","prepublishOnly":"yarn build"},"dependencies":{"express":"^5.1.0"},"publishConfig":{"registry":"https://registry.npmjs.org","access":"public"},"devDependencies":{"@types/express":"^5.0.2","tsup":"^8.5.0"},"_id":"@aqcq/express-reply@0.2.1","gitHead":"bfb7f23207d5e980c4b16b80a2668c3d2399cf27","_nodeVersion":"22.13.0","_npmVersion":"10.9.2","dist":{"integrity":"sha512-hdeJDNr55B0DYQrNwtGl41jJQT3GtCSv6fb7ODaE9M63/wd/2OXMdgm6aLsNLbXWnSo5fTBXDd8aR2WyDR7PTw==","shasum":"558a28c6b054cbfbfac5389210c4a4dbd18e0c65","tarball":"https://registry.npmjs.org/@aqcq/express-reply/-/express-reply-0.2.1.tgz","fileCount":8,"unpackedSize":59974,"signatures":[{"keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U","sig":"MEYCIQCEE58Zlj1PFS+qLvJjVd3wYDWV1pbtkyrmFYNxlbB2EgIhAMiXTlhSveDUowgZcxzk+//PuhU5wKdhjfTBVNx34a+I"}]},"_npmUser":{"name":"penghuteng","email":"penghuteng@hotmail.com"},"directories":{},"maintainers":[{"name":"penghuteng","email":"penghuteng@hotmail.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages-npm-production","tmp":"tmp/express-reply_0.2.1_1749461423052_0.771728048296245"},"_hasShrinkwrap":false}},"time":{"created":"2025-06-04T07:26:38.026Z","modified":"2025-06-09T09:30:23.489Z","0.0.1":"2025-06-04T07:26:38.301Z","0.0.3":"2025-06-04T07:42:44.563Z","0.1.0":"2025-06-06T03:39:46.641Z","0.1.1":"2025-06-06T04:06:27.083Z","0.1.2":"2025-06-06T06:32:46.513Z","0.1.3":"2025-06-09T02:59:33.527Z","0.1.4":"2025-06-09T09:17:02.278Z","0.2.0":"2025-06-09T09:20:55.292Z","0.2.1":"2025-06-09T09:30:23.282Z"},"license":"MIT","keywords":["aqcq","express","reply","middleware","express-reply"],"description":"Express Reply middleware","maintainers":[{"name":"penghuteng","email":"penghuteng@hotmail.com"}],"readme":"# @aqcq/express-reply\n\nExpress Reply middleware，为 Express Response 对象添加统一的响应方法和自动错误捕获功能。\n\n## 特色功能\n\n✨ **自动错误捕获** - 无需手动调用 `next(error)`，直接 `throw` 即可  \n🚀 **统一响应格式** - 标准化成功和错误响应结构  \n📝 **完整 TypeScript 支持** - 类型提示和自动补全  \n🔧 **灵活配置** - 支持预定义和自定义错误类型  \n\n## 安装\n\n```bash\nnpm install @aqcq/express-reply\n# 或\nyarn add @aqcq/express-reply\n```\n\n## 核心功能\n\n### 🎯 自动错误捕获（推荐方式）\n\n使用 `catchError` 包装器，让你可以直接 `throw` 错误，无需调用 `next()`：\n\n```javascript\nimport express from 'express';\nimport { errorMiddleware, ResponseError, catchError } from '@aqcq/express-reply';\n\nconst app = express();\n\n// 异步路由 - 自动捕获错误\napp.get('/api/user/:id', catchError(async (req, res) => {\n  const { id } = req.params;\n  \n  if (id === '404') {\n    // 直接抛出错误，无需 next()！\n    throw new ResponseError('VALIDATION_ERROR');\n  }\n  \n  // 模拟异步数据库操作\n  const user = await getUserFromDB(id);\n  res.reply(user);\n}));\n\n// 同步路由 - 自动捕获错误\napp.get('/api/sync', catchError((req, res) => {\n  // 同步代码中也可以直接抛出错误\n  throw new ResponseError('HTTP_ERROR');\n}));\n\n// 错误处理中间件（必须放在最后）\napp.use(errorMiddleware());\napp.listen(3000);\n```\n\n### 🔧 针对性错误捕获\n\n如果你明确知道路由是同步还是异步的，可以使用更具体的包装器：\n\n```javascript\nimport { asyncHandler, syncHandler } from '@aqcq/express-reply';\n\n// 专门用于异步路由\napp.get('/api/async', asyncHandler(async (req, res) => {\n  await someAsyncOperation();\n  throw new ResponseError('REQUEST_AI_ERROR');\n}));\n\n// 专门用于同步路由\napp.get('/api/sync', syncHandler((req, res) => {\n  throw new ResponseError('RATE_LIMIT_ERROR');\n}));\n```\n\n### 📋 传统方式（向后兼容）\n\n如果不使用错误捕获包装器，仍需手动调用 `next()`：\n\n```javascript\napp.get('/api/traditional', async (req, res, next) => {\n  try {\n    throw new ResponseError('VALIDATION_ERROR');\n  } catch (error) {\n    next(error); // 传统方式需要手动调用\n  }\n});\n```\n\n### ✅ 统一响应格式\n\n使用内置的响应方法来标准化你的API响应：\n\n```javascript\nimport express from 'express';\nimport { replyMiddleware, catchError } from '@aqcq/express-reply';\n\nconst app = express();\n\n// 注册 reply 中间件\napp.use(replyMiddleware);\n\napp.get('/api/success', catchError(async (req, res) => {\n  // 成功响应 - 统一格式\n  res.reply({ \n    message: 'Hello World', \n    data: { id: 1, name: '用户名' } \n  });\n}));\n\napp.get('/api/fail', catchError((req, res) => {\n  // 方式1: 直接使用响应方法\n  res.replyFail('VALIDATION_ERROR');\n  \n  // 方式2: 抛出错误（推荐）\n  // throw new ResponseError('VALIDATION_ERROR');\n}));\n\napp.listen(3000);\n```\n\n### TypeScript 支持\n\n本包提供完整的 TypeScript 类型支持。安装后，你的 Express Response 对象会自动扩展以下方法：\n\n```typescript\ninterface Response {\n  reply: (data: any) => void;\n  replyFail: (name: ErrorName) => void;\n}\n```\n\n在 TypeScript 项目中使用时，你会获得完整的类型提示和自动补全：\n\n```typescript\nimport express from 'express';\nimport { replyMiddleware, ErrorName } from '@aqcq/express-reply';\n\nconst app = express();\napp.use(replyMiddleware);\n\napp.get('/api/users', (req, res) => {\n  // TypeScript 会为 res.reply 和 res.replyFail 提供类型提示\n  res.reply({ users: [] });\n  res.replyFail('USER_LIMIT_ERROR'); // 错误名称会有自动补全\n});\n```\n\n## API 参考\n\n### 错误捕获包装器\n\n#### catchError(handler) - 推荐使用\n\n通用错误捕获包装器，自动处理同步和异步错误：\n\n```typescript\nimport { catchError } from '@aqcq/express-reply';\n\napp.get('/api/route', catchError(async (req, res) => {\n  // 可以是同步或异步函数\n  throw new ResponseError('VALIDATION_ERROR');\n}));\n```\n\n#### asyncHandler(handler)\n\n专门用于异步路由的错误捕获：\n\n```typescript\nimport { asyncHandler } from '@aqcq/express-reply';\n\napp.get('/api/async', asyncHandler(async (req, res) => {\n  await someAsyncOperation();\n  throw new ResponseError('REQUEST_AI_ERROR');\n}));\n```\n\n#### syncHandler(handler)\n\n专门用于同步路由的错误捕获：\n\n```typescript\nimport { syncHandler } from '@aqcq/express-reply';\n\napp.get('/api/sync', syncHandler((req, res) => {\n  throw new ResponseError('HTTP_ERROR');\n}));\n```\n\n### 响应方法\n\n#### res.reply(data)\n\n发送成功响应。\n\n- `data`: 要返回的数据（任意类型）\n\n响应格式：\n```json\n{\n  \"code\": 0,\n  \"message\": \"success\",\n  \"timestamp\": 1234567890,\n  \"data\": \"你传入的数据\"\n}\n```\n\n#### res.replyFail(errorName, code?)\n\n发送错误响应。\n\n- `errorName`: 错误名称（预定义类型或自定义字符串）\n- `code`: 可选的错误码，默认为 5000\n\n响应格式：\n```json\n{\n  \"code\": 2001,\n  \"message\": \"parameter validation error\",\n  \"success\": false\n}\n```\n\n### 错误类\n\n#### new ResponseError(message, code?)\n\n创建一个可以被错误中间件捕获的错误实例。\n\n- `message`: 错误名称（预定义类型）或自定义错误消息\n- `code`: 可选的错误码，默认为 500\n\n```typescript\n// 使用预定义错误类型\nthrow new ResponseError('VALIDATION_ERROR');\n\n// 使用自定义错误消息和错误码\nthrow new ResponseError('自定义错误消息', 4001);\n```\n\n## 支持的错误类型及错误码\n\n```js\n[\n  {\n    code: 1001,\n    name: 'HTTP_ERROR',\n    message: 'internal unknown error',\n    _apiDesc: '内部未知错误',\n  },\n  {\n    code: 2001,\n    name: 'VALIDATION_ERROR',\n    message: 'parameter validation error',\n    _apiDesc: '参数校验错误',\n  },\n  {\n    code: 4002,\n    name: 'REQUEST_AI_ERROR',\n    message: 'requestAI error',\n  },\n  {\n    code: 4003,\n    name: 'USER_LIMIT_ERROR',\n    message:\n      'The limit for current model has been reached. Please wait until the next period or upgrade your plan to get more.',\n  },\n  {\n    code: 4003,\n    name: 'NOT_BASE_BOT_USAGE_LIMIT_ERROR',\n    message:\n      'The monthly queries for GPT-4, which this bot is based on, has been exhausted. Please use another bot.',\n  },\n  {\n    code: 4004,\n    name: 'USAGE_LIMIT_FOR_FREE_ERROR',\n    message:\n      'Free users can only use the standard model ( 10 queries per day ). Please try again tomorrow or upgrade your plan to get more.',\n  },\n  {\n    code: 4005,\n    name: 'BASE_BOT_NOT_FOUND_ERRO',\n    message:\n      'The base bot for your current bot has been deleted. Please reconfigure another base robot.',\n  },\n  {\n    code: 4006,\n    name: 'ONLY_USE_GPT3DOT5_ERROR',\n    message:\n      'Your complimentary queries has been exhausted, you can now only use GPT-3.5 (10 queries per day).',\n  },\n  {\n    code: 4008,\n    name: 'REQUEST_AI_WITH_NETWORK_AUTH_ERROR',\n    message: 'Unauthorized',\n  },\n  {\n    code: 4009,\n    name: 'ONLY_USE_BASIC_BOT_ERROR',\n    message:\n      'The advanced drawing model is not available for free users. Upgrade your plan to get more advanced features.',\n  },\n  {\n    code: 4010,\n    name: 'BOT_NETWORK_ERROR',\n    message: 'Internet access is not available for free users.',\n  },\n  {\n    code: 4011,\n    name: 'ONLY_PRO_USER_CAN_USE_ERRO',\n    message: 'insufficient User Permissions',\n    _apiDesc: 'insufficient User Permissions',\n  },\n  {\n    code: 4012,\n    name: 'AI_USE_PRO_ERROR',\n    message: 'The advanced drawing model is not available for Air Plan.Please upgrade your plan.',\n  },\n  {\n    code: 4013,\n    name: 'MODEL_NOT_FOUND_ERROR',\n    message: 'Model not found',\n    _apiDesc: 'Model not found',\n  },\n  {\n    code: 4014,\n    name: 'MODEL_UNAVAILABLE_ERROR',\n    message: 'The model you are using is not available. Please try another model.',\n  },\n  {\n    code: 4015,\n    name: 'MODEL_UNAVAILABLE_ERROR',\n    message: 'Model unavailable',\n    _apiDesc: 'Model unavailable',\n  },\n  {\n    code: 5001,\n    name: 'CREATE_ACTION_ERROR',\n    message: 'Creation failure',\n    _apiDesc: 'Creation failure',\n  },\n  {\n    code: 5040,\n    name: 'RESPONSE_MODEL_NOT_FOUND_ERRO',\n    message: 'model not found',\n    _apiDesc: '模型不存在',\n  },\n  {\n    code: 5041,\n    name: 'RESPONSE_GEN_TITLE_ERROR',\n    message: 'generate title failed',\n    _apiDesc: '生成标题失败',\n  },\n  {\n    code: 5042,\n    name: 'RESPONSE_QUERY_ERROR',\n    message: 'query failed',\n    _apiDesc: '查询失败',\n  },\n  {\n    code: 5043,\n    name: 'RESPONSE_BOT_OPERATION_ERROR',\n    message: 'operation failed',\n    _apiDesc: 'bot操作失败',\n  },\n  {\n    code: 5044,\n    name: 'RESPONSE_BOT_EXISTS_ERROR',\n    message: 'Bot already exists',\n    _apiDesc: 'bot已存在',\n  },\n  {\n    code: 6001,\n    name: 'RATE_LIMIT_ERROR',\n    message: 'Request rate limit',\n    _apiDesc: 'Creation failure',\n  },\n]\n```\n\n完整的错误类型列表请参考源码中的 `ERROR_MESSAGES`。\n\n## 最佳实践\n\n### ✅ 推荐做法\n\n```javascript\nimport { replyMiddleware, errorMiddleware, catchError, ResponseError } from '@aqcq/express-reply';\n\nconst app = express();\n\n// 1. 注册 reply 中间件\napp.use(replyMiddleware);\n\n// 2. 使用 catchError 包装所有路由\napp.get('/api/users', catchError(async (req, res) => {\n  // 3. 直接抛出错误，无需 next()\n  if (!req.user) {\n    throw new ResponseError('VALIDATION_ERROR');\n  }\n  \n  // 4. 使用统一的响应格式\n  res.reply({ users: await getUsers() });\n}));\n\n// 5. 错误处理中间件放在最后\napp.use(errorMiddleware());\n```\n\n### ❌ 避免的做法\n\n```javascript\n// 不推荐：混合使用传统方式和新方式\napp.get('/api/bad', async (req, res, next) => {\n  try {\n    throw new ResponseError('ERROR');\n  } catch (error) {\n    next(error); // 多余的 next() 调用\n  }\n});\n\n// 不推荐：忘记使用错误捕获包装器\napp.get('/api/bad2', async (req, res, next) => {\n  throw new ResponseError('ERROR'); // 异步错误不会被捕获\n});\n```\n\n## 注意事项\n\n1. **中间件顺序很重要**：\n   - `replyMiddleware` 要在业务路由之前注册\n   - `errorMiddleware` 要在所有路由之后注册\n\n2. **错误捕获**：\n   - 使用 `catchError` 包装器可以自动捕获所有错误\n   - 不使用包装器时，异步错误需要手动调用 `next(error)`\n\n3. **响应格式**：\n   - `res.reply()` 和 `res.replyFail()` 会自动设置适当的 HTTP 状态码\n   - 调用后响应立即发送，无需手动调用其他响应方法\n\n4. **TypeScript 支持**：\n   - 包含完整的类型定义，提供最佳的开发体验\n   - 错误名称会有自动补全功能\n\n## License\n\nMIT\n","readmeFilename":"Readme.md"}