@athosjs/pro 0.1.4-alpha
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 +518 -0
- package/bootstrap.cjs +107 -0
- package/bootstrap.cjs.map +1 -0
- package/bootstrap.d.ts +8 -0
- package/bootstrap.d.ts.map +1 -0
- package/bootstrap.js +103 -0
- package/bootstrap.js.map +1 -0
- package/core/athos-application.cjs +362 -0
- package/core/athos-application.cjs.map +1 -0
- package/core/athos-application.d.ts +17 -0
- package/core/athos-application.d.ts.map +1 -0
- package/core/athos-application.js +357 -0
- package/core/athos-application.js.map +1 -0
- package/core/discovery.cjs +47 -0
- package/core/discovery.cjs.map +1 -0
- package/core/discovery.d.ts +6 -0
- package/core/discovery.d.ts.map +1 -0
- package/core/discovery.js +45 -0
- package/core/discovery.js.map +1 -0
- package/core/i18n.cjs +12 -0
- package/core/i18n.cjs.map +1 -0
- package/core/i18n.d.ts +4 -0
- package/core/i18n.d.ts.map +1 -0
- package/core/i18n.js +10 -0
- package/core/i18n.js.map +1 -0
- package/core/pipeline.cjs +251 -0
- package/core/pipeline.cjs.map +1 -0
- package/core/pipeline.d.ts +11 -0
- package/core/pipeline.d.ts.map +1 -0
- package/core/pipeline.js +246 -0
- package/core/pipeline.js.map +1 -0
- package/core/router-initializer.cjs +158 -0
- package/core/router-initializer.cjs.map +1 -0
- package/core/router-initializer.d.ts +26 -0
- package/core/router-initializer.d.ts.map +1 -0
- package/core/router-initializer.js +156 -0
- package/core/router-initializer.js.map +1 -0
- package/core/scanner.cjs +141 -0
- package/core/scanner.cjs.map +1 -0
- package/core/scanner.d.ts +7 -0
- package/core/scanner.d.ts.map +1 -0
- package/core/scanner.js +139 -0
- package/core/scanner.js.map +1 -0
- package/experimental.cjs +23 -0
- package/experimental.cjs.map +1 -0
- package/experimental.d.ts +9 -0
- package/experimental.d.ts.map +1 -0
- package/experimental.js +5 -0
- package/experimental.js.map +1 -0
- package/functions.cjs +67 -0
- package/functions.cjs.map +1 -0
- package/functions.d.ts +10 -0
- package/functions.d.ts.map +1 -0
- package/functions.js +62 -0
- package/functions.js.map +1 -0
- package/http-profile.cjs +48 -0
- package/http-profile.cjs.map +1 -0
- package/http-profile.d.ts +6 -0
- package/http-profile.d.ts.map +1 -0
- package/http-profile.js +44 -0
- package/http-profile.js.map +1 -0
- package/index.cjs +281 -0
- package/index.cjs.map +1 -0
- package/index.d.ts +23 -0
- package/index.d.ts.map +1 -0
- package/index.js +23 -0
- package/index.js.map +1 -0
- package/observability.cjs +191 -0
- package/observability.cjs.map +1 -0
- package/observability.d.ts +8 -0
- package/observability.d.ts.map +1 -0
- package/observability.js +188 -0
- package/observability.js.map +1 -0
- package/package.json +42 -0
- package/policies.cjs +30 -0
- package/policies.cjs.map +1 -0
- package/policies.d.ts +21 -0
- package/policies.d.ts.map +1 -0
- package/policies.js +27 -0
- package/policies.js.map +1 -0
- package/resilience.cjs +280 -0
- package/resilience.cjs.map +1 -0
- package/resilience.d.ts +6 -0
- package/resilience.d.ts.map +1 -0
- package/resilience.js +276 -0
- package/resilience.js.map +1 -0
- package/security.cjs +142 -0
- package/security.cjs.map +1 -0
- package/security.d.ts +11 -0
- package/security.d.ts.map +1 -0
- package/security.js +136 -0
- package/security.js.map +1 -0
- package/types.d.ts +3 -0
- package/types.d.ts.map +1 -0
|
@@ -0,0 +1,158 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
var core = require('@athosjs/core');
|
|
4
|
+
var http = require('@athosjs/http');
|
|
5
|
+
var metadata = require('@athosjs/metadata');
|
|
6
|
+
var policies = require('../policies.cjs');
|
|
7
|
+
|
|
8
|
+
class RouterInitializer {
|
|
9
|
+
static initialize(app, container, controllers) {
|
|
10
|
+
for (const controllerClass of controllers){
|
|
11
|
+
const controllerMeta = metadata.getMetadata(controllerClass, core.CONTROLLER_METADATA_KEY);
|
|
12
|
+
const routes = metadata.getMetadata(controllerClass, core.ROUTE_METADATA_KEY) ?? [];
|
|
13
|
+
const version = controllerMeta?.version;
|
|
14
|
+
const basePath = version ? http.joinHttpPaths(`/v${version}`, controllerMeta?.path ?? "/") : controllerMeta?.path ?? "/";
|
|
15
|
+
const controllerScope = metadata.getInjectableMetadata(controllerClass)?.scope ?? "singleton";
|
|
16
|
+
const controllerSingleton = controllerScope === "singleton";
|
|
17
|
+
const preResolvedInstance = controllerSingleton ? container.resolve(controllerClass) : undefined;
|
|
18
|
+
const requiresPerRequestController = !controllerSingleton;
|
|
19
|
+
for (const route of routes){
|
|
20
|
+
const fullPath = http.joinHttpPaths(basePath, route.path);
|
|
21
|
+
const method = route.method.toLowerCase();
|
|
22
|
+
const propertyKey = route.propertyKey;
|
|
23
|
+
const needsScope = requiresPerRequestController || typeof container.requiresScope === "function" && container.requiresScope(controllerClass);
|
|
24
|
+
const rawParamMeta = metadata.getMetadata(controllerClass, core.PARAM_METADATA_KEY, propertyKey) ?? [];
|
|
25
|
+
const sortedParams = [
|
|
26
|
+
...rawParamMeta
|
|
27
|
+
].sort((a, b)=>a.index - b.index);
|
|
28
|
+
const designParamTypes = Reflect.getMetadata("design:paramtypes", controllerClass.prototype, propertyKey) ?? [];
|
|
29
|
+
const policyClass = metadata.getMetadata(controllerClass, policies.USE_POLICY_METADATA_KEY, propertyKey);
|
|
30
|
+
const plan = {
|
|
31
|
+
controllerClass,
|
|
32
|
+
propertyKey,
|
|
33
|
+
fullPath,
|
|
34
|
+
method,
|
|
35
|
+
needsScope,
|
|
36
|
+
preResolvedInstance,
|
|
37
|
+
sortedParams,
|
|
38
|
+
designParamTypes,
|
|
39
|
+
policies: policyClass ? [
|
|
40
|
+
policyClass
|
|
41
|
+
] : []
|
|
42
|
+
};
|
|
43
|
+
RouterInitializer.bindRoute(app, plan);
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
static bindRoute(app, plan) {
|
|
48
|
+
const { controllerClass, propertyKey, fullPath, method, needsScope, preResolvedInstance, sortedParams, designParamTypes, policies } = plan;
|
|
49
|
+
const handler = async (req, res, context)=>{
|
|
50
|
+
const profiler = context.kernel.profiler;
|
|
51
|
+
const startedAt = profiler.enabled ? profiler.now() : 0;
|
|
52
|
+
const args = [];
|
|
53
|
+
if (sortedParams.length > 0) {
|
|
54
|
+
const startedAtParams = profiler.enabled ? profiler.now() : 0;
|
|
55
|
+
for (const meta of sortedParams){
|
|
56
|
+
const targetType = designParamTypes[meta.index];
|
|
57
|
+
switch(meta.kind){
|
|
58
|
+
case "req":
|
|
59
|
+
args[meta.index] = req;
|
|
60
|
+
break;
|
|
61
|
+
case "res":
|
|
62
|
+
args[meta.index] = res;
|
|
63
|
+
break;
|
|
64
|
+
case "context":
|
|
65
|
+
args[meta.index] = context;
|
|
66
|
+
break;
|
|
67
|
+
case "body":
|
|
68
|
+
args[meta.index] = await resolveDecoratedValue(app, meta, meta.name ? context.body?.[meta.name] : context.body, "http.request.body", targetType);
|
|
69
|
+
break;
|
|
70
|
+
case "param":
|
|
71
|
+
args[meta.index] = await resolveDecoratedValue(app, meta, meta.name ? context.params?.[meta.name] : context.params, "http.request.params", targetType);
|
|
72
|
+
break;
|
|
73
|
+
case "query":
|
|
74
|
+
args[meta.index] = await resolveDecoratedValue(app, meta, meta.name ? context.query?.get ? context.query.get(meta.name) : context.query?.[meta.name] : toQueryLikeObject(context.query), "http.request.query", targetType);
|
|
75
|
+
break;
|
|
76
|
+
case "header":
|
|
77
|
+
args[meta.index] = await resolveDecoratedValue(app, meta, meta.name ? context.headers?.get?.(meta.name) ?? context.headers?.[meta.name] : toHeadersLikeObject(context.headers), "http.request.headers", targetType);
|
|
78
|
+
break;
|
|
79
|
+
case "cookie":
|
|
80
|
+
args[meta.index] = await resolveDecoratedValue(app, meta, meta.name ? context.cookies?.[meta.name] : context.cookies, "http.request.cookies", targetType);
|
|
81
|
+
break;
|
|
82
|
+
case "state":
|
|
83
|
+
args[meta.index] = meta.name ? context.state.get(meta.name) : context.state.snapshot();
|
|
84
|
+
break;
|
|
85
|
+
case "file":
|
|
86
|
+
args[meta.index] = await req.files?.get(meta.name, meta.options);
|
|
87
|
+
break;
|
|
88
|
+
case "files":
|
|
89
|
+
{
|
|
90
|
+
const all = await req.files?.all(meta.options);
|
|
91
|
+
args[meta.index] = all ? Object.values(all).flat() : [];
|
|
92
|
+
break;
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
if (startedAtParams !== 0) {
|
|
97
|
+
profiler.recordTiming(`pro.controller.resolve_params:${controllerClass.name || "anonymous"}`, profiler.now() - startedAtParams);
|
|
98
|
+
}
|
|
99
|
+
} else {
|
|
100
|
+
args.push(req, res, context);
|
|
101
|
+
}
|
|
102
|
+
const instance = preResolvedInstance ?? context.execution.services.resolve(controllerClass);
|
|
103
|
+
const result = await instance[propertyKey](...args);
|
|
104
|
+
if (startedAt !== 0) {
|
|
105
|
+
profiler.recordTiming(`pro.controller.invoke:${controllerClass.name || "anonymous"}`, profiler.now() - startedAt);
|
|
106
|
+
profiler.recordTiming(`pro.controller.total:${controllerClass.name || "anonymous"}`, profiler.now() - startedAt);
|
|
107
|
+
}
|
|
108
|
+
return result;
|
|
109
|
+
};
|
|
110
|
+
handler._isController = true;
|
|
111
|
+
handler.needsScope = needsScope;
|
|
112
|
+
handler.controllerClass = controllerClass;
|
|
113
|
+
handler.propertyKey = propertyKey;
|
|
114
|
+
const routeOptions = {
|
|
115
|
+
...policies.length > 0 ? {
|
|
116
|
+
policies
|
|
117
|
+
} : {}
|
|
118
|
+
};
|
|
119
|
+
app[method](fullPath, routeOptions, handler);
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
function isSchemaCapableType(value) {
|
|
123
|
+
return typeof value === "function" && value !== String && value !== Number && value !== Boolean && value !== Object && value !== Array && value !== Promise;
|
|
124
|
+
}
|
|
125
|
+
async function resolveDecoratedValue(app, meta, rawValue, source, targetType) {
|
|
126
|
+
const explicitSchema = meta.options?.schema;
|
|
127
|
+
if (explicitSchema !== undefined) {
|
|
128
|
+
return app.validateSchemaInput(explicitSchema, rawValue, source, true);
|
|
129
|
+
}
|
|
130
|
+
if (isSchemaCapableType(targetType) && app.validation.adapter) {
|
|
131
|
+
return app.validateSchemaInput(targetType, rawValue, source, true);
|
|
132
|
+
}
|
|
133
|
+
return rawValue;
|
|
134
|
+
}
|
|
135
|
+
function toQueryLikeObject(value) {
|
|
136
|
+
if (!(value instanceof URLSearchParams)) {
|
|
137
|
+
return value;
|
|
138
|
+
}
|
|
139
|
+
const output = Object.create(null);
|
|
140
|
+
for (const key of value.keys()){
|
|
141
|
+
const all = value.getAll(key);
|
|
142
|
+
output[key] = all.length <= 1 ? all[0] ?? "" : all;
|
|
143
|
+
}
|
|
144
|
+
return output;
|
|
145
|
+
}
|
|
146
|
+
function toHeadersLikeObject(value) {
|
|
147
|
+
if (!(value instanceof Headers)) {
|
|
148
|
+
return value;
|
|
149
|
+
}
|
|
150
|
+
const output = Object.create(null);
|
|
151
|
+
value.forEach((headerValue, key)=>{
|
|
152
|
+
output[key] = headerValue.includes(",") ? headerValue.split(",").map((entry)=>entry.trim()) : headerValue;
|
|
153
|
+
});
|
|
154
|
+
return output;
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
exports.RouterInitializer = RouterInitializer;
|
|
158
|
+
//# sourceMappingURL=router-initializer.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"router-initializer.cjs","sources":["../../../../packages/pro/src/core/router-initializer.ts"],"sourcesContent":["import { CONTROLLER_METADATA_KEY, PARAM_METADATA_KEY, ROUTE_METADATA_KEY } from \"@athosjs/core\";\nimport { joinHttpPaths } from \"@athosjs/http\";\nimport type { HttpApplication } from \"@athosjs/http/application\";\nimport { getInjectableMetadata, getMetadata } from \"@athosjs/metadata\";\nimport { USE_POLICY_METADATA_KEY } from \"../policies\";\n\ninterface CompiledParam {\n\tindex: number;\n\tkind: string;\n\tname?: string;\n\toptions?: { schema?: unknown };\n}\n\ninterface ControllerRoutePlan {\n\tcontrollerClass: any;\n\tpropertyKey: string;\n\tfullPath: string;\n\tmethod: string;\n\tneedsScope: boolean;\n\tpreResolvedInstance: any | undefined;\n\tsortedParams: CompiledParam[];\n\tdesignParamTypes: any[];\n\tpolicies: any[];\n}\n\nexport class RouterInitializer {\n\tstatic initialize(app: HttpApplication, container: any, controllers: any[]) {\n\t\tfor (const controllerClass of controllers) {\n\t\t\tconst controllerMeta = getMetadata<any>(controllerClass, CONTROLLER_METADATA_KEY);\n\t\t\tconst routes = getMetadata<any[]>(controllerClass, ROUTE_METADATA_KEY) ?? [];\n\t\t\tconst version = controllerMeta?.version;\n\t\t\tconst basePath = version ? joinHttpPaths(`/v${version}`, controllerMeta?.path ?? \"/\") : (controllerMeta?.path ?? \"/\");\n\t\t\tconst controllerScope = getInjectableMetadata(controllerClass)?.scope ?? \"singleton\";\n\t\t\tconst controllerSingleton = controllerScope === \"singleton\";\n\t\t\tconst preResolvedInstance = controllerSingleton ? container.resolve(controllerClass) : undefined;\n\t\t\tconst requiresPerRequestController = !controllerSingleton;\n\n\t\t\tfor (const route of routes) {\n\t\t\t\tconst fullPath = joinHttpPaths(basePath, route.path);\n\t\t\t\tconst method = route.method.toLowerCase();\n\t\t\t\tconst propertyKey = route.propertyKey;\n\t\t\t\tconst needsScope =\n\t\t\t\t\trequiresPerRequestController ||\n\t\t\t\t\t(typeof container.requiresScope === \"function\" && container.requiresScope(controllerClass));\n\n\t\t\t\tconst rawParamMeta: CompiledParam[] = getMetadata<any[]>(controllerClass, PARAM_METADATA_KEY, propertyKey) ?? [];\n\t\t\t\tconst sortedParams = [...rawParamMeta].sort((a: any, b: any) => a.index - b.index);\n\t\t\t\tconst designParamTypes: any[] =\n\t\t\t\t\tReflect.getMetadata(\"design:paramtypes\", controllerClass.prototype, propertyKey) ?? [];\n\n\t\t\t\tconst policyClass = getMetadata(controllerClass, USE_POLICY_METADATA_KEY, propertyKey);\n\n\t\t\t\tconst plan: ControllerRoutePlan = {\n\t\t\t\t\tcontrollerClass,\n\t\t\t\t\tpropertyKey,\n\t\t\t\t\tfullPath,\n\t\t\t\t\tmethod,\n\t\t\t\t\tneedsScope,\n\t\t\t\t\tpreResolvedInstance,\n\t\t\t\t\tsortedParams,\n\t\t\t\t\tdesignParamTypes,\n\t\t\t\t\tpolicies: policyClass ? [policyClass] : [],\n\t\t\t\t};\n\n\t\t\t\tRouterInitializer.bindRoute(app, plan);\n\t\t\t}\n\t\t}\n\t}\n\n\tstatic bindRoute(app: HttpApplication, plan: ControllerRoutePlan) {\n\t\tconst { controllerClass, propertyKey, fullPath, method, needsScope, preResolvedInstance, sortedParams, designParamTypes, policies } = plan;\n\n\t\tconst handler = async (req: any, res: any, context: any) => {\n\t\t\tconst profiler = context.kernel.profiler;\n\t\t\tconst startedAt = profiler.enabled ? profiler.now() : 0;\n\t\t\tconst args: any[] = [];\n\n\t\t\tif (sortedParams.length > 0) {\n\t\t\t\tconst startedAtParams = profiler.enabled ? profiler.now() : 0;\n\t\t\t\tfor (const meta of sortedParams) {\n\t\t\t\t\tconst targetType = designParamTypes[meta.index];\n\t\t\t\t\tswitch (meta.kind) {\n\t\t\t\t\t\tcase \"req\":\n\t\t\t\t\t\t\targs[meta.index] = req;\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\tcase \"res\":\n\t\t\t\t\t\t\targs[meta.index] = res;\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\tcase \"context\":\n\t\t\t\t\t\t\targs[meta.index] = context;\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\tcase \"body\":\n\t\t\t\t\t\t\targs[meta.index] = await resolveDecoratedValue(\n\t\t\t\t\t\t\t\tapp, meta, meta.name ? context.body?.[meta.name] : context.body,\n\t\t\t\t\t\t\t\t\"http.request.body\", targetType,\n\t\t\t\t\t\t\t);\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\tcase \"param\":\n\t\t\t\t\t\t\targs[meta.index] = await resolveDecoratedValue(\n\t\t\t\t\t\t\t\tapp, meta, meta.name ? context.params?.[meta.name] : context.params,\n\t\t\t\t\t\t\t\t\"http.request.params\", targetType,\n\t\t\t\t\t\t\t);\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\tcase \"query\":\n\t\t\t\t\t\t\targs[meta.index] = await resolveDecoratedValue(\n\t\t\t\t\t\t\t\tapp, meta,\n\t\t\t\t\t\t\t\tmeta.name\n\t\t\t\t\t\t\t\t\t? (context.query?.get ? context.query.get(meta.name) : context.query?.[meta.name])\n\t\t\t\t\t\t\t\t\t: toQueryLikeObject(context.query),\n\t\t\t\t\t\t\t\t\"http.request.query\", targetType,\n\t\t\t\t\t\t\t);\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\tcase \"header\":\n\t\t\t\t\t\t\targs[meta.index] = await resolveDecoratedValue(\n\t\t\t\t\t\t\t\tapp, meta,\n\t\t\t\t\t\t\t\tmeta.name ? (context.headers?.get?.(meta.name) ?? context.headers?.[meta.name]) : toHeadersLikeObject(context.headers),\n\t\t\t\t\t\t\t\t\"http.request.headers\", targetType,\n\t\t\t\t\t\t\t);\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\tcase \"cookie\":\n\t\t\t\t\t\t\targs[meta.index] = await resolveDecoratedValue(\n\t\t\t\t\t\t\t\tapp, meta, meta.name ? context.cookies?.[meta.name] : context.cookies,\n\t\t\t\t\t\t\t\t\"http.request.cookies\", targetType,\n\t\t\t\t\t\t\t);\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\tcase \"state\":\n\t\t\t\t\t\t\targs[meta.index] = meta.name ? context.state.get(meta.name) : context.state.snapshot();\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\tcase \"file\":\n\t\t\t\t\t\t\targs[meta.index] = await req.files?.get(meta.name, meta.options);\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\tcase \"files\": {\n\t\t\t\t\t\t\tconst all = await req.files?.all(meta.options);\n\t\t\t\t\t\t\targs[meta.index] = all ? Object.values(all).flat() : [];\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tif (startedAtParams !== 0) {\n\t\t\t\t\tprofiler.recordTiming(\n\t\t\t\t\t\t`pro.controller.resolve_params:${controllerClass.name || \"anonymous\"}`,\n\t\t\t\t\t\tprofiler.now() - startedAtParams,\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\targs.push(req, res, context);\n\t\t\t}\n\n\t\t\tconst instance = preResolvedInstance ?? context.execution.services.resolve(controllerClass);\n\t\t\tconst result = await instance[propertyKey](...args);\n\n\t\t\tif (startedAt !== 0) {\n\t\t\t\tprofiler.recordTiming(`pro.controller.invoke:${controllerClass.name || \"anonymous\"}`, profiler.now() - startedAt);\n\t\t\t\tprofiler.recordTiming(`pro.controller.total:${controllerClass.name || \"anonymous\"}`, profiler.now() - startedAt);\n\t\t\t}\n\n\t\t\treturn result;\n\t\t};\n\n\t\t(handler as any)._isController = true;\n\t\t(handler as any).needsScope = needsScope;\n\t\t(handler as any).controllerClass = controllerClass;\n\t\t(handler as any).propertyKey = propertyKey;\n\n\t\tconst routeOptions: any = { ...(policies.length > 0 ? { policies } : {}) };\n\t\t(app as any)[method](fullPath, routeOptions, handler);\n\t}\n}\n\nfunction isSchemaCapableType(value: unknown): boolean {\n\treturn (\n\t\ttypeof value === \"function\" &&\n\t\tvalue !== String &&\n\t\tvalue !== Number &&\n\t\tvalue !== Boolean &&\n\t\tvalue !== Object &&\n\t\tvalue !== Array &&\n\t\tvalue !== Promise\n\t);\n}\n\nasync function resolveDecoratedValue(\n\tapp: HttpApplication,\n\tmeta: any,\n\trawValue: unknown,\n\tsource: string,\n\ttargetType: unknown,\n): Promise<unknown> {\n\tconst explicitSchema = meta.options?.schema;\n\tif (explicitSchema !== undefined) {\n\t\treturn app.validateSchemaInput(explicitSchema, rawValue, source, true);\n\t}\n\n\tif (isSchemaCapableType(targetType) && app.validation.adapter) {\n\t\treturn app.validateSchemaInput(targetType, rawValue, source, true);\n\t}\n\n\treturn rawValue;\n}\n\nfunction toQueryLikeObject(value: unknown): unknown {\n\tif (!(value instanceof URLSearchParams)) {\n\t\treturn value;\n\t}\n\n\tconst output: Record<string, string | string[]> = Object.create(null);\n\tfor (const key of value.keys()) {\n\t\tconst all = value.getAll(key);\n\t\toutput[key] = all.length <= 1 ? (all[0] ?? \"\") : all;\n\t}\n\treturn output;\n}\n\nfunction toHeadersLikeObject(value: unknown): unknown {\n\tif (!(value instanceof Headers)) {\n\t\treturn value;\n\t}\n\n\tconst output: Record<string, string | string[]> = Object.create(null);\n\tvalue.forEach((headerValue, key) => {\n\t\toutput[key] = headerValue.includes(\",\") ? headerValue.split(\",\").map((entry) => entry.trim()) : headerValue;\n\t});\n\treturn output;\n}\n"],"names":["RouterInitializer","initialize","app","container","controllers","controllerClass","controllerMeta","getMetadata","CONTROLLER_METADATA_KEY","routes","ROUTE_METADATA_KEY","version","basePath","joinHttpPaths","path","controllerScope","getInjectableMetadata","scope","controllerSingleton","preResolvedInstance","resolve","undefined","requiresPerRequestController","route","fullPath","method","toLowerCase","propertyKey","needsScope","requiresScope","rawParamMeta","PARAM_METADATA_KEY","sortedParams","sort","a","b","index","designParamTypes","Reflect","prototype","policyClass","USE_POLICY_METADATA_KEY","plan","policies","bindRoute","handler","req","res","context","profiler","kernel","startedAt","enabled","now","args","length","startedAtParams","meta","targetType","kind","resolveDecoratedValue","name","body","params","query","get","toQueryLikeObject","headers","toHeadersLikeObject","cookies","state","snapshot","files","options","all","Object","values","flat","recordTiming","push","instance","execution","services","result","_isController","routeOptions","isSchemaCapableType","value","String","Number","Boolean","Array","Promise","rawValue","source","explicitSchema","schema","validateSchemaInput","validation","adapter","URLSearchParams","output","create","key","keys","getAll","Headers","forEach","headerValue","includes","split","map","entry","trim"],"mappings":";;;;;;;AAyBO,MAAMA,iBAAAA,CAAAA;AACZ,IAAA,OAAOC,WAAWC,GAAoB,EAAEC,SAAc,EAAEC,WAAkB,EAAE;QAC3E,KAAK,MAAMC,mBAAmBD,WAAAA,CAAa;YAC1C,MAAME,cAAAA,GAAiBC,qBAAiBF,eAAAA,EAAiBG,4BAAAA,CAAAA;AACzD,YAAA,MAAMC,MAAAA,GAASF,oBAAAA,CAAmBF,eAAAA,EAAiBK,uBAAAA,CAAAA,IAAuB,EAAE;AAC5E,YAAA,MAAMC,UAAUL,cAAAA,EAAgBK,OAAAA;AAChC,YAAA,MAAMC,QAAAA,GAAWD,OAAAA,GAAUE,kBAAAA,CAAc,CAAC,EAAE,EAAEF,OAAAA,CAAAA,CAAS,EAAEL,cAAAA,EAAgBQ,IAAAA,IAAQ,GAAA,CAAA,GAAQR,cAAAA,EAAgBQ,IAAAA,IAAQ,GAAA;YACjH,MAAMC,eAAAA,GAAkBC,8BAAAA,CAAsBX,eAAAA,CAAAA,EAAkBY,KAAAA,IAAS,WAAA;AACzE,YAAA,MAAMC,sBAAsBH,eAAAA,KAAoB,WAAA;AAChD,YAAA,MAAMI,mBAAAA,GAAsBD,mBAAAA,GAAsBf,SAAAA,CAAUiB,OAAO,CAACf,eAAAA,CAAAA,GAAmBgB,SAAAA;AACvF,YAAA,MAAMC,+BAA+B,CAACJ,mBAAAA;YAEtC,KAAK,MAAMK,SAASd,MAAAA,CAAQ;AAC3B,gBAAA,MAAMe,QAAAA,GAAWX,kBAAAA,CAAcD,QAAAA,EAAUW,KAAAA,CAAMT,IAAI,CAAA;AACnD,gBAAA,MAAMW,MAAAA,GAASF,KAAAA,CAAME,MAAM,CAACC,WAAW,EAAA;gBACvC,MAAMC,WAAAA,GAAcJ,MAAMI,WAAW;gBACrC,MAAMC,UAAAA,GACLN,gCACC,OAAOnB,SAAAA,CAAU0B,aAAa,KAAK,UAAA,IAAc1B,SAAAA,CAAU0B,aAAa,CAACxB,eAAAA,CAAAA;AAE3E,gBAAA,MAAMyB,YAAAA,GAAgCvB,oBAAAA,CAAmBF,eAAAA,EAAiB0B,uBAAAA,EAAoBJ,gBAAgB,EAAE;AAChH,gBAAA,MAAMK,YAAAA,GAAe;AAAIF,oBAAAA,GAAAA;iBAAa,CAACG,IAAI,CAAC,CAACC,CAAAA,EAAQC,IAAWD,CAAAA,CAAEE,KAAK,GAAGD,CAAAA,CAAEC,KAAK,CAAA;gBACjF,MAAMC,gBAAAA,GACLC,QAAQ/B,WAAW,CAAC,qBAAqBF,eAAAA,CAAgBkC,SAAS,EAAEZ,WAAAA,CAAAA,IAAgB,EAAE;gBAEvF,MAAMa,WAAAA,GAAcjC,oBAAAA,CAAYF,eAAAA,EAAiBoC,gCAAAA,EAAyBd,WAAAA,CAAAA;AAE1E,gBAAA,MAAMe,IAAAA,GAA4B;AACjCrC,oBAAAA,eAAAA;AACAsB,oBAAAA,WAAAA;AACAH,oBAAAA,QAAAA;AACAC,oBAAAA,MAAAA;AACAG,oBAAAA,UAAAA;AACAT,oBAAAA,mBAAAA;AACAa,oBAAAA,YAAAA;AACAK,oBAAAA,gBAAAA;AACAM,oBAAAA,QAAAA,EAAUH,WAAAA,GAAc;AAACA,wBAAAA;AAAY,qBAAA,GAAG;AACzC,iBAAA;gBAEAxC,iBAAAA,CAAkB4C,SAAS,CAAC1C,GAAAA,EAAKwC,IAAAA,CAAAA;AAClC,YAAA;AACD,QAAA;AACD,IAAA;AAEA,IAAA,OAAOE,SAAAA,CAAU1C,GAAoB,EAAEwC,IAAyB,EAAE;AACjE,QAAA,MAAM,EAAErC,eAAe,EAAEsB,WAAW,EAAEH,QAAQ,EAAEC,MAAM,EAAEG,UAAU,EAAET,mBAAmB,EAAEa,YAAY,EAAEK,gBAAgB,EAAEM,QAAQ,EAAE,GAAGD,IAAAA;QAEtI,MAAMG,OAAAA,GAAU,OAAOC,GAAAA,EAAUC,GAAAA,EAAUC,OAAAA,GAAAA;AAC1C,YAAA,MAAMC,QAAAA,GAAWD,OAAAA,CAAQE,MAAM,CAACD,QAAQ;AACxC,YAAA,MAAME,YAAYF,QAAAA,CAASG,OAAO,GAAGH,QAAAA,CAASI,GAAG,EAAA,GAAK,CAAA;AACtD,YAAA,MAAMC,OAAc,EAAE;YAEtB,IAAItB,YAAAA,CAAauB,MAAM,GAAG,CAAA,EAAG;AAC5B,gBAAA,MAAMC,kBAAkBP,QAAAA,CAASG,OAAO,GAAGH,QAAAA,CAASI,GAAG,EAAA,GAAK,CAAA;gBAC5D,KAAK,MAAMI,QAAQzB,YAAAA,CAAc;AAChC,oBAAA,MAAM0B,UAAAA,GAAarB,gBAAgB,CAACoB,IAAAA,CAAKrB,KAAK,CAAC;AAC/C,oBAAA,OAAQqB,KAAKE,IAAI;wBAChB,KAAK,KAAA;AACJL,4BAAAA,IAAI,CAACG,IAAAA,CAAKrB,KAAK,CAAC,GAAGU,GAAAA;AACnB,4BAAA;wBACD,KAAK,KAAA;AACJQ,4BAAAA,IAAI,CAACG,IAAAA,CAAKrB,KAAK,CAAC,GAAGW,GAAAA;AACnB,4BAAA;wBACD,KAAK,SAAA;AACJO,4BAAAA,IAAI,CAACG,IAAAA,CAAKrB,KAAK,CAAC,GAAGY,OAAAA;AACnB,4BAAA;wBACD,KAAK,MAAA;4BACJM,IAAI,CAACG,KAAKrB,KAAK,CAAC,GAAG,MAAMwB,qBAAAA,CACxB1D,GAAAA,EAAKuD,IAAAA,EAAMA,IAAAA,CAAKI,IAAI,GAAGb,OAAAA,CAAQc,IAAI,GAAGL,IAAAA,CAAKI,IAAI,CAAC,GAAGb,OAAAA,CAAQc,IAAI,EAC/D,mBAAA,EAAqBJ,UAAAA,CAAAA;AAEtB,4BAAA;wBACD,KAAK,OAAA;4BACJJ,IAAI,CAACG,KAAKrB,KAAK,CAAC,GAAG,MAAMwB,qBAAAA,CACxB1D,GAAAA,EAAKuD,IAAAA,EAAMA,IAAAA,CAAKI,IAAI,GAAGb,OAAAA,CAAQe,MAAM,GAAGN,IAAAA,CAAKI,IAAI,CAAC,GAAGb,OAAAA,CAAQe,MAAM,EACnE,qBAAA,EAAuBL,UAAAA,CAAAA;AAExB,4BAAA;wBACD,KAAK,OAAA;AACJJ,4BAAAA,IAAI,CAACG,IAAAA,CAAKrB,KAAK,CAAC,GAAG,MAAMwB,qBAAAA,CACxB1D,GAAAA,EAAKuD,IAAAA,EACLA,IAAAA,CAAKI,IAAI,GACLb,OAAAA,CAAQgB,KAAK,EAAEC,MAAMjB,OAAAA,CAAQgB,KAAK,CAACC,GAAG,CAACR,IAAAA,CAAKI,IAAI,CAAA,GAAIb,OAAAA,CAAQgB,KAAK,GAAGP,IAAAA,CAAKI,IAAI,CAAC,GAC/EK,iBAAAA,CAAkBlB,OAAAA,CAAQgB,KAAK,GAClC,oBAAA,EAAsBN,UAAAA,CAAAA;AAEvB,4BAAA;wBACD,KAAK,QAAA;AACJJ,4BAAAA,IAAI,CAACG,IAAAA,CAAKrB,KAAK,CAAC,GAAG,MAAMwB,qBAAAA,CACxB1D,GAAAA,EAAKuD,IAAAA,EACLA,IAAAA,CAAKI,IAAI,GAAIb,QAAQmB,OAAO,EAAEF,GAAAA,GAAMR,IAAAA,CAAKI,IAAI,CAAA,IAAKb,OAAAA,CAAQmB,OAAO,GAAGV,IAAAA,CAAKI,IAAI,CAAC,GAAIO,mBAAAA,CAAoBpB,OAAAA,CAAQmB,OAAO,GACrH,sBAAA,EAAwBT,UAAAA,CAAAA;AAEzB,4BAAA;wBACD,KAAK,QAAA;4BACJJ,IAAI,CAACG,KAAKrB,KAAK,CAAC,GAAG,MAAMwB,qBAAAA,CACxB1D,GAAAA,EAAKuD,IAAAA,EAAMA,IAAAA,CAAKI,IAAI,GAAGb,OAAAA,CAAQqB,OAAO,GAAGZ,IAAAA,CAAKI,IAAI,CAAC,GAAGb,OAAAA,CAAQqB,OAAO,EACrE,sBAAA,EAAwBX,UAAAA,CAAAA;AAEzB,4BAAA;wBACD,KAAK,OAAA;AACJJ,4BAAAA,IAAI,CAACG,IAAAA,CAAKrB,KAAK,CAAC,GAAGqB,IAAAA,CAAKI,IAAI,GAAGb,OAAAA,CAAQsB,KAAK,CAACL,GAAG,CAACR,IAAAA,CAAKI,IAAI,IAAIb,OAAAA,CAAQsB,KAAK,CAACC,QAAQ,EAAA;AACpF,4BAAA;wBACD,KAAK,MAAA;AACJjB,4BAAAA,IAAI,CAACG,IAAAA,CAAKrB,KAAK,CAAC,GAAG,MAAMU,GAAAA,CAAI0B,KAAK,EAAEP,GAAAA,CAAIR,IAAAA,CAAKI,IAAI,EAAEJ,KAAKgB,OAAO,CAAA;AAC/D,4BAAA;wBACD,KAAK,OAAA;AAAS,4BAAA;AACb,gCAAA,MAAMC,MAAM,MAAM5B,GAAAA,CAAI0B,KAAK,EAAEE,GAAAA,CAAIjB,KAAKgB,OAAO,CAAA;AAC7CnB,gCAAAA,IAAI,CAACG,IAAAA,CAAKrB,KAAK,CAAC,GAAGsC,GAAAA,GAAMC,MAAAA,CAAOC,MAAM,CAACF,GAAAA,CAAAA,CAAKG,IAAI,EAAA,GAAK,EAAE;AACvD,gCAAA;AACD,4BAAA;AACD;AACD,gBAAA;AACA,gBAAA,IAAIrB,oBAAoB,CAAA,EAAG;AAC1BP,oBAAAA,QAAAA,CAAS6B,YAAY,CACpB,CAAC,8BAA8B,EAAEzE,eAAAA,CAAgBwD,IAAI,IAAI,WAAA,CAAA,CAAa,EACtEZ,QAAAA,CAASI,GAAG,EAAA,GAAKG,eAAAA,CAAAA;AAEnB,gBAAA;YACD,CAAA,MAAO;gBACNF,IAAAA,CAAKyB,IAAI,CAACjC,GAAAA,EAAKC,GAAAA,EAAKC,OAAAA,CAAAA;AACrB,YAAA;YAEA,MAAMgC,QAAAA,GAAW7D,uBAAuB6B,OAAAA,CAAQiC,SAAS,CAACC,QAAQ,CAAC9D,OAAO,CAACf,eAAAA,CAAAA;AAC3E,YAAA,MAAM8E,MAAAA,GAAS,MAAMH,QAAQ,CAACrD,YAAY,CAAA,GAAI2B,IAAAA,CAAAA;AAE9C,YAAA,IAAIH,cAAc,CAAA,EAAG;AACpBF,gBAAAA,QAAAA,CAAS6B,YAAY,CAAC,CAAC,sBAAsB,EAAEzE,eAAAA,CAAgBwD,IAAI,IAAI,WAAA,CAAA,CAAa,EAAEZ,QAAAA,CAASI,GAAG,EAAA,GAAKF,SAAAA,CAAAA;AACvGF,gBAAAA,QAAAA,CAAS6B,YAAY,CAAC,CAAC,qBAAqB,EAAEzE,eAAAA,CAAgBwD,IAAI,IAAI,WAAA,CAAA,CAAa,EAAEZ,QAAAA,CAASI,GAAG,EAAA,GAAKF,SAAAA,CAAAA;AACvG,YAAA;YAEA,OAAOgC,MAAAA;AACR,QAAA,CAAA;AAECtC,QAAAA,OAAAA,CAAgBuC,aAAa,GAAG,IAAA;AAChCvC,QAAAA,OAAAA,CAAgBjB,UAAU,GAAGA,UAAAA;AAC7BiB,QAAAA,OAAAA,CAAgBxC,eAAe,GAAGA,eAAAA;AAClCwC,QAAAA,OAAAA,CAAgBlB,WAAW,GAAGA,WAAAA;AAE/B,QAAA,MAAM0D,YAAAA,GAAoB;YAAE,GAAI1C,QAAAA,CAASY,MAAM,GAAG,CAAA,GAAI;AAAEZ,gBAAAA;AAAS,aAAA,GAAI;AAAI,SAAA;AACxEzC,QAAAA,GAAW,CAACuB,MAAAA,CAAO,CAACD,QAAAA,EAAU6D,YAAAA,EAAcxC,OAAAA,CAAAA;AAC9C,IAAA;AACD;AAEA,SAASyC,oBAAoBC,KAAc,EAAA;AAC1C,IAAA,OACC,OAAOA,KAAAA,KAAU,UAAA,IACjBA,KAAAA,KAAUC,MAAAA,IACVD,KAAAA,KAAUE,MAAAA,IACVF,KAAAA,KAAUG,OAAAA,IACVH,KAAAA,KAAUZ,MAAAA,IACVY,KAAAA,KAAUI,SACVJ,KAAAA,KAAUK,OAAAA;AAEZ;AAEA,eAAehC,qBAAAA,CACd1D,GAAoB,EACpBuD,IAAS,EACToC,QAAiB,EACjBC,MAAc,EACdpC,UAAmB,EAAA;IAEnB,MAAMqC,cAAAA,GAAiBtC,IAAAA,CAAKgB,OAAO,EAAEuB,MAAAA;AACrC,IAAA,IAAID,mBAAmB1E,SAAAA,EAAW;AACjC,QAAA,OAAOnB,GAAAA,CAAI+F,mBAAmB,CAACF,cAAAA,EAAgBF,UAAUC,MAAAA,EAAQ,IAAA,CAAA;AAClE,IAAA;AAEA,IAAA,IAAIR,oBAAoB5B,UAAAA,CAAAA,IAAexD,GAAAA,CAAIgG,UAAU,CAACC,OAAO,EAAE;AAC9D,QAAA,OAAOjG,GAAAA,CAAI+F,mBAAmB,CAACvC,UAAAA,EAAYmC,UAAUC,MAAAA,EAAQ,IAAA,CAAA;AAC9D,IAAA;IAEA,OAAOD,QAAAA;AACR;AAEA,SAAS3B,kBAAkBqB,KAAc,EAAA;AACxC,IAAA,IAAI,EAAEA,KAAAA,YAAiBa,eAAc,CAAA,EAAI;QACxC,OAAOb,KAAAA;AACR,IAAA;IAEA,MAAMc,MAAAA,GAA4C1B,MAAAA,CAAO2B,MAAM,CAAC,IAAA,CAAA;AAChE,IAAA,KAAK,MAAMC,GAAAA,IAAOhB,KAAAA,CAAMiB,IAAI,EAAA,CAAI;QAC/B,MAAM9B,GAAAA,GAAMa,KAAAA,CAAMkB,MAAM,CAACF,GAAAA,CAAAA;QACzBF,MAAM,CAACE,GAAAA,CAAI,GAAG7B,GAAAA,CAAInB,MAAM,IAAI,CAAA,GAAKmB,GAAG,CAAC,CAAA,CAAE,IAAI,EAAA,GAAMA,GAAAA;AAClD,IAAA;IACA,OAAO2B,MAAAA;AACR;AAEA,SAASjC,oBAAoBmB,KAAc,EAAA;AAC1C,IAAA,IAAI,EAAEA,KAAAA,YAAiBmB,OAAM,CAAA,EAAI;QAChC,OAAOnB,KAAAA;AACR,IAAA;IAEA,MAAMc,MAAAA,GAA4C1B,MAAAA,CAAO2B,MAAM,CAAC,IAAA,CAAA;IAChEf,KAAAA,CAAMoB,OAAO,CAAC,CAACC,WAAAA,EAAaL,GAAAA,GAAAA;AAC3BF,QAAAA,MAAM,CAACE,GAAAA,CAAI,GAAGK,WAAAA,CAAYC,QAAQ,CAAC,GAAA,CAAA,GAAOD,WAAAA,CAAYE,KAAK,CAAC,KAAKC,GAAG,CAAC,CAACC,KAAAA,GAAUA,KAAAA,CAAMC,IAAI,EAAA,CAAA,GAAML,WAAAA;AACjG,IAAA,CAAA,CAAA;IACA,OAAOP,MAAAA;AACR;;;;"}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import type { HttpApplication } from "@athosjs/http/application";
|
|
2
|
+
interface CompiledParam {
|
|
3
|
+
index: number;
|
|
4
|
+
kind: string;
|
|
5
|
+
name?: string;
|
|
6
|
+
options?: {
|
|
7
|
+
schema?: unknown;
|
|
8
|
+
};
|
|
9
|
+
}
|
|
10
|
+
interface ControllerRoutePlan {
|
|
11
|
+
controllerClass: any;
|
|
12
|
+
propertyKey: string;
|
|
13
|
+
fullPath: string;
|
|
14
|
+
method: string;
|
|
15
|
+
needsScope: boolean;
|
|
16
|
+
preResolvedInstance: any | undefined;
|
|
17
|
+
sortedParams: CompiledParam[];
|
|
18
|
+
designParamTypes: any[];
|
|
19
|
+
policies: any[];
|
|
20
|
+
}
|
|
21
|
+
export declare class RouterInitializer {
|
|
22
|
+
static initialize(app: HttpApplication, container: any, controllers: any[]): void;
|
|
23
|
+
static bindRoute(app: HttpApplication, plan: ControllerRoutePlan): void;
|
|
24
|
+
}
|
|
25
|
+
export {};
|
|
26
|
+
//# sourceMappingURL=router-initializer.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"router-initializer.d.ts","sourceRoot":"","sources":["../../../../../../../packages/pro/src/core/router-initializer.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,2BAA2B,CAAC;AAIjE,UAAU,aAAa;IACtB,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,OAAO,CAAC,EAAE;QAAE,MAAM,CAAC,EAAE,OAAO,CAAA;KAAE,CAAC;CAC/B;AAED,UAAU,mBAAmB;IAC5B,eAAe,EAAE,GAAG,CAAC;IACrB,WAAW,EAAE,MAAM,CAAC;IACpB,QAAQ,EAAE,MAAM,CAAC;IACjB,MAAM,EAAE,MAAM,CAAC;IACf,UAAU,EAAE,OAAO,CAAC;IACpB,mBAAmB,EAAE,GAAG,GAAG,SAAS,CAAC;IACrC,YAAY,EAAE,aAAa,EAAE,CAAC;IAC9B,gBAAgB,EAAE,GAAG,EAAE,CAAC;IACxB,QAAQ,EAAE,GAAG,EAAE,CAAC;CAChB;AAED,qBAAa,iBAAiB;IAC7B,MAAM,CAAC,UAAU,CAAC,GAAG,EAAE,eAAe,EAAE,SAAS,EAAE,GAAG,EAAE,WAAW,EAAE,GAAG,EAAE;IA2C1E,MAAM,CAAC,SAAS,CAAC,GAAG,EAAE,eAAe,EAAE,IAAI,EAAE,mBAAmB;CAkGhE"}
|
|
@@ -0,0 +1,156 @@
|
|
|
1
|
+
import { CONTROLLER_METADATA_KEY, ROUTE_METADATA_KEY, PARAM_METADATA_KEY } from '@athosjs/core';
|
|
2
|
+
import { joinHttpPaths } from '@athosjs/http';
|
|
3
|
+
import { getMetadata, getInjectableMetadata } from '@athosjs/metadata';
|
|
4
|
+
import { USE_POLICY_METADATA_KEY } from '../policies.js';
|
|
5
|
+
|
|
6
|
+
class RouterInitializer {
|
|
7
|
+
static initialize(app, container, controllers) {
|
|
8
|
+
for (const controllerClass of controllers){
|
|
9
|
+
const controllerMeta = getMetadata(controllerClass, CONTROLLER_METADATA_KEY);
|
|
10
|
+
const routes = getMetadata(controllerClass, ROUTE_METADATA_KEY) ?? [];
|
|
11
|
+
const version = controllerMeta?.version;
|
|
12
|
+
const basePath = version ? joinHttpPaths(`/v${version}`, controllerMeta?.path ?? "/") : controllerMeta?.path ?? "/";
|
|
13
|
+
const controllerScope = getInjectableMetadata(controllerClass)?.scope ?? "singleton";
|
|
14
|
+
const controllerSingleton = controllerScope === "singleton";
|
|
15
|
+
const preResolvedInstance = controllerSingleton ? container.resolve(controllerClass) : undefined;
|
|
16
|
+
const requiresPerRequestController = !controllerSingleton;
|
|
17
|
+
for (const route of routes){
|
|
18
|
+
const fullPath = joinHttpPaths(basePath, route.path);
|
|
19
|
+
const method = route.method.toLowerCase();
|
|
20
|
+
const propertyKey = route.propertyKey;
|
|
21
|
+
const needsScope = requiresPerRequestController || typeof container.requiresScope === "function" && container.requiresScope(controllerClass);
|
|
22
|
+
const rawParamMeta = getMetadata(controllerClass, PARAM_METADATA_KEY, propertyKey) ?? [];
|
|
23
|
+
const sortedParams = [
|
|
24
|
+
...rawParamMeta
|
|
25
|
+
].sort((a, b)=>a.index - b.index);
|
|
26
|
+
const designParamTypes = Reflect.getMetadata("design:paramtypes", controllerClass.prototype, propertyKey) ?? [];
|
|
27
|
+
const policyClass = getMetadata(controllerClass, USE_POLICY_METADATA_KEY, propertyKey);
|
|
28
|
+
const plan = {
|
|
29
|
+
controllerClass,
|
|
30
|
+
propertyKey,
|
|
31
|
+
fullPath,
|
|
32
|
+
method,
|
|
33
|
+
needsScope,
|
|
34
|
+
preResolvedInstance,
|
|
35
|
+
sortedParams,
|
|
36
|
+
designParamTypes,
|
|
37
|
+
policies: policyClass ? [
|
|
38
|
+
policyClass
|
|
39
|
+
] : []
|
|
40
|
+
};
|
|
41
|
+
RouterInitializer.bindRoute(app, plan);
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
static bindRoute(app, plan) {
|
|
46
|
+
const { controllerClass, propertyKey, fullPath, method, needsScope, preResolvedInstance, sortedParams, designParamTypes, policies } = plan;
|
|
47
|
+
const handler = async (req, res, context)=>{
|
|
48
|
+
const profiler = context.kernel.profiler;
|
|
49
|
+
const startedAt = profiler.enabled ? profiler.now() : 0;
|
|
50
|
+
const args = [];
|
|
51
|
+
if (sortedParams.length > 0) {
|
|
52
|
+
const startedAtParams = profiler.enabled ? profiler.now() : 0;
|
|
53
|
+
for (const meta of sortedParams){
|
|
54
|
+
const targetType = designParamTypes[meta.index];
|
|
55
|
+
switch(meta.kind){
|
|
56
|
+
case "req":
|
|
57
|
+
args[meta.index] = req;
|
|
58
|
+
break;
|
|
59
|
+
case "res":
|
|
60
|
+
args[meta.index] = res;
|
|
61
|
+
break;
|
|
62
|
+
case "context":
|
|
63
|
+
args[meta.index] = context;
|
|
64
|
+
break;
|
|
65
|
+
case "body":
|
|
66
|
+
args[meta.index] = await resolveDecoratedValue(app, meta, meta.name ? context.body?.[meta.name] : context.body, "http.request.body", targetType);
|
|
67
|
+
break;
|
|
68
|
+
case "param":
|
|
69
|
+
args[meta.index] = await resolveDecoratedValue(app, meta, meta.name ? context.params?.[meta.name] : context.params, "http.request.params", targetType);
|
|
70
|
+
break;
|
|
71
|
+
case "query":
|
|
72
|
+
args[meta.index] = await resolveDecoratedValue(app, meta, meta.name ? context.query?.get ? context.query.get(meta.name) : context.query?.[meta.name] : toQueryLikeObject(context.query), "http.request.query", targetType);
|
|
73
|
+
break;
|
|
74
|
+
case "header":
|
|
75
|
+
args[meta.index] = await resolveDecoratedValue(app, meta, meta.name ? context.headers?.get?.(meta.name) ?? context.headers?.[meta.name] : toHeadersLikeObject(context.headers), "http.request.headers", targetType);
|
|
76
|
+
break;
|
|
77
|
+
case "cookie":
|
|
78
|
+
args[meta.index] = await resolveDecoratedValue(app, meta, meta.name ? context.cookies?.[meta.name] : context.cookies, "http.request.cookies", targetType);
|
|
79
|
+
break;
|
|
80
|
+
case "state":
|
|
81
|
+
args[meta.index] = meta.name ? context.state.get(meta.name) : context.state.snapshot();
|
|
82
|
+
break;
|
|
83
|
+
case "file":
|
|
84
|
+
args[meta.index] = await req.files?.get(meta.name, meta.options);
|
|
85
|
+
break;
|
|
86
|
+
case "files":
|
|
87
|
+
{
|
|
88
|
+
const all = await req.files?.all(meta.options);
|
|
89
|
+
args[meta.index] = all ? Object.values(all).flat() : [];
|
|
90
|
+
break;
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
if (startedAtParams !== 0) {
|
|
95
|
+
profiler.recordTiming(`pro.controller.resolve_params:${controllerClass.name || "anonymous"}`, profiler.now() - startedAtParams);
|
|
96
|
+
}
|
|
97
|
+
} else {
|
|
98
|
+
args.push(req, res, context);
|
|
99
|
+
}
|
|
100
|
+
const instance = preResolvedInstance ?? context.execution.services.resolve(controllerClass);
|
|
101
|
+
const result = await instance[propertyKey](...args);
|
|
102
|
+
if (startedAt !== 0) {
|
|
103
|
+
profiler.recordTiming(`pro.controller.invoke:${controllerClass.name || "anonymous"}`, profiler.now() - startedAt);
|
|
104
|
+
profiler.recordTiming(`pro.controller.total:${controllerClass.name || "anonymous"}`, profiler.now() - startedAt);
|
|
105
|
+
}
|
|
106
|
+
return result;
|
|
107
|
+
};
|
|
108
|
+
handler._isController = true;
|
|
109
|
+
handler.needsScope = needsScope;
|
|
110
|
+
handler.controllerClass = controllerClass;
|
|
111
|
+
handler.propertyKey = propertyKey;
|
|
112
|
+
const routeOptions = {
|
|
113
|
+
...policies.length > 0 ? {
|
|
114
|
+
policies
|
|
115
|
+
} : {}
|
|
116
|
+
};
|
|
117
|
+
app[method](fullPath, routeOptions, handler);
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
function isSchemaCapableType(value) {
|
|
121
|
+
return typeof value === "function" && value !== String && value !== Number && value !== Boolean && value !== Object && value !== Array && value !== Promise;
|
|
122
|
+
}
|
|
123
|
+
async function resolveDecoratedValue(app, meta, rawValue, source, targetType) {
|
|
124
|
+
const explicitSchema = meta.options?.schema;
|
|
125
|
+
if (explicitSchema !== undefined) {
|
|
126
|
+
return app.validateSchemaInput(explicitSchema, rawValue, source, true);
|
|
127
|
+
}
|
|
128
|
+
if (isSchemaCapableType(targetType) && app.validation.adapter) {
|
|
129
|
+
return app.validateSchemaInput(targetType, rawValue, source, true);
|
|
130
|
+
}
|
|
131
|
+
return rawValue;
|
|
132
|
+
}
|
|
133
|
+
function toQueryLikeObject(value) {
|
|
134
|
+
if (!(value instanceof URLSearchParams)) {
|
|
135
|
+
return value;
|
|
136
|
+
}
|
|
137
|
+
const output = Object.create(null);
|
|
138
|
+
for (const key of value.keys()){
|
|
139
|
+
const all = value.getAll(key);
|
|
140
|
+
output[key] = all.length <= 1 ? all[0] ?? "" : all;
|
|
141
|
+
}
|
|
142
|
+
return output;
|
|
143
|
+
}
|
|
144
|
+
function toHeadersLikeObject(value) {
|
|
145
|
+
if (!(value instanceof Headers)) {
|
|
146
|
+
return value;
|
|
147
|
+
}
|
|
148
|
+
const output = Object.create(null);
|
|
149
|
+
value.forEach((headerValue, key)=>{
|
|
150
|
+
output[key] = headerValue.includes(",") ? headerValue.split(",").map((entry)=>entry.trim()) : headerValue;
|
|
151
|
+
});
|
|
152
|
+
return output;
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
export { RouterInitializer };
|
|
156
|
+
//# sourceMappingURL=router-initializer.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"router-initializer.js","sources":["../../../../packages/pro/src/core/router-initializer.ts"],"sourcesContent":["import { CONTROLLER_METADATA_KEY, PARAM_METADATA_KEY, ROUTE_METADATA_KEY } from \"@athosjs/core\";\nimport { joinHttpPaths } from \"@athosjs/http\";\nimport type { HttpApplication } from \"@athosjs/http/application\";\nimport { getInjectableMetadata, getMetadata } from \"@athosjs/metadata\";\nimport { USE_POLICY_METADATA_KEY } from \"../policies\";\n\ninterface CompiledParam {\n\tindex: number;\n\tkind: string;\n\tname?: string;\n\toptions?: { schema?: unknown };\n}\n\ninterface ControllerRoutePlan {\n\tcontrollerClass: any;\n\tpropertyKey: string;\n\tfullPath: string;\n\tmethod: string;\n\tneedsScope: boolean;\n\tpreResolvedInstance: any | undefined;\n\tsortedParams: CompiledParam[];\n\tdesignParamTypes: any[];\n\tpolicies: any[];\n}\n\nexport class RouterInitializer {\n\tstatic initialize(app: HttpApplication, container: any, controllers: any[]) {\n\t\tfor (const controllerClass of controllers) {\n\t\t\tconst controllerMeta = getMetadata<any>(controllerClass, CONTROLLER_METADATA_KEY);\n\t\t\tconst routes = getMetadata<any[]>(controllerClass, ROUTE_METADATA_KEY) ?? [];\n\t\t\tconst version = controllerMeta?.version;\n\t\t\tconst basePath = version ? joinHttpPaths(`/v${version}`, controllerMeta?.path ?? \"/\") : (controllerMeta?.path ?? \"/\");\n\t\t\tconst controllerScope = getInjectableMetadata(controllerClass)?.scope ?? \"singleton\";\n\t\t\tconst controllerSingleton = controllerScope === \"singleton\";\n\t\t\tconst preResolvedInstance = controllerSingleton ? container.resolve(controllerClass) : undefined;\n\t\t\tconst requiresPerRequestController = !controllerSingleton;\n\n\t\t\tfor (const route of routes) {\n\t\t\t\tconst fullPath = joinHttpPaths(basePath, route.path);\n\t\t\t\tconst method = route.method.toLowerCase();\n\t\t\t\tconst propertyKey = route.propertyKey;\n\t\t\t\tconst needsScope =\n\t\t\t\t\trequiresPerRequestController ||\n\t\t\t\t\t(typeof container.requiresScope === \"function\" && container.requiresScope(controllerClass));\n\n\t\t\t\tconst rawParamMeta: CompiledParam[] = getMetadata<any[]>(controllerClass, PARAM_METADATA_KEY, propertyKey) ?? [];\n\t\t\t\tconst sortedParams = [...rawParamMeta].sort((a: any, b: any) => a.index - b.index);\n\t\t\t\tconst designParamTypes: any[] =\n\t\t\t\t\tReflect.getMetadata(\"design:paramtypes\", controllerClass.prototype, propertyKey) ?? [];\n\n\t\t\t\tconst policyClass = getMetadata(controllerClass, USE_POLICY_METADATA_KEY, propertyKey);\n\n\t\t\t\tconst plan: ControllerRoutePlan = {\n\t\t\t\t\tcontrollerClass,\n\t\t\t\t\tpropertyKey,\n\t\t\t\t\tfullPath,\n\t\t\t\t\tmethod,\n\t\t\t\t\tneedsScope,\n\t\t\t\t\tpreResolvedInstance,\n\t\t\t\t\tsortedParams,\n\t\t\t\t\tdesignParamTypes,\n\t\t\t\t\tpolicies: policyClass ? [policyClass] : [],\n\t\t\t\t};\n\n\t\t\t\tRouterInitializer.bindRoute(app, plan);\n\t\t\t}\n\t\t}\n\t}\n\n\tstatic bindRoute(app: HttpApplication, plan: ControllerRoutePlan) {\n\t\tconst { controllerClass, propertyKey, fullPath, method, needsScope, preResolvedInstance, sortedParams, designParamTypes, policies } = plan;\n\n\t\tconst handler = async (req: any, res: any, context: any) => {\n\t\t\tconst profiler = context.kernel.profiler;\n\t\t\tconst startedAt = profiler.enabled ? profiler.now() : 0;\n\t\t\tconst args: any[] = [];\n\n\t\t\tif (sortedParams.length > 0) {\n\t\t\t\tconst startedAtParams = profiler.enabled ? profiler.now() : 0;\n\t\t\t\tfor (const meta of sortedParams) {\n\t\t\t\t\tconst targetType = designParamTypes[meta.index];\n\t\t\t\t\tswitch (meta.kind) {\n\t\t\t\t\t\tcase \"req\":\n\t\t\t\t\t\t\targs[meta.index] = req;\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\tcase \"res\":\n\t\t\t\t\t\t\targs[meta.index] = res;\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\tcase \"context\":\n\t\t\t\t\t\t\targs[meta.index] = context;\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\tcase \"body\":\n\t\t\t\t\t\t\targs[meta.index] = await resolveDecoratedValue(\n\t\t\t\t\t\t\t\tapp, meta, meta.name ? context.body?.[meta.name] : context.body,\n\t\t\t\t\t\t\t\t\"http.request.body\", targetType,\n\t\t\t\t\t\t\t);\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\tcase \"param\":\n\t\t\t\t\t\t\targs[meta.index] = await resolveDecoratedValue(\n\t\t\t\t\t\t\t\tapp, meta, meta.name ? context.params?.[meta.name] : context.params,\n\t\t\t\t\t\t\t\t\"http.request.params\", targetType,\n\t\t\t\t\t\t\t);\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\tcase \"query\":\n\t\t\t\t\t\t\targs[meta.index] = await resolveDecoratedValue(\n\t\t\t\t\t\t\t\tapp, meta,\n\t\t\t\t\t\t\t\tmeta.name\n\t\t\t\t\t\t\t\t\t? (context.query?.get ? context.query.get(meta.name) : context.query?.[meta.name])\n\t\t\t\t\t\t\t\t\t: toQueryLikeObject(context.query),\n\t\t\t\t\t\t\t\t\"http.request.query\", targetType,\n\t\t\t\t\t\t\t);\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\tcase \"header\":\n\t\t\t\t\t\t\targs[meta.index] = await resolveDecoratedValue(\n\t\t\t\t\t\t\t\tapp, meta,\n\t\t\t\t\t\t\t\tmeta.name ? (context.headers?.get?.(meta.name) ?? context.headers?.[meta.name]) : toHeadersLikeObject(context.headers),\n\t\t\t\t\t\t\t\t\"http.request.headers\", targetType,\n\t\t\t\t\t\t\t);\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\tcase \"cookie\":\n\t\t\t\t\t\t\targs[meta.index] = await resolveDecoratedValue(\n\t\t\t\t\t\t\t\tapp, meta, meta.name ? context.cookies?.[meta.name] : context.cookies,\n\t\t\t\t\t\t\t\t\"http.request.cookies\", targetType,\n\t\t\t\t\t\t\t);\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\tcase \"state\":\n\t\t\t\t\t\t\targs[meta.index] = meta.name ? context.state.get(meta.name) : context.state.snapshot();\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\tcase \"file\":\n\t\t\t\t\t\t\targs[meta.index] = await req.files?.get(meta.name, meta.options);\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\tcase \"files\": {\n\t\t\t\t\t\t\tconst all = await req.files?.all(meta.options);\n\t\t\t\t\t\t\targs[meta.index] = all ? Object.values(all).flat() : [];\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tif (startedAtParams !== 0) {\n\t\t\t\t\tprofiler.recordTiming(\n\t\t\t\t\t\t`pro.controller.resolve_params:${controllerClass.name || \"anonymous\"}`,\n\t\t\t\t\t\tprofiler.now() - startedAtParams,\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\targs.push(req, res, context);\n\t\t\t}\n\n\t\t\tconst instance = preResolvedInstance ?? context.execution.services.resolve(controllerClass);\n\t\t\tconst result = await instance[propertyKey](...args);\n\n\t\t\tif (startedAt !== 0) {\n\t\t\t\tprofiler.recordTiming(`pro.controller.invoke:${controllerClass.name || \"anonymous\"}`, profiler.now() - startedAt);\n\t\t\t\tprofiler.recordTiming(`pro.controller.total:${controllerClass.name || \"anonymous\"}`, profiler.now() - startedAt);\n\t\t\t}\n\n\t\t\treturn result;\n\t\t};\n\n\t\t(handler as any)._isController = true;\n\t\t(handler as any).needsScope = needsScope;\n\t\t(handler as any).controllerClass = controllerClass;\n\t\t(handler as any).propertyKey = propertyKey;\n\n\t\tconst routeOptions: any = { ...(policies.length > 0 ? { policies } : {}) };\n\t\t(app as any)[method](fullPath, routeOptions, handler);\n\t}\n}\n\nfunction isSchemaCapableType(value: unknown): boolean {\n\treturn (\n\t\ttypeof value === \"function\" &&\n\t\tvalue !== String &&\n\t\tvalue !== Number &&\n\t\tvalue !== Boolean &&\n\t\tvalue !== Object &&\n\t\tvalue !== Array &&\n\t\tvalue !== Promise\n\t);\n}\n\nasync function resolveDecoratedValue(\n\tapp: HttpApplication,\n\tmeta: any,\n\trawValue: unknown,\n\tsource: string,\n\ttargetType: unknown,\n): Promise<unknown> {\n\tconst explicitSchema = meta.options?.schema;\n\tif (explicitSchema !== undefined) {\n\t\treturn app.validateSchemaInput(explicitSchema, rawValue, source, true);\n\t}\n\n\tif (isSchemaCapableType(targetType) && app.validation.adapter) {\n\t\treturn app.validateSchemaInput(targetType, rawValue, source, true);\n\t}\n\n\treturn rawValue;\n}\n\nfunction toQueryLikeObject(value: unknown): unknown {\n\tif (!(value instanceof URLSearchParams)) {\n\t\treturn value;\n\t}\n\n\tconst output: Record<string, string | string[]> = Object.create(null);\n\tfor (const key of value.keys()) {\n\t\tconst all = value.getAll(key);\n\t\toutput[key] = all.length <= 1 ? (all[0] ?? \"\") : all;\n\t}\n\treturn output;\n}\n\nfunction toHeadersLikeObject(value: unknown): unknown {\n\tif (!(value instanceof Headers)) {\n\t\treturn value;\n\t}\n\n\tconst output: Record<string, string | string[]> = Object.create(null);\n\tvalue.forEach((headerValue, key) => {\n\t\toutput[key] = headerValue.includes(\",\") ? headerValue.split(\",\").map((entry) => entry.trim()) : headerValue;\n\t});\n\treturn output;\n}\n"],"names":["RouterInitializer","initialize","app","container","controllers","controllerClass","controllerMeta","getMetadata","CONTROLLER_METADATA_KEY","routes","ROUTE_METADATA_KEY","version","basePath","joinHttpPaths","path","controllerScope","getInjectableMetadata","scope","controllerSingleton","preResolvedInstance","resolve","undefined","requiresPerRequestController","route","fullPath","method","toLowerCase","propertyKey","needsScope","requiresScope","rawParamMeta","PARAM_METADATA_KEY","sortedParams","sort","a","b","index","designParamTypes","Reflect","prototype","policyClass","USE_POLICY_METADATA_KEY","plan","policies","bindRoute","handler","req","res","context","profiler","kernel","startedAt","enabled","now","args","length","startedAtParams","meta","targetType","kind","resolveDecoratedValue","name","body","params","query","get","toQueryLikeObject","headers","toHeadersLikeObject","cookies","state","snapshot","files","options","all","Object","values","flat","recordTiming","push","instance","execution","services","result","_isController","routeOptions","isSchemaCapableType","value","String","Number","Boolean","Array","Promise","rawValue","source","explicitSchema","schema","validateSchemaInput","validation","adapter","URLSearchParams","output","create","key","keys","getAll","Headers","forEach","headerValue","includes","split","map","entry","trim"],"mappings":"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"}
|
package/core/scanner.cjs
ADDED
|
@@ -0,0 +1,141 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
var node_fs = require('node:fs');
|
|
4
|
+
var constants = require('@athosjs/constants');
|
|
5
|
+
var core = require('@athosjs/core');
|
|
6
|
+
var metadata = require('@athosjs/metadata');
|
|
7
|
+
var platform = require('@athosjs/runtime/platform');
|
|
8
|
+
var node_path = require('node:path');
|
|
9
|
+
|
|
10
|
+
const DISCOVERY_SOURCE_FILE_METADATA_KEY = Symbol.for("athos:discovery:source-file");
|
|
11
|
+
class FileScanner {
|
|
12
|
+
static async scanAndLoad(baseDir, includeDirectories = [
|
|
13
|
+
"src",
|
|
14
|
+
"app"
|
|
15
|
+
], options) {
|
|
16
|
+
const absoluteBaseDir = platform.Platform.path.resolve(FileScanner.#normalizeDiscoveryRoot(baseDir));
|
|
17
|
+
const roots = FileScanner.#resolveDiscoveryRoots(absoluteBaseDir, includeDirectories);
|
|
18
|
+
const files = roots.flatMap((root)=>FileScanner.#walk(root));
|
|
19
|
+
const modules = [];
|
|
20
|
+
const errors = [];
|
|
21
|
+
for (const file of files){
|
|
22
|
+
if (FileScanner.#isLoadable(file)) {
|
|
23
|
+
const resolved = FileScanner.#resolveCompiledFile(file, absoluteBaseDir);
|
|
24
|
+
try {
|
|
25
|
+
const moduleExports = await import(platform.Platform.url.pathToFileURL(resolved).href);
|
|
26
|
+
FileScanner.#annotateDiscoveredModuleExports(moduleExports, file);
|
|
27
|
+
modules.push(moduleExports);
|
|
28
|
+
} catch (error) {
|
|
29
|
+
const cause = error instanceof Error ? error.message : String(error);
|
|
30
|
+
if (options?.ignoreDiscoveryErrors) {
|
|
31
|
+
errors.push({
|
|
32
|
+
file,
|
|
33
|
+
cause
|
|
34
|
+
});
|
|
35
|
+
} else {
|
|
36
|
+
throw core.createAthosError(constants.ATHOS_ERROR_CODES.MODULE_INVALID, `Failed to load discovered file: ${file}. ${cause}`, {
|
|
37
|
+
details: {
|
|
38
|
+
file,
|
|
39
|
+
cause
|
|
40
|
+
}
|
|
41
|
+
});
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
if (errors.length > 0) {
|
|
47
|
+
console.warn(`[athos/discovery] ${errors.length} file(s) failed to load but were ignored:`);
|
|
48
|
+
for (const { file, cause } of errors){
|
|
49
|
+
console.warn(` - ${file}: ${cause}`);
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
return modules;
|
|
53
|
+
}
|
|
54
|
+
static #resolveCompiledFile(file, baseDir) {
|
|
55
|
+
const ext = platform.Platform.path.extname(file);
|
|
56
|
+
if (ext !== ".ts") {
|
|
57
|
+
return file;
|
|
58
|
+
}
|
|
59
|
+
const projectRoot = FileScanner.#findProjectRoot(file);
|
|
60
|
+
if (!projectRoot) {
|
|
61
|
+
return file;
|
|
62
|
+
}
|
|
63
|
+
const distDir = platform.Platform.path.join(projectRoot, "dist");
|
|
64
|
+
if (!node_fs.existsSync(distDir)) {
|
|
65
|
+
return file;
|
|
66
|
+
}
|
|
67
|
+
const relativePath = node_path.relative(baseDir, file);
|
|
68
|
+
const compiledJs = platform.Platform.path.join(distDir, relativePath).replace(/\.ts$/u, ".js");
|
|
69
|
+
if (node_fs.existsSync(compiledJs)) return compiledJs;
|
|
70
|
+
return file;
|
|
71
|
+
}
|
|
72
|
+
static #resolveDiscoveryRoots(baseDir, includeDirectories) {
|
|
73
|
+
const configuredRoots = includeDirectories.map((directory)=>platform.Platform.path.resolve(baseDir, directory)).filter((directory)=>{
|
|
74
|
+
try {
|
|
75
|
+
return node_fs.statSync(directory).isDirectory();
|
|
76
|
+
} catch {
|
|
77
|
+
return false;
|
|
78
|
+
}
|
|
79
|
+
});
|
|
80
|
+
return configuredRoots.length === 0 ? [] : configuredRoots;
|
|
81
|
+
}
|
|
82
|
+
static #walk(dir) {
|
|
83
|
+
const results = [];
|
|
84
|
+
const skipDirs = [
|
|
85
|
+
"node_modules",
|
|
86
|
+
".git",
|
|
87
|
+
"build",
|
|
88
|
+
".athos"
|
|
89
|
+
];
|
|
90
|
+
let list;
|
|
91
|
+
try {
|
|
92
|
+
list = node_fs.readdirSync(dir);
|
|
93
|
+
} catch (error) {
|
|
94
|
+
throw core.createAthosError(constants.ATHOS_ERROR_CODES.MODULE_INVALID, `Failed to scan discovery directory ${dir}.`, {
|
|
95
|
+
details: {
|
|
96
|
+
directory: dir,
|
|
97
|
+
cause: error instanceof Error ? error.message : String(error)
|
|
98
|
+
}
|
|
99
|
+
});
|
|
100
|
+
}
|
|
101
|
+
for (const file of list){
|
|
102
|
+
if (skipDirs.includes(file)) continue;
|
|
103
|
+
const path = platform.Platform.path.join(dir, file);
|
|
104
|
+
const stat = node_fs.statSync(path);
|
|
105
|
+
if (stat?.isDirectory()) {
|
|
106
|
+
results.push(...FileScanner.#walk(path));
|
|
107
|
+
} else {
|
|
108
|
+
results.push(path);
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
return results;
|
|
112
|
+
}
|
|
113
|
+
static #isLoadable(file) {
|
|
114
|
+
const ext = platform.Platform.path.extname(file);
|
|
115
|
+
return (ext === ".ts" || ext === ".js" || ext === "" || ext === ".mjs") && !file.endsWith(".d.ts") && !file.includes(".test.") && !file.includes(".spec.") && !file.includes("/scripts/") && !file.includes("/examples/");
|
|
116
|
+
}
|
|
117
|
+
static #findProjectRoot(dir) {
|
|
118
|
+
let current = node_path.resolve(dir);
|
|
119
|
+
while(true){
|
|
120
|
+
if (node_fs.existsSync(platform.Platform.path.join(current, "package.json"))) return current;
|
|
121
|
+
const parent = node_path.dirname(current);
|
|
122
|
+
if (parent === current) return undefined;
|
|
123
|
+
current = parent;
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
static #annotateDiscoveredModuleExports(moduleExports, file) {
|
|
127
|
+
for (const value of Object.values(moduleExports)){
|
|
128
|
+
if (typeof value === "function") {
|
|
129
|
+
metadata.defineMetadata(value, DISCOVERY_SOURCE_FILE_METADATA_KEY, file);
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
static #normalizeDiscoveryRoot(root) {
|
|
134
|
+
if (root instanceof URL) return platform.Platform.url.fileURLToPath(root);
|
|
135
|
+
if (root.startsWith("file://")) return platform.Platform.url.fileURLToPath(root);
|
|
136
|
+
return root;
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
exports.FileScanner = FileScanner;
|
|
141
|
+
//# sourceMappingURL=scanner.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"scanner.cjs","sources":["../../../../packages/pro/src/core/scanner.ts"],"sourcesContent":["import { readdirSync, statSync, existsSync } from \"node:fs\";\nimport { ATHOS_ERROR_CODES } from \"@athosjs/constants\";\nimport { createAthosError } from \"@athosjs/core\";\nimport { defineMetadata } from \"@athosjs/metadata\";\nimport { Platform } from \"@athosjs/runtime/platform\";\nimport { resolve, dirname, relative } from \"node:path\";\n\nconst DISCOVERY_SOURCE_FILE_METADATA_KEY = Symbol.for(\"athos:discovery:source-file\");\n\nexport class FileScanner {\n\tstatic async scanAndLoad(\n\t\tbaseDir: string | URL,\n\t\tincludeDirectories: readonly string[] = [\"src\", \"app\"],\n\t\toptions?: { ignoreDiscoveryErrors?: boolean },\n\t): Promise<readonly Record<string, unknown>[]> {\n\t\tconst absoluteBaseDir = Platform.path.resolve(FileScanner.#normalizeDiscoveryRoot(baseDir));\n\t\tconst roots = FileScanner.#resolveDiscoveryRoots(absoluteBaseDir, includeDirectories);\n\t\tconst files = roots.flatMap((root) => FileScanner.#walk(root));\n\t\tconst modules: Record<string, unknown>[] = [];\n\t\tconst errors: Array<{ file: string; cause: string }> = [];\n\n\t\tfor (const file of files) {\n\t\t\tif (FileScanner.#isLoadable(file)) {\n\t\t\t\tconst resolved = FileScanner.#resolveCompiledFile(file, absoluteBaseDir);\n\t\t\t\ttry {\n\t\t\t\t\tconst moduleExports = await import(Platform.url.pathToFileURL(resolved).href);\n\t\t\t\t\tFileScanner.#annotateDiscoveredModuleExports(moduleExports, file);\n\t\t\t\t\tmodules.push(moduleExports);\n\t\t\t\t} catch (error) {\n\t\t\t\t\tconst cause = error instanceof Error ? error.message : String(error);\n\t\t\t\t\tif (options?.ignoreDiscoveryErrors) {\n\t\t\t\t\t\terrors.push({ file, cause });\n\t\t\t\t\t} else {\n\t\t\t\t\t\tthrow createAthosError(\n\t\t\t\t\t\t\tATHOS_ERROR_CODES.MODULE_INVALID,\n\t\t\t\t\t\t\t`Failed to load discovered file: ${file}. ${cause}`,\n\t\t\t\t\t\t\t{ details: { file, cause } },\n\t\t\t\t\t\t);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tif (errors.length > 0) {\n\t\t\tconsole.warn(`[athos/discovery] ${errors.length} file(s) failed to load but were ignored:`);\n\t\t\tfor (const { file, cause } of errors) {\n\t\t\t\tconsole.warn(` - ${file}: ${cause}`);\n\t\t\t}\n\t\t}\n\n\t\treturn modules;\n\t}\n\n\tstatic #resolveCompiledFile(file: string, baseDir: string): string {\n\t\tconst ext = Platform.path.extname(file);\n\t\tif (ext !== \".ts\") {\n\t\t return file;\n\t\t}\n\n\t\tconst projectRoot = FileScanner.#findProjectRoot(file);\n\t\tif (!projectRoot) {\n\t\t return file;\n\t\t}\n\n\t\tconst distDir = Platform.path.join(projectRoot, \"dist\");\n if (!existsSync(distDir)) {\n return file;\n\t\t}\n\n\t\tconst relativePath = relative(baseDir, file);\n\t\tconst compiledJs = Platform.path.join(distDir, relativePath).replace(/\\.ts$/u, \".js\");\n\n\t\tif (existsSync(compiledJs)) return compiledJs;\n\t\treturn file;\n\t}\n\n\tstatic #resolveDiscoveryRoots(baseDir: string, includeDirectories: readonly string[]): string[] {\n\t\tconst configuredRoots = includeDirectories\n\t\t\t.map((directory) => Platform.path.resolve(baseDir, directory))\n\t\t\t.filter((directory) => {\n\t\t\t\ttry { return statSync(directory).isDirectory(); } catch { return false; }\n\t\t\t});\n\n\t\treturn configuredRoots.length === 0 ? [] : configuredRoots;\n\t}\n\n\tstatic #walk(dir: string): string[] {\n\t\tconst results: string[] = [];\n\t\tconst skipDirs = [\"node_modules\", \".git\", \"build\", \".athos\"];\n\n\t\tlet list: string[];\n\t\ttry {\n\t\t\tlist = readdirSync(dir);\n\t\t} catch (error) {\n\t\t\tthrow createAthosError(ATHOS_ERROR_CODES.MODULE_INVALID, `Failed to scan discovery directory ${dir}.`, {\n\t\t\t\tdetails: { directory: dir, cause: error instanceof Error ? error.message : String(error) },\n\t\t\t});\n\t\t}\n\n\t\tfor (const file of list) {\n\t\t\tif (skipDirs.includes(file)) continue;\n\n\t\t\tconst path = Platform.path.join(dir, file);\n\t\t\tconst stat = statSync(path);\n\n\t\t\tif (stat?.isDirectory()) {\n\t\t\t\tresults.push(...FileScanner.#walk(path));\n\t\t\t} else {\n\t\t\t\tresults.push(path);\n\t\t\t}\n\t\t}\n\t\treturn results;\n\t}\n\n\tstatic #isLoadable(file: string): boolean {\n\t\tconst ext = Platform.path.extname(file);\n\t\treturn (\n\t\t\t(ext === \".ts\" || ext === \".js\" || ext === \"\" || ext === \".mjs\") &&\n\t\t\t!file.endsWith(\".d.ts\") &&\n\t\t\t!file.includes(\".test.\") &&\n\t\t\t!file.includes(\".spec.\") &&\n\t\t\t!file.includes(\"/scripts/\") &&\n\t\t\t!file.includes(\"/examples/\")\n\t\t);\n\t}\n\n\tstatic #findProjectRoot(dir: string): string | undefined {\n\t\tlet current = resolve(dir);\n\t\twhile (true) {\n\t\t\tif (existsSync(Platform.path.join(current, \"package.json\"))) return current;\n\t\t\tconst parent = dirname(current);\n\t\t\tif (parent === current) return undefined;\n\t\t\tcurrent = parent;\n\t\t}\n\t}\n\n\tstatic #annotateDiscoveredModuleExports(moduleExports: Record<string, unknown>, file: string): void {\n\t\tfor (const value of Object.values(moduleExports)) {\n\t\t\tif (typeof value === \"function\") {\n\t\t\t\tdefineMetadata(value, DISCOVERY_SOURCE_FILE_METADATA_KEY, file);\n\t\t\t}\n\t\t}\n\t}\n\n\tstatic #normalizeDiscoveryRoot(root: string | URL): string {\n\t\tif (root instanceof URL) return Platform.url.fileURLToPath(root);\n\t\tif (root.startsWith(\"file://\")) return Platform.url.fileURLToPath(root);\n\t\treturn root;\n\t}\n}\n"],"names":["DISCOVERY_SOURCE_FILE_METADATA_KEY","Symbol","for","FileScanner","scanAndLoad","baseDir","includeDirectories","options","absoluteBaseDir","Platform","path","resolve","roots","files","flatMap","root","modules","errors","file","resolved","moduleExports","url","pathToFileURL","href","push","error","cause","Error","message","String","ignoreDiscoveryErrors","createAthosError","ATHOS_ERROR_CODES","MODULE_INVALID","details","length","console","warn","ext","extname","projectRoot","distDir","join","existsSync","relativePath","relative","compiledJs","replace","configuredRoots","map","directory","filter","statSync","isDirectory","dir","results","skipDirs","list","readdirSync","includes","stat","endsWith","current","parent","dirname","undefined","value","Object","values","defineMetadata","URL","fileURLToPath","startsWith"],"mappings":"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"}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
export declare class FileScanner {
|
|
2
|
+
#private;
|
|
3
|
+
static scanAndLoad(baseDir: string | URL, includeDirectories?: readonly string[], options?: {
|
|
4
|
+
ignoreDiscoveryErrors?: boolean;
|
|
5
|
+
}): Promise<readonly Record<string, unknown>[]>;
|
|
6
|
+
}
|
|
7
|
+
//# sourceMappingURL=scanner.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"scanner.d.ts","sourceRoot":"","sources":["../../../../../../../packages/pro/src/core/scanner.ts"],"names":[],"mappings":"AASA,qBAAa,WAAW;;WACV,WAAW,CACvB,OAAO,EAAE,MAAM,GAAG,GAAG,EACrB,kBAAkB,GAAE,SAAS,MAAM,EAAmB,EACtD,OAAO,CAAC,EAAE;QAAE,qBAAqB,CAAC,EAAE,OAAO,CAAA;KAAE,GAC3C,OAAO,CAAC,SAAS,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,CAAC;CAuI9C"}
|