cc-viewer 1.7.12 → 1.7.13
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/dist/assets/App-CtPaGTFc.js +2 -0
- package/dist/assets/{MdxEditorPanel-DjSuLHCK.js → MdxEditorPanel-CdZjsgUe.js} +1 -1
- package/dist/assets/{Mobile-CHdZ2iSv.js → Mobile-BV5o9yFd.js} +1 -1
- package/dist/assets/{ProxyStatsModal-B6xp1knz.js → ProxyStatsModal-DGMd41pC.js} +1 -1
- package/dist/assets/index-DSTQIMmZ.js +2 -0
- package/dist/assets/seqResourceLoaders-DGyoo_5i.js +2 -0
- package/dist/assets/{seqResourceLoaders-0RXZfUKp.css → seqResourceLoaders-pBUn3c_a.css} +1 -1
- package/dist/index.html +1 -1
- package/package.json +1 -1
- package/server/lib/log-management.js +57 -0
- package/server/lib/v2/adapter.js +9 -110
- package/server/lib/v2/convert-manager.js +7 -1
- package/server/lib/v2/migrate-prompt.js +39 -1
- package/server/lib/v2/session-list.js +276 -0
- package/server/lib/v2/session-select.js +4 -4
- package/server/routes/logs.js +50 -8
- package/dist/assets/App-BKG6t0Yf.js +0 -2
- package/dist/assets/index-QCUTFwkw.js +0 -2
- package/dist/assets/seqResourceLoaders-DQIaFrCX.js +0 -2
package/server/routes/logs.js
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
// Local log management routes (moved verbatim from server.js handleRequest).
|
|
2
|
-
import { existsSync, realpathSync, statSync, createReadStream, mkdtempSync, rmSync } from 'node:fs';
|
|
2
|
+
import { existsSync, realpathSync, statSync, createReadStream, mkdtempSync, rmSync, readdirSync } from 'node:fs';
|
|
3
3
|
import { join, basename } from 'node:path';
|
|
4
4
|
import { tmpdir } from 'node:os';
|
|
5
5
|
import AdmZip from 'adm-zip';
|
|
6
6
|
import { LOG_DIR } from '../../findcc.js';
|
|
7
7
|
import { _projectName, _v2Writer } from '../interceptor.js';
|
|
8
|
-
import { listV2Logs, listLocalLogs, countListedV1Files, deleteLogFiles, validateLogPath } from '../lib/log-management.js';
|
|
8
|
+
import { listV2Logs, listV2LogsPage, listLocalLogs, countListedV1Files, deleteLogFiles, validateLogPath } from '../lib/log-management.js';
|
|
9
9
|
import { countLogEntries, streamRawEntriesAsync, readTailEntries } from '../lib/log-stream.js';
|
|
10
10
|
import { sseHead, sseWrite, wireEnd } from '../lib/wire-compress.js';
|
|
11
|
-
import { dirSizeSync } from '../lib/v2/layout.js';
|
|
11
|
+
import { dirSizeSync, sanitizePathComponent } from '../lib/v2/layout.js';
|
|
12
12
|
import { extractV2Zip } from '../lib/log-zip.js';
|
|
13
13
|
import { startConvert, stopConvert, convertStatus } from '../lib/v2/convert-manager.js';
|
|
14
14
|
import { migrationStatus } from '../lib/v2/migrate-prompt.js';
|
|
@@ -32,18 +32,60 @@ async function localLogs(req, res, parsedUrl, isLocal, deps) {
|
|
|
32
32
|
res.end(JSON.stringify(v1));
|
|
33
33
|
return;
|
|
34
34
|
}
|
|
35
|
-
|
|
35
|
+
// Server-side pagination (2026-07-31): ?page=&pageSize= switches the v2
|
|
36
|
+
// list to a per-project page — only the requested page's sessions are
|
|
37
|
+
// summarized. Response shape becomes {items, total, page, pageSize} plus
|
|
38
|
+
// the same _-prefixed side signals below. No params = legacy grouped shape.
|
|
39
|
+
const pageParam = parsedUrl?.searchParams?.get('page');
|
|
40
|
+
let payload;
|
|
41
|
+
if (pageParam != null) {
|
|
42
|
+
// Optional ?project= views another project's logs (the modal's project
|
|
43
|
+
// switcher). Strict-compare against sanitizePathComponent (same pattern
|
|
44
|
+
// as parseV2Ref) so '..'/ separators can't traverse out of LOG_DIR;
|
|
45
|
+
// absent/empty falls back to the active project.
|
|
46
|
+
const rawProject = parsedUrl.searchParams.get('project');
|
|
47
|
+
let target = _projectName;
|
|
48
|
+
if (rawProject) {
|
|
49
|
+
if (rawProject !== sanitizePathComponent(rawProject)) {
|
|
50
|
+
res.writeHead(400, { 'Content-Type': 'application/json' });
|
|
51
|
+
res.end(JSON.stringify({ error: 'Invalid project name' }));
|
|
52
|
+
return;
|
|
53
|
+
}
|
|
54
|
+
target = rawProject;
|
|
55
|
+
}
|
|
56
|
+
const page = Math.max(1, parseInt(pageParam, 10) || 1);
|
|
57
|
+
const pageSize = Math.min(200, Math.max(1, parseInt(parsedUrl.searchParams.get('pageSize'), 10) || 50));
|
|
58
|
+
payload = listV2LogsPage(LOG_DIR, target, { page, pageSize });
|
|
59
|
+
// _currentProject must stay the ACTIVE project (_projectName), not the
|
|
60
|
+
// viewed one (listV2LogsPage sets it to `target`): the frontend's global
|
|
61
|
+
// currentProject drives the sidebar / migration counts / v1 banner, and
|
|
62
|
+
// the viewed project is carried separately by its own logViewProject
|
|
63
|
+
// state. Overwriting it here would let "viewing project A" leak into
|
|
64
|
+
// global state. _viewedProject tells the client which project this page
|
|
65
|
+
// actually lists.
|
|
66
|
+
payload._currentProject = _projectName || '';
|
|
67
|
+
payload._viewedProject = target || '';
|
|
68
|
+
// Project list for the modal's switcher dropdown. LOG_DIR's top level
|
|
69
|
+
// holds one dir per project (recycle dirs live INSIDE each project, so
|
|
70
|
+
// nothing to filter here) — but skip dot-prefixed hidden dirs.
|
|
71
|
+
try {
|
|
72
|
+
payload._allProjects = readdirSync(LOG_DIR, { withFileTypes: true })
|
|
73
|
+
.filter(e => e.isDirectory() && !e.name.startsWith('.')).map(e => e.name).sort();
|
|
74
|
+
} catch { payload._allProjects = []; }
|
|
75
|
+
} else {
|
|
76
|
+
payload = listV2Logs(LOG_DIR, _projectName);
|
|
77
|
+
}
|
|
36
78
|
// Legacy v1 files are not in this list — surface two distinct signals:
|
|
37
79
|
// - _v1FileCount: v1 files ON DISK (gates the v1-view entry link; the
|
|
38
80
|
// converter never deletes sources, so this outlives a finished migration)
|
|
39
81
|
// - _unmigratedV1Count/Bytes: files still AWAITING migration (gates the
|
|
40
82
|
// migrate button + hint inside the v1 view and the startup prompt)
|
|
41
83
|
const mig = migrationStatus(LOG_DIR, _projectName || '');
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
84
|
+
payload._unmigratedV1Count = mig.files;
|
|
85
|
+
payload._unmigratedV1Bytes = mig.totalBytes;
|
|
86
|
+
payload._v1FileCount = _projectName ? countListedV1Files(join(LOG_DIR, _projectName)) : 0;
|
|
45
87
|
res.writeHead(200, { 'Content-Type': 'application/json' });
|
|
46
|
-
res.end(JSON.stringify(
|
|
88
|
+
res.end(JSON.stringify(payload));
|
|
47
89
|
} catch (err) {
|
|
48
90
|
res.writeHead(500, { 'Content-Type': 'application/json' });
|
|
49
91
|
res.end(JSON.stringify({ error: err.message }));
|