@honeybbq/teamspeak 1.0.0-beta.12 → 1.0.0-beta.13

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 (139) hide show
  1. package/README.md +40 -5
  2. package/dist/client/capabilities.d.ts +4 -4
  3. package/dist/client/capabilities.d.ts.map +1 -1
  4. package/dist/client/capabilities.js +3 -8
  5. package/dist/client/capabilities.js.map +1 -1
  6. package/dist/client/client.d.ts.map +1 -1
  7. package/dist/client/client.js +50 -9
  8. package/dist/client/client.js.map +1 -1
  9. package/dist/client/crypto/identity.d.ts +2 -0
  10. package/dist/client/crypto/identity.d.ts.map +1 -1
  11. package/dist/client/crypto/identity.js +2 -2
  12. package/dist/client/crypto/identity.js.map +1 -1
  13. package/dist/client/crypto/index.d.ts +1 -1
  14. package/dist/client/crypto/index.d.ts.map +1 -1
  15. package/dist/client/crypto/index.js +1 -1
  16. package/dist/client/crypto/index.js.map +1 -1
  17. package/dist/client/index.d.ts +1 -1
  18. package/dist/client/index.d.ts.map +1 -1
  19. package/dist/client/index.js +1 -1
  20. package/dist/client/index.js.map +1 -1
  21. package/dist/client/trace.d.ts +7 -0
  22. package/dist/client/trace.d.ts.map +1 -1
  23. package/dist/client/transport/handler.d.ts +2 -0
  24. package/dist/client/transport/handler.d.ts.map +1 -1
  25. package/dist/client/transport/handler.js +4 -0
  26. package/dist/client/transport/handler.js.map +1 -1
  27. package/dist/client/types.d.ts +9 -2
  28. package/dist/client/types.d.ts.map +1 -1
  29. package/dist/client/types.js +2 -0
  30. package/dist/client/types.js.map +1 -1
  31. package/dist/client/view.d.ts +3 -3
  32. package/dist/client/view.d.ts.map +1 -1
  33. package/dist/client/view.js.map +1 -1
  34. package/dist/core/api/channels.d.ts +7 -3
  35. package/dist/core/api/channels.d.ts.map +1 -1
  36. package/dist/core/api/channels.js +5 -3
  37. package/dist/core/api/channels.js.map +1 -1
  38. package/dist/core/api/clients.d.ts +38 -1
  39. package/dist/core/api/clients.d.ts.map +1 -1
  40. package/dist/core/api/clients.js +33 -2
  41. package/dist/core/api/clients.js.map +1 -1
  42. package/dist/core/api/command.d.ts +18 -1
  43. package/dist/core/api/command.d.ts.map +1 -1
  44. package/dist/core/api/command.js +7 -1
  45. package/dist/core/api/command.js.map +1 -1
  46. package/dist/core/api/instance.d.ts +10 -2
  47. package/dist/core/api/instance.d.ts.map +1 -1
  48. package/dist/core/api/instance.js +6 -2
  49. package/dist/core/api/instance.js.map +1 -1
  50. package/dist/core/api/moderation.d.ts +7 -0
  51. package/dist/core/api/moderation.d.ts.map +1 -1
  52. package/dist/core/api/moderation.js +7 -0
  53. package/dist/core/api/moderation.js.map +1 -1
  54. package/dist/core/api/parse.d.ts.map +1 -1
  55. package/dist/core/api/parse.js +1 -0
  56. package/dist/core/api/parse.js.map +1 -1
  57. package/dist/core/api/server.d.ts +9 -0
  58. package/dist/core/api/server.d.ts.map +1 -1
  59. package/dist/core/api/server.js +3 -0
  60. package/dist/core/api/server.js.map +1 -1
  61. package/dist/core/command/responses.d.ts.map +1 -1
  62. package/dist/core/command/responses.js +1 -0
  63. package/dist/core/command/responses.js.map +1 -1
  64. package/dist/core/events.d.ts +47 -5
  65. package/dist/core/events.d.ts.map +1 -1
  66. package/dist/core/index.d.ts +2 -2
  67. package/dist/core/index.d.ts.map +1 -1
  68. package/dist/core/index.js +1 -1
  69. package/dist/core/index.js.map +1 -1
  70. package/dist/core/notification-name.d.ts +4 -0
  71. package/dist/core/notification-name.d.ts.map +1 -1
  72. package/dist/core/notification-name.js +4 -0
  73. package/dist/core/notification-name.js.map +1 -1
  74. package/dist/core/notifications.d.ts +6 -2
  75. package/dist/core/notifications.d.ts.map +1 -1
  76. package/dist/core/notifications.js +32 -1
  77. package/dist/core/notifications.js.map +1 -1
  78. package/dist/core/types.d.ts +7 -0
  79. package/dist/core/types.d.ts.map +1 -1
  80. package/dist/core/types.js +16 -0
  81. package/dist/core/types.js.map +1 -1
  82. package/dist/query/client.d.ts +12 -3
  83. package/dist/query/client.d.ts.map +1 -1
  84. package/dist/query/client.js +22 -15
  85. package/dist/query/client.js.map +1 -1
  86. package/dist/query/index.d.ts +1 -1
  87. package/dist/query/index.d.ts.map +1 -1
  88. package/dist/query/options.d.ts +17 -5
  89. package/dist/query/options.d.ts.map +1 -1
  90. package/dist/query/options.js +1 -0
  91. package/dist/query/options.js.map +1 -1
  92. package/dist/query/ssh.d.ts.map +1 -1
  93. package/dist/query/ssh.js +4 -1
  94. package/dist/query/ssh.js.map +1 -1
  95. package/dist/query/stream.d.ts +8 -3
  96. package/dist/query/stream.d.ts.map +1 -1
  97. package/dist/query/stream.js +26 -3
  98. package/dist/query/stream.js.map +1 -1
  99. package/dist/query/tcp.js +1 -1
  100. package/dist/query/tcp.js.map +1 -1
  101. package/dist/query/transport.d.ts +35 -0
  102. package/dist/query/transport.d.ts.map +1 -1
  103. package/dist/query/web.d.ts +17 -5
  104. package/dist/query/web.d.ts.map +1 -1
  105. package/dist/query/web.js +38 -9
  106. package/dist/query/web.js.map +1 -1
  107. package/package.json +6 -5
  108. package/src/client/capabilities.ts +14 -11
  109. package/src/client/client.ts +47 -6
  110. package/src/client/crypto/identity.ts +2 -2
  111. package/src/client/crypto/index.ts +1 -0
  112. package/src/client/index.ts +2 -0
  113. package/src/client/trace.ts +7 -0
  114. package/src/client/transport/handler.ts +5 -0
  115. package/src/client/types.ts +9 -0
  116. package/src/client/view.ts +2 -3
  117. package/src/core/api/channels.ts +9 -3
  118. package/src/core/api/clients.ts +73 -2
  119. package/src/core/api/command.ts +22 -1
  120. package/src/core/api/instance.ts +20 -2
  121. package/src/core/api/moderation.ts +7 -0
  122. package/src/core/api/parse.ts +1 -0
  123. package/src/core/api/server.ts +12 -0
  124. package/src/core/command/responses.ts +1 -0
  125. package/src/core/events.ts +48 -5
  126. package/src/core/index.ts +2 -1
  127. package/src/core/notification-name.ts +4 -0
  128. package/src/core/notifications.ts +48 -17
  129. package/src/core/types.ts +14 -0
  130. package/src/query/client.ts +28 -15
  131. package/src/query/index.ts +1 -1
  132. package/src/query/options.ts +19 -5
  133. package/src/query/ssh.ts +6 -1
  134. package/src/query/stream.ts +31 -4
  135. package/src/query/tcp.ts +1 -1
  136. package/src/query/testing/live.ts +311 -0
  137. package/src/query/testing/ssh-keys.ts +67 -0
  138. package/src/query/transport.ts +36 -0
  139. package/src/query/web.ts +57 -14
