edilkamin 1.1.0 → 1.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/README.md CHANGED
@@ -1,6 +1,7 @@
1
1
  # Edilkamin.js
2
2
 
3
3
  [![Tests](https://github.com/AndreMiras/edilkamin.js/workflows/Tests/badge.svg)](https://github.com/AndreMiras/edilkamin.js/actions/workflows/tests.yml)
4
+ [![CLI Tests](https://github.com/AndreMiras/edilkamin.js/actions/workflows/cli-tests.yml/badge.svg)](https://github.com/AndreMiras/edilkamin.js/actions/workflows/cli-tests.yml)
4
5
  [![Documentation](https://github.com/AndreMiras/edilkamin.js/workflows/Documentation/badge.svg)](https://github.com/AndreMiras/edilkamin.js/actions/workflows/documentation.yml)
5
6
  [![npm version](https://badge.fury.io/js/edilkamin.svg)](https://badge.fury.io/js/edilkamin)
6
7
 
@@ -39,12 +40,26 @@ It's also possible to change the default backend URL:
39
40
  ```js
40
41
  import { signIn, configure } from "edilkamin";
41
42
 
42
- const baseUrl = "https://my-proxy.com/"
43
+ const baseUrl = "https://my-proxy.com/";
43
44
  const { deviceInfo, setPower } = configure(baseUrl);
44
45
  deviceInfo(token, macAddress).then(console.log);
45
46
  setPower(token, macAddress, 0).then(console.log);
46
47
  ```
47
48
 
49
+ ## CLI
50
+
51
+ The library includes a CLI tool that is useful for debugging.
52
+
53
+ ```sh
54
+ yarn cli deviceInfo --mac $MAC --username $USERNAME --password $PASSWORD
55
+ ```
56
+
57
+ Or with `npx` once the library is installed:
58
+
59
+ ```sh
60
+ npx edilkamin deviceInfo --mac $MAC --username $USERNAME --password $PASSWORD
61
+ ```
62
+
48
63
  ## Motivations
49
64
 
50
65
  - providing an open source web alternative
@@ -0,0 +1,48 @@
1
+ {
2
+ "name": "edilkamin",
3
+ "version": "1.2.0",
4
+ "description": "",
5
+ "main": "dist/index.js",
6
+ "types": "dist/index.d.ts",
7
+ "scripts": {
8
+ "cli": "ts-node src/cli.ts",
9
+ "test": "mocha --require ts-node/register src/*.test.ts",
10
+ "lint": "prettier --check src docs .github *.md",
11
+ "format": "prettier --write src docs .github *.md",
12
+ "build": "tsc"
13
+ },
14
+ "files": [
15
+ "/dist"
16
+ ],
17
+ "repository": {
18
+ "type": "git",
19
+ "url": "git+https://github.com/AndreMiras/edilkamin.js.git"
20
+ },
21
+ "author": "Andre Miras",
22
+ "license": "MIT",
23
+ "bugs": {
24
+ "url": "https://github.com/AndreMiras/edilkamin.js/issues"
25
+ },
26
+ "homepage": "https://github.com/AndreMiras/edilkamin.js#readme",
27
+ "bin": {
28
+ "edilkamin": "dist/cli.js"
29
+ },
30
+ "dependencies": {
31
+ "@aws-amplify/core": "^4.3.14",
32
+ "aws-amplify": "^4.3.14",
33
+ "aws-crt": "^1.14.5"
34
+ },
35
+ "devDependencies": {
36
+ "@aws-amplify/cli": "^7.6.21",
37
+ "@types/mocha": "^10.0.10",
38
+ "@types/sinon": "^17.0.3",
39
+ "mocha": "^10.8.2",
40
+ "prettier": "^2.5.1",
41
+ "sinon": "^19.0.2",
42
+ "ts-node": "^10.9.1",
43
+ "typedoc": "^0.22.12"
44
+ },
45
+ "optionalDependencies": {
46
+ "commander": "^12.1.0"
47
+ }
48
+ }
@@ -0,0 +1,3 @@
1
+ #!/usr/bin/env node
2
+ declare const main: () => void;
3
+ export { main };
@@ -0,0 +1,85 @@
1
+ #!/usr/bin/env node
2
+ "use strict";
3
+ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
4
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
5
+ return new (P || (P = Promise))(function (resolve, reject) {
6
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
7
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
8
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
9
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
10
+ });
11
+ };
12
+ var __importDefault = (this && this.__importDefault) || function (mod) {
13
+ return (mod && mod.__esModule) ? mod : { "default": mod };
14
+ };
15
+ Object.defineProperty(exports, "__esModule", { value: true });
16
+ exports.main = void 0;
17
+ const library_1 = require("./library");
18
+ const commander_1 = require("commander");
19
+ const readline_1 = __importDefault(require("readline"));
20
+ const package_json_1 = require("../package.json");
21
+ const promptPassword = () => {
22
+ const rl = readline_1.default.createInterface({
23
+ input: process.stdin,
24
+ output: process.stdout,
25
+ terminal: true,
26
+ });
27
+ return new Promise((resolve) => {
28
+ rl.question("Enter password: ", (password) => {
29
+ // Hide the password input
30
+ readline_1.default.moveCursor(process.stdout, 0, -1);
31
+ readline_1.default.clearLine(process.stdout, 0);
32
+ rl.close();
33
+ resolve(password);
34
+ });
35
+ // Disable input echoing for password
36
+ process.stdin.on("data", (char) => {
37
+ if (char.toString("hex") === "0d0a")
38
+ return; // Enter key
39
+ process.stdout.write("*");
40
+ });
41
+ });
42
+ };
43
+ /**
44
+ * Adds common options (username and password) to a command.
45
+ * @param command The command to which options should be added.
46
+ * @returns The command with options added.
47
+ */
48
+ const addCommonOptions = (command) => command
49
+ .requiredOption("-u, --username <username>", "Username")
50
+ .option("-p, --password <password>", "Password");
51
+ const createProgram = () => {
52
+ const program = new commander_1.Command();
53
+ program
54
+ .name("edilkamin-cli")
55
+ .description("CLI tool for interacting with the Edilkamin API")
56
+ .version(package_json_1.version);
57
+ // Command: signIn
58
+ addCommonOptions(program.command("signIn").description("Sign in and retrieve a JWT token")).action((options) => __awaiter(void 0, void 0, void 0, function* () {
59
+ const { username, password } = options;
60
+ const pwd = password || (yield promptPassword());
61
+ const jwtToken = yield library_1.signIn(username, pwd);
62
+ console.log("JWT Token:", jwtToken);
63
+ }));
64
+ // Command: deviceInfo
65
+ addCommonOptions(program
66
+ .command("deviceInfo")
67
+ .description("Retrieve device info for a specific MAC address")
68
+ .requiredOption("-m, --mac <macAddress>", "MAC address of the device")).action((options) => __awaiter(void 0, void 0, void 0, function* () {
69
+ const { username, password, mac } = options;
70
+ const pwd = password || (yield promptPassword());
71
+ const jwtToken = yield library_1.signIn(username, pwd);
72
+ const api = library_1.configure(); // Use the default API configuration
73
+ const deviceInfo = yield api.deviceInfo(jwtToken, mac);
74
+ console.log("Device Info:", deviceInfo.data);
75
+ }));
76
+ return program;
77
+ };
78
+ const main = () => {
79
+ const program = createProgram();
80
+ program.parse(process.argv);
81
+ };
82
+ exports.main = main;
83
+ if (require.main === module) {
84
+ main();
85
+ }
@@ -0,0 +1,4 @@
1
+ export { API_URL } from "./constants";
2
+ export { CommandsType, DeviceInfoType, StatusType, TemperaturesType, UserParametersType, } from "./types";
3
+ export { signIn, configure } from "./library";
4
+ export declare const deviceInfo: (jwtToken: string, macAddress: string) => Promise<import("axios").AxiosResponse<import("./types").DeviceInfoType, any>>, 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>>;
@@ -4,9 +4,9 @@ import { DeviceInfoType } from "./types";
4
4
  */
5
5
  declare const signIn: (username: string, password: string) => Promise<string>;
6
6
  declare const configure: (baseURL?: string) => {
7
- deviceInfo: (jwtToken: string, macAddress: string) => Promise<import("axios").AxiosResponse<DeviceInfoType>>;
8
- setPower: (jwtToken: string, macAddress: string, value: number) => Promise<import("axios").AxiosResponse<any>>;
9
- setPowerOff: (jwtToken: string, macAddress: string) => Promise<import("axios").AxiosResponse<any>>;
10
- setPowerOn: (jwtToken: string, macAddress: string) => Promise<import("axios").AxiosResponse<any>>;
7
+ deviceInfo: (jwtToken: string, macAddress: string) => Promise<import("axios").AxiosResponse<DeviceInfoType, any>>;
8
+ setPower: (jwtToken: string, macAddress: string, value: number) => Promise<import("axios").AxiosResponse<any, any>>;
9
+ setPowerOff: (jwtToken: string, macAddress: string) => Promise<import("axios").AxiosResponse<any, any>>;
10
+ setPowerOn: (jwtToken: string, macAddress: string) => Promise<import("axios").AxiosResponse<any, any>>;
11
11
  };
12
12
  export { signIn, configure };
@@ -8,11 +8,13 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
8
8
  step((generator = generator.apply(thisArg, _arguments || [])).next());
9
9
  });
10
10
  };
11
+ var __importDefault = (this && this.__importDefault) || function (mod) {
12
+ return (mod && mod.__esModule) ? mod : { "default": mod };
13
+ };
11
14
  Object.defineProperty(exports, "__esModule", { value: true });
12
15
  exports.configure = exports.signIn = void 0;
13
- const assert_1 = require("assert");
14
16
  const aws_amplify_1 = require("aws-amplify");
15
- const axios_1 = require("axios");
17
+ const axios_1 = __importDefault(require("axios"));
16
18
  const constants_1 = require("./constants");
17
19
  const amplifyconfiguration = {
18
20
  Auth: {
@@ -34,7 +36,7 @@ exports.signIn = signIn;
34
36
  const deviceInfo = (axiosInstance) => (jwtToken, macAddress) => axiosInstance.get(`device/${macAddress}/info`, {
35
37
  headers: headers(jwtToken),
36
38
  });
37
- const mqttCommand = (axiosInstance) => (jwtToken, macAddress, payload) => axiosInstance.put(`mqtt/command`, Object.assign({ mac_address: macAddress }, payload), { headers: headers(jwtToken) });
39
+ const mqttCommand = (axiosInstance) => (jwtToken, macAddress, payload) => axiosInstance.put("mqtt/command", Object.assign({ mac_address: macAddress }, payload), { headers: headers(jwtToken) });
38
40
  const setPower = (axiosInstance) => (jwtToken, macAddress, value) => mqttCommand(axiosInstance)(jwtToken, macAddress, { name: "power", value });
39
41
  const setPowerOn = (axiosInstance) => (jwtToken, macAddress) => setPower(axiosInstance)(jwtToken, macAddress, 1);
40
42
  const setPowerOff = (axiosInstance) => (jwtToken, macAddress) => setPower(axiosInstance)(jwtToken, macAddress, 0);
@@ -53,12 +55,3 @@ const configure = (baseURL = constants_1.API_URL) => {
53
55
  };
54
56
  exports.configure = configure;
55
57
  const defaultApi = configure();
56
- const main = () => __awaiter(void 0, void 0, void 0, function* () {
57
- const { USERNAME, PASSWORD, MAC_ADDRESS } = process.env;
58
- assert_1.ok(USERNAME);
59
- assert_1.ok(PASSWORD);
60
- assert_1.ok(MAC_ADDRESS);
61
- const jwtToken = yield signIn(USERNAME, PASSWORD);
62
- const info = yield defaultApi.deviceInfo(jwtToken, MAC_ADDRESS);
63
- console.log({ info });
64
- });
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,97 @@
1
+ "use strict";
2
+ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
3
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
4
+ return new (P || (P = Promise))(function (resolve, reject) {
5
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
6
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
7
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
8
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
9
+ });
10
+ };
11
+ var __importDefault = (this && this.__importDefault) || function (mod) {
12
+ return (mod && mod.__esModule) ? mod : { "default": mod };
13
+ };
14
+ Object.defineProperty(exports, "__esModule", { value: true });
15
+ const assert_1 = require("assert");
16
+ const sinon_1 = __importDefault(require("sinon"));
17
+ const aws_amplify_1 = require("aws-amplify");
18
+ const axios_1 = __importDefault(require("axios"));
19
+ const library_1 = require("../src/library");
20
+ describe("library", () => {
21
+ let axiosStub;
22
+ beforeEach(() => {
23
+ axiosStub = sinon_1.default.stub(axios_1.default, "create").returns({
24
+ get: sinon_1.default.stub(),
25
+ put: sinon_1.default.stub(),
26
+ });
27
+ });
28
+ afterEach(() => {
29
+ sinon_1.default.restore();
30
+ });
31
+ describe("signIn", () => {
32
+ it("should return a JWT token on successful login", () => __awaiter(void 0, void 0, void 0, function* () {
33
+ const expectedJwtToken = "mockToken123";
34
+ const mockUserSession = {
35
+ getAccessToken: () => ({ jwtToken: expectedJwtToken }),
36
+ };
37
+ const mockUser = {
38
+ getSignInUserSession: () => mockUserSession,
39
+ };
40
+ const signInStub = sinon_1.default.stub(aws_amplify_1.Auth, "signIn").resolves(mockUser);
41
+ const jwtToken = yield library_1.signIn("mockUser", "mockPassword");
42
+ assert_1.strict.ok(signInStub.calledOnce);
43
+ assert_1.strict.equal(jwtToken, expectedJwtToken);
44
+ }));
45
+ });
46
+ describe("configure", () => {
47
+ it("should create API methods with the correct baseURL", () => {
48
+ const baseURL = "https://example.com/api";
49
+ const api = library_1.configure(baseURL);
50
+ assert_1.strict.ok(axiosStub.calledOnce);
51
+ assert_1.strict.deepEqual(axiosStub.firstCall.args[0], { baseURL });
52
+ assert_1.strict.deepEqual(Object.keys(api), [
53
+ "deviceInfo",
54
+ "setPower",
55
+ "setPowerOff",
56
+ "setPowerOn",
57
+ ]);
58
+ });
59
+ });
60
+ describe("API Methods", () => {
61
+ it("should call axios for deviceInfo", () => __awaiter(void 0, void 0, void 0, function* () {
62
+ const mockAxios = {
63
+ get: sinon_1.default
64
+ .stub()
65
+ .resolves({ data: { id: "123", name: "Mock Device" } }),
66
+ };
67
+ axiosStub.returns(mockAxios);
68
+ const api = library_1.configure("https://example.com/api");
69
+ const result = yield api.deviceInfo("mockToken", "mockMacAddress");
70
+ assert_1.strict.ok(mockAxios.get.calledOnce);
71
+ assert_1.strict.equal(mockAxios.get.firstCall.args[0], "device/mockMacAddress/info");
72
+ assert_1.strict.deepEqual(mockAxios.get.firstCall.args[1], {
73
+ headers: { Authorization: "Bearer mockToken" },
74
+ });
75
+ assert_1.strict.deepEqual(result.data, { id: "123", name: "Mock Device" });
76
+ }));
77
+ it("should call axios for setPowerOn", () => __awaiter(void 0, void 0, void 0, function* () {
78
+ const mockAxios = {
79
+ put: sinon_1.default.stub().resolves({ status: 200 }),
80
+ };
81
+ axiosStub.returns(mockAxios);
82
+ const api = library_1.configure("https://example.com/api");
83
+ const result = yield api.setPowerOn("mockToken", "mockMacAddress");
84
+ assert_1.strict.ok(mockAxios.put.calledOnce);
85
+ assert_1.strict.equal(mockAxios.put.firstCall.args[0], "mqtt/command");
86
+ assert_1.strict.deepEqual(mockAxios.put.firstCall.args[1], {
87
+ mac_address: "mockMacAddress",
88
+ name: "power",
89
+ value: 1,
90
+ });
91
+ assert_1.strict.deepEqual(mockAxios.put.firstCall.args[2], {
92
+ headers: { Authorization: "Bearer mockToken" },
93
+ });
94
+ assert_1.strict.equal(result.status, 200);
95
+ }));
96
+ });
97
+ });
package/package.json CHANGED
@@ -1,11 +1,12 @@
1
1
  {
2
2
  "name": "edilkamin",
3
- "version": "1.1.0",
3
+ "version": "1.2.0",
4
4
  "description": "",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",
7
7
  "scripts": {
8
- "test": "echo \"Error: no test specified\" && exit 1",
8
+ "cli": "ts-node src/cli.ts",
9
+ "test": "mocha --require ts-node/register src/*.test.ts",
9
10
  "lint": "prettier --check src docs .github *.md",
10
11
  "format": "prettier --write src docs .github *.md",
11
12
  "build": "tsc"
@@ -23,14 +24,25 @@
23
24
  "url": "https://github.com/AndreMiras/edilkamin.js/issues"
24
25
  },
25
26
  "homepage": "https://github.com/AndreMiras/edilkamin.js#readme",
27
+ "bin": {
28
+ "edilkamin": "dist/cli.js"
29
+ },
26
30
  "dependencies": {
27
31
  "@aws-amplify/core": "^4.3.14",
28
- "aws-amplify": "^4.3.14"
32
+ "aws-amplify": "^4.3.14",
33
+ "aws-crt": "^1.14.5"
29
34
  },
30
35
  "devDependencies": {
31
36
  "@aws-amplify/cli": "^7.6.21",
37
+ "@types/mocha": "^10.0.10",
38
+ "@types/sinon": "^17.0.3",
39
+ "mocha": "^10.8.2",
32
40
  "prettier": "^2.5.1",
41
+ "sinon": "^19.0.2",
33
42
  "ts-node": "^10.9.1",
34
43
  "typedoc": "^0.22.12"
44
+ },
45
+ "optionalDependencies": {
46
+ "commander": "^12.1.0"
35
47
  }
36
48
  }
package/dist/index.d.ts DELETED
@@ -1,4 +0,0 @@
1
- export { API_URL } from "./constants";
2
- export { CommandsType, DeviceInfoType, StatusType, TemperaturesType, UserParametersType, } from "./types";
3
- export { signIn, configure } from "./library";
4
- export declare const deviceInfo: (jwtToken: string, macAddress: string) => Promise<import("axios").AxiosResponse<import("./types").DeviceInfoType>>, setPower: (jwtToken: string, macAddress: string, value: number) => Promise<import("axios").AxiosResponse<any>>, setPowerOff: (jwtToken: string, macAddress: string) => Promise<import("axios").AxiosResponse<any>>, setPowerOn: (jwtToken: string, macAddress: string) => Promise<import("axios").AxiosResponse<any>>;
File without changes
File without changes
File without changes
File without changes
File without changes