@bananacool467/authtics-host 0.0.1-beta.7 → 0.0.1-beta.9
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 +17 -15
- package/dist/cli.js +56 -5
- package/dist/devPanel.js +55 -16
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -1,9 +1,11 @@
|
|
|
1
1
|
# Authtics Host
|
|
2
2
|
|
|
3
|
-
Version 0.0.1-beta.
|
|
3
|
+
Version 0.0.1-beta.9
|
|
4
4
|
License: MIT
|
|
5
5
|
|
|
6
|
-
(
|
|
6
|
+
**(UPDATE (Security Update): Now versions, 0.0.1-beta.9 and over now requires DAT (Developer Access Token) restriction to access remote controls such as: Restarting and Shutting Down)**
|
|
7
|
+
|
|
8
|
+
**(NOTE: This version is in BETA, bugs are expected)**
|
|
7
9
|
|
|
8
10
|
Authtics Host is a framework inspired by Next.js. Authtics Host supports SSR (Server-Side Rendering) and uses esbuild.
|
|
9
11
|
|
|
@@ -33,14 +35,14 @@ To make your app, with auto paging and auto filing, your file tree should look l
|
|
|
33
35
|
|
|
34
36
|
**(NOTE: the public folder is for auto filing)**
|
|
35
37
|
|
|
36
|
-
index.ts should look like:
|
|
38
|
+
`index.ts` should look like:
|
|
37
39
|
```ts
|
|
38
40
|
import { App } from "@bananacool467/authtics-host";
|
|
39
41
|
|
|
40
42
|
const app = new App();
|
|
41
43
|
```
|
|
42
44
|
|
|
43
|
-
authtics_host.config.ts should look like:
|
|
45
|
+
`authtics_host.config.ts` should look like:
|
|
44
46
|
```ts
|
|
45
47
|
import { defineConfig } from "@bananacool467/authtics-host";
|
|
46
48
|
|
|
@@ -55,7 +57,7 @@ export default defineConfig({
|
|
|
55
57
|
})
|
|
56
58
|
```
|
|
57
59
|
|
|
58
|
-
client/pages/index.tsx should look like:
|
|
60
|
+
`client/pages/index.tsx` should look like:
|
|
59
61
|
```tsx
|
|
60
62
|
export default function Index () {
|
|
61
63
|
return (
|
|
@@ -75,7 +77,7 @@ To make your app, without auto paging and auto filing, your file tree should loo
|
|
|
75
77
|
index.tsx
|
|
76
78
|
```
|
|
77
79
|
|
|
78
|
-
index.ts should look like:
|
|
80
|
+
`index.ts` should look like:
|
|
79
81
|
```ts
|
|
80
82
|
import { App } from "@bananacool467/authtics-host";
|
|
81
83
|
|
|
@@ -83,7 +85,7 @@ const app = new App();
|
|
|
83
85
|
app.registerApp("client/app.tsx");
|
|
84
86
|
```
|
|
85
87
|
|
|
86
|
-
authtics_host.config.ts should look like:
|
|
88
|
+
`authtics_host.config.ts` should look like:
|
|
87
89
|
```ts
|
|
88
90
|
import { defineConfig } from "@bananacool467/authtics-host";
|
|
89
91
|
|
|
@@ -96,7 +98,7 @@ export default defineConfig({
|
|
|
96
98
|
})
|
|
97
99
|
```
|
|
98
100
|
|
|
99
|
-
client/app.tsx should look like:
|
|
101
|
+
`client/app.tsx` should look like:
|
|
100
102
|
```tsx
|
|
101
103
|
import { Route } from "@bananacool467/authtics-host";
|
|
102
104
|
import Index from "./pages/index";
|
|
@@ -110,7 +112,7 @@ export default function App() {
|
|
|
110
112
|
}
|
|
111
113
|
```
|
|
112
114
|
|
|
113
|
-
client/pages/index.tsx should look like:
|
|
115
|
+
`client/pages/index.tsx` should look like:
|
|
114
116
|
```tsx
|
|
115
117
|
export default function Index () {
|
|
116
118
|
return (
|
|
@@ -119,14 +121,14 @@ export default function Index () {
|
|
|
119
121
|
}
|
|
120
122
|
```
|
|
121
123
|
|
|
122
|
-
## To
|
|
124
|
+
## To Run The Project
|
|
123
125
|
|
|
124
|
-
Make sure Node 22 is installed:
|
|
126
|
+
Make sure **Node 22** is installed:
|
|
125
127
|
```
|
|
126
128
|
nvm install 22
|
|
127
129
|
```
|
|
128
130
|
|
|
129
|
-
To switch to Node 22 use:
|
|
131
|
+
To switch to **Node 22** use:
|
|
130
132
|
```
|
|
131
133
|
nvm use 22
|
|
132
134
|
```
|
|
@@ -138,9 +140,9 @@ node --experimental-strip-types index.ts
|
|
|
138
140
|
|
|
139
141
|
## Result
|
|
140
142
|
|
|
141
|
-
Then when you run your project, you will get a page just saying **"Hello, World!"** and you should see a
|
|
143
|
+
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
144
|
|
|
143
|
-
## Developer Panel Notes
|
|
145
|
+
## Developer Panel Notes And Warnings And DAT (Developer Access Token)
|
|
144
146
|
|
|
145
147
|
A DAT (Developer Access Token) is your token that is used to access the Developer Panel.
|
|
146
148
|
|
|
@@ -164,6 +166,6 @@ There isn't any limit of DATs you can add.
|
|
|
164
166
|
|
|
165
167
|
**(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.)**
|
|
166
168
|
|
|
167
|
-
## Contacting
|
|
169
|
+
## Contacting The Developer Of Authtics Host
|
|
168
170
|
|
|
169
171
|
If you ever encounter a bug, report it to (or have questions, contact): authtics@proton.me
|
package/dist/cli.js
CHANGED
|
@@ -110,6 +110,39 @@ export default class App {
|
|
|
110
110
|
server;
|
|
111
111
|
constructor() {
|
|
112
112
|
this.server = start();
|
|
113
|
+
this.post('/__authtics_host_apis__/get-dat-restriction-missing', async (req, res) => {
|
|
114
|
+
const reqBody = (await getJsonBody(req));
|
|
115
|
+
let datMatched = false;
|
|
116
|
+
let datRestrictedEnv = false;
|
|
117
|
+
if (config_.dat && config_.dat == reqBody.dat)
|
|
118
|
+
datMatched = true;
|
|
119
|
+
if (config_.dat == undefined)
|
|
120
|
+
datMatched = true;
|
|
121
|
+
if (config_.dat && Array.isArray(config_.dat) && config_.dat.includes(reqBody.dat))
|
|
122
|
+
datMatched = true;
|
|
123
|
+
if (datMatched) {
|
|
124
|
+
if (config_.dat !== undefined)
|
|
125
|
+
datRestrictedEnv = true;
|
|
126
|
+
res.writeHead(200, { "Content-Type": "application/json" });
|
|
127
|
+
res.end(JSON.stringify({
|
|
128
|
+
enabled: datRestrictedEnv
|
|
129
|
+
}));
|
|
130
|
+
}
|
|
131
|
+
});
|
|
132
|
+
this.post('/__authtics_host_apis__/get-dat-matching', async (req, res) => {
|
|
133
|
+
const reqBody = (await getJsonBody(req));
|
|
134
|
+
let datMatched = false;
|
|
135
|
+
if (config_.dat && config_.dat == reqBody.dat)
|
|
136
|
+
datMatched = true;
|
|
137
|
+
if (config_.dat == undefined)
|
|
138
|
+
datMatched = true;
|
|
139
|
+
if (config_.dat && Array.isArray(config_.dat) && config_.dat.includes(reqBody.dat))
|
|
140
|
+
datMatched = true;
|
|
141
|
+
res.writeHead(200, { "Content-Type": "application/json" });
|
|
142
|
+
res.end(JSON.stringify({
|
|
143
|
+
isMatching: datMatched
|
|
144
|
+
}));
|
|
145
|
+
});
|
|
113
146
|
this.post('/__authtics_host_apis__/get-cpu_memory', async (req, res) => {
|
|
114
147
|
const reqBody = (await getJsonBody(req));
|
|
115
148
|
let datMatched = false;
|
|
@@ -166,8 +199,6 @@ export default class App {
|
|
|
166
199
|
let datMatched = false;
|
|
167
200
|
if (config_.dat && config_.dat == reqBody.dat)
|
|
168
201
|
datMatched = true;
|
|
169
|
-
if (config_.dat == undefined)
|
|
170
|
-
datMatched = true;
|
|
171
202
|
if (config_.dat && Array.isArray(config_.dat) && config_.dat.includes(reqBody.dat))
|
|
172
203
|
datMatched = true;
|
|
173
204
|
if (datMatched) {
|
|
@@ -189,8 +220,6 @@ export default class App {
|
|
|
189
220
|
let datMatched = false;
|
|
190
221
|
if (config_.dat && config_.dat == reqBody.dat)
|
|
191
222
|
datMatched = true;
|
|
192
|
-
if (config_.dat == undefined)
|
|
193
|
-
datMatched = true;
|
|
194
223
|
if (config_.dat && Array.isArray(config_.dat) && config_.dat.includes(reqBody.dat))
|
|
195
224
|
datMatched = true;
|
|
196
225
|
if (datMatched) {
|
|
@@ -233,6 +262,27 @@ export default class App {
|
|
|
233
262
|
}));
|
|
234
263
|
}
|
|
235
264
|
});
|
|
265
|
+
this.post("/__authtics_host_apis__/get-host-ver", async (req, res) => {
|
|
266
|
+
const reqBody = (await getJsonBody(req));
|
|
267
|
+
let datMatched = false;
|
|
268
|
+
if (config_.dat && config_.dat == reqBody.dat)
|
|
269
|
+
datMatched = true;
|
|
270
|
+
if (config_.dat == undefined)
|
|
271
|
+
datMatched = true;
|
|
272
|
+
if (config_.dat && Array.isArray(config_.dat) && config_.dat.includes(reqBody.dat))
|
|
273
|
+
datMatched = true;
|
|
274
|
+
if (datMatched) {
|
|
275
|
+
const packageJsonPath = path.join(__dirname, '../package.json');
|
|
276
|
+
let packageJson;
|
|
277
|
+
if (fs.existsSync(packageJsonPath))
|
|
278
|
+
packageJson = JSON.parse(fs.readFileSync(packageJsonPath, 'utf-8'));
|
|
279
|
+
const packageJsonVersion = packageJson.version || "Unknown";
|
|
280
|
+
res.writeHead(200, { "Content-Type": "application/json" });
|
|
281
|
+
res.end(JSON.stringify({
|
|
282
|
+
version: packageJsonVersion
|
|
283
|
+
}));
|
|
284
|
+
}
|
|
285
|
+
});
|
|
236
286
|
this.post("/__authtics_host_apis__/get-file-by-pathname", async (req, res) => {
|
|
237
287
|
const reqBody = (await getJsonBody(req));
|
|
238
288
|
let datMatched = false;
|
|
@@ -245,7 +295,8 @@ export default class App {
|
|
|
245
295
|
if (datMatched) {
|
|
246
296
|
const pathname = reqBody.pathname;
|
|
247
297
|
const pagesDir = config_.autoPage === true ? path.join(process.cwd(), config_.autoPageDir || "") : undefined;
|
|
248
|
-
const
|
|
298
|
+
const safePath = path.normalize(pathname).replace(/^(\.\.[\/\\])+/, '');
|
|
299
|
+
const filePath = pagesDir ? path.join(pagesDir, safePath + ".tsx") : undefined;
|
|
249
300
|
const fileExists = filePath ? fs.existsSync(filePath) : true;
|
|
250
301
|
res.writeHead(200, { "Content-Type": "application/json" });
|
|
251
302
|
res.end(JSON.stringify({
|
package/dist/devPanel.js
CHANGED
|
@@ -138,14 +138,14 @@ function installConsoleInterceptor() {
|
|
|
138
138
|
};
|
|
139
139
|
});
|
|
140
140
|
}
|
|
141
|
-
function PanelButton({ onClick, onClick2, children, style, fullWidth }) {
|
|
141
|
+
function PanelButton({ onClick, onClick2, children, style, fullWidth, disabled }) {
|
|
142
142
|
const [hovered, setHovered] = useState(false);
|
|
143
143
|
const [pressed, setPressed] = useState(false);
|
|
144
144
|
return (_jsx("div", { onClick: (e) => {
|
|
145
|
-
if (onClick) {
|
|
145
|
+
if (onClick && !disabled) {
|
|
146
146
|
onClick();
|
|
147
147
|
}
|
|
148
|
-
else if (onClick2) {
|
|
148
|
+
else if (onClick2 && !disabled) {
|
|
149
149
|
onClick2(e);
|
|
150
150
|
}
|
|
151
151
|
}, onMouseEnter: () => setHovered(true), onMouseLeave: () => { setHovered(false); setPressed(false); }, onMouseDown: () => setPressed(true), onMouseUp: () => setPressed(false), style: {
|
|
@@ -194,12 +194,14 @@ export default function DevPanel() {
|
|
|
194
194
|
const [isSsr, setIsSsr] = useState(false);
|
|
195
195
|
const cpuUsage = useRef(0);
|
|
196
196
|
const heapUsage = useRef(0);
|
|
197
|
+
const [datMatch, setDatMatch] = useState(false);
|
|
197
198
|
const [compilerType, setCompilerType] = useState("?");
|
|
198
199
|
const [errorDetail, setErrorDetail] = useState(undefined);
|
|
199
200
|
const [httpVersion, setHttpVersion] = useState("v?.?");
|
|
200
201
|
const [errorBoxOpenable, setErrorBoxOpenable] = useState(false);
|
|
201
202
|
const [uptime, setUptime] = useState("00:00:00:00");
|
|
202
203
|
const [requests, setRequests] = useState(0);
|
|
204
|
+
const [hostVersion, setHostVersion] = useState("Loading...");
|
|
203
205
|
const [users, setUsers] = useState(0);
|
|
204
206
|
const [token, setToken] = useState(null);
|
|
205
207
|
const [tokenLength, setTokenLength] = useState(0);
|
|
@@ -211,6 +213,7 @@ export default function DevPanel() {
|
|
|
211
213
|
const frames = useRef(0);
|
|
212
214
|
const consoleScrollRef = useRef(null);
|
|
213
215
|
const [isAtBottom, setIsAtBottom] = useState(true);
|
|
216
|
+
const [datRestrictionMissing, setDatRestrictionMissing] = useState(true);
|
|
214
217
|
const [pos, setPos] = React.useState({ x: 20, y: 20 });
|
|
215
218
|
const [dragging, setDragging] = React.useState(false);
|
|
216
219
|
const offset = React.useRef({ x: 0, y: 0 });
|
|
@@ -476,6 +479,30 @@ useEffect(() => {
|
|
|
476
479
|
setPath(data.filePath);
|
|
477
480
|
}
|
|
478
481
|
};
|
|
482
|
+
const getDatMatching = async () => {
|
|
483
|
+
const resp = await fetch('/__authtics_host_apis__/get-dat-matching', {
|
|
484
|
+
method: 'POST',
|
|
485
|
+
headers: { 'Content-Type': 'application/json' },
|
|
486
|
+
body: JSON.stringify({ dat: localStorage.getItem('dat') })
|
|
487
|
+
});
|
|
488
|
+
if (resp.status === 200) {
|
|
489
|
+
const data = await resp.json();
|
|
490
|
+
setDatMatch(data.isMatching);
|
|
491
|
+
if (!data.isMatching) {
|
|
492
|
+
doc?.getElementById('authtics-dev-panel-root')?.remove();
|
|
493
|
+
return;
|
|
494
|
+
}
|
|
495
|
+
const resp2 = await fetch('/__authtics_host_apis__/get-dat-restriction-missing', {
|
|
496
|
+
method: 'POST',
|
|
497
|
+
headers: { 'Content-Type': 'application/json' },
|
|
498
|
+
body: JSON.stringify({ dat: localStorage.getItem('dat') })
|
|
499
|
+
});
|
|
500
|
+
if (resp2.status === 200) {
|
|
501
|
+
const data = await resp2.json();
|
|
502
|
+
setDatRestrictionMissing(!data.enabled);
|
|
503
|
+
}
|
|
504
|
+
}
|
|
505
|
+
};
|
|
479
506
|
const isSSR = async () => {
|
|
480
507
|
const resp = await fetch('/__authtics_host_apis__/get-is-ssr', {
|
|
481
508
|
method: 'POST',
|
|
@@ -499,6 +526,17 @@ useEffect(() => {
|
|
|
499
526
|
heapUsage.current = data.heapUsed;
|
|
500
527
|
}
|
|
501
528
|
};
|
|
529
|
+
const getHostVersion = async () => {
|
|
530
|
+
const resp = await fetch('/__authtics_host_apis__/get-host-ver', {
|
|
531
|
+
method: 'POST',
|
|
532
|
+
headers: { 'Content-Type': 'application/json' },
|
|
533
|
+
body: JSON.stringify({ dat: localStorage.getItem('dat') })
|
|
534
|
+
});
|
|
535
|
+
if (resp.status === 200) {
|
|
536
|
+
const data = await resp.json();
|
|
537
|
+
setHostVersion(data.version);
|
|
538
|
+
}
|
|
539
|
+
};
|
|
502
540
|
const getCompilerType = async () => {
|
|
503
541
|
const resp = await fetch('/__authtics_host_apis__/get-compiler', {
|
|
504
542
|
method: 'POST',
|
|
@@ -559,6 +597,8 @@ useEffect(() => {
|
|
|
559
597
|
getHttpVersion();
|
|
560
598
|
isSSR();
|
|
561
599
|
userSettings();
|
|
600
|
+
getHostVersion();
|
|
601
|
+
getDatMatching();
|
|
562
602
|
setInterval(() => {
|
|
563
603
|
getUsage();
|
|
564
604
|
}, 250);
|
|
@@ -642,17 +682,6 @@ useEffect(() => {
|
|
|
642
682
|
}, []);
|
|
643
683
|
// Chart tick every 2 seconds — snapshot pending bytes then reset
|
|
644
684
|
useEffect(() => {
|
|
645
|
-
/*let nE;
|
|
646
|
-
const navigationEntries = performance.getEntriesByType("navigation");
|
|
647
|
-
if (navigationEntries.length > 0) {
|
|
648
|
-
const navigationEntry = navigationEntries[0] as PerformanceNavigationTiming;
|
|
649
|
-
nE = navigationEntry;
|
|
650
|
-
}
|
|
651
|
-
let statusCode = 404;
|
|
652
|
-
if (nE instanceof PerformanceNavigationTiming) {
|
|
653
|
-
statusCode = nE.responseStatus;
|
|
654
|
-
}
|
|
655
|
-
setStatus(statusCode);*/
|
|
656
685
|
const interval = setInterval(() => {
|
|
657
686
|
const s = pendingSent.current;
|
|
658
687
|
const r = pendingReceived.current;
|
|
@@ -1104,7 +1133,7 @@ useEffect(() => {
|
|
|
1104
1133
|
border: '1px solid #eee',
|
|
1105
1134
|
fontSize: '12px',
|
|
1106
1135
|
color: '#333',
|
|
1107
|
-
}, children: [_jsx("span", { style: { fontSize: '12px', color: '#333' }, children: "Version" }),
|
|
1136
|
+
}, children: [_jsx("span", { style: { fontSize: '12px', color: '#333' }, children: "Version" }), _jsxs("span", { style: { fontSize: '12px', color: 'blue' }, children: ["v", hostVersion] })] }), _jsxs("div", { style: {
|
|
1108
1137
|
display: 'flex',
|
|
1109
1138
|
justifyContent: 'space-between',
|
|
1110
1139
|
padding: '6px 10px',
|
|
@@ -1186,7 +1215,17 @@ useEffect(() => {
|
|
|
1186
1215
|
gap: '6px',
|
|
1187
1216
|
color: '#fff',
|
|
1188
1217
|
flexDirection: 'row',
|
|
1189
|
-
}, children: [_jsx(CircleX, { size: 12 }), "Invalid Developer Access Token (DAT)"] }) })) : (_jsx(_Fragment, {})),
|
|
1218
|
+
}, children: [_jsx(CircleX, { size: 12 }), "Invalid Developer Access Token (DAT)"] }) })) : (_jsx(_Fragment, {})), hostVersion === "0.0.1-beta.9" ? (_jsx(_Fragment, { children: _jsx("div", { style: {
|
|
1219
|
+
display: 'flex',
|
|
1220
|
+
background: 'orange',
|
|
1221
|
+
borderRadius: '10px',
|
|
1222
|
+
padding: '6px 10px',
|
|
1223
|
+
justifyContent: 'left',
|
|
1224
|
+
alignItems: 'center',
|
|
1225
|
+
gap: '6px',
|
|
1226
|
+
color: '#fff',
|
|
1227
|
+
flexDirection: 'row',
|
|
1228
|
+
}, 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."] })) : (_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."] })) : (_jsx(_Fragment, {}))] })] })) }) }), datMatch ? (_jsxs("div", { onClick: () => setOpen(o => !o), style: {
|
|
1190
1229
|
display: 'flex',
|
|
1191
1230
|
flexDirection: 'row',
|
|
1192
1231
|
alignItems: 'center',
|
package/package.json
CHANGED