@lspeasy/server 1.0.1

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.
@@ -0,0 +1,52 @@
1
+ /**
2
+ * Message dispatcher - routes incoming requests to registered handlers
3
+ */
4
+ import type { Message, Transport, Logger, ClientCapabilities } from '@lspeasy/core';
5
+ import type { RequestHandler, NotificationHandler } from './types.js';
6
+ /**
7
+ * Message dispatcher manages request/notification routing
8
+ */
9
+ export declare class MessageDispatcher {
10
+ private readonly logger;
11
+ private requestHandlers;
12
+ private notificationHandlers;
13
+ private pendingRequests;
14
+ private clientCapabilities?;
15
+ constructor(logger: Logger);
16
+ /**
17
+ * Register a request handler
18
+ */
19
+ registerRequest<Params, Result>(method: string, handler: RequestHandler<Params, Result>): void;
20
+ /**
21
+ * Register a notification handler
22
+ */
23
+ registerNotification<Params>(method: string, handler: NotificationHandler<Params>): void;
24
+ /**
25
+ * Unregister a request handler
26
+ */
27
+ unregisterRequest(method: string): void;
28
+ /**
29
+ * Unregister a notification handler
30
+ */
31
+ unregisterNotification(method: string): void;
32
+ /**
33
+ * Set client capabilities (from initialize request)
34
+ */
35
+ setClientCapabilities(capabilities: ClientCapabilities): void;
36
+ /**
37
+ * Dispatch an incoming message
38
+ */
39
+ dispatch(message: Message, transport: Transport, cancellationTokens: Map<number | string, AbortController>): Promise<void>;
40
+ private dispatchRequest;
41
+ private dispatchNotification;
42
+ private sendError;
43
+ /**
44
+ * Cancel a pending request
45
+ */
46
+ cancelRequest(id: number | string): void;
47
+ /**
48
+ * Clear all handlers
49
+ */
50
+ clear(): void;
51
+ }
52
+ //# sourceMappingURL=dispatcher.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"dispatcher.d.ts","sourceRoot":"","sources":["../src/dispatcher.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,KAAK,EACV,OAAO,EAGP,SAAS,EAET,MAAM,EACN,kBAAkB,EACnB,MAAM,eAAe,CAAC;AAGvB,OAAO,KAAK,EACV,cAAc,EACd,mBAAmB,EAGpB,MAAM,YAAY,CAAC;AAEpB;;GAEG;AACH,qBAAa,iBAAiB;IAUhB,OAAO,CAAC,QAAQ,CAAC,MAAM;IATnC,OAAO,CAAC,eAAe,CAInB;IACJ,OAAO,CAAC,oBAAoB,CAA+D;IAC3F,OAAO,CAAC,eAAe,CAA+C;IACtE,OAAO,CAAC,kBAAkB,CAAC,CAAqB;IAEhD,YAA6B,MAAM,EAAE,MAAM,EAAI;IAE/C;;OAEG;IACH,eAAe,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,cAAc,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG,IAAI,CAG7F;IAED;;OAEG;IACH,oBAAoB,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,mBAAmB,CAAC,MAAM,CAAC,GAAG,IAAI,CAGvF;IAED;;OAEG;IACH,iBAAiB,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI,CAGtC;IAED;;OAEG;IACH,sBAAsB,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI,CAG3C;IAED;;OAEG;IACH,qBAAqB,CAAC,YAAY,EAAE,kBAAkB,GAAG,IAAI,CAE5D;IAED;;OAEG;IACG,QAAQ,CACZ,OAAO,EAAE,OAAO,EAChB,SAAS,EAAE,SAAS,EACpB,kBAAkB,EAAE,GAAG,CAAC,MAAM,GAAG,MAAM,EAAE,eAAe,CAAC,GACxD,OAAO,CAAC,IAAI,CAAC,CAMf;YAKa,eAAe;YA8Df,oBAAoB;YAuBpB,SAAS;IAgBvB;;OAEG;IACH,aAAa,CAAC,EAAE,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAOvC;IAED;;OAEG;IACH,KAAK,IAAI,IAAI,CAIZ;CACF"}
@@ -0,0 +1,174 @@
1
+ /**
2
+ * Message dispatcher - routes incoming requests to registered handlers
3
+ */
4
+ import { ResponseError, isRequestMessage, isNotificationMessage } from '@lspeasy/core';
5
+ import { HandlerRegistry } from '@lspeasy/core/utils';
6
+ /**
7
+ * Message dispatcher manages request/notification routing
8
+ */
9
+ export class MessageDispatcher {
10
+ logger;
11
+ requestHandlers = new HandlerRegistry();
12
+ notificationHandlers = new HandlerRegistry();
13
+ pendingRequests = new Map();
14
+ clientCapabilities;
15
+ constructor(logger) {
16
+ this.logger = logger;
17
+ }
18
+ /**
19
+ * Register a request handler
20
+ */
21
+ registerRequest(method, handler) {
22
+ this.requestHandlers.register(method, handler);
23
+ this.logger.debug(`Registered request handler: ${method}`);
24
+ }
25
+ /**
26
+ * Register a notification handler
27
+ */
28
+ registerNotification(method, handler) {
29
+ this.notificationHandlers.register(method, handler);
30
+ this.logger.debug(`Registered notification handler: ${method}`);
31
+ }
32
+ /**
33
+ * Unregister a request handler
34
+ */
35
+ unregisterRequest(method) {
36
+ this.requestHandlers.unregister(method);
37
+ this.logger.debug(`Unregistered request handler: ${method}`);
38
+ }
39
+ /**
40
+ * Unregister a notification handler
41
+ */
42
+ unregisterNotification(method) {
43
+ this.notificationHandlers.unregister(method);
44
+ this.logger.debug(`Unregistered notification handler: ${method}`);
45
+ }
46
+ /**
47
+ * Set client capabilities (from initialize request)
48
+ */
49
+ setClientCapabilities(capabilities) {
50
+ this.clientCapabilities = capabilities;
51
+ }
52
+ /**
53
+ * Dispatch an incoming message
54
+ */
55
+ async dispatch(message, transport, cancellationTokens) {
56
+ if (isRequestMessage(message)) {
57
+ await this.dispatchRequest(message, transport, cancellationTokens);
58
+ }
59
+ else if (isNotificationMessage(message)) {
60
+ await this.dispatchNotification(message);
61
+ }
62
+ }
63
+ /**
64
+ * Dispatch a request message
65
+ */
66
+ async dispatchRequest(request, transport, cancellationTokens) {
67
+ const { id, method, params } = request;
68
+ try {
69
+ // Check if handler exists
70
+ const handler = this.requestHandlers.get(method);
71
+ if (!handler) {
72
+ await this.sendError(transport, id, ResponseError.methodNotFound(method));
73
+ return;
74
+ }
75
+ // Create cancellation token for this request
76
+ const abortController = new AbortController();
77
+ cancellationTokens.set(id, abortController);
78
+ const cancellationToken = {
79
+ get isCancellationRequested() {
80
+ return abortController.signal.aborted;
81
+ },
82
+ onCancellationRequested: (listener) => {
83
+ abortController.signal.addEventListener('abort', listener);
84
+ return { dispose: () => abortController.signal.removeEventListener('abort', listener) };
85
+ }
86
+ };
87
+ // Execute handler
88
+ const result = await handler(params, cancellationToken, {
89
+ id,
90
+ method,
91
+ clientCapabilities: this.clientCapabilities
92
+ });
93
+ // Send success response
94
+ // Normalize undefined → null per JSON-RPC 2.0 spec:
95
+ // a response MUST contain either "result" or "error" — omitting
96
+ // "result" (which happens when JSON.stringify drops undefined)
97
+ // produces an invalid message the client can never resolve.
98
+ await transport.send({
99
+ jsonrpc: '2.0',
100
+ id,
101
+ result: result ?? null
102
+ });
103
+ }
104
+ catch (error) {
105
+ // Send error response
106
+ if (error instanceof ResponseError) {
107
+ await this.sendError(transport, id, error);
108
+ }
109
+ else {
110
+ const message = error instanceof Error ? error.message : 'Internal error';
111
+ await this.sendError(transport, id, ResponseError.internalError(message, { error }));
112
+ }
113
+ }
114
+ finally {
115
+ cancellationTokens.delete(id);
116
+ }
117
+ }
118
+ /**
119
+ * Dispatch a notification message
120
+ */
121
+ async dispatchNotification(notification) {
122
+ const { method, params } = notification;
123
+ try {
124
+ const handler = this.notificationHandlers.get(method);
125
+ if (!handler) {
126
+ this.logger.debug(`No handler for notification: ${method}`);
127
+ return;
128
+ }
129
+ await handler(params, {
130
+ method,
131
+ clientCapabilities: this.clientCapabilities
132
+ });
133
+ }
134
+ catch (error) {
135
+ // Notifications don't send error responses, just log
136
+ this.logger.error(`Error in notification handler ${method}:`, error);
137
+ }
138
+ }
139
+ /**
140
+ * Send error response
141
+ */
142
+ async sendError(transport, id, error) {
143
+ try {
144
+ await transport.send({
145
+ jsonrpc: '2.0',
146
+ id,
147
+ error: error.toJSON()
148
+ });
149
+ }
150
+ catch (sendError) {
151
+ this.logger.error('Failed to send error response:', sendError);
152
+ }
153
+ }
154
+ /**
155
+ * Cancel a pending request
156
+ */
157
+ cancelRequest(id) {
158
+ const controller = this.pendingRequests.get(id);
159
+ if (controller) {
160
+ controller.abort();
161
+ this.pendingRequests.delete(id);
162
+ this.logger.debug(`Cancelled request ${id}`);
163
+ }
164
+ }
165
+ /**
166
+ * Clear all handlers
167
+ */
168
+ clear() {
169
+ this.requestHandlers.clear();
170
+ this.notificationHandlers.clear();
171
+ this.pendingRequests.clear();
172
+ }
173
+ }
174
+ //# sourceMappingURL=dispatcher.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"dispatcher.js","sourceRoot":"","sources":["../src/dispatcher.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,10 @@
1
+ /**
2
+ * @lspeasy/server - Build LSP servers with simple, typed API
3
+ */
4
+ export { LSPServer } from './server.js';
5
+ export type { ServerOptions, RequestHandler, NotificationHandler, RequestContext, NotificationContext, Server } from './types.js';
6
+ export { ServerState } from './types.js';
7
+ export { MessageDispatcher } from './dispatcher.js';
8
+ export type { Transport, CancellationToken, Logger, ServerCapabilities, ClientCapabilities, InitializeParams, InitializeResult, HoverParams, Hover, CompletionParams, CompletionList, CompletionItem, DefinitionParams, Definition, LSPRequestMethod, LSPNotificationMethod, ParamsForRequest, ResultForRequest, ParamsForNotification } from '@lspeasy/core';
9
+ export { ResponseError, JSONRPCErrorCode, StdioTransport, ConsoleLogger, LogLevel } from '@lspeasy/core';
10
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;GAEG;AAGH,OAAO,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AAGxC,YAAY,EACV,aAAa,EACb,cAAc,EACd,mBAAmB,EACnB,cAAc,EACd,mBAAmB,EACnB,MAAM,EACP,MAAM,YAAY,CAAC;AAEpB,OAAO,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AAGzC,OAAO,EAAE,iBAAiB,EAAE,MAAM,iBAAiB,CAAC;AAGpD,YAAY,EACV,SAAS,EACT,iBAAiB,EACjB,MAAM,EACN,kBAAkB,EAClB,kBAAkB,EAClB,gBAAgB,EAChB,gBAAgB,EAChB,WAAW,EACX,KAAK,EACL,gBAAgB,EAChB,cAAc,EACd,cAAc,EACd,gBAAgB,EAChB,UAAU,EAEV,gBAAgB,EAChB,qBAAqB,EACrB,gBAAgB,EAChB,gBAAgB,EAChB,qBAAqB,EACtB,MAAM,eAAe,CAAC;AAEvB,OAAO,EACL,aAAa,EACb,gBAAgB,EAChB,cAAc,EACd,aAAa,EACb,QAAQ,EACT,MAAM,eAAe,CAAC"}
package/dist/index.js ADDED
@@ -0,0 +1,10 @@
1
+ /**
2
+ * @lspeasy/server - Build LSP servers with simple, typed API
3
+ */
4
+ // Main server class
5
+ export { LSPServer } from './server.js';
6
+ export { ServerState } from './types.js';
7
+ // Internal exports for testing
8
+ export { MessageDispatcher } from './dispatcher.js';
9
+ export { ResponseError, JSONRPCErrorCode, StdioTransport, ConsoleLogger, LogLevel } from '@lspeasy/core';
10
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,oBAAoB;AACpB,OAAO,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AAYxC,OAAO,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AAEzC,+BAA+B;AAC/B,OAAO,EAAE,iBAAiB,EAAE,MAAM,iBAAiB,CAAC;AA0BpD,OAAO,EACL,aAAa,EACb,gBAAgB,EAChB,cAAc,EACd,aAAa,EACb,QAAQ,EACT,MAAM,eAAe,CAAC"}
@@ -0,0 +1,39 @@
1
+ /**
2
+ * LSP lifecycle management - initialize/initialized handshake
3
+ */
4
+ import type { Transport, InitializeParams, InitializeResult, InitializedParams, ServerCapabilities, Logger } from '@lspeasy/core';
5
+ /**
6
+ * Manages LSP server lifecycle (initialize/initialized/shutdown/exit)
7
+ */
8
+ export declare class LifecycleManager {
9
+ private readonly name;
10
+ private readonly version;
11
+ private readonly logger;
12
+ private serverCapabilities;
13
+ constructor(name: string, version: string, logger: Logger);
14
+ /**
15
+ * Set server capabilities
16
+ */
17
+ setCapabilities(capabilities: ServerCapabilities): void;
18
+ /**
19
+ * Get current capabilities
20
+ */
21
+ getCapabilities(): ServerCapabilities;
22
+ /**
23
+ * Handle initialize request
24
+ */
25
+ handleInitialize(params: InitializeParams, _transport: Transport, _id: number | string): Promise<InitializeResult>;
26
+ /**
27
+ * Handle initialized notification
28
+ */
29
+ handleInitialized(params: InitializedParams): void;
30
+ /**
31
+ * Handle shutdown request
32
+ */
33
+ handleShutdown(_transport: Transport, _id: number | string): Promise<void>;
34
+ /**
35
+ * Handle exit notification
36
+ */
37
+ handleExit(): void;
38
+ }
39
+ //# sourceMappingURL=lifecycle.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"lifecycle.d.ts","sourceRoot":"","sources":["../src/lifecycle.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,KAAK,EACV,SAAS,EACT,gBAAgB,EAChB,gBAAgB,EAChB,iBAAiB,EACjB,kBAAkB,EAClB,MAAM,EACP,MAAM,eAAe,CAAC;AAEvB;;GAEG;AACH,qBAAa,gBAAgB;IAIzB,OAAO,CAAC,QAAQ,CAAC,IAAI;IACrB,OAAO,CAAC,QAAQ,CAAC,OAAO;IACxB,OAAO,CAAC,QAAQ,CAAC,MAAM;IALzB,OAAO,CAAC,kBAAkB,CAA0B;IAEpD,YACmB,IAAI,EAAE,MAAM,EACZ,OAAO,EAAE,MAAM,EACf,MAAM,EAAE,MAAM,EAC7B;IAEJ;;OAEG;IACH,eAAe,CAAC,YAAY,EAAE,kBAAkB,GAAG,IAAI,CAEtD;IAED;;OAEG;IACH,eAAe,IAAI,kBAAkB,CAEpC;IAED;;OAEG;IACG,gBAAgB,CACpB,MAAM,EAAE,gBAAgB,EACxB,UAAU,EAAE,SAAS,EACrB,GAAG,EAAE,MAAM,GAAG,MAAM,GACnB,OAAO,CAAC,gBAAgB,CAAC,CAc3B;IAED;;OAEG;IACH,iBAAiB,CAAC,MAAM,EAAE,iBAAiB,GAAG,IAAI,CAGjD;IAED;;OAEG;IACG,cAAc,CAAC,UAAU,EAAE,SAAS,EAAE,GAAG,EAAE,MAAM,GAAG,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAG/E;IAED;;OAEG;IACH,UAAU,IAAI,IAAI,CAEjB;CACF"}
@@ -0,0 +1,66 @@
1
+ /**
2
+ * LSP lifecycle management - initialize/initialized handshake
3
+ */
4
+ /**
5
+ * Manages LSP server lifecycle (initialize/initialized/shutdown/exit)
6
+ */
7
+ export class LifecycleManager {
8
+ name;
9
+ version;
10
+ logger;
11
+ serverCapabilities = {};
12
+ constructor(name, version, logger) {
13
+ this.name = name;
14
+ this.version = version;
15
+ this.logger = logger;
16
+ }
17
+ /**
18
+ * Set server capabilities
19
+ */
20
+ setCapabilities(capabilities) {
21
+ this.serverCapabilities = capabilities;
22
+ }
23
+ /**
24
+ * Get current capabilities
25
+ */
26
+ getCapabilities() {
27
+ return this.serverCapabilities;
28
+ }
29
+ /**
30
+ * Handle initialize request
31
+ */
32
+ async handleInitialize(params, _transport, _id) {
33
+ this.logger.info('Initializing server...');
34
+ this.logger.debug('Initialize params:', params);
35
+ const result = {
36
+ capabilities: this.serverCapabilities,
37
+ serverInfo: {
38
+ name: this.name,
39
+ version: this.version
40
+ }
41
+ };
42
+ this.logger.info('Server initialized');
43
+ return result;
44
+ }
45
+ /**
46
+ * Handle initialized notification
47
+ */
48
+ handleInitialized(params) {
49
+ this.logger.info('Client sent initialized notification');
50
+ this.logger.debug('Initialized params:', params);
51
+ }
52
+ /**
53
+ * Handle shutdown request
54
+ */
55
+ async handleShutdown(_transport, _id) {
56
+ this.logger.info('Shutting down server...');
57
+ this.logger.info('Server shutdown complete');
58
+ }
59
+ /**
60
+ * Handle exit notification
61
+ */
62
+ handleExit() {
63
+ this.logger.info('Server exit');
64
+ }
65
+ }
66
+ //# sourceMappingURL=lifecycle.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"lifecycle.js","sourceRoot":"","sources":["../src/lifecycle.ts"],"names":[],"mappings":"AAAA;;GAEG;AAWH;;GAEG;AACH,MAAM,OAAO,gBAAgB;IAIR,IAAI;IACJ,OAAO;IACP,MAAM;IALjB,kBAAkB,GAAuB,EAAE,CAAC;IAEpD,YACmB,IAAY,EACZ,OAAe,EACf,MAAc,EAC/B;oBAHiB,IAAI;uBACJ,OAAO;sBACP,MAAM;IACtB,CAAC;IAEJ;;OAEG;IACH,eAAe,CAAC,YAAgC,EAAQ;QACtD,IAAI,CAAC,kBAAkB,GAAG,YAAY,CAAC;IAAA,CACxC;IAED;;OAEG;IACH,eAAe,GAAuB;QACpC,OAAO,IAAI,CAAC,kBAAkB,CAAC;IAAA,CAChC;IAED;;OAEG;IACH,KAAK,CAAC,gBAAgB,CACpB,MAAwB,EACxB,UAAqB,EACrB,GAAoB,EACO;QAC3B,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,wBAAwB,CAAC,CAAC;QAC3C,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,oBAAoB,EAAE,MAAM,CAAC,CAAC;QAEhD,MAAM,MAAM,GAAqB;YAC/B,YAAY,EAAE,IAAI,CAAC,kBAAkB;YACrC,UAAU,EAAE;gBACV,IAAI,EAAE,IAAI,CAAC,IAAI;gBACf,OAAO,EAAE,IAAI,CAAC,OAAO;aACtB;SACF,CAAC;QAEF,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,oBAAoB,CAAC,CAAC;QACvC,OAAO,MAAM,CAAC;IAAA,CACf;IAED;;OAEG;IACH,iBAAiB,CAAC,MAAyB,EAAQ;QACjD,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,sCAAsC,CAAC,CAAC;QACzD,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,qBAAqB,EAAE,MAAM,CAAC,CAAC;IAAA,CAClD;IAED;;OAEG;IACH,KAAK,CAAC,cAAc,CAAC,UAAqB,EAAE,GAAoB,EAAiB;QAC/E,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,yBAAyB,CAAC,CAAC;QAC5C,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,0BAA0B,CAAC,CAAC;IAAA,CAC9C;IAED;;OAEG;IACH,UAAU,GAAS;QACjB,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,aAAa,CAAC,CAAC;IAAA,CACjC;CACF"}
@@ -0,0 +1,40 @@
1
+ /**
2
+ * Progress reporting support for LSP servers
3
+ *
4
+ * @module server/progress
5
+ */
6
+ import type { ProgressToken } from 'vscode-languageserver-protocol';
7
+ import { createProgressToken } from '@lspeasy/core';
8
+ /**
9
+ * Progress reporter for work done progress
10
+ */
11
+ export interface ProgressReporter {
12
+ /**
13
+ * Begin progress reporting
14
+ */
15
+ begin(title: string, cancellable?: boolean, message?: string, percentage?: number): Promise<void>;
16
+ /**
17
+ * Report progress
18
+ */
19
+ report(message?: string, percentage?: number): Promise<void>;
20
+ /**
21
+ * End progress reporting
22
+ */
23
+ end(message?: string): Promise<void>;
24
+ }
25
+ /**
26
+ * Internal interface for sending progress notifications
27
+ */
28
+ interface ProgressSender {
29
+ sendNotification(method: string, params: unknown): Promise<void>;
30
+ }
31
+ /**
32
+ * Create a progress reporter for a given token
33
+ * @internal
34
+ */
35
+ export declare function createProgressReporter(token: ProgressToken, sender: ProgressSender): ProgressReporter;
36
+ /**
37
+ * Generate a unique progress token
38
+ */
39
+ export { createProgressToken };
40
+ //# sourceMappingURL=progress.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"progress.d.ts","sourceRoot":"","sources":["../src/progress.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,gCAAgC,CAAC;AACpE,OAAO,EAIL,mBAAmB,EACpB,MAAM,eAAe,CAAC;AAEvB;;GAEG;AACH,MAAM,WAAW,gBAAgB;IAC/B;;OAEG;IACH,KAAK,CAAC,KAAK,EAAE,MAAM,EAAE,WAAW,CAAC,EAAE,OAAO,EAAE,OAAO,CAAC,EAAE,MAAM,EAAE,UAAU,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAElG;;OAEG;IACH,MAAM,CAAC,OAAO,CAAC,EAAE,MAAM,EAAE,UAAU,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAE7D;;OAEG;IACH,GAAG,CAAC,OAAO,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;CACtC;AAED;;GAEG;AACH,UAAU,cAAc;IACtB,gBAAgB,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,OAAO,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;CAClE;AAyCD;;;GAGG;AACH,wBAAgB,sBAAsB,CACpC,KAAK,EAAE,aAAa,EACpB,MAAM,EAAE,cAAc,GACrB,gBAAgB,CAElB;AAED;;GAEG;AACH,OAAO,EAAE,mBAAmB,EAAE,CAAC"}
@@ -0,0 +1,50 @@
1
+ /**
2
+ * Progress reporting support for LSP servers
3
+ *
4
+ * @module server/progress
5
+ */
6
+ import { createProgressBegin, createProgressReport, createProgressEnd, createProgressToken } from '@lspeasy/core';
7
+ /**
8
+ * Implementation of ProgressReporter
9
+ */
10
+ class ProgressReporterImpl {
11
+ token;
12
+ sender;
13
+ constructor(token, sender) {
14
+ this.token = token;
15
+ this.sender = sender;
16
+ }
17
+ async begin(title, cancellable, message, percentage) {
18
+ const value = createProgressBegin(title, cancellable, message, percentage);
19
+ await this.sender.sendNotification('$/progress', {
20
+ token: this.token,
21
+ value
22
+ });
23
+ }
24
+ async report(message, percentage) {
25
+ const value = createProgressReport(message, percentage);
26
+ await this.sender.sendNotification('$/progress', {
27
+ token: this.token,
28
+ value
29
+ });
30
+ }
31
+ async end(message) {
32
+ const value = createProgressEnd(message);
33
+ await this.sender.sendNotification('$/progress', {
34
+ token: this.token,
35
+ value
36
+ });
37
+ }
38
+ }
39
+ /**
40
+ * Create a progress reporter for a given token
41
+ * @internal
42
+ */
43
+ export function createProgressReporter(token, sender) {
44
+ return new ProgressReporterImpl(token, sender);
45
+ }
46
+ /**
47
+ * Generate a unique progress token
48
+ */
49
+ export { createProgressToken };
50
+ //# sourceMappingURL=progress.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"progress.js","sourceRoot":"","sources":["../src/progress.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAGH,OAAO,EACL,mBAAmB,EACnB,oBAAoB,EACpB,iBAAiB,EACjB,mBAAmB,EACpB,MAAM,eAAe,CAAC;AA6BvB;;GAEG;AACH,MAAM,oBAAoB;IAEd,KAAK;IACL,MAAM;IAFhB,YACU,KAAoB,EACpB,MAAsB,EAC9B;qBAFQ,KAAK;sBACL,MAAM;IACb,CAAC;IAEJ,KAAK,CAAC,KAAK,CACT,KAAa,EACb,WAAqB,EACrB,OAAgB,EAChB,UAAmB,EACJ;QACf,MAAM,KAAK,GAAG,mBAAmB,CAAC,KAAK,EAAE,WAAW,EAAE,OAAO,EAAE,UAAU,CAAC,CAAC;QAC3E,MAAM,IAAI,CAAC,MAAM,CAAC,gBAAgB,CAAC,YAAY,EAAE;YAC/C,KAAK,EAAE,IAAI,CAAC,KAAK;YACjB,KAAK;SACN,CAAC,CAAC;IAAA,CACJ;IAED,KAAK,CAAC,MAAM,CAAC,OAAgB,EAAE,UAAmB,EAAiB;QACjE,MAAM,KAAK,GAAG,oBAAoB,CAAC,OAAO,EAAE,UAAU,CAAC,CAAC;QACxD,MAAM,IAAI,CAAC,MAAM,CAAC,gBAAgB,CAAC,YAAY,EAAE;YAC/C,KAAK,EAAE,IAAI,CAAC,KAAK;YACjB,KAAK;SACN,CAAC,CAAC;IAAA,CACJ;IAED,KAAK,CAAC,GAAG,CAAC,OAAgB,EAAiB;QACzC,MAAM,KAAK,GAAG,iBAAiB,CAAC,OAAO,CAAC,CAAC;QACzC,MAAM,IAAI,CAAC,MAAM,CAAC,gBAAgB,CAAC,YAAY,EAAE;YAC/C,KAAK,EAAE,IAAI,CAAC,KAAK;YACjB,KAAK;SACN,CAAC,CAAC;IAAA,CACJ;CACF;AAED;;;GAGG;AACH,MAAM,UAAU,sBAAsB,CACpC,KAAoB,EACpB,MAAsB,EACJ;IAClB,OAAO,IAAI,oBAAoB,CAAC,KAAK,EAAE,MAAM,CAAC,CAAC;AAAA,CAChD;AAED;;GAEG;AACH,OAAO,EAAE,mBAAmB,EAAE,CAAC"}
@@ -0,0 +1,176 @@
1
+ /**
2
+ * LSP Server - Main server class for handling LSP connections
3
+ */
4
+ import type { Transport, Disposable, ServerCapabilities, ClientCapabilities, LSPRequestMethod, LSPNotificationMethod, ParamsForRequest, ResultForRequest, ParamsForNotification, Server } from '@lspeasy/core';
5
+ import type { ServerOptions, RequestHandler, NotificationHandler } from './types.js';
6
+ import { ServerState } from './types.js';
7
+ /**
8
+ * LSP Server class with dynamic capability-aware typing
9
+ *
10
+ * This class dynamically provides handler registration and send methods based on capabilities.
11
+ * Methods are type-safe and conditionally available based on the Capabilities type parameter.
12
+ *
13
+ * @template Capabilities - Server capabilities (defaults to ServerCapabilities)
14
+ *
15
+ * @example
16
+ * // Create a server with specific capabilities
17
+ * type MyCaps = { hoverProvider: true; completionProvider: { triggerCharacters: ['.'] } };
18
+ * const server = new LSPServer<MyCaps>();
19
+ * server.setCapabilities({ hoverProvider: true, completionProvider: { triggerCharacters: ['.'] } });
20
+ * // server.textDocument.onHover is available for registration
21
+ * // server.textDocument.onCompletion is available for registration
22
+ */
23
+ export declare class BaseLSPServer<Capabilities extends Partial<ServerCapabilities> = ServerCapabilities> {
24
+ private readonly logger;
25
+ private readonly middlewareRegistrations;
26
+ private readonly dispatcher;
27
+ private readonly lifecycleManager;
28
+ private readonly name;
29
+ private readonly version;
30
+ private readonly options;
31
+ private capabilityGuard?;
32
+ private clientCapabilityGuard?;
33
+ private events;
34
+ private transportAttachment;
35
+ private pendingRequests;
36
+ private transport?;
37
+ private state;
38
+ private cancellationTokens;
39
+ private clientCapabilities?;
40
+ private clientInfo?;
41
+ constructor(options?: ServerOptions<Capabilities>);
42
+ /**
43
+ * Register a request handler with automatic type inference
44
+ *
45
+ * @example
46
+ * // Type parameters are automatically inferred from method name
47
+ * server.onRequest('textDocument/hover', async (params) => {
48
+ * // params is automatically typed as HoverParams
49
+ * return { contents: 'Hover text' };
50
+ * });
51
+ */
52
+ onRequest<Method extends LSPRequestMethod & string>(method: Method, handler: RequestHandler<ParamsForRequest<Method>, ResultForRequest<Method>>): Disposable;
53
+ /**
54
+ * Register a request handler with explicit type parameters (backwards compatible)
55
+ */
56
+ onRequest<Method extends string, Params = unknown, Result = unknown>(method: Method, handler: RequestHandler<Params, Result>): Disposable;
57
+ /**
58
+ * Register a notification handler with automatic type inference
59
+ *
60
+ * @example
61
+ * // Type parameters are automatically inferred from method name
62
+ * server.onNotification('textDocument/didOpen', (params) => {
63
+ * // params is automatically typed as DidOpenTextDocumentParams
64
+ * });
65
+ */
66
+ onNotification<Method extends LSPNotificationMethod & string>(method: Method, handler: NotificationHandler<ParamsForNotification<Method>>): Disposable;
67
+ /**
68
+ * Register a notification handler with explicit type parameters (backwards compatible)
69
+ */
70
+ onNotification<Method extends string, Params = unknown>(method: Method, handler: NotificationHandler<Params>): Disposable;
71
+ /**
72
+ * Set server capabilities
73
+ */
74
+ setCapabilities(capabilities: Capabilities): void;
75
+ /**
76
+ * Get server capabilities
77
+ */
78
+ getServerCapabilities(): ServerCapabilities;
79
+ /**
80
+ * Get client capabilities (available after initialization)
81
+ */
82
+ getClientCapabilities(): ClientCapabilities | undefined;
83
+ /**
84
+ * Register a single capability, returning a new typed reference via intersection.
85
+ * The returned reference is the same instance, with a narrowed type that includes
86
+ * the newly registered capability.
87
+ *
88
+ * @template K - The capability key to register
89
+ * @param key - The server capability key (e.g. 'hoverProvider')
90
+ * @param value - The capability value
91
+ * @returns The same server instance with an expanded capability type
92
+ *
93
+ * @example
94
+ * const server = new LSPServer();
95
+ * const withHover = server.registerCapability('hoverProvider', true);
96
+ * // withHover is typed as LSPServer<Capabilities & Pick<ServerCapabilities, 'hoverProvider'>>
97
+ */
98
+ registerCapability<K extends keyof ServerCapabilities>(key: K, value: ServerCapabilities[K]): LSPServer<Capabilities & Pick<ServerCapabilities, K>>;
99
+ /**
100
+ * Zero-cost type narrowing for client capabilities.
101
+ * Returns `this` cast to include capability-aware send methods for the given ClientCaps.
102
+ *
103
+ * @template C - The expected client capabilities shape
104
+ * @returns The same server instance, typed with capability-aware methods
105
+ *
106
+ * @example
107
+ * const server = new LSPServer<MyCaps>();
108
+ * const typed = server.expect<MyClientCaps>();
109
+ * // typed now has send methods gated by MyClientCaps
110
+ */
111
+ expect<C extends Partial<ClientCapabilities>>(): this & Server<C, Capabilities>;
112
+ /**
113
+ * Send a server-to-client request.
114
+ */
115
+ sendRequest<Method extends LSPRequestMethod<'serverToClient'>>(method: Method, params?: ParamsForRequest<Method>): Promise<ResultForRequest<Method>>;
116
+ /**
117
+ * Send a server-to-client notification.
118
+ */
119
+ sendNotification<Method extends LSPNotificationMethod<'serverToClient'>>(method: Method, params?: ParamsForNotification<Method>): Promise<void>;
120
+ /**
121
+ * Start listening on a transport
122
+ */
123
+ listen(transport: Transport): Promise<void>;
124
+ /**
125
+ * Graceful shutdown
126
+ */
127
+ shutdown(timeout?: number): Promise<void>;
128
+ /**
129
+ * Force close
130
+ */
131
+ close(): Promise<void>;
132
+ /**
133
+ * Check if server is listening and initialized
134
+ */
135
+ isListening(): boolean;
136
+ /**
137
+ * Get current server state
138
+ */
139
+ getState(): ServerState;
140
+ /**
141
+ * Get client info (available after initialization)
142
+ */
143
+ getClientInfo(): {
144
+ name: string;
145
+ version?: string;
146
+ } | undefined;
147
+ /**
148
+ * Subscribe to listening events
149
+ */
150
+ onListening(handler: () => void): Disposable;
151
+ /**
152
+ * Subscribe to shutdown events
153
+ */
154
+ onShutdown(handler: () => void): Disposable;
155
+ /**
156
+ * Subscribe to error events
157
+ */
158
+ onError(handler: (error: Error) => void): Disposable;
159
+ /**
160
+ * Register built-in lifecycle handlers
161
+ */
162
+ private registerBuiltinHandlers;
163
+ private handleMessage;
164
+ private getMessageType;
165
+ private getMessageMethod;
166
+ private resolveShortCircuitRequest;
167
+ private buildMiddlewareContext;
168
+ private sendWithMiddleware;
169
+ /**
170
+ * Handle response messages for server-initiated requests.
171
+ */
172
+ private handleResponse;
173
+ }
174
+ export type LSPServer<ServerCaps extends Partial<ServerCapabilities> = ServerCapabilities> = BaseLSPServer<ServerCaps> & Server<ClientCapabilities, ServerCaps>;
175
+ export declare const LSPServer: new <ServerCaps extends Partial<ServerCapabilities> = ServerCapabilities>(options?: ServerOptions<ServerCaps>) => LSPServer<ServerCaps>;
176
+ //# sourceMappingURL=server.d.ts.map