out-of-scope 发现,来自 #5822(PR #6303)的实现过程,按 Prime Directive #10 单独立单。未认领。
事实
RestServer 用 getApiBasePath() 决定自己所有路由的前缀:
packages/rest/src/rest-server.ts — return api.apiPath ?? ${''}${'$'}{api.basePath}/${'$'}{api.version}${''};
而 rest-api-plugin.ts 给两个 direct-mount registrar 算的 base 不读 apiPath:
packages/rest/src/rest-api-plugin.ts — const basePath = config.api?.api?.basePath || '/api'; const version = config.api?.api?.version || 'v1'; const versionedBase = ${''}${'$'}{basePath}/${'$'}{version}${''};
apiPath 是 spec 里可声明的公开配置键(packages/spec/src/api/rest-server.zod.ts:
"Full API path (defaults to {basePath}/{version})",并已进 content/docs/references/api/rest-server.mdx)。
后果
部署一旦设置 api.apiPath(例如 /backend/api/v9):
- CRUD / metadata / reports / … 等全部 route-manager 路由挂在
/backend/api/v9/...;
- 而
packages.*(4 条)与 datasources/:name/external/*(5 条)仍然挂在 /api/v1/...。
即 SDK 的 packages.list / packages.get / packages.uninstall /
datasources.external.* 在该部署上打到 {apiPath}/packages 会 404,真正服务它们的是另一个前缀。
默认配置(不设 apiPath)两者相等,所以今天的 example / showcase 都撞不到 —— 仓库里没有任何
example 设置过 apiPath。
与 #5822 的关系(不是它引入的,但被它照出来)
#5822(PR #6303)让这 9 条对 RestServer.getRoutes() 可枚举。枚举面因此如实显示它们挂在
/api/v1/...;而 {apiPath} 那份 /openapi.json 会按 isUnderBase 把它们过滤掉 ——
文档没有说谎(它们确实不在那个 base 下),但这正好把前缀不一致变成可见现象。PR #6303
刻意没有顺手改前缀:改它会移动 9 条路由的线上 URL,属于独立的、需要评审的行为变更。
复现
defineStack({ /* … */ server: { api: { apiPath: '/backend/api/v9' } } })
// GET /backend/api/v9/data/:object → 200(route-manager 路由跟随 apiPath)
// GET /backend/api/v9/packages → 404
// GET /api/v1/packages → 200(direct-mount 路由没跟随)
可能的处置(留给分诊,不预设)
- 让
rest-api-plugin.ts 用与 RestServer.getApiBasePath() 同一个表达式(或直接把这个
base 从 RestServer 暴露出来,单一真相源),9 条跟随 apiPath —— 行为变更:设置了
apiPath 的部署上这 9 条 URL 会移动;
- 或者裁定
apiPath 只管 route-manager 面,并把这个边界写进 apiPath 的 .describe() 与文档
—— 但那等于承认一个部署里有两个 API 前缀;
- 或者退役
apiPath(ADR-0049 enforce-or-remove 的形状:一个声明了却只被一半路由遵守的键)。
查重
origin/main 与 open issue 各搜过 apiPath / direct-mount / basePath 前缀,无同题单;
#5822 是发现现场(处置面不同,PR #6303 已写明为何不在其中修)。
out-of-scope 发现,来自 #5822(PR #6303)的实现过程,按 Prime Directive #10 单独立单。未认领。
事实
RestServer用getApiBasePath()决定自己所有路由的前缀:packages/rest/src/rest-server.ts—return api.apiPath ?? ${''}${'$'}{api.basePath}/${'$'}{api.version}${''};而
rest-api-plugin.ts给两个 direct-mount registrar 算的 base 不读apiPath:packages/rest/src/rest-api-plugin.ts—const basePath = config.api?.api?.basePath || '/api'; const version = config.api?.api?.version || 'v1'; const versionedBase = ${''}${'$'}{basePath}/${'$'}{version}${''};apiPath是 spec 里可声明的公开配置键(packages/spec/src/api/rest-server.zod.ts:"Full API path (defaults to {basePath}/{version})",并已进
content/docs/references/api/rest-server.mdx)。后果
部署一旦设置
api.apiPath(例如/backend/api/v9):/backend/api/v9/...;packages.*(4 条)与datasources/:name/external/*(5 条)仍然挂在/api/v1/...。即 SDK 的
packages.list/packages.get/packages.uninstall/datasources.external.*在该部署上打到{apiPath}/packages会 404,真正服务它们的是另一个前缀。默认配置(不设
apiPath)两者相等,所以今天的 example / showcase 都撞不到 —— 仓库里没有任何example 设置过
apiPath。与 #5822 的关系(不是它引入的,但被它照出来)
#5822(PR #6303)让这 9 条对
RestServer.getRoutes()可枚举。枚举面因此如实显示它们挂在/api/v1/...;而{apiPath}那份/openapi.json会按isUnderBase把它们过滤掉 ——文档没有说谎(它们确实不在那个 base 下),但这正好把前缀不一致变成可见现象。PR #6303
刻意没有顺手改前缀:改它会移动 9 条路由的线上 URL,属于独立的、需要评审的行为变更。
复现
可能的处置(留给分诊,不预设)
rest-api-plugin.ts用与RestServer.getApiBasePath()同一个表达式(或直接把这个base 从
RestServer暴露出来,单一真相源),9 条跟随apiPath—— 行为变更:设置了apiPath的部署上这 9 条 URL 会移动;apiPath只管 route-manager 面,并把这个边界写进apiPath的.describe()与文档—— 但那等于承认一个部署里有两个 API 前缀;
apiPath(ADR-0049 enforce-or-remove 的形状:一个声明了却只被一半路由遵守的键)。查重
origin/main与 open issue 各搜过apiPath/direct-mount/basePath 前缀,无同题单;#5822 是发现现场(处置面不同,PR #6303 已写明为何不在其中修)。