iobroker.beszel 0.1.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.
Files changed (46) hide show
  1. package/.github/auto-merge.yml +2 -0
  2. package/.github/dependabot.yml +12 -0
  3. package/.github/workflows/automerge-dependabot.yml +32 -0
  4. package/.github/workflows/test-and-release.yml +62 -0
  5. package/.vscode/settings.json +12 -0
  6. package/CHANGELOG.md +13 -0
  7. package/CLAUDE.md +91 -0
  8. package/LICENSE +21 -0
  9. package/README.md +187 -0
  10. package/admin/beszel.svg +9 -0
  11. package/admin/i18n/de/translations.json +43 -0
  12. package/admin/i18n/en/translations.json +43 -0
  13. package/admin/i18n/es/translations.json +43 -0
  14. package/admin/i18n/fr/translations.json +43 -0
  15. package/admin/i18n/it/translations.json +43 -0
  16. package/admin/i18n/nl/translations.json +43 -0
  17. package/admin/i18n/pl/translations.json +43 -0
  18. package/admin/i18n/pt/translations.json +43 -0
  19. package/admin/i18n/ru/translations.json +43 -0
  20. package/admin/i18n/uk/translations.json +43 -0
  21. package/admin/i18n/zh-cn/translations.json +43 -0
  22. package/admin/jsonConfig.json +240 -0
  23. package/build/lib/beszel-client.d.ts +39 -0
  24. package/build/lib/beszel-client.d.ts.map +1 -0
  25. package/build/lib/beszel-client.js +199 -0
  26. package/build/lib/state-manager.d.ts +47 -0
  27. package/build/lib/state-manager.d.ts.map +1 -0
  28. package/build/lib/state-manager.js +738 -0
  29. package/build/lib/types.d.ts +174 -0
  30. package/build/lib/types.d.ts.map +1 -0
  31. package/build/lib/types.js +2 -0
  32. package/build/main.d.ts +2 -0
  33. package/build/main.d.ts.map +1 -0
  34. package/build/main.js +191 -0
  35. package/eslint.config.mjs +36 -0
  36. package/io-package.json +162 -0
  37. package/package.json +61 -0
  38. package/scripts/version.js +28 -0
  39. package/src/lib/beszel-client.ts +216 -0
  40. package/src/lib/state-manager.ts +1050 -0
  41. package/src/lib/types.ts +192 -0
  42. package/src/main.ts +199 -0
  43. package/test/testPackageFiles.ts +5 -0
  44. package/tsconfig.build.json +7 -0
  45. package/tsconfig.json +24 -0
  46. package/tsconfig.test.json +9 -0