@@ -1,4 +1,4 @@
1
- import type { QueryTransport } from "./transport.js";
1
+ import type { QueryTransport, QueryTransportStats } from "./transport.js";
2
2
  /**
3
3
  * The part of a duplex byte stream a line transport uses. A `node:net` socket
4
4
  * is one; so is an SSH shell channel, or a test double.
@@ -29,10 +29,15 @@ export declare class StreamTransport implements QueryTransport {
29
29
  onClose: ((error: Error | undefined) => void) | null;
30
30
  /**
31
31
  * `onEnd` runs once the stream is closed, to release what the stream sits
32
- * on: an SSH session's connection, say.
32
+ * on: an SSH session's connection, say. `identity` says which kind of
33
+ * connection this is and where it points, for {@link StreamTransport.stats}.
33
34
  */
34
- constructor(stream: QueryStream, onEnd?: () => void);
35
+ constructor(stream: QueryStream, onEnd?: () => void, identity?: {
36
+ readonly transport: "tcp" | "ssh";
37
+ readonly address: string;
38
+ });
35
39
  send(line: string): Promise<void>;
40
+ stats(): QueryTransportStats;
36
41
  /**
37
42
  * Say `quit`, give the server a moment to end the session, and close.
38
43
  *
@@ -1 +1 @@
1
- {"version":3,"file":"stream.d.ts","sourceRoot":"","sources":["../../src/query/stream.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,gBAAgB,CAAC;AAErD;;;GAGG;AACH,MAAM,WAAW,WAAW;IAC1B,+FAA+F;IAC/F,KAAK,CAAC,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,CAAC,KAAK,CAAC,EAAE,KAAK,GAAG,IAAI,KAAK,IAAI,GAAG,OAAO,CAAC;IACvE,wBAAwB;IACxB,GAAG,IAAI,OAAO,CAAC;IACf,sCAAsC;IACtC,EAAE,CAAC,KAAK,EAAE,MAAM,EAAE,QAAQ,EAAE,CAAC,KAAK,EAAE,UAAU,KAAK,IAAI,GAAG,OAAO,CAAC;IAClE,uDAAuD;IACvD,EAAE,CAAC,KAAK,EAAE,OAAO,EAAE,QAAQ,EAAE,CAAC,KAAK,EAAE,KAAK,KAAK,IAAI,GAAG,OAAO,CAAC;IAC9D,qCAAqC;IACrC,EAAE,CAAC,KAAK,EAAE,OAAO,EAAE,QAAQ,EAAE,MAAM,IAAI,GAAG,OAAO,CAAC;CACnD;AAKD;;;;;GAKG;AACH,qBAAa,eAAgB,YAAW,cAAc;;IACpD,+EAA+E;IAC/E,QAAQ,CAAC,qBAAqB,QAAQ;IACtC,MAAM,EAAE,CAAC,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAC,GAAG,IAAI,CAAQ;IAC/C,OAAO,EAAE,CAAC,CAAC,KAAK,EAAE,KAAK,GAAG,SAAS,KAAK,IAAI,CAAC,GAAG,IAAI,CAAQ;IAa5D;;;OAGG;IACH,YAAY,MAAM,EAAE,WAAW,EAAE,KAAK,CAAC,EAAE,MAAM,IAAI,EAQlD;IAED,IAAI,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAKhC;IAED;;;;;;;OAOG;IACG,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC,CA2B3B;CAmBF"}
1
+ {"version":3,"file":"stream.d.ts","sourceRoot":"","sources":["../../src/query/stream.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,cAAc,EAAE,mBAAmB,EAAE,MAAM,gBAAgB,CAAC;AAE1E;;;GAGG;AACH,MAAM,WAAW,WAAW;IAC1B,+FAA+F;IAC/F,KAAK,CAAC,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,CAAC,KAAK,CAAC,EAAE,KAAK,GAAG,IAAI,KAAK,IAAI,GAAG,OAAO,CAAC;IACvE,wBAAwB;IACxB,GAAG,IAAI,OAAO,CAAC;IACf,sCAAsC;IACtC,EAAE,CAAC,KAAK,EAAE,MAAM,EAAE,QAAQ,EAAE,CAAC,KAAK,EAAE,UAAU,KAAK,IAAI,GAAG,OAAO,CAAC;IAClE,uDAAuD;IACvD,EAAE,CAAC,KAAK,EAAE,OAAO,EAAE,QAAQ,EAAE,CAAC,KAAK,EAAE,KAAK,KAAK,IAAI,GAAG,OAAO,CAAC;IAC9D,qCAAqC;IACrC,EAAE,CAAC,KAAK,EAAE,OAAO,EAAE,QAAQ,EAAE,MAAM,IAAI,GAAG,OAAO,CAAC;CACnD;AAKD;;;;;GAKG;AACH,qBAAa,eAAgB,YAAW,cAAc;;IACpD,+EAA+E;IAC/E,QAAQ,CAAC,qBAAqB,QAAQ;IACtC,MAAM,EAAE,CAAC,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAC,GAAG,IAAI,CAAQ;IAC/C,OAAO,EAAE,CAAC,CAAC,KAAK,EAAE,KAAK,GAAG,SAAS,KAAK,IAAI,CAAC,GAAG,IAAI,CAAQ;IAiB5D;;;;OAIG;IACH,YACE,MAAM,EAAE,WAAW,EACnB,KAAK,CAAC,EAAE,MAAM,IAAI,EAClB,QAAQ,CAAC,EAAE;QAAE,QAAQ,CAAC,SAAS,EAAE,KAAK,GAAG,KAAK,CAAC;QAAC,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAA;KAAE,EAU3E;IAED,IAAI,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAWhC;IAED,KAAK,IAAI,mBAAmB,CAQ3B;IAED;;;;;;;OAOG;IACG,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC,CA2B3B;CAoBF"}
@@ -22,13 +22,19 @@ export class StreamTransport {
22
22
  /** Wakes a `close()` that is waiting for the server to end the session. */
23
23
  #onEnded;
24
24
  #error;
25
+ #identity;
26
+ #openedAt = new Date();
27
+ #bytesSent = 0;
28
+ #bytesReceived = 0;
25
29
  /**
26
30
  * `onEnd` runs once the stream is closed, to release what the stream sits
27
- * on: an SSH session's connection, say.
31
+ * on: an SSH session's connection, say. `identity` says which kind of
32
+ * connection this is and where it points, for {@link StreamTransport.stats}.
28
33
  */
