@seriousme/opifex 1.2.1 → 1.3.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 (104) hide show
  1. package/CHANGELOG.md +16 -0
  2. package/README.md +72 -4
  3. package/bin/conformanceServer.ts +1 -1
  4. package/bin/mqtt.ts +5 -2
  5. package/client/client.ts +3 -3
  6. package/client/context.ts +2 -0
  7. package/client/mod.ts +1 -2
  8. package/deno/client.ts +4 -3
  9. package/deno/server.ts +3 -2
  10. package/deno.json +4 -1
  11. package/dev_utils/dummyConn.ts +4 -4
  12. package/dist/bin/conformanceServer.js +52 -0
  13. package/dist/bin/demoServer.js +29 -57
  14. package/dist/bin/mqtt.js +148 -187
  15. package/dist/client/ConnectionState.js +7 -0
  16. package/dist/client/client.js +125 -0
  17. package/dist/client/context.js +148 -0
  18. package/dist/client/deps.js +5 -0
  19. package/dist/client/handlers/handleConnack.js +18 -0
  20. package/dist/client/handlers/handlePacket.js +50 -0
  21. package/dist/client/handlers/handlePuback.js +6 -0
  22. package/dist/client/handlers/handlePubcomp.js +9 -0
  23. package/dist/client/handlers/handlePublish.js +28 -0
  24. package/dist/client/handlers/handlePubrec.js +17 -0
  25. package/dist/client/handlers/handlePubrel.js +19 -0
  26. package/dist/client/handlers/handleSuback.js +9 -0
  27. package/dist/client/handlers/handleUnsuback.js +7 -0
  28. package/dist/client/mod.js +5 -3
  29. package/dist/client/store/deps.js +1 -0
  30. package/dist/client/store/memoryStore.js +36 -0
  31. package/dist/client/store/store.js +1 -0
  32. package/dist/mqttConn/mqttConn.js +104 -0
  33. package/dist/mqttPacket/AuthenticationResult.js +12 -0
  34. package/dist/mqttPacket/BitMask.js +10 -0
  35. package/dist/mqttPacket/PacketType.js +18 -0
  36. package/dist/mqttPacket/connack.js +27 -0
  37. package/dist/mqttPacket/connect.js +115 -0
  38. package/dist/mqttPacket/decoder.js +89 -0
  39. package/dist/mqttPacket/disconnect.js +14 -0
  40. package/dist/mqttPacket/encoder.js +56 -0
  41. package/dist/mqttPacket/length.js +43 -0
  42. package/dist/mqttPacket/mod.js +71 -0
  43. package/dist/mqttPacket/pingreq.js +15 -0
  44. package/dist/mqttPacket/pingres.js +14 -0
  45. package/dist/mqttPacket/puback.js +20 -0
  46. package/dist/mqttPacket/pubcomp.js +20 -0
  47. package/dist/mqttPacket/publish.js +51 -0
  48. package/dist/mqttPacket/pubrec.js +20 -0
  49. package/dist/mqttPacket/pubrel.js +20 -0
  50. package/dist/mqttPacket/suback.js +29 -0
  51. package/dist/mqttPacket/subscribe.js +52 -0
  52. package/dist/mqttPacket/types.js +1 -0
  53. package/dist/mqttPacket/unsuback.js +20 -0
  54. package/dist/mqttPacket/unsubscribe.js +36 -0
  55. package/dist/mqttPacket/validators.js +15 -0
  56. package/dist/node/client.js +65 -0
  57. package/dist/node/server.js +22 -0
  58. package/dist/node/wrapNodeSocket.js +47 -0
  59. package/dist/persistence/deps.js +3 -0
  60. package/dist/persistence/memory/memoryPersistence.js +117 -0
  61. package/dist/persistence/persistence.js +1 -0
  62. package/dist/persistence/store.js +1 -0
  63. package/dist/server/context.js +100 -0
  64. package/dist/server/deps.js +5 -0
  65. package/dist/server/handlers/handleConnect.js +46 -0
  66. package/dist/server/handlers/handleDisconnect.js +4 -0
  67. package/dist/server/handlers/handlePacket.js +58 -0
  68. package/dist/server/handlers/handlePingreq.js +6 -0
  69. package/dist/server/handlers/handlePuback.js +8 -0
  70. package/dist/server/handlers/handlePubcomp.js +8 -0
  71. package/dist/server/handlers/handlePublish.js +40 -0
  72. package/dist/server/handlers/handlePubrec.js +15 -0
  73. package/dist/server/handlers/handlePubrel.js +18 -0
  74. package/dist/server/handlers/handleSubscribe.js +33 -0
  75. package/dist/server/handlers/handleUnsubscribe.js +12 -0
  76. package/dist/server/mod.js +7 -589
  77. package/dist/server/server.js +47 -0
  78. package/dist/socket/socket.js +36 -0
  79. package/dist/timer/timer.js +40 -0
  80. package/dist/trie/trie.js +95 -0
  81. package/dist/tsconfig.tsbuildinfo +1 -0
  82. package/dist/utils/args.js +61 -0
  83. package/dist/utils/assert.js +19 -0
  84. package/dist/utils/asyncQueue.js +56 -0
  85. package/dist/utils/deferred.js +11 -0
  86. package/dist/utils/logger.js +29 -0
  87. package/dist/utils/mod.js +7 -0
  88. package/dist/utils/nextTick.js +3 -0
  89. package/dist/utils/platform.js +4 -0
  90. package/mqttConn/mqttConn.ts +4 -1
  91. package/node/client.ts +30 -6
  92. package/node/server.ts +2 -0
  93. package/node/wrapNodeSocket.ts +1 -1
  94. package/package.json +16 -3
  95. package/server/mod.ts +1 -2
  96. package/socket/socket.ts +3 -2
  97. package/timer/timer.ts +1 -1
  98. package/tsconfig.json +3 -0
  99. package/.vscode/extensions.json +0 -10
  100. package/.vscode/settings.json +0 -12
  101. package/deno/wrapDenoConn.ts +0 -12
  102. package/dist/client-DqLTBVC2.js +0 -541
  103. package/dist/timer-DDWVNsyG.js +0 -924
  104. package/dist/wrapNodeSocket-BAJm059T.js +0 -115
