@tom2012/cc-web 2026.4.19-r → 2026.4.19-t

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 (61) hide show
  1. package/README.md +1 -1
  2. package/backend/dist/adapters/claude-adapter.d.ts +1 -1
  3. package/backend/dist/adapters/claude-adapter.d.ts.map +1 -1
  4. package/backend/dist/adapters/claude-adapter.js +62 -10
  5. package/backend/dist/adapters/claude-adapter.js.map +1 -1
  6. package/backend/dist/adapters/types.d.ts +1 -1
  7. package/backend/dist/adapters/types.d.ts.map +1 -1
  8. package/backend/dist/index.d.ts.map +1 -1
  9. package/backend/dist/index.js +4 -22
  10. package/backend/dist/index.js.map +1 -1
  11. package/backend/dist/routes/claude.d.ts.map +1 -1
  12. package/backend/dist/routes/claude.js +23 -1
  13. package/backend/dist/routes/claude.js.map +1 -1
  14. package/backend/dist/routes/projects.d.ts.map +1 -1
  15. package/backend/dist/routes/projects.js +26 -6
  16. package/backend/dist/routes/projects.js.map +1 -1
  17. package/backend/dist/routes/sync.d.ts +3 -0
  18. package/backend/dist/routes/sync.d.ts.map +1 -0
  19. package/backend/dist/routes/sync.js +183 -0
  20. package/backend/dist/routes/sync.js.map +1 -0
  21. package/backend/dist/sync-config.d.ts +62 -0
  22. package/backend/dist/sync-config.d.ts.map +1 -0
  23. package/backend/dist/sync-config.js +207 -0
  24. package/backend/dist/sync-config.js.map +1 -0
  25. package/backend/dist/sync-scheduler.d.ts +7 -0
  26. package/backend/dist/sync-scheduler.d.ts.map +1 -0
  27. package/backend/dist/sync-scheduler.js +157 -0
  28. package/backend/dist/sync-scheduler.js.map +1 -0
  29. package/backend/dist/sync-service.d.ts +51 -0
  30. package/backend/dist/sync-service.d.ts.map +1 -0
  31. package/backend/dist/sync-service.js +344 -0
  32. package/backend/dist/sync-service.js.map +1 -0
  33. package/backend/dist/user-prefs.d.ts +3 -0
  34. package/backend/dist/user-prefs.d.ts.map +1 -0
  35. package/backend/dist/user-prefs.js +87 -0
  36. package/backend/dist/user-prefs.js.map +1 -0
  37. package/frontend/dist/assets/AssistantMessageContent-D1-3VpWE.js +13 -0
  38. package/frontend/dist/assets/GraphPreview-CeI4sbtV.js +8 -0
  39. package/frontend/dist/assets/MobilePage-BP7c3W3D.js +14 -0
  40. package/frontend/dist/assets/{OfficePreview-CLGxDBuB.js → OfficePreview-Dgs4aiYi.js} +2 -2
  41. package/frontend/dist/assets/{ProjectPage-Bpj8XUcg.js → ProjectPage-DPv57nD9.js} +5 -6
  42. package/frontend/dist/assets/SettingsPage-CFSmKovg.js +13 -0
  43. package/frontend/dist/assets/{SkillHubPage-BWkab_k8.js → SkillHubPage-4g29B-Hr.js} +2 -2
  44. package/frontend/dist/assets/{chevron-down-Bn3Wxb1A.js → chevron-down-CyDTNuVw.js} +1 -1
  45. package/frontend/dist/assets/{chevron-up-DjQ2Kt99.js → chevron-up-BURz786o.js} +1 -1
  46. package/frontend/dist/assets/{index-nuXK9Vzi.js → index-BFWZX3Hz.js} +6 -6
  47. package/frontend/dist/assets/index-D0NB3R9q.css +1 -0
  48. package/frontend/dist/assets/index-Uy-V98k3.js +13 -0
  49. package/frontend/dist/assets/{index-BpQn0KbO.js → index-z4qRGojt.js} +1 -1
  50. package/frontend/dist/assets/{jszip.min-k094Tbts.js → jszip.min-CPG_u-b-.js} +1 -1
  51. package/frontend/dist/assets/{search-DlCQSCBu.js → search-CZ83atP-.js} +1 -1
  52. package/frontend/dist/index.html +2 -2
  53. package/package.json +1 -1
  54. package/frontend/dist/assets/AssistantMessageContent-BXGoUnPl.js +0 -13
  55. package/frontend/dist/assets/GraphPreview-Ca22U4BP.js +0 -2
  56. package/frontend/dist/assets/MobilePage-CIUktKA8.js +0 -14
  57. package/frontend/dist/assets/PlanPanel-TLlCo5cs.js +0 -13
  58. package/frontend/dist/assets/SettingsPage-Cy00qya-.js +0 -13
  59. package/frontend/dist/assets/index-CYLf1vI2.js +0 -7
  60. package/frontend/dist/assets/index-b8oVHVON.css +0 -1
  61. package/frontend/dist/assets/maximize-2-C1mkwgJj.js +0 -7
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sync-scheduler.js","sourceRoot":"","sources":["../src/sync-scheduler.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,51 @@
1
+ import { type SyncDirection } from './sync-config';
2
+ /**
3
+ * rsync-driven sync service.
4
+ *
5
+ * Design choices worth noting:
6
+ *
7
+ * - **SSH options go through a wrapper script**, not through `rsync -e "ssh -p 22 -i …"`.
8
+ * Rsync parses the `-e` value by splitting on whitespace, so any keyPath with a space
9
+ * or an attacker-crafted `-oProxyCommand=…` would escalate self-config to code execution
10
+ * as the ccweb process. A wrapper `sh -c 'exec ssh <hardcoded opts> "$@"'` file written
11
+ * with user values quoted by `shell-quote` equivalent semantics removes this vector
12
+ * entirely.
13
+ * - **Password auth** uses `sshpass -e` wrapping the same script. `SSHPASS` env stays
14
+ * in the parent and is inherited by child only — never appears in argv or logs.
15
+ * - **Concurrency**: one in-flight sync per (user, project); subsequent calls return
16
+ * `{ skipped: true }`.
17
+ * - **Logs**: written via createWriteStream (ordered); file truncated to keep the last
18
+ * ~20 runs, preventing long-term growth (--stats is used so a run is ~20 lines, not
19
+ * the hundreds of lines --progress emitted).
20
+ * - **bidirectional**: is NOT a safe two-way sync (rsync can't). The push leg is run
21
+ * without --delete and with -u (update-if-newer), so remote-newer files survive the
22
+ * pull leg that follows. Deletions must be handled manually.
23
+ */
24
+ export interface SyncResult {
25
+ ok: boolean;
26
+ exitCode: number | null;
27
+ durationMs: number;
28
+ bytes: number;
29
+ filesTransferred: number;
30
+ logTail: string;
31
+ skipped?: true;
32
+ reason?: string;
33
+ }
34
+ /**
35
+ * Sync one project. Bidirectional runs the push leg without --delete (so the
36
+ * following pull can restore remote-newer files), then the pull leg.
37
+ */
38
+ export declare function syncProject(username: string, projectId: string, projectName: string, localPath: string, overrideDirection?: SyncDirection): Promise<SyncResult>;
39
+ export declare function isSyncing(username: string, projectId: string): boolean;
40
+ export declare function listInFlight(username: string): string[];
41
+ /**
42
+ * Non-destructive connection test: runs `rsync --version` through the same
43
+ * wrapper script rsync would use, so if this succeeds a real sync's
44
+ * SSH setup will also succeed. Uses the test `exit 0` on the remote instead
45
+ * of `--version` (which doesn't touch ssh at all).
46
+ */
47
+ export declare function testConnection(username: string): Promise<{
48
+ ok: boolean;
49
+ message: string;
50
+ }>;
51
+ //# sourceMappingURL=sync-service.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sync-service.d.ts","sourceRoot":"","sources":["../src/sync-service.ts"],"names":[],"mappings":"AAMA,OAAO,EAEY,KAAK,aAAa,EACpC,MAAM,eAAe,CAAC;AAEvB;;;;;;;;;;;;;;;;;;;;;GAqBG;AAEH,MAAM,WAAW,UAAU;IACzB,EAAE,EAAE,OAAO,CAAC;IACZ,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;IACxB,UAAU,EAAE,MAAM,CAAC;IACnB,KAAK,EAAE,MAAM,CAAC;IACd,gBAAgB,EAAE,MAAM,CAAC;IACzB,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,CAAC,EAAE,IAAI,CAAC;IACf,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AA4ND;;;GAGG;AACH,wBAAsB,WAAW,CAC/B,QAAQ,EAAE,MAAM,EAChB,SAAS,EAAE,MAAM,EACjB,WAAW,EAAE,MAAM,EACnB,SAAS,EAAE,MAAM,EACjB,iBAAiB,CAAC,EAAE,aAAa,GAChC,OAAO,CAAC,UAAU,CAAC,CAsDrB;AAED,wBAAgB,SAAS,CAAC,QAAQ,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,OAAO,CAEtE;AAED,wBAAgB,YAAY,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,EAAE,CAOvD;AAED;;;;;GAKG;AACH,wBAAsB,cAAc,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC;IAAE,EAAE,EAAE,OAAO,CAAC;IAAC,OAAO,EAAE,MAAM,CAAA;CAAE,CAAC,CAkChG"}
@@ -0,0 +1,344 @@
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
+ exports.syncProject = syncProject;
37
+ exports.isSyncing = isSyncing;
38
+ exports.listInFlight = listInFlight;
39
+ exports.testConnection = testConnection;
40
+ const child_process_1 = require("child_process");
41
+ const fs = __importStar(require("fs"));
42
+ const path = __importStar(require("path"));
43
+ const os = __importStar(require("os"));
44
+ const crypto = __importStar(require("crypto"));
45
+ const config_1 = require("./config");
46
+ const sync_config_1 = require("./sync-config");
47
+ const LOGS_DIR = path.join(config_1.DATA_DIR, 'sync-logs');
48
+ const WRAP_DIR = path.join(config_1.DATA_DIR, 'sync-ssh');
49
+ const LOG_MAX_BYTES = 2 * 1024 * 1024; // 2 MB per project
50
+ const inFlight = new Map();
51
+ function inFlightKey(username, projectId) {
52
+ return `${username}::${projectId}`;
53
+ }
54
+ function userSlug(username) {
55
+ return crypto.createHash('sha1').update(`ccweb-sync-user:${username}`).digest('hex');
56
+ }
57
+ function ensureLogDir(username) {
58
+ const dir = path.join(LOGS_DIR, userSlug(username));
59
+ if (!fs.existsSync(dir))
60
+ fs.mkdirSync(dir, { recursive: true, mode: 0o700 });
61
+ return dir;
62
+ }
63
+ function ensureWrapDir() {
64
+ if (!fs.existsSync(WRAP_DIR))
65
+ fs.mkdirSync(WRAP_DIR, { recursive: true, mode: 0o700 });
66
+ return WRAP_DIR;
67
+ }
68
+ function resolveKeyPath(p) {
69
+ if (!p)
70
+ return null;
71
+ if (p.startsWith('~'))
72
+ return path.join(os.homedir(), p.slice(1));
73
+ return p;
74
+ }
75
+ /** Test that `sshpass` is on PATH; needed only for password auth. */
76
+ function hasSshpass() {
77
+ try {
78
+ (0, child_process_1.execSync)('command -v sshpass', { stdio: 'ignore', shell: '/bin/sh' });
79
+ return true;
80
+ }
81
+ catch {
82
+ return false;
83
+ }
84
+ }
85
+ // ── SSH wrapper script ───────────────────────────────────────────────────────
86
+ /**
87
+ * POSIX shell single-quoting: wrap in `'…'` and replace any embedded `'`
88
+ * with `'\''`. Safe for all byte strings.
89
+ */
90
+ function shSingleQuote(s) {
91
+ return `'${s.replace(/'/g, `'\\''`)}'`;
92
+ }
93
+ /**
94
+ * Write (or refresh) a per-user SSH wrapper script. Rsync's `-e` takes a
95
+ * single token that it splits on whitespace; by passing it a path to this
96
+ * script, the rsync subprocess exec's the script as a *command*, passing the
97
+ * `[user@host, remote-command...]` tail as positional args. The script
98
+ * itself hardcodes all SSH options in shell-quoted form, so no user value is
99
+ * ever re-tokenized by anything between us and ssh.
100
+ *
101
+ * For password auth the same script prepends `sshpass -e`; SSHPASS is read
102
+ * from the inherited env at run time.
103
+ *
104
+ * Returns the absolute path to the script, written 0700.
105
+ */
106
+ function writeSshWrapper(cfg) {
107
+ ensureWrapDir();
108
+ const knownHostsFile = path.join(os.homedir(), '.ssh', 'known_hosts_ccweb');
109
+ const parts = [];
110
+ if (cfg.authMethod === 'password')
111
+ parts.push('sshpass', '-e');
112
+ parts.push('ssh');
113
+ parts.push('-p', String(cfg.port));
114
+ parts.push('-o', 'StrictHostKeyChecking=accept-new');
115
+ parts.push('-o', `UserKnownHostsFile=${knownHostsFile}`);
116
+ parts.push('-o', 'BatchMode=yes');
117
+ parts.push('-o', 'ConnectTimeout=20');
118
+ if (cfg.authMethod === 'key') {
119
+ const keyPath = resolveKeyPath(cfg.keyPath);
120
+ if (keyPath) {
121
+ parts.push('-i', keyPath);
122
+ parts.push('-o', 'IdentitiesOnly=yes');
123
+ }
124
+ }
125
+ // Quote every component once, here, and never string-concat user data again
126
+ const quoted = parts.map(shSingleQuote).join(' ');
127
+ const script = `#!/bin/sh\nexec ${quoted} "$@"\n`;
128
+ const file = path.join(WRAP_DIR, `${userSlug(cfg.username)}.sh`);
129
+ fs.writeFileSync(file, script, { mode: 0o700 });
130
+ return file;
131
+ }
132
+ // ── Log rotation ────────────────────────────────────────────────────────────
133
+ function rotateLogIfLarge(logFile) {
134
+ try {
135
+ const stat = fs.statSync(logFile);
136
+ if (stat.size > LOG_MAX_BYTES) {
137
+ // Keep the last half by reading tail and overwriting; avoids
138
+ // renaming (which would leave a .old file on disk forever).
139
+ const fd = fs.openSync(logFile, 'r');
140
+ const halfSize = Math.floor(LOG_MAX_BYTES / 2);
141
+ const buf = Buffer.alloc(halfSize);
142
+ fs.readSync(fd, buf, 0, halfSize, stat.size - halfSize);
143
+ fs.closeSync(fd);
144
+ // Align to next newline so we don't start mid-line
145
+ const nl = buf.indexOf(0x0a);
146
+ const tail = nl >= 0 ? buf.subarray(nl + 1) : buf;
147
+ fs.writeFileSync(logFile, Buffer.concat([Buffer.from('===== (older entries rotated) =====\n'), tail]));
148
+ }
149
+ }
150
+ catch { /* missing file or read failure — no-op */ }
151
+ }
152
+ function buildRsyncArgs(cfg, localPath, folderName, excludes, direction, bidirectionalLeg) {
153
+ const wrapper = writeSshWrapper(cfg);
154
+ const args = ['-az', '--stats'];
155
+ args.push('-e', wrapper);
156
+ for (const pat of excludes) {
157
+ const trimmed = pat.trim();
158
+ if (trimmed)
159
+ args.push('--exclude', trimmed);
160
+ }
161
+ const localSpec = localPath.endsWith('/') ? localPath : localPath + '/';
162
+ // path.posix.join on sanitized name; folderName is already validated to
163
+ // contain no `..` / separators.
164
+ const remoteSpec = `${cfg.user}@${cfg.host}:${path.posix.join(cfg.remoteRoot, folderName)}/`;
165
+ if (direction === 'push') {
166
+ // Only the pure-push path uses --delete (mirror semantics). The push leg
167
+ // of "bidirectional" must not delete remote-newer files the pull leg is
168
+ // about to bring back.
169
+ if (!bidirectionalLeg)
170
+ args.push('--delete');
171
+ else
172
+ args.push('-u');
173
+ args.push(localSpec, remoteSpec);
174
+ }
175
+ else {
176
+ // pull: never --delete (protects local work-in-progress)
177
+ args.push(remoteSpec, localSpec);
178
+ }
179
+ const env = { ...process.env };
180
+ if (cfg.authMethod === 'password' && cfg.passwordEnc) {
181
+ const pw = (0, sync_config_1.decryptPassword)(cfg.passwordEnc, cfg.passwordFp);
182
+ if (pw)
183
+ env.SSHPASS = pw;
184
+ }
185
+ return { args, env };
186
+ }
187
+ async function runOne(cfg, projectId, folderName, localPath, direction, bidirectionalLeg) {
188
+ const excludes = [...cfg.defaultExcludes, ...(cfg.projectExcludes[projectId] ?? [])];
189
+ const { args, env } = buildRsyncArgs(cfg, localPath, folderName, excludes, direction, bidirectionalLeg);
190
+ if (cfg.authMethod === 'password' && !env.SSHPASS) {
191
+ return { ok: false, exitCode: null, durationMs: 0, bytes: 0, filesTransferred: 0, logTail: '', reason: 'password-decrypt-failed' };
192
+ }
193
+ const logDir = ensureLogDir(cfg.username);
194
+ const logFile = path.join(logDir, `${projectId}.log`);
195
+ rotateLogIfLarge(logFile);
196
+ const startStamp = new Date().toISOString();
197
+ const header = `\n===== ${startStamp} ${direction.toUpperCase()}${bidirectionalLeg ? '(bidi)' : ''} ${folderName} =====\n`;
198
+ const started = Date.now();
199
+ return await new Promise((resolve) => {
200
+ let combined = '';
201
+ const logStream = fs.createWriteStream(logFile, { flags: 'a', mode: 0o600 });
202
+ logStream.write(header);
203
+ const child = (0, child_process_1.spawn)('rsync', args, { env, cwd: os.homedir(), stdio: ['ignore', 'pipe', 'pipe'] });
204
+ const onData = (buf) => {
205
+ const s = buf.toString();
206
+ combined += s;
207
+ logStream.write(s);
208
+ };
209
+ child.stdout.on('data', onData);
210
+ child.stderr.on('data', onData);
211
+ child.on('error', (err) => {
212
+ logStream.write(`spawn error: ${err.message}\n`);
213
+ logStream.end();
214
+ resolve({ ok: false, exitCode: null, durationMs: Date.now() - started, bytes: 0, filesTransferred: 0, logTail: err.message, reason: 'spawn-failed' });
215
+ });
216
+ child.on('close', (code) => {
217
+ logStream.end();
218
+ const ok = code === 0;
219
+ // --stats output: "Total transferred file size: N bytes" and "Number of regular files transferred: N"
220
+ const bytesMatch = combined.match(/total transferred file size:\s*([\d,]+)\s*bytes/i);
221
+ const filesMatch = combined.match(/number of regular files transferred:\s*([\d,]+)/i);
222
+ const bytes = bytesMatch ? parseInt(bytesMatch[1].replace(/,/g, ''), 10) : 0;
223
+ const files = filesMatch ? parseInt(filesMatch[1].replace(/,/g, ''), 10) : 0;
224
+ const logTail = combined.split('\n').slice(-30).join('\n');
225
+ resolve({ ok, exitCode: code, durationMs: Date.now() - started, bytes, filesTransferred: files, logTail });
226
+ });
227
+ });
228
+ }
229
+ // ── Public API ──────────────────────────────────────────────────────────────
230
+ /**
231
+ * Sync one project. Bidirectional runs the push leg without --delete (so the
232
+ * following pull can restore remote-newer files), then the pull leg.
233
+ */
234
+ async function syncProject(username, projectId, projectName, localPath, overrideDirection) {
235
+ const key = inFlightKey(username, projectId);
236
+ if (inFlight.has(key)) {
237
+ return { ok: false, exitCode: null, durationMs: 0, bytes: 0, filesTransferred: 0, logTail: '', skipped: true, reason: 'already-syncing' };
238
+ }
239
+ const cfg = (0, sync_config_1.getSyncConfig)(username);
240
+ // Preflight validation — fail fast with a clear reason instead of spawning
241
+ // rsync and watching it error cryptically.
242
+ if (!cfg.host || !cfg.user || !cfg.remoteRoot) {
243
+ return { ok: false, exitCode: null, durationMs: 0, bytes: 0, filesTransferred: 0, logTail: '', reason: 'incomplete-config' };
244
+ }
245
+ if (cfg.authMethod === 'key' && !cfg.keyPath) {
246
+ return { ok: false, exitCode: null, durationMs: 0, bytes: 0, filesTransferred: 0, logTail: '', reason: 'missing-key-path' };
247
+ }
248
+ if (cfg.authMethod === 'password' && !hasSshpass()) {
249
+ return { ok: false, exitCode: null, durationMs: 0, bytes: 0, filesTransferred: 0, logTail: '', reason: 'sshpass-not-installed' };
250
+ }
251
+ if (!fs.existsSync(localPath)) {
252
+ return { ok: false, exitCode: null, durationMs: 0, bytes: 0, filesTransferred: 0, logTail: '', reason: 'local-path-missing' };
253
+ }
254
+ // Folder name on the remote: prefer the project display name, fall back to
255
+ // basename then projectId. Must be sanitized or we'd let a project name
256
+ // containing `..` escape the remote root.
257
+ const rawName = projectName || path.basename(localPath) || projectId;
258
+ const folderName = (0, sync_config_1.sanitizeFolderName)(rawName) ?? projectId;
259
+ const direction = overrideDirection ?? cfg.direction;
260
+ const job = (async () => {
261
+ if (direction === 'bidirectional') {
262
+ const push = await runOne(cfg, projectId, folderName, localPath, 'push', true);
263
+ if (!push.ok)
264
+ return push;
265
+ const pull = await runOne(cfg, projectId, folderName, localPath, 'pull', true);
266
+ return {
267
+ ok: pull.ok,
268
+ exitCode: pull.exitCode,
269
+ durationMs: push.durationMs + pull.durationMs,
270
+ bytes: push.bytes + pull.bytes,
271
+ filesTransferred: push.filesTransferred + pull.filesTransferred,
272
+ logTail: `[PUSH]\n${push.logTail}\n[PULL]\n${pull.logTail}`,
273
+ };
274
+ }
275
+ return runOne(cfg, projectId, folderName, localPath, direction, false);
276
+ })();
277
+ inFlight.set(key, job);
278
+ try {
279
+ return await job;
280
+ }
281
+ finally {
282
+ inFlight.delete(key);
283
+ }
284
+ }
285
+ function isSyncing(username, projectId) {
286
+ return inFlight.has(inFlightKey(username, projectId));
287
+ }
288
+ function listInFlight(username) {
289
+ const prefix = `${username}::`;
290
+ const out = [];
291
+ for (const k of inFlight.keys()) {
292
+ if (k.startsWith(prefix))
293
+ out.push(k.slice(prefix.length));
294
+ }
295
+ return out;
296
+ }
297
+ /**
298
+ * Non-destructive connection test: runs `rsync --version` through the same
299
+ * wrapper script rsync would use, so if this succeeds a real sync's
300
+ * SSH setup will also succeed. Uses the test `exit 0` on the remote instead
301
+ * of `--version` (which doesn't touch ssh at all).
302
+ */
303
+ async function testConnection(username) {
304
+ const cfg = (0, sync_config_1.getSyncConfig)(username);
305
+ if (!cfg.host || !cfg.user)
306
+ return { ok: false, message: '未配置 host/user' };
307
+ if (cfg.authMethod === 'password' && !hasSshpass()) {
308
+ return { ok: false, message: '未安装 sshpass(密码认证需要)。请用 key 认证或安装 sshpass。' };
309
+ }
310
+ if (cfg.authMethod === 'password' && cfg.passwordEnc) {
311
+ const pw = (0, sync_config_1.decryptPassword)(cfg.passwordEnc, cfg.passwordFp);
312
+ if (!pw)
313
+ return { ok: false, message: '密码解密失败(服务端密钥可能已轮换)。请重新输入密码。' };
314
+ }
315
+ const wrapper = writeSshWrapper(cfg);
316
+ const env = { ...process.env };
317
+ if (cfg.authMethod === 'password' && cfg.passwordEnc) {
318
+ const pw = (0, sync_config_1.decryptPassword)(cfg.passwordEnc, cfg.passwordFp);
319
+ if (pw)
320
+ env.SSHPASS = pw;
321
+ }
322
+ return await new Promise((resolve) => {
323
+ let err = '';
324
+ // Invoke the wrapper directly — same exec path as rsync's -e would.
325
+ const child = (0, child_process_1.spawn)(wrapper, [`${cfg.user}@${cfg.host}`, 'true'], { env, stdio: ['ignore', 'ignore', 'pipe'] });
326
+ const timeout = setTimeout(() => {
327
+ try {
328
+ child.kill('SIGTERM');
329
+ }
330
+ catch { /* ignore */ }
331
+ resolve({ ok: false, message: '连接超时(30s)' });
332
+ }, 30000);
333
+ child.stderr.on('data', (b) => { err += b.toString(); });
334
+ child.on('error', (e) => { clearTimeout(timeout); resolve({ ok: false, message: `spawn 失败: ${e.message}` }); });
335
+ child.on('close', (code) => {
336
+ clearTimeout(timeout);
337
+ if (code === 0)
338
+ resolve({ ok: true, message: '连接成功' });
339
+ else
340
+ resolve({ ok: false, message: err.trim() || `ssh 退出码 ${code}` });
341
+ });
342
+ });
343
+ }
344
+ //# sourceMappingURL=sync-service.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sync-service.js","sourceRoot":"","sources":["../src/sync-service.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,3 @@
1
+ export declare function getUserPref<T = unknown>(username: string, key: string): T | undefined;
2
+ export declare function setUserPref(username: string, key: string, value: unknown): void;
3
+ //# sourceMappingURL=user-prefs.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"user-prefs.d.ts","sourceRoot":"","sources":["../src/user-prefs.ts"],"names":[],"mappings":"AA0CA,wBAAgB,WAAW,CAAC,CAAC,GAAG,OAAO,EAAE,QAAQ,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,CAAC,GAAG,SAAS,CAGrF;AAED,wBAAgB,WAAW,CAAC,QAAQ,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,OAAO,GAAG,IAAI,CAK/E"}
@@ -0,0 +1,87 @@
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
+ exports.getUserPref = getUserPref;
37
+ exports.setUserPref = setUserPref;
38
+ const fs = __importStar(require("fs"));
39
+ const path = __importStar(require("path"));
40
+ const config_1 = require("./config");
41
+ /**
42
+ * Per-user preferences persisted across restarts.
43
+ *
44
+ * Shape on disk: `{ [username]: { [key]: value } }`
45
+ *
46
+ * Keeps tiny, non-secret client-side state (project order, ui prefs) in one
47
+ * file rather than scattering one file per user × feature. Not for anything
48
+ * security-sensitive — no auth data here.
49
+ */
50
+ const PREFS_FILE = path.join(config_1.DATA_DIR, 'user-prefs.json');
51
+ let cache = null;
52
+ let cacheMtime = 0;
53
+ function readAll() {
54
+ try {
55
+ const stat = fs.statSync(PREFS_FILE);
56
+ if (cache && stat.mtimeMs === cacheMtime)
57
+ return cache;
58
+ const raw = fs.readFileSync(PREFS_FILE, 'utf-8');
59
+ cache = JSON.parse(raw);
60
+ cacheMtime = stat.mtimeMs;
61
+ return cache;
62
+ }
63
+ catch {
64
+ cache = {};
65
+ cacheMtime = 0;
66
+ return cache;
67
+ }
68
+ }
69
+ function writeAll(prefs) {
70
+ (0, config_1.atomicWriteSync)(PREFS_FILE, JSON.stringify(prefs, null, 2));
71
+ cache = prefs;
72
+ try {
73
+ cacheMtime = fs.statSync(PREFS_FILE).mtimeMs;
74
+ }
75
+ catch { /* ignore */ }
76
+ }
77
+ function getUserPref(username, key) {
78
+ const all = readAll();
79
+ return all[username]?.[key];
80
+ }
81
+ function setUserPref(username, key, value) {
82
+ const all = readAll();
83
+ const forUser = { ...(all[username] ?? {}) };
84
+ forUser[key] = value;
85
+ writeAll({ ...all, [username]: forUser });
86
+ }
87
+ //# sourceMappingURL=user-prefs.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"user-prefs.js","sourceRoot":"","sources":["../src/user-prefs.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AA0CA,kCAGC;AAED,kCAKC;AApDD,uCAAyB;AACzB,2CAA6B;AAC7B,qCAAqD;AAErD;;;;;;;;GAQG;AAEH,MAAM,UAAU,GAAG,IAAI,CAAC,IAAI,CAAC,iBAAQ,EAAE,iBAAiB,CAAC,CAAC;AAI1D,IAAI,KAAK,GAAiB,IAAI,CAAC;AAC/B,IAAI,UAAU,GAAG,CAAC,CAAC;AAEnB,SAAS,OAAO;IACd,IAAI,CAAC;QACH,MAAM,IAAI,GAAG,EAAE,CAAC,QAAQ,CAAC,UAAU,CAAC,CAAC;QACrC,IAAI,KAAK,IAAI,IAAI,CAAC,OAAO,KAAK,UAAU;YAAE,OAAO,KAAK,CAAC;QACvD,MAAM,GAAG,GAAG,EAAE,CAAC,YAAY,CAAC,UAAU,EAAE,OAAO,CAAC,CAAC;QACjD,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAU,CAAC;QACjC,UAAU,GAAG,IAAI,CAAC,OAAO,CAAC;QAC1B,OAAO,KAAK,CAAC;IACf,CAAC;IAAC,MAAM,CAAC;QACP,KAAK,GAAG,EAAE,CAAC;QACX,UAAU,GAAG,CAAC,CAAC;QACf,OAAO,KAAK,CAAC;IACf,CAAC;AACH,CAAC;AAED,SAAS,QAAQ,CAAC,KAAY;IAC5B,IAAA,wBAAe,EAAC,UAAU,EAAE,IAAI,CAAC,SAAS,CAAC,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC;IAC5D,KAAK,GAAG,KAAK,CAAC;IACd,IAAI,CAAC;QAAC,UAAU,GAAG,EAAE,CAAC,QAAQ,CAAC,UAAU,CAAC,CAAC,OAAO,CAAC;IAAC,CAAC;IAAC,MAAM,CAAC,CAAC,YAAY,CAAC,CAAC;AAC9E,CAAC;AAED,SAAgB,WAAW,CAAc,QAAgB,EAAE,GAAW;IACpE,MAAM,GAAG,GAAG,OAAO,EAAE,CAAC;IACtB,OAAO,GAAG,CAAC,QAAQ,CAAC,EAAE,CAAC,GAAG,CAAkB,CAAC;AAC/C,CAAC;AAED,SAAgB,WAAW,CAAC,QAAgB,EAAE,GAAW,EAAE,KAAc;IACvE,MAAM,GAAG,GAAG,OAAO,EAAE,CAAC;IACtB,MAAM,OAAO,GAAG,EAAE,GAAG,CAAC,GAAG,CAAC,QAAQ,CAAC,IAAI,EAAE,CAAC,EAAE,CAAC;IAC7C,OAAO,CAAC,GAAG,CAAC,GAAG,KAAK,CAAC;IACrB,QAAQ,CAAC,EAAE,GAAG,GAAG,EAAE,CAAC,QAAQ,CAAC,EAAE,OAAO,EAAE,CAAC,CAAC;AAC5C,CAAC"}