@@ -0,0 +1,174 @@
1
+ /**
2
+ * Adapter configuration as stored in ioBroker native config
3
+ */
4
+ export interface AdapterConfig {
5
+ url: string;
6
+ username: string;
7
+ password: string;
8
+ pollInterval: number;
9
+ metrics_uptime: boolean;
10
+ metrics_agentVersion: boolean;
11
+ metrics_services: boolean;
12
+ metrics_cpu: boolean;
13
+ metrics_loadAvg: boolean;
14
+ metrics_cpuBreakdown: boolean;
15
+ metrics_memory: boolean;
16
+ metrics_memoryDetails: boolean;
17
+ metrics_swap: boolean;
18
+ metrics_disk: boolean;
19
+ metrics_diskSpeed: boolean;
20
+ metrics_extraFs: boolean;
21
+ metrics_network: boolean;
22
+ metrics_temperature: boolean;
23
+ metrics_temperatureDetails: boolean;
24
+ metrics_gpu: boolean;
25
+ metrics_containers: boolean;
26
+ metrics_battery: boolean;
27
+ }
28
+ /**
29
+ * System info object from Beszel systems record
30
+ */
31
+ export interface SystemInfo {
32
+ /** Uptime in seconds */
33
+ u?: number;
34
+ /** Agent version */
35
+ v?: string;
36
+ /** Systemd services [total, failed] */
37
+ sv?: [number, number];
38
+ /** Load average [1m, 5m, 15m] */
39
+ la?: [number, number, number];
40
+ /** Battery [percent, charge_state] */
41
+ bat?: [number, number];
42
+ /** Connection type */
43
+ ct?: number;
44
+ }
45
+ /**
46
+ * A system record from /api/collections/systems/records
47
+ */
48
+ export interface BeszelSystem {
49
+ id: string;
50
+ name: string;
51
+ status: "up" | "down" | "paused" | "pending";
52
+ host: string;
53
+ info: SystemInfo;
54
+ }
55
+ /**
56
+ * Extra filesystem stats
57
+ */
58
+ export interface FsStats {
59
+ /** disk total GB */
60
+ d?: number;
61
+ /** disk used GB */
62
+ du?: number;
63
+ /** read MB/s */
64
+ r?: number;
65
+ /** write MB/s */
66
+ w?: number;
67
+ }
68
+ /**
69
+ * GPU data
70
+ */
71
+ export interface GPUData {
72
+ /** GPU name */
73
+ n?: string;
74
+ /** GPU usage % */
75
+ u?: number;
76
+ /** GPU memory used GB */
77
+ mu?: number;
78
+ /** GPU memory total GB */
79
+ mt?: number;
80
+ /** GPU power W */
81
+ p?: number;
82
+ }
83
+ /**
84
+ * The stats object inside a system_stats record
85
+ */
86
+ export interface SystemStats {
87
+ /** CPU usage % */
88
+ cpu?: number;
89
+ /** RAM used GB */
90
+ mu?: number;
91
+ /** RAM total GB */
92
+ m?: number;
93
+ /** RAM % */
94
+ mp?: number;
95
+ /** Buffers + cache GB */
96
+ mb?: number;
97
+ /** ZFS ARC GB */
98
+ mz?: number;
99
+ /** Swap used GB */
100
+ su?: number;
101
+ /** Swap total GB */
102
+ s?: number;
103
+ /** Disk used GB */
104
+ du?: number;
105
+ /** Disk total GB */
106
+ d?: number;
107
+ /** Disk % */
108
+ dp?: number;
109
+ /** Disk read MB/s */
110
+ dr?: number;
111
+ /** Disk write MB/s */
112
+ dw?: number;
113
+ /** Network sent MB/s */
114
+ ns?: number;
115
+ /** Network recv MB/s */
116
+ nr?: number;
117
+ /** Temperatures map sensor->°C */
118
+ t?: Record<string, number>;
119
+ /** Load avg [1m, 5m, 15m] */
120
+ la?: [number, number, number];
121
+ /** GPU data */
122
+ g?: Record<string, GPUData>;
123
+ /** Extra filesystems */
124
+ efs?: Record<string, FsStats>;
125
+ /** Battery [%, charge_state] */
126
+ bat?: [number, number];
127
+ /** CPU breakdown [user, sys, iowait, steal, idle] % */
128
+ cpub?: number[];
129
+ }
130
+ /**
131
+ * A system_stats record from /api/collections/system_stats/records
132
+ */
133
+ export interface BeszelSystemStats {
134
+ id: string;
135
+ system: string;
136
+ type: string;
137
+ stats: SystemStats;
138
+ updated: string;
139
+ }
140
+ /**
141
+ * A container record from /api/collections/containers/records
142
+ */
143
+ export interface BeszelContainer {
144
+ id: string;
145
+ system: string;
146
+ name: string;
147
+ status: string;
148
+ health: number;
149
+ cpu: number;
150
+ memory: number;
151
+ image: string;
152
+ }
153
+ /**
154
+ * PocketBase list response
155
+ */
156
+ export interface PocketBaseList<T> {
157
+ page: number;
158
+ perPage: number;
159
+ totalItems: number;
160
+ totalPages: number;
161
+ items: T[];
162
+ }
163
+ /**
164
+ * PocketBase auth response
165
+ */
166
+ export interface AuthResponse {
167
+ token: string;
168
+ record: {
169
+ id: string;
170
+ email: string;
171
+ [key: string]: unknown;
172
+ };
173
+ }
174
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/lib/types.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=main.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"main.d.ts","sourceRoot":"","sources":["../src/main.ts"],"names":[],"mappings":""}
package/build/main.js ADDED
@@ -0,0 +1,191 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || (function () {
19
+ var ownKeys = function(o) {
20
+ ownKeys = Object.getOwnPropertyNames || function (o) {
21
+ var ar = [];
22
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
+ return ar;
24
+ };
25
+ return ownKeys(o);
26
+ };
27
+ return function (mod) {
28
+ if (mod && mod.__esModule) return mod;
29
+ var result = {};
30
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
+ __setModuleDefault(result, mod);
32
+ return result;
33
+ };
34
+ })();
35
+ Object.defineProperty(exports, "__esModule", { value: true });
36
+ const utils = __importStar(require("@iobroker/adapter-core"));
37
+ const beszel_client_js_1 = require("./lib/beszel-client.js");
38
+ const state_manager_js_1 = require("./lib/state-manager.js");
39
+ class BeszelAdapter extends utils.Adapter {
40
+ client = null;
41
+ stateManager = null;
42
+ pollTimer = null;
43
+ isPolling = false;
44
+ constructor(options = {}) {
45
+ super({
46
+ ...options,
47
+ name: "beszel",
48
+ });
49
+ this.on("ready", this.onReady.bind(this));
50
+ this.on("unload", this.onUnload.bind(this));
51
+ this.on("message", this.onMessage.bind(this));
52
+ }
53
+ async onReady() {
54
+ const config = this.config;
55
+ // Ensure info objects exist before any setState calls
56
+ await this.setObjectNotExistsAsync("info", {
57
+ type: "channel",
58
+ common: { name: "Information" },
59
+ native: {},
60
+ });
61
+ await this.setObjectNotExistsAsync("info.connection", {
62
+ type: "state",
63
+ common: {
64
+ name: "Connection status",
65
+ type: "boolean",
66
+ role: "indicator.connected",
67
+ read: true,
68
+ write: false,
69
+ def: false,
70
+ },
71
+ native: {},
72
+ });
73
+ await this.setStateAsync("info.connection", { val: false, ack: true });
74
+ // Validate required config
75
+ if (!config.url || !config.username || !config.password) {
76
+ this.log.error("Beszel adapter: URL, username, and password are required. Please configure the adapter.");
77
+ await this.setStateAsync("info.connection", { val: false, ack: true });
78
+ return;
79
+ }
80
+ this.client = new beszel_client_js_1.BeszelClient(config.url, config.username, config.password);
81
+ this.stateManager = new state_manager_js_1.StateManager(this);
82
+ // Cleanup disabled metric states for existing systems (config may have changed)
83
+ const existingObjects = await this.getObjectViewAsync("system", "device", {
84
+ startkey: `${this.namespace}.systems.`,
85
+ endkey: `${this.namespace}.systems.\u9999`,
86
+ });
87
+ if (existingObjects?.rows) {
88
+ for (const row of existingObjects.rows) {
89
+ const relId = row.id.startsWith(`${this.namespace}.`)
90
+ ? row.id.slice(this.namespace.length + 1)
91
+ : row.id;
92
+ const parts = relId.split(".");
93
+ if (parts.length === 2 && parts[0] === "systems") {
94
+ await this.stateManager.cleanupMetrics(parts[1], config);
95
+ }
96
+ }
97
+ }
98
+ // Initial poll
99
+ await this.poll();
100
+ // Set up recurring poll
101
+ const intervalMs = Math.max(10, config.pollInterval ?? 60) * 1000;
102
+ this.pollTimer = setInterval(() => {
103
+ void this.poll();
104
+ }, intervalMs);
105
+ this.log.info(`Beszel adapter started. Polling every ${config.pollInterval ?? 60}s from ${config.url}`);
106
+ }
107
+ async onUnload(callback) {
108
+ try {
109
+ if (this.pollTimer) {
110
+ clearInterval(this.pollTimer);
111
+ this.pollTimer = null;
112
+ }
113
+ await this.setStateAsync("info.connection", { val: false, ack: true });
114
+ }
115
+ catch {
116
+ // ignore
117
+ }
118
+ callback();
119
+ }
120
+ async onMessage(obj) {
121
+ if (obj.command === "checkConnection") {
122
+ const config = obj.message;
123
+ const url = config.url ?? "";
124
+ const username = config.username ?? "";
125
+ const password = config.password ?? "";
126
+ if (!url || !username || !password) {
127
+ this.sendTo(obj.from, obj.command, {
128
+ success: false,
129
+ message: "URL, username and password are required",
130
+ }, obj.callback);
131
+ return;
132
+ }
133
+ const testClient = new beszel_client_js_1.BeszelClient(url, username, password);
134
+ const result = await testClient.checkConnection();
135
+ this.sendTo(obj.from, obj.command, result, obj.callback);
136
+ }
137
+ }
138
+ async poll() {
139
+ if (this.isPolling) {
140
+ this.log.debug("Skipping poll — previous poll still running");
141
+ return;
142
+ }
143
+ if (!this.client || !this.stateManager) {
144
+ return;
145
+ }
146
+ this.isPolling = true;
147
+ try {
148
+ const config = this.config;
149
+ // Fetch all data
150
+ const [systems, containers] = await Promise.all([
151
+ this.client.getSystems(),
152
+ config.metrics_containers
153
+ ? this.client.getContainers()
154
+ : Promise.resolve([]),
155
+ ]);
156
+ const systemIds = systems.map((s) => s.id);
157
+ const statsMap = await this.client.getLatestStats(systemIds);
158
+ // Update connection state
159
+ await this.setStateAsync("info.connection", { val: true, ack: true });
160
+ // Update each system
161
+ for (const system of systems) {
162
+ const stats = statsMap.get(system.id);
163
+ const sysContainers = containers.filter((c) => c.system === system.id);
164
+ await this.stateManager.updateSystem(system, stats, sysContainers, config);
165
+ }
166
+ // Cleanup stale systems
167
+ await this.stateManager.cleanupSystems(systems.map((s) => s.name));
168
+ this.log.debug(`Polled ${systems.length} systems successfully`);
169
+ }
170
+ catch (err) {
171
+ const errMsg = err instanceof Error ? err.message : String(err);
172
+ this.log.error(`Poll failed: ${errMsg}`);
173
+ // On 401, invalidate token so next poll re-authenticates
174
+ if (err instanceof Error &&
175
+ err.code === "UNAUTHORIZED") {
176
+ this.client?.invalidateToken();
177
+ }
178
+ await this.setStateAsync("info.connection", { val: false, ack: true });
179
+ }
180
+ finally {
181
+ this.isPolling = false;
182
+ }
183
+ }
184
+ }
185
+ if (require.main !== module) {
186
+ // Export the constructor in compact mode
187
+ module.exports = (options) => new BeszelAdapter(options);
188
+ }
189
+ else {
190
+ (() => new BeszelAdapter())();
191
+ }
@@ -0,0 +1,36 @@
1
+ import config from "@iobroker/eslint-config";
2
+
3
+ export default [
4
+ ...config,
5
+ {
6
+ languageOptions: {
7
+ parserOptions: {
8
+ projectService: { allowDefaultProject: ["*.mjs"] },
9
+ tsconfigRootDir: import.meta.dirname,
10
+ },
11
+ },
12
+ },
13
+ {
14
+ // Test files use Mocha globals
15
+ files: ["test/**/*.js"],
16
+ languageOptions: {
17
+ globals: {
18
+ describe: "readonly",
19
+ it: "readonly",
20
+ before: "readonly",
21
+ after: "readonly",
22
+ beforeEach: "readonly",
23
+ afterEach: "readonly",
24
+ },
25
+ },
26
+ },
27
+ {
28
+ ignores: [
29
+ "build/**",
30
+ "node_modules/**",
31
+ "admin/**",
32
+ "test/**",
33
+ "scripts/**",
34
+ ],
35
+ },
36
+ ];
@@ -0,0 +1,162 @@
1
+ {
2
+ "common": {
3
+ "name": "beszel",
4
+ "version": "0.1.2",
5
+ "news": {
6
+ "0.1.2": {
7
+ "en": "Fix: add missing cpu_steal state to CPU breakdown metric",
8
+ "de": "Fix: fehlender cpu_steal Datenpunkt bei CPU Breakdown ergänzt",
9
+ "ru": "Исправление: добавлено отсутствующее состояние cpu_steal в разбивке CPU",
10
+ "pt": "Correção: adicionado estado cpu_steal ausente na métrica de detalhamento da CPU",
11
+ "nl": "Fix: ontbrekende cpu_steal staat toegevoegd aan CPU breakdown metric",
12
+ "fr": "Correction: état cpu_steal manquant ajouté à la métrique de détail CPU",
13
+ "it": "Fix: aggiunto lo stato cpu_steal mancante nella metrica di dettaglio CPU",
14
+ "es": "Corrección: agregado el estado cpu_steal faltante en la métrica de desglose CPU",
15
+ "pl": "Poprawka: dodano brakujący stan cpu_steal w metryce szczegółów CPU",
16
+ "uk": "Виправлення: додано відсутній стан cpu_steal у деталізації CPU",
17
+ "zh-cn": "修复:在 CPU 详细指标中添加缺失的 cpu_steal 状态"
18
+ },
19
+ "0.1.1": {
20
+ "en": "Fix: disabled metric states are now removed on adapter restart",
21
+ "de": "Fix: deaktivierte Metric-Datenpunkte werden beim Neustart gelöscht",
22
+ "ru": "Исправление: отключённые метрики удаляются при перезапуске",
23
+ "pt": "Correção: estados de métricas desativadas são removidos ao reiniciar",
24
+ "nl": "Fix: uitgeschakelde metrische staten worden verwijderd bij herstart",
25
+ "fr": "Correction: les états de métriques désactivées sont supprimés au redémarrage",
26
+ "it": "Fix: gli stati delle metriche disabilitate vengono rimossi al riavvio",
27
+ "es": "Corrección: los estados de métricas desactivadas se eliminan al reiniciar",
28
+ "pl": "Poprawka: wyłączone stany metryk są usuwane przy ponownym uruchomieniu",
29
+ "uk": "Виправлення: вимкнені стани метрик видаляються при перезапуску",
30
+ "zh-cn": "修复:适配器重启时删除已禁用的指标状态"
31
+ },
32
+ "0.1.0": {
33
+ "en": "Initial release",
34
+ "de": "Erstveröffentlichung",
35
+ "ru": "Первый выпуск",
36
+ "pt": "Lançamento inicial",
37
+ "nl": "Eerste release",
38
+ "fr": "Première version",
39
+ "it": "Prima versione",
40
+ "es": "Versión inicial",
41
+ "pl": "Pierwsze wydanie",
42
+ "uk": "Перший випуск",
43
+ "zh-cn": "初始版本"
44
+ }
45
+ },
46
+ "titleLang": {
47
+ "en": "Beszel Monitor",
48
+ "de": "Beszel Monitor",
49
+ "ru": "Монитор Beszel",
50
+ "pt": "Monitor Beszel",
51
+ "nl": "Beszel Monitor",
52
+ "fr": "Moniteur Beszel",
53
+ "it": "Monitor Beszel",
54
+ "es": "Monitor Beszel",
55
+ "pl": "Monitor Beszel",
56
+ "uk": "Монітор Beszel",
57
+ "zh-cn": "Beszel 监控"
58
+ },
59
+ "desc": {
60
+ "en": "Connects to a Beszel Hub and exposes server metrics as ioBroker states",
61
+ "de": "Verbindet sich mit einem Beszel Hub und stellt Server-Metriken als ioBroker-Datenpunkte bereit",
62
+ "ru": "Подключается к Beszel Hub и предоставляет метрики сервера как состояния ioBroker",
63
+ "pt": "Conecta-se a um Beszel Hub e expõe métricas do servidor como estados ioBroker",
64
+ "nl": "Verbindt met een Beszel Hub en stelt servermetrisch beschikbaar als ioBroker-staten",
65
+ "fr": "Se connecte à un Beszel Hub et expose les métriques du serveur comme états ioBroker",
66
+ "it": "Si connette a un Beszel Hub ed espone le metriche del server come stati ioBroker",
67
+ "es": "Se conecta a un Beszel Hub y expone métricas del servidor como estados ioBroker",
68
+ "pl": "Łączy się z Beszel Hub i udostępnia metryki serwera jako stany ioBroker",
69
+ "uk": "Підключається до Beszel Hub та надає метрики сервера як стани ioBroker",
70
+ "zh-cn": "连接到 Beszel Hub 并将服务器指标作为 ioBroker 状态公开"
71
+ },
72
+ "authors": [
73
+ "krobi <krobi@power-dreams.com>"
74
+ ],
75
+ "licenseInformation": {
76
+ "license": "MIT",
77
+ "type": "free"
78
+ },
79
+ "platform": "Javascript/Node.js",
80
+ "icon": "beszel.svg",
81
+ "extIcon": "https://raw.githubusercontent.com/krobipd/iobroker.beszel/main/admin/beszel.svg",
82
+ "readme": "https://github.com/krobipd/iobroker.beszel/blob/main/README.md",
83
+ "enabled": true,
84
+ "tier": 3,
85
+ "loglevel": "info",
86
+ "mode": "daemon",
87
+ "type": "monitoring",
88
+ "compact": true,
89
+ "connectionType": "local",
90
+ "dataSource": "poll",
91
+ "adminUI": {
92
+ "config": "json"
93
+ },
94
+ "supportedMessages": {
95
+ "stopInstance": true,
96
+ "checkConnection": true
97
+ },
98
+ "dependencies": [
99
+ {
100
+ "js-controller": ">=7.0.0"
101
+ }
102
+ ],
103
+ "globalDependencies": [
104
+ {
105
+ "admin": ">=7.6.20"
106
+ }
107
+ ],
108
+ "instanceObjects": [
109
+ {
110
+ "_id": "info",
111
+ "type": "channel",
112
+ "common": {
113
+ "name": "Information"
114
+ },
115
+ "native": {}
116
+ },
117
+ {
118
+ "_id": "info.connection",
119
+ "type": "state",
120
+ "common": {
121
+ "name": "Connection status",
122
+ "type": "boolean",
123
+ "role": "indicator.connected",
124
+ "read": true,
125
+ "write": false,
126
+ "def": false
127
+ },
128
+ "native": {}
129
+ }
130
+ ]
131
+ },
132
+ "encryptedNative": [
133
+ "password"
134
+ ],
135
+ "protectedNative": [
136
+ "password"
137
+ ],
138
+ "native": {
139
+ "url": "",
140
+ "username": "",
141
+ "password": "",
142
+ "pollInterval": 60,
143
+ "metrics_uptime": true,
144
+ "metrics_agentVersion": false,
145
+ "metrics_services": false,
146
+ "metrics_cpu": true,
147
+ "metrics_loadAvg": true,
148
+ "metrics_cpuBreakdown": false,
149
+ "metrics_memory": true,
150
+ "metrics_memoryDetails": false,
151
+ "metrics_swap": false,
152
+ "metrics_disk": true,
153
+ "metrics_diskSpeed": true,
154
+ "metrics_extraFs": false,
155
+ "metrics_network": true,
156
+ "metrics_temperature": true,
157
+ "metrics_temperatureDetails": false,
158
+ "metrics_gpu": false,
159
+ "metrics_containers": false,
160
+ "metrics_battery": false
161
+ }
162
+ }
package/package.json ADDED
@@ -0,0 +1,61 @@
1
+ {
2
+ "name": "iobroker.beszel",
3
+ "version": "0.1.2",
4
+ "description": "ioBroker adapter for Beszel server monitoring",
5
+ "author": {
6
+ "name": "krobi",
7
+ "email": "krobi@power-dreams.com"
8
+ },
9
+ "homepage": "https://github.com/krobipd/iobroker.beszel",
10
+ "license": "MIT",
11
+ "keywords": [
12
+ "ioBroker",
13
+ "beszel",
14
+ "monitoring",
15
+ "server",
16
+ "metrics"
17
+ ],
18
+ "repository": {
19
+ "type": "git",
20
+ "url": "git+https://github.com/krobipd/iobroker.beszel.git"
21
+ },
22
+ "engines": {
23
+ "node": ">=20.0.0"
24
+ },
25
+ "dependencies": {
26
+ "@iobroker/adapter-core": "^3.2.3"
27
+ },
28
+ "devDependencies": {
29
+ "@iobroker/build-tools": "^3.0.1",
30
+ "@iobroker/eslint-config": "^1.0.0",
31
+ "@iobroker/testing": "^4.1.3",
32
+ "@types/node": "^22.0.0",
33
+ "mocha": "^11.0.0",
34
+ "source-map-support": "^0.5.21",
35
+ "ts-node": "^10.9.2",
36
+ "typescript": "^5.6.3"
37
+ },
38
+ "main": "build/main.js",
39
+ "scripts": {
40
+ "prebuild": "rm -rf ./build",
41
+ "build:ts": "tsc -p tsconfig.build.json",
42
+ "build": "npm run build:ts",
43
+ "build:test": "tsc -p tsconfig.test.json",
44
+ "watch": "tsc -w",
45
+ "check": "tsc --noEmit",
46
+ "test:package": "npm run build:test && mocha --exit \"build/test/testPackageFiles.js\"",
47
+ "test:integration": "npm run build:test && mocha --exit \"build/test/**/*.js\"",
48
+ "test": "npm run build:test && mocha --exit \"build/test/**/*.js\"",
49
+ "test:ci": "npm run build:test && mocha --exit --reporter spec \"build/test/**/*.js\"",
50
+ "lint": "eslint",
51
+ "lint:fix": "eslint --fix",
52
+ "prepare": "npm run build",
53
+ "version:patch": "node scripts/version.js patch",
54
+ "version:minor": "node scripts/version.js minor",
55
+ "version:major": "node scripts/version.js major"
56
+ },
57
+ "bugs": {
58
+ "url": "https://github.com/krobipd/iobroker.beszel/issues"
59
+ },
60
+ "readmeFilename": "README.md"
61
+ }
@@ -0,0 +1,28 @@
1
+ const fs = require('fs');
2
+ const { execSync } = require('child_process');
3
+
4
+ const type = process.argv[2] || 'patch';
5
+ const pkg = JSON.parse(fs.readFileSync('package.json', 'utf8'));
6
+ const ioPkg = JSON.parse(fs.readFileSync('io-package.json', 'utf8'));
7
+
8
+ // Version erhöhen
9
+ const [major, minor, patch] = pkg.version.split('.').map(Number);
10
+ const newVersion = type === 'major' ? `${major + 1}.0.0`
11
+ : type === 'minor' ? `${major}.${minor + 1}.0`
12
+ : `${major}.${minor}.${patch + 1}`;
13
+
14
+ console.log(`Bumping version: ${pkg.version} -> ${newVersion}`);
15
+
16
+ // Dateien aktualisieren
17
+ pkg.version = newVersion;
18
+ ioPkg.common.version = newVersion;
19
+
20
+ fs.writeFileSync('package.json', JSON.stringify(pkg, null, '\t') + '\n');
21
+ fs.writeFileSync('io-package.json', JSON.stringify(ioPkg, null, '\t') + '\n');
22
+
23
+ // Git Commit und Tag
24
+ execSync(`git add package.json io-package.json`);
25
+ execSync(`git commit -m "chore: bump version to ${newVersion}"`);
26
+ execSync(`git tag v${newVersion}`);
27
+
28
+ console.log(`\nTo push: git push && git push origin v${newVersion}`);