@@ -0,0 +1,95 @@
1
+ export class Trie {
2
+ #value;
3
+ #children;
4
+ separator = "/";
5
+ wildcardOne = "+";
6
+ wildcardSubtree = "#";
7
+ reservedPrefix = "$";
8
+ looseCompare;
9
+ constructor(looseCompare = false) {
10
+ this.#value = [];
11
+ this.#children = new Map();
12
+ this.looseCompare = looseCompare;
13
+ }
14
+ matchChild(child, parts) {
15
+ const childNode = this.#children.get(child);
16
+ return childNode ? childNode._match(parts) : [];
17
+ }
18
+ match(key) {
19
+ const parts = key.split(this.separator);
20
+ // toplevel wildcards are not allowed to match toplevel reserved topics
21
+ if (parts.length > 0 && parts[0].charAt(0) === this.reservedPrefix) {
22
+ return this._matchPrefix(parts);
23
+ }
24
+ return this._match(parts);
25
+ }
26
+ _matchPrefix(parts) {
27
+ if (parts.length === 0) {
28
+ return this.#value ? this.#value : [];
29
+ }
30
+ const [first, ...rest] = parts;
31
+ return this.matchChild(first, rest);
32
+ }
33
+ _match(parts) {
34
+ if (parts.length === 0) {
35
+ return this.#value ? this.#value : [];
36
+ }
37
+ const [first, ...rest] = parts;
38
+ const exact = this.matchChild(first, rest);
39
+ const single = this.matchChild(this.wildcardOne, rest);
40
+ const subtree = this.matchChild(this.wildcardSubtree, []);
41
+ const results = exact.concat(single, subtree);
42
+ return results;
43
+ }
44
+ add(key, value) {
45
+ return this._add(key.split(this.separator), value);
46
+ }
47
+ _add(parts, value) {
48
+ if (parts.length === 0) {
49
+ this.#value = this.#value.concat(value);
50
+ return;
51
+ }
52
+ const [first, ...rest] = parts;
53
+ const child = this.#children.get(first);
54
+ if (child instanceof Trie) {
55
+ child._add(rest, value);
56
+ }
57
+ else {
58
+ const node = new Trie(this.looseCompare);
59
+ this.#children.set(first, node);
60
+ node._add(rest, value);
61
+ }
62
+ return;
63
+ }
64
+ remove(key, value) {
65
+ return this._remove(key.split(this.separator), value);
66
+ }
67
+ _remove(parts, value) {
68
+ if (parts.length === 0) {
69
+ const arr = this.#value || [];
70
+ this.#value = arr.filter(this.filter(value));
71
+ return;
72
+ }
73
+ const [first, ...rest] = parts;
74
+ const node = this.#children.get(first);
75
+ if (node) {
76
+ node._remove(rest, value);
77
+ if (node.#value.length === 0 && this.#children.size === 0) {
78
+ this.#children.delete(first);
79
+ }
80
+ }
81
+ }
82
+ filter(value) {
83
+ if (this.looseCompare && typeof value === "object") {
84
+ return (item) => {
85
+ for (const key in value) {
86
+ if (value[key] !== item[key]) {
87
+ return true;
88
+ }
89
+ }
90
+ return false;
91
+ };
92
+ }
93
+ return (item) => item !== value;
94
+ }
95
+ }
@@ -0,0 +1 @@
1
+ {"root":["../bin/conformanceServer.ts","../bin/demoServer.ts","../bin/mqtt.ts"],"version":"5.7.0-beta"}
@@ -0,0 +1,61 @@
1
+ function formatValue(key, value, boolean, string) {
2
+ if (key === "__proto__" || key === "constructor") {
3
+ throw new Error(`Invalid argument: ${key}`);
4
+ }
5
+ if (boolean.includes(key)) {
6
+ if (value !== "false") {
7
+ return true;
8
+ }
9
+ return false;
10
+ }
11
+ if (!string.includes(key)) {
12
+ const num = Number(value);
13
+ if (!Number.isNaN(num)) {
14
+ return num;
15
+ }
16
+ }
17
+ return value;
18
+ }
19
+ function parseKeyValue(arg, alias) {
20
+ if (arg.startsWith("--no-")) {
21
+ const key = arg.slice(5);
22
+ return [key, false];
23
+ }
24
+ if (arg.startsWith("--")) {
25
+ const [key, value] = arg.slice(2).split("=", 2);
26
+ return [key, value];
27
+ }
28
+ if (arg.startsWith("-")) {
29
+ const [flag, value] = arg.slice(1).split("=", 2);
30
+ const key = alias[flag] || flag;
31
+ return [key, value];
32
+ }
33
+ return ["_", arg];
34
+ }
35
+ export function parseArgs(args, opts = {}) {
36
+ const { alias = {}, boolean = [], string = [], default: defaults = {} } = opts;
37
+ const result = { ...defaults };
38
+ result["_"] = [];
39
+ for (let i = 0; i < args.length; i++) {
40
+ const [key, value] = parseKeyValue(args[i], alias);
41
+ if (key === "_") {
42
+ result["_"].push(formatValue(key, value, boolean, string));
43
+ continue;
44
+ }
45
+ if (value === undefined) {
46
+ const nextArg = args[i + 1];
47
+ if (nextArg !== undefined &&
48
+ !nextArg.startsWith("-") &&
49
+ !boolean.includes(key)) {
50
+ result[key] = formatValue(key, nextArg, boolean, string);
51
+ i++;
52
+ }
53
+ else {
54
+ result[key] = formatValue(key, value, boolean, string);
55
+ }
56
+ continue;
57
+ }
58
+ result[key] = formatValue(key, value, boolean, string);
59
+ }
60
+ return result;
61
+ }
@@ -0,0 +1,19 @@
1
+ export class AssertionError extends Error {
2
+ /** Constructs a new instance. */
3
+ constructor(message) {
4
+ super(message);
5
+ this.name = "AssertionError";
6
+ }
7
+ }
8
+ export function assert(expr, msg = "") {
9
+ if (!expr) {
10
+ throw new AssertionError(msg);
11
+ }
12
+ }
13
+ export function assertArrayIncludes(actual, expected, msg) {
14
+ const actualArr = Array.from(actual);
15
+ const expectedArr = Array.from(expected);
16
+ for (const item of expectedArr) {
17
+ assert(actualArr.includes(item), msg + `\nExpected: ${expectedArr}\nActual: ${actualArr}`);
18
+ }
19
+ }
@@ -0,0 +1,56 @@
1
+ import { nextTick } from "./nextTick.js";
2
+ export class AsyncQueue {
3
+ queue = [];
4
+ maxQueueLength = Infinity;
5
+ nextResolve = (_value) => { };
6
+ nextReject = (_reason) => { };
7
+ done = false;
8
+ hasNext = false;
9
+ constructor(maxQueueLength) {
10
+ if (maxQueueLength) {
11
+ this.maxQueueLength = maxQueueLength;
12
+ }
13
+ }
14
+ async next() {
15
+ await nextTick();
16
+ if (this.done && this.queue.length === 0) {
17
+ return Promise.reject("Closed");
18
+ }
19
+ return new Promise((resolve, reject) => {
20
+ if (this.queue.length > 0) {
21
+ const item = this.queue.shift();
22
+ if (item) {
23
+ return resolve(item);
24
+ }
25
+ }
26
+ this.nextResolve = resolve;
27
+ this.nextReject = reject;
28
+ this.hasNext = true;
29
+ });
30
+ }
31
+ close(reason = "closed") {
32
+ this.done = true;
33
+ if (this.hasNext) {
34
+ this.nextReject(reason);
35
+ }
36
+ }
37
+ async *[Symbol.asyncIterator]() {
38
+ while (true) {
39
+ yield this.next();
40
+ }
41
+ }
42
+ push(item) {
43
+ if (this.hasNext) {
44
+ this.nextResolve(item);
45
+ this.hasNext = false;
46
+ return;
47
+ }
48
+ if (this.queue.length > this.maxQueueLength) {
49
+ this.queue.shift();
50
+ }
51
+ this.queue.push(item);
52
+ }
53
+ get isDone() {
54
+ return this.done;
55
+ }
56
+ }
@@ -0,0 +1,11 @@
1
+ export class Deferred {
2
+ promise;
3
+ resolve;
4
+ reject;
5
+ constructor() {
6
+ this.promise = new Promise((resolve, reject) => {
7
+ this.resolve = resolve;
8
+ this.reject = reject;
9
+ });
10
+ }
11
+ }
@@ -0,0 +1,29 @@
1
+ export const LogLevel = {
2
+ error: 0,
3
+ warn: 1,
4
+ info: 2,
5
+ verbose: 3,
6
+ debug: 4,
7
+ };
8
+ export class Logger {
9
+ defaultError = console.error;
10
+ defaultWarn = console.warn;
11
+ defaultInfo = console.info;
12
+ defaultVerbose = console.log;
13
+ defaultDebug = console.log;
14
+ // deno-lint-ignore no-explicit-any
15
+ noop = (..._data) => { };
16
+ error = this.defaultError;
17
+ warn = this.defaultWarn;
18
+ info = this.defaultInfo;
19
+ verbose = this.noop;
20
+ debug = this.noop;
21
+ constructor() { }
22
+ level(logLevel) {
23
+ this.warn = logLevel > 0 ? this.defaultWarn : this.noop;
24
+ this.info = logLevel > 1 ? this.defaultInfo : this.noop;
25
+ this.verbose = logLevel > 2 ? this.defaultVerbose : this.noop;
26
+ this.debug = logLevel > 3 ? this.defaultDebug : this.noop;
27
+ }
28
+ }
29
+ export const logger = new Logger();
@@ -0,0 +1,7 @@
1
+ export { assert } from "./assert.js";
2
+ export { Deferred } from "./deferred.js";
3
+ export { Logger, logger, LogLevel } from "./logger.js";
4
+ export { AsyncQueue } from "./asyncQueue.js";
5
+ export { nextTick } from "./nextTick.js";
6
+ export { parseArgs } from "./args.js";
7
+ export { getArgs } from "./platform.js";
@@ -0,0 +1,3 @@
1
+ export function nextTick() {
2
+ return new Promise((resolve) => setTimeout(resolve, 0));
3
+ }
@@ -0,0 +1,4 @@
1
+ import { argv } from "node:process";
2
+ export function getArgs() {
3
+ return argv.slice(2);
4
+ }
@@ -112,7 +112,10 @@ export class MqttConn implements IMqttConn {
112
112
  async send(data: AnyPacket): Promise<void> {
113
113
  try {
114
114
  await this.conn.write(encode(data));
115
- } catch {
115
+ } catch (err) {
116
+ if (err instanceof Error) {
117
+ this._reason = err.message;
118
+ }
116
119
  this.close();
117
120
  }
118
121
  }
package/node/client.ts CHANGED
@@ -1,7 +1,9 @@
1
+ // this a NodeJS specific implementation of TCP client sockets
2
+ // it extends the platform agnostic Client class
1
3
  import { Client } from "../client/client.ts";
2
4
  import { logger } from "../client/deps.ts";
3
5
  import { readFile } from "node:fs/promises";
4
- import { connect } from "node:net";
6
+ import { createConnection } from "node:net";
5
7
  import * as tls from "node:tls";
6
8
  import type { SockConn } from "../socket/socket.ts";
7
9
  import { wrapNodeSocket } from "./wrapNodeSocket.ts";
@@ -18,16 +20,29 @@ export async function getCaCerts(filename: string | undefined) {
18
20
  }
19
21
 
20
22
  export class TcpClient extends Client {
21
- protected async connectMQTT(hostname: string, port = 1883) {
23
+ protected connectMQTT(hostname: string, port = 1883): Promise<SockConn> {
22
24
  logger.debug({ hostname, port });
23
- return wrapNodeSocket(await connect({ host: hostname, port }));
25
+ return new Promise((resolve, reject) => {
26
+ const socket = createConnection(
27
+ { port, host: hostname },
28
+ () => {
29
+ logger.debug("Connected to server");
30
+ resolve(wrapNodeSocket(socket));
31
+ },
32
+ );
33
+ socket.once("error", (err) => {
34
+ // @ts-ignore the type spec of err is missing err.code
35
+ logger.debug("Connection failed: ", err);
36
+ reject(err);
37
+ });
38
+ });
24
39
  }
25
40
 
26
- protected async connectMQTTS(
41
+ protected connectMQTTS(
27
42
  hostname: string,
28
43
  port = 8883,
29
44
  caCerts?: string[],
30
- ) {
45
+ ): Promise<SockConn> {
31
46
  const opts = {
32
47
  host: hostname,
33
48
  port,
@@ -36,7 +51,16 @@ export class TcpClient extends Client {
36
51
  : undefined,
37
52
  };
38
53
  logger.debug({ hostname, port, caCerts });
39
- return wrapNodeSocket(await tls.connect(opts));
54
+ return new Promise((resolve, reject) => {
55
+ const socket = tls.connect(opts, () => {
56
+ logger.debug("Connected to server");
57
+ resolve(wrapNodeSocket(socket));
58
+ });
59
+ socket.once("error", (err) => {
60
+ logger.debug("Connection failed", err);
61
+ reject(err);
62
+ });
63
+ });
40
64
  }
41
65
 
42
66
  protected override createConn(
package/node/server.ts CHANGED
@@ -1,3 +1,5 @@
1
+ // This a NodeJS specific implementation of a TCP socket listener
2
+ // it uses the platform agnostic MqttServer class
1
3
  import type { Server } from "node:net";
2
4
  import { createServer } from "node:net";
3
5
  import type { MqttServerOptions } from "../server/mod.ts";
@@ -47,7 +47,7 @@ export function wrapNodeSocket(socket: Socket): SockConn {
47
47
  const conn: SockConn = {
48
48
  readable: readable as ReadableStream<Uint8Array>,
49
49
  writable: writable as WritableStream<Uint8Array>,
50
- closer: () => closer(socket),
50
+ close: () => closer(socket),
51
51
  remoteAddr,
52
52
  };
53
53
  return conn;
package/package.json CHANGED
@@ -1,12 +1,16 @@
1
1
  {
2
2
  "name": "@seriousme/opifex",
3
- "version": "1.2.1",
3
+ "version": "1.3.0",
4
4
  "description": "MQTT client & server for Deno & NodeJS",
5
5
  "type": "module",
6
6
  "scripts": {
7
7
  "test": "node --experimental-strip-types --test --test-skip-pattern='/^Deno/'",
8
- "build": "npx pkgroll --clean-dist --src .",
9
- "postbuild": "deno fmt"
8
+ "prebuild": "rm -rf dist",
9
+ "build": "npx -p typescript@beta tsc --build",
10
+ "postbuild": "deno fmt",
11
+ "preversion": "npm run test",
12
+ "version": "npm run build",
13
+ "postversion": "jq '( { name:.name , version:.version} + .deno)' package.json > deno.json"
10
14
  },
11
15
  "keywords": [
12
16
  "MQTT",
@@ -21,6 +25,15 @@
21
25
  "./server": "./dist/server/mod.js",
22
26
  "./client": "./dist/client/mod.js"
23
27
  },
28
+ "deno": {
29
+ "exports": {
30
+ "./server": "./server/mod.ts",
31
+ "./client": "./client/mod.ts"
32
+ },
33
+ "exclude": [
34
+ "dist"
35
+ ]
36
+ },
24
37
  "author": "Hans Klunder",
25
38
  "license": "MIT",
26
39
  "repository": {
package/server/mod.ts CHANGED
@@ -1,6 +1,5 @@
1
1
  /**
2
- * This module provides an MQTT Server interface
3
- * see the /bin folder for examples
2
+ * This module provides an MQTT Server interface see the /bin folder for examples
4
3
  * @module
5
4
  */
6
5
  export { AuthenticationResult } from "./deps.ts";
package/socket/socket.ts CHANGED
@@ -13,7 +13,7 @@ export interface UnixAddr {
13
13
  export type SockConn = {
14
14
  readable: ReadableStream<Uint8Array>;
15
15
  writable: WritableStream<Uint8Array>;
16
- closer: () => void;
16
+ close: () => void;
17
17
  localAddr?: SockAddr;
18
18
  remoteAddr?: SockAddr;
19
19
  };
@@ -29,7 +29,8 @@ export class Conn {
29
29
  this.closed = false;
30
30
  this.reader = sockConn.readable.getReader({ mode: "byob" });
31
31
  this.writer = sockConn.writable.getWriter();
32
- this.closer = sockConn.closer;
32
+ // this.writer.closed.then(() => this.closed = true);
33
+ this.closer = sockConn.close.bind(sockConn);
33
34
  this.remoteAddr = sockConn.remoteAddr;
34
35
  }
35
36
 
package/timer/timer.ts CHANGED
@@ -2,7 +2,7 @@ export class Timer {
2
2
  readonly delay: number; // delay in microseconds
3
3
  // deno-lint-ignore ban-types
4
4
  private action: Function; // function to perform when timer expires
5
- private timer = 0;
5
+ private timer?: ReturnType<typeof setTimeout>;
6
6
  private end = 0;
7
7
  private running = false;
8
8
 
package/tsconfig.json CHANGED
@@ -5,12 +5,15 @@
5
5
  "module": "esnext",
6
6
  "moduleResolution": "node",
7
7
  "resolveJsonModule": true,
8
+ "allowImportingTsExtensions": true,
9
+ "rewriteRelativeImportExtensions": true,
8
10
  "strict": true,
9
11
  "outDir": "dist",
10
12
  "esModuleInterop": true,
11
13
  "isolatedModules": true,
12
14
  "skipLibCheck": true
13
15
  },
16
+ "include": ["bin/*.ts"],
14
17
  "exclude": [
15
18
  "dist",
16
19
  "deno",
@@ -1,10 +0,0 @@
1
- {
2
- // See https://go.microsoft.com/fwlink/?LinkId=827846 to learn about workspace recommendations.
3
- // Extension identifier format: ${publisher}.${name}. Example: vscode.csharp
4
-
5
- // List of extensions which should be recommended for users of this workspace.
6
- "recommendations": ["denoland.vscode-deno"],
7
-
8
- // List of extensions recommended by VS Code that should not be recommended for users of this workspace.
9
- "unwantedRecommendations": []
10
- }
@@ -1,12 +0,0 @@
1
- {
2
- "deno.enable": true,
3
- "deno.suggest.imports.hosts": {
4
- "https://deno.land": true,
5
- "https://io": false,
6
- "https://d": false,
7
- "https://de": false,
8
- "https://deno": false,
9
- "https://deno.": false,
10
- "https://deno.la": false
11
- }
12
- }
@@ -1,12 +0,0 @@
1
- import type { SockConn } from "../socket/socket.ts";
2
-
3
- export function wrapDenoConn(denoConn: Deno.Conn) {
4
- const conn: SockConn = {
5
- readable: denoConn.readable,
6
- writable: denoConn.writable,
7
- closer: denoConn.close.bind(denoConn),
8
- localAddr: denoConn.localAddr,
9
- remoteAddr: denoConn.remoteAddr,
10
- };
11
- return conn;
12
- }