@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.
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2024-present Pradeep Mouli
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,218 @@
1
+ # @lspeasy/server
2
+
3
+ Build Language Server Protocol (LSP) servers with a simple, type-safe API.
4
+
5
+ ## Installation
6
+
7
+ ```bash
8
+ npm install @lspeasy/server @lspeasy/core
9
+ # or
10
+ pnpm add @lspeasy/server @lspeasy/core
11
+ # or
12
+ yarn add @lspeasy/server @lspeasy/core
13
+ ```
14
+
15
+ For WebSocket server transports, install `ws`:
16
+
17
+ ```bash
18
+ pnpm add ws
19
+ ```
20
+
21
+ ## Quick Start
22
+
23
+ Create a minimal hover server in less than 30 lines:
24
+
25
+ ```typescript
26
+ import { LSPServer, StdioTransport } from '@lspeasy/server';
27
+ import type { HoverParams, Hover } from '@lspeasy/server';
28
+
29
+ // Create server
30
+ const server = new LSPServer({
31
+ name: 'my-language-server',
32
+ version: '1.0.0'
33
+ });
34
+
35
+ // Set capabilities
36
+ server.setCapabilities({
37
+ hoverProvider: true
38
+ });
39
+
40
+ // Register hover handler
41
+ server.onRequest<'textDocument/hover', HoverParams, Hover | null>(
42
+ 'textDocument/hover',
43
+ async (params, token) => {
44
+ return {
45
+ contents: {
46
+ kind: 'markdown',
47
+ value: `# Hover\nLine ${params.position.line}`
48
+ }
49
+ };
50
+ }
51
+ );
52
+
53
+ // Start server
54
+ const transport = new StdioTransport();
55
+ await server.listen(transport);
56
+ ```
57
+
58
+ ## Features
59
+
60
+ - **Type-Safe Handlers**: Fully typed request and notification handlers with IntelliSense support
61
+ - **Automatic Validation**: Built-in parameter validation using Zod schemas
62
+ - **Lifecycle Management**: Automatic initialize/shutdown handshake handling
63
+ - **Cancellation Support**: Built-in cancellation token support for long-running operations
64
+ - **Error Handling**: Comprehensive error handling with LSP error codes
65
+ - **Chainable API**: Fluent API with method chaining
66
+
67
+ ## Handler Registration
68
+
69
+ ### Request Handlers
70
+
71
+ Request handlers receive parameters, a cancellation token, and return a result:
72
+
73
+ ```typescript
74
+ server.onRequest<'textDocument/completion', CompletionParams, CompletionList>(
75
+ 'textDocument/completion',
76
+ async (params, token, context) => {
77
+ // Check for cancellation
78
+ if (token.isCancellationRequested) {
79
+ return { isIncomplete: false, items: [] };
80
+ }
81
+
82
+ // Return completions
83
+ return {
84
+ isIncomplete: false,
85
+ items: [
86
+ { label: 'function', kind: 3 },
87
+ { label: 'const', kind: 6 }
88
+ ]
89
+ };
90
+ }
91
+ );
92
+ ```
93
+
94
+ ### Notification Handlers
95
+
96
+ Notification handlers receive parameters but don't return a value:
97
+
98
+ ```typescript
99
+ server.onNotification('textDocument/didOpen', (params, context) => {
100
+ console.log('Document opened:', params.textDocument.uri);
101
+ });
102
+ ```
103
+
104
+ ### Method Chaining
105
+
106
+ Chain multiple handler registrations:
107
+
108
+ ```typescript
109
+ server
110
+ .onRequest('textDocument/hover', hoverHandler)
111
+ .onRequest('textDocument/completion', completionHandler)
112
+ .onNotification('textDocument/didOpen', didOpenHandler)
113
+ .onNotification('textDocument/didChange', didChangeHandler);
114
+ ```
115
+
116
+ ## Server Options
117
+
118
+ ```typescript
119
+ interface ServerOptions {
120
+ // Server name (sent in initialize response)
121
+ name?: string;
122
+
123
+ // Server version (sent in initialize response)
124
+ version?: string;
125
+
126
+ // Logger instance (defaults to ConsoleLogger)
127
+ logger?: Logger;
128
+
129
+ // Log level (defaults to 'info')
130
+ logLevel?: 'trace' | 'debug' | 'info' | 'warn' | 'error';
131
+
132
+ // Custom validation error handler
133
+ onValidationError?: (error: ZodError, request: RequestContext) => ResponseError;
134
+ }
135
+ ```
136
+
137
+ ## Error Handling
138
+
139
+ Throw `ResponseError` for custom error codes:
140
+
141
+ ```typescript
142
+ import { ResponseError, JSONRPCErrorCode } from '@lspeasy/server';
143
+
144
+ server.onRequest('custom/method', async (params) => {
145
+ if (!params.valid) {
146
+ throw new ResponseError(
147
+ JSONRPCErrorCode.InvalidParams,
148
+ 'Validation failed',
149
+ { details: 'Invalid input' }
150
+ );
151
+ }
152
+ return { success: true };
153
+ });
154
+ ```
155
+
156
+ ## Lifecycle
157
+
158
+ The server automatically handles the LSP lifecycle:
159
+
160
+ 1. **Initialize**: Client sends `initialize` request → Server responds with capabilities
161
+ 2. **Initialized**: Client sends `initialized` notification → Server is ready
162
+ 3. **Running**: Server processes requests and notifications
163
+ 4. **Shutdown**: Client sends `shutdown` request → Server prepares to exit
164
+ 5. **Exit**: Client sends `exit` notification → Server closes
165
+
166
+ ### Graceful Shutdown
167
+
168
+ ```typescript
169
+ // Graceful shutdown (waits for pending requests)
170
+ await server.shutdown(5000); // 5 second timeout
171
+
172
+ // Force close
173
+ await server.close();
174
+ ```
175
+
176
+ ## Examples
177
+
178
+ Check out the [examples directory](../../examples/server/) for complete examples:
179
+
180
+ - [minimal-server.ts](../../examples/server/minimal-server.ts) - Basic hover server
181
+ - [hover-server.ts](../../examples/server/hover-server.ts) - Hover + completion with document tracking
182
+
183
+ ## API Reference
184
+
185
+ ### LSPServer
186
+
187
+ ```typescript
188
+ class LSPServer<Capabilities extends Partial<ServerCapabilities> = ServerCapabilities>
189
+ ```
190
+
191
+ #### Methods
192
+
193
+ - `onRequest<Method, Params, Result>(method, handler)` - Register request handler
194
+ - `onNotification<Method, Params>(method, handler)` - Register notification handler
195
+ - `setCapabilities(capabilities)` - Set server capabilities
196
+ - `getCapabilities()` - Get current capabilities
197
+ - `listen(transport)` - Start server on transport
198
+ - `shutdown(timeout?)` - Graceful shutdown
199
+ - `close()` - Force close
200
+
201
+ ### Handler Types
202
+
203
+ ```typescript
204
+ type RequestHandler<Params, Result> = (
205
+ params: Params,
206
+ token: CancellationToken,
207
+ context: RequestContext
208
+ ) => Promise<Result> | Result;
209
+
210
+ type NotificationHandler<Params> = (
211
+ params: Params,
212
+ context: NotificationContext
213
+ ) => void | Promise<void>;
214
+ ```
215
+
216
+ ## License
217
+
218
+ MIT
@@ -0,0 +1,56 @@
1
+ /**
2
+ * Capability validation for server handlers
3
+ *
4
+ * Ensures handlers can only be registered for declared capabilities
5
+ */
6
+ import type { ClientCapabilities, ServerCapabilities } from '@lspeasy/core';
7
+ import type { Logger } from '@lspeasy/core';
8
+ /**
9
+ * Validates that a handler can be registered for a method
10
+ * based on declared server capabilities
11
+ */
12
+ export declare class CapabilityGuard {
13
+ private readonly capabilities;
14
+ private readonly logger;
15
+ private readonly strict;
16
+ constructor(capabilities: Partial<ServerCapabilities>, logger: Logger, strict?: boolean);
17
+ /**
18
+ * Check if handler registration is allowed for this method
19
+ *
20
+ * @param method - LSP method name
21
+ * @returns true if allowed, false otherwise
22
+ * @throws Error if strict mode enabled and capability not declared
23
+ */
24
+ canRegisterHandler(method: string): boolean;
25
+ getAllowedMethods(): string[];
26
+ }
27
+ /**
28
+ * Validates that server-to-client messages respect declared client capabilities
29
+ */
30
+ export declare class ClientCapabilityGuard {
31
+ private readonly capabilities;
32
+ private readonly logger;
33
+ private readonly strict;
34
+ constructor(capabilities: Partial<ClientCapabilities>, logger: Logger, strict?: boolean);
35
+ /**
36
+ * Check if a request can be sent to the client
37
+ *
38
+ * @param method - LSP method name
39
+ * @returns true if allowed, false otherwise
40
+ * @throws Error if strict mode enabled and client capability not declared
41
+ */
42
+ canSendRequest(method: string): boolean;
43
+ /**
44
+ * Check if a notification can be sent to the client
45
+ *
46
+ * @param method - LSP method name
47
+ * @returns true if allowed, false otherwise
48
+ * @throws Error if strict mode enabled and client capability not declared
49
+ */
50
+ canSendNotification(method: string): boolean;
51
+ /**
52
+ * Get list of capabilities the client declared
53
+ */
54
+ getClientCapabilities(): Partial<ClientCapabilities>;
55
+ }
56
+ //# sourceMappingURL=capability-guard.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"capability-guard.d.ts","sourceRoot":"","sources":["../src/capability-guard.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,KAAK,EAAE,kBAAkB,EAAE,kBAAkB,EAAE,MAAM,eAAe,CAAC;AAC5E,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,eAAe,CAAC;AA+C5C;;;GAGG;AACH,qBAAa,eAAe;IAExB,OAAO,CAAC,QAAQ,CAAC,YAAY;IAC7B,OAAO,CAAC,QAAQ,CAAC,MAAM;IACvB,OAAO,CAAC,QAAQ,CAAC,MAAM;IAHzB,YACmB,YAAY,EAAE,OAAO,CAAC,kBAAkB,CAAC,EACzC,MAAM,EAAE,MAAM,EACd,MAAM,GAAE,OAAe,EACtC;IAEJ;;;;;;OAMG;IACH,kBAAkB,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAuD1C;IAED,iBAAiB,IAAI,MAAM,EAAE,CAK5B;CACF;AAED;;GAEG;AACH,qBAAa,qBAAqB;IAE9B,OAAO,CAAC,QAAQ,CAAC,YAAY;IAC7B,OAAO,CAAC,QAAQ,CAAC,MAAM;IACvB,OAAO,CAAC,QAAQ,CAAC,MAAM;IAHzB,YACmB,YAAY,EAAE,OAAO,CAAC,kBAAkB,CAAC,EACzC,MAAM,EAAE,MAAM,EACd,MAAM,GAAE,OAAe,EACtC;IAEJ;;;;;;OAMG;IACH,cAAc,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CA2CtC;IAED;;;;;;OAMG;IACH,mBAAmB,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CA2C3C;IAED;;OAEG;IACH,qBAAqB,IAAI,OAAO,CAAC,kBAAkB,CAAC,CAEnD;CACF"}
@@ -0,0 +1,212 @@
1
+ /**
2
+ * Capability validation for server handlers
3
+ *
4
+ * Ensures handlers can only be registered for declared capabilities
5
+ */
6
+ import { LSPNotification, LSPRequest, getClientCapabilityForNotificationMethod, getClientCapabilityForRequestMethod, hasServerCapability, hasClientCapability, getCapabilityForNotificationMethod, getCapabilityForRequestMethod } from '@lspeasy/core';
7
+ function buildMethodSets(capabilityKey) {
8
+ const all = new Set();
9
+ const alwaysAllowed = new Set();
10
+ for (const namespaceDefinitions of Object.values(LSPRequest)) {
11
+ for (const definition of Object.values(namespaceDefinitions)) {
12
+ const entry = definition;
13
+ all.add(entry.Method);
14
+ if (!entry[capabilityKey]) {
15
+ alwaysAllowed.add(entry.Method);
16
+ }
17
+ }
18
+ }
19
+ for (const namespaceDefinitions of Object.values(LSPNotification)) {
20
+ for (const definition of Object.values(namespaceDefinitions)) {
21
+ const entry = definition;
22
+ all.add(entry.Method);
23
+ if (!entry[capabilityKey]) {
24
+ alwaysAllowed.add(entry.Method);
25
+ }
26
+ }
27
+ }
28
+ return { all, alwaysAllowed };
29
+ }
30
+ const SERVER_METHODS = buildMethodSets('ServerCapability');
31
+ const CLIENT_METHODS = buildMethodSets('ClientCapability');
32
+ /**
33
+ * Validates that a handler can be registered for a method
34
+ * based on declared server capabilities
35
+ */
36
+ export class CapabilityGuard {
37
+ capabilities;
38
+ logger;
39
+ strict;
40
+ constructor(capabilities, logger, strict = false) {
41
+ this.capabilities = capabilities;
42
+ this.logger = logger;
43
+ this.strict = strict;
44
+ }
45
+ /**
46
+ * Check if handler registration is allowed for this method
47
+ *
48
+ * @param method - LSP method name
49
+ * @returns true if allowed, false otherwise
50
+ * @throws Error if strict mode enabled and capability not declared
51
+ */
52
+ canRegisterHandler(method) {
53
+ if (!SERVER_METHODS.all.has(method)) {
54
+ if (!this.strict) {
55
+ this.logger.debug(`Unknown method ${method}, allowing in non-strict mode`);
56
+ return true;
57
+ }
58
+ const error = `Cannot register handler for unknown method: ${method}`;
59
+ this.logger.error(error);
60
+ if (this.strict) {
61
+ throw new Error(error);
62
+ }
63
+ return false;
64
+ }
65
+ if (SERVER_METHODS.alwaysAllowed.has(method)) {
66
+ return true;
67
+ }
68
+ // Check if method requires a capability (try both request and notification)
69
+ let capabilityKey = getCapabilityForRequestMethod(method);
70
+ if (!capabilityKey) {
71
+ capabilityKey = getCapabilityForNotificationMethod(method);
72
+ }
73
+ if (!capabilityKey) {
74
+ // Unknown method - allow in non-strict mode
75
+ if (!this.strict) {
76
+ this.logger.debug(`Unknown method ${method}, allowing in non-strict mode`);
77
+ return true;
78
+ }
79
+ const error = `Cannot register handler for unknown method: ${method}`;
80
+ this.logger.error(error);
81
+ if (this.strict) {
82
+ throw new Error(error);
83
+ }
84
+ return false;
85
+ }
86
+ if (capabilityKey === 'alwaysOn') {
87
+ return true;
88
+ }
89
+ // Check if capability is declared
90
+ if (!hasServerCapability(this.capabilities, capabilityKey)) {
91
+ const error = `Cannot register handler for ${method}: server capability '${capabilityKey}' not declared`;
92
+ this.logger.warn(error);
93
+ if (this.strict) {
94
+ throw new Error(error);
95
+ }
96
+ return false;
97
+ }
98
+ return true;
99
+ }
100
+ getAllowedMethods() {
101
+ // This would require iterating through all LSP methods
102
+ // For now, return an empty array - can be enhanced if needed
103
+ this.logger.warn('getAllowedMethods not fully implemented - returns empty array');
104
+ return [];
105
+ }
106
+ }
107
+ /**
108
+ * Validates that server-to-client messages respect declared client capabilities
109
+ */
110
+ export class ClientCapabilityGuard {
111
+ capabilities;
112
+ logger;
113
+ strict;
114
+ constructor(capabilities, logger, strict = false) {
115
+ this.capabilities = capabilities;
116
+ this.logger = logger;
117
+ this.strict = strict;
118
+ }
119
+ /**
120
+ * Check if a request can be sent to the client
121
+ *
122
+ * @param method - LSP method name
123
+ * @returns true if allowed, false otherwise
124
+ * @throws Error if strict mode enabled and client capability not declared
125
+ */
126
+ canSendRequest(method) {
127
+ if (!CLIENT_METHODS.all.has(method)) {
128
+ if (!this.strict) {
129
+ this.logger.debug(`Unknown request method ${method}, allowing in non-strict mode`);
130
+ return true;
131
+ }
132
+ const error = `Cannot send request for unknown method: ${method}`;
133
+ this.logger.error(error);
134
+ throw new Error(error);
135
+ }
136
+ if (CLIENT_METHODS.alwaysAllowed.has(method)) {
137
+ return true;
138
+ }
139
+ const capabilityKey = getClientCapabilityForRequestMethod(method);
140
+ if (!capabilityKey) {
141
+ if (!this.strict) {
142
+ this.logger.debug(`Unknown request method ${method}, allowing in non-strict mode`);
143
+ return true;
144
+ }
145
+ const error = `Cannot send request for unknown method: ${method}`;
146
+ this.logger.error(error);
147
+ throw new Error(error);
148
+ }
149
+ if (capabilityKey === 'alwaysOn') {
150
+ return true;
151
+ }
152
+ if (!hasClientCapability(this.capabilities, capabilityKey)) {
153
+ const error = `Cannot send request ${method}: client capability '${capabilityKey}' not declared`;
154
+ this.logger.warn(error);
155
+ if (this.strict) {
156
+ throw new Error(error);
157
+ }
158
+ return false;
159
+ }
160
+ return true;
161
+ }
162
+ /**
163
+ * Check if a notification can be sent to the client
164
+ *
165
+ * @param method - LSP method name
166
+ * @returns true if allowed, false otherwise
167
+ * @throws Error if strict mode enabled and client capability not declared
168
+ */
169
+ canSendNotification(method) {
170
+ if (!CLIENT_METHODS.all.has(method)) {
171
+ if (!this.strict) {
172
+ this.logger.debug(`Unknown notification method ${method}, allowing in non-strict mode`);
173
+ return true;
174
+ }
175
+ const error = `Cannot send notification for unknown method: ${method}`;
176
+ this.logger.error(error);
177
+ throw new Error(error);
178
+ }
179
+ if (CLIENT_METHODS.alwaysAllowed.has(method)) {
180
+ return true;
181
+ }
182
+ const capabilityKey = getClientCapabilityForNotificationMethod(method);
183
+ if (!capabilityKey) {
184
+ if (!this.strict) {
185
+ this.logger.debug(`Unknown notification method ${method}, allowing in non-strict mode`);
186
+ return true;
187
+ }
188
+ const error = `Cannot send notification for unknown method: ${method}`;
189
+ this.logger.error(error);
190
+ throw new Error(error);
191
+ }
192
+ if (capabilityKey === 'alwaysOn') {
193
+ return true;
194
+ }
195
+ if (!hasClientCapability(this.capabilities, capabilityKey)) {
196
+ const error = `Cannot send notification ${method}: client capability '${capabilityKey}' not declared`;
197
+ this.logger.warn(error);
198
+ if (this.strict) {
199
+ throw new Error(error);
200
+ }
201
+ return false;
202
+ }
203
+ return true;
204
+ }
205
+ /**
206
+ * Get list of capabilities the client declared
207
+ */
208
+ getClientCapabilities() {
209
+ return { ...this.capabilities };
210
+ }
211
+ }
212
+ //# sourceMappingURL=capability-guard.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"capability-guard.js","sourceRoot":"","sources":["../src/capability-guard.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,19 @@
1
+ /**
2
+ * Capability-aware dynamic method injection for server
3
+ *
4
+ * Dynamically adds handler registration methods and send methods to the server
5
+ * based on declared capabilities
6
+ */
7
+ import type { LSPServer } from './server.js';
8
+ import type { ServerCapabilities } from '@lspeasy/core';
9
+ /**
10
+ * Initialize capability-aware handler registration methods on the server
11
+ * Creates namespace.onMethod() style methods for registering handlers
12
+ */
13
+ export declare function initializeServerHandlerMethods<Capabilities extends Partial<ServerCapabilities>>(server: LSPServer<Capabilities>): void;
14
+ /**
15
+ * Initialize capability-aware send methods on the server
16
+ * Creates namespace.method() style methods for sending requests/notifications to client
17
+ */
18
+ export declare function initializeServerSendMethods<Capabilities extends Partial<ServerCapabilities>>(server: LSPServer<Capabilities>): void;
19
+ //# sourceMappingURL=capability-proxy.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"capability-proxy.d.ts","sourceRoot":"","sources":["../src/capability-proxy.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AAC7C,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,eAAe,CAAC;AAIxD;;;GAGG;AACH,wBAAgB,8BAA8B,CAAC,YAAY,SAAS,OAAO,CAAC,kBAAkB,CAAC,EAC7F,MAAM,EAAE,SAAS,CAAC,YAAY,CAAC,GAC9B,IAAI,CAyEN;AAED;;;GAGG;AACH,wBAAgB,2BAA2B,CAAC,YAAY,SAAS,OAAO,CAAC,kBAAkB,CAAC,EAC1F,MAAM,EAAE,SAAS,CAAC,YAAY,CAAC,GAC9B,IAAI,CAoDN"}
@@ -0,0 +1,121 @@
1
+ /**
2
+ * Capability-aware dynamic method injection for server
3
+ *
4
+ * Dynamically adds handler registration methods and send methods to the server
5
+ * based on declared capabilities
6
+ */
7
+ import { LSPRequest, LSPNotification, hasServerCapability } from '@lspeasy/core';
8
+ import camelCase from 'camelcase';
9
+ /**
10
+ * Initialize capability-aware handler registration methods on the server
11
+ * Creates namespace.onMethod() style methods for registering handlers
12
+ */
13
+ export function initializeServerHandlerMethods(server) {
14
+ const capabilities = server.getServerCapabilities();
15
+ // Add handler registration methods for requests
16
+ for (const [namespaceName, namespaceDefinitions] of Object.entries(LSPRequest)) {
17
+ const clientPropertyName = camelCase(namespaceName);
18
+ const namespace = {};
19
+ for (const [methodKey, definition] of Object.entries(namespaceDefinitions)) {
20
+ const def = definition;
21
+ // Only add methods for clientToServer or both directions
22
+ if (def.Direction !== 'clientToServer' && def.Direction !== 'both') {
23
+ continue;
24
+ }
25
+ // Check if capability is satisfied
26
+ if (def.ServerCapability) {
27
+ // Skip if capability is not set
28
+ if (!hasServerCapability(capabilities, def.ServerCapability)) {
29
+ continue;
30
+ }
31
+ }
32
+ // Create handler registration method: onMethod
33
+ const handlerMethodName = `on${methodKey}`;
34
+ namespace[handlerMethodName] = function (handler) {
35
+ return server.onRequest(def.Method, handler);
36
+ };
37
+ }
38
+ // Only add namespace if it has at least one method
39
+ if (Object.keys(namespace).length > 0) {
40
+ if (!server[clientPropertyName]) {
41
+ server[clientPropertyName] = {};
42
+ }
43
+ Object.assign(server[clientPropertyName], namespace);
44
+ }
45
+ }
46
+ // Add handler registration methods for notifications
47
+ for (const [namespaceName, namespaceDefinitions] of Object.entries(LSPNotification)) {
48
+ const clientPropertyName = camelCase(namespaceName);
49
+ const namespace = {};
50
+ for (const [methodKey, definition] of Object.entries(namespaceDefinitions)) {
51
+ const def = definition;
52
+ // Only add methods for clientToServer or both directions
53
+ if (def.Direction !== 'clientToServer' && def.Direction !== 'both') {
54
+ continue;
55
+ }
56
+ // Check if notification requires capability
57
+ if (def.ServerCapability && !hasServerCapability(capabilities, def.ServerCapability)) {
58
+ continue;
59
+ }
60
+ // Create handler registration method: onMethod
61
+ const handlerMethodName = `on${methodKey}`;
62
+ namespace[handlerMethodName] = function (handler) {
63
+ return server.onNotification(def.Method, handler);
64
+ };
65
+ }
66
+ // Only add namespace if it has at least one method
67
+ if (Object.keys(namespace).length > 0) {
68
+ if (!server[clientPropertyName]) {
69
+ server[clientPropertyName] = {};
70
+ }
71
+ Object.assign(server[clientPropertyName], namespace);
72
+ }
73
+ }
74
+ }
75
+ /**
76
+ * Initialize capability-aware send methods on the server
77
+ * Creates namespace.method() style methods for sending requests/notifications to client
78
+ */
79
+ export function initializeServerSendMethods(server) {
80
+ // Add send methods for server-to-client requests
81
+ for (const [namespaceName, namespaceDefinitions] of Object.entries(LSPRequest)) {
82
+ const clientPropertyName = camelCase(namespaceName);
83
+ if (!server[clientPropertyName]) {
84
+ server[clientPropertyName] = {};
85
+ }
86
+ const namespace = server[clientPropertyName];
87
+ for (const [methodKey, definition] of Object.entries(namespaceDefinitions)) {
88
+ const def = definition;
89
+ // Only add methods for serverToClient or both directions
90
+ if (def.Direction !== 'serverToClient' && def.Direction !== 'both') {
91
+ continue;
92
+ }
93
+ // Create send method
94
+ const sendMethodName = camelCase(methodKey);
95
+ namespace[sendMethodName] = async function (params) {
96
+ return server.sendRequest(def.Method, params);
97
+ };
98
+ }
99
+ }
100
+ // Add send methods for server-to-client notifications
101
+ for (const [namespaceName, namespaceDefinitions] of Object.entries(LSPNotification)) {
102
+ const clientPropertyName = camelCase(namespaceName);
103
+ if (!server[clientPropertyName]) {
104
+ server[clientPropertyName] = {};
105
+ }
106
+ const namespace = server[clientPropertyName];
107
+ for (const [methodKey, definition] of Object.entries(namespaceDefinitions)) {
108
+ const def = definition;
109
+ // Only add methods for serverToClient or both directions
110
+ if (def.Direction !== 'serverToClient' && def.Direction !== 'both') {
111
+ continue;
112
+ }
113
+ // Create send method
114
+ const sendMethodName = camelCase(methodKey);
115
+ namespace[sendMethodName] = async function (params) {
116
+ return server.sendNotification(def.Method, params);
117
+ };
118
+ }
119
+ }
120
+ }
121
+ //# sourceMappingURL=capability-proxy.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"capability-proxy.js","sourceRoot":"","sources":["../src/capability-proxy.ts"],"names":[],"mappings":"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"}