edilkamin 1.6.0 → 1.6.2
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/.github/dependabot.yml +25 -0
- package/.github/workflows/cli-tests.yml +2 -2
- package/.github/workflows/documentation.yml +2 -2
- package/.github/workflows/publish.yml +2 -2
- package/.github/workflows/tests.yml +2 -2
- package/README.md +30 -0
- package/dist/esm/buffer-utils.d.ts +25 -0
- package/dist/esm/buffer-utils.js +70 -0
- package/dist/esm/buffer-utils.test.d.ts +1 -0
- package/dist/esm/buffer-utils.test.js +181 -0
- package/dist/esm/cli.js +47 -5
- package/dist/esm/constants.d.ts +3 -1
- package/dist/esm/constants.js +4 -2
- package/dist/esm/index.d.ts +5 -3
- package/dist/esm/index.js +4 -2
- package/dist/esm/library.d.ts +9 -7
- package/dist/esm/library.js +59 -5
- package/dist/esm/library.test.js +260 -1
- package/dist/esm/serial-utils.d.ts +33 -0
- package/dist/esm/serial-utils.js +45 -0
- package/dist/esm/serial-utils.test.d.ts +1 -0
- package/dist/esm/serial-utils.test.js +48 -0
- package/dist/esm/types.d.ts +49 -1
- package/package.json +7 -5
- package/src/buffer-utils.test.ts +225 -0
- package/src/buffer-utils.ts +83 -0
- package/src/cli.ts +97 -11
- package/src/constants.ts +5 -2
- package/src/index.ts +14 -1
- package/src/library.test.ts +323 -1
- package/src/library.ts +93 -8
- package/src/serial-utils.test.ts +64 -0
- package/src/serial-utils.ts +50 -0
- package/src/types.ts +60 -0
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
version: 2
|
|
2
|
+
updates:
|
|
3
|
+
# npm dependencies
|
|
4
|
+
- package-ecosystem: "npm"
|
|
5
|
+
directory: "/"
|
|
6
|
+
schedule:
|
|
7
|
+
interval: "weekly"
|
|
8
|
+
day: "monday"
|
|
9
|
+
time: "09:00"
|
|
10
|
+
timezone: "UTC"
|
|
11
|
+
open-pull-requests-limit: 5
|
|
12
|
+
commit-message:
|
|
13
|
+
prefix: ":arrow_up:"
|
|
14
|
+
|
|
15
|
+
# GitHub Actions dependencies
|
|
16
|
+
- package-ecosystem: "github-actions"
|
|
17
|
+
directory: "/"
|
|
18
|
+
schedule:
|
|
19
|
+
interval: "weekly"
|
|
20
|
+
day: "monday"
|
|
21
|
+
time: "09:00"
|
|
22
|
+
timezone: "UTC"
|
|
23
|
+
open-pull-requests-limit: 5
|
|
24
|
+
commit-message:
|
|
25
|
+
prefix: ":arrow_up:"
|
|
@@ -12,8 +12,8 @@ jobs:
|
|
|
12
12
|
matrix:
|
|
13
13
|
node-version: [20.x, 22.x]
|
|
14
14
|
steps:
|
|
15
|
-
- uses: actions/checkout@
|
|
16
|
-
- uses: actions/setup-node@
|
|
15
|
+
- uses: actions/checkout@v6
|
|
16
|
+
- uses: actions/setup-node@v6
|
|
17
17
|
with:
|
|
18
18
|
node-version: ${{ matrix.node-version }}
|
|
19
19
|
- run: yarn install --no-ignore-optional
|
|
@@ -9,8 +9,8 @@ jobs:
|
|
|
9
9
|
runs-on: ubuntu-latest
|
|
10
10
|
timeout-minutes: 5
|
|
11
11
|
steps:
|
|
12
|
-
- uses: actions/checkout@
|
|
13
|
-
- uses: actions/setup-node@
|
|
12
|
+
- uses: actions/checkout@v6
|
|
13
|
+
- uses: actions/setup-node@v6
|
|
14
14
|
with:
|
|
15
15
|
node-version: "22.x"
|
|
16
16
|
registry-url: "https://registry.npmjs.org"
|
|
@@ -12,8 +12,8 @@ jobs:
|
|
|
12
12
|
matrix:
|
|
13
13
|
node-version: [20.x, 22.x]
|
|
14
14
|
steps:
|
|
15
|
-
- uses: actions/checkout@
|
|
16
|
-
- uses: actions/setup-node@
|
|
15
|
+
- uses: actions/checkout@v6
|
|
16
|
+
- uses: actions/setup-node@v6
|
|
17
17
|
with:
|
|
18
18
|
node-version: ${{ matrix.node-version }}
|
|
19
19
|
- run: yarn install
|
package/README.md
CHANGED
|
@@ -61,6 +61,36 @@ Or with `npx` once the library is installed:
|
|
|
61
61
|
npx edilkamin deviceInfo --mac $MAC --username $USERNAME --password $PASSWORD
|
|
62
62
|
```
|
|
63
63
|
|
|
64
|
+
## API Versions
|
|
65
|
+
|
|
66
|
+
This library supports both the new and legacy Edilkamin API endpoints.
|
|
67
|
+
|
|
68
|
+
### CLI Usage
|
|
69
|
+
|
|
70
|
+
```sh
|
|
71
|
+
# New API (default)
|
|
72
|
+
yarn cli deviceInfo --mac $MAC --username $USERNAME --password $PASSWORD
|
|
73
|
+
|
|
74
|
+
# Legacy API
|
|
75
|
+
yarn cli deviceInfo --mac $MAC --username $USERNAME --password $PASSWORD --legacy
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
### Library Usage
|
|
79
|
+
|
|
80
|
+
```js
|
|
81
|
+
import { configure, signIn, OLD_API_URL, NEW_API_URL } from "edilkamin";
|
|
82
|
+
|
|
83
|
+
// New API (default)
|
|
84
|
+
const token = await signIn(username, password);
|
|
85
|
+
const api = configure();
|
|
86
|
+
|
|
87
|
+
// Legacy API
|
|
88
|
+
const legacyToken = await signIn(username, password, true);
|
|
89
|
+
const legacyApi = configure(OLD_API_URL);
|
|
90
|
+
```
|
|
91
|
+
|
|
92
|
+
> **Note**: The legacy API uses AWS API Gateway and may be deprecated in the future.
|
|
93
|
+
|
|
64
94
|
## Motivations
|
|
65
95
|
|
|
66
96
|
- providing an open source web alternative
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import { BufferEncodedType } from "./types";
|
|
2
|
+
/**
|
|
3
|
+
* Type guard to check if a value is a serialized Node.js Buffer.
|
|
4
|
+
* Node.js Buffers serialize to JSON as: {type: "Buffer", data: [...]}
|
|
5
|
+
*
|
|
6
|
+
* @param value - The value to check
|
|
7
|
+
* @returns True if the value is a Buffer-encoded object
|
|
8
|
+
*/
|
|
9
|
+
declare const isBuffer: (value: unknown) => value is BufferEncodedType;
|
|
10
|
+
/**
|
|
11
|
+
* Decompresses a Buffer-encoded gzip object and parses the resulting JSON.
|
|
12
|
+
*
|
|
13
|
+
* @param bufferObj - A serialized Buffer object containing gzip data
|
|
14
|
+
* @returns The decompressed and parsed JSON data, or the original object on failure
|
|
15
|
+
*/
|
|
16
|
+
declare const decompressBuffer: (bufferObj: BufferEncodedType) => unknown;
|
|
17
|
+
/**
|
|
18
|
+
* Recursively processes an API response to decompress any Buffer-encoded fields.
|
|
19
|
+
* Handles nested objects and arrays, preserving structure while decompressing.
|
|
20
|
+
*
|
|
21
|
+
* @param data - The API response data to process
|
|
22
|
+
* @returns The processed data with all Buffer fields decompressed
|
|
23
|
+
*/
|
|
24
|
+
declare const processResponse: <T>(data: T) => T;
|
|
25
|
+
export { decompressBuffer, isBuffer, processResponse };
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
import pako from "pako";
|
|
2
|
+
/**
|
|
3
|
+
* Type guard to check if a value is a serialized Node.js Buffer.
|
|
4
|
+
* Node.js Buffers serialize to JSON as: {type: "Buffer", data: [...]}
|
|
5
|
+
*
|
|
6
|
+
* @param value - The value to check
|
|
7
|
+
* @returns True if the value is a Buffer-encoded object
|
|
8
|
+
*/
|
|
9
|
+
const isBuffer = (value) => {
|
|
10
|
+
return (typeof value === "object" &&
|
|
11
|
+
value !== null &&
|
|
12
|
+
"type" in value &&
|
|
13
|
+
value.type === "Buffer" &&
|
|
14
|
+
"data" in value &&
|
|
15
|
+
Array.isArray(value.data));
|
|
16
|
+
};
|
|
17
|
+
/**
|
|
18
|
+
* Decompresses a Buffer-encoded gzip object and parses the resulting JSON.
|
|
19
|
+
*
|
|
20
|
+
* @param bufferObj - A serialized Buffer object containing gzip data
|
|
21
|
+
* @returns The decompressed and parsed JSON data, or the original object on failure
|
|
22
|
+
*/
|
|
23
|
+
const decompressBuffer = (bufferObj) => {
|
|
24
|
+
try {
|
|
25
|
+
// Convert data array to Uint8Array for pako
|
|
26
|
+
const compressed = new Uint8Array(bufferObj.data);
|
|
27
|
+
// Decompress with gzip
|
|
28
|
+
const decompressed = pako.ungzip(compressed, { to: "string" });
|
|
29
|
+
// Parse JSON
|
|
30
|
+
return JSON.parse(decompressed);
|
|
31
|
+
}
|
|
32
|
+
catch (error) {
|
|
33
|
+
// Log warning but return original to maintain backward compatibility
|
|
34
|
+
console.warn("Failed to decompress buffer:", error);
|
|
35
|
+
return bufferObj;
|
|
36
|
+
}
|
|
37
|
+
};
|
|
38
|
+
/**
|
|
39
|
+
* Recursively processes an API response to decompress any Buffer-encoded fields.
|
|
40
|
+
* Handles nested objects and arrays, preserving structure while decompressing.
|
|
41
|
+
*
|
|
42
|
+
* @param data - The API response data to process
|
|
43
|
+
* @returns The processed data with all Buffer fields decompressed
|
|
44
|
+
*/
|
|
45
|
+
const processResponse = (data) => {
|
|
46
|
+
if (data === null || data === undefined) {
|
|
47
|
+
return data;
|
|
48
|
+
}
|
|
49
|
+
// Check if this is a Buffer object
|
|
50
|
+
if (isBuffer(data)) {
|
|
51
|
+
const decompressed = decompressBuffer(data);
|
|
52
|
+
// Recursively process the decompressed result (may contain nested buffers)
|
|
53
|
+
return processResponse(decompressed);
|
|
54
|
+
}
|
|
55
|
+
// Recursively process arrays
|
|
56
|
+
if (Array.isArray(data)) {
|
|
57
|
+
return data.map((item) => processResponse(item));
|
|
58
|
+
}
|
|
59
|
+
// Recursively process objects
|
|
60
|
+
if (typeof data === "object") {
|
|
61
|
+
const processed = {};
|
|
62
|
+
for (const [key, value] of Object.entries(data)) {
|
|
63
|
+
processed[key] = processResponse(value);
|
|
64
|
+
}
|
|
65
|
+
return processed;
|
|
66
|
+
}
|
|
67
|
+
// Primitive value, return as-is
|
|
68
|
+
return data;
|
|
69
|
+
};
|
|
70
|
+
export { decompressBuffer, isBuffer, processResponse };
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,181 @@
|
|
|
1
|
+
import { strict as assert } from "assert";
|
|
2
|
+
import pako from "pako";
|
|
3
|
+
import sinon from "sinon";
|
|
4
|
+
import { decompressBuffer, isBuffer, processResponse } from "./buffer-utils";
|
|
5
|
+
/**
|
|
6
|
+
* Helper to create a gzip-compressed Buffer object for testing.
|
|
7
|
+
*/
|
|
8
|
+
const createGzippedBuffer = (data) => {
|
|
9
|
+
const json = JSON.stringify(data);
|
|
10
|
+
const compressed = pako.gzip(json);
|
|
11
|
+
return {
|
|
12
|
+
type: "Buffer",
|
|
13
|
+
data: Array.from(compressed),
|
|
14
|
+
};
|
|
15
|
+
};
|
|
16
|
+
describe("buffer-utils", () => {
|
|
17
|
+
afterEach(() => {
|
|
18
|
+
sinon.restore();
|
|
19
|
+
});
|
|
20
|
+
describe("isBuffer", () => {
|
|
21
|
+
it("should detect valid Buffer objects", () => {
|
|
22
|
+
const buffer = { type: "Buffer", data: [31, 139, 8, 0] };
|
|
23
|
+
assert.ok(isBuffer(buffer));
|
|
24
|
+
});
|
|
25
|
+
it("should detect empty Buffer objects", () => {
|
|
26
|
+
const buffer = { type: "Buffer", data: [] };
|
|
27
|
+
assert.ok(isBuffer(buffer));
|
|
28
|
+
});
|
|
29
|
+
it("should reject non-Buffer objects with wrong type", () => {
|
|
30
|
+
assert.ok(!isBuffer({ type: "NotBuffer", data: [] }));
|
|
31
|
+
});
|
|
32
|
+
it("should reject objects without type field", () => {
|
|
33
|
+
assert.ok(!isBuffer({ data: [1, 2, 3] }));
|
|
34
|
+
});
|
|
35
|
+
it("should reject objects without data field", () => {
|
|
36
|
+
assert.ok(!isBuffer({ type: "Buffer" }));
|
|
37
|
+
});
|
|
38
|
+
it("should reject objects with non-array data", () => {
|
|
39
|
+
assert.ok(!isBuffer({ type: "Buffer", data: "not an array" }));
|
|
40
|
+
});
|
|
41
|
+
it("should reject null", () => {
|
|
42
|
+
assert.ok(!isBuffer(null));
|
|
43
|
+
});
|
|
44
|
+
it("should reject undefined", () => {
|
|
45
|
+
assert.ok(!isBuffer(undefined));
|
|
46
|
+
});
|
|
47
|
+
it("should reject primitives", () => {
|
|
48
|
+
assert.ok(!isBuffer("string"));
|
|
49
|
+
assert.ok(!isBuffer(123));
|
|
50
|
+
assert.ok(!isBuffer(true));
|
|
51
|
+
});
|
|
52
|
+
});
|
|
53
|
+
describe("decompressBuffer", () => {
|
|
54
|
+
it("should decompress gzipped JSON buffer", () => {
|
|
55
|
+
const originalData = { test: "value", nested: { key: 123 } };
|
|
56
|
+
const bufferObj = createGzippedBuffer(originalData);
|
|
57
|
+
const result = decompressBuffer(bufferObj);
|
|
58
|
+
assert.deepEqual(result, originalData);
|
|
59
|
+
});
|
|
60
|
+
it("should handle gzipped arrays", () => {
|
|
61
|
+
const originalData = [1, 2, 3, "test"];
|
|
62
|
+
const bufferObj = createGzippedBuffer(originalData);
|
|
63
|
+
const result = decompressBuffer(bufferObj);
|
|
64
|
+
assert.deepEqual(result, originalData);
|
|
65
|
+
});
|
|
66
|
+
it("should handle gzipped strings", () => {
|
|
67
|
+
const originalData = "test string";
|
|
68
|
+
const bufferObj = createGzippedBuffer(originalData);
|
|
69
|
+
const result = decompressBuffer(bufferObj);
|
|
70
|
+
assert.equal(result, originalData);
|
|
71
|
+
});
|
|
72
|
+
it("should return original value if decompression fails", () => {
|
|
73
|
+
const consoleWarnStub = sinon.stub(console, "warn");
|
|
74
|
+
const invalidBuffer = { type: "Buffer", data: [1, 2, 3] };
|
|
75
|
+
const result = decompressBuffer(invalidBuffer);
|
|
76
|
+
assert.deepEqual(result, invalidBuffer);
|
|
77
|
+
assert.ok(consoleWarnStub.calledOnce);
|
|
78
|
+
});
|
|
79
|
+
it("should return original value if JSON parsing fails", () => {
|
|
80
|
+
const consoleWarnStub = sinon.stub(console, "warn");
|
|
81
|
+
// Create valid gzip but invalid JSON
|
|
82
|
+
const invalidJson = "not valid json {";
|
|
83
|
+
const compressed = pako.gzip(invalidJson);
|
|
84
|
+
const bufferObj = {
|
|
85
|
+
type: "Buffer",
|
|
86
|
+
data: Array.from(compressed),
|
|
87
|
+
};
|
|
88
|
+
const result = decompressBuffer(bufferObj);
|
|
89
|
+
assert.deepEqual(result, bufferObj);
|
|
90
|
+
assert.ok(consoleWarnStub.calledOnce);
|
|
91
|
+
});
|
|
92
|
+
});
|
|
93
|
+
describe("processResponse", () => {
|
|
94
|
+
it("should pass through null", () => {
|
|
95
|
+
assert.equal(processResponse(null), null);
|
|
96
|
+
});
|
|
97
|
+
it("should pass through undefined", () => {
|
|
98
|
+
assert.equal(processResponse(undefined), undefined);
|
|
99
|
+
});
|
|
100
|
+
it("should pass through primitives", () => {
|
|
101
|
+
assert.equal(processResponse("string"), "string");
|
|
102
|
+
assert.equal(processResponse(123), 123);
|
|
103
|
+
assert.equal(processResponse(true), true);
|
|
104
|
+
});
|
|
105
|
+
it("should pass through plain objects", () => {
|
|
106
|
+
const obj = { key: "value", nested: { num: 42 } };
|
|
107
|
+
assert.deepEqual(processResponse(obj), obj);
|
|
108
|
+
});
|
|
109
|
+
it("should pass through plain arrays", () => {
|
|
110
|
+
const arr = [1, "two", { three: 3 }];
|
|
111
|
+
assert.deepEqual(processResponse(arr), arr);
|
|
112
|
+
});
|
|
113
|
+
it("should decompress Buffer at root level", () => {
|
|
114
|
+
const originalData = { decompressed: true };
|
|
115
|
+
const buffer = createGzippedBuffer(originalData);
|
|
116
|
+
const result = processResponse(buffer);
|
|
117
|
+
assert.deepEqual(result, originalData);
|
|
118
|
+
});
|
|
119
|
+
it("should decompress nested Buffer fields", () => {
|
|
120
|
+
const statusData = { commands: { power: true } };
|
|
121
|
+
const response = {
|
|
122
|
+
plain: "data",
|
|
123
|
+
status: createGzippedBuffer(statusData),
|
|
124
|
+
};
|
|
125
|
+
const result = processResponse(response);
|
|
126
|
+
assert.equal(result.plain, "data");
|
|
127
|
+
assert.deepEqual(result.status, statusData);
|
|
128
|
+
});
|
|
129
|
+
it("should recursively decompress deeply nested Buffers", () => {
|
|
130
|
+
const innerData = { value: 42 };
|
|
131
|
+
const middleData = { inner: createGzippedBuffer(innerData) };
|
|
132
|
+
const response = {
|
|
133
|
+
outer: createGzippedBuffer(middleData),
|
|
134
|
+
};
|
|
135
|
+
const result = processResponse(response);
|
|
136
|
+
assert.deepEqual(result, { outer: { inner: { value: 42 } } });
|
|
137
|
+
});
|
|
138
|
+
it("should handle arrays containing Buffers", () => {
|
|
139
|
+
const itemData = { id: 1 };
|
|
140
|
+
const response = {
|
|
141
|
+
items: [createGzippedBuffer(itemData), { id: 2 }],
|
|
142
|
+
};
|
|
143
|
+
const result = processResponse(response);
|
|
144
|
+
assert.deepEqual(result.items, [{ id: 1 }, { id: 2 }]);
|
|
145
|
+
});
|
|
146
|
+
it("should handle mixed compressed and uncompressed fields", () => {
|
|
147
|
+
const compressedStatus = { commands: { power: true } };
|
|
148
|
+
const response = {
|
|
149
|
+
status: createGzippedBuffer(compressedStatus),
|
|
150
|
+
nvm: { user_parameters: { temperature: 22 } },
|
|
151
|
+
plain_field: "unchanged",
|
|
152
|
+
};
|
|
153
|
+
const result = processResponse(response);
|
|
154
|
+
assert.deepEqual(result.status, compressedStatus);
|
|
155
|
+
assert.deepEqual(result.nvm, { user_parameters: { temperature: 22 } });
|
|
156
|
+
assert.equal(result.plain_field, "unchanged");
|
|
157
|
+
});
|
|
158
|
+
it("should handle real-world DeviceInfo structure with compressed status", () => {
|
|
159
|
+
const statusData = {
|
|
160
|
+
commands: { power: true },
|
|
161
|
+
temperatures: { board: 25, enviroment: 20 },
|
|
162
|
+
};
|
|
163
|
+
const nvmData = {
|
|
164
|
+
user_parameters: {
|
|
165
|
+
enviroment_1_temperature: 22,
|
|
166
|
+
enviroment_2_temperature: 0,
|
|
167
|
+
enviroment_3_temperature: 0,
|
|
168
|
+
is_auto: false,
|
|
169
|
+
is_sound_active: true,
|
|
170
|
+
},
|
|
171
|
+
};
|
|
172
|
+
const response = {
|
|
173
|
+
status: createGzippedBuffer(statusData),
|
|
174
|
+
nvm: createGzippedBuffer(nvmData),
|
|
175
|
+
};
|
|
176
|
+
const result = processResponse(response);
|
|
177
|
+
assert.deepEqual(result.status, statusData);
|
|
178
|
+
assert.deepEqual(result.nvm, nvmData);
|
|
179
|
+
});
|
|
180
|
+
});
|
|
181
|
+
});
|
package/dist/esm/cli.js
CHANGED
|
@@ -11,6 +11,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
|
|
|
11
11
|
import { Command } from "commander";
|
|
12
12
|
import readline from "readline";
|
|
13
13
|
import { version } from "../package.json";
|
|
14
|
+
import { NEW_API_URL, OLD_API_URL } from "./constants";
|
|
14
15
|
import { configure, signIn } from "./library";
|
|
15
16
|
const promptPassword = () => {
|
|
16
17
|
const rl = readline.createInterface({
|
|
@@ -48,17 +49,24 @@ const addAuthOptions = (command) => command
|
|
|
48
49
|
* @returns The command with the MAC address option added.
|
|
49
50
|
*/
|
|
50
51
|
const addMacOption = (command) => command.requiredOption("-m, --mac <macAddress>", "MAC address of the device");
|
|
52
|
+
/**
|
|
53
|
+
* Adds legacy API option to a command.
|
|
54
|
+
* @param command The command to which the legacy option should be added.
|
|
55
|
+
* @returns The command with the legacy option added.
|
|
56
|
+
*/
|
|
57
|
+
const addLegacyOption = (command) => command.option("--legacy", "Use legacy API endpoint (old AWS Gateway)");
|
|
51
58
|
/**
|
|
52
59
|
* Handles common authentication and API initialization logic.
|
|
53
60
|
* @param options The options passed from the CLI command.
|
|
54
61
|
* @returns An object containing the normalized MAC, JWT token, and configured API instance.
|
|
55
62
|
*/
|
|
56
63
|
const initializeCommand = (options) => __awaiter(void 0, void 0, void 0, function* () {
|
|
57
|
-
const { username, password, mac } = options;
|
|
64
|
+
const { username, password, mac, legacy = false } = options;
|
|
58
65
|
const normalizedMac = mac.replace(/:/g, "");
|
|
59
66
|
const pwd = password || (yield promptPassword());
|
|
60
|
-
const jwtToken = yield signIn(username, pwd);
|
|
61
|
-
const
|
|
67
|
+
const jwtToken = yield signIn(username, pwd, legacy);
|
|
68
|
+
const apiUrl = legacy ? OLD_API_URL : NEW_API_URL;
|
|
69
|
+
const api = configure(apiUrl);
|
|
62
70
|
return { normalizedMac, jwtToken, api };
|
|
63
71
|
});
|
|
64
72
|
/**
|
|
@@ -117,7 +125,7 @@ const createProgram = () => {
|
|
|
117
125
|
getter: (api, jwtToken, mac) => api.getTargetTemperature(jwtToken, mac),
|
|
118
126
|
},
|
|
119
127
|
].forEach(({ commandName, description, getter }) => {
|
|
120
|
-
addMacOption(addAuthOptions(program.command(commandName).description(description))).action((options) => executeGetter(options, getter));
|
|
128
|
+
addLegacyOption(addMacOption(addAuthOptions(program.command(commandName).description(description)))).action((options) => executeGetter(options, getter));
|
|
121
129
|
});
|
|
122
130
|
// Generic setter commands
|
|
123
131
|
[
|
|
@@ -132,8 +140,42 @@ const createProgram = () => {
|
|
|
132
140
|
setter: (api, jwtToken, mac, value) => api.setTargetTemperature(jwtToken, mac, value),
|
|
133
141
|
},
|
|
134
142
|
].forEach(({ commandName, description, setter }) => {
|
|
135
|
-
addMacOption(addAuthOptions(program.command(commandName).description(description)).requiredOption("-v, --value <number>", "Value to set", parseFloat)).action((options) => executeSetter(options, setter));
|
|
143
|
+
addLegacyOption(addMacOption(addAuthOptions(program.command(commandName).description(description)).requiredOption("-v, --value <number>", "Value to set", parseFloat))).action((options) => executeSetter(options, setter));
|
|
136
144
|
});
|
|
145
|
+
// Command: register
|
|
146
|
+
addLegacyOption(addAuthOptions(program
|
|
147
|
+
.command("register")
|
|
148
|
+
.description("Register a device with your account")))
|
|
149
|
+
.requiredOption("-m, --mac <macAddress>", "MAC address of the device")
|
|
150
|
+
.requiredOption("-s, --serial <serialNumber>", "Device serial number")
|
|
151
|
+
.requiredOption("-n, --name <deviceName>", "Device name")
|
|
152
|
+
.requiredOption("-r, --room <deviceRoom>", "Room name")
|
|
153
|
+
.action((options) => __awaiter(void 0, void 0, void 0, function* () {
|
|
154
|
+
const { username, password, mac, serial, name, room, legacy = false, } = options;
|
|
155
|
+
const normalizedMac = mac.replace(/:/g, "");
|
|
156
|
+
const pwd = password || (yield promptPassword());
|
|
157
|
+
const jwtToken = yield signIn(username, pwd, legacy);
|
|
158
|
+
const apiUrl = legacy ? OLD_API_URL : NEW_API_URL;
|
|
159
|
+
const api = configure(apiUrl);
|
|
160
|
+
const result = yield api.registerDevice(jwtToken, normalizedMac, serial, name, room);
|
|
161
|
+
console.log("Device registered successfully:");
|
|
162
|
+
console.log(JSON.stringify(result, null, 2));
|
|
163
|
+
}));
|
|
164
|
+
// Command: editDevice
|
|
165
|
+
addLegacyOption(addMacOption(addAuthOptions(program.command("editDevice").description("Update device name and room"))))
|
|
166
|
+
.requiredOption("-n, --name <deviceName>", "Device name")
|
|
167
|
+
.requiredOption("-r, --room <deviceRoom>", "Room name")
|
|
168
|
+
.action((options) => __awaiter(void 0, void 0, void 0, function* () {
|
|
169
|
+
const { username, password, mac, name, room, legacy = false } = options;
|
|
170
|
+
const normalizedMac = mac.replace(/:/g, "");
|
|
171
|
+
const pwd = password || (yield promptPassword());
|
|
172
|
+
const jwtToken = yield signIn(username, pwd, legacy);
|
|
173
|
+
const apiUrl = legacy ? OLD_API_URL : NEW_API_URL;
|
|
174
|
+
const api = configure(apiUrl);
|
|
175
|
+
const result = yield api.editDevice(jwtToken, normalizedMac, name, room);
|
|
176
|
+
console.log("Device updated successfully:");
|
|
177
|
+
console.log(JSON.stringify(result, null, 2));
|
|
178
|
+
}));
|
|
137
179
|
return program;
|
|
138
180
|
};
|
|
139
181
|
const main = () => {
|
package/dist/esm/constants.d.ts
CHANGED
|
@@ -1,2 +1,4 @@
|
|
|
1
|
+
declare const OLD_API_URL = "https://fxtj7xkgc6.execute-api.eu-central-1.amazonaws.com/prod/";
|
|
2
|
+
declare const NEW_API_URL = "https://the-mind-api.edilkamin.com/";
|
|
1
3
|
declare const API_URL = "https://the-mind-api.edilkamin.com/";
|
|
2
|
-
export { API_URL };
|
|
4
|
+
export { API_URL, NEW_API_URL, OLD_API_URL };
|
package/dist/esm/constants.js
CHANGED
|
@@ -1,2 +1,4 @@
|
|
|
1
|
-
const
|
|
2
|
-
|
|
1
|
+
const OLD_API_URL = "https://fxtj7xkgc6.execute-api.eu-central-1.amazonaws.com/prod/";
|
|
2
|
+
const NEW_API_URL = "https://the-mind-api.edilkamin.com/";
|
|
3
|
+
const API_URL = NEW_API_URL;
|
|
4
|
+
export { API_URL, NEW_API_URL, OLD_API_URL };
|
package/dist/esm/index.d.ts
CHANGED
|
@@ -1,4 +1,6 @@
|
|
|
1
|
-
export {
|
|
1
|
+
export { decompressBuffer, isBuffer, processResponse } from "./buffer-utils";
|
|
2
|
+
export { API_URL, NEW_API_URL, OLD_API_URL } from "./constants";
|
|
2
3
|
export { configure, signIn } from "./library";
|
|
3
|
-
export {
|
|
4
|
-
export
|
|
4
|
+
export { serialNumberDisplay, serialNumberFromHex, serialNumberToHex, } from "./serial-utils";
|
|
5
|
+
export { BufferEncodedType, CommandsType, DeviceAssociationBody, DeviceAssociationResponse, DeviceInfoRawType, DeviceInfoType, EditDeviceAssociationBody, StatusType, TemperaturesType, UserParametersType, } from "./types";
|
|
6
|
+
export declare const deviceInfo: (jwtToken: string, macAddress: string) => Promise<import("./types").DeviceInfoType>, registerDevice: (jwtToken: string, macAddress: string, serialNumber: string, deviceName?: string, deviceRoom?: string) => Promise<import("./types").DeviceAssociationResponse>, editDevice: (jwtToken: string, macAddress: string, deviceName?: string, deviceRoom?: string) => Promise<import("./types").DeviceAssociationResponse>, setPower: (jwtToken: string, macAddress: string, value: number) => Promise<import("axios").AxiosResponse<any, any, {}>>, setPowerOff: (jwtToken: string, macAddress: string) => Promise<import("axios").AxiosResponse<any, any, {}>>, setPowerOn: (jwtToken: string, macAddress: string) => Promise<import("axios").AxiosResponse<any, any, {}>>, getPower: (jwtToken: string, macAddress: string) => Promise<boolean>, getEnvironmentTemperature: (jwtToken: string, macAddress: string) => Promise<number>, getTargetTemperature: (jwtToken: string, macAddress: string) => Promise<number>, setTargetTemperature: (jwtToken: string, macAddress: string, temperature: number) => Promise<import("axios").AxiosResponse<any, any, {}>>;
|
package/dist/esm/index.js
CHANGED
|
@@ -1,4 +1,6 @@
|
|
|
1
1
|
import { configure } from "./library";
|
|
2
|
-
export {
|
|
2
|
+
export { decompressBuffer, isBuffer, processResponse } from "./buffer-utils";
|
|
3
|
+
export { API_URL, NEW_API_URL, OLD_API_URL } from "./constants";
|
|
3
4
|
export { configure, signIn } from "./library";
|
|
4
|
-
export
|
|
5
|
+
export { serialNumberDisplay, serialNumberFromHex, serialNumberToHex, } from "./serial-utils";
|
|
6
|
+
export const { deviceInfo, registerDevice, editDevice, setPower, setPowerOff, setPowerOn, getPower, getEnvironmentTemperature, getTargetTemperature, setTargetTemperature, } = configure();
|
package/dist/esm/library.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import * as amplifyAuth from "aws-amplify/auth";
|
|
2
|
-
import { DeviceInfoType } from "./types";
|
|
2
|
+
import { DeviceAssociationResponse, DeviceInfoType } from "./types";
|
|
3
3
|
/**
|
|
4
4
|
* Generates headers with a JWT token for authenticated requests.
|
|
5
5
|
* @param {string} jwtToken - The JWT token for authorization.
|
|
@@ -14,9 +14,9 @@ declare const headers: (jwtToken: string) => {
|
|
|
14
14
|
* @returns {object} - An object containing authentication-related methods.
|
|
15
15
|
*/
|
|
16
16
|
declare const createAuthService: (auth: typeof amplifyAuth) => {
|
|
17
|
-
signIn: (username: string, password: string) => Promise<string>;
|
|
17
|
+
signIn: (username: string, password: string, legacy?: boolean) => Promise<string>;
|
|
18
18
|
};
|
|
19
|
-
declare const signIn: (username: string, password: string) => Promise<string>;
|
|
19
|
+
declare const signIn: (username: string, password: string, legacy?: boolean) => Promise<string>;
|
|
20
20
|
/**
|
|
21
21
|
* Configures the library for API interactions.
|
|
22
22
|
* Initializes API methods with a specified base URL.
|
|
@@ -30,12 +30,14 @@ declare const signIn: (username: string, password: string) => Promise<string>;
|
|
|
30
30
|
*/
|
|
31
31
|
declare const configure: (baseURL?: string) => {
|
|
32
32
|
deviceInfo: (jwtToken: string, macAddress: string) => Promise<DeviceInfoType>;
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
33
|
+
registerDevice: (jwtToken: string, macAddress: string, serialNumber: string, deviceName?: string, deviceRoom?: string) => Promise<DeviceAssociationResponse>;
|
|
34
|
+
editDevice: (jwtToken: string, macAddress: string, deviceName?: string, deviceRoom?: string) => Promise<DeviceAssociationResponse>;
|
|
35
|
+
setPower: (jwtToken: string, macAddress: string, value: number) => Promise<import("axios").AxiosResponse<any, any, {}>>;
|
|
36
|
+
setPowerOff: (jwtToken: string, macAddress: string) => Promise<import("axios").AxiosResponse<any, any, {}>>;
|
|
37
|
+
setPowerOn: (jwtToken: string, macAddress: string) => Promise<import("axios").AxiosResponse<any, any, {}>>;
|
|
36
38
|
getPower: (jwtToken: string, macAddress: string) => Promise<boolean>;
|
|
37
39
|
getEnvironmentTemperature: (jwtToken: string, macAddress: string) => Promise<number>;
|
|
38
40
|
getTargetTemperature: (jwtToken: string, macAddress: string) => Promise<number>;
|
|
39
|
-
setTargetTemperature: (jwtToken: string, macAddress: string, temperature: number) => Promise<import("axios").AxiosResponse<any, any>>;
|
|
41
|
+
setTargetTemperature: (jwtToken: string, macAddress: string, temperature: number) => Promise<import("axios").AxiosResponse<any, any, {}>>;
|
|
40
42
|
};
|
|
41
43
|
export { configure, createAuthService, headers, signIn };
|