@olenbetong/appframe-vite 3.1.17 → 4.0.0-rc.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/build.js +10 -0
- package/lib/devServer.d.ts +8 -6
- package/lib/devServer.js +85 -176
- package/lib/index.d.ts +2 -3
- package/lib/index.js +48 -7
- package/lib/proxy.d.ts +5 -0
- package/lib/proxy.js +3 -0
- package/package.json +4 -2
package/lib/build.js
CHANGED
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
import { exists } from "fs-extra";
|
|
2
|
+
import { resolve } from "node:path";
|
|
1
3
|
import { visualizer } from "rollup-plugin-visualizer";
|
|
2
4
|
import { viteExternalsPlugin } from "vite-plugin-externals";
|
|
3
5
|
import { importJson } from "./importJson.js";
|
|
@@ -17,7 +19,15 @@ export async function addAppframeBuildConfig(config) {
|
|
|
17
19
|
"react-dom": "ReactDOM",
|
|
18
20
|
}));
|
|
19
21
|
}
|
|
22
|
+
let entry = resolve(process.cwd(), "./src/index.tsx");
|
|
23
|
+
if (!(await exists(resolve(entry)))) {
|
|
24
|
+
entry = resolve(process.cwd(), "./src/index.ts");
|
|
25
|
+
}
|
|
26
|
+
if (!(await exists(resolve(entry)))) {
|
|
27
|
+
entry = resolve(process.cwd(), "./src/index.js");
|
|
28
|
+
}
|
|
20
29
|
config.build.rollupOptions = {
|
|
30
|
+
input: entry,
|
|
21
31
|
plugins: [visualizer({ filename: "./dist/stats.html", gzipSize: true })],
|
|
22
32
|
output: {
|
|
23
33
|
globals: appframe.build.externals !== false
|
package/lib/devServer.d.ts
CHANGED
|
@@ -1,6 +1,8 @@
|
|
|
1
|
-
import {
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
1
|
+
import { Connect, ViteDevServer } from "vite";
|
|
2
|
+
export declare function getLoginInfo(): {
|
|
3
|
+
hostname: any;
|
|
4
|
+
username: string;
|
|
5
|
+
password: string;
|
|
6
|
+
};
|
|
7
|
+
export declare function getProxyRoutes(): string[];
|
|
8
|
+
export declare function createDevMiddleware(vite: ViteDevServer): Connect.NextHandleFunction;
|
package/lib/devServer.js
CHANGED
|
@@ -1,31 +1,13 @@
|
|
|
1
1
|
import { Client } from "@olenbetong/appframe-data";
|
|
2
|
-
import { watch } from "chokidar";
|
|
3
2
|
import dotenv from "dotenv";
|
|
4
|
-
import
|
|
5
|
-
import
|
|
6
|
-
import
|
|
7
|
-
import open from "open";
|
|
8
|
-
import tcpPortUsed from "tcp-port-used";
|
|
3
|
+
import { exists } from "fs-extra";
|
|
4
|
+
import { JSDOM } from "jsdom";
|
|
5
|
+
import { resolve } from "node:path";
|
|
9
6
|
import { importJson } from "./importJson.js";
|
|
10
|
-
import { createAppframeProxy } from "./proxy.js";
|
|
11
7
|
dotenv.config();
|
|
12
8
|
let appPkg = await importJson("./package.json", true);
|
|
13
9
|
let { appframe } = appPkg;
|
|
14
|
-
|
|
15
|
-
async function getUserSession() {
|
|
16
|
-
if (userSession) {
|
|
17
|
-
return userSession;
|
|
18
|
-
}
|
|
19
|
-
let { hostname, username, password } = await getLoginInfo();
|
|
20
|
-
let client = new Client(hostname);
|
|
21
|
-
await client.login(username, password);
|
|
22
|
-
let userResult = await client.afFetch("/api/system/usersession", {
|
|
23
|
-
timeout: 5000,
|
|
24
|
-
});
|
|
25
|
-
userSession = await userResult.json();
|
|
26
|
-
return userSession;
|
|
27
|
-
}
|
|
28
|
-
function getLoginInfo() {
|
|
10
|
+
export function getLoginInfo() {
|
|
29
11
|
const hostname = appframe.proxy?.hostname ?? appframe.deploy?.hostname ?? "dev.obet.no";
|
|
30
12
|
const { APPFRAME_LOGIN: username, APPFRAME_PWD: password } = process.env;
|
|
31
13
|
if (!username || !password) {
|
|
@@ -33,173 +15,100 @@ function getLoginInfo() {
|
|
|
33
15
|
}
|
|
34
16
|
return { hostname, username, password };
|
|
35
17
|
}
|
|
36
|
-
export function
|
|
37
|
-
let { hostname, username, password } = getLoginInfo();
|
|
38
|
-
const proxy = createAppframeProxy({ hostname, username, password });
|
|
39
|
-
try {
|
|
40
|
-
let appPkgUrl = `file://${process.cwd()}/package.json`;
|
|
41
|
-
watch(appPkgUrl).on("all", async () => {
|
|
42
|
-
appPkg = await importJson("./package.json", true);
|
|
43
|
-
appframe = appPkg.appframe;
|
|
44
|
-
let { hostname } = getLoginInfo();
|
|
45
|
-
proxy.setHostname(hostname);
|
|
46
|
-
});
|
|
47
|
-
}
|
|
48
|
-
catch (error) {
|
|
49
|
-
console.log(`Failed to watch package.json: ${error.message}`);
|
|
50
|
-
}
|
|
18
|
+
export function getProxyRoutes() {
|
|
51
19
|
const proxyRoutes = [
|
|
52
|
-
"
|
|
53
|
-
"
|
|
54
|
-
"
|
|
55
|
-
"
|
|
56
|
-
"
|
|
57
|
-
"/
|
|
58
|
-
"
|
|
59
|
-
"
|
|
60
|
-
"
|
|
61
|
-
"
|
|
62
|
-
"
|
|
63
|
-
"
|
|
64
|
-
"
|
|
20
|
+
"^/api/.*",
|
|
21
|
+
"^/file/.*",
|
|
22
|
+
"^/filestore/.*",
|
|
23
|
+
"^/static/dbimages/.*",
|
|
24
|
+
"^/static/images/.*",
|
|
25
|
+
"^/static/graphics/.*",
|
|
26
|
+
"^/destroy/.*",
|
|
27
|
+
"^/create/.*",
|
|
28
|
+
"^/update/.*",
|
|
29
|
+
"^/retrieve/.*",
|
|
30
|
+
"^/exec/.*",
|
|
31
|
+
"^/report/.*",
|
|
32
|
+
"^/rowcount/.*",
|
|
33
|
+
"^/lib/.*",
|
|
34
|
+
"^/login",
|
|
35
|
+
"^/logout",
|
|
65
36
|
];
|
|
66
37
|
if (appframe.proxy?.routes) {
|
|
67
38
|
proxyRoutes.push(...appframe.proxy.routes);
|
|
68
39
|
}
|
|
69
|
-
|
|
70
|
-
proxyRoutes.forEach((route) => {
|
|
71
|
-
router.use(route, proxy);
|
|
72
|
-
});
|
|
73
|
-
return router;
|
|
40
|
+
return proxyRoutes;
|
|
74
41
|
}
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
<template id="PromptBeforeReloadDialog">
|
|
83
|
-
<dialog class="do-prompt">
|
|
84
|
-
<form method="dialog">
|
|
85
|
-
<article>
|
|
86
|
-
<p>There are unsaved changes. Would you like to save before reloading data?
|
|
87
|
-
</article>
|
|
88
|
-
<footer>
|
|
89
|
-
<menu>
|
|
90
|
-
<li><button value="cancel">Cancel reloading</button></li>
|
|
91
|
-
<li><button value="reload">Reload without saving</button></li>
|
|
92
|
-
<li><button class="primary" value="save-and-reload">Save and reload</button></li>
|
|
93
|
-
</menu>
|
|
94
|
-
</footer>
|
|
95
|
-
</form>
|
|
96
|
-
</dialog>
|
|
97
|
-
</template>
|
|
98
|
-
|
|
99
|
-
<script type="text/javascript">
|
|
100
|
-
function waitForDialog(dialog) {
|
|
101
|
-
return new Promise((resolve) => {
|
|
102
|
-
dialog.addEventListener("close", resolve, { once: true });
|
|
42
|
+
async function getArticleHtml() {
|
|
43
|
+
let { hostname, username, password } = getLoginInfo();
|
|
44
|
+
let article = appframe.article?.id;
|
|
45
|
+
let client = new Client(hostname);
|
|
46
|
+
await client.login(username, password);
|
|
47
|
+
let response = await client.afFetch(`/${article}`, {
|
|
48
|
+
timeout: 30000,
|
|
103
49
|
});
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
headingLevelLabel: l('Heading level'),
|
|
146
|
-
mainLabel: l('main'),
|
|
147
|
-
searchLabel: l('search'),
|
|
148
|
-
navLabel: l('navigation'),
|
|
149
|
-
asideLabel: l('aside'),
|
|
150
|
-
footerLabel: l('footer'),
|
|
151
|
-
headerLabel: l('header'),
|
|
152
|
-
formLabel: l('form'),
|
|
153
|
-
msgNoLandmarksFound: l('No landmarks to skip to'),
|
|
154
|
-
msgNoHeadingsFound: l('No main headings to skip to')
|
|
50
|
+
if (response.ok) {
|
|
51
|
+
let html = await response.text();
|
|
52
|
+
let entry;
|
|
53
|
+
if (await exists(resolve(process.cwd(), "./src/index.tsx"))) {
|
|
54
|
+
entry = "/src/index.tsx";
|
|
55
|
+
}
|
|
56
|
+
else if (await exists(resolve(process.cwd(), "./src/index.ts"))) {
|
|
57
|
+
entry = "/src/index.ts";
|
|
58
|
+
}
|
|
59
|
+
else if (await exists(resolve(process.cwd(), "./src/index.js"))) {
|
|
60
|
+
entry = "/src/index.js";
|
|
61
|
+
}
|
|
62
|
+
let dom = new JSDOM(html);
|
|
63
|
+
let nodesToRemove = [];
|
|
64
|
+
dom.window.document.querySelectorAll("script").forEach((script) => {
|
|
65
|
+
if (script.src?.startsWith(`/file/article/script/${article}/main`)) {
|
|
66
|
+
let mainScript = dom.window.document.createElement("script");
|
|
67
|
+
mainScript.type = "module";
|
|
68
|
+
mainScript.src = entry;
|
|
69
|
+
script.insertAdjacentElement("beforebegin", mainScript);
|
|
70
|
+
nodesToRemove.push(script);
|
|
71
|
+
}
|
|
72
|
+
else if (script.src?.includes("bugsnag")) {
|
|
73
|
+
nodesToRemove.push(script);
|
|
74
|
+
}
|
|
75
|
+
else if (script.textContent?.includes("bugsnagOptions") ||
|
|
76
|
+
script.textContent?.includes("web-vitals") ||
|
|
77
|
+
script.textContent?.includes("serviceWorker.register")) {
|
|
78
|
+
nodesToRemove.push(script);
|
|
79
|
+
}
|
|
80
|
+
});
|
|
81
|
+
dom.window.document.querySelectorAll("link").forEach((link) => {
|
|
82
|
+
if (link.rel === "stylesheet" && link.href?.startsWith(`/file/article/style/${article}`)) {
|
|
83
|
+
nodesToRemove.push(link);
|
|
84
|
+
}
|
|
85
|
+
else if (link.rel === "prefetch" && link.href?.startsWith(`/file/article`)) {
|
|
86
|
+
nodesToRemove.push(link);
|
|
87
|
+
}
|
|
88
|
+
});
|
|
89
|
+
nodesToRemove.forEach((node) => node.remove());
|
|
90
|
+
return dom.serialize();
|
|
155
91
|
}
|
|
156
|
-
|
|
157
|
-
};
|
|
158
|
-
</script>
|
|
159
|
-
<script src="/lib/paypal-skipto/downloads/js/skipto.min.js" async></script>`)
|
|
160
|
-
.replace(`<!-- {Theme} -->`, isPartner
|
|
161
|
-
? `
|
|
162
|
-
<link rel="stylesheet" href="/file/site/style/ob.application.min.css" />
|
|
163
|
-
<link rel="stylesheet" href="/file/site/style/ob.theme.base.less" />
|
|
164
|
-
<link rel="stylesheet" href="/file/site/style/ob.theme.betongost.less" />
|
|
165
|
-
<link rel="stylesheet" href="/file/site/style/ob.theme.olenbetong.less" />
|
|
166
|
-
<link rel="stylesheet" href="/file/site/style/ob.theme.ribe.less" />
|
|
167
|
-
<link rel="stylesheet" href="/file/site/style/ob.theme.sjb.less" />
|
|
168
|
-
`
|
|
169
|
-
: `
|
|
170
|
-
<link rel="stylesheet" href="/file/site/style/ob.theme.base.less" />
|
|
171
|
-
<link rel="stylesheet" href="/file/site/style/ob.theme.betongost.less" />
|
|
172
|
-
<link rel="stylesheet" href="/file/site/style/ob.theme.forsand.less" />
|
|
173
|
-
<link rel="stylesheet" href="/file/site/style/ob.theme.olenbetong.less" />
|
|
174
|
-
<link rel="stylesheet" href="/file/site/style/ob.theme.ribe.less" />
|
|
175
|
-
<link rel="stylesheet" href="/file/site/style/ob.theme.sjb.less" />
|
|
176
|
-
<link rel="stylesheet" href="/file/site/style/ob.es.application.min.css" />`);
|
|
177
|
-
};
|
|
92
|
+
throw Error(`Failed to get article '${article}' from '${hostname}': ${response.status} ${response.statusText}`);
|
|
178
93
|
}
|
|
179
94
|
export function createDevMiddleware(vite) {
|
|
180
95
|
return async (req, res, next) => {
|
|
181
|
-
let transformer = createHtmlTransformer();
|
|
182
96
|
const url = req.originalUrl;
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
97
|
+
if (url === "/" || url?.startsWith("/" + appPkg.appframe.article.id)) {
|
|
98
|
+
try {
|
|
99
|
+
let html = await getArticleHtml();
|
|
100
|
+
html = await vite.transformIndexHtml(url ?? "", html);
|
|
101
|
+
res.statusCode = 200;
|
|
102
|
+
res.setHeader("Content-Type", "text/html");
|
|
103
|
+
res.end(html);
|
|
104
|
+
}
|
|
105
|
+
catch (error) {
|
|
106
|
+
vite.ssrFixStacktrace(error);
|
|
107
|
+
next(error);
|
|
108
|
+
}
|
|
188
109
|
}
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
next(error);
|
|
110
|
+
else {
|
|
111
|
+
next();
|
|
192
112
|
}
|
|
193
113
|
};
|
|
194
114
|
}
|
|
195
|
-
export async function startDevServer(app) {
|
|
196
|
-
let port = 3000;
|
|
197
|
-
let used = true;
|
|
198
|
-
do {
|
|
199
|
-
used = await tcpPortUsed.check(port);
|
|
200
|
-
if (used)
|
|
201
|
-
port++;
|
|
202
|
-
} while (used);
|
|
203
|
-
app.listen(port);
|
|
204
|
-
open(`http://localhost:${port}/${appframe.article.id}`);
|
|
205
|
-
}
|
package/lib/index.d.ts
CHANGED
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
import { Plugin } from "vite";
|
|
2
2
|
import { addAppframeBuildConfig } from "./build.js";
|
|
3
|
-
import { createDevMiddleware
|
|
3
|
+
import { createDevMiddleware } from "./devServer.js";
|
|
4
4
|
export default function appframe(): Plugin;
|
|
5
|
-
export { addAppframeBuildConfig };
|
|
6
|
-
export { createDevMiddleware, createProxyMiddleware, startDevServer };
|
|
5
|
+
export { addAppframeBuildConfig, createDevMiddleware };
|
package/lib/index.js
CHANGED
|
@@ -1,15 +1,24 @@
|
|
|
1
1
|
import { addAppframeBuildConfig } from "./build.js";
|
|
2
|
-
import { createDevMiddleware,
|
|
2
|
+
import { createDevMiddleware, getLoginInfo, getProxyRoutes } from "./devServer.js";
|
|
3
|
+
import { getLastSession, login } from "./proxy.js";
|
|
3
4
|
export default function appframe() {
|
|
4
|
-
let transformIndexHtml = createHtmlTransformer();
|
|
5
5
|
return {
|
|
6
6
|
name: "appframe",
|
|
7
|
+
resolveId(source) {
|
|
8
|
+
if (source.startsWith("/file/") || source.startsWith("/lib/")) {
|
|
9
|
+
return false;
|
|
10
|
+
}
|
|
11
|
+
return null;
|
|
12
|
+
},
|
|
7
13
|
async config(currentConfig, env) {
|
|
8
14
|
const { command } = env;
|
|
9
15
|
let config = {
|
|
16
|
+
...currentConfig,
|
|
10
17
|
build: {
|
|
18
|
+
...currentConfig.build,
|
|
11
19
|
target: currentConfig.build?.target ?? ["chrome90", "safari14"],
|
|
12
20
|
rollupOptions: {
|
|
21
|
+
...currentConfig.build?.rollupOptions,
|
|
13
22
|
output: {
|
|
14
23
|
assetFileNames: (assetInfo) => {
|
|
15
24
|
if (assetInfo.name === "style.css")
|
|
@@ -20,23 +29,55 @@ export default function appframe() {
|
|
|
20
29
|
},
|
|
21
30
|
},
|
|
22
31
|
resolve: {
|
|
32
|
+
...currentConfig.resolve,
|
|
23
33
|
alias: [{ find: "~/", replacement: "/src/" }],
|
|
24
34
|
},
|
|
25
35
|
};
|
|
26
36
|
if (command === "build") {
|
|
27
37
|
await addAppframeBuildConfig(config);
|
|
28
38
|
}
|
|
39
|
+
let proxy = config.server?.proxy ?? {};
|
|
40
|
+
let routes = getProxyRoutes();
|
|
41
|
+
let { hostname, username, password } = getLoginInfo();
|
|
42
|
+
await login(hostname, username, password);
|
|
43
|
+
// After changing the plugin to use the Vite proxy instead of a custom
|
|
44
|
+
// express server with node-http-proxy, we can no longer ensure the requests
|
|
45
|
+
// have a valid login. To reduce the amount of problems we get with expired
|
|
46
|
+
// sessions, we run the login procedure every 5 minutes to renew the session.
|
|
47
|
+
setInterval(async () => {
|
|
48
|
+
await login(hostname, username, password);
|
|
49
|
+
}, 1000 * 60 * 5);
|
|
50
|
+
for (let route of routes) {
|
|
51
|
+
proxy[route] = {
|
|
52
|
+
target: `https://${hostname}`,
|
|
53
|
+
changeOrigin: true,
|
|
54
|
+
configure(proxy, options) {
|
|
55
|
+
proxy.on("proxyReq", (proxyReq, req, res, options) => {
|
|
56
|
+
let authCookies = getLastSession(hostname)?.authCookies;
|
|
57
|
+
if (authCookies) {
|
|
58
|
+
let cookies = [];
|
|
59
|
+
cookies.push(`AppframeWebAuth=${authCookies["AppframeWebAuth"]}`);
|
|
60
|
+
cookies.push(`AppframeWebSession=${authCookies["AppframeWebSession"]}`);
|
|
61
|
+
proxyReq.setHeader("cookie", cookies.join(";"));
|
|
62
|
+
// If left unchanged, the origin will be the local IP address, which makes Appframe
|
|
63
|
+
// return 403 errors
|
|
64
|
+
proxyReq.setHeader("origin", `https://${hostname}`);
|
|
65
|
+
}
|
|
66
|
+
});
|
|
67
|
+
},
|
|
68
|
+
};
|
|
69
|
+
}
|
|
70
|
+
config.server = {
|
|
71
|
+
...config.server,
|
|
72
|
+
proxy,
|
|
73
|
+
};
|
|
29
74
|
return config;
|
|
30
75
|
},
|
|
31
76
|
async configureServer(_server) {
|
|
32
|
-
let proxyMiddleware = createProxyMiddleware();
|
|
33
|
-
_server.middlewares.use(proxyMiddleware);
|
|
34
77
|
return () => {
|
|
35
78
|
_server.middlewares.use(createDevMiddleware(_server));
|
|
36
79
|
};
|
|
37
80
|
},
|
|
38
|
-
transformIndexHtml,
|
|
39
81
|
};
|
|
40
82
|
}
|
|
41
|
-
export { addAppframeBuildConfig };
|
|
42
|
-
export { createDevMiddleware, createProxyMiddleware, startDevServer };
|
|
83
|
+
export { addAppframeBuildConfig, createDevMiddleware };
|
package/lib/proxy.d.ts
CHANGED
|
@@ -1,5 +1,10 @@
|
|
|
1
1
|
import e from "express";
|
|
2
2
|
type CookieObject = Record<string, string>;
|
|
3
|
+
type LoginCacheEntry = {
|
|
4
|
+
timestamp: number;
|
|
5
|
+
authCookies: CookieObject;
|
|
6
|
+
};
|
|
7
|
+
export declare function getLastSession(hostname: any): LoginCacheEntry | undefined;
|
|
3
8
|
export declare function login(hostname: string, username: string, password: string): Promise<CookieObject>;
|
|
4
9
|
export type createProxyOptions = {
|
|
5
10
|
/**
|
package/lib/proxy.js
CHANGED
|
@@ -2,6 +2,9 @@ import expressProxy from "express-http-proxy";
|
|
|
2
2
|
import https from "node:https";
|
|
3
3
|
const lastLogin = new Map();
|
|
4
4
|
let currentLogin = null;
|
|
5
|
+
export function getLastSession(hostname) {
|
|
6
|
+
return lastLogin.get(hostname);
|
|
7
|
+
}
|
|
5
8
|
export async function login(hostname, username, password) {
|
|
6
9
|
if (currentLogin) {
|
|
7
10
|
await currentLogin;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@olenbetong/appframe-vite",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "4.0.0-rc.0",
|
|
4
4
|
"description": "Tools to use and deploy Vite applications to Appframe",
|
|
5
5
|
"main": "./lib/index.js",
|
|
6
6
|
"type": "module",
|
|
@@ -22,10 +22,12 @@
|
|
|
22
22
|
"@olenbetong/appframe-data": "^0.8.10",
|
|
23
23
|
"chokidar": "^3.5.3",
|
|
24
24
|
"dotenv": "^16.3.1",
|
|
25
|
+
"jsdom": "^22.1.0",
|
|
25
26
|
"rollup-plugin-visualizer": "^5.9.2",
|
|
26
27
|
"vite-plugin-externals": "^0.6.2"
|
|
27
28
|
},
|
|
28
29
|
"devDependencies": {
|
|
30
|
+
"@types/jsdom": "^21.1.2",
|
|
29
31
|
"typescript": "^5.1.6"
|
|
30
32
|
},
|
|
31
33
|
"peerDependencies": {
|
|
@@ -40,5 +42,5 @@
|
|
|
40
42
|
"open": "^9.1.0",
|
|
41
43
|
"tcp-port-used": "^1.0.2"
|
|
42
44
|
},
|
|
43
|
-
"gitHead": "
|
|
45
|
+
"gitHead": "0875957c231dcd1c5b3e765f45d5a3017c1e30b3"
|
|
44
46
|
}
|