windsor-bot 0.1.0 → 0.1.1

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/README.md CHANGED
@@ -123,6 +123,6 @@ The control panel is a Preact app served by the diagnostics server and can:
123
123
  1. Show runtime bot status and recent events.
124
124
  2. Save basic setup into a local `windsor.config.json` file (Discord token, server id, etc).
125
125
 
126
- The browser app source lives in `src/web/app.tsx` and is bundled on-demand by the server using the esbuild API.
126
+ The browser app source lives in `src/web/app.tsx`. It is bundled into the npm package during the build and served by the diagnostics server; development runs can still bundle the source on demand.
127
127
 
128
128
  `windsor.config.json` is gitignored because it can contain secrets.
package/dist/server.js CHANGED
@@ -1,7 +1,8 @@
1
1
  import { createServer } from 'http';
2
2
  import { build } from 'esbuild';
3
- import { stat } from 'fs/promises';
4
- import { join } from 'path';
3
+ import { readFile, stat } from 'fs/promises';
4
+ import { dirname, join } from 'path';
5
+ import { fileURLToPath } from 'url';
5
6
  import { getCurrentConfig, updateConfig, checkPassword, hashPassword, getConfigFilePath, } from './config.js';
6
7
  import { printTestPage, getImageFeed, clearImageFeed, renderFeedHtml } from './printing/index.js';
7
8
  const MAX_EVENTS = 200;
@@ -73,13 +74,29 @@ async function readJsonBody(req) {
73
74
  }
74
75
  let appBundleCache = null;
75
76
  async function loadAppScript() {
76
- const entryPoint = join(process.cwd(), 'src', 'web', 'app.tsx');
77
- const sourceStat = await stat(entryPoint);
78
- if (appBundleCache && appBundleCache.mtimeMs === sourceStat.mtimeMs) {
77
+ const runtimeDir = dirname(fileURLToPath(import.meta.url));
78
+ const bundledApp = join(runtimeDir, 'web', 'app.bundle.js');
79
+ const sourceEntryPoint = join(runtimeDir, '..', 'src', 'web', 'app.tsx');
80
+ const appPath = await stat(bundledApp).then(() => bundledApp).catch((error) => {
81
+ if (error instanceof Error && 'code' in error && error.code === 'ENOENT') {
82
+ return sourceEntryPoint;
83
+ }
84
+ throw error;
85
+ });
86
+ const appStat = await stat(appPath);
87
+ if (appPath === bundledApp) {
88
+ if (appBundleCache && appBundleCache.mtimeMs === appStat.mtimeMs) {
89
+ return appBundleCache.script;
90
+ }
91
+ const script = await readFile(appPath, 'utf8');
92
+ appBundleCache = { script, mtimeMs: appStat.mtimeMs };
93
+ return script;
94
+ }
95
+ if (appBundleCache && appBundleCache.mtimeMs === appStat.mtimeMs) {
79
96
  return appBundleCache.script;
80
97
  }
81
98
  const result = await build({
82
- entryPoints: [entryPoint],
99
+ entryPoints: [sourceEntryPoint],
83
100
  bundle: true,
84
101
  write: false,
85
102
  platform: 'browser',
@@ -92,7 +109,7 @@ async function loadAppScript() {
92
109
  const firstFile = result.outputFiles[0];
93
110
  if (!firstFile)
94
111
  throw new Error('Failed to generate app bundle');
95
- appBundleCache = { script: firstFile.text, mtimeMs: sourceStat.mtimeMs };
112
+ appBundleCache = { script: firstFile.text, mtimeMs: appStat.mtimeMs };
96
113
  return firstFile.text;
97
114
  }
98
115
  function renderHtmlShell() {