pinokiod 3.41.0 → 3.43.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 (82) hide show
  1. package/kernel/api/browser/index.js +3 -1
  2. package/kernel/api/cloudflare/index.js +3 -3
  3. package/kernel/api/index.js +187 -51
  4. package/kernel/api/loading/index.js +15 -0
  5. package/kernel/api/process/index.js +7 -0
  6. package/kernel/api/shell/index.js +0 -2
  7. package/kernel/bin/browserless.js +22 -0
  8. package/kernel/bin/caddy.js +36 -4
  9. package/kernel/bin/index.js +4 -1
  10. package/kernel/bin/setup.js +38 -5
  11. package/kernel/connect/backend.js +110 -0
  12. package/kernel/connect/config.js +171 -0
  13. package/kernel/connect/index.js +18 -7
  14. package/kernel/connect/providers/huggingface/index.js +98 -0
  15. package/kernel/connect/providers/x/index.js +0 -1
  16. package/kernel/environment.js +91 -19
  17. package/kernel/git.js +46 -3
  18. package/kernel/index.js +119 -39
  19. package/kernel/peer.js +40 -5
  20. package/kernel/plugin.js +3 -2
  21. package/kernel/procs.js +27 -20
  22. package/kernel/prototype.js +30 -16
  23. package/kernel/router/common.js +1 -1
  24. package/kernel/router/connector.js +1 -3
  25. package/kernel/router/index.js +38 -4
  26. package/kernel/router/localhost_home_router.js +5 -1
  27. package/kernel/router/localhost_port_router.js +27 -1
  28. package/kernel/router/localhost_static_router.js +93 -0
  29. package/kernel/router/localhost_variable_router.js +14 -9
  30. package/kernel/router/peer_peer_router.js +3 -0
  31. package/kernel/router/peer_static_router.js +43 -0
  32. package/kernel/router/peer_variable_router.js +15 -14
  33. package/kernel/router/processor.js +26 -1
  34. package/kernel/router/rewriter.js +59 -0
  35. package/kernel/scripts/git/commit +11 -1
  36. package/kernel/shell.js +8 -3
  37. package/kernel/util.js +65 -6
  38. package/package.json +2 -1
  39. package/server/index.js +1037 -964
  40. package/server/public/common.js +382 -1
  41. package/server/public/fscreator.js +0 -1
  42. package/server/public/loading.js +17 -0
  43. package/server/public/notifyinput.js +0 -1
  44. package/server/public/opener.js +4 -2
  45. package/server/public/style.css +311 -11
  46. package/server/socket.js +7 -1
  47. package/server/views/app.ejs +1747 -351
  48. package/server/views/columns.ejs +338 -0
  49. package/server/views/connect/huggingface.ejs +353 -0
  50. package/server/views/connect/index.ejs +410 -0
  51. package/server/views/connect/x.ejs +43 -9
  52. package/server/views/connect.ejs +709 -49
  53. package/server/views/container.ejs +357 -0
  54. package/server/views/d.ejs +251 -62
  55. package/server/views/download.ejs +54 -10
  56. package/server/views/editor.ejs +11 -0
  57. package/server/views/explore.ejs +40 -15
  58. package/server/views/file_explorer.ejs +25 -246
  59. package/server/views/form.ejs +44 -1
  60. package/server/views/frame.ejs +39 -1
  61. package/server/views/github.ejs +48 -11
  62. package/server/views/help.ejs +48 -7
  63. package/server/views/index.ejs +119 -58
  64. package/server/views/index2.ejs +3 -4
  65. package/server/views/init/index.ejs +651 -197
  66. package/server/views/install.ejs +1 -1
  67. package/server/views/mini.ejs +47 -18
  68. package/server/views/net.ejs +199 -67
  69. package/server/views/network.ejs +220 -94
  70. package/server/views/network2.ejs +3 -4
  71. package/server/views/old_network.ejs +3 -3
  72. package/server/views/prototype/index.ejs +48 -11
  73. package/server/views/review.ejs +1005 -0
  74. package/server/views/rows.ejs +341 -0
  75. package/server/views/screenshots.ejs +1020 -0
  76. package/server/views/settings.ejs +160 -23
  77. package/server/views/setup.ejs +49 -7
  78. package/server/views/setup_home.ejs +43 -10
  79. package/server/views/shell.ejs +7 -1
  80. package/server/views/start.ejs +14 -9
  81. package/server/views/terminal.ejs +13 -2
  82. package/server/views/tools.ejs +1015 -0
