pinokiod 7.1.68 → 7.1.70
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 +72 -47
- package/server/lib/secure_router_debug.js +116 -0
- package/server/lib/secure_router_ready.js +96 -0
- package/server/public/setup-wait-debug.js +108 -0
- package/server/views/setup.ejs +55 -14
package/package.json
CHANGED
package/server/index.js
CHANGED
|
@@ -79,6 +79,8 @@ const { createInjectRouter, resolveInjectList } = require("./lib/inject_router")
|
|
|
79
79
|
const { createTaskPackageService } = require("./lib/task_packages")
|
|
80
80
|
const { createTaskWorkspaceLinkService } = require("./lib/task_workspace_links")
|
|
81
81
|
const { createContentValidationService } = require("./lib/content_validation")
|
|
82
|
+
const { buildSecureRouterDebugSnapshot, createSecureRouterDebugStore } = require("./lib/secure_router_debug")
|
|
83
|
+
const { ensureSecureRouterReady } = require("./lib/secure_router_ready")
|
|
82
84
|
const AppRegistryService = require("./lib/app_registry")
|
|
83
85
|
const AppLogService = require("./lib/app_logs")
|
|
84
86
|
const AppSearchService = require("./lib/app_search")
|
|
@@ -253,6 +255,7 @@ class Server {
|
|
|
253
255
|
updated_at: new Date().toISOString()
|
|
254
256
|
}
|
|
255
257
|
this.startup_status_run_id = 0
|
|
258
|
+
this.secure_router_debug = createSecureRouterDebugStore()
|
|
256
259
|
this.installFatalHandlers()
|
|
257
260
|
}
|
|
258
261
|
setStartupStatus(patch = {}) {
|
|
@@ -5480,53 +5483,45 @@ class Server {
|
|
|
5480
5483
|
return list
|
|
5481
5484
|
}
|
|
5482
5485
|
async check_router_up() {
|
|
5483
|
-
|
|
5484
|
-
|
|
5486
|
+
// check if caddy is runnign properly
|
|
5487
|
+
// try https://pinokio.localhost
|
|
5488
|
+
// if it works, proceed
|
|
5489
|
+
// if not, redirect
|
|
5490
|
+
let https_running = false
|
|
5485
5491
|
try {
|
|
5486
5492
|
let res = await axios.get(`http://127.0.0.1:2019/config/`, {
|
|
5487
5493
|
timeout: 2000
|
|
5488
5494
|
})
|
|
5489
|
-
|
|
5490
|
-
|
|
5491
|
-
|
|
5492
|
-
stage: "caddy_admin_unavailable",
|
|
5493
|
-
error: "caddy admin unavailable",
|
|
5494
|
-
detail: e && e.message ? e.message : String(e)
|
|
5495
|
+
let test = /pinokio\.localhost/.test(JSON.stringify(res.data))
|
|
5496
|
+
if (test) {
|
|
5497
|
+
https_running = true
|
|
5495
5498
|
}
|
|
5499
|
+
} catch (e) {
|
|
5500
|
+
return { error: "caddy admin unavailable" }
|
|
5496
5501
|
}
|
|
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
|
-
}
|
|
5502
|
+
// console.log({ https_running })
|
|
5503
|
+
if (!https_running) {
|
|
5504
|
+
return { error: "pinokio.host not yet available" }
|
|
5505
|
+
}
|
|
5506
|
+
|
|
5507
|
+
// check if pinokio.localhost router is running
|
|
5508
|
+
let router_running = false
|
|
5509
|
+
let router = this.kernel.router.published()
|
|
5510
|
+
for(let ip in router) {
|
|
5511
|
+
let domains = router[ip]
|
|
5512
|
+
if (domains.includes("pinokio.localhost")) {
|
|
5513
|
+
router_running = true
|
|
5514
|
+
break
|
|
5524
5515
|
}
|
|
5525
5516
|
}
|
|
5526
|
-
if (!
|
|
5527
|
-
|
|
5517
|
+
if (!router_running) {
|
|
5518
|
+
return { error: "pinokio.localhost not yet available" }
|
|
5528
5519
|
}
|
|
5529
|
-
|
|
5520
|
+
|
|
5521
|
+
return { success: true }
|
|
5522
|
+
}
|
|
5523
|
+
async ensureSecureRouterReady(timeout = 120000, interval = 500) {
|
|
5524
|
+
return ensureSecureRouterReady(this, timeout, interval)
|
|
5530
5525
|
}
|
|
5531
5526
|
async start(options) {
|
|
5532
5527
|
this.debug = false
|
|
@@ -5797,6 +5792,12 @@ class Server {
|
|
|
5797
5792
|
phase: "initializing_environment"
|
|
5798
5793
|
})
|
|
5799
5794
|
await Environment.init({}, this.kernel)
|
|
5795
|
+
if (this.kernel && this.kernel.peer && this.kernel.peer.https_active) {
|
|
5796
|
+
setStartupStatus({
|
|
5797
|
+
phase: "waiting_for_secure_router"
|
|
5798
|
+
})
|
|
5799
|
+
await this.ensureSecureRouterReady()
|
|
5800
|
+
}
|
|
5800
5801
|
setStartupStatus({
|
|
5801
5802
|
sys_ready: this.getStartupStatus().sys_ready,
|
|
5802
5803
|
managed_ready: true,
|
|
@@ -11438,8 +11439,36 @@ class Server {
|
|
|
11438
11439
|
return
|
|
11439
11440
|
}
|
|
11440
11441
|
|
|
11441
|
-
|
|
11442
|
-
|
|
11442
|
+
let https_running = false
|
|
11443
|
+
try {
|
|
11444
|
+
let res = await axios.get(`http://127.0.0.1:2019/config/`, {
|
|
11445
|
+
timeout: 2000
|
|
11446
|
+
})
|
|
11447
|
+
let test = /pinokio\.localhost/.test(JSON.stringify(res.data))
|
|
11448
|
+
if (test) {
|
|
11449
|
+
https_running = true
|
|
11450
|
+
}
|
|
11451
|
+
} catch (e) {
|
|
11452
|
+
console.log(e)
|
|
11453
|
+
}
|
|
11454
|
+
if (!https_running) {
|
|
11455
|
+
// res.json({ error: "pinokio.host not yet available" })
|
|
11456
|
+
res.redirect("/setup/connect?callback=/connect/" + req.params.provider)
|
|
11457
|
+
return
|
|
11458
|
+
}
|
|
11459
|
+
|
|
11460
|
+
// check if pinokio.localhost router is running
|
|
11461
|
+
let router_running = false
|
|
11462
|
+
let router = this.kernel.router.published()
|
|
11463
|
+
for(let ip in router) {
|
|
11464
|
+
let domains = router[ip]
|
|
11465
|
+
if (domains.includes("pinokio.localhost")) {
|
|
11466
|
+
router_running = true
|
|
11467
|
+
break
|
|
11468
|
+
}
|
|
11469
|
+
}
|
|
11470
|
+
if (!router_running) {
|
|
11471
|
+
// res.json({ error: "pinokio.localhost not yet available" })
|
|
11443
11472
|
res.redirect("/setup/connect?callback=/connect/" + req.params.provider)
|
|
11444
11473
|
return
|
|
11445
11474
|
}
|
|
@@ -15422,6 +15451,9 @@ class Server {
|
|
|
15422
15451
|
this.app.get("/pinokio/startup_status", ex((req, res) => {
|
|
15423
15452
|
res.json(this.getStartupStatus())
|
|
15424
15453
|
}))
|
|
15454
|
+
this.app.get("/pinokio/secure_router_debug", ex(async (req, res) => {
|
|
15455
|
+
res.json(await buildSecureRouterDebugSnapshot(this, this.secure_router_debug))
|
|
15456
|
+
}))
|
|
15425
15457
|
this.app.get("/pinokio/requirements_ready", ex((req, res) => {
|
|
15426
15458
|
res.json(this.getStartupStatus())
|
|
15427
15459
|
}))
|
|
@@ -15557,13 +15589,6 @@ class Server {
|
|
|
15557
15589
|
server_ready: true,
|
|
15558
15590
|
phase: this.getStartupStatus().phase === "idle" ? "ready" : this.getStartupStatus().phase
|
|
15559
15591
|
})
|
|
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
15592
|
resolve()
|
|
15568
15593
|
});
|
|
15569
15594
|
this.httpTerminator = createHttpTerminator({
|
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
function createSecureRouterDebugStore() {
|
|
2
|
+
return {
|
|
3
|
+
events: [],
|
|
4
|
+
state: {
|
|
5
|
+
active: false,
|
|
6
|
+
started_at: null,
|
|
7
|
+
updated_at: null,
|
|
8
|
+
last_status: null,
|
|
9
|
+
caddy_start_attempted: false,
|
|
10
|
+
caddy_start_finished: false,
|
|
11
|
+
caddy_start_error: null,
|
|
12
|
+
refresh_attempted: false,
|
|
13
|
+
refresh_finished: false,
|
|
14
|
+
refresh_error: null,
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
function clone(value) {
|
|
20
|
+
return JSON.parse(JSON.stringify(value))
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
function recordSecureRouterDebug(store, message, patch = {}) {
|
|
24
|
+
if (!store) {
|
|
25
|
+
return
|
|
26
|
+
}
|
|
27
|
+
const timestamp = new Date().toISOString()
|
|
28
|
+
store.state = {
|
|
29
|
+
...(store.state || {}),
|
|
30
|
+
...patch,
|
|
31
|
+
updated_at: timestamp
|
|
32
|
+
}
|
|
33
|
+
store.events.push({
|
|
34
|
+
at: timestamp,
|
|
35
|
+
message
|
|
36
|
+
})
|
|
37
|
+
if (store.events.length > 20) {
|
|
38
|
+
store.events.shift()
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
async function buildSecureRouterDebugSnapshot(server, store) {
|
|
43
|
+
const kernel = server && server.kernel ? server.kernel : null
|
|
44
|
+
const peer = kernel && kernel.peer ? kernel.peer : null
|
|
45
|
+
const router = kernel && kernel.router && typeof kernel.router.published === "function"
|
|
46
|
+
? (kernel.router.published() || {})
|
|
47
|
+
: {}
|
|
48
|
+
const routerDialKeys = Object.keys(router)
|
|
49
|
+
const hasPinokioLocalhost = routerDialKeys.some((dial) => {
|
|
50
|
+
const domains = Array.isArray(router[dial]) ? router[dial] : []
|
|
51
|
+
return domains.includes("pinokio.localhost")
|
|
52
|
+
})
|
|
53
|
+
const caddy = kernel && kernel.bin && kernel.bin.mod
|
|
54
|
+
? kernel.bin.mod.caddy
|
|
55
|
+
: null
|
|
56
|
+
let caddyInstalled = null
|
|
57
|
+
let caddyRunning = null
|
|
58
|
+
try {
|
|
59
|
+
if (caddy && typeof caddy.installed === "function") {
|
|
60
|
+
caddyInstalled = await caddy.installed()
|
|
61
|
+
}
|
|
62
|
+
} catch (error) {
|
|
63
|
+
caddyInstalled = { error: error && error.message ? error.message : String(error) }
|
|
64
|
+
}
|
|
65
|
+
try {
|
|
66
|
+
if (caddy && typeof caddy.running === "function") {
|
|
67
|
+
caddyRunning = await caddy.running()
|
|
68
|
+
}
|
|
69
|
+
} catch (error) {
|
|
70
|
+
caddyRunning = { error: error && error.message ? error.message : String(error) }
|
|
71
|
+
}
|
|
72
|
+
const startupStatus = server && typeof server.getStartupStatus === "function"
|
|
73
|
+
? server.getStartupStatus()
|
|
74
|
+
: null
|
|
75
|
+
const state = store && store.state ? clone(store.state) : {}
|
|
76
|
+
const events = store && Array.isArray(store.events) ? clone(store.events) : []
|
|
77
|
+
return {
|
|
78
|
+
wait: state,
|
|
79
|
+
flags: {
|
|
80
|
+
peer_active: peer ? !!peer.peer_active : null,
|
|
81
|
+
https_active: peer ? !!peer.https_active : null,
|
|
82
|
+
active: peer ? !!peer.active : null,
|
|
83
|
+
},
|
|
84
|
+
caddy: {
|
|
85
|
+
installed: caddyInstalled,
|
|
86
|
+
running: caddyRunning,
|
|
87
|
+
start_attempted: !!state.caddy_start_attempted,
|
|
88
|
+
start_finished: !!state.caddy_start_finished,
|
|
89
|
+
start_error: state.caddy_start_error || null,
|
|
90
|
+
},
|
|
91
|
+
peer: {
|
|
92
|
+
host: peer && peer.host ? peer.host : null,
|
|
93
|
+
name: peer && peer.name ? peer.name : null,
|
|
94
|
+
has_info: !!(peer && peer.info),
|
|
95
|
+
has_host_info: !!(peer && peer.info && peer.host && peer.info[peer.host]),
|
|
96
|
+
refreshing: !!(peer && peer.refreshing),
|
|
97
|
+
},
|
|
98
|
+
router: {
|
|
99
|
+
published_count: routerDialKeys.length,
|
|
100
|
+
published_dials: routerDialKeys.slice(0, 10),
|
|
101
|
+
has_pinokio_localhost: hasPinokioLocalhost,
|
|
102
|
+
refresh_attempted: !!state.refresh_attempted,
|
|
103
|
+
refresh_finished: !!state.refresh_finished,
|
|
104
|
+
refresh_error: state.refresh_error || null,
|
|
105
|
+
last_status: state.last_status || null,
|
|
106
|
+
},
|
|
107
|
+
startup: startupStatus,
|
|
108
|
+
events
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
module.exports = {
|
|
113
|
+
buildSecureRouterDebugSnapshot,
|
|
114
|
+
createSecureRouterDebugStore,
|
|
115
|
+
recordSecureRouterDebug,
|
|
116
|
+
}
|
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
const { createSecureRouterDebugStore, recordSecureRouterDebug } = require("./secure_router_debug")
|
|
2
|
+
|
|
3
|
+
async function ensureSecureRouterReady(server, timeout = 120000, interval = 500) {
|
|
4
|
+
if (!(server.kernel && server.kernel.peer && server.kernel.peer.https_active)) {
|
|
5
|
+
return { success: true, stage: "disabled" }
|
|
6
|
+
}
|
|
7
|
+
server.secure_router_debug = createSecureRouterDebugStore()
|
|
8
|
+
recordSecureRouterDebug(server.secure_router_debug, "wait started", {
|
|
9
|
+
active: true,
|
|
10
|
+
started_at: new Date().toISOString(),
|
|
11
|
+
last_status: null,
|
|
12
|
+
caddy_start_attempted: false,
|
|
13
|
+
caddy_start_finished: false,
|
|
14
|
+
caddy_start_error: null,
|
|
15
|
+
refresh_attempted: false,
|
|
16
|
+
refresh_finished: false,
|
|
17
|
+
refresh_error: null,
|
|
18
|
+
})
|
|
19
|
+
const caddy = server.kernel && server.kernel.bin && server.kernel.bin.mod
|
|
20
|
+
? server.kernel.bin.mod.caddy
|
|
21
|
+
: null
|
|
22
|
+
const deadline = Date.now() + timeout
|
|
23
|
+
let startedCaddyManually = false
|
|
24
|
+
let refreshedRouter = false
|
|
25
|
+
let lastStatus = null
|
|
26
|
+
let lastStatusSummary = null
|
|
27
|
+
while (Date.now() < deadline) {
|
|
28
|
+
lastStatus = await server.check_router_up()
|
|
29
|
+
const statusSummary = lastStatus && lastStatus.success
|
|
30
|
+
? "success"
|
|
31
|
+
: (lastStatus && lastStatus.error ? lastStatus.error : JSON.stringify(lastStatus))
|
|
32
|
+
if (statusSummary !== lastStatusSummary) {
|
|
33
|
+
lastStatusSummary = statusSummary
|
|
34
|
+
recordSecureRouterDebug(server.secure_router_debug, `check_router_up -> ${statusSummary}`, {
|
|
35
|
+
last_status: lastStatus
|
|
36
|
+
})
|
|
37
|
+
}
|
|
38
|
+
if (lastStatus && lastStatus.success) {
|
|
39
|
+
recordSecureRouterDebug(server.secure_router_debug, "wait success", {
|
|
40
|
+
active: false
|
|
41
|
+
})
|
|
42
|
+
return lastStatus
|
|
43
|
+
}
|
|
44
|
+
if (
|
|
45
|
+
lastStatus &&
|
|
46
|
+
lastStatus.error === "caddy admin unavailable" &&
|
|
47
|
+
!startedCaddyManually &&
|
|
48
|
+
caddy &&
|
|
49
|
+
typeof caddy.start === "function"
|
|
50
|
+
) {
|
|
51
|
+
startedCaddyManually = true
|
|
52
|
+
recordSecureRouterDebug(server.secure_router_debug, "manual caddy.start() attempted", {
|
|
53
|
+
caddy_start_attempted: true
|
|
54
|
+
})
|
|
55
|
+
try {
|
|
56
|
+
await caddy.start()
|
|
57
|
+
recordSecureRouterDebug(server.secure_router_debug, "manual caddy.start() finished", {
|
|
58
|
+
caddy_start_finished: true
|
|
59
|
+
})
|
|
60
|
+
} catch (e) {
|
|
61
|
+
recordSecureRouterDebug(server.secure_router_debug, "manual caddy.start() failed", {
|
|
62
|
+
caddy_start_error: e && e.message ? e.message : String(e)
|
|
63
|
+
})
|
|
64
|
+
throw e
|
|
65
|
+
}
|
|
66
|
+
continue
|
|
67
|
+
}
|
|
68
|
+
if (!refreshedRouter) {
|
|
69
|
+
refreshedRouter = true
|
|
70
|
+
recordSecureRouterDebug(server.secure_router_debug, "kernel.refresh(true) attempted", {
|
|
71
|
+
refresh_attempted: true
|
|
72
|
+
})
|
|
73
|
+
await server.kernel.refresh(true).then(() => {
|
|
74
|
+
recordSecureRouterDebug(server.secure_router_debug, "kernel.refresh(true) finished", {
|
|
75
|
+
refresh_finished: true
|
|
76
|
+
})
|
|
77
|
+
}).catch((e) => {
|
|
78
|
+
recordSecureRouterDebug(server.secure_router_debug, "kernel.refresh(true) failed", {
|
|
79
|
+
refresh_error: e && e.message ? e.message : String(e)
|
|
80
|
+
})
|
|
81
|
+
})
|
|
82
|
+
continue
|
|
83
|
+
}
|
|
84
|
+
await new Promise((resolve) => {
|
|
85
|
+
setTimeout(resolve, interval)
|
|
86
|
+
})
|
|
87
|
+
}
|
|
88
|
+
recordSecureRouterDebug(server.secure_router_debug, "wait timeout", {
|
|
89
|
+
active: false
|
|
90
|
+
})
|
|
91
|
+
throw new Error(lastStatus && lastStatus.error ? lastStatus.error : "secure router did not come up")
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
module.exports = {
|
|
95
|
+
ensureSecureRouterReady,
|
|
96
|
+
}
|
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
(function () {
|
|
2
|
+
const HISTORY_LIMIT = 12
|
|
3
|
+
|
|
4
|
+
function create(waitRoot) {
|
|
5
|
+
const state = {
|
|
6
|
+
events: [],
|
|
7
|
+
phase: null,
|
|
8
|
+
router: null,
|
|
9
|
+
startupError: null,
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
function ensurePanel() {
|
|
13
|
+
if (!waitRoot) {
|
|
14
|
+
return null
|
|
15
|
+
}
|
|
16
|
+
let panel = waitRoot.querySelector(".wait-debug")
|
|
17
|
+
if (!panel) {
|
|
18
|
+
panel = document.createElement("div")
|
|
19
|
+
panel.className = "wait-debug"
|
|
20
|
+
panel.style.marginTop = "16px"
|
|
21
|
+
panel.style.padding = "12px"
|
|
22
|
+
panel.style.border = "1px solid rgba(255,255,255,0.12)"
|
|
23
|
+
panel.style.borderRadius = "8px"
|
|
24
|
+
panel.style.background = "rgba(255,255,255,0.04)"
|
|
25
|
+
panel.style.textAlign = "left"
|
|
26
|
+
panel.innerHTML = [
|
|
27
|
+
'<div style="font-size:12px;font-weight:600;letter-spacing:0.04em;text-transform:uppercase;opacity:0.75;margin-bottom:8px;">Debug</div>',
|
|
28
|
+
'<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>'
|
|
29
|
+
].join("")
|
|
30
|
+
waitRoot.appendChild(panel)
|
|
31
|
+
}
|
|
32
|
+
return panel.querySelector(".wait-debug-body")
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
function event(message) {
|
|
36
|
+
const timestamp = new Date().toLocaleTimeString()
|
|
37
|
+
const entry = `[${timestamp}] ${message}`
|
|
38
|
+
if (state.events[state.events.length - 1] !== entry) {
|
|
39
|
+
state.events.push(entry)
|
|
40
|
+
if (state.events.length > HISTORY_LIMIT) {
|
|
41
|
+
state.events.shift()
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
function track({ routerStatus, startupStatus } = {}) {
|
|
47
|
+
if (startupStatus && startupStatus.phase && startupStatus.phase !== state.phase) {
|
|
48
|
+
state.phase = startupStatus.phase
|
|
49
|
+
event(`phase -> ${startupStatus.phase}`)
|
|
50
|
+
}
|
|
51
|
+
const routerSummary = routerStatus
|
|
52
|
+
? (routerStatus.success ? "success" : (routerStatus.error || JSON.stringify(routerStatus)))
|
|
53
|
+
: null
|
|
54
|
+
if (routerSummary && routerSummary !== state.router) {
|
|
55
|
+
state.router = routerSummary
|
|
56
|
+
event(`router -> ${routerSummary}`)
|
|
57
|
+
}
|
|
58
|
+
if (startupStatus && startupStatus.error && startupStatus.error !== state.startupError) {
|
|
59
|
+
state.startupError = startupStatus.error
|
|
60
|
+
event(`startup error -> ${startupStatus.error}`)
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
function render({ startedAt, routerStatus, startupStatus, serverDebug } = {}) {
|
|
65
|
+
const body = ensurePanel()
|
|
66
|
+
if (!body) {
|
|
67
|
+
return
|
|
68
|
+
}
|
|
69
|
+
const elapsedSeconds = startedAt ? Math.max(0, Math.floor((Date.now() - startedAt) / 1000)) : 0
|
|
70
|
+
const lines = [
|
|
71
|
+
`Elapsed: ${elapsedSeconds}s`,
|
|
72
|
+
`Startup phase: ${startupStatus && startupStatus.phase ? startupStatus.phase : "-"}`,
|
|
73
|
+
`Startup error: ${startupStatus && startupStatus.error ? startupStatus.error : "-"}`,
|
|
74
|
+
`Router check: ${routerStatus ? JSON.stringify(routerStatus) : "-"}`,
|
|
75
|
+
]
|
|
76
|
+
if (serverDebug) {
|
|
77
|
+
lines.push(`Flags: ${JSON.stringify(serverDebug.flags || null)}`)
|
|
78
|
+
lines.push(`Caddy: ${JSON.stringify(serverDebug.caddy || null)}`)
|
|
79
|
+
lines.push(`Peer: ${JSON.stringify(serverDebug.peer || null)}`)
|
|
80
|
+
lines.push(`Router: ${JSON.stringify(serverDebug.router || null)}`)
|
|
81
|
+
lines.push(`Wait: ${JSON.stringify(serverDebug.wait || null)}`)
|
|
82
|
+
}
|
|
83
|
+
if (state.events.length > 0) {
|
|
84
|
+
lines.push("")
|
|
85
|
+
lines.push("Recent page events:")
|
|
86
|
+
lines.push(...state.events)
|
|
87
|
+
}
|
|
88
|
+
if (serverDebug && Array.isArray(serverDebug.events) && serverDebug.events.length > 0) {
|
|
89
|
+
lines.push("")
|
|
90
|
+
lines.push("Recent server events:")
|
|
91
|
+
for (const entry of serverDebug.events) {
|
|
92
|
+
lines.push(`[${entry.at}] ${entry.message}`)
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
body.textContent = lines.join("\n")
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
return {
|
|
99
|
+
event,
|
|
100
|
+
render,
|
|
101
|
+
track,
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
window.PinokioSetupWaitDebug = {
|
|
106
|
+
create
|
|
107
|
+
}
|
|
108
|
+
})();
|
package/server/views/setup.ejs
CHANGED
|
@@ -13,6 +13,7 @@
|
|
|
13
13
|
<% if (agent === "electron") { %>
|
|
14
14
|
<link href="/electron.css" rel="stylesheet"/>
|
|
15
15
|
<% } %>
|
|
16
|
+
<script src="/setup-wait-debug.js"></script>
|
|
16
17
|
<style>
|
|
17
18
|
html {
|
|
18
19
|
scroll-behavior: smooth;
|
|
@@ -243,17 +244,45 @@ document.addEventListener("DOMContentLoaded", async () => {
|
|
|
243
244
|
const waitRoot = document.querySelector(".requirements .content")
|
|
244
245
|
const waitLabel = document.querySelector(".requirements .content .loading span")
|
|
245
246
|
const WAIT_TIMEOUT_MS = 120000
|
|
246
|
-
const
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
pinokio_router_missing: "Restarting Pinokio... (waiting for Pinokio router)"
|
|
251
|
-
}
|
|
247
|
+
const waitDebug = window.PinokioSetupWaitDebug ? window.PinokioSetupWaitDebug.create(waitRoot) : null
|
|
248
|
+
let lastRouterStatus = null
|
|
249
|
+
let lastStartupStatus = null
|
|
250
|
+
let lastServerDebug = null
|
|
252
251
|
const setWaitLabel = (message) => {
|
|
253
252
|
if (waitLabel) {
|
|
254
253
|
waitLabel.textContent = message
|
|
255
254
|
}
|
|
256
255
|
}
|
|
256
|
+
const pushWaitDebugEvent = (message) => {
|
|
257
|
+
if (waitDebug) {
|
|
258
|
+
waitDebug.event(message)
|
|
259
|
+
}
|
|
260
|
+
}
|
|
261
|
+
const renderWaitDebug = ({ startedAt, routerStatus, startupStatus, serverDebug } = {}) => {
|
|
262
|
+
if (typeof routerStatus !== "undefined") {
|
|
263
|
+
lastRouterStatus = routerStatus
|
|
264
|
+
}
|
|
265
|
+
if (typeof startupStatus !== "undefined") {
|
|
266
|
+
lastStartupStatus = startupStatus
|
|
267
|
+
}
|
|
268
|
+
if (typeof serverDebug !== "undefined") {
|
|
269
|
+
lastServerDebug = serverDebug
|
|
270
|
+
}
|
|
271
|
+
if (!waitDebug) {
|
|
272
|
+
return
|
|
273
|
+
}
|
|
274
|
+
waitDebug.render({
|
|
275
|
+
startedAt,
|
|
276
|
+
routerStatus: lastRouterStatus,
|
|
277
|
+
startupStatus: lastStartupStatus,
|
|
278
|
+
serverDebug: lastServerDebug,
|
|
279
|
+
})
|
|
280
|
+
}
|
|
281
|
+
const trackWaitDebug = ({ routerStatus, startupStatus } = {}) => {
|
|
282
|
+
if (waitDebug) {
|
|
283
|
+
waitDebug.track({ routerStatus, startupStatus })
|
|
284
|
+
}
|
|
285
|
+
}
|
|
257
286
|
const showWaitError = (message) => {
|
|
258
287
|
if (waitRoot) {
|
|
259
288
|
waitRoot.innerHTML = `
|
|
@@ -265,6 +294,7 @@ document.addEventListener("DOMContentLoaded", async () => {
|
|
|
265
294
|
<a class='btn' href='${location.href}'>Retry</a>
|
|
266
295
|
</div>
|
|
267
296
|
`
|
|
297
|
+
renderWaitDebug()
|
|
268
298
|
} else {
|
|
269
299
|
alert(message)
|
|
270
300
|
}
|
|
@@ -272,6 +302,8 @@ document.addEventListener("DOMContentLoaded", async () => {
|
|
|
272
302
|
|
|
273
303
|
try {
|
|
274
304
|
setWaitLabel("Enabling secure localhost access...")
|
|
305
|
+
pushWaitDebugEvent("saving secure localhost flags")
|
|
306
|
+
renderWaitDebug()
|
|
275
307
|
const networkResponse = await fetch("/network", {
|
|
276
308
|
method: "post",
|
|
277
309
|
headers: { "Content-Type": "application/json" },
|
|
@@ -285,8 +317,12 @@ document.addEventListener("DOMContentLoaded", async () => {
|
|
|
285
317
|
if (networkResponse && networkResponse.error) {
|
|
286
318
|
throw new Error(networkResponse.error)
|
|
287
319
|
}
|
|
320
|
+
pushWaitDebugEvent("secure localhost flags saved")
|
|
321
|
+
renderWaitDebug()
|
|
288
322
|
|
|
289
323
|
setWaitLabel("Restarting Pinokio...")
|
|
324
|
+
pushWaitDebugEvent("restart requested")
|
|
325
|
+
renderWaitDebug()
|
|
290
326
|
try {
|
|
291
327
|
await fetch("/restart", {
|
|
292
328
|
method: "post"
|
|
@@ -298,13 +334,15 @@ document.addEventListener("DOMContentLoaded", async () => {
|
|
|
298
334
|
const startedAt = Date.now()
|
|
299
335
|
let lastKnownError = null
|
|
300
336
|
let lastKnownPhase = null
|
|
337
|
+
renderWaitDebug({ startedAt })
|
|
301
338
|
|
|
302
339
|
await new Promise((resolve, reject) => {
|
|
303
340
|
const interval = setInterval(async () => {
|
|
304
341
|
try {
|
|
305
|
-
const [routerStatus, startupStatus] = await Promise.all([
|
|
342
|
+
const [routerStatus, startupStatus, serverDebug] = await Promise.all([
|
|
306
343
|
fetch("/check_router_up").then((res) => res.json()),
|
|
307
|
-
fetch("/pinokio/startup_status").then((res) => res.json()).catch(() => null)
|
|
344
|
+
fetch("/pinokio/startup_status").then((res) => res.json()).catch(() => null),
|
|
345
|
+
fetch("/pinokio/secure_router_debug").then((res) => res.json()).catch(() => null)
|
|
308
346
|
])
|
|
309
347
|
|
|
310
348
|
if (routerStatus && routerStatus.success) {
|
|
@@ -319,16 +357,15 @@ document.addEventListener("DOMContentLoaded", async () => {
|
|
|
319
357
|
if (startupStatus && startupStatus.error) {
|
|
320
358
|
lastKnownError = startupStatus.error
|
|
321
359
|
}
|
|
360
|
+
trackWaitDebug({ routerStatus, startupStatus })
|
|
322
361
|
if (startupStatus && startupStatus.phase) {
|
|
323
|
-
lastKnownPhase =
|
|
324
|
-
const
|
|
325
|
-
? ROUTER_STAGE_MESSAGES[routerStatus.stage]
|
|
326
|
-
: null
|
|
327
|
-
const phaseMessage = routerStageMessage || (startupStatus.phase === "ready"
|
|
362
|
+
lastKnownPhase = startupStatus.phase
|
|
363
|
+
const phaseMessage = startupStatus.phase === "ready"
|
|
328
364
|
? "Secure router is almost ready..."
|
|
329
|
-
: `Restarting Pinokio... (${startupStatus.phase.replace(/_/g, " ")})`
|
|
365
|
+
: `Restarting Pinokio... (${startupStatus.phase.replace(/_/g, " ")})`
|
|
330
366
|
setWaitLabel(phaseMessage)
|
|
331
367
|
}
|
|
368
|
+
renderWaitDebug({ startedAt, routerStatus, startupStatus, serverDebug })
|
|
332
369
|
|
|
333
370
|
if (startupStatus && startupStatus.phase === "error") {
|
|
334
371
|
clearInterval(interval)
|
|
@@ -339,10 +376,14 @@ document.addEventListener("DOMContentLoaded", async () => {
|
|
|
339
376
|
if ((Date.now() - startedAt) >= WAIT_TIMEOUT_MS) {
|
|
340
377
|
clearInterval(interval)
|
|
341
378
|
const detail = lastKnownError || lastKnownPhase || "secure localhost router did not come up"
|
|
379
|
+
pushWaitDebugEvent(`timeout -> ${detail}`)
|
|
380
|
+
renderWaitDebug({ startedAt, routerStatus, startupStatus })
|
|
342
381
|
reject(new Error(`Timed out waiting for restart: ${detail}`))
|
|
343
382
|
}
|
|
344
383
|
} catch (error) {
|
|
345
384
|
lastKnownError = error && error.message ? error.message : String(error)
|
|
385
|
+
pushWaitDebugEvent(`poll error -> ${lastKnownError}`)
|
|
386
|
+
renderWaitDebug({ startedAt })
|
|
346
387
|
if ((Date.now() - startedAt) >= WAIT_TIMEOUT_MS) {
|
|
347
388
|
clearInterval(interval)
|
|
348
389
|
reject(new Error(`Timed out waiting for restart: ${lastKnownError}`))
|