@typed-assistant/builder 0.0.35 → 0.0.37

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 CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@typed-assistant/builder",
3
- "version": "0.0.35",
3
+ "version": "0.0.37",
4
4
  "exports": {
5
5
  "./appProcess": "./src/appProcess.tsx",
6
6
  "./bunInstall": "./src/bunInstall.tsx",
@@ -25,9 +25,9 @@
25
25
  "ts-toolbelt": "^9.6.0",
26
26
  "typescript": "^5.3.3",
27
27
  "@typed-assistant/eslint-config": "0.0.8",
28
+ "@typed-assistant/logger": "0.0.12",
28
29
  "@typed-assistant/typescript-config": "0.0.8",
29
- "@typed-assistant/utils": "0.0.12",
30
- "@typed-assistant/logger": "0.0.12"
30
+ "@typed-assistant/utils": "0.0.13"
31
31
  },
32
32
  "peerDependencies": {
33
33
  "home-assistant-js-websocket": "^8.2.0"
@@ -15,7 +15,46 @@ import { setupGitPoller } from "./setupGitPoller"
15
15
  import { setupWebhook } from "./setupWebhook"
16
16
  import { startWebappServer } from "./setupWebserver"
17
17
  import { restartAddon } from "./restartAddon"
18
- import { getAddonInfo } from "./getAddonInfo"
18
+ import { getAddonInfo as getAddonInfoAPI } from "./getAddonInfo"
19
+ import debounce from "debounce"
20
+
21
+ export async function setup({
22
+ entryFile,
23
+ mdiPaths,
24
+ onProcessError,
25
+ }: {
26
+ entryFile: string
27
+ } & Parameters<typeof generateTypes>[0] &
28
+ Pick<Parameters<typeof checkProcesses>[1], "onProcessError">) {
29
+ const addonInfo = await getAddonInfo()
30
+ const basePath = addonInfo?.data.ingress_entry ?? ""
31
+ const slug = addonInfo?.data.slug ?? ""
32
+ const directoryToWatch = join(process.cwd(), "./src")
33
+ const addonUrl = `${slug}/ingress`
34
+
35
+ checkProcesses(entryFile, { addonUrl, onProcessError })
36
+ await setupGitSync()
37
+
38
+ let subprocesses = await buildAndStartAppProcess(entryFile, {
39
+ mdiPaths: mdiPaths,
40
+ })
41
+
42
+ startWebappServer({
43
+ basePath,
44
+ getSubprocesses: () => subprocesses,
45
+ })
46
+ setupWatcher({
47
+ directoryToWatch,
48
+ entryFile,
49
+ mdiPaths,
50
+ onSubprocessChange: (newSubprocesses) => {
51
+ subprocesses = newSubprocesses
52
+ },
53
+ getSubprocesses: () => subprocesses,
54
+ })
55
+
56
+ return subprocesses
57
+ }
19
58
 
20
59
  type Processes = Awaited<ReturnType<typeof buildAndStartAppProcess>>
21
60
 
@@ -58,15 +97,9 @@ const checkProcesses = async (
58
97
  {
59
98
  addonUrl,
60
99
  onProcessError,
61
- restartAddonUrl,
62
100
  }: {
63
101
  addonUrl: string
64
- onProcessError?: (
65
- message: string,
66
- addonUrl: string,
67
- restartAddonUrl?: string,
68
- ) => void
69
- restartAddonUrl: string
102
+ onProcessError?: (message: string, addonUrl: string) => void
70
103
  },
71
104
  ) => {
72
105
  const ps = await $`ps -f`.text()
@@ -75,11 +108,10 @@ const checkProcesses = async (
75
108
  if (matches.length > 1) {
76
109
  multipleProcessesErrorCount++
77
110
  if (multipleProcessesErrorCount > 5) {
78
- const message = `🚨 Multiple processes detected. Restarting TypedAssistant addon...`
111
+ const message = `🚨 Multiple processes detected. Check the logs...`
79
112
  log(message)
80
113
  log(ps)
81
- onProcessError?.(message, addonUrl, restartAddonUrl)
82
- // restartAddon()
114
+ onProcessError?.(message, addonUrl)
83
115
  return
84
116
  }
85
117
  } else {
@@ -89,11 +121,10 @@ const checkProcesses = async (
89
121
  if (matches.length === 0) {
90
122
  noProcessesErrorCount++
91
123
  if (noProcessesErrorCount > 5) {
92
- const message = `🚨 No processes detected. Restarting TypedAssistant addon...`
124
+ const message = `🚨 No processes detected. Check the logs...`
93
125
  log(message)
94
126
  log(ps)
95
- onProcessError?.(message, addonUrl, restartAddonUrl)
96
- // restartAddon()
127
+ onProcessError?.(message, addonUrl)
97
128
  return
98
129
  }
99
130
  } else {
@@ -101,48 +132,19 @@ const checkProcesses = async (
101
132
  }
102
133
 
103
134
  setTimeout(
104
- () =>
105
- checkProcesses(entryFile, { addonUrl, onProcessError, restartAddonUrl }),
135
+ () => checkProcesses(entryFile, { addonUrl, onProcessError }),
106
136
  5000,
107
137
  )
108
138
  }
109
139
 
110
- export async function setup({
111
- entryFile,
112
- mdiPaths,
113
- onProcessError,
114
- }: {
115
- entryFile: string
116
- } & Parameters<typeof generateTypes>[0] &
117
- Pick<Parameters<typeof checkProcesses>[1], "onProcessError">) {
118
- const addonInfo = await getAddonInfo()
119
- const basePath = addonInfo?.data.ingress_entry ?? ""
120
- const directoryToWatch = join(process.cwd(), "./src")
121
- const addonUrl = basePath
122
- const restartAddonUrl = `${basePath}/restart-addon`
140
+ const getAddonInfo = async () => {
141
+ log("🔍 Getting addon info...")
123
142
 
124
- checkProcesses(entryFile, { addonUrl, onProcessError, restartAddonUrl })
125
- await setupGitSync()
143
+ const { data, error } = await getAddonInfoAPI()
126
144
 
127
- let subprocesses = await buildAndStartAppProcess(entryFile, {
128
- mdiPaths: mdiPaths,
129
- })
145
+ if (error) log(`🚨 Failed to get addon info: ${error}`)
130
146
 
131
- startWebappServer({
132
- basePath,
133
- getSubprocesses: () => subprocesses,
134
- })
135
- setupWatcher({
136
- directoryToWatch,
137
- entryFile,
138
- mdiPaths,
139
- onSubprocessChange: (newSubprocesses) => {
140
- subprocesses = newSubprocesses
141
- },
142
- getSubprocesses: () => subprocesses,
143
- })
144
-
145
- return subprocesses
147
+ return data
146
148
  }
147
149
 
148
150
  const setupGitSync = async () => {
@@ -191,7 +193,7 @@ function setupWatcher({
191
193
  const watcher = watch(
192
194
  directoryToWatch,
193
195
  { recursive: true },
194
- async function onFileChange(event, filename) {
196
+ debounce(async function onFileChange(event, filename) {
195
197
  if (!filename) return
196
198
  if (shouldIgnoreFileOrFolder(filename)) return
197
199
  log(`⚠️ Change to ${filename} detected.`)
@@ -203,7 +205,7 @@ function setupWatcher({
203
205
  await killAndRestartApp(entryFile, { mdiPaths }, getSubprocesses()),
204
206
  )
205
207
  }
206
- },
208
+ }, 200),
207
209
  )
208
210
 
209
211
  addKillListener(() => {
@@ -2,14 +2,73 @@ import { log } from "@typed-assistant/logger"
2
2
  import { getSupervisorAPI } from "@typed-assistant/utils/getHassAPI"
3
3
  import { withErrorHandling } from "@typed-assistant/utils/withErrorHandling"
4
4
 
5
- export const getAddonInfo = async () => {
6
- log("🔍 Getting addon info...")
7
-
8
- const { data, error } = await withErrorHandling(getSupervisorAPI)<{
9
- data: { ingress_entry: string }
10
- }>("/addons/self/info")
11
-
12
- if (error) log(`🚨 Failed to get addon info: ${error}`)
13
-
14
- return data
5
+ type AddonInfoResponse = {
6
+ result: string
7
+ data: {
8
+ name: string
9
+ slug: string
10
+ hostname: string
11
+ description: string
12
+ long_description: string
13
+ advanced: boolean
14
+ stage: string
15
+ repository: string
16
+ version_latest: string
17
+ protected: boolean
18
+ rating: number
19
+ boot: string
20
+ arch: string[]
21
+ machine: any[]
22
+ homeassistant: null
23
+ url: string
24
+ detached: boolean
25
+ available: boolean
26
+ build: boolean
27
+ network: null
28
+ network_description: null
29
+ host_network: boolean
30
+ host_pid: boolean
31
+ host_ipc: boolean
32
+ host_uts: boolean
33
+ host_dbus: boolean
34
+ full_access: boolean
35
+ apparmor: string
36
+ icon: boolean
37
+ logo: boolean
38
+ changelog: boolean
39
+ documentation: boolean
40
+ stdin: boolean
41
+ hassio_api: boolean
42
+ hassio_role: string
43
+ auth_api: boolean
44
+ homeassistant_api: boolean
45
+ gpio: boolean
46
+ usb: boolean
47
+ uart: boolean
48
+ kernel_modules: boolean
49
+ devicetree: boolean
50
+ udev: boolean
51
+ docker_api: boolean
52
+ video: boolean
53
+ audio: boolean
54
+ startup: string
55
+ ingress: boolean
56
+ signed: boolean
57
+ state: string
58
+ webui: null
59
+ ingress_entry: string
60
+ ingress_url: string
61
+ ingress_port: number
62
+ ingress_panel: boolean
63
+ audio_input: null
64
+ audio_output: null
65
+ auto_update: boolean
66
+ ip_address: string
67
+ version: string
68
+ update_available: boolean
69
+ watchdog: boolean
70
+ }
15
71
  }
72
+
73
+ export const getAddonInfo = () =>
74
+ withErrorHandling(getSupervisorAPI)<AddonInfoResponse>("/addons/self/info")
@@ -1,4 +1,5 @@
1
1
  import { log } from "@typed-assistant/logger"
2
+ import { handleFetchError } from "@typed-assistant/utils/getHassAPI"
2
3
  import { withErrorHandling } from "@typed-assistant/utils/withErrorHandling"
3
4
  import { z } from "zod"
4
5
 
@@ -97,19 +98,6 @@ const Webhook = z.object({
97
98
 
98
99
  type Webhook = z.infer<typeof Webhook>
99
100
 
100
- const handleFetchError = async (d: Response): Promise<Response> => {
101
- if (!d.ok)
102
- throw new Error(
103
- d.status +
104
- " " +
105
- d.statusText +
106
- (d.headers.get("Content-Type")?.includes("application/json")
107
- ? `:\n${JSON.stringify(await d.json(), null, 2)}`
108
- : ""),
109
- )
110
- return d
111
- }
112
-
113
101
  const retryTimeout = 2000
114
102
  let retries = 0
115
103
  export const setupWebhook = async (): Promise<void> => {
@@ -6,15 +6,9 @@ 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 {
10
- addKillListener,
11
- addSoftKillListener,
12
- killSubprocess,
13
- } from "./killProcess"
14
- import { restartAddon } from "./restartAddon"
15
9
  import { getAddonInfo } from "./getAddonInfo"
16
- import { withErrorHandling } from "@typed-assistant/utils/withErrorHandling"
17
- import { getSupervisorAPI } from "@typed-assistant/utils/getHassAPI"
10
+ import { addKillListener, killSubprocess } from "./killProcess"
11
+ import { restartAddon } from "./restartAddon"
18
12
 
19
13
  const indexHtmlFilePath = `${import.meta.dir}/webserver/index.html` as const
20
14
  const cssFile = `${import.meta.dir}/webserver/input.css` as const
@@ -114,14 +108,18 @@ export const startWebappServer = async ({
114
108
  .get("/restart-addon", async () => {
115
109
  await killSubprocess(getSubprocesses().app)
116
110
  restartAddon()
111
+ return { message: "Restarting addon..." }
117
112
  })
118
113
  .get("/addon-info", async () => {
119
- const { data, error } = await withErrorHandling(getSupervisorAPI)<{
120
- data: { ingress_entry: string }
121
- }>("/addons/self/info")
114
+ const { data, error } = await getAddonInfo()
122
115
 
123
116
  if (error) return error
124
- return data
117
+ return {
118
+ ...data.data,
119
+ options: "HIDDEN",
120
+ schema: "HIDDEN",
121
+ translations: "HIDDEN",
122
+ }
125
123
  })
126
124
  .get(
127
125
  "/log.txt",