@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.
- package/README.md +1 -1
- package/backend/dist/adapters/claude-adapter.d.ts +1 -1
- package/backend/dist/adapters/claude-adapter.d.ts.map +1 -1
- package/backend/dist/adapters/claude-adapter.js +62 -10
- package/backend/dist/adapters/claude-adapter.js.map +1 -1
- package/backend/dist/adapters/types.d.ts +1 -1
- package/backend/dist/adapters/types.d.ts.map +1 -1
- package/backend/dist/index.d.ts.map +1 -1
- package/backend/dist/index.js +4 -22
- package/backend/dist/index.js.map +1 -1
- package/backend/dist/routes/claude.d.ts.map +1 -1
- package/backend/dist/routes/claude.js +23 -1
- package/backend/dist/routes/claude.js.map +1 -1
- package/backend/dist/routes/projects.d.ts.map +1 -1
- package/backend/dist/routes/projects.js +26 -6
- package/backend/dist/routes/projects.js.map +1 -1
- package/backend/dist/routes/sync.d.ts +3 -0
- package/backend/dist/routes/sync.d.ts.map +1 -0
- package/backend/dist/routes/sync.js +183 -0
- package/backend/dist/routes/sync.js.map +1 -0
- package/backend/dist/sync-config.d.ts +62 -0
- package/backend/dist/sync-config.d.ts.map +1 -0
- package/backend/dist/sync-config.js +207 -0
- package/backend/dist/sync-config.js.map +1 -0
- package/backend/dist/sync-scheduler.d.ts +7 -0
- package/backend/dist/sync-scheduler.d.ts.map +1 -0
- package/backend/dist/sync-scheduler.js +157 -0
- package/backend/dist/sync-scheduler.js.map +1 -0
- package/backend/dist/sync-service.d.ts +51 -0
- package/backend/dist/sync-service.d.ts.map +1 -0
- package/backend/dist/sync-service.js +344 -0
- package/backend/dist/sync-service.js.map +1 -0
- package/backend/dist/user-prefs.d.ts +3 -0
- package/backend/dist/user-prefs.d.ts.map +1 -0
- package/backend/dist/user-prefs.js +87 -0
- package/backend/dist/user-prefs.js.map +1 -0
- package/frontend/dist/assets/AssistantMessageContent-D1-3VpWE.js +13 -0
- package/frontend/dist/assets/GraphPreview-CeI4sbtV.js +8 -0
- package/frontend/dist/assets/MobilePage-BP7c3W3D.js +14 -0
- package/frontend/dist/assets/{OfficePreview-CLGxDBuB.js → OfficePreview-Dgs4aiYi.js} +2 -2
- package/frontend/dist/assets/{ProjectPage-Bpj8XUcg.js → ProjectPage-DPv57nD9.js} +5 -6
- package/frontend/dist/assets/SettingsPage-CFSmKovg.js +13 -0
- package/frontend/dist/assets/{SkillHubPage-BWkab_k8.js → SkillHubPage-4g29B-Hr.js} +2 -2
- package/frontend/dist/assets/{chevron-down-Bn3Wxb1A.js → chevron-down-CyDTNuVw.js} +1 -1
- package/frontend/dist/assets/{chevron-up-DjQ2Kt99.js → chevron-up-BURz786o.js} +1 -1
- package/frontend/dist/assets/{index-nuXK9Vzi.js → index-BFWZX3Hz.js} +6 -6
- package/frontend/dist/assets/index-D0NB3R9q.css +1 -0
- package/frontend/dist/assets/index-Uy-V98k3.js +13 -0
- package/frontend/dist/assets/{index-BpQn0KbO.js → index-z4qRGojt.js} +1 -1
- package/frontend/dist/assets/{jszip.min-k094Tbts.js → jszip.min-CPG_u-b-.js} +1 -1
- package/frontend/dist/assets/{search-DlCQSCBu.js → search-CZ83atP-.js} +1 -1
- package/frontend/dist/index.html +2 -2
- package/package.json +1 -1
- package/frontend/dist/assets/AssistantMessageContent-BXGoUnPl.js +0 -13
- package/frontend/dist/assets/GraphPreview-Ca22U4BP.js +0 -2
- package/frontend/dist/assets/MobilePage-CIUktKA8.js +0 -14
- package/frontend/dist/assets/PlanPanel-TLlCo5cs.js +0 -13
- package/frontend/dist/assets/SettingsPage-Cy00qya-.js +0 -13
- package/frontend/dist/assets/index-CYLf1vI2.js +0 -7
- package/frontend/dist/assets/index-b8oVHVON.css +0 -1
- 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":";;AAqFA,oCAOC;AAkDD,gDAWC;AAED,8CAIC;AA/JD,qCAAuD;AACvD,+CAAuE;AACvE,iDAA6C;AAuB7C;;8CAE8C;AAC9C,SAAS,UAAU,CAAC,GAAW,EAAE,GAAW,EAAE,GAAW;IACvD,MAAM,GAAG,GAAG,IAAI,GAAG,EAAU,CAAC;IAC9B,KAAK,MAAM,OAAO,IAAI,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,EAAE,CAAC;QACrC,MAAM,IAAI,GAAG,OAAO,CAAC,IAAI,EAAE,CAAC;QAC5B,IAAI,CAAC,IAAI;YAAE,OAAO,IAAI,CAAC;QACvB,IAAI,IAAI,GAAG,CAAC,CAAC;QACb,IAAI,SAAS,GAAG,IAAI,CAAC;QACrB,MAAM,QAAQ,GAAG,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC;QACnC,IAAI,QAAQ,IAAI,CAAC,EAAE,CAAC;YAClB,MAAM,OAAO,GAAG,IAAI,CAAC,KAAK,CAAC,QAAQ,GAAG,CAAC,CAAC,CAAC;YACzC,MAAM,MAAM,GAAG,QAAQ,CAAC,OAAO,EAAE,EAAE,CAAC,CAAC;YACrC,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,MAAM,CAAC,IAAI,MAAM,IAAI,CAAC;gBAAE,OAAO,IAAI,CAAC;YACzD,IAAI,GAAG,MAAM,CAAC;YACd,SAAS,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC,EAAE,QAAQ,CAAC,CAAC;QACtC,CAAC;QACD,IAAI,KAAK,GAAG,GAAG,CAAC;QAChB,IAAI,GAAG,GAAG,GAAG,CAAC;QACd,IAAI,SAAS,KAAK,GAAG,EAAE,CAAC;YACtB,gBAAgB;QAClB,CAAC;aAAM,IAAI,SAAS,CAAC,QAAQ,CAAC,GAAG,CAAC,EAAE,CAAC;YACnC,MAAM,CAAC,IAAI,EAAE,IAAI,CAAC,GAAG,SAAS,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;YAC1C,MAAM,CAAC,GAAG,QAAQ,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC;YAC7B,MAAM,CAAC,GAAG,QAAQ,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC;YAC7B,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC,CAAC;gBAAE,OAAO,IAAI,CAAC;YAC5D,IAAI,CAAC,GAAG,CAAC;gBAAE,OAAO,IAAI,CAAC,CAAmB,4BAA4B;YACtE,IAAI,CAAC,GAAG,GAAG,IAAI,CAAC,GAAG,GAAG;gBAAE,OAAO,IAAI,CAAC,CAAM,eAAe;YACzD,KAAK,GAAG,CAAC,CAAC;YACV,GAAG,GAAG,CAAC,CAAC;QACV,CAAC;aAAM,CAAC;YACN,MAAM,CAAC,GAAG,QAAQ,CAAC,SAAS,EAAE,EAAE,CAAC,CAAC;YAClC,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,GAAG,IAAI,CAAC,GAAG,GAAG;gBAAE,OAAO,IAAI,CAAC;YAC3D,KAAK,GAAG,GAAG,GAAG,CAAC,CAAC;QAClB,CAAC;QACD,KAAK,IAAI,CAAC,GAAG,KAAK,EAAE,CAAC,IAAI,GAAG,EAAE,CAAC,IAAI,IAAI,EAAE,CAAC;YACxC,IAAI,CAAC,IAAI,GAAG,IAAI,CAAC,IAAI,GAAG;gBAAE,GAAG,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC;QACvC,CAAC;IACH,CAAC;IACD,IAAI,GAAG,CAAC,IAAI,KAAK,CAAC;QAAE,OAAO,IAAI,CAAC;IAChC,OAAO,GAAG,CAAC;AACb,CAAC;AAED,SAAS,SAAS,CAAC,IAAY;IAC7B,MAAM,KAAK,GAAG,IAAI,CAAC,IAAI,EAAE,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC;IACvC,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,IAAI,CAAC;IACpC,MAAM,CAAC,CAAC,EAAE,CAAC,EAAE,GAAG,EAAE,EAAE,EAAE,GAAG,CAAC,GAAG,KAAK,CAAC;IACnC,MAAM,MAAM,GAAG,UAAU,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC;IACpC,MAAM,IAAI,GAAG,UAAU,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC;IAClC,MAAM,IAAI,GAAG,UAAU,CAAC,GAAG,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC;IACpC,MAAM,KAAK,GAAG,UAAU,CAAC,EAAE,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC;IACpC,MAAM,IAAI,GAAG,UAAU,CAAC,GAAG,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC;IACnC,IAAI,CAAC,MAAM,IAAI,CAAC,IAAI,IAAI,CAAC,IAAI,IAAI,CAAC,KAAK,IAAI,CAAC,IAAI;QAAE,OAAO,IAAI,CAAC;IAC9D,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,GAAG,EAAE,IAAI,EAAE,KAAK,EAAE,GAAG,EAAE,IAAI,EAAE,CAAC;AACvD,CAAC;AAED;;uCAEuC;AACvC,SAAgB,YAAY,CAAC,IAAY;IACvC,IAAI,CAAC,IAAI,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE;QAAE,OAAO,MAAM,CAAC;IACzC,MAAM,KAAK,GAAG,IAAI,CAAC,IAAI,EAAE,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC;IACvC,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,yBAAyB,KAAK,CAAC,MAAM,IAAI,CAAC;IACzE,MAAM,MAAM,GAAG,SAAS,CAAC,IAAI,CAAC,CAAC;IAC/B,IAAI,CAAC,MAAM;QAAE,OAAO,0BAA0B,CAAC;IAC/C,OAAO,IAAI,CAAC;AACd,CAAC;AAED,SAAS,OAAO,CAAC,IAAgB,EAAE,GAAS;IAC1C,OAAO,CACL,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,GAAG,CAAC,UAAU,EAAE,CAAC;QACjC,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,QAAQ,EAAE,CAAC;QAC7B,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,OAAO,EAAE,CAAC;QAC3B,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,GAAG,CAAC,QAAQ,EAAE,GAAG,CAAC,CAAC;QAClC,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,MAAM,EAAE,CAAC,CAC3B,CAAC;AACJ,CAAC;AAED,+EAA+E;AAE/E,IAAI,QAAQ,GAA0B,IAAI,CAAC;AAC3C,IAAI,aAAa,GAA0B,IAAI,CAAC;AAEhD;;oCAEoC;AACpC,MAAM,UAAU,GAAG,IAAI,GAAG,EAAkB,CAAC;AAE7C,SAAS,SAAS,CAAC,CAAO;IACxB,MAAM,GAAG,GAAG,CAAC,CAAS,EAAE,EAAE,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC;IACtD,OAAO,GAAG,CAAC,CAAC,WAAW,EAAE,GAAG,GAAG,CAAC,CAAC,CAAC,QAAQ,EAAE,GAAG,CAAC,CAAC,GAAG,GAAG,CAAC,CAAC,CAAC,OAAO,EAAE,CAAC,GAAG,GAAG,CAAC,CAAC,CAAC,QAAQ,EAAE,CAAC,GAAG,GAAG,CAAC,CAAC,CAAC,UAAU,EAAE,CAAC,EAAE,CAAC;AACnH,CAAC;AAED,KAAK,UAAU,gBAAgB,CAAC,GAAS;IACvC,MAAM,UAAU,GAAG,SAAS,CAAC,GAAG,CAAC,CAAC;IAClC,MAAM,KAAK,GAAG,IAAA,qCAAuB,GAAE,CAAC;IACxC,KAAK,MAAM,QAAQ,IAAI,KAAK,EAAE,CAAC;QAC7B,MAAM,GAAG,GAAG,IAAA,2BAAa,EAAC,QAAQ,CAAC,CAAC;QACpC,IAAI,CAAC,GAAG,CAAC,QAAQ,CAAC,OAAO,IAAI,CAAC,GAAG,CAAC,QAAQ,CAAC,IAAI;YAAE,SAAS;QAC1D,MAAM,MAAM,GAAG,SAAS,CAAC,GAAG,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC;QAC5C,IAAI,CAAC,MAAM,IAAI,CAAC,OAAO,CAAC,MAAM,EAAE,GAAG,CAAC;YAAE,SAAS;QAC/C,yCAAyC;QACzC,IAAI,UAAU,CAAC,GAAG,CAAC,QAAQ,CAAC,KAAK,UAAU;YAAE,SAAS;QACtD,UAAU,CAAC,GAAG,CAAC,QAAQ,EAAE,UAAU,CAAC,CAAC;QAErC,MAAM,QAAQ,GAAG,IAAA,oBAAW,GAAE,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,QAAQ,IAAI,IAAA,uBAAc,EAAC,CAAC,EAAE,QAAQ,CAAC,CAAC,CAAC;QACzF,KAAK,MAAM,CAAC,IAAI,QAAQ,EAAE,CAAC;YACzB,IAAI,CAAC;gBACH,MAAM,IAAA,0BAAW,EAAC,QAAQ,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC,UAAU,CAAC,CAAC;YAC1D,CAAC;YAAC,OAAO,GAAG,EAAE,CAAC;gBACb,OAAO,CAAC,KAAK,CAAC,oBAAoB,QAAQ,IAAI,CAAC,CAAC,IAAI,UAAU,EAAG,GAAa,CAAC,OAAO,CAAC,CAAC;YAC1F,CAAC;QACH,CAAC;IACH,CAAC;AACH,CAAC;AAED,SAAgB,kBAAkB;IAChC,IAAI,QAAQ,IAAI,aAAa;QAAE,OAAO;IACtC,wEAAwE;IACxE,MAAM,UAAU,GAAG,CAAC,EAAE,GAAG,IAAI,IAAI,EAAE,CAAC,UAAU,EAAE,CAAC,GAAG,IAAI,CAAC;IACzD,aAAa,GAAG,UAAU,CAAC,GAAG,EAAE;QAC9B,aAAa,GAAG,IAAI,CAAC;QACrB,KAAK,gBAAgB,CAAC,IAAI,IAAI,EAAE,CAAC,CAAC,KAAK,CAAC,GAAG,EAAE,GAAgB,CAAC,CAAC,CAAC;QAChE,QAAQ,GAAG,WAAW,CAAC,GAAG,EAAE;YAC1B,KAAK,gBAAgB,CAAC,IAAI,IAAI,EAAE,CAAC,CAAC,KAAK,CAAC,GAAG,EAAE,GAAgB,CAAC,CAAC,CAAC;QAClE,CAAC,EAAE,KAAM,CAAC,CAAC;IACb,CAAC,EAAE,UAAU,CAAC,CAAC;AACjB,CAAC;AAED,SAAgB,iBAAiB;IAC/B,IAAI,aAAa,EAAE,CAAC;QAAC,YAAY,CAAC,aAAa,CAAC,CAAC;QAAC,aAAa,GAAG,IAAI,CAAC;IAAC,CAAC;IACzE,IAAI,QAAQ,EAAE,CAAC;QAAC,aAAa,CAAC,QAAQ,CAAC,CAAC;QAAC,QAAQ,GAAG,IAAI,CAAC;IAAC,CAAC;IAC3D,UAAU,CAAC,KAAK,EAAE,CAAC;AACrB,CAAC"}
|
|
@@ -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 @@
|
|
|
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"}
|