htmx-router 1.0.0-pre1 → 1.0.0-pre4
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/cli/config.d.ts +13 -0
- package/cli/config.js +11 -0
- package/cli/index.d.ts +2 -0
- package/cli/index.js +37 -0
- package/cookies.d.ts +29 -0
- package/cookies.js +82 -0
- package/css.d.ts +21 -0
- package/css.js +60 -0
- package/defer.d.ts +14 -0
- package/defer.js +80 -0
- package/endpoint.d.ts +20 -0
- package/endpoint.js +40 -0
- package/event-source.d.ts +26 -0
- package/event-source.js +116 -0
- package/index.d.ts +19 -0
- package/index.js +2 -0
- package/internal/client.d.ts +1 -0
- package/internal/client.js +14 -0
- package/internal/compile/manifest.d.ts +1 -0
- package/internal/compile/manifest.js +179 -0
- package/internal/component/defer.d.ts +4 -0
- package/internal/component/defer.js +19 -0
- package/internal/component/head.d.ts +5 -0
- package/internal/component/head.js +22 -0
- package/internal/component/index.d.ts +4 -0
- package/internal/component/index.js +4 -0
- package/internal/component/scripts.d.ts +4 -0
- package/internal/component/scripts.js +23 -0
- package/internal/mount.d.ts +10 -0
- package/internal/mount.js +88 -0
- package/internal/request/http.d.ts +10 -0
- package/internal/request/http.js +61 -0
- package/internal/request/index.d.ts +17 -0
- package/internal/request/index.js +8 -0
- package/internal/request/native.d.ts +9 -0
- package/internal/request/native.js +48 -0
- package/internal/router.d.ts +15 -0
- package/internal/router.js +24 -0
- package/internal/util.d.ts +4 -0
- package/internal/util.js +49 -0
- package/package.json +2 -2
- package/response.d.ts +13 -0
- package/response.js +46 -0
- package/router.d.ts +33 -0
- package/router.js +206 -0
- package/shell.d.ts +120 -0
- package/shell.js +261 -0
- package/util/parameters.d.ts +10 -0
- package/util/parameters.js +1 -0
- package/util/path-builder.d.ts +1 -0
- package/util/path-builder.js +45 -0
- package/util/route.d.ts +2 -0
- package/util/route.js +58 -0
- package/vite/bundle-splitter.d.ts +4 -0
- package/vite/bundle-splitter.js +26 -0
- package/vite/client-island.d.ts +4 -0
- package/vite/client-island.js +14 -0
- package/vite/index.d.ts +3 -0
- package/vite/index.js +3 -0
- package/vite/router.d.ts +2 -0
- package/vite/router.js +29 -0
- package/example/eventdim-react/package.json +0 -67
- package/example/eventdim-react/server.js +0 -90
- package/example/island-react/global.d.ts +0 -8
- package/example/island-react/package.json +0 -38
- package/example/island-react/server.js +0 -58
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import { ServerOnlyWarning } from "../internal/util.js";
|
|
2
|
+
ServerOnlyWarning("path-builder");
|
|
3
|
+
import { relative } from "path";
|
|
4
|
+
/*
|
|
5
|
+
// This feature is disabled because vite doesn't compile import.meta.url to the original url when making the SSR build
|
|
6
|
+
// Even though it's used statically in the routes
|
|
7
|
+
|
|
8
|
+
const parameters = {
|
|
9
|
+
userID: Number
|
|
10
|
+
};
|
|
11
|
+
|
|
12
|
+
const urlPath = RoutePathBuilder<typeof parameters>(import.meta.url);
|
|
13
|
+
|
|
14
|
+
export function loader({ params }: RouteContext<typeof parameters>) {
|
|
15
|
+
return <div>You are currently at {urlPath({ userID: params.userID.toString() })}</div>
|
|
16
|
+
}
|
|
17
|
+
*/
|
|
18
|
+
// This feature isn't particularly helpful for a router to refer to it's own URL
|
|
19
|
+
// But instead is useful because you could export this function
|
|
20
|
+
// Allowing other routes to use it, and thus if you move the file your imports will auto update by your LSP
|
|
21
|
+
// And thus so would your SSR rendered urls
|
|
22
|
+
function RoutePathBuilder(importUrl) {
|
|
23
|
+
// file runs all imports before actually executing the route.tsx
|
|
24
|
+
// so I have to do this BS instead of pre-compiling
|
|
25
|
+
let compiled = null;
|
|
26
|
+
return (params) => {
|
|
27
|
+
if (!compiled) {
|
|
28
|
+
const root = globalThis.HTMX_ROUTER_ROOT;
|
|
29
|
+
let path = importUrl.slice("file:///".length);
|
|
30
|
+
const raw = relative(root, path).replaceAll("\\", "/");
|
|
31
|
+
const i = raw.lastIndexOf(".");
|
|
32
|
+
compiled = raw.slice(0, i).split("/");
|
|
33
|
+
}
|
|
34
|
+
let path = "";
|
|
35
|
+
for (const frag of compiled) {
|
|
36
|
+
path += "/";
|
|
37
|
+
if (frag[0] != "$") {
|
|
38
|
+
path += frag;
|
|
39
|
+
continue;
|
|
40
|
+
}
|
|
41
|
+
path += params[frag.slice(1)] || "_";
|
|
42
|
+
}
|
|
43
|
+
return path;
|
|
44
|
+
};
|
|
45
|
+
}
|
package/util/route.d.ts
ADDED
package/util/route.js
ADDED
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
import { ServerOnlyWarning } from "../internal/util.js";
|
|
2
|
+
ServerOnlyWarning("route-path");
|
|
3
|
+
export function RoutePath() {
|
|
4
|
+
const frags = new Array();
|
|
5
|
+
return (params) => {
|
|
6
|
+
const t = params;
|
|
7
|
+
if (typeof t === "string") {
|
|
8
|
+
Compile("/" + t, frags);
|
|
9
|
+
return "";
|
|
10
|
+
}
|
|
11
|
+
return Parse(frags, params);
|
|
12
|
+
};
|
|
13
|
+
}
|
|
14
|
+
const indexRoute = "/_index";
|
|
15
|
+
function Compile(url, into) {
|
|
16
|
+
let cursor = 0;
|
|
17
|
+
let i = 1;
|
|
18
|
+
for (; i < url.length; i++) {
|
|
19
|
+
if (url[i] !== "$")
|
|
20
|
+
continue;
|
|
21
|
+
if (url[i - 1] !== "/")
|
|
22
|
+
continue;
|
|
23
|
+
let e = url.indexOf("/", i + 1);
|
|
24
|
+
if (e === -1)
|
|
25
|
+
e = url.length;
|
|
26
|
+
into.push(url.slice(cursor, i));
|
|
27
|
+
into.push(url.slice(i, e));
|
|
28
|
+
cursor = e;
|
|
29
|
+
i = e - 1;
|
|
30
|
+
}
|
|
31
|
+
// remainder
|
|
32
|
+
if (cursor != i)
|
|
33
|
+
into.push(url.slice(cursor));
|
|
34
|
+
// remove _index from end if present
|
|
35
|
+
const lastI = into.length - 1;
|
|
36
|
+
const last = into[lastI];
|
|
37
|
+
if (last && last.endsWith(indexRoute)) {
|
|
38
|
+
if (last.length === indexRoute.length)
|
|
39
|
+
into.length--;
|
|
40
|
+
else
|
|
41
|
+
into[lastI] = last.slice(0, -indexRoute.length);
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
function Parse(fragments, params) {
|
|
45
|
+
let out = "";
|
|
46
|
+
for (const frag of fragments) {
|
|
47
|
+
if (!frag.startsWith("$")) {
|
|
48
|
+
out += frag;
|
|
49
|
+
continue;
|
|
50
|
+
}
|
|
51
|
+
const key = frag.slice(1);
|
|
52
|
+
const param = params[key];
|
|
53
|
+
if (!param)
|
|
54
|
+
throw new Error(`Missing ${key} parameter required for route`);
|
|
55
|
+
out += param;
|
|
56
|
+
}
|
|
57
|
+
return out;
|
|
58
|
+
}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import { ServerOnlyWarning } from "../internal/util.js";
|
|
2
|
+
ServerOnlyWarning("bundle-splitter");
|
|
3
|
+
const serverPattern = /\.server\.[tj]s(x)?/;
|
|
4
|
+
const clientPattern = /\.client\.[tj]s(x)?/;
|
|
5
|
+
const BLANK_MODULE = "export {};";
|
|
6
|
+
export function BundleSplitter() {
|
|
7
|
+
return {
|
|
8
|
+
name: "htmx-bundle-splitter",
|
|
9
|
+
enforce: "pre",
|
|
10
|
+
transform: (code, id, options) => {
|
|
11
|
+
const ssr = options?.ssr || false;
|
|
12
|
+
const pattern = ssr ? clientPattern : serverPattern;
|
|
13
|
+
if (pattern.test(id))
|
|
14
|
+
return BLANK_MODULE;
|
|
15
|
+
if (ssr) {
|
|
16
|
+
if (code.startsWith('"use client"'))
|
|
17
|
+
return BLANK_MODULE;
|
|
18
|
+
}
|
|
19
|
+
else {
|
|
20
|
+
if (code.startsWith('"use server"'))
|
|
21
|
+
return BLANK_MODULE;
|
|
22
|
+
}
|
|
23
|
+
return code;
|
|
24
|
+
}
|
|
25
|
+
};
|
|
26
|
+
}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { resolve } from "path";
|
|
2
|
+
import { CompileManifest } from "../internal/compile/manifest.js";
|
|
3
|
+
export function ClientIsland(framework) {
|
|
4
|
+
const file = resolve("./app/manifest.tsx").replaceAll("\\", "/");
|
|
5
|
+
return {
|
|
6
|
+
name: "vite-plugin-htmx-client-island",
|
|
7
|
+
enforce: "pre",
|
|
8
|
+
transform: (code, id, options) => {
|
|
9
|
+
if (id !== file)
|
|
10
|
+
return code;
|
|
11
|
+
return CompileManifest(framework, code, options?.ssr || false);
|
|
12
|
+
}
|
|
13
|
+
};
|
|
14
|
+
}
|
package/vite/index.d.ts
ADDED
package/vite/index.js
ADDED
package/vite/router.d.ts
ADDED
package/vite/router.js
ADDED
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
export function Router() {
|
|
2
|
+
const virtualModuleId = "virtual:htmx-router/dynamic.tsx";
|
|
3
|
+
const resolvedVirtualModuleId = '\0' + virtualModuleId;
|
|
4
|
+
return {
|
|
5
|
+
name: "vite-plugin-htmx-router",
|
|
6
|
+
resolveId(id) {
|
|
7
|
+
if (id === virtualModuleId)
|
|
8
|
+
return resolvedVirtualModuleId;
|
|
9
|
+
},
|
|
10
|
+
load(id) {
|
|
11
|
+
if (id !== resolvedVirtualModuleId)
|
|
12
|
+
return;
|
|
13
|
+
return source;
|
|
14
|
+
}
|
|
15
|
+
};
|
|
16
|
+
}
|
|
17
|
+
const source = `export function Scripts() {
|
|
18
|
+
if (headCache) return headCache;
|
|
19
|
+
|
|
20
|
+
const res = <>
|
|
21
|
+
<link href={GetSheetUrl()} rel="stylesheet"></link>
|
|
22
|
+
{ isProduction ? "" : <script type="module" src="/@vite/client"></script> }
|
|
23
|
+
<script type="module" src={clientEntry}></script>
|
|
24
|
+
<script src={GetMountUrl()}></script>
|
|
25
|
+
</>;
|
|
26
|
+
|
|
27
|
+
if (isProduction) headCache = res;
|
|
28
|
+
return res;
|
|
29
|
+
}`;
|
|
@@ -1,67 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"name": "eventdim-react",
|
|
3
|
-
"private": "true",
|
|
4
|
-
"version": "1.0.0",
|
|
5
|
-
"main": "index.js",
|
|
6
|
-
"type": "module",
|
|
7
|
-
"scripts": {
|
|
8
|
-
"prepare": "npx htmx-router && prisma generate && prisma migrate deploy",
|
|
9
|
-
"docker": "docker compose up -d",
|
|
10
|
-
"dev": "node ./server.js",
|
|
11
|
-
"build": "run-s build:*",
|
|
12
|
-
"build:router": "npx htmx-router",
|
|
13
|
-
"build:prisma": "npx prisma generate",
|
|
14
|
-
"build:client": "vite build",
|
|
15
|
-
"build:server": "vite build --ssr app/entry.server.ts --outDir dist/server",
|
|
16
|
-
"validate": "run-s validate:*",
|
|
17
|
-
"validate:typecheck": "tsc --noEmit",
|
|
18
|
-
"validate:lint": "eslint --ignore-path .gitignore --cache --cache-location ./node_modules/.cache/eslint .",
|
|
19
|
-
"preview": "cross-env NODE_ENV=production node ./server.js"
|
|
20
|
-
},
|
|
21
|
-
"keywords": [],
|
|
22
|
-
"author": "",
|
|
23
|
-
"license": "ISC",
|
|
24
|
-
"description": "",
|
|
25
|
-
"dependencies": {
|
|
26
|
-
"@fortawesome/free-brands-svg-icons": "^6.7.2",
|
|
27
|
-
"@fortawesome/free-solid-svg-icons": "^6.7.2",
|
|
28
|
-
"@fortawesome/react-fontawesome": "^0.2.2",
|
|
29
|
-
"@prisma/client": "^6.1.0",
|
|
30
|
-
"bcryptjs": "^2.4.3",
|
|
31
|
-
"cbor2": "^1.8.0",
|
|
32
|
-
"cross-env": "^7.0.3",
|
|
33
|
-
"dotenv": "^16.4.7",
|
|
34
|
-
"express": "^4.21.2",
|
|
35
|
-
"htmx-router": "^1.0.0-alpha.5",
|
|
36
|
-
"morgan": "^1.10.0",
|
|
37
|
-
"react": "^19.0.0",
|
|
38
|
-
"react-dom": "^19.0.0",
|
|
39
|
-
"tiny-invariant": "^1.3.3",
|
|
40
|
-
"zxcvbn": "^4.4.2"
|
|
41
|
-
},
|
|
42
|
-
"devDependencies": {
|
|
43
|
-
"@types/bcryptjs": "^2.4.6",
|
|
44
|
-
"@types/express": "^4.17.21",
|
|
45
|
-
"@types/nodemailer": "^6.4.15",
|
|
46
|
-
"@types/react": "^18.2.20",
|
|
47
|
-
"@types/react-dom": "^18.2.7",
|
|
48
|
-
"@types/zxcvbn": "^4.4.4",
|
|
49
|
-
"@typescript-eslint/eslint-plugin": "^6.7.4",
|
|
50
|
-
"@typescript-eslint/parser": "^6.7.4",
|
|
51
|
-
"eslint": "^8.38.0",
|
|
52
|
-
"eslint-import-resolver-typescript": "^3.6.1",
|
|
53
|
-
"eslint-plugin-import": "^2.28.1",
|
|
54
|
-
"eslint-plugin-jsx-a11y": "^6.7.1",
|
|
55
|
-
"eslint-plugin-react": "^7.33.2",
|
|
56
|
-
"eslint-plugin-react-hooks": "^4.6.0",
|
|
57
|
-
"npm-run-all": "^4.1.5",
|
|
58
|
-
"prisma": "^6.1.0",
|
|
59
|
-
"typed-htmx": "^0.3.1",
|
|
60
|
-
"typescript": "^5.5.4",
|
|
61
|
-
"vite-tsconfig-paths": "^5.1.3",
|
|
62
|
-
"vite": "^6.0.1"
|
|
63
|
-
},
|
|
64
|
-
"engines": {
|
|
65
|
-
"node": ">=20.0.0"
|
|
66
|
-
}
|
|
67
|
-
}
|
|
@@ -1,90 +0,0 @@
|
|
|
1
|
-
/// <reference types="node" />
|
|
2
|
-
/* eslint-disable */
|
|
3
|
-
import 'dotenv/config'
|
|
4
|
-
import * as path from "path";
|
|
5
|
-
import { createRequestHandler } from 'htmx-router';
|
|
6
|
-
import { renderToString } from 'react-dom/server';
|
|
7
|
-
import express from 'express';
|
|
8
|
-
import morgan from "morgan";
|
|
9
|
-
|
|
10
|
-
const port = process.env.PORT || 3000;
|
|
11
|
-
const app = express();
|
|
12
|
-
|
|
13
|
-
const viteDevServer =
|
|
14
|
-
process.env.NODE_ENV === "production"
|
|
15
|
-
? null
|
|
16
|
-
: await import("vite").then((vite) =>
|
|
17
|
-
vite.createServer({
|
|
18
|
-
server: { middlewareMode: true },
|
|
19
|
-
appType: 'custom'
|
|
20
|
-
})
|
|
21
|
-
);
|
|
22
|
-
|
|
23
|
-
app.use(
|
|
24
|
-
viteDevServer
|
|
25
|
-
? viteDevServer.middlewares
|
|
26
|
-
: express.static("./dist/client")
|
|
27
|
-
);
|
|
28
|
-
|
|
29
|
-
// logging
|
|
30
|
-
app.use(morgan("tiny"));
|
|
31
|
-
|
|
32
|
-
const build = viteDevServer
|
|
33
|
-
? () => viteDevServer.ssrLoadModule('./app/entry.server.ts')
|
|
34
|
-
: await import('./dist/server/entry.server.js');
|
|
35
|
-
|
|
36
|
-
app.use('*', createRequestHandler.http({
|
|
37
|
-
build, viteDevServer,
|
|
38
|
-
render: (res) => {
|
|
39
|
-
const headers = new Headers();
|
|
40
|
-
headers.set("Content-Type", "text/html; charset=UTF-8");
|
|
41
|
-
headers.set("Cache-Control", "no-cache");
|
|
42
|
-
|
|
43
|
-
const stream = renderToString(res);
|
|
44
|
-
return new Response(stream, { headers });
|
|
45
|
-
}
|
|
46
|
-
}));
|
|
47
|
-
|
|
48
|
-
// Start http server
|
|
49
|
-
app.listen(port, () => {
|
|
50
|
-
console.log(`Server started at http://localhost:${port}`)
|
|
51
|
-
})
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
// Reload pages on file change
|
|
55
|
-
if (viteDevServer) {
|
|
56
|
-
const focus = path.resolve("./app");
|
|
57
|
-
viteDevServer.watcher.on('change', (file) => {
|
|
58
|
-
if (!file.startsWith(focus)) return;
|
|
59
|
-
console.log(`File changed: ${path.relative("./app", file)}`);
|
|
60
|
-
|
|
61
|
-
console.log('Triggering full page reload');
|
|
62
|
-
viteDevServer.ws.send({ type: 'full-reload' });
|
|
63
|
-
});
|
|
64
|
-
}
|
|
65
|
-
|
|
66
|
-
const shutdown = () => {
|
|
67
|
-
console.log("Shutting down server...");
|
|
68
|
-
|
|
69
|
-
// Close the server gracefully
|
|
70
|
-
server.close((err) => {
|
|
71
|
-
if (err) {
|
|
72
|
-
console.error("Error during server shutdown:", err);
|
|
73
|
-
process.exit(1);
|
|
74
|
-
}
|
|
75
|
-
console.log("Server shut down gracefully.");
|
|
76
|
-
process.exit(0);
|
|
77
|
-
});
|
|
78
|
-
};
|
|
79
|
-
|
|
80
|
-
process.on('SIGTERM', shutdown);
|
|
81
|
-
process.on('SIGHUP', shutdown);
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
process .on('unhandledRejection', (reason, p) => {
|
|
85
|
-
console.error(reason, 'Unhandled Rejection at Promise', p);
|
|
86
|
-
})
|
|
87
|
-
.on('uncaughtException', err => {
|
|
88
|
-
console.error(err, 'Uncaught Exception thrown');
|
|
89
|
-
process.exit(1);
|
|
90
|
-
});
|
|
@@ -1,38 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"type": "module",
|
|
3
|
-
"scripts": {
|
|
4
|
-
"prepare": "npx htmx-router",
|
|
5
|
-
"dev": "node ./server.js",
|
|
6
|
-
"build": "run-s build:*",
|
|
7
|
-
"build:router": "npx htmx-router",
|
|
8
|
-
"build:client": "vite build",
|
|
9
|
-
"build:server": "vite build --ssr app/entry.server.ts --outDir dist/server",
|
|
10
|
-
"preview": "cross-env NODE_ENV=production node ./server.js",
|
|
11
|
-
"validate": "npx tsc -noEmit"
|
|
12
|
-
},
|
|
13
|
-
"license": "MIT",
|
|
14
|
-
"dependencies": {
|
|
15
|
-
"cross-env": "^7.0.3",
|
|
16
|
-
"dotenv": "^16.3.1",
|
|
17
|
-
"express": "^4.21.1",
|
|
18
|
-
"morgan": "^1.10.0",
|
|
19
|
-
"npm-run-all": "^4.1.5",
|
|
20
|
-
"htmx-router": "^1.0.0-alpha.1",
|
|
21
|
-
"react": "^19.0.0",
|
|
22
|
-
"react-dom": "^19.0.0",
|
|
23
|
-
"serve-static": "^1.16.2",
|
|
24
|
-
"tsconfig-paths": "^4.2.0"
|
|
25
|
-
},
|
|
26
|
-
"devDependencies": {
|
|
27
|
-
"@types/express": "^5.0.0",
|
|
28
|
-
"@types/node": "^20.4.5",
|
|
29
|
-
"@types/react-dom": "^19.0.2",
|
|
30
|
-
"@types/react": "^19.0.1",
|
|
31
|
-
"@types/serve-static": "^1.15.7",
|
|
32
|
-
"ts-node": "^10.9.1",
|
|
33
|
-
"typed-htmx": "^0.3.1",
|
|
34
|
-
"typescript": "^5.1.6",
|
|
35
|
-
"vite-tsconfig-paths": "^5.1.3",
|
|
36
|
-
"vite": "^6.0.1"
|
|
37
|
-
}
|
|
38
|
-
}
|
|
@@ -1,58 +0,0 @@
|
|
|
1
|
-
import { createRequestHandler } from 'htmx-router';
|
|
2
|
-
import { renderToString } from 'react-dom/server';
|
|
3
|
-
import express from 'express';
|
|
4
|
-
import morgan from "morgan";
|
|
5
|
-
|
|
6
|
-
const port = process.env.PORT || 5173;
|
|
7
|
-
const app = express();
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
const viteDevServer =
|
|
11
|
-
process.env.NODE_ENV === "production"
|
|
12
|
-
? null
|
|
13
|
-
: await import("vite").then((vite) =>
|
|
14
|
-
vite.createServer({
|
|
15
|
-
server: { middlewareMode: true },
|
|
16
|
-
appType: 'custom'
|
|
17
|
-
})
|
|
18
|
-
);
|
|
19
|
-
|
|
20
|
-
app.use(
|
|
21
|
-
viteDevServer
|
|
22
|
-
? viteDevServer.middlewares
|
|
23
|
-
: express.static("./dist/client")
|
|
24
|
-
);
|
|
25
|
-
|
|
26
|
-
// logging
|
|
27
|
-
app.use(morgan("tiny"));
|
|
28
|
-
|
|
29
|
-
const build = viteDevServer
|
|
30
|
-
? () => viteDevServer.ssrLoadModule('./app/entry.server.ts')
|
|
31
|
-
: await import('./dist/server/entry.server.js');
|
|
32
|
-
|
|
33
|
-
app.use('*', createRequestHandler.http({
|
|
34
|
-
build, viteDevServer,
|
|
35
|
-
render: (res) => {
|
|
36
|
-
const headers = new Headers();
|
|
37
|
-
headers.set("Content-Type", "text/html; charset=UTF-8");
|
|
38
|
-
|
|
39
|
-
const stream = renderToString(res);
|
|
40
|
-
return new Response(stream, { headers });
|
|
41
|
-
}
|
|
42
|
-
}));
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
// Start http server
|
|
46
|
-
app.listen(port, () => {
|
|
47
|
-
console.log(`Server started at http://localhost:${port}`)
|
|
48
|
-
})
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
// Reload pages on file change
|
|
52
|
-
if (viteDevServer)
|
|
53
|
-
viteDevServer.watcher.on('change', (file) => {
|
|
54
|
-
console.log(`File changed: ${file}`);
|
|
55
|
-
|
|
56
|
-
console.log('Triggering full page reload');
|
|
57
|
-
viteDevServer.ws.send({ type: 'full-reload' });
|
|
58
|
-
});
|