Skip to content

Commit d11d651

Browse files
committed
refactoring types
1 parent 2ede49e commit d11d651

File tree

5 files changed

+62
-83
lines changed

5 files changed

+62
-83
lines changed

src/TryCatchFinallyHooks.ts

Lines changed: 28 additions & 55 deletions
Original file line numberDiff line numberDiff line change
@@ -1,79 +1,51 @@
11
import { FunctionContext, createTryCatchFinally, FunctionInterceptors } from "./tryCatchFinally";
22

3-
export interface ITryCatchFinallyHook<TContext={}>{
4-
onTry(ctx: FunctionContext & TContext): void | {
5-
onCatch?(): void
6-
onFinally?(): void
3+
export interface ITryCatchFinallyHook<TParentContext extends FunctionContext=FunctionContext, TrtReturnContext={}>{
4+
onTry(ctx: TParentContext): void | {
5+
context?: TrtReturnContext
6+
onCatch?(ctx:TParentContext&TrtReturnContext): void
7+
onFinally?(ctx:TParentContext&TrtReturnContext): void
78
/**
89
* If true, the hook will be executed after all other hooks
910
*/
1011
lastInQueue?: boolean
1112
}
1213
}
1314

14-
export type HookContextOf<THook> = THook extends ITryCatchFinallyHook<infer T> ? T : never
15+
export type HookContextOf<THook> = THook extends ITryCatchFinallyHook<infer T1,infer T2> ? T1&T2 : never
1516

1617
export type DecoratorArgsOf<THookContext> = THookContext extends {args?: infer TArgs extends {}} ? TArgs : {}
1718

18-
export class TryCatchFinallyHooksBuilder<THookContext extends {}, TDecoratorArgs extends {} = DecoratorArgsOf<THookContext>> //implements FunctionInterceptors
19+
export class TryCatchFinallyHooksBuilder<FullHookContext extends FunctionContext = FunctionContext>
1920
{
20-
// onTry():{
21-
// context?: {} | undefined;
22-
// onCatch?: ((ctx: FunctionContext<(...args: any[]) => any>) => void) | undefined;
23-
// onFinally?: ((ctx: FunctionContext<(...args: any[]) => any>) => void) | undefined;
24-
// }
25-
// {
26-
// const ctx = {}
27-
// const hooksRes = this.forEachHook(hook=> hook.onTry(ctx))
28-
// for (const hookRes of [...hooksRes]) {
29-
// if(hookRes && hookRes.lastInQueue){
30-
// const [itemToMove] =hooksRes.splice(hooksRes.indexOf(hookRes), 1)
31-
// hooksRes.push(itemToMove)
32-
// }
33-
// }
34-
35-
// return {
36-
// onFinally(ctx) {
37-
// for (const hr of hooksRes) {
38-
// if(hr && hr.onFinally) hr.onFinally()
39-
// }
40-
// },
41-
// onCatch(ctx) {
42-
// for (const hr of hooksRes) {
43-
// if(hr && hr.onCatch) hr.onCatch()
44-
// }
45-
// }
46-
// }
47-
// }
21+
private hooks:ITryCatchFinallyHook[] = []
4822

49-
private hooks:ITryCatchFinallyHook<any>[] = []
50-
51-
add<NewHookContext, NewArgs = DecoratorArgsOf<NewHookContext>>(hook: ITryCatchFinallyHook<THookContext & NewHookContext>)
52-
: TryCatchFinallyHooksBuilder<THookContext & NewHookContext, TDecoratorArgs & NewArgs>
23+
add<THookContext extends {}, TryReturnContext extends {}={}>(hook: ITryCatchFinallyHook<FullHookContext & THookContext,TryReturnContext>)
24+
: TryCatchFinallyHooksBuilder<THookContext &FullHookContext & TryReturnContext>
5325
{
5426
this.hooks.push(hook);
5527
return this as any;
5628
}
5729

58-
static createHook<HookContext>(onTry: ITryCatchFinallyHook<HookContext>['onTry']) : ITryCatchFinallyHook<HookContext>
30+
static createHook<TryHookContext, TryReturnContext={}>(onTry: ITryCatchFinallyHook<TryHookContext&FunctionContext, TryReturnContext>['onTry']) : ITryCatchFinallyHook<TryHookContext&FunctionContext, TryReturnContext>
5931
{
6032
return {
6133
onTry
62-
}
34+
} as any
6335
}
6436

65-
createAndAdd<NewHookContext, NewArgs = NewHookContext extends {args?: infer TNewArgs}? TNewArgs : {}>(onTry:ITryCatchFinallyHook<THookContext & NewHookContext>['onTry']): TryCatchFinallyHooksBuilder<THookContext & NewHookContext, TDecoratorArgs & NewArgs>
37+
createAndAdd<TryReturnContext={}>(onTry:ITryCatchFinallyHook<FullHookContext,TryReturnContext>['onTry']): TryCatchFinallyHooksBuilder<FullHookContext & TryReturnContext>
6638
{
67-
this.add(TryCatchFinallyHooksBuilder.createHook(onTry))
39+
this.add(TryCatchFinallyHooksBuilder.createHook(onTry) as any)
6840
return this as any
6941
}
7042

71-
asFunctionWrapper(args?: TDecoratorArgs): <TFunc extends (...args:any[])=>any>(func:TFunc)=>TFunc
43+
asFunctionWrapper(args?: DecoratorArgsOf<FullHookContext>): <TFunc extends (...args:any[])=>any>(func:TFunc)=>TFunc
7244
{
7345
const _this = this
7446
const beforeHooksTry = this.beforeHooksTry.bind(this)
7547
const afterHooksTry = this.afterHooksTry?.bind(this)
76-
type TContext = THookContext & FunctionContext
48+
type TContext = FullHookContext & FunctionContext
7749
return (func:any)=>{
7850
return createTryCatchFinally(func, {
7951
onTry(funcCtx) {
@@ -90,15 +62,15 @@ export class TryCatchFinallyHooksBuilder<THookContext extends {}, TDecoratorArgs
9062
}
9163

9264
return {
93-
onFinally() {
65+
onFinally(_ctx) {
9466
for (const hr of hooksRes) {
95-
if(hr && hr.onFinally) hr.onFinally()
67+
if(hr && hr.onFinally) hr.onFinally(_ctx)
9668
}
9769
bht.onFinally?.()
9870
},
99-
onCatch() {
71+
onCatch(_ctx) {
10072
for (const hr of hooksRes) {
101-
if(hr && hr.onCatch) hr.onCatch()
73+
if(hr && hr.onCatch) hr.onCatch(_ctx)
10274
}
10375
bht.onCatch?.()
10476
}
@@ -108,18 +80,18 @@ export class TryCatchFinallyHooksBuilder<THookContext extends {}, TDecoratorArgs
10880
}
10981
}
11082

111-
asDecorator(args?: TDecoratorArgs): MethodDecorator
83+
asDecorator(args?: DecoratorArgsOf<FullHookContext>): MethodDecorator
11284
{
11385
return (target:any, propertyKey, descriptor) => {
11486
descriptor.value = this.asFunctionWrapper(args)(descriptor.value as any)
11587
}
11688
}
117-
createDecorator(): (args:TDecoratorArgs)=>MethodDecorator
89+
createDecorator(): (args:DecoratorArgsOf<FullHookContext>)=>MethodDecorator
11890
{
11991
return args=>this.asDecorator(args)
12092
}
12193

122-
protected beforeHooksTry(ctx: THookContext):{
94+
protected beforeHooksTry(ctx: FullHookContext):{
12395
onCatch?(): void
12496
onFinally?(): void
12597
}
@@ -134,12 +106,12 @@ export class TryCatchFinallyHooksBuilder<THookContext extends {}, TDecoratorArgs
134106
},
135107
}
136108
}
137-
protected afterHooksTry?(ctx: THookContext):{
109+
protected afterHooksTry?(ctx: FullHookContext):{
138110
onCatch?(): void
139111
onFinally?(): void
140112
}
141113

142-
asScope<TResult>(args: TDecoratorArgs, scope:()=>TResult):TResult
114+
asScope<TResult>(args: DecoratorArgsOf<FullHookContext>, scope:()=>TResult):TResult
143115
{
144116
return this.asFunctionWrapper(args)(scope)()
145117
}
@@ -149,11 +121,12 @@ export class TryCatchFinallyHooksBuilder<THookContext extends {}, TDecoratorArgs
149121
return this.hooks.map(h=>fn(h));
150122
}
151123

152-
private _currentContext:(THookContext & FunctionContext)|undefined = undefined
124+
private _currentContext:(FullHookContext & FunctionContext)|undefined = undefined
153125
get current(){
154126
return this._currentContext
155127
}
156128

157129
}
158130

159-
export type ContextOf<TTryCatchFinallyHooksBuilder extends TryCatchFinallyHooksBuilder<any>> = TTryCatchFinallyHooksBuilder extends TryCatchFinallyHooksBuilder<infer T> ? T & FunctionContext : never
131+
export type ContextOf<TTryCatchFinallyHooksBuilder extends TryCatchFinallyHooksBuilder<any>>
132+
= TTryCatchFinallyHooksBuilder extends TryCatchFinallyHooksBuilder<infer T1> ? T1 : never

src/callStack.ts

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
1-
import { ITryCatchFinallyHook } from "./TryCatchFinallyHooks";
1+
import { ITryCatchFinallyHook, TryCatchFinallyHooksBuilder } from "./TryCatchFinallyHooks";
2+
import { FunctionContext } from "./tryCatchFinally";
23

34
/**
45
* This is a callstack tracker, which provides Stack of Called Function Context - works both for async and sync call stacks
@@ -17,8 +18,9 @@ const callPrefix = 'callstack_callId:'
1718

1819
export type CallstackContext = { args: { name?: string;}, name:string, id: string, callstack: CallstackContext[] };
1920

20-
export const callStack: ITryCatchFinallyHook<CallstackContext> = {
21-
onTry(ctx) {
21+
22+
export const callStack = TryCatchFinallyHooksBuilder.createHook<CallstackContext>(
23+
(ctx)=>{
2224
if(!ctx.name)
2325
ctx.name = ctx.args.name || ctx.func.name || '<anonymous>'
2426

@@ -47,7 +49,7 @@ export const callStack: ITryCatchFinallyHook<CallstackContext> = {
4749
lastInQueue: true
4850
};
4951
}
50-
};
52+
)
5153

5254
function prepareActionStackTrace(error: Error, stack: NodeJS.CallSite[]): string[] {
5355
return stack

src/example/logOnFinally.ts

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,10 @@
11
import { TryCatchFinallyHooksBuilder } from "../TryCatchFinallyHooks";
22

3-
export const logOnFinally = TryCatchFinallyHooksBuilder.createHook<{ args: { name: string; }; }>(ctx => {
3+
export const logOnFinally = TryCatchFinallyHooksBuilder.createHook<{ args: { name?: string; }; name:string }>(ctx => {
4+
if(!ctx.name) ctx.name = ctx.args.name || ctx.func.name || '<anonymous>'
45
return {
56
onFinally() {
67
console.log(`Function ${ctx.args.name} finished!`);
7-
}
8+
},
89
};
910
});

src/example/tracker.test.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ import 'jest-extended'
33

44
test("log onTry asScope",()=>{
55
const log = jest.fn()
6-
const track = new TryCatchFinallyHooksBuilder().add<{args:{name: string}}>({
6+
const track = new TryCatchFinallyHooksBuilder().add<{ args:{name: string}}>({
77
onTry(ctx) {
88
log("onTry",ctx.args.name)
99
},

src/example/tracker.ts

Lines changed: 24 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -3,32 +3,35 @@ import { logOnFinally } from "./logOnFinally";
33
import { measureDuration } from "../measureDuration";
44
import { TryCatchFinallyHooksBuilder, ContextOf } from "../TryCatchFinallyHooks";
55

6-
const track = (() => {
7-
const t1 = new TryCatchFinallyHooksBuilder()
8-
.add(callStack)
9-
.add(measureDuration)
10-
.add(logOnFinally)
11-
.createAndAdd(ctx => {
12-
return {
13-
onFinally() {
14-
const datadog: any = {};
15-
datadog.histogram(`action-${ctx.args.name}-duration`, ctx.duration, { tags: ['action:' + ctx.args.name, 'callstack:' + ctx.callstack.map(c => c.args.name).join('/')] });
16-
},
17-
};
18-
});
19-
20-
return t1.createAndAdd<{ defer(fnToDefer: (ctx: ContextOf<typeof t1>) => void): void; }>(ctx => {
21-
const funcsToDefer: (() => void)[] = [];
22-
ctx.defer = funcsToDefer.push.bind(funcsToDefer);
6+
const track = new TryCatchFinallyHooksBuilder()
7+
.add(callStack)
8+
.add(measureDuration)
9+
.add(logOnFinally)
10+
.createAndAdd(ctx => {
2311
return {
2412
onFinally() {
13+
const datadog: any = {};
14+
datadog.histogram(`action-${ctx.args.name}-duration`, ctx.duration, { tags: ['action:' + ctx.name, 'callstack:' + ctx.callstack.map(c => c.name).join('/')] });
15+
},
16+
};
17+
})
18+
.createAndAdd((ctx) => {
19+
type DeferContext = typeof ctx
20+
const funcsToDefer = [] as ((_ctx:DeferContext) => void)[]
21+
return {
22+
context: {
23+
defer(fn:(_ctx:DeferContext)=>void) {
24+
funcsToDefer.push(fn)
25+
}
26+
},
27+
onFinally(_ctx) {
2528
for (const defer of funcsToDefer) {
26-
defer();
29+
defer(_ctx);
2730
}
2831
}
29-
};
30-
});
31-
})();
32+
}
33+
})
34+
;
3235
const myTrackedFunction = track.asFunctionWrapper({ name: 'MyAction' })(
3336
function myTrackedFunction(a: number, b: number) {
3437
track.current!.defer((op) => {

0 commit comments

Comments
 (0)