verteilen-core 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.
Files changed (55) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +2 -0
  3. package/bun.lock +730 -0
  4. package/index.ts +1 -0
  5. package/jest.config.js +8 -0
  6. package/package.json +42 -0
  7. package/src/client/analysis.ts +377 -0
  8. package/src/client/client.ts +230 -0
  9. package/src/client/cluster.ts +125 -0
  10. package/src/client/execute.ts +210 -0
  11. package/src/client/http.ts +45 -0
  12. package/src/client/javascript.ts +535 -0
  13. package/src/client/job_execute.ts +216 -0
  14. package/src/client/job_parameter.ts +41 -0
  15. package/src/client/os.ts +210 -0
  16. package/src/client/parameter.ts +58 -0
  17. package/src/client/resource.ts +121 -0
  18. package/src/client/shell.ts +147 -0
  19. package/src/interface/base.ts +82 -0
  20. package/src/interface/bus.ts +144 -0
  21. package/src/interface/enum.ts +181 -0
  22. package/src/interface/execute.ts +47 -0
  23. package/src/interface/record.ts +131 -0
  24. package/src/interface/server.ts +91 -0
  25. package/src/interface/struct.ts +292 -0
  26. package/src/interface/table.ts +34 -0
  27. package/src/interface/ui.ts +35 -0
  28. package/src/interface.ts +50 -0
  29. package/src/lan/en.json +395 -0
  30. package/src/lan/zh_TW.json +395 -0
  31. package/src/plugins/i18n.ts +20 -0
  32. package/src/script/console_manager.ts +135 -0
  33. package/src/script/console_server_manager.ts +46 -0
  34. package/src/script/execute/base.ts +309 -0
  35. package/src/script/execute/feedback.ts +212 -0
  36. package/src/script/execute/region_job.ts +14 -0
  37. package/src/script/execute/region_project.ts +23 -0
  38. package/src/script/execute/region_subtask.ts +14 -0
  39. package/src/script/execute/region_task.ts +23 -0
  40. package/src/script/execute/runner.ts +339 -0
  41. package/src/script/execute/util_parser.ts +175 -0
  42. package/src/script/execute_manager.ts +348 -0
  43. package/src/script/socket_manager.ts +329 -0
  44. package/src/script/webhook_manager.ts +6 -0
  45. package/src/script/webhook_server_manager.ts +102 -0
  46. package/src/util/server/console_handle.ts +248 -0
  47. package/src/util/server/log_handle.ts +194 -0
  48. package/test/TEST.ts +63 -0
  49. package/test/client/execute.test.ts +54 -0
  50. package/test/client/javascript.test.ts +78 -0
  51. package/test/client/server.test.ts +26 -0
  52. package/test/client/task.test.ts +136 -0
  53. package/test/script/parser.test.ts +110 -0
  54. package/test/script/socket.test.ts +27 -0
  55. package/tsconfig.json +15 -0