29
- constructor(stream, onEnd) {
34
+ constructor(stream, onEnd, identity) {
30
35
  this.#stream = stream;
31
36
  this.#onEnd = onEnd;
37
+ this.#identity = identity;
32
38
  stream.on("data", (chunk) => this.#handleData(chunk));
33
39
  stream.on("error", (error) => {
34
40
  this.#error = error;
@@ -39,9 +45,25 @@ export class StreamTransport {
39
45
  if (this.#ended)
40
46
  return Promise.reject(new Error("the query connection is closed"));
41
47
  return new Promise((resolve, reject) => {
42
- this.#stream.write(`${line}\n`, (error) => (error ? reject(error) : resolve()));
48
+ this.#stream.write(`${line}\n`, (error) => {
49
+ if (error)
50
+ reject(error);
51
+ else {
52
+ this.#bytesSent += Buffer.byteLength(line) + 1;
53
+ resolve();
54
+ }
55
+ });
43
56
  });
44
57
  }
58
+ stats() {
59
+ return {
60
+ connectedAt: this.#openedAt,
61
+ transport: this.#identity?.transport,
62
+ address: this.#identity?.address ?? "",
63
+ bytesSent: this.#bytesSent,
64
+ bytesReceived: this.#bytesReceived,
65
+ };
66
+ }
45
67
  /**
46
68
  * Say `quit`, give the server a moment to end the session, and close.
47
69
  *
@@ -78,6 +100,7 @@ export class StreamTransport {
78
100
  this.#handleClose();
79
101
  }
80
102
  #handleData(chunk) {
103
+ this.#bytesReceived += chunk.byteLength;
81
104
  for (const line of this.#reader.push(chunk)) {
82
105
  if (this.#banner > 0) {
83
106
  this.#banner--;
@@ -1 +1 @@
1
- {"version":3,"file":"stream.js","sourceRoot":"","sources":["../../src/query/stream.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"stream.js","sourceRoot":"","sources":["../../src/query/stream.ts"],"names":[],"mappings":"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"}
package/dist/query/tcp.js CHANGED
@@ -11,7 +11,7 @@ export async function connectTcp(options) {
11
11
  signal?.throwIfAborted();
12
12
  const stream = await connect(host, port);
13
13
  await opened(stream, signal);
14
- return new StreamTransport(stream);
14
+ return new StreamTransport(stream, undefined, { transport: "tcp", address: `${host}:${port}` });
15
15
  }
16
16
  /** A connected `node:net` socket, with whole lines sent as they are written. */
17
17
  function defaultConnect(host, port) {
@@ -1 +1 @@
1
- {"version":3,"file":"tcp.js","sourceRoot":"","sources":["../../src/query/tcp.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,gBAAgB,EAAE,MAAM,UAAU,CAAC;AAE5C,OAAO,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;AAgC9C;;;;;GAKG;AACH,MAAM,CAAC,KAAK,UAAU,UAAU,CAAC,OAAmB;IAClD,MAAM,EAAE,IAAI,EAAE,IAAI,GAAG,KAAK,EAAE,MAAM,EAAE,OAAO,GAAG,cAAc,EAAE,GAAG,OAAO,CAAC;IACzE,MAAM,EAAE,cAAc,EAAE,CAAC;IACzB,MAAM,MAAM,GAAG,MAAM,OAAO,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC;IACzC,MAAM,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAC7B,OAAO,IAAI,eAAe,CAAC,MAAM,CAAC,CAAC;AACrC,CAAC;AAED,gFAAgF;AAChF,SAAS,cAAc,CAAC,IAAY,EAAE,IAAY;IAChD,MAAM,MAAM,GAAG,gBAAgB,CAAC,EAAE,IAAI,EAAE,IAAI,EAAE,CAAC,CAAC;IAChD,uEAAuE;IACvE,YAAY;IACZ,MAAM,CAAC,UAAU,CAAC,IAAI,CAAC,CAAC;IACxB,OAAO,MAAM,CAAC;AAChB,CAAC;AAED;;;;;;GAMG;AACH,SAAS,MAAM,CAAC,MAAc,EAAE,MAA+B;IAC7D,MAAM,UAAU,GAAI,MAA4C,CAAC,UAAU,CAAC;IAC5E,IAAI,UAAU,KAAK,IAAI;QAAE,OAAO,OAAO,CAAC,OAAO,EAAE,CAAC;IAClD,OAAO,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE;QACrC,MAAM,MAAM,GAAG,CAAC,KAAY,EAAQ,EAAE;YACpC,MAAM,EAAE,mBAAmB,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC;YAC9C,MAAM,CAAC,KAAK,CAAC,CAAC;QAChB,CAAC,CAAC;QACF,MAAM,OAAO,GAAG,GAAS,EAAE;YACzB,MAAM,CAAC,OAAO,EAAE,CAAC;YACjB,MAAM,CAAC,MAAO,CAAC,MAAe,CAAC,CAAC;QAClC,CAAC,CAAC;QACF,MAAM,EAAE,gBAAgB,CAAC,OAAO,EAAE,OAAO,EAAE,EAAE,IAAI,EAAE,IAAI,EAAE,CAAC,CAAC;QAC3D,MAAM,CAAC,IAAI,CAAC,OAAO,EAAE,MAAM,CAAC,CAAC;QAC7B,MAAM,CAAC,IAAI,CAAC,SAAS,EAAE,GAAG,EAAE;YAC1B,MAAM,CAAC,GAAG,CAAC,OAAO,EAAE,MAAM,CAAC,CAAC;YAC5B,MAAM,EAAE,mBAAmB,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC;YAC9C,OAAO,EAAE,CAAC;QACZ,CAAC,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;AACL,CAAC"}
1
+ {"version":3,"file":"tcp.js","sourceRoot":"","sources":["../../src/query/tcp.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,gBAAgB,EAAE,MAAM,UAAU,CAAC;AAE5C,OAAO,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;AAgC9C;;;;;GAKG;AACH,MAAM,CAAC,KAAK,UAAU,UAAU,CAAC,OAAmB;IAClD,MAAM,EAAE,IAAI,EAAE,IAAI,GAAG,KAAK,EAAE,MAAM,EAAE,OAAO,GAAG,cAAc,EAAE,GAAG,OAAO,CAAC;IACzE,MAAM,EAAE,cAAc,EAAE,CAAC;IACzB,MAAM,MAAM,GAAG,MAAM,OAAO,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC;IACzC,MAAM,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAC7B,OAAO,IAAI,eAAe,CAAC,MAAM,EAAE,SAAS,EAAE,EAAE,SAAS,EAAE,KAAK,EAAE,OAAO,EAAE,GAAG,IAAI,IAAI,IAAI,EAAE,EAAE,CAAC,CAAC;AAClG,CAAC;AAED,gFAAgF;AAChF,SAAS,cAAc,CAAC,IAAY,EAAE,IAAY;IAChD,MAAM,MAAM,GAAG,gBAAgB,CAAC,EAAE,IAAI,EAAE,IAAI,EAAE,CAAC,CAAC;IAChD,uEAAuE;IACvE,YAAY;IACZ,MAAM,CAAC,UAAU,CAAC,IAAI,CAAC,CAAC;IACxB,OAAO,MAAM,CAAC;AAChB,CAAC;AAED;;;;;;GAMG;AACH,SAAS,MAAM,CAAC,MAAc,EAAE,MAA+B;IAC7D,MAAM,UAAU,GAAI,MAA4C,CAAC,UAAU,CAAC;IAC5E,IAAI,UAAU,KAAK,IAAI;QAAE,OAAO,OAAO,CAAC,OAAO,EAAE,CAAC;IAClD,OAAO,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE;QACrC,MAAM,MAAM,GAAG,CAAC,KAAY,EAAQ,EAAE;YACpC,MAAM,EAAE,mBAAmB,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC;YAC9C,MAAM,CAAC,KAAK,CAAC,CAAC;QAChB,CAAC,CAAC;QACF,MAAM,OAAO,GAAG,GAAS,EAAE;YACzB,MAAM,CAAC,OAAO,EAAE,CAAC;YACjB,MAAM,CAAC,MAAO,CAAC,MAAe,CAAC,CAAC;QAClC,CAAC,CAAC;QACF,MAAM,EAAE,gBAAgB,CAAC,OAAO,EAAE,OAAO,EAAE,EAAE,IAAI,EAAE,IAAI,EAAE,CAAC,CAAC;QAC3D,MAAM,CAAC,IAAI,CAAC,OAAO,EAAE,MAAM,CAAC,CAAC;QAC7B,MAAM,CAAC,IAAI,CAAC,SAAS,EAAE,GAAG,EAAE;YAC1B,MAAM,CAAC,GAAG,CAAC,OAAO,EAAE,MAAM,CAAC,CAAC;YAC5B,MAAM,EAAE,mBAAmB,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC;YAC9C,OAAO,EAAE,CAAC;QACZ,CAAC,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;AACL,CAAC"}
@@ -1,3 +1,33 @@
1
+ /**
2
+ * What a connection reports about itself, enough for a metrics exporter to
3
+ * publish without reaching into the client.
4
+ *
5
+ * @experimental Part of the `@honeybbq/teamspeak/query` entry, which may
6
+ * change in a minor release.
7
+ */
8
+ export interface QueryTransportStats {
9
+ /** When the current connection was opened; undefined when there is none. */
10
+ readonly connectedAt: Date | undefined;
11
+ /** The kind of connection; undefined when there is none, or for a transport that does not say. */
12
+ readonly transport: "tcp" | "ssh" | "web" | undefined;
13
+ /**
14
+ * Where it points: `host:port` for raw TCP, `user@host:port` for SSH, the
15
+ * base URL for WebQuery. Never a password or an api key; "" when there is
16
+ * no connection.
17
+ */
18
+ readonly address: string;
19
+ /**
20
+ * What the line protocol has written, line terminators included; for
21
+ * WebQuery, the request bodies. It is what the transport sent, not what the
22
+ * socket did: headers and retries are not counted.
23
+ */
24
+ readonly bytesSent: number;
25
+ /**
26
+ * What the server has sent, banner included: the bytes read from the stream
27
+ * for raw TCP and SSH, the response bodies for WebQuery.
28
+ */
29
+ readonly bytesReceived: number;
30
+ }
1
31
  /**
2
32
  * The connection a ServerQuery client talks over.
3
33
  *
@@ -33,5 +63,10 @@ export interface QueryTransport {
33
63
  onClose: ((error: Error | undefined) => void) | null;
34
64
  /** End the connection. */
35
65
  close(): Promise<void>;
66
+ /**
67
+ * What the connection reports about itself, for `QueryClient.stats`. A
68
+ * transport that does not keep counts leaves it out.
69
+ */
70
+ stats?(): QueryTransportStats;
36
71
  }
37
72
  //# sourceMappingURL=transport.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"transport.d.ts","sourceRoot":"","sources":["../../src/query/transport.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AACH,MAAM,WAAW,cAAc;IAC7B;;;;;;;;;;;;OAYG;IACH,QAAQ,CAAC,qBAAqB,EAAE,OAAO,CAAC;IACxC,qEAAqE;IACrE,IAAI,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAClC;;;OAGG;IACH,MAAM,EAAE,CAAC,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAC,GAAG,IAAI,CAAC;IACxC,oFAAoF;IACpF,OAAO,EAAE,CAAC,CAAC,KAAK,EAAE,KAAK,GAAG,SAAS,KAAK,IAAI,CAAC,GAAG,IAAI,CAAC;IACrD,0BAA0B;IAC1B,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;CACxB"}
1
+ {"version":3,"file":"transport.d.ts","sourceRoot":"","sources":["../../src/query/transport.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AACH,MAAM,WAAW,mBAAmB;IAClC,4EAA4E;IAC5E,QAAQ,CAAC,WAAW,EAAE,IAAI,GAAG,SAAS,CAAC;IACvC,kGAAkG;IAClG,QAAQ,CAAC,SAAS,EAAE,KAAK,GAAG,KAAK,GAAG,KAAK,GAAG,SAAS,CAAC;IACtD;;;;OAIG;IACH,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB;;;;OAIG;IACH,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B;;;OAGG;IACH,QAAQ,CAAC,aAAa,EAAE,MAAM,CAAC;CAChC;AAED;;;;;;;;GAQG;AACH,MAAM,WAAW,cAAc;IAC7B;;;;;;;;;;;;OAYG;IACH,QAAQ,CAAC,qBAAqB,EAAE,OAAO,CAAC;IACxC,qEAAqE;IACrE,IAAI,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAClC;;;OAGG;IACH,MAAM,EAAE,CAAC,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAC,GAAG,IAAI,CAAC;IACxC,oFAAoF;IACpF,OAAO,EAAE,CAAC,CAAC,KAAK,EAAE,KAAK,GAAG,SAAS,KAAK,IAAI,CAAC,GAAG,IAAI,CAAC;IACrD,0BAA0B;IAC1B,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;IACvB;;;OAGG;IACH,KAAK,CAAC,IAAI,mBAAmB,CAAC;CAC/B"}
@@ -1,5 +1,5 @@
1
1
  import { TeamspeakError } from "@honeybbq/teamspeak";
2
- import type { QueryTransport } from "./transport.js";
2
+ import type { QueryTransport, QueryTransportStats } from "./transport.js";
3
3
  /**
4
4
  * A WebQuery request that failed with an HTTP status and no TeamSpeak error in
5
5
  * its answer: a wrong or missing api key, a server that is not a WebQuery. A
@@ -41,7 +41,11 @@ export type WebCredentials = {
41
41
  };
42
42
  /** How a WebQuery is reached. */
43
43
  export type WebQueryOptions = WebCredentials & {
44
- /** The server's base URL, such as `http://127.0.0.1:10080`. */
44
+ /**
45
+ * The server's base URL, such as `http://127.0.0.1:10080` or
46
+ * `https://ts.example.com:10443`. The default `fetch` speaks `http:` and
47
+ * `https:` and refuses any other scheme.
48
+ */
45
49
  readonly url: string;
46
50
  /**
47
51
  * The virtual server to address; `use` changes it. Unset leaves the server out
@@ -51,9 +55,16 @@ export type WebQueryOptions = WebCredentials & {
51
55
  */
52
56
  readonly serverID?: number | bigint | undefined;
53
57
  /**
54
- * The `fetch` to use. By default a small one over `node:http`: the global
55
- * `fetch` refuses port 10080, WebQuery's own default, as a port the Fetch
56
- * standard blocks.
58
+ * The `fetch` to use. By default a small one over `node:http` for an `http:`
59
+ * URL and `node:https` for an `https:` one: the global `fetch` refuses port
60
+ * 10080, WebQuery's own default, as a port the Fetch standard blocks.
61
+ *
62
+ * Over HTTPS the default verifies the server's certificate against the
63
+ * trust store Node uses, and never skips that. A server whose certificate
64
+ * comes from a private CA, or is self-signed, is trusted one of two ways:
65
+ * start Node with `NODE_EXTRA_CA_CERTS=ca.pem`, or pass a `fetch` that
66
+ * trusts the CA, such as one over `node:https` with an `https.Agent` whose
67
+ * `ca` is that certificate.
57
68
  */
58
69
  readonly fetch?: typeof fetch | undefined;
59
70
  };
@@ -79,6 +90,7 @@ export declare class WebQueryTransport implements QueryTransport {
79
90
  onClose: ((error: Error | undefined) => void) | null;
80
91
  constructor(options: WebQueryOptions);
81
92
  send(line: string): Promise<void>;
93
+ stats(): QueryTransportStats;
82
94
  close(): Promise<void>;
83
95
  }
84
96
  //# sourceMappingURL=web.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"web.d.ts","sourceRoot":"","sources":["../../src/query/web.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAC;AAErD,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,gBAAgB,CAAC;AAErD;;;;;GAKG;AACH,qBAAa,iBAAkB,SAAQ,cAAc;IACnD,4DAA4D;IAC5D,gBAAyB,IAAI,EAAE,MAAM,CAAuB;IAU5D,uBAAuB;IACvB,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IAExB,YAAY,MAAM,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,EAG7C;CACF;AAED;;;;;;;;;;;;;;GAcG;AACH,MAAM,MAAM,cAAc,GACtB;IACE,6DAA6D;IAC7D,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,6CAA6C;IAC7C,QAAQ,CAAC,KAAK,CAAC,EAAE,KAAK,CAAC;CACxB,GACD;IACE,6EAA6E;IAC7E,QAAQ,CAAC,KAAK,EAAE,IAAI,CAAC;IACrB,0CAA0C;IAC1C,QAAQ,CAAC,MAAM,CAAC,EAAE,KAAK,CAAC;CACzB,CAAC;AAEN,iCAAiC;AACjC,MAAM,MAAM,eAAe,GAAG,cAAc,GAAG;IAC7C,+DAA+D;IAC/D,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC;IACrB;;;;;OAKG;IACH,QAAQ,CAAC,QAAQ,CAAC,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAAC;IAChD;;;;OAIG;IACH,QAAQ,CAAC,KAAK,CAAC,EAAE,OAAO,KAAK,GAAG,SAAS,CAAC;CAC3C,CAAC;AAYF;;;;;;;;;;;;;GAaG;AACH,qBAAa,iBAAkB,YAAW,cAAc;;IACtD,wEAAwE;IACxE,QAAQ,CAAC,qBAAqB,SAAS;IACvC,MAAM,EAAE,CAAC,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAC,GAAG,IAAI,CAAQ;IAC/C,OAAO,EAAE,CAAC,CAAC,KAAK,EAAE,KAAK,GAAG,SAAS,KAAK,IAAI,CAAC,GAAG,IAAI,CAAQ;IAQ5D,YAAY,OAAO,EAAE,eAAe,EAcnC;IAEK,IAAI,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CA6CtC;IAED,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC,CAKrB;CAmBF"}
1
+ {"version":3,"file":"web.d.ts","sourceRoot":"","sources":["../../src/query/web.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAC;AAErD,OAAO,KAAK,EAAE,cAAc,EAAE,mBAAmB,EAAE,MAAM,gBAAgB,CAAC;AAE1E;;;;;GAKG;AACH,qBAAa,iBAAkB,SAAQ,cAAc;IACnD,4DAA4D;IAC5D,gBAAyB,IAAI,EAAE,MAAM,CAAuB;IAU5D,uBAAuB;IACvB,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IAExB,YAAY,MAAM,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,EAG7C;CACF;AAED;;;;;;;;;;;;;;GAcG;AACH,MAAM,MAAM,cAAc,GACtB;IACE,6DAA6D;IAC7D,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,6CAA6C;IAC7C,QAAQ,CAAC,KAAK,CAAC,EAAE,KAAK,CAAC;CACxB,GACD;IACE,6EAA6E;IAC7E,QAAQ,CAAC,KAAK,EAAE,IAAI,CAAC;IACrB,0CAA0C;IAC1C,QAAQ,CAAC,MAAM,CAAC,EAAE,KAAK,CAAC;CACzB,CAAC;AAEN,iCAAiC;AACjC,MAAM,MAAM,eAAe,GAAG,cAAc,GAAG;IAC7C;;;;OAIG;IACH,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC;IACrB;;;;;OAKG;IACH,QAAQ,CAAC,QAAQ,CAAC,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAAC;IAChD;;;;;;;;;;;OAWG;IACH,QAAQ,CAAC,KAAK,CAAC,EAAE,OAAO,KAAK,GAAG,SAAS,CAAC;CAC3C,CAAC;AAYF;;;;;;;;;;;;;GAaG;AACH,qBAAa,iBAAkB,YAAW,cAAc;;IACtD,wEAAwE;IACxE,QAAQ,CAAC,qBAAqB,SAAS;IACvC,MAAM,EAAE,CAAC,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAC,GAAG,IAAI,CAAQ;IAC/C,OAAO,EAAE,CAAC,CAAC,KAAK,EAAE,KAAK,GAAG,SAAS,KAAK,IAAI,CAAC,GAAG,IAAI,CAAQ;IAW5D,YAAY,OAAO,EAAE,eAAe,EAsBnC;IAEK,IAAI,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAiDtC;IAED,KAAK,IAAI,mBAAmB,CAY3B;IAED,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC,CAKrB;CAmBF"}
package/dist/query/web.js CHANGED
@@ -1,4 +1,5 @@
1
- import { request } from "node:http";
1
+ import { request as httpRequest } from "node:http";
2
+ import { request as httpsRequest } from "node:https";
2
3
  import { TeamspeakError } from "@honeybbq/teamspeak";
3
4
  import { buildCommandOrdered, parseCommand, splitCommandRows } from "../core/internal.js";
4
5
  /**
@@ -49,6 +50,9 @@ export class WebQueryTransport {
49
50
  #prefix;
50
51
  #fetch;
51
52
  #closed = false;
53
+ #openedAt = new Date();
54
+ #bytesSent = 0;
55
+ #bytesReceived = 0;
52
56
  constructor(options) {
53
57
  this.#base = options.url.replace(/\/+$/, "");
54
58
  if (options.guest === true) {
@@ -61,7 +65,13 @@ export class WebQueryTransport {
61
65
  }
62
66
  this.#apiKey = options.apiKey;
63
67
  this.#prefix = options.serverID === undefined ? "" : `/${options.serverID}`;
64
- this.#fetch = options.fetch ?? httpFetch;
68
+ if (options.fetch === undefined) {
69
+ const { protocol } = new URL(options.url);
70
+ if (protocol !== "http:" && protocol !== "https:") {
71
+ throw new TypeError(`WebQuery is reached over http: or https:, not ${protocol}; pass a fetch to use another scheme`);
72
+ }
73
+ }
74
+ this.#fetch = options.fetch ?? nodeFetch;
65
75
  }
66
76
  async send(line) {
67
77
  if (this.#closed)
@@ -75,17 +85,21 @@ export class WebQueryTransport {
75
85
  return;
76
86
  }
77
87
  const params = rows.map((row) => ({ ...row.params }));
88
+ const body = JSON.stringify(params.length === 1 ? params[0] : params);
78
89
  const response = await this.#fetch(`${this.#base}${this.#prefix}/${name}`, {
79
90
  method: "POST",
80
91
  headers: {
81
92
  ...(this.#apiKey === undefined ? {} : { "x-api-key": this.#apiKey }),
82
93
  "content-type": "application/json",
83
94
  },
84
- body: JSON.stringify(params.length === 1 ? params[0] : params),
95
+ body,
85
96
  });
97
+ this.#bytesSent += Buffer.byteLength(body);
86
98
  let answer;
87
99
  try {
88
- answer = (await response.json());
100
+ const text = await response.text();
101
+ this.#bytesReceived += Buffer.byteLength(text);
102
+ answer = JSON.parse(text);
89
103
  }
90
104
  catch {
91
105
  // Not JSON: nothing the server said about the command.
@@ -93,8 +107,8 @@ export class WebQueryTransport {
93
107
  const code = answer?.status?.code;
94
108
  if (typeof code !== "number")
95
109
  throw new WebQueryHttpError(response.status, response.statusText);
96
- const body = answer?.body;
97
- for (const row of Array.isArray(body) ? body : []) {
110
+ const rowsBody = answer?.body;
111
+ for (const row of Array.isArray(rowsBody) ? rowsBody : []) {
98
112
  if (typeof row === "object" && row !== null)
99
113
  this.onLine?.(rowLine(row));
100
114
  }
@@ -107,6 +121,19 @@ export class WebQueryTransport {
107
121
  ...Object.entries(tail),
108
122
  ]));
109
123
  }
124
+ stats() {
125
+ // The base URL as given, without a user or password a caller put in it.
126
+ const url = new URL(this.#base);
127
+ url.username = "";
128
+ url.password = "";
129
+ return {
130
+ connectedAt: this.#openedAt,
131
+ transport: "web",
132
+ address: url.toString().replace(/\/+$/, ""),
133
+ bytesSent: this.#bytesSent,
134
+ bytesReceived: this.#bytesReceived,
135
+ };
136
+ }
110
137
  close() {
111
138
  if (this.#closed)
112
139
  return Promise.resolve();
@@ -139,10 +166,12 @@ function rowLine(row) {
139
166
  return buildCommandOrdered("", fields).slice(1);
140
167
  }
141
168
  /**
142
- * The part of `fetch` this transport uses, over `node:http`: a POST with a
143
- * string body, answered with a `Response`. Plain HTTP only, as WebQuery is.
169
+ * The part of `fetch` this transport uses, over `node:http` or `node:https`
170
+ * by the URL's scheme: a POST with a string body, answered with a `Response`.
171
+ * An HTTPS certificate is verified the way Node does by default.
144
172
  */
145
- const httpFetch = ((url, init) => new Promise((resolve, reject) => {
173
+ const nodeFetch = ((url, init) => new Promise((resolve, reject) => {
174
+ const request = new URL(url).protocol === "https:" ? httpsRequest : httpRequest;
146
175
  const req = request(url, { method: init.method, headers: init.headers }, (res) => {
147
176
  const chunks = [];
148
177
  res.on("data", (chunk) => chunks.push(chunk));
@@ -1 +1 @@
1
- {"version":3,"file":"web.js","sourceRoot":"","sources":["../../src/query/web.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,OAAO,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAC;AACrD,OAAO,EAAE,mBAAmB,EAAE,YAAY,EAAE,gBAAgB,EAAE,MAAM,qBAAqB,CAAC;AAG1F;;;;;GAKG;AACH,MAAM,OAAO,iBAAkB,SAAQ,cAAc;IACnD,4DAA4D;IAC5D,MAAM,CAAmB,IAAI,GAAW,mBAAmB,CAAC;IAC5D;QACE,MAAM,CAAC,cAAc,CAAC,IAAI,CAAC,SAAS,EAAE,MAAM,EAAE;YAC5C,KAAK,EAAE,mBAAmB;YAC1B,QAAQ,EAAE,IAAI;YACd,YAAY,EAAE,IAAI;YAClB,UAAU,EAAE,KAAK;SAClB,CAAC,CAAC;IACL,CAAC;IAED,uBAAuB;IACd,MAAM,CAAS;IAExB,YAAY,MAAc,EAAE,UAAkB;QAC5C,KAAK,CAAC,0BAA0B,MAAM,GAAG,UAAU,KAAK,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,UAAU,EAAE,EAAE,CAAC,CAAC;QACtF,IAAI,CAAC,MAAM,GAAG,MAAM,CAAC;IACvB,CAAC;CACF;AA4DD;;;;;;;;;;;;;GAaG;AACH,MAAM,OAAO,iBAAiB;IAC5B,wEAAwE;IAC/D,qBAAqB,GAAG,KAAK,CAAC;IACvC,MAAM,GAAoC,IAAI,CAAC;IAC/C,OAAO,GAAgD,IAAI,CAAC;IAE5D,KAAK,CAAS;IACd,OAAO,CAAqB;IAC5B,OAAO,CAAS;IAChB,MAAM,CAAe;IACrB,OAAO,GAAG,KAAK,CAAC;IAEhB,YAAY,OAAwB;QAClC,IAAI,CAAC,KAAK,GAAG,OAAO,CAAC,GAAG,CAAC,OAAO,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC;QAC7C,IAAI,OAAO,CAAC,KAAK,KAAK,IAAI,EAAE,CAAC;YAC3B,IAAI,OAAO,CAAC,MAAM,KAAK,SAAS,EAAE,CAAC;gBACjC,MAAM,IAAI,SAAS,CAAC,gEAAgE,CAAC,CAAC;YACxF,CAAC;QACH,CAAC;aAAM,IAAI,OAAO,OAAO,CAAC,MAAM,KAAK,QAAQ,IAAI,OAAO,CAAC,MAAM,KAAK,EAAE,EAAE,CAAC;YACvE,MAAM,IAAI,SAAS,CACjB,qFAAqF,CACtF,CAAC;QACJ,CAAC;QACD,IAAI,CAAC,OAAO,GAAG,OAAO,CAAC,MAAM,CAAC;QAC9B,IAAI,CAAC,OAAO,GAAG,OAAO,CAAC,QAAQ,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,OAAO,CAAC,QAAQ,EAAE,CAAC;QAC5E,IAAI,CAAC,MAAM,GAAG,OAAO,CAAC,KAAK,IAAI,SAAS,CAAC;IAC3C,CAAC;IAED,KAAK,CAAC,IAAI,CAAC,IAAY;QACrB,IAAI,IAAI,CAAC,OAAO;YAAE,MAAM,IAAI,KAAK,CAAC,gCAAgC,CAAC,CAAC;QACpE,MAAM,IAAI,GAAG,gBAAgB,CAAC,IAAI,CAAC;aAChC,GAAG,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,YAAY,CAAC,GAAG,CAAC,CAAC;aAC/B,MAAM,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,GAAG,KAAK,IAAI,CAAC,CAAC;QACjC,MAAM,IAAI,GAAG,IAAI,CAAC,CAAC,CAAC,EAAE,IAAI,IAAI,EAAE,CAAC;QAEjC,IAAI,IAAI,KAAK,KAAK,EAAE,CAAC;YACnB,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAE,CAAC,MAAM,CAAC,CAAC;YAC3B,OAAO;QACT,CAAC;QAED,MAAM,MAAM,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,CAAC,EAAE,GAAG,GAAG,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC;QACtD,MAAM,QAAQ,GAAG,MAAM,IAAI,CAAC,MAAM,CAAC,GAAG,IAAI,CAAC,KAAK,GAAG,IAAI,CAAC,OAAO,IAAI,IAAI,EAAE,EAAE;YACzE,MAAM,EAAE,MAAM;YACd,OAAO,EAAE;gBACP,GAAG,CAAC,IAAI,CAAC,OAAO,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,WAAW,EAAE,IAAI,CAAC,OAAO,EAAE,CAAC;gBACpE,cAAc,EAAE,kBAAkB;aACnC;YACD,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,MAAM,KAAK,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC;SAC/D,CAAC,CAAC;QAEH,IAAI,MAA6B,CAAC;QAClC,IAAI,CAAC;YACH,MAAM,GAAG,CAAC,MAAM,QAAQ,CAAC,IAAI,EAAE,CAAc,CAAC;QAChD,CAAC;QAAC,MAAM,CAAC;YACP,uDAAuD;QACzD,CAAC;QACD,MAAM,IAAI,GAAG,MAAM,EAAE,MAAM,EAAE,IAAI,CAAC;QAClC,IAAI,OAAO,IAAI,KAAK,QAAQ;YAAE,MAAM,IAAI,iBAAiB,CAAC,QAAQ,CAAC,MAAM,EAAE,QAAQ,CAAC,UAAU,CAAC,CAAC;QAEhG,MAAM,IAAI,GAAG,MAAM,EAAE,IAAI,CAAC;QAC1B,KAAK,MAAM,GAAG,IAAI,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC;YAClD,IAAI,OAAO,GAAG,KAAK,QAAQ,IAAI,GAAG,KAAK,IAAI;gBAAE,IAAI,CAAC,MAAM,EAAE,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC;QAC3E,CAAC;QACD,MAAM,OAAO,GAAG,MAAM,EAAE,MAAM,EAAE,OAAO,CAAC;QACxC,MAAM,KAAK,GAAG,MAAM,EAAE,MAAM,EAAE,aAAa,CAAC;QAC5C,MAAM,IAAI,GAAG,OAAO,KAAK,KAAK,QAAQ,IAAI,KAAK,KAAK,EAAE,CAAC,CAAC,CAAC,EAAE,SAAS,EAAE,KAAK,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;QACnF,IAAI,CAAC,MAAM,EAAE,CACX,mBAAmB,CAAC,OAAO,EAAE;YAC3B,CAAC,IAAI,EAAE,MAAM,CAAC,IAAI,CAAC,CAAC;YACpB,CAAC,KAAK,EAAE,OAAO,OAAO,KAAK,QAAQ,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,CAAC;YACnD,GAAG,MAAM,CAAC,OAAO,CAAC,IAAI,CAAC;SACxB,CAAC,CACH,CAAC;IACJ,CAAC;IAED,KAAK;QACH,IAAI,IAAI,CAAC,OAAO;YAAE,OAAO,OAAO,CAAC,OAAO,EAAE,CAAC;QAC3C,IAAI,CAAC,OAAO,GAAG,IAAI,CAAC;QACpB,IAAI,CAAC,OAAO,EAAE,CAAC,SAAS,CAAC,CAAC;QAC1B,OAAO,OAAO,CAAC,OAAO,EAAE,CAAC;IAC3B,CAAC;IAED,mFAAmF;IACnF,IAAI,CAAC,MAAwC;QAC3C,MAAM,GAAG,GAAG,MAAM,CAAC,KAAK,CAAC,CAAC;QAC1B,MAAM,IAAI,GAAG,MAAM,CAAC,MAAM,CAAC,CAAC;QAC5B,IAAI,GAAG,KAAK,SAAS,IAAI,OAAO,CAAC,IAAI,CAAC,GAAG,CAAC;YAAE,IAAI,CAAC,OAAO,GAAG,IAAI,GAAG,EAAE,CAAC;aAChE,IAAI,IAAI,KAAK,SAAS,IAAI,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC;YAAE,IAAI,CAAC,OAAO,GAAG,WAAW,IAAI,EAAE,CAAC;aAC/E,CAAC;YACJ,IAAI,CAAC,MAAM,EAAE,CACX,mBAAmB,CAAC,OAAO,EAAE;gBAC3B,CAAC,IAAI,EAAE,MAAM,CAAC;gBACd,CAAC,KAAK,EAAE,mBAAmB,CAAC;aAC7B,CAAC,CACH,CAAC;YACF,OAAO;QACT,CAAC;QACD,IAAI,CAAC,MAAM,EAAE,CAAC,mBAAmB,CAAC,CAAC;IACrC,CAAC;CACF;AAED,mGAAmG;AACnG,SAAS,OAAO,CAAC,GAAW;IAC1B,MAAM,MAAM,GAAG,MAAM,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,GAAG,CACpC,CAAC,CAAC,GAAG,EAAE,KAAK,CAAC,EAAE,EAAE,CAAC,CAAC,GAAG,EAAE,OAAO,KAAK,KAAK,QAAQ,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAU,CACpF,CAAC;IACF,2DAA2D;IAC3D,OAAO,mBAAmB,CAAC,EAAE,EAAE,MAAM,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;AAClD,CAAC;AAED;;;GAGG;AACH,MAAM,SAAS,GAAG,CAAC,CAAC,GAAW,EAAE,IAAiB,EAAE,EAAE,CACpD,IAAI,OAAO,CAAW,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE;IACxC,MAAM,GAAG,GAAG,OAAO,CACjB,GAAG,EACH,EAAE,MAAM,EAAE,IAAI,CAAC,MAAM,EAAE,OAAO,EAAE,IAAI,CAAC,OAAiC,EAAE,EACxE,CAAC,GAAG,EAAE,EAAE;QACN,MAAM,MAAM,GAAa,EAAE,CAAC;QAC5B,GAAG,CAAC,EAAE,CAAC,MAAM,EAAE,CAAC,KAAa,EAAE,EAAE,CAAC,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC;QACtD,GAAG,CAAC,EAAE,CAAC,OAAO,EAAE,MAAM,CAAC,CAAC;QACxB,GAAG,CAAC,EAAE,CAAC,KAAK,EAAE,GAAG,EAAE,CACjB,OAAO,CACL,IAAI,QAAQ,CAAC,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,EAAE;YAClC,MAAM,EAAE,GAAG,CAAC,UAAU,IAAI,CAAC;YAC3B,UAAU,EAAE,GAAG,CAAC,aAAa,IAAI,EAAE;SACpC,CAAC,CACH,CACF,CAAC;IACJ,CAAC,CACF,CAAC;IACF,GAAG,CAAC,EAAE,CAAC,OAAO,EAAE,MAAM,CAAC,CAAC;IACxB,GAAG,CAAC,GAAG,CAAC,IAAI,CAAC,IAAc,CAAC,CAAC;AAC/B,CAAC,CAAC,CAA4B,CAAC"}
1
+ {"version":3,"file":"web.js","sourceRoot":"","sources":["../../src/query/web.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@honeybbq/teamspeak",
3
- "version": "1.0.0-beta.12",
3
+ "version": "1.0.0-beta.13",
4
4
  "description": "TeamSpeak SDK for TypeScript: a clean-room voice client for Node.js, and the typed commands, ids and errors every connection shares",
5
5
  "keywords": [
6
6
  "client",
@@ -94,16 +94,17 @@
94
94
  },
95
95
  "scripts": {
96
96
  "build": "tsc -p tsconfig.build.json",
97
- "test": "vitest run",
97
+ "test": "vitest run --project @honeybbq/teamspeak --project scripts",
98
98
  "test:watch": "vitest",
99
99
  "lint": "oxlint --deny-warnings .",
100
100
  "fmt": "oxfmt .",
101
101
  "fmt:check": "oxfmt --check .",
102
102
  "typecheck": "tsc --noEmit",
103
103
  "check": "pnpm typecheck && pnpm lint && pnpm fmt:check",
104
- "test:integration": "vitest run src/client/integration.test.ts src/client/voice-features.integration.test.ts src/client/avatars.integration.test.ts src/client/view.integration.test.ts src/client/puzzle.integration.test.ts src/query/integration.test.ts --reporter=verbose",
105
- "test:integration:client": "vitest run src/client/integration.test.ts src/client/voice-features.integration.test.ts src/client/avatars.integration.test.ts src/client/view.integration.test.ts src/client/puzzle.integration.test.ts --reporter=verbose",
106
- "test:integration:query": "vitest run src/query/integration.test.ts --reporter=verbose",
104
+ "test:integration": "vitest run --project integration --exclude src/query/instance.integration.test.ts --reporter=verbose",
105
+ "test:integration:client": "vitest run --project integration src/client/ --reporter=verbose",
106
+ "test:integration:query": "vitest run --project integration src/query/ --exclude src/query/instance.integration.test.ts --reporter=verbose",
107
+ "test:integration:instance": "TEAMSPEAK_QUERY_DESTRUCTIVE=1 TEAMSPEAK_QUERY_STOP_INSTANCE=1 vitest run --project integration src/query/instance.integration.test.ts --reporter=verbose",
107
108
  "test:integration:ts3": "TEAMSPEAK_ADDR=127.0.0.1:9987 TEAMSPEAK_DEFAULT_CHANNEL=Alpha TEAMSPEAK_PASSWORD_CHANNEL=Secret TEAMSPEAK_PASSWORD_CHANNEL_PASSWORD=hunter2 pnpm test:integration",
108
109
  "test:integration:ts6": "TEAMSPEAK_ADDR=127.0.0.1:9988 TEAMSPEAK_DEFAULT_CHANNEL=Alpha TEAMSPEAK_PASSWORD_CHANNEL=Secret TEAMSPEAK_PASSWORD_CHANNEL_PASSWORD=hunter2 pnpm test:integration",
109
110
  "test:integration:both": "pnpm test:integration:ts3 && pnpm test:integration:ts6",
@@ -12,7 +12,14 @@
12
12
  * round trip.
13
13
  */
14
14
 
15
- import { asServerID, type IconID, type ServerFamily, type ServerID } from "@honeybbq/teamspeak";
15
+ import {
16
+ asServerID,
17
+ HostMessageMode,
18
+ serverFamilyForVersion,
19
+ type IconID,
20
+ type ServerFamily,
21
+ type ServerID,
22
+ } from "@honeybbq/teamspeak";
16
23
  import { parseIconID, parseUint64 } from "../core/internal.js";
17
24
  import { uidAlgorithmForVersion, type UIDAlgorithm } from "./crypto/identity.js";
18
25
 
@@ -51,10 +58,10 @@ export interface ServerCapabilities {
51
58
  readonly hostMessage: string;
52
59
  /**
53
60
  * How the host message is to be shown (`virtualserver_hostmessage_mode`).
54
- * Compare it with `HostMessageMode`; a server may send a value the table
55
- * does not name.
61
+ * A value the `HostMessageMode` table does not name is passed through as the
62
+ * server sent it.
56
63
  */
57
- readonly hostMessageMode: number;
64
+ readonly hostMessageMode: HostMessageMode;
58
65
  }
59
66
 
60
67
  /**
@@ -70,14 +77,10 @@ export function parseServerCapabilities(
70
77
  const parsed = Number.parseInt(version, 10);
71
78
  const major = Number.isNaN(parsed) ? 0 : parsed;
72
79
 
73
- let family: ServerFamily = "unknown";
74
- if (major === 3) family = "ts3";
75
- else if (major >= 6) family = "ts6";
76
-
77
80
  return {
78
81
  version,
79
82
  major,
80
- family,
83
+ family: serverFamilyForVersion(version),
81
84
  uidAlgorithm: uidAlgorithmForVersion(version),
82
85
  name: params["virtualserver_name"] ?? "",
83
86
  iconID: parseIconID(params["virtualserver_icon_id"]),
@@ -100,7 +103,7 @@ export function unknownServerCapabilities(): ServerCapabilities {
100
103
  return parseServerCapabilities("");
101
104
  }
102
105
 
103
- function hostMessageMode(value: string | undefined): number {
106
+ function hostMessageMode(value: string | undefined): HostMessageMode {
104
107
  const parsed = Number.parseInt(value ?? "", 10);
105
- return Number.isNaN(parsed) ? 0 : parsed;
108
+ return (Number.isNaN(parsed) ? HostMessageMode.None : parsed) as HostMessageMode;
106
109
  }
@@ -16,7 +16,7 @@ import { callHook } from "./hooks.js";
16
16
  import { puzzleOf } from "./handshake/crypt-handshake.js";
17
17
  import {
18
18
  type ChannelID,
19
- type ClientEnterEvent,
19
+ type ClientEntry,
20
20
  type ClientID,
21
21
  type Codec,
22
22
  type KickedEvent,
@@ -152,7 +152,7 @@ export interface ClientInternals {
152
152
  nickname: string;
153
153
  clid: number;
154
154
  /** The clients this one knows of, as its events and `invokerGroups` read them. */
155
- readonly clients: ReadonlyMap<number, ClientEnterEvent>;
155
+ readonly clients: ReadonlyMap<number, ClientEntry>;
156
156
  capabilities: ServerCapabilities;
157
157
  /** Mark the attempt in progress connected. */
158
158
  markConnected(initServer?: Readonly<Record<string, string>>): void;
@@ -217,6 +217,27 @@ interface AttemptTrace {
217
217
  welcomeDone: boolean;
218
218
  /** The channel rows the welcome sequence has delivered so far. */
219
219
  channels: number;
220
+ /** Where the key exchange stands, before the shared secret exists. */
221
+ stage: "init1" | "puzzleSolving" | "puzzleAnswered";
222
+ /** The last Init1 step of the server's that was answered; -1 for none. */
223
+ init1Step: number;
224
+ }
225
+
226
+ /** What an attempt is waiting for now, for the report of an attempt that ended. */
227
+ function describeWaiting(trace: AttemptTrace, clientEkPending: boolean): string {
228
+ if (trace.phase === ConnectPhase.Open) {
229
+ return trace.target === "" ? "the server address to resolve" : "the connection to open";
230
+ }
231
+ if (trace.phase === ConnectPhase.Join) {
232
+ return clientEkPending
233
+ ? "the server's answer to clientek"
234
+ : "the server's answer to clientinit";
235
+ }
236
+ if (trace.stage === "puzzleSolving") return "the RSA puzzle to be solved";
237
+ if (trace.stage === "puzzleAnswered") return "the server's answer to the RSA puzzle";
238
+ return trace.init1Step < 0
239
+ ? "the server's first answer to init1"
240
+ : `the server's init1 step after step ${trace.init1Step}`;
220
241
  }
221
242
 
222
243
  /** A session that began with `sessionStart`, until its `sessionEnd`. */
@@ -407,7 +428,7 @@ export class Client implements CommandExecutor, AsyncDisposable {
407
428
  #throttle = new CommandThrottle();
408
429
  #cmdTrack = new CommandTracker(() => this.#clid);
409
430
  #viewStore: ViewStore;
410
- #clients: Map<number, ClientEnterEvent>;
431
+ #clients: Map<number, ClientEntry>;
411
432
  #attempt: ConnectAttempt = newConnectAttempt();
412
433
 
413
434
  #listeners = new Map<keyof EventMap, Subscription[]>();
@@ -577,17 +598,27 @@ export class Client implements CommandExecutor, AsyncDisposable {
577
598
  sessionStarted: false,
578
599
  welcomeDone: false,
579
600
  channels: 0,
601
+ stage: "init1",
602
+ init1Step: -1,
580
603
  };
581
604
  attempt.trace = trace;
582
- attempt.onFail = (error) =>
605
+ attempt.onFail = (error) => {
606
+ const waitingFor = describeWaiting(trace, this.#handler.clientEkPending);
607
+ this.#logger.info("connection attempt ended", {
608
+ phase: trace.phase,
609
+ waitingFor,
610
+ error: String(error),
611
+ });
583
612
  this.#callHook(this.#trace?.attemptFailed, () => ({
584
613
  attempt: trace.attempt,
585
614
  reconnect: trace.reconnect,
586
615
  phase: trace.phase,
587
616
  error,
588
617
  target: trace.target,
618
+ waitingFor,
589
619
  durationMs: performance.now() - trace.startedAt,
590
620
  }));
621
+ };
591
622
 
592
623
  // The handshake may complete just as the signal fires, in which case
593
624
  // #failConnection leaves the session alone and the caller gets the
@@ -1376,12 +1407,18 @@ export class Client implements CommandExecutor, AsyncDisposable {
1376
1407
  if (this.#crypt.cryptoInitComplete) return;
1377
1408
  const signal = this.#attempt.signal;
1378
1409
  const handler = this.#handler;
1410
+ const trace = this.#attempt.trace;
1411
+ const step = p.data[0] ?? 0x7f;
1379
1412
  const response = processInit1(this.#crypt, p.data, signal);
1380
1413
  if (response instanceof Promise) {
1381
1414
  // The puzzle: solved in slices, so the loop keeps running meanwhile.
1415
+ if (trace !== undefined) trace.stage = "puzzleSolving";
1382
1416
  response.then(
1383
1417
  (answer) => {
1384
- if (answer && !signal.aborted) handler.sendPacket(PacketType.Init1, answer, 0);
1418
+ if (answer && !signal.aborted) {
1419
+ handler.sendPacket(PacketType.Init1, answer, 0);
1420
+ if (trace !== undefined) trace.stage = "puzzleAnswered";
1421
+ }
1385
1422
  },
1386
1423
  (error: unknown) => {
1387
1424
  // An attempt that ended did so for its own reason; the abandoned
@@ -1391,6 +1428,7 @@ export class Client implements CommandExecutor, AsyncDisposable {
1391
1428
  );
1392
1429
  } else if (response) {
1393
1430
  handler.sendPacket(PacketType.Init1, response, 0);
1431
+ if (trace !== undefined) trace.init1Step = step === 0x7f ? -1 : step;
1394
1432
  }
1395
1433
  return;
1396
1434
  }
@@ -1628,7 +1666,7 @@ export class Client implements CommandExecutor, AsyncDisposable {
1628
1666
  }
1629
1667
  }
1630
1668
 
1631
- #processNotificationResult(result: NotificationResult, leaving?: ClientEnterEvent): void {
1669
+ #processNotificationResult(result: NotificationResult, leaving?: ClientEntry): void {
1632
1670
  switch (result.kind) {
1633
1671
  case "clientEnter": {
1634
1672
  const info = result.info;
@@ -1741,6 +1779,9 @@ export class Client implements CommandExecutor, AsyncDisposable {
1741
1779
  case "clientChatComposing":
1742
1780
  this.#emitServerEvent({ name: "clientChatComposing", payload: result.event });
1743
1781
  break;
1782
+ case "clientChatClosed":
1783
+ this.#emitServerEvent({ name: "clientChatClosed", payload: result.event });
1784
+ break;
1744
1785
  case "poked":
1745
1786
  this.#emitServerEvent({ name: "poked", payload: result.event });
1746
1787
  break;
@@ -13,8 +13,8 @@ const P256_SCALAR_SIZE = 32;
13
13
  const P256_UNCOMPRESSED_KEY_SIZE = 65;
14
14
  const P256_POINT_PREFIX = 0x04;
15
15
 
16
- /** The most a security level can be: SHA-1 is 160 bits wide. */
17
- const MAX_SECURITY_LEVEL = 160;
16
+ /** The highest security level there is: the level counts zero bits of a SHA-1 digest, which has 160. */
17
+ export const MAX_SECURITY_LEVEL = 160;
18
18
 
19
19
  let createIdentity: (privateKey: KeyObject, offset: bigint) => Identity;
20
20
  let privateKeyOf: (identity: Identity) => KeyObject;
@@ -5,6 +5,7 @@ export {
5
5
  generateIdentitySync,
6
6
  uidFromPublicKey,
7
7
  uidAlgorithmForVersion,
8
+ MAX_SECURITY_LEVEL,
8
9
  hash512,
9
10
  importPublicKey,
10
11
  } from "./identity.js";
@@ -94,5 +94,7 @@ export {
94
94
  generateIdentity,
95
95
  generateIdentitySync,
96
96
  uidFromPublicKey,
97
+ uidAlgorithmForVersion,
98
+ MAX_SECURITY_LEVEL,
97
99
  } from "./crypto/index.js";
98
100
  export type { UIDAlgorithm } from "./crypto/index.js";
@@ -136,6 +136,13 @@ export interface AttemptFailedInfo extends AttemptInfo {
136
136
  readonly error: unknown;
137
137
  /** The `host:port` being dialled; empty when the attempt failed before `resolveDone`. */
138
138
  readonly target: string;
139
+ /**
140
+ * What the attempt was waiting for when it ended, in words for a person or a
141
+ * log, such as `the server's answer to clientek`. It is finer than
142
+ * {@link AttemptFailedInfo.phase}, and its wording may change in any release:
143
+ * do not match on it.
144
+ */
145
+ readonly waitingFor: string;
139
146
  /** Milliseconds since `resolveStart`. */
140
147
  readonly durationMs: number;
141
148
  }