@bananacool467/authtics-host 0.1.2 → 0.1.5

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/README.md CHANGED
@@ -1,6 +1,6 @@
1
1
  # Authtics Host
2
2
 
3
- Version 0.1.2
3
+ Version 0.1.5
4
4
  License: MIT
5
5
 
6
6
  Authtics Host is a framework inspired by Next.js. Authtics Host supports SSR (Server-Side Rendering) and uses esbuild.
@@ -151,19 +151,29 @@ Then when you run your project, you will get a page just saying **"Hello, World!
151
151
 
152
152
  The Developer Panel is what you could use to help you debug your code. The Developer Panel has **7 tabs**:
153
153
 
154
- **Console** — Shows current logs
155
- **Route** — Shows information about the current route
156
- **Webpage Info** — Shows information about the website/webpage
157
- **Network** — Shows the current ping and shows sent fetches from the client and shows received from the server after fetching
158
- **Client Info** — Shows information about your client's User Agent, OS and FPS
159
- **About Host** — Shows the current version of Authtics Host
160
- **Server Info** — Shows how much heap was used and how much CPU was used on the server and how much requests there were and how much users are currently on the site and how long the site has been up
154
+ **Console** — Shows current logs.
155
+ **Route** — Shows information about the current route.
156
+ **Webpage Info** — Shows information about the website/webpage.
157
+ **Network** — Shows the current ping and shows sent fetches from the client and shows received from the server after fetching.
158
+ **Client Info** — Shows information about your client's User Agent, OS and FPS.
159
+ **About Host** — Shows the current version of Authtics Host.
160
+ **Server Info** — Shows how much heap was used and how much CPU was used on the server and how much requests there were and how much users are currently on the site and how long the site has been up.
161
161
 
162
- The information the Developer Panel shows is just your **DAT** (Developer Access Token).
162
+ The information the Developer Panel shows outside of the tabs is just your **DAT** (Developer Access Token).
163
163
 
164
164
  **(NOTE: If you do not set DAT restriction (Which will be explained on how to set it up in the next section), you will only get access to the Console and Network tabs)**
165
165
 
