@oxmc/node-smbios 1.0.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/package.json ADDED
@@ -0,0 +1,70 @@
1
+ {
2
+ "name": "@oxmc/node-smbios",
3
+ "version": "1.0.0",
4
+ "description": "A Node.js module designed to retrieve detailed system and hardware information from SMBIOS.",
5
+ "main": "index.js",
6
+ "scripts": {
7
+ "install": "node-pre-gyp install --fallback-to-build",
8
+ "build": "node-gyp rebuild",
9
+ "clean": "node-gyp clean",
10
+ "test": "node example.js",
11
+ "package": "node-pre-gyp package",
12
+ "publish-binary": "node-pre-gyp-github publish"
13
+ },
14
+ "binary": {
15
+ "module_name": "smbios",
16
+ "module_path": "./build/Release/",
17
+ "package_name": "{module_name}-v{version}-{node_abi}-{platform}-{arch}.tar.gz",
18
+ "host": "https://github.com/oxmc/node-smbios/releases/download/",
19
+ "remote_path": "v{version}"
20
+ },
21
+ "keywords": [
22
+ "smbios",
23
+ "dmi",
24
+ "system-information",
25
+ "hardware",
26
+ "bios",
27
+ "motherboard",
28
+ "baseboard",
29
+ "processor",
30
+ "cpu",
31
+ "memory",
32
+ "ram",
33
+ "chassis",
34
+ "native",
35
+ "addon",
36
+ "cross-platform",
37
+ "windows",
38
+ "linux",
39
+ "macos",
40
+ "system-info",
41
+ "hardware-info"
42
+ ],
43
+ "author": "Seth Olivarez <me@oxmc.me> (https://oxmc.me)",
44
+ "license": "GPL-3.0-only",
45
+ "repository": {
46
+ "type": "git",
47
+ "url": "git+https://github.com/oxmc/node-smbios.git"
48
+ },
49
+ "bugs": {
50
+ "url": "https://github.com/oxmc/node-smbios/issues"
51
+ },
52
+ "homepage": "https://github.com/oxmc/node-smbios#readme",
53
+ "gypfile": true,
54
+ "dependencies": {
55
+ "@mapbox/node-pre-gyp": "^2.0.3",
56
+ "node-addon-api": "^8.0.0"
57
+ },
58
+ "devDependencies": {
59
+ "node-gyp": "^10.0.0",
60
+ "node-pre-gyp-github": "^2.0.0"
61
+ },
62
+ "engines": {
63
+ "node": ">=18.0.0"
64
+ },
65
+ "os": [
66
+ "darwin",
67
+ "linux",
68
+ "win32"
69
+ ]
70
+ }
@@ -0,0 +1,266 @@
1
+ #include <napi.h>
2
+ #include "smbios_common.h"
3
+
4
+ namespace smbios {
5
+
6
+ /**
7
+ * Convert BiosInfo struct to JavaScript object
8
+ */
9
+ Napi::Object BiosInfoToObject(Napi::Env env, const BiosInfo& info) {
10
+ Napi::Object obj = Napi::Object::New(env);
11
+ obj.Set("vendor", Napi::String::New(env, info.vendor));
12
+ obj.Set("version", Napi::String::New(env, info.version));
13
+ obj.Set("releaseDate", Napi::String::New(env, info.releaseDate));
14
+ obj.Set("biosCharacteristics", Napi::String::New(env, info.biosCharacteristics));
15
+ return obj;
16
+ }
17
+
18
+ /**
19
+ * Convert SystemInfo struct to JavaScript object
20
+ */
21
+ Napi::Object SystemInfoToObject(Napi::Env env, const SystemInfo& info) {
22
+ Napi::Object obj = Napi::Object::New(env);
23
+ obj.Set("manufacturer", Napi::String::New(env, info.manufacturer));
24
+ obj.Set("productName", Napi::String::New(env, info.productName));
25
+ obj.Set("serialNumber", Napi::String::New(env, info.serialNumber));
26
+ obj.Set("uuid", Napi::String::New(env, info.uuid));
27
+ obj.Set("skuNumber", Napi::String::New(env, info.skuNumber));
28
+ obj.Set("family", Napi::String::New(env, info.family));
29
+ obj.Set("wakeUpType", Napi::String::New(env, info.wakeUpType));
30
+ return obj;
31
+ }
32
+
33
+ /**
34
+ * Convert BoardInfo struct to JavaScript object
35
+ */
36
+ Napi::Object BoardInfoToObject(Napi::Env env, const BoardInfo& info) {
37
+ Napi::Object obj = Napi::Object::New(env);
38
+ obj.Set("manufacturer", Napi::String::New(env, info.manufacturer));
39
+ obj.Set("product", Napi::String::New(env, info.product));
40
+ obj.Set("version", Napi::String::New(env, info.version));
41
+ obj.Set("serialNumber", Napi::String::New(env, info.serialNumber));
42
+ obj.Set("assetTag", Napi::String::New(env, info.assetTag));
43
+ obj.Set("locationInChassis", Napi::String::New(env, info.locationInChassis));
44
+ return obj;
45
+ }
46
+
47
+ /**
48
+ * Convert ProcessorInfo struct to JavaScript object
49
+ */
50
+ Napi::Object ProcessorInfoToObject(Napi::Env env, const ProcessorInfo& info) {
51
+ Napi::Object obj = Napi::Object::New(env);
52
+ obj.Set("manufacturer", Napi::String::New(env, info.manufacturer));
53
+ obj.Set("version", Napi::String::New(env, info.version));
54
+ obj.Set("socketDesignation", Napi::String::New(env, info.socketDesignation));
55
+ obj.Set("processorType", Napi::String::New(env, info.processorType));
56
+ obj.Set("processorFamily", Napi::String::New(env, info.processorFamily));
57
+ obj.Set("maxSpeed", Napi::String::New(env, info.maxSpeed));
58
+ obj.Set("currentSpeed", Napi::String::New(env, info.currentSpeed));
59
+ obj.Set("coreCount", Napi::String::New(env, info.coreCount));
60
+ obj.Set("threadCount", Napi::String::New(env, info.threadCount));
61
+ obj.Set("l2CacheSize", Napi::String::New(env, info.l2CacheSize));
62
+ obj.Set("l3CacheSize", Napi::String::New(env, info.l3CacheSize));
63
+ return obj;
64
+ }
65
+
66
+ /**
67
+ * Convert MemoryInfo struct to JavaScript object
68
+ */
69
+ Napi::Object MemoryInfoToObject(Napi::Env env, const MemoryInfo& info) {
70
+ Napi::Object obj = Napi::Object::New(env);
71
+ obj.Set("totalPhysicalMemory", Napi::String::New(env, info.totalPhysicalMemory));
72
+ obj.Set("availablePhysicalMemory", Napi::String::New(env, info.availablePhysicalMemory));
73
+ obj.Set("totalVirtualMemory", Napi::String::New(env, info.totalVirtualMemory));
74
+ obj.Set("availableVirtualMemory", Napi::String::New(env, info.availableVirtualMemory));
75
+ obj.Set("memoryDevices", Napi::String::New(env, info.memoryDevices));
76
+ obj.Set("maxCapacity", Napi::String::New(env, info.maxCapacity));
77
+ return obj;
78
+ }
79
+
80
+ /**
81
+ * Convert ChassisInfo struct to JavaScript object
82
+ */
83
+ Napi::Object ChassisInfoToObject(Napi::Env env, const ChassisInfo& info) {
84
+ Napi::Object obj = Napi::Object::New(env);
85
+ obj.Set("manufacturer", Napi::String::New(env, info.manufacturer));
86
+ obj.Set("type", Napi::String::New(env, info.type));
87
+ obj.Set("version", Napi::String::New(env, info.version));
88
+ obj.Set("serialNumber", Napi::String::New(env, info.serialNumber));
89
+ obj.Set("assetTag", Napi::String::New(env, info.assetTag));
90
+ obj.Set("bootUpState", Napi::String::New(env, info.bootUpState));
91
+ obj.Set("powerSupplyState", Napi::String::New(env, info.powerSupplyState));
92
+ obj.Set("thermalState", Napi::String::New(env, info.thermalState));
93
+ return obj;
94
+ }
95
+
96
+ /**
97
+ * Node.js binding: getBiosInfo()
98
+ */
99
+ Napi::Value GetBiosInfoWrapped(const Napi::CallbackInfo& info) {
100
+ Napi::Env env = info.Env();
101
+
102
+ try {
103
+ BiosInfo biosInfo = GetBiosInfo();
104
+ return BiosInfoToObject(env, biosInfo);
105
+ } catch (const std::exception& e) {
106
+ Napi::Error::New(env, e.what()).ThrowAsJavaScriptException();
107
+ return env.Null();
108
+ }
109
+ }
110
+
111
+ /**
112
+ * Node.js binding: getSystemInfo()
113
+ */
114
+ Napi::Value GetSystemInfoWrapped(const Napi::CallbackInfo& info) {
115
+ Napi::Env env = info.Env();
116
+
117
+ try {
118
+ SystemInfo systemInfo = GetSystemInfo();
119
+ return SystemInfoToObject(env, systemInfo);
120
+ } catch (const std::exception& e) {
121
+ Napi::Error::New(env, e.what()).ThrowAsJavaScriptException();
122
+ return env.Null();
123
+ }
124
+ }
125
+
126
+ /**
127
+ * Node.js binding: getBoardInfo()
128
+ */
129
+ Napi::Value GetBoardInfoWrapped(const Napi::CallbackInfo& info) {
130
+ Napi::Env env = info.Env();
131
+
132
+ try {
133
+ BoardInfo boardInfo = GetBoardInfo();
134
+ return BoardInfoToObject(env, boardInfo);
135
+ } catch (const std::exception& e) {
136
+ Napi::Error::New(env, e.what()).ThrowAsJavaScriptException();
137
+ return env.Null();
138
+ }
139
+ }
140
+
141
+ /**
142
+ * Node.js binding: getProcessorInfo()
143
+ */
144
+ Napi::Value GetProcessorInfoWrapped(const Napi::CallbackInfo& info) {
145
+ Napi::Env env = info.Env();
146
+
147
+ try {
148
+ ProcessorInfo procInfo = GetProcessorInfo();
149
+ return ProcessorInfoToObject(env, procInfo);
150
+ } catch (const std::exception& e) {
151
+ Napi::Error::New(env, e.what()).ThrowAsJavaScriptException();
152
+ return env.Null();
153
+ }
154
+ }
155
+
156
+ /**
157
+ * Node.js binding: getMemoryInfo()
158
+ */
159
+ Napi::Value GetMemoryInfoWrapped(const Napi::CallbackInfo& info) {
160
+ Napi::Env env = info.Env();
161
+
162
+ try {
163
+ MemoryInfo memInfo = GetMemoryInfo();
164
+ return MemoryInfoToObject(env, memInfo);
165
+ } catch (const std::exception& e) {
166
+ Napi::Error::New(env, e.what()).ThrowAsJavaScriptException();
167
+ return env.Null();
168
+ }
169
+ }
170
+
171
+ /**
172
+ * Node.js binding: getChassisInfo()
173
+ */
174
+ Napi::Value GetChassisInfoWrapped(const Napi::CallbackInfo& info) {
175
+ Napi::Env env = info.Env();
176
+
177
+ try {
178
+ ChassisInfo chassisInfo = GetChassisInfo();
179
+ return ChassisInfoToObject(env, chassisInfo);
180
+ } catch (const std::exception& e) {
181
+ Napi::Error::New(env, e.what()).ThrowAsJavaScriptException();
182
+ return env.Null();
183
+ }
184
+ }
185
+
186
+ /**
187
+ * Node.js binding: getAllInfo()
188
+ * Returns all information in a single call
189
+ */
190
+ Napi::Value GetAllInfoWrapped(const Napi::CallbackInfo& info) {
191
+ Napi::Env env = info.Env();
192
+
193
+ try {
194
+ Napi::Object result = Napi::Object::New(env);
195
+
196
+ BiosInfo biosInfo = GetBiosInfo();
197
+ SystemInfo systemInfo = GetSystemInfo();
198
+ BoardInfo boardInfo = GetBoardInfo();
199
+ ProcessorInfo procInfo = GetProcessorInfo();
200
+ MemoryInfo memInfo = GetMemoryInfo();
201
+ ChassisInfo chassisInfo = GetChassisInfo();
202
+
203
+ result.Set("bios", BiosInfoToObject(env, biosInfo));
204
+ result.Set("system", SystemInfoToObject(env, systemInfo));
205
+ result.Set("board", BoardInfoToObject(env, boardInfo));
206
+ result.Set("processor", ProcessorInfoToObject(env, procInfo));
207
+ result.Set("memory", MemoryInfoToObject(env, memInfo));
208
+ result.Set("chassis", ChassisInfoToObject(env, chassisInfo));
209
+
210
+ return result;
211
+ } catch (const std::exception& e) {
212
+ Napi::Error::New(env, e.what()).ThrowAsJavaScriptException();
213
+ return env.Null();
214
+ }
215
+ }
216
+
217
+ /**
218
+ * Initialize the Node.js addon
219
+ */
220
+ Napi::Object Init(Napi::Env env, Napi::Object exports) {
221
+ exports.Set(
222
+ Napi::String::New(env, "getBiosInfo"),
223
+ Napi::Function::New(env, GetBiosInfoWrapped)
224
+ );
225
+
226
+ exports.Set(
227
+ Napi::String::New(env, "getSystemInfo"),
228
+ Napi::Function::New(env, GetSystemInfoWrapped)
229
+ );
230
+
231
+ exports.Set(
232
+ Napi::String::New(env, "getBoardInfo"),
233
+ Napi::Function::New(env, GetBoardInfoWrapped)
234
+ );
235
+
236
+ exports.Set(
237
+ Napi::String::New(env, "getProcessorInfo"),
238
+ Napi::Function::New(env, GetProcessorInfoWrapped)
239
+ );
240
+
241
+ exports.Set(
242
+ Napi::String::New(env, "getMemoryInfo"),
243
+ Napi::Function::New(env, GetMemoryInfoWrapped)
244
+ );
245
+
246
+ exports.Set(
247
+ Napi::String::New(env, "getChassisInfo"),
248
+ Napi::Function::New(env, GetChassisInfoWrapped)
249
+ );
250
+
251
+ exports.Set(
252
+ Napi::String::New(env, "getAllInfo"),
253
+ Napi::Function::New(env, GetAllInfoWrapped)
254
+ );
255
+
256
+ return exports;
257
+ }
258
+
259
+ } // namespace smbios
260
+
261
+ // Register the addon (must be outside namespace)
262
+ Napi::Object InitModule(Napi::Env env, Napi::Object exports) {
263
+ return smbios::Init(env, exports);
264
+ }
265
+
266
+ NODE_API_MODULE(addon, InitModule)
@@ -0,0 +1,214 @@
1
+ #include "../smbios_common.h"
2
+
3
+ #ifdef __linux__
4
+
5
+ #include <fstream>
6
+ #include <string>
7
+
8
+ namespace smbios {
9
+
10
+ // DMI information is typically available in /sys/class/dmi/id/
11
+ const std::string DMI_PATH = "/sys/class/dmi/id/";
12
+
13
+ /**
14
+ * Read DMI file content
15
+ */
16
+ std::string ReadDMI(const std::string& filename) {
17
+ std::string path = DMI_PATH + filename;
18
+ return ReadFile(path);
19
+ }
20
+
21
+ BiosInfo GetBiosInfo() {
22
+ BiosInfo info;
23
+
24
+ info.vendor = ReadDMI("bios_vendor");
25
+ info.version = ReadDMI("bios_version");
26
+ info.releaseDate = ReadDMI("bios_date");
27
+ info.biosCharacteristics = ReadDMI("modalias");
28
+
29
+ return info;
30
+ }
31
+
32
+ SystemInfo GetSystemInfo() {
33
+ SystemInfo info;
34
+
35
+ info.manufacturer = ReadDMI("sys_vendor");
36
+ info.productName = ReadDMI("product_name");
37
+ info.serialNumber = ReadDMI("product_serial");
38
+ info.uuid = ReadDMI("product_uuid");
39
+ info.skuNumber = ReadDMI("product_sku");
40
+ info.family = ReadDMI("product_family");
41
+ info.wakeUpType = ReadDMI("chassis_type");
42
+
43
+ // Clean up common placeholder values
44
+ if (info.serialNumber == "To Be Filled By O.E.M." ||
45
+ info.serialNumber == "System Serial Number" ||
46
+ info.serialNumber == "0") {
47
+ info.serialNumber = "";
48
+ }
49
+
50
+ if (info.uuid == "To Be Filled By O.E.M." ||
51
+ info.uuid == "00000000-0000-0000-0000-000000000000") {
52
+ info.uuid = "";
53
+ }
54
+
55
+ return info;
56
+ }
57
+
58
+ BoardInfo GetBoardInfo() {
59
+ BoardInfo info;
60
+
61
+ info.manufacturer = ReadDMI("board_vendor");
62
+ info.product = ReadDMI("board_name");
63
+ info.version = ReadDMI("board_version");
64
+ info.serialNumber = ReadDMI("board_serial");
65
+ info.assetTag = ReadDMI("board_asset_tag");
66
+ info.locationInChassis = ReadDMI("chassis_vendor");
67
+
68
+ // Clean up common placeholder values
69
+ if (info.serialNumber == "To Be Filled By O.E.M." ||
70
+ info.serialNumber == "Board Serial Number" ||
71
+ info.serialNumber == "0") {
72
+ info.serialNumber = "";
73
+ }
74
+
75
+ if (info.assetTag == "To Be Filled By O.E.M." ||
76
+ info.assetTag == "Asset Tag" ||
77
+ info.assetTag == "0") {
78
+ info.assetTag = "";
79
+ }
80
+
81
+ return info;
82
+ }
83
+
84
+ ProcessorInfo GetProcessorInfo() {
85
+ ProcessorInfo info;
86
+
87
+ // Try to read from /proc/cpuinfo
88
+ std::ifstream cpuinfo("/proc/cpuinfo");
89
+ if (cpuinfo.is_open()) {
90
+ std::string line;
91
+ while (std::getline(cpuinfo, line)) {
92
+ if (line.find("vendor_id") != std::string::npos) {
93
+ size_t pos = line.find(":");
94
+ if (pos != std::string::npos) {
95
+ info.manufacturer = TrimString(line.substr(pos + 1));
96
+ }
97
+ } else if (line.find("model name") != std::string::npos) {
98
+ size_t pos = line.find(":");
99
+ if (pos != std::string::npos) {
100
+ info.version = TrimString(line.substr(pos + 1));
101
+ }
102
+ } else if (line.find("cpu family") != std::string::npos) {
103
+ size_t pos = line.find(":");
104
+ if (pos != std::string::npos) {
105
+ info.processorFamily = TrimString(line.substr(pos + 1));
106
+ }
107
+ } else if (line.find("cpu MHz") != std::string::npos) {
108
+ size_t pos = line.find(":");
109
+ if (pos != std::string::npos) {
110
+ info.currentSpeed = TrimString(line.substr(pos + 1));
111
+ }
112
+ } else if (line.find("cpu cores") != std::string::npos) {
113
+ size_t pos = line.find(":");
114
+ if (pos != std::string::npos) {
115
+ info.coreCount = TrimString(line.substr(pos + 1));
116
+ }
117
+ } else if (line.find("siblings") != std::string::npos && info.threadCount.empty()) {
118
+ size_t pos = line.find(":");
119
+ if (pos != std::string::npos) {
120
+ info.threadCount = TrimString(line.substr(pos + 1));
121
+ }
122
+ }
123
+ }
124
+ cpuinfo.close();
125
+ }
126
+
127
+ info.socketDesignation = "CPU Socket";
128
+ info.processorType = "Central Processor";
129
+ info.maxSpeed = info.currentSpeed; // Approximation
130
+
131
+ // Try to get cache sizes
132
+ std::string l2Cache = ReadFile("/sys/devices/system/cpu/cpu0/cache/index2/size");
133
+ if (!l2Cache.empty()) {
134
+ info.l2CacheSize = l2Cache;
135
+ }
136
+
137
+ std::string l3Cache = ReadFile("/sys/devices/system/cpu/cpu0/cache/index3/size");
138
+ if (!l3Cache.empty()) {
139
+ info.l3CacheSize = l3Cache;
140
+ }
141
+
142
+ return info;
143
+ }
144
+
145
+ MemoryInfo GetMemoryInfo() {
146
+ MemoryInfo info;
147
+
148
+ // Read from /proc/meminfo
149
+ std::ifstream meminfo("/proc/meminfo");
150
+ if (meminfo.is_open()) {
151
+ std::string line;
152
+ while (std::getline(meminfo, line)) {
153
+ if (line.find("MemTotal") != std::string::npos) {
154
+ size_t pos = line.find(":");
155
+ if (pos != std::string::npos) {
156
+ std::string value = TrimString(line.substr(pos + 1));
157
+ // Convert from KB to bytes
158
+ try {
159
+ size_t kb = std::stoull(value);
160
+ info.totalPhysicalMemory = std::to_string(kb * 1024);
161
+ } catch (...) {
162
+ info.totalPhysicalMemory = value;
163
+ }
164
+ }
165
+ } else if (line.find("MemAvailable") != std::string::npos) {
166
+ size_t pos = line.find(":");
167
+ if (pos != std::string::npos) {
168
+ std::string value = TrimString(line.substr(pos + 1));
169
+ try {
170
+ size_t kb = std::stoull(value);
171
+ info.availablePhysicalMemory = std::to_string(kb * 1024);
172
+ } catch (...) {
173
+ info.availablePhysicalMemory = value;
174
+ }
175
+ }
176
+ } else if (line.find("SwapTotal") != std::string::npos) {
177
+ size_t pos = line.find(":");
178
+ if (pos != std::string::npos) {
179
+ info.totalVirtualMemory = TrimString(line.substr(pos + 1));
180
+ }
181
+ } else if (line.find("SwapFree") != std::string::npos) {
182
+ size_t pos = line.find(":");
183
+ if (pos != std::string::npos) {
184
+ info.availableVirtualMemory = TrimString(line.substr(pos + 1));
185
+ }
186
+ }
187
+ }
188
+ meminfo.close();
189
+ }
190
+
191
+ info.memoryDevices = "N/A";
192
+ info.maxCapacity = info.totalPhysicalMemory;
193
+
194
+ return info;
195
+ }
196
+
197
+ ChassisInfo GetChassisInfo() {
198
+ ChassisInfo info;
199
+
200
+ info.manufacturer = ReadDMI("chassis_vendor");
201
+ info.type = ReadDMI("chassis_type");
202
+ info.version = ReadDMI("chassis_version");
203
+ info.serialNumber = ReadDMI("chassis_serial");
204
+ info.assetTag = ReadDMI("chassis_asset_tag");
205
+ info.bootUpState = "Normal";
206
+ info.powerSupplyState = "Safe";
207
+ info.thermalState = "Safe";
208
+
209
+ return info;
210
+ }
211
+
212
+ } // namespace smbios
213
+
214
+ #endif // __linux__