用途:这是 AdonisJS 模块化项目里 routes.ts 的编写约定。每个模块自带 routes.ts,由 module-scaffolding 中接好的 preload 发现,没有 autoloader。路由同时是 URL 生成(Tuyau 等类型化客户端与服务端 URL 构建器读取命名路由)、中间件链和参数类型的唯一来源。
主要能力与规则:数字参数必须加 router.matchers.number(),否则非数字 URL 会进入控制器,Number('foo') 得到 NaN,Postgres 抛 invalid input syntax for type integer,返回 500;加了匹配器则在更早阶段 404。CRUD 动词走 router.resource(),自定义动词动作(activate、publish、finalize)写成同文件内独立的 router.post(...),不要塞进资源控制器。路由名按 URL 层级命名,如 parents.children.action,是前端类型化 URL 客户端与服务端 urlFor(...) 的共同契约。嵌套资源用 .params({ parents: 'parent_id' }) 重命名父段,并对每个 id 用 .where('parent_id', router.matchers.number()).where('id', router.matchers.number()) 约束,参数用语义化 snake_case。共享中间件的路由放进同一个 router.group(() => {...}).middleware(...),公开路由放组外。
使用方式:资源路由用 .only([...]) 裁剪到控制器实际暴露的动作;动词路由配 .as(...) 命名。若服务端调用方需要原始模式(含 :params 的模板,如 start/transmit.ts 中的 transmit.authorize),因该文件在 preload 阶段执行、早于 Server.boot() 调用 router.commit(),此时 router.findOrFail(name).pattern 会抛错;优先把模式导出为常量并写功能测试断言其等于 router.findOrFail(name).pattern,其次用 app.ready(...) 延迟,但后者救不了 transmit.authorize。
限制与反模式:数字 :id 不加 matcher 会 500;动词动作塞进资源控制器会污染命名并迫使 .only 膨胀;在 start/*.ts 顶层调用 router.findOrFail 会因路由未提交而失败;嵌套资源把参数改名为 id1/id2 会破坏 URL 客户端;逐条路由挂巨大中间件链而非用 group。相关技能:module-scaffolding、crud、actions-events、notifications、testing。