@tom2012/cc-web 1.5.10

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.
Files changed (59) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +339 -0
  3. package/backend/dist/auth.d.ts +15 -0
  4. package/backend/dist/auth.d.ts.map +1 -0
  5. package/backend/dist/auth.js +92 -0
  6. package/backend/dist/auth.js.map +1 -0
  7. package/backend/dist/config.d.ts +33 -0
  8. package/backend/dist/config.d.ts.map +1 -0
  9. package/backend/dist/config.js +155 -0
  10. package/backend/dist/config.js.map +1 -0
  11. package/backend/dist/index.d.ts +3 -0
  12. package/backend/dist/index.d.ts.map +1 -0
  13. package/backend/dist/index.js +499 -0
  14. package/backend/dist/index.js.map +1 -0
  15. package/backend/dist/routes/auth.d.ts +3 -0
  16. package/backend/dist/routes/auth.d.ts.map +1 -0
  17. package/backend/dist/routes/auth.js +108 -0
  18. package/backend/dist/routes/auth.js.map +1 -0
  19. package/backend/dist/routes/filesystem.d.ts +3 -0
  20. package/backend/dist/routes/filesystem.d.ts.map +1 -0
  21. package/backend/dist/routes/filesystem.js +243 -0
  22. package/backend/dist/routes/filesystem.js.map +1 -0
  23. package/backend/dist/routes/projects.d.ts +3 -0
  24. package/backend/dist/routes/projects.d.ts.map +1 -0
  25. package/backend/dist/routes/projects.js +235 -0
  26. package/backend/dist/routes/projects.js.map +1 -0
  27. package/backend/dist/routes/shortcuts.d.ts +3 -0
  28. package/backend/dist/routes/shortcuts.d.ts.map +1 -0
  29. package/backend/dist/routes/shortcuts.js +88 -0
  30. package/backend/dist/routes/shortcuts.js.map +1 -0
  31. package/backend/dist/routes/update.d.ts +3 -0
  32. package/backend/dist/routes/update.d.ts.map +1 -0
  33. package/backend/dist/routes/update.js +104 -0
  34. package/backend/dist/routes/update.js.map +1 -0
  35. package/backend/dist/session-manager.d.ts +47 -0
  36. package/backend/dist/session-manager.d.ts.map +1 -0
  37. package/backend/dist/session-manager.js +345 -0
  38. package/backend/dist/session-manager.js.map +1 -0
  39. package/backend/dist/terminal-manager.d.ts +27 -0
  40. package/backend/dist/terminal-manager.d.ts.map +1 -0
  41. package/backend/dist/terminal-manager.js +211 -0
  42. package/backend/dist/terminal-manager.js.map +1 -0
  43. package/backend/dist/types.d.ts +17 -0
  44. package/backend/dist/types.d.ts.map +1 -0
  45. package/backend/dist/types.js +3 -0
  46. package/backend/dist/types.js.map +1 -0
  47. package/backend/dist/usage-terminal.d.ts +18 -0
  48. package/backend/dist/usage-terminal.d.ts.map +1 -0
  49. package/backend/dist/usage-terminal.js +189 -0
  50. package/backend/dist/usage-terminal.js.map +1 -0
  51. package/backend/package-lock.json +1965 -0
  52. package/backend/package.json +31 -0
  53. package/bin/ccweb.js +478 -0
  54. package/electron/dist/main.js +455 -0
  55. package/frontend/dist/assets/index-CQjbS4zv.css +32 -0
  56. package/frontend/dist/assets/index-CtyR65A4.js +434 -0
  57. package/frontend/dist/index.html +14 -0
  58. package/frontend/dist/terminal.svg +4 -0
  59. package/package.json +88 -0