166
- ## Developer Panel Notes And Warnings And DAT (Developer Access Token)
166
+ The Developer Panel also have remote buttons:
167
+
168
+ **Restart App** — Restarts the website.
169
+ **Shut Down App** — Stops the website.
170
+ **Pause Users**/**Resume Users** — Stops users from reaching a site and they will get a JSON error message like this when visiting if Pause Users is on:
171
+ ```json
172
+ { "message": "unhandled request" }
173
+ ```
174
+ unless you click **Resume Users**.
175
+
176
+ ## Developer Panel Notes And DAT (Developer Access Token)
167
177
 
168
178
  A DAT (Developer Access Token) is your token that is used to access the Developer Panel.
169
179
 
@@ -185,7 +195,7 @@ But if you have multiple DATs, then use:
185
195
 
186
196
  There isn't any limit of DATs you can add.
187
197
 
188
- **(Warning: Make sure `devMode` is set to `false` in production. If `devMode` is on and DAT restriction is disabled, anyone can access the restart and shutdown endpoints.)**
198
+ **(NOTE: Adding your DAT will give you access to Restart and Shutdown and Pause/Resume Users features)**
189
199
 
190
200
  ## Contacting The Developer Of Authtics Host
191
201
 
package/dist/cli.js CHANGED
@@ -9,6 +9,7 @@ let config_ = {};
9
9
  let uptime = 0;
10
10
  let totalRequests = 0;
11
11
  let users = 0;
12
+ let usersPaused = false;
12
13
  const jiti = createJiti(import.meta.url);
13
14
  const routes = new Map();
14
15
  const __filename = url.fileURLToPath(import.meta.url);
@@ -96,6 +97,48 @@ export default class App {
96
97
  server;
97
98
  constructor() {
98
99
  this.server = start();
100
+ this.get('/failed-to-handle', async (req, res) => {
101
+ if (!usersPaused) {
102
+ res.writeHead(302, {
103
+ 'Location': '/'
104
+ });
105
+ res.end();
106
+ return;
107
+ }
108
+ ;
109
+ res.writeHead(200, { "Content-Type": "application/json" });
110
+ res.end(JSON.stringify({
111
+ message: "unhandled request"
112
+ }));
113
+ });
114
+ this.post('/__authtics_host_apis__/set-users-paused', async (req, res) => {
115
+ const reqBody = (await getJsonBody(req));
116
+ let datMatched = false;
117
+ if (config_.dat && config_.dat == reqBody.dat)
118
+ datMatched = true;
119
+ if (config_.dat && Array.isArray(config_.dat) && config_.dat.includes(reqBody.dat))
120
+ datMatched = true;
121
+ if (datMatched) {
122
+ usersPaused = reqBody.paused;
123
+ res.writeHead(200, { "Content-Type": "application/json" });
124
+ res.end(JSON.stringify({
125
+ message: "ok"
126
+ }));
127
+ }
128
+ });
129
+ this.post('/__authtics_host_apis__/is-users-paused', async (req, res) => {
130
+ const reqBody = (await getJsonBody(req));
131
+ let datMatched = false;
132
+ if (config_.dat && config_.dat == reqBody.dat)
133
+ datMatched = true;
134
+ if (config_.dat && Array.isArray(config_.dat) && config_.dat.includes(reqBody.dat))
135
+ datMatched = true;
136
+ res.writeHead(200, { "Content-Type": "application/json" });
137
+ res.end(JSON.stringify({
138
+ paused: (datMatched ? false : usersPaused),
139
+ realInfo: usersPaused
140
+ }));
141
+ });
99
142
  this.post('/__authtics_host_apis__/get-dat-restriction-missing', async (req, res) => {
100
143
  const reqBody = (await getJsonBody(req));
101
144
  let datMatched = false;
@@ -266,8 +309,26 @@ export default class App {
266
309
  const pathname = reqBody.pathname;
267
310
  const pagesDir = config_.autoPage === true ? path.join(process.cwd(), config_.autoPageDir || "") : undefined;
268
311
  const safePath = path.normalize(pathname).replace(/^(\.\.[\/\\])+/, '');
269
- const filePath = pagesDir ? path.join(pagesDir, safePath + ".tsx") : undefined;
270
- const fileExists = filePath ? fs.existsSync(filePath) : true;
312
+ let filePath = pagesDir ? path.join(pagesDir, (safePath !== "/" ? safePath : "index") + ".tsx") : undefined;
313
+ let fileExists = filePath ? fs.existsSync(filePath) : true;
314
+ const publicDir = config_.autoFile === true ? path.join(process.cwd(), config_.autoFileDir || "") : undefined;
315
+ if (publicDir && !fileExists) {
316
+ const staticPath = path.join(publicDir, pathname);
317
+ const safePath = path.resolve(staticPath);
318
+ if (safePath.startsWith(path.resolve(publicDir))) {
319
+ filePath = safePath;
320
+ fileExists = fs.existsSync(safePath) && fs.statSync(safePath).isFile();
321
+ }
322
+ }
323
+ if (pathname.startsWith("/api/") && pagesDir != null && !fileExists) {
324
+ const apiFile = path.join(pagesDir, `${pathname}.ts`);
325
+ const apiFileTsx = path.join(pagesDir, `${pathname}.tsx`);
326
+ filePath = fs.existsSync(apiFile) ? apiFile : fs.existsSync(apiFileTsx) ? apiFileTsx : apiFile;
327
+ fileExists = filePath == apiFileTsx ? fs.existsSync(apiFileTsx) : fs.existsSync(apiFile);
328
+ }
329
+ if (!fileExists) {
330
+ filePath = "File is unresolvable. Could be because it's not found.";
331
+ }
271
332
  res.writeHead(200, { "Content-Type": "application/json" });
272
333
  res.end(JSON.stringify({
273
334
  fileExists,
@@ -327,10 +388,6 @@ async function start() {
327
388
  }
328
389
  catch {
329
390
  }
330
- if (config.autoPage == null)
331
- config.autoPage = true;
332
- if (config.autoFile == null)
333
- config.autoFile = true;
334
391
  const PORT = config.port ?? 3000;
335
392
  const showPanel = config.devMode !== false;
336
393
  const autoPaging = config.autoPage !== false;
@@ -402,8 +459,24 @@ async function start() {
402
459
  return res.end(JSON.stringify({ error: e.message }));
403
460
  }
404
461
  }
405
- res.writeHead(404);
406
- return res.end(JSON.stringify({ error: `API route not found: ${pathname}` }));
462
+ const notFoundPath = path.join(__dirname, '404.js');
463
+ if (fs.existsSync(notFoundPath)) {
464
+ try {
465
+ let html = await renderPage(notFoundPath, url, actuallyShowPanel, compiler, hotReload, autoPaging, config.autoPageDir, (routes.get("APP_TSX") || ""));
466
+ res.setHeader("Content-Type", "text/html");
467
+ res.writeHead(404);
468
+ html = html.replace("<script>", "<script>\nwindow.__status_code__ = 404;");
469
+ res.end(html);
470
+ }
471
+ catch (e) {
472
+ res.writeHead(404);
473
+ res.end(`<html><head></head><body><center><b>404</b> | Not found: ${url}</center></body></html>`);
474
+ }
475
+ }
476
+ else {
477
+ res.writeHead(404);
478
+ res.end(`<html><head></head><body><center><b>404</b> | Not found: ${url}</center></body></html>`);
479
+ }
407
480
  }
408
481
  const urlPath = pathname === "/" ? "/index" : pathname;
409
482
  const tsxPath = pagesDir ? path.join(pagesDir, `${urlPath}.tsx`) : undefined;
package/dist/config.d.ts CHANGED
@@ -6,10 +6,10 @@ export interface AuthticsConfig {
6
6
  compilerType?: 'esbuild' | 'babel';
7
7
  hotReload?: boolean;
8
8
  dat?: string | string[];
9
- showError?: boolean | null;
10
- autoPage?: boolean | null;
9
+ showError?: boolean;
10
+ autoPage?: boolean;
11
11
  autoPageDir?: string;
12
- autoFile?: boolean | null;
12
+ autoFile?: boolean;
13
13
  autoFileDir?: string;
14
14
  }
15
15
  export declare function defineConfig(config: AuthticsConfig): AuthticsConfig;
package/dist/config.js CHANGED
@@ -1,7 +1,17 @@
1
1
  export function defineConfig(config) {
2
- if (config.autoPage == null)
2
+ if (config.autoPage == undefined)
3
3
  config.autoPage = true;
4
- if (config.autoFile == null)
4
+ if (config.autoFile == undefined)
5
5
  config.autoFile = true;
6
+ if (config.showError == undefined)
7
+ config.showError = true;
8
+ if (config.compilerType == undefined)
9
+ config.compilerType = 'esbuild';
10
+ if (config.ssr == undefined)
11
+ config.ssr = true;
12
+ if (config.port == undefined || config.port == 0)
13
+ config.port = 3000;
14
+ if (config.devMode == undefined)
15
+ config.devMode = true;
6
16
  return config;
7
17
  }
package/dist/devPanel.js CHANGED
@@ -1,6 +1,6 @@
1
1
  import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
2
2
  import React, { useState, useEffect, useRef } from 'react';
3
- import { ShieldCheck, CircleX, ChevronDown, ChevronUp, Bug, AlertTriangle, Info, ArrowLeft, Wifi, Terminal, Route, Globe, ChevronRight, ChevronLeft, Server, TriangleAlert, Eye } from 'lucide-react';
3
+ import { ShieldCheck, CircleX, ChevronDown, ChevronUp, Bug, AlertTriangle, Info, ArrowLeft, Wifi, Terminal, Route, Globe, ChevronRight, ChevronLeft, Server, TriangleAlert, Eye, Zap } from 'lucide-react';
4
4
  import Prism from 'prismjs';
5
5
  import 'prismjs/components/prism-javascript';
6
6
  Prism.languages.javascript['builtin'] = /\b(window|document|console|navigator|localStorage|sessionStorage|fetch|Promise|setTimeout|setInterval|clearTimeout|clearInterval|requestAnimationFrame|Math|JSON|Object|Array|String|Number|Boolean|Date|RegExp|Error|Map|Set|Symbol|Proxy|Reflect|performance|history|location|screen|crypto|indexedDB|alert|confirm|prompt)\b/;
@@ -63,7 +63,7 @@ function Sparkline({ data, color, label, unit }) {
63
63
  return _jsx("circle", { cx: last[0], cy: last[1], r: "2.5", fill: color });
64
64
  })()] }))] })] }));
65
65
  }
66
- function installNetworkInterceptor(onFetch, setFetch, onBytesClient, onBytesServer) {
66
+ function installNetworkInterceptor(onFetch, setFetch, onEventSource, setEventSource, onWebSocket, setWebSocket, onResource, setResource, onBytesClient, onBytesServer) {
67
67
  if (window.__authtics_network_intercepted__)
68
68
  return;
69
69
  window.__authtics_network_intercepted__ = true;
@@ -100,6 +100,144 @@ function installNetworkInterceptor(onFetch, setFetch, onBytesClient, onBytesServ
100
100
  throw e;
101
101
  }
102
102
  };
103
+ const OriginalWebSocket = window.WebSocket;
104
+ window.WebSocket = function (url, protocols) {
105
+ fetchId++;
106
+ const savedId = fetchId;
107
+ const ws = new OriginalWebSocket(url, protocols);
108
+ if (url.includes('__authtics'))
109
+ return ws;
110
+ onWebSocket({
111
+ url,
112
+ status: 'Connecting...',
113
+ id: savedId,
114
+ type: "WebSocket"
115
+ });
116
+ ws.addEventListener('open', () => {
117
+ setWebSocket({
118
+ url,
119
+ status: 'Connected',
120
+ id: savedId,
121
+ type: "WebSocket"
122
+ });
123
+ });
124
+ ws.addEventListener('close', () => {
125
+ setWebSocket({
126
+ url,
127
+ status: 'Disconnected',
128
+ id: savedId,
129
+ type: "WebSocket"
130
+ });
131
+ });
132
+ ws.addEventListener('message', (event) => {
133
+ const bytes = new Blob([event.data]).size;
134
+ onBytesServer(bytes);
135
+ setWebSocket({
136
+ url,
137
+ status: 'Connected',
138
+ id: savedId,
139
+ type: "WebSocket"
140
+ });
141
+ });
142
+ ws.addEventListener('error', () => {
143
+ const status = ws.readyState === OriginalWebSocket.CLOSED
144
+ ? 'Disconnected'
145
+ : 'Connection Failed';
146
+ setWebSocket({
147
+ url,
148
+ status,
149
+ id: savedId,
150
+ type: "WebSocket"
151
+ });
152
+ });
153
+ const OriginalSend = ws.send;
154
+ ws.send = function (data) {
155
+ let bytes = 0;
156
+ if (typeof data === 'string') {
157
+ bytes = new Blob([data]).size;
158
+ }
159
+ else if (data instanceof Blob) {
160
+ bytes = data.size;
161
+ }
162
+ else if (data instanceof ArrayBuffer || data instanceof SharedArrayBuffer) {
163
+ bytes = data.byteLength;
164
+ }
165
+ else if (ArrayBuffer.isView(data)) {
166
+ bytes = data.byteLength;
167
+ }
168
+ onBytesClient(bytes);
169
+ OriginalSend.call(this, data);
170
+ };
171
+ return ws;
172
+ };
173
+ Object.defineProperty(window.WebSocket, 'prototype', {
174
+ value: OriginalWebSocket.prototype,
175
+ writable: false
176
+ });
177
+ Object.assign(window.WebSocket, OriginalWebSocket);
178
+ const OriginalEventSource = window.EventSource;
179
+ window.EventSource = function (url, eventSourceInitDict) {
180
+ fetchId++;
181
+ const savedId = fetchId;
182
+ const es = new OriginalEventSource(url, eventSourceInitDict);
183
+ if (url.includes('__authtics'))
184
+ return es;
185
+ onEventSource({
186
+ url,
187
+ status: 'Connecting...',
188
+ id: savedId,
189
+ type: "EventSource"
190
+ });
191
+ es.addEventListener('open', () => {
192
+ setEventSource({
193
+ url,
194
+ status: 'Connected',
195
+ id: savedId,
196
+ type: "EventSource"
197
+ });
198
+ });
199
+ es.addEventListener('message', (event) => {
200
+ const bytes = new Blob([event.data]).size;
201
+ onBytesServer(bytes);
202
+ setEventSource({
203
+ url,
204
+ status: 'Connected',
205
+ id: savedId,
206
+ type: "EventSource"
207
+ });
208
+ });
209
+ es.addEventListener('error', () => {
210
+ const status = es.readyState === OriginalEventSource.CLOSED
211
+ ? 'Disconnected'
212
+ : 'Connection Failed';
213
+ setEventSource({
214
+ url,
215
+ status: status,
216
+ id: savedId,
217
+ type: "EventSource"
218
+ });
219
+ });
220
+ return es;
221
+ };
222
+ window.EventSource.prototype = OriginalEventSource.prototype;
223
+ Object.assign(window.EventSource, OriginalEventSource);
224
+ setTimeout(() => {
225
+ const queryImg = document.querySelectorAll('img');
226
+ const queryScript = document.querySelectorAll('script');
227
+ const queryLink = document.querySelectorAll('link');
228
+ queryImg.forEach((img) => {
229
+ if (img.src)
230
+ onResource({ url: img.src, type: 'img', id: fetchId++ });
231
+ });
232
+ queryScript.forEach((script) => {
233
+ if (script.src)
234
+ onResource({ url: script.src, type: 'script', id: fetchId++ });
235
+ });
236
+ queryLink.forEach((link) => {
237
+ if (link.href)
238
+ onResource({ url: link.href, type: 'link', id: fetchId++ });
239
+ });
240
+ }, 5000);
103
241
  }
104
242
  function installConsoleInterceptor() {
105
243
  if (window.__authtics_intercepted__)
@@ -171,6 +309,11 @@ export default function DevPanel() {
171
309
  const [hasIssue, setHasIssue] = useState(false);
172
310
  const [ping__, setPing__] = useState(0);
173
311
  const [networkFetches, setNetworkFetches] = useState([]);
312
+ const [eventSources, setEventSources] = useState([]);
313
+ const [usersPaused, setUsersPaused] = useState(false);
314
+ const [usersPausedRealInfo, setUsersPausedRealInfo] = useState(false);
315
+ const [webSockets, setWebSockets] = useState([]);
316
+ const [resourcesFound, setResourcesFound] = useState([]);
174
317
  const [status, setStatus] = useState(200);
175
318
  const [code, setCode] = useState('');
176
319
  const [pathName, setPathName] = useState(undefined);
@@ -254,7 +397,19 @@ export default function DevPanel() {
254
397
  if (resp.status === 200) {
255
398
  const data = await resp.json();
256
399
  setDatMatch(data.isMatching);
257
- if (!data.isMatching) {
400
+ const resp3 = await fetch('/__authtics_host_apis__/is-users-paused', {
401
+ method: 'POST',
402
+ headers: { 'Content-Type': 'application/json' },
403
+ body: JSON.stringify({ dat: localStorage.getItem('dat') })
404
+ });
405
+ let paused = false;
406
+ if (resp3.status === 200) {
407
+ const data = await resp3.json();
408
+ paused = data.paused;
409
+ setUsersPaused(paused);
410
+ setUsersPausedRealInfo(data.realInfo);
411
+ }
412
+ if (!data.isMatching && !paused) {
258
413
  doc?.getElementById('authtics-dev-panel-root')?.remove();
259
414
  }
260
415
  const resp2 = await fetch('/__authtics_host_apis__/get-dat-restriction-missing', {
@@ -369,11 +524,9 @@ export default function DevPanel() {
369
524
  isSSR();
370
525
  userSettings();
371
526
  getHostVersion();
372
- setInterval(() => {
373
- getUsage();
374
- }, 250);
375
527
  setInterval(() => {
376
528
  update();
529
+ getUsage();
377
530
  }, 500);
378
531
  }
379
532
  }, 250);
@@ -469,7 +622,7 @@ export default function DevPanel() {
469
622
  }, []);
470
623
  useEffect(() => {
471
624
  installConsoleInterceptor();
472
- installNetworkInterceptor((f) => setNetworkFetches(prev => [...prev.slice(-49), f]), (f) => setNetworkFetches(prev => prev.map(p => p.id === f.id ? f : p)), (sent) => {
625
+ installNetworkInterceptor((f) => setNetworkFetches(prev => [...prev.slice(-49), f]), (f) => setNetworkFetches(prev => prev.map(p => p.id === f.id ? f : p)), (f) => setEventSources(prev => [...prev.slice(-49), f]), (f) => setEventSources(prev => prev.map(p => p.id === f.id ? f : p)), (f) => setWebSockets(prev => [...prev.slice(-49), f]), (f) => setWebSockets(prev => prev.map(p => p.id === f.id ? f : p)), (f) => setResourcesFound(prev => [...prev.slice(-49), f]), (f) => setResourcesFound(prev => prev.map(p => p.id === f.id ? f : p)), (sent) => {
473
626
  pendingSent.current += sent;
474
627
  }, (received) => {
475
628
  pendingReceived.current += received;
@@ -595,6 +748,38 @@ export default function DevPanel() {
595
748
  }
596
749
  }));
597
750
  };
751
+ const pause_Resume_Users = async () => {
752
+ if (usersPausedRealInfo) {
753
+ const resp = await fetch('/__authtics_host_apis__/set-users-paused', {
754
+ method: 'POST',
755
+ headers: { 'Content-Type': 'application/json' },
756
+ body: JSON.stringify({
757
+ dat: localStorage.getItem('dat'),
758
+ paused: false
759
+ })
760
+ });
761
+ if (resp.status === 200) {
762
+ setUsersPausedRealInfo(false);
763
+ }
764
+ }
765
+ else {
766
+ const resp = await fetch('/__authtics_host_apis__/set-users-paused', {
767
+ method: 'POST',
768
+ headers: { 'Content-Type': 'application/json' },
769
+ body: JSON.stringify({
770
+ dat: localStorage.getItem('dat'),
771
+ paused: true
772
+ })
773
+ });
774
+ if (resp.status === 200) {
775
+ setUsersPausedRealInfo(true);
776
+ }
777
+ }
778
+ };
779
+ if (usersPaused) {
780
+ doc?.getElementById('root')?.remove();
781
+ window.location.href = '/failed-to-handle';
782
+ }
598
783
  return (_jsxs(_Fragment, { children: [_jsx("div", { style: {
599
784
  position: 'absolute',
600
785
  zIndex: 999999,
@@ -733,7 +918,7 @@ export default function DevPanel() {
733
918
  border: '1px solid #eee',
734
919
  fontSize: '12px',
735
920
  color: '#333',
736
- }, children: [_jsx("span", { children: "Ping" }), _jsx("span", { style: { color: ping__ < 100 ? '#16a34a' : ping__ < 300 ? '#d97706' : '#e53e3e', fontFamily: 'monospace' }, children: ping__ > 0 ? `${ping__}ms` : '??ms' })] }), datRestrictionMissing ? (_jsxs("span", { style: { display: 'flex', opacity: 0.5, fontSize: 10, justifyContent: 'center', alignItems: 'center', gap: '4px' }, children: [_jsx(Info, { size: 10 }), "this analytic is unavaliable. Set \"dat\" in the Authtics Host config to set restriction and then restart."] })) : (_jsx(_Fragment, {})), _jsx(Sparkline, { data: receivedHistory, color: "#3b82f6", label: "Received", unit: " bytes" }), _jsx(Sparkline, { data: sentHistory, color: "#16a34a", label: "Sent", unit: " bytes" }), networkFetches.length === 0
921
+ }, children: [_jsx("span", { children: "Ping" }), _jsx("span", { style: { color: ping__ < 100 ? '#16a34a' : ping__ < 300 ? '#d97706' : '#e53e3e', fontFamily: 'monospace' }, children: ping__ > 0 ? `${ping__}ms` : '??ms' })] }), datRestrictionMissing ? (_jsxs("span", { style: { display: 'flex', opacity: 0.5, fontSize: 10, justifyContent: 'center', alignItems: 'center', gap: '4px' }, children: [_jsx(Info, { size: 10 }), "this analytic is unavaliable. Set \"dat\" in the Authtics Host config to set restriction and then restart."] })) : (_jsx(_Fragment, {})), _jsx(Sparkline, { data: receivedHistory, color: "#3b82f6", label: "Received", unit: " bytes" }), _jsx(Sparkline, { data: sentHistory, color: "#16a34a", label: "Sent", unit: " bytes" }), _jsxs("span", { style: { fontSize: '15px', color: '#333', fontWeight: 'bold' }, children: ["Fetches \u2014 ", networkFetches.length, " total fetches"] }), networkFetches.length === 0
737
922
  ? _jsx("div", { style: { color: '#aaa', fontSize: '12px', padding: '4px 2px' }, children: "No network requests yet." })
738
923
  : [...networkFetches].reverse().map((f, i) => (_jsxs("div", { style: {
739
924
  background: '#fff',
@@ -753,7 +938,25 @@ export default function DevPanel() {
753
938
  obj___.innerText = f.response?.slice(0, 100) + "...";
754
939
  obj___.removeAttribute('expanded');
755
940
  e.currentTarget.innerText = `View more (${f.response ? (f.response.split('').length - 100) : 0} bytes hidden)`;
756
- } }, style: { padding: '8px 10px', borderRadius: '10px', background: '#34a8eb', color: '#fff', border: 'none', cursor: 'pointer', margin: '10px', textAlign: 'center', fontFamily: 'system-ui, sans-serif' }, children: ["View more (", f.response ? (f.response.split('').length - 100) : 0, " bytes hidden)"] })) : (_jsx(_Fragment, {}))) : (_jsx(_Fragment, {}))] }, i)))] })] })) : routeOpen ? (_jsxs(_Fragment, { children: [_jsxs("div", { style: {
941
+ } }, style: { padding: '8px 10px', borderRadius: '10px', background: '#34a8eb', color: '#fff', border: 'none', cursor: 'pointer', margin: '10px', textAlign: 'center', fontFamily: 'system-ui, sans-serif' }, children: ["View more (", f.response ? (f.response.split('').length - 100) : 0, " bytes hidden)"] })) : (_jsx(_Fragment, {}))) : (_jsx(_Fragment, {}))] }, i))), _jsx("span", { style: { fontSize: '15px', color: '#333', fontWeight: 'bold' }, children: "Active connections" }), eventSources.length === 0 ? (_jsx("div", { style: { color: '#aaa', fontSize: '12px', padding: '4px 2px' }, children: "No active connections." })) :
942
+ [...eventSources, ...webSockets].reverse().map((es, i) => (_jsx("div", { style: {
943
+ background: '#fff',
944
+ display: 'flex',
945
+ flexDirection: 'column',
946
+ borderRadius: '10px',
947
+ border: '1px solid #eee',
948
+ fontSize: '11px',
949
+ fontFamily: 'monospace'
950
+ }, children: _jsxs("div", { style: { display: 'flex', justifyContent: 'space-between', gap: '8px', padding: '6px 10px' }, children: [_jsxs("span", { style: { color: '#3b82f6', display: 'flex', gap: '4px', justifyContent: 'center', alignItems: 'center' }, children: [es.type === "EventSource" ? _jsx(Zap, { color: "green", size: 12 }) : es.type === "WebSocket" ? _jsx(Globe, { color: "green", size: 12 }) : _jsx(_Fragment, {}), es.type === "EventSource" ? "Event Source" : es.type === "WebSocket" ? "Web Socket" : "???"] }), _jsx("span", { style: { flex: 1, overflow: 'hidden', textOverflow: 'ellipsis', whiteSpace: 'nowrap', color: '#333' }, children: es.url }), _jsx("span", { style: { color: es.status === 'Connected' ? '#16a34a' : es.status === 'Disconnected' ? '#e53e3e' : 'orange' }, children: es.status === 'Connected' ? 'Active' : es.status === 'Disconnected' ? 'Disconnected' : es.status === 'Connecting...' ? '...' : es.status === 'Connection Failed' ? 'Failed' : 'Unknown' })] }) }, i))), _jsxs("span", { style: { fontSize: '15px', color: '#333', fontWeight: 'bold' }, children: ["Resources Found \u2014 ", resourcesFound.length, " total resources"] }), resourcesFound.length === 0 ? (_jsx("div", { style: { color: '#aaa', fontSize: '12px', padding: '4px 2px' }, children: "No resources found." })) :
951
+ [...resourcesFound].reverse().map((r, i) => (_jsx("div", { style: {
952
+ background: '#fff',
953
+ display: 'flex',
954
+ flexDirection: 'column',
955
+ borderRadius: '10px',
956
+ border: '1px solid #eee',
957
+ fontSize: '11px',
958
+ fontFamily: 'monospace'
959
+ }, children: _jsxs("div", { style: { display: 'flex', justifyContent: 'space-between', gap: '8px', padding: '6px 10px' }, children: [_jsx("span", { style: { color: '#3b82f6', display: 'flex', gap: '4px', justifyContent: 'center', alignItems: 'center' }, children: r.type }), _jsx("span", { style: { flex: 1, color: '#333' }, children: r.url })] }) }, i)))] })] })) : routeOpen ? (_jsxs(_Fragment, { children: [_jsxs("div", { style: {
757
960
  padding: '6px 8px',
758
961
  borderBottom: '1px solid #ddd',
759
962
  background: '#fff',
@@ -997,7 +1200,7 @@ export default function DevPanel() {
997
1200
  gap: '6px',
998
1201
  color: '#fff',
999
1202
  flexDirection: 'row',
1000
- }, children: "Updates to security. Apps with version 0.0.1-beta.9 and over will now require DAT restriction to access remote features like restarting and shutting down the app." }) })) : (_jsx(_Fragment, {})), _jsx(PanelButton, { onClick: () => { restart(); }, fullWidth: true, style: { color: '#fff', justifyContent: 'center', height: '32px', background: '#ba4e4e' }, disabled: datRestrictionMissing, children: _jsx("span", { style: { display: 'flex', alignItems: 'center', gap: '6px', textAlign: 'center' }, children: "Restart App" }) }), datRestrictionMissing ? (_jsxs("span", { style: { display: 'flex', opacity: 0.5, fontSize: 10, justifyContent: 'center', alignItems: 'center', gap: '4px' }, children: [_jsx(Info, { size: 10 }), "Restarting the app is unavaliable. Set \"dat\" in the Authtics Host config to set restriction and then restart."] })) : (_jsx(_Fragment, {})), _jsx(PanelButton, { onClick: () => { shutDown(); }, fullWidth: true, style: { color: '#fff', justifyContent: 'center', height: '32px', background: '#ba4e4e' }, disabled: datRestrictionMissing, children: _jsx("span", { style: { display: 'flex', alignItems: 'center', gap: '6px', textAlign: 'center' }, children: "Shut Down App" }) }), datRestrictionMissing ? (_jsxs("span", { style: { display: 'flex', opacity: 0.5, fontSize: 10, justifyContent: 'center', alignItems: 'center', gap: '4px' }, children: [_jsx(Info, { size: 10 }), "Shutting down the app is unavaliable. Set \"dat\" in the Authtics Host config to set restriction and then restart."] })) : (_jsx(_Fragment, {}))] })] })) }) }), datMatch ? (_jsxs("div", { onClick: () => setOpen(o => !o), style: {
1203
+ }, children: "Updates to security. Apps with version 0.0.1-beta.9 and over will now require DAT restriction to access remote features like restarting and shutting down the app." }) })) : (_jsx(_Fragment, {})), _jsx(PanelButton, { onClick: () => { restart(); }, fullWidth: true, style: { color: '#fff', justifyContent: 'center', height: '32px', background: '#ba4e4e' }, disabled: datRestrictionMissing, children: _jsx("span", { style: { display: 'flex', alignItems: 'center', gap: '6px', textAlign: 'center' }, children: "Restart App" }) }), datRestrictionMissing ? (_jsxs("span", { style: { display: 'flex', opacity: 0.5, fontSize: 10, justifyContent: 'center', alignItems: 'center', gap: '4px' }, children: [_jsx(Info, { size: 10 }), "Restarting the app is unavaliable. Set \"dat\" in the Authtics Host config to set restriction and then restart."] })) : (_jsx(_Fragment, {})), _jsx(PanelButton, { onClick: () => { shutDown(); }, fullWidth: true, style: { color: '#fff', justifyContent: 'center', height: '32px', background: '#ba4e4e' }, disabled: datRestrictionMissing, children: _jsx("span", { style: { display: 'flex', alignItems: 'center', gap: '6px', textAlign: 'center' }, children: "Shut Down App" }) }), datRestrictionMissing ? (_jsxs("span", { style: { display: 'flex', opacity: 0.5, fontSize: 10, justifyContent: 'center', alignItems: 'center', gap: '4px' }, children: [_jsx(Info, { size: 10 }), "Shutting down the app is unavaliable. Set \"dat\" in the Authtics Host config to set restriction and then restart."] })) : (_jsx(_Fragment, {})), _jsx(PanelButton, { onClick: () => { pause_Resume_Users(); }, fullWidth: true, style: { color: '#fff', justifyContent: 'center', height: '32px', background: '#ba4e4e' }, disabled: datRestrictionMissing, children: _jsx("span", { style: { display: 'flex', alignItems: 'center', gap: '6px', textAlign: 'center' }, children: usersPausedRealInfo ? "Resume Users" : "Pause Users" }) }), datRestrictionMissing ? (_jsxs("span", { style: { display: 'flex', opacity: 0.5, fontSize: 10, justifyContent: 'center', alignItems: 'center', gap: '4px' }, children: [_jsx(Info, { size: 10 }), "Pausing users from accessing the app is unavaliable. Set \"dat\" in the Authtics Host config to set restriction and then restart."] })) : (_jsx(_Fragment, {}))] })] })) }) }), datMatch ? (_jsxs("div", { onClick: () => setOpen(o => !o), style: {
1001
1204
  display: 'flex',
1002
1205
  flexDirection: 'row',
1003
1206
  alignItems: 'center',
@@ -162,23 +162,23 @@ export async function renderPage(tsxPath, reqUrl, showPanel = true, compiler = '
162
162
  }
163
163
  if (!clientCode || !serverCode) {
164
164
  const virtualServer = `
165
- import Page from ${JSON.stringify(tsxPath)};
166
165
  ${usesDevPanel ? `import DevPanel from ${JSON.stringify(devPanelPath)};` : ""}
166
+ import Page from ${JSON.stringify(tsxPath)};
167
167
  export default Page;
168
168
  ${usesDevPanel ? `export { DevPanel };` : ""}
169
169
  `;
170
170
  const virtualClient = `
171
171
  import React from "react";
172
172
  import { hydrateRoot } from "react-dom/client";
173
- import Page from ${JSON.stringify(tsxPath)};
174
173
  ${usesDevPanel ? `import DevPanel from ${JSON.stringify(devPanelPath)};` : ""}
174
+ import Page from ${JSON.stringify(tsxPath)};
175
175
 
176
- const rootEl = document.getElementById("root");
177
- if (rootEl) hydrateRoot(rootEl, React.createElement(Page));
178
176
  ${usesDevPanel ? `
179
177
  const panelEl = document.getElementById("authtics-dev-panel-root");
180
178
  if (panelEl) hydrateRoot(panelEl, React.createElement(DevPanel));
181
179
  ` : ""}
180
+ const rootEl = document.getElementById("root");
181
+ if (rootEl) hydrateRoot(rootEl, React.createElement(Page));
182
182
  `;
183
183
  if (compiler === 'babel') {
184
184
  serverCode = await buildWithBabel(tsxPath, virtualServer, 'node');
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@bananacool467/authtics-host",
3
- "version": "0.1.2",
3
+ "version": "0.1.5",
4
4
  "description": "A Next.js-inspired SSR framework for Node.js with TypeScript and JSX support.",
5
5
  "main": "./dist/index.js",
6
6
  "types": "./dist/index.d.ts",
@@ -37,7 +37,8 @@
37
37
  "dev",
38
38
  "developer",
39
39
  "HostJS",
40
- "Host.js"
40
+ "Host.js",
41
+ "website"
41
42
  ],
42
43
  "author": "bananacool467",
43
44
  "license": "MIT",
@@ -46,8 +47,6 @@
46
47
  "@babel/preset-env": "^7.29.0",
47
48
  "@babel/preset-react": "^7.28.5",
48
49
  "@babel/preset-typescript": "^7.28.5",
49
- "@types/babel__core": "^7.20.5",
50
- "@types/babel__preset-env": "^7.10.0",
51
50
  "esbuild": "^0.27.3",
52
51
  "jiti": "^2.6.1",
53
52
  "lucide-react": "^0.577.0",
@@ -63,6 +62,8 @@
63
62
  "@types/prismjs": "^1.26.6",
64
63
  "@types/react": "^19.2.14",
65
64
  "@types/react-dom": "^19.2.3",
66
- "@types/react-syntax-highlighter": "^15.5.13"
65
+ "@types/react-syntax-highlighter": "^15.5.13",
66
+ "@types/babel__core": "^7.20.5",
67
+ "@types/babel__preset-env": "^7.10.0"
67
68
  }
68
69
  }