package/kernel/git.js CHANGED
@@ -4,16 +4,18 @@ const path = require('path')
4
4
  const { glob, sync, hasMagic } = require('glob-gitignore')
5
5
  const http = require('isomorphic-git/http/node')
6
6
  const ini = require('ini')
7
+ const Util = require('./util')
7
8
  class Git {
8
9
  constructor(kernel) {
9
10
  this.kernel = kernel
10
11
  this.dirs = new Set()
12
+ this.mapping = {}
11
13
  }
12
14
  async findGitDirs(dir, results = []) {
13
15
  const entries = await fs.promises.readdir(dir, { withFileTypes: true });
14
-
15
16
  for (const entry of entries) {
16
- if (entry.isDirectory()) {
17
+ let type = await Util.file_type(dir, entry)
18
+ if (type.directory) {
17
19
  if (entry.name === '.git') {
18
20
  results.push(path.join(dir, entry.name));
19
21
  continue; // don't go deeper in this repo
@@ -26,6 +28,16 @@ class Git {
26
28
  }
27
29
  return results;
28
30
  }
31
+ async index(kernel) {
32
+ await this.repos(kernel.path("api"))
33
+ }
34
+ find(git_url) {
35
+ let found = this.mapping[git_url]
36
+ if (!found) {
37
+ found = this.mapping[git_url + ".git"]
38
+ }
39
+ return found
40
+ }
29
41
 
30
42
  async repos (root) {
31
43
  let _repos = await this.findGitDirs(root)
@@ -47,10 +59,13 @@ class Git {
47
59
  const gitParentRelPath = path.relative(this.kernel.path("api"), gitParentPath)
48
60
  let dir = path.dirname(gitPath)
49
61
  let display_name
62
+ let main
50
63
  if (gitRelPathSansGit === ".") {
51
64
  display_name = name
65
+ main = true
52
66
  } else {
53
67
  display_name = `${name}/${gitRelPathSansGit}`
68
+ main = false
54
69
  }
55
70
  try {
56
71
  let gitRemote = await git.getConfig({
@@ -60,16 +75,26 @@ class Git {
60
75
  path: 'remote.origin.url'
61
76
  })
62
77
  repos.push({
78
+ main,
63
79
  name: display_name,
64
80
  gitPath,
65
81
  gitRelPath,
66
82
  gitParentPath,
67
83
  gitParentRelPath,
68
84
  dir,
69
- url: gitRemote
85
+ url: gitRemote,
70
86
  })
87
+ if (!this.mapping[gitRemote]) {
88
+ let head = await this.getHead(gitParentPath)
89
+ this.mapping[gitRemote] = {
90
+ main,
91
+ path: gitParentPath,
92
+ head
93
+ }
94
+ }
71
95
  } catch (e) {
72
96
  repos.push({
97
+ main,
73
98
  name: display_name,
74
99
  gitPath,
75
100
  gitRelPath,
@@ -92,6 +117,24 @@ class Git {
92
117
  return null
93
118
  }
94
119
  }
120
+ async getHead(repoPath) {
121
+ const commits = await git.log({
122
+ fs,
123
+ dir: repoPath,
124
+ depth: 1, // only get the latest commit
125
+ });
126
+
127
+ if (commits.length === 0) {
128
+ throw new Error("No commits found in repository");
129
+ }
130
+
131
+ const { oid, commit } = commits[0];
132
+ return {
133
+ hash: oid,
134
+ message: commit.message,
135
+ };
136
+ }
137
+
95
138
  async resolveCommitOid(dir, ref) {
96
139
  const oid = await git.resolveRef({ fs, dir, ref });
97
140
  const { type } = await git.readObject({ fs, dir, oid });
package/kernel/index.js CHANGED
@@ -43,6 +43,7 @@ const { ProxyAgent } = require('proxy-agent');
43
43
  const fakeUa = require('fake-useragent');
44
44
  //const kill = require('./tree-kill');
45
45
  const kill = require('kill-sync')
46
+ const ejs = require('ejs');
46
47
  const VARS = {
47
48
  pip: {
48
49
  install: {
@@ -83,11 +84,101 @@ class Kernel {
83
84
  this.jsdom = jsdom
84
85
  this.exposed = {}
85
86
  this.envs = {}
87
+ this.pinokio_configs = {}
86
88
  this.shellpath = shellPath.sync()
87
89
  this.favicon = new Favicon()
88
90
 
89
91
 
90
92
  }
93
+ async renderFile(filepath, data) {
94
+ let response = await new Promise((resolve, reject) => {
95
+ ejs.renderFile(filepath, data, (err, rendered) => {
96
+ if (err) {
97
+ reject(err)
98
+ } else {
99
+ resolve(rendered)
100
+ }
101
+ })
102
+ })
103
+ return response
104
+ }
105
+ async dns(request) {
106
+ let config
107
+ let api_path
108
+ let name
109
+
110
+ let is_static_project // is_static_project := no pinokio.js file
111
+ if (request.path) {
112
+ let relpath = path.relative(this.path("api"), request.path)
113
+ // chunks: "comfy.git/start.js"
114
+ let chunks = relpath.split(path.sep)
115
+ // name: "comfy.git"
116
+ name = chunks[0]
117
+ let launcher = await this.api.launcher(name)
118
+ config = launcher.script
119
+ api_path = launcher.root
120
+ } else {
121
+ config = request.config
122
+ name = request.name
123
+ api_path = this.path("api", request.name)
124
+ }
125
+ if (!config) {
126
+ is_static_project = true
127
+ }
128
+ let dns = {
129
+ "@": [
130
+ "$local.url@start", // load local.url for "start" script
131
+ ".", // load ./index.html
132
+ "dist", // load ./dist/index.html
133
+ "build", // load ./build/index.html
134
+ "docs" // load ./docs/index.html
135
+ ]
136
+ }
137
+ if (config) {
138
+ if (config.dns) {
139
+ for(let key in config.dns) {
140
+ if (config.dns[key]) {
141
+ config.dns[key] = config.dns[key].concat(dns[key])
142
+ }
143
+ }
144
+ } else {
145
+ config.dns = dns
146
+ }
147
+ } else {
148
+ config = {
149
+ dns
150
+ }
151
+ }
152
+
153
+ for(let key in config.dns) {
154
+ let filtered = []
155
+ for(let item of config.dns[key]) {
156
+ if (item.startsWith("$")) {
157
+ if (is_static_project) {
158
+ // do not add since there will be no local variables
159
+ } else {
160
+ filtered.push(item)
161
+ }
162
+ } else if (item.startsWith(":")) {
163
+ // port
164
+ filtered.push(item)
165
+ } else {
166
+ // file path => check if the <path>/index.html exists
167
+ let exists = await this.exists(path.resolve(api_path, item, "index.html"))
168
+ if (exists) {
169
+ filtered.push(item)
170
+ }
171
+ }
172
+ }
173
+ if (!filtered.includes(".")) {
174
+ filtered.push(".")
175
+ }
176
+ config.dns[key] = filtered
177
+
178
+ }
179
+ this.pinokio_configs[name] = config
180
+ }
181
+
91
182
  /*
92
183
  kernel.env() => return the system environment
93
184
  kernel.env("api/stablediffusion") => returns the full environment object
@@ -218,6 +309,9 @@ class Kernel {
218
309
  return 42003
219
310
  }
220
311
  }
312
+ async symlink({ from, to }) {
313
+ await Util.symlink({ from, to })
314
+ }
221
315
  port(port) {
222
316
  // 1. if port is passed, check port
223
317
  // 2. if no port is passed, get the next available port
@@ -292,7 +386,6 @@ class Kernel {
292
386
  }
293
387
  async refresh(notify_peers) {
294
388
  const ts = Date.now()
295
- // console.time("Total " + ts)
296
389
  let network_active = await this.network_active()
297
390
  if (!network_active) {
298
391
  return
@@ -306,43 +399,33 @@ class Kernel {
306
399
  }
307
400
 
308
401
  // 1. get the process list
309
- // console.time("> 1. Proc Refresh"+ts)
310
402
  await this.processes.refresh()
311
- // console.timeEnd("> 1. Proc Refresh"+ts)
312
403
 
313
404
  // 2. refresh peer info to reflect the proc info
314
- // console.time("> 2. Peer Refresh"+ts)
315
405
  //await this.peer.refresh()
316
406
  await this.peer.refresh_host(this.peer.host)
317
- // console.timeEnd("> 2. Peer Refresh"+ts)
318
407
 
319
408
  // 3. load custom routers from ~/pinokio/network
320
- // console.time("> 3. Router Init"+ts)
321
409
  await this.router.init()
322
- // console.timeEnd("> 3. Router Init"+ts)
323
410
 
324
411
  // 4. set current local host router info
325
- // console.time("> 4. Router Local"+ts)
326
412
  await this.router.local()
327
- // console.timeEnd("> 4. Router Local"+ts)
328
413
 
329
414
  // 7. update remote router
330
- // console.time("> 7. Router Remote"+ts)
331
415
  await this.router.remote()
332
- // console.timeEnd("> 7. Router Remote"+ts)
416
+
417
+ await this.router.static()
333
418
 
334
419
  await this.router.custom_domain()
335
420
 
421
+
336
422
  this.router.fallback()
337
423
 
338
424
  // 8. update caddy config
339
- // console.time("> 8. Router Update"+ts)
340
425
  await this.router.update()
341
- // console.timeEnd("> 8. Router Update"+ts)
342
426
 
343
427
  // 6. tell peers to refresh
344
428
  let changed
345
- // console.time("> 9. notify if changed")
346
429
  let new_config = JSON.stringify(await this.peer.current_host())
347
430
  if (this.old_config !== new_config) {
348
431
  console.log("Proc config has changed. update router.")
@@ -355,11 +438,9 @@ class Kernel {
355
438
  if (changed) {
356
439
  await this.peer.notify_refresh()
357
440
  }
358
- // console.timeEnd("> 9. notify if changed")
359
441
  // 9. announce self to the peer network
360
442
  this.peer.announce()
361
443
  }
362
- // console.timeEnd("Total " + ts)
363
444
  }
364
445
  async clearLog(group) {
365
446
  let relativePath = path.relative(this.homedir, group)
@@ -382,7 +463,6 @@ class Kernel {
382
463
  }
383
464
  }
384
465
  async download(options, ondata) {
385
- console.log("download", { options })
386
466
  const agent = new ProxyAgent();
387
467
  const userAgent = fakeUa()
388
468
  let url = options.uri
@@ -396,7 +476,6 @@ class Kernel {
396
476
  if (options.filename) {
397
477
  opts.fileName = options.filename
398
478
  }
399
- console.log("Download", opts)
400
479
  if (process.env.HTTP_PROXY && process.env.HTTP_PROXY.length > 0) {
401
480
  opts.httpRequestOptions = { agent }
402
481
  opts.httpsRequestOptions = { agent }
@@ -538,23 +617,24 @@ class Kernel {
538
617
  }
539
618
  }
540
619
 
620
+
541
621
  let files = await fs.promises.readdir(this.api.userdir, { withFileTypes: true })
542
- let folders = files.filter((f) => { return f.isDirectory() }).map((x) => { return x.name })
622
+ // let folders = files.filter((f) => { return f.isDirectory() }).map((x) => { return x.name })
623
+ let folders = []
624
+ for(let file of files) {
625
+ // for(let folder of folders) {
626
+ let file_path = this.path("api", file.name)
627
+ let type = await Util.file_type(this.path("api"), file)
628
+ if (type.directory) {
629
+ folders.push(file.name)
630
+ await this.dns({
631
+ path: file_path
632
+ })
633
+ }
634
+ }
635
+
543
636
  let meta = {}
544
637
  for(let folder of folders) {
545
-
546
- let pinokiojson = this.path("api", folder, "pinokio.json")
547
- let pinokiometajson = this.path("api", folder, "pinokio_meta.json")
548
- let pinokiojs = this.path("api", folder, "pinokio.js")
549
- let exists1 = await this.exists(pinokiojson)
550
- let exists2 = await this.exists(pinokiometajson)
551
- let exists3 = await this.exists(pinokiojs)
552
- // if (!exists1 && !exists2 && !exists3) {
553
- // await fs.promises.writeFile(pinokiojson, JSON.stringify({
554
- // title: "No title",
555
- // description: ""
556
- // }))
557
- // }
558
638
  let pinokio = await this.api.meta(folder)
559
639
  if (pinokio) {
560
640
  i.api.push({
@@ -598,7 +678,6 @@ class Kernel {
598
678
  }
599
679
  }
600
680
  which(name, pattern) {
601
- console.log("Which", { name, pattern })
602
681
  if (this.platform === "win32") {
603
682
  try {
604
683
  const result = execSync(`where ${name}`, { env: this.envs, encoding: "utf-8" })
@@ -755,7 +834,7 @@ class Kernel {
755
834
  // if it doesn't exist, write to ~/pinokio/ENVIRONMENT
756
835
  let e = await this.exists(this.homedir, "ENVIRONMENT")
757
836
  if (!e) {
758
- let str = await Environment.ENV("system", this.homedir)
837
+ let str = await Environment.ENV("system", this.homedir, this)
759
838
  await fs.promises.writeFile(path.resolve(this.homedir, "ENVIRONMENT"), str)
760
839
  }
761
840
 
@@ -768,7 +847,7 @@ class Kernel {
768
847
  await Util.update_env(fullpath, updated)
769
848
 
770
849
  // 2. mkdir all the folders if not already created
771
- await Environment.init_folders(this.homedir)
850
+ await Environment.init_folders(this.homedir, this)
772
851
 
773
852
  // if key.json doesn't exist, create an empty json file
774
853
  let ee = await this.exists(this.homedir, "key.json")
@@ -776,8 +855,6 @@ class Kernel {
776
855
  await fs.promises.writeFile(path.resolve(this.homedir, "key.json"), JSON.stringify({}))
777
856
  }
778
857
 
779
-
780
-
781
858
  // // 3. check if Caddyfile exists
782
859
  // let e2 = await this.exists(this.homedir, "Caddyfile")
783
860
  // if (!e2) {
@@ -793,6 +870,9 @@ class Kernel {
793
870
  // let contents = await fs.promises.readdir(this.homedir)
794
871
  //await this.bin.init()
795
872
  let ts = Date.now()
873
+ this.git.index(this).then(() => {
874
+ //console.log(this.git.mapping)
875
+ })
796
876
  this.bin.init().then(() => {
797
877
  if (this.homedir) {
798
878
  this.shell.init().then(async () => {
@@ -832,7 +912,7 @@ class Kernel {
832
912
 
833
913
  this.sysinfo = info
834
914
 
835
- await this.getInfo()
915
+ await this.getInfo(true)
836
916
 
837
917
  await fs.promises.mkdir(this.path("logs"), { recursive: true }).catch((e) => { })
838
918
  await fs.promises.writeFile(this.path("logs/system.json"), JSON.stringify(this.i, null, 2))
@@ -845,7 +925,7 @@ class Kernel {
845
925
  if (this.i) {
846
926
  for(let api of this.i.api) {
847
927
  let env_path = path.resolve(this.api.userdir, api.path)
848
- let e = await Environment.get(env_path)
928
+ let e = await Environment.get(env_path, this)
849
929
  if (e.PINOKIO_SCRIPT_AUTOLAUNCH && e.PINOKIO_SCRIPT_AUTOLAUNCH.trim().length > 0) {
850
930
  let autolaunch_path = path.resolve(env_path, e.PINOKIO_SCRIPT_AUTOLAUNCH)
851
931
  let exists = await this.exists(autolaunch_path)
package/kernel/peer.js CHANGED
@@ -39,7 +39,7 @@ class PeerDiscovery {
39
39
  }
40
40
  }
41
41
  async check(kernel) {
42
- let env = await Environment.get(kernel.homedir)
42
+ let env = await Environment.get(kernel.homedir, kernel)
43
43
  //let peer_active = true
44
44
  let peer_active = false
45
45
  if (env && env.PINOKIO_NETWORK_ACTIVE && (env.PINOKIO_NETWORK_ACTIVE==="1" || env.PINOKIO_NETWORK_ACTIVE.toLowerCase()==="true")) {
@@ -65,7 +65,7 @@ class PeerDiscovery {
65
65
  }
66
66
  }
67
67
  async start(kernel) {
68
- let env = await Environment.get(kernel.homedir)
68
+ let env = await Environment.get(kernel.homedir, kernel)
69
69
 
70
70
  // by default expose to the local network
71
71
  //this.active = true
@@ -211,7 +211,7 @@ class PeerDiscovery {
211
211
  if (icon) {
212
212
  http_icon = `http://${this.host}:42000${icon}`;
213
213
  //https_icon = `https://${appname}.${this.name}.localhost/${iconpath}?raw=true`
214
- https_icon = `https://pinokio.${this.name}.localhost/raw/${appname}/${iconpath}`
214
+ https_icon = `https://pinokio.${this.name}.localhost/asset/api/${appname}/${iconpath}`
215
215
  } else {
216
216
  for(let protocol of ["https", "http"]) {
217
217
  if (protocol === "https") {
@@ -254,9 +254,28 @@ class PeerDiscovery {
254
254
  if (external_port) {
255
255
  external_ip = `${this.host}:${external_port}`
256
256
  }
257
+ let internal_router = []
258
+ // check both the 127.0.0.1 and 0.0.0.0 for local ip
259
+ let a = router["127.0.0.1:" + proc.port]
260
+ let b = router["0.0.0.0:" + proc.port]
261
+ let c = router["localhost:" + proc.port]
262
+ if (a) {
263
+ internal_router = internal_router.concat(a)
264
+ }
265
+ if (b) {
266
+ internal_router = internal_router.concat(b)
267
+ }
268
+ if (c) {
269
+ internal_router = internal_router.concat(c)
270
+ }
271
+ // let ip =
272
+ // if (router[proc.ip]) {
273
+ // }proc.
274
+
275
+
257
276
  let info = {
258
277
  external_router: router[external_ip] || [],
259
- internal_router: router[proc.ip] || [],
278
+ internal_router,
260
279
  external_ip,
261
280
  external_port: parseInt(external_port),
262
281
  internal_port: parseInt(internal_port),
@@ -302,20 +321,23 @@ class PeerDiscovery {
302
321
  let https_icon = null
303
322
  let http_href = null
304
323
  let https_href = null
324
+ let app_href = null
305
325
  if (meta && !meta.init_required) {
306
326
  if (meta.title) {
307
327
  if (meta.icon) {
308
328
  http_icon = `http://${this.host}:42000${meta.icon}`;
309
329
  //https_icon = `https://${folder}.${this.name}.localhost/${meta.iconpath}?raw=true`
310
- https_icon = `https://pinokio.${this.name}.localhost/raw/${folder}/${meta.iconpath}`
330
+ https_icon = `https://pinokio.${this.name}.localhost/asset/api/${folder}/${meta.iconpath}`
311
331
  }
312
332
  //https_href = `https://${folder}.${this.name}.localhost`
313
333
  https_href = `https://pinokio.${this.name}.localhost/p/${folder}`
314
334
  http_href = `http://${this.host}:42000/p/${folder}`
335
+ app_href = `https://${folder}.${this.name}.localhost`
315
336
  installed.push({
316
337
  folder,
317
338
  http_icon,
318
339
  https_icon,
340
+ app_href,
319
341
  https_href,
320
342
  http_href,
321
343
  ...meta
@@ -329,13 +351,26 @@ class PeerDiscovery {
329
351
  let d = Date.now()
330
352
  let router_info = await this.router_info()
331
353
  let installed = await this.installed()
354
+ let peers = Object.values(this.info).filter((info) => {
355
+ return info.host !== this.host
356
+ }).map((info) => {
357
+ return {
358
+ name: info.name,
359
+ host: info.host
360
+ }
361
+ })
332
362
  return {
363
+ version: this.kernel.version,
333
364
  home: this.kernel.homedir,
334
365
  arch: this.kernel.arch,
335
366
  platform: this.kernel.platform,
367
+ gpu: this.kernel.gpu,
368
+ gpus: this.kernel.gpus,
336
369
  name: this.name,
337
370
  host: this.host,
371
+ peers: peers,
338
372
  port_mapping: this.kernel.router.port_mapping,
373
+ rewrite_mapping: this.kernel.router.rewrite_mapping,
339
374
  proc: this.kernel.processes.info,
340
375
  router: this.kernel.router.published(),
341
376
  router_info,
package/kernel/plugin.js CHANGED
@@ -14,10 +14,11 @@ class Plugin {
14
14
  let plugins = []
15
15
  for(let plugin_path of plugin_paths) {
16
16
  let config = await this.kernel.require(path.resolve(plugin_dir, plugin_path))
17
- let cwd = plugin_path.split("/").slice(0, -1).join("/")
17
+ let chunks = plugin_path.split(path.sep)
18
+ let cwd = chunks.slice(0, -1).join("/")
18
19
  config.image = "/asset/plugin/" + cwd + "/" + config.icon
19
20
  plugins.push({
20
- href: "/run/plugin/" + plugin_path,
21
+ href: "/run/plugin/" + chunks.join("/"),
21
22
  ...config
22
23
  })
23
24
  }
package/kernel/procs.js CHANGED
@@ -13,7 +13,7 @@ class Procs {
13
13
  this.kernel = kernel
14
14
  this.cache = {}
15
15
  }
16
- async isHttp(port) {
16
+ async isHttp(host, port) {
17
17
  // ignore caddy
18
18
  if (parseInt(port) === 2019) {
19
19
  return false
@@ -21,16 +21,16 @@ class Procs {
21
21
  if (this.cache.hasOwnProperty("" + port)) {
22
22
  return this.cache["" + port]
23
23
  }
24
- let ip = "127.0.0.1"
24
+ // let ip = "127.0.0.1"
25
25
  let timeout = 1000
26
26
  let response = await new Promise(resolve => {
27
27
  const socket = new net.Socket();
28
28
  let response = '';
29
29
  let resolved = false;
30
30
  socket.setTimeout(timeout);
31
- socket.connect(port, ip, () => {
31
+ socket.connect(port, host, () => {
32
32
  // Use a nonsense method to trigger a 400/405/501 from real HTTP servers
33
- socket.write(`FOO / HTTP/1.1\r\nHost: ${ip}\r\nConnection: close\r\n\r\n`);
33
+ socket.write(`FOO / HTTP/1.1\r\nHost: ${host}\r\nConnection: close\r\n\r\n`);
34
34
  });
35
35
  socket.on('data', chunk => {
36
36
  response += chunk.toString();
@@ -73,7 +73,6 @@ class Procs {
73
73
  let pids = new Set()
74
74
  let s = stdout.trim()
75
75
  const lines = s.split('\n');
76
- // console.time("###### Line parsing")
77
76
  for(let line of lines) {
78
77
  if (isWin) {
79
78
  // Skip headers
@@ -90,11 +89,17 @@ class Procs {
90
89
  }
91
90
 
92
91
  //if (state !== 'LISTENING') continue;
93
- const chunks = localAddress.split(":")
94
- const port = chunks.pop()
95
- let ip = chunks.pop()
96
- if (!ip || ip === "*") {
92
+ const chunks = /(.+):([0-9]+)/.exec(localAddress)
93
+ let host = chunks[1]
94
+ let port = chunks[2]
95
+ let ip
96
+
97
+ if (host === "*") {
97
98
  ip = "127.0.0.1:" + port
99
+ host = "127.0.0.1"
100
+ } else if (host === "[::1]") {
101
+ host = "::1"
102
+ ip = localAddress
98
103
  } else {
99
104
  ip = localAddress
100
105
  }
@@ -105,9 +110,8 @@ class Procs {
105
110
 
106
111
  if (pids.has(pid+"/"+port)) continue;
107
112
  pids.add(pid+"/"+port)
108
- results.push({ port, pid, ip });
113
+ results.push({ port, pid, ip, host });
109
114
  } catch (e) {
110
- // console.log("ERROR", e)
111
115
  }
112
116
  } else {
113
117
  // if (!/LISTEN/.test(line)) continue;
@@ -123,27 +127,30 @@ class Procs {
123
127
 
124
128
  const match = line.match(/([^\s]+:\d+)\s/);
125
129
  const localAddress = match?.[1];
126
-
127
- const chunks = localAddress.split(":")
128
- const port = chunks.pop()
129
- let ip = chunks.pop()
130
- if (!ip || ip === "*") {
130
+ const chunks = /(.+):([0-9]+)/.exec(localAddress)
131
+ let host = chunks[1]
132
+ let port = chunks[2]
133
+ let ip
134
+ if (host === "*") {
131
135
  ip = "127.0.0.1:" + port
136
+ host = "127.0.0.1"
137
+ } else if (host === "[::1]") {
138
+ host = "::1"
139
+ ip = localAddress
132
140
  } else {
133
141
  ip = localAddress
134
142
  }
135
143
 
136
144
  if (pids.has(pid+"/"+port)) continue;
137
145
  pids.add(pid+"/"+port)
138
- if (pid && port) results.push({ port, pid, ip });
146
+ if (pid && port) results.push({ port, pid, ip, host });
139
147
  } catch (e) {
140
- // console.log("Error", e)
141
148
  }
142
149
  }
143
150
  }
144
- const http_check = await Promise.all(results.map(({ port }) => {
151
+ const http_check = await Promise.all(results.map(({ host, port }) => {
145
152
  return limit(() => {
146
- return this.isHttp(port)
153
+ return this.isHttp(host, port)
147
154
  })
148
155
  }))
149
156
  let filtered = []