Advertisement
Guest User

Untitled

a guest
Sep 18th, 2019
146
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 2.03 KB | None | 0 0
  1. import "reflect-metadata";
  2.  
  3. type TypeOf<T> = new (...args: any[]) => T;
  4. type Instantiator = <T>(type: TypeOf<T>) => T;
  5.  
  6. const RunArgKeys = {
  7. run: Symbol(),
  8. }
  9.  
  10. export interface Runnable {
  11. run(...args: any[]): Promise<any>;
  12. }
  13.  
  14. export function RunArg<T>(factory: TypeOf<RunArgFactory<T>>, ) {
  15. return (proto: Runnable, method: string, index: number) => {
  16. const key = RunArgKeys[method];
  17. if (!key) throw new Error(`${method} not supported`);
  18.  
  19. if (!Reflect.hasMetadata(key, proto)) {
  20. Reflect.defineMetadata(key, [], proto);
  21. }
  22.  
  23. let list = Reflect.getMetadata(key, proto);
  24. list[index] = factory;
  25. }
  26. }
  27.  
  28. export interface RunArgFactory<T> {
  29. produceRunArgFor(r: Runnable): Promise<T>;
  30. releaseRunArgFor(r: Runnable): Promise<void>;
  31. aroundRun?<T>(run: () => Promise<T>, r: Runnable): Promise<T>;
  32. }
  33.  
  34. const wraps = {
  35.  
  36. runnable: (runnable: Runnable, args: any[]) => () => runnable.run(...args),
  37.  
  38. around: (
  39. arounder: RunArgFactory<any>,
  40. execution: () => Promise<any>,
  41. runnable: Runnable,
  42. ) => () => arounder.aroundRun!(execution, runnable),
  43. }
  44.  
  45. export async function run(
  46. runnable: Runnable,
  47. instantiate: Instantiator,
  48. ) {
  49.  
  50. let args: any[] = [];
  51.  
  52. let factories: RunArgFactory<any>[] = (
  53. Reflect.getMetadata(RunArgKeys.run, runnable) as TypeOf<RunArgFactory<any>>[]
  54. ).map(instantiate);
  55. let arounders: RunArgFactory<any>[] = [];
  56. for (let factory of factories) {
  57. args.push(await factory.produceRunArgFor(runnable));
  58. if (factory.aroundRun) arounders.push(factory);
  59. }
  60.  
  61. try {
  62. if (!arounders.length) return await runnable.run(...args);
  63.  
  64. let execution = wraps.runnable(runnable, args);
  65. for (let arounder of arounders) {
  66. execution = wraps.around(arounder, execution, runnable);
  67. }
  68.  
  69. return await execution();
  70. } catch (e) {
  71. throw e;
  72. } finally {
  73. for (let factory of factories) {
  74. await factory.releaseRunArgFor(runnable);
  75. }
  76. }
  77. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement