@514labs/moose-lsp 1.0.0

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.
Files changed (84) hide show
  1. package/dist/clickhouseData.d.ts +78 -0
  2. package/dist/clickhouseData.js +112 -0
  3. package/dist/clickhouseData.js.map +1 -0
  4. package/dist/clickhouseData.test.d.ts +2 -0
  5. package/dist/clickhouseData.test.js +93 -0
  6. package/dist/clickhouseData.test.js.map +1 -0
  7. package/dist/clickhouseVersion.d.ts +49 -0
  8. package/dist/clickhouseVersion.js +149 -0
  9. package/dist/clickhouseVersion.js.map +1 -0
  10. package/dist/clickhouseVersion.test.d.ts +2 -0
  11. package/dist/clickhouseVersion.test.js +114 -0
  12. package/dist/clickhouseVersion.test.js.map +1 -0
  13. package/dist/codeActions.d.ts +27 -0
  14. package/dist/codeActions.js +173 -0
  15. package/dist/codeActions.js.map +1 -0
  16. package/dist/codeActions.test.d.ts +2 -0
  17. package/dist/codeActions.test.js +207 -0
  18. package/dist/codeActions.test.js.map +1 -0
  19. package/dist/completions.d.ts +22 -0
  20. package/dist/completions.js +228 -0
  21. package/dist/completions.js.map +1 -0
  22. package/dist/completions.test.d.ts +2 -0
  23. package/dist/completions.test.js +283 -0
  24. package/dist/completions.test.js.map +1 -0
  25. package/dist/data/clickhouse-25.6.json +30772 -0
  26. package/dist/data/clickhouse-25.8.json +31872 -0
  27. package/dist/diagnostics.d.ts +18 -0
  28. package/dist/diagnostics.js +54 -0
  29. package/dist/diagnostics.js.map +1 -0
  30. package/dist/diagnostics.test.d.ts +2 -0
  31. package/dist/diagnostics.test.js +110 -0
  32. package/dist/diagnostics.test.js.map +1 -0
  33. package/dist/formatting.d.ts +36 -0
  34. package/dist/formatting.js +70 -0
  35. package/dist/formatting.js.map +1 -0
  36. package/dist/formatting.test.d.ts +2 -0
  37. package/dist/formatting.test.js +93 -0
  38. package/dist/formatting.test.js.map +1 -0
  39. package/dist/hover.d.ts +43 -0
  40. package/dist/hover.js +198 -0
  41. package/dist/hover.js.map +1 -0
  42. package/dist/hover.test.d.ts +2 -0
  43. package/dist/hover.test.js +319 -0
  44. package/dist/hover.test.js.map +1 -0
  45. package/dist/index.d.ts +2 -0
  46. package/dist/index.js +26 -0
  47. package/dist/index.js.map +1 -0
  48. package/dist/projectDetector.d.ts +7 -0
  49. package/dist/projectDetector.js +66 -0
  50. package/dist/projectDetector.js.map +1 -0
  51. package/dist/projectDetector.test.d.ts +2 -0
  52. package/dist/projectDetector.test.js +114 -0
  53. package/dist/projectDetector.test.js.map +1 -0
  54. package/dist/server.d.ts +2 -0
  55. package/dist/server.integration.test.d.ts +2 -0
  56. package/dist/server.integration.test.js +190 -0
  57. package/dist/server.integration.test.js.map +1 -0
  58. package/dist/server.js +426 -0
  59. package/dist/server.js.map +1 -0
  60. package/dist/serverLogic.d.ts +32 -0
  61. package/dist/serverLogic.js +51 -0
  62. package/dist/serverLogic.js.map +1 -0
  63. package/dist/serverLogic.test.d.ts +2 -0
  64. package/dist/serverLogic.test.js +264 -0
  65. package/dist/serverLogic.test.js.map +1 -0
  66. package/dist/sqlExtractor.d.ts +15 -0
  67. package/dist/sqlExtractor.js +106 -0
  68. package/dist/sqlExtractor.js.map +1 -0
  69. package/dist/sqlExtractor.test.d.ts +2 -0
  70. package/dist/sqlExtractor.test.js +268 -0
  71. package/dist/sqlExtractor.test.js.map +1 -0
  72. package/dist/sqlLocations.d.ts +31 -0
  73. package/dist/sqlLocations.js +52 -0
  74. package/dist/sqlLocations.js.map +1 -0
  75. package/dist/sqlLocations.test.d.ts +2 -0
  76. package/dist/sqlLocations.test.js +95 -0
  77. package/dist/sqlLocations.test.js.map +1 -0
  78. package/dist/typescriptService.d.ts +29 -0
  79. package/dist/typescriptService.js +138 -0
  80. package/dist/typescriptService.js.map +1 -0
  81. package/dist/typescriptService.test.d.ts +2 -0
  82. package/dist/typescriptService.test.js +201 -0
  83. package/dist/typescriptService.test.js.map +1 -0
  84. package/package.json +47 -0
