@1agh/maude 0.18.2 → 0.19.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.
@@ -1022,9 +1022,9 @@ async function buildSystemData() {
1022
1022
  } catch {}
1023
1023
  const items = [];
1024
1024
  for (const m of matches) {
1025
- const files = await findFiles(m.abs, m.rel, ['.html']);
1025
+ const files = await findFiles(m.abs, m.rel, ['.tsx', '.html']);
1026
1026
  for (const f of files) {
1027
- const fname = f.split('/').pop().replace(/\.html$/i, '');
1027
+ const fname = f.split('/').pop().replace(/\.(tsx|html)$/i, '');
1028
1028
  const group = f.split('/').slice(-2, -1)[0] || folderName;
1029
1029
  // For "index.html" prefer the group name as the label (e.g. "desktop", "mobile")
1030
1030
  const label = (fname.toLowerCase() === 'index') ? group : fname;
@@ -46,41 +46,87 @@ const http = createHttp(ctx, api, inspect);
46
46
  const fsWatch = createFsWatch(ctx);
47
47
 
48
48
  // Port: --port arg > $PORT > $MDCC_DEV_PORT > 4399.
49
- function resolvePort(): number {
49
+ // When the port wasn't explicitly chosen and the default is busy (another
50
+ // project's dev-server is running on the same machine), walk up to 4408 before
51
+ // giving up. Explicit ports stay fatal so users notice their own collisions.
52
+ function resolvePort(): { port: number; explicit: boolean } {
50
53
  const i = process.argv.indexOf('--port');
51
- if (i !== -1 && process.argv[i + 1]) return Number(process.argv[i + 1]);
54
+ if (i !== -1 && process.argv[i + 1]) return { port: Number(process.argv[i + 1]), explicit: true };
52
55
  const env = process.env.PORT ?? process.env.MDCC_DEV_PORT;
53
- if (env) return Number(env);
54
- return 4399;
56
+ if (env) return { port: Number(env), explicit: true };
57
+ return { port: 4399, explicit: false };
55
58
  }
56
59
 
57
- const PORT = resolvePort();
58
-
59
- const server = Bun.serve<{ id: string; remote: string }, never>({
60
- port: PORT,
61
- hostname: '127.0.0.1',
62
- development: process.env.NODE_ENV !== 'production',
63
- routes: http.routes,
64
- async fetch(req, srv) {
65
- // WebSocket upgrade.
66
- if (new URL(req.url).pathname.startsWith('/_ws')) {
67
- const ok = srv.upgrade(req, {
68
- data: {
69
- id: crypto.randomUUID(),
70
- remote: req.headers.get('x-forwarded-for') ?? '127.0.0.1',
71
- },
72
- });
73
- if (ok) return undefined as unknown as Response;
74
- return new Response('Upgrade failed', { status: 400 });
60
+ const { port: BASE_PORT, explicit: PORT_EXPLICIT } = resolvePort();
61
+
62
+ type BunServer = ReturnType<typeof Bun.serve<{ id: string; remote: string }, never>>;
63
+
64
+ function startServer(port: number): BunServer {
65
+ return Bun.serve<{ id: string; remote: string }, never>({
66
+ port,
67
+ hostname: '127.0.0.1',
68
+ development: process.env.NODE_ENV !== 'production',
69
+ routes: http.routes,
70
+ async fetch(req, srv) {
71
+ // WebSocket upgrade.
72
+ if (new URL(req.url).pathname.startsWith('/_ws')) {
73
+ const ok = srv.upgrade(req, {
74
+ data: {
75
+ id: crypto.randomUUID(),
76
+ remote: req.headers.get('x-forwarded-for') ?? '127.0.0.1',
77
+ },
78
+ });
79
+ if (ok) return undefined as unknown as Response;
80
+ return new Response('Upgrade failed', { status: 400 });
81
+ }
82
+ return http.fetch(req);
83
+ },
84
+ websocket: ws.handler,
85
+ error(e) {
86
+ console.error('[bun.serve error]', e);
87
+ return new Response('Server error', { status: 500 });
88
+ },
89
+ });
90
+ }
91
+
92
+ function isAddrInUse(e: unknown): boolean {
93
+ if (!e || typeof e !== 'object') return false;
94
+ const err = e as { code?: string; errno?: number };
95
+ return err.code === 'EADDRINUSE';
96
+ }
97
+
98
+ let server: BunServer;
99
+ {
100
+ const MAX_TRIES = PORT_EXPLICIT ? 1 : 10;
101
+ let lastErr: unknown;
102
+ let bound: BunServer | null = null;
103
+ for (let i = 0; i < MAX_TRIES; i++) {
104
+ const tryPort = BASE_PORT + i;
105
+ try {
106
+ bound = startServer(tryPort);
107
+ if (i > 0) {
108
+ console.log(`[port] ${BASE_PORT} busy, using ${tryPort} instead.`);
109
+ }
110
+ break;
111
+ } catch (e) {
112
+ lastErr = e;
113
+ if (!isAddrInUse(e)) throw e;
75
114
  }
76
- return http.fetch(req);
77
- },
78
- websocket: ws.handler,
79
- error(e) {
80
- console.error('[bun.serve error]', e);
81
- return new Response('Server error', { status: 500 });
82
- },
83
- });
115
+ }
116
+ if (!bound) {
117
+ if (PORT_EXPLICIT) {
118
+ console.error(
119
+ `\n Port ${BASE_PORT} is in use. Pick a different one with --port <N> or $PORT.\n`
120
+ );
121
+ } else {
122
+ console.error(
123
+ `\n Ports ${BASE_PORT}-${BASE_PORT + MAX_TRIES - 1} are all in use. Stop a running dev-server or pass --port <N>.\n`
124
+ );
125
+ }
126
+ throw lastErr;
127
+ }
128
+ server = bound;
129
+ }
84
130
 
85
131
  await Bun.write(
86
132
  ctx.paths.serverInfoFile,