pinokiod 3.8.0 → 3.8.5
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/cuda.js +7 -0
- 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 +687 -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
|
@@ -0,0 +1,189 @@
|
|
|
1
|
+
const FSEditor = async ({title, description, old_path, icon, iconpath, redirect, copy, move, edit }) => {
|
|
2
|
+
console.log({ icon, iconpath })
|
|
3
|
+
const compare = async (file1, file2) => {
|
|
4
|
+
if (file1.size !== file2.size) return false;
|
|
5
|
+
console.log({ file1, file2 })
|
|
6
|
+
const buffer1 = await file1.arrayBuffer();
|
|
7
|
+
const buffer2 = await file2.arrayBuffer();
|
|
8
|
+
const view1 = new Uint8Array(buffer1);
|
|
9
|
+
const view2 = new Uint8Array(buffer2);
|
|
10
|
+
for (let i = 0; i < view1.length; i++) {
|
|
11
|
+
if (view1[i] !== view2[i]) return false;
|
|
12
|
+
}
|
|
13
|
+
return true;
|
|
14
|
+
}
|
|
15
|
+
let dirty
|
|
16
|
+
let mode
|
|
17
|
+
let new_path
|
|
18
|
+
let initial_file
|
|
19
|
+
let title_label
|
|
20
|
+
let file_type
|
|
21
|
+
let folderpath_html = ""
|
|
22
|
+
if (copy) {
|
|
23
|
+
mode = "copy"
|
|
24
|
+
title_label = "Copy to"
|
|
25
|
+
} else if (move) {
|
|
26
|
+
mode = "move"
|
|
27
|
+
title_label = "Move to"
|
|
28
|
+
} else {
|
|
29
|
+
mode = "edit"
|
|
30
|
+
title_label = "Edit"
|
|
31
|
+
}
|
|
32
|
+
if (copy || move) {
|
|
33
|
+
folderpath_html = `<div class='folder-row'>
|
|
34
|
+
<label for='new-folder-description'>Folder Path</label>
|
|
35
|
+
<div class='field-row'>
|
|
36
|
+
<label>/api/</label>
|
|
37
|
+
<input id="new-folder-path" class="swal2-input" placeholder="Folder Path" value="${old_path}" />
|
|
38
|
+
</div>
|
|
39
|
+
</div>`
|
|
40
|
+
}
|
|
41
|
+
let result = await Swal.fire({
|
|
42
|
+
title: title_label,
|
|
43
|
+
html: `<div class='filepond-wrapper'>
|
|
44
|
+
<div class='avatar-field'>
|
|
45
|
+
<input id='new-folder-image' type="file" class="filepond" name="avatar" accept="image/png, image/jpeg, image/gif" />
|
|
46
|
+
</div>
|
|
47
|
+
<div class='folder-rows'>
|
|
48
|
+
${folderpath_html}
|
|
49
|
+
<div class='folder-row'>
|
|
50
|
+
<label for='new-folder-title'>Title</label>
|
|
51
|
+
<input id="new-folder-title" class="swal2-input" placeholder="Folder Name" value="${title}" />
|
|
52
|
+
</div>
|
|
53
|
+
<div class='folder-row'>
|
|
54
|
+
<label for='new-folder-description'>Description</label>
|
|
55
|
+
<textarea id="new-folder-description" class="swal2-input" placeholder="Folder Description">${description}</textarea>
|
|
56
|
+
</div>
|
|
57
|
+
</div>
|
|
58
|
+
</div>`,
|
|
59
|
+
allowOutsideClick: true,
|
|
60
|
+
focusConfirm: false,
|
|
61
|
+
// showCancelButton: true,
|
|
62
|
+
confirmButtonText: 'Save',
|
|
63
|
+
didOpen: () => {
|
|
64
|
+
const textarea = document.querySelector("#new-folder-description")
|
|
65
|
+
textarea.style.height = 'auto';
|
|
66
|
+
textarea.style.height = textarea.scrollHeight + 'px';
|
|
67
|
+
textarea.addEventListener('input', () => {
|
|
68
|
+
textarea.style.height = textarea.scrollHeight + 'px';
|
|
69
|
+
});
|
|
70
|
+
FilePond.registerPlugin(
|
|
71
|
+
FilePondPluginFileValidateType,
|
|
72
|
+
FilePondPluginImageExifOrientation,
|
|
73
|
+
FilePondPluginImagePreview,
|
|
74
|
+
FilePondPluginImageCrop,
|
|
75
|
+
FilePondPluginImageResize,
|
|
76
|
+
FilePondPluginImageTransform,
|
|
77
|
+
FilePondPluginImageEdit
|
|
78
|
+
);
|
|
79
|
+
pond = FilePond.create(
|
|
80
|
+
document.querySelector('#new-folder-image'),
|
|
81
|
+
{
|
|
82
|
+
allowReplace: true,
|
|
83
|
+
allowRevert: true,
|
|
84
|
+
allowRemove: true,
|
|
85
|
+
|
|
86
|
+
allowImageCrop: true,
|
|
87
|
+
allowImageEdit: true,
|
|
88
|
+
allowImageTransform: true,
|
|
89
|
+
|
|
90
|
+
|
|
91
|
+
labelIdle: `Drag & Drop your picture or <span class="filepond--label-action">Browse</span>`,
|
|
92
|
+
imagePreviewHeight: 170,
|
|
93
|
+
imageCropAspectRatio: '1:1',
|
|
94
|
+
imageResizeTargetWidth: 200,
|
|
95
|
+
imageResizeTargetHeight: 200,
|
|
96
|
+
stylePanelLayout: 'compact circle',
|
|
97
|
+
instantUpload: false,
|
|
98
|
+
server: {
|
|
99
|
+
process: {
|
|
100
|
+
url: '/pinokio/upload', // optional if same as above
|
|
101
|
+
ondata: (formData) => {
|
|
102
|
+
console.log("upload", { dirty })
|
|
103
|
+
if (dirty) {
|
|
104
|
+
formData.append("icon_dirty", true)
|
|
105
|
+
}
|
|
106
|
+
formData.append("icon_path", iconpath)
|
|
107
|
+
let title = Swal.getPopup().querySelector('#new-folder-title').value
|
|
108
|
+
let description = Swal.getPopup().querySelector('#new-folder-description').value
|
|
109
|
+
let folder_path_el = Swal.getPopup().querySelector('#new-folder-path')
|
|
110
|
+
formData.append("title", title)
|
|
111
|
+
formData.append("description", description)
|
|
112
|
+
formData.append("old_path", old_path)
|
|
113
|
+
let path
|
|
114
|
+
if (folder_path_el) {
|
|
115
|
+
path = folder_path_el.value
|
|
116
|
+
formData.append("new_path", path)
|
|
117
|
+
} else {
|
|
118
|
+
path = old_path
|
|
119
|
+
formData.append("new_path", old_path)
|
|
120
|
+
}
|
|
121
|
+
if (mode === "copy") {
|
|
122
|
+
formData.append("copy", true)
|
|
123
|
+
} else if (mode === "move") {
|
|
124
|
+
formData.append("move", true)
|
|
125
|
+
}
|
|
126
|
+
if (edit) {
|
|
127
|
+
formData.append("edit", true)
|
|
128
|
+
}
|
|
129
|
+
new_path = path
|
|
130
|
+
return formData;
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
},
|
|
134
|
+
onaddfile(error, file) {
|
|
135
|
+
console.log({ file, initial_file })
|
|
136
|
+
if (initial_file) {
|
|
137
|
+
compare(initial_file.file, file.file).then((same) => {
|
|
138
|
+
if (same) {
|
|
139
|
+
// don't do anything
|
|
140
|
+
} else {
|
|
141
|
+
dirty = true
|
|
142
|
+
// make sure the image mime type is transformed into the same type as the existing image
|
|
143
|
+
pond.setOptions({
|
|
144
|
+
imageTransformOutputMimeType: initial_file.fileType
|
|
145
|
+
})
|
|
146
|
+
}
|
|
147
|
+
initial_file = file
|
|
148
|
+
})
|
|
149
|
+
} else {
|
|
150
|
+
initial_file = file
|
|
151
|
+
}
|
|
152
|
+
},
|
|
153
|
+
onprocessfile(error, file) {
|
|
154
|
+
console.log("onprocessfile")
|
|
155
|
+
debugger
|
|
156
|
+
if (error) {
|
|
157
|
+
alert(error.body)
|
|
158
|
+
} else {
|
|
159
|
+
Swal.close()
|
|
160
|
+
if (new_path) {
|
|
161
|
+
location.href = redirect(new_path)
|
|
162
|
+
} else {
|
|
163
|
+
location.href = location.href
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
},
|
|
167
|
+
files: [
|
|
168
|
+
{
|
|
169
|
+
type: 'local',
|
|
170
|
+
source: icon,
|
|
171
|
+
}
|
|
172
|
+
]
|
|
173
|
+
}
|
|
174
|
+
);
|
|
175
|
+
},
|
|
176
|
+
preConfirm: () => {
|
|
177
|
+
if (mode === "copy") {
|
|
178
|
+
let new_path = Swal.getPopup().querySelector('#new-folder-path').value
|
|
179
|
+
if (new_path === old_path) {
|
|
180
|
+
alert("Please specify a new folder name to copy to")
|
|
181
|
+
return false
|
|
182
|
+
}
|
|
183
|
+
}
|
|
184
|
+
pond.processFile()
|
|
185
|
+
return false
|
|
186
|
+
}
|
|
187
|
+
})
|
|
188
|
+
|
|
189
|
+
}
|
|
Binary file
|
package/server/public/opener.js
CHANGED
|
@@ -9,13 +9,15 @@ document.addEventListener("click", async (e) => {
|
|
|
9
9
|
}
|
|
10
10
|
if (el) {
|
|
11
11
|
let filepath = el.getAttribute("data-filepath")
|
|
12
|
+
let command = el.getAttribute("data-command")
|
|
12
13
|
await fetch("/openfs", {
|
|
13
14
|
method: "post",
|
|
14
15
|
headers: {
|
|
15
16
|
"Content-Type": "application/json"
|
|
16
17
|
},
|
|
17
18
|
body: JSON.stringify({
|
|
18
|
-
path: filepath
|
|
19
|
+
path: filepath,
|
|
20
|
+
command
|
|
19
21
|
})
|
|
20
22
|
}).then((res) => {
|
|
21
23
|
return res.json()
|
|
Binary file
|
|
Binary file
|
package/server/public/style.css
CHANGED
|
@@ -1,3 +1,9 @@
|
|
|
1
|
+
@font-face {
|
|
2
|
+
font-family: 'SpaceMono';
|
|
3
|
+
src: url('/SpaceMono-Regular.ttf') format('truetype');
|
|
4
|
+
font-weight: normal;
|
|
5
|
+
font-style: normal;
|
|
6
|
+
}
|
|
1
7
|
:root {
|
|
2
8
|
--content-width: 900px;
|
|
3
9
|
|
|
@@ -53,6 +59,16 @@
|
|
|
53
59
|
*/
|
|
54
60
|
--dark-btn-color: whitesmoke;
|
|
55
61
|
}
|
|
62
|
+
.drawer {
|
|
63
|
+
max-height: 100000px;
|
|
64
|
+
overflow: hidden;
|
|
65
|
+
height: auto;
|
|
66
|
+
transition: max-height 3s ease-in-out;
|
|
67
|
+
}
|
|
68
|
+
.drawer.vertical-collapsed {
|
|
69
|
+
max-height: 0;
|
|
70
|
+
}
|
|
71
|
+
|
|
56
72
|
.type-tabs {
|
|
57
73
|
display: flex;
|
|
58
74
|
padding: 20px 20px 0;
|
|
@@ -87,7 +103,13 @@ body.dark .type-tabs {
|
|
|
87
103
|
height: 20px;
|
|
88
104
|
margin-right: 5px;
|
|
89
105
|
}
|
|
106
|
+
.navheader2 {
|
|
107
|
+
padding: 15px 10px;
|
|
108
|
+
background: white;
|
|
109
|
+
}
|
|
90
110
|
.navheader {
|
|
111
|
+
backdrop-filter: blur(16px);
|
|
112
|
+
|
|
91
113
|
padding: 15px 10px;
|
|
92
114
|
}
|
|
93
115
|
body.columns footer {
|
|
@@ -190,8 +212,10 @@ footer {
|
|
|
190
212
|
overflow: auto;
|
|
191
213
|
*/
|
|
192
214
|
box-sizing: border-box;
|
|
215
|
+
/*
|
|
193
216
|
color: var(--dark-color);
|
|
194
217
|
background: var(--dark-bg);
|
|
218
|
+
*/
|
|
195
219
|
/*
|
|
196
220
|
border-top: 1px solid rgba(255,255,255,0.05);
|
|
197
221
|
*/
|
|
@@ -207,7 +231,9 @@ footer b i {
|
|
|
207
231
|
}
|
|
208
232
|
footer b {
|
|
209
233
|
flex-shrink: 0;
|
|
234
|
+
/*
|
|
210
235
|
color: var(--dark-btn-color);
|
|
236
|
+
*/
|
|
211
237
|
margin-right: 10px;
|
|
212
238
|
font-weight: normal;
|
|
213
239
|
font-size: 11px;
|
|
@@ -551,6 +577,7 @@ body.columns main #editor {
|
|
|
551
577
|
height: 100% !important;
|
|
552
578
|
}
|
|
553
579
|
#terminal {
|
|
580
|
+
|
|
554
581
|
height: 100%;
|
|
555
582
|
/*
|
|
556
583
|
overflow: auto;
|
|
@@ -595,9 +622,12 @@ body.columns .containers {
|
|
|
595
622
|
height: 100%;
|
|
596
623
|
}
|
|
597
624
|
.terminal-container {
|
|
625
|
+
background: white;
|
|
598
626
|
flex-grow: 1;
|
|
599
627
|
position: relative;
|
|
628
|
+
/*
|
|
600
629
|
background: var(--dark-bg);
|
|
630
|
+
*/
|
|
601
631
|
overflow: auto;
|
|
602
632
|
}
|
|
603
633
|
.terminal-container #terminal-resize {
|
|
@@ -675,10 +705,16 @@ body.columns .containers {
|
|
|
675
705
|
margin: 0 auto;
|
|
676
706
|
}
|
|
677
707
|
*/
|
|
708
|
+
.xterm-rows {
|
|
709
|
+
font-family: "Space Mono", monospace !important;
|
|
710
|
+
font-weight: 400 !important;
|
|
711
|
+
font-style: normal !important;
|
|
712
|
+
|
|
713
|
+
}
|
|
678
714
|
.xterm {
|
|
679
|
-
padding: 10px 20px !important;
|
|
680
|
-
/*
|
|
681
715
|
padding: 0 20px !important;
|
|
716
|
+
/*
|
|
717
|
+
padding: 10px 20px !important;
|
|
682
718
|
*/
|
|
683
719
|
cursor: pointer;
|
|
684
720
|
overflow: auto;
|
|
@@ -691,15 +727,17 @@ body.columns .containers {
|
|
|
691
727
|
.panels > div {
|
|
692
728
|
width: 50%;
|
|
693
729
|
}
|
|
730
|
+
/*
|
|
694
731
|
body.dark header {
|
|
695
732
|
background: var(--dark-nav-bg);
|
|
696
733
|
}
|
|
734
|
+
*/
|
|
697
735
|
header {
|
|
698
|
-
background: var(--dark-nav-bg);
|
|
699
736
|
/*
|
|
737
|
+
background: var(--dark-nav-bg);
|
|
700
738
|
background: var(--light-nav-bg);
|
|
701
|
-
*/
|
|
702
739
|
background: white;
|
|
740
|
+
*/
|
|
703
741
|
position: sticky;
|
|
704
742
|
padding: 10px;
|
|
705
743
|
top: 0;
|
|
@@ -1005,13 +1043,19 @@ body.dark .line i {
|
|
|
1005
1043
|
text-align: center;
|
|
1006
1044
|
}
|
|
1007
1045
|
.line img {
|
|
1008
|
-
|
|
1009
|
-
|
|
1010
|
-
|
|
1046
|
+
width: 50px;
|
|
1047
|
+
height: 50px;
|
|
1048
|
+
/*
|
|
1049
|
+
padding: 10px;
|
|
1011
1050
|
*/
|
|
1051
|
+
padding: 4px;
|
|
1052
|
+
/*
|
|
1012
1053
|
width: 40px;
|
|
1013
1054
|
height: 40px;
|
|
1055
|
+
*/
|
|
1056
|
+
/*
|
|
1014
1057
|
border-radius: 10px;
|
|
1058
|
+
*/
|
|
1015
1059
|
}
|
|
1016
1060
|
body.dark .line .btn {
|
|
1017
1061
|
color: var(--dark-btn-color);
|
|
@@ -1172,7 +1216,7 @@ body.dark .swal2-popup {
|
|
|
1172
1216
|
color: var(--dark-btn-color);
|
|
1173
1217
|
}
|
|
1174
1218
|
.swal2-popup {
|
|
1175
|
-
border-radius:
|
|
1219
|
+
border-radius: 0px !important;
|
|
1176
1220
|
box-sizing: border-box;
|
|
1177
1221
|
}
|
|
1178
1222
|
.swal2-html-container a {
|
|
@@ -1331,6 +1375,9 @@ body.dark .swal2-styled.swal2-confirm{
|
|
|
1331
1375
|
font-weight: bold;
|
|
1332
1376
|
border: none;
|
|
1333
1377
|
}
|
|
1378
|
+
.swal2-input:focus, .swal2-file:focus, .swal2-textarea:focus {
|
|
1379
|
+
box-shadow: none !important;
|
|
1380
|
+
}
|
|
1334
1381
|
.swal2-input {
|
|
1335
1382
|
margin: 0 !important;
|
|
1336
1383
|
width: 100% !important;
|
|
@@ -1484,6 +1531,16 @@ b {
|
|
|
1484
1531
|
.opener.btn {
|
|
1485
1532
|
background: royalblue;
|
|
1486
1533
|
}
|
|
1534
|
+
.field-row {
|
|
1535
|
+
display: flex;
|
|
1536
|
+
align-items: center;
|
|
1537
|
+
}
|
|
1538
|
+
.folder-row .field-row label {
|
|
1539
|
+
font-size: 14px;
|
|
1540
|
+
flex-shrink: 0;
|
|
1541
|
+
padding: 0 5px 0 0;
|
|
1542
|
+
display: block;
|
|
1543
|
+
}
|
|
1487
1544
|
body.dark #new-window {
|
|
1488
1545
|
color: var(--dark-btn-color);
|
|
1489
1546
|
}
|
|
@@ -1591,15 +1648,27 @@ nav.error-message {
|
|
|
1591
1648
|
color: rgba(0,0,0,0.7);
|
|
1592
1649
|
font-weight: bold;
|
|
1593
1650
|
}
|
|
1651
|
+
/*
|
|
1594
1652
|
.not-running-apps, .running-apps {
|
|
1595
1653
|
background: rgba(0,0,100,0.04);
|
|
1596
1654
|
}
|
|
1597
1655
|
body.dark .not-running-apps, body.dark .running-apps {
|
|
1598
1656
|
background: rgba(255,255,255,0.03);
|
|
1599
1657
|
}
|
|
1658
|
+
*/
|
|
1659
|
+
/*
|
|
1660
|
+
.running-apps .line .title {
|
|
1661
|
+
color: #82bc09;
|
|
1662
|
+
}
|
|
1663
|
+
*/
|
|
1600
1664
|
.running-apps .line img {
|
|
1601
|
-
|
|
1665
|
+
background: #82bc09;
|
|
1666
|
+
/*
|
|
1667
|
+
border: 3px solid #8fd400;
|
|
1668
|
+
*/
|
|
1669
|
+
/*
|
|
1602
1670
|
border-radius: 5px;
|
|
1671
|
+
*/
|
|
1603
1672
|
}
|
|
1604
1673
|
/*
|
|
1605
1674
|
.running-apps .line.align-top h3 .col .title {
|
|
@@ -1701,6 +1770,16 @@ footer.status {
|
|
|
1701
1770
|
text-transform: uppercase;
|
|
1702
1771
|
}
|
|
1703
1772
|
|
|
1773
|
+
#fsmenu {
|
|
1774
|
+
/*
|
|
1775
|
+
background: rgba(0,0,100,0.04);
|
|
1776
|
+
*/
|
|
1777
|
+
display: flex;
|
|
1778
|
+
padding: 10px;
|
|
1779
|
+
/*
|
|
1780
|
+
padding: 20px 20px 0;
|
|
1781
|
+
*/
|
|
1782
|
+
}
|
|
1704
1783
|
mark{
|
|
1705
1784
|
background: firebrick;
|
|
1706
1785
|
color: white;
|
|
@@ -1714,3 +1793,46 @@ mark{
|
|
|
1714
1793
|
color: royalblue !important;
|
|
1715
1794
|
cursor: pointer;
|
|
1716
1795
|
}
|
|
1796
|
+
|
|
1797
|
+
.filepond--image-preview-wrapper {
|
|
1798
|
+
border-radius: 0 !important;
|
|
1799
|
+
}
|
|
1800
|
+
|
|
1801
|
+
.filepond-wrapper {
|
|
1802
|
+
/*
|
|
1803
|
+
position: relative;
|
|
1804
|
+
display: inline-block;
|
|
1805
|
+
*/
|
|
1806
|
+
display: flex;
|
|
1807
|
+
}
|
|
1808
|
+
.filepond-wrapper .folder-rows {
|
|
1809
|
+
flex-grow: 1;
|
|
1810
|
+
}
|
|
1811
|
+
.filepond-wrapper .avatar-field {
|
|
1812
|
+
width: 150px;
|
|
1813
|
+
margin-right: 15px;
|
|
1814
|
+
margin-top: 10px;
|
|
1815
|
+
}
|
|
1816
|
+
.folder-row {
|
|
1817
|
+
text-align: left;
|
|
1818
|
+
padding-bottom: 10px;
|
|
1819
|
+
}
|
|
1820
|
+
.folder-row label {
|
|
1821
|
+
padding: 5px 0;
|
|
1822
|
+
display: block;
|
|
1823
|
+
font-size: 14px;
|
|
1824
|
+
}
|
|
1825
|
+
.folderpath {
|
|
1826
|
+
opacity: 0.5;
|
|
1827
|
+
}
|
|
1828
|
+
.swal2-modal .filepond--root button {
|
|
1829
|
+
cursor: pointer;
|
|
1830
|
+
background: black !important;
|
|
1831
|
+
color: white !important;
|
|
1832
|
+
border: 2px solid !important;
|
|
1833
|
+
/*
|
|
1834
|
+
background: unset !important;
|
|
1835
|
+
*/
|
|
1836
|
+
padding: unset !important;
|
|
1837
|
+
font-size: unset !important;
|
|
1838
|
+
}
|
package/server/socket.js
CHANGED
|
@@ -1,8 +1,10 @@
|
|
|
1
1
|
const WebSocket = require('ws');
|
|
2
|
+
const Util = require("../kernel/util")
|
|
2
3
|
class Socket {
|
|
3
4
|
constructor(parent) {
|
|
4
5
|
this.buffer = {}
|
|
5
6
|
this.connected = {}
|
|
7
|
+
this.active_shell = {}
|
|
6
8
|
this.parent = parent
|
|
7
9
|
this.server = parent.server
|
|
8
10
|
// this.kernel = parent.kernel
|
|
@@ -17,6 +19,7 @@ class Socket {
|
|
|
17
19
|
});
|
|
18
20
|
ws.on('message', async (message) => {
|
|
19
21
|
const req = JSON.parse(message);
|
|
22
|
+
console.log({ req })
|
|
20
23
|
if (req.response) {
|
|
21
24
|
this.parent.kernel.api.respond(req)
|
|
22
25
|
} else {
|
|
@@ -25,49 +28,109 @@ class Socket {
|
|
|
25
28
|
// look for repos that match
|
|
26
29
|
|
|
27
30
|
if (req.uri) {
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
}
|
|
45
|
-
} else if (req.stop) {
|
|
46
|
-
this.parent.kernel.api.stop({ params: req })
|
|
31
|
+
console.log("## 1")
|
|
32
|
+
if (req.mode === "open") {
|
|
33
|
+
console.log("## 2")
|
|
34
|
+
// get the default script and respond
|
|
35
|
+
let id = this.parent.kernel.api.filePath(req.uri)
|
|
36
|
+
try {
|
|
37
|
+
console.log("## 3")
|
|
38
|
+
let default_url = await this.parent.kernel.api.get_default(id)
|
|
39
|
+
console.log({ id, default_url })
|
|
40
|
+
ws.send(JSON.stringify({
|
|
41
|
+
data: {
|
|
42
|
+
uri: default_url
|
|
43
|
+
}
|
|
44
|
+
}))
|
|
45
|
+
} catch (e) {
|
|
46
|
+
console.log(e)
|
|
47
|
+
}
|
|
47
48
|
} else {
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
if (req.
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
49
|
+
console.log("## 4")
|
|
50
|
+
console.log("REQ.URI", req.uri)
|
|
51
|
+
if (req.uri.startsWith("http")) {
|
|
52
|
+
console.log("## 5")
|
|
53
|
+
// open
|
|
54
|
+
Util.openfs(req.uri, { mode: "open" })
|
|
55
|
+
} else {
|
|
56
|
+
console.log("## 6")
|
|
57
|
+
console.log("sdfsfsfsdfsd>>>>>>>>>>>>>>>>>>>>>>>>>>>")
|
|
58
|
+
/******************************************************************
|
|
59
|
+
*
|
|
60
|
+
* req.uri is ALWAYS either of the two:
|
|
61
|
+
* 1. ~/...
|
|
62
|
+
* 2. https://github.com/...
|
|
63
|
+
*
|
|
64
|
+
* Need to turn it into absolute file path before subscribing
|
|
65
|
+
*
|
|
66
|
+
******************************************************************/
|
|
67
|
+
|
|
68
|
+
// req.uri is always http or absolute path
|
|
69
|
+
let id = this.parent.kernel.api.filePath(req.uri)
|
|
70
|
+
|
|
71
|
+
if (req.status) {
|
|
72
|
+
console.log("## 7")
|
|
73
|
+
ws.send(JSON.stringify({
|
|
74
|
+
data: this.parent.kernel.api.running[id] ? true : false
|
|
75
|
+
}))
|
|
76
|
+
} else if (req.stop) {
|
|
77
|
+
console.log("## 8")
|
|
78
|
+
console.log(">>>>>>>>>>>>>>>>>>>>>")
|
|
79
|
+
this.parent.kernel.api.stop({ params: req })
|
|
80
|
+
} else {
|
|
81
|
+
console.log("## 9")
|
|
82
|
+
let buf = this.buffer[id]
|
|
83
|
+
let sh = this.active_shell[id]
|
|
84
|
+
this.subscribe(ws, id, buf, sh)
|
|
85
|
+
if (req.mode !== "listen") {
|
|
86
|
+
console.log("## 10")
|
|
87
|
+
// Run only if currently not running
|
|
88
|
+
if (!this.parent.kernel.api.running[id]) {
|
|
89
|
+
console.log("## 11")
|
|
90
|
+
|
|
91
|
+
// clear the log first
|
|
92
|
+
|
|
93
|
+
await this.parent.kernel.clearLog(id)
|
|
94
|
+
|
|
95
|
+
|
|
96
|
+
this.parent.kernel.api.process(req)
|
|
97
|
+
}
|
|
98
|
+
}
|
|
60
99
|
}
|
|
61
100
|
}
|
|
62
|
-
}
|
|
63
101
|
|
|
102
|
+
}
|
|
64
103
|
} else if (req.method) {
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
this.
|
|
104
|
+
if (req.id) {
|
|
105
|
+
console.log("req.id", req.id)
|
|
106
|
+
let buf = this.buffer[req.id]
|
|
107
|
+
let sh = this.active_shell[req.id]
|
|
108
|
+
console.log({ buf, sh })
|
|
109
|
+
this.subscribe(ws, req.id, buf, sh)
|
|
110
|
+
console.log("Process 2")
|
|
111
|
+
if (!sh) {
|
|
112
|
+
//if (req.mode !== "listen") {
|
|
113
|
+
console.log("Process 3")
|
|
114
|
+
this.parent.kernel.api.process(req)
|
|
115
|
+
console.log("Process 4")
|
|
116
|
+
}
|
|
117
|
+
} else {
|
|
118
|
+
console.log("Process 1")
|
|
119
|
+
this.subscribe(ws, req.method)
|
|
120
|
+
console.log("Process 2")
|
|
121
|
+
if (req.mode !== "listen") {
|
|
122
|
+
console.log("Process 3")
|
|
123
|
+
this.parent.kernel.api.process(req)
|
|
124
|
+
console.log("Process 4")
|
|
125
|
+
}
|
|
68
126
|
}
|
|
69
127
|
} else if (req.emit) {
|
|
70
128
|
this.parent.kernel.shell.emit(req)
|
|
129
|
+
} else if (req.key && req.id) {
|
|
130
|
+
this.parent.kernel.shell.emit({
|
|
131
|
+
id: req.id,
|
|
132
|
+
emit: req.key
|
|
133
|
+
})
|
|
71
134
|
}
|
|
72
135
|
}
|
|
73
136
|
|
|
@@ -78,11 +141,16 @@ class Socket {
|
|
|
78
141
|
headers.push('Access-Control-Allow-Headers: Origin, X-Requested-With, Content-Type, Accept');
|
|
79
142
|
});
|
|
80
143
|
}
|
|
81
|
-
subscribe(ws, id) {
|
|
144
|
+
subscribe(ws, id, buf, sh) {
|
|
82
145
|
|
|
83
146
|
if (this.parent.kernel.api.running[id]) {
|
|
84
147
|
ws.send(JSON.stringify({
|
|
85
|
-
type: "connect"
|
|
148
|
+
type: "connect",
|
|
149
|
+
data: {
|
|
150
|
+
id,
|
|
151
|
+
state: buf,
|
|
152
|
+
shell: sh
|
|
153
|
+
}
|
|
86
154
|
}))
|
|
87
155
|
}
|
|
88
156
|
|
|
@@ -120,6 +188,15 @@ class Socket {
|
|
|
120
188
|
});
|
|
121
189
|
}
|
|
122
190
|
|
|
191
|
+
if (!this.buffer[id]) {
|
|
192
|
+
this.buffer[id] = ""
|
|
193
|
+
}
|
|
194
|
+
if (e.data && e.data.raw) this.buffer[id] += e.data.raw
|
|
195
|
+
|
|
196
|
+
if (e.data && e.data.shell_id) {
|
|
197
|
+
this.active_shell[id] = e.data.shell_id
|
|
198
|
+
}
|
|
199
|
+
|
|
123
200
|
// send to caller session
|
|
124
201
|
if (e.caller) {
|
|
125
202
|
let caller
|
|
@@ -148,6 +225,15 @@ class Socket {
|
|
|
148
225
|
}
|
|
149
226
|
});
|
|
150
227
|
}
|
|
228
|
+
|
|
229
|
+
if (!this.buffer[caller]) {
|
|
230
|
+
this.buffer[caller] = ""
|
|
231
|
+
}
|
|
232
|
+
if (e.data.raw) this.buffer[caller] += e.data.raw
|
|
233
|
+
|
|
234
|
+
if (e.data && e.data.shell_id) {
|
|
235
|
+
this.active_shell[caller] = e.data.shell_id
|
|
236
|
+
}
|
|
151
237
|
}
|
|
152
238
|
}
|
|
153
239
|
}
|