[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"skill:01M6EMM91F0XDF37XCG6P6KC0P":3,"skill-same:01M6EMM91F0XDF37XCG6P6KC0P":78},{"skillNo":4,"name":5,"nameZh":6,"description":7,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":16,"categories":17,"keywords":28,"publishedAt":44,"linkOnly":45,"markdownContent":46,"markdownBody":47,"frontMatter":48,"refName":49,"commitSha":50,"skillDirectory":51,"forksCount":52,"repositoryHtmlUrl":53,"repositoryHomepageUrl":54,"ownerHtmlUrl":55,"ownerBlogUrl":6,"ownerDescription":56,"updatedAt":57,"install":58,"resources":71},"01M6EMM91F0XDF37XCG6P6KC0P","pitfalls-express-api",null,"Express API conventions and storage patterns. Use when building REST APIs, defining routes, or implementing storage interfaces. Triggers on: Express, router, API route, status code, storage interface.","ComeOnOliver\u002Fskillshub","ComeOnOliver","https:\u002F\u002Favatars.githubusercontent.com\u002Fu\u002F43215937?v=4","01M6E5JNFECJAAVFE0W7SMWWD2","Haoran Shu","01M6E5JNNDQS7AJZDYFQ8TPZCK",66,"MIT","https:\u002F\u002Fgithub.com\u002FComeOnOliver\u002Fskillshub\u002Fblob\u002Fmain\u002Fskills\u002Faiskillstore\u002Fmarketplace\u002Fbarissozen\u002Fpitfalls-express-api\u002FSKILL.md",[18,23],{"categoryNo":19,"categoryName":20,"taxonomyType":21,"taxonomyTypeDesc":22},"01JBSEEDCAT000000000000010","后端与接口","SCENARIO","使用场景",{"categoryNo":24,"categoryName":25,"taxonomyType":26,"taxonomyTypeDesc":27},"01JBSEEDCAT000000000000030","开发工程师","PROFESSION","适用职业",[29,30,31,32,33,34,35,36,37,38,39,40,41,42,43],"api","express","express api","pitfalls express api","storage","status","code","api conventions","REST","use","router","patterns","route","conventions","triggers","2026-11-10 10:12:30",false,"---\nname: pitfalls-express-api\ndescription: \"Express API conventions and storage patterns. Use when building REST APIs, defining routes, or implementing storage interfaces. Triggers on: Express, router, API route, status code, storage interface.\"\n---\n\n# Express API Pitfalls\n\nCommon pitfalls and correct patterns for Express APIs.\n\n## When to Use\n\n- Building REST API routes\n- Implementing storage interfaces\n- Setting HTTP status codes\n- Validating request bodies\n- Reviewing Express API code\n\n## Workflow\n\n### Step 1: Verify Route Structure\n\nCheck that routes follow REST conventions.\n\n### Step 2: Check Status Codes\n\nEnsure correct status codes for each operation.\n\n### Step 3: Verify Validation\n\nConfirm input validation middleware is in place.\n\n---\n\n## Route Structure\n\n```typescript\n\u002F\u002F Public routes\nGET  \u002Fapi\u002Fresource          \u002F\u002F List\nGET  \u002Fapi\u002Fresource\u002F:id      \u002F\u002F Get one\n\n\u002F\u002F Admin routes (with auth middleware)\nPOST   \u002Fapi\u002Fadmin\u002Fresource      \u002F\u002F Create (201)\nPATCH  \u002Fapi\u002Fadmin\u002Fresource\u002F:id  \u002F\u002F Update (200)\nDELETE \u002Fapi\u002Fadmin\u002Fresource\u002F:id  \u002F\u002F Delete (204)\n\n\u002F\u002F ✅ Always validate before storage\nrouter.post('\u002F', validateBody(schema), async (req, res) => {\n  const validated = req.body; \u002F\u002F Already validated by middleware\n});\n```\n\n## Status Codes\n\n| Operation | Success | Not Found | Invalid |\n|-----------|---------|-----------|---------|\n| GET | 200 | 404 | 400 |\n| POST | 201 | - | 400 |\n| PATCH | 200 | 404 | 400 |\n| DELETE | 204 | 404 | - |\n\n## Storage Interface Pattern\n\n```typescript\n\u002F\u002F ✅ Define interface for all storage operations\ninterface IStorage {\n  \u002F\u002F Strategies\n  getStrategies(): Promise\u003CStrategy[]>;\n  getStrategy(id: string): Promise\u003CStrategy | undefined>;\n  createStrategy(data: NewStrategy): Promise\u003CStrategy>;\n  updateStrategy(id: string, data: Partial\u003CStrategy>): Promise\u003CStrategy | undefined>;\n  deleteStrategy(id: string): Promise\u003Cboolean>;\n}\n\n\u002F\u002F ✅ Implement for different backends\nclass DbStorage implements IStorage { ... }  \u002F\u002F PostgreSQL\nclass MemStorage implements IStorage { ... } \u002F\u002F Testing\n```\n\n## Background Job Patterns\n\n```typescript\n\u002F\u002F ✅ Cleanup on process exit\nconst intervals: NodeJS.Timeout[] = [];\n\nfunction startJob(fn: () => void, ms: number) {\n  const id = setInterval(fn, ms);\n  intervals.push(id);\n  return id;\n}\n\nprocess.on('SIGTERM', () => {\n  intervals.forEach(clearInterval);\n  process.exit(0);\n});\n\n\u002F\u002F ✅ Handle overlapping executions\nlet isRunning = false;\nasync function scanForOpportunities() {\n  if (isRunning) return;\n  isRunning = true;\n  try {\n    await scan();\n  } finally {\n    isRunning = false;\n  }\n}\n```\n\n## Quick Checklist\n\n- [ ] Routes follow REST conventions\n- [ ] Correct status codes returned\n- [ ] Input validation on all endpoints\n- [ ] Storage interface abstraction used\n- [ ] Background jobs handle cleanup\n","# Express API Pitfalls\n\nCommon pitfalls and correct patterns for Express APIs.\n\n## When to Use\n\n- Building REST API routes\n- Implementing storage interfaces\n- Setting HTTP status codes\n- Validating request bodies\n- Reviewing Express API code\n\n## Workflow\n\n### Step 1: Verify Route Structure\n\nCheck that routes follow REST conventions.\n\n### Step 2: Check Status Codes\n\nEnsure correct status codes for each operation.\n\n### Step 3: Verify Validation\n\nConfirm input validation middleware is in place.\n\n---\n\n## Route Structure\n\n```typescript\n\u002F\u002F Public routes\nGET  \u002Fapi\u002Fresource          \u002F\u002F List\nGET  \u002Fapi\u002Fresource\u002F:id      \u002F\u002F Get one\n\n\u002F\u002F Admin routes (with auth middleware)\nPOST   \u002Fapi\u002Fadmin\u002Fresource      \u002F\u002F Create (201)\nPATCH  \u002Fapi\u002Fadmin\u002Fresource\u002F:id  \u002F\u002F Update (200)\nDELETE \u002Fapi\u002Fadmin\u002Fresource\u002F:id  \u002F\u002F Delete (204)\n\n\u002F\u002F ✅ Always validate before storage\nrouter.post('\u002F', validateBody(schema), async (req, res) => {\n  const validated = req.body; \u002F\u002F Already validated by middleware\n});\n```\n\n## Status Codes\n\n| Operation | Success | Not Found | Invalid |\n|-----------|---------|-----------|---------|\n| GET | 200 | 404 | 400 |\n| POST | 201 | - | 400 |\n| PATCH | 200 | 404 | 400 |\n| DELETE | 204 | 404 | - |\n\n## Storage Interface Pattern\n\n```typescript\n\u002F\u002F ✅ Define interface for all storage operations\ninterface IStorage {\n  \u002F\u002F Strategies\n  getStrategies(): Promise\u003CStrategy[]>;\n  getStrategy(id: string): Promise\u003CStrategy | undefined>;\n  createStrategy(data: NewStrategy): Promise\u003CStrategy>;\n  updateStrategy(id: string, data: Partial\u003CStrategy>): Promise\u003CStrategy | undefined>;\n  deleteStrategy(id: string): Promise\u003Cboolean>;\n}\n\n\u002F\u002F ✅ Implement for different backends\nclass DbStorage implements IStorage { ... }  \u002F\u002F PostgreSQL\nclass MemStorage implements IStorage { ... } \u002F\u002F Testing\n```\n\n## Background Job Patterns\n\n```typescript\n\u002F\u002F ✅ Cleanup on process exit\nconst intervals: NodeJS.Timeout[] = [];\n\nfunction startJob(fn: () => void, ms: number) {\n  const id = setInterval(fn, ms);\n  intervals.push(id);\n  return id;\n}\n\nprocess.on('SIGTERM', () => {\n  intervals.forEach(clearInterval);\n  process.exit(0);\n});\n\n\u002F\u002F ✅ Handle overlapping executions\nlet isRunning = false;\nasync function scanForOpportunities() {\n  if (isRunning) return;\n  isRunning = true;\n  try {\n    await scan();\n  } finally {\n    isRunning = false;\n  }\n}\n```\n\n## Quick Checklist\n\n- [ ] Routes follow REST conventions\n- [ ] Correct status codes returned\n- [ ] Input validation on all endpoints\n- [ ] Storage interface abstraction used\n- [ ] Background jobs handle cleanup\n",{"name":5,"description":7},"main","def8531e65114c0fca8fb8551c1871ee0eed705c","skills\u002Faiskillstore\u002Fmarketplace\u002Fbarissozen\u002Fpitfalls-express-api",24,"https:\u002F\u002Fgithub.com\u002FComeOnOliver\u002Fskillshub","https:\u002F\u002Fskillshub.wtf","https:\u002F\u002Fgithub.com\u002FComeOnOliver","AI & Blockchain Engineer\r\n","2026-06-24 22:07:19",{"source":8,"skillName":5,"commands":59,"prompt":69,"zipAvailable":70},[60,63,66],{"tool":61,"command":62},"npx","npx skills add ComeOnOliver\u002Fskillshub --skill pitfalls-express-api",{"tool":64,"command":65},"bunx","bunx skills add ComeOnOliver\u002Fskillshub --skill pitfalls-express-api",{"tool":67,"command":68},"pnpm","pnpm dlx skills add ComeOnOliver\u002Fskillshub --skill pitfalls-express-api","安装技能，技能地址：https:\u002F\u002Fgithub.com\u002FComeOnOliver\u002Fskillshub\u002Fblob\u002Fmain\u002Fskills\u002Faiskillstore\u002Fmarketplace\u002Fbarissozen\u002Fpitfalls-express-api\u002FSKILL.md",true,[72],{"path":73,"resourceType":74,"resourceTypeDesc":75,"sizeBytes":76,"sourceHtmlUrl":77},"skill-report.json","REFERENCE","参考文档",9453,"https:\u002F\u002Fgithub.com\u002FComeOnOliver\u002Fskillshub\u002Fblob\u002Fmain\u002Fskills\u002Faiskillstore\u002Fmarketplace\u002Fbarissozen\u002Fpitfalls-express-api\u002Fskill-report.json",[79,91,101,110,116,123],{"skillNo":80,"name":81,"nameZh":6,"description":6,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":82,"categories":83,"keywords":87,"publishedAt":44},"01M6FKJN13GMG4KY57J3QD8GY5","model-hierarchy-skill","https:\u002F\u002Fgithub.com\u002FComeOnOliver\u002Fskillshub\u002Fblob\u002Fmain\u002Fskills\u002Fzscole\u002Fmodel-hierarchy-skill\u002Fmodel-hierarchy-skill\u002FSKILL.md",[84],{"categoryNo":85,"categoryName":86,"taxonomyType":21,"taxonomyTypeDesc":22},"01JBSEEDCAT000000000000023","Skill与智能体开发",[88,89,90],"model","model hierarchy","model hierarchy skill",{"skillNo":92,"name":93,"nameZh":6,"description":6,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":94,"categories":95,"keywords":97,"publishedAt":44},"01M6FKJJJ6GCAMR4PPPRD12M5X","zoom-mcp","https:\u002F\u002Fgithub.com\u002FComeOnOliver\u002Fskillshub\u002Fblob\u002Fmain\u002Fskills\u002Fzoom\u002Fskills\u002Fzoom-mcp\u002FSKILL.md",[96],{"categoryNo":85,"categoryName":86,"taxonomyType":21,"taxonomyTypeDesc":22},[98,99,100],"MCP","zoom","zoom mcp",{"skillNo":102,"name":103,"nameZh":6,"description":6,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":104,"categories":105,"keywords":106,"publishedAt":44},"01M6FKJE3KYT3KPEZMEEHYKA6K","zoom-apps-sdk","https:\u002F\u002Fgithub.com\u002FComeOnOliver\u002Fskillshub\u002Fblob\u002Fmain\u002Fskills\u002Fzoom\u002Fskills\u002Fzoom-apps-sdk\u002FSKILL.md",[],[107,108,109,99],"sdk","zoom apps sdk","apps",{"skillNo":111,"name":112,"nameZh":6,"description":6,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":113,"categories":114,"keywords":115,"publishedAt":44},"01M6FKJ9EDH9Q5VWDF8HAJRSP0","windows","https:\u002F\u002Fgithub.com\u002FComeOnOliver\u002Fskillshub\u002Fblob\u002Fmain\u002Fskills\u002Fzoom\u002Fskills\u002Fwindows\u002FSKILL.md",[],[112],{"skillNo":117,"name":118,"nameZh":6,"description":6,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":119,"categories":120,"keywords":122,"publishedAt":44},"01M6FKJ666BEEFC3AE9GJ72Q93","whiteboard","https:\u002F\u002Fgithub.com\u002FComeOnOliver\u002Fskillshub\u002Fblob\u002Fmain\u002Fskills\u002Fzoom\u002Fskills\u002Fwhiteboard\u002FSKILL.md",[121],{"categoryNo":85,"categoryName":86,"taxonomyType":21,"taxonomyTypeDesc":22},[118],{"skillNo":124,"name":125,"nameZh":6,"description":6,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":126,"categories":127,"keywords":128,"publishedAt":44},"01M6FKJ21WFCDGTJQ2Q91T9DVW","websockets","https:\u002F\u002Fgithub.com\u002FComeOnOliver\u002Fskillshub\u002Fblob\u002Fmain\u002Fskills\u002Fzoom\u002Fskills\u002Fwebsockets\u002FSKILL.md",[],[125]]