@typed-assistant/builder 0.0.33 → 0.0.34
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/package.json +3 -3
- package/src/appProcess.tsx +33 -30
- package/src/setupWebserver.tsx +21 -1
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@typed-assistant/builder",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.34",
|
|
4
4
|
"exports": {
|
|
5
5
|
"./appProcess": "./src/appProcess.tsx",
|
|
6
6
|
"./bunInstall": "./src/bunInstall.tsx",
|
|
@@ -24,10 +24,10 @@
|
|
|
24
24
|
"home-assistant-js-websocket": "^8.2.0",
|
|
25
25
|
"ts-toolbelt": "^9.6.0",
|
|
26
26
|
"typescript": "^5.3.3",
|
|
27
|
+
"@typed-assistant/typescript-config": "0.0.7",
|
|
27
28
|
"@typed-assistant/eslint-config": "0.0.7",
|
|
28
29
|
"@typed-assistant/logger": "0.0.11",
|
|
29
|
-
"@typed-assistant/
|
|
30
|
-
"@typed-assistant/utils": "0.0.10"
|
|
30
|
+
"@typed-assistant/utils": "0.0.11"
|
|
31
31
|
},
|
|
32
32
|
"peerDependencies": {
|
|
33
33
|
"home-assistant-js-websocket": "^8.2.0"
|
package/src/appProcess.tsx
CHANGED
|
@@ -1,7 +1,5 @@
|
|
|
1
1
|
import { log } from "@typed-assistant/logger"
|
|
2
2
|
import { generateTypes } from "@typed-assistant/types/generateTypes"
|
|
3
|
-
import { getSupervisorAPI } from "@typed-assistant/utils/getHassAPI"
|
|
4
|
-
import { withErrorHandling } from "@typed-assistant/utils/withErrorHandling"
|
|
5
3
|
import type { Subprocess } from "bun"
|
|
6
4
|
import { $ } from "bun"
|
|
7
5
|
import { readFileSync, watch } from "fs"
|
|
@@ -16,6 +14,8 @@ import {
|
|
|
16
14
|
import { setupGitPoller } from "./setupGitPoller"
|
|
17
15
|
import { setupWebhook } from "./setupWebhook"
|
|
18
16
|
import { startWebappServer } from "./setupWebserver"
|
|
17
|
+
import { restartAddon } from "./restartAddon"
|
|
18
|
+
import { getAddonInfo } from "./getAddonInfo"
|
|
19
19
|
|
|
20
20
|
type Processes = Awaited<ReturnType<typeof buildAndStartAppProcess>>
|
|
21
21
|
|
|
@@ -55,7 +55,19 @@ let multipleProcessesErrorCount = 0
|
|
|
55
55
|
let noProcessesErrorCount = 0
|
|
56
56
|
const checkProcesses = async (
|
|
57
57
|
entryFile: string,
|
|
58
|
-
{
|
|
58
|
+
{
|
|
59
|
+
addonUrl,
|
|
60
|
+
onProcessError,
|
|
61
|
+
restartAddonUrl,
|
|
62
|
+
}: {
|
|
63
|
+
addonUrl: string
|
|
64
|
+
onProcessError?: (
|
|
65
|
+
message: string,
|
|
66
|
+
addonUrl: string,
|
|
67
|
+
restartAddonUrl?: string,
|
|
68
|
+
) => void
|
|
69
|
+
restartAddonUrl: string
|
|
70
|
+
},
|
|
59
71
|
) => {
|
|
60
72
|
const ps = await $`ps -f`.text()
|
|
61
73
|
const matches = ps.match(new RegExp(`bun .+${entryFile}`, "gmi")) ?? []
|
|
@@ -66,7 +78,7 @@ const checkProcesses = async (
|
|
|
66
78
|
const message = `🚨 Multiple processes detected. Restarting TypedAssistant addon...`
|
|
67
79
|
log(message)
|
|
68
80
|
log(ps)
|
|
69
|
-
onProcessError?.(message)
|
|
81
|
+
onProcessError?.(message, addonUrl, restartAddonUrl)
|
|
70
82
|
// restartAddon()
|
|
71
83
|
return
|
|
72
84
|
}
|
|
@@ -80,7 +92,7 @@ const checkProcesses = async (
|
|
|
80
92
|
const message = `🚨 No processes detected. Restarting TypedAssistant addon...`
|
|
81
93
|
log(message)
|
|
82
94
|
log(ps)
|
|
83
|
-
onProcessError?.(message)
|
|
95
|
+
onProcessError?.(message, addonUrl, restartAddonUrl)
|
|
84
96
|
// restartAddon()
|
|
85
97
|
return
|
|
86
98
|
}
|
|
@@ -88,7 +100,11 @@ const checkProcesses = async (
|
|
|
88
100
|
noProcessesErrorCount = 0
|
|
89
101
|
}
|
|
90
102
|
|
|
91
|
-
setTimeout(
|
|
103
|
+
setTimeout(
|
|
104
|
+
() =>
|
|
105
|
+
checkProcesses(entryFile, { addonUrl, onProcessError, restartAddonUrl }),
|
|
106
|
+
5000,
|
|
107
|
+
)
|
|
92
108
|
}
|
|
93
109
|
|
|
94
110
|
export async function setup({
|
|
@@ -98,12 +114,14 @@ export async function setup({
|
|
|
98
114
|
}: {
|
|
99
115
|
entryFile: string
|
|
100
116
|
} & Parameters<typeof generateTypes>[0] &
|
|
101
|
-
Parameters<typeof checkProcesses>[1]) {
|
|
117
|
+
Pick<Parameters<typeof checkProcesses>[1], "onProcessError">) {
|
|
102
118
|
const addonInfo = await getAddonInfo()
|
|
103
119
|
const basePath = addonInfo?.data.ingress_entry ?? ""
|
|
104
120
|
const directoryToWatch = join(process.cwd(), "./src")
|
|
121
|
+
const addonUrl = basePath
|
|
122
|
+
const restartAddonUrl = `${basePath}/restart-addon`
|
|
105
123
|
|
|
106
|
-
checkProcesses(entryFile, { onProcessError })
|
|
124
|
+
checkProcesses(entryFile, { addonUrl, onProcessError, restartAddonUrl })
|
|
107
125
|
await setupGitSync()
|
|
108
126
|
|
|
109
127
|
let subprocesses = await buildAndStartAppProcess(entryFile, {
|
|
@@ -152,28 +170,6 @@ const ig = ignore().add(
|
|
|
152
170
|
const shouldIgnoreFileOrFolder = (filename: string) =>
|
|
153
171
|
ig.ignores(relative(process.cwd(), filename))
|
|
154
172
|
|
|
155
|
-
const restartAddon = async () => {
|
|
156
|
-
if (!process.env.SUPERVISOR_TOKEN) {
|
|
157
|
-
log("♻️ Can't restart addon. Exiting...")
|
|
158
|
-
process.exit(0)
|
|
159
|
-
return
|
|
160
|
-
}
|
|
161
|
-
log("♻️ Restarting addon...")
|
|
162
|
-
await getSupervisorAPI(`/addons/self/restart`, { method: "POST" })
|
|
163
|
-
}
|
|
164
|
-
|
|
165
|
-
const getAddonInfo = async () => {
|
|
166
|
-
log("🔍 Getting addon info...")
|
|
167
|
-
|
|
168
|
-
const { data, error } = await withErrorHandling(getSupervisorAPI)<{
|
|
169
|
-
data: { ingress_entry: string }
|
|
170
|
-
}>("/addons/self/info")
|
|
171
|
-
|
|
172
|
-
if (error) log(`🚨 Failed to get addon info: ${error}`)
|
|
173
|
-
|
|
174
|
-
return data
|
|
175
|
-
}
|
|
176
|
-
|
|
177
173
|
function setupWatcher({
|
|
178
174
|
directoryToWatch,
|
|
179
175
|
entryFile,
|
|
@@ -200,6 +196,7 @@ function setupWatcher({
|
|
|
200
196
|
if (shouldIgnoreFileOrFolder(filename)) return
|
|
201
197
|
log(`⚠️ Change to ${filename} detected.`)
|
|
202
198
|
if (filename.endsWith("process.tsx")) {
|
|
199
|
+
await killSubprocess(getSubprocesses().app)
|
|
203
200
|
await restartAddon()
|
|
204
201
|
} else {
|
|
205
202
|
onSubprocessChange(
|
|
@@ -222,3 +219,9 @@ process.on("SIGINT", async () => {
|
|
|
222
219
|
await callKillListeners()
|
|
223
220
|
process.exit(0)
|
|
224
221
|
})
|
|
222
|
+
process.on("SIGTERM", async () => {
|
|
223
|
+
log("👋 Exiting...")
|
|
224
|
+
await callSoftKillListeners()
|
|
225
|
+
await callKillListeners()
|
|
226
|
+
process.exit(0)
|
|
227
|
+
})
|
package/src/setupWebserver.tsx
CHANGED
|
@@ -6,7 +6,15 @@ import { Elysia, t } from "elysia"
|
|
|
6
6
|
import { watch } from "fs"
|
|
7
7
|
import { basename, join } from "path"
|
|
8
8
|
import type { List, String } from "ts-toolbelt"
|
|
9
|
-
import {
|
|
9
|
+
import {
|
|
10
|
+
addKillListener,
|
|
11
|
+
addSoftKillListener,
|
|
12
|
+
killSubprocess,
|
|
13
|
+
} from "./killProcess"
|
|
14
|
+
import { restartAddon } from "./restartAddon"
|
|
15
|
+
import { getAddonInfo } from "./getAddonInfo"
|
|
16
|
+
import { withErrorHandling } from "@typed-assistant/utils/withErrorHandling"
|
|
17
|
+
import { getSupervisorAPI } from "@typed-assistant/utils/getHassAPI"
|
|
10
18
|
|
|
11
19
|
const indexHtmlFilePath = `${import.meta.dir}/webserver/index.html` as const
|
|
12
20
|
const cssFile = `${import.meta.dir}/webserver/input.css` as const
|
|
@@ -103,6 +111,18 @@ export const startWebappServer = async ({
|
|
|
103
111
|
headers: { "content-type": "text/html" },
|
|
104
112
|
}),
|
|
105
113
|
)
|
|
114
|
+
.get("/restart-addon", async () => {
|
|
115
|
+
await killSubprocess(getSubprocesses().app)
|
|
116
|
+
restartAddon()
|
|
117
|
+
})
|
|
118
|
+
.get("/addon-info", async () => {
|
|
119
|
+
const { data, error } = await withErrorHandling(getSupervisorAPI)<{
|
|
120
|
+
data: { ingress_entry: string }
|
|
121
|
+
}>("/addons/self/info")
|
|
122
|
+
|
|
123
|
+
if (error) return error
|
|
124
|
+
return data
|
|
125
|
+
})
|
|
106
126
|
.get(
|
|
107
127
|
"/log.txt",
|
|
108
128
|
async ({ query }) => {
|