@olenbetong/appframe-vite 4.0.0-rc.0 → 4.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/lib/devServer.d.ts +2 -2
- package/lib/devServer.js +8 -2
- package/lib/index.js +27 -2
- package/lib/proxy.d.ts +0 -15
- package/lib/proxy.js +12 -34
- package/package.json +3 -2
package/lib/devServer.d.ts
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import { Connect, ViteDevServer } from "vite";
|
|
2
|
-
export declare function getLoginInfo(): {
|
|
2
|
+
export declare function getLoginInfo(): Promise<{
|
|
3
3
|
hostname: any;
|
|
4
4
|
username: string;
|
|
5
5
|
password: string;
|
|
6
|
-
}
|
|
6
|
+
}>;
|
|
7
7
|
export declare function getProxyRoutes(): string[];
|
|
8
8
|
export declare function createDevMiddleware(vite: ViteDevServer): Connect.NextHandleFunction;
|
package/lib/devServer.js
CHANGED
|
@@ -7,7 +7,8 @@ import { importJson } from "./importJson.js";
|
|
|
7
7
|
dotenv.config();
|
|
8
8
|
let appPkg = await importJson("./package.json", true);
|
|
9
9
|
let { appframe } = appPkg;
|
|
10
|
-
export function getLoginInfo() {
|
|
10
|
+
export async function getLoginInfo() {
|
|
11
|
+
let { appframe } = await importJson("./package.json", true);
|
|
11
12
|
const hostname = appframe.proxy?.hostname ?? appframe.deploy?.hostname ?? "dev.obet.no";
|
|
12
13
|
const { APPFRAME_LOGIN: username, APPFRAME_PWD: password } = process.env;
|
|
13
14
|
if (!username || !password) {
|
|
@@ -40,7 +41,7 @@ export function getProxyRoutes() {
|
|
|
40
41
|
return proxyRoutes;
|
|
41
42
|
}
|
|
42
43
|
async function getArticleHtml() {
|
|
43
|
-
let { hostname, username, password } = getLoginInfo();
|
|
44
|
+
let { hostname, username, password } = await getLoginInfo();
|
|
44
45
|
let article = appframe.article?.id;
|
|
45
46
|
let client = new Client(hostname);
|
|
46
47
|
await client.login(username, password);
|
|
@@ -87,6 +88,11 @@ async function getArticleHtml() {
|
|
|
87
88
|
}
|
|
88
89
|
});
|
|
89
90
|
nodesToRemove.forEach((node) => node.remove());
|
|
91
|
+
dom.window.document.querySelectorAll("a").forEach((anchor) => {
|
|
92
|
+
if (anchor.href?.startsWith("/") && !anchor.href?.startsWith(`/${article}`)) {
|
|
93
|
+
anchor.href = `https://${hostname}${anchor.href}`;
|
|
94
|
+
}
|
|
95
|
+
});
|
|
90
96
|
return dom.serialize();
|
|
91
97
|
}
|
|
92
98
|
throw Error(`Failed to get article '${article}' from '${hostname}': ${response.status} ${response.statusText}`);
|
package/lib/index.js
CHANGED
|
@@ -1,6 +1,27 @@
|
|
|
1
|
+
import { watch } from "chokidar";
|
|
1
2
|
import { addAppframeBuildConfig } from "./build.js";
|
|
2
3
|
import { createDevMiddleware, getLoginInfo, getProxyRoutes } from "./devServer.js";
|
|
4
|
+
import { importJson } from "./importJson.js";
|
|
3
5
|
import { getLastSession, login } from "./proxy.js";
|
|
6
|
+
let interval;
|
|
7
|
+
let server;
|
|
8
|
+
let lastHostname;
|
|
9
|
+
try {
|
|
10
|
+
let appPkgUrl = `file://${process.cwd()}/package.json`;
|
|
11
|
+
watch(appPkgUrl).on("all", async () => {
|
|
12
|
+
if (server) {
|
|
13
|
+
let appPkg = await importJson("./package.json", true);
|
|
14
|
+
let config = appPkg.appframe;
|
|
15
|
+
let { hostname } = await getLoginInfo();
|
|
16
|
+
if (lastHostname !== hostname) {
|
|
17
|
+
server.restart(false);
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
});
|
|
21
|
+
}
|
|
22
|
+
catch (error) {
|
|
23
|
+
console.log(`Failed to watch package.json: ${error.message}`);
|
|
24
|
+
}
|
|
4
25
|
export default function appframe() {
|
|
5
26
|
return {
|
|
6
27
|
name: "appframe",
|
|
@@ -38,13 +59,16 @@ export default function appframe() {
|
|
|
38
59
|
}
|
|
39
60
|
let proxy = config.server?.proxy ?? {};
|
|
40
61
|
let routes = getProxyRoutes();
|
|
41
|
-
let { hostname, username, password } = getLoginInfo();
|
|
62
|
+
let { hostname, username, password } = await getLoginInfo();
|
|
63
|
+
lastHostname = hostname;
|
|
42
64
|
await login(hostname, username, password);
|
|
65
|
+
if (interval)
|
|
66
|
+
clearInterval(interval);
|
|
43
67
|
// After changing the plugin to use the Vite proxy instead of a custom
|
|
44
68
|
// express server with node-http-proxy, we can no longer ensure the requests
|
|
45
69
|
// have a valid login. To reduce the amount of problems we get with expired
|
|
46
70
|
// sessions, we run the login procedure every 5 minutes to renew the session.
|
|
47
|
-
setInterval(async () => {
|
|
71
|
+
interval = setInterval(async () => {
|
|
48
72
|
await login(hostname, username, password);
|
|
49
73
|
}, 1000 * 60 * 5);
|
|
50
74
|
for (let route of routes) {
|
|
@@ -74,6 +98,7 @@ export default function appframe() {
|
|
|
74
98
|
return config;
|
|
75
99
|
},
|
|
76
100
|
async configureServer(_server) {
|
|
101
|
+
server = _server;
|
|
77
102
|
return () => {
|
|
78
103
|
_server.middlewares.use(createDevMiddleware(_server));
|
|
79
104
|
};
|
package/lib/proxy.d.ts
CHANGED
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
import e from "express";
|
|
2
1
|
type CookieObject = Record<string, string>;
|
|
3
2
|
type LoginCacheEntry = {
|
|
4
3
|
timestamp: number;
|
|
@@ -6,18 +5,4 @@ type LoginCacheEntry = {
|
|
|
6
5
|
};
|
|
7
6
|
export declare function getLastSession(hostname: any): LoginCacheEntry | undefined;
|
|
8
7
|
export declare function login(hostname: string, username: string, password: string): Promise<CookieObject>;
|
|
9
|
-
export type createProxyOptions = {
|
|
10
|
-
/**
|
|
11
|
-
* If true, will wait for the first login request to complete before returning.
|
|
12
|
-
*/
|
|
13
|
-
autoLogin?: boolean;
|
|
14
|
-
hostname: string;
|
|
15
|
-
username: string;
|
|
16
|
-
password: string;
|
|
17
|
-
protocol?: "http" | "https";
|
|
18
|
-
};
|
|
19
|
-
export type AppframeProxy = e.RequestHandler & {
|
|
20
|
-
setHostname: (hostname: string) => Promise<void>;
|
|
21
|
-
};
|
|
22
|
-
export declare function createAppframeProxy(options: createProxyOptions): AppframeProxy;
|
|
23
8
|
export {};
|
package/lib/proxy.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import
|
|
1
|
+
import chalk from "chalk";
|
|
2
2
|
import https from "node:https";
|
|
3
3
|
const lastLogin = new Map();
|
|
4
4
|
let currentLogin = null;
|
|
@@ -17,7 +17,7 @@ export async function login(hostname, username, password) {
|
|
|
17
17
|
return;
|
|
18
18
|
}
|
|
19
19
|
else {
|
|
20
|
-
|
|
20
|
+
process.stdout.write(`${chalk.bgBlueBright(hostname)}: Renewing authentication cookies...`);
|
|
21
21
|
lastLogin.delete(hostname);
|
|
22
22
|
}
|
|
23
23
|
}
|
|
@@ -33,8 +33,14 @@ export async function login(hostname, username, password) {
|
|
|
33
33
|
"Content-Length": data.length,
|
|
34
34
|
},
|
|
35
35
|
};
|
|
36
|
-
|
|
36
|
+
process.stdout.clearLine(0);
|
|
37
|
+
process.stdout.write(`\r${chalk.bgBlueBright(hostname)}: Authenticating`);
|
|
38
|
+
let start = performance.now();
|
|
39
|
+
let interval = setInterval(() => {
|
|
40
|
+
process.stdout.write(`.`);
|
|
41
|
+
}, 100);
|
|
37
42
|
let request = https.request(options, (response) => {
|
|
43
|
+
clearInterval(interval);
|
|
38
44
|
let status = response.statusCode ?? 600;
|
|
39
45
|
if (status < 400) {
|
|
40
46
|
let cookies = response.headers["set-cookie"] ?? [];
|
|
@@ -46,7 +52,8 @@ export async function login(hostname, username, password) {
|
|
|
46
52
|
cookieObj[key] = value;
|
|
47
53
|
}
|
|
48
54
|
}
|
|
49
|
-
|
|
55
|
+
process.stdout.clearLine(0);
|
|
56
|
+
process.stdout.write(`\r${chalk.bgBlueBright(hostname)}: Authenticated (${Math.floor(performance.now() - start)}ms)\n`);
|
|
50
57
|
lastLogin.set(hostname, {
|
|
51
58
|
timestamp: Date.now(),
|
|
52
59
|
authCookies: cookieObj,
|
|
@@ -54,7 +61,7 @@ export async function login(hostname, username, password) {
|
|
|
54
61
|
resolve(cookieObj);
|
|
55
62
|
}
|
|
56
63
|
else {
|
|
57
|
-
reject(Error(
|
|
64
|
+
reject(Error(`${chalk.bgBlueBright(hostname)}: Authentication failed: ${response.statusCode} ${response.statusMessage}`));
|
|
58
65
|
}
|
|
59
66
|
});
|
|
60
67
|
request.write(data);
|
|
@@ -74,32 +81,3 @@ export async function login(hostname, username, password) {
|
|
|
74
81
|
throw error;
|
|
75
82
|
}
|
|
76
83
|
}
|
|
77
|
-
export function createAppframeProxy(options) {
|
|
78
|
-
let { hostname, password, protocol = "https", username } = options;
|
|
79
|
-
// @ts-ignore
|
|
80
|
-
const proxy = expressProxy(() => `${protocol}://${hostname}`, {
|
|
81
|
-
memoizeHost: false,
|
|
82
|
-
proxyReqOptDecorator: async function (proxyReqOpts) {
|
|
83
|
-
if (!proxyReqOpts.path?.startsWith("/login")) {
|
|
84
|
-
let authCookies = await login(hostname, username, password);
|
|
85
|
-
let cookies = [];
|
|
86
|
-
cookies.push(`AppframeWebAuth=${authCookies["AppframeWebAuth"]}`);
|
|
87
|
-
cookies.push(`AppframeWebSession=${authCookies["AppframeWebSession"]}`);
|
|
88
|
-
proxyReqOpts.headers = proxyReqOpts.headers ?? {};
|
|
89
|
-
proxyReqOpts.headers["cookie"] = cookies.join(";");
|
|
90
|
-
}
|
|
91
|
-
return proxyReqOpts;
|
|
92
|
-
},
|
|
93
|
-
proxyReqPathResolver: function (req) {
|
|
94
|
-
return req.originalUrl;
|
|
95
|
-
},
|
|
96
|
-
});
|
|
97
|
-
proxy.setHostname = async (newHostname) => {
|
|
98
|
-
if (hostname !== newHostname) {
|
|
99
|
-
hostname = newHostname;
|
|
100
|
-
console.log(`Changing proxy host to '${newHostname}'...`);
|
|
101
|
-
await login(hostname, username, password);
|
|
102
|
-
}
|
|
103
|
-
};
|
|
104
|
-
return proxy;
|
|
105
|
-
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@olenbetong/appframe-vite",
|
|
3
|
-
"version": "4.0.0
|
|
3
|
+
"version": "4.0.0",
|
|
4
4
|
"description": "Tools to use and deploy Vite applications to Appframe",
|
|
5
5
|
"main": "./lib/index.js",
|
|
6
6
|
"type": "module",
|
|
@@ -20,6 +20,7 @@
|
|
|
20
20
|
"license": "MIT",
|
|
21
21
|
"dependencies": {
|
|
22
22
|
"@olenbetong/appframe-data": "^0.8.10",
|
|
23
|
+
"chalk": "^5.3.0",
|
|
23
24
|
"chokidar": "^3.5.3",
|
|
24
25
|
"dotenv": "^16.3.1",
|
|
25
26
|
"jsdom": "^22.1.0",
|
|
@@ -42,5 +43,5 @@
|
|
|
42
43
|
"open": "^9.1.0",
|
|
43
44
|
"tcp-port-used": "^1.0.2"
|
|
44
45
|
},
|
|
45
|
-
"gitHead": "
|
|
46
|
+
"gitHead": "d4c8d2d9010a49c9052947bbf7593c6bd13af9b4"
|
|
46
47
|
}
|