@bananacool467/authtics-host 0.0.2-beta.3 → 0.1.0

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,13 +1,15 @@
1
1
  # Authtics Host
2
2
 
3
- Version 0.0.2-beta.3
3
+ Version 0.1.0
4
4
  License: MIT
5
5
 
6
- **(NOTE: This version is in BETA, bugs are expected)**
6
+ **(NOTE: THIS IS AUTHTICS HOST'S FIRST RELEASE 🎉🎉🎉)**
7
7
 
8
8
  Authtics Host is a framework inspired by Next.js. Authtics Host supports SSR (Server-Side Rendering) and uses esbuild.
9
9
 
10
- ## Setting up
10
+ **(NOTE: The short name for Authtics Host is HostJS or Host.js)**
11
+
12
+ ## Setting Up
11
13
 
12
14
  To get **Authtics Host** use:
13
15
  ```bash
@@ -98,17 +100,23 @@ export default defineConfig({
98
100
 
99
101
  `client/app.tsx` should look like:
100
102
  ```tsx
101
- import { Route } from "@bananacool467/authtics-host";
103
+ import { Route, RouteMap } from "@bananacool467/authtics-host";
102
104
  import Index from "./pages/index";
103
105
 
104
106
  export default function App() {
105
107
  return (
106
- <>
108
+ <RouteMap>
107
109
  <Route at="/" statusCode={200} page={Index} />
108
- </>
110
+ <RouteMap/>
109
111
  )
110
112
  }
111
113
  ```
114
+ **(NOTE: You can change the `statusCode` to anything you want, the property is optional, it either gives 404 or 200 if the `statusCode` is missing.)**
115
+ **(NOTE: To make an 404 page you can use:**
116
+ ```tsx
117
+ <Route statusCode={404} page={NotFound} />
118
+ ```
119
+ **)**
112
120
 
113
121
  `client/pages/index.tsx` should look like:
114
122
  ```tsx
@@ -140,6 +148,20 @@ node --experimental-strip-types index.ts
140
148
 
141
149
  Then when you run your project, you will get a page just saying **"Hello, World!"** and you should see a clickable Developer Panel at the bottom-right.
142
150
 
151
+ ## About The Developer Panel
152
+
153
+ The Developer Panel is what you could use to help you debug your code. The Developer Panel has **7 tabs**:
154
+
155
+ **Console** — Shows current logs
156
+ **Route** — Shows information about the current route
157
+ **Webpage Info** — Shows information about the website/webpage
158
+ **Network** — Shows the current ping and shows sent fetches from the client and shows received from the server after fetching
159
+ **Client Info** — Shows information about your client's User Agent, OS and FPS
160
+ **About Host** — Shows the current version of Authtics Host
161
+ **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
162
+
163
+ **(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)**
164
+
143
165
  ## Developer Panel Notes And Warnings And DAT (Developer Access Token)
144
166
 
145
167
  A DAT (Developer Access Token) is your token that is used to access the Developer Panel.
package/dist/cli.js CHANGED
@@ -331,7 +331,6 @@ async function start() {
331
331
  config.autoPage = true;
332
332
  if (config.autoFile == null)
333
333
  config.autoFile = true;
334
- console.log(JSON.stringify(config));
335
334
  const PORT = config.port ?? 3000;
336
335
  const showPanel = config.devMode !== false;
337
336
  const autoPaging = config.autoPage !== false;
@@ -411,7 +410,7 @@ async function start() {
411
410
  const htmlPath = pagesDir ? path.join(pagesDir, `${urlPath}.html`) : undefined;
412
411
  if (tsxPath && fs.existsSync(tsxPath)) {
413
412
  try {
414
- const html = await renderPage(tsxPath, url, actuallyShowPanel, compiler, hotReload, autoPaging);
413
+ const html = await renderPage(tsxPath, url, actuallyShowPanel, compiler, hotReload, autoPaging, config.autoPageDir, (routes.get("APP_TSX") || ""));
415
414
  res.setHeader("Content-Type", "text/html");
416
415
  return res.end(html);
417
416
  }
@@ -430,7 +429,7 @@ async function start() {
430
429
  const appPath = path.join(process.cwd(), appTsxPath);
431
430
  if (fs.existsSync(appPath)) {
432
431
  try {
433
- const html = await renderPage(appPath, url, actuallyShowPanel, compiler, hotReload, autoPaging);
432
+ const html = await renderPage(appPath, url, actuallyShowPanel, compiler, hotReload, autoPaging, config.autoPageDir, (routes.get("APP_TSX") || ""));
434
433
  res.setHeader("Content-Type", "text/html");
435
434
  return res.end(html);
436
435
  }
@@ -444,7 +443,7 @@ async function start() {
444
443
  const notFoundPath = path.join(__dirname, '404.js');
445
444
  if (fs.existsSync(notFoundPath)) {
446
445
  try {
447
- let html = await renderPage(notFoundPath, url, actuallyShowPanel, compiler, hotReload, autoPaging);
446
+ let html = await renderPage(notFoundPath, url, actuallyShowPanel, compiler, hotReload, autoPaging, config.autoPageDir, (routes.get("APP_TSX") || ""));
448
447
  res.setHeader("Content-Type", "text/html");
449
448
  res.writeHead(404);
450
449
  html = html.replace("<script>", "<script>\nwindow.__status_code__ = 404;");
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 } from 'lucide-react';
3
+ import { ShieldCheck, CircleX, ChevronDown, ChevronUp, Bug, AlertTriangle, Info, ArrowLeft, Wifi, Terminal, Route, Globe, ChevronRight, ChevronLeft, Server, TriangleAlert, Eye } 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/;
@@ -178,6 +178,7 @@ export default function DevPanel() {
178
178
  const [protocol, setProtocol] = useState(undefined);
179
179
  const [path, setPath] = useState(undefined);
180
180
  const [isSsr, setIsSsr] = useState(false);
181
+ const datRestrictionMissingRef = useRef(true);
181
182
  const cpuUsage = useRef(0);
182
183
  const heapUsage = useRef(0);
183
184
  const [datMatch, setDatMatch] = useState(false);
@@ -191,6 +192,7 @@ export default function DevPanel() {
191
192
  const [users, setUsers] = useState(0);
192
193
  const [token, setToken] = useState(null);
193
194
  const [tokenLength, setTokenLength] = useState(0);
195
+ const [tokenHidden, setTokenHidden] = useState(true);
194
196
  const [consoleInputFocused, setConsoleInputFocused] = useState(false);
195
197
  const consoleInputRef = useRef(null);
196
198
  const overlayRef = useRef(null);
@@ -251,7 +253,6 @@ export default function DevPanel() {
251
253
  setDatMatch(data.isMatching);
252
254
  if (!data.isMatching) {
253
255
  doc?.getElementById('authtics-dev-panel-root')?.remove();
254
- return;
255
256
  }
256
257
  const resp2 = await fetch('/__authtics_host_apis__/get-dat-restriction-missing', {
257
258
  method: 'POST',
@@ -261,8 +262,11 @@ export default function DevPanel() {
261
262
  if (resp2.status === 200) {
262
263
  const data = await resp2.json();
263
264
  setDatRestrictionMissing(!data.enabled);
265
+ datRestrictionMissingRef.current = !data.enabled;
266
+ return "";
264
267
  }
265
268
  }
269
+ return "";
266
270
  };
267
271
  const isSSR = async () => {
268
272
  const resp = await fetch('/__authtics_host_apis__/get-is-ssr', {
@@ -354,20 +358,22 @@ export default function DevPanel() {
354
358
  };
355
359
  setTimeout(async () => {
356
360
  await getDatMatching();
357
- if (datRestrictionMissing === false) {
358
- getPath();
359
- getCompilerType();
360
- getHttpVersion();
361
- isSSR();
362
- userSettings();
363
- getHostVersion();
364
- setInterval(() => {
365
- getUsage();
366
- }, 250);
367
- setInterval(() => {
368
- update();
369
- }, 500);
370
- }
361
+ setTimeout(() => {
362
+ if (datRestrictionMissingRef.current === false) {
363
+ getPath();
364
+ getCompilerType();
365
+ getHttpVersion();
366
+ isSSR();
367
+ userSettings();
368
+ getHostVersion();
369
+ setInterval(() => {
370
+ getUsage();
371
+ }, 250);
372
+ setInterval(() => {
373
+ update();
374
+ }, 500);
375
+ }
376
+ }, 250);
371
377
  }, 250);
372
378
  }, []);
373
379
  const restart = async () => {
@@ -491,7 +497,7 @@ export default function DevPanel() {
491
497
  catch (error) {
492
498
  }
493
499
  window.addEventListener('authtics:log', handler);
494
- setStatus(window.__status_code__ | 200);
500
+ setInterval(() => setStatus(window.__status_code__ || 200), 1000);
495
501
  setPathName(window.location.pathname);
496
502
  setHostName(window.location.hostname);
497
503
  setDoc(document);
@@ -932,7 +938,6 @@ export default function DevPanel() {
932
938
  maxHeight: '260px',
933
939
  flexDirection: 'column',
934
940
  }, children: [_jsxs("div", { style: {
935
- display: 'flex',
936
941
  justifyContent: 'space-between',
937
942
  padding: '6px 10px',
938
943
  background: '#fff',
@@ -940,7 +945,24 @@ export default function DevPanel() {
940
945
  border: '1px solid #eee',
941
946
  fontSize: '12px',
942
947
  color: '#333',
943
- }, children: [_jsx("span", { style: { fontSize: '12px', color: '#333' }, children: "DAT (Developer Access Token)" }), _jsx("span", { style: { fontSize: '12px', color: 'blue' }, children: token })] }), tokenLength !== 16 ? (_jsx(_Fragment, { children: _jsxs("div", { style: {
948
+ display: 'flex'
949
+ }, children: [_jsx("span", { style: { fontSize: '12px', color: '#333', position: 'relative' }, children: "DAT (Developer Access Token)" }), _jsxs("div", { style: { position: 'relative',
950
+ display: 'inline-flex' }, children: [_jsx("span", { style: { fontSize: '12px', color: 'blue' }, children: token }), tokenHidden && (_jsxs("div", { style: {
951
+ position: 'absolute',
952
+ top: 0, left: 0,
953
+ marginTop: '-2.5px',
954
+ width: '100%', height: '100%',
955
+ backdropFilter: 'blur(10px)',
956
+ backgroundColor: 'rgba(255,255,255,0.3)',
957
+ cursor: 'pointer',
958
+ padding: '2.5px 2.5px',
959
+ borderRadius: '8px',
960
+ textAlign: 'center',
961
+ display: 'flex',
962
+ justifyContent: 'center',
963
+ alignItems: 'center',
964
+ gap: '4px'
965
+ }, onClick: () => setTokenHidden(false), children: [_jsx(Eye, { size: 12 }), "Click to reveal"] }))] })] }), tokenLength !== 16 ? (_jsx(_Fragment, { children: _jsxs("div", { style: {
944
966
  display: 'flex',
945
967
  background: '#ba4e4e',
946
968
  borderRadius: '10px',
package/dist/index.d.ts CHANGED
@@ -1,4 +1,5 @@
1
1
  import { defineConfig } from './config.js';
2
2
  import App from './cli.js';
3
- import Route from './route.js';
4
- export { App, Route, defineConfig };
3
+ import { Route } from './route.js';
4
+ import { RouteMap } from './route.js';
5
+ export { App, Route, RouteMap, defineConfig };
package/dist/index.js CHANGED
@@ -1,4 +1,5 @@
1
1
  import { defineConfig } from './config.js';
2
2
  import App from './cli.js';
3
- import Route from './route.js';
4
- export { App, Route, defineConfig };
3
+ import { Route } from './route.js';
4
+ import { RouteMap } from './route.js';
5
+ export { App, Route, RouteMap, defineConfig };
@@ -1,3 +1,3 @@
1
1
  export type CompilerType = 'esbuild' | 'babel';
2
2
  export declare function findFileUpwards(startDir: string, relativePath: string): string | null;
3
- export declare function renderPage(tsxPath: string, reqUrl?: string, showPanel?: boolean, compiler?: CompilerType, hotReload?: boolean, autoPaging?: boolean): Promise<string>;
3
+ export declare function renderPage(tsxPath: string, reqUrl?: string, showPanel?: boolean, compiler?: CompilerType, hotReload?: boolean, autoPaging?: boolean, autoPageDir?: string, appDir?: string): Promise<string>;
@@ -75,26 +75,20 @@ function resolveDevPanelPath() {
75
75
  return null;
76
76
  }
77
77
  const devPanelPath = resolveDevPanelPath();
78
- function resolveTemplate(tsxPath) {
79
- const pagesDir = path.join(process.cwd(), "pages");
80
- let dir = path.dirname(tsxPath);
81
- while (true) {
82
- const candidate = path.join(dir, "_template.html");
83
- if (fs.existsSync(candidate))
84
- return candidate;
85
- if (dir === pagesDir || dir === path.dirname(pagesDir))
86
- break;
87
- const parent = path.dirname(dir);
88
- if (parent === dir)
89
- break;
90
- dir = parent;
78
+ function resolveTemplate(appDir, autoPageDir, autoPaging) {
79
+ let nextToCli;
80
+ if (autoPaging) {
81
+ nextToCli = path.join(process.cwd(), autoPageDir || "", "_template.html");
91
82
  }
92
- return null;
83
+ else {
84
+ nextToCli = path.join(process.cwd(), appDir || "", "../", "_template.html");
85
+ }
86
+ return nextToCli;
93
87
  }
94
88
  function buildHtml(opts) {
95
89
  const { pageHtml, clientCode, devPanelContainer, templatePath, hotReload } = opts;
96
90
  const hmrScript = hotReload ? HMR_SCRIPT : '';
97
- if (templatePath) {
91
+ if (templatePath && fs.existsSync(templatePath)) {
98
92
  let template = fs.readFileSync(templatePath, "utf-8");
99
93
  const contentTag = /<authtics_host_content\s*\/>/i;
100
94
  if (contentTag.test(template)) {
@@ -146,13 +140,13 @@ const HMR_SCRIPT = `
146
140
  })();
147
141
  </script>
148
142
  `;
149
- export async function renderPage(tsxPath, reqUrl, showPanel = true, compiler = 'esbuild', hotReload = false, autoPaging = true) {
143
+ export async function renderPage(tsxPath, reqUrl, showPanel = true, compiler = 'esbuild', hotReload = false, autoPaging = true, autoPageDir, appDir) {
150
144
  ensureTempDirs();
151
145
  if (!fs.existsSync(tsxPath)) {
152
146
  throw new Error(`renderPage: source file not found: ${tsxPath}`);
153
147
  }
154
148
  const usesDevPanel = showPanel && devPanelPath !== null;
155
- const templatePath = resolveTemplate(tsxPath);
149
+ const templatePath = resolveTemplate(appDir, autoPageDir, autoPaging);
156
150
  const tempPath = tempFileForTsx(tsxPath);
157
151
  const serverCjsPath = tempPath.replace(/\.json$/, ".server.cjs");
158
152
  let clientCode;
package/dist/route.d.ts CHANGED
@@ -1,4 +1,7 @@
1
- export default function Route({ page, statusCode, at }: {
1
+ export declare function RouteMap({ children }: {
2
+ children?: React.ReactNode;
3
+ }): import("react/jsx-runtime").JSX.Element;
4
+ export declare function Route({ page, statusCode, at }: {
2
5
  page: Function;
3
6
  statusCode?: number;
4
7
  at?: string;
package/dist/route.js CHANGED
@@ -1,30 +1,55 @@
1
1
  import { jsx as _jsx, Fragment as _Fragment } from "react/jsx-runtime";
2
- import { useEffect, useState } from "react";
3
- export default function Route({ page, statusCode, at }) {
4
- const Page = page;
5
- const [pathName, setPathName] = useState("");
6
- const [is404, setIs404] = useState(false);
7
- const [thisPassed, setThisPassed] = useState(false);
2
+ import { useEffect, useState, useRef } from "react";
3
+ import NotFound from "./404.js";
4
+ export function RouteMap({ children }) {
5
+ const childArray = useRef(children);
6
+ const [path, setPath] = useState('');
7
+ const matched = useRef(null);
8
+ const [MatchedEl, setMatchedEl] = useState(null);
9
+ const [currentlyAwaiting, setCurrentlyAwaiting] = useState(true);
10
+ const [At404, setAt404] = useState(false);
8
11
  useEffect(() => {
9
- setPathName(window.location.pathname);
12
+ setPath(window.location.pathname);
10
13
  }, []);
11
14
  useEffect(() => {
12
- if (window.___passed == true)
13
- return;
14
- if (at == "" || at == undefined) {
15
- window.__status_code__ = statusCode || 404;
16
- setIs404(true);
15
+ const childrenToProcess = Array.isArray(childArray.current)
16
+ ? childArray.current
17
+ : [childArray.current];
18
+ childrenToProcess.forEach((child) => {
19
+ if (child?.props?.at === path) {
20
+ matched.current = child.props;
21
+ }
22
+ });
23
+ if (!matched.current) {
24
+ childrenToProcess.forEach((child) => {
25
+ if (child?.props?.at === undefined) {
26
+ matched.current = child.props;
27
+ setAt404(true);
28
+ }
29
+ });
30
+ }
31
+ setCurrentlyAwaiting(false);
32
+ }, [path]);
33
+ useEffect(() => {
34
+ if (matched.current && !At404) {
35
+ setMatchedEl(() => matched.current.page);
36
+ window.__status_code__ = matched.current.statusCode || 200;
37
+ }
38
+ else if (At404) {
39
+ setMatchedEl(() => matched.current.page);
40
+ window.__status_code__ = matched.current.statusCode || 404;
17
41
  }
18
42
  else {
19
- if (pathName == at) {
20
- window.__status_code__ = statusCode || 200;
21
- }
22
- else {
23
- return;
24
- }
43
+ setMatchedEl(() => NotFound);
44
+ window.__status_code__ = 404;
25
45
  }
26
- window.___passed = true;
27
- setThisPassed(true);
28
- }, [pathName]);
29
- return (_jsx(_Fragment, { children: thisPassed ? (_jsx(_Fragment, { children: _jsx(Page, {}) })) : (_jsx(_Fragment, {})) }));
46
+ }, [path]);
47
+ if (matched.current && MatchedEl)
48
+ return _jsx(MatchedEl, {});
49
+ if (currentlyAwaiting)
50
+ return _jsx(_Fragment, {});
51
+ return _jsx(NotFound, {});
52
+ }
53
+ export function Route({ page, statusCode, at }) {
54
+ return (_jsx(_Fragment, {}));
30
55
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@bananacool467/authtics-host",
3
- "version": "0.0.2-beta.3",
3
+ "version": "0.1.0",
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",
@@ -35,7 +35,8 @@
35
35
  "lightweight",
36
36
  "hot-reload",
37
37
  "dev",
38
- "developer"
38
+ "developer",
39
+ "HostJS"
39
40
  ],
40
41
  "author": "bananacool467",
41
42
  "license": "MIT",