websocket-text-relay 1.1.7 → 1.1.9
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/biome.json +37 -0
- package/changelog.md +14 -0
- package/package.json +12 -15
- package/src/index.js +2 -2
- package/src/language-server/JsonRpcInterface.js +4 -4
- package/src/language-server/JsonRpcInterface.test.js +42 -43
- package/src/language-server/LspReader.js +1 -1
- package/src/language-server/LspReader.test.js +48 -47
- package/src/language-server/LspWriter.test.js +12 -11
- package/src/ui/index.html +36 -33
- package/src/ui/js/data/wtrActivity.js +1 -1
- package/src/ui/js/data/wtrStatus.js +1 -1
- package/src/ui/js/setup/eventSubscriber.js +1 -0
- package/src/ui/js/setup.js +4 -3
- package/src/websocket-interface/WebsocketInterface.js +2 -2
- package/src/websocket-interface/WtrSession.js +4 -4
- package/src/websocket-interface/httpServer.js +4 -3
- package/src/websocket-interface/websocketApi.js +4 -4
- package/src/websocket-interface/websocketServer.js +2 -2
- package/.prettierignore +0 -3
- package/.prettierrc +0 -4
- package/eslint.config.js +0 -32
package/biome.json
ADDED
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$schema": "https://biomejs.dev/schemas/2.4.8/schema.json",
|
|
3
|
+
"vcs": {
|
|
4
|
+
"enabled": true,
|
|
5
|
+
"clientKind": "git",
|
|
6
|
+
"useIgnoreFile": true
|
|
7
|
+
},
|
|
8
|
+
"files": {
|
|
9
|
+
"ignoreUnknown": false,
|
|
10
|
+
"includes": ["src/**/*"]
|
|
11
|
+
},
|
|
12
|
+
"formatter": {
|
|
13
|
+
"enabled": true,
|
|
14
|
+
"indentStyle": "space",
|
|
15
|
+
"lineWidth": 110
|
|
16
|
+
},
|
|
17
|
+
"linter": {
|
|
18
|
+
"enabled": true,
|
|
19
|
+
"rules": {
|
|
20
|
+
"recommended": true
|
|
21
|
+
}
|
|
22
|
+
},
|
|
23
|
+
"javascript": {
|
|
24
|
+
"formatter": {
|
|
25
|
+
"quoteStyle": "double",
|
|
26
|
+
"semicolons": "asNeeded"
|
|
27
|
+
}
|
|
28
|
+
},
|
|
29
|
+
"assist": {
|
|
30
|
+
"enabled": true,
|
|
31
|
+
"actions": {
|
|
32
|
+
"source": {
|
|
33
|
+
"organizeImports": "on"
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
}
|
package/changelog.md
CHANGED
|
@@ -1,3 +1,17 @@
|
|
|
1
|
+
## 1.1.9 - 2026/03/22
|
|
2
|
+
|
|
3
|
+
### Dependencies Update
|
|
4
|
+
|
|
5
|
+
- Separate out dev dependencies.
|
|
6
|
+
|
|
7
|
+
## 1.1.8 - 2026/03/22
|
|
8
|
+
|
|
9
|
+
### Dependencies Update
|
|
10
|
+
|
|
11
|
+
- Switch to Biome for formatting and linting.
|
|
12
|
+
- Switch to native nodejs test runner
|
|
13
|
+
- Remove all old dependencies
|
|
14
|
+
|
|
1
15
|
## 1.1.7 - 2025/12/19
|
|
2
16
|
|
|
3
17
|
### UI Update
|
package/package.json
CHANGED
|
@@ -1,16 +1,17 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "websocket-text-relay",
|
|
3
|
-
"version": "1.1.
|
|
3
|
+
"version": "1.1.9",
|
|
4
4
|
"description": "An LSP server for sending live file updates from your text editor to the front end via websockets.",
|
|
5
5
|
"bin": {
|
|
6
6
|
"websocket-text-relay": "./start.js"
|
|
7
7
|
},
|
|
8
8
|
"scripts": {
|
|
9
|
-
"format": "
|
|
10
|
-
"lint": "
|
|
11
|
-
"
|
|
12
|
-
"test": "
|
|
13
|
-
"test:
|
|
9
|
+
"format": "biome check --write",
|
|
10
|
+
"lint": "biome check",
|
|
11
|
+
"test:run": "node --test",
|
|
12
|
+
"test:coverage": "node --test --experimental-test-coverage",
|
|
13
|
+
"test:watch": "node --test --watch",
|
|
14
|
+
"test": "npm run lint && npm run test:run"
|
|
14
15
|
},
|
|
15
16
|
"type": "module",
|
|
16
17
|
"main": "./src/index.js",
|
|
@@ -35,16 +36,12 @@
|
|
|
35
36
|
"url": "https://github.com/niels4/websocket-text-relay/issues"
|
|
36
37
|
},
|
|
37
38
|
"homepage": "https://github.com/niels4/websocket-text-relay#readme",
|
|
38
|
-
"devDependencies": {
|
|
39
|
-
"@eslint/js": "9.39.2",
|
|
40
|
-
"@vitest/coverage-v8": "4.0.16",
|
|
41
|
-
"@vitest/ui": "4.0.16",
|
|
42
|
-
"eslint": "9.39.2",
|
|
43
|
-
"globals": "16.5.0",
|
|
44
|
-
"prettier": "3.7.4",
|
|
45
|
-
"vitest": "4.0.16"
|
|
46
|
-
},
|
|
47
39
|
"dependencies": {
|
|
48
40
|
"ws": "8.18.3"
|
|
41
|
+
},
|
|
42
|
+
"devDependencies": {
|
|
43
|
+
"@biomejs/biome": "2.4.8",
|
|
44
|
+
"@types/node": "25.5.0",
|
|
45
|
+
"typescript": "5.9.3"
|
|
49
46
|
}
|
|
50
47
|
}
|
package/src/index.js
CHANGED
|
@@ -7,8 +7,8 @@ const resolvePort = (portParam) => {
|
|
|
7
7
|
if (portParam != null) {
|
|
8
8
|
return portParam
|
|
9
9
|
}
|
|
10
|
-
if (process.env
|
|
11
|
-
return process.env
|
|
10
|
+
if (process.env.websocket_text_relay_port != null) {
|
|
11
|
+
return process.env.websocket_text_relay_port
|
|
12
12
|
}
|
|
13
13
|
return DEFAULT_WS_PORT
|
|
14
14
|
}
|
|
@@ -1,6 +1,4 @@
|
|
|
1
1
|
import { EventEmitter } from "node:events"
|
|
2
|
-
import { LspReader } from "./LspReader.js"
|
|
3
|
-
import { writeNotification, writeRequest, writeResponse } from "./LspWriter.js"
|
|
4
2
|
import {
|
|
5
3
|
invalidRequestErrorCode,
|
|
6
4
|
invalidRequestErrorMessage,
|
|
@@ -11,6 +9,8 @@ import {
|
|
|
11
9
|
unexpectedRequestErrorCode,
|
|
12
10
|
unexpectedRequestErrorMessage,
|
|
13
11
|
} from "./constants.js"
|
|
12
|
+
import { LspReader } from "./LspReader.js"
|
|
13
|
+
import { writeNotification, writeRequest, writeResponse } from "./LspWriter.js"
|
|
14
14
|
|
|
15
15
|
export class JsonRpcInterface {
|
|
16
16
|
constructor({ inputStream, outputStream }) {
|
|
@@ -34,7 +34,7 @@ export class JsonRpcInterface {
|
|
|
34
34
|
onNotification(method, handler) {
|
|
35
35
|
if (this.notificationHandlers.has(method)) {
|
|
36
36
|
throw new Error(
|
|
37
|
-
|
|
37
|
+
`Can only register one notification handler at a time. Duplicate method handlers for ${method}`,
|
|
38
38
|
)
|
|
39
39
|
}
|
|
40
40
|
this.notificationHandlers.set(method, handler)
|
|
@@ -47,7 +47,7 @@ export class JsonRpcInterface {
|
|
|
47
47
|
onRequest(method, handler) {
|
|
48
48
|
if (this.requestHandlers.has(method)) {
|
|
49
49
|
throw new Error(
|
|
50
|
-
|
|
50
|
+
`Can only register one request handler at a time. Duplicate method handlers for ${method}`,
|
|
51
51
|
)
|
|
52
52
|
}
|
|
53
53
|
this.requestHandlers.set(method, handler)
|
|
@@ -1,7 +1,6 @@
|
|
|
1
|
-
import
|
|
1
|
+
import assert from "node:assert/strict"
|
|
2
2
|
import { PassThrough, Writable } from "node:stream"
|
|
3
|
-
import {
|
|
4
|
-
import { TESTONLY_resetRequestId } from "./LspWriter.js"
|
|
3
|
+
import { before as beforeAll, describe, it } from "node:test"
|
|
5
4
|
import {
|
|
6
5
|
invalidRequestErrorCode,
|
|
7
6
|
invalidRequestErrorMessage,
|
|
@@ -12,6 +11,8 @@ import {
|
|
|
12
11
|
unexpectedRequestErrorCode,
|
|
13
12
|
unexpectedRequestErrorMessage,
|
|
14
13
|
} from "./constants.js"
|
|
14
|
+
import { JsonRpcInterface } from "./JsonRpcInterface.js"
|
|
15
|
+
import { TESTONLY_resetRequestId } from "./LspWriter.js"
|
|
15
16
|
|
|
16
17
|
describe("JsonRpcInterface", () => {
|
|
17
18
|
describe("onNotification", () => {
|
|
@@ -34,14 +35,14 @@ describe("JsonRpcInterface", () => {
|
|
|
34
35
|
})
|
|
35
36
|
|
|
36
37
|
it("should call the handler with the correct params", () => {
|
|
37
|
-
|
|
38
|
+
assert.deepStrictEqual(actualParams, expectedParams)
|
|
38
39
|
})
|
|
39
40
|
})
|
|
40
41
|
|
|
41
42
|
describe("when attempting to register duplicate onNotification handlers ", () => {
|
|
42
43
|
let inputStream, outputStream, jsonRpc
|
|
43
|
-
|
|
44
|
-
|
|
44
|
+
const f1 = () => {}
|
|
45
|
+
const f2 = () => {}
|
|
45
46
|
|
|
46
47
|
beforeAll(() => {
|
|
47
48
|
inputStream = new PassThrough()
|
|
@@ -52,9 +53,7 @@ describe("JsonRpcInterface", () => {
|
|
|
52
53
|
})
|
|
53
54
|
|
|
54
55
|
it("should throw an error if we try to register the same method twice (without first removing the handler)", () => {
|
|
55
|
-
|
|
56
|
-
/duplicate method handlers/i,
|
|
57
|
-
)
|
|
56
|
+
assert.throws(() => jsonRpc.onNotification("test/test-method", f2), /duplicate method handlers/i)
|
|
58
57
|
})
|
|
59
58
|
})
|
|
60
59
|
|
|
@@ -63,8 +62,8 @@ describe("JsonRpcInterface", () => {
|
|
|
63
62
|
const incomingMessage = `Content-Length: 64\r\n\r\n{"jsonrpc":"2.0","method":"test/test-method","params":{"a":"1"}}`
|
|
64
63
|
let f1Fired = false
|
|
65
64
|
let f2Fired = false
|
|
66
|
-
|
|
67
|
-
|
|
65
|
+
const f1 = () => (f1Fired = true)
|
|
66
|
+
const f2 = () => (f2Fired = true)
|
|
68
67
|
|
|
69
68
|
beforeAll(() => {
|
|
70
69
|
inputStream = new PassThrough()
|
|
@@ -79,8 +78,8 @@ describe("JsonRpcInterface", () => {
|
|
|
79
78
|
})
|
|
80
79
|
|
|
81
80
|
it("should call function f2 instead of f1", () => {
|
|
82
|
-
|
|
83
|
-
|
|
81
|
+
assert.strictEqual(f1Fired, false)
|
|
82
|
+
assert.strictEqual(f2Fired, true)
|
|
84
83
|
})
|
|
85
84
|
})
|
|
86
85
|
|
|
@@ -111,7 +110,7 @@ describe("JsonRpcInterface", () => {
|
|
|
111
110
|
})
|
|
112
111
|
|
|
113
112
|
it("should fire the notification-error event with the correct error data", () => {
|
|
114
|
-
|
|
113
|
+
assert.deepStrictEqual(actualError, expectedError)
|
|
115
114
|
})
|
|
116
115
|
})
|
|
117
116
|
|
|
@@ -138,7 +137,7 @@ describe("JsonRpcInterface", () => {
|
|
|
138
137
|
})
|
|
139
138
|
|
|
140
139
|
it("should fire the notification-error event with the correct error data", () => {
|
|
141
|
-
|
|
140
|
+
assert.deepStrictEqual(actualError, expectedError)
|
|
142
141
|
})
|
|
143
142
|
})
|
|
144
143
|
})
|
|
@@ -170,11 +169,11 @@ describe("JsonRpcInterface", () => {
|
|
|
170
169
|
})
|
|
171
170
|
|
|
172
171
|
it("should call the handler with the correct params", () => {
|
|
173
|
-
|
|
172
|
+
assert.deepStrictEqual(actualParams, expectedParams)
|
|
174
173
|
})
|
|
175
174
|
|
|
176
175
|
it("should write the response to the output stream", () => {
|
|
177
|
-
|
|
176
|
+
assert.deepStrictEqual(actualOutput, expectedOutput)
|
|
178
177
|
})
|
|
179
178
|
})
|
|
180
179
|
|
|
@@ -207,23 +206,23 @@ describe("JsonRpcInterface", () => {
|
|
|
207
206
|
})
|
|
208
207
|
|
|
209
208
|
it("should call the handler with the correct params", () => {
|
|
210
|
-
|
|
209
|
+
assert.deepStrictEqual(actualParams, expectedParams)
|
|
211
210
|
})
|
|
212
211
|
|
|
213
212
|
it("should not write the response until the promise resolves", () => {
|
|
214
|
-
|
|
213
|
+
assert.deepStrictEqual(actualOutput, "")
|
|
215
214
|
})
|
|
216
215
|
|
|
217
216
|
it("should write the response after the async function resolves with the result", async () => {
|
|
218
217
|
await new Promise((resolve) => setTimeout(resolve, 1))
|
|
219
|
-
|
|
218
|
+
assert.deepStrictEqual(actualOutput, expectedOutput)
|
|
220
219
|
})
|
|
221
220
|
})
|
|
222
221
|
|
|
223
222
|
describe("when attempting to register duplicate onRequest handlers ", () => {
|
|
224
223
|
let inputStream, outputStream, jsonRpc
|
|
225
|
-
|
|
226
|
-
|
|
224
|
+
const f1 = () => {}
|
|
225
|
+
const f2 = () => {}
|
|
227
226
|
|
|
228
227
|
beforeAll(() => {
|
|
229
228
|
inputStream = new PassThrough()
|
|
@@ -234,7 +233,7 @@ describe("JsonRpcInterface", () => {
|
|
|
234
233
|
})
|
|
235
234
|
|
|
236
235
|
it("should throw an error if we try to register the same method twice (without first removing the handler)", () => {
|
|
237
|
-
|
|
236
|
+
assert.throws(() => jsonRpc.onRequest("test/test-method", f2), /duplicate method handlers/i)
|
|
238
237
|
})
|
|
239
238
|
})
|
|
240
239
|
|
|
@@ -242,8 +241,8 @@ describe("JsonRpcInterface", () => {
|
|
|
242
241
|
const incomingMessage = `Content-Length: 73\r\n\r\n{"jsonrpc":"2.0","id":"0","method":"test/test-method","params":{"a":"1"}}`
|
|
243
242
|
let f1Fired = false
|
|
244
243
|
let f2Fired = false
|
|
245
|
-
|
|
246
|
-
|
|
244
|
+
const f1 = () => (f1Fired = true)
|
|
245
|
+
const f2 = () => (f2Fired = true)
|
|
247
246
|
|
|
248
247
|
beforeAll(() => {
|
|
249
248
|
const inputStream = new PassThrough()
|
|
@@ -258,8 +257,8 @@ describe("JsonRpcInterface", () => {
|
|
|
258
257
|
})
|
|
259
258
|
|
|
260
259
|
it("should call function f2 instead of f1", () => {
|
|
261
|
-
|
|
262
|
-
|
|
260
|
+
assert.strictEqual(f1Fired, false)
|
|
261
|
+
assert.strictEqual(f2Fired, true)
|
|
263
262
|
})
|
|
264
263
|
})
|
|
265
264
|
|
|
@@ -299,11 +298,11 @@ describe("JsonRpcInterface", () => {
|
|
|
299
298
|
})
|
|
300
299
|
|
|
301
300
|
it("should fire the notification-error event with the correct error data", () => {
|
|
302
|
-
|
|
301
|
+
assert.deepStrictEqual(actualError, expectedError)
|
|
303
302
|
})
|
|
304
303
|
|
|
305
304
|
it("should write the error to the output stream", () => {
|
|
306
|
-
|
|
305
|
+
assert.deepStrictEqual(actualOutput, expectedOutput)
|
|
307
306
|
})
|
|
308
307
|
})
|
|
309
308
|
|
|
@@ -339,11 +338,11 @@ describe("JsonRpcInterface", () => {
|
|
|
339
338
|
})
|
|
340
339
|
|
|
341
340
|
it("should fire the notification-error event with the correct error data", () => {
|
|
342
|
-
|
|
341
|
+
assert.deepStrictEqual(actualError, expectedError)
|
|
343
342
|
})
|
|
344
343
|
|
|
345
344
|
it("should write the error to the output stream", () => {
|
|
346
|
-
|
|
345
|
+
assert.deepStrictEqual(actualOutput, expectedOutput)
|
|
347
346
|
})
|
|
348
347
|
})
|
|
349
348
|
})
|
|
@@ -367,7 +366,7 @@ describe("JsonRpcInterface", () => {
|
|
|
367
366
|
})
|
|
368
367
|
|
|
369
368
|
it("should write a notification message without an ID property on the output stream", () => {
|
|
370
|
-
|
|
369
|
+
assert.deepStrictEqual(actualOutput, expectedOutput)
|
|
371
370
|
})
|
|
372
371
|
})
|
|
373
372
|
|
|
@@ -399,18 +398,18 @@ describe("JsonRpcInterface", () => {
|
|
|
399
398
|
})
|
|
400
399
|
|
|
401
400
|
it("should write the request message to the output stream", () => {
|
|
402
|
-
|
|
401
|
+
assert.deepStrictEqual(actualOutput, expectedOutput)
|
|
403
402
|
})
|
|
404
403
|
|
|
405
404
|
it("should return an unresolved promise", () => {
|
|
406
|
-
|
|
407
|
-
|
|
405
|
+
assert.strictEqual(requestPromise instanceof Promise, true)
|
|
406
|
+
assert.strictEqual(actualResult, null)
|
|
408
407
|
})
|
|
409
408
|
|
|
410
409
|
it("should resolve the promise when the client responds with a result", async () => {
|
|
411
410
|
inputStream.write(clientResponse)
|
|
412
411
|
const result = await requestPromise
|
|
413
|
-
|
|
412
|
+
assert.deepStrictEqual(result, expectedResult)
|
|
414
413
|
})
|
|
415
414
|
})
|
|
416
415
|
|
|
@@ -441,18 +440,18 @@ describe("JsonRpcInterface", () => {
|
|
|
441
440
|
})
|
|
442
441
|
|
|
443
442
|
it("should write the request message to the output stream", () => {
|
|
444
|
-
|
|
443
|
+
assert.deepStrictEqual(actualOutput, expectedOutput)
|
|
445
444
|
})
|
|
446
445
|
|
|
447
446
|
it("should return an unresolved promise", () => {
|
|
448
|
-
|
|
449
|
-
|
|
447
|
+
assert.strictEqual(requestPromise instanceof Promise, true)
|
|
448
|
+
assert.strictEqual(actualResult, null)
|
|
450
449
|
})
|
|
451
450
|
|
|
452
451
|
it("should reject the promise when the client responds with an error", async () => {
|
|
453
452
|
inputStream.write(clientResponse)
|
|
454
453
|
await requestPromise.catch((error) => {
|
|
455
|
-
|
|
454
|
+
assert.deepStrictEqual(error, expectedError)
|
|
456
455
|
})
|
|
457
456
|
})
|
|
458
457
|
})
|
|
@@ -476,7 +475,7 @@ describe("JsonRpcInterface", () => {
|
|
|
476
475
|
})
|
|
477
476
|
|
|
478
477
|
it("should write the error to the output stream", () => {
|
|
479
|
-
|
|
478
|
+
assert.deepStrictEqual(actualOutput, expectedOutput)
|
|
480
479
|
})
|
|
481
480
|
})
|
|
482
481
|
|
|
@@ -516,11 +515,11 @@ describe("JsonRpcInterface", () => {
|
|
|
516
515
|
})
|
|
517
516
|
|
|
518
517
|
it("should emit an rpc-error event on the events emitter", () => {
|
|
519
|
-
|
|
518
|
+
assert.deepStrictEqual(actualError, expectedError)
|
|
520
519
|
})
|
|
521
520
|
|
|
522
521
|
it("should notify the client that it sent an invalid rpc message", () => {
|
|
523
|
-
|
|
522
|
+
assert.deepStrictEqual(actualOutput, expectedOutput)
|
|
524
523
|
})
|
|
525
524
|
})
|
|
526
525
|
})
|
|
@@ -1,7 +1,8 @@
|
|
|
1
|
+
import assert from "node:assert/strict"
|
|
1
2
|
import { PassThrough } from "node:stream"
|
|
2
|
-
import {
|
|
3
|
-
import { LspReader } from "./LspReader.js"
|
|
3
|
+
import { before as beforeAll, describe, it } from "node:test"
|
|
4
4
|
import { parseErrorCode, parseHeaderErrorMessage, parseJsonErrorMessage } from "./constants.js"
|
|
5
|
+
import { LspReader } from "./LspReader.js"
|
|
5
6
|
|
|
6
7
|
describe("LspReader", () => {
|
|
7
8
|
describe("simple case", () => {
|
|
@@ -26,7 +27,7 @@ describe("LspReader", () => {
|
|
|
26
27
|
})
|
|
27
28
|
|
|
28
29
|
it("should parse the incoming data and emit the json rpc message object", () => {
|
|
29
|
-
|
|
30
|
+
assert.deepStrictEqual(actualMessageObj, expectedMessageObj)
|
|
30
31
|
})
|
|
31
32
|
})
|
|
32
33
|
|
|
@@ -51,7 +52,7 @@ describe("LspReader", () => {
|
|
|
51
52
|
})
|
|
52
53
|
|
|
53
54
|
it("should parse the incoming data and emit the json rpc message object", () => {
|
|
54
|
-
|
|
55
|
+
assert.deepStrictEqual(actualMessageObj, expectedMessageObj)
|
|
55
56
|
})
|
|
56
57
|
})
|
|
57
58
|
})
|
|
@@ -77,11 +78,11 @@ describe("LspReader", () => {
|
|
|
77
78
|
})
|
|
78
79
|
|
|
79
80
|
it("should emit an 'parse-error' event with the parse header error message", () => {
|
|
80
|
-
|
|
81
|
+
assert.deepStrictEqual(actualError, expectedError)
|
|
81
82
|
})
|
|
82
83
|
|
|
83
84
|
it("should not emit any objects", () => {
|
|
84
|
-
|
|
85
|
+
assert.strictEqual(actualMessageObj, null)
|
|
85
86
|
})
|
|
86
87
|
})
|
|
87
88
|
|
|
@@ -97,8 +98,8 @@ describe("LspReader", () => {
|
|
|
97
98
|
method: "test/test-method",
|
|
98
99
|
params: { b: "2" },
|
|
99
100
|
}
|
|
100
|
-
|
|
101
|
-
|
|
101
|
+
const actualMessageObjs = []
|
|
102
|
+
const actualErrors = []
|
|
102
103
|
|
|
103
104
|
beforeAll(() => {
|
|
104
105
|
const inputStream = new PassThrough()
|
|
@@ -116,13 +117,13 @@ describe("LspReader", () => {
|
|
|
116
117
|
})
|
|
117
118
|
|
|
118
119
|
it("should emit only 1 'parse-error' event with the parse header error message", () => {
|
|
119
|
-
|
|
120
|
-
|
|
120
|
+
assert.strictEqual(actualErrors.length, 1)
|
|
121
|
+
assert.deepStrictEqual(actualErrors[0], expectedError)
|
|
121
122
|
})
|
|
122
123
|
|
|
123
124
|
it("should not emit one object from the message with the valid header", () => {
|
|
124
|
-
|
|
125
|
-
|
|
125
|
+
assert.strictEqual(actualMessageObjs.length, 1)
|
|
126
|
+
assert.deepStrictEqual(actualMessageObjs[0], expectedObject)
|
|
126
127
|
})
|
|
127
128
|
})
|
|
128
129
|
|
|
@@ -138,8 +139,8 @@ describe("LspReader", () => {
|
|
|
138
139
|
method: "test/test-method",
|
|
139
140
|
params: { b: "2" },
|
|
140
141
|
}
|
|
141
|
-
|
|
142
|
-
|
|
142
|
+
const actualMessageObjs = []
|
|
143
|
+
const actualErrors = []
|
|
143
144
|
|
|
144
145
|
beforeAll(() => {
|
|
145
146
|
const inputStream = new PassThrough()
|
|
@@ -157,13 +158,13 @@ describe("LspReader", () => {
|
|
|
157
158
|
})
|
|
158
159
|
|
|
159
160
|
it("should emit only 1 'parse-error' event with the parse header error message", () => {
|
|
160
|
-
|
|
161
|
-
|
|
161
|
+
assert.strictEqual(actualErrors.length, 1)
|
|
162
|
+
assert.deepStrictEqual(actualErrors[0], expectedError)
|
|
162
163
|
})
|
|
163
164
|
|
|
164
165
|
it("should not emit one object from the message with the valid header", () => {
|
|
165
|
-
|
|
166
|
-
|
|
166
|
+
assert.strictEqual(actualMessageObjs.length, 1)
|
|
167
|
+
assert.deepStrictEqual(actualMessageObjs[0], expectedObject)
|
|
167
168
|
})
|
|
168
169
|
})
|
|
169
170
|
|
|
@@ -187,11 +188,11 @@ describe("LspReader", () => {
|
|
|
187
188
|
})
|
|
188
189
|
|
|
189
190
|
it("should emit an 'parse-error' event with the parse JSON error message", () => {
|
|
190
|
-
|
|
191
|
+
assert.deepStrictEqual(actualError, expectedError)
|
|
191
192
|
})
|
|
192
193
|
|
|
193
194
|
it("should not emit any objects", () => {
|
|
194
|
-
|
|
195
|
+
assert.strictEqual(actualMessageObj, null)
|
|
195
196
|
})
|
|
196
197
|
})
|
|
197
198
|
})
|
|
@@ -228,11 +229,11 @@ describe("LspReader", () => {
|
|
|
228
229
|
})
|
|
229
230
|
|
|
230
231
|
it("should not emit an error", () => {
|
|
231
|
-
|
|
232
|
+
assert.strictEqual(actualError, null)
|
|
232
233
|
})
|
|
233
234
|
|
|
234
235
|
it("should buffer the data until it can parse the incoming data and emit the json rpc message object", () => {
|
|
235
|
-
|
|
236
|
+
assert.deepStrictEqual(actualMessageObj, expectedMessageObj)
|
|
236
237
|
})
|
|
237
238
|
})
|
|
238
239
|
|
|
@@ -274,11 +275,11 @@ describe("LspReader", () => {
|
|
|
274
275
|
})
|
|
275
276
|
|
|
276
277
|
it("should not emit an error", () => {
|
|
277
|
-
|
|
278
|
+
assert.strictEqual(actualError, null)
|
|
278
279
|
})
|
|
279
280
|
|
|
280
281
|
it("should buffer the data until it can parse the incoming data and emit the json rpc message object", () => {
|
|
281
|
-
|
|
282
|
+
assert.deepStrictEqual(actualMessageObj, expectedMessageObj)
|
|
282
283
|
})
|
|
283
284
|
})
|
|
284
285
|
|
|
@@ -313,11 +314,11 @@ describe("LspReader", () => {
|
|
|
313
314
|
})
|
|
314
315
|
|
|
315
316
|
it("should not emit an error", () => {
|
|
316
|
-
|
|
317
|
+
assert.strictEqual(actualError, null)
|
|
317
318
|
})
|
|
318
319
|
|
|
319
320
|
it("should buffer the data until it can parse the incoming data and emit the json rpc message object", () => {
|
|
320
|
-
|
|
321
|
+
assert.deepStrictEqual(actualMessageObj, expectedMessageObj)
|
|
321
322
|
})
|
|
322
323
|
})
|
|
323
324
|
|
|
@@ -362,11 +363,11 @@ describe("LspReader", () => {
|
|
|
362
363
|
})
|
|
363
364
|
|
|
364
365
|
it("should not emit an error", () => {
|
|
365
|
-
|
|
366
|
+
assert.strictEqual(actualError, null)
|
|
366
367
|
})
|
|
367
368
|
|
|
368
369
|
it("should buffer the data until it can parse the incoming data and emit the json rpc message object", () => {
|
|
369
|
-
|
|
370
|
+
assert.deepStrictEqual(actualMessageObj, expectedMessageObj)
|
|
370
371
|
})
|
|
371
372
|
})
|
|
372
373
|
})
|
|
@@ -396,19 +397,19 @@ describe("LspReader", () => {
|
|
|
396
397
|
})
|
|
397
398
|
|
|
398
399
|
it("should construct the lspReader with the passed in initialBufferSize", () => {
|
|
399
|
-
|
|
400
|
+
assert.strictEqual(actualInitialBufferSize, 10)
|
|
400
401
|
})
|
|
401
402
|
|
|
402
403
|
it("should need to trigger a resize", () => {
|
|
403
|
-
|
|
404
|
+
assert.strictEqual(inputData.length > actualInitialBufferSize, true)
|
|
404
405
|
})
|
|
405
406
|
|
|
406
407
|
it("should increase the buffer to a size larger than the message chunk", () => {
|
|
407
|
-
|
|
408
|
+
assert.strictEqual(lspReader.buffer.length > inputData.length, true)
|
|
408
409
|
})
|
|
409
410
|
|
|
410
411
|
it("should parse the incoming data and emit the json rpc message object", () => {
|
|
411
|
-
|
|
412
|
+
assert.deepStrictEqual(actualMessageObj, expectedMessageObj)
|
|
412
413
|
})
|
|
413
414
|
})
|
|
414
415
|
|
|
@@ -446,24 +447,24 @@ describe("LspReader", () => {
|
|
|
446
447
|
})
|
|
447
448
|
|
|
448
449
|
it("should not emit an error", () => {
|
|
449
|
-
|
|
450
|
+
assert.strictEqual(actualError, null)
|
|
450
451
|
})
|
|
451
452
|
|
|
452
453
|
it("should construct the lspReader with the passed in initialBufferSize", () => {
|
|
453
|
-
|
|
454
|
+
assert.strictEqual(actualInitialBufferSize, 70)
|
|
454
455
|
})
|
|
455
456
|
|
|
456
457
|
it("should need to trigger a resize after the first buffered message", () => {
|
|
457
|
-
|
|
458
|
-
|
|
458
|
+
assert.strictEqual(inputData[0].length < actualInitialBufferSize, true)
|
|
459
|
+
assert.strictEqual(inputData[1].length > actualInitialBufferSize, true)
|
|
459
460
|
})
|
|
460
461
|
|
|
461
462
|
it("should increase the buffer to a size larger than the combined message chunks", () => {
|
|
462
|
-
|
|
463
|
+
assert.strictEqual(lspReader.buffer.length > inputData[0].length + inputData[1].length, true)
|
|
463
464
|
})
|
|
464
465
|
|
|
465
466
|
it("should buffer the data until it can parse the incoming data and emit the json rpc message object", () => {
|
|
466
|
-
|
|
467
|
+
assert.deepStrictEqual(actualMessageObj, expectedMessageObj)
|
|
467
468
|
})
|
|
468
469
|
})
|
|
469
470
|
})
|
|
@@ -480,7 +481,7 @@ describe("LspReader", () => {
|
|
|
480
481
|
{ jsonrpc: "2.0", id: "1", method: "test/test-method", params: { b: "2" } },
|
|
481
482
|
{ jsonrpc: "2.0", id: "2", method: "test/test-method", params: { c: "3" } },
|
|
482
483
|
]
|
|
483
|
-
|
|
484
|
+
const actualMessageObjs = []
|
|
484
485
|
let actualError = null
|
|
485
486
|
|
|
486
487
|
beforeAll(() => {
|
|
@@ -500,11 +501,11 @@ describe("LspReader", () => {
|
|
|
500
501
|
})
|
|
501
502
|
|
|
502
503
|
it("should not emit an error", () => {
|
|
503
|
-
|
|
504
|
+
assert.strictEqual(actualError, null)
|
|
504
505
|
})
|
|
505
506
|
|
|
506
507
|
it("should emit each message in the order it was received", () => {
|
|
507
|
-
|
|
508
|
+
assert.deepStrictEqual(actualMessageObjs, expectedMessageObjs)
|
|
508
509
|
})
|
|
509
510
|
})
|
|
510
511
|
|
|
@@ -521,7 +522,7 @@ describe("LspReader", () => {
|
|
|
521
522
|
{ jsonrpc: "2.0", id: "1", method: "test/test-method", params: { b: "2" } },
|
|
522
523
|
{ jsonrpc: "2.0", id: "2", method: "test/test-method", params: { c: "3" } },
|
|
523
524
|
]
|
|
524
|
-
|
|
525
|
+
const actualMessageObjs = []
|
|
525
526
|
let actualError = null
|
|
526
527
|
|
|
527
528
|
beforeAll(() => {
|
|
@@ -539,11 +540,11 @@ describe("LspReader", () => {
|
|
|
539
540
|
})
|
|
540
541
|
|
|
541
542
|
it("should not emit an error", () => {
|
|
542
|
-
|
|
543
|
+
assert.strictEqual(actualError, null)
|
|
543
544
|
})
|
|
544
545
|
|
|
545
546
|
it("should emit each message in the order it was received", () => {
|
|
546
|
-
|
|
547
|
+
assert.deepStrictEqual(actualMessageObjs, expectedMessageObjs)
|
|
547
548
|
})
|
|
548
549
|
})
|
|
549
550
|
|
|
@@ -559,7 +560,7 @@ describe("LspReader", () => {
|
|
|
559
560
|
{ jsonrpc: "2.0", id: "1", method: "test/test-method", params: { b: "2" } },
|
|
560
561
|
{ jsonrpc: "2.0", id: "2", method: "test/test-method", params: { c: "3" } },
|
|
561
562
|
]
|
|
562
|
-
|
|
563
|
+
const actualMessageObjs = []
|
|
563
564
|
let actualError = null
|
|
564
565
|
|
|
565
566
|
beforeAll(() => {
|
|
@@ -579,11 +580,11 @@ describe("LspReader", () => {
|
|
|
579
580
|
})
|
|
580
581
|
|
|
581
582
|
it("should not emit an error", () => {
|
|
582
|
-
|
|
583
|
+
assert.strictEqual(actualError, null)
|
|
583
584
|
})
|
|
584
585
|
|
|
585
586
|
it("should emit each message in the order it was received", () => {
|
|
586
|
-
|
|
587
|
+
assert.deepStrictEqual(actualMessageObjs, expectedMessageObjs)
|
|
587
588
|
})
|
|
588
589
|
})
|
|
589
590
|
})
|
|
@@ -1,8 +1,9 @@
|
|
|
1
|
+
import assert from "node:assert/strict"
|
|
1
2
|
import { Writable } from "node:stream"
|
|
2
|
-
import {
|
|
3
|
+
import { before as beforeAll, describe, it } from "node:test"
|
|
3
4
|
import {
|
|
4
|
-
TESTONLY_resetRequestId,
|
|
5
5
|
createHeader,
|
|
6
|
+
TESTONLY_resetRequestId,
|
|
6
7
|
writeNotification,
|
|
7
8
|
writeRequest,
|
|
8
9
|
writeResponse,
|
|
@@ -17,7 +18,7 @@ describe("LspWriter", () => {
|
|
|
17
18
|
|
|
18
19
|
it("Should create header with correct length", () => {
|
|
19
20
|
const actual = createHeader(JSON.stringify(messageObj))
|
|
20
|
-
|
|
21
|
+
assert.deepStrictEqual(actual, expectedHeader)
|
|
21
22
|
})
|
|
22
23
|
})
|
|
23
24
|
|
|
@@ -27,7 +28,7 @@ describe("LspWriter", () => {
|
|
|
27
28
|
|
|
28
29
|
it("Should create header with correct length", () => {
|
|
29
30
|
const actual = createHeader(JSON.stringify(messageObj))
|
|
30
|
-
|
|
31
|
+
assert.deepStrictEqual(actual, expectedHeader)
|
|
31
32
|
})
|
|
32
33
|
})
|
|
33
34
|
|
|
@@ -37,7 +38,7 @@ describe("LspWriter", () => {
|
|
|
37
38
|
|
|
38
39
|
it("Should create header with correct byte length, not string length", () => {
|
|
39
40
|
const actual = createHeader(JSON.stringify(messageObj))
|
|
40
|
-
|
|
41
|
+
assert.deepStrictEqual(actual, expectedHeader)
|
|
41
42
|
})
|
|
42
43
|
})
|
|
43
44
|
})
|
|
@@ -59,7 +60,7 @@ describe("LspWriter", () => {
|
|
|
59
60
|
})
|
|
60
61
|
|
|
61
62
|
it("should stringify the json and add a Content-Length header, then write the head and json to the output stream", () => {
|
|
62
|
-
|
|
63
|
+
assert.deepEqual(actualOutput, expectedOutput)
|
|
63
64
|
})
|
|
64
65
|
})
|
|
65
66
|
})
|
|
@@ -82,7 +83,7 @@ describe("LspWriter", () => {
|
|
|
82
83
|
})
|
|
83
84
|
|
|
84
85
|
it("should create a response object with a result property (and no error) and write it to the output stream", () => {
|
|
85
|
-
|
|
86
|
+
assert.deepEqual(actualOutput, expectedOutput)
|
|
86
87
|
})
|
|
87
88
|
})
|
|
88
89
|
|
|
@@ -103,7 +104,7 @@ describe("LspWriter", () => {
|
|
|
103
104
|
})
|
|
104
105
|
|
|
105
106
|
it("should create a response object with an error property (and no result) and write it to the output stream", () => {
|
|
106
|
-
|
|
107
|
+
assert.deepEqual(actualOutput, expectedOutput)
|
|
107
108
|
})
|
|
108
109
|
})
|
|
109
110
|
})
|
|
@@ -126,7 +127,7 @@ describe("LspWriter", () => {
|
|
|
126
127
|
})
|
|
127
128
|
|
|
128
129
|
it("should write a notification message without an ID property on the output stream", () => {
|
|
129
|
-
|
|
130
|
+
assert.deepEqual(actualOutput, expectedOutput)
|
|
130
131
|
})
|
|
131
132
|
})
|
|
132
133
|
})
|
|
@@ -150,7 +151,7 @@ describe("LspWriter", () => {
|
|
|
150
151
|
})
|
|
151
152
|
|
|
152
153
|
it("should write a request message with an ID property on the output stream", () => {
|
|
153
|
-
|
|
154
|
+
assert.deepEqual(actualOutput, expectedOutput)
|
|
154
155
|
})
|
|
155
156
|
})
|
|
156
157
|
|
|
@@ -179,7 +180,7 @@ describe("LspWriter", () => {
|
|
|
179
180
|
})
|
|
180
181
|
|
|
181
182
|
it("should write multiple request messages with increasing IDs", () => {
|
|
182
|
-
|
|
183
|
+
assert.deepEqual(actualOutput, expectedOutput)
|
|
183
184
|
})
|
|
184
185
|
})
|
|
185
186
|
})
|
package/src/ui/index.html
CHANGED
|
@@ -1,41 +1,44 @@
|
|
|
1
1
|
<!doctype html>
|
|
2
2
|
<html lang="en">
|
|
3
|
-
<head>
|
|
4
|
-
<meta charset="utf-8" />
|
|
5
|
-
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
|
6
3
|
|
|
7
|
-
|
|
4
|
+
<head>
|
|
5
|
+
<meta charset="utf-8" />
|
|
6
|
+
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
|
8
7
|
|
|
9
|
-
|
|
10
|
-
<link rel="stylesheet" href="css/fonts.css" />
|
|
11
|
-
<style id="main_style"></style>
|
|
12
|
-
<script type="module" src="js/setup.js" defer></script>
|
|
8
|
+
<title>WTR Status</title>
|
|
13
9
|
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
}
|
|
10
|
+
<link rel="icon" type="image/png" href="favicon.png" />
|
|
11
|
+
<link rel="stylesheet" href="css/fonts.css" />
|
|
12
|
+
<style id="main_style"></style>
|
|
13
|
+
<script type="module" src="js/setup.js" defer></script>
|
|
19
14
|
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
15
|
+
<style>
|
|
16
|
+
html {
|
|
17
|
+
height: 100dvh;
|
|
18
|
+
overscroll-behavior: none;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
#svg_root {
|
|
22
|
+
position: absolute;
|
|
23
|
+
top: 0;
|
|
24
|
+
left: 0;
|
|
25
|
+
height: 100dvh;
|
|
26
|
+
width: 100dvw;
|
|
27
|
+
}
|
|
28
|
+
</style>
|
|
29
|
+
</head>
|
|
30
|
+
|
|
31
|
+
<body class="base_colors color_theme">
|
|
32
|
+
<svg id="svg_root" viewBox="-1 -1 2 2" xmlns="http://www.w3.org/2000/svg">
|
|
33
|
+
<title>Main Svg Canvas</title>
|
|
34
|
+
<g id="headers_group"></g>
|
|
35
|
+
<g id="editor_wedges_group" class="wedge_group"></g>
|
|
36
|
+
<g id="client_wedges_group" class="wedge_group"></g>
|
|
37
|
+
<g id="activity_time_series_group"></g>
|
|
38
|
+
<g id="activity_labels_group"></g>
|
|
39
|
+
<g id="status_ring_group"></g>
|
|
40
|
+
<g id="footer_status_group"></g>
|
|
41
|
+
</svg>
|
|
42
|
+
</body>
|
|
29
43
|
|
|
30
|
-
<body class="base_colors color_theme">
|
|
31
|
-
<svg id="svg_root" viewBox="-1 -1 2 2" xmlns="http://www.w3.org/2000/svg">
|
|
32
|
-
<g id="headers_group"></g>
|
|
33
|
-
<g id="editor_wedges_group" class="wedge_group"></g>
|
|
34
|
-
<g id="client_wedges_group" class="wedge_group"></g>
|
|
35
|
-
<g id="activity_time_series_group"></g>
|
|
36
|
-
<g id="activity_labels_group"></g>
|
|
37
|
-
<g id="status_ring_group"></g>
|
|
38
|
-
<g id="footer_status_group"></g>
|
|
39
|
-
</svg>
|
|
40
|
-
</body>
|
|
41
44
|
</html>
|
|
@@ -14,7 +14,7 @@ const currentStatus = {
|
|
|
14
14
|
}
|
|
15
15
|
|
|
16
16
|
const wtrStatusEmitter = new EventEmitter()
|
|
17
|
-
wtrStatusEmitter.on =
|
|
17
|
+
wtrStatusEmitter.on = (event, handler) => {
|
|
18
18
|
EventEmitter.prototype.on.call(wtrStatusEmitter, event, handler)
|
|
19
19
|
// automatically push the data to the event handler when it initially subscribes
|
|
20
20
|
if (event === "data") {
|
|
@@ -2,6 +2,7 @@ const allCleanupFunctions = new Map()
|
|
|
2
2
|
|
|
3
3
|
export const eventSubscriber = (key) => {
|
|
4
4
|
const previousCleanupFunctions = allCleanupFunctions.get(key)
|
|
5
|
+
// biome-ignore lint/suspicious/useIterableCallbackReturn: Keep the function a 1 liner
|
|
5
6
|
previousCleanupFunctions?.forEach((f) => f())
|
|
6
7
|
|
|
7
8
|
const cleanupFunctions = []
|
package/src/ui/js/setup.js
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { getEvalOnChangeFiles, clearEvalOnChangeFiles } from "./setup/evalOnChange.js" // initialize dependencies on the global __WTR__ object
|
|
1
|
+
import { emitActivity } from "./data/wtrActivity.js"
|
|
3
2
|
import { setIsOnline, setSessions } from "./data/wtrStatus.js"
|
|
3
|
+
import { clearEvalOnChangeFiles, getEvalOnChangeFiles } from "./setup/evalOnChange.js" // initialize dependencies on the global __WTR__ object
|
|
4
4
|
import { eventSubscriber } from "./setup/eventSubscriber.js" // make sure the eventSubscriber function is available on the __WTR__ object
|
|
5
|
-
import {
|
|
5
|
+
import { WebsocketClient } from "./setup/WebsocketClient.js"
|
|
6
6
|
|
|
7
7
|
const searchParams = new URLSearchParams(window.location.search)
|
|
8
8
|
|
|
@@ -39,6 +39,7 @@ const handleJs = (contents, jsEndsWith) => {
|
|
|
39
39
|
// register and clean up event handlers on a per file basis
|
|
40
40
|
window.__WTR__.onEvent = eventSubscriber(jsEndsWith)
|
|
41
41
|
try {
|
|
42
|
+
// biome-ignore lint/security/noGlobalEval: Live updates requires eval
|
|
42
43
|
eval(contents)
|
|
43
44
|
} catch (e) {
|
|
44
45
|
window._lastEvalError = e
|
|
@@ -1,8 +1,8 @@
|
|
|
1
|
+
import { EventEmitter } from "node:events"
|
|
1
2
|
import { WebsocketClient } from "./WebsocketClient.js"
|
|
2
3
|
import { WtrSession } from "./WtrSession.js"
|
|
3
4
|
import { apiMethods } from "./websocketApi.js"
|
|
4
5
|
import { createWebsocketServer } from "./websocketServer.js"
|
|
5
|
-
import { EventEmitter } from "node:events"
|
|
6
6
|
|
|
7
7
|
const watchActiveFilesMessage = { method: "watch-editor-active-files" }
|
|
8
8
|
|
|
@@ -81,7 +81,7 @@ export class WebsocketInterface {
|
|
|
81
81
|
_sendMessageToServer(message) {
|
|
82
82
|
if (this.serverSession) {
|
|
83
83
|
this.serverSession._handleApiMessage(message)
|
|
84
|
-
} else if (this.wsClient
|
|
84
|
+
} else if (this.wsClient?.socketOpen) {
|
|
85
85
|
this.wsClient.sendMessage(message)
|
|
86
86
|
}
|
|
87
87
|
}
|
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
import { EventEmitter } from "node:events"
|
|
2
|
-
import { getNextId } from "./util.js"
|
|
3
2
|
import {
|
|
4
|
-
startSessionStatus,
|
|
5
3
|
endSessionStatus,
|
|
6
|
-
statusEvents,
|
|
7
4
|
removeWatchedFileLinks,
|
|
5
|
+
startSessionStatus,
|
|
6
|
+
statusEvents,
|
|
8
7
|
} from "./sessionManager.js"
|
|
8
|
+
import { getNextId } from "./util.js"
|
|
9
9
|
|
|
10
10
|
export class WtrSession {
|
|
11
11
|
constructor({ apiMethods, wsConnection, wsInterfaceEmitter }) {
|
|
@@ -118,7 +118,7 @@ export class WtrSession {
|
|
|
118
118
|
}
|
|
119
119
|
|
|
120
120
|
_handleApiMessage(message) {
|
|
121
|
-
const method = message
|
|
121
|
+
const method = message?.method
|
|
122
122
|
const methodHandler = this.apiMethods.get(method)
|
|
123
123
|
if (!methodHandler) {
|
|
124
124
|
this.emitter.emit("log", { level: "error", text: `unknown ws api method: ${method}` })
|
|
@@ -1,9 +1,10 @@
|
|
|
1
|
-
import { createServer } from "node:http"
|
|
2
|
-
import path from "node:path"
|
|
3
1
|
import { createReadStream } from "node:fs"
|
|
4
2
|
import fs from "node:fs/promises"
|
|
3
|
+
import { createServer } from "node:http"
|
|
4
|
+
import path from "node:path"
|
|
5
5
|
import * as url from "node:url"
|
|
6
6
|
import { isValidOrigin } from "./util.js"
|
|
7
|
+
|
|
7
8
|
const parentDir = url.fileURLToPath(new URL("..", import.meta.url))
|
|
8
9
|
|
|
9
10
|
const uiDirName = "ui"
|
|
@@ -19,7 +20,7 @@ const allowedFileTypes = new Map([
|
|
|
19
20
|
])
|
|
20
21
|
|
|
21
22
|
const getFilePath = (url) => {
|
|
22
|
-
url = url === "/" ? "./index.html" :
|
|
23
|
+
url = url === "/" ? "./index.html" : `.${url}`
|
|
23
24
|
return path.join(uiDirPath, url)
|
|
24
25
|
}
|
|
25
26
|
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
import {
|
|
2
|
-
|
|
3
|
-
statusEvents,
|
|
2
|
+
addOpenedFileLinks,
|
|
4
3
|
addWatchedFileLinks,
|
|
5
|
-
removeWatchedFileLinks,
|
|
6
4
|
removeOpenedFileLinks,
|
|
7
|
-
|
|
5
|
+
removeWatchedFileLinks,
|
|
6
|
+
statusEvents,
|
|
7
|
+
triggerStatusUpdate,
|
|
8
8
|
} from "./sessionManager.js"
|
|
9
9
|
|
|
10
10
|
export const apiMethods = new Map([
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import { WebSocketServer } from "ws"
|
|
2
2
|
import { createHttpServer } from "./httpServer.js"
|
|
3
|
-
import { apiMethods } from "./websocketApi.js"
|
|
4
|
-
import { WtrSession } from "./WtrSession.js"
|
|
5
3
|
import { isValidOrigin } from "./util.js"
|
|
4
|
+
import { WtrSession } from "./WtrSession.js"
|
|
5
|
+
import { apiMethods } from "./websocketApi.js"
|
|
6
6
|
|
|
7
7
|
export const createWebsocketServer = async ({ port, allowedHosts, allowNetworkAccess }) => {
|
|
8
8
|
const httpServer = await createHttpServer({ port, allowedHosts, allowNetworkAccess }) // promise will reject if can't start HTTP server on specified port
|
package/.prettierignore
DELETED
package/.prettierrc
DELETED
package/eslint.config.js
DELETED
|
@@ -1,32 +0,0 @@
|
|
|
1
|
-
import js from "@eslint/js"
|
|
2
|
-
import globals from "globals"
|
|
3
|
-
import { defineConfig } from "eslint/config"
|
|
4
|
-
|
|
5
|
-
const wtrGlobals = {
|
|
6
|
-
__WTR__: "readonly",
|
|
7
|
-
}
|
|
8
|
-
|
|
9
|
-
export default defineConfig([
|
|
10
|
-
{
|
|
11
|
-
files: ["**/*.{js,mjs,cjs}"],
|
|
12
|
-
plugins: { js },
|
|
13
|
-
extends: ["js/recommended"],
|
|
14
|
-
languageOptions: { globals: { ...globals.node, ...globals.browser, ...wtrGlobals } },
|
|
15
|
-
},
|
|
16
|
-
{
|
|
17
|
-
rules: {
|
|
18
|
-
semi: ["error", "never"],
|
|
19
|
-
indent: ["error", 2],
|
|
20
|
-
"no-multiple-empty-lines": ["error", { max: 1 }],
|
|
21
|
-
"no-unused-vars": 1,
|
|
22
|
-
"no-return-assign": 0,
|
|
23
|
-
"multiline-ternary": 0,
|
|
24
|
-
"object-curly-spacing": 0,
|
|
25
|
-
"object-property-newline": 0,
|
|
26
|
-
"object-curly-newline": 0,
|
|
27
|
-
quotes: 0,
|
|
28
|
-
"quote-props": 0,
|
|
29
|
-
"import/no-absolute-path": 0,
|
|
30
|
-
},
|
|
31
|
-
},
|
|
32
|
-
])
|