orbitchat 3.5.3 → 3.5.4
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/bin/orbitchat.js +59 -13
- package/dist/assets/ChartRenderer-BK9VmJeQ.js +80 -0
- package/dist/assets/{MermaidRenderer-CrwrWA79.js → MermaidRenderer-qzVgEt2x.js} +5 -5
- package/dist/assets/{MusicRenderer-DsCYCPzj.js → MusicRenderer-D7rL8A6g.js} +2 -2
- package/dist/assets/{SVGRenderer-4l9fyX1s.js → SVGRenderer-BEKEOm3s.js} +1 -1
- package/dist/assets/{_basePickBy-C7S27-r4.js → _basePickBy-DjEbiWID.js} +1 -1
- package/dist/assets/{_baseUniq-7f9rjySx.js → _baseUniq-BJ_CGYjc.js} +1 -1
- package/dist/assets/{architectureDiagram-2XIMDMQ5-RDQYD3py.js → architectureDiagram-2XIMDMQ5-Os-EdwOr.js} +1 -1
- package/dist/assets/{blockDiagram-WCTKOSBZ-Bvd59nkz.js → blockDiagram-WCTKOSBZ-dOlyr0sT.js} +1 -1
- package/dist/assets/{c4Diagram-IC4MRINW-BspB3C3a.js → c4Diagram-IC4MRINW-Bo18Ckoj.js} +1 -1
- package/dist/assets/channel-u3m7-f_Y.js +1 -0
- package/dist/assets/{chunk-4BX2VUAB-CF_0yBPD.js → chunk-4BX2VUAB-Bd4J2y84.js} +1 -1
- package/dist/assets/{chunk-55IACEB6-DH0Z48MR.js → chunk-55IACEB6-D31lfA_a.js} +1 -1
- package/dist/assets/{chunk-FMBD7UC4-D0VfP_qK.js → chunk-FMBD7UC4-D7f0j4zs.js} +1 -1
- package/dist/assets/{chunk-JSJVCQXG-BWDXqKOo.js → chunk-JSJVCQXG-i60xlQfX.js} +1 -1
- package/dist/assets/{chunk-KX2RTZJC-neUa6q9l.js → chunk-KX2RTZJC-DOMFBwQb.js} +1 -1
- package/dist/assets/{chunk-NQ4KR5QH-B2DKcXKz.js → chunk-NQ4KR5QH-Z6JCXOAb.js} +1 -1
- package/dist/assets/{chunk-QZHKN3VN-CB8rRoOU.js → chunk-QZHKN3VN-EGcB7IW2.js} +1 -1
- package/dist/assets/{chunk-WL4C6EOR-BWSVDtLk.js → chunk-WL4C6EOR-Dtoe_nFJ.js} +1 -1
- package/dist/assets/classDiagram-VBA2DB6C-CK4JEESe.js +1 -0
- package/dist/assets/classDiagram-v2-RAHNMMFH-CK4JEESe.js +1 -0
- package/dist/assets/clone-lXpWKNyV.js +1 -0
- package/dist/assets/{cose-bilkent-S5V4N54A-BkQN7T_Z.js → cose-bilkent-S5V4N54A-DwaP6XDY.js} +1 -1
- package/dist/assets/{dagre-KLK3FWXG-2aRZ42WU.js → dagre-KLK3FWXG-3iS8nwUM.js} +1 -1
- package/dist/assets/{diagram-E7M64L7V-B0nhOFG7.js → diagram-E7M64L7V-DWn04JQu.js} +1 -1
- package/dist/assets/{diagram-IFDJBPK2-B9V7kAOO.js → diagram-IFDJBPK2-CeCAfVij.js} +1 -1
- package/dist/assets/{diagram-P4PSJMXO-CFFdtr8I.js → diagram-P4PSJMXO-mjl_7jtT.js} +1 -1
- package/dist/assets/{erDiagram-INFDFZHY-B5ffop2h.js → erDiagram-INFDFZHY-Dl81qwyk.js} +1 -1
- package/dist/assets/{flowDiagram-PKNHOUZH-BWbYNUvl.js → flowDiagram-PKNHOUZH-Du4oI4VY.js} +1 -1
- package/dist/assets/{ganttDiagram-A5KZAMGK-Chhnbfig.js → ganttDiagram-A5KZAMGK-B4O-QXYi.js} +1 -1
- package/dist/assets/{gitGraphDiagram-K3NZZRJ6-V8UBDhXq.js → gitGraphDiagram-K3NZZRJ6-Cju5-Jsp.js} +1 -1
- package/dist/assets/{graph-CX33kXjo.js → graph-BRWBJHvn.js} +1 -1
- package/dist/assets/{index-6t_LHUnB.js → index-C8kIMiLQ.js} +124 -124
- package/dist/assets/{index-DUcrCaMk.js → index-O3Qu_V1p.js} +1 -1
- package/dist/assets/{infoDiagram-LFFYTUFH-D39liguC.js → infoDiagram-LFFYTUFH-BtIElN3U.js} +1 -1
- package/dist/assets/{ishikawaDiagram-PHBUUO56-DP_IEmay.js → ishikawaDiagram-PHBUUO56-BKL_bByI.js} +1 -1
- package/dist/assets/{journeyDiagram-4ABVD52K-DZtCCP2H.js → journeyDiagram-4ABVD52K-B7azS9rj.js} +1 -1
- package/dist/assets/{kanban-definition-K7BYSVSG-BJjJciwh.js → kanban-definition-K7BYSVSG-jcg_PkQS.js} +1 -1
- package/dist/assets/{layout-xvakIQ0I.js → layout-M6cSIos1.js} +1 -1
- package/dist/assets/{mindmap-definition-YRQLILUH-BFYkJYKW.js → mindmap-definition-YRQLILUH-Cf0IOJrc.js} +1 -1
- package/dist/assets/{pieDiagram-SKSYHLDU-B4LgWQ3r.js → pieDiagram-SKSYHLDU-DZkXQWf1.js} +1 -1
- package/dist/assets/{quadrantDiagram-337W2JSQ-SbaxPO9C.js → quadrantDiagram-337W2JSQ-CBv4NF9N.js} +1 -1
- package/dist/assets/{requirementDiagram-Z7DCOOCP-cHZA8avY.js → requirementDiagram-Z7DCOOCP-DBFzO_Ft.js} +1 -1
- package/dist/assets/{sankeyDiagram-WA2Y5GQK-BOvJicIs.js → sankeyDiagram-WA2Y5GQK-CSP7f-pA.js} +1 -1
- package/dist/assets/{sequenceDiagram-2WXFIKYE-Dk9q2HeF.js → sequenceDiagram-2WXFIKYE-BTC0RRGS.js} +1 -1
- package/dist/assets/{stateDiagram-RAJIS63D--PnsFKDS.js → stateDiagram-RAJIS63D-CAh_mwJy.js} +1 -1
- package/dist/assets/stateDiagram-v2-FVOUBMTO-DnFZfFm4.js +1 -0
- package/dist/assets/{timeline-definition-YZTLITO2-yQqhjBjA.js → timeline-definition-YZTLITO2-BLdeBeSr.js} +1 -1
- package/dist/assets/treemap-KZPCXAKY-LlRSRQLF.js +162 -0
- package/dist/assets/{vennDiagram-LZ73GAT5-DtcZ-nWZ.js → vennDiagram-LZ73GAT5-_Bk0EQ8g.js} +1 -1
- package/dist/assets/{xychartDiagram-JWTSCODW-CcHyoLw8.js → xychartDiagram-JWTSCODW-CB8cW01V.js} +1 -1
- package/dist/index.html +1 -1
- package/package.json +1 -6
- package/dist/assets/ChartRenderer-DqtgMzkG.js +0 -80
- package/dist/assets/channel-CyC077Do.js +0 -1
- package/dist/assets/classDiagram-VBA2DB6C-SQx6yVWX.js +0 -1
- package/dist/assets/classDiagram-v2-RAHNMMFH-SQx6yVWX.js +0 -1
- package/dist/assets/clone-DThclz6H.js +0 -1
- package/dist/assets/stateDiagram-v2-FVOUBMTO-IRiLaZKp.js +0 -1
- package/dist/assets/treemap-KZPCXAKY-ChqK5F5-.js +0 -162
package/bin/orbitchat.js
CHANGED
|
@@ -10,7 +10,7 @@
|
|
|
10
10
|
import express from 'express';
|
|
11
11
|
import fs from 'fs';
|
|
12
12
|
import path from 'path';
|
|
13
|
-
import {
|
|
13
|
+
import { execFileSync } from 'child_process';
|
|
14
14
|
import { fileURLToPath } from 'url';
|
|
15
15
|
import { dirname } from 'path';
|
|
16
16
|
import { createProxyMiddleware } from 'http-proxy-middleware';
|
|
@@ -96,6 +96,7 @@ function deepMerge(target, source) {
|
|
|
96
96
|
if (!isObject(target) || !isObject(source)) return source;
|
|
97
97
|
const output = { ...target };
|
|
98
98
|
Object.keys(source).forEach(key => {
|
|
99
|
+
if (key === '__proto__' || key === 'constructor' || key === 'prototype') return;
|
|
99
100
|
if (isObject(target[key]) && isObject(source[key])) {
|
|
100
101
|
output[key] = deepMerge(target[key], source[key]);
|
|
101
102
|
} else if (source[key] !== undefined) {
|
|
@@ -280,17 +281,35 @@ function createServer(distPath, config, serverConfig = {}) {
|
|
|
280
281
|
});
|
|
281
282
|
}
|
|
282
283
|
|
|
283
|
-
// Guest rate limiting
|
|
284
|
+
// Guest rate limiting — only applies to unauthenticated requests.
|
|
285
|
+
// Exempt read-only endpoints, file operations, and adapter info to avoid
|
|
286
|
+
// hitting limits during normal page load and file upload workflows.
|
|
284
287
|
if (serverConfig.rateLimit?.enabled !== false) {
|
|
285
288
|
const rl = serverConfig.rateLimit || {};
|
|
289
|
+
const rateLimitWindowMs = rl.windowMs || 60000;
|
|
290
|
+
const retryAfterSeconds = Math.ceil(rateLimitWindowMs / 1000);
|
|
291
|
+
|
|
292
|
+
const isExemptPath = (req) =>
|
|
293
|
+
req.method === 'OPTIONS' ||
|
|
294
|
+
req.path === '/adapters' ||
|
|
295
|
+
req.path.startsWith('/files') ||
|
|
296
|
+
req.path.startsWith('/admin/adapters') ||
|
|
297
|
+
req.path.startsWith('/admin/chat-history');
|
|
298
|
+
|
|
286
299
|
const apiLimiter = rateLimit({
|
|
287
|
-
windowMs:
|
|
288
|
-
skip:
|
|
289
|
-
handler: (
|
|
300
|
+
windowMs: rateLimitWindowMs, max: rl.maxRequests || 60,
|
|
301
|
+
skip: isExemptPath,
|
|
302
|
+
handler: (_req, res) => {
|
|
303
|
+
res.setHeader('Retry-After', retryAfterSeconds);
|
|
304
|
+
res.status(429).json({ error: 'Too many requests' });
|
|
305
|
+
},
|
|
290
306
|
});
|
|
291
307
|
const chatLimiter = rateLimit({
|
|
292
308
|
windowMs: rl.chat?.windowMs || 60000, max: rl.chat?.maxRequests || 10,
|
|
293
|
-
handler: (
|
|
309
|
+
handler: (_req, res) => {
|
|
310
|
+
res.setHeader('Retry-After', Math.ceil((rl.chat?.windowMs || 60000) / 1000));
|
|
311
|
+
res.status(429).json({ error: 'Chat rate limit exceeded' });
|
|
312
|
+
},
|
|
294
313
|
});
|
|
295
314
|
app.use('/api', (req, res, next) => { if (req.headers.authorization) return next(); apiLimiter(req, res, next); });
|
|
296
315
|
app.use('/api', (req, res, next) => {
|
|
@@ -401,12 +420,25 @@ function createServer(distPath, config, serverConfig = {}) {
|
|
|
401
420
|
app.use(express.json());
|
|
402
421
|
if (!apiOnly && distPath) {
|
|
403
422
|
app.use(express.static(distPath, { index: false }));
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
423
|
+
|
|
424
|
+
// Pre-build the index.html template once at startup instead of reading on every request
|
|
425
|
+
const indexPath = path.join(distPath, 'index.html');
|
|
426
|
+
let indexTemplate = null;
|
|
427
|
+
try {
|
|
428
|
+
indexTemplate = fs.readFileSync(indexPath, 'utf8');
|
|
429
|
+
} catch (err) {
|
|
430
|
+
console.error(`[orbitchat] Failed to read ${indexPath}:`, err.message);
|
|
431
|
+
}
|
|
432
|
+
|
|
433
|
+
// Escape </script> sequences in JSON to prevent XSS when injecting into HTML
|
|
434
|
+
const safeConfigJson = JSON.stringify(config).replace(/<\/(script)/gi, '<\\/$1');
|
|
435
|
+
|
|
436
|
+
// Pre-compute the transformed HTML
|
|
437
|
+
let cachedHtml = null;
|
|
438
|
+
if (indexTemplate) {
|
|
439
|
+
let content = indexTemplate;
|
|
408
440
|
content = content.replace(/<script id="orbit-chat-config" type="application\/json">[\s\S]*?<\/script>/, '<!-- Config injected -->');
|
|
409
|
-
const configScript = `<script>window.ORBIT_CHAT_CONFIG = ${
|
|
441
|
+
const configScript = `<script>window.ORBIT_CHAT_CONFIG = ${safeConfigJson};</script>`;
|
|
410
442
|
content = content.replace(/<head>/i, '<head>\n ' + configScript);
|
|
411
443
|
if (config.application?.name) content = content.replace(/<title>.*?<\/title>/i, `<title>${config.application.name}</title>`);
|
|
412
444
|
if (config.application?.favicon?.trim()) {
|
|
@@ -417,8 +449,14 @@ function createServer(distPath, config, serverConfig = {}) {
|
|
|
417
449
|
content = content.replace(/<head>/i, `<head>\n ${iconTag}`);
|
|
418
450
|
}
|
|
419
451
|
}
|
|
452
|
+
cachedHtml = content;
|
|
453
|
+
}
|
|
454
|
+
|
|
455
|
+
app.get(/(.*)/, (req, res) => {
|
|
456
|
+
if (req.path.startsWith('/api/')) return res.status(404).json({ error: 'Not found' });
|
|
457
|
+
if (!cachedHtml) return res.status(500).send('index.html not found');
|
|
420
458
|
res.setHeader('Content-Type', 'text/html');
|
|
421
|
-
res.send(
|
|
459
|
+
res.send(cachedHtml);
|
|
422
460
|
});
|
|
423
461
|
}
|
|
424
462
|
return app;
|
|
@@ -478,7 +516,15 @@ function main() {
|
|
|
478
516
|
|
|
479
517
|
const server = app.listen(serverConfig.port, serverConfig.host, () => {
|
|
480
518
|
console.debug(`🚀 ORBIT Chat is running at http://${serverConfig.host}:${serverConfig.port}`);
|
|
481
|
-
if (serverConfig.open)
|
|
519
|
+
if (serverConfig.open) {
|
|
520
|
+
const url = `http://${serverConfig.host}:${serverConfig.port}`;
|
|
521
|
+
try {
|
|
522
|
+
// Use execFileSync to avoid shell injection — arguments are passed directly
|
|
523
|
+
execFileSync('open', [url], { stdio: 'ignore' });
|
|
524
|
+
} catch {
|
|
525
|
+
console.debug(`Open your browser at ${url}`);
|
|
526
|
+
}
|
|
527
|
+
}
|
|
482
528
|
});
|
|
483
529
|
// http-proxy may register multiple close listeners when routing across many adapters.
|
|
484
530
|
// Raise the listener cap to avoid noisy false-positive MaxListeners warnings.
|