pinokiod 7.5.26 → 7.5.28
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/index.js +2 -5
- package/kernel/info.js +20 -0
- package/kernel/shell.js +2 -54
- package/kernel/sysinfo.js +2 -2
- package/package.json +1 -1
- package/server/public/common.js +42 -0
- package/server/public/style.css +142 -14
- package/server/public/task-launcher.css +11 -0
- package/server/views/app.ejs +173 -15
- package/server/views/app_search_test.ejs +3 -0
- package/server/views/connect/x.ejs +3 -0
- package/server/views/container.ejs +3 -0
- package/server/views/download.ejs +3 -0
- package/server/views/explore.ejs +3 -0
- package/server/views/form.ejs +3 -0
- package/server/views/frame.ejs +3 -0
- package/server/views/help.ejs +3 -0
- package/server/views/index.ejs +21 -66
- package/server/views/index2.ejs +3 -0
- package/server/views/init/index.ejs +3 -0
- package/server/views/mini.ejs +3 -0
- package/server/views/net.ejs +3 -0
- package/server/views/network.ejs +3 -0
- package/server/views/network2.ejs +3 -0
- package/server/views/old_network.ejs +3 -0
- package/server/views/partials/app_navheader.ejs +3 -0
- package/server/views/partials/home_action_modal.ejs +18 -31
- package/server/views/partials/main_sidebar.ejs +101 -4
- package/server/views/prototype/index.ejs +3 -0
- package/server/views/review.ejs +3 -0
- package/server/views/screenshots.ejs +3 -0
- package/server/views/settings.ejs +3 -0
- package/server/views/setup_home.ejs +3 -0
- package/server/views/terminal.ejs +3 -0
- package/server/views/terminals.ejs +3 -0
- package/test/info-ready.test.js +88 -0
- package/test/launch-settings-ui.test.js +3 -0
- package/test/shell-cleaned-log.test.js +66 -0
|
@@ -35,6 +35,7 @@
|
|
|
35
35
|
<i class="fa-solid fa-bars" aria-hidden="true"></i>
|
|
36
36
|
</button>
|
|
37
37
|
<button type="button" class="main-sidebar-mobile-backdrop" data-main-sidebar-backdrop aria-label="Close navigation" hidden></button>
|
|
38
|
+
<button type="button" class="main-sidebar-peek-trigger" data-main-sidebar-peek-trigger aria-label="Show navigation" aria-controls="main-sidebar" aria-expanded="false"></button>
|
|
38
39
|
<aside class="main-sidebar" id="main-sidebar" aria-label="Primary navigation">
|
|
39
40
|
<nav class="main-sidebar-nav" aria-label="Pinokio navigation">
|
|
40
41
|
<div class='main-sidebar-section main-sidebar-section-actions' aria-label="Actions">
|
|
@@ -155,6 +156,7 @@
|
|
|
155
156
|
|
|
156
157
|
const headerToggle = document.getElementById("minimize-header");
|
|
157
158
|
const sidebar = document.getElementById("main-sidebar");
|
|
159
|
+
const peekTrigger = document.querySelector("[data-main-sidebar-peek-trigger]");
|
|
158
160
|
if (body && sidebar && headerToggle && !headerToggle.dataset.mainSidebarHeaderToggle) {
|
|
159
161
|
headerToggle.dataset.mainSidebarHeaderToggle = "true";
|
|
160
162
|
headerToggle.classList.add("sidebar-toggle", "main-sidebar-header-toggle");
|
|
@@ -182,17 +184,66 @@
|
|
|
182
184
|
}
|
|
183
185
|
};
|
|
184
186
|
|
|
185
|
-
const
|
|
187
|
+
const desktopPeekMq = window.matchMedia("(min-width: 769px) and (hover: hover) and (pointer: fine)");
|
|
188
|
+
const storageKey = "pinokio.main-sidebar-collapsed";
|
|
189
|
+
let peekCloseTimer = 0;
|
|
190
|
+
|
|
191
|
+
const isCollapsed = () => body.classList.contains("main-sidebar-collapsed");
|
|
192
|
+
const isPeeking = () => body.classList.contains("main-sidebar-peeking");
|
|
193
|
+
const syncSidebarVisibility = () => {
|
|
194
|
+
const peeking = isPeeking();
|
|
195
|
+
sidebar.setAttribute("aria-hidden", isCollapsed() && !peeking ? "true" : "false");
|
|
196
|
+
if (peekTrigger) {
|
|
197
|
+
peekTrigger.setAttribute("aria-expanded", peeking ? "true" : "false");
|
|
198
|
+
}
|
|
199
|
+
};
|
|
200
|
+
const canPeek = () => desktopPeekMq.matches && isCollapsed() && !body.classList.contains("main-sidebar-mobile-open");
|
|
201
|
+
const setPeeking = (peeking) => {
|
|
202
|
+
const next = !!peeking && canPeek();
|
|
203
|
+
window.clearTimeout(peekCloseTimer);
|
|
204
|
+
body.classList.toggle("main-sidebar-peeking", next);
|
|
205
|
+
syncSidebarVisibility();
|
|
206
|
+
};
|
|
207
|
+
const shouldKeepPeekOpen = () => {
|
|
208
|
+
const active = document.activeElement;
|
|
209
|
+
return (
|
|
210
|
+
(peekTrigger && peekTrigger.matches(":hover")) ||
|
|
211
|
+
sidebar.matches(":hover") ||
|
|
212
|
+
(peekTrigger && active === peekTrigger) ||
|
|
213
|
+
(active instanceof Node && sidebar.contains(active))
|
|
214
|
+
);
|
|
215
|
+
};
|
|
216
|
+
const closePeekSoon = () => {
|
|
217
|
+
window.clearTimeout(peekCloseTimer);
|
|
218
|
+
peekCloseTimer = window.setTimeout(() => {
|
|
219
|
+
if (shouldKeepPeekOpen()) return;
|
|
220
|
+
setPeeking(false);
|
|
221
|
+
}, 120);
|
|
222
|
+
};
|
|
223
|
+
|
|
224
|
+
const setCollapsed = (collapsed, options = {}) => {
|
|
186
225
|
const next = !!collapsed;
|
|
226
|
+
if (!next) {
|
|
227
|
+
body.classList.remove("main-sidebar-peeking");
|
|
228
|
+
}
|
|
187
229
|
body.classList.toggle("main-sidebar-collapsed", next);
|
|
188
|
-
|
|
230
|
+
syncSidebarVisibility();
|
|
189
231
|
updateToggle(next);
|
|
232
|
+
if (options.persist !== false) {
|
|
233
|
+
try {
|
|
234
|
+
window.localStorage.setItem(storageKey, next ? "1" : "0");
|
|
235
|
+
} catch (_) {}
|
|
236
|
+
}
|
|
190
237
|
document.dispatchEvent(new CustomEvent("pinokio:sidebar-state", {
|
|
191
238
|
detail: { collapsed: next, source: "main-sidebar" }
|
|
192
239
|
}));
|
|
193
240
|
};
|
|
194
241
|
|
|
195
|
-
|
|
242
|
+
let initialCollapsed = false;
|
|
243
|
+
try {
|
|
244
|
+
initialCollapsed = window.localStorage.getItem(storageKey) === "1";
|
|
245
|
+
} catch (_) {}
|
|
246
|
+
setCollapsed(initialCollapsed, { persist: false });
|
|
196
247
|
requestAnimationFrame(() => {
|
|
197
248
|
body.classList.add("main-sidebar-motion-ready");
|
|
198
249
|
});
|
|
@@ -202,9 +253,55 @@
|
|
|
202
253
|
setCollapsed(!body.classList.contains("main-sidebar-collapsed"));
|
|
203
254
|
});
|
|
204
255
|
|
|
256
|
+
if (peekTrigger) {
|
|
257
|
+
peekTrigger.addEventListener("pointerenter", () => setPeeking(true));
|
|
258
|
+
peekTrigger.addEventListener("focus", () => setPeeking(true));
|
|
259
|
+
peekTrigger.addEventListener("click", () => setPeeking(true));
|
|
260
|
+
peekTrigger.addEventListener("pointerleave", closePeekSoon);
|
|
261
|
+
peekTrigger.addEventListener("blur", closePeekSoon);
|
|
262
|
+
sidebar.addEventListener("pointerenter", () => {
|
|
263
|
+
if (isPeeking()) {
|
|
264
|
+
window.clearTimeout(peekCloseTimer);
|
|
265
|
+
}
|
|
266
|
+
});
|
|
267
|
+
sidebar.addEventListener("focusin", () => {
|
|
268
|
+
if (isPeeking()) {
|
|
269
|
+
window.clearTimeout(peekCloseTimer);
|
|
270
|
+
}
|
|
271
|
+
});
|
|
272
|
+
sidebar.addEventListener("pointerleave", closePeekSoon);
|
|
273
|
+
sidebar.addEventListener("focusout", closePeekSoon);
|
|
274
|
+
document.addEventListener("pointerdown", (event) => {
|
|
275
|
+
if (!isPeeking()) return;
|
|
276
|
+
const target = event.target;
|
|
277
|
+
if (target instanceof Node && (sidebar.contains(target) || peekTrigger.contains(target))) return;
|
|
278
|
+
setPeeking(false);
|
|
279
|
+
});
|
|
280
|
+
document.addEventListener("keydown", (event) => {
|
|
281
|
+
if (event.key === "Escape" && isPeeking()) {
|
|
282
|
+
setPeeking(false);
|
|
283
|
+
if (typeof peekTrigger.focus === "function") {
|
|
284
|
+
peekTrigger.focus();
|
|
285
|
+
}
|
|
286
|
+
}
|
|
287
|
+
});
|
|
288
|
+
const handlePeekMediaChange = () => {
|
|
289
|
+
if (!desktopPeekMq.matches) {
|
|
290
|
+
setPeeking(false);
|
|
291
|
+
}
|
|
292
|
+
};
|
|
293
|
+
if (typeof desktopPeekMq.addEventListener === "function") {
|
|
294
|
+
desktopPeekMq.addEventListener("change", handlePeekMediaChange);
|
|
295
|
+
} else if (typeof desktopPeekMq.addListener === "function") {
|
|
296
|
+
desktopPeekMq.addListener(handlePeekMediaChange);
|
|
297
|
+
}
|
|
298
|
+
}
|
|
299
|
+
|
|
205
300
|
window.PinokioMainSidebar = {
|
|
206
301
|
setCollapsed,
|
|
207
|
-
|
|
302
|
+
setPeeking,
|
|
303
|
+
isCollapsed,
|
|
304
|
+
isPeeking
|
|
208
305
|
};
|
|
209
306
|
}
|
|
210
307
|
|
|
@@ -1010,6 +1010,9 @@ body.dark .appcanvas {
|
|
|
1010
1010
|
<button class='btn2' id='minimize-header' data-tippy-content="fullscreen" title='fullscreen'>
|
|
1011
1011
|
<div><i class="fa-solid fa-expand"></i></div>
|
|
1012
1012
|
</button>
|
|
1013
|
+
<a class='btn2 pinokio-explore-nav-button' href="/home?mode=explore" data-pinokio-explore-nav="true" data-tippy-content="Explore" title="Explore" aria-label="Explore">
|
|
1014
|
+
<div><i class="fa-solid fa-globe" aria-hidden="true"></i></div>
|
|
1015
|
+
</a>
|
|
1013
1016
|
<button class='btn2' id='back' data-tippy-content="back"><div><i class="fa-solid fa-chevron-left"></i></div></button>
|
|
1014
1017
|
<button class='btn2' id='forward' data-tippy-content="forward"><div><i class="fa-solid fa-chevron-right"></i></div></button>
|
|
1015
1018
|
<button class='btn2' id='refresh-page' data-tippy-content="refresh"><div><i class="fa-solid fa-rotate-right"></i></div></button>
|
package/server/views/review.ejs
CHANGED
|
@@ -941,6 +941,9 @@ body.dark .top-menu .btn2.selected {
|
|
|
941
941
|
<button class='btn2' id='minimize-header' data-tippy-content="fullscreen" title='fullscreen'>
|
|
942
942
|
<div><i class="fa-solid fa-expand"></i></div>
|
|
943
943
|
</button>
|
|
944
|
+
<a class='btn2 pinokio-explore-nav-button' href="/home?mode=explore" data-pinokio-explore-nav="true" data-tippy-content="Explore" title="Explore" aria-label="Explore">
|
|
945
|
+
<div><i class="fa-solid fa-globe" aria-hidden="true"></i></div>
|
|
946
|
+
</a>
|
|
944
947
|
<button class='btn2' id='back' data-tippy-content="back"><div><i class="fa-solid fa-chevron-left"></i></div></button>
|
|
945
948
|
<button class='btn2' id='forward' data-tippy-content="forward"><div><i class="fa-solid fa-chevron-right"></i></div></button>
|
|
946
949
|
<button class='btn2' id='refresh-page' data-tippy-content="refresh"><div><i class="fa-solid fa-rotate-right"></i></div></button>
|
|
@@ -873,6 +873,9 @@ document.addEventListener('DOMContentLoaded', function() {
|
|
|
873
873
|
<button class='btn2' id='minimize-header' data-tippy-content="fullscreen" title='fullscreen'>
|
|
874
874
|
<div><i class="fa-solid fa-expand"></i></div>
|
|
875
875
|
</button>
|
|
876
|
+
<a class='btn2 pinokio-explore-nav-button' href="/home?mode=explore" data-pinokio-explore-nav="true" data-tippy-content="Explore" title="Explore" aria-label="Explore">
|
|
877
|
+
<div><i class="fa-solid fa-globe" aria-hidden="true"></i></div>
|
|
878
|
+
</a>
|
|
876
879
|
<button class='btn2' id='back' data-tippy-content="back"><div><i class="fa-solid fa-chevron-left"></i></div></button>
|
|
877
880
|
<button class='btn2' id='forward' data-tippy-content="forward"><div><i class="fa-solid fa-chevron-right"></i></div></button>
|
|
878
881
|
<button class='btn2' id='refresh-page' data-tippy-content="refresh"><div><i class="fa-solid fa-rotate-right"></i></div></button>
|
|
@@ -1011,6 +1011,9 @@ document.addEventListener('DOMContentLoaded', function() {
|
|
|
1011
1011
|
<button class='btn2' id='minimize-header' data-tippy-content="fullscreen" title='fullscreen'>
|
|
1012
1012
|
<div><i class="fa-solid fa-expand"></i></div>
|
|
1013
1013
|
</button>
|
|
1014
|
+
<a class='btn2 pinokio-explore-nav-button' href="/home?mode=explore" data-pinokio-explore-nav="true" data-tippy-content="Explore" title="Explore" aria-label="Explore">
|
|
1015
|
+
<div><i class="fa-solid fa-globe" aria-hidden="true"></i></div>
|
|
1016
|
+
</a>
|
|
1014
1017
|
<button class='btn2' id='back' data-tippy-content="back"><div><i class="fa-solid fa-chevron-left"></i></div></button>
|
|
1015
1018
|
<button class='btn2' id='forward' data-tippy-content="forward"><div><i class="fa-solid fa-chevron-right"></i></div></button>
|
|
1016
1019
|
<button class='btn2' id='refresh-page' data-tippy-content="refresh"><div><i class="fa-solid fa-rotate-right"></i></div></button>
|
|
@@ -155,6 +155,9 @@ body.dark .card {
|
|
|
155
155
|
<button class='btn2' id='minimize-header' data-tippy-content="fullscreen" title='fullscreen'>
|
|
156
156
|
<div><i class="fa-solid fa-expand"></i></div>
|
|
157
157
|
</button>
|
|
158
|
+
<a class='btn2 pinokio-explore-nav-button' href="/home?mode=explore" data-pinokio-explore-nav="true" data-tippy-content="Explore" title="Explore" aria-label="Explore">
|
|
159
|
+
<div><i class="fa-solid fa-globe" aria-hidden="true"></i></div>
|
|
160
|
+
</a>
|
|
158
161
|
<button class='btn2' id='screenshot' data-tippy-content="screen capture"><i class="fa-solid fa-camera"></i></button>
|
|
159
162
|
<button class='btn2' id='inspector' data-tippy-content="X-ray mode"><i class="fa-solid fa-eye"></i></button>
|
|
160
163
|
<div class='flexible'></div>
|
|
@@ -3403,6 +3403,9 @@ const reloadMemory = async () => {
|
|
|
3403
3403
|
<button class="btn2" id="minimize-header" data-tippy-content="fullscreen" title="fullscreen">
|
|
3404
3404
|
<div><i class="fa-solid fa-expand"></i></div>
|
|
3405
3405
|
</button>
|
|
3406
|
+
<a class='btn2 pinokio-explore-nav-button' href="/home?mode=explore" data-pinokio-explore-nav="true" data-tippy-content="Explore" title="Explore" aria-label="Explore">
|
|
3407
|
+
<div><i class="fa-solid fa-globe" aria-hidden="true"></i></div>
|
|
3408
|
+
</a>
|
|
3406
3409
|
<button class="btn2" id="back" data-tippy-content="back"><div><i class="fa-solid fa-chevron-left"></i></div></button>
|
|
3407
3410
|
<button class="btn2" id="forward" data-tippy-content="forward"><div><i class="fa-solid fa-chevron-right"></i></div></button>
|
|
3408
3411
|
<button class="btn2" id="refresh-page" data-tippy-content="refresh"><div><i class="fa-solid fa-rotate-right"></i></div></button>
|
|
@@ -4554,6 +4554,9 @@ body.dark .pinokio-git-commit-item {
|
|
|
4554
4554
|
<button class="btn2" id="minimize-header" data-tippy-content="fullscreen" title="fullscreen">
|
|
4555
4555
|
<div><i class="fa-solid fa-expand"></i></div>
|
|
4556
4556
|
</button>
|
|
4557
|
+
<a class='btn2 pinokio-explore-nav-button' href="/home?mode=explore" data-pinokio-explore-nav="true" data-tippy-content="Explore" title="Explore" aria-label="Explore">
|
|
4558
|
+
<div><i class="fa-solid fa-globe" aria-hidden="true"></i></div>
|
|
4559
|
+
</a>
|
|
4557
4560
|
<button class="btn2" id="back" data-tippy-content="back"><div><i class="fa-solid fa-chevron-left"></i></div></button>
|
|
4558
4561
|
<button class="btn2" id="forward" data-tippy-content="forward"><div><i class="fa-solid fa-chevron-right"></i></div></button>
|
|
4559
4562
|
<button class="btn2" id="refresh-page" data-tippy-content="refresh"><div><i class="fa-solid fa-rotate-right"></i></div></button>
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
const assert = require("node:assert/strict")
|
|
2
|
+
const fs = require("node:fs")
|
|
3
|
+
const os = require("node:os")
|
|
4
|
+
const path = require("node:path")
|
|
5
|
+
const test = require("node:test")
|
|
6
|
+
|
|
7
|
+
const Info = require("../kernel/info")
|
|
8
|
+
|
|
9
|
+
const createInfo = ({ callerFile, scriptResolve, readyPaths = [] }) => {
|
|
10
|
+
const ready = new Set(readyPaths.map((item) => path.resolve(item)))
|
|
11
|
+
const info = new Info({
|
|
12
|
+
script: {
|
|
13
|
+
resolve: scriptResolve || (() => false)
|
|
14
|
+
},
|
|
15
|
+
isScriptReady: (scriptPath) => ready.has(path.resolve(scriptPath))
|
|
16
|
+
})
|
|
17
|
+
info.caller = () => callerFile
|
|
18
|
+
return info
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
test("info.ready checks caller-relative script paths first", (t) => {
|
|
22
|
+
const root = fs.mkdtempSync(path.join(os.tmpdir(), "pinokio-info-ready-"))
|
|
23
|
+
t.after(() => fs.rmSync(root, { recursive: true, force: true }))
|
|
24
|
+
|
|
25
|
+
const appRoot = path.join(root, "app")
|
|
26
|
+
const callerFile = path.join(appRoot, "pinokio.js")
|
|
27
|
+
const startScript = path.join(appRoot, "start.js")
|
|
28
|
+
fs.mkdirSync(appRoot, { recursive: true })
|
|
29
|
+
fs.writeFileSync(callerFile, "module.exports = {}")
|
|
30
|
+
fs.writeFileSync(startScript, "module.exports = {}")
|
|
31
|
+
|
|
32
|
+
let resolverCalls = 0
|
|
33
|
+
const info = createInfo({
|
|
34
|
+
callerFile,
|
|
35
|
+
scriptResolve: () => {
|
|
36
|
+
resolverCalls += 1
|
|
37
|
+
return false
|
|
38
|
+
},
|
|
39
|
+
readyPaths: [startScript]
|
|
40
|
+
})
|
|
41
|
+
|
|
42
|
+
assert.equal(info.ready("start.js"), true)
|
|
43
|
+
assert.equal(resolverCalls, 0)
|
|
44
|
+
})
|
|
45
|
+
|
|
46
|
+
test("info.ready falls back to Pinokio script URI resolution", (t) => {
|
|
47
|
+
const root = fs.mkdtempSync(path.join(os.tmpdir(), "pinokio-info-ready-"))
|
|
48
|
+
t.after(() => fs.rmSync(root, { recursive: true, force: true }))
|
|
49
|
+
|
|
50
|
+
const callerFile = path.join(root, "caller", "pinokio.js")
|
|
51
|
+
const remoteRoot = path.join(root, "api", "remote.git")
|
|
52
|
+
const remoteStart = path.join(remoteRoot, "start.js")
|
|
53
|
+
const remoteUri = "https://github.com/example/remote.git"
|
|
54
|
+
fs.mkdirSync(path.dirname(callerFile), { recursive: true })
|
|
55
|
+
fs.mkdirSync(remoteRoot, { recursive: true })
|
|
56
|
+
fs.writeFileSync(callerFile, "module.exports = {}")
|
|
57
|
+
fs.writeFileSync(remoteStart, "module.exports = {}")
|
|
58
|
+
|
|
59
|
+
const info = createInfo({
|
|
60
|
+
callerFile,
|
|
61
|
+
scriptResolve: (...args) => {
|
|
62
|
+
if (args[0] === remoteUri) {
|
|
63
|
+
return path.resolve(remoteRoot, ...args.slice(1))
|
|
64
|
+
}
|
|
65
|
+
return false
|
|
66
|
+
},
|
|
67
|
+
readyPaths: [remoteStart]
|
|
68
|
+
})
|
|
69
|
+
|
|
70
|
+
assert.equal(info.ready(remoteUri, "start.js"), true)
|
|
71
|
+
})
|
|
72
|
+
|
|
73
|
+
test("info.ready returns false when neither relative nor URI path is ready", (t) => {
|
|
74
|
+
const root = fs.mkdtempSync(path.join(os.tmpdir(), "pinokio-info-ready-"))
|
|
75
|
+
t.after(() => fs.rmSync(root, { recursive: true, force: true }))
|
|
76
|
+
|
|
77
|
+
const appRoot = path.join(root, "app")
|
|
78
|
+
const callerFile = path.join(appRoot, "pinokio.js")
|
|
79
|
+
fs.mkdirSync(appRoot, { recursive: true })
|
|
80
|
+
fs.writeFileSync(callerFile, "module.exports = {}")
|
|
81
|
+
|
|
82
|
+
const info = createInfo({
|
|
83
|
+
callerFile,
|
|
84
|
+
scriptResolve: () => false
|
|
85
|
+
})
|
|
86
|
+
|
|
87
|
+
assert.equal(info.ready("missing.js"), false)
|
|
88
|
+
})
|
|
@@ -369,6 +369,9 @@ test("static guard: open without launching is not wired to launch requirement st
|
|
|
369
369
|
|
|
370
370
|
assert.match(homeActionModal, /Open without launching/)
|
|
371
371
|
assert.match(homeActionModal, /class='home-mode-command home-browse' data-src='<%= item\.view_url %>'/)
|
|
372
|
+
assert.match(homeActionModal, /Open dev mode/)
|
|
373
|
+
assert.doesNotMatch(homeActionModal, /home-actions-tabs|home-actions-tab|role='tab'|role='tabpanel'/)
|
|
374
|
+
assert.doesNotMatch(homeActionModal, /Open files mode/)
|
|
372
375
|
assert.doesNotMatch(homeActionModal, /launch.requirements|data-launch-requirements|frame-link/)
|
|
373
376
|
assert.match(homeView, /if \(target\) \{[\s\S]*window\.PinokioHomeGuardNavigate\(src\)[\s\S]*location\.href = src/)
|
|
374
377
|
assert.match(statusClient, /const status = data && data\.ok \? data\.status : null/)
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
const assert = require('node:assert/strict')
|
|
2
|
+
const fs = require('node:fs/promises')
|
|
3
|
+
const os = require('node:os')
|
|
4
|
+
const path = require('node:path')
|
|
5
|
+
const test = require('node:test')
|
|
6
|
+
|
|
7
|
+
const Kernel = require('../kernel')
|
|
8
|
+
|
|
9
|
+
async function exists(targetPath) {
|
|
10
|
+
try {
|
|
11
|
+
await fs.access(targetPath)
|
|
12
|
+
return true
|
|
13
|
+
} catch (_) {
|
|
14
|
+
return false
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
test('kernel shell logs write cleaned output without creating info logs', async () => {
|
|
19
|
+
const root = await fs.mkdtemp(path.join(os.tmpdir(), 'pinokio-shell-cleaned-log-'))
|
|
20
|
+
try {
|
|
21
|
+
const kernel = Object.create(Kernel.prototype)
|
|
22
|
+
kernel.homedir = root
|
|
23
|
+
|
|
24
|
+
const group = path.join(root, 'api', 'demo', 'start.js')
|
|
25
|
+
await Kernel.prototype._log.call(kernel, {
|
|
26
|
+
cleaned: 'hello from cleaned log\n'
|
|
27
|
+
}, group, {
|
|
28
|
+
index: 3
|
|
29
|
+
})
|
|
30
|
+
|
|
31
|
+
const relativeGroup = path.relative(root, group)
|
|
32
|
+
const cleanedLog = path.join(root, 'logs', 'shell', 'cleaned', `${relativeGroup}.3.txt`)
|
|
33
|
+
const infoLog = path.join(root, 'logs', 'shell', 'info', `${relativeGroup}.3.txt`)
|
|
34
|
+
|
|
35
|
+
assert.equal(await exists(cleanedLog), true)
|
|
36
|
+
assert.equal(await fs.readFile(cleanedLog, 'utf8'), 'hello from cleaned log\n')
|
|
37
|
+
assert.equal(await exists(infoLog), false)
|
|
38
|
+
} finally {
|
|
39
|
+
await fs.rm(root, { recursive: true, force: true })
|
|
40
|
+
}
|
|
41
|
+
})
|
|
42
|
+
|
|
43
|
+
test('kernel shell log clearing removes cleaned files and legacy info files', async () => {
|
|
44
|
+
const root = await fs.mkdtemp(path.join(os.tmpdir(), 'pinokio-shell-cleaned-clear-'))
|
|
45
|
+
try {
|
|
46
|
+
const kernel = Object.create(Kernel.prototype)
|
|
47
|
+
kernel.homedir = root
|
|
48
|
+
|
|
49
|
+
const group = path.join(root, 'api', 'demo', 'start.js')
|
|
50
|
+
const relativeGroup = path.relative(root, group)
|
|
51
|
+
const cleanedLog = path.join(root, 'logs', 'shell', 'cleaned', `${relativeGroup}.3.txt`)
|
|
52
|
+
const infoLog = path.join(root, 'logs', 'shell', 'info', `${relativeGroup}.3.txt`)
|
|
53
|
+
|
|
54
|
+
await fs.mkdir(path.dirname(cleanedLog), { recursive: true })
|
|
55
|
+
await fs.mkdir(path.dirname(infoLog), { recursive: true })
|
|
56
|
+
await fs.writeFile(cleanedLog, 'cleaned\n')
|
|
57
|
+
await fs.writeFile(infoLog, 'legacy info\n')
|
|
58
|
+
|
|
59
|
+
await Kernel.prototype.clearLog.call(kernel, group)
|
|
60
|
+
|
|
61
|
+
assert.equal(await exists(cleanedLog), false)
|
|
62
|
+
assert.equal(await exists(infoLog), false)
|
|
63
|
+
} finally {
|
|
64
|
+
await fs.rm(root, { recursive: true, force: true })
|
|
65
|
+
}
|
|
66
|
+
})
|