koatty 4.3.3 → 5.0.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/CHANGELOG.md +85 -0
- package/dist/index.d.ts +1 -1
- package/dist/index.js +331 -43
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +340 -43
- package/dist/index.mjs.map +1 -1
- package/dist/package.json +21 -14
- package/package.json +20 -13
- package/.rollup.config.js +0 -89
- package/.turbo/turbo-build.log +0 -99
- package/.turbo/turbo-clean.log +0 -4
- package/.turbo/turbo-lint.log +0 -18
- package/.turbo/turbo-test.log +0 -114
- package/TASKS.md +0 -1227
- package/examples/README.md +0 -172
- package/examples/basic-app/README.md +0 -72
- package/examples/basic-app/package.json +0 -23
- package/examples/basic-app/pnpm-workspace.yaml +0 -4
- package/examples/basic-app/resource/data.json +0 -2
- package/examples/basic-app/resource/graphql/User.graphql +0 -22
- package/examples/basic-app/resource/proto/.gitkeep +0 -0
- package/examples/basic-app/resource/proto/hello.proto +0 -19
- package/examples/basic-app/static/.gitkeep +0 -0
- package/examples/basic-app/static/favicon.ico +0 -0
- package/examples/basic-app/test-app.js +0 -28
- package/examples/basic-app/test-logger.js +0 -19
- package/examples/basic-app/test-simple.ts +0 -13
- package/examples/basic-app/view/index.html +0 -25
- package/tsconfig.test.json +0 -16
- package/tsconfig.tsbuildinfo +0 -1
- package/tsup.config.ts +0 -6
package/dist/index.mjs
CHANGED
|
@@ -1,8 +1,11 @@
|
|
|
1
|
+
import { createRequire } from 'node:module';
|
|
2
|
+
import { fileURLToPath } from 'node:url';
|
|
3
|
+
import { dirname } from 'node:path';
|
|
1
4
|
import { LoadConfigs } from 'koatty_config';
|
|
2
5
|
export { Config } from 'koatty_config';
|
|
3
|
-
import { IOC, TAGGED_CLS } from 'koatty_container';
|
|
6
|
+
import { IOC, TAGGED_CLS, Container } from 'koatty_container';
|
|
4
7
|
export * from 'koatty_container';
|
|
5
|
-
import { AppEvent, AppEventArr, asyncEvent, ComponentManager, implementsMiddlewareInterface, MIDDLEWARE_OPTIONS, protocolMiddleware,
|
|
8
|
+
import { AppEvent, AppEventArr, asyncEvent, ComponentManager, implementsMiddlewareInterface, MIDDLEWARE_OPTIONS, protocolMiddleware, implementsServiceInterface, implementsAspectInterface, Koatty } from 'koatty_core';
|
|
6
9
|
export * from 'koatty_core';
|
|
7
10
|
export * from 'koatty_exception';
|
|
8
11
|
import { Helper } from 'koatty_lib';
|
|
@@ -10,14 +13,18 @@ export { Helper } from 'koatty_lib';
|
|
|
10
13
|
export * from 'koatty_router';
|
|
11
14
|
export * from 'koatty_serve';
|
|
12
15
|
import { DefaultLogger } from 'koatty_logger';
|
|
13
|
-
export { Log,
|
|
16
|
+
export { Log, DefaultLogger as Logger } from 'koatty_logger';
|
|
14
17
|
import { Load } from 'koatty_loader';
|
|
15
18
|
import { Trace } from 'koatty_trace';
|
|
16
19
|
import * as path from 'path';
|
|
20
|
+
import * as fs from 'fs';
|
|
17
21
|
|
|
22
|
+
createRequire(import.meta.url);
|
|
23
|
+
const __filename$1 = fileURLToPath(import.meta.url);
|
|
24
|
+
const __dirname$1 = dirname(__filename$1);
|
|
18
25
|
/*!
|
|
19
26
|
* @Author: richen
|
|
20
|
-
* @Date: 2026-09-
|
|
27
|
+
* @Date: 2026-09-30 05:09:10
|
|
21
28
|
* @License: BSD (3-Clause)
|
|
22
29
|
* @Copyright (c) - <richenlin(at)gmail.com>
|
|
23
30
|
* @HomePage: https://koatty.org/
|
|
@@ -34,7 +41,7 @@ var require_package = __commonJS({
|
|
|
34
41
|
"package.json"(exports$1, module) {
|
|
35
42
|
module.exports = {
|
|
36
43
|
name: "koatty",
|
|
37
|
-
version: "
|
|
44
|
+
version: "5.0.0",
|
|
38
45
|
description: "Koa + Typescript = koatty. Use Typescript's decorator implement auto injection.",
|
|
39
46
|
scripts: {
|
|
40
47
|
build: "pnpm run build:js && pnpm run build:dts && pnpm run build:doc && pnpm run build:cp",
|
|
@@ -45,7 +52,8 @@ var require_package = __commonJS({
|
|
|
45
52
|
clean: "rimraf dist temp docs/api",
|
|
46
53
|
lint: "eslint --ext .ts,.js ./src",
|
|
47
54
|
test: "pnpm run lint && jest --passWithNoTests",
|
|
48
|
-
"test:cov": "jest --collectCoverage --detectOpenHandles"
|
|
55
|
+
"test:cov": "jest --collectCoverage --detectOpenHandles",
|
|
56
|
+
"test:example": "jest --config examples/mcp-order-service/jest.config.js --coverage=false"
|
|
49
57
|
},
|
|
50
58
|
main: "./dist/index.js",
|
|
51
59
|
exports: {
|
|
@@ -142,7 +150,13 @@ var require_package = __commonJS({
|
|
|
142
150
|
koatty_trace: "workspace:*",
|
|
143
151
|
"ts-morph": "^27.0.2"
|
|
144
152
|
},
|
|
145
|
-
types: "./dist/index.d.ts"
|
|
153
|
+
types: "./dist/index.d.ts",
|
|
154
|
+
files: [
|
|
155
|
+
"dist",
|
|
156
|
+
"README.md",
|
|
157
|
+
"CHANGELOG.md",
|
|
158
|
+
"LICENSE"
|
|
159
|
+
]
|
|
146
160
|
};
|
|
147
161
|
}
|
|
148
162
|
});
|
|
@@ -189,7 +203,7 @@ function checkRuntime() {
|
|
|
189
203
|
__name(checkRuntime, "checkRuntime");
|
|
190
204
|
var checkUTRuntime = /* @__PURE__ */ __name(() => {
|
|
191
205
|
let isUTRuntime = false;
|
|
192
|
-
const argv =
|
|
206
|
+
const argv = String(process.argv[1] ?? "");
|
|
193
207
|
if (argv.indexOf("jest") > -1) {
|
|
194
208
|
isUTRuntime = true;
|
|
195
209
|
}
|
|
@@ -207,11 +221,264 @@ var LOGO = `
|
|
|
207
221
|
-------------------------------------------
|
|
208
222
|
https://github.com/koatty
|
|
209
223
|
`;
|
|
224
|
+
|
|
225
|
+
// src/config/config.ts
|
|
226
|
+
var config_default = {
|
|
227
|
+
/*app config*/
|
|
228
|
+
logsLevel: "debug"
|
|
229
|
+
};
|
|
230
|
+
|
|
231
|
+
// src/config/middleware.ts
|
|
232
|
+
var middleware_default = {
|
|
233
|
+
// List of loaded middleware(except for the middleware loaded by default),
|
|
234
|
+
// executed in the order of elements
|
|
235
|
+
list: [],
|
|
236
|
+
// middleware configuration
|
|
237
|
+
config: {
|
|
238
|
+
// ============================================
|
|
239
|
+
// Trace Middleware - 请求链路追踪中间件
|
|
240
|
+
// ============================================
|
|
241
|
+
// Koatty-Trace 用于追踪请求链路、记录日志、收集指标
|
|
242
|
+
// 它会自动作为第一个中间件加载,无需添加到 list 中
|
|
243
|
+
trace: {
|
|
244
|
+
// response timeout in milliseconds
|
|
245
|
+
timeout: 1e4,
|
|
246
|
+
// request id header name
|
|
247
|
+
requestIdHeaderName: "X-Request-Id",
|
|
248
|
+
// request id name
|
|
249
|
+
requestIdName: "requestId",
|
|
250
|
+
// id generator function
|
|
251
|
+
// idFactory: Function,
|
|
252
|
+
// encoding
|
|
253
|
+
encoding: "utf-8",
|
|
254
|
+
// Whether to enable trace (default: false)
|
|
255
|
+
enableTrace: false,
|
|
256
|
+
// asynchooks enabled
|
|
257
|
+
asyncHooks: false,
|
|
258
|
+
/**
|
|
259
|
+
* Metrics configuration
|
|
260
|
+
*/
|
|
261
|
+
metricsConf: {
|
|
262
|
+
/**
|
|
263
|
+
* Metrics reporter function
|
|
264
|
+
*/
|
|
265
|
+
// reporter: (metrics: {
|
|
266
|
+
// duration: number,
|
|
267
|
+
// status: number,
|
|
268
|
+
// path: string,
|
|
269
|
+
// attributes: Record<string, any>,
|
|
270
|
+
// }) => void,
|
|
271
|
+
/**
|
|
272
|
+
* Default attributes for metrics
|
|
273
|
+
*/
|
|
274
|
+
defaultAttributes: {},
|
|
275
|
+
/**
|
|
276
|
+
* Prometheus metrics endpoint (production only)
|
|
277
|
+
*/
|
|
278
|
+
metricsEndpoint: "/metrics",
|
|
279
|
+
/**
|
|
280
|
+
* Metrics report interval in milliseconds (default: 5000)
|
|
281
|
+
*/
|
|
282
|
+
reportInterval: 5e3,
|
|
283
|
+
/**
|
|
284
|
+
* Prometheus metrics port (default: 9464)
|
|
285
|
+
*/
|
|
286
|
+
metricsPort: 9464
|
|
287
|
+
},
|
|
288
|
+
/**
|
|
289
|
+
* OpenTelemetry configuration
|
|
290
|
+
*/
|
|
291
|
+
opentelemetryConf: {
|
|
292
|
+
/**
|
|
293
|
+
* OTLP endpoint URL
|
|
294
|
+
*/
|
|
295
|
+
endpoint: "http://localhost:4318/v1/traces",
|
|
296
|
+
/**
|
|
297
|
+
* Whether to enable topology analysis (default: same as enableTrace)
|
|
298
|
+
*
|
|
299
|
+
*/
|
|
300
|
+
enableTopology: false,
|
|
301
|
+
/**
|
|
302
|
+
* OTLP headers
|
|
303
|
+
*/
|
|
304
|
+
headers: {},
|
|
305
|
+
/**
|
|
306
|
+
* Resource attributes
|
|
307
|
+
*/
|
|
308
|
+
resourceAttributes: {},
|
|
309
|
+
/**
|
|
310
|
+
* Instrumentations to enable
|
|
311
|
+
*/
|
|
312
|
+
instrumentations: [],
|
|
313
|
+
/**
|
|
314
|
+
* Exporter timeout in milliseconds
|
|
315
|
+
*/
|
|
316
|
+
timeout: 1e4,
|
|
317
|
+
/**
|
|
318
|
+
* Maximum lifetime for a span in milliseconds
|
|
319
|
+
*/
|
|
320
|
+
spanTimeout: 3e4,
|
|
321
|
+
/**
|
|
322
|
+
* Maximum number of active spans in memory (default: 1000)
|
|
323
|
+
*/
|
|
324
|
+
maxActiveSpans: 1e3,
|
|
325
|
+
/**
|
|
326
|
+
* Request attributes to be added to the span
|
|
327
|
+
*/
|
|
328
|
+
// spanAttributes: (ctx: KoattyContext) => Record<string, any>,
|
|
329
|
+
/**
|
|
330
|
+
* Sampling rate (0.0 - 1.0)
|
|
331
|
+
*/
|
|
332
|
+
samplingRate: 1,
|
|
333
|
+
/**
|
|
334
|
+
* Maximum number of spans in batch queue
|
|
335
|
+
*/
|
|
336
|
+
batchMaxQueueSize: 2048,
|
|
337
|
+
/**
|
|
338
|
+
* Maximum number of spans to export in one batch
|
|
339
|
+
*/
|
|
340
|
+
batchMaxExportSize: 512,
|
|
341
|
+
/**
|
|
342
|
+
* Delay between batch exports in milliseconds
|
|
343
|
+
*/
|
|
344
|
+
batchDelayMillis: 5e3,
|
|
345
|
+
/**
|
|
346
|
+
* Timeout for batch export in milliseconds
|
|
347
|
+
*/
|
|
348
|
+
batchExportTimeout: 3e4
|
|
349
|
+
},
|
|
350
|
+
/**
|
|
351
|
+
* Retry configuration
|
|
352
|
+
*/
|
|
353
|
+
retryConf: {
|
|
354
|
+
/**
|
|
355
|
+
* Whether to enable retry mechanism (default: false)
|
|
356
|
+
*/
|
|
357
|
+
enabled: false,
|
|
358
|
+
/**
|
|
359
|
+
* Max retry count when error occurs (default: 3)
|
|
360
|
+
*/
|
|
361
|
+
count: 3,
|
|
362
|
+
/**
|
|
363
|
+
* Retry interval in milliseconds (default: 1000)
|
|
364
|
+
*/
|
|
365
|
+
interval: 1e3
|
|
366
|
+
}
|
|
367
|
+
}
|
|
368
|
+
}
|
|
369
|
+
};
|
|
370
|
+
|
|
371
|
+
// src/config/plugin.ts
|
|
372
|
+
var plugin_default = {
|
|
373
|
+
// ============================================================
|
|
374
|
+
// User plugin loading list (executed in order)
|
|
375
|
+
// Note: Core components (@Component) are loaded automatically
|
|
376
|
+
// ============================================================
|
|
377
|
+
list: [],
|
|
378
|
+
// ============================================================
|
|
379
|
+
// Component/Plugin configuration
|
|
380
|
+
// ============================================================
|
|
381
|
+
config: {
|
|
382
|
+
// --- Core components (@Component) ---
|
|
383
|
+
// Framework built-in components, usually do not need to modify
|
|
384
|
+
// Can be disabled by setting enabled: false
|
|
385
|
+
RouterComponent: {
|
|
386
|
+
enabled: true
|
|
387
|
+
},
|
|
388
|
+
ServeComponent: {
|
|
389
|
+
enabled: true
|
|
390
|
+
}
|
|
391
|
+
}
|
|
392
|
+
};
|
|
393
|
+
|
|
394
|
+
// src/config/router.ts
|
|
395
|
+
var router_default = {
|
|
396
|
+
/**
|
|
397
|
+
* prefix of the router
|
|
398
|
+
*/
|
|
399
|
+
// prefix: string,
|
|
400
|
+
/**
|
|
401
|
+
* Methods which should be supported by the router.
|
|
402
|
+
*/
|
|
403
|
+
// methods?: string[];
|
|
404
|
+
// routerPath?: string;
|
|
405
|
+
/**
|
|
406
|
+
* Whether or not routing should be case-sensitive.
|
|
407
|
+
*/
|
|
408
|
+
// sensitive?: boolean;
|
|
409
|
+
/**
|
|
410
|
+
* Whether or not routes should matched strictly.
|
|
411
|
+
*
|
|
412
|
+
* If strict matching is enabled, the trailing slash is taken into
|
|
413
|
+
* account when matching routes.
|
|
414
|
+
*/
|
|
415
|
+
// strict?: boolean;
|
|
416
|
+
/**
|
|
417
|
+
* payload options
|
|
418
|
+
*
|
|
419
|
+
*/
|
|
420
|
+
payload: {
|
|
421
|
+
extTypes: {
|
|
422
|
+
json: [
|
|
423
|
+
"application/json"
|
|
424
|
+
],
|
|
425
|
+
form: [
|
|
426
|
+
"application/x-www-form-urlencoded"
|
|
427
|
+
],
|
|
428
|
+
text: [
|
|
429
|
+
"text/plain"
|
|
430
|
+
],
|
|
431
|
+
multipart: [
|
|
432
|
+
"multipart/form-data"
|
|
433
|
+
],
|
|
434
|
+
xml: [
|
|
435
|
+
"text/xml"
|
|
436
|
+
],
|
|
437
|
+
grpc: [
|
|
438
|
+
"application/grpc"
|
|
439
|
+
],
|
|
440
|
+
graphql: [
|
|
441
|
+
"application/graphql+json"
|
|
442
|
+
],
|
|
443
|
+
websocket: [
|
|
444
|
+
"application/websocket"
|
|
445
|
+
]
|
|
446
|
+
},
|
|
447
|
+
// body-size limit intentionally unset (ADR-102): the security profile
|
|
448
|
+
// decides (1mb in production, 20mb in development) unless the project
|
|
449
|
+
// config/router.ts sets payload.limit explicitly
|
|
450
|
+
encoding: "utf-8",
|
|
451
|
+
multiples: true
|
|
452
|
+
}
|
|
453
|
+
};
|
|
454
|
+
|
|
455
|
+
// src/config/server.ts
|
|
456
|
+
var server_default = {
|
|
457
|
+
hostname: process.env.IP || "127.0.0.1",
|
|
458
|
+
// server port: single value (e.g. 3000) or array (e.g. [3000, 3001])
|
|
459
|
+
// For multi-protocol: if port is array, each port maps to corresponding protocol
|
|
460
|
+
// If port is single value, first protocol uses it, others auto-increment (3000, 3001, 3002...)
|
|
461
|
+
port: process.env.PORT || process.env.APP_PORT || 3e3,
|
|
462
|
+
// Server protocol: 'http' | 'https' | 'http2' | 'grpc' | 'ws' | 'wss' | 'graphql'
|
|
463
|
+
// For multi-protocol: use array like ["http", "grpc"] and configure ext below
|
|
464
|
+
protocol: "http",
|
|
465
|
+
trace: false,
|
|
466
|
+
ssl: {
|
|
467
|
+
mode: "auto",
|
|
468
|
+
key: "",
|
|
469
|
+
cert: "",
|
|
470
|
+
ca: ""
|
|
471
|
+
// ca file path
|
|
472
|
+
}
|
|
473
|
+
};
|
|
474
|
+
|
|
475
|
+
// src/core/Loader.ts
|
|
210
476
|
var Loader = class _Loader {
|
|
211
477
|
static {
|
|
212
478
|
__name(this, "Loader");
|
|
213
479
|
}
|
|
214
480
|
app;
|
|
481
|
+
static loggingApps = /* @__PURE__ */ new Set();
|
|
215
482
|
/**
|
|
216
483
|
* Creates an instance of Loader.
|
|
217
484
|
* @param {KoattyApplication} app
|
|
@@ -239,7 +506,7 @@ var Loader = class _Loader {
|
|
|
239
506
|
}
|
|
240
507
|
const rootPath = app.rootPath || process.cwd();
|
|
241
508
|
const appPath = app.appPath || path.resolve(rootPath, app.appDebug ? "src" : "dist");
|
|
242
|
-
const koattyPath = path.resolve(__dirname, "..");
|
|
509
|
+
const koattyPath = path.resolve(__dirname$1, "..");
|
|
243
510
|
Helper.define(app, "rootPath", rootPath);
|
|
244
511
|
Helper.define(app, "appPath", appPath);
|
|
245
512
|
Helper.define(app, "koattyPath", koattyPath);
|
|
@@ -250,6 +517,11 @@ var Loader = class _Loader {
|
|
|
250
517
|
app.version = app.version || pkg2.version;
|
|
251
518
|
}
|
|
252
519
|
}
|
|
520
|
+
Helper.define(app, "paths", {
|
|
521
|
+
rootPath,
|
|
522
|
+
appPath,
|
|
523
|
+
koattyPath
|
|
524
|
+
});
|
|
253
525
|
process.env.ROOT_PATH = rootPath;
|
|
254
526
|
process.env.APP_PATH = appPath;
|
|
255
527
|
process.env.KOATTY_PATH = koattyPath;
|
|
@@ -314,16 +586,31 @@ var Loader = class _Loader {
|
|
|
314
586
|
const componentMetas = _Loader.GetComponentMeta(app, target);
|
|
315
587
|
const configurationMetas = _Loader.GetConfigurationMeta(app, target);
|
|
316
588
|
const exSet = /* @__PURE__ */ new Set();
|
|
317
|
-
|
|
589
|
+
const manifestFile = path.join(app.rootPath, ".koatty", "manifest.json");
|
|
590
|
+
Load(componentMetas, app.rootPath, (fileName, xpath, xTarget) => {
|
|
318
591
|
checkClass(fileName, xpath, xTarget, exSet);
|
|
592
|
+
const exports$1 = typeof xTarget === "function" ? [
|
|
593
|
+
xTarget
|
|
594
|
+
] : Object.values(xTarget ?? {});
|
|
595
|
+
for (const component of exports$1) {
|
|
596
|
+
if (Helper.isClass(component)) app.container.saveClass(IOC.getType(component), component, IOC.getIdentifier(component));
|
|
597
|
+
}
|
|
319
598
|
}, [
|
|
320
599
|
"**/**.js",
|
|
321
600
|
"**/**.ts",
|
|
322
601
|
"!**/**.d.ts"
|
|
323
602
|
], [
|
|
324
603
|
...configurationMetas,
|
|
325
|
-
`${target.name || ".no"}.ts
|
|
326
|
-
|
|
604
|
+
`${target.name || ".no"}.ts`,
|
|
605
|
+
`${target.name || ".no"}.js`
|
|
606
|
+
], {
|
|
607
|
+
manifestFile: app.env === "production" && fs.existsSync(manifestFile) ? manifestFile : void 0
|
|
608
|
+
});
|
|
609
|
+
for (const item of IOC.listClass("COMPONENT")) {
|
|
610
|
+
const id = IOC.getIdentifier(item.target);
|
|
611
|
+
const options = IOC.getPropertyData("COMPONENT_OPTIONS", item.target, id);
|
|
612
|
+
if (options?.scope === "core") app.container.saveClass("COMPONENT", item.target, id);
|
|
613
|
+
}
|
|
327
614
|
exSet.clear();
|
|
328
615
|
}
|
|
329
616
|
/**
|
|
@@ -338,6 +625,7 @@ var Loader = class _Loader {
|
|
|
338
625
|
const data = app.getMetaData("_configs") || [];
|
|
339
626
|
const configs = data[0] || {};
|
|
340
627
|
if (configs.config) {
|
|
628
|
+
_Loader.loggingApps.add(app);
|
|
341
629
|
const opt = configs.config;
|
|
342
630
|
let logLevel = "debug", logFilePath = "", sensFields = [];
|
|
343
631
|
if (app.env === "production") {
|
|
@@ -372,7 +660,8 @@ var Loader = class _Loader {
|
|
|
372
660
|
}
|
|
373
661
|
app.once(AppEvent.appStop, async () => {
|
|
374
662
|
await DefaultLogger.flushBatch();
|
|
375
|
-
|
|
663
|
+
_Loader.loggingApps.delete(app);
|
|
664
|
+
if (_Loader.loggingApps.size === 0) DefaultLogger.enableBatch(false);
|
|
376
665
|
});
|
|
377
666
|
}
|
|
378
667
|
}
|
|
@@ -393,8 +682,8 @@ var Loader = class _Loader {
|
|
|
393
682
|
*/
|
|
394
683
|
static async LoadAllComponents(app, target) {
|
|
395
684
|
try {
|
|
396
|
-
if (Helper.isFunction(
|
|
397
|
-
|
|
685
|
+
if (Helper.isFunction(app.container.preloadMetadata)) {
|
|
686
|
+
app.container.preloadMetadata();
|
|
398
687
|
}
|
|
399
688
|
} catch (error) {
|
|
400
689
|
DefaultLogger.Error("[Loader] preloadMetadata failed:", error);
|
|
@@ -450,12 +739,15 @@ var Loader = class _Loader {
|
|
|
450
739
|
await asyncEvent(app, event);
|
|
451
740
|
break;
|
|
452
741
|
case AppEvent.loadServe:
|
|
742
|
+
await app.container?.ready?.();
|
|
453
743
|
DefaultLogger.Log("Koatty", "", "Emit loadServe ...");
|
|
454
744
|
await asyncEvent(app, event);
|
|
455
745
|
break;
|
|
456
746
|
case AppEvent.appReady:
|
|
457
747
|
DefaultLogger.Log("Koatty", "", "Emit appReady ...");
|
|
458
748
|
await asyncEvent(app, event);
|
|
749
|
+
await app.container?.ready?.();
|
|
750
|
+
app.container?.seal?.();
|
|
459
751
|
break;
|
|
460
752
|
default:
|
|
461
753
|
await asyncEvent(app, event);
|
|
@@ -473,18 +765,23 @@ var Loader = class _Loader {
|
|
|
473
765
|
* @param {string[]} [loadPath] - Optional array of paths to load application configs from
|
|
474
766
|
*/
|
|
475
767
|
LoadConfigs(loadPath) {
|
|
476
|
-
const frameConfig = {
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
768
|
+
const frameConfig = Helper.clone({
|
|
769
|
+
config: config_default,
|
|
770
|
+
middleware: middleware_default,
|
|
771
|
+
plugin: plugin_default,
|
|
772
|
+
router: router_default,
|
|
773
|
+
server: server_default
|
|
774
|
+
}, true);
|
|
482
775
|
if (Helper.isArray(loadPath)) {
|
|
483
776
|
loadPath = loadPath.length > 0 ? loadPath : [
|
|
484
777
|
"./config"
|
|
485
778
|
];
|
|
486
779
|
}
|
|
487
|
-
|
|
780
|
+
const manifest = path.join(this.app.rootPath, ".koatty/manifest.json");
|
|
781
|
+
let appConfig = LoadConfigs(loadPath, this.app.appPath, void 0, void 0, void 0, this.app.env === "production" && fs.existsSync(manifest) ? {
|
|
782
|
+
manifestFile: manifest,
|
|
783
|
+
baseDir: this.app.rootPath
|
|
784
|
+
} : void 0);
|
|
488
785
|
appConfig = Helper.extend(frameConfig, appConfig, true);
|
|
489
786
|
this.app.setMetaData("_configs", appConfig);
|
|
490
787
|
}
|
|
@@ -516,16 +813,16 @@ var Loader = class _Loader {
|
|
|
516
813
|
} catch (error) {
|
|
517
814
|
DefaultLogger.Warn(`Trace middleware failed to load: ${error.message}`);
|
|
518
815
|
}
|
|
519
|
-
const appMiddleware =
|
|
816
|
+
const appMiddleware = this.app.container.listClass("MIDDLEWARE") ?? [];
|
|
520
817
|
appMiddleware.forEach((item) => {
|
|
521
818
|
item.id = (item.id ?? "").replace("MIDDLEWARE:", "");
|
|
522
819
|
if (item.id && Helper.isClass(item.target)) {
|
|
523
|
-
|
|
820
|
+
this.app.container.reg(item.id, item.target, {
|
|
524
821
|
scope: "Prototype",
|
|
525
822
|
type: "MIDDLEWARE",
|
|
526
823
|
args: []
|
|
527
824
|
});
|
|
528
|
-
const ctl =
|
|
825
|
+
const ctl = this.app.container.getInsByClass(item.target);
|
|
529
826
|
if (!implementsMiddlewareInterface(ctl)) {
|
|
530
827
|
throw Error(`The middleware ${item.id} must implements interface 'IMiddleware'.`);
|
|
531
828
|
}
|
|
@@ -538,7 +835,7 @@ var Loader = class _Loader {
|
|
|
538
835
|
});
|
|
539
836
|
const middlewareConfig = middlewareConf.config || {};
|
|
540
837
|
for (const key of Array.from(appMList)) {
|
|
541
|
-
const handle =
|
|
838
|
+
const handle = this.app.container.get(key, "MIDDLEWARE");
|
|
542
839
|
if (!handle) {
|
|
543
840
|
throw Error(`Middleware ${key} load error.`);
|
|
544
841
|
}
|
|
@@ -551,7 +848,7 @@ var Loader = class _Loader {
|
|
|
551
848
|
let decoratorOptions = {};
|
|
552
849
|
if (middlewareClass) {
|
|
553
850
|
try {
|
|
554
|
-
decoratorOptions =
|
|
851
|
+
decoratorOptions = this.app.container.getPropertyData(MIDDLEWARE_OPTIONS, middlewareClass, key) || {};
|
|
555
852
|
} catch {
|
|
556
853
|
decoratorOptions = {};
|
|
557
854
|
}
|
|
@@ -591,21 +888,17 @@ var Loader = class _Loader {
|
|
|
591
888
|
* @throws {Error} If a controller does not implement the IController interface.
|
|
592
889
|
*/
|
|
593
890
|
async LoadControllers() {
|
|
594
|
-
const controllerList =
|
|
891
|
+
const controllerList = this.app.container.listClass("CONTROLLER");
|
|
595
892
|
const controllers = [];
|
|
596
893
|
controllerList.forEach((item) => {
|
|
597
894
|
item.id = (item.id ?? "").replace("CONTROLLER:", "");
|
|
598
895
|
if (item.id && Helper.isClass(item.target)) {
|
|
599
896
|
DefaultLogger.Debug(`Load controller: ${item.id}`);
|
|
600
|
-
|
|
897
|
+
this.app.container.reg(item.id, item.target, {
|
|
601
898
|
scope: "Prototype",
|
|
602
899
|
type: "CONTROLLER",
|
|
603
900
|
args: []
|
|
604
901
|
});
|
|
605
|
-
const ctl = IOC.getInsByClass(item.target);
|
|
606
|
-
if (!implementsControllerInterface(ctl)) {
|
|
607
|
-
throw Error(`The controller ${item.id} must implements interface 'IController'.`);
|
|
608
|
-
}
|
|
609
902
|
controllers.push(item.id);
|
|
610
903
|
}
|
|
611
904
|
});
|
|
@@ -622,17 +915,20 @@ var Loader = class _Loader {
|
|
|
622
915
|
* @throws {Error} When service does not implement IService interface
|
|
623
916
|
*/
|
|
624
917
|
async LoadServices() {
|
|
625
|
-
const serviceList =
|
|
918
|
+
const serviceList = this.app.container.listClass("SERVICE");
|
|
626
919
|
for (const item of serviceList) {
|
|
627
920
|
item.id = (item.id ?? "").replace("SERVICE:", "");
|
|
628
921
|
if (item.id && Helper.isClass(item.target)) {
|
|
629
922
|
DefaultLogger.Debug(`Load service: ${item.id}`);
|
|
630
|
-
|
|
923
|
+
const options = this.app.container.getPropertyData("SERVICE_OPTIONS", item.target, item.id) ?? {};
|
|
924
|
+
this.app.container.reg(item.id, item.target, {
|
|
631
925
|
scope: "Singleton",
|
|
926
|
+
...options,
|
|
632
927
|
type: "SERVICE",
|
|
633
|
-
args: []
|
|
928
|
+
args: options.args ?? []
|
|
634
929
|
});
|
|
635
|
-
|
|
930
|
+
if (options.scope === "Request") continue;
|
|
931
|
+
const ctl = this.app.container.getInsByClass(item.target);
|
|
636
932
|
if (!implementsServiceInterface(ctl)) {
|
|
637
933
|
throw Error(`The service ${item.id} must implements interface 'IService'.`);
|
|
638
934
|
}
|
|
@@ -651,17 +947,17 @@ var Loader = class _Loader {
|
|
|
651
947
|
* @throws {Error} When plugin loading fails
|
|
652
948
|
*/
|
|
653
949
|
async LoadComponents(componentManager) {
|
|
654
|
-
const componentList =
|
|
950
|
+
const componentList = this.app.container.listClass("COMPONENT");
|
|
655
951
|
componentList.forEach((item) => {
|
|
656
952
|
item.id = (item.id ?? "").replace("COMPONENT:", "");
|
|
657
953
|
if (Helper.isClass(item.target)) {
|
|
658
|
-
|
|
954
|
+
this.app.container.reg(item.id, item.target, {
|
|
659
955
|
scope: "Singleton",
|
|
660
956
|
type: "COMPONENT",
|
|
661
957
|
args: []
|
|
662
958
|
});
|
|
663
959
|
if (item.id && item.id.endsWith("Aspect")) {
|
|
664
|
-
const ctl =
|
|
960
|
+
const ctl = this.app.container.getInsByClass(item.target);
|
|
665
961
|
if (!implementsAspectInterface(ctl)) {
|
|
666
962
|
throw Error(`The aspect ${item.id} must implements interface 'IAspect'.`);
|
|
667
963
|
}
|
|
@@ -681,7 +977,7 @@ var Loader = class _Loader {
|
|
|
681
977
|
}
|
|
682
978
|
const pluginConfList = pluginsConf.list ?? [];
|
|
683
979
|
for (const key of pluginConfList) {
|
|
684
|
-
const handle =
|
|
980
|
+
const handle = this.app.container.get(key, "COMPONENT");
|
|
685
981
|
if (!handle) {
|
|
686
982
|
throw Error(`Plugin ${key} load error.`);
|
|
687
983
|
}
|
|
@@ -730,7 +1026,8 @@ var bootstrapApplication = /* @__PURE__ */ __name(async function(target, bootFun
|
|
|
730
1026
|
DefaultLogger.Log("Koatty", "", "Execute bootFunc ...");
|
|
731
1027
|
await bootFunc(app);
|
|
732
1028
|
}
|
|
733
|
-
IOC.
|
|
1029
|
+
if (!app.container || app.container === IOC) app.container = new Container();
|
|
1030
|
+
app.container.setApp(app);
|
|
734
1031
|
DefaultLogger.Log("Koatty", "", "ComponentScan ...");
|
|
735
1032
|
Loader.CheckAllComponents(app, target);
|
|
736
1033
|
await Loader.LoadAllComponents(app, target);
|
|
@@ -772,7 +1069,6 @@ var listenCallback = /* @__PURE__ */ __name((app) => {
|
|
|
772
1069
|
DefaultLogger.Log("Koatty", "", `App Environment: ${app.env}`);
|
|
773
1070
|
if (app.appDebug) DefaultLogger.Warn(`Running in debug mode.`);
|
|
774
1071
|
DefaultLogger.Log("Koatty", "", "====================================");
|
|
775
|
-
asyncEvent(app, AppEvent.appStart);
|
|
776
1072
|
}, "listenCallback");
|
|
777
1073
|
function Bootstrap(bootFunc) {
|
|
778
1074
|
return IOC.createDecorator((target, _context) => {
|
|
@@ -780,6 +1076,7 @@ function Bootstrap(bootFunc) {
|
|
|
780
1076
|
throw new Error(`class does not inherit from Koatty`);
|
|
781
1077
|
}
|
|
782
1078
|
IOC.saveClass("COMPONENT", target, "KOATTY_APP");
|
|
1079
|
+
if (checkUTRuntime()) return;
|
|
783
1080
|
ExecBootStrap(bootFunc)(target).catch((err) => {
|
|
784
1081
|
DefaultLogger.Fatal(err);
|
|
785
1082
|
process.exitCode = 1;
|