@@ -8,76 +8,84 @@ import { LogId } from "../common/logger.js";
8
8
9
9
type PayloadOf < K extends keyof SessionEvents > = SessionEvents [ K ] [ 0 ] ;
10
10
11
- type ResourceConfiguration = { name : string ; uri : string ; config : ResourceMetadata } ;
11
+ export type ResourceConfiguration = {
12
+ name : string ;
13
+ uri : string ;
14
+ config : ResourceMetadata ;
15
+ } ;
12
16
13
- export function ReactiveResource < Value , RelevantEvents extends readonly ( keyof SessionEvents ) [ ] > (
14
- { name, uri, config : resourceConfig } : ResourceConfiguration ,
15
- {
16
- initial,
17
- events,
18
- } : {
19
- initial : Value ;
20
- events : RelevantEvents ;
21
- }
22
- ) {
23
- type SomeEvent = RelevantEvents [ number ] ;
17
+ export type ReactiveResourceOptions < Value , RelevantEvents extends readonly ( keyof SessionEvents ) [ ] > = {
18
+ initial : Value ;
19
+ events : RelevantEvents ;
20
+ } ;
24
21
25
- abstract class NewReactiveResource {
26
- protected readonly session : Session ;
27
- protected readonly config : UserConfig ;
28
- protected current : Value ;
22
+ export abstract class ReactiveResource < Value , RelevantEvents extends readonly ( keyof SessionEvents ) [ ] > {
23
+ protected readonly session : Session ;
24
+ protected readonly config : UserConfig ;
25
+ protected current : Value ;
26
+ protected readonly name : string ;
27
+ protected readonly uri : string ;
28
+ protected readonly resourceConfig : ResourceMetadata ;
29
+ protected readonly events : RelevantEvents ;
29
30
30
- constructor (
31
- protected readonly server : Server ,
32
- protected readonly telemetry : Telemetry ,
33
- current ?: Value
34
- ) {
35
- this . current = current ?? initial ;
36
- this . session = server . session ;
37
- this . config = server . userConfig ;
31
+ constructor (
32
+ resourceConfiguration : ResourceConfiguration ,
33
+ options : ReactiveResourceOptions < Value , RelevantEvents > ,
34
+ protected readonly server : Server ,
35
+ protected readonly telemetry : Telemetry ,
36
+ current ?: Value
37
+ ) {
38
+ this . name = resourceConfiguration . name ;
39
+ this . uri = resourceConfiguration . uri ;
40
+ this . resourceConfig = resourceConfiguration . config ;
41
+ this . events = options . events ;
42
+ this . current = current ?? options . initial ;
43
+ this . session = server . session ;
44
+ this . config = server . userConfig ;
38
45
39
- for ( const event of events ) {
40
- this . session . on ( event , ( ...args : SessionEvents [ typeof event ] ) => {
41
- this . reduceApply ( event , ( args as unknown [ ] ) [ 0 ] as PayloadOf < typeof event > ) ;
42
- void this . triggerUpdate ( ) ;
43
- } ) ;
44
- }
45
- }
46
+ this . setupEventListeners ( ) ;
47
+ }
46
48
47
- public register ( ) : void {
48
- this . server . mcpServer . registerResource ( name , uri , resourceConfig , this . resourceCallback ) ;
49
+ private setupEventListeners ( ) : void {
50
+ for ( const event of this . events ) {
51
+ this . session . on ( event , ( ...args : SessionEvents [ typeof event ] ) => {
52
+ this . reduceApply ( event , ( args as unknown [ ] ) [ 0 ] as PayloadOf < typeof event > ) ;
53
+ void this . triggerUpdate ( ) ;
54
+ } ) ;
49
55
}
56
+ }
50
57
51
- private resourceCallback : ReadResourceCallback = ( uri ) => ( {
52
- contents : [
53
- {
54
- text : this . toOutput ( ) ,
55
- mimeType : "application/json" ,
56
- uri : uri . href ,
57
- } ,
58
- ] ,
59
- } ) ;
58
+ public register ( ) : void {
59
+ this . server . mcpServer . registerResource ( this . name , this . uri , this . resourceConfig , this . resourceCallback ) ;
60
+ }
60
61
61
- private async triggerUpdate ( ) {
62
- try {
63
- await this . server . mcpServer . server . sendResourceUpdated ( { uri } ) ;
64
- this . server . mcpServer . sendResourceListChanged ( ) ;
65
- } catch ( error : unknown ) {
66
- this . session . logger . warning ( {
67
- id : LogId . resourceUpdateFailure ,
68
- context : "resource" ,
69
- message : `Could not send the latest resources to the client: ${ error as string } ` ,
70
- } ) ;
71
- }
72
- }
62
+ private resourceCallback : ReadResourceCallback = ( uri ) => ( {
63
+ contents : [
64
+ {
65
+ text : this . toOutput ( ) ,
66
+ mimeType : "application/json" ,
67
+ uri : uri . href ,
68
+ } ,
69
+ ] ,
70
+ } ) ;
73
71
74
- reduceApply ( eventName : SomeEvent , ...event : PayloadOf < SomeEvent > [ ] ) : void {
75
- this . current = this . reduce ( eventName , ...event ) ;
72
+ private async triggerUpdate ( ) : Promise < void > {
73
+ try {
74
+ await this . server . mcpServer . server . sendResourceUpdated ( { uri : this . uri } ) ;
75
+ this . server . mcpServer . sendResourceListChanged ( ) ;
76
+ } catch ( error : unknown ) {
77
+ this . session . logger . warning ( {
78
+ id : LogId . resourceUpdateFailure ,
79
+ context : "resource" ,
80
+ message : `Could not send the latest resources to the client: ${ error as string } ` ,
81
+ } ) ;
76
82
}
83
+ }
77
84
78
- protected abstract reduce ( eventName : SomeEvent , ...event : PayloadOf < SomeEvent > [ ] ) : Value ;
79
- abstract toOutput ( ) : string ;
85
+ protected reduceApply ( eventName : RelevantEvents [ number ] , ...event : PayloadOf < RelevantEvents [ number ] > [ ] ) : void {
86
+ this . current = this . reduce ( eventName , ... event ) ;
80
87
}
81
88
82
- return NewReactiveResource ;
89
+ protected abstract reduce ( eventName : RelevantEvents [ number ] , ...event : PayloadOf < RelevantEvents [ number ] > [ ] ) : Value ;
90
+ public abstract toOutput ( ) : string ;
83
91
}
0 commit comments