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 CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "pinokiod",
3
- "version": "7.1.68",
3
+ "version": "7.1.69",
4
4
  "description": "",
5
5
  "main": "index.js",
6
6
  "scripts": {
package/server/index.js CHANGED
@@ -5480,53 +5480,80 @@ class Server {
5480
5480
  return list
5481
5481
  }
5482
5482
  async check_router_up() {
5483
- let response
5484
- let config
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
- config = res.data
5490
- } catch (e) {
5491
- response = {
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
- if (!response) {
5498
- if (config === null || typeof config === "undefined") {
5499
- response = {
5500
- stage: "caddy_config_empty",
5501
- error: "caddy config not yet loaded"
5502
- }
5503
- } else if (!/pinokio\.localhost/.test(JSON.stringify(config))) {
5504
- response = {
5505
- stage: "caddy_route_missing",
5506
- error: "pinokio.localhost missing from caddy config"
5507
- }
5508
- } else {
5509
- let router_running = false
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 (!response) {
5527
- response = { success: true, stage: "ready" }
5514
+ if (!router_running) {
5515
+ return { error: "pinokio.localhost not yet available" }
5528
5516
  }
5529
- return response
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
- const routerStatus = await this.check_router_up()
11442
- if (!routerStatus.success) {
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({
@@ -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 ROUTER_STAGE_MESSAGES = {
247
- caddy_admin_unavailable: "Restarting Pinokio... (waiting for Caddy)",
248
- caddy_config_empty: "Restarting Pinokio... (publishing secure router)",
249
- caddy_route_missing: "Restarting Pinokio... (loading pinokio.localhost)",
250
- pinokio_router_missing: "Restarting Pinokio... (waiting for Pinokio router)"
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 = (routerStatus && routerStatus.stage) || startupStatus.phase
324
- const routerStageMessage = routerStatus && routerStatus.stage
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}`))