pinokiod 7.1.68 → 7.1.69
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/package.json +1 -1
- package/server/index.js +101 -47
- package/server/views/setup.ejs +95 -11
package/package.json
CHANGED
package/server/index.js
CHANGED
|
@@ -5480,53 +5480,80 @@ class Server {
|
|
|
5480
5480
|
return list
|
|
5481
5481
|
}
|
|
5482
5482
|
async check_router_up() {
|
|
5483
|
-
|
|
5484
|
-
|
|
5483
|
+
// check if caddy is runnign properly
|
|
5484
|
+
// try https://pinokio.localhost
|
|
5485
|
+
// if it works, proceed
|
|
5486
|
+
// if not, redirect
|
|
5487
|
+
let https_running = false
|
|
5485
5488
|
try {
|
|
5486
5489
|
let res = await axios.get(`http://127.0.0.1:2019/config/`, {
|
|
5487
5490
|
timeout: 2000
|
|
5488
5491
|
})
|
|
5489
|
-
|
|
5490
|
-
|
|
5491
|
-
|
|
5492
|
-
stage: "caddy_admin_unavailable",
|
|
5493
|
-
error: "caddy admin unavailable",
|
|
5494
|
-
detail: e && e.message ? e.message : String(e)
|
|
5492
|
+
let test = /pinokio\.localhost/.test(JSON.stringify(res.data))
|
|
5493
|
+
if (test) {
|
|
5494
|
+
https_running = true
|
|
5495
5495
|
}
|
|
5496
|
+
} catch (e) {
|
|
5497
|
+
return { error: "caddy admin unavailable" }
|
|
5496
5498
|
}
|
|
5497
|
-
|
|
5498
|
-
|
|
5499
|
-
|
|
5500
|
-
|
|
5501
|
-
|
|
5502
|
-
|
|
5503
|
-
|
|
5504
|
-
|
|
5505
|
-
|
|
5506
|
-
|
|
5507
|
-
|
|
5508
|
-
|
|
5509
|
-
|
|
5510
|
-
let router = this.kernel.router.published()
|
|
5511
|
-
for (let ip in router) {
|
|
5512
|
-
let domains = router[ip]
|
|
5513
|
-
if (domains.includes("pinokio.localhost")) {
|
|
5514
|
-
router_running = true
|
|
5515
|
-
break
|
|
5516
|
-
}
|
|
5517
|
-
}
|
|
5518
|
-
if (!router_running) {
|
|
5519
|
-
response = {
|
|
5520
|
-
stage: "pinokio_router_missing",
|
|
5521
|
-
error: "pinokio.localhost not yet published by Pinokio router"
|
|
5522
|
-
}
|
|
5523
|
-
}
|
|
5499
|
+
// console.log({ https_running })
|
|
5500
|
+
if (!https_running) {
|
|
5501
|
+
return { error: "pinokio.host not yet available" }
|
|
5502
|
+
}
|
|
5503
|
+
|
|
5504
|
+
// check if pinokio.localhost router is running
|
|
5505
|
+
let router_running = false
|
|
5506
|
+
let router = this.kernel.router.published()
|
|
5507
|
+
for(let ip in router) {
|
|
5508
|
+
let domains = router[ip]
|
|
5509
|
+
if (domains.includes("pinokio.localhost")) {
|
|
5510
|
+
router_running = true
|
|
5511
|
+
break
|
|
5524
5512
|
}
|
|
5525
5513
|
}
|
|
5526
|
-
if (!
|
|
5527
|
-
|
|
5514
|
+
if (!router_running) {
|
|
5515
|
+
return { error: "pinokio.localhost not yet available" }
|
|
5528
5516
|
}
|
|
5529
|
-
|
|
5517
|
+
|
|
5518
|
+
return { success: true }
|
|
5519
|
+
}
|
|
5520
|
+
async ensureSecureRouterReady(timeout = 120000, interval = 500) {
|
|
5521
|
+
if (!(this.kernel && this.kernel.peer && this.kernel.peer.https_active)) {
|
|
5522
|
+
return { success: true, stage: "disabled" }
|
|
5523
|
+
}
|
|
5524
|
+
const caddy = this.kernel && this.kernel.bin && this.kernel.bin.mod
|
|
5525
|
+
? this.kernel.bin.mod.caddy
|
|
5526
|
+
: null
|
|
5527
|
+
const deadline = Date.now() + timeout
|
|
5528
|
+
let startedCaddyManually = false
|
|
5529
|
+
let refreshedRouter = false
|
|
5530
|
+
let lastStatus = null
|
|
5531
|
+
while (Date.now() < deadline) {
|
|
5532
|
+
lastStatus = await this.check_router_up()
|
|
5533
|
+
if (lastStatus && lastStatus.success) {
|
|
5534
|
+
return lastStatus
|
|
5535
|
+
}
|
|
5536
|
+
if (
|
|
5537
|
+
lastStatus &&
|
|
5538
|
+
lastStatus.error === "caddy admin unavailable" &&
|
|
5539
|
+
!startedCaddyManually &&
|
|
5540
|
+
caddy &&
|
|
5541
|
+
typeof caddy.start === "function"
|
|
5542
|
+
) {
|
|
5543
|
+
startedCaddyManually = true
|
|
5544
|
+
await caddy.start()
|
|
5545
|
+
continue
|
|
5546
|
+
}
|
|
5547
|
+
if (!refreshedRouter) {
|
|
5548
|
+
refreshedRouter = true
|
|
5549
|
+
await this.kernel.refresh(true).catch(() => {})
|
|
5550
|
+
continue
|
|
5551
|
+
}
|
|
5552
|
+
await new Promise((resolve) => {
|
|
5553
|
+
setTimeout(resolve, interval)
|
|
5554
|
+
})
|
|
5555
|
+
}
|
|
5556
|
+
throw new Error(lastStatus && lastStatus.error ? lastStatus.error : "secure router did not come up")
|
|
5530
5557
|
}
|
|
5531
5558
|
async start(options) {
|
|
5532
5559
|
this.debug = false
|
|
@@ -5797,6 +5824,12 @@ class Server {
|
|
|
5797
5824
|
phase: "initializing_environment"
|
|
5798
5825
|
})
|
|
5799
5826
|
await Environment.init({}, this.kernel)
|
|
5827
|
+
if (this.kernel && this.kernel.peer && this.kernel.peer.https_active) {
|
|
5828
|
+
setStartupStatus({
|
|
5829
|
+
phase: "waiting_for_secure_router"
|
|
5830
|
+
})
|
|
5831
|
+
await this.ensureSecureRouterReady()
|
|
5832
|
+
}
|
|
5800
5833
|
setStartupStatus({
|
|
5801
5834
|
sys_ready: this.getStartupStatus().sys_ready,
|
|
5802
5835
|
managed_ready: true,
|
|
@@ -11438,8 +11471,36 @@ class Server {
|
|
|
11438
11471
|
return
|
|
11439
11472
|
}
|
|
11440
11473
|
|
|
11441
|
-
|
|
11442
|
-
|
|
11474
|
+
let https_running = false
|
|
11475
|
+
try {
|
|
11476
|
+
let res = await axios.get(`http://127.0.0.1:2019/config/`, {
|
|
11477
|
+
timeout: 2000
|
|
11478
|
+
})
|
|
11479
|
+
let test = /pinokio\.localhost/.test(JSON.stringify(res.data))
|
|
11480
|
+
if (test) {
|
|
11481
|
+
https_running = true
|
|
11482
|
+
}
|
|
11483
|
+
} catch (e) {
|
|
11484
|
+
console.log(e)
|
|
11485
|
+
}
|
|
11486
|
+
if (!https_running) {
|
|
11487
|
+
// res.json({ error: "pinokio.host not yet available" })
|
|
11488
|
+
res.redirect("/setup/connect?callback=/connect/" + req.params.provider)
|
|
11489
|
+
return
|
|
11490
|
+
}
|
|
11491
|
+
|
|
11492
|
+
// check if pinokio.localhost router is running
|
|
11493
|
+
let router_running = false
|
|
11494
|
+
let router = this.kernel.router.published()
|
|
11495
|
+
for(let ip in router) {
|
|
11496
|
+
let domains = router[ip]
|
|
11497
|
+
if (domains.includes("pinokio.localhost")) {
|
|
11498
|
+
router_running = true
|
|
11499
|
+
break
|
|
11500
|
+
}
|
|
11501
|
+
}
|
|
11502
|
+
if (!router_running) {
|
|
11503
|
+
// res.json({ error: "pinokio.localhost not yet available" })
|
|
11443
11504
|
res.redirect("/setup/connect?callback=/connect/" + req.params.provider)
|
|
11444
11505
|
return
|
|
11445
11506
|
}
|
|
@@ -15557,13 +15618,6 @@ class Server {
|
|
|
15557
15618
|
server_ready: true,
|
|
15558
15619
|
phase: this.getStartupStatus().phase === "idle" ? "ready" : this.getStartupStatus().phase
|
|
15559
15620
|
})
|
|
15560
|
-
if (this.kernel && this.kernel.peer && this.kernel.peer.https_active) {
|
|
15561
|
-
this.kernel.refresh(true).then(() => {
|
|
15562
|
-
return this.check_router_up()
|
|
15563
|
-
}).catch((error) => {
|
|
15564
|
-
console.warn("[Pinokiod] initial secure router refresh failed", error && error.message ? error.message : error)
|
|
15565
|
-
})
|
|
15566
|
-
}
|
|
15567
15621
|
resolve()
|
|
15568
15622
|
});
|
|
15569
15623
|
this.httpTerminator = createHttpTerminator({
|
package/server/views/setup.ejs
CHANGED
|
@@ -243,17 +243,76 @@ document.addEventListener("DOMContentLoaded", async () => {
|
|
|
243
243
|
const waitRoot = document.querySelector(".requirements .content")
|
|
244
244
|
const waitLabel = document.querySelector(".requirements .content .loading span")
|
|
245
245
|
const WAIT_TIMEOUT_MS = 120000
|
|
246
|
-
const
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
246
|
+
const WAIT_DEBUG_HISTORY_LIMIT = 12
|
|
247
|
+
const waitDebugState = {
|
|
248
|
+
events: [],
|
|
249
|
+
phase: null,
|
|
250
|
+
router: null,
|
|
251
|
+
startupError: null,
|
|
251
252
|
}
|
|
252
253
|
const setWaitLabel = (message) => {
|
|
253
254
|
if (waitLabel) {
|
|
254
255
|
waitLabel.textContent = message
|
|
255
256
|
}
|
|
256
257
|
}
|
|
258
|
+
const pushWaitDebugEvent = (message) => {
|
|
259
|
+
const timestamp = new Date().toLocaleTimeString()
|
|
260
|
+
const entry = `[${timestamp}] ${message}`
|
|
261
|
+
if (waitDebugState.events[waitDebugState.events.length - 1] !== entry) {
|
|
262
|
+
waitDebugState.events.push(entry)
|
|
263
|
+
if (waitDebugState.events.length > WAIT_DEBUG_HISTORY_LIMIT) {
|
|
264
|
+
waitDebugState.events.shift()
|
|
265
|
+
}
|
|
266
|
+
}
|
|
267
|
+
}
|
|
268
|
+
const ensureWaitDebugPanel = () => {
|
|
269
|
+
if (!waitRoot) {
|
|
270
|
+
return null
|
|
271
|
+
}
|
|
272
|
+
let panel = waitRoot.querySelector(".wait-debug")
|
|
273
|
+
if (!panel) {
|
|
274
|
+
panel = document.createElement("div")
|
|
275
|
+
panel.className = "wait-debug"
|
|
276
|
+
panel.style.marginTop = "16px"
|
|
277
|
+
panel.style.padding = "12px"
|
|
278
|
+
panel.style.border = "1px solid rgba(255,255,255,0.12)"
|
|
279
|
+
panel.style.borderRadius = "8px"
|
|
280
|
+
panel.style.background = "rgba(255,255,255,0.04)"
|
|
281
|
+
panel.style.textAlign = "left"
|
|
282
|
+
panel.innerHTML = `
|
|
283
|
+
<div style="font-size:12px;font-weight:600;letter-spacing:0.04em;text-transform:uppercase;opacity:0.75;margin-bottom:8px;">Debug</div>
|
|
284
|
+
<pre class="wait-debug-body" style="margin:0;text-align:left;white-space:pre-wrap;word-break:break-word;font-size:12px;line-height:1.5;opacity:0.9;"></pre>
|
|
285
|
+
`
|
|
286
|
+
waitRoot.appendChild(panel)
|
|
287
|
+
}
|
|
288
|
+
return panel.querySelector(".wait-debug-body")
|
|
289
|
+
}
|
|
290
|
+
const renderWaitDebug = ({ startedAt, routerStatus, startupStatus } = {}) => {
|
|
291
|
+
const body = ensureWaitDebugPanel()
|
|
292
|
+
if (!body) {
|
|
293
|
+
return
|
|
294
|
+
}
|
|
295
|
+
const elapsedSeconds = startedAt ? Math.max(0, Math.floor((Date.now() - startedAt) / 1000)) : 0
|
|
296
|
+
const lines = [
|
|
297
|
+
`Elapsed: ${elapsedSeconds}s`,
|
|
298
|
+
`Startup phase: ${startupStatus && startupStatus.phase ? startupStatus.phase : "-"}`,
|
|
299
|
+
`Startup error: ${startupStatus && startupStatus.error ? startupStatus.error : "-"}`,
|
|
300
|
+
`Router check: ${routerStatus ? JSON.stringify(routerStatus) : "-"}`,
|
|
301
|
+
`Startup payload: ${startupStatus ? JSON.stringify({
|
|
302
|
+
phase: startupStatus.phase || null,
|
|
303
|
+
error: startupStatus.error || null,
|
|
304
|
+
startup_pending: startupStatus.startup_pending,
|
|
305
|
+
requirements_pending: startupStatus.requirements_pending,
|
|
306
|
+
updated_at: startupStatus.updated_at || null
|
|
307
|
+
}) : "-"}`,
|
|
308
|
+
]
|
|
309
|
+
if (waitDebugState.events.length > 0) {
|
|
310
|
+
lines.push("")
|
|
311
|
+
lines.push("Recent events:")
|
|
312
|
+
lines.push(...waitDebugState.events)
|
|
313
|
+
}
|
|
314
|
+
body.textContent = lines.join("\n")
|
|
315
|
+
}
|
|
257
316
|
const showWaitError = (message) => {
|
|
258
317
|
if (waitRoot) {
|
|
259
318
|
waitRoot.innerHTML = `
|
|
@@ -265,6 +324,7 @@ document.addEventListener("DOMContentLoaded", async () => {
|
|
|
265
324
|
<a class='btn' href='${location.href}'>Retry</a>
|
|
266
325
|
</div>
|
|
267
326
|
`
|
|
327
|
+
renderWaitDebug()
|
|
268
328
|
} else {
|
|
269
329
|
alert(message)
|
|
270
330
|
}
|
|
@@ -272,6 +332,8 @@ document.addEventListener("DOMContentLoaded", async () => {
|
|
|
272
332
|
|
|
273
333
|
try {
|
|
274
334
|
setWaitLabel("Enabling secure localhost access...")
|
|
335
|
+
pushWaitDebugEvent("saving secure localhost flags")
|
|
336
|
+
renderWaitDebug()
|
|
275
337
|
const networkResponse = await fetch("/network", {
|
|
276
338
|
method: "post",
|
|
277
339
|
headers: { "Content-Type": "application/json" },
|
|
@@ -285,8 +347,12 @@ document.addEventListener("DOMContentLoaded", async () => {
|
|
|
285
347
|
if (networkResponse && networkResponse.error) {
|
|
286
348
|
throw new Error(networkResponse.error)
|
|
287
349
|
}
|
|
350
|
+
pushWaitDebugEvent("secure localhost flags saved")
|
|
351
|
+
renderWaitDebug()
|
|
288
352
|
|
|
289
353
|
setWaitLabel("Restarting Pinokio...")
|
|
354
|
+
pushWaitDebugEvent("restart requested")
|
|
355
|
+
renderWaitDebug()
|
|
290
356
|
try {
|
|
291
357
|
await fetch("/restart", {
|
|
292
358
|
method: "post"
|
|
@@ -298,6 +364,7 @@ document.addEventListener("DOMContentLoaded", async () => {
|
|
|
298
364
|
const startedAt = Date.now()
|
|
299
365
|
let lastKnownError = null
|
|
300
366
|
let lastKnownPhase = null
|
|
367
|
+
renderWaitDebug({ startedAt })
|
|
301
368
|
|
|
302
369
|
await new Promise((resolve, reject) => {
|
|
303
370
|
const interval = setInterval(async () => {
|
|
@@ -319,16 +386,29 @@ document.addEventListener("DOMContentLoaded", async () => {
|
|
|
319
386
|
if (startupStatus && startupStatus.error) {
|
|
320
387
|
lastKnownError = startupStatus.error
|
|
321
388
|
}
|
|
389
|
+
if (startupStatus && startupStatus.phase && startupStatus.phase !== waitDebugState.phase) {
|
|
390
|
+
waitDebugState.phase = startupStatus.phase
|
|
391
|
+
pushWaitDebugEvent(`phase -> ${startupStatus.phase}`)
|
|
392
|
+
}
|
|
393
|
+
const routerSummary = routerStatus
|
|
394
|
+
? (routerStatus.success ? "success" : (routerStatus.error || JSON.stringify(routerStatus)))
|
|
395
|
+
: null
|
|
396
|
+
if (routerSummary && routerSummary !== waitDebugState.router) {
|
|
397
|
+
waitDebugState.router = routerSummary
|
|
398
|
+
pushWaitDebugEvent(`router -> ${routerSummary}`)
|
|
399
|
+
}
|
|
400
|
+
if (startupStatus && startupStatus.error && startupStatus.error !== waitDebugState.startupError) {
|
|
401
|
+
waitDebugState.startupError = startupStatus.error
|
|
402
|
+
pushWaitDebugEvent(`startup error -> ${startupStatus.error}`)
|
|
403
|
+
}
|
|
322
404
|
if (startupStatus && startupStatus.phase) {
|
|
323
|
-
lastKnownPhase =
|
|
324
|
-
const
|
|
325
|
-
? ROUTER_STAGE_MESSAGES[routerStatus.stage]
|
|
326
|
-
: null
|
|
327
|
-
const phaseMessage = routerStageMessage || (startupStatus.phase === "ready"
|
|
405
|
+
lastKnownPhase = startupStatus.phase
|
|
406
|
+
const phaseMessage = startupStatus.phase === "ready"
|
|
328
407
|
? "Secure router is almost ready..."
|
|
329
|
-
: `Restarting Pinokio... (${startupStatus.phase.replace(/_/g, " ")})`
|
|
408
|
+
: `Restarting Pinokio... (${startupStatus.phase.replace(/_/g, " ")})`
|
|
330
409
|
setWaitLabel(phaseMessage)
|
|
331
410
|
}
|
|
411
|
+
renderWaitDebug({ startedAt, routerStatus, startupStatus })
|
|
332
412
|
|
|
333
413
|
if (startupStatus && startupStatus.phase === "error") {
|
|
334
414
|
clearInterval(interval)
|
|
@@ -339,10 +419,14 @@ document.addEventListener("DOMContentLoaded", async () => {
|
|
|
339
419
|
if ((Date.now() - startedAt) >= WAIT_TIMEOUT_MS) {
|
|
340
420
|
clearInterval(interval)
|
|
341
421
|
const detail = lastKnownError || lastKnownPhase || "secure localhost router did not come up"
|
|
422
|
+
pushWaitDebugEvent(`timeout -> ${detail}`)
|
|
423
|
+
renderWaitDebug({ startedAt, routerStatus, startupStatus })
|
|
342
424
|
reject(new Error(`Timed out waiting for restart: ${detail}`))
|
|
343
425
|
}
|
|
344
426
|
} catch (error) {
|
|
345
427
|
lastKnownError = error && error.message ? error.message : String(error)
|
|
428
|
+
pushWaitDebugEvent(`poll error -> ${lastKnownError}`)
|
|
429
|
+
renderWaitDebug({ startedAt })
|
|
346
430
|
if ((Date.now() - startedAt) >= WAIT_TIMEOUT_MS) {
|
|
347
431
|
clearInterval(interval)
|
|
348
432
|
reject(new Error(`Timed out waiting for restart: ${lastKnownError}`))
|