okgoes-core 0.0.0-stage → 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +319 -2
- package/dist/application.d.ts +101 -0
- package/dist/application.js +575 -0
- package/dist/config.d.ts +36 -0
- package/dist/config.js +68 -0
- package/dist/constants.d.ts +21 -0
- package/dist/constants.js +32 -0
- package/dist/controller.d.ts +31 -0
- package/dist/controller.js +89 -0
- package/dist/core/compose.d.ts +7 -0
- package/dist/core/compose.js +36 -0
- package/dist/core/context.d.ts +85 -0
- package/dist/core/context.js +202 -0
- package/dist/core/cookies.d.ts +33 -0
- package/dist/core/cookies.js +169 -0
- package/dist/core/error.d.ts +13 -0
- package/dist/core/error.js +47 -0
- package/dist/core/koa.d.ts +34 -0
- package/dist/core/koa.js +170 -0
- package/dist/core/request.d.ts +48 -0
- package/dist/core/request.js +227 -0
- package/dist/core/response.d.ts +40 -0
- package/dist/core/response.js +224 -0
- package/dist/core/statuses.d.ts +7 -0
- package/dist/core/statuses.js +88 -0
- package/dist/core/utils.d.ts +18 -0
- package/dist/core/utils.js +192 -0
- package/dist/decorators.d.ts +10 -0
- package/dist/decorators.js +53 -0
- package/dist/index.d.ts +43 -0
- package/dist/index.js +155 -0
- package/dist/loader.d.ts +4 -0
- package/dist/loader.js +82 -0
- package/dist/middleware/body.d.ts +32 -0
- package/dist/middleware/body.js +254 -0
- package/dist/middleware/cors.d.ts +14 -0
- package/dist/middleware/cors.js +57 -0
- package/dist/middleware/proxy.d.ts +47 -0
- package/dist/middleware/proxy.js +244 -0
- package/dist/middleware/session.d.ts +24 -0
- package/dist/middleware/session.js +71 -0
- package/dist/middleware/static.d.ts +14 -0
- package/dist/middleware/static.js +119 -0
- package/dist/middleware/views.d.ts +13 -0
- package/dist/middleware/views.js +39 -0
- package/dist/model.d.ts +11 -0
- package/dist/model.js +31 -0
- package/dist/request.d.ts +22 -0
- package/dist/request.js +52 -0
- package/dist/response.d.ts +23 -0
- package/dist/response.js +79 -0
- package/dist/route-resolver.d.ts +24 -0
- package/dist/route-resolver.js +72 -0
- package/dist/router.d.ts +20 -0
- package/dist/router.js +68 -0
- package/dist/types.d.ts +137 -0
- package/dist/types.js +12 -0
- package/dist/view/engine.d.ts +19 -0
- package/dist/view/engine.js +137 -0
- package/package.json +29 -3
package/README.md
CHANGED
|
@@ -1,3 +1,320 @@
|
|
|
1
|
-
#
|
|
1
|
+
# okgoes-core
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
零远端依赖的 Node.js MVC 框架:基于 `node:http` 自研 Koa 风格内核与中间件,内置隐性路由(模块/控制器/方法自动映射)、可配置路由模式、插件系统、最小 EJS 兼容模板引擎。
|
|
4
|
+
|
|
5
|
+
## 特性
|
|
6
|
+
|
|
7
|
+
- **零远端依赖**:`dependencies` 为空,仅使用 Node.js 内置模块(http/https/crypto/stream/fs/path/querystring)
|
|
8
|
+
- **隐性路由(约定路由)**:`/模块/控制器/方法` 自动映射到 `src/controller/{module}/{controller}.controller.ts` 的对应方法,无需注册
|
|
9
|
+
- **路由模式可配置**:`routing.mode = auto | manual | both`
|
|
10
|
+
- **服务端渲染**:`render()` 无参时按约定定位模板 `views/{module}/{controller}/{action}.ejs`
|
|
11
|
+
- **插件系统**:`OkgoesPlugin.install(app, options)` 可注册中间件 / service
|
|
12
|
+
- **控制器返回值自动响应**:返回对象转 JSON,返回字符串输出 HTML
|
|
13
|
+
- **中间件顺序可控**:`app.useBefore / useAfter / useAt` 在指定核心阶段前后插入自定义中间件
|
|
14
|
+
- **自定义 server / WebSocket 共用端口**:`app.callback()` / `app.startWithoutListen()` 直接拿到 koa callback
|
|
15
|
+
- **约定路由 404 可定制**:`config.notFound.redirect / handler` 或 `app.koa.on("notFound", ctx => ...)`
|
|
16
|
+
- **内置反向代理**:`config.proxy` 拦截指定路径前缀,流式转发到 Java/Go/Python 等后端,支持路径重写、changeOrigin、https、自定义头,避免前端跨域
|
|
17
|
+
- **debug 模式 + 全局异常捕获**:`config.debug` 输出完整堆栈/请求详情/视图渲染错误;`config.error` 支持 handler / byStatus / redirect / render 错误页 / 进程级异常捕获
|
|
18
|
+
- 内置 session / cors / 静态资源 / body 解析 / 访问日志,均为自研实现,可配置开关
|
|
19
|
+
|
|
20
|
+
## 快速开始
|
|
21
|
+
|
|
22
|
+
```bash
|
|
23
|
+
npm install okgoes-core okgoes-cli -D
|
|
24
|
+
npx okgoes create my-app
|
|
25
|
+
cd my-app && npm install && npm run dev
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
## 目录约定
|
|
29
|
+
|
|
30
|
+
```
|
|
31
|
+
src/
|
|
32
|
+
config/index.ts # 应用配置
|
|
33
|
+
controller/index.controller.ts # GET / -> index()
|
|
34
|
+
controller/admin/post.controller.ts # GET /admin/post -> index()
|
|
35
|
+
model/user.model.ts # 继承 Model
|
|
36
|
+
middleware/auth.ts # 自定义中间件
|
|
37
|
+
plugin/metrics.ts # 自定义插件
|
|
38
|
+
routes.ts # 显式路由(manual/both 模式)
|
|
39
|
+
views/index/index.ejs # 约定模板
|
|
40
|
+
public/ # 静态资源
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
## 路由配置
|
|
44
|
+
|
|
45
|
+
```ts
|
|
46
|
+
// src/config/index.ts
|
|
47
|
+
const config: AppConfig = {
|
|
48
|
+
routing: {
|
|
49
|
+
mode: "auto", // auto: 隐性路由 | manual: 显式路由 | both
|
|
50
|
+
defaultController: "index",
|
|
51
|
+
defaultAction: "index",
|
|
52
|
+
modules: ["admin"], // 模块白名单,URL 首段命中才解析为模块
|
|
53
|
+
},
|
|
54
|
+
};
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
- 约定路由:`/admin/user/read/1` → `admin/user.controller.ts` 的 `read()`,附加段通过 `request.getRouteArgs()` 获取
|
|
58
|
+
- 显式路由:
|
|
59
|
+
|
|
60
|
+
```ts
|
|
61
|
+
// src/routes.ts
|
|
62
|
+
export default function register(router: Router) {
|
|
63
|
+
router.get("/api/users/:id", UserController, "read");
|
|
64
|
+
}
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
显式路由 `:id` 自动注入 `request.params.id`;`both` 模式显式优先、隐性兜底。
|
|
68
|
+
|
|
69
|
+
## HTTP 方法限制
|
|
70
|
+
|
|
71
|
+
```ts
|
|
72
|
+
import { Controller, Get, Post } from "okgoes-core";
|
|
73
|
+
|
|
74
|
+
export default class IndexController extends Controller {
|
|
75
|
+
@Get()
|
|
76
|
+
async info() {
|
|
77
|
+
return { ok: true }; // 仅 GET,其他方法返回 405;返回对象自动 JSON
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
@Post()
|
|
81
|
+
async create() {
|
|
82
|
+
return this.service("repository").save(this.req.getBody());
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
```
|
|
86
|
+
|
|
87
|
+
`this.req` / `this.res` / `this.context` / `this.application` 是 `initialize()` 后非 null 的 getter,
|
|
88
|
+
无需 `this.request?.` 或 `this.ctx!` 噪音。`this.request` / `this.ctx` 等原字段仍保留以兼容。
|
|
89
|
+
|
|
90
|
+
## 渲染
|
|
91
|
+
|
|
92
|
+
```ts
|
|
93
|
+
async index() {
|
|
94
|
+
await this.render({ title: "hi" }); // 约定定位 views/index/index.ejs
|
|
95
|
+
await this.render("admin/list", { list: [] }); // 指定模板
|
|
96
|
+
await this.renderAction("markdown", { doc }); // 切换到同控制器下 markdown action 的模板
|
|
97
|
+
}
|
|
98
|
+
```
|
|
99
|
+
|
|
100
|
+
## 中间件装配顺序
|
|
101
|
+
|
|
102
|
+
默认装配顺序(核心阶段名常量 `CoreMiddleware`):
|
|
103
|
+
|
|
104
|
+
```
|
|
105
|
+
error → accessLog → cors → session → body → views → static
|
|
106
|
+
```
|
|
107
|
+
|
|
108
|
+
`app.use(fn)` 推入的自定义中间件晚于所有核心中间件。如需在核心阶段前后插入(例如鉴权先于 CORS):
|
|
109
|
+
|
|
110
|
+
```ts
|
|
111
|
+
import { Application, CoreMiddleware } from "okgoes-core";
|
|
112
|
+
|
|
113
|
+
const app = new Application(baseDir, config);
|
|
114
|
+
app.useBefore(CoreMiddleware.Cors, authMiddleware); // 鉴权先于 CORS,鉴权失败不返回 CORS 头
|
|
115
|
+
app.useAfter(CoreMiddleware.Session, requestIdMiddleware);
|
|
116
|
+
```
|
|
117
|
+
|
|
118
|
+
## debug 模式与全局异常捕获
|
|
119
|
+
|
|
120
|
+
### debug 模式
|
|
121
|
+
|
|
122
|
+
```ts
|
|
123
|
+
new Application(baseDir, { debug: true });
|
|
124
|
+
```
|
|
125
|
+
|
|
126
|
+
开启后:
|
|
127
|
+
- 错误响应体包含 `stack`、`request`(method/url/path/query/headers)
|
|
128
|
+
- 视图渲染错误附加 `template` 路径与 `viewExtension`,便于定位是哪个模板出错
|
|
129
|
+
- 日志输出完整错误对象(含堆栈)
|
|
130
|
+
- 关闭时 5xx 仅返回 `{ code, message: "Internal Server Error" }`,不暴露内部信息;4xx 或 `err.expose = true` 仍暴露 message
|
|
131
|
+
|
|
132
|
+
### 全局异常捕获
|
|
133
|
+
|
|
134
|
+
```ts
|
|
135
|
+
new Application(baseDir, {
|
|
136
|
+
error: {
|
|
137
|
+
handler: (err, ctx) => { ctx.status = 500; ctx.body = { code: 500, msg: err.message }; },
|
|
138
|
+
byStatus: { 404: { redirect: "/page/404" }, 500: { handler: (err, ctx) => ctx.redirect("/page/500") } },
|
|
139
|
+
redirect: "/oops",
|
|
140
|
+
render: true,
|
|
141
|
+
expose: false,
|
|
142
|
+
},
|
|
143
|
+
});
|
|
144
|
+
```
|
|
145
|
+
|
|
146
|
+
处理优先级:`handler` > `byStatus[code]` > `redirect` > `render` > 默认 JSON 响应。
|
|
147
|
+
|
|
148
|
+
错误页模板可访问 `{ status, err, message, stack }`(stack 仅 debug 模式传入):
|
|
149
|
+
|
|
150
|
+
```ejs
|
|
151
|
+
<!-- views/error/500.ejs -->
|
|
152
|
+
<h1><%= status %></h1>
|
|
153
|
+
<p><%= message %></p>
|
|
154
|
+
<% if (stack) { %><pre><%= stack %></pre><% } %>
|
|
155
|
+
```
|
|
156
|
+
|
|
157
|
+
### 进程级未捕获异常
|
|
158
|
+
|
|
159
|
+
```ts
|
|
160
|
+
app.captureProcessErrors({ exit: true, onUncaught: (err) => {}, onUnhandled: (reason) => {} });
|
|
161
|
+
```
|
|
162
|
+
|
|
163
|
+
也可在中间件内手动调用 `app.handleError(err, ctx)` 走统一异常处理链。
|
|
164
|
+
|
|
165
|
+
## 自定义 404
|
|
166
|
+
|
|
167
|
+
```ts
|
|
168
|
+
const app = new Application(baseDir, {
|
|
169
|
+
notFound: { redirect: "/page/404" }, // 友好 404 页面
|
|
170
|
+
// 或
|
|
171
|
+
notFound: { handler: (ctx) => { ctx.body = { code: 404 }; } },
|
|
172
|
+
});
|
|
173
|
+
|
|
174
|
+
// 或事件式
|
|
175
|
+
app.koa.on("notFound", (ctx) => ctx.redirect("/page/404"));
|
|
176
|
+
```
|
|
177
|
+
|
|
178
|
+
## 反向代理(转发到 Java/Go/Python 等后端)
|
|
179
|
+
|
|
180
|
+
后端渲染场景下,API 可能由其他语言的后端提供。通过 `config.proxy` 拦截指定路径前缀,
|
|
181
|
+
流式转发到目标后端,前端同源访问 `/api/xxx` 即可,无需 CORS。
|
|
182
|
+
|
|
183
|
+
```ts
|
|
184
|
+
const app = new Application(baseDir, {
|
|
185
|
+
proxy: {
|
|
186
|
+
"/api": {
|
|
187
|
+
target: "http://localhost:8080", // Java 后端
|
|
188
|
+
rewrite: (p) => p.replace(/^\/api/, ""), // /api/users -> /users
|
|
189
|
+
},
|
|
190
|
+
"/java": {
|
|
191
|
+
target: "https://java-backend.internal",
|
|
192
|
+
pathRewrite: { "^/java": "/v1" }, // /java/items -> /v1/items
|
|
193
|
+
headers: { "X-Source": "okgoes" }, // 附加请求头
|
|
194
|
+
},
|
|
195
|
+
"/upstream": {
|
|
196
|
+
target: "http://127.0.0.1:9000",
|
|
197
|
+
changeOrigin: true, // 改 Host 为目标 host(默认 true)
|
|
198
|
+
timeout: 30000, // 30s 超时返回 504
|
|
199
|
+
},
|
|
200
|
+
},
|
|
201
|
+
});
|
|
202
|
+
```
|
|
203
|
+
|
|
204
|
+
也可单独挂载中间件:
|
|
205
|
+
|
|
206
|
+
```ts
|
|
207
|
+
import { createProxy } from "okgoes-core";
|
|
208
|
+
app.use(createProxy({ "/api": { target: "http://localhost:8080" } }));
|
|
209
|
+
```
|
|
210
|
+
|
|
211
|
+
说明:
|
|
212
|
+
- 代理在 body 解析之前执行,命中后直接流式转发原始请求体,不调 `next()`
|
|
213
|
+
- 自动注入 `X-Forwarded-For / Host / Proto` 头
|
|
214
|
+
- 目标不可达返回 502,超时返回 504
|
|
215
|
+
- 支持 https 目标(`secure: true` 校验证书,默认不校验,便于内网自签)
|
|
216
|
+
- `filter` 可按 ctx 条件决定是否命中(如仅代理 GET)
|
|
217
|
+
- 装配阶段为 `CoreMiddleware.Proxy`,可用 `app.useBefore / useAfter` 在其前后插入自定义逻辑
|
|
218
|
+
|
|
219
|
+
## 自定义 server / WebSocket 共用端口
|
|
220
|
+
|
|
221
|
+
```ts
|
|
222
|
+
import * as http from "http";
|
|
223
|
+
import { WebSocketServer } from "ws";
|
|
224
|
+
import { Application } from "okgoes-core";
|
|
225
|
+
|
|
226
|
+
const app = new Application(baseDir, config);
|
|
227
|
+
const koa = await app.startWithoutListen();
|
|
228
|
+
const server = http.createServer(koa.callback());
|
|
229
|
+
new WebSocketServer({ server });
|
|
230
|
+
server.listen(3000);
|
|
231
|
+
```
|
|
232
|
+
|
|
233
|
+
或直接 `app.callback()` 拿到 koa callback 用于 `http.createServer`。
|
|
234
|
+
|
|
235
|
+
## 自定义调度(dispatch)
|
|
236
|
+
|
|
237
|
+
`Application.dispatch(controllerClass, actionName, ctx, resolvedRoute?, routeParams?)` 可独立调用,
|
|
238
|
+
自动处理:实例化、initialize、HTTP method 装饰器约束、返回值自动响应(对象→JSON,字符串→HTML)。
|
|
239
|
+
|
|
240
|
+
```ts
|
|
241
|
+
// 自定义 404 重定向 + 权限前置 + 约定路由兜底
|
|
242
|
+
app.use(async (ctx, next) => {
|
|
243
|
+
const resolver = app.createRouteResolver(ctx.path);
|
|
244
|
+
const route = resolver.getResolvedRoute();
|
|
245
|
+
ctx.state.resolvedRoute = route;
|
|
246
|
+
if (!await hasPermission(route)) { ctx.redirect("/login"); return; }
|
|
247
|
+
const ControllerClass = loadControllerClass(...);
|
|
248
|
+
if (!ControllerClass) { ctx.redirect("/page/404"); return; }
|
|
249
|
+
await app.dispatch(ControllerClass, route.actionName, ctx, route);
|
|
250
|
+
});
|
|
251
|
+
```
|
|
252
|
+
|
|
253
|
+
也可用导出的 `createConventionRouter({ baseDir, routing, notFound })` 工厂单独创建约定路由中间件。
|
|
254
|
+
|
|
255
|
+
## bare 模式 / 完全手动装配
|
|
256
|
+
|
|
257
|
+
```ts
|
|
258
|
+
new Application(baseDir, { bare: true }); // 跳过所有核心中间件自动装配
|
|
259
|
+
// 等价
|
|
260
|
+
new Application(baseDir, { autoLoad: false });
|
|
261
|
+
```
|
|
262
|
+
|
|
263
|
+
## ctx 自定义属性类型扩展
|
|
264
|
+
|
|
265
|
+
框架自身把 `resolvedRoute` 写入 `ctx.state.resolvedRoute`,业务方可通过 `declare module` 扩展:
|
|
266
|
+
|
|
267
|
+
```ts
|
|
268
|
+
declare module "okgoes-core" {
|
|
269
|
+
interface ContextState {
|
|
270
|
+
userId?: number;
|
|
271
|
+
}
|
|
272
|
+
}
|
|
273
|
+
// 中间件内 ctx.state.userId 有类型
|
|
274
|
+
```
|
|
275
|
+
|
|
276
|
+
## 插件
|
|
277
|
+
|
|
278
|
+
```ts
|
|
279
|
+
export default function metricsPlugin(): OkgoesPlugin {
|
|
280
|
+
return {
|
|
281
|
+
name: "metrics",
|
|
282
|
+
install(app, options) {
|
|
283
|
+
let count = 0;
|
|
284
|
+
app.service("metrics", { count: () => count }); // controller 内 this.service("metrics")
|
|
285
|
+
app.use(async (ctx, next) => { count++; await next(); });
|
|
286
|
+
},
|
|
287
|
+
};
|
|
288
|
+
}
|
|
289
|
+
|
|
290
|
+
app.usePlugin(metricsPlugin(), { prefix: "[demo]" });
|
|
291
|
+
```
|
|
292
|
+
|
|
293
|
+
## CORS `allowHeaders: "*"` 行为说明
|
|
294
|
+
|
|
295
|
+
当 `allowHeaders` 未提供时,框架透传请求头 `Access-Control-Request-Headers`(兼容 `credentials: true`)。
|
|
296
|
+
显式传 `"*"` 会原样写入 `Access-Control-Allow-Headers: *`;按 CORS 规范,`*` 与 `credentials: true` 同时使用时
|
|
297
|
+
部分浏览器不生效,建议省略 `allowHeaders` 或显式列出所需头。
|
|
298
|
+
|
|
299
|
+
## API 速查
|
|
300
|
+
|
|
301
|
+
| 名称 | 说明 |
|
|
302
|
+
|------|------|
|
|
303
|
+
| `Application.use(fn)` | 推入自定义中间件(晚于核心中间件) |
|
|
304
|
+
| `Application.useBefore(stage, fn)` | 在核心阶段之前插入 |
|
|
305
|
+
| `Application.useAfter(stage, fn)` | 在核心阶段之后插入 |
|
|
306
|
+
| `Application.useAt(stage, fn)` | 等价于 useBefore |
|
|
307
|
+
| `Application.callback()` | 返回 koa callback,用于自定义 server |
|
|
308
|
+
| `Application.startWithoutListen()` | 装配但不 listen,返回 koa 实例 |
|
|
309
|
+
| `Application.dispatch(...)` | 手动调度控制器 action |
|
|
310
|
+
| `Application.createConventionRouteMiddleware()` | 取出约定路由中间件(public) |
|
|
311
|
+
| `Application.getRoutingConfig()` | 暴露路由配置,避免多处定义 |
|
|
312
|
+
| `Application.createRouteResolver(pathname)` | 复用 app config 创建 RouteResolver |
|
|
313
|
+
| `createConventionRouter({ baseDir, routing, notFound })` | 独立创建约定路由中间件工厂 |
|
|
314
|
+
| `createProxy(options)` | 反向代理中间件工厂,键为路径前缀 |
|
|
315
|
+
| `Application.handleError(err, ctx)` | 手动触发统一异常处理链 |
|
|
316
|
+
| `Application.captureProcessErrors(opts)` | 挂接进程级 uncaughtException / unhandledRejection |
|
|
317
|
+
| `CoreMiddleware` | 核心中间件阶段名常量 |
|
|
318
|
+
| `HttpMethod` | HTTP 方法常量与类型 |
|
|
319
|
+
| `UploadedFile` | 上传文件类型 |
|
|
320
|
+
| `Koa` | 底层内核类(已导出) |
|
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
import Koa from "./core/koa";
|
|
2
|
+
import Context from "./core/context";
|
|
3
|
+
import { AppConfig, Middleware, OkgoesPlugin, ResolvedRoute, RoutingConfig } from "./types";
|
|
4
|
+
import { ResolvedConfig } from "./config";
|
|
5
|
+
import RouteResolver from "./route-resolver";
|
|
6
|
+
import Router from "./router";
|
|
7
|
+
import { CoreMiddlewareName } from "./constants";
|
|
8
|
+
export interface OkgoesLogger {
|
|
9
|
+
info(...args: any[]): void;
|
|
10
|
+
warn(...args: any[]): void;
|
|
11
|
+
error(...args: any[]): void;
|
|
12
|
+
}
|
|
13
|
+
export { CoreMiddleware, CoreMiddlewareName } from "./constants";
|
|
14
|
+
export default class Application {
|
|
15
|
+
readonly baseDir: string;
|
|
16
|
+
readonly koa: Koa;
|
|
17
|
+
readonly router: Router;
|
|
18
|
+
config: ResolvedConfig;
|
|
19
|
+
logger: OkgoesLogger;
|
|
20
|
+
private readonly services;
|
|
21
|
+
private readonly customMiddlewares;
|
|
22
|
+
private readonly stagedMiddlewares;
|
|
23
|
+
private readonly pluginRegistrations;
|
|
24
|
+
private isStarted;
|
|
25
|
+
constructor(baseDir: string, config?: AppConfig);
|
|
26
|
+
use(middleware: Middleware): this;
|
|
27
|
+
/**
|
|
28
|
+
* 在指定核心中间件之前插入自定义中间件。
|
|
29
|
+
* 例:app.useBefore("cors", authMiddleware) 让鉴权先于 CORS 执行。
|
|
30
|
+
* 必须在 start() 之前调用。
|
|
31
|
+
*/
|
|
32
|
+
useBefore(stage: CoreMiddlewareName | string, middleware: Middleware): this;
|
|
33
|
+
/** 在指定核心中间件之后插入自定义中间件。 */
|
|
34
|
+
useAfter(stage: CoreMiddlewareName | string, middleware: Middleware): this;
|
|
35
|
+
/** 在指定核心中间件位置插入(替换语义:在该阶段之前执行)。等价于 useBefore。 */
|
|
36
|
+
useAt(stage: CoreMiddlewareName | string, middleware: Middleware): this;
|
|
37
|
+
usePlugin(plugin: OkgoesPlugin, options?: any): this;
|
|
38
|
+
service(name: string, instance: any): this;
|
|
39
|
+
getService<T = any>(name: string): T;
|
|
40
|
+
hasService(name: string): boolean;
|
|
41
|
+
get controllerBaseDir(): string;
|
|
42
|
+
/** 暴露路由配置,供外部构造 RouteResolver 时复用,避免多处定义不一致。 */
|
|
43
|
+
getRoutingConfig(): RoutingConfig;
|
|
44
|
+
/** 复用 app 的 config 创建 RouteResolver,避免每次手动构造 RoutingConfig。 */
|
|
45
|
+
createRouteResolver(pathname: string): RouteResolver;
|
|
46
|
+
/** 直接返回 koa callback,用于 http.createServer(app.callback()) 自定义 server / WebSocket 共用端口。 */
|
|
47
|
+
callback(): (req: any, res: any) => void;
|
|
48
|
+
/**
|
|
49
|
+
* 装配中间件但不 listen,返回 koa 实例。
|
|
50
|
+
* 用于 WebSocket / HTTPS / 自定义 server 场景:const server = http.createServer(app.startWithoutListen().callback());
|
|
51
|
+
*/
|
|
52
|
+
startWithoutListen(): Promise<Koa>;
|
|
53
|
+
start(): Promise<Koa>;
|
|
54
|
+
private ensureMiddlewaresMounted;
|
|
55
|
+
/**
|
|
56
|
+
* 装配核心中间件与分阶段插入的自定义中间件。
|
|
57
|
+
* 顺序:error → [before/after error] → accessLog → ... → static → [after static]
|
|
58
|
+
* bare 模式下跳过所有核心中间件,仅保留 error 兜底与分阶段插入项。
|
|
59
|
+
*/
|
|
60
|
+
private assembleMiddlewares;
|
|
61
|
+
private createProxyMiddleware;
|
|
62
|
+
private createViewsMiddleware;
|
|
63
|
+
private createStaticMiddleware;
|
|
64
|
+
private flushStagedBefore;
|
|
65
|
+
private flushStagedAfter;
|
|
66
|
+
private flushStagedAround;
|
|
67
|
+
private createErrorHandlerMiddleware;
|
|
68
|
+
/**
|
|
69
|
+
* 全局异常统一入口。处理优先级:
|
|
70
|
+
* handler > byStatus[code] > redirect > render > 默认响应。
|
|
71
|
+
* debug 模式输出完整堆栈与请求详情;非 debug 仅暴露 4xx 或 err.expose 的 message。
|
|
72
|
+
*/
|
|
73
|
+
handleError(err: any, ctx: Context): Promise<void>;
|
|
74
|
+
/** 渲染约定错误页 views/error/{status}.ext,模板不存在时返回 false 回退默认响应 */
|
|
75
|
+
private renderErrorPage;
|
|
76
|
+
/** 默认错误响应体:debug 或 expose 时输出详情,否则仅暴露 4xx / err.expose 的 message */
|
|
77
|
+
private writeDefaultErrorBody;
|
|
78
|
+
/**
|
|
79
|
+
* 可选挂接进程级未捕获异常(uncaughtException / unhandledRejection)。
|
|
80
|
+
* 默认仅日志记录不退出进程;传入 { exit: true } 时在 uncaughtException 后退出,
|
|
81
|
+
* 便于配合 PM2 / systemd 等进程管理器自动重启。
|
|
82
|
+
*/
|
|
83
|
+
captureProcessErrors(options?: {
|
|
84
|
+
exit?: boolean;
|
|
85
|
+
onUncaught?: (err: Error) => void;
|
|
86
|
+
onUnhandled?: (err: any) => void;
|
|
87
|
+
}): this;
|
|
88
|
+
/** 约定路由 / dispatch 命中失败时统一走此处的 404 处理,支持 redirect / handler / 事件。 */
|
|
89
|
+
private handleNotFound;
|
|
90
|
+
private createAccessLogMiddleware;
|
|
91
|
+
private mountRouterLayer;
|
|
92
|
+
private resolveSourceFile;
|
|
93
|
+
/**
|
|
94
|
+
* 约定路由中间件(public,可单独取出用于自定义调度)。
|
|
95
|
+
* 解析 URL → 定位控制器文件 → 加载控制器类 → dispatch。
|
|
96
|
+
* 控制器不存在时调用 next(),由 error handler 兜底为 404。
|
|
97
|
+
*/
|
|
98
|
+
createConventionRouteMiddleware(): Middleware;
|
|
99
|
+
/** 实例化控制器、注入请求响应并执行 action,返回值自动写入响应 */
|
|
100
|
+
dispatch(controllerClass: new () => any, actionName: string, ctx: Context, resolvedRoute?: ResolvedRoute | null, routeParams?: Record<string, string>): Promise<void>;
|
|
101
|
+
}
|