@@ -0,0 +1 @@
1
+ {"version":3,"file":"config.js","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,3 @@
1
+ declare const app: import("express-serve-static-core").Express;
2
+ export default app;
3
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AA8NA,QAAA,MAAM,GAAG,6CAAY,CAAC;AA+PtB,eAAe,GAAG,CAAC"}
@@ -0,0 +1,499 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || (function () {
19
+ var ownKeys = function(o) {
20
+ ownKeys = Object.getOwnPropertyNames || function (o) {
21
+ var ar = [];
22
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
+ return ar;
24
+ };
25
+ return ownKeys(o);
26
+ };
27
+ return function (mod) {
28
+ if (mod && mod.__esModule) return mod;
29
+ var result = {};
30
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
+ __setModuleDefault(result, mod);
32
+ return result;
33
+ };
34
+ })();
35
+ var __importDefault = (this && this.__importDefault) || function (mod) {
36
+ return (mod && mod.__esModule) ? mod : { "default": mod };
37
+ };
38
+ Object.defineProperty(exports, "__esModule", { value: true });
39
+ const express_1 = __importDefault(require("express"));
40
+ const cors_1 = __importDefault(require("cors"));
41
+ const http = __importStar(require("http"));
42
+ const path = __importStar(require("path"));
43
+ const fs = __importStar(require("fs"));
44
+ const WebSocket = __importStar(require("ws"));
45
+ const config_1 = require("./config");
46
+ const auth_1 = require("./auth");
47
+ const terminal_manager_1 = require("./terminal-manager");
48
+ const uuid_1 = require("uuid");
49
+ const auth_2 = __importDefault(require("./routes/auth"));
50
+ const projects_1 = __importDefault(require("./routes/projects"));
51
+ const filesystem_1 = __importDefault(require("./routes/filesystem"));
52
+ const shortcuts_1 = __importDefault(require("./routes/shortcuts"));
53
+ const update_1 = __importDefault(require("./routes/update"));
54
+ (0, config_1.initDataDirs)();
55
+ migrateProjectConfigs();
56
+ seedPresetShortcuts();
57
+ /** Backfill .ccweb/project.json for projects created before this feature existed */
58
+ function migrateProjectConfigs() {
59
+ for (const project of (0, config_1.getProjects)()) {
60
+ try {
61
+ if (!(0, config_1.readProjectConfig)(project.folderPath)) {
62
+ (0, config_1.writeProjectConfig)(project.folderPath, project);
63
+ console.log(`[Migration] Wrote .ccweb/project.json for "${project.name}"`);
64
+ }
65
+ }
66
+ catch (err) {
67
+ console.error(`[Migration] Failed for "${project.name}":`, err);
68
+ }
69
+ }
70
+ }
71
+ function seedPresetShortcuts() {
72
+ let shortcuts = (0, config_1.getGlobalShortcuts)();
73
+ let changed = false;
74
+ // 1. Seed: 图关系笔记本操作规范
75
+ const NOTEBOOK_LABEL = '[Built-in] 图关系笔记本操作规范';
76
+ let notebookGuide = shortcuts.find((s) => s.label === NOTEBOOK_LABEL);
77
+ if (!notebookGuide) {
78
+ notebookGuide = {
79
+ id: (0, uuid_1.v4)(), label: NOTEBOOK_LABEL,
80
+ command: `你现在可以使用「图关系笔记本」来管理结构化知识。笔记本以纯文件形式存储在项目目录的 .notebook/ 文件夹中,你直接读写这些文件即可操作。
81
+
82
+ ## 重要:请立即将以下规范固化到本项目的记忆中
83
+
84
+ 请你现在就使用 Claude Code 的记忆系统(写入 memory 文件),将下面的「图关系笔记本规范」完整保存为一条项目记忆。这样即使跨会话,你也不会遗忘这些规则。保存后请确认。
85
+
86
+ ---
87
+
88
+ ## 图关系笔记本规范
89
+
90
+ ### 文件结构
91
+
92
+ \`\`\`
93
+ .notebook/
94
+ ├── graph.yaml ← 唯一的元数据文件:页面注册表 + 有向依赖关系
95
+ └── pages/
96
+ └── *.md ← 每个页面一个 Markdown 文件
97
+ \`\`\`
98
+
99
+ ### graph.yaml 格式
100
+
101
+ \`\`\`yaml
102
+ # 图关系笔记本元数据
103
+ pages:
104
+ - id: <kebab-case 唯一标识>
105
+ title: <页面标题>
106
+ file: <文件名.md>
107
+ parent: <父页面id | null> # 层级结构(类似文件夹组织)
108
+
109
+ relations:
110
+ # from → to 表示 to 页面的内容依赖于 from 页面
111
+ - from: <源页面id>
112
+ to: <目标页面id>
113
+ label: <可选标签>
114
+ \`\`\`
115
+
116
+ ### 操作规则(必须严格遵守)
117
+
118
+ 1. **新建页面**:
119
+ - 在 .notebook/pages/ 下创建 .md 文件
120
+ - 在 graph.yaml 的 pages 列表中添加对应条目
121
+ - 两步必须同时完成
122
+
123
+ 2. **删除页面**:
124
+ - 删除 .md 文件
125
+ - 从 graph.yaml 的 pages 中移除该条目
126
+ - 从 graph.yaml 的 relations 中移除所有涉及该页面的关系(from 或 to)
127
+ - 三步必须同时完成
128
+
129
+ 3. **新建关系**:在 graph.yaml 的 relations 中添加条目
130
+ - from → to 语义:to 页面的内容依赖于 from 页面
131
+ - 不允许自环(from 不能等于 to)
132
+
133
+ 4. **删除关系**:从 graph.yaml 的 relations 中移除对应条目
134
+
135
+ 5. **修改页面前(关键!)**:
136
+ - 先读取 graph.yaml
137
+ - 找到该页面作为 to 的所有 relations(即它的直接上游依赖)
138
+ - 阅读所有上游页面的内容
139
+ - 然后再修改当前页面,确保与上游一致
140
+
141
+ 6. **查询上游依赖**:从 graph.yaml 的 relations 中,沿 from 方向递归遍历
142
+ 7. **查询下游被依赖**:从 graph.yaml 的 relations 中,沿 to 方向递归遍历
143
+
144
+ ### 约束
145
+ - graph.yaml 是唯一的元数据源,不要在其他地方维护页面列表或关系
146
+ - 页面 id 使用 kebab-case(如 master-outline, section1-outline)
147
+ - 每次增删页面文件都**必须**同步更新 graph.yaml
148
+ - 如果 .notebook/ 目录不存在,先创建 .notebook/pages/ 目录和空的 graph.yaml(内容为 pages: []\\nrelations: [])`,
149
+ };
150
+ shortcuts.push(notebookGuide);
151
+ changed = true;
152
+ console.log('[Seed] Created preset shortcut: 图关系笔记本操作规范');
153
+ }
154
+ // 2. Seed: 小说模式 (inherits 操作规范)
155
+ const NOVEL_LABEL = '[Built-in] 小说模式';
156
+ if (!shortcuts.some((s) => s.label === NOVEL_LABEL)) {
157
+ shortcuts.push({
158
+ id: (0, uuid_1.v4)(), label: NOVEL_LABEL,
159
+ parentId: notebookGuide.id,
160
+ command: `请进入「小说模式」。你已经通过继承收到了图关系笔记本的操作规范(如果还没有写入记忆,请先完成),现在按照以下小说专用规则操作 .notebook/。
161
+
162
+ ## 第一步:初始化
163
+
164
+ 1. 读取当前项目目录下的 .notebook/graph.yaml
165
+ 2. 如果 .notebook/ 不存在,按操作规范创建目录和空 graph.yaml
166
+ 3. 如果已有页面,读取现有结构并跳过已存在的内容
167
+ 4. 按下方模板创建缺失的页面文件和关系
168
+
169
+ ## 页面模板
170
+
171
+ 按操作规范,在 .notebook/pages/ 下创建 .md 文件并同步注册到 graph.yaml:
172
+
173
+ ### 根页面(无上游依赖)
174
+ | id | 文件 | 内容 |
175
+ |----|------|------|
176
+ | master-outline | 全文总纲.md | 世界观、整体框架、故事简介、Section 划分、主要人物表 |
177
+ | writing-style | 文字风格.md | 语言风格定义、叙事视角、节奏要求、禁忌事项 |
178
+ | good-example-1 | 好的示例-1.md | 一段优秀的小说片段(按需创建更多:good-example-2, ...) |
179
+ | bad-example-1 | 坏的示例-1.md | 一段需要避免的写法(按需创建更多:bad-example-2, ...) |
180
+
181
+ ### 中间页面(按需扩展)
182
+ | id 模式 | 文件模式 | 内容 |
183
+ |---------|----------|------|
184
+ | sectionN-outline | SectionN-总纲.md | 该 Section 的 Subsection 划分、涉及人物、情节走向 |
185
+ | sectionN-subM-outline | SectionN-SubM-总纲.md | 该 Subsection 下每章大纲、人物、关键事件 |
186
+ | sectionN-subM-chK | SectionN-SubM-ChK.md | 章节正文 |
187
+
188
+ N/M/K 为数字,按实际章节递增。
189
+
190
+ ## 有向依赖关系规则
191
+
192
+ 在 graph.yaml 的 relations 中严格按以下模式建立(from → to = to 依赖 from):
193
+
194
+ \`\`\`
195
+ 全文总纲 → 每个 Section 总纲
196
+ 好的示例(每个) → 文字风格
197
+ 坏的示例(每个) → 文字风格
198
+ 文字风格 → 每个章节正文
199
+ Section 总纲 → 其所有 Subsection 总纲
200
+ Subsection 总纲 → 其所有章节正文
201
+ \`\`\`
202
+
203
+ 示例 graph.yaml(1 个 Section、1 个 Subsection、1 章):
204
+
205
+ \`\`\`yaml
206
+ pages:
207
+ - { id: master-outline, title: 全文总纲, file: 全文总纲.md, parent: null }
208
+ - { id: writing-style, title: 文字风格, file: 文字风格.md, parent: null }
209
+ - { id: good-example-1, title: 好的示例-1, file: 好的示例-1.md, parent: null }
210
+ - { id: bad-example-1, title: 坏的示例-1, file: 坏的示例-1.md, parent: null }
211
+ - { id: section1-outline, title: Section1 总纲, file: Section1-总纲.md, parent: master-outline }
212
+ - { id: section1-sub1-outline, title: Section1-Sub1 总纲, file: Section1-Sub1-总纲.md, parent: section1-outline }
213
+ - { id: section1-sub1-ch1, title: Section1-Sub1-Ch1, file: Section1-Sub1-Ch1.md, parent: section1-sub1-outline }
214
+
215
+ relations:
216
+ - { from: master-outline, to: section1-outline }
217
+ - { from: good-example-1, to: writing-style }
218
+ - { from: bad-example-1, to: writing-style }
219
+ - { from: writing-style, to: section1-sub1-ch1 }
220
+ - { from: section1-outline, to: section1-sub1-outline }
221
+ - { from: section1-sub1-outline, to: section1-sub1-ch1 }
222
+ \`\`\`
223
+
224
+ ## 工作流程
225
+
226
+ ### 创建/修改任何页面前
227
+ 按操作规范:先读 graph.yaml → 找到该页面的所有上游(from→该页面的 relations)→ 读取上游页面内容 → 再编写当前页面。
228
+
229
+ ### 正向更新(我说「更新」时)
230
+ 1. 读 graph.yaml 构建完整依赖图
231
+ 2. 找到所有根节点(没有任何 relation 以它为 to 的页面)
232
+ 3. 按拓扑序逐层向下:先更新父页面,再更新子页面
233
+ 4. 每更新一个页面前,读取其所有直接上游页面的最新内容
234
+ 5. 确保父子之间逻辑一致、不冲突
235
+
236
+ ### 反向更新(我说「根据 X 反向更新」时)
237
+ 1. 从我指定的页面出发
238
+ 2. 读 graph.yaml 找到它的直接上游页面
239
+ 3. 根据当前页面内容修改上游页面使之一致
240
+ 4. 对上游页面重复此过程,迭代直到所有祖先更新完毕
241
+
242
+ ### 新增 Section/Subsection/章节
243
+ 1. 创建对应 .md 文件
244
+ 2. 在 graph.yaml 的 pages 中添加条目(parent 设为其层级父页面 id)
245
+ 3. 在 graph.yaml 的 relations 中按上述规则添加所有依赖边
246
+ 4. 读取上游页面内容后再编写新页面
247
+
248
+ 请确认你理解了小说模式规则,然后开始初始化 .notebook/。`,
249
+ });
250
+ changed = true;
251
+ console.log('[Seed] Created preset shortcut: 小说模式');
252
+ }
253
+ if (changed)
254
+ (0, config_1.saveGlobalShortcuts)(shortcuts);
255
+ }
256
+ const app = (0, express_1.default)();
257
+ const PORT = parseInt(process.env.CCWEB_PORT || '3001', 10);
258
+ // Security headers
259
+ app.use((_req, res, next) => {
260
+ res.setHeader('X-Content-Type-Options', 'nosniff');
261
+ res.setHeader('X-Frame-Options', 'DENY');
262
+ res.setHeader('X-XSS-Protection', '1; mode=block');
263
+ res.setHeader('Content-Security-Policy', "default-src 'self'; script-src 'self' 'unsafe-inline' 'unsafe-eval'; style-src 'self' 'unsafe-inline'; img-src 'self' data:; connect-src 'self' ws: wss:; font-src 'self' data:");
264
+ next();
265
+ });
266
+ app.use((0, cors_1.default)({
267
+ origin: (origin, callback) => {
268
+ // Allow requests with no origin (same-origin, curl, Electron, etc.)
269
+ if (!origin)
270
+ return callback(null, true);
271
+ // Allow localhost origins (any port) for dev and Electron
272
+ try {
273
+ const u = new URL(origin);
274
+ if (u.hostname === 'localhost' || u.hostname === '127.0.0.1' || u.hostname === '::1') {
275
+ return callback(null, true);
276
+ }
277
+ }
278
+ catch { /* invalid origin */ }
279
+ callback(new Error('Not allowed by CORS'));
280
+ },
281
+ credentials: true,
282
+ }));
283
+ app.use(express_1.default.json());
284
+ app.use('/api/auth', auth_2.default);
285
+ app.use('/api/projects', auth_1.authMiddleware, projects_1.default);
286
+ app.use('/api/filesystem', auth_1.authMiddleware, filesystem_1.default);
287
+ app.use('/api/shortcuts', auth_1.authMiddleware, shortcuts_1.default);
288
+ app.use('/api/update', auth_1.authMiddleware, update_1.default);
289
+ app.get('/health', (_req, res) => res.json({ status: 'ok' }));
290
+ // Serve built frontend (production / Electron)
291
+ const frontendDist = path.join(__dirname, '../../frontend/dist');
292
+ if (fs.existsSync(frontendDist)) {
293
+ app.use(express_1.default.static(frontendDist));
294
+ app.get('*', (_req, res, next) => {
295
+ if (_req.path.startsWith('/api/') || _req.path.startsWith('/ws/'))
296
+ return next();
297
+ res.sendFile(path.join(frontendDist, 'index.html'));
298
+ });
299
+ }
300
+ const server = http.createServer(app);
301
+ const wss = new WebSocket.Server({ noServer: true });
302
+ // projectId → connected WebSocket clients (all in terminal mode)
303
+ const projectClients = new Map();
304
+ function broadcast(projectId, rawData) {
305
+ const clients = projectClients.get(projectId);
306
+ if (!clients)
307
+ return;
308
+ const payload = JSON.stringify({ type: 'terminal_data', data: rawData });
309
+ for (const client of clients) {
310
+ if (client.readyState === WebSocket.WebSocket.OPEN)
311
+ client.send(payload);
312
+ }
313
+ }
314
+ function isLocalWs(req) {
315
+ const ip = req.socket.remoteAddress || '';
316
+ return ip === '127.0.0.1' || ip === '::1' || ip === '::ffff:127.0.0.1';
317
+ }
318
+ wss.on('connection', (ws, req) => {
319
+ const parsedUrl = new URL(req.url || '', 'http://localhost');
320
+ const match = parsedUrl.pathname?.match(/^\/ws\/projects\/([^/]+)$/);
321
+ if (!match) {
322
+ ws.close(1008, 'Invalid path');
323
+ return;
324
+ }
325
+ const projectId = match[1];
326
+ const localConnection = isLocalWs(req);
327
+ let authenticated = localConnection; // localhost = pre-authenticated
328
+ const authTimeout = localConnection ? null : setTimeout(() => {
329
+ if (!authenticated)
330
+ ws.close(1008, 'Authentication timeout');
331
+ }, 10000);
332
+ // For local connections, set up project immediately
333
+ if (localConnection) {
334
+ const project = (0, config_1.getProject)(projectId);
335
+ if (!project) {
336
+ ws.send(JSON.stringify({ type: 'error', message: 'Project not found' }));
337
+ ws.close(1008, 'Project not found');
338
+ return;
339
+ }
340
+ const broadcastFn = (data) => broadcast(projectId, data);
341
+ terminal_manager_1.terminalManager.getOrCreate(project, broadcastFn);
342
+ terminal_manager_1.terminalManager.updateBroadcast(projectId, broadcastFn);
343
+ ws.send(JSON.stringify({ type: 'connected', projectId }));
344
+ ws.send(JSON.stringify({ type: 'status', status: project.status }));
345
+ }
346
+ ws.on('message', (rawMsg) => {
347
+ try {
348
+ let parsed;
349
+ try {
350
+ parsed = JSON.parse(rawMsg.toString());
351
+ }
352
+ catch {
353
+ return;
354
+ }
355
+ // ── Auth handshake (skipped for localhost) ─────────────────────────────────
356
+ if (!authenticated) {
357
+ if (parsed.type !== 'auth' || !parsed.token) {
358
+ ws.close(1008, 'Authentication required');
359
+ return;
360
+ }
361
+ if (!(0, auth_1.verifyToken)(parsed.token)) {
362
+ ws.close(1008, 'Invalid token');
363
+ return;
364
+ }
365
+ if (authTimeout)
366
+ clearTimeout(authTimeout);
367
+ authenticated = true;
368
+ const project = (0, config_1.getProject)(projectId);
369
+ if (!project) {
370
+ ws.send(JSON.stringify({ type: 'error', message: 'Project not found' }));
371
+ ws.close(1008, 'Project not found');
372
+ return;
373
+ }
374
+ const broadcastFn = (data) => broadcast(projectId, data);
375
+ terminal_manager_1.terminalManager.getOrCreate(project, broadcastFn);
376
+ terminal_manager_1.terminalManager.updateBroadcast(projectId, broadcastFn);
377
+ ws.send(JSON.stringify({ type: 'connected', projectId }));
378
+ ws.send(JSON.stringify({ type: 'status', status: project.status }));
379
+ return;
380
+ }
381
+ // For local connections, skip the auth message if sent anyway
382
+ if (parsed.type === 'auth')
383
+ return;
384
+ // ── Authenticated messages ────────────────────────────────────────────────
385
+ switch (parsed.type) {
386
+ case 'terminal_subscribe':
387
+ // Resize PTY to browser dimensions before replaying scrollback
388
+ if (typeof parsed.cols === 'number' && typeof parsed.rows === 'number') {
389
+ terminal_manager_1.terminalManager.resize(projectId, parsed.cols, parsed.rows);
390
+ }
391
+ // Replay history so reconnecting clients see prior output
392
+ {
393
+ const scrollback = terminal_manager_1.terminalManager.getScrollback(projectId);
394
+ if (scrollback)
395
+ ws.send(JSON.stringify({ type: 'terminal_data', data: scrollback }));
396
+ }
397
+ // Register as a live client
398
+ if (!projectClients.has(projectId))
399
+ projectClients.set(projectId, new Set());
400
+ projectClients.get(projectId).add(ws);
401
+ ws.send(JSON.stringify({ type: 'terminal_subscribed' }));
402
+ break;
403
+ case 'terminal_input':
404
+ if (typeof parsed.data === 'string')
405
+ terminal_manager_1.terminalManager.writeRaw(projectId, parsed.data);
406
+ break;
407
+ case 'terminal_resize':
408
+ if (typeof parsed.cols === 'number' && typeof parsed.rows === 'number') {
409
+ terminal_manager_1.terminalManager.resize(projectId, parsed.cols, parsed.rows);
410
+ }
411
+ break;
412
+ }
413
+ }
414
+ catch (err) {
415
+ console.error(`[WS] Message handling error for project ${projectId}:`, err);
416
+ try {
417
+ ws.send(JSON.stringify({ type: 'error', message: 'Internal server error' }));
418
+ }
419
+ catch { /**/ }
420
+ }
421
+ });
422
+ ws.on('close', () => {
423
+ const clients = projectClients.get(projectId);
424
+ if (clients) {
425
+ clients.delete(ws);
426
+ if (clients.size === 0)
427
+ projectClients.delete(projectId);
428
+ }
429
+ });
430
+ ws.on('error', (err) => console.error(`[WS] Error for project ${projectId}:`, err));
431
+ });
432
+ server.on('upgrade', (req, socket, head) => {
433
+ const pathname = new URL(req.url || '', 'http://localhost').pathname;
434
+ if (!pathname.startsWith('/ws/')) {
435
+ socket.destroy();
436
+ return;
437
+ }
438
+ // Validate WebSocket Origin — only allow localhost origins
439
+ const origin = req.headers.origin;
440
+ if (origin) {
441
+ try {
442
+ const u = new URL(origin);
443
+ if (u.hostname !== 'localhost' && u.hostname !== '127.0.0.1' && u.hostname !== '::1') {
444
+ socket.write('HTTP/1.1 403 Forbidden\r\n\r\n');
445
+ socket.destroy();
446
+ return;
447
+ }
448
+ }
449
+ catch {
450
+ socket.write('HTTP/1.1 403 Forbidden\r\n\r\n');
451
+ socket.destroy();
452
+ return;
453
+ }
454
+ }
455
+ wss.handleUpgrade(req, socket, head, (ws) => wss.emit('connection', ws, req));
456
+ });
457
+ function tryListen(port, maxAttempts = 20) {
458
+ server.once('error', (err) => {
459
+ if (err.code === 'EADDRINUSE' && maxAttempts > 1) {
460
+ console.log(`[Server] Port ${port} in use, trying ${port + 1}...`);
461
+ tryListen(port + 1, maxAttempts - 1);
462
+ }
463
+ else {
464
+ console.error(`[Server] Failed to listen:`, err);
465
+ process.exit(1);
466
+ }
467
+ });
468
+ server.listen(port, () => {
469
+ console.log(`[Server] Running on http://localhost:${port}`);
470
+ // Notify parent (Electron) of the actual port via IPC
471
+ if (process.send) {
472
+ process.send({ type: 'server-port', port });
473
+ }
474
+ terminal_manager_1.terminalManager.resumeAll();
475
+ });
476
+ }
477
+ tryListen(PORT);
478
+ // Graceful shutdown
479
+ function shutdown() {
480
+ console.log('[Server] Shutting down...');
481
+ // Stop all terminals (kills PTY processes)
482
+ for (const project of (0, config_1.getProjects)()) {
483
+ if (terminal_manager_1.terminalManager.hasTerminal(project.id)) {
484
+ terminal_manager_1.terminalManager.stop(project.id);
485
+ }
486
+ }
487
+ // Close WebSocket connections
488
+ wss.clients.forEach((ws) => ws.close(1001, 'Server shutting down'));
489
+ server.close(() => {
490
+ console.log('[Server] Closed.');
491
+ process.exit(0);
492
+ });
493
+ // Force exit after 5s
494
+ setTimeout(() => process.exit(1), 5000).unref();
495
+ }
496
+ process.on('SIGTERM', shutdown);
497
+ process.on('SIGINT', shutdown);
498
+ exports.default = app;
499
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,3 @@
1
+ declare const router: import("express-serve-static-core").Router;
2
+ export default router;
3
+ //# sourceMappingURL=auth.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"auth.d.ts","sourceRoot":"","sources":["../../src/routes/auth.ts"],"names":[],"mappings":"AAMA,QAAA,MAAM,MAAM,4CAAW,CAAC;AA0ExB,eAAe,MAAM,CAAC"}
@@ -0,0 +1,108 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || (function () {
19
+ var ownKeys = function(o) {
20
+ ownKeys = Object.getOwnPropertyNames || function (o) {
21
+ var ar = [];
22
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
+ return ar;
24
+ };
25
+ return ownKeys(o);
26
+ };
27
+ return function (mod) {
28
+ if (mod && mod.__esModule) return mod;
29
+ var result = {};
30
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
+ __setModuleDefault(result, mod);
32
+ return result;
33
+ };
34
+ })();
35
+ Object.defineProperty(exports, "__esModule", { value: true });
36
+ const express_1 = require("express");
37
+ const bcrypt = __importStar(require("bcryptjs"));
38
+ const jwt = __importStar(require("jsonwebtoken"));
39
+ const config_1 = require("../config");
40
+ const auth_1 = require("../auth");
41
+ const router = (0, express_1.Router)();
42
+ // Simple rate limiter for login attempts
43
+ const loginAttempts = new Map();
44
+ const MAX_LOGIN_ATTEMPTS = 5;
45
+ const RATE_LIMIT_WINDOW_MS = 15 * 60 * 1000; // 15 minutes
46
+ function isRateLimited(ip) {
47
+ const now = Date.now();
48
+ // Prune expired entries to prevent unbounded Map growth
49
+ for (const [key, val] of loginAttempts) {
50
+ if (now > val.resetAt)
51
+ loginAttempts.delete(key);
52
+ }
53
+ const entry = loginAttempts.get(ip);
54
+ if (!entry || now > entry.resetAt) {
55
+ loginAttempts.set(ip, { count: 1, resetAt: now + RATE_LIMIT_WINDOW_MS });
56
+ return false;
57
+ }
58
+ entry.count++;
59
+ return entry.count > MAX_LOGIN_ATTEMPTS;
60
+ }
61
+ // GET /api/auth/local-token — returns JWT without credentials (localhost only)
62
+ router.get('/local-token', (req, res) => {
63
+ if (!(0, auth_1.isLocalRequest)(req)) {
64
+ res.status(403).json({ error: 'Local access only' });
65
+ return;
66
+ }
67
+ try {
68
+ const token = (0, auth_1.generateLocalToken)();
69
+ res.json({ token });
70
+ }
71
+ catch {
72
+ res.status(500).json({ error: 'Server configuration error' });
73
+ }
74
+ });
75
+ router.post('/login', async (req, res) => {
76
+ const ip = req.ip || req.socket.remoteAddress || 'unknown';
77
+ if (isRateLimited(ip)) {
78
+ res.status(429).json({ error: 'Too many login attempts. Try again later.' });
79
+ return;
80
+ }
81
+ const { username, password } = req.body;
82
+ if (!username || !password) {
83
+ res.status(400).json({ error: 'Username and password are required' });
84
+ return;
85
+ }
86
+ let config;
87
+ try {
88
+ config = (0, config_1.getConfig)();
89
+ }
90
+ catch (err) {
91
+ res.status(500).json({ error: 'Server configuration error. Run npm run setup first.' });
92
+ return;
93
+ }
94
+ if (username !== config.username) {
95
+ res.status(401).json({ error: 'Invalid credentials' });
96
+ return;
97
+ }
98
+ const valid = await bcrypt.compare(password, config.passwordHash);
99
+ if (!valid) {
100
+ res.status(401).json({ error: 'Invalid credentials' });
101
+ return;
102
+ }
103
+ console.log(`[Auth] Successful login for user "${username}" from ${ip}`);
104
+ const token = jwt.sign({ username }, config.jwtSecret, { expiresIn: '30d' });
105
+ res.json({ token });
106
+ });
107
+ exports.default = router;
108
+ //# sourceMappingURL=auth.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"auth.js","sourceRoot":"","sources":["../../src/routes/auth.ts"],"names":[],"mappings":"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"}