pinokiod 3.8.1 → 3.8.6
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/fs/index.js +6 -4
- package/kernel/api/index.js +102 -31
- package/kernel/bin/index.js +143 -4
- package/kernel/bin/node.js +9 -0
- package/kernel/index.js +32 -1
- package/kernel/info.js +1 -0
- package/kernel/prototype.js +47 -0
- package/kernel/shell.js +110 -54
- package/kernel/shells.js +16 -7
- package/kernel/store.js +58 -0
- package/kernel/util.js +106 -35
- package/package.json +1 -1
- package/script/index.js +12 -0
- package/server/index.js +466 -250
- package/server/public/SpaceMono-Bold.ttf +0 -0
- package/server/public/SpaceMono-BoldItalic.ttf +0 -0
- package/server/public/SpaceMono-Italic.ttf +0 -0
- package/server/public/SpaceMono-Regular.ttf +0 -0
- package/server/public/filepond-plugin-file-validate-type.min.js +9 -0
- package/server/public/filepond-plugin-image-crop.min.js +9 -0
- package/server/public/filepond-plugin-image-edit.min.css +8 -0
- package/server/public/filepond-plugin-image-edit.min.js +9 -0
- package/server/public/filepond-plugin-image-exif-orientation.min.js +9 -0
- package/server/public/filepond-plugin-image-preview.min.css +8 -0
- package/server/public/filepond-plugin-image-preview.min.js +9 -0
- package/server/public/filepond-plugin-image-resize.min.js +9 -0
- package/server/public/filepond-plugin-image-transform.min.js +9 -0
- package/server/public/filepond.min.css +8 -0
- package/server/public/filepond.min.js +9 -0
- package/server/public/fscreator.js +160 -0
- package/server/public/fseditor.js +189 -0
- package/server/public/github.png +0 -0
- package/server/public/opener.js +3 -1
- package/server/public/pinokio-black.png +0 -0
- package/server/public/pinokio-black2.png +0 -0
- package/server/public/style.css +131 -9
- package/server/socket.js +123 -37
- package/server/views/app.ejs +184 -11
- package/server/views/editor.ejs +12 -2
- package/server/views/explore.ejs +4 -3
- package/server/views/help.ejs +4 -2
- package/server/views/index.ejs +218 -80
- package/server/views/install.ejs +1 -1
- package/server/views/local_editor.ejs +282 -0
- package/server/views/minterm.ejs +692 -0
- package/server/views/partials/menu.ejs +7 -1
- package/server/views/prototypes.ejs +463 -0
- package/server/views/proxy.ejs +10 -4
- package/server/views/settings.ejs +4 -3
- package/server/views/terminal.ejs +99 -15
package/kernel/api/fs/index.js
CHANGED
|
@@ -75,16 +75,18 @@ class FS {
|
|
|
75
75
|
/*
|
|
76
76
|
params := {
|
|
77
77
|
path: <filepath>,
|
|
78
|
-
|
|
78
|
+
command: "view(default)|open|<any command in PATH>"
|
|
79
79
|
}
|
|
80
80
|
open finder/file explorer at path
|
|
81
81
|
*/
|
|
82
82
|
let dirPath = path.resolve(req.cwd, req.params.path)
|
|
83
83
|
ondata({ raw: `\r\nopening path: ${dirPath}\r\n` })
|
|
84
|
-
if (req.params.
|
|
85
|
-
Util.openfs(dirPath, req.params
|
|
84
|
+
if (req.params.command) {
|
|
85
|
+
Util.openfs(dirPath, req.params, kernel)
|
|
86
|
+
} else if (req.params.mode) {
|
|
87
|
+
Util.openfs(dirPath, req.params, kernel)
|
|
86
88
|
} else {
|
|
87
|
-
Util.openfs(dirPath)
|
|
89
|
+
Util.openfs(dirPath, {}, kernel)
|
|
88
90
|
}
|
|
89
91
|
}
|
|
90
92
|
|
package/kernel/api/index.js
CHANGED
|
@@ -119,21 +119,22 @@ class Api {
|
|
|
119
119
|
return result
|
|
120
120
|
}
|
|
121
121
|
async stop(req, ondata) {
|
|
122
|
+
console.log(">>>>>>>>>>>>>>>>>> STOP")
|
|
122
123
|
// 1. set the "stop" flag for the uri, so the next execution in the queue for the uri will NOT queue another task
|
|
123
124
|
// 2. stream a message closing the socket
|
|
125
|
+
console.time("stop 1")
|
|
124
126
|
|
|
125
127
|
let requestPath = this.filePath(req.params.uri)
|
|
126
128
|
|
|
127
|
-
|
|
128
|
-
|
|
129
129
|
let { cwd, script } = await this.resolveScript(requestPath)
|
|
130
|
-
console.log("STOP", { script })
|
|
131
130
|
if (script.on) {
|
|
132
131
|
if (script.on.stop) {
|
|
133
132
|
await this.process(script.on.stop)
|
|
134
133
|
}
|
|
135
134
|
}
|
|
135
|
+
console.timeEnd("stop 1")
|
|
136
136
|
|
|
137
|
+
console.time("stop 2")
|
|
137
138
|
// reset modules
|
|
138
139
|
let modpath = this.resolvePath(cwd, req.params.uri)
|
|
139
140
|
console.log("STOP modpath", modpath)
|
|
@@ -159,10 +160,15 @@ class Api {
|
|
|
159
160
|
|
|
160
161
|
// stop all proxies
|
|
161
162
|
this.stopProxy({ script: requestPath })
|
|
163
|
+
console.timeEnd("stop 2")
|
|
162
164
|
|
|
163
165
|
// stop all cloudflare tunnels
|
|
164
166
|
|
|
167
|
+
console.time("stop 3")
|
|
165
168
|
await this.kernel.stopCloudflare({ path: requestPath })
|
|
169
|
+
console.timeEnd("stop 3")
|
|
170
|
+
|
|
171
|
+
console.time("stop 4")
|
|
166
172
|
|
|
167
173
|
// if there are any pending waiters, delete them
|
|
168
174
|
|
|
@@ -179,6 +185,7 @@ class Api {
|
|
|
179
185
|
id: requestPath,
|
|
180
186
|
type: "disconnect"
|
|
181
187
|
})
|
|
188
|
+
console.timeEnd("stop 4")
|
|
182
189
|
return true
|
|
183
190
|
}
|
|
184
191
|
async startScripts() {
|
|
@@ -352,13 +359,20 @@ class Api {
|
|
|
352
359
|
let modpath
|
|
353
360
|
if (matched_repo.length > 0) {
|
|
354
361
|
let repo_uri = matched_repo[0]
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
.slice(1) // remove the leading '/' for relative path
|
|
362
|
+
if (!repo_uri.endsWith(".git")) {
|
|
363
|
+
repo_uri = repo_uri + ".git"
|
|
364
|
+
}
|
|
359
365
|
|
|
360
366
|
let repopath = this.gitPath[repo_uri]
|
|
361
|
-
|
|
367
|
+
if (uri === repo_uri) {
|
|
368
|
+
modpath = path.resolve(repopath)
|
|
369
|
+
} else {
|
|
370
|
+
let relative_path = uri
|
|
371
|
+
.replace(repo_uri, "") // remove the git repo uri
|
|
372
|
+
.slice(1) // remove the leading '/' for relative path
|
|
373
|
+
modpath = path.resolve(repopath, relative_path)
|
|
374
|
+
}
|
|
375
|
+
|
|
362
376
|
} else {
|
|
363
377
|
//console.log("no matching gitpath")
|
|
364
378
|
}
|
|
@@ -1121,6 +1135,35 @@ class Api {
|
|
|
1121
1135
|
this.process(request, resolve)
|
|
1122
1136
|
})
|
|
1123
1137
|
}
|
|
1138
|
+
async get_default(repo_path) {
|
|
1139
|
+
let p = path.resolve(repo_path, "pinokio.js")
|
|
1140
|
+
// call 'process' based on the current status
|
|
1141
|
+
let config = (await this.loader.load(p)).resolved
|
|
1142
|
+
if (config && config.menu) {
|
|
1143
|
+
if (typeof config.menu === "function") {
|
|
1144
|
+
if (config.menu.constructor.name === "AsyncFunction") {
|
|
1145
|
+
config.menu = await config.menu(this.kernel, this.kernel.info)
|
|
1146
|
+
} else {
|
|
1147
|
+
config.menu = config.menu(this.kernel, this.kernel.info)
|
|
1148
|
+
}
|
|
1149
|
+
}
|
|
1150
|
+
// find the default item in the menu
|
|
1151
|
+
let running = config.menu.filter((item) => {
|
|
1152
|
+
return item.default
|
|
1153
|
+
})
|
|
1154
|
+
if (running.length > 0) {
|
|
1155
|
+
let r = running[0]
|
|
1156
|
+
if (r.href) {
|
|
1157
|
+
if (r.href.startsWith("http")) {
|
|
1158
|
+
return r.href
|
|
1159
|
+
} else {
|
|
1160
|
+
let href = path.resolve(repo_path, r.href)
|
|
1161
|
+
return href
|
|
1162
|
+
}
|
|
1163
|
+
}
|
|
1164
|
+
}
|
|
1165
|
+
}
|
|
1166
|
+
}
|
|
1124
1167
|
async process(request, done) {
|
|
1125
1168
|
/**************************************************************
|
|
1126
1169
|
*
|
|
@@ -1162,43 +1205,67 @@ class Api {
|
|
|
1162
1205
|
// this.kernel.keys = (await this.loader.load(keypath)).resolved
|
|
1163
1206
|
|
|
1164
1207
|
// init shell before running just to make sure the environment variables are fresh
|
|
1165
|
-
console.time("shell.init")
|
|
1166
1208
|
await this.kernel.shell.init()
|
|
1167
|
-
console.timeEnd("shell.init")
|
|
1168
1209
|
|
|
1169
1210
|
if (request.uri){
|
|
1211
|
+
|
|
1170
1212
|
this.counter++;
|
|
1171
1213
|
// API Call
|
|
1172
1214
|
|
|
1173
1215
|
request.path = this.resolvePath(this.userdir, request.uri)
|
|
1174
|
-
let { cwd, script } = await this.resolveScript(request.path)
|
|
1175
|
-
request.cwd = cwd
|
|
1176
1216
|
|
|
1177
|
-
if (!script) {
|
|
1178
|
-
this.ondata({
|
|
1179
|
-
id: request.path,
|
|
1180
|
-
type: "error",
|
|
1181
|
-
data: "the endpoint does not exist: " + request.uri,
|
|
1182
|
-
})
|
|
1183
|
-
} else {
|
|
1184
|
-
// 3. Check if the resolved endpoint has the "run" attribute and it's an array
|
|
1185
|
-
//if (script.run && Array.isArray(script.run)) {
|
|
1186
|
-
if (script.run) {
|
|
1187
|
-
|
|
1188
|
-
this.running[request.path] = true
|
|
1189
|
-
|
|
1190
|
-
this.done[request.path] = done
|
|
1191
|
-
|
|
1192
|
-
this.queue(request, script.run[0], request.input, 0, script.run.length, cwd, request.input)
|
|
1193
1217
|
|
|
1218
|
+
// if the path is
|
|
1219
|
+
let relative = path.relative(this.kernel.homedir, request.path)
|
|
1220
|
+
let chunks = relative.split(path.sep)
|
|
1221
|
+
console.log({ chunks })
|
|
1222
|
+
if (chunks.length == 2) {
|
|
1223
|
+
// the script is requesting a uri of the git repo
|
|
1224
|
+
// look for pinokio.js
|
|
1225
|
+
let p = path.resolve(request.path, "pinokio.js")
|
|
1226
|
+
let exists = await this.exists(p)
|
|
1227
|
+
console.log({ p, exists })
|
|
1228
|
+
if (exists) {
|
|
1229
|
+
await this.launch(request, p)
|
|
1194
1230
|
} else {
|
|
1195
1231
|
this.ondata({
|
|
1196
1232
|
id: request.path,
|
|
1197
1233
|
type: "error",
|
|
1198
|
-
data: "
|
|
1234
|
+
data: "uri doesn't exist \r\n" + JSON.stringify(request, null, 2)
|
|
1199
1235
|
})
|
|
1200
1236
|
}
|
|
1237
|
+
} else {
|
|
1238
|
+
console.log({ request })
|
|
1239
|
+
let { cwd, script } = await this.resolveScript(request.path)
|
|
1240
|
+
request.cwd = cwd
|
|
1241
|
+
|
|
1242
|
+
if (!script) {
|
|
1243
|
+
this.ondata({
|
|
1244
|
+
id: request.path,
|
|
1245
|
+
type: "error",
|
|
1246
|
+
data: "the endpoint does not exist: " + request.uri,
|
|
1247
|
+
})
|
|
1248
|
+
} else {
|
|
1249
|
+
// 3. Check if the resolved endpoint has the "run" attribute and it's an array
|
|
1250
|
+
//if (script.run && Array.isArray(script.run)) {
|
|
1251
|
+
if (script.run) {
|
|
1252
|
+
|
|
1253
|
+
this.running[request.path] = true
|
|
1254
|
+
|
|
1255
|
+
this.done[request.path] = done
|
|
1256
|
+
|
|
1257
|
+
this.queue(request, script.run[0], request.input, 0, script.run.length, cwd, request.input)
|
|
1258
|
+
|
|
1259
|
+
} else {
|
|
1260
|
+
this.ondata({
|
|
1261
|
+
id: request.path,
|
|
1262
|
+
type: "error",
|
|
1263
|
+
data: "missing attribute: run"
|
|
1264
|
+
})
|
|
1265
|
+
}
|
|
1266
|
+
}
|
|
1201
1267
|
}
|
|
1268
|
+
|
|
1202
1269
|
} else if (request.method) {
|
|
1203
1270
|
let pass = 0;
|
|
1204
1271
|
while(true) {
|
|
@@ -1229,12 +1296,16 @@ class Api {
|
|
|
1229
1296
|
|
|
1230
1297
|
// Kernel Call
|
|
1231
1298
|
let resolved = await this.resolveMethod(request)
|
|
1299
|
+
let id = request.id ? request.id : request.method
|
|
1300
|
+
if (request.id) {
|
|
1301
|
+
this.running[request.id] = true
|
|
1302
|
+
}
|
|
1232
1303
|
try {
|
|
1233
1304
|
resolved.dirname = resolved.dirname
|
|
1234
1305
|
let result = await this.run(resolved.method, request, (stream, type) => {
|
|
1235
1306
|
this.ondata({
|
|
1236
1307
|
kernel: true,
|
|
1237
|
-
id
|
|
1308
|
+
id,
|
|
1238
1309
|
type: (type ? type : "stream"),
|
|
1239
1310
|
data: stream,
|
|
1240
1311
|
rpc: request,
|
|
@@ -1243,7 +1314,7 @@ class Api {
|
|
|
1243
1314
|
})
|
|
1244
1315
|
this.ondata({
|
|
1245
1316
|
kernel: true,
|
|
1246
|
-
id
|
|
1317
|
+
id,
|
|
1247
1318
|
type: "result",
|
|
1248
1319
|
data: result,
|
|
1249
1320
|
rpc: request,
|
package/kernel/bin/index.js
CHANGED
|
@@ -37,12 +37,28 @@ class Bin {
|
|
|
37
37
|
this.arch = os.arch()
|
|
38
38
|
this.platform = os.platform()
|
|
39
39
|
}
|
|
40
|
+
async shell_kill(params, ondata) {
|
|
41
|
+
console.log("shell_kill", params)
|
|
42
|
+
this.kernel.shell.kill(params.params)
|
|
43
|
+
}
|
|
44
|
+
async shell_start(params, ondata) {
|
|
45
|
+
params.path = params.path || this.path()
|
|
46
|
+
console.log("this.client?", this.client)
|
|
47
|
+
if (this.client) {
|
|
48
|
+
params.cols = this.client.cols
|
|
49
|
+
params.rows = this.client.rows
|
|
50
|
+
}
|
|
51
|
+
console.log({ params })
|
|
52
|
+
let response = await this.kernel.shell.start(params, null, ondata)
|
|
53
|
+
return response
|
|
54
|
+
}
|
|
40
55
|
async exec(params, ondata) {
|
|
41
56
|
params.path = params.path || this.path()
|
|
42
57
|
if (this.client) {
|
|
43
58
|
params.cols = this.client.cols
|
|
44
59
|
params.rows = this.client.rows
|
|
45
60
|
}
|
|
61
|
+
console.log({ params })
|
|
46
62
|
let response = await this.kernel.shell.run(params, null, ondata)
|
|
47
63
|
return response
|
|
48
64
|
}
|
|
@@ -646,6 +662,24 @@ class Bin {
|
|
|
646
662
|
}
|
|
647
663
|
// }
|
|
648
664
|
}
|
|
665
|
+
async path_exists(req, ondata) {
|
|
666
|
+
let abspath = this.kernel.api.resolvePath(this.kernel.api.userdir, req.params.uri)
|
|
667
|
+
if (abspath) {
|
|
668
|
+
console.log({ abspath })
|
|
669
|
+
let exists = await new Promise(r=>fs.access(abspath, fs.constants.F_OK, e => r(!e)))
|
|
670
|
+
return exists
|
|
671
|
+
} else {
|
|
672
|
+
return false
|
|
673
|
+
}
|
|
674
|
+
}
|
|
675
|
+
async install2(req, ondata) {
|
|
676
|
+
let { requirements, install_required, requirements_pending, error } = await this.check_bin()
|
|
677
|
+
req.params = JSON.stringify(requirements)
|
|
678
|
+
if (this.install_required) {
|
|
679
|
+
let res = await this.install(req, ondata)
|
|
680
|
+
return res
|
|
681
|
+
}
|
|
682
|
+
}
|
|
649
683
|
async install(req, ondata) {
|
|
650
684
|
/*
|
|
651
685
|
req.params := {
|
|
@@ -665,6 +699,8 @@ class Bin {
|
|
|
665
699
|
this.client = null
|
|
666
700
|
}
|
|
667
701
|
|
|
702
|
+
console.log("install", req)
|
|
703
|
+
|
|
668
704
|
let requirements = JSON.parse(req.params)
|
|
669
705
|
|
|
670
706
|
for(let x=0; x<10; x++) {
|
|
@@ -738,17 +774,29 @@ class Bin {
|
|
|
738
774
|
//}
|
|
739
775
|
await this.init()
|
|
740
776
|
}
|
|
777
|
+
async installed(r) {
|
|
778
|
+
if (Array.isArray(r.name)) {
|
|
779
|
+
for(let name of r.name) {
|
|
780
|
+
let installed = await this._installed(name, r.type)
|
|
781
|
+
if (!installed) return false
|
|
782
|
+
}
|
|
783
|
+
return true
|
|
784
|
+
} else {
|
|
785
|
+
let installed = await this._installed(r.name, r.type)
|
|
786
|
+
return installed
|
|
787
|
+
}
|
|
788
|
+
}
|
|
741
789
|
async _installed(name, type) {
|
|
742
790
|
if (type === "conda") {
|
|
743
|
-
return this.
|
|
791
|
+
return this.installed.conda.has(name)
|
|
744
792
|
} else if (type === "pip") {
|
|
745
|
-
return this.
|
|
793
|
+
return this.installed.pip && this.installed.pip.has(name)
|
|
746
794
|
} else if (type === "brew") {
|
|
747
|
-
return this.
|
|
795
|
+
return this.installed.brew.has(name)
|
|
748
796
|
} else {
|
|
749
797
|
// check kernel/bin/<module>.installed()
|
|
750
798
|
let filepath = path.resolve(__dirname, "..", "kernel", "bin", name + ".js")
|
|
751
|
-
let mod = this.
|
|
799
|
+
let mod = this.mod[name]
|
|
752
800
|
let installed = false
|
|
753
801
|
if (mod.installed) {
|
|
754
802
|
installed = await mod.installed()
|
|
@@ -756,6 +804,97 @@ class Bin {
|
|
|
756
804
|
return installed
|
|
757
805
|
}
|
|
758
806
|
}
|
|
807
|
+
async check_bin() {
|
|
808
|
+
let requirements = [
|
|
809
|
+
{ name: "conda", },
|
|
810
|
+
{ name: "git", },
|
|
811
|
+
{ name: "zip", },
|
|
812
|
+
{ name: "node", },
|
|
813
|
+
{ name: "ffmpeg", }
|
|
814
|
+
]
|
|
815
|
+
let platform = os.platform()
|
|
816
|
+
if (platform === "win32") {
|
|
817
|
+
requirements.push({ name: "registry" })
|
|
818
|
+
requirements.push({ name: "vs" })
|
|
819
|
+
}
|
|
820
|
+
if (platform === "darwin") {
|
|
821
|
+
requirements.push({ name: "brew" })
|
|
822
|
+
}
|
|
823
|
+
if (platform === "linux") {
|
|
824
|
+
requirements.push({ name: "gxx" })
|
|
825
|
+
}
|
|
826
|
+
if (this.kernel.gpu === "nvidia") {
|
|
827
|
+
requirements.push({ name: "cuda", })
|
|
828
|
+
}
|
|
829
|
+
requirements = requirements.concat([
|
|
830
|
+
{ name: "py" },
|
|
831
|
+
{ name: "cloudflared" },
|
|
832
|
+
{ name: "playwright" },
|
|
833
|
+
{ name: "huggingface" },
|
|
834
|
+
{ name: "uv" }
|
|
835
|
+
])
|
|
836
|
+
|
|
837
|
+
let requirements_pending = !this.installed_initialized
|
|
838
|
+
let install_required = true
|
|
839
|
+
if (!requirements_pending) {
|
|
840
|
+
install_required = false
|
|
841
|
+
for(let i=0; i<requirements.length; i++) {
|
|
842
|
+
let r = requirements[i]
|
|
843
|
+
console.time(r.name)
|
|
844
|
+
let installed = await this.installed(r)
|
|
845
|
+
console.log({ r, installed })
|
|
846
|
+
console.timeEnd(r.name)
|
|
847
|
+
requirements[i].installed = installed
|
|
848
|
+
if (!installed) {
|
|
849
|
+
install_required = true
|
|
850
|
+
}
|
|
851
|
+
}
|
|
852
|
+
}
|
|
853
|
+
|
|
854
|
+
let error = null
|
|
855
|
+
try {
|
|
856
|
+
this.compatible()
|
|
857
|
+
} catch (e) {
|
|
858
|
+
error = e.message
|
|
859
|
+
install_required = true
|
|
860
|
+
}
|
|
861
|
+
|
|
862
|
+
this.install_required = install_required
|
|
863
|
+
this.requirements_pending = requirements_pending
|
|
864
|
+
|
|
865
|
+
console.log("check_bin finished 2")
|
|
866
|
+
return {
|
|
867
|
+
error,
|
|
868
|
+
requirements,
|
|
869
|
+
install_required,
|
|
870
|
+
requirements_pending
|
|
871
|
+
}
|
|
872
|
+
|
|
873
|
+
}
|
|
874
|
+
winBuildNumber() {
|
|
875
|
+
let osVersion = (/(\d+)\.(\d+)\.(\d+)/g).exec(os.release());
|
|
876
|
+
let buildNumber = 0;
|
|
877
|
+
if (osVersion && osVersion.length === 4) {
|
|
878
|
+
buildNumber = parseInt(osVersion[3]);
|
|
879
|
+
}
|
|
880
|
+
return buildNumber;
|
|
881
|
+
}
|
|
882
|
+
compatible() {
|
|
883
|
+
if (this.kernel.platform === "win32") {
|
|
884
|
+
let buildNumber = this.winBuildNumber()
|
|
885
|
+
if (buildNumber < 18309) {
|
|
886
|
+
// must use conpty for node-pty, and conpty is only supported in win>=18309
|
|
887
|
+
console.log("Windows buildNumber", buildNumber)
|
|
888
|
+
throw new Error(`Pinokio supports Windows release 18309 and up (current system: ${buildNumber}`)
|
|
889
|
+
}
|
|
890
|
+
|
|
891
|
+
// if (buildNumber > 25000) {
|
|
892
|
+
// console.log("Windows buildNumber", buildNumber)
|
|
893
|
+
// throw new Error(`Pinokio does not currently support Windows Canary (versions 25000 and up). The current system is ${buildNumber}`)
|
|
894
|
+
//
|
|
895
|
+
// }
|
|
896
|
+
}
|
|
897
|
+
}
|
|
759
898
|
async sh(params, ondata) {
|
|
760
899
|
let response = await this.kernel.shell.run(params, null, ondata)
|
|
761
900
|
return response
|
package/kernel/bin/node.js
CHANGED
|
@@ -20,6 +20,15 @@ class Node {
|
|
|
20
20
|
async installed() {
|
|
21
21
|
return this.kernel.bin.installed.conda.has("nodejs") && this.kernel.bin.installed.conda.has("pnpm")
|
|
22
22
|
}
|
|
23
|
+
env() {
|
|
24
|
+
return {
|
|
25
|
+
PATH: [this.kernel.path("bin/npm"), this.kernel.path("bin/npm/bin")],
|
|
26
|
+
NPM_CONFIG_PREFIX: this.kernel.path("bin/npm"),
|
|
27
|
+
npm_config_prefix: this.kernel.path("bin/npm"),
|
|
28
|
+
PNPM_HOME: this.kernel.path("bin/npm"),
|
|
29
|
+
pnpm_home: this.kernel.path("bin/npm"),
|
|
30
|
+
}
|
|
31
|
+
}
|
|
23
32
|
async uninstall(req, ondata) {
|
|
24
33
|
await this.kernel.bin.exec({
|
|
25
34
|
message: "conda remove nodejs pnpm",
|
package/kernel/index.js
CHANGED
|
@@ -7,6 +7,7 @@ const fastq = require('fastq')
|
|
|
7
7
|
const fetch = require('cross-fetch');
|
|
8
8
|
const waitOn = require('wait-on');
|
|
9
9
|
const system = require('systeminformation');
|
|
10
|
+
const shellPath = require('shell-path');
|
|
10
11
|
const Sysinfo = require('./sysinfo')
|
|
11
12
|
const portfinder = require('portfinder-cp');
|
|
12
13
|
const { execSync } = require('child_process')
|
|
@@ -26,6 +27,8 @@ const Config = require("./pinokio.json")
|
|
|
26
27
|
const Info = require('./info')
|
|
27
28
|
const Pipe = require("../pipe")
|
|
28
29
|
const Cloudflare = require('./api/cloudflare')
|
|
30
|
+
const Store = require('./store')
|
|
31
|
+
const Proto = require('./prototype')
|
|
29
32
|
const VARS = {
|
|
30
33
|
pip: {
|
|
31
34
|
install: {
|
|
@@ -42,7 +45,29 @@ class Kernel {
|
|
|
42
45
|
schema = "<=3.7.0"
|
|
43
46
|
constructor(store) {
|
|
44
47
|
this.fetch = fetch
|
|
45
|
-
|
|
48
|
+
|
|
49
|
+
// STORE
|
|
50
|
+
// Previously custom STORE could be passed in. This was to support both electron and server based initialization
|
|
51
|
+
// But this creates complexity because the store location is not fixed
|
|
52
|
+
// Migrating it to ~/.pinokio/config.json
|
|
53
|
+
//
|
|
54
|
+
// 1. does ~/.pinokio exist?
|
|
55
|
+
// - load from that file
|
|
56
|
+
// 2. does ~/.pinokio NOT exist?
|
|
57
|
+
// - save the passed in options to the `~/.pinokio`
|
|
58
|
+
// - load the config
|
|
59
|
+
|
|
60
|
+
this.store = new Store()
|
|
61
|
+
let exists = this.store.exists()
|
|
62
|
+
console.log("Store exists?", exists)
|
|
63
|
+
if (!exists) {
|
|
64
|
+
console.log("doesn't exist")
|
|
65
|
+
// clone the store to the new store
|
|
66
|
+
this.store.clone(store.store)
|
|
67
|
+
// load from the store (this will be the last time this is used, since the next time it loads, it will load from the new store)
|
|
68
|
+
}
|
|
69
|
+
console.log("this.store", this.store.store())
|
|
70
|
+
|
|
46
71
|
this.arch = os.arch()
|
|
47
72
|
this.os = os
|
|
48
73
|
this.platform = os.platform()
|
|
@@ -52,7 +77,9 @@ class Kernel {
|
|
|
52
77
|
this.envs = {}
|
|
53
78
|
this.info = new Info(this)
|
|
54
79
|
this.pipe = new Pipe(this)
|
|
80
|
+
this.proto = new Proto(this)
|
|
55
81
|
this.cloudflare = new Cloudflare()
|
|
82
|
+
this.shellpath = shellPath.sync()
|
|
56
83
|
}
|
|
57
84
|
/*
|
|
58
85
|
kernel.env() => return the system environment
|
|
@@ -513,6 +540,7 @@ class Kernel {
|
|
|
513
540
|
console.log("bin init finished")
|
|
514
541
|
if (this.homedir) {
|
|
515
542
|
this.shell.init().then(async () => {
|
|
543
|
+
this.bin.check_bin()
|
|
516
544
|
if (this.envs) {
|
|
517
545
|
this.template.update({
|
|
518
546
|
env: this.envs,
|
|
@@ -616,6 +644,9 @@ class Kernel {
|
|
|
616
644
|
await fs.promises.writeFile(this.path("logs/system.json"), JSON.stringify(this.i, null, 2))
|
|
617
645
|
let pwpath = this.bin.path("playwright/node_modules/playwright")
|
|
618
646
|
this.playwright = (await this.loader.load(pwpath)).resolved
|
|
647
|
+
|
|
648
|
+
|
|
649
|
+
await this.proto.init()
|
|
619
650
|
}
|
|
620
651
|
|
|
621
652
|
} catch (e) {
|
package/kernel/info.js
CHANGED
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
const fs = require('fs')
|
|
2
|
+
const path = require('path')
|
|
3
|
+
class Proto {
|
|
4
|
+
constructor(kernel) {
|
|
5
|
+
this.kernel = kernel
|
|
6
|
+
}
|
|
7
|
+
async init() {
|
|
8
|
+
|
|
9
|
+
// if ~/pinokio/prototype doesn't exist, clone
|
|
10
|
+
let exists = await this.kernel.exists("prototype")
|
|
11
|
+
if (!exists) {
|
|
12
|
+
console.log("prototype doesn't exist. cloning...")
|
|
13
|
+
await this.kernel.exec({
|
|
14
|
+
message: "git clone https://github.com/peanutcocktail/prototype",
|
|
15
|
+
path: this.kernel.homedir
|
|
16
|
+
}, (e) => {
|
|
17
|
+
process.stdout.write(e.raw)
|
|
18
|
+
})
|
|
19
|
+
}
|
|
20
|
+
// get all prototypes
|
|
21
|
+
let prototype_dir = path.resolve(this.kernel.homedir, "prototype")
|
|
22
|
+
let prototypes = await fs.promises.readdir(prototype_dir, { withFileTypes: true })
|
|
23
|
+
prototypes = prototypes.filter(d => d.isDirectory()).map(d => d.name);
|
|
24
|
+
console.log({ prototypes })
|
|
25
|
+
this.items = []
|
|
26
|
+
this.kv = {}
|
|
27
|
+
for(let proto of prototypes) {
|
|
28
|
+
let pinokiojs = path.resolve(prototype_dir, proto, "pinokio.js")
|
|
29
|
+
let config = await this.kernel.require(pinokiojs)
|
|
30
|
+
console.log({ config })
|
|
31
|
+
if (config && config.type === "prototype") {
|
|
32
|
+
if (config.icon) {
|
|
33
|
+
config.icon = "/prototype/" + proto + "/" + config.icon
|
|
34
|
+
} else {
|
|
35
|
+
config.icon === "/pinokio-black.png"
|
|
36
|
+
}
|
|
37
|
+
let c = {
|
|
38
|
+
id: proto,
|
|
39
|
+
...config
|
|
40
|
+
}
|
|
41
|
+
this.items.push(c)
|
|
42
|
+
this.kv[proto] = c
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
module.exports = Proto
|