-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #10 from zgid123/express-runner-feat/resolve-ioc-f…
…or-controller [express-runner]: resolve ioc
- Loading branch information
Showing
7 changed files
with
210 additions
and
38 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,109 @@ | ||
import { | ||
pushToIoCContainer, | ||
getFromIoCContainer, | ||
getInjectionMetadata, | ||
getInjectParamMetadata, | ||
type IInjectionProps, | ||
} from '@abyss.ts/core'; | ||
|
||
export function mapInjections(): void { | ||
console.log('Scanning injections...'); | ||
|
||
const injections = getInjectionMetadata(); | ||
const groupedInjections = topologicalGroup(injections); | ||
|
||
for (const pack of groupedInjections) { | ||
for (const injection of pack) { | ||
const { target, scope } = injection; | ||
|
||
if (scope === 'singleton') { | ||
const metadata = getInjectParamMetadata({ | ||
target, | ||
}); | ||
|
||
const params = metadata.map(({ extractor }) => { | ||
return getFromIoCContainer(extractor); | ||
}); | ||
|
||
const instance = new target(...params); | ||
|
||
pushToIoCContainer({ | ||
target, | ||
instance, | ||
}); | ||
} | ||
} | ||
} | ||
|
||
console.log('Finish scanning injections!\n'); | ||
} | ||
|
||
export function topologicalGroup( | ||
injections: Array<IInjectionProps | null>, | ||
): IInjectionProps[][] { | ||
const visited: Record<TAny, { visited: true; level: number }> = {}; | ||
const result: IInjectionProps[][] = []; | ||
|
||
while (injections.length) { | ||
const removedIndexes = []; | ||
|
||
for (let i = 0, n = injections.length; i < n; i++) { | ||
const injection = injections[i]; | ||
|
||
if (!injection) { | ||
removedIndexes.push(i); | ||
continue; | ||
} | ||
|
||
const { target } = injection; | ||
|
||
const params = getInjectParamMetadata({ | ||
target, | ||
}); | ||
|
||
if (!params.length) { | ||
result[0] ||= []; | ||
result[0].push(injection); | ||
removedIndexes.push(i); | ||
|
||
visited[target] = { | ||
level: 0, | ||
visited: true, | ||
}; | ||
|
||
continue; | ||
} | ||
|
||
let level = 0; | ||
let visitedAllDependencies = true; | ||
|
||
params.forEach((injectable) => { | ||
const { extractor } = injectable; | ||
const visitedData = visited[extractor]; | ||
|
||
if (visitedData) { | ||
level = Math.max(level, visitedData.level); | ||
} else { | ||
visitedAllDependencies = false; | ||
} | ||
}); | ||
|
||
if (visitedAllDependencies) { | ||
result[level + 1] ||= []; | ||
result[level + 1]!.push(injection); | ||
removedIndexes.push(i); | ||
|
||
visited[target] = { | ||
visited: true, | ||
level: level + 1, | ||
}; | ||
} | ||
} | ||
|
||
removedIndexes.reverse().forEach((index) => { | ||
injections.splice(index, 1); | ||
}); | ||
} | ||
|
||
return result; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,52 @@ | ||
import { Router } from 'express'; | ||
import { | ||
combine, | ||
getFromIoCContainer, | ||
getControllerMetadata, | ||
getInjectParamMetadata, | ||
getControllerActionMetadata, | ||
} from '@abyss.ts/core'; | ||
|
||
import { mapParameters } from './actionUtils'; | ||
|
||
export function mapRoutes(controllers: TAny[]): [string[], Router] { | ||
console.log('Initializing routes...'); | ||
|
||
const routes: string[] = []; | ||
const router = Router(); | ||
|
||
for (const controller of controllers) { | ||
const { route } = getControllerMetadata(controller); | ||
const actions = getControllerActionMetadata(controller); | ||
const injects = getInjectParamMetadata({ target: controller }); | ||
|
||
const injections = injects.map(({ extractor }) => { | ||
return getFromIoCContainer(extractor); | ||
}); | ||
|
||
const controllerInstance = new controller(...injections); | ||
|
||
for (const action of actions) { | ||
const { exec, httpMethod, route: actionRoute, propertyKey } = action; | ||
const httpRoute = `/${combine({ joinWith: '/' }, route, actionRoute)}`; | ||
|
||
routes.push( | ||
combine({ joinWith: ' ' }, httpMethod.toUpperCase(), httpRoute), | ||
); | ||
|
||
router[httpMethod](httpRoute, (req, res) => { | ||
const params = mapParameters({ | ||
controller, | ||
propertyKey, | ||
request: req, | ||
}); | ||
|
||
res.send(exec.bind(controllerInstance)(...params)); | ||
}); | ||
} | ||
} | ||
|
||
console.log('Finish initializing routes!\n'); | ||
|
||
return [routes, router]; | ||
} |
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.