@totemsdk/edge-coap 0.1.0 → 0.2.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.
package/dist/index.d.ts CHANGED
@@ -3,3 +3,5 @@ export { createCoapGateway } from './gateway.js';
3
3
  export type { CoapGatewayConfig, CoapGateway } from './gateway.js';
4
4
  export { createCoapSensorBridge } from './sensor-bridge.js';
5
5
  export type { CoapSensorBinding, CoapSensorBridgeConfig, CoapSensorBridge } from './sensor-bridge.js';
6
+ export { NativeCoapTransport } from './native-transport.js';
7
+ export type { NativeCoapConfig } from './native-transport.js';
package/dist/index.js CHANGED
@@ -1,7 +1,9 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.createCoapSensorBridge = exports.createCoapGateway = void 0;
3
+ exports.NativeCoapTransport = exports.createCoapSensorBridge = exports.createCoapGateway = void 0;
4
4
  var gateway_js_1 = require("./gateway.js");
5
5
  Object.defineProperty(exports, "createCoapGateway", { enumerable: true, get: function () { return gateway_js_1.createCoapGateway; } });
6
6
  var sensor_bridge_js_1 = require("./sensor-bridge.js");
7
7
  Object.defineProperty(exports, "createCoapSensorBridge", { enumerable: true, get: function () { return sensor_bridge_js_1.createCoapSensorBridge; } });
8
+ var native_transport_js_1 = require("./native-transport.js");
9
+ Object.defineProperty(exports, "NativeCoapTransport", { enumerable: true, get: function () { return native_transport_js_1.NativeCoapTransport; } });
@@ -0,0 +1,31 @@
1
+ /**
2
+ * NativeCoapTransport — connects to the edge-coap Go binary over TCP.
3
+ *
4
+ * The Go binary listens on a local TCP socket (default 127.0.0.1:15003)
5
+ * and accepts newline-delimited JSON requests. This class implements
6
+ * CoapTransportPort by forwarding all calls to the Go process.
7
+ */
8
+ import type { CoapTransportPort } from './transport.js';
9
+ export interface NativeCoapConfig {
10
+ host?: string;
11
+ port?: number;
12
+ connectTimeoutMs?: number;
13
+ requestTimeoutMs?: number;
14
+ }
15
+ export declare class NativeCoapTransport implements CoapTransportPort {
16
+ private socket;
17
+ private buffer;
18
+ private pending;
19
+ private messageHandlers;
20
+ private errorHandlers;
21
+ private readonly config;
22
+ constructor(config?: NativeCoapConfig);
23
+ bind(_port: number): Promise<void>;
24
+ close(): Promise<void>;
25
+ send(host: string, port: number, message: Uint8Array): Promise<void>;
26
+ onMessage(handler: (message: Uint8Array, remote: {
27
+ host: string;
28
+ port: number;
29
+ }) => void): () => void;
30
+ onError(handler: (err: Error) => void): () => void;
31
+ }
@@ -0,0 +1,127 @@
1
+ "use strict";
2
+ /**
3
+ * NativeCoapTransport — connects to the edge-coap Go binary over TCP.
4
+ *
5
+ * The Go binary listens on a local TCP socket (default 127.0.0.1:15003)
6
+ * and accepts newline-delimited JSON requests. This class implements
7
+ * CoapTransportPort by forwarding all calls to the Go process.
8
+ */
9
+ Object.defineProperty(exports, "__esModule", { value: true });
10
+ exports.NativeCoapTransport = void 0;
11
+ let requestCounter = 0;
12
+ class NativeCoapTransport {
13
+ constructor(config = {}) {
14
+ this.socket = null;
15
+ this.buffer = '';
16
+ this.pending = new Map();
17
+ this.messageHandlers = [];
18
+ this.errorHandlers = [];
19
+ this.config = {
20
+ host: config.host ?? '127.0.0.1',
21
+ port: config.port ?? 15003,
22
+ connectTimeoutMs: config.connectTimeoutMs ?? 5000,
23
+ requestTimeoutMs: config.requestTimeoutMs ?? 10000,
24
+ };
25
+ }
26
+ async bind(_port) {
27
+ const net = await import('net');
28
+ return new Promise((resolve, reject) => {
29
+ const timer = setTimeout(() => {
30
+ this.socket?.destroy();
31
+ reject(new Error(`NativeCoapTransport: connect timeout`));
32
+ }, this.config.connectTimeoutMs);
33
+ this.socket = net.createConnection({ host: this.config.host, port: this.config.port }, () => {
34
+ clearTimeout(timer);
35
+ resolve();
36
+ });
37
+ this.socket.on('data', (chunk) => {
38
+ this.buffer += chunk.toString('utf-8');
39
+ const lines = this.buffer.split('\n');
40
+ this.buffer = lines.pop() ?? '';
41
+ for (const line of lines) {
42
+ if (!line.trim())
43
+ continue;
44
+ try {
45
+ const msg = JSON.parse(line);
46
+ if (msg.type === 'message') {
47
+ const push = msg;
48
+ const data = hexToBytes(push.data);
49
+ for (const handler of this.messageHandlers) {
50
+ try {
51
+ handler(data, { host: push.host, port: push.port });
52
+ }
53
+ catch { }
54
+ }
55
+ }
56
+ else if (msg.id && this.pending.has(msg.id)) {
57
+ const { resolve: res, reject: rej } = this.pending.get(msg.id);
58
+ this.pending.delete(msg.id);
59
+ if (msg.ok)
60
+ res();
61
+ else
62
+ rej(new Error(msg.error ?? 'unknown error'));
63
+ }
64
+ }
65
+ catch { }
66
+ }
67
+ });
68
+ this.socket.on('error', (err) => {
69
+ for (const handler of this.errorHandlers) {
70
+ try {
71
+ handler(err);
72
+ }
73
+ catch { }
74
+ }
75
+ });
76
+ this.socket.on('close', () => {
77
+ for (const [, p] of this.pending)
78
+ p.reject(new Error('connection closed'));
79
+ this.pending.clear();
80
+ });
81
+ });
82
+ }
83
+ async close() {
84
+ if (this.socket) {
85
+ this.socket.destroy();
86
+ this.socket = null;
87
+ }
88
+ }
89
+ async send(host, port, message) {
90
+ if (!this.socket)
91
+ throw new Error('NativeCoapTransport: not connected');
92
+ const id = `coap-${++requestCounter}`;
93
+ const req = { id, host, port, data: bytesToHex(message) };
94
+ return new Promise((resolve, reject) => {
95
+ const timer = setTimeout(() => {
96
+ this.pending.delete(id);
97
+ reject(new Error(`NativeCoapTransport: request ${id} timed out`));
98
+ }, this.config.requestTimeoutMs);
99
+ this.pending.set(id, {
100
+ resolve: () => { clearTimeout(timer); resolve(); },
101
+ reject: (err) => { clearTimeout(timer); reject(err); },
102
+ });
103
+ this.socket.write(JSON.stringify(req) + '\n');
104
+ });
105
+ }
106
+ onMessage(handler) {
107
+ this.messageHandlers.push(handler);
108
+ return () => { this.messageHandlers = this.messageHandlers.filter(h => h !== handler); };
109
+ }
110
+ onError(handler) {
111
+ this.errorHandlers.push(handler);
112
+ return () => { this.errorHandlers = this.errorHandlers.filter(h => h !== handler); };
113
+ }
114
+ }
115
+ exports.NativeCoapTransport = NativeCoapTransport;
116
+ function bytesToHex(bytes) {
117
+ return Array.from(bytes).map(b => b.toString(16).padStart(2, '0')).join('');
118
+ }
119
+ function hexToBytes(hex) {
120
+ if (hex.length % 2 !== 0)
121
+ throw new Error('Invalid hex string');
122
+ const arr = new Uint8Array(hex.length / 2);
123
+ for (let i = 0; i < arr.length; i++) {
124
+ arr[i] = parseInt(hex.slice(i * 2, i * 2 + 2), 16);
125
+ }
126
+ return arr;
127
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@totemsdk/edge-coap",
3
- "version": "0.1.0",
3
+ "version": "0.2.0",
4
4
  "description": "Edge runtime adapter for CoAP — constrained devices, RFC 7252, UDP transport",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",
@@ -11,15 +11,13 @@
11
11
  "import": "./dist/index.js"
12
12
  }
