mirror of
https://github.com/aljazceru/pear-docs.git
synced 2025-12-17 22:44:21 +01:00
201
index.html
201
index.html
@@ -1,4 +1,5 @@
|
|||||||
<!DOCTYPE html>
|
<!DOCTYPE html>
|
||||||
|
|
||||||
<body>
|
<body>
|
||||||
<style>
|
<style>
|
||||||
@font-face {
|
@font-face {
|
||||||
@@ -7,34 +8,36 @@
|
|||||||
font-weight: 400;
|
font-weight: 400;
|
||||||
font-style: normal;
|
font-style: normal;
|
||||||
}
|
}
|
||||||
|
|
||||||
@font-face {
|
@font-face {
|
||||||
font-family: 'overpass-mono';
|
font-family: 'overpass-mono';
|
||||||
src: url('~redhat-overpass-font/webfonts/overpass-mono-webfont/overpass-mono-bold.woff2') format('woff2');
|
src: url('~redhat-overpass-font/webfonts/overpass-mono-webfont/overpass-mono-bold.woff2') format('woff2');
|
||||||
font-weight: 600;
|
font-weight: 600;
|
||||||
font-style: normal;
|
font-style: normal;
|
||||||
}
|
}
|
||||||
|
|
||||||
body {
|
body {
|
||||||
background: #151517;
|
background: #151517;
|
||||||
box-sizing: border-box;
|
box-sizing: border-box;
|
||||||
border-radius: 8px;
|
border-radius: 8px;
|
||||||
font-family:'overpass-mono';
|
font-family: 'overpass-mono';
|
||||||
-webkit-font-smoothing: antialiased;
|
-webkit-font-smoothing: antialiased;
|
||||||
color: #efeaea;
|
color: #efeaea;
|
||||||
transition: background-color .4s, color .4s;
|
transition: background-color .4s, color .4s;
|
||||||
}
|
}
|
||||||
|
|
||||||
::-webkit-scrollbar {
|
::-webkit-scrollbar {
|
||||||
width: 7px;
|
width: 7px;
|
||||||
height: 7px;
|
height: 7px;
|
||||||
}
|
}
|
||||||
|
|
||||||
::-webkit-scrollbar-track {
|
::-webkit-scrollbar-track {
|
||||||
background: #151517;
|
background: #151517;
|
||||||
}
|
}
|
||||||
|
|
||||||
::-webkit-scrollbar-thumb {
|
::-webkit-scrollbar-thumb {
|
||||||
background: #727272;
|
background: #727272;
|
||||||
}
|
}
|
||||||
|
|
||||||
html.light body {
|
html.light body {
|
||||||
background: #efeaea;
|
background: #efeaea;
|
||||||
@@ -51,12 +54,11 @@
|
|||||||
nav {
|
nav {
|
||||||
height: 146px;
|
height: 146px;
|
||||||
float: left;
|
float: left;
|
||||||
padding-left: 2em;
|
padding-left: .75rem;
|
||||||
padding-top: 2em;
|
padding-top: 2em;
|
||||||
margin-right: 30rem;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
nav > a {
|
nav>a {
|
||||||
display: block;
|
display: block;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -79,9 +81,9 @@
|
|||||||
|
|
||||||
header {
|
header {
|
||||||
top: 0;
|
top: 0;
|
||||||
left:0;
|
left: 0;
|
||||||
height: 170px;
|
height: 170px;
|
||||||
z-index:10;
|
z-index: 10;
|
||||||
background: rgba(21, 21, 23, 0.9);
|
background: rgba(21, 21, 23, 0.9);
|
||||||
padding-top: 20px;
|
padding-top: 20px;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
@@ -97,28 +99,62 @@
|
|||||||
user-select: none;
|
user-select: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
h1 { padding: .5rem; border-right: 1px solid #B0D944; border-bottom: 1px solid #B0D944; display: inline-block; padding-right: 0.75em; padding-left: 0.5em; font-weight: bold; font-size: 1.6rem; margin-block-start: 0.67em; margin-block-end: 0.67em; }
|
h1 {
|
||||||
blockquote { outline: 1px solid #323532; margin-inline-start: 0; margin-inline-end: 0; display: block; margin-block-start: 1rem; margin-block-end: 0; padding: 1px; font-size: .825rem }
|
padding: .5rem;
|
||||||
blockquote::before { content: "ℹ"; float: left; font-size: 1.625rem; margin-left: 1rem; margin-right: 0.625rem; }
|
border-right: 1px solid #B0D944;
|
||||||
.col { max-width: 63rem; margin: 0 auto; margin-top: 1rem; }
|
border-bottom: 1px solid #B0D944;
|
||||||
|
display: inline-block;
|
||||||
|
padding-right: 0.75em;
|
||||||
|
padding-left: 0.5em;
|
||||||
|
font-weight: bold;
|
||||||
|
font-size: 1.6rem;
|
||||||
|
margin-block-start: 0.67em;
|
||||||
|
margin-block-end: 0.67em;
|
||||||
|
}
|
||||||
|
|
||||||
#back, #mode {
|
blockquote {
|
||||||
width: 32px;
|
outline: 1px solid #323532;
|
||||||
height: 32px;
|
margin-inline-start: 0;
|
||||||
position: absolute;
|
margin-inline-end: 0;
|
||||||
right: 0.4rem;
|
display: block;
|
||||||
cursor: pointer;
|
margin-block-start: 1rem;
|
||||||
user-select: none;
|
margin-block-end: 0;
|
||||||
opacity: .65;
|
padding: 1px;
|
||||||
}
|
font-size: .825rem
|
||||||
|
}
|
||||||
|
|
||||||
#back {
|
blockquote::before {
|
||||||
top: 10px;
|
content: "ℹ";
|
||||||
}
|
float: left;
|
||||||
|
font-size: 1.625rem;
|
||||||
|
margin-left: 1rem;
|
||||||
|
margin-right: 0.625rem;
|
||||||
|
}
|
||||||
|
|
||||||
#mode {
|
.col {
|
||||||
top: 60px;
|
max-width: 63rem;
|
||||||
}
|
margin: 0 auto;
|
||||||
|
margin-top: 1rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
#back,
|
||||||
|
#mode {
|
||||||
|
width: 32px;
|
||||||
|
height: 32px;
|
||||||
|
position: absolute;
|
||||||
|
right: 0.4rem;
|
||||||
|
cursor: pointer;
|
||||||
|
user-select: none;
|
||||||
|
opacity: .65;
|
||||||
|
}
|
||||||
|
|
||||||
|
#back {
|
||||||
|
top: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
#mode {
|
||||||
|
top: 60px;
|
||||||
|
}
|
||||||
|
|
||||||
#bar {
|
#bar {
|
||||||
backdrop-filter: blur(64px);
|
backdrop-filter: blur(64px);
|
||||||
@@ -135,58 +171,87 @@
|
|||||||
left: 0;
|
left: 0;
|
||||||
top: 0;
|
top: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
#bar:hover {
|
#bar:hover {
|
||||||
outline: #B0D944;
|
outline: #B0D944;
|
||||||
}
|
}
|
||||||
|
|
||||||
pear-ctrl {
|
pear-ctrl {
|
||||||
margin-top: 9px;
|
margin-top: 9px;
|
||||||
margin-left: 9px;
|
margin-left: 9px;
|
||||||
}
|
}
|
||||||
pear-ctrl[data-platform="dawrin"] { float: left; margin-top: 4px; }
|
|
||||||
|
|
||||||
system-status, docs-viewer { position: relative; top: 156px }
|
pear-ctrl[data-platform="dawrin"] {
|
||||||
|
float: left;
|
||||||
|
margin-top: 4px;
|
||||||
|
}
|
||||||
|
|
||||||
a:visited, a:active, a { color: #B0D944; outline: none; text-decoration: none; }
|
system-status,
|
||||||
app-router a:visited, app-router a:active, app-router a {
|
docs-viewer,
|
||||||
|
developer-tooling {
|
||||||
|
position: relative;
|
||||||
|
top: 156px
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
a:visited,
|
||||||
|
a:active,
|
||||||
|
a {
|
||||||
|
color: #B0D944;
|
||||||
|
outline: none;
|
||||||
|
text-decoration: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
app-router a:visited,
|
||||||
|
app-router a:active,
|
||||||
|
app-router a {
|
||||||
color: #B0D944;
|
color: #B0D944;
|
||||||
}
|
}
|
||||||
app-router[data-load="system-status"] a[href='/'], app-router[data-load="system-status"] a:active[href='/'], app-router[data-load="system-status"] a:visited[href='/'],
|
|
||||||
app-router[data-load="docs-viewer"] a[href='/documentation'], app-router[data-load="docs-viewer"] a:active[href='/documentation'], app-router[data-load="docs-viewer"] a:visited[href='/documentation'] {
|
app-router[data-load="system-status"] a[href='/'],
|
||||||
|
app-router[data-load="system-status"] a:active[href='/'],
|
||||||
|
app-router[data-load="system-status"] a:visited[href='/'],
|
||||||
|
app-router[data-load="docs-viewer"] a[href='/documentation'],
|
||||||
|
app-router[data-load="docs-viewer"] a:active[href='/documentation'],
|
||||||
|
app-router[data-load="docs-viewer"] a:visited[href='/documentation'],
|
||||||
|
app-router[data-load="developer-tooling"] a[href='/devtools'],
|
||||||
|
app-router[data-load="developer-tooling"] a:active[href='/devtools'],
|
||||||
|
app-router[data-load="developer-tooling"] a:visited[href='/devtools'] {
|
||||||
color: rgb(78, 250, 92);
|
color: rgb(78, 250, 92);
|
||||||
}
|
}
|
||||||
|
|
||||||
</style>
|
</style>
|
||||||
<div id="bar"><pear-ctrl></pear-ctrl></div>
|
<div id="bar"><pear-ctrl></pear-ctrl></div>
|
||||||
<app-router docs-viewer="/documentation" system-status="/" data-load="system-status">
|
<app-router docs-viewer="/documentation" developer-tooling="/devtools" system-status="/" data-load="system-status">
|
||||||
<header>
|
<header>
|
||||||
<div id="headin">
|
<div id="headin">
|
||||||
<svg id="logo" width="102" height="146" viewBox="0 0 102 146" fill="none" xmlns="http://www.w3.org/2000/svg">
|
<svg id="logo" width="102" height="146" viewBox="0 0 102 146" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||||
<g clip-path="url(#clip0_8912_10861)">
|
<g clip-path="url(#clip0_8912_10861)">
|
||||||
<path d="M47.4056 0.838379H54.5943V15.0361H47.4056V0.838379Z" fill="#B0D944"/>
|
<path d="M47.4056 0.838379H54.5943V15.0361H47.4056V0.838379Z" fill="#B0D944" />
|
||||||
<path d="M43.8113 19.5305V22.406H36.6226V26.0004H65.3774V22.406H58.1887V16.8347H51V19.5305H43.8113Z" fill="#B0D944"/>
|
<path d="M43.8113 19.5305V22.406H36.6226V26.0004H65.3774V22.406H58.1887V16.8347H51V19.5305H43.8113Z" fill="#B0D944" />
|
||||||
<path d="M72.5662 27.7974H51V30.4931H29.4339V36.963H72.5662V27.7974Z" fill="#B0D944"/>
|
<path d="M72.5662 27.7974H51V30.4931H29.4339V36.963H72.5662V27.7974Z" fill="#B0D944" />
|
||||||
<path d="M79.7548 38.7593H51V41.455H22.2451V47.9249H79.7548V38.7593Z" fill="#B0D944"/>
|
<path d="M79.7548 38.7593H51V41.455H22.2451V47.9249H79.7548V38.7593Z" fill="#B0D944" />
|
||||||
<path d="M79.7548 49.7219H51V52.4177H22.2451V58.8875H79.7548V49.7219Z" fill="#B0D944"/>
|
<path d="M79.7548 49.7219H51V52.4177H22.2451V58.8875H79.7548V49.7219Z" fill="#B0D944" />
|
||||||
<path d="M86.9436 60.6846H51V63.3803H15.0565V69.8502H86.9436V60.6846Z" fill="#B0D944"/>
|
<path d="M86.9436 60.6846H51V63.3803H15.0565V69.8502H86.9436V60.6846Z" fill="#B0D944" />
|
||||||
<path d="M86.9436 71.6481H51V74.3438H15.0565V80.8137H86.9436V71.6481Z" fill="#B0D944"/>
|
<path d="M86.9436 71.6481H51V74.3438H15.0565V80.8137H86.9436V71.6481Z" fill="#B0D944" />
|
||||||
<path d="M94.1323 82.61H51V85.3058H7.86774V91.7756H94.1323V82.61Z" fill="#B0D944"/>
|
<path d="M94.1323 82.61H51V85.3058H7.86774V91.7756H94.1323V82.61Z" fill="#B0D944" />
|
||||||
<path d="M101.321 93.5726H51V96.2684H0.679016V102.738H101.321V93.5726Z" fill="#B0D944"/>
|
<path d="M101.321 93.5726H51V96.2684H0.679016V102.738H101.321V93.5726Z" fill="#B0D944" />
|
||||||
<path d="M101.321 104.536H51V107.232H0.679016V113.702H101.321V104.536Z" fill="#B0D944"/>
|
<path d="M101.321 104.536H51V107.232H0.679016V113.702H101.321V104.536Z" fill="#B0D944" />
|
||||||
<path d="M101.321 115.499H51V118.195H0.679016V124.664H101.321V115.499Z" fill="#B0D944"/>
|
<path d="M101.321 115.499H51V118.195H0.679016V124.664H101.321V115.499Z" fill="#B0D944" />
|
||||||
<path d="M86.9436 126.461H51V129.156H15.0565V135.626H86.9436V126.461Z" fill="#B0D944"/>
|
<path d="M86.9436 126.461H51V129.156H15.0565V135.626H86.9436V126.461Z" fill="#B0D944" />
|
||||||
<path d="M72.5662 137.424H51V140.12H29.4339V144.613H72.5662V137.424Z" fill="#B0D944"/>
|
<path d="M72.5662 137.424H51V140.12H29.4339V144.613H72.5662V137.424Z" fill="#B0D944" />
|
||||||
</g>
|
</g>
|
||||||
<defs>
|
<defs>
|
||||||
<clipPath id="clip0_8912_10861">
|
<clipPath id="clip0_8912_10861">
|
||||||
<rect width="100.642" height="145.571" fill="white" transform="translate(0.679016 0.214233)"/>
|
<rect width="100.642" height="145.571" fill="white" transform="translate(0.679016 0.214233)" />
|
||||||
</clipPath>
|
</clipPath>
|
||||||
</defs>
|
</defs>
|
||||||
</svg>
|
</svg>
|
||||||
<img id="mode" src="/assets/light.svg" onclick="document.documentElement.classList.toggle('light');">
|
<img id="mode" src="/assets/light.svg" onclick="document.documentElement.classList.toggle('light');">
|
||||||
<img id="back" src="/assets/arrow.svg" onclick="history.back()">
|
<img id="back" src="/assets/arrow.svg" onclick="history.back()">
|
||||||
<nav>
|
<nav>
|
||||||
<a href="/" style="text-indent: -1rem">System Status</a>
|
<a href="/">System Status</a>
|
||||||
<a href="/documentation">Documentation</a>
|
<a href="/documentation">Documentation</a>
|
||||||
|
<a href="/devtools">Developer Tooling</a>
|
||||||
</nav>
|
</nav>
|
||||||
<pre>
|
<pre>
|
||||||
__ \ _ \ _` | __|
|
__ \ _ \ _` | __|
|
||||||
@@ -196,14 +261,18 @@
|
|||||||
</pre>
|
</pre>
|
||||||
</div>
|
</div>
|
||||||
</header>
|
</header>
|
||||||
<section id="status">
|
<section>
|
||||||
<div class="col"><system-status></system-status></div>
|
<div class="col"><system-status></system-status></div>
|
||||||
</section>
|
</section>
|
||||||
<script type='module' src='./lib/system-status.js'></script>
|
<script type='module' src='./lib/system-status.js'></script>
|
||||||
<section id="documentation">
|
<section>
|
||||||
<div class="col"><docs-viewer></docs-viewer></div>
|
<div class="col"><docs-viewer></docs-viewer></div>
|
||||||
</section>
|
</section>
|
||||||
<script type='module' src='./lib/docs-viewer.js'></script>
|
<script type='module' src='./lib/docs-viewer.js'></script>
|
||||||
|
<section>
|
||||||
|
<div class="col"><developer-tooling></devtools></div>
|
||||||
|
</section>
|
||||||
|
<script type='module' src='./lib/devtools.js'></script>
|
||||||
</app-router>
|
</app-router>
|
||||||
<script type='module' src='./lib/app-router.js'></script>
|
<script type='module' src='./lib/app-router.js'></script>
|
||||||
</body>
|
</body>
|
||||||
|
|||||||
@@ -49,6 +49,8 @@ customElements.define('app-router', class AppRouter extends HTMLElement {
|
|||||||
window.addEventListener('load', () => {
|
window.addEventListener('load', () => {
|
||||||
if (Pear.config.link.indexOf('pear://pulse') === 0) {
|
if (Pear.config.link.indexOf('pear://pulse') === 0) {
|
||||||
this.load(Pear.config.link.slice(12)).catch(console.error)
|
this.load(Pear.config.link.slice(12)).catch(console.error)
|
||||||
|
} else {
|
||||||
|
this.load('/')
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|||||||
278
lib/devtools.js
Normal file
278
lib/devtools.js
Normal file
@@ -0,0 +1,278 @@
|
|||||||
|
/* eslint-env browser */
|
||||||
|
import http from 'http'
|
||||||
|
import { WebSocketServer } from 'ws'
|
||||||
|
import { Session } from '@holepunchto/pear-inspect'
|
||||||
|
import b4a from 'b4a'
|
||||||
|
|
||||||
|
customElements.define('developer-tooling', class extends HTMLElement {
|
||||||
|
router = null
|
||||||
|
|
||||||
|
constructor () {
|
||||||
|
super()
|
||||||
|
this.template = document.createElement('template')
|
||||||
|
this.template.innerHTML = `
|
||||||
|
<div>
|
||||||
|
<style>
|
||||||
|
#add-key-input {
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
#add-key-error {
|
||||||
|
color: red;
|
||||||
|
}
|
||||||
|
|
||||||
|
#no-apps.hidden {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.app {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
|
.app .title {
|
||||||
|
white-space: nowrap;
|
||||||
|
overflow: hidden;
|
||||||
|
text-overflow: ellipsis;
|
||||||
|
}
|
||||||
|
.app:hover .remove {
|
||||||
|
display: block;
|
||||||
|
}
|
||||||
|
.app .remove {
|
||||||
|
cursor: pointer;
|
||||||
|
padding-right: 10px;
|
||||||
|
margin-left: calc(-1rem - 10px);
|
||||||
|
width: 1rem;
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
#remote-inspect-explain {
|
||||||
|
float:left;
|
||||||
|
max-width:55%;
|
||||||
|
}
|
||||||
|
#remote-inspect {
|
||||||
|
float:right;
|
||||||
|
max-width:40%;
|
||||||
|
}
|
||||||
|
|
||||||
|
h2 { margin: 0 }
|
||||||
|
p {
|
||||||
|
margin-block-start: 0.75em;
|
||||||
|
margin-block-end: 0.75em;
|
||||||
|
}
|
||||||
|
|
||||||
|
input {
|
||||||
|
all: unset;
|
||||||
|
border: 1px ridge #B0D944;
|
||||||
|
background: #000;
|
||||||
|
color: #B0D944;
|
||||||
|
padding: .45rem;
|
||||||
|
font-family: monospace;
|
||||||
|
font-size: 1rem;
|
||||||
|
line-height: 1rem;
|
||||||
|
}
|
||||||
|
code {
|
||||||
|
background: #3a4816;
|
||||||
|
color: #efeaea;
|
||||||
|
padding: 0.25rem;
|
||||||
|
padding-top: 0.1rem;
|
||||||
|
padding-bottom: 0.15rem;
|
||||||
|
font-family: 'overpass-mono';
|
||||||
|
border-radius: 1px;
|
||||||
|
font-size: .9em;
|
||||||
|
}
|
||||||
|
pre > code { display: block; line-height: 1.025rem; padding-left: 1em; background: #181e19 }
|
||||||
|
</style>
|
||||||
|
|
||||||
|
<div>
|
||||||
|
<h1>Developer Tooling</h1>
|
||||||
|
<div id=remote-inspect-explain>
|
||||||
|
<h2>Remotely inspect Pear applications.</h2>
|
||||||
|
|
||||||
|
<p> Some application setup is required to enable remote debugging </p>
|
||||||
|
<p> First install the <code>pear-inspect</code> module into the application </p>
|
||||||
|
<pre><code>npm install pear-inspect</code></pre>
|
||||||
|
<p> Then add the following JavaScript code to the application, at the top: </p>
|
||||||
|
|
||||||
|
<pre><code>if (Pear.config.dev) {
|
||||||
|
const { Inspector } = await import('pear-inspect')
|
||||||
|
const inpector = await new Inspector()
|
||||||
|
const key = await inpector.enable()
|
||||||
|
console.log('Pear Inspector key:', key.toString('hex'))
|
||||||
|
}</code></pre>
|
||||||
|
|
||||||
|
<p>When the application is opened in development mode the inspection key will be logged.</p>
|
||||||
|
<p>Paste the logged key into the input and use a compatible inspect protocol tool, such as chrome://inspect to view the remote target</p>
|
||||||
|
</div>
|
||||||
|
<div id=remote-inspect>
|
||||||
|
<div>
|
||||||
|
<form id="add-key-form">
|
||||||
|
<input id="add-key-input" type="text" placeholder="Paste Pear Inspector Key Here"/>
|
||||||
|
<p id="add-key-error"></p>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
<h2>Apps</h2>
|
||||||
|
<h3 id="no-apps">No apps added. Add an inspect key to start debugging.</h3>
|
||||||
|
<div id="apps"></div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
`
|
||||||
|
this.root = this.attachShadow({ mode: 'open' })
|
||||||
|
this.root.appendChild(this.template.content.cloneNode(true))
|
||||||
|
|
||||||
|
this.addKeyFormElem = this.root.querySelector('#add-key-form')
|
||||||
|
this.addKeyInputElem = this.root.querySelector('#add-key-input')
|
||||||
|
this.addKeyErrorElem = this.root.querySelector('#add-key-error')
|
||||||
|
this.appsElem = this.root.querySelector('#apps')
|
||||||
|
this.noAppsElem = this.root.querySelector('#no-apps')
|
||||||
|
this.apps = new Map()
|
||||||
|
|
||||||
|
this.addKeyInputElem.addEventListener('keypress', e => {
|
||||||
|
this.addKeyErrorElem.textContent = ''
|
||||||
|
})
|
||||||
|
|
||||||
|
this.addKeyFormElem.addEventListener('submit', e => {
|
||||||
|
e.preventDefault()
|
||||||
|
const inspectorKey = this.addKeyInputElem.value
|
||||||
|
if (inspectorKey.length !== 64) {
|
||||||
|
this.addKeyErrorElem.textContent = 'Key needs to be 64 characters long'
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
const sessionId = generateUuid()
|
||||||
|
const inspectorSession = new Session({ inspectorKey: b4a.from(inspectorKey, 'hex') })
|
||||||
|
const app = {
|
||||||
|
inspectorKey,
|
||||||
|
title: '',
|
||||||
|
url: '',
|
||||||
|
inspectorSession
|
||||||
|
}
|
||||||
|
|
||||||
|
inspectorSession.on('close', () => {
|
||||||
|
this.apps.delete(sessionId)
|
||||||
|
this.renderApps()
|
||||||
|
})
|
||||||
|
inspectorSession.on('info', ({ filename }) => {
|
||||||
|
app.url = filename
|
||||||
|
app.title = filename.split('/').pop()
|
||||||
|
this.apps.set(sessionId, app)
|
||||||
|
this.renderApps()
|
||||||
|
})
|
||||||
|
|
||||||
|
this.addKeyInputElem.value = ''
|
||||||
|
this.addKeyErrorElem.textContent = ''
|
||||||
|
this.renderApps()
|
||||||
|
})
|
||||||
|
|
||||||
|
const devtoolsHttpServer = http.createServer()
|
||||||
|
const devToolsWsServer = new WebSocketServer({ noServer: true })
|
||||||
|
|
||||||
|
devtoolsHttpServer.listen(9229, () => console.log('[devtoolsHttpServer] running on port 9229'))
|
||||||
|
devtoolsHttpServer.on('request', (req, res) => {
|
||||||
|
if (req.url !== '/json/list') {
|
||||||
|
res.writeHead(404)
|
||||||
|
res.end()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
const targets = [...this.apps].map(([sessionId, app]) => ({
|
||||||
|
description: 'node.js instance', // `Pear app: ${app.name}`,
|
||||||
|
devtoolsFrontendUrl: `devtools://devtools/bundled/js_app.html?experiments=true&v8only=true&ws=127.0.0.1:9229/${sessionId}`,
|
||||||
|
devtoolsFrontendUrlCompat: `devtools://devtools/bundled/inspector.html?experiments=true&v8only=true&ws=127.0.0.1:9229/${sessionId}`,
|
||||||
|
faviconUrl: 'https://nodejs.org/static/images/favicons/favicon.ico',
|
||||||
|
id: sessionId,
|
||||||
|
title: app.title,
|
||||||
|
type: 'node',
|
||||||
|
url: `file://${app.url}`,
|
||||||
|
webSocketDebuggerUrl: `ws://127.0.0.1:9229/${sessionId}`
|
||||||
|
}))
|
||||||
|
|
||||||
|
res.writeHead(200, {
|
||||||
|
'Content-Type': 'application/json; charset=UTF-8',
|
||||||
|
'Cache-Control': 'no-cache',
|
||||||
|
'Content-Length': JSON.stringify(targets).length
|
||||||
|
})
|
||||||
|
res.end(JSON.stringify(targets))
|
||||||
|
})
|
||||||
|
devtoolsHttpServer.on('upgrade', (request, socket, head) => {
|
||||||
|
console.log(`[devtoolsHttpServer] UPGRADE. url=${request.url}`)
|
||||||
|
const sessionId = request.url.substr(1)
|
||||||
|
const sessionIdExists = this.apps.has(sessionId)
|
||||||
|
if (!sessionIdExists) return socket.destroy()
|
||||||
|
|
||||||
|
devToolsWsServer.handleUpgrade(request, socket, head, ws => devToolsWsServer.emit('connection', ws, request))
|
||||||
|
})
|
||||||
|
|
||||||
|
devToolsWsServer.on('connection', (devtoolsSocket, request) => {
|
||||||
|
const sessionId = request.url.substr(1)
|
||||||
|
const app = this.apps.get(sessionId)
|
||||||
|
if (!app) return devtoolsSocket.destroy()
|
||||||
|
|
||||||
|
const { inspectorSession } = app
|
||||||
|
|
||||||
|
const onMessage = msg => {
|
||||||
|
const { pearInspectMethod } = msg
|
||||||
|
const isACDPMessage = !pearInspectMethod
|
||||||
|
|
||||||
|
if (isACDPMessage) return devtoolsSocket.send(JSON.stringify(msg))
|
||||||
|
}
|
||||||
|
inspectorSession.connect()
|
||||||
|
inspectorSession.on('message', onMessage)
|
||||||
|
devtoolsSocket.on('message', msg => inspectorSession.post(JSON.parse(msg)))
|
||||||
|
devtoolsSocket.on('close', () => {
|
||||||
|
inspectorSession.disconnect()
|
||||||
|
inspectorSession.off('message', onMessage)
|
||||||
|
app.connected = false
|
||||||
|
this.renderApps()
|
||||||
|
})
|
||||||
|
|
||||||
|
app.connected = true
|
||||||
|
this.renderApps()
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
renderApps () {
|
||||||
|
this.appsElem.replaceChildren(...[...this.apps].map(([sessionId, app]) => {
|
||||||
|
const div = document.createElement('div')
|
||||||
|
div.innerHTML = `
|
||||||
|
<div class="app">
|
||||||
|
<div class="remove" data-session-id="${sessionId}">✕</div>
|
||||||
|
<div class="title">${app.title} (${app.url})</div>
|
||||||
|
</div>
|
||||||
|
`
|
||||||
|
div.querySelector('.remove').addEventListener('click', () => {
|
||||||
|
this.apps.delete(sessionId)
|
||||||
|
this.renderApps()
|
||||||
|
})
|
||||||
|
|
||||||
|
return div
|
||||||
|
}))
|
||||||
|
|
||||||
|
if (this.apps.size > 0) {
|
||||||
|
this.noAppsElem.classList.add('hidden')
|
||||||
|
} else {
|
||||||
|
this.noAppsElem.classList.remove('hidden')
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
load () {
|
||||||
|
this.style.display = ''
|
||||||
|
}
|
||||||
|
|
||||||
|
unload () {
|
||||||
|
this.style.display = 'none'
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
// Can't use `uuid` module for some reason as it results in a throw with `crypto` when importing
|
||||||
|
function generateUuid () {
|
||||||
|
let result, i, j
|
||||||
|
result = ''
|
||||||
|
for (j = 0; j < 32; j++) {
|
||||||
|
if (j === 8 || j === 12 || j === 16 || j === 20) {
|
||||||
|
result = result + '-'
|
||||||
|
}
|
||||||
|
i = Math.floor(Math.random() * 16).toString(16)
|
||||||
|
result = result + i
|
||||||
|
}
|
||||||
|
return result
|
||||||
|
}
|
||||||
@@ -10,6 +10,10 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"redhat-overpass-font": "^1.0.0"
|
"@holepunchto/pear-inspect": "^3.0.1",
|
||||||
|
"b4a": "^1.6.4",
|
||||||
|
"bare-path": "^2.1.0",
|
||||||
|
"redhat-overpass-font": "^1.0.0",
|
||||||
|
"ws": "^8.16.0"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user