@@ -0,0 +1,66 @@
1
+ #!/usr/bin/env node
2
+ "use strict";
3
+ var __create = Object.create;
4
+ var __defProp = Object.defineProperty;
5
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
6
+ var __getOwnPropNames = Object.getOwnPropertyNames;
7
+ var __getProtoOf = Object.getPrototypeOf;
8
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
9
+ var __export = (target, all) => {
10
+ for (var name in all)
11
+ __defProp(target, name, { get: all[name], enumerable: true });
12
+ };
13
+ var __copyProps = (to, from, except, desc) => {
14
+ if (from && typeof from === "object" || typeof from === "function") {
15
+ for (let key of __getOwnPropNames(from))
16
+ if (!__hasOwnProp.call(to, key) && key !== except)
17
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
18
+ }
19
+ return to;
20
+ };
21
+ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
22
+ // If the importer is in node compatibility mode or this is not an ESM
23
+ // file that has been converted to a CommonJS file using a Babel-
24
+ // compatible transform (i.e. "__esModule" has not been set), then set
25
+ // "default" to the CommonJS "module.exports" for node compatibility.
26
+ isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
27
+ mod
28
+ ));
29
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
30
+ var projectDetector_exports = {};
31
+ __export(projectDetector_exports, {
32
+ detectMooseProject: () => detectMooseProject
33
+ });
34
+ module.exports = __toCommonJS(projectDetector_exports);
35
+ var fs = __toESM(require("node:fs/promises"));
36
+ var path = __toESM(require("node:path"));
37
+ var import_glob = require("glob");
38
+ async function detectMooseProject(workspaceRoot) {
39
+ try {
40
+ const packageJsonPaths = await (0, import_glob.glob)("**/package.json", {
41
+ cwd: workspaceRoot,
42
+ ignore: ["**/node_modules/**", "**/dist/**", "**/target/**"]
43
+ });
44
+ for (const relativePath of packageJsonPaths) {
45
+ const fullPath = path.join(workspaceRoot, relativePath);
46
+ try {
47
+ const content = await fs.readFile(fullPath, "utf-8");
48
+ const pkg = JSON.parse(content);
49
+ const deps = { ...pkg.dependencies, ...pkg.devDependencies };
50
+ if (deps["@514labs/moose-lib"]) {
51
+ return path.dirname(fullPath);
52
+ }
53
+ } catch (_error) {
54
+ }
55
+ }
56
+ return null;
57
+ } catch (error) {
58
+ console.error("Error detecting Moose project:", error);
59
+ return null;
60
+ }
61
+ }
62
+ // Annotate the CommonJS export names for ESM import in node:
63
+ 0 && (module.exports = {
64
+ detectMooseProject
65
+ });
66
+ //# sourceMappingURL=projectDetector.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/projectDetector.ts"],"sourcesContent":["import * as fs from 'node:fs/promises';\nimport * as path from 'node:path';\nimport { glob } from 'glob';\n\n/**\n * Detects a Moose project by searching for package.json files containing @514labs/moose-lib\n * Supports monorepos by recursively searching subdirectories\n */\nexport async function detectMooseProject(\n workspaceRoot: string,\n): Promise<string | null> {\n try {\n // Find all package.json files in workspace\n const packageJsonPaths = await glob('**/package.json', {\n cwd: workspaceRoot,\n ignore: ['**/node_modules/**', '**/dist/**', '**/target/**'],\n });\n\n for (const relativePath of packageJsonPaths) {\n const fullPath = path.join(workspaceRoot, relativePath);\n\n try {\n const content = await fs.readFile(fullPath, 'utf-8');\n const pkg = JSON.parse(content);\n\n const deps = { ...pkg.dependencies, ...pkg.devDependencies };\n if (deps['@514labs/moose-lib']) {\n // Return the directory containing this package.json\n return path.dirname(fullPath);\n }\n } catch (_error) {}\n }\n\n return null;\n } catch (error) {\n console.error('Error detecting Moose project:', error);\n return null;\n }\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,SAAoB;AACpB,WAAsB;AACtB,kBAAqB;AAMrB,eAAsB,mBACpB,eACwB;AACxB,MAAI;AAEF,UAAM,mBAAmB,UAAM,kBAAK,mBAAmB;AAAA,MACrD,KAAK;AAAA,MACL,QAAQ,CAAC,sBAAsB,cAAc,cAAc;AAAA,IAC7D,CAAC;AAED,eAAW,gBAAgB,kBAAkB;AAC3C,YAAM,WAAW,KAAK,KAAK,eAAe,YAAY;AAEtD,UAAI;AACF,cAAM,UAAU,MAAM,GAAG,SAAS,UAAU,OAAO;AACnD,cAAM,MAAM,KAAK,MAAM,OAAO;AAE9B,cAAM,OAAO,EAAE,GAAG,IAAI,cAAc,GAAG,IAAI,gBAAgB;AAC3D,YAAI,KAAK,oBAAoB,GAAG;AAE9B,iBAAO,KAAK,QAAQ,QAAQ;AAAA,QAC9B;AAAA,MACF,SAAS,QAAQ;AAAA,MAAC;AAAA,IACpB;AAEA,WAAO;AAAA,EACT,SAAS,OAAO;AACd,YAAQ,MAAM,kCAAkC,KAAK;AACrD,WAAO;AAAA,EACT;AACF;","names":[]}
@@ -0,0 +1,2 @@
1
+
2
+ export { }
@@ -0,0 +1,114 @@
1
+ #!/usr/bin/env node
2
+ "use strict";
3
+ var __create = Object.create;
4
+ var __defProp = Object.defineProperty;
5
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
6
+ var __getOwnPropNames = Object.getOwnPropertyNames;
7
+ var __getProtoOf = Object.getPrototypeOf;
8
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
9
+ var __copyProps = (to, from, except, desc) => {
10
+ if (from && typeof from === "object" || typeof from === "function") {
11
+ for (let key of __getOwnPropNames(from))
12
+ if (!__hasOwnProp.call(to, key) && key !== except)
13
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
14
+ }
15
+ return to;
16
+ };
17
+ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
18
+ // If the importer is in node compatibility mode or this is not an ESM
19
+ // file that has been converted to a CommonJS file using a Babel-
20
+ // compatible transform (i.e. "__esModule" has not been set), then set
21
+ // "default" to the CommonJS "module.exports" for node compatibility.
22
+ isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
23
+ mod
24
+ ));
25
+ var import_node_assert = __toESM(require("node:assert"));
26
+ var fs = __toESM(require("node:fs/promises"));
27
+ var os = __toESM(require("node:os"));
28
+ var path = __toESM(require("node:path"));
29
+ var import_node_test = require("node:test");
30
+ var import_projectDetector = require("./projectDetector");
31
+ (0, import_node_test.test)("Project Detection Tests", async (t) => {
32
+ await t.test("finds Moose project in root directory", async () => {
33
+ const tmpDir = await fs.mkdtemp(path.join(os.tmpdir(), "moose-lsp-test-"));
34
+ try {
35
+ await fs.writeFile(
36
+ path.join(tmpDir, "package.json"),
37
+ JSON.stringify({
38
+ name: "test-project",
39
+ dependencies: {
40
+ "@514labs/moose-lib": "^1.0.0"
41
+ }
42
+ })
43
+ );
44
+ const result = await (0, import_projectDetector.detectMooseProject)(tmpDir);
45
+ import_node_assert.default.strictEqual(result, tmpDir);
46
+ } finally {
47
+ await fs.rm(tmpDir, { recursive: true, force: true });
48
+ }
49
+ });
50
+ await t.test("finds Moose project in monorepo subdirectory", async () => {
51
+ const tmpDir = await fs.mkdtemp(path.join(os.tmpdir(), "moose-lsp-test-"));
52
+ try {
53
+ await fs.writeFile(
54
+ path.join(tmpDir, "package.json"),
55
+ JSON.stringify({
56
+ name: "monorepo-root",
57
+ private: true
58
+ })
59
+ );
60
+ const packagesDir = path.join(tmpDir, "packages", "moose-backend");
61
+ await fs.mkdir(packagesDir, { recursive: true });
62
+ await fs.writeFile(
63
+ path.join(packagesDir, "package.json"),
64
+ JSON.stringify({
65
+ name: "moose-backend",
66
+ dependencies: {
67
+ "@514labs/moose-lib": "^1.0.0"
68
+ }
69
+ })
70
+ );
71
+ const result = await (0, import_projectDetector.detectMooseProject)(tmpDir);
72
+ import_node_assert.default.strictEqual(result, packagesDir);
73
+ } finally {
74
+ await fs.rm(tmpDir, { recursive: true, force: true });
75
+ }
76
+ });
77
+ await t.test("returns null when no Moose project found", async () => {
78
+ const tmpDir = await fs.mkdtemp(path.join(os.tmpdir(), "moose-lsp-test-"));
79
+ try {
80
+ await fs.writeFile(
81
+ path.join(tmpDir, "package.json"),
82
+ JSON.stringify({
83
+ name: "non-moose-project",
84
+ dependencies: {
85
+ express: "^4.0.0"
86
+ }
87
+ })
88
+ );
89
+ const result = await (0, import_projectDetector.detectMooseProject)(tmpDir);
90
+ import_node_assert.default.strictEqual(result, null);
91
+ } finally {
92
+ await fs.rm(tmpDir, { recursive: true, force: true });
93
+ }
94
+ });
95
+ await t.test("checks devDependencies as well", async () => {
96
+ const tmpDir = await fs.mkdtemp(path.join(os.tmpdir(), "moose-lsp-test-"));
97
+ try {
98
+ await fs.writeFile(
99
+ path.join(tmpDir, "package.json"),
100
+ JSON.stringify({
101
+ name: "test-project",
102
+ devDependencies: {
103
+ "@514labs/moose-lib": "^1.0.0"
104
+ }
105
+ })
106
+ );
107
+ const result = await (0, import_projectDetector.detectMooseProject)(tmpDir);
108
+ import_node_assert.default.strictEqual(result, tmpDir);
109
+ } finally {
110
+ await fs.rm(tmpDir, { recursive: true, force: true });
111
+ }
112
+ });
113
+ });
114
+ //# sourceMappingURL=projectDetector.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/projectDetector.test.ts"],"sourcesContent":["import assert from 'node:assert';\nimport * as fs from 'node:fs/promises';\nimport * as os from 'node:os';\nimport * as path from 'node:path';\nimport { test } from 'node:test';\nimport { detectMooseProject } from './projectDetector';\n\ntest('Project Detection Tests', async (t) => {\n await t.test('finds Moose project in root directory', async () => {\n const tmpDir = await fs.mkdtemp(path.join(os.tmpdir(), 'moose-lsp-test-'));\n\n try {\n // Create package.json with moose-lib dependency\n await fs.writeFile(\n path.join(tmpDir, 'package.json'),\n JSON.stringify({\n name: 'test-project',\n dependencies: {\n '@514labs/moose-lib': '^1.0.0',\n },\n }),\n );\n\n const result = await detectMooseProject(tmpDir);\n assert.strictEqual(result, tmpDir);\n } finally {\n await fs.rm(tmpDir, { recursive: true, force: true });\n }\n });\n\n await t.test('finds Moose project in monorepo subdirectory', async () => {\n const tmpDir = await fs.mkdtemp(path.join(os.tmpdir(), 'moose-lsp-test-'));\n\n try {\n // Create root package.json without moose-lib\n await fs.writeFile(\n path.join(tmpDir, 'package.json'),\n JSON.stringify({\n name: 'monorepo-root',\n private: true,\n }),\n );\n\n // Create packages directory\n const packagesDir = path.join(tmpDir, 'packages', 'moose-backend');\n await fs.mkdir(packagesDir, { recursive: true });\n\n // Create package.json with moose-lib in subdirectory\n await fs.writeFile(\n path.join(packagesDir, 'package.json'),\n JSON.stringify({\n name: 'moose-backend',\n dependencies: {\n '@514labs/moose-lib': '^1.0.0',\n },\n }),\n );\n\n const result = await detectMooseProject(tmpDir);\n assert.strictEqual(result, packagesDir);\n } finally {\n await fs.rm(tmpDir, { recursive: true, force: true });\n }\n });\n\n await t.test('returns null when no Moose project found', async () => {\n const tmpDir = await fs.mkdtemp(path.join(os.tmpdir(), 'moose-lsp-test-'));\n\n try {\n // Create package.json without moose-lib\n await fs.writeFile(\n path.join(tmpDir, 'package.json'),\n JSON.stringify({\n name: 'non-moose-project',\n dependencies: {\n express: '^4.0.0',\n },\n }),\n );\n\n const result = await detectMooseProject(tmpDir);\n assert.strictEqual(result, null);\n } finally {\n await fs.rm(tmpDir, { recursive: true, force: true });\n }\n });\n\n await t.test('checks devDependencies as well', async () => {\n const tmpDir = await fs.mkdtemp(path.join(os.tmpdir(), 'moose-lsp-test-'));\n\n try {\n await fs.writeFile(\n path.join(tmpDir, 'package.json'),\n JSON.stringify({\n name: 'test-project',\n devDependencies: {\n '@514labs/moose-lib': '^1.0.0',\n },\n }),\n );\n\n const result = await detectMooseProject(tmpDir);\n assert.strictEqual(result, tmpDir);\n } finally {\n await fs.rm(tmpDir, { recursive: true, force: true });\n }\n });\n});\n"],"mappings":"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","names":["assert"]}
@@ -0,0 +1,2 @@
1
+
2
+ export { }
@@ -0,0 +1,2 @@
1
+
2
+ export { }
@@ -0,0 +1,190 @@
1
+ #!/usr/bin/env node
2
+ "use strict";
3
+ var __create = Object.create;
4
+ var __defProp = Object.defineProperty;
5
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
6
+ var __getOwnPropNames = Object.getOwnPropertyNames;
7
+ var __getProtoOf = Object.getPrototypeOf;
8
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
9
+ var __copyProps = (to, from, except, desc) => {
10
+ if (from && typeof from === "object" || typeof from === "function") {
11
+ for (let key of __getOwnPropNames(from))
12
+ if (!__hasOwnProp.call(to, key) && key !== except)
13
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
14
+ }
15
+ return to;
16
+ };
17
+ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
18
+ // If the importer is in node compatibility mode or this is not an ESM
19
+ // file that has been converted to a CommonJS file using a Babel-
20
+ // compatible transform (i.e. "__esModule" has not been set), then set
21
+ // "default" to the CommonJS "module.exports" for node compatibility.
22
+ isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
23
+ mod
24
+ ));
25
+ var import_node_assert = __toESM(require("node:assert"));
26
+ var import_node_child_process = require("node:child_process");
27
+ var path = __toESM(require("node:path"));
28
+ var import_node_test = require("node:test");
29
+ class LspClient {
30
+ constructor(serverPath2) {
31
+ this.buffer = "";
32
+ this.messages = [];
33
+ this.nextId = 1;
34
+ this.process = (0, import_node_child_process.spawn)("node", [serverPath2, "--stdio"], {
35
+ stdio: ["pipe", "pipe", "pipe"]
36
+ });
37
+ this.process.stdout?.on("data", (data) => {
38
+ this.buffer += data.toString();
39
+ this.parseMessages();
40
+ });
41
+ this.process.stderr?.on("data", (_data) => {
42
+ });
43
+ }
44
+ parseMessages() {
45
+ while (true) {
46
+ const headerEnd = this.buffer.indexOf("\r\n\r\n");
47
+ if (headerEnd === -1) break;
48
+ const header = this.buffer.slice(0, headerEnd);
49
+ const match = header.match(/Content-Length: (\d+)/);
50
+ if (!match) break;
51
+ const contentLength = parseInt(match[1], 10);
52
+ const contentStart = headerEnd + 4;
53
+ const contentEnd = contentStart + contentLength;
54
+ if (this.buffer.length < contentEnd) break;
55
+ const content = this.buffer.slice(contentStart, contentEnd);
56
+ this.buffer = this.buffer.slice(contentEnd);
57
+ const message = JSON.parse(content);
58
+ this.messages.push(message);
59
+ if (this.onMessage) {
60
+ this.onMessage(message);
61
+ }
62
+ }
63
+ }
64
+ send(message) {
65
+ const content = JSON.stringify(message);
66
+ const header = `Content-Length: ${Buffer.byteLength(content)}\r
67
+ \r
68
+ `;
69
+ this.process.stdin?.write(header + content);
70
+ }
71
+ async request(method, params, timeoutMs = 5e3) {
72
+ const id = this.nextId++;
73
+ return new Promise((resolve, reject) => {
74
+ const timeout = setTimeout(() => {
75
+ this.onMessage = void 0;
76
+ reject(new Error(`Timeout waiting for response to ${method}`));
77
+ }, timeoutMs);
78
+ this.onMessage = (msg) => {
79
+ if (msg.id === id) {
80
+ clearTimeout(timeout);
81
+ this.onMessage = void 0;
82
+ resolve(msg);
83
+ }
84
+ };
85
+ const existing = this.messages.find((m) => m.id === id);
86
+ if (existing) {
87
+ clearTimeout(timeout);
88
+ this.onMessage = void 0;
89
+ resolve(existing);
90
+ return;
91
+ }
92
+ this.send({ jsonrpc: "2.0", id, method, params });
93
+ });
94
+ }
95
+ notify(method, params) {
96
+ this.send({ jsonrpc: "2.0", method, params });
97
+ }
98
+ async waitForCondition(predicate, timeoutMs = 5e3) {
99
+ const deadline = Date.now() + timeoutMs;
100
+ while (Date.now() < deadline) {
101
+ if (predicate(this.messages)) {
102
+ return;
103
+ }
104
+ await new Promise((resolve) => setTimeout(resolve, 50));
105
+ }
106
+ throw new Error("Timeout waiting for condition");
107
+ }
108
+ getMessages() {
109
+ return [...this.messages];
110
+ }
111
+ close() {
112
+ this.process.kill();
113
+ }
114
+ }
115
+ const serverPath = path.join(__dirname, "..", "dist", "server.js");
116
+ (0, import_node_test.test)("Server Integration Tests", async (t) => {
117
+ await t.test("responds to initialize request", async () => {
118
+ const client = new LspClient(serverPath);
119
+ try {
120
+ const response = await client.request("initialize", {
121
+ processId: null,
122
+ rootUri: "file:///tmp/test-project",
123
+ capabilities: {}
124
+ });
125
+ import_node_assert.default.ok(response.result, "Should have result");
126
+ const result = response.result;
127
+ import_node_assert.default.ok(result.capabilities, "Should have capabilities");
128
+ import_node_assert.default.ok(
129
+ result.capabilities.textDocumentSync,
130
+ "Should have textDocumentSync capability"
131
+ );
132
+ } finally {
133
+ client.close();
134
+ }
135
+ });
136
+ await t.test("handles didSave notification and logs message", async () => {
137
+ const client = new LspClient(serverPath);
138
+ try {
139
+ await client.request("initialize", {
140
+ processId: null,
141
+ rootUri: "file:///tmp/test-project",
142
+ capabilities: {
143
+ textDocument: {
144
+ synchronization: {
145
+ didSave: true
146
+ }
147
+ }
148
+ }
149
+ });
150
+ client.notify("initialized", {});
151
+ await new Promise((resolve) => setTimeout(resolve, 100));
152
+ client.notify("textDocument/didOpen", {
153
+ textDocument: {
154
+ uri: "file:///tmp/test-project/app/test.ts",
155
+ languageId: "typescript",
156
+ version: 1,
157
+ text: "const x = 1;"
158
+ }
159
+ });
160
+ await new Promise((resolve) => setTimeout(resolve, 50));
161
+ client.notify("textDocument/didSave", {
162
+ textDocument: {
163
+ uri: "file:///tmp/test-project/app/test.ts"
164
+ }
165
+ });
166
+ await client.waitForCondition((messages2) => {
167
+ return messages2.some((m) => {
168
+ if (m.method !== "window/logMessage") return false;
169
+ const params = m.params;
170
+ return params.message.includes("didSave received");
171
+ });
172
+ }, 3e3);
173
+ const messages = client.getMessages();
174
+ const logMessages = messages.filter(
175
+ (m) => m.method === "window/logMessage"
176
+ );
177
+ const didSaveLog = logMessages.find((m) => {
178
+ const params = m.params;
179
+ return params.message.includes("didSave received");
180
+ });
181
+ import_node_assert.default.ok(
182
+ didSaveLog,
183
+ `Should log didSave received message. Got: ${JSON.stringify(logMessages.map((m) => m.params.message))}`
184
+ );
185
+ } finally {
186
+ client.close();
187
+ }
188
+ });
189
+ });
190
+ //# sourceMappingURL=server.integration.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/server.integration.test.ts"],"sourcesContent":["import assert from 'node:assert';\nimport { type ChildProcess, spawn } from 'node:child_process';\nimport * as path from 'node:path';\nimport { test } from 'node:test';\n\ninterface LspMessage {\n jsonrpc: '2.0';\n id?: number;\n method?: string;\n params?: unknown;\n result?: unknown;\n error?: unknown;\n}\n\nclass LspClient {\n private process: ChildProcess;\n private buffer = '';\n private messages: LspMessage[] = [];\n private nextId = 1;\n private onMessage?: (msg: LspMessage) => void;\n\n constructor(serverPath: string) {\n this.process = spawn('node', [serverPath, '--stdio'], {\n stdio: ['pipe', 'pipe', 'pipe'],\n });\n\n this.process.stdout?.on('data', (data: Buffer) => {\n this.buffer += data.toString();\n this.parseMessages();\n });\n\n this.process.stderr?.on('data', (_data: Buffer) => {\n // Uncomment for debugging:\n // console.error('LSP stderr:', _data.toString());\n });\n }\n\n private parseMessages() {\n while (true) {\n const headerEnd = this.buffer.indexOf('\\r\\n\\r\\n');\n if (headerEnd === -1) break;\n\n const header = this.buffer.slice(0, headerEnd);\n const match = header.match(/Content-Length: (\\d+)/);\n if (!match) break;\n\n const contentLength = parseInt(match[1], 10);\n const contentStart = headerEnd + 4;\n const contentEnd = contentStart + contentLength;\n\n if (this.buffer.length < contentEnd) break;\n\n const content = this.buffer.slice(contentStart, contentEnd);\n this.buffer = this.buffer.slice(contentEnd);\n\n const message = JSON.parse(content) as LspMessage;\n this.messages.push(message);\n\n if (this.onMessage) {\n this.onMessage(message);\n }\n }\n }\n\n send(message: LspMessage): void {\n const content = JSON.stringify(message);\n const header = `Content-Length: ${Buffer.byteLength(content)}\\r\\n\\r\\n`;\n this.process.stdin?.write(header + content);\n }\n\n async request(\n method: string,\n params: unknown,\n timeoutMs = 5000,\n ): Promise<LspMessage> {\n const id = this.nextId++;\n\n return new Promise((resolve, reject) => {\n const timeout = setTimeout(() => {\n this.onMessage = undefined;\n reject(new Error(`Timeout waiting for response to ${method}`));\n }, timeoutMs);\n\n this.onMessage = (msg) => {\n if (msg.id === id) {\n clearTimeout(timeout);\n this.onMessage = undefined;\n resolve(msg);\n }\n };\n\n // Check if response already arrived\n const existing = this.messages.find((m) => m.id === id);\n if (existing) {\n clearTimeout(timeout);\n this.onMessage = undefined;\n resolve(existing);\n return;\n }\n\n this.send({ jsonrpc: '2.0', id, method, params });\n });\n }\n\n notify(method: string, params: unknown): void {\n this.send({ jsonrpc: '2.0', method, params });\n }\n\n async waitForCondition(\n predicate: (messages: LspMessage[]) => boolean,\n timeoutMs = 5000,\n ): Promise<void> {\n const deadline = Date.now() + timeoutMs;\n\n while (Date.now() < deadline) {\n if (predicate(this.messages)) {\n return;\n }\n await new Promise((resolve) => setTimeout(resolve, 50));\n }\n\n throw new Error('Timeout waiting for condition');\n }\n\n getMessages(): LspMessage[] {\n return [...this.messages];\n }\n\n close(): void {\n this.process.kill();\n }\n}\n\nconst serverPath = path.join(__dirname, '..', 'dist', 'server.js');\n\ntest('Server Integration Tests', async (t) => {\n await t.test('responds to initialize request', async () => {\n const client = new LspClient(serverPath);\n\n try {\n const response = await client.request('initialize', {\n processId: null,\n rootUri: 'file:///tmp/test-project',\n capabilities: {},\n });\n\n assert.ok(response.result, 'Should have result');\n const result = response.result as {\n capabilities: { textDocumentSync: unknown };\n };\n assert.ok(result.capabilities, 'Should have capabilities');\n assert.ok(\n result.capabilities.textDocumentSync,\n 'Should have textDocumentSync capability',\n );\n } finally {\n client.close();\n }\n });\n\n await t.test('handles didSave notification and logs message', async () => {\n const client = new LspClient(serverPath);\n\n try {\n // Initialize\n await client.request('initialize', {\n processId: null,\n rootUri: 'file:///tmp/test-project',\n capabilities: {\n textDocument: {\n synchronization: {\n didSave: true,\n },\n },\n },\n });\n\n // Send initialized\n client.notify('initialized', {});\n\n // Wait a bit for server to be ready\n await new Promise((resolve) => setTimeout(resolve, 100));\n\n // Must send didOpen before didSave (TextDocuments requires this)\n client.notify('textDocument/didOpen', {\n textDocument: {\n uri: 'file:///tmp/test-project/app/test.ts',\n languageId: 'typescript',\n version: 1,\n text: 'const x = 1;',\n },\n });\n\n await new Promise((resolve) => setTimeout(resolve, 50));\n\n // Send didSave\n client.notify('textDocument/didSave', {\n textDocument: {\n uri: 'file:///tmp/test-project/app/test.ts',\n },\n });\n\n // Wait for the didSave log message\n await client.waitForCondition((messages) => {\n return messages.some((m) => {\n if (m.method !== 'window/logMessage') return false;\n const params = m.params as { message: string };\n return params.message.includes('didSave received');\n });\n }, 3000);\n\n // Verify\n const messages = client.getMessages();\n const logMessages = messages.filter(\n (m) => m.method === 'window/logMessage',\n );\n const didSaveLog = logMessages.find((m) => {\n const params = m.params as { message: string };\n return params.message.includes('didSave received');\n });\n\n assert.ok(\n didSaveLog,\n `Should log didSave received message. Got: ${JSON.stringify(logMessages.map((m) => (m.params as { message: string }).message))}`,\n );\n } finally {\n client.close();\n }\n });\n});\n"],"mappings":"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","names":["serverPath","assert","messages"]}