@@ -0,0 +1,216 @@
1
+ // ========================
2
+ //
3
+ // Share Codebase
4
+ //
5
+ // ========================
6
+ import WebSocket from "ws";
7
+ import { Job, JobCategory, JobType, JobType2, JobType2Text, JobTypeText, Libraries, Messager, Messager_log, OnePath, Parameter, PluginList, TwoPath } from "../interface";
8
+ import { i18n } from "../plugins/i18n";
9
+ import { ClientJavascript } from "./javascript";
10
+ import { ClientJobParameter } from "./job_parameter";
11
+ import { ClientOS } from "./os";
12
+
13
+ /**
14
+ * The job execute worker\
15
+ * This class should spawn by the cluster thread to prevent heavy calculation on the main thread
16
+ */
17
+ export class ClientJobExecute {
18
+ /**
19
+ * Project parameters for references
20
+ */
21
+ parameter:Parameter | undefined
22
+ /**
23
+ * User library for scripts
24
+ */
25
+ libraries:Libraries | undefined
26
+ /**
27
+ * The job uuid\
28
+ * This will put in the prefix of message
29
+ */
30
+ tag: string
31
+ runtime:string
32
+
33
+ private messager:Messager
34
+ private messager_log:Messager_log
35
+ private javascript:ClientJavascript
36
+ private os:ClientOS
37
+ private para:ClientJobParameter
38
+ private job:Job
39
+ private plugin:PluginList
40
+
41
+ constructor(_messager:Messager, _messager_log:Messager_log, _job:Job, _source:WebSocket | undefined, _plugin:PluginList){
42
+ this.messager = _messager
43
+ this.messager_log = _messager_log
44
+ this.tag = _job.uuid
45
+ this.runtime = _job.runtime_uuid || ''
46
+ this.job = _job
47
+ this.plugin = _plugin
48
+ this.para = new ClientJobParameter()
49
+ this.os = new ClientOS(() => this.tag, () => this.job.runtime_uuid || '', _messager, _messager_log)
50
+ this.javascript = new ClientJavascript(_messager, _messager_log, () => this.job)
51
+ this.parameter = process.env.parameter != undefined ? JSON.parse(process.env.parameter) : undefined
52
+ this.libraries = process.env.libraries != undefined ? JSON.parse(process.env.libraries) : undefined
53
+
54
+ ClientJavascript.Init(_messager, _messager_log, this.os, this.para,
55
+ () => this.libraries,
56
+ () => this.parameter,
57
+ () => this.job
58
+ )
59
+ }
60
+
61
+ /**
62
+ * The entry function to execute the job container
63
+ * @param job Target job
64
+ */
65
+ execute = () => {
66
+ // Output the job type message to let user know what is going on
67
+ this.messager_log(`[Execute] ${this.job.uuid} ${this.job.category == JobCategory.Execution ? i18n.global.t(JobTypeText[this.job.type]) : i18n.global.t(JobType2Text[this.job.type])}`, this.tag, this.runtime)
68
+ const child = this.job.category == JobCategory.Execution ? this.execute_job_exe() : this.execute_job_con()
69
+ return child
70
+ }
71
+
72
+ stop_all = () => {
73
+ this.os.stopall()
74
+ }
75
+
76
+ /**
77
+ * Execute the job that classify as run
78
+ * @param job Target job
79
+ * @returns Promise instance
80
+ */
81
+ private execute_job_exe = () => {
82
+ return new Promise<string>(async (resolve, reject) => {
83
+ switch(this.job.type as JobType){
84
+ case JobType.COPY_FILE:
85
+ {
86
+ const data:TwoPath = { from: this.job.string_args[0], to: this.job.string_args[1] }
87
+ this.os.file_copy(data)
88
+ resolve(`Copy file successfully, ${data.from}, ${data.to}`)
89
+ break
90
+ }
91
+ case JobType.COPY_DIR:
92
+ {
93
+ const data:TwoPath = { from: this.job.string_args[0], to: this.job.string_args[1] }
94
+ this.os.dir_copy(data)
95
+ resolve(`Copy dir successfully, ${data.from}, ${data.to}`)
96
+ break
97
+ }
98
+ case JobType.DELETE_FILE:
99
+ {
100
+ const data:OnePath = { path: this.job.string_args[0] }
101
+ this.os.file_delete(data)
102
+ resolve(`Delete file successfully, ${data.path}`)
103
+ break
104
+ }
105
+ case JobType.DELETE_DIR:
106
+ {
107
+ const data:OnePath = { path: this.job.string_args[0] }
108
+ this.os.dir_delete(data)
109
+ resolve(`Delete folder successfully, ${data.path}`)
110
+ break
111
+ }
112
+ case JobType.CREATE_DIR:
113
+ {
114
+ const data:OnePath = { path: this.job.string_args[0] }
115
+ this.os.dir_create(data)
116
+ resolve(`Create dir successfully, ${data.path}`)
117
+ break
118
+ }
119
+ case JobType.CREATE_FILE:
120
+ {
121
+ const data:TwoPath = { from: this.job.string_args[0], to: this.job.string_args[1] }
122
+ this.os.file_write(data)
123
+ resolve(`Create file successfully, ${data.from} ${data.to}`)
124
+ break
125
+ }
126
+ case JobType.RENAME:
127
+ {
128
+ const data:TwoPath = { from: this.job.string_args[0], to: this.job.string_args[1] }
129
+ this.os.rename(data)
130
+ resolve(`Rename successfully, ${data.from} ${data.to}`)
131
+ break
132
+ }
133
+ case JobType.JAVASCRIPT:
134
+ {
135
+ await this.javascript.JavascriptExecuteWithLib(this.job.script, this.job.string_args).then(() => {
136
+ resolve(`Execute Javascript successfully`)
137
+ }).catch(k => {
138
+ reject(k)
139
+ })
140
+ break
141
+ }
142
+ case JobType.COMMAND:
143
+ {
144
+ this.os.command(this.job.string_args[1], this.job.string_args[2], this.job.string_args[0]).then(m => {
145
+ resolve(m)
146
+ }).catch(err => {
147
+ reject(err)
148
+ })
149
+ break
150
+ }
151
+ case JobType.LIB_COMMAND:
152
+ {
153
+ const target = this.plugin.plugins.find(x => x.name == this.job.string_args[0])
154
+ if(target == undefined){
155
+ reject("Cannot find plugin " + this.job.string_args[0])
156
+ return
157
+ }
158
+
159
+ const archTarget = target.contents.find(x => x.arch == process.arch && x.platform == process.platform)
160
+ if(archTarget == undefined){
161
+ reject({
162
+ code: 1,
163
+ message: "Cannot find plugin match arch " + this.job.string_args[0] + " " + process.arch
164
+ })
165
+ return
166
+ }
167
+
168
+ this.os.lib_command(archTarget.filename, this.job.string_args[1]).then(m => {
169
+ resolve(m)
170
+ }).catch(err => {
171
+ reject(err)
172
+ })
173
+ break
174
+ }
175
+ }
176
+ })
177
+ }
178
+
179
+ /**
180
+ * Execute the job that classify as condition
181
+ * @param job Target job
182
+ * @returns Promise instance
183
+ */
184
+ private execute_job_con = () => {
185
+ return new Promise<string>(async (resolve, reject) => {
186
+ switch(this.job.type as JobType2){
187
+ case JobType2.CHECK_PATH:
188
+ {
189
+ const data:OnePath = { path: this.job.string_args[0] }
190
+ if(this.os.fs_exist(data)){
191
+ resolve(`Path exist ${data.path}`)
192
+ }else{
193
+ reject({
194
+ code: 2,
195
+ message: `Path not exist ${data.path}`
196
+ })
197
+ }
198
+ break
199
+ }
200
+ case JobType2.JAVASCRIPT:
201
+ {
202
+ const r = await this.javascript.JavascriptExecuteWithLib(this.job.script, this.job.string_args)
203
+ if(r != undefined && r == 0){
204
+ resolve(`Execute Javascript successfully`)
205
+ }else{
206
+ reject({
207
+ code: 3,
208
+ message: `Execute Javascript failed`
209
+ })
210
+ }
211
+ break
212
+ }
213
+ }
214
+ })
215
+ }
216
+ }
@@ -0,0 +1,41 @@
1
+ // ========================
2
+ //
3
+ // Share Codebase
4
+ //
5
+ // ========================
6
+ import { Header, Setter } from "../interface"
7
+
8
+ export class ClientJobParameter {
9
+ /**
10
+ * Update parameter number on the cluster server
11
+ * @param data Target KeyValue
12
+ */
13
+ feedbacknumber = (data:Setter) => {
14
+ this.feedback("feedbacknumber", data)
15
+ }
16
+ feedbackboolean = (data:Setter) => {
17
+ this.feedback("feedbackboolean", data)
18
+ }
19
+ feedbackstring = (data:Setter) => {
20
+ this.feedback("feedbackstring", data)
21
+ }
22
+ feedbackobject = (data:Setter) => {
23
+ this.feedback("feedbackobject", data)
24
+ }
25
+ feedbacklist = (data:Setter) => {
26
+ this.feedback("feedbacklist", data)
27
+ }
28
+ feedbackselect = (data:Setter) => {
29
+ this.feedback("feedbackselect", data)
30
+ }
31
+ private feedback = (title:string, data:Setter) => {
32
+ const p:Header = {
33
+ name: title,
34
+ data: {
35
+ key: data.key,
36
+ value: data.value
37
+ }
38
+ }
39
+ console.log(JSON.stringify(p))
40
+ }
41
+ }
@@ -0,0 +1,210 @@
1
+ // ========================
2
+ //
3
+ // Share Codebase
4
+ //
5
+ // ========================
6
+ import { ChildProcess, exec, spawn } from 'child_process';
7
+ import tkill from 'tree-kill'
8
+ import * as fs from "fs";
9
+ import * as path from "path";
10
+ import * as os from "os";
11
+ import { DATA_FOLDER, Messager, Messager_log, OnePath, TwoPath } from "../interface";
12
+
13
+ type getstring = ()=>string
14
+
15
+ /**
16
+ * The operation system related actions utility\
17
+ * If you want to do something related to things below
18
+ * * File operation
19
+ * * Folder checker
20
+ * * Writing a file
21
+ * * Call a exe file
22
+ *
23
+ * Please get a instance of this, and call the methods instead using fs youself
24
+ */
25
+ export class ClientOS {
26
+ private messager:Messager
27
+ private messager_log:Messager_log
28
+ private tag:getstring
29
+ private runtime:getstring
30
+ private children:Array<ChildProcess> = []
31
+
32
+ /**
33
+ *
34
+ * @param _tag The tag getter that put in the prefix of the message
35
+ * @param _messager Message method
36
+ * @param _messager_log Message method with output on the screen feature
37
+ */
38
+ constructor(_tag:getstring, _runtime:getstring, _messager:Messager, _messager_log:Messager_log){
39
+ this.tag = _tag
40
+ this.runtime = _runtime
41
+ this.messager = _messager
42
+ this.messager_log = _messager_log
43
+ }
44
+
45
+ file_copy = (data:TwoPath) => {
46
+ this.messager(`[OS Action] File copy, ${data.from} => ${data.to}`, this.tag())
47
+ fs.copyFileSync(data.from, data.to)
48
+ }
49
+
50
+ dir_copy = (data:TwoPath) => {
51
+ this.messager(`[OS Action] Folder copy, ${data.from} => ${data.to}`, this.tag())
52
+ fs.cpSync(data.from, data.to, { recursive: true, force: true })
53
+ }
54
+
55
+ file_delete = (data:OnePath) => {
56
+ this.messager(`[OS Action] File delete, ${data.path}`, this.tag())
57
+ fs.rmSync(data.path);
58
+ }
59
+
60
+ dir_delete = (data:OnePath) => {
61
+ this.messager(`[OS Action] Folder delete, ${data.path}`, this.tag())
62
+ fs.rmSync(data.path, { recursive: true, force: true })
63
+ }
64
+
65
+ rename = (data:TwoPath) => {
66
+ this.messager(`[OS Action] File or dir rename, ${data.from} => ${data.to}`, this.tag())
67
+ fs.renameSync(data.from, data.to)
68
+ }
69
+
70
+ fs_exist = (data:OnePath):boolean => {
71
+ const v = fs.existsSync(data.path)
72
+ this.messager(`[OS Action] Check path exists, ${data.path}`, this.tag())
73
+ return v
74
+ }
75
+
76
+ fs_dir_exist = (data:OnePath):boolean => {
77
+ const p = this.fs_exist(data)
78
+ if(!p) return false
79
+ const stat = fs.statSync(data.path)
80
+ return stat.isDirectory()
81
+ }
82
+
83
+ fs_file_exist = (data:OnePath):boolean => {
84
+ const p = this.fs_exist(data)
85
+ if(!p) return false
86
+ const stat = fs.statSync(data.path)
87
+ return stat.isFile()
88
+ }
89
+
90
+ dir_files = (data:OnePath):Array<string> => {
91
+ const r = fs.readdirSync(data.path, { withFileTypes: true }).filter(x => x.isFile()).map(x => x.name)
92
+ return r as string[]
93
+ }
94
+
95
+ dir_dirs = (data:OnePath):Array<string> => {
96
+ const r = fs.readdirSync(data.path, { withFileTypes: true }).filter(x => x.isDirectory()).map(x => x.name)
97
+ return r as string[]
98
+ }
99
+
100
+ dir_create = (data:OnePath) => {
101
+ this.messager(`[OS Action] Create folder, ${data.path}`, this.tag())
102
+ fs.mkdirSync(data.path, {recursive: true})
103
+ }
104
+
105
+ file_write = (data:TwoPath) => {
106
+ this.messager(`[OS Action] Create file, ${data.from}`, this.tag())
107
+ fs.writeFileSync(data.from, data.to)
108
+ }
109
+
110
+ file_read = (data:OnePath) => {
111
+ return fs.readFileSync(data.path).toString()
112
+ }
113
+
114
+ /**
115
+ * Kill all current running processes
116
+ */
117
+ stopall = () => {
118
+ this.children.forEach(x => {
119
+ x.stdin!.write('q')
120
+ x.stdin!.end()
121
+ tkill(x.pid!, 'SIGKILL')
122
+ })
123
+ this.children = []
124
+ }
125
+
126
+ lib_command = async (command:string, args:string):Promise<string> => {
127
+ const cc = process.platform == "win32" ? command : "./" + command
128
+ return this.command(cc, args, path.join(os.homedir(), DATA_FOLDER, "exe"))
129
+ }
130
+
131
+ /**
132
+ * Call command on terminal
133
+ * @param cwd The system location
134
+ * @param command Command name, Or you can put filename here
135
+ * @param args Arguments, It will split by space afterward
136
+ * @returns
137
+ */
138
+ command = async (command:string, args:string, cwd?:string):Promise<string> => {
139
+ this.messager_log(`[OS Action] Command cwd: ${cwd}`, this.tag())
140
+ this.messager_log(`[OS Action] Command command: ${command}`, this.tag())
141
+ this.messager_log(`[OS Action] Command args: ${args}`, this.tag())
142
+ return new Promise<string>((resolve, reject) => {
143
+ const child = spawn(command, args.split(' '),
144
+ {
145
+ cwd: cwd,
146
+ shell: true,
147
+ stdio: ['pipe', 'pipe', 'pipe']
148
+ })
149
+ child.stdin.setDefaultEncoding('utf8')
150
+ // The kill process detecter
151
+ child.on('spawn', () => {
152
+ this.children.push(child)
153
+ this.messager_log(`[Command] Spawn process`, this.tag())
154
+ })
155
+ child.on('error', (err) => {
156
+ this.messager_log(`[Command] Error: ${err}`, this.tag())
157
+ reject(`Error ${err}`)
158
+ })
159
+ child.on('exit', (code, signal) => {
160
+ this.messager_log(`[Command] Process Exit: ${code}`, this.tag())
161
+ })
162
+ child.on('message', (message, sendHandle) => {
163
+ this.messager_log(`[Command] : ${message.toString()}`, this.tag())
164
+ })
165
+ child.on('close', (code, signal) => {
166
+ this.messager_log(`[Command] Process Close: ${code}`, this.tag())
167
+ const index = this.children.findIndex(x => x.pid == child.pid)
168
+ if(index != -1) this.children.splice(index, 1)
169
+ resolve(`Successfully ${code}`)
170
+ })
171
+ child.stdout.setEncoding('utf8');
172
+ child.stdout.on('data', (chunk) => {
173
+ this.messager_log(`[Command Info] : ${chunk.toString()}`, this.tag())
174
+ })
175
+ child.stderr.setEncoding('utf8');
176
+ child.stderr.on('data', (chunk) => {
177
+ this.messager_log(`[Command Error] : ${chunk.toString()}`, this.tag())
178
+ })
179
+ })
180
+ }
181
+
182
+ command_sync = async (command:string, args:string, cwd?:string):Promise<string> => {
183
+ return this.command(command, args, cwd)
184
+ }
185
+
186
+ command_exec = (command:string, args:string, cwd?:string) => {
187
+ this.messager_log(`[OS Action] Command cwd: ${cwd}`, this.tag())
188
+ this.messager_log(`[OS Action] Command command: ${command}`, this.tag())
189
+ this.messager_log(`[OS Action] Command args: ${args}`, this.tag())
190
+ const child = exec(`${command} ${args}`, {
191
+ cwd: cwd
192
+ })
193
+
194
+ child.on('spawn', () => {
195
+ this.messager_log(`[Command] Spawn process`, this.tag())
196
+ })
197
+ child.on('error', (err) => {
198
+ this.messager_log(`[Command] Error: ${err}`, this.tag())
199
+ })
200
+ child.on('exit', (code, signal) => {
201
+ this.messager_log(`[Command] Process Exit: ${code}`, this.tag())
202
+ })
203
+ child.on('message', (message, sendHandle) => {
204
+ this.messager_log(`[Command] : ${message.toString()}`, this.tag())
205
+ })
206
+ child.on('close', (code, signal) => {
207
+ this.messager_log(`[Command] Process Close: ${code}`, this.tag())
208
+ })
209
+ }
210
+ }
@@ -0,0 +1,58 @@
1
+ // ========================
2
+ //
3
+ // Share Codebase
4
+ //
5
+ // ========================
6
+ import WebSocket from "ws";
7
+ import { Header, Setter } from "../interface";
8
+
9
+ /**
10
+ * The parameter feedback helper\
11
+ * Update the main parameter container on the cluster server
12
+ */
13
+ export class ClientParameter {
14
+ private source:WebSocket | undefined
15
+
16
+ constructor(_source:WebSocket | undefined){
17
+ this.source = _source
18
+ }
19
+
20
+ /**
21
+ * Update parameter number on the cluster server
22
+ * @param data Target KeyValue
23
+ */
24
+ feedbacknumber = (data:Setter) => {
25
+ this.feedback("feedback_number", data)
26
+ }
27
+ /**
28
+ * Update parameter boolean on the cluster server
29
+ * @param data Target KeyValue
30
+ */
31
+ feedbackboolean = (data:Setter) => {
32
+ this.feedback("feedback_boolean", data)
33
+ }
34
+ /**
35
+ * Update parameter string on the cluster server
36
+ * @param data Target KeyValue
37
+ */
38
+ feedbackstring = (data:Setter) => {
39
+ this.feedback("feedback_string", data)
40
+ }
41
+ feedbackobject = (data:Setter) => {
42
+ this.feedback("feedback_object", data)
43
+ }
44
+ feedbacklist = (data:Setter) => {
45
+ this.feedback("feedback_list", data)
46
+ }
47
+ feedbackselect = (data:Setter) => {
48
+ this.feedback("feedback_select", data)
49
+ }
50
+ private feedback = (title:string, data:Setter) => {
51
+ if(this.source == undefined) return
52
+ const p:Header = {
53
+ name: title,
54
+ data: data
55
+ }
56
+ this.source.send(JSON.stringify(p, null, 2))
57
+ }
58
+ }
@@ -0,0 +1,121 @@
1
+ // ========================
2
+ //
3
+ // Share Codebase
4
+ //
5
+ // ========================
6
+ import si from "systeminformation"
7
+ import { ResourceType } from "../interface"
8
+ import { SystemLoad } from "../interface/struct"
9
+
10
+ /**
11
+ * The resource query helper
12
+ */
13
+ export class ClientResource {
14
+ is_query = false
15
+
16
+ Query = async (src:SystemLoad | undefined = undefined, type:ResourceType = ResourceType.ALL):Promise<SystemLoad> => {
17
+ this.is_query = true
18
+ const result:SystemLoad = src != undefined ? src : this.create_new()
19
+
20
+ const _system = (type & ResourceType.SYSTEM ) == ResourceType.SYSTEM ? si.system() : undefined
21
+ const _cpu = si.cpu()
22
+ const _ram = si.mem()
23
+ const _battery = si.battery()
24
+ const _load = si.currentLoad()
25
+ const _os = si.osInfo()
26
+ const _gpu = si.graphics()
27
+ const _disk = si.fsSize()
28
+ const _net = si.networkStats()
29
+ this.is_query = false
30
+
31
+ return await Promise.all([_system, _cpu, _ram, _battery, _load, _os, _gpu, _disk, _net]).then(x => {
32
+ const system = x[0]
33
+ const cpu = x[1]
34
+ const ram = x[2]
35
+ const battery = x[3]
36
+ const load = x[4]
37
+ const os = x[5]
38
+ const gpu = x[6]
39
+ const disk = x[7]
40
+ const net = x[8]
41
+
42
+ if(system != undefined){
43
+ result.system_name = `${system.manufacturer} ${system.model}`
44
+ result.virtual = system.virtual
45
+ }
46
+ if(os != undefined){
47
+ result.platform = process.platform
48
+ result.arch = process.arch
49
+ result.hostname = os.hostname
50
+ }
51
+ if(cpu != undefined){
52
+ result.cpu_name = `${cpu.manufacturer} ${cpu.brand} ${cpu.speed}`
53
+ result.cpu_core = cpu.cores
54
+ }
55
+ if(load != undefined){
56
+ result.cpu_usage = load.currentLoadGuest + load.currentLoadIrq + load.currentLoadSystem + load.currentLoad + load.currentLoadSteal + load.currentLoadNice
57
+ }
58
+ if(ram != undefined){
59
+ result.ram_usage = ram.used
60
+ result.ram_free = ram.free
61
+ result.ram_total = ram.total
62
+ }
63
+ if(battery != undefined){
64
+ result.battery = battery.hasBattery ? battery.percent : 1
65
+ result.charging = battery.isCharging
66
+ }
67
+ if(gpu != undefined){
68
+ result.gpu = gpu.controllers.map(x => ({
69
+ gpu_name: `${x.vendor} ${x.model}`
70
+ }))
71
+ }
72
+ if(disk != undefined){
73
+ result.disk = disk.map(x => ({
74
+ disk_name: x.fs,
75
+ disk_type: x.type,
76
+ disk_free: x.available,
77
+ disk_total: x.size,
78
+ disk_usage: x.used,
79
+ disk_percentage: x.use,
80
+ }))
81
+ }
82
+ if(net != undefined){
83
+ result.net = net.map(x => ({
84
+ net_name: x.iface,
85
+ download: x.rx_sec,
86
+ upload: x.tx_sec
87
+ }))
88
+ }
89
+
90
+ result.pid_usage = process.pid
91
+ return result
92
+ })
93
+ }
94
+
95
+ private create_new = ():SystemLoad => {
96
+ return {
97
+ system_name: '',
98
+ virtual: false,
99
+ platform: '',
100
+ arch: '',
101
+ hostname: '',
102
+
103
+ cpu_name: '',
104
+ cpu_core: 0,
105
+ cpu_usage: 0,
106
+
107
+ ram_usage: 0,
108
+ ram_free: 0,
109
+ ram_total: 0,
110
+
111
+ battery: 0,
112
+ charging: false,
113
+
114
+ gpu: [],
115
+ disk: [],
116
+ net: [],
117
+
118
+ pid_usage: 0
119
+ }
120
+ }
121
+ }