@typed-assistant/builder 0.0.80 → 0.0.82

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/CHANGELOG.md CHANGED
@@ -1,5 +1,17 @@
1
1
  # @typed-assistant/builder
2
2
 
3
+ ## 0.0.82
4
+
5
+ ### Patch Changes
6
+
7
+ - Restart app when an empty string is returned from the process.
8
+
9
+ ## 0.0.81
10
+
11
+ ### Patch Changes
12
+
13
+ - Pin Elysia to 1.1.x.
14
+
3
15
  ## 0.0.79
4
16
 
5
17
  ### Patch Changes
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@typed-assistant/builder",
3
- "version": "0.0.80",
3
+ "version": "0.0.82",
4
4
  "exports": {
5
5
  "./appProcess": "./src/appProcess.tsx",
6
6
  "./bunInstall": "./src/bunInstall.tsx",
@@ -13,7 +13,7 @@
13
13
  "@types/react-dom": "^18.3.1",
14
14
  "ansi-to-html": "^0.7.2",
15
15
  "debounce": "^2.0.0",
16
- "elysia": "^1.1.25",
16
+ "elysia": "~1.1.25",
17
17
  "ignore": "^5.3.0",
18
18
  "react": "^18",
19
19
  "react-dom": "^18",
@@ -28,10 +28,10 @@
28
28
  "eslint-plugin-html": "^7.1.0",
29
29
  "ts-toolbelt": "^9.6.0",
30
30
  "typescript": "^5.4.0",
31
- "@typed-assistant/eslint-config": "0.0.10",
32
31
  "@typed-assistant/logger": "0.0.22",
33
32
  "@typed-assistant/typescript-config": "0.0.10",
34
- "@typed-assistant/utils": "0.0.19"
33
+ "@typed-assistant/utils": "0.0.19",
34
+ "@typed-assistant/eslint-config": "0.0.10"
35
35
  },
36
36
  "publishConfig": {
37
37
  "access": "public",
@@ -45,7 +45,13 @@ const getReader = (
45
45
  ) => {
46
46
  const cachedReader = readers[type].get(stream)
47
47
  if (!cachedReader) {
48
- readers[type].forEach((_reader, cachedStream) => {
48
+ readers[type].forEach((reader, cachedStream) => {
49
+ // Properly release the lock before deleting
50
+ try {
51
+ reader.releaseLock()
52
+ } catch (e) {
53
+ // Ignore if already released
54
+ }
49
55
  readers[type].delete(cachedStream)
50
56
  })
51
57
  }
@@ -65,6 +71,8 @@ let stats = {
65
71
  memory_percent: null as number | null,
66
72
  max_memory_usage: 0,
67
73
  }
74
+ let statsInterval: ReturnType<typeof setInterval> | null = null
75
+
68
76
  const getStats = async () => {
69
77
  const { data, error } = await withErrorHandling(
70
78
  getSupervisorAPI<{
@@ -93,8 +101,6 @@ const getStats = async () => {
93
101
  : stats.max_memory_usage,
94
102
  }
95
103
  }
96
-
97
- setTimeout(getStats, 10 * ONE_SECOND)
98
104
  }
99
105
 
100
106
  export const startWebappServer = async ({
@@ -233,14 +239,7 @@ export const startWebappServer = async ({
233
239
  }),
234
240
 
235
241
  async open(ws) {
236
- ws.send(
237
- await getLogsFromFile({
238
- filter: ws.data.query.filter,
239
- level: ws.data.query.level,
240
- limit: ws.data.query.limit,
241
- offset: ws.data.query.offset,
242
- }),
243
- )
242
+ // Set the log subscriber first to avoid race conditions
244
243
  logSubscribers.set(ws.id, async () => {
245
244
  ws.send(
246
245
  await getLogsFromFile({
@@ -251,6 +250,15 @@ export const startWebappServer = async ({
251
250
  }),
252
251
  )
253
252
  })
253
+ // Then send the initial logs
254
+ ws.send(
255
+ await getLogsFromFile({
256
+ filter: ws.data.query.filter,
257
+ level: ws.data.query.level,
258
+ limit: ws.data.query.limit,
259
+ offset: ws.data.query.offset,
260
+ }),
261
+ )
254
262
  },
255
263
  close(ws) {
256
264
  logSubscribers.delete(ws.id)
@@ -337,11 +345,34 @@ export const startWebappServer = async ({
337
345
 
338
346
  watchLogFileSize()
339
347
 
340
- getStats()
348
+ // Start stats polling interval
349
+ statsInterval = setInterval(getStats, 10 * 1000)
341
350
 
342
351
  addKillListener(async () => {
343
352
  watcher.close()
344
353
  await server.stop()
354
+ // Clean up all websocket subscribers
355
+ subscribers.clear()
356
+ logSubscribers.clear()
357
+ // Release and clear all readers
358
+ for (const reader of readers.stdout.values()) {
359
+ try {
360
+ reader.releaseLock()
361
+ } catch (e) {
362
+ /* ignore */
363
+ }
364
+ }
365
+ for (const reader of readers.stderr.values()) {
366
+ try {
367
+ reader.releaseLock()
368
+ } catch (e) {
369
+ /* ignore */
370
+ }
371
+ }
372
+ readers.stdout.clear()
373
+ readers.stderr.clear()
374
+ // Clear stats polling interval
375
+ if (statsInterval) clearInterval(statsInterval)
345
376
  })
346
377
 
347
378
  // eslint-disable-next-line no-constant-condition
@@ -373,12 +404,14 @@ export const startWebappServer = async ({
373
404
  emoji: "💀",
374
405
  additionalDetails: JSON.stringify({
375
406
  exitCode: getSubprocesses().app.exitCode,
407
+ stderrValue,
408
+ stderrValueDecoded: decodedString,
376
409
  }),
377
410
  },
378
- "Process is returning an empty string",
411
+ "Process is returning an empty string. Restarting app...",
379
412
  )
380
- await new Promise((resolve) => setTimeout(resolve, 1000))
381
- continue
413
+ onRestartAppRequest()
414
+ break
382
415
  }
383
416
  subscribers.forEach((send) => send(convertedMessage))
384
417
  }