@kurdel/runtime 0.1.0-beta.1
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/LICENSE +21 -0
- package/README.md +44 -0
- package/lib/app/errors/controller-action-missing-result-error.d.ts +9 -0
- package/lib/app/errors/controller-action-missing-result-error.js +14 -0
- package/lib/app/errors/controller-action-missing-result-error.js.map +1 -0
- package/lib/app/errors/module-validation-error.d.ts +25 -0
- package/lib/app/errors/module-validation-error.js +29 -0
- package/lib/app/errors/module-validation-error.js.map +1 -0
- package/lib/app/errors/provider-configuration-error.d.ts +24 -0
- package/lib/app/errors/provider-configuration-error.js +28 -0
- package/lib/app/errors/provider-configuration-error.js.map +1 -0
- package/lib/app/index.d.ts +1 -0
- package/lib/app/index.js +2 -0
- package/lib/app/index.js.map +1 -0
- package/lib/app/lifecycle-manager.d.ts +26 -0
- package/lib/app/lifecycle-manager.js +40 -0
- package/lib/app/lifecycle-manager.js.map +1 -0
- package/lib/app/module-loader.d.ts +29 -0
- package/lib/app/module-loader.js +61 -0
- package/lib/app/module-loader.js.map +1 -0
- package/lib/app/provider-registrar.d.ts +29 -0
- package/lib/app/provider-registrar.js +67 -0
- package/lib/app/provider-registrar.js.map +1 -0
- package/lib/app/runtime-application.d.ts +75 -0
- package/lib/app/runtime-application.js +97 -0
- package/lib/app/runtime-application.js.map +1 -0
- package/lib/app/runtime-composer.d.ts +25 -0
- package/lib/app/runtime-composer.js +100 -0
- package/lib/app/runtime-composer.js.map +1 -0
- package/lib/app/server-runner.d.ts +36 -0
- package/lib/app/server-runner.js +65 -0
- package/lib/app/server-runner.js.map +1 -0
- package/lib/http/index.d.ts +6 -0
- package/lib/http/index.js +7 -0
- package/lib/http/index.js.map +1 -0
- package/lib/http/is-http-error.d.ts +2 -0
- package/lib/http/is-http-error.js +7 -0
- package/lib/http/is-http-error.js.map +1 -0
- package/lib/http/noop-response-renderer.d.ts +7 -0
- package/lib/http/noop-response-renderer.js +10 -0
- package/lib/http/noop-response-renderer.js.map +1 -0
- package/lib/http/render-action-result.d.ts +4 -0
- package/lib/http/render-action-result.js +24 -0
- package/lib/http/render-action-result.js.map +1 -0
- package/lib/http/runtime-controller-pipe.d.ts +16 -0
- package/lib/http/runtime-controller-pipe.js +26 -0
- package/lib/http/runtime-controller-pipe.js.map +1 -0
- package/lib/http/runtime-controller-resolver.d.ts +12 -0
- package/lib/http/runtime-controller-resolver.js +29 -0
- package/lib/http/runtime-controller-resolver.js.map +1 -0
- package/lib/http/runtime-http-context-factory.d.ts +29 -0
- package/lib/http/runtime-http-context-factory.js +91 -0
- package/lib/http/runtime-http-context-factory.js.map +1 -0
- package/lib/http/runtime-middleware-pipe.d.ts +15 -0
- package/lib/http/runtime-middleware-pipe.js +31 -0
- package/lib/http/runtime-middleware-pipe.js.map +1 -0
- package/lib/http/runtime-middleware-registry.d.ts +18 -0
- package/lib/http/runtime-middleware-registry.js +39 -0
- package/lib/http/runtime-middleware-registry.js.map +1 -0
- package/lib/http/runtime-request-orchestrator.d.ts +21 -0
- package/lib/http/runtime-request-orchestrator.js +114 -0
- package/lib/http/runtime-request-orchestrator.js.map +1 -0
- package/lib/http/runtime-response-renderer.d.ts +12 -0
- package/lib/http/runtime-response-renderer.js +37 -0
- package/lib/http/runtime-response-renderer.js.map +1 -0
- package/lib/http/runtime-router.d.ts +37 -0
- package/lib/http/runtime-router.js +135 -0
- package/lib/http/runtime-router.js.map +1 -0
- package/lib/index.d.ts +3 -0
- package/lib/index.js +4 -0
- package/lib/index.js.map +1 -0
- package/lib/middlewares/create-validator.d.ts +7 -0
- package/lib/middlewares/create-validator.js +21 -0
- package/lib/middlewares/create-validator.js.map +1 -0
- package/lib/middlewares/error-handle.d.ts +2 -0
- package/lib/middlewares/error-handle.js +30 -0
- package/lib/middlewares/error-handle.js.map +1 -0
- package/lib/middlewares/index.d.ts +2 -0
- package/lib/middlewares/index.js +3 -0
- package/lib/middlewares/index.js.map +1 -0
- package/lib/middlewares/json-body-parser.d.ts +14 -0
- package/lib/middlewares/json-body-parser.js +23 -0
- package/lib/middlewares/json-body-parser.js.map +1 -0
- package/lib/middlewares/schema-validator.d.ts +13 -0
- package/lib/middlewares/schema-validator.js +44 -0
- package/lib/middlewares/schema-validator.js.map +1 -0
- package/lib/modules/controller-module.d.ts +23 -0
- package/lib/modules/controller-module.js +76 -0
- package/lib/modules/controller-module.js.map +1 -0
- package/lib/modules/database-module.d.ts +25 -0
- package/lib/modules/database-module.js +40 -0
- package/lib/modules/database-module.js.map +1 -0
- package/lib/modules/index.d.ts +1 -0
- package/lib/modules/index.js +2 -0
- package/lib/modules/index.js.map +1 -0
- package/lib/modules/lifecycle-module.d.ts +9 -0
- package/lib/modules/lifecycle-module.js +17 -0
- package/lib/modules/lifecycle-module.js.map +1 -0
- package/lib/modules/middleware-module.d.ts +18 -0
- package/lib/modules/middleware-module.js +45 -0
- package/lib/modules/middleware-module.js.map +1 -0
- package/lib/modules/model-module.d.ts +17 -0
- package/lib/modules/model-module.js +24 -0
- package/lib/modules/model-module.js.map +1 -0
- package/lib/modules/server-module.d.ts +30 -0
- package/lib/modules/server-module.js +65 -0
- package/lib/modules/server-module.js.map +1 -0
- package/lib/template/ensure-template-engine-binding.d.ts +2 -0
- package/lib/template/ensure-template-engine-binding.js +8 -0
- package/lib/template/ensure-template-engine-binding.js.map +1 -0
- package/lib/template/index.d.ts +1 -0
- package/lib/template/index.js +2 -0
- package/lib/template/index.js.map +1 -0
- package/lib/template/noop-template-engine.d.ts +4 -0
- package/lib/template/noop-template-engine.js +6 -0
- package/lib/template/noop-template-engine.js.map +1 -0
- package/package.json +64 -0
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
import { IoCContainer } from '@kurdel/ioc';
|
|
2
|
+
import { TOKENS } from '@kurdel/core/tokens';
|
|
3
|
+
import { ModuleLoader } from '../app/module-loader.js';
|
|
4
|
+
import { LifecycleManager } from '../app/lifecycle-manager.js';
|
|
5
|
+
import { ServerRunner } from '../app/server-runner.js';
|
|
6
|
+
import { RuntimeComposer } from '../app/runtime-composer.js';
|
|
7
|
+
/**
|
|
8
|
+
* kurdel runtime application.
|
|
9
|
+
*
|
|
10
|
+
* Coordinates module initialization, dependency registration,
|
|
11
|
+
* and server lifecycle within a single runtime instance.
|
|
12
|
+
*
|
|
13
|
+
* Responsibilities:
|
|
14
|
+
* - Aggregate declarations from user modules (controllers, middlewares, models)
|
|
15
|
+
* - Compose built-in runtime modules (server/router/middleware/model/database/lifecycle)
|
|
16
|
+
* - Initialize all modules via ModuleLoader and register providers in IoC
|
|
17
|
+
* - Manage application lifecycle (OnStart / OnShutdown)
|
|
18
|
+
* - Start and stop the HTTP server via ServerAdapter (no Node.js types leak)
|
|
19
|
+
*
|
|
20
|
+
* Design notes:
|
|
21
|
+
* - Lives entirely in runtime; consumers interact only through the public Application API
|
|
22
|
+
* - “IoC first”: every dependency is resolved via tokens and interfaces
|
|
23
|
+
* - Request scope creation is delegated to ServerModule (per-request)
|
|
24
|
+
*/
|
|
25
|
+
export class RuntimeApplication {
|
|
26
|
+
/** Read-only accessor exposing the underlying IoC container. */
|
|
27
|
+
get container() {
|
|
28
|
+
return this.ioc;
|
|
29
|
+
}
|
|
30
|
+
/**
|
|
31
|
+
* Construct a new runtime application.
|
|
32
|
+
*
|
|
33
|
+
* Steps performed:
|
|
34
|
+
* - Store runtime configuration
|
|
35
|
+
* - Compose the module pipeline (built-ins + user modules) via RuntimeComposer
|
|
36
|
+
*/
|
|
37
|
+
constructor(config) {
|
|
38
|
+
/** Root IoC container — central registry for all runtime providers. */
|
|
39
|
+
this.ioc = new IoCContainer();
|
|
40
|
+
/** Handles lifecycle hook execution (OnStart / OnShutdown). */
|
|
41
|
+
this.lifecycle = new LifecycleManager();
|
|
42
|
+
this.config = config;
|
|
43
|
+
this.modules = RuntimeComposer.compose(config);
|
|
44
|
+
}
|
|
45
|
+
/**
|
|
46
|
+
* Add extra modules programmatically before bootstrap.
|
|
47
|
+
* Useful for integration tests or dynamic composition in code.
|
|
48
|
+
*/
|
|
49
|
+
use(...modules) {
|
|
50
|
+
this.modules.push(...modules);
|
|
51
|
+
}
|
|
52
|
+
/**
|
|
53
|
+
* Bootstrap the runtime:
|
|
54
|
+
* - Validate and initialize all modules
|
|
55
|
+
* - Register declared providers into the IoC container
|
|
56
|
+
* - Execute each module’s optional `register()` hook
|
|
57
|
+
*
|
|
58
|
+
* Must be called before `listen()`.
|
|
59
|
+
*/
|
|
60
|
+
async bootstrap() {
|
|
61
|
+
const loader = new ModuleLoader(this.ioc);
|
|
62
|
+
await loader.init(this.modules, this.config);
|
|
63
|
+
}
|
|
64
|
+
/**
|
|
65
|
+
* Start the HTTP server via the registered ServerAdapter and return a handle.
|
|
66
|
+
*
|
|
67
|
+
* Lifecycle sequence:
|
|
68
|
+
* 1) Resolve ServerAdapter from IoC
|
|
69
|
+
* 2) Gather OnStart / OnShutdown hooks (LifecycleModule ensures their presence)
|
|
70
|
+
* 3) Delegate to ServerRunner to handle listen/close mechanics
|
|
71
|
+
*
|
|
72
|
+
* Supports both overloads:
|
|
73
|
+
* - listen(port, callback)
|
|
74
|
+
* - listen(port, host, callback)
|
|
75
|
+
*/
|
|
76
|
+
listen(port, hostOrCb, cb) {
|
|
77
|
+
const adapter = this.ioc.get(TOKENS.ServerAdapter);
|
|
78
|
+
const onStart = this.ioc.has(TOKENS.OnStart)
|
|
79
|
+
? this.ioc.get(TOKENS.OnStart)
|
|
80
|
+
: [];
|
|
81
|
+
const onShutdown = this.ioc.has(TOKENS.OnShutdown)
|
|
82
|
+
? this.ioc.get(TOKENS.OnShutdown)
|
|
83
|
+
: [];
|
|
84
|
+
const runner = new ServerRunner(adapter, this.lifecycle);
|
|
85
|
+
return runner.listen(onStart, onShutdown, port, hostOrCb, cb);
|
|
86
|
+
}
|
|
87
|
+
/**
|
|
88
|
+
* Expose the underlying IoC container for advanced scenarios:
|
|
89
|
+
* diagnostics, module introspection, or test overrides.
|
|
90
|
+
*
|
|
91
|
+
* Prefer resolving dependencies via typed tokens in normal app code.
|
|
92
|
+
*/
|
|
93
|
+
getContainer() {
|
|
94
|
+
return this.container;
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
//# sourceMappingURL=runtime-application.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"runtime-application.js","sourceRoot":"","sources":["../../src/app/runtime-application.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAG3C,OAAO,EAAE,MAAM,EAAE,MAAM,qBAAqB,CAAC;AAE7C,OAAO,EAAE,YAAY,EAAE,MAAM,0BAA0B,CAAC;AACxD,OAAO,EAAE,gBAAgB,EAAE,MAAM,8BAA8B,CAAC;AAChE,OAAO,EAAE,YAAY,EAAE,MAAM,0BAA0B,CAAC;AACxD,OAAO,EAAE,eAAe,EAAE,MAAM,6BAA6B,CAAC;AAE9D;;;;;;;;;;;;;;;;;GAiBG;AACH,MAAM,OAAO,kBAAkB;IAa7B,gEAAgE;IAChE,IAAI,SAAS;QACX,OAAO,IAAI,CAAC,GAAG,CAAC;IAClB,CAAC;IAED;;;;;;OAMG;IACH,YAAY,MAAiB;QArB7B,uEAAuE;QACtD,QAAG,GAAG,IAAI,YAAY,EAAE,CAAC;QAK1C,+DAA+D;QAC9C,cAAS,GAAG,IAAI,gBAAgB,EAAE,CAAC;QAelD,IAAI,CAAC,MAAM,GAAG,MAAM,CAAC;QACrB,IAAI,CAAC,OAAO,GAAG,eAAe,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC;IACjD,CAAC;IAED;;;OAGG;IACH,GAAG,CAAC,GAAG,OAAoB;QACzB,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,GAAG,OAAO,CAAC,CAAC;IAChC,CAAC;IAED;;;;;;;OAOG;IACH,KAAK,CAAC,SAAS;QACb,MAAM,MAAM,GAAG,IAAI,YAAY,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;QAC1C,MAAM,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,IAAI,CAAC,MAAM,CAAC,CAAC;IAC/C,CAAC;IAED;;;;;;;;;;;OAWG;IACH,MAAM,CAAC,IAAY,EAAE,QAAgC,EAAE,EAAe;QACpE,MAAM,OAAO,GAAG,IAAI,CAAC,GAAG,CAAC,GAAG,CAAgB,MAAM,CAAC,aAAa,CAAC,CAAC;QAElE,MAAM,OAAO,GAAG,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,MAAM,CAAC,OAAO,CAAC;YAC1C,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,GAAG,CAA0B,MAAM,CAAC,OAAO,CAAC;YACvD,CAAC,CAAC,EAAE,CAAC;QAEP,MAAM,UAAU,GAAG,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,MAAM,CAAC,UAAU,CAAC;YAChD,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,GAAG,CAA0B,MAAM,CAAC,UAAU,CAAC;YAC1D,CAAC,CAAC,EAAE,CAAC;QAEP,MAAM,MAAM,GAAG,IAAI,YAAY,CAAC,OAAO,EAAE,IAAI,CAAC,SAAS,CAAC,CAAC;QACzD,OAAO,MAAM,CAAC,MAAM,CAAC,OAAO,EAAE,UAAU,EAAE,IAAI,EAAE,QAAQ,EAAE,EAAE,CAAC,CAAC;IAChE,CAAC;IAED;;;;;OAKG;IACH,YAAY;QACV,OAAO,IAAI,CAAC,SAAS,CAAC;IACxB,CAAC;CACF"}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import { type AppConfig, type AppModule } from '@kurdel/core/app';
|
|
2
|
+
/**
|
|
3
|
+
* ## RuntimeComposer
|
|
4
|
+
*
|
|
5
|
+
* Builds the deterministic runtime module chain for a Kurdel application.
|
|
6
|
+
* Responsible for aggregating user-defined HTTP modules and assembling
|
|
7
|
+
* framework modules in a well-defined initialization order.
|
|
8
|
+
*/
|
|
9
|
+
export declare class RuntimeComposer {
|
|
10
|
+
/** Default priority map for built-in modules. */
|
|
11
|
+
private static readonly DEFAULT_PRIORITIES;
|
|
12
|
+
/**
|
|
13
|
+
* Main composition entrypoint.
|
|
14
|
+
* @returns Ordered list of AppModules ready for initialization.
|
|
15
|
+
*/
|
|
16
|
+
static compose(config: AppConfig): AppModule[];
|
|
17
|
+
/** Selects only modules exposing HTTP artifacts. */
|
|
18
|
+
private static extractHttpModules;
|
|
19
|
+
/** Aggregates HTTP declarations across all HttpModules. */
|
|
20
|
+
private static collectHttpArtifacts;
|
|
21
|
+
/** Sorts modules deterministically by priority. */
|
|
22
|
+
private static sortByPriority;
|
|
23
|
+
/** Ensures that no two modules register the same provider token. */
|
|
24
|
+
private static validateUniqueProviders;
|
|
25
|
+
}
|
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
import { ModulePriority } from '@kurdel/core/app';
|
|
2
|
+
import { LifecycleModule } from '../modules/lifecycle-module.js';
|
|
3
|
+
import { DatabaseModule } from '../modules/database-module.js';
|
|
4
|
+
import { ModelModule } from '../modules/model-module.js';
|
|
5
|
+
import { MiddlewareModule } from '../modules/middleware-module.js';
|
|
6
|
+
import { ControllerModule } from '../modules/controller-module.js';
|
|
7
|
+
import { ServerModule } from '../modules/server-module.js';
|
|
8
|
+
import { ModuleValidationError } from '../app/errors/module-validation-error.js';
|
|
9
|
+
/**
|
|
10
|
+
* ## RuntimeComposer
|
|
11
|
+
*
|
|
12
|
+
* Builds the deterministic runtime module chain for a Kurdel application.
|
|
13
|
+
* Responsible for aggregating user-defined HTTP modules and assembling
|
|
14
|
+
* framework modules in a well-defined initialization order.
|
|
15
|
+
*/
|
|
16
|
+
export class RuntimeComposer {
|
|
17
|
+
/**
|
|
18
|
+
* Main composition entrypoint.
|
|
19
|
+
* @returns Ordered list of AppModules ready for initialization.
|
|
20
|
+
*/
|
|
21
|
+
static compose(config) {
|
|
22
|
+
const modules = config.modules ?? [];
|
|
23
|
+
const httpModules = this.extractHttpModules(modules);
|
|
24
|
+
const { models, controllers, middlewares } = this.collectHttpArtifacts(httpModules);
|
|
25
|
+
const unsorted = [
|
|
26
|
+
new LifecycleModule(),
|
|
27
|
+
new DatabaseModule(),
|
|
28
|
+
new ModelModule(models),
|
|
29
|
+
new MiddlewareModule(middlewares),
|
|
30
|
+
new ControllerModule(controllers),
|
|
31
|
+
new ServerModule(),
|
|
32
|
+
...modules,
|
|
33
|
+
];
|
|
34
|
+
const pipeline = this.sortByPriority(unsorted);
|
|
35
|
+
this.validateUniqueProviders(pipeline);
|
|
36
|
+
return pipeline;
|
|
37
|
+
}
|
|
38
|
+
// ------------------------------------------------------------
|
|
39
|
+
// Extraction helpers
|
|
40
|
+
// ------------------------------------------------------------
|
|
41
|
+
/** Selects only modules exposing HTTP artifacts. */
|
|
42
|
+
static extractHttpModules(modules) {
|
|
43
|
+
return modules.filter((m) => 'models' in m || 'controllers' in m || 'middlewares' in m);
|
|
44
|
+
}
|
|
45
|
+
/** Aggregates HTTP declarations across all HttpModules. */
|
|
46
|
+
static collectHttpArtifacts(httpModules) {
|
|
47
|
+
const models = httpModules.flatMap(m => m.models ?? []);
|
|
48
|
+
const controllers = httpModules.flatMap(m => m.controllers ?? []);
|
|
49
|
+
const middlewares = httpModules.flatMap(m => (m.middlewares ?? []).map((mw) => typeof mw === 'function'
|
|
50
|
+
? { use: mw, zone: 'pre', priority: 0 }
|
|
51
|
+
: {
|
|
52
|
+
use: mw.use,
|
|
53
|
+
zone: mw.zone ?? 'pre',
|
|
54
|
+
priority: mw.priority ?? 0,
|
|
55
|
+
action: mw.action,
|
|
56
|
+
}));
|
|
57
|
+
return { models, controllers, middlewares };
|
|
58
|
+
}
|
|
59
|
+
// ------------------------------------------------------------
|
|
60
|
+
// Sorting and validation
|
|
61
|
+
// ------------------------------------------------------------
|
|
62
|
+
/** Sorts modules deterministically by priority. */
|
|
63
|
+
static sortByPriority(modules) {
|
|
64
|
+
return modules
|
|
65
|
+
.map((m, index) => ({
|
|
66
|
+
mod: m,
|
|
67
|
+
order: index,
|
|
68
|
+
prio: m.priority ??
|
|
69
|
+
RuntimeComposer.DEFAULT_PRIORITIES.get(m.constructor.name) ??
|
|
70
|
+
ModulePriority.User,
|
|
71
|
+
}))
|
|
72
|
+
.sort((a, b) => (a.prio === b.prio ? a.order - b.order : a.prio - b.prio))
|
|
73
|
+
.map(e => e.mod);
|
|
74
|
+
}
|
|
75
|
+
/** Ensures that no two modules register the same provider token. */
|
|
76
|
+
static validateUniqueProviders(modules) {
|
|
77
|
+
const tokenToModule = new Map();
|
|
78
|
+
for (const mod of modules) {
|
|
79
|
+
const moduleName = mod.constructor?.name ?? 'AnonymousModule';
|
|
80
|
+
for (const provider of mod.providers ?? []) {
|
|
81
|
+
const token = provider.provide;
|
|
82
|
+
const owner = tokenToModule.get(token);
|
|
83
|
+
if (owner) {
|
|
84
|
+
throw new ModuleValidationError(`Duplicate provider for token "${String(token)}" between modules "${owner}" and "${moduleName}".`);
|
|
85
|
+
}
|
|
86
|
+
tokenToModule.set(token, moduleName);
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
/** Default priority map for built-in modules. */
|
|
92
|
+
RuntimeComposer.DEFAULT_PRIORITIES = new Map([
|
|
93
|
+
['LifecycleModule', ModulePriority.Lifecycle],
|
|
94
|
+
['DatabaseModule', ModulePriority.Database],
|
|
95
|
+
['ModelModule', ModulePriority.Model],
|
|
96
|
+
['MiddlewareModule', ModulePriority.Middleware],
|
|
97
|
+
['ControllerModule', ModulePriority.Controller],
|
|
98
|
+
['ServerModule', ModulePriority.Server],
|
|
99
|
+
]);
|
|
100
|
+
//# sourceMappingURL=runtime-composer.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"runtime-composer.js","sourceRoot":"","sources":["../../src/app/runtime-composer.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import type { ServerAdapter, RunningServer } from '@kurdel/core/http';
|
|
2
|
+
import type { LifecycleManager } from '../app/lifecycle-manager.js';
|
|
3
|
+
/**
|
|
4
|
+
* Orchestrates HTTP server startup and graceful shutdown.
|
|
5
|
+
*
|
|
6
|
+
* Responsibilities:
|
|
7
|
+
* - Bridge between the framework runtime and the low-level ServerAdapter.
|
|
8
|
+
* - Execute OnStart and OnShutdown lifecycle hooks in proper order.
|
|
9
|
+
* - Wrap the raw server handle into a consistent RunningServer API.
|
|
10
|
+
*
|
|
11
|
+
* Design notes:
|
|
12
|
+
* - ServerRunner is runtime-only; no Node.js types leak through public API.
|
|
13
|
+
* - Hook execution order:
|
|
14
|
+
* - OnStart → forward order
|
|
15
|
+
* - OnShutdown → reverse order (LIFO)
|
|
16
|
+
* - The per-request IoC scope is managed elsewhere (ServerModule).
|
|
17
|
+
*/
|
|
18
|
+
export declare class ServerRunner {
|
|
19
|
+
private readonly adapter;
|
|
20
|
+
private readonly lifecycle;
|
|
21
|
+
constructor(adapter: ServerAdapter, lifecycle: LifecycleManager);
|
|
22
|
+
/**
|
|
23
|
+
* Start the HTTP server and return a handle for runtime control.
|
|
24
|
+
*
|
|
25
|
+
* @param onStart - Hooks executed once the server signals readiness.
|
|
26
|
+
* @param onShutdown - Hooks executed during graceful shutdown.
|
|
27
|
+
* @param port - Port number to listen on.
|
|
28
|
+
* @param hostOrCb - Optional hostname or callback function.
|
|
29
|
+
* @param cb - Optional callback (if hostname was provided).
|
|
30
|
+
*
|
|
31
|
+
* Supports both call forms:
|
|
32
|
+
* - listen(port, callback)
|
|
33
|
+
* - listen(port, host, callback)
|
|
34
|
+
*/
|
|
35
|
+
listen(onStart: (() => Promise<void>)[] | undefined, onShutdown: (() => Promise<void>)[] | undefined, port: number, hostOrCb?: string | (() => void), cb?: () => void): RunningServer;
|
|
36
|
+
}
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Orchestrates HTTP server startup and graceful shutdown.
|
|
3
|
+
*
|
|
4
|
+
* Responsibilities:
|
|
5
|
+
* - Bridge between the framework runtime and the low-level ServerAdapter.
|
|
6
|
+
* - Execute OnStart and OnShutdown lifecycle hooks in proper order.
|
|
7
|
+
* - Wrap the raw server handle into a consistent RunningServer API.
|
|
8
|
+
*
|
|
9
|
+
* Design notes:
|
|
10
|
+
* - ServerRunner is runtime-only; no Node.js types leak through public API.
|
|
11
|
+
* - Hook execution order:
|
|
12
|
+
* - OnStart → forward order
|
|
13
|
+
* - OnShutdown → reverse order (LIFO)
|
|
14
|
+
* - The per-request IoC scope is managed elsewhere (ServerModule).
|
|
15
|
+
*/
|
|
16
|
+
export class ServerRunner {
|
|
17
|
+
constructor(adapter, lifecycle) {
|
|
18
|
+
this.adapter = adapter;
|
|
19
|
+
this.lifecycle = lifecycle;
|
|
20
|
+
}
|
|
21
|
+
/**
|
|
22
|
+
* Start the HTTP server and return a handle for runtime control.
|
|
23
|
+
*
|
|
24
|
+
* @param onStart - Hooks executed once the server signals readiness.
|
|
25
|
+
* @param onShutdown - Hooks executed during graceful shutdown.
|
|
26
|
+
* @param port - Port number to listen on.
|
|
27
|
+
* @param hostOrCb - Optional hostname or callback function.
|
|
28
|
+
* @param cb - Optional callback (if hostname was provided).
|
|
29
|
+
*
|
|
30
|
+
* Supports both call forms:
|
|
31
|
+
* - listen(port, callback)
|
|
32
|
+
* - listen(port, host, callback)
|
|
33
|
+
*/
|
|
34
|
+
listen(onStart = [], onShutdown = [], port, hostOrCb, cb) {
|
|
35
|
+
// Normalize callback overloads
|
|
36
|
+
const userCb = typeof hostOrCb === 'function' ? hostOrCb : cb;
|
|
37
|
+
// Wrap user callback with lifecycle hook execution
|
|
38
|
+
const onReady = async () => {
|
|
39
|
+
await this.lifecycle.runHooks('start', onStart);
|
|
40
|
+
userCb?.();
|
|
41
|
+
};
|
|
42
|
+
// Call adapter.listen with correct overload
|
|
43
|
+
if (typeof hostOrCb === 'string') {
|
|
44
|
+
this.adapter.listen?.(port, hostOrCb, onReady);
|
|
45
|
+
}
|
|
46
|
+
else {
|
|
47
|
+
this.adapter.listen?.(port, onReady);
|
|
48
|
+
}
|
|
49
|
+
// Expose the running server handle
|
|
50
|
+
return {
|
|
51
|
+
/** Access the underlying server (if adapter exposes it) */
|
|
52
|
+
raw: this.adapter.raw?.bind(this.adapter),
|
|
53
|
+
/** Graceful shutdown: stop adapter, then run shutdown hooks (LIFO) */
|
|
54
|
+
close: async () => {
|
|
55
|
+
try {
|
|
56
|
+
await Promise.resolve(this.adapter.close?.());
|
|
57
|
+
}
|
|
58
|
+
finally {
|
|
59
|
+
await this.lifecycle.runHooks('shutdown', [...onShutdown].reverse());
|
|
60
|
+
}
|
|
61
|
+
},
|
|
62
|
+
};
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
//# sourceMappingURL=server-runner.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"server-runner.js","sourceRoot":"","sources":["../../src/app/server-runner.ts"],"names":[],"mappings":"AAGA;;;;;;;;;;;;;;GAcG;AACH,MAAM,OAAO,YAAY;IACvB,YACmB,OAAsB,EACtB,SAA2B;QAD3B,YAAO,GAAP,OAAO,CAAe;QACtB,cAAS,GAAT,SAAS,CAAkB;IAC3C,CAAC;IAEJ;;;;;;;;;;;;OAYG;IACH,MAAM,CACJ,UAAmC,EAAE,EACrC,aAAsC,EAAE,EACxC,IAAY,EACZ,QAAgC,EAChC,EAAe;QAEf,+BAA+B;QAC/B,MAAM,MAAM,GAAG,OAAO,QAAQ,KAAK,UAAU,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,EAAE,CAAC;QAE9D,mDAAmD;QACnD,MAAM,OAAO,GAAG,KAAK,IAAI,EAAE;YACzB,MAAM,IAAI,CAAC,SAAS,CAAC,QAAQ,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC;YAChD,MAAM,EAAE,EAAE,CAAC;QACb,CAAC,CAAC;QAEF,4CAA4C;QAC5C,IAAI,OAAO,QAAQ,KAAK,QAAQ,EAAE,CAAC;YACjC,IAAI,CAAC,OAAO,CAAC,MAAM,EAAE,CAAC,IAAI,EAAE,QAAQ,EAAE,OAAO,CAAC,CAAC;QACjD,CAAC;aAAM,CAAC;YACN,IAAI,CAAC,OAAO,CAAC,MAAM,EAAE,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC;QACvC,CAAC;QAED,mCAAmC;QACnC,OAAO;YACL,2DAA2D;YAC3D,GAAG,EAAE,IAAI,CAAC,OAAO,CAAC,GAAG,EAAE,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC;YAEzC,sEAAsE;YACtE,KAAK,EAAE,KAAK,IAAI,EAAE;gBAChB,IAAI,CAAC;oBACH,MAAM,OAAO,CAAC,OAAO,CAAC,IAAI,CAAC,OAAO,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC;gBAChD,CAAC;wBAAS,CAAC;oBACT,MAAM,IAAI,CAAC,SAAS,CAAC,QAAQ,CAAC,UAAU,EAAE,CAAC,GAAG,UAAU,CAAC,CAAC,OAAO,EAAE,CAAC,CAAC;gBACvE,CAAC;YACH,CAAC;SACF,CAAC;IACJ,CAAC;CACF"}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
export * from './is-http-error.js';
|
|
2
|
+
export * from './noop-response-renderer.js';
|
|
3
|
+
export * from './runtime-request-orchestrator.js';
|
|
4
|
+
export * from './runtime-response-renderer.js';
|
|
5
|
+
export * from './render-action-result.js';
|
|
6
|
+
export * from './runtime-router.js';
|
|
7
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/http/index.ts"],"names":[],"mappings":"AAAA,cAAc,oBAAoB,CAAC;AACnC,cAAc,6BAA6B,CAAC;AAC5C,cAAc,mCAAmC,CAAC;AAClD,cAAc,gCAAgC,CAAC;AAC/C,cAAc,2BAA2B,CAAC;AAC1C,cAAc,qBAAqB,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"is-http-error.js","sourceRoot":"","sources":["../../src/http/is-http-error.ts"],"names":[],"mappings":"AAEA,MAAM,UAAU,WAAW,CAAC,GAAY;IACtC,OAAO,CACL,OAAO,GAAG,KAAK,QAAQ;QACvB,GAAG,KAAK,IAAI;QACZ,QAAQ,IAAI,GAAG;QACf,OAAQ,GAAW,CAAC,MAAM,KAAK,QAAQ,CACxC,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import type { HttpResponse } from '@kurdel/common';
|
|
2
|
+
import type { ActionResult, ResponseRenderer } from '@kurdel/core/http';
|
|
3
|
+
/** No-op renderer used for non-platform runtime tests. */
|
|
4
|
+
export declare class NoopResponseRenderer implements ResponseRenderer {
|
|
5
|
+
render(_res: HttpResponse, _result: ActionResult | void): void;
|
|
6
|
+
handleError(_res: HttpResponse, _err: unknown): void;
|
|
7
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"noop-response-renderer.js","sourceRoot":"","sources":["../../src/http/noop-response-renderer.ts"],"names":[],"mappings":"AAGA,0DAA0D;AAC1D,MAAM,OAAO,oBAAoB;IAC/B,MAAM,CAAC,IAAkB,EAAE,OAA4B;QACrD,aAAa;IACf,CAAC;IAED,WAAW,CAAC,IAAkB,EAAE,IAAa;QAC3C,aAAa;IACf,CAAC;CACF"}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
/** Node-bound renderer for ActionResult. */
|
|
2
|
+
export function renderActionResult(res, r) {
|
|
3
|
+
switch (r.kind) {
|
|
4
|
+
case 'json':
|
|
5
|
+
res.status(r.status).json(r.body);
|
|
6
|
+
break;
|
|
7
|
+
case 'text':
|
|
8
|
+
res.status(r.status).send(r.body);
|
|
9
|
+
break;
|
|
10
|
+
case 'html': {
|
|
11
|
+
const withHeaders = res;
|
|
12
|
+
withHeaders.setHeader?.('Content-Type', r.contentType ?? 'text/html; charset=utf-8');
|
|
13
|
+
res.status(r.status).send(r.body);
|
|
14
|
+
break;
|
|
15
|
+
}
|
|
16
|
+
case 'redirect':
|
|
17
|
+
res.redirect(r.status, r.location);
|
|
18
|
+
break;
|
|
19
|
+
case 'empty':
|
|
20
|
+
res.status(r.status).send('');
|
|
21
|
+
break;
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
//# sourceMappingURL=render-action-result.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"render-action-result.js","sourceRoot":"","sources":["../../src/http/render-action-result.ts"],"names":[],"mappings":"AAIA,4CAA4C;AAC5C,MAAM,UAAU,kBAAkB,CAAC,GAAiB,EAAE,CAAe;IACnE,QAAQ,CAAC,CAAC,IAAI,EAAE,CAAC;QACf,KAAK,MAAM;YACT,GAAG,CAAC,MAAM,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC;YAClC,MAAM;QACR,KAAK,MAAM;YACT,GAAG,CAAC,MAAM,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC;YAClC,MAAM;QACR,KAAK,MAAM,CAAC,CAAC,CAAC;YACZ,MAAM,WAAW,GAAG,GAA8B,CAAC;YACnD,WAAW,CAAC,SAAS,EAAE,CAAC,cAAc,EAAE,CAAC,CAAC,WAAW,IAAI,0BAA0B,CAAC,CAAC;YACrF,GAAG,CAAC,MAAM,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC;YAClC,MAAM;QACR,CAAC;QACD,KAAK,UAAU;YACb,GAAG,CAAC,QAAQ,CAAC,CAAC,CAAC,MAAM,EAAE,CAAC,CAAC,QAAQ,CAAC,CAAC;YACnC,MAAM;QACR,KAAK,OAAO;YACV,GAAG,CAAC,MAAM,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;YAC9B,MAAM;IACV,CAAC;AACH,CAAC"}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import type { HttpContext, Controller, Middleware, ActionResult } from '@kurdel/core/http';
|
|
2
|
+
/**
|
|
3
|
+
* RuntimeControllerPipe
|
|
4
|
+
*
|
|
5
|
+
* Executes a controller action within a pre-assembled middleware chain.
|
|
6
|
+
*
|
|
7
|
+
* Notes:
|
|
8
|
+
* - The list of middlewares is prepared upstream (e.g. by RuntimeRequestOrchestrator)
|
|
9
|
+
* - ControllerPipe does not merge middlewares itself
|
|
10
|
+
* - If the action is missing, produces a 404 text result
|
|
11
|
+
*/
|
|
12
|
+
export declare class RuntimeControllerPipe<TReadable = unknown> {
|
|
13
|
+
private readonly middlewares;
|
|
14
|
+
constructor(middlewares?: readonly Middleware<HttpContext<any, any, TReadable>>[]);
|
|
15
|
+
run(controller: Controller<any>, ctx: HttpContext<unknown, Record<string, string>, TReadable>, actionName: string): Promise<ActionResult<TReadable> | void>;
|
|
16
|
+
}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import { RuntimeMiddlewarePipe } from '../http/runtime-middleware-pipe.js';
|
|
2
|
+
/**
|
|
3
|
+
* RuntimeControllerPipe
|
|
4
|
+
*
|
|
5
|
+
* Executes a controller action within a pre-assembled middleware chain.
|
|
6
|
+
*
|
|
7
|
+
* Notes:
|
|
8
|
+
* - The list of middlewares is prepared upstream (e.g. by RuntimeRequestOrchestrator)
|
|
9
|
+
* - ControllerPipe does not merge middlewares itself
|
|
10
|
+
* - If the action is missing, produces a 404 text result
|
|
11
|
+
*/
|
|
12
|
+
export class RuntimeControllerPipe {
|
|
13
|
+
constructor(middlewares = []) {
|
|
14
|
+
this.middlewares = middlewares;
|
|
15
|
+
}
|
|
16
|
+
async run(controller, ctx, actionName) {
|
|
17
|
+
const handler = controller.getAction(actionName);
|
|
18
|
+
if (typeof handler !== 'function') {
|
|
19
|
+
return ctx.text(404, `Action '${actionName}' not found in '${controller.constructor.name}'.`);
|
|
20
|
+
}
|
|
21
|
+
const pipe = new RuntimeMiddlewarePipe(this.middlewares);
|
|
22
|
+
const result = await pipe.run(ctx, async () => (await handler.call(controller, ctx)));
|
|
23
|
+
return result;
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
//# sourceMappingURL=runtime-controller-pipe.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"runtime-controller-pipe.js","sourceRoot":"","sources":["../../src/http/runtime-controller-pipe.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,qBAAqB,EAAE,MAAM,qCAAqC,CAAC;AAE5E;;;;;;;;;GASG;AACH,MAAM,OAAO,qBAAqB;IAChC,YACmB,cAAuE,EAAE;QAAzE,gBAAW,GAAX,WAAW,CAA8D;IACzF,CAAC;IAEJ,KAAK,CAAC,GAAG,CACP,UAA2B,EAC3B,GAA4D,EAC5D,UAAkB;QAElB,MAAM,OAAO,GAAG,UAAU,CAAC,SAAS,CAAC,UAAU,CAAC,CAAC;QAEjD,IAAI,OAAO,OAAO,KAAK,UAAU,EAAE,CAAC;YAClC,OAAO,GAAG,CAAC,IAAI,CAAC,GAAG,EAAE,WAAW,UAAU,mBAAmB,UAAU,CAAC,WAAW,CAAC,IAAI,IAAI,CAAC,CAAC;QAChG,CAAC;QAED,MAAM,IAAI,GAAG,IAAI,qBAAqB,CAAC,IAAI,CAAC,WAA2B,CAAC,CAAC;QAEzE,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,GAAG,CAC3B,GAAG,EACH,KAAK,IAAI,EAAE,CAAC,CAAC,MAAM,OAAO,CAAC,IAAI,CAAC,UAAU,EAAE,GAAG,CAAC,CAA4B,CAC7E,CAAC;QAEF,OAAO,MAAwC,CAAC;IAClD,CAAC;CACF"}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import type { Newable } from '@kurdel/common';
|
|
2
|
+
import type { Container } from '@kurdel/ioc';
|
|
3
|
+
import type { ControllerResolver } from '@kurdel/core/http';
|
|
4
|
+
export declare class RuntimeControllerResolver implements ControllerResolver {
|
|
5
|
+
private readonly root;
|
|
6
|
+
constructor(root: Container);
|
|
7
|
+
/**
|
|
8
|
+
* Resolve controller instance from the provided request scope.
|
|
9
|
+
* Falls back to the root container when not registered in the scope.
|
|
10
|
+
*/
|
|
11
|
+
resolve<T>(cls: Newable<T>, scope?: Container): T;
|
|
12
|
+
}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
export class RuntimeControllerResolver {
|
|
2
|
+
constructor(root) {
|
|
3
|
+
this.root = root;
|
|
4
|
+
}
|
|
5
|
+
/**
|
|
6
|
+
* Resolve controller instance from the provided request scope.
|
|
7
|
+
* Falls back to the root container when not registered in the scope.
|
|
8
|
+
*/
|
|
9
|
+
resolve(cls, scope) {
|
|
10
|
+
const c = scope ?? this.root;
|
|
11
|
+
// Prefer request scope; if scope.has() falls back to parent itself, the try-get below is enough.
|
|
12
|
+
if (typeof c.has === 'function') {
|
|
13
|
+
if (c.has(cls))
|
|
14
|
+
return c.get(cls);
|
|
15
|
+
// fallback to root if scope doesn't have it AND has() doesn't climb parents
|
|
16
|
+
if (c !== this.root && this.root.has?.(cls))
|
|
17
|
+
return this.root.get(cls);
|
|
18
|
+
}
|
|
19
|
+
// If has() isn’t available or already climbs to parent, single get() is sufficient.
|
|
20
|
+
try {
|
|
21
|
+
return c.get(cls);
|
|
22
|
+
}
|
|
23
|
+
catch {
|
|
24
|
+
// Final fallback to root
|
|
25
|
+
return this.root.get(cls);
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
//# sourceMappingURL=runtime-controller-resolver.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"runtime-controller-resolver.js","sourceRoot":"","sources":["../../src/http/runtime-controller-resolver.ts"],"names":[],"mappings":"AAIA,MAAM,OAAO,yBAAyB;IACpC,YAA6B,IAAe;QAAf,SAAI,GAAJ,IAAI,CAAW;IAAG,CAAC;IAEhD;;;OAGG;IACH,OAAO,CAAI,GAAe,EAAE,KAAiB;QAC3C,MAAM,CAAC,GAAG,KAAK,IAAI,IAAI,CAAC,IAAI,CAAC;QAE7B,iGAAiG;QACjG,IAAI,OAAO,CAAC,CAAC,GAAG,KAAK,UAAU,EAAE,CAAC;YAChC,IAAI,CAAC,CAAC,GAAG,CAAC,GAAG,CAAC;gBAAE,OAAO,CAAC,CAAC,GAAG,CAAI,GAAG,CAAC,CAAC;YACrC,4EAA4E;YAC5E,IAAI,CAAC,KAAK,IAAI,CAAC,IAAI,IAAI,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,CAAC,GAAG,CAAC;gBAAE,OAAO,IAAI,CAAC,IAAI,CAAC,GAAG,CAAI,GAAG,CAAC,CAAC;QAC5E,CAAC;QAED,oFAAoF;QACpF,IAAI,CAAC;YACH,OAAO,CAAC,CAAC,GAAG,CAAI,GAAG,CAAC,CAAC;QACvB,CAAC;QAAC,MAAM,CAAC;YACP,yBAAyB;YACzB,OAAO,IAAI,CAAC,IAAI,CAAC,GAAG,CAAI,GAAG,CAAC,CAAC;QAC/B,CAAC;IACH,CAAC;CACF"}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import type { HttpRequest, HttpResponse } from '@kurdel/common';
|
|
2
|
+
import type { Container } from '@kurdel/ioc';
|
|
3
|
+
import type { HttpContext, RouteMatch } from '@kurdel/core/http';
|
|
4
|
+
/**
|
|
5
|
+
* ## RuntimeHttpContextFactory
|
|
6
|
+
*
|
|
7
|
+
* Responsible for constructing per-request {@link HttpContext} objects.
|
|
8
|
+
*
|
|
9
|
+
* Each incoming request receives a fresh, isolated context encapsulating:
|
|
10
|
+
* - HTTP request/response wrappers provided by the adapter
|
|
11
|
+
* - parsed URL, query, params, body
|
|
12
|
+
* - matched route metadata (controller/action/schema/auth)
|
|
13
|
+
* - a request-scoped IoC container
|
|
14
|
+
* - typed constructors for {@link ActionResult}
|
|
15
|
+
*
|
|
16
|
+
* The context object is immutable except for `result`,
|
|
17
|
+
* which is later populated by the orchestrator and renderer.
|
|
18
|
+
*/
|
|
19
|
+
export declare class RuntimeHttpContextFactory {
|
|
20
|
+
/**
|
|
21
|
+
* Constructs a fully initialized {@link HttpContext} instance.
|
|
22
|
+
*
|
|
23
|
+
* @param req - incoming HTTP request
|
|
24
|
+
* @param res - outgoing HTTP response
|
|
25
|
+
* @param match - router resolution result
|
|
26
|
+
* @param scope - request-scoped IoC container
|
|
27
|
+
*/
|
|
28
|
+
create(req: HttpRequest, res: HttpResponse, match: RouteMatch, scope: Container): HttpContext;
|
|
29
|
+
}
|