@bananacool467/authtics-host 0.2.4 → 0.2.6
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 +20 -34
- package/dist/cli.js +64 -51
- package/dist/config.d.ts +3 -1
- package/dist/config.js +6 -0
- package/dist/devPanel.js +82 -13
- package/dist/renderEngine.d.ts +4 -1
- package/dist/renderEngine.js +187 -34
- package/package.json +16 -11
package/README.md
CHANGED
|
@@ -1,17 +1,11 @@
|
|
|
1
1
|
# Authtics Host
|
|
2
2
|
|
|
3
|
-
Version 0.2.
|
|
3
|
+
Version 0.2.6, License: MIT
|
|
4
4
|
|
|
5
|
-
Authtics Host is a web framework inspired by Next.js. Authtics Host supports SSR (Server-Side Rendering) and uses
|
|
5
|
+
Authtics Host is a web framework inspired by Next.js. Authtics Host supports SSR (Server-Side Rendering), SSG (Static Site Generation), CSR (Client-Side Rendering) and SRTWS (Site Rendering Through WebSockets) and uses **Esbuild**. This is not to be confused with auth platforms.
|
|
6
6
|
|
|
7
7
|
**(NOTE: The short name for Authtics Host is HostJS or Host.js)**
|
|
8
8
|
|
|
9
|
-
**(From the Developer: I am having 1 small issue:**
|
|
10
|
-
|
|
11
|
-
1. **Web Socket Connections** are **not showing** in the DevPanel's Network tab
|
|
12
|
-
|
|
13
|
-
**I need help fixing that)**
|
|
14
|
-
|
|
15
9
|
## Setting Up
|
|
16
10
|
|
|
17
11
|
To get **Authtics Host** use:
|
|
@@ -51,7 +45,7 @@ import { defineConfig } from "@bananacool467/authtics-host";
|
|
|
51
45
|
|
|
52
46
|
export default defineConfig({
|
|
53
47
|
port: 8000,
|
|
54
|
-
|
|
48
|
+
renderType: 'ssr',
|
|
55
49
|
devMode: true,
|
|
56
50
|
autoFile: true,
|
|
57
51
|
autoPage: true,
|
|
@@ -94,7 +88,7 @@ import { defineConfig } from "@bananacool467/authtics-host";
|
|
|
94
88
|
|
|
95
89
|
export default defineConfig({
|
|
96
90
|
port: 8000,
|
|
97
|
-
|
|
91
|
+
renderType: 'ssr',
|
|
98
92
|
devMode: true,
|
|
99
93
|
autoFile: false,
|
|
100
94
|
autoPage: false
|
|
@@ -154,7 +148,7 @@ Then when you run your project, you will get a page just saying **"Hello, World!
|
|
|
154
148
|
|
|
155
149
|
## About The Developer Panel
|
|
156
150
|
|
|
157
|
-
The Developer Panel is what you could use to help you debug your code. The Developer Panel has **
|
|
151
|
+
The Developer Panel is what you could use to help you debug your code. The Developer Panel has **8 tabs**:
|
|
158
152
|
|
|
159
153
|
* **Console** — Shows current logs.
|
|
160
154
|
* **Route** — Shows information about the current route.
|
|
@@ -163,6 +157,7 @@ The Developer Panel is what you could use to help you debug your code. The Devel
|
|
|
163
157
|
* **Client Info** — Shows information about your client's User Agent, OS **(Operating System)** and FPS **(Frames Per Second)**.
|
|
164
158
|
* **About Host** — Shows the current version of *Authtics Host*.
|
|
165
159
|
* **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.
|
|
160
|
+
* **Panel Customization** — Customize the dev panel.
|
|
166
161
|
|
|
167
162
|
The information the Developer Panel shows outside of the tabs is just your **DAT** (Developer Access Token).
|
|
168
163
|
|
|
@@ -186,6 +181,17 @@ and then create a file like `paused.tsx` and then inside `App.tsx`, import `Paus
|
|
|
186
181
|
```
|
|
187
182
|
and if your using `autoPaging` then you just create a file named `_paused.tsx`.
|
|
188
183
|
|
|
184
|
+
## Page Patching
|
|
185
|
+
|
|
186
|
+
Pages may fail to render in SSR if it uses `window` instead of assigning it to a **useState** while in a **useEffect** in *React*
|
|
187
|
+
|
|
188
|
+
You can fix this by adding this to your config file:
|
|
189
|
+
```json
|
|
190
|
+
"patchForSsr": true
|
|
191
|
+
```
|
|
192
|
+
|
|
193
|
+
It makes a fake `window`, `document`, etc for SSR when building for Node. Which fixes the issue.
|
|
194
|
+
|
|
189
195
|
## App APIs
|
|
190
196
|
|
|
191
197
|
You can add APIs like `get`, `post`, `del` and `put`.
|
|
@@ -203,30 +209,10 @@ Hello!
|
|
|
203
209
|
|
|
204
210
|
## Notes about Authtics Host
|
|
205
211
|
|
|
206
|
-
|
|
207
|
-
The developer (The one that is writing this README) may add a feature where Authtics Host converts:
|
|
208
|
-
```tsx
|
|
209
|
-
export function Component() {
|
|
210
|
-
return (
|
|
211
|
-
<p>{window.__status_code__}</p>
|
|
212
|
-
)
|
|
213
|
-
}
|
|
214
|
-
```
|
|
215
|
-
To:
|
|
216
|
-
```tsx
|
|
217
|
-
import { useState, useEffect } from 'react';
|
|
218
|
-
export function Component() {
|
|
219
|
-
const [__window, __set_window] = useState<any>(null);
|
|
220
|
-
useEffect(() => {
|
|
221
|
-
if (window) __set_window(window);
|
|
222
|
-
}, []);
|
|
223
|
-
return (
|
|
224
|
-
<p>{__window.__status_code__}</p>
|
|
225
|
-
)
|
|
226
|
-
}
|
|
227
|
-
```
|
|
212
|
+
The developer might redesign the UI for the DevPanel using [UI Tools](https://npmjs.com/package/@bananakitssu/ui-tools).
|
|
228
213
|
|
|
229
|
-
|
|
214
|
+
> **Warning**:
|
|
215
|
+
> SRTWS may not work properly. It may render pages, but not run scripts.
|
|
230
216
|
|
|
231
217
|
> **Warning**:
|
|
232
218
|
> Asking AI about HostJS is not recommended, it will give an Auth platform and call HostJS/Authtics Host a typo, say it doesn't exist, say it was renamed, it is private, or the account doesn't exist. Or if it knows, it may swap your server script with regular **Node.js**/**ExpressJS**/**Next.js** or use **Next.js-like** code because this framework is **Next.js-inspired**
|
package/dist/cli.js
CHANGED
|
@@ -4,12 +4,14 @@ import { createJiti } from "jiti";
|
|
|
4
4
|
import path from "node:path";
|
|
5
5
|
import fs from "node:fs";
|
|
6
6
|
import url from "node:url";
|
|
7
|
-
import { renderPage } from "./renderEngine.js";
|
|
7
|
+
import { renderPage, handleSrtwsConnection } from "./renderEngine.js";
|
|
8
|
+
import { tempFileForTsx } from "./rendererTempFiles.js";
|
|
8
9
|
let config_ = {};
|
|
9
10
|
let uptime = 0;
|
|
10
11
|
let totalRequests = 0;
|
|
11
12
|
let users = 0;
|
|
12
13
|
let usersPaused = false;
|
|
14
|
+
let srtws;
|
|
13
15
|
const jiti = createJiti(import.meta.url);
|
|
14
16
|
const routes = new Map();
|
|
15
17
|
const __filename = url.fileURLToPath(import.meta.url);
|
|
@@ -143,9 +145,9 @@ export default class App {
|
|
|
143
145
|
this.startServer();
|
|
144
146
|
this.post('/__authtics_host_apis__/set-users-paused', async (req, res) => {
|
|
145
147
|
let datMatched = false;
|
|
146
|
-
if (config_.dat && config_.dat == req.
|
|
148
|
+
if (config_.dat && config_.dat == req.dat)
|
|
147
149
|
datMatched = true;
|
|
148
|
-
if (config_.dat && Array.isArray(config_.dat) && config_.dat.includes(req.
|
|
150
|
+
if (config_.dat && Array.isArray(config_.dat) && config_.dat.includes(req.dat))
|
|
149
151
|
datMatched = true;
|
|
150
152
|
if (datMatched) {
|
|
151
153
|
usersPaused = req.body.paused;
|
|
@@ -157,9 +159,9 @@ export default class App {
|
|
|
157
159
|
});
|
|
158
160
|
this.post('/__authtics_host_apis__/is-users-paused', async (req, res) => {
|
|
159
161
|
let datMatched = false;
|
|
160
|
-
if (config_.dat && config_.dat == req.
|
|
162
|
+
if (config_.dat && config_.dat == req.dat)
|
|
161
163
|
datMatched = true;
|
|
162
|
-
if (config_.dat && Array.isArray(config_.dat) && config_.dat.includes(req.
|
|
164
|
+
if (config_.dat && Array.isArray(config_.dat) && config_.dat.includes(req.dat))
|
|
163
165
|
datMatched = true;
|
|
164
166
|
res.writeHead(200, { "Content-Type": "application/json" });
|
|
165
167
|
if (datMatched) {
|
|
@@ -172,11 +174,11 @@ export default class App {
|
|
|
172
174
|
this.post('/__authtics_host_apis__/get-dat-restriction-missing', async (req, res) => {
|
|
173
175
|
let datMatched = false;
|
|
174
176
|
let datRestrictedEnv = false;
|
|
175
|
-
if (config_.dat && config_.dat == req.
|
|
177
|
+
if (config_.dat && config_.dat == req.dat)
|
|
176
178
|
datMatched = true;
|
|
177
179
|
if (config_.dat == undefined)
|
|
178
180
|
datMatched = true;
|
|
179
|
-
if (config_.dat && Array.isArray(config_.dat) && config_.dat.includes(req.
|
|
181
|
+
if (config_.dat && Array.isArray(config_.dat) && config_.dat.includes(req.dat))
|
|
180
182
|
datMatched = true;
|
|
181
183
|
if (datMatched) {
|
|
182
184
|
if (config_.dat !== undefined)
|
|
@@ -189,11 +191,11 @@ export default class App {
|
|
|
189
191
|
});
|
|
190
192
|
this.post('/__authtics_host_apis__/get-dat-matching', async (req, res) => {
|
|
191
193
|
let datMatched = false;
|
|
192
|
-
if (config_.dat && config_.dat == req.
|
|
194
|
+
if (config_.dat && config_.dat == req.dat)
|
|
193
195
|
datMatched = true;
|
|
194
196
|
if (config_.dat == undefined)
|
|
195
197
|
datMatched = true;
|
|
196
|
-
if (config_.dat && Array.isArray(config_.dat) && config_.dat.includes(req.
|
|
198
|
+
if (config_.dat && Array.isArray(config_.dat) && config_.dat.includes(req.dat))
|
|
197
199
|
datMatched = true;
|
|
198
200
|
res.writeHead(200, { "Content-Type": "application/json" });
|
|
199
201
|
res.end(JSON.stringify({
|
|
@@ -202,9 +204,9 @@ export default class App {
|
|
|
202
204
|
});
|
|
203
205
|
this.post('/__authtics_host_apis__/get-cpu_memory', async (req, res) => {
|
|
204
206
|
let datMatched = false;
|
|
205
|
-
if (config_.dat && config_.dat == req.
|
|
207
|
+
if (config_.dat && config_.dat == req.dat)
|
|
206
208
|
datMatched = true;
|
|
207
|
-
if (config_.dat && Array.isArray(config_.dat) && config_.dat.includes(req.
|
|
209
|
+
if (config_.dat && Array.isArray(config_.dat) && config_.dat.includes(req.dat))
|
|
208
210
|
datMatched = true;
|
|
209
211
|
if (datMatched) {
|
|
210
212
|
const { heapUsed, heapTotal, rss } = process.memoryUsage();
|
|
@@ -212,15 +214,16 @@ export default class App {
|
|
|
212
214
|
res.writeHead(200, { "Content-Type": "application/json" });
|
|
213
215
|
res.end(JSON.stringify({
|
|
214
216
|
cpuUsage,
|
|
215
|
-
heapUsed
|
|
217
|
+
heapUsed,
|
|
218
|
+
heapTotal
|
|
216
219
|
}));
|
|
217
220
|
}
|
|
218
221
|
});
|
|
219
222
|
this.post('/__authtics_host_apis__/get-user-settings', async (req, res) => {
|
|
220
223
|
let datMatched = false;
|
|
221
|
-
if (config_.dat && config_.dat == req.
|
|
224
|
+
if (config_.dat && config_.dat == req.dat)
|
|
222
225
|
datMatched = true;
|
|
223
|
-
if (config_.dat && Array.isArray(config_.dat) && config_.dat.includes(req.
|
|
226
|
+
if (config_.dat && Array.isArray(config_.dat) && config_.dat.includes(req.dat))
|
|
224
227
|
datMatched = true;
|
|
225
228
|
if (datMatched) {
|
|
226
229
|
res.writeHead(200, { "Content-Type": "application/json" });
|
|
@@ -231,9 +234,9 @@ export default class App {
|
|
|
231
234
|
});
|
|
232
235
|
this.post("/__authtics_host_apis__/get-server-info", async (req, res) => {
|
|
233
236
|
let datMatched = false;
|
|
234
|
-
if (config_.dat && config_.dat == req.
|
|
237
|
+
if (config_.dat && config_.dat == req.dat)
|
|
235
238
|
datMatched = true;
|
|
236
|
-
if (config_.dat && Array.isArray(config_.dat) && config_.dat.includes(req.
|
|
239
|
+
if (config_.dat && Array.isArray(config_.dat) && config_.dat.includes(req.dat))
|
|
237
240
|
datMatched = true;
|
|
238
241
|
if (datMatched) {
|
|
239
242
|
res.writeHead(200, { "Content-Type": "application/json" });
|
|
@@ -244,9 +247,9 @@ export default class App {
|
|
|
244
247
|
});
|
|
245
248
|
this.post("/__authtics_host_apis__/restart", async (req, res) => {
|
|
246
249
|
let datMatched = false;
|
|
247
|
-
if (config_.dat && config_.dat == req.
|
|
250
|
+
if (config_.dat && config_.dat == req.dat)
|
|
248
251
|
datMatched = true;
|
|
249
|
-
if (config_.dat && Array.isArray(config_.dat) && config_.dat.includes(req.
|
|
252
|
+
if (config_.dat && Array.isArray(config_.dat) && config_.dat.includes(req.dat))
|
|
250
253
|
datMatched = true;
|
|
251
254
|
if (datMatched) {
|
|
252
255
|
res.writeHead(200, { "Content-Type": "application/json" });
|
|
@@ -257,14 +260,16 @@ export default class App {
|
|
|
257
260
|
stdio: 'inherit'
|
|
258
261
|
});
|
|
259
262
|
child.unref();
|
|
260
|
-
|
|
263
|
+
this.server.close(() => {
|
|
264
|
+
process.kill(process.pid, 'SIGTERM');
|
|
265
|
+
});
|
|
261
266
|
}
|
|
262
267
|
});
|
|
263
268
|
this.post("/__authtics_host_apis__/shutdown", async (req, res) => {
|
|
264
269
|
let datMatched = false;
|
|
265
|
-
if (config_.dat && config_.dat == req.
|
|
270
|
+
if (config_.dat && config_.dat == req.dat)
|
|
266
271
|
datMatched = true;
|
|
267
|
-
if (config_.dat && Array.isArray(config_.dat) && config_.dat.includes(req.
|
|
272
|
+
if (config_.dat && Array.isArray(config_.dat) && config_.dat.includes(req.dat))
|
|
268
273
|
datMatched = true;
|
|
269
274
|
if (datMatched) {
|
|
270
275
|
res.writeHead(200, { "Content-Type": "application/json" });
|
|
@@ -274,24 +279,24 @@ export default class App {
|
|
|
274
279
|
});
|
|
275
280
|
}
|
|
276
281
|
});
|
|
277
|
-
this.post("/__authtics_host_apis__/get-
|
|
282
|
+
this.post("/__authtics_host_apis__/get-render-type", async (req, res) => {
|
|
278
283
|
let datMatched = false;
|
|
279
|
-
if (config_.dat && config_.dat == req.
|
|
284
|
+
if (config_.dat && config_.dat == req.dat)
|
|
280
285
|
datMatched = true;
|
|
281
|
-
if (config_.dat && Array.isArray(config_.dat) && config_.dat.includes(req.
|
|
286
|
+
if (config_.dat && Array.isArray(config_.dat) && config_.dat.includes(req.dat))
|
|
282
287
|
datMatched = true;
|
|
283
288
|
if (datMatched) {
|
|
284
289
|
res.writeHead(200, { "Content-Type": "application/json" });
|
|
285
290
|
res.end(JSON.stringify({
|
|
286
|
-
|
|
291
|
+
renderType: config_.renderType
|
|
287
292
|
}));
|
|
288
293
|
}
|
|
289
294
|
});
|
|
290
295
|
this.post("/__authtics_host_apis__/get-compiler", async (req, res) => {
|
|
291
296
|
let datMatched = false;
|
|
292
|
-
if (config_.dat && config_.dat == req.
|
|
297
|
+
if (config_.dat && config_.dat == req.dat)
|
|
293
298
|
datMatched = true;
|
|
294
|
-
if (config_.dat && Array.isArray(config_.dat) && config_.dat.includes(req.
|
|
299
|
+
if (config_.dat && Array.isArray(config_.dat) && config_.dat.includes(req.dat))
|
|
295
300
|
datMatched = true;
|
|
296
301
|
if (datMatched) {
|
|
297
302
|
res.writeHead(200, { "Content-Type": "application/json" });
|
|
@@ -302,9 +307,9 @@ export default class App {
|
|
|
302
307
|
});
|
|
303
308
|
this.post("/__authtics_host_apis__/get-host-ver", async (req, res) => {
|
|
304
309
|
let datMatched = false;
|
|
305
|
-
if (config_.dat && config_.dat == req.
|
|
310
|
+
if (config_.dat && config_.dat == req.dat)
|
|
306
311
|
datMatched = true;
|
|
307
|
-
if (config_.dat && Array.isArray(config_.dat) && config_.dat.includes(req.
|
|
312
|
+
if (config_.dat && Array.isArray(config_.dat) && config_.dat.includes(req.dat))
|
|
308
313
|
datMatched = true;
|
|
309
314
|
if (datMatched) {
|
|
310
315
|
const packageJsonPath = path.join(__dirname, '../package.json');
|
|
@@ -320,9 +325,9 @@ export default class App {
|
|
|
320
325
|
});
|
|
321
326
|
this.post("/__authtics_host_apis__/get-file-by-pathname", async (req, res) => {
|
|
322
327
|
let datMatched = false;
|
|
323
|
-
if (config_.dat && config_.dat == req.
|
|
328
|
+
if (config_.dat && config_.dat == req.dat)
|
|
324
329
|
datMatched = true;
|
|
325
|
-
if (config_.dat && Array.isArray(config_.dat) && config_.dat.includes(req.
|
|
330
|
+
if (config_.dat && Array.isArray(config_.dat) && config_.dat.includes(req.dat))
|
|
326
331
|
datMatched = true;
|
|
327
332
|
if (datMatched) {
|
|
328
333
|
const pathname = req.body.pathname;
|
|
@@ -357,9 +362,9 @@ export default class App {
|
|
|
357
362
|
});
|
|
358
363
|
this.post("/__authtics_host_apis__/ping", async (req, res) => {
|
|
359
364
|
let datMatched = false;
|
|
360
|
-
if (config_.dat && config_.dat == req.
|
|
365
|
+
if (config_.dat && config_.dat == req.dat)
|
|
361
366
|
datMatched = true;
|
|
362
|
-
if (config_.dat && Array.isArray(config_.dat) && config_.dat.includes(req.
|
|
367
|
+
if (config_.dat && Array.isArray(config_.dat) && config_.dat.includes(req.dat))
|
|
363
368
|
datMatched = true;
|
|
364
369
|
if (datMatched) {
|
|
365
370
|
res.setHeader("Content-Type", "application/json");
|
|
@@ -368,9 +373,9 @@ export default class App {
|
|
|
368
373
|
});
|
|
369
374
|
this.post('/__authtics_host_apis__/get-connection', async (req, res) => {
|
|
370
375
|
let datMatched = false;
|
|
371
|
-
if (config_.dat && config_.dat == req.
|
|
376
|
+
if (config_.dat && config_.dat == req.dat)
|
|
372
377
|
datMatched = true;
|
|
373
|
-
if (config_.dat && Array.isArray(config_.dat) && config_.dat.includes(req.
|
|
378
|
+
if (config_.dat && Array.isArray(config_.dat) && config_.dat.includes(req.dat))
|
|
374
379
|
datMatched = true;
|
|
375
380
|
if (datMatched) {
|
|
376
381
|
res.writeHead(200, { "Content-Type": "application/json" });
|
|
@@ -418,6 +423,7 @@ async function start() {
|
|
|
418
423
|
catch {
|
|
419
424
|
}
|
|
420
425
|
const PORT = config.port ?? 3000;
|
|
426
|
+
const renderType = config.renderType ?? 'ssr';
|
|
421
427
|
const showPanel = config.devMode !== false;
|
|
422
428
|
const autoPaging = config.autoPage !== false;
|
|
423
429
|
const compiler = 'esbuild';
|
|
@@ -552,7 +558,7 @@ async function start() {
|
|
|
552
558
|
}
|
|
553
559
|
const routeKey = `${method}:${pathname}`;
|
|
554
560
|
if (routes.has(routeKey)) {
|
|
555
|
-
if (Array.isArray(config_.dat) && !config_.dat.includes(req.
|
|
561
|
+
if (Array.isArray(config_.dat) && !config_.dat.includes(req.dat) && usersPaused && !routeKey.endsWith('.js')) {
|
|
556
562
|
if (autoPaging) {
|
|
557
563
|
const pausedTsxFile = pagesDir ? path.join(pagesDir, "_paused.tsx") : undefined;
|
|
558
564
|
if (fs.existsSync(pausedTsxFile || "")) {
|
|
@@ -562,7 +568,7 @@ async function start() {
|
|
|
562
568
|
res.setHeader("Content-Type", "application/javascript");
|
|
563
569
|
res.end(f);
|
|
564
570
|
});
|
|
565
|
-
}, (p) => { routes.delete(`GET:${p}`); }, req.
|
|
571
|
+
}, (p) => { routes.delete(`GET:${p}`); }, req.dat, config_.dat, config_.renderType, config_.patchForSsr);
|
|
566
572
|
html = html.replace("<script>", "<script>\nwindow.__paused__ = true;");
|
|
567
573
|
res.setHeader("Content-Type", "text/html");
|
|
568
574
|
return res.end(html);
|
|
@@ -585,7 +591,7 @@ async function start() {
|
|
|
585
591
|
res.setHeader("Content-Type", "application/javascript");
|
|
586
592
|
res.end(f);
|
|
587
593
|
});
|
|
588
|
-
}, (p) => { routes.delete(`GET:${p}`); }, req.cookies.dat, config_.dat);
|
|
594
|
+
}, (p) => { routes.delete(`GET:${p}`); }, req.cookies.dat, config_.dat, config_.renderType);
|
|
589
595
|
html = html.replace("<script>", "<script>\nwindow.__paused__ = true;");
|
|
590
596
|
res.setHeader("Content-Type", "text/html");
|
|
591
597
|
return res.end(html);
|
|
@@ -605,7 +611,7 @@ async function start() {
|
|
|
605
611
|
message: "unhandled request"
|
|
606
612
|
}));
|
|
607
613
|
}
|
|
608
|
-
if (config_.dat !== req.
|
|
614
|
+
if (config_.dat !== req.dat && usersPaused && !routeKey.endsWith('.js') && !Array.isArray(config_.dat)) {
|
|
609
615
|
if (autoPaging) {
|
|
610
616
|
const pausedTsxFile = pagesDir ? path.join(pagesDir, "_paused.tsx") : undefined;
|
|
611
617
|
if (fs.existsSync(pausedTsxFile || "")) {
|
|
@@ -615,7 +621,7 @@ async function start() {
|
|
|
615
621
|
res.setHeader("Content-Type", "application/javascript");
|
|
616
622
|
res.end(f);
|
|
617
623
|
});
|
|
618
|
-
}, (p) => { routes.delete(`GET:${p}`); }, req.cookies.dat, config_.dat);
|
|
624
|
+
}, (p) => { routes.delete(`GET:${p}`); }, req.cookies.dat, config_.dat, config_.renderType, config_.patchForSsr);
|
|
619
625
|
html = html.replace("<script>", "<script>\nwindow.__paused__ = true;");
|
|
620
626
|
res.setHeader("Content-Type", "text/html");
|
|
621
627
|
return res.end(html);
|
|
@@ -638,7 +644,7 @@ async function start() {
|
|
|
638
644
|
res.setHeader("Content-Type", "application/javascript");
|
|
639
645
|
res.end(f);
|
|
640
646
|
});
|
|
641
|
-
}, (p) => { routes.delete(`GET:${p}`); }, req.cookies.dat, config_.dat);
|
|
647
|
+
}, (p) => { routes.delete(`GET:${p}`); }, req.cookies.dat, config_.dat, config_.renderType);
|
|
642
648
|
html = html.replace("<script>", "<script>\nwindow.__paused__ = true;");
|
|
643
649
|
res.setHeader("Content-Type", "text/html");
|
|
644
650
|
return res.end(html);
|
|
@@ -679,7 +685,10 @@ async function start() {
|
|
|
679
685
|
req.on('close', () => { hmrClients.delete(res); users--; });
|
|
680
686
|
return;
|
|
681
687
|
}
|
|
682
|
-
if (
|
|
688
|
+
if (pathname === '/__authtics_srtws__') {
|
|
689
|
+
return;
|
|
690
|
+
}
|
|
691
|
+
if (Array.isArray(config_.dat) && !config_.dat.includes(req.dat) && usersPaused) {
|
|
683
692
|
if (autoPaging) {
|
|
684
693
|
const pausedTsxFile = pagesDir ? path.join(pagesDir, "_paused.tsx") : undefined;
|
|
685
694
|
if (fs.existsSync(pausedTsxFile || "")) {
|
|
@@ -689,7 +698,7 @@ async function start() {
|
|
|
689
698
|
res.setHeader("Content-Type", "application/javascript");
|
|
690
699
|
res.end(f);
|
|
691
700
|
});
|
|
692
|
-
}, (p) => { routes.delete(`GET:${p}`); }, req.cookies.dat, config_.dat);
|
|
701
|
+
}, (p) => { routes.delete(`GET:${p}`); }, req.cookies.dat, config_.dat, config_.renderType, config_.patchForSsr);
|
|
693
702
|
html = html.replace("<script>", "<script>\nwindow.__paused__ = true;");
|
|
694
703
|
res.setHeader("Content-Type", "text/html");
|
|
695
704
|
return res.end(html);
|
|
@@ -712,7 +721,7 @@ async function start() {
|
|
|
712
721
|
res.setHeader("Content-Type", "application/javascript");
|
|
713
722
|
res.end(f);
|
|
714
723
|
});
|
|
715
|
-
}, (p) => { routes.delete(`GET:${p}`); }, req.cookies.dat, config_.dat);
|
|
724
|
+
}, (p) => { routes.delete(`GET:${p}`); }, req.cookies.dat, config_.dat, config_.renderType, config_.patchForSsr);
|
|
716
725
|
html = html.replace("<script>", "<script>\nwindow.__paused__ = true;");
|
|
717
726
|
res.setHeader("Content-Type", "text/html");
|
|
718
727
|
return res.end(html);
|
|
@@ -732,7 +741,7 @@ async function start() {
|
|
|
732
741
|
message: "unhandled request"
|
|
733
742
|
}));
|
|
734
743
|
}
|
|
735
|
-
if (config.dat !== req.
|
|
744
|
+
if (config.dat !== req.dat && usersPaused && !Array.isArray(config_.dat)) {
|
|
736
745
|
if (autoPaging) {
|
|
737
746
|
const pausedTsxFile = pagesDir ? path.join(pagesDir, "_paused.tsx") : undefined;
|
|
738
747
|
if (fs.existsSync(pausedTsxFile || "")) {
|
|
@@ -742,7 +751,7 @@ async function start() {
|
|
|
742
751
|
res.setHeader("Content-Type", "application/javascript");
|
|
743
752
|
res.end(f);
|
|
744
753
|
});
|
|
745
|
-
}, (p) => { routes.delete(`GET:${p}`); }, req.cookies.dat, config_.dat);
|
|
754
|
+
}, (p) => { routes.delete(`GET:${p}`); }, req.cookies.dat, config_.dat, config_.renderType, config_.patchForSsr);
|
|
746
755
|
html = html.replace("<script>", "<script>\nwindow.__paused__ = true;");
|
|
747
756
|
res.setHeader("Content-Type", "text/html");
|
|
748
757
|
return res.end(html);
|
|
@@ -765,7 +774,7 @@ async function start() {
|
|
|
765
774
|
res.setHeader("Content-Type", "application/javascript");
|
|
766
775
|
res.end(f);
|
|
767
776
|
});
|
|
768
|
-
}, (p) => { routes.delete(`GET:${p}`); }, req.cookies.dat, config_.dat);
|
|
777
|
+
}, (p) => { routes.delete(`GET:${p}`); }, req.cookies.dat, config_.dat, config_.renderType, config_.patchForSsr);
|
|
769
778
|
html = html.replace("<script>", "<script>\nwindow.__paused__ = true;");
|
|
770
779
|
res.setHeader("Content-Type", "text/html");
|
|
771
780
|
return res.end(html);
|
|
@@ -823,7 +832,7 @@ async function start() {
|
|
|
823
832
|
res.setHeader("Content-Type", "application/javascript");
|
|
824
833
|
res.end(f);
|
|
825
834
|
});
|
|
826
|
-
}, (p) => { routes.delete(`GET:${p}`); }, req.cookies.dat, config_.dat);
|
|
835
|
+
}, (p) => { routes.delete(`GET:${p}`); }, req.cookies.dat, config_.dat, config_.renderType, config_.patchForSsr);
|
|
827
836
|
res.setHeader("Content-Type", "text/html");
|
|
828
837
|
res.writeHead(404);
|
|
829
838
|
html = html.replace("<script>", "<script>\nwindow.__status_code__ = 404;");
|
|
@@ -842,6 +851,10 @@ async function start() {
|
|
|
842
851
|
const urlPath = pathname === "/" ? "/index" : pathname;
|
|
843
852
|
const tsxPath = pagesDir ? path.join(pagesDir, `${urlPath}.tsx`) : undefined;
|
|
844
853
|
const htmlPath = pagesDir ? path.join(pagesDir, `${urlPath}.html`) : undefined;
|
|
854
|
+
if (fs.existsSync(tempFileForTsx(tsxPath || ""))) {
|
|
855
|
+
const { default: PageComponent } = await import(tempFileForTsx(tsxPath || "").replace(/\.json$/, ".server.cjs"));
|
|
856
|
+
srtws = handleSrtwsConnection(server, PageComponent);
|
|
857
|
+
}
|
|
845
858
|
if (tsxPath && fs.existsSync(tsxPath)) {
|
|
846
859
|
try {
|
|
847
860
|
const html = await renderPage(tsxPath, url, actuallyShowPanel, compiler, hotReload, autoPaging, config.autoPageDir, (routes.get("APP_TSX") || ""), (f, p) => {
|
|
@@ -849,7 +862,7 @@ async function start() {
|
|
|
849
862
|
res.setHeader("Content-Type", "application/javascript");
|
|
850
863
|
res.end(f);
|
|
851
864
|
});
|
|
852
|
-
}, (p) => { routes.delete(`GET:${p}`); }, req.cookies.dat, config_.dat);
|
|
865
|
+
}, (p) => { routes.delete(`GET:${p}`); }, req.cookies.dat, config_.dat, config_.renderType, config_.patchForSsr);
|
|
853
866
|
res.setHeader("Content-Type", "text/html");
|
|
854
867
|
return res.end(html);
|
|
855
868
|
}
|
|
@@ -873,7 +886,7 @@ async function start() {
|
|
|
873
886
|
res.setHeader("Content-Type", "application/javascript");
|
|
874
887
|
res.end(f);
|
|
875
888
|
});
|
|
876
|
-
}, (p) => { routes.delete(`GET:${p}`); }, req.cookies.dat, config_.dat);
|
|
889
|
+
}, (p) => { routes.delete(`GET:${p}`); }, req.cookies.dat, config_.dat, config_.renderType, config_.patchForSsr);
|
|
877
890
|
res.setHeader("Content-Type", "text/html");
|
|
878
891
|
return res.end(html);
|
|
879
892
|
}
|
|
@@ -892,7 +905,7 @@ async function start() {
|
|
|
892
905
|
res.setHeader("Content-Type", "application/javascript");
|
|
893
906
|
res.end(f);
|
|
894
907
|
});
|
|
895
|
-
}, (p) => { routes.delete(`GET:${p}`); }, req.cookies.dat, config_.dat);
|
|
908
|
+
}, (p) => { routes.delete(`GET:${p}`); }, req.cookies.dat, config_.dat, config_.renderType, config_.patchForSsr);
|
|
896
909
|
res.setHeader("Content-Type", "text/html");
|
|
897
910
|
res.writeHead(404);
|
|
898
911
|
html = html.replace("<script>", "<script>\nwindow.__status_code__ = 404;");
|
package/dist/config.d.ts
CHANGED
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
export interface AuthticsConfig {
|
|
2
2
|
port?: number;
|
|
3
3
|
ssr?: boolean;
|
|
4
|
+
renderType?: 'ssr' | 'csr' | 'ssg' | 'srtws';
|
|
4
5
|
dir?: string;
|
|
5
6
|
devMode?: boolean;
|
|
6
|
-
compilerType?: 'esbuild'
|
|
7
|
+
compilerType?: 'esbuild';
|
|
7
8
|
hotReload?: boolean;
|
|
8
9
|
dat?: string | string[];
|
|
9
10
|
showError?: boolean;
|
|
@@ -12,5 +13,6 @@ export interface AuthticsConfig {
|
|
|
12
13
|
autoFile?: boolean;
|
|
13
14
|
autoFileDir?: string;
|
|
14
15
|
hasPausedRoute?: boolean;
|
|
16
|
+
patchForSsr?: boolean;
|
|
15
17
|
}
|
|
16
18
|
export declare function defineConfig(config: AuthticsConfig): AuthticsConfig;
|
package/dist/config.js
CHANGED
|
@@ -7,8 +7,14 @@ export function defineConfig(config) {
|
|
|
7
7
|
config.showError = true;
|
|
8
8
|
if (config.compilerType == undefined)
|
|
9
9
|
config.compilerType = 'esbuild';
|
|
10
|
+
if (config.patchForSsr === undefined)
|
|
11
|
+
config.patchForSsr = false;
|
|
10
12
|
if (config.ssr == undefined)
|
|
11
13
|
config.ssr = true;
|
|
14
|
+
else
|
|
15
|
+
console.warn("Using \"ssr\" in Authtics Host Config is deprecated. Use \"renderType\" instead.");
|
|
16
|
+
if (config.renderType == undefined)
|
|
17
|
+
config.renderType = config.ssr ? 'ssr' : 'csr';
|
|
12
18
|
if (config.port == undefined || config.port == 0)
|
|
13
19
|
config.port = 3000;
|
|
14
20
|
if (config.devMode == undefined)
|
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 { useState, useEffect, useRef } from 'react';
|
|
3
|
-
import { ShieldCheck, CircleX, ChevronDown, ChevronUp, Bug, AlertTriangle, Info, ArrowLeft, Wifi, Terminal, Route, Globe, ChevronRight, ChevronLeft, Server, TriangleAlert, Eye, Zap, Power } from 'lucide-react';
|
|
3
|
+
import { ShieldCheck, CircleX, ChevronDown, ChevronUp, Bug, AlertTriangle, Info, ArrowLeft, Wifi, Terminal, Route, Globe, ChevronRight, ChevronLeft, Server, Cog, TriangleAlert, Eye, Zap, Power, Check as Tick } from 'lucide-react';
|
|
4
4
|
function getCallerSource() {
|
|
5
5
|
try {
|
|
6
6
|
const stack = new Error().stack ?? '';
|
|
@@ -349,8 +349,13 @@ export default function DevPanel() {
|
|
|
349
349
|
const [clientInfoOpen, setClientInfoOpen] = useState(false);
|
|
350
350
|
const [aboutHostOpen, setAboutHostOpen] = useState(false);
|
|
351
351
|
const [serverInfoOpen, setServerInfoOpen] = useState(false);
|
|
352
|
+
const [panelCustomOpen, setPanelCustomOpen] = useState(false);
|
|
352
353
|
const [shutdown, setShutdown] = useState(false);
|
|
353
354
|
const [shuttingDown, setShuttingDown] = useState(false);
|
|
355
|
+
const [panelColor, setPanelColor] = useState({
|
|
356
|
+
background: '#111',
|
|
357
|
+
border: '#333'
|
|
358
|
+
});
|
|
354
359
|
const [hasIssue, setHasIssue] = useState(false);
|
|
355
360
|
const [ping__, setPing__] = useState(0);
|
|
356
361
|
const [networkFetches, setNetworkFetches] = useState([]);
|
|
@@ -363,10 +368,11 @@ export default function DevPanel() {
|
|
|
363
368
|
const [hostName, setHostName] = useState(undefined);
|
|
364
369
|
const [protocol, setProtocol] = useState(undefined);
|
|
365
370
|
const [path, setPath] = useState(undefined);
|
|
366
|
-
const [
|
|
371
|
+
const [renderType, setRenderType] = useState("???");
|
|
367
372
|
const datRestrictionMissingRef = useRef(true);
|
|
368
373
|
const cpuUsage = useRef(0);
|
|
369
374
|
const heapUsage = useRef(0);
|
|
375
|
+
const heapTotal = useRef(0);
|
|
370
376
|
const [datMatch, setDatMatch] = useState(false);
|
|
371
377
|
const [compilerType, setCompilerType] = useState("?");
|
|
372
378
|
const [httpVersion, setHttpVersion] = useState("v?.?");
|
|
@@ -384,6 +390,7 @@ export default function DevPanel() {
|
|
|
384
390
|
const consoleScrollRef = useRef(null);
|
|
385
391
|
const [isAtBottom, setIsAtBottom] = useState(true);
|
|
386
392
|
const [datRestrictionMissing, setDatRestrictionMissing] = useState(true);
|
|
393
|
+
const [heapResult, setHeapResult] = useState("0 Bytes / 0 Bytes");
|
|
387
394
|
const cookie = {
|
|
388
395
|
set: (k, v) => document.cookie = `${k}=${v}; path=/`,
|
|
389
396
|
get: (k) => Object.fromEntries(document.cookie.split(";")
|
|
@@ -463,15 +470,15 @@ export default function DevPanel() {
|
|
|
463
470
|
}
|
|
464
471
|
return "";
|
|
465
472
|
};
|
|
466
|
-
const
|
|
467
|
-
const resp = await fetch('/__authtics_host_apis__/get-
|
|
473
|
+
const getRenderType = async () => {
|
|
474
|
+
const resp = await fetch('/__authtics_host_apis__/get-render-type', {
|
|
468
475
|
method: 'POST',
|
|
469
476
|
headers: { 'Content-Type': 'application/json' },
|
|
470
477
|
body: JSON.stringify({})
|
|
471
478
|
});
|
|
472
479
|
if (resp.status === 200) {
|
|
473
480
|
const data = await resp.json();
|
|
474
|
-
|
|
481
|
+
setRenderType(data.renderType);
|
|
475
482
|
}
|
|
476
483
|
};
|
|
477
484
|
const getUsage = async () => {
|
|
@@ -484,6 +491,7 @@ export default function DevPanel() {
|
|
|
484
491
|
const data = await resp.json();
|
|
485
492
|
cpuUsage.current = data.cpuUsage;
|
|
486
493
|
heapUsage.current = data.heapUsed;
|
|
494
|
+
heapTotal.current = data.heapTotal;
|
|
487
495
|
}
|
|
488
496
|
};
|
|
489
497
|
const getHostVersion = async () => {
|
|
@@ -558,7 +566,7 @@ export default function DevPanel() {
|
|
|
558
566
|
getPath();
|
|
559
567
|
getCompilerType();
|
|
560
568
|
getHttpVersion();
|
|
561
|
-
|
|
569
|
+
getRenderType();
|
|
562
570
|
userSettings();
|
|
563
571
|
getHostVersion();
|
|
564
572
|
setInterval(() => {
|
|
@@ -630,19 +638,31 @@ export default function DevPanel() {
|
|
|
630
638
|
}, 1000);
|
|
631
639
|
return () => clearInterval(interval);
|
|
632
640
|
}, []);
|
|
641
|
+
const formatBytes = (b, d = 2, r = false) => {
|
|
642
|
+
if (b === 0)
|
|
643
|
+
return r ? 'Bytes' : '0 Bytes';
|
|
644
|
+
const k = 1024;
|
|
645
|
+
const dm = d < 0 ? 0 : d;
|
|
646
|
+
const sizes = ['Bytes', 'KB', 'MB', 'GB', 'TB', 'PB'];
|
|
647
|
+
const i = Math.floor(Math.log(b) / Math.log(k));
|
|
648
|
+
return r ? sizes[i] : parseFloat((b / Math.pow(k, i)).toFixed(dm)) + ' ' + sizes[i];
|
|
649
|
+
};
|
|
633
650
|
useEffect(() => {
|
|
634
651
|
const interval = setInterval(() => {
|
|
635
652
|
const s = pendingSent.current;
|
|
636
653
|
const r = pendingReceived.current;
|
|
637
654
|
const c = cpuUsage.current;
|
|
638
|
-
const h = heapUsage.current;
|
|
655
|
+
const h = formatBytes(heapUsage.current);
|
|
656
|
+
const t = ` ${formatBytes(heapUsage.current, 0, true)} / ` + formatBytes(heapTotal.current);
|
|
657
|
+
setHeapResult(t);
|
|
658
|
+
const h_num = Number(h.split(" ")[0]);
|
|
639
659
|
const f = frames.current;
|
|
640
660
|
pendingSent.current = 0;
|
|
641
661
|
pendingReceived.current = 0;
|
|
642
662
|
cpuUsage.current = 0;
|
|
643
663
|
heapUsage.current = 0;
|
|
644
664
|
setCpuUsageHistory(prev => [...prev.slice(-(MAX_POINTS - 1)), c]);
|
|
645
|
-
setHeapUsageHistory(prev => [...prev.slice(-(MAX_POINTS - 1)),
|
|
665
|
+
setHeapUsageHistory(prev => [...prev.slice(-(MAX_POINTS - 1)), h_num]);
|
|
646
666
|
setSentHistory(prev => [...prev.slice(-(MAX_POINTS - 1)), s]);
|
|
647
667
|
setReceivedHistory(prev => [...prev.slice(-(MAX_POINTS - 1)), r]);
|
|
648
668
|
setFpsHistory(prev => [...prev.slice(-(MAX_POINTS - 1)), f]);
|
|
@@ -668,6 +688,16 @@ export default function DevPanel() {
|
|
|
668
688
|
};
|
|
669
689
|
try {
|
|
670
690
|
const existingToken = cookie.get('dat');
|
|
691
|
+
const panelColor = cookie.get('panelColor');
|
|
692
|
+
if (panelColor) {
|
|
693
|
+
setPanelColor({
|
|
694
|
+
background: panelColor.split('|')[0],
|
|
695
|
+
border: panelColor.split('|')[1]
|
|
696
|
+
});
|
|
697
|
+
}
|
|
698
|
+
else {
|
|
699
|
+
cookie.set('panelColor', '#111|#333');
|
|
700
|
+
}
|
|
671
701
|
if (existingToken) {
|
|
672
702
|
setToken(existingToken);
|
|
673
703
|
let length_ = existingToken?.split('');
|
|
@@ -1041,7 +1071,7 @@ export default function DevPanel() {
|
|
|
1041
1071
|
border: '1px solid #eee',
|
|
1042
1072
|
fontSize: '12px',
|
|
1043
1073
|
color: '#333',
|
|
1044
|
-
}, children: [_jsx("span", { style: { fontSize: '12px', color: '#333' }, children: "Renderer Type" }), _jsx("span", { style: { fontSize: '12px', color: 'blue' }, children:
|
|
1074
|
+
}, children: [_jsx("span", { style: { fontSize: '12px', color: '#333' }, children: "Renderer Type" }), _jsx("span", { style: { fontSize: '12px', color: 'blue' }, children: renderType === "ssr" ? 'SSR (Server-Side Rendering)' : renderType === "csr" ? 'CSR (Client-Side Rendering)' : renderType === "ssg" ? 'SSG (Static Site Generation)' : '???' })] }), _jsxs("div", { style: {
|
|
1045
1075
|
display: 'flex',
|
|
1046
1076
|
justifyContent: 'space-between',
|
|
1047
1077
|
padding: '6px 10px',
|
|
@@ -1084,7 +1114,46 @@ export default function DevPanel() {
|
|
|
1084
1114
|
border: '1px solid #eee',
|
|
1085
1115
|
fontSize: '12px',
|
|
1086
1116
|
color: '#333',
|
|
1087
|
-
}, children: [_jsx("span", { style: { fontSize: '12px', color: '#333' }, children: "OS" }), _jsx("span", { style: { fontSize: '12px', color: 'blue' }, children: getOS() })] }), _jsx(Sparkline, { data: fpsHistory, color: frames.current < 30 ? '#e53e3e' : frames.current < 60 ? '#d97706' : '#16a34a', label: "FPS", unit: " frames" })] })] })) :
|
|
1117
|
+
}, children: [_jsx("span", { style: { fontSize: '12px', color: '#333' }, children: "OS" }), _jsx("span", { style: { fontSize: '12px', color: 'blue' }, children: getOS() })] }), _jsx(Sparkline, { data: fpsHistory, color: frames.current < 30 ? '#e53e3e' : frames.current < 60 ? '#d97706' : '#16a34a', label: "FPS", unit: " frames" })] })] })) : panelCustomOpen && !shutdown ? (_jsxs(_Fragment, { children: [_jsxs("div", { style: {
|
|
1118
|
+
padding: '6px 8px',
|
|
1119
|
+
borderBottom: '1px solid #ddd',
|
|
1120
|
+
background: '#fff',
|
|
1121
|
+
display: 'flex',
|
|
1122
|
+
alignItems: 'center',
|
|
1123
|
+
gap: '6px',
|
|
1124
|
+
}, children: [_jsxs(PanelButton, { onClick: () => setPanelCustomOpen(false), style: { color: '#555' }, children: [_jsx(ArrowLeft, { size: 12 }), " Back"] }), _jsxs("span", { style: { fontSize: '12px', display: 'flex', alignItems: 'center', gap: '4px', color: '#333' }, children: [_jsx(Cog, { size: 12, color: "#3b82f6" }), " Panel Configuration"] })] }), _jsxs("div", { style: { overflowY: 'auto', maxHeight: '260px', padding: '10px', display: 'flex', flexDirection: 'column', gap: '8px' }, children: [_jsx("span", { style: { fontSize: '12px', color: '#333' }, children: "Colors" }), _jsxs("div", { style: {
|
|
1125
|
+
display: 'flex',
|
|
1126
|
+
justifyContent: 'space-between',
|
|
1127
|
+
padding: '6px 10px',
|
|
1128
|
+
background: '#fff',
|
|
1129
|
+
borderRadius: '10px',
|
|
1130
|
+
border: '1px solid #eee',
|
|
1131
|
+
alignItems: 'center'
|
|
1132
|
+
}, children: [_jsxs("div", { style: { background: '#16a34a', width: '50px', height: '50px', borderRadius: '100px', cursor: 'pointer', alignItems: 'center', textAlign: 'center', justifyContent: 'center', flexDirection: 'column', display: 'flex', border: '1px solid #15803d', gap: '8px' }, onClick: () => {
|
|
1133
|
+
setPanelColor({
|
|
1134
|
+
background: '#16a34a',
|
|
1135
|
+
border: '#15803d'
|
|
1136
|
+
});
|
|
1137
|
+
cookie.set('panelColor', '#16a34a|#15803d');
|
|
1138
|
+
}, children: [panelColor.background === '#16a34a' ? _jsx(Tick, { color: "white", size: 12 }) : _jsx(_Fragment, {}), " ", _jsx("span", { style: { fontSize: '12px', color: '#fff' }, children: "Green" })] }), _jsxs("div", { style: { background: '#111', width: '50px', height: '50px', borderRadius: '100px', cursor: 'pointer', alignItems: 'center', textAlign: 'center', justifyContent: 'center', flexDirection: 'column', display: 'flex', border: '1px solid #333', gap: '8px' }, onClick: () => {
|
|
1139
|
+
setPanelColor({
|
|
1140
|
+
background: '#111',
|
|
1141
|
+
border: '#333'
|
|
1142
|
+
});
|
|
1143
|
+
cookie.set('panelColor', '#111|#333');
|
|
1144
|
+
}, children: [panelColor.background === '#111' ? _jsx(Tick, { color: "white", size: 12 }) : _jsx(_Fragment, {}), " ", _jsx("span", { style: { fontSize: '12px', color: '#fff' }, children: "Black" })] }), _jsxs("div", { style: { background: '#f7c623', width: '50px', height: '50px', borderRadius: '100px', cursor: 'pointer', alignItems: 'center', textAlign: 'center', justifyContent: 'center', flexDirection: 'column', display: 'flex', border: '1px solid #d9ad1e', gap: '8px' }, onClick: () => {
|
|
1145
|
+
setPanelColor({
|
|
1146
|
+
background: '#f7c623',
|
|
1147
|
+
border: '#d9ad1e'
|
|
1148
|
+
});
|
|
1149
|
+
cookie.set('panelColor', '#f7c623|#d9ad1e');
|
|
1150
|
+
}, children: [panelColor.background === '#f7c623' ? _jsx(Tick, { color: "white", size: 12 }) : _jsx(_Fragment, {}), " ", _jsx("span", { style: { fontSize: '12px', color: '#fff' }, children: "Yellow" })] }), _jsxs("div", { style: { background: '#3bb0ff', width: '50px', height: '50px', borderRadius: '100px', cursor: 'pointer', alignItems: 'center', textAlign: 'center', justifyContent: 'center', flexDirection: 'column', display: 'flex', border: '1px solid #3290cf', gap: '8px' }, onClick: () => {
|
|
1151
|
+
setPanelColor({
|
|
1152
|
+
background: '#3bb0ff',
|
|
1153
|
+
border: '#3290cf'
|
|
1154
|
+
});
|
|
1155
|
+
cookie.set('panelColor', '#3bb0ff|#3290cf');
|
|
1156
|
+
}, children: [panelColor.background === '#3bb0ff' ? _jsx(Tick, { color: "white", size: 12 }) : _jsx(_Fragment, {}), " ", _jsx("span", { style: { fontSize: '12px', color: '#fff' }, children: "Blue" })] })] })] })] })) : aboutHostOpen && !shutdown ? (_jsxs(_Fragment, { children: [_jsxs("div", { style: {
|
|
1088
1157
|
padding: '6px 8px',
|
|
1089
1158
|
borderBottom: '1px solid #ddd',
|
|
1090
1159
|
background: '#fff',
|
|
@@ -1154,7 +1223,7 @@ export default function DevPanel() {
|
|
|
1154
1223
|
border: '1px solid #eee',
|
|
1155
1224
|
fontSize: '12px',
|
|
1156
1225
|
color: '#333',
|
|
1157
|
-
}, children: [_jsx("span", { style: { fontSize: '12px', color: '#333' }, children: "Total current users" }), _jsx("span", { style: { fontSize: '12px', color: 'blue' }, children: users })] }), _jsx(Sparkline, { data: cpuUsageHistory, color: "#3b82f6", label: "CPU Usage", unit: "" }), _jsx(Sparkline, { data: heapUsageHistory, color: "#3b82f6", label: "Heap Used", unit:
|
|
1226
|
+
}, children: [_jsx("span", { style: { fontSize: '12px', color: '#333' }, children: "Total current users" }), _jsx("span", { style: { fontSize: '12px', color: 'blue' }, children: users })] }), _jsx(Sparkline, { data: cpuUsageHistory, color: "#3b82f6", label: "CPU Usage", unit: "" }), _jsx(Sparkline, { data: heapUsageHistory, color: "#3b82f6", label: "Heap Used", unit: heapResult })] })] })) : !shutdown ? (_jsxs(_Fragment, { children: [_jsxs("div", { style: { padding: '8px', gap: '4px', display: 'flex', flexDirection: 'column' }, children: [_jsxs(PanelButton, { onClick: () => setConsoleOpen(true), fullWidth: true, style: { color: '#333', justifyContent: 'space-between', height: '32px' }, children: [_jsxs("span", { style: { display: 'flex', alignItems: 'center', gap: '6px' }, children: [_jsx(Terminal, { size: 12, color: "#16a34a" }), " Console"] }), logs.length > 0 && (_jsx("span", { style: { color: '#111', borderRadius: '100px', padding: '1px 6px', fontSize: '10px' }, children: logs.length }))] }), _jsxs(PanelButton, { onClick: () => setRouteOpen(true), fullWidth: true, style: { color: '#333', justifyContent: 'space-between', height: '32px' }, children: [_jsxs("span", { style: { display: 'flex', alignItems: 'center', gap: '6px' }, children: [_jsx(Route, { size: 12, color: "#3b82f6" }), " Route"] }), _jsxs("span", { style: { color: '#111', borderRadius: '100px', padding: '1px 6px', fontSize: '10px', display: 'flex', alignItems: 'center', justifyContent: 'center', gap: '4px' }, children: [datRestrictionMissing && _jsx(TriangleAlert, { size: 12, color: "orange" }), pathName] })] }), _jsxs(PanelButton, { onClick: () => setWebpageInfoOpen(true), fullWidth: true, style: { color: '#333', justifyContent: 'space-between', height: '32px' }, children: [_jsxs("span", { style: { display: 'flex', alignItems: 'center', gap: '6px' }, children: [_jsx(Globe, { size: 12, color: "#3b82f6" }), " Webpage Info"] }), datRestrictionMissing && _jsx(TriangleAlert, { size: 12, color: "orange" })] }), _jsx(PanelButton, { onClick: () => setPanelCustomOpen(true), fullWidth: true, style: { color: '#333', justifyContent: 'space-between', height: '32px' }, children: _jsxs("span", { style: { display: 'flex', alignItems: 'center', gap: '6px' }, children: [_jsx(Cog, { size: 12, color: "#3b82f6" }), " Panel Customization"] }) }), _jsx(PanelButton, { onClick: () => setNetworkOpen(true), fullWidth: true, style: { color: '#333', justifyContent: 'space-between', height: '32px' }, children: _jsxs("span", { style: { display: 'flex', alignItems: 'center', gap: '6px' }, children: [_jsx(Wifi, { size: 12, color: "#3b82f6" }), " Network"] }) }), _jsxs(PanelButton, { onClick: () => setClientInfoOpen(true), fullWidth: true, style: { color: '#333', justifyContent: 'space-between', height: '32px' }, children: [_jsxs("span", { style: { display: 'flex', alignItems: 'center', gap: '6px' }, children: [_jsx(Info, { size: 12, color: "#3b82f6" }), " Client Info"] }), datRestrictionMissing && _jsx(TriangleAlert, { size: 12, color: "orange" })] }), _jsxs(PanelButton, { onClick: () => setAboutHostOpen(true), fullWidth: true, style: { color: '#333', justifyContent: 'space-between', height: '32px' }, children: [_jsxs("span", { style: { display: 'flex', alignItems: 'center', gap: '6px' }, children: [_jsx(ShieldCheck, { size: 12, color: "#f472b6" }), " About HostJS"] }), datRestrictionMissing && _jsx(TriangleAlert, { size: 12, color: "orange" })] }), _jsxs(PanelButton, { onClick: () => setServerInfoOpen(true), fullWidth: true, style: { color: '#333', justifyContent: 'space-between', height: '32px' }, children: [_jsxs("span", { style: { display: 'flex', alignItems: 'center', gap: '6px' }, children: [_jsx(Server, { size: 12, color: "#f472b6" }), " Server Info"] }), datRestrictionMissing && _jsx(TriangleAlert, { size: 12, color: "orange" })] })] }), _jsxs("div", { style: {
|
|
1158
1227
|
padding: '6px 8px',
|
|
1159
1228
|
borderTop: '1px solid #ddd',
|
|
1160
1229
|
background: '#fff',
|
|
@@ -1214,8 +1283,8 @@ export default function DevPanel() {
|
|
|
1214
1283
|
alignItems: 'center',
|
|
1215
1284
|
padding: '8px 12px',
|
|
1216
1285
|
borderRadius: hasIssue ? '100px' : '10px',
|
|
1217
|
-
background: hasIssue ? '#ba4e4e' :
|
|
1218
|
-
border: hasIssue ? '1px solid #991b1b' :
|
|
1286
|
+
background: hasIssue ? '#ba4e4e' : panelColor.background,
|
|
1287
|
+
border: hasIssue ? '1px solid #991b1b' : `1px solid ${panelColor.border ?? '#333'}`,
|
|
1219
1288
|
boxShadow: hasIssue
|
|
1220
1289
|
? '0 4px 20px rgba(220,38,38,0.2)'
|
|
1221
1290
|
: '0 4px 20px rgba(0,0,0,0.4)',
|
package/dist/renderEngine.d.ts
CHANGED
|
@@ -1,3 +1,6 @@
|
|
|
1
|
+
import React from "react";
|
|
2
|
+
export declare function handleSrtwsConnection(server: any, PageComponent: React.ComponentType<any>): boolean;
|
|
1
3
|
export type CompilerType = 'esbuild';
|
|
4
|
+
export type RenderMode = 'ssr' | 'csr' | 'ssg' | 'srtws';
|
|
2
5
|
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, autoPageDir?: string, appDir?: string, fileHandler?: (f: string, p: string) => void, rmvFileHandler?: (p: string) => void, reqDAT?: string | undefined, configDAT?: string | string[] | undefined): Promise<string>;
|
|
6
|
+
export declare function renderPage(tsxPath: string, reqUrl?: string, showPanel?: boolean, compiler?: CompilerType, hotReload?: boolean, autoPaging?: boolean, autoPageDir?: string, appDir?: string, fileHandler?: (f: string, p: string) => void, rmvFileHandler?: (p: string) => void, reqDAT?: string | undefined, configDAT?: string | string[] | undefined, renderMode?: RenderMode, patchForSsr?: boolean): Promise<string>;
|
package/dist/renderEngine.js
CHANGED
|
@@ -7,6 +7,32 @@ import { renderToString } from "react-dom/server";
|
|
|
7
7
|
import { tempFileForTsx, writeTempFile, readTempFile, ensureTempDirs, } from "./rendererTempFiles.js";
|
|
8
8
|
import { createRequire } from "node:module";
|
|
9
9
|
const customRequire = createRequire(import.meta.url);
|
|
10
|
+
import { WebSocketServer } from "ws";
|
|
11
|
+
export function handleSrtwsConnection(server, PageComponent) {
|
|
12
|
+
const wss = new WebSocketServer({ noServer: true });
|
|
13
|
+
server.on("upgrade", (req, socket, head) => {
|
|
14
|
+
if (req.url === "/__authtics_srtws__") {
|
|
15
|
+
wss.handleUpgrade(req, socket, head, (ws) => {
|
|
16
|
+
wss.emit("connection", ws, req);
|
|
17
|
+
});
|
|
18
|
+
}
|
|
19
|
+
});
|
|
20
|
+
wss.on("connection", (ws) => {
|
|
21
|
+
const renderAndSend = () => {
|
|
22
|
+
const pageHtml = renderToString(React.createElement(PageComponent));
|
|
23
|
+
ws.send(JSON.stringify({ type: "DOM", html: pageHtml }));
|
|
24
|
+
};
|
|
25
|
+
ws.on("message", () => {
|
|
26
|
+
try {
|
|
27
|
+
renderAndSend();
|
|
28
|
+
}
|
|
29
|
+
catch (err) {
|
|
30
|
+
console.error("[authtics] SRTWS error:", err);
|
|
31
|
+
}
|
|
32
|
+
});
|
|
33
|
+
});
|
|
34
|
+
return true;
|
|
35
|
+
}
|
|
10
36
|
const __filename = fileURLToPath(import.meta.url);
|
|
11
37
|
const __dirname = path.dirname(__filename);
|
|
12
38
|
const NODE_BUILTINS = [
|
|
@@ -23,6 +49,24 @@ const NODE_BUILTINS = [
|
|
|
23
49
|
'node:module', 'node:process', 'node:string_decoder', 'node:querystring',
|
|
24
50
|
'express', 'jiti',
|
|
25
51
|
];
|
|
52
|
+
const SRTWS_CLIENT_SCRIPT = `<script>
|
|
53
|
+
(function() {
|
|
54
|
+
const protocol = window.location.protocol === 'https:' ? 'wss://' : 'ws://';
|
|
55
|
+
const ws = new WebSocket(protocol + window.location.host + '/__authtics_srtws__');
|
|
56
|
+
|
|
57
|
+
ws.onmessage = function(event) {
|
|
58
|
+
const msg = JSON.parse(event.data);
|
|
59
|
+
if (msg.type === 'DOM') {
|
|
60
|
+
const root = document.getElementById('root');
|
|
61
|
+
if (root) root.innerHTML = msg.html;
|
|
62
|
+
}
|
|
63
|
+
};
|
|
64
|
+
|
|
65
|
+
ws.onopen = function() {
|
|
66
|
+
ws.send(JSON.stringify({}));
|
|
67
|
+
};
|
|
68
|
+
})();
|
|
69
|
+
</script>`;
|
|
26
70
|
const nodeStubPlugin = {
|
|
27
71
|
name: 'browser-node-stub',
|
|
28
72
|
setup(build) {
|
|
@@ -42,7 +86,7 @@ const nodeStubPlugin = {
|
|
|
42
86
|
}));
|
|
43
87
|
},
|
|
44
88
|
};
|
|
45
|
-
async function buildWithEsbuild(virtualContent, resolveDir, platform) {
|
|
89
|
+
async function buildWithEsbuild(virtualContent, resolveDir, platform, patchForSsr = false) {
|
|
46
90
|
const toFwdSlash = (p) => p.split(path.sep).join('/');
|
|
47
91
|
const isNode = platform === 'node';
|
|
48
92
|
const result = await esbuild.build({
|
|
@@ -56,10 +100,86 @@ async function buildWithEsbuild(virtualContent, resolveDir, platform) {
|
|
|
56
100
|
format: isNode ? 'cjs' : 'iife',
|
|
57
101
|
platform,
|
|
58
102
|
jsx: 'automatic',
|
|
59
|
-
sourcemap:
|
|
103
|
+
sourcemap: false,
|
|
60
104
|
target: isNode ? ['node18'] : ['es2020'],
|
|
61
105
|
minify: true,
|
|
62
106
|
treeShaking: true,
|
|
107
|
+
banner: (isNode && patchForSsr) ? {
|
|
108
|
+
js: `if (typeof globalThis.window === "undefined") {
|
|
109
|
+
const noop = () => {};
|
|
110
|
+
|
|
111
|
+
const createStorageMock = () => {
|
|
112
|
+
let store = {};
|
|
113
|
+
return {
|
|
114
|
+
getItem: (key) => store[key] ?? null,
|
|
115
|
+
setItem: (key, val) => { store[key] = String(val); },
|
|
116
|
+
removeItem: (key) => { delete store[key]; },
|
|
117
|
+
clear: () => { store = {}; },
|
|
118
|
+
key: (i) => Object.keys(store)[i] ?? null,
|
|
119
|
+
get length() { return Object.keys(store).length; },
|
|
120
|
+
};
|
|
121
|
+
};
|
|
122
|
+
|
|
123
|
+
const mockLocalStorage = createStorageMock();
|
|
124
|
+
const mockSessionStorage = createStorageMock();
|
|
125
|
+
|
|
126
|
+
const mockElement = {
|
|
127
|
+
setAttribute: noop,
|
|
128
|
+
getAttribute: () => null,
|
|
129
|
+
removeAttribute: noop,
|
|
130
|
+
style: {},
|
|
131
|
+
appendChild: (node) => node,
|
|
132
|
+
removeChild: (node) => node,
|
|
133
|
+
addEventListener: noop,
|
|
134
|
+
removeEventListener: noop,
|
|
135
|
+
classList: { add: noop, remove: noop, toggle: noop, contains: () => false },
|
|
136
|
+
};
|
|
137
|
+
|
|
138
|
+
const mockDocument = {
|
|
139
|
+
createElement: () => mockElement,
|
|
140
|
+
querySelector: () => null,
|
|
141
|
+
querySelectorAll: () => [],
|
|
142
|
+
getElementById: () => null,
|
|
143
|
+
getElementsByTagName: () => [],
|
|
144
|
+
getElementsByClassName: () => [],
|
|
145
|
+
cookie: "",
|
|
146
|
+
body: mockElement,
|
|
147
|
+
documentElement: mockElement,
|
|
148
|
+
addEventListener: noop,
|
|
149
|
+
removeEventListener: noop,
|
|
150
|
+
};
|
|
151
|
+
|
|
152
|
+
const mockNavigator = {
|
|
153
|
+
userAgent: "Mozilla/5.0 (Server-Side)",
|
|
154
|
+
language: "en-US",
|
|
155
|
+
languages: ["en-US"],
|
|
156
|
+
onLine: true,
|
|
157
|
+
clipboard: { writeText: async () => {}, readText: async () => "" },
|
|
158
|
+
};
|
|
159
|
+
|
|
160
|
+
|
|
161
|
+
globalThis.document = globalThis.document || mockDocument;
|
|
162
|
+
globalThis.navigator = globalThis.navigator || mockNavigator;
|
|
163
|
+
globalThis.localStorage = globalThis.localStorage || mockLocalStorage;
|
|
164
|
+
globalThis.sessionStorage = globalThis.sessionStorage || mockSessionStorage;
|
|
165
|
+
|
|
166
|
+
globalThis.window = new Proxy(globalThis, {
|
|
167
|
+
get: (target, prop) => {
|
|
168
|
+
if (prop in target) return target[prop];
|
|
169
|
+
if (prop === 'document') return globalThis.document;
|
|
170
|
+
if (prop === 'navigator') return globalThis.navigator;
|
|
171
|
+
if (prop === 'localStorage') return globalThis.localStorage;
|
|
172
|
+
if (prop === 'sessionStorage') return globalThis.sessionStorage;
|
|
173
|
+
if (prop === 'addEventListener' || prop === 'removeEventListener') return noop;
|
|
174
|
+
if (prop === 'location') return { href: '', search: '', pathname: '/', origin: '', assign: noop, replace: noop };
|
|
175
|
+
if (prop === 'matchMedia') return () => ({ matches: false, addEventListener: noop, removeEventListener: noop, dispatchEvent: noop });
|
|
176
|
+
if (prop === 'getComputedStyle') return () => ({ getPropertyValue: () => '' });
|
|
177
|
+
if (prop === 'requestAnimationFrame' || prop === 'cancelAnimationFrame') return (cb) => setTimeout(cb, 0);
|
|
178
|
+
return undefined;
|
|
179
|
+
}
|
|
180
|
+
});
|
|
181
|
+
}`
|
|
182
|
+
} : undefined,
|
|
63
183
|
plugins: isNode ? [] : [nodeStubPlugin],
|
|
64
184
|
external: isNode
|
|
65
185
|
? ['react', 'react-dom', 'react-dom/server', 'react/jsx-runtime', 'react/jsx-dev-runtime',
|
|
@@ -108,17 +228,18 @@ function resolveTemplate(appDir, autoPageDir, autoPaging) {
|
|
|
108
228
|
return nextToCli;
|
|
109
229
|
}
|
|
110
230
|
function buildHtml(opts) {
|
|
111
|
-
const { pageHtml, clientCode, devPanelContainer, templatePath, hotReload, fileName, datRestricted, devMode } = opts;
|
|
231
|
+
const { pageHtml, clientCode, devPanelContainer, templatePath, hotReload, fileName, datRestricted, devMode, renderMode } = opts;
|
|
112
232
|
const configScript = `<script>window.__authtics_config__={datRestricted:${datRestricted ? 'true' : 'false'},devMode:${devMode !== false ? 'true' : 'false'}};</script>`;
|
|
113
233
|
const hmrScript = hotReload ? HMR_SCRIPT : '';
|
|
234
|
+
const srtwsScript = renderMode === 'srtws' ? SRTWS_CLIENT_SCRIPT : '';
|
|
114
235
|
if (templatePath && fs.existsSync(templatePath)) {
|
|
115
236
|
let template = fs.readFileSync(templatePath, "utf-8");
|
|
116
237
|
const contentTag = /<authtics_host_content\s*\/>/i;
|
|
117
238
|
if (contentTag.test(template)) {
|
|
118
239
|
template = template.replace(contentTag, `<div id="root">${pageHtml}</div>\n ${devPanelContainer}`);
|
|
119
240
|
template = template.includes("</body>")
|
|
120
|
-
? template.replace("</body>", ` ${configScript}${fileName ? `<script src="${fileName}"></script>` : `<script>${clientCode}</script>`}\n${hmrScript}</body>`)
|
|
121
|
-
: template + `\n${configScript}${fileName ? `<script src="${fileName}"></script>` : `<script>${clientCode}</script>`}\n${hmrScript}`;
|
|
241
|
+
? template.replace("</body>", ` ${configScript}${srtwsScript}${fileName ? `<script src="${fileName}"></script>` : `<script>${clientCode}</script>`}\n${hmrScript}</body>`)
|
|
242
|
+
: template + `\n${configScript}${srtwsScript}${fileName ? `<script src="${fileName}"></script>` : `<script>${clientCode}</script>`}\n${hmrScript}`;
|
|
122
243
|
return template;
|
|
123
244
|
}
|
|
124
245
|
console.warn('[authtics] _template.html has no <authtics_host_content /> — using default layout.');
|
|
@@ -133,7 +254,8 @@ function buildHtml(opts) {
|
|
|
133
254
|
<div id="root">${pageHtml}</div>
|
|
134
255
|
${devPanelContainer}
|
|
135
256
|
${configScript}
|
|
136
|
-
${fileName ? `<script src="${fileName}"></script>` : `<script>${clientCode}</script>`}
|
|
257
|
+
${renderMode === 'srtws' ? '' : (fileName ? `<script src="${fileName}"></script>` : `<script>${clientCode}</script>`)}
|
|
258
|
+
${srtwsScript}
|
|
137
259
|
${hmrScript}
|
|
138
260
|
</body>
|
|
139
261
|
</html>`;
|
|
@@ -180,7 +302,7 @@ const HMR_SCRIPT = `<script>(function(){
|
|
|
180
302
|
}
|
|
181
303
|
};
|
|
182
304
|
})();</script>`;
|
|
183
|
-
export async function renderPage(tsxPath, reqUrl, showPanel = true, compiler = 'esbuild', hotReload = false, autoPaging = true, autoPageDir, appDir, fileHandler, rmvFileHandler, reqDAT, configDAT) {
|
|
305
|
+
export async function renderPage(tsxPath, reqUrl, showPanel = true, compiler = 'esbuild', hotReload = false, autoPaging = true, autoPageDir, appDir, fileHandler, rmvFileHandler, reqDAT, configDAT, renderMode = 'ssr', patchForSsr = false) {
|
|
184
306
|
ensureTempDirs();
|
|
185
307
|
if (!fs.existsSync(tsxPath)) {
|
|
186
308
|
throw new Error(`renderPage: source file not found: ${tsxPath}`);
|
|
@@ -198,6 +320,14 @@ export async function renderPage(tsxPath, reqUrl, showPanel = true, compiler = '
|
|
|
198
320
|
const templatePath = resolveTemplate(appDir, autoPageDir, autoPaging);
|
|
199
321
|
const tempPath = tempFileForTsx(tsxPath);
|
|
200
322
|
const serverCjsPath = tempPath.replace(/\.json$/, ".server.cjs");
|
|
323
|
+
const ssgHtmlPath = tempPath.replace(/\.json$/, ".ssg.html");
|
|
324
|
+
if (renderMode === 'ssg' && isCacheValid(tsxPath, ssgHtmlPath, serverCjsPath, templatePath, devPanelPath)) {
|
|
325
|
+
try {
|
|
326
|
+
return fs.readFileSync(ssgHtmlPath, "utf-8");
|
|
327
|
+
}
|
|
328
|
+
catch {
|
|
329
|
+
}
|
|
330
|
+
}
|
|
201
331
|
let clientCode;
|
|
202
332
|
let serverCode;
|
|
203
333
|
let freshWrite = false;
|
|
@@ -210,7 +340,8 @@ export async function renderPage(tsxPath, reqUrl, showPanel = true, compiler = '
|
|
|
210
340
|
catch {
|
|
211
341
|
}
|
|
212
342
|
}
|
|
213
|
-
|
|
343
|
+
const isCsr = renderMode === 'csr';
|
|
344
|
+
if (!clientCode || (!serverCode && !isCsr)) {
|
|
214
345
|
const virtualServer = `
|
|
215
346
|
${usesDevPanel ? `import DevPanel from ${JSON.stringify(devPanelPath)};` : ""}
|
|
216
347
|
import Page from ${JSON.stringify(tsxPath)};
|
|
@@ -219,49 +350,71 @@ export async function renderPage(tsxPath, reqUrl, showPanel = true, compiler = '
|
|
|
219
350
|
`;
|
|
220
351
|
const virtualClient = `
|
|
221
352
|
import React from "react";
|
|
222
|
-
import { hydrateRoot } from "react-dom/client";
|
|
353
|
+
import { ${renderMode === 'csr' ? 'createRoot' : 'hydrateRoot'} } from "react-dom/client";
|
|
223
354
|
${usesDevPanel ? `import DevPanel from ${JSON.stringify(devPanelPath)};` : ""}
|
|
224
355
|
import Page from ${JSON.stringify(tsxPath)};
|
|
225
356
|
|
|
226
357
|
${usesDevPanel ? `
|
|
227
358
|
const panelEl = document.getElementById("authtics-dev-panel-root");
|
|
228
|
-
if (panelEl) hydrateRoot(panelEl, React.createElement(DevPanel))
|
|
359
|
+
if (panelEl) ${renderMode === 'csr' ? `createRoot(panelEl).render(React.createElement(DevPanel));` : `hydrateRoot(panelEl, React.createElement(DevPanel));`}
|
|
229
360
|
` : ""}
|
|
230
361
|
const rootEl = document.getElementById("root");
|
|
231
|
-
if (rootEl)
|
|
362
|
+
if (rootEl) {
|
|
363
|
+
${renderMode === 'csr'
|
|
364
|
+
? `createRoot(rootEl).render(React.createElement(Page));`
|
|
365
|
+
: `hydrateRoot(rootEl, React.createElement(Page));`}
|
|
366
|
+
}
|
|
232
367
|
`;
|
|
233
368
|
if (compiler === 'esbuild') {
|
|
234
|
-
|
|
235
|
-
|
|
369
|
+
if (!isCsr)
|
|
370
|
+
serverCode = await buildWithEsbuild(virtualServer, process.cwd(), 'node', patchForSsr);
|
|
371
|
+
if (renderMode !== 'srtws') {
|
|
372
|
+
clientCode = await buildWithEsbuild(virtualClient, process.cwd(), 'browser');
|
|
373
|
+
}
|
|
374
|
+
else {
|
|
375
|
+
clientCode = "";
|
|
376
|
+
}
|
|
236
377
|
}
|
|
237
|
-
|
|
378
|
+
if (serverCode)
|
|
379
|
+
await fs.promises.writeFile(serverCjsPath, serverCode || "", "utf-8");
|
|
238
380
|
writeTempFile(tempPath, JSON.stringify({ clientCode }));
|
|
239
381
|
freshWrite = true;
|
|
240
382
|
}
|
|
241
383
|
fileHandler ? fileHandler(clientCode || "", `/${path.basename(tempPath).replace(".json", ".js").replace(".tsx_", ".").toLowerCase()}`) : null;
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
const exports = serverModule.__esModule ? serverModule.default : serverModule;
|
|
246
|
-
const PageComponent = exports?.default?.default ??
|
|
247
|
-
exports?.default ??
|
|
248
|
-
exports?.Page ??
|
|
249
|
-
exports?.page ??
|
|
250
|
-
(typeof exports === 'function' ? exports : null);
|
|
251
|
-
const DevPanelComponent = usesDevPanel ? (exports.DevPanel ?? null) : null;
|
|
252
|
-
if (!PageComponent) {
|
|
253
|
-
throw new Error(`renderPage: no default export found in ${tsxPath}`);
|
|
254
|
-
}
|
|
255
|
-
const pageHtml = renderToString(React.createElement(PageComponent));
|
|
256
|
-
const devPanelHtml = DevPanelComponent
|
|
257
|
-
? renderToString(React.createElement(DevPanelComponent))
|
|
258
|
-
: "";
|
|
259
|
-
const devPanelContainer = usesDevPanel
|
|
260
|
-
? `<div id="authtics-dev-panel-root">${devPanelHtml}</div>`
|
|
384
|
+
let pageHtml = "";
|
|
385
|
+
let devPanelContainer = usesDevPanel
|
|
386
|
+
? `<div id="authtics-dev-panel-root"></div>`
|
|
261
387
|
: "";
|
|
262
|
-
|
|
388
|
+
if (!isCsr) {
|
|
389
|
+
const absoluteServerPath = path.resolve(serverCjsPath);
|
|
390
|
+
delete customRequire.cache[absoluteServerPath];
|
|
391
|
+
const serverModule = customRequire(absoluteServerPath);
|
|
392
|
+
const exports = serverModule.__esModule ? serverModule.default : serverModule;
|
|
393
|
+
const PageComponent = exports?.default?.default ??
|
|
394
|
+
exports?.default ??
|
|
395
|
+
exports?.Page ??
|
|
396
|
+
exports?.page ??
|
|
397
|
+
(typeof exports === 'function' ? exports : null);
|
|
398
|
+
const DevPanelComponent = usesDevPanel ? (exports.DevPanel ?? null) : null;
|
|
399
|
+
if (!PageComponent) {
|
|
400
|
+
throw new Error(`renderPage: no default export found in ${tsxPath}`);
|
|
401
|
+
}
|
|
402
|
+
pageHtml = renderToString(React.createElement(PageComponent));
|
|
403
|
+
const devPanelHtml = DevPanelComponent
|
|
404
|
+
? renderToString(React.createElement(DevPanelComponent))
|
|
405
|
+
: "";
|
|
406
|
+
devPanelContainer = usesDevPanel
|
|
407
|
+
? `<div id="authtics-dev-panel-root">${devPanelHtml}</div>`
|
|
408
|
+
: "";
|
|
409
|
+
}
|
|
410
|
+
const finalHtml = buildHtml({ pageHtml, clientCode: clientCode || "", devPanelContainer, templatePath, hotReload,
|
|
263
411
|
fileName: `/${path.basename(tempPath).replace(".json", ".js").replace(".tsx_", ".").toLowerCase()}`,
|
|
264
412
|
datRestricted: configDAT !== undefined,
|
|
265
413
|
devMode: showPanel,
|
|
414
|
+
renderMode
|
|
266
415
|
});
|
|
416
|
+
if (renderMode === 'ssg') {
|
|
417
|
+
await fs.promises.writeFile(ssgHtmlPath, finalHtml, "utf-8");
|
|
418
|
+
}
|
|
419
|
+
return finalHtml;
|
|
267
420
|
}
|
package/package.json
CHANGED
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@bananacool467/authtics-host",
|
|
3
|
-
"version": "0.2.
|
|
4
|
-
"description": "Authtics Host, A Next.js-inspired
|
|
3
|
+
"version": "0.2.6",
|
|
4
|
+
"description": "Authtics Host, A Next.js-inspired web framework for Node.js and React with TypeScript and JSX support.",
|
|
5
5
|
"main": "./dist/index.js",
|
|
6
6
|
"types": "./dist/index.d.ts",
|
|
7
7
|
"type": "module",
|
|
8
8
|
"sideEffects": false,
|
|
9
9
|
"bin": {
|
|
10
|
-
"
|
|
10
|
+
"host": "dist/cli.js"
|
|
11
11
|
},
|
|
12
12
|
"exports": {
|
|
13
13
|
".": "./dist/index.js"
|
|
@@ -25,6 +25,9 @@
|
|
|
25
25
|
"host",
|
|
26
26
|
"server-side-rendering",
|
|
27
27
|
"ssr",
|
|
28
|
+
"ssg",
|
|
29
|
+
"csr",
|
|
30
|
+
"srtws",
|
|
28
31
|
"framework",
|
|
29
32
|
"nodejs",
|
|
30
33
|
"typescript",
|
|
@@ -44,26 +47,28 @@
|
|
|
44
47
|
"author": "bananacool467",
|
|
45
48
|
"license": "MIT",
|
|
46
49
|
"dependencies": {
|
|
47
|
-
"esbuild": "^0.
|
|
50
|
+
"esbuild": "^0.28.2",
|
|
48
51
|
"jiti": "^2.6.1",
|
|
49
52
|
"lucide-react": "^0.577.0",
|
|
50
|
-
"prismjs": "^1.30.0"
|
|
53
|
+
"prismjs": "^1.30.0",
|
|
54
|
+
"ws": "^8.21.3"
|
|
51
55
|
},
|
|
52
56
|
"peerDependencies": {
|
|
53
57
|
"react": "^19.2.4",
|
|
54
58
|
"react-dom": "^19.2.4"
|
|
55
59
|
},
|
|
56
60
|
"devDependencies": {
|
|
61
|
+
"@babel/core": "^7.29.0",
|
|
62
|
+
"@babel/preset-env": "^7.29.0",
|
|
63
|
+
"@babel/preset-react": "^7.28.5",
|
|
64
|
+
"@babel/preset-typescript": "^7.28.5",
|
|
65
|
+
"@types/babel__core": "^7.20.5",
|
|
66
|
+
"@types/babel__preset-env": "^7.10.0",
|
|
57
67
|
"@types/node": "^22.13.11",
|
|
58
68
|
"@types/prismjs": "^1.26.6",
|
|
59
69
|
"@types/react": "^19.2.14",
|
|
60
70
|
"@types/react-dom": "^19.2.3",
|
|
61
71
|
"@types/react-syntax-highlighter": "^15.5.13",
|
|
62
|
-
"@types/
|
|
63
|
-
"@types/babel__preset-env": "^7.10.0",
|
|
64
|
-
"@babel/core": "^7.29.0",
|
|
65
|
-
"@babel/preset-env": "^7.29.0",
|
|
66
|
-
"@babel/preset-react": "^7.28.5",
|
|
67
|
-
"@babel/preset-typescript": "^7.28.5"
|
|
72
|
+
"@types/ws": "^8.18.1"
|
|
68
73
|
}
|
|
69
74
|
}
|