pinokiod 3.9.3 → 3.9.13
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/kernel/api/index.js +153 -67
- package/kernel/api/rm/index.js +3 -2
- package/kernel/api/set/index.js +4 -2
- package/kernel/bin/caddy.js +0 -2
- package/kernel/bin/index.js +13 -0
- package/kernel/index.js +10 -8
- package/kernel/info.js +3 -0
- package/kernel/plugin.js +34 -0
- package/kernel/router/index.js +1 -1
- package/kernel/router/localhost_variable_router.js +1 -1
- package/kernel/router/peer_variable_router.js +1 -1
- package/kernel/shell.js +14 -0
- package/kernel/util.js +19 -1
- package/package.json +1 -1
- package/server/index.js +296 -98
- package/server/public/electron.css +2 -0
- package/server/public/modalinput.js +7 -2
- package/server/public/opener.js +32 -0
- package/server/public/style.css +33 -2
- package/server/socket.js +7 -3
- package/server/views/app.ejs +188 -72
- package/server/views/env_editor.ejs +1 -0
- package/server/views/file_explorer.ejs +1 -1
- package/server/views/index.ejs +35 -16
- package/server/views/partials/dynamic.ejs +54 -6
- package/server/views/partials/menu.ejs +11 -6
- package/server/views/prototype/index.ejs +366 -31
- package/server/views/prototype/show.ejs +386 -30
- package/server/views/required_env_editor.ejs +1 -0
- package/server/views/settings.ejs +58 -43
- package/server/views/terminal.ejs +6 -0
- package/:w +0 -1247
package/server/index.js
CHANGED
|
@@ -45,6 +45,7 @@ const packagejson = require("../package.json")
|
|
|
45
45
|
const Environment = require("../kernel/environment")
|
|
46
46
|
const Cloudflare = require("../kernel/api/cloudflare")
|
|
47
47
|
const Util = require("../kernel/util")
|
|
48
|
+
const Info = require("../kernel/info")
|
|
48
49
|
|
|
49
50
|
const Setup = require("../kernel/bin/setup")
|
|
50
51
|
|
|
@@ -101,11 +102,9 @@ class Server {
|
|
|
101
102
|
return new Promise(r=>fs.access(s, fs.constants.F_OK, e => r(!e)))
|
|
102
103
|
}
|
|
103
104
|
async updateMeta(formData, app_path) {
|
|
104
|
-
console.log("updateMeta", app_path)
|
|
105
105
|
if (formData.icon_dirty) {
|
|
106
106
|
// write icon file
|
|
107
107
|
let icon_path = this.kernel.path("api", formData.new_path, formData.icon_path)
|
|
108
|
-
console.log({ icon_path })
|
|
109
108
|
await fs.promises.writeFile(icon_path, formData.avatar)
|
|
110
109
|
}
|
|
111
110
|
|
|
@@ -114,7 +113,6 @@ class Server {
|
|
|
114
113
|
let meta_path = this.kernel.path("api", app_path, "pinokio.json")
|
|
115
114
|
console.log("meta_path", meta_path)
|
|
116
115
|
let meta = (await this.kernel.loader.load(meta_path)).resolved
|
|
117
|
-
console.log("meta", meta)
|
|
118
116
|
if (!meta) meta = {}
|
|
119
117
|
if (formData.title) {
|
|
120
118
|
meta.title = formData.title
|
|
@@ -124,10 +122,69 @@ class Server {
|
|
|
124
122
|
meta.description = formData.description
|
|
125
123
|
dirty = true
|
|
126
124
|
}
|
|
125
|
+
if (!meta.plugin) {
|
|
126
|
+
meta.plugin = {
|
|
127
|
+
menu: []
|
|
128
|
+
}
|
|
129
|
+
}
|
|
127
130
|
if (dirty) {
|
|
128
131
|
await fs.promises.writeFile(meta_path, JSON.stringify(meta, null, 2))
|
|
129
132
|
}
|
|
130
133
|
}
|
|
134
|
+
running_dynamic (name, menu) {
|
|
135
|
+
let cwd = this.kernel.path("api", name)
|
|
136
|
+
let running_dynamic = []
|
|
137
|
+
const traverse = (obj, indexPath) => {
|
|
138
|
+
if (Array.isArray(obj)) {
|
|
139
|
+
for(let i=0; i<obj.length; i++) {
|
|
140
|
+
let item = obj[i]
|
|
141
|
+
let newIndexPath
|
|
142
|
+
if (indexPath) {
|
|
143
|
+
newIndexPath = indexPath + "." + i
|
|
144
|
+
} else {
|
|
145
|
+
newIndexPath = "" + i
|
|
146
|
+
}
|
|
147
|
+
traverse(item, newIndexPath);
|
|
148
|
+
}
|
|
149
|
+
} else if (obj !== null && typeof obj === 'object') {
|
|
150
|
+
for (const key in obj) {
|
|
151
|
+
if (key === 'href') {
|
|
152
|
+
let href = obj[key]
|
|
153
|
+
if (href.startsWith("/api")) {
|
|
154
|
+
let uri_path = new URL("http://localhost" + href).pathname
|
|
155
|
+
let filepath = this.kernel.path(...uri_path.split("/"))
|
|
156
|
+
|
|
157
|
+
let id = `${filepath}?cwd=${cwd}`
|
|
158
|
+
//if (this.kernel.api.running[filepath]) {
|
|
159
|
+
if (this.kernel.api.running[id]) {
|
|
160
|
+
obj.display = "indent"
|
|
161
|
+
running_dynamic.push(obj)
|
|
162
|
+
}
|
|
163
|
+
} else if (href.startsWith("/run")) {
|
|
164
|
+
let uri_path = new URL("http://localhost" + href).pathname
|
|
165
|
+
let _filepath = uri_path.split("/").filter(x=>x).slice(1)
|
|
166
|
+
let filepath = this.kernel.path(..._filepath)
|
|
167
|
+
let id = `${filepath}?cwd=${cwd}`
|
|
168
|
+
//if (this.kernel.api.running[filepath]) {
|
|
169
|
+
if (this.kernel.api.running[id]) {
|
|
170
|
+
obj.display = "indent"
|
|
171
|
+
running_dynamic.push(obj)
|
|
172
|
+
}
|
|
173
|
+
}
|
|
174
|
+
} else if (key === "shell") {
|
|
175
|
+
let shell_id = this.get_shell_id(name, indexPath, obj[key])
|
|
176
|
+
if (this.kernel.api.running[shell_id]) {
|
|
177
|
+
obj.display = "indent"
|
|
178
|
+
running_dynamic.push(obj)
|
|
179
|
+
}
|
|
180
|
+
}
|
|
181
|
+
traverse(obj[key], indexPath);
|
|
182
|
+
}
|
|
183
|
+
}
|
|
184
|
+
}
|
|
185
|
+
traverse(menu)
|
|
186
|
+
return running_dynamic
|
|
187
|
+
}
|
|
131
188
|
async createMeta(formData) {
|
|
132
189
|
let _path = this.kernel.path("api", formData.path)
|
|
133
190
|
await fs.promises.mkdir(_path, { recursive: true }).catch((e) => {})
|
|
@@ -139,7 +196,10 @@ class Server {
|
|
|
139
196
|
let meta = {
|
|
140
197
|
title: formData.title,
|
|
141
198
|
description: formData.description,
|
|
142
|
-
icon: "icon.png"
|
|
199
|
+
icon: "icon.png",
|
|
200
|
+
plugin: {
|
|
201
|
+
menu: []
|
|
202
|
+
}
|
|
143
203
|
}
|
|
144
204
|
await fs.promises.writeFile(meta_path, JSON.stringify(meta, null, 2))
|
|
145
205
|
}
|
|
@@ -274,7 +334,6 @@ class Server {
|
|
|
274
334
|
let error = null
|
|
275
335
|
if (config && config.version) {
|
|
276
336
|
let coerced = semver.coerce(config.version)
|
|
277
|
-
// console.log("version", { coerced, v: config.version })
|
|
278
337
|
if (semver.satisfies(coerced, this.kernel.schema)) {
|
|
279
338
|
console.log("semver satisfied", config.version, this.kernel.schema)
|
|
280
339
|
} else {
|
|
@@ -331,8 +390,8 @@ class Server {
|
|
|
331
390
|
}).filter((file) => {
|
|
332
391
|
return file.name !== "pinokio.js" && file.name !== "pinokio.json" && file.name !== "pinokio_meta.json"
|
|
333
392
|
})
|
|
334
|
-
console.log("files", files)
|
|
335
393
|
config = {
|
|
394
|
+
init_required: true,
|
|
336
395
|
icon: config.icon,
|
|
337
396
|
title: name,
|
|
338
397
|
menu: files.map((file) => {
|
|
@@ -346,7 +405,6 @@ class Server {
|
|
|
346
405
|
await this.renderMenu(uri, name, config, [])
|
|
347
406
|
}
|
|
348
407
|
let platform = os.platform()
|
|
349
|
-
console.log("config before", { config })
|
|
350
408
|
|
|
351
409
|
// if (config.icon) {
|
|
352
410
|
// //config.iconpath = this.kernel.path("api", name, config.icon)
|
|
@@ -358,28 +416,25 @@ class Server {
|
|
|
358
416
|
// config.icon = "/pinokio-black.png"
|
|
359
417
|
// }
|
|
360
418
|
|
|
361
|
-
console.log("config after", { config })
|
|
362
419
|
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
let
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
mem[k]
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
}
|
|
382
|
-
}
|
|
420
|
+
// // get all memory variable stied to the current repository
|
|
421
|
+
// let api_path = this.kernel.path("api", name)
|
|
422
|
+
// let mem = {}
|
|
423
|
+
// for(let type in this.kernel.memory) {
|
|
424
|
+
// // type := local|global
|
|
425
|
+
// let vars = this.kernel.memory[type]
|
|
426
|
+
// for(let k in vars) {
|
|
427
|
+
// if (k.includes(api_path)) {
|
|
428
|
+
// if (mem[k]) {
|
|
429
|
+
// mem[k][type] = vars[k]
|
|
430
|
+
// } else {
|
|
431
|
+
// mem[k] = {
|
|
432
|
+
// [type]: vars[k]
|
|
433
|
+
// }
|
|
434
|
+
// }
|
|
435
|
+
// }
|
|
436
|
+
// }
|
|
437
|
+
// }
|
|
383
438
|
|
|
384
439
|
await this.init_env("api/" + name)
|
|
385
440
|
|
|
@@ -418,9 +473,11 @@ class Server {
|
|
|
418
473
|
let plugin = await this.getPlugin(name)
|
|
419
474
|
let plugin_menu = null
|
|
420
475
|
if (plugin && plugin.menu && Array.isArray(plugin.menu)) {
|
|
421
|
-
|
|
476
|
+
let running_dynamic = this.running_dynamic(name, plugin.menu)
|
|
477
|
+
plugin_menu = plugin.menu.concat(running_dynamic)
|
|
422
478
|
}
|
|
423
|
-
|
|
479
|
+
const result = {
|
|
480
|
+
path: this.kernel.path("api", name),
|
|
424
481
|
plugin_menu,
|
|
425
482
|
portal: this.portal,
|
|
426
483
|
install: this.install,
|
|
@@ -428,7 +485,7 @@ class Server {
|
|
|
428
485
|
env,
|
|
429
486
|
mode,
|
|
430
487
|
port: this.port,
|
|
431
|
-
mem,
|
|
488
|
+
// mem,
|
|
432
489
|
type,
|
|
433
490
|
platform,
|
|
434
491
|
running:this.kernel.api.running,
|
|
@@ -450,7 +507,8 @@ class Server {
|
|
|
450
507
|
src: "/_api/" + name,
|
|
451
508
|
execUrl: "/api/" + name,
|
|
452
509
|
// rawpath,
|
|
453
|
-
}
|
|
510
|
+
}
|
|
511
|
+
res.render("app", result)
|
|
454
512
|
}
|
|
455
513
|
getVariationUrls(req) {
|
|
456
514
|
let edu = new URL("http://localhost" + req.originalUrl)
|
|
@@ -467,6 +525,16 @@ class Server {
|
|
|
467
525
|
}
|
|
468
526
|
return { editorUrl, prevUrl }
|
|
469
527
|
}
|
|
528
|
+
get_shell_id(name, i, rendered) {
|
|
529
|
+
let hash = crypto.createHash('md5').update(JSON.stringify(rendered)).digest('hex')
|
|
530
|
+
let shell_id
|
|
531
|
+
if (rendered.id) {
|
|
532
|
+
shell_id = encodeURIComponent(`${name}_${rendered.id}`)
|
|
533
|
+
} else {
|
|
534
|
+
shell_id = encodeURIComponent(`${name}_${i}_${hash}`)
|
|
535
|
+
}
|
|
536
|
+
return shell_id
|
|
537
|
+
}
|
|
470
538
|
async render(req, res, pathComponents, meta) {
|
|
471
539
|
let base_path = req.base || this.kernel.path("api")
|
|
472
540
|
let full_filepath = path.resolve(base_path, ...pathComponents)
|
|
@@ -734,6 +802,7 @@ class Server {
|
|
|
734
802
|
content = await fs.promises.readFile(filepath, "utf8")
|
|
735
803
|
} catch (e) {
|
|
736
804
|
content = ""
|
|
805
|
+
console.log(">>>>>>>>>> Error", e)
|
|
737
806
|
}
|
|
738
807
|
|
|
739
808
|
/********************************************************************
|
|
@@ -924,9 +993,11 @@ class Server {
|
|
|
924
993
|
execUrl: "~" + req.originalUrl.replace(/^\/_api/, "\/api"),
|
|
925
994
|
proxies: this.kernel.api.proxies[filepath],
|
|
926
995
|
cwd: req.query.cwd,
|
|
996
|
+
script_id: (req.base ? `${full_filepath}?cwd=${req.query.cwd}` : null),
|
|
927
997
|
script_path: (req.base ? full_filepath : null),
|
|
928
998
|
}
|
|
929
999
|
|
|
1000
|
+
|
|
930
1001
|
res.render(template, result)
|
|
931
1002
|
}
|
|
932
1003
|
|
|
@@ -1173,17 +1244,29 @@ class Server {
|
|
|
1173
1244
|
// check if there is a running process with this folder name
|
|
1174
1245
|
let runningApps = new Set()
|
|
1175
1246
|
for(let key in this.kernel.api.running) {
|
|
1176
|
-
let p = this.kernel.path("api", items[i].name) + path.sep
|
|
1247
|
+
//let p = this.kernel.path("api", items[i].name) + path.sep
|
|
1248
|
+
let p = this.kernel.path("api", items[i].name)
|
|
1249
|
+
|
|
1177
1250
|
//let re = new RegExp(items[i].name)
|
|
1178
1251
|
//if (re.test(key)) {
|
|
1179
1252
|
//if (p === key) {
|
|
1180
|
-
|
|
1253
|
+
|
|
1254
|
+
|
|
1255
|
+
// not only should include the pattern, but also end with it (otherwise can include similar patterns such as /api/qqqa, /api/qqqaaa, etc.
|
|
1256
|
+
if (key.includes(p) && key.endsWith(p)) {
|
|
1181
1257
|
items[i].running = true
|
|
1182
1258
|
items[i].index = index
|
|
1183
|
-
if (items[i].running_scripts) {
|
|
1259
|
+
if (!items[i].running_scripts) {
|
|
1260
|
+
items[i].running_scripts = []
|
|
1261
|
+
}
|
|
1262
|
+
if (key.startsWith(p)) {
|
|
1184
1263
|
items[i].running_scripts.push({ path: path.relative(this.kernel.homedir, key), name: path.relative(p, key) })
|
|
1185
1264
|
} else {
|
|
1186
|
-
|
|
1265
|
+
let chunks = key.split("?")
|
|
1266
|
+
let dev = chunks[0]
|
|
1267
|
+
let name_chunks = dev.split(path.sep)
|
|
1268
|
+
let name = name_chunks[name_chunks.length-1]
|
|
1269
|
+
items[i].running_scripts.push({ id: key, name })
|
|
1187
1270
|
}
|
|
1188
1271
|
index++;
|
|
1189
1272
|
running.push(items[i])
|
|
@@ -1427,7 +1510,7 @@ class Server {
|
|
|
1427
1510
|
}
|
|
1428
1511
|
|
|
1429
1512
|
|
|
1430
|
-
async renderMenu(uri, name, config, pathComponents) {
|
|
1513
|
+
async renderMenu(uri, name, config, pathComponents, indexPath) {
|
|
1431
1514
|
if (config.menu) {
|
|
1432
1515
|
|
|
1433
1516
|
// config.menu = [{
|
|
@@ -1454,7 +1537,13 @@ class Server {
|
|
|
1454
1537
|
let menuitem = config.menu[i]
|
|
1455
1538
|
|
|
1456
1539
|
if (menuitem.menu) {
|
|
1457
|
-
let
|
|
1540
|
+
let newIndexPath
|
|
1541
|
+
if (indexPath) {
|
|
1542
|
+
newIndexPath = indexPath + "." + i
|
|
1543
|
+
} else {
|
|
1544
|
+
newIndexPath = "" + i
|
|
1545
|
+
}
|
|
1546
|
+
let m = await this.renderMenu(uri, name, { menu: menuitem.menu }, pathComponents, newIndexPath)
|
|
1458
1547
|
menuitem.menu = m.menu
|
|
1459
1548
|
}
|
|
1460
1549
|
|
|
@@ -1471,11 +1560,28 @@ class Server {
|
|
|
1471
1560
|
// file explorer
|
|
1472
1561
|
config.menu[i].href = path.resolve(this.kernel.homedir, "api", name, menuitem.href)
|
|
1473
1562
|
} else {
|
|
1474
|
-
|
|
1475
|
-
|
|
1476
|
-
|
|
1477
|
-
|
|
1478
|
-
|
|
1563
|
+
if (menuitem.href.startsWith("/")) {
|
|
1564
|
+
config.menu[i].href = menuitem.href
|
|
1565
|
+
} else {
|
|
1566
|
+
let absolute = path.resolve(__dirname, ...pathComponents, menuitem.href)
|
|
1567
|
+
let seed = path.resolve(__dirname)
|
|
1568
|
+
let p = absolute.replace(seed, "")
|
|
1569
|
+
let link = p.split(/[\/\\]/).filter((x) => { return x }).join("/")
|
|
1570
|
+
config.menu[i].href = "/api/" + name + "/" + link
|
|
1571
|
+
}
|
|
1572
|
+
}
|
|
1573
|
+
} else if (menuitem.run) {
|
|
1574
|
+
let rendered = this.kernel.template.render(menuitem, {})
|
|
1575
|
+
// file explorer
|
|
1576
|
+
if (typeof rendered.run === "object") {
|
|
1577
|
+
let run = rendered.run
|
|
1578
|
+
config.menu[i].run = run.message
|
|
1579
|
+
config.menu[i].cwd = run.path ? path.resolve(this.kernel.homedir, "api", name, run.path) : path.resolve(this.kernel.homedir, "api", name)
|
|
1580
|
+
config.menu[i].href = "/api/" + name
|
|
1581
|
+
} else {
|
|
1582
|
+
config.menu[i].run = rendered.run
|
|
1583
|
+
config.menu[i].cwd = path.resolve(this.kernel.homedir, "api", name)
|
|
1584
|
+
config.menu[i].href = "/api/" + name
|
|
1479
1585
|
}
|
|
1480
1586
|
}
|
|
1481
1587
|
}
|
|
@@ -1533,13 +1639,22 @@ class Server {
|
|
|
1533
1639
|
|
|
1534
1640
|
// deterministic shell id generation
|
|
1535
1641
|
// `${api_path}_${i}_${hash}`
|
|
1536
|
-
let
|
|
1537
|
-
|
|
1538
|
-
|
|
1539
|
-
shell_id = encodeURIComponent(`${name}_${rendered.id}`)
|
|
1642
|
+
let currentIndexPath
|
|
1643
|
+
if (indexPath) {
|
|
1644
|
+
currentIndexPath = indexPath + "." + i
|
|
1540
1645
|
} else {
|
|
1541
|
-
|
|
1646
|
+
currentIndexPath = "" + i
|
|
1542
1647
|
}
|
|
1648
|
+
let shell_id = this.get_shell_id(name, currentIndexPath, rendered)
|
|
1649
|
+
|
|
1650
|
+
|
|
1651
|
+
// let hash = crypto.createHash('md5').update(JSON.stringify(rendered)).digest('hex')
|
|
1652
|
+
// let shell_id
|
|
1653
|
+
// if (rendered.id) {
|
|
1654
|
+
// shell_id = encodeURIComponent(`${name}_${rendered.id}`)
|
|
1655
|
+
// } else {
|
|
1656
|
+
// shell_id = encodeURIComponent(`${name}_${i}_${hash}`)
|
|
1657
|
+
// }
|
|
1543
1658
|
menuitem.href = "/shell/" + shell_id + "?" + params.toString()
|
|
1544
1659
|
let shell = this.kernel.shell.get(shell_id)
|
|
1545
1660
|
if (shell) {
|
|
@@ -1552,9 +1667,16 @@ class Server {
|
|
|
1552
1667
|
if (menuitem.href.startsWith("http")) {
|
|
1553
1668
|
menuitem.src = menuitem.href
|
|
1554
1669
|
} else if (menuitem.href.startsWith("/")) {
|
|
1555
|
-
|
|
1556
|
-
|
|
1557
|
-
|
|
1670
|
+
let run_path = "/run"
|
|
1671
|
+
if (menuitem.href.startsWith(run_path)) {
|
|
1672
|
+
u = new URL("http://localhost" + menuitem.href.slice(run_path.length))
|
|
1673
|
+
u.search = ""
|
|
1674
|
+
menuitem.src = u.pathname
|
|
1675
|
+
} else {
|
|
1676
|
+
u = new URL("http://localhost" + menuitem.href)
|
|
1677
|
+
u.search = ""
|
|
1678
|
+
menuitem.src = u.pathname
|
|
1679
|
+
}
|
|
1558
1680
|
} else {
|
|
1559
1681
|
u = new URL("http://localhost/" + menuitem.href)
|
|
1560
1682
|
u.search = ""
|
|
@@ -1563,9 +1685,21 @@ class Server {
|
|
|
1563
1685
|
|
|
1564
1686
|
// check running
|
|
1565
1687
|
let fullpath = this.kernel.path(menuitem.src.slice(1))
|
|
1566
|
-
|
|
1567
|
-
|
|
1688
|
+
let relpath = path.relative(this.kernel.homedir, fullpath)
|
|
1689
|
+
if (relpath.startsWith("api")) {
|
|
1690
|
+
// api script
|
|
1691
|
+
if (this.kernel.api.running[fullpath]) {
|
|
1692
|
+
menuitem.running = true
|
|
1693
|
+
}
|
|
1694
|
+
} else {
|
|
1695
|
+
// prototype script
|
|
1696
|
+
let api_path = this.kernel.path("api", name)
|
|
1697
|
+
let id = `${fullpath}?cwd=${api_path}`
|
|
1698
|
+
if (this.kernel.api.running[id]) {
|
|
1699
|
+
menuitem.running = true
|
|
1700
|
+
}
|
|
1568
1701
|
}
|
|
1702
|
+
|
|
1569
1703
|
|
|
1570
1704
|
}
|
|
1571
1705
|
|
|
@@ -1637,9 +1771,16 @@ class Server {
|
|
|
1637
1771
|
config.menu[i].btn = menuitem.html
|
|
1638
1772
|
}
|
|
1639
1773
|
} else if (menuitem.hasOwnProperty("text")) {
|
|
1640
|
-
|
|
1641
1774
|
if (menuitem.hasOwnProperty("icon")) {
|
|
1642
1775
|
menuitem.html = `<i class="${menuitem.icon}"></i> ${menuitem.text}`
|
|
1776
|
+
} else if (menuitem.hasOwnProperty("image")) {
|
|
1777
|
+
let imagePath
|
|
1778
|
+
if (menuitem.image.startsWith("/")) {
|
|
1779
|
+
imagePath = menuitem.image
|
|
1780
|
+
} else {
|
|
1781
|
+
imagePath = `/api/${name}/${menuitem.image}?raw=true`
|
|
1782
|
+
}
|
|
1783
|
+
menuitem.html = `<img class='menu-item-image' src='${imagePath}' /> ${menuitem.text}`
|
|
1643
1784
|
} else {
|
|
1644
1785
|
menuitem.html = `${menuitem.text}`
|
|
1645
1786
|
}
|
|
@@ -1679,10 +1820,6 @@ class Server {
|
|
|
1679
1820
|
})
|
|
1680
1821
|
|
|
1681
1822
|
|
|
1682
|
-
|
|
1683
|
-
|
|
1684
|
-
|
|
1685
|
-
|
|
1686
1823
|
// // get all proxies that belong to this repository
|
|
1687
1824
|
// let childProxies = []
|
|
1688
1825
|
// for(let scriptPath in this.kernel.api.proxies) {
|
|
@@ -2110,17 +2247,15 @@ class Server {
|
|
|
2110
2247
|
}
|
|
2111
2248
|
}
|
|
2112
2249
|
async getPlugin(name) {
|
|
2113
|
-
let
|
|
2114
|
-
|
|
2115
|
-
|
|
2116
|
-
let plugin_menu = null
|
|
2117
|
-
if (pinokio_json && pinokio_json.plugin && pinokio_json.plugin.menu && Array.isArray(pinokio_json.plugin.menu)) {
|
|
2118
|
-
let uri = this.kernel.path("api")
|
|
2119
|
-
let config = pinokio_json.plugin
|
|
2120
|
-
await this.renderMenu(uri, name, config, [])
|
|
2121
|
-
return config
|
|
2250
|
+
let info = new Info(this.kernel)
|
|
2251
|
+
info.caller = () => {
|
|
2252
|
+
return this.kernel.path("api", name, "pinokio.js")
|
|
2122
2253
|
}
|
|
2123
|
-
|
|
2254
|
+
let menu = await this.kernel.plugin.config.menu(this.kernel, info)
|
|
2255
|
+
let plugin = { menu }
|
|
2256
|
+
let uri = this.kernel.path("api")
|
|
2257
|
+
await this.renderMenu(uri, name, plugin, [])
|
|
2258
|
+
return plugin
|
|
2124
2259
|
}
|
|
2125
2260
|
|
|
2126
2261
|
async start(options) {
|
|
@@ -2630,7 +2765,6 @@ class Server {
|
|
|
2630
2765
|
*/
|
|
2631
2766
|
this.app.post("/connect/:provider/login", ex(async (req, res) => {
|
|
2632
2767
|
try {
|
|
2633
|
-
console.log("params", req.params)
|
|
2634
2768
|
let response = await this.kernel.connect.login(req.params.provider, req.body)
|
|
2635
2769
|
res.json(response)
|
|
2636
2770
|
} catch (e) {
|
|
@@ -2639,7 +2773,6 @@ class Server {
|
|
|
2639
2773
|
}))
|
|
2640
2774
|
this.app.post("/connect/:provider/logout", ex(async (req, res) => {
|
|
2641
2775
|
try {
|
|
2642
|
-
console.log("params", req.params)
|
|
2643
2776
|
await this.kernel.connect.logout(req.params.provider, req.body)
|
|
2644
2777
|
res.json({ success: true })
|
|
2645
2778
|
} catch (e) {
|
|
@@ -2663,6 +2796,14 @@ class Server {
|
|
|
2663
2796
|
res.json({ error: e.message })
|
|
2664
2797
|
}
|
|
2665
2798
|
}))
|
|
2799
|
+
this.app.post("/runcmd", ex(async (req, res) => {
|
|
2800
|
+
//Util.openfs(req.body.path, req.body.mode)
|
|
2801
|
+
let cwd = req.body.cwd
|
|
2802
|
+
let cmd = req.body.run
|
|
2803
|
+
console.log({ cmd, cwd })
|
|
2804
|
+
Util.run(cmd, cwd, this.kernel)
|
|
2805
|
+
res.json({ success: true })
|
|
2806
|
+
}))
|
|
2666
2807
|
this.app.post("/openfs", ex(async (req, res) => {
|
|
2667
2808
|
//Util.openfs(req.body.path, req.body.mode)
|
|
2668
2809
|
Util.openfs(req.body.path, req.body, this.kernel)
|
|
@@ -2864,13 +3005,11 @@ class Server {
|
|
|
2864
3005
|
}
|
|
2865
3006
|
*/
|
|
2866
3007
|
|
|
2867
|
-
console.log("SHELLS", this.kernel.shell.shells.map((s) => { return { id: s.id, message: s.params.message } }))
|
|
2868
3008
|
// create a new term from cwd
|
|
2869
3009
|
let id = decodeURIComponent(req.params.id)
|
|
2870
3010
|
let cwd = this.kernel.path(this.kernel.api.filePath(decodeURIComponent(req.query.path)))
|
|
2871
3011
|
let message = req.query.message ? decodeURIComponent(req.query.message) : null
|
|
2872
3012
|
//let message = req.query.message ? req.query.message : null
|
|
2873
|
-
console.log({ message })
|
|
2874
3013
|
let venv = req.query.venv ? decodeURIComponent(req.query.venv) : null
|
|
2875
3014
|
let input = req.query.input ? true : false
|
|
2876
3015
|
let callback = req.query.callback ? decodeURIComponent(req.query.callback) : null
|
|
@@ -2906,7 +3045,6 @@ class Server {
|
|
|
2906
3045
|
// }
|
|
2907
3046
|
|
|
2908
3047
|
let shell = this.kernel.shell.get(id)
|
|
2909
|
-
console.log({ shell })
|
|
2910
3048
|
res.render("shell", {
|
|
2911
3049
|
theme: this.theme,
|
|
2912
3050
|
agent: this.agent,
|
|
@@ -2972,12 +3110,8 @@ class Server {
|
|
|
2972
3110
|
4. mode:connect => conda, git, caddy
|
|
2973
3111
|
*/
|
|
2974
3112
|
|
|
2975
|
-
console.log("setup mode", req.params.mode)
|
|
2976
|
-
|
|
2977
3113
|
let bin = this.kernel.bin.preset(req.params.mode)
|
|
2978
3114
|
|
|
2979
|
-
console.log("__ bin", bin)
|
|
2980
|
-
|
|
2981
3115
|
let { requirements, install_required, requirements_pending, error } = await this.kernel.bin.check({
|
|
2982
3116
|
bin
|
|
2983
3117
|
})
|
|
@@ -2988,7 +3122,6 @@ class Server {
|
|
|
2988
3122
|
requirements[i].dependencies = bin.conda_requirements
|
|
2989
3123
|
}
|
|
2990
3124
|
}
|
|
2991
|
-
console.log("RE", JSON.stringify(requirements, null, 2))
|
|
2992
3125
|
let current = req.query.callback || req.originalUrl
|
|
2993
3126
|
res.render("setup", {
|
|
2994
3127
|
error,
|
|
@@ -3010,7 +3143,6 @@ class Server {
|
|
|
3010
3143
|
let { requirements, install_required, requirements_pending, error } = await this.kernel.bin.check({
|
|
3011
3144
|
bin: this.kernel.bin.preset("network"),
|
|
3012
3145
|
})
|
|
3013
|
-
console.log({ requirements, install_required, requirements_pending })
|
|
3014
3146
|
|
|
3015
3147
|
if (!requirements_pending && install_required) {
|
|
3016
3148
|
res.redirect("/setup/network?callback=/network")
|
|
@@ -3149,14 +3281,17 @@ class Server {
|
|
|
3149
3281
|
|
|
3150
3282
|
|
|
3151
3283
|
// write title/description to pinokio.json
|
|
3152
|
-
let meta_path = path.resolve(folder_path, "pinokio.json")
|
|
3153
|
-
let meta = {
|
|
3154
|
-
title: "No title",
|
|
3155
|
-
description: "",
|
|
3156
|
-
icon: "icon.png"
|
|
3157
|
-
|
|
3158
|
-
|
|
3159
|
-
|
|
3284
|
+
// let meta_path = path.resolve(folder_path, "pinokio.json")
|
|
3285
|
+
// let meta = {
|
|
3286
|
+
// title: "No title",
|
|
3287
|
+
// description: "",
|
|
3288
|
+
// icon: "icon.png",
|
|
3289
|
+
// plugin: {
|
|
3290
|
+
// menu: []
|
|
3291
|
+
// }
|
|
3292
|
+
// }
|
|
3293
|
+
// console.log({ folder_path, default_icon_path, icon_path, meta_path, meta })
|
|
3294
|
+
// await fs.promises.writeFile(meta_path, JSON.stringify(meta, null, 2))
|
|
3160
3295
|
|
|
3161
3296
|
res.json({
|
|
3162
3297
|
success: "/pinokio/browser/"+folder
|
|
@@ -3271,9 +3406,32 @@ class Server {
|
|
|
3271
3406
|
}))
|
|
3272
3407
|
this.app.get("/prototype/run/*", ex(async (req, res) => {
|
|
3273
3408
|
let pathComponents = req.params[0].split("/").concat("pinokio.js")
|
|
3409
|
+
let config = await this.kernel.api.meta({ path: req.query.path })
|
|
3410
|
+
let pinokiojson_path = path.resolve(req.query.path, "pinokio.json")
|
|
3411
|
+
let pinokiojson = await this.kernel.require(pinokiojson_path)
|
|
3412
|
+
if (pinokiojson) {
|
|
3413
|
+
if (pinokiojson.plugin) {
|
|
3414
|
+
if (pinokiojson.plugin.menu) {
|
|
3415
|
+
} else {
|
|
3416
|
+
pinokiojson.plugin.menu = []
|
|
3417
|
+
await fs.promises.writeFile(pinokiojson_path, JSON.stringify(pinokiojson, null, 2))
|
|
3418
|
+
}
|
|
3419
|
+
} else {
|
|
3420
|
+
pinokiojson.plugin = { menu: [] }
|
|
3421
|
+
await fs.promises.writeFile(pinokiojson_path, JSON.stringify(pinokiojson, null, 2))
|
|
3422
|
+
}
|
|
3423
|
+
} else {
|
|
3424
|
+
pinokiojson = {
|
|
3425
|
+
plugin: {
|
|
3426
|
+
menu: []
|
|
3427
|
+
}
|
|
3428
|
+
}
|
|
3429
|
+
await fs.promises.writeFile(pinokiojson_path, JSON.stringify(pinokiojson, null, 2))
|
|
3430
|
+
}
|
|
3274
3431
|
req.base = this.kernel.path("prototype")
|
|
3275
|
-
req.query.callback =
|
|
3276
|
-
req.query.
|
|
3432
|
+
req.query.callback = config.ui
|
|
3433
|
+
//req.query.callback = config.browse
|
|
3434
|
+
req.query.cwd = req.query.path
|
|
3277
3435
|
await this.render(req, res, pathComponents, null)
|
|
3278
3436
|
}))
|
|
3279
3437
|
this.app.get("/prototype/show/*", ex(async (req, res) => {
|
|
@@ -3282,7 +3440,10 @@ class Server {
|
|
|
3282
3440
|
let title = this.kernel.proto.kv[name].title
|
|
3283
3441
|
let description = this.kernel.proto.kv[name].description
|
|
3284
3442
|
let readme = await this.kernel.proto.readme(name)
|
|
3443
|
+
let config = await this.kernel.api.meta({ path: req.query.path })
|
|
3285
3444
|
res.render("prototype/show", {
|
|
3445
|
+
config,
|
|
3446
|
+
path: req.query.path,
|
|
3286
3447
|
icon,
|
|
3287
3448
|
title,
|
|
3288
3449
|
description,
|
|
@@ -3290,7 +3451,7 @@ class Server {
|
|
|
3290
3451
|
prototype_path: name,
|
|
3291
3452
|
portal: this.portal,
|
|
3292
3453
|
readme,
|
|
3293
|
-
items: this.kernel.proto.items,
|
|
3454
|
+
items: this.kernel.proto.items.filter(item => item.type === 'init'),
|
|
3294
3455
|
logo: this.logo,
|
|
3295
3456
|
theme: this.theme,
|
|
3296
3457
|
agent: this.agent,
|
|
@@ -3298,9 +3459,28 @@ class Server {
|
|
|
3298
3459
|
})
|
|
3299
3460
|
}))
|
|
3300
3461
|
this.app.get("/prototype", ex(async (req, res) => {
|
|
3462
|
+
// load meta
|
|
3463
|
+
let config = await this.kernel.api.meta({ path: req.query.path })
|
|
3464
|
+
let items = this.kernel.proto.items
|
|
3465
|
+
if (req.query.type) {
|
|
3466
|
+
items = this.kernel.proto.items.filter(item => item.type === req.query.type)
|
|
3467
|
+
}
|
|
3468
|
+
let title
|
|
3469
|
+
let description
|
|
3470
|
+
if (req.query.type === "init") {
|
|
3471
|
+
title = "Initialize"
|
|
3472
|
+
description = "Select an option to intitialize the project with. This may overwrite the folder if you already have existing files"
|
|
3473
|
+
} else if (req.query.type === "extension") {
|
|
3474
|
+
title = "Extensions"
|
|
3475
|
+
description = "Add extension modules to the current folder"
|
|
3476
|
+
}
|
|
3301
3477
|
res.render("prototype/index", {
|
|
3478
|
+
title,
|
|
3479
|
+
description,
|
|
3480
|
+
config,
|
|
3481
|
+
path: req.query.path,
|
|
3302
3482
|
portal: this.portal,
|
|
3303
|
-
items
|
|
3483
|
+
items,
|
|
3304
3484
|
logo: this.logo,
|
|
3305
3485
|
theme: this.theme,
|
|
3306
3486
|
agent: this.agent,
|
|
@@ -3318,7 +3498,6 @@ class Server {
|
|
|
3318
3498
|
id
|
|
3319
3499
|
}
|
|
3320
3500
|
*/
|
|
3321
|
-
console.log("req.body", req.body)
|
|
3322
3501
|
let formData = req.body
|
|
3323
3502
|
for(let key in req.files) {
|
|
3324
3503
|
let file = req.files[key]
|
|
@@ -3357,7 +3536,6 @@ class Server {
|
|
|
3357
3536
|
id
|
|
3358
3537
|
}
|
|
3359
3538
|
*/
|
|
3360
|
-
console.log("req.body", req.body)
|
|
3361
3539
|
let formData = req.body
|
|
3362
3540
|
for(let key in req.files) {
|
|
3363
3541
|
let file = req.files[key]
|
|
@@ -3626,7 +3804,6 @@ class Server {
|
|
|
3626
3804
|
let pathComponents = req.params[0].split("/")
|
|
3627
3805
|
let filepath = path.resolve(this.kernel.homedir, req.params[0])
|
|
3628
3806
|
const content = await fs.promises.readFile(filepath, "utf8")
|
|
3629
|
-
console.log({ pathComponents, content })
|
|
3630
3807
|
res.render("general_editor", {
|
|
3631
3808
|
theme: this.theme,
|
|
3632
3809
|
filepath,
|
|
@@ -3639,6 +3816,20 @@ class Server {
|
|
|
3639
3816
|
res.json(this.startScripts)
|
|
3640
3817
|
}
|
|
3641
3818
|
}))
|
|
3819
|
+
this.app.get("/asset/*", ex((req, res) => {
|
|
3820
|
+
let pathComponents = req.params[0].split("/")
|
|
3821
|
+
let filepath = this.kernel.path(...pathComponents)
|
|
3822
|
+
try {
|
|
3823
|
+
if (req.query.frame) {
|
|
3824
|
+
let m = mime.lookup(filepath)
|
|
3825
|
+
res.type("text/plain")
|
|
3826
|
+
}
|
|
3827
|
+
//res.setHeader('Content-Disposition', 'inline');
|
|
3828
|
+
res.sendFile(filepath)
|
|
3829
|
+
} catch (e) {
|
|
3830
|
+
res.status(404).send(e.message);
|
|
3831
|
+
}
|
|
3832
|
+
}))
|
|
3642
3833
|
this.app.get("/raw/*", ex((req, res) => {
|
|
3643
3834
|
let pathComponents = req.params[0].split("/")
|
|
3644
3835
|
let filepath = this.kernel.path("api", ...pathComponents)
|
|
@@ -3662,6 +3853,15 @@ class Server {
|
|
|
3662
3853
|
res.status(404).send(e.message)
|
|
3663
3854
|
}
|
|
3664
3855
|
}))
|
|
3856
|
+
this.app.get("/run/*", ex(async (req, res) => {
|
|
3857
|
+
let pathComponents = req.params[0].split("/")
|
|
3858
|
+
req.base = this.kernel.homedir
|
|
3859
|
+
try {
|
|
3860
|
+
await this.render(req, res, pathComponents)
|
|
3861
|
+
} catch (e) {
|
|
3862
|
+
res.status(404).send(e.message)
|
|
3863
|
+
}
|
|
3864
|
+
}))
|
|
3665
3865
|
this.app.get("/api/*", ex(async (req, res) => {
|
|
3666
3866
|
let pathComponents = req.params[0].split("/")
|
|
3667
3867
|
if (req.query && 'command' in req.query) {
|
|
@@ -3698,10 +3898,10 @@ class Server {
|
|
|
3698
3898
|
}))
|
|
3699
3899
|
this.app.get("/pinokio/dynamic/:name", ex(async (req, res) => {
|
|
3700
3900
|
let plugin = await this.getPlugin(req.params.name)
|
|
3701
|
-
let plugin_menu = null
|
|
3702
3901
|
let html = ""
|
|
3703
3902
|
if (plugin && plugin.menu && Array.isArray(plugin.menu)) {
|
|
3704
|
-
|
|
3903
|
+
let running_dynamic = this.running_dynamic(req.params.name, plugin.menu)
|
|
3904
|
+
plugin.menu = plugin.menu.concat(running_dynamic)
|
|
3705
3905
|
html = await new Promise((resolve, reject) => {
|
|
3706
3906
|
ejs.renderFile(path.resolve(__dirname, "views/partials/dynamic.ejs"), { dynamic: plugin.menu }, (err, html) => {
|
|
3707
3907
|
resolve(html)
|
|
@@ -3735,7 +3935,6 @@ class Server {
|
|
|
3735
3935
|
}).filter((file) => {
|
|
3736
3936
|
return file.name !== "pinokio.js" && file.name !== "pinokio.json" && file.name !== "pinokio_meta.json"
|
|
3737
3937
|
})
|
|
3738
|
-
console.log("files", files)
|
|
3739
3938
|
config = {
|
|
3740
3939
|
title: name,
|
|
3741
3940
|
menu: files.map((file) => {
|
|
@@ -3769,7 +3968,6 @@ class Server {
|
|
|
3769
3968
|
}))
|
|
3770
3969
|
this.app.post("/pinokio/peer/refresh", ex(async (req, res) => {
|
|
3771
3970
|
// refresh and broadcast
|
|
3772
|
-
console.log("/peer/refresh")
|
|
3773
3971
|
await this.kernel.refresh()
|
|
3774
3972
|
res.json({ success: true })
|
|
3775
3973
|
}))
|