13
13
  },
14
- "scripts": {
15
- "build": "tsc",
16
- "prepare": "tsc",
17
- "clean": "rm -rf dist",
18
- "test": "jest --passWithNoTests"
19
- },
20
- "files": ["dist", "README.md", "LICENSE"],
14
+ "files": [
15
+ "dist",
16
+ "README.md",
17
+ "LICENSE"
18
+ ],
21
19
  "dependencies": {
22
- "@totemsdk/edge": "^0.1.3"
20
+ "@totemsdk/edge": "^1.0.0"
23
21
  },
24
22
  "devDependencies": {
25
23
  "@types/jest": "^30.0.0",
@@ -28,16 +26,36 @@
28
26
  "ts-jest": "^29.0.0",
29
27
  "typescript": "^7.0.2"
30
28
  },
31
- "engines": { "node": ">=18.0.0" },
32
- "publishConfig": { "access": "public" },
29
+ "engines": {
30
+ "node": ">=18.0.0"
31
+ },
32
+ "publishConfig": {
33
+ "access": "public"
34
+ },
33
35
  "license": "MIT",
34
36
  "author": "Totem SDK",
35
37
  "homepage": "https://totem.ing",
36
38
  "repository": {
37
39
  "type": "git",
38
- "url": "git+https://github.com/totem-sdk/totem-sdk.git",
39
- "directory": "packages/totem-sdk/packages/edge-coap"
40
+ "url": "git+https://github.com/Totem-Edge/totem-sdk.git",
41
+ "directory": "packages/edge-coap"
42
+ },
43
+ "keywords": [
44
+ "totem",
45
+ "totemsdk",
46
+ "minima",
47
+ "blockchain",
48
+ "edge",
49
+ "coap",
50
+ "transport"
51
+ ],
52
+ "bugs": {
53
+ "url": "https://github.com/Totem-Edge/totem-sdk/issues"
40
54
  },
41
- "keywords": ["totem", "totemsdk", "minima", "blockchain", "edge", "coap", "transport"],
42
- "bugs": { "url": "https://github.com/totem-sdk/totem-sdk/issues" }
43
- }
55
+ "scripts": {
56
+ "build": "tsc",
57
+ "clean": "rm -rf dist bin",
58
+ "test": "jest",
59
+ "build:go": "cd go && go build -o ../bin/edge-coap ."
60
+ }
61
+ }