dsh-config-manager 0.1.0
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 +216 -0
- package/README.zh-CN.md +218 -0
- package/cordis.patch.yml +45 -0
- package/dsh.bundle.patch +21 -0
- package/dsh.client +39 -0
- package/lib/adapters/agent-presets.d.ts +13 -0
- package/lib/adapters/agent-presets.js +14 -0
- package/lib/adapters/agent-presets.js.map +1 -0
- package/lib/adapters/credentials.d.ts +36 -0
- package/lib/adapters/credentials.js +121 -0
- package/lib/adapters/credentials.js.map +1 -0
- package/lib/adapters/file-collection.d.ts +14 -0
- package/lib/adapters/file-collection.js +102 -0
- package/lib/adapters/file-collection.js.map +1 -0
- package/lib/adapters/index.d.ts +38 -0
- package/lib/adapters/index.js +46 -0
- package/lib/adapters/index.js.map +1 -0
- package/lib/adapters/mcp.d.ts +27 -0
- package/lib/adapters/mcp.js +175 -0
- package/lib/adapters/mcp.js.map +1 -0
- package/lib/adapters/plugin-files.d.ts +15 -0
- package/lib/adapters/plugin-files.js +91 -0
- package/lib/adapters/plugin-files.js.map +1 -0
- package/lib/adapters/plugins.d.ts +13 -0
- package/lib/adapters/plugins.js +177 -0
- package/lib/adapters/plugins.js.map +1 -0
- package/lib/adapters/prompts.d.ts +29 -0
- package/lib/adapters/prompts.js +228 -0
- package/lib/adapters/prompts.js.map +1 -0
- package/lib/adapters/providers.d.ts +33 -0
- package/lib/adapters/providers.js +143 -0
- package/lib/adapters/providers.js.map +1 -0
- package/lib/adapters/sessions.d.ts +14 -0
- package/lib/adapters/sessions.js +15 -0
- package/lib/adapters/sessions.js.map +1 -0
- package/lib/adapters/settings.d.ts +23 -0
- package/lib/adapters/settings.js +142 -0
- package/lib/adapters/settings.js.map +1 -0
- package/lib/adapters/skills.d.ts +13 -0
- package/lib/adapters/skills.js +14 -0
- package/lib/adapters/skills.js.map +1 -0
- package/lib/adapters/test-helpers.d.ts +99 -0
- package/lib/adapters/test-helpers.js +192 -0
- package/lib/adapters/test-helpers.js.map +1 -0
- package/lib/adapters/ui.d.ts +26 -0
- package/lib/adapters/ui.js +88 -0
- package/lib/adapters/ui.js.map +1 -0
- package/lib/adapters/workspaces.d.ts +12 -0
- package/lib/adapters/workspaces.js +92 -0
- package/lib/adapters/workspaces.js.map +1 -0
- package/lib/client.d.ts +377 -0
- package/lib/client.js +2598 -0
- package/lib/client.js.map +1 -0
- package/lib/core/analyzer.d.ts +35 -0
- package/lib/core/analyzer.js +563 -0
- package/lib/core/analyzer.js.map +1 -0
- package/lib/core/backup.d.ts +29 -0
- package/lib/core/backup.js +184 -0
- package/lib/core/backup.js.map +1 -0
- package/lib/core/exporter.d.ts +37 -0
- package/lib/core/exporter.js +222 -0
- package/lib/core/exporter.js.map +1 -0
- package/lib/core/importer.d.ts +42 -0
- package/lib/core/importer.js +25 -0
- package/lib/core/importer.js.map +1 -0
- package/lib/core/index.d.ts +12 -0
- package/lib/core/index.js +11 -0
- package/lib/core/index.js.map +1 -0
- package/lib/core/rollback.d.ts +9 -0
- package/lib/core/rollback.js +136 -0
- package/lib/core/rollback.js.map +1 -0
- package/lib/core/types.d.ts +331 -0
- package/lib/core/types.js +18 -0
- package/lib/core/types.js.map +1 -0
- package/lib/core/validator.d.ts +18 -0
- package/lib/core/validator.js +77 -0
- package/lib/core/validator.js.map +1 -0
- package/lib/index.d.ts +51 -0
- package/lib/index.js +875 -0
- package/lib/index.js.map +1 -0
- package/lib/migrations/index.d.ts +29 -0
- package/lib/migrations/index.js +56 -0
- package/lib/migrations/index.js.map +1 -0
- package/lib/migrations/v1-to-v2.d.ts +9 -0
- package/lib/migrations/v1-to-v2.js +10 -0
- package/lib/migrations/v1-to-v2.js.map +1 -0
- package/lib/profiles/index.d.ts +4 -0
- package/lib/profiles/index.js +5 -0
- package/lib/profiles/index.js.map +1 -0
- package/lib/profiles/profile-manager.d.ts +102 -0
- package/lib/profiles/profile-manager.js +522 -0
- package/lib/profiles/profile-manager.js.map +1 -0
- package/lib/schema/config.d.ts +28 -0
- package/lib/schema/config.js +136 -0
- package/lib/schema/config.js.map +1 -0
- package/lib/schema/manifest.d.ts +28 -0
- package/lib/schema/manifest.js +109 -0
- package/lib/schema/manifest.js.map +1 -0
- package/lib/schema/types.d.ts +169 -0
- package/lib/schema/types.js +8 -0
- package/lib/schema/types.js.map +1 -0
- package/lib/schema/versions.d.ts +27 -0
- package/lib/schema/versions.js +50 -0
- package/lib/schema/versions.js.map +1 -0
- package/lib/security/encryption.d.ts +41 -0
- package/lib/security/encryption.js +152 -0
- package/lib/security/encryption.js.map +1 -0
- package/lib/security/index.d.ts +16 -0
- package/lib/security/index.js +17 -0
- package/lib/security/index.js.map +1 -0
- package/lib/security/integrity.d.ts +30 -0
- package/lib/security/integrity.js +78 -0
- package/lib/security/integrity.js.map +1 -0
- package/lib/security/redaction.d.ts +26 -0
- package/lib/security/redaction.js +95 -0
- package/lib/security/redaction.js.map +1 -0
- package/lib/security/secret-scanner.d.ts +48 -0
- package/lib/security/secret-scanner.js +253 -0
- package/lib/security/secret-scanner.js.map +1 -0
- package/lib/security/zip-security.d.ts +27 -0
- package/lib/security/zip-security.js +154 -0
- package/lib/security/zip-security.js.map +1 -0
- package/lib/ui/conflict-view.d.ts +28 -0
- package/lib/ui/conflict-view.js +49 -0
- package/lib/ui/conflict-view.js.map +1 -0
- package/lib/ui/errors.d.ts +17 -0
- package/lib/ui/errors.js +76 -0
- package/lib/ui/errors.js.map +1 -0
- package/lib/ui/export-flow.d.ts +62 -0
- package/lib/ui/export-flow.js +79 -0
- package/lib/ui/export-flow.js.map +1 -0
- package/lib/ui/import-wizard.d.ts +67 -0
- package/lib/ui/import-wizard.js +169 -0
- package/lib/ui/import-wizard.js.map +1 -0
- package/lib/ui/path-mapping.d.ts +38 -0
- package/lib/ui/path-mapping.js +75 -0
- package/lib/ui/path-mapping.js.map +1 -0
- package/lib/ui/progress.d.ts +27 -0
- package/lib/ui/progress.js +76 -0
- package/lib/ui/progress.js.map +1 -0
- package/lib/ui/report.d.ts +21 -0
- package/lib/ui/report.js +146 -0
- package/lib/ui/report.js.map +1 -0
- package/lib/ui/test-helpers.d.ts +62 -0
- package/lib/ui/test-helpers.js +147 -0
- package/lib/ui/test-helpers.js.map +1 -0
- package/lib/ui/types.d.ts +129 -0
- package/lib/ui/types.js +21 -0
- package/lib/ui/types.js.map +1 -0
- package/lib/utils/hashing.d.ts +17 -0
- package/lib/utils/hashing.js +41 -0
- package/lib/utils/hashing.js.map +1 -0
- package/lib/utils/json.d.ts +24 -0
- package/lib/utils/json.js +76 -0
- package/lib/utils/json.js.map +1 -0
- package/lib/utils/logger.d.ts +39 -0
- package/lib/utils/logger.js +82 -0
- package/lib/utils/logger.js.map +1 -0
- package/lib/utils/paths.d.ts +31 -0
- package/lib/utils/paths.js +132 -0
- package/lib/utils/paths.js.map +1 -0
- package/lib/utils/zip.d.ts +54 -0
- package/lib/utils/zip.js +285 -0
- package/lib/utils/zip.js.map +1 -0
- package/package.json +109 -0
- package/src/adapters/agent-presets.ts +14 -0
- package/src/adapters/credentials.test.ts +90 -0
- package/src/adapters/credentials.ts +141 -0
- package/src/adapters/file-collection.ts +110 -0
- package/src/adapters/files.test.ts +113 -0
- package/src/adapters/index.ts +69 -0
- package/src/adapters/mcp.test.ts +96 -0
- package/src/adapters/mcp.ts +181 -0
- package/src/adapters/plugin-files.ts +96 -0
- package/src/adapters/plugins.test.ts +72 -0
- package/src/adapters/plugins.ts +176 -0
- package/src/adapters/prompts.test.ts +110 -0
- package/src/adapters/prompts.ts +226 -0
- package/src/adapters/providers.test.ts +125 -0
- package/src/adapters/providers.ts +161 -0
- package/src/adapters/roundtrip.test.ts +188 -0
- package/src/adapters/sessions.ts +15 -0
- package/src/adapters/settings.test.ts +93 -0
- package/src/adapters/settings.ts +165 -0
- package/src/adapters/skills.ts +14 -0
- package/src/adapters/test-helpers.ts +207 -0
- package/src/adapters/ui.test.ts +56 -0
- package/src/adapters/ui.ts +106 -0
- package/src/adapters/workspaces.test.ts +79 -0
- package/src/adapters/workspaces.ts +95 -0
- package/src/client/CLIENT_DEPENDENCIES.md +101 -0
- package/src/client/ConfigManagerSection.tsx +60 -0
- package/src/client/api.ts +270 -0
- package/src/client/client-types.ts +27 -0
- package/src/client/common/ErrorBanner.tsx +68 -0
- package/src/client/common/ProgressBar.tsx +49 -0
- package/src/client/common/ReportView.tsx +117 -0
- package/src/client/common/ui.tsx +165 -0
- package/src/client/config-manager.module.css +759 -0
- package/src/client/css-modules.d.ts +8 -0
- package/src/client/export/ExportView.tsx +222 -0
- package/src/client/import/ConflictList.tsx +72 -0
- package/src/client/import/ImportWizardView.tsx +406 -0
- package/src/client/import/PathMappingForm.tsx +77 -0
- package/src/client/index.ts +65 -0
- package/src/client/locales.ts +182 -0
- package/src/core/analyzer.ts +631 -0
- package/src/core/backup.ts +212 -0
- package/src/core/exporter.ts +246 -0
- package/src/core/importer.ts +66 -0
- package/src/core/index.ts +39 -0
- package/src/core/rollback.ts +140 -0
- package/src/core/smoke.test.ts +717 -0
- package/src/core/types.ts +343 -0
- package/src/core/validator.ts +84 -0
- package/src/index.ts +942 -0
- package/src/migrations/index.ts +71 -0
- package/src/migrations/v1-to-v2.ts +17 -0
- package/src/profiles/index.ts +8 -0
- package/src/profiles/profile-manager.test.ts +280 -0
- package/src/profiles/profile-manager.ts +606 -0
- package/src/schema/config.ts +137 -0
- package/src/schema/manifest.ts +124 -0
- package/src/schema/types.ts +179 -0
- package/src/schema/versions.ts +55 -0
- package/src/security/encryption.ts +180 -0
- package/src/security/index.ts +16 -0
- package/src/security/integrity.ts +102 -0
- package/src/security/redaction.ts +101 -0
- package/src/security/secret-scanner.ts +275 -0
- package/src/security/security.test.ts +796 -0
- package/src/security/zip-security.ts +180 -0
- package/src/ui/conflict-view.test.ts +62 -0
- package/src/ui/conflict-view.ts +65 -0
- package/src/ui/errors.test.ts +44 -0
- package/src/ui/errors.ts +95 -0
- package/src/ui/export-flow.test.ts +75 -0
- package/src/ui/export-flow.ts +128 -0
- package/src/ui/import-wizard.test.ts +128 -0
- package/src/ui/import-wizard.ts +208 -0
- package/src/ui/path-mapping.test.ts +67 -0
- package/src/ui/path-mapping.ts +103 -0
- package/src/ui/progress.test.ts +42 -0
- package/src/ui/progress.ts +90 -0
- package/src/ui/report.test.ts +93 -0
- package/src/ui/report.ts +140 -0
- package/src/ui/test-helpers.ts +177 -0
- package/src/ui/types.ts +193 -0
- package/src/utils/hashing.ts +53 -0
- package/src/utils/json.ts +77 -0
- package/src/utils/logger.ts +114 -0
- package/src/utils/paths.ts +122 -0
- package/src/utils/zip.ts +332 -0
|
@@ -0,0 +1,192 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 适配器测试基础设施(仿 src/core/smoke.test.ts 的内存 mock 门面)。
|
|
3
|
+
* 仅供 src/adapters/*.test.ts 使用,不参与生产构建语义。
|
|
4
|
+
*/
|
|
5
|
+
import { normalizePath } from "../utils/paths.js";
|
|
6
|
+
import { createLogger } from "../utils/logger.js";
|
|
7
|
+
import { sha256Hex } from "../utils/hashing.js";
|
|
8
|
+
export class MemFs {
|
|
9
|
+
files = new Map();
|
|
10
|
+
homeDir;
|
|
11
|
+
constructor(homeDir) {
|
|
12
|
+
this.homeDir = homeDir;
|
|
13
|
+
}
|
|
14
|
+
key(p) {
|
|
15
|
+
return normalizePath(p.startsWith(this.homeDir) ? p : `${this.homeDir}/${p}`);
|
|
16
|
+
}
|
|
17
|
+
async readFile(relPath) {
|
|
18
|
+
const v = this.files.get(this.key(relPath));
|
|
19
|
+
if (v === undefined)
|
|
20
|
+
throw new Error(`ENOENT: ${relPath}`);
|
|
21
|
+
return v;
|
|
22
|
+
}
|
|
23
|
+
async writeFile(relPath, data) {
|
|
24
|
+
this.files.set(this.key(relPath), data);
|
|
25
|
+
}
|
|
26
|
+
async exists(relPath) {
|
|
27
|
+
return this.files.has(this.key(relPath));
|
|
28
|
+
}
|
|
29
|
+
async copy(from, to) {
|
|
30
|
+
const v = this.files.get(this.key(from));
|
|
31
|
+
if (v === undefined)
|
|
32
|
+
throw new Error(`ENOENT: ${from}`);
|
|
33
|
+
this.files.set(this.key(to), v);
|
|
34
|
+
}
|
|
35
|
+
async remove(relPath) {
|
|
36
|
+
this.files.delete(this.key(relPath));
|
|
37
|
+
}
|
|
38
|
+
async listRecursive(dir) {
|
|
39
|
+
const base = normalizePath(this.homeDir);
|
|
40
|
+
const prefix = normalizePath(dir) === '' ? base : `${base}/${normalizePath(dir)}`;
|
|
41
|
+
const out = [];
|
|
42
|
+
for (const k of this.files.keys()) {
|
|
43
|
+
if (k === prefix || k.startsWith(prefix + '/')) {
|
|
44
|
+
out.push(k.slice(base.length).replace(/^[\\/]+/, ''));
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
return out.sort();
|
|
48
|
+
}
|
|
49
|
+
async mkdir() { }
|
|
50
|
+
}
|
|
51
|
+
export class MemSettings {
|
|
52
|
+
ns = new Map();
|
|
53
|
+
async describe(namespace, _opts) {
|
|
54
|
+
const rec = this.ns.get(namespace);
|
|
55
|
+
if (!rec)
|
|
56
|
+
throw new Error(`namespace not found: ${namespace}`);
|
|
57
|
+
return { value: rec.value, base: rec.base, revision: rec.revision, applies: rec.applies, secrets: rec.secrets };
|
|
58
|
+
}
|
|
59
|
+
async replace(namespace, value, expectedRevision) {
|
|
60
|
+
const rec = this.ns.get(namespace);
|
|
61
|
+
if (expectedRevision !== undefined && rec && rec.revision !== expectedRevision) {
|
|
62
|
+
throw new Error(`SETTINGS_CONFLICT: ${namespace} revision ${rec.revision} !== ${expectedRevision}`);
|
|
63
|
+
}
|
|
64
|
+
this.ns.set(namespace, {
|
|
65
|
+
value, revision: (rec?.revision ?? 0) + 1, secrets: rec?.secrets ?? [], base: rec?.base, applies: rec?.applies,
|
|
66
|
+
});
|
|
67
|
+
}
|
|
68
|
+
async update(namespace, patch, expectedRevision) {
|
|
69
|
+
const rec = this.ns.get(namespace);
|
|
70
|
+
if (expectedRevision !== undefined && rec && rec.revision !== expectedRevision) {
|
|
71
|
+
throw new Error(`SETTINGS_CONFLICT: ${namespace} revision ${rec.revision} !== ${expectedRevision}`);
|
|
72
|
+
}
|
|
73
|
+
const merged = { ...rec?.value, ...patch };
|
|
74
|
+
this.ns.set(namespace, { value: merged, revision: (rec?.revision ?? 0) + 1, secrets: rec?.secrets ?? [] });
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
export class MemCredentials {
|
|
78
|
+
values = new Map();
|
|
79
|
+
async describe(ref) {
|
|
80
|
+
const v = this.values.get(ref);
|
|
81
|
+
return { configured: v !== undefined, source: v !== undefined ? 'file' : 'env', writable: true };
|
|
82
|
+
}
|
|
83
|
+
async set(ref, value) { this.values.set(ref, value); }
|
|
84
|
+
async unset(ref) { this.values.delete(ref); }
|
|
85
|
+
}
|
|
86
|
+
export class MemPlugins {
|
|
87
|
+
installed = new Map();
|
|
88
|
+
async listInstalled() {
|
|
89
|
+
return [...this.installed.values()];
|
|
90
|
+
}
|
|
91
|
+
async install(pkg) {
|
|
92
|
+
if (this.installed.has(pkg))
|
|
93
|
+
return { needsRestart: false };
|
|
94
|
+
this.installed.set(pkg, { name: pkg, version: '1.0.0', enabled: true });
|
|
95
|
+
return { needsRestart: true };
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
export class MemWorkspace {
|
|
99
|
+
records = new Map();
|
|
100
|
+
async listRecords() { return [...this.records.values()]; }
|
|
101
|
+
async writeRecord(r) { this.records.set(r.id, r); }
|
|
102
|
+
async removeRecord(id) { this.records.delete(id); }
|
|
103
|
+
}
|
|
104
|
+
export class MemPatch {
|
|
105
|
+
lines = new Map();
|
|
106
|
+
async readPatchLines(_file) {
|
|
107
|
+
return [...this.lines.values()];
|
|
108
|
+
}
|
|
109
|
+
async applyPatchChanges(_file, changes) {
|
|
110
|
+
for (const c of changes) {
|
|
111
|
+
if (c.action === 'remove')
|
|
112
|
+
this.lines.delete(c.lineId);
|
|
113
|
+
else
|
|
114
|
+
this.lines.set(c.lineId, { lineId: c.lineId, raw: c.raw });
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
export class MemSnapshotStore {
|
|
119
|
+
snapshots = new Map();
|
|
120
|
+
blobs = new Map();
|
|
121
|
+
async save(snapshot, blobs = new Map()) {
|
|
122
|
+
this.snapshots.set(snapshot.id, snapshot);
|
|
123
|
+
for (const [k, v] of blobs)
|
|
124
|
+
this.blobs.set(`${snapshot.id}/${k}`, v);
|
|
125
|
+
return snapshot.id;
|
|
126
|
+
}
|
|
127
|
+
async load(id) {
|
|
128
|
+
const s = this.snapshots.get(id);
|
|
129
|
+
if (!s)
|
|
130
|
+
throw new Error(`snapshot not found: ${id}`);
|
|
131
|
+
return s;
|
|
132
|
+
}
|
|
133
|
+
async readBlob(id, blobPath) {
|
|
134
|
+
const v = this.blobs.get(`${id}/${blobPath}`);
|
|
135
|
+
if (!v)
|
|
136
|
+
throw new Error(`blob not found: ${id}/${blobPath}`);
|
|
137
|
+
return v;
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
export class MockHostContext {
|
|
141
|
+
platform;
|
|
142
|
+
arch = 'x64';
|
|
143
|
+
homeDir;
|
|
144
|
+
dshVersion = '0.1.0-rc.6';
|
|
145
|
+
log;
|
|
146
|
+
settings = new MemSettings();
|
|
147
|
+
credentials = new MemCredentials();
|
|
148
|
+
plugins = new MemPlugins();
|
|
149
|
+
workspace = new MemWorkspace();
|
|
150
|
+
patchFile = new MemPatch();
|
|
151
|
+
fs;
|
|
152
|
+
constructor(platform, homeDir) {
|
|
153
|
+
this.platform = platform;
|
|
154
|
+
this.homeDir = homeDir;
|
|
155
|
+
this.fs = new MemFs(homeDir);
|
|
156
|
+
this.log = createLogger({ level: 'error', sink: () => { } });
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
export function makeContext(platform, homeDir) {
|
|
160
|
+
return new MockHostContext(platform, homeDir);
|
|
161
|
+
}
|
|
162
|
+
/** 构造最小合法 manifest(adapter 单测用;真实 manifest 由 exporter 生成) */
|
|
163
|
+
export function makeManifest(platform = 'win32') {
|
|
164
|
+
return {
|
|
165
|
+
schemaVersion: 1,
|
|
166
|
+
exporter: { name: 'dsh-config-manager-test', version: '0.0.0' },
|
|
167
|
+
source: { dshVersion: '0.1.0-rc.6', platform: platform, arch: 'x64' },
|
|
168
|
+
exportedAt: new Date('2026-08-14T12:00:00.000Z').toISOString(),
|
|
169
|
+
sections: {
|
|
170
|
+
settings: false, ui: false, providers: false, plugins: false, mcp: false, prompts: false,
|
|
171
|
+
skills: false, agentPresets: false, workspaces: false, pluginFiles: false,
|
|
172
|
+
credentialsStatus: false, secrets: false, sessions: false,
|
|
173
|
+
},
|
|
174
|
+
security: { containsSecrets: false, encrypted: false, encryption: null },
|
|
175
|
+
};
|
|
176
|
+
}
|
|
177
|
+
/** 构造 ImportContext(adapter 单测用;sections 键运行时即 SectionId 字符串) */
|
|
178
|
+
export function makeImportContext(target, sections, overrides = {}) {
|
|
179
|
+
return {
|
|
180
|
+
manifest: makeManifest(target.platform),
|
|
181
|
+
targetPlatform: target.platform,
|
|
182
|
+
target,
|
|
183
|
+
sections: sections,
|
|
184
|
+
pathMappings: [],
|
|
185
|
+
resolutions: {},
|
|
186
|
+
secretInputs: {},
|
|
187
|
+
log: target.log,
|
|
188
|
+
...overrides,
|
|
189
|
+
};
|
|
190
|
+
}
|
|
191
|
+
export { sha256Hex };
|
|
192
|
+
//# sourceMappingURL=test-helpers.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"test-helpers.js","sourceRoot":"","sources":["../../src/adapters/test-helpers.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* ui 分区 adapter(设计 §3.3/§4.1/§4.3):
|
|
3
|
+
* 数据源 = settings.yaml 中「UI 类」namespace(pet / dsh-better-sidebar / remote-web-ui / ui-onboarding / skin 等)。
|
|
4
|
+
* localStorage 等 Host 不可迁移的 UI 状态以 uiMigrationNotes 纯说明形式导出(不含任何值)。
|
|
5
|
+
*/
|
|
6
|
+
import type { UiSection } from '../schema/types.ts';
|
|
7
|
+
import type { ApplyResult, ConfigAdapter, ExportOptions, ExportSection, HostContext, ImportContext, PlanItem, ValidationResult } from '../core/types.ts';
|
|
8
|
+
import { type NamespaceProvider } from './settings.ts';
|
|
9
|
+
/** UI 类 namespace 前缀名单(设计 §4.1;随新插件扩展,只影响「某一 namespace 归哪一边」,不影响数据完整性) */
|
|
10
|
+
export declare const KNOWN_UI_NAMESPACE_PREFIXES: readonly string[];
|
|
11
|
+
/** namespace 名是否属于 UI 类(大小写不敏感前缀匹配) */
|
|
12
|
+
export declare function isUiNamespace(name: string): boolean;
|
|
13
|
+
/** localStorage 等 Host 无通道的 UI 状态说明(纯说明,不含值;研究报告 §2.2/§4.4) */
|
|
14
|
+
export declare const UI_MIGRATION_NOTES: UiSection['uiMigrationNotes'];
|
|
15
|
+
export declare class UiAdapter implements ConfigAdapter<UiSection> {
|
|
16
|
+
readonly id: "ui";
|
|
17
|
+
readonly displayName = "UI Preferences";
|
|
18
|
+
readonly defaultIncluded = true;
|
|
19
|
+
readonly portability: "portable";
|
|
20
|
+
private readonly namespaces;
|
|
21
|
+
constructor(namespaces?: string[] | NamespaceProvider);
|
|
22
|
+
export(ctx: HostContext, _options: ExportOptions): Promise<ExportSection<UiSection>>;
|
|
23
|
+
analyzeImport(data: UiSection, ctx: ImportContext): Promise<PlanItem[]>;
|
|
24
|
+
applyItem(item: PlanItem, ctx: ImportContext): Promise<ApplyResult>;
|
|
25
|
+
validate(data: UiSection): Promise<ValidationResult>;
|
|
26
|
+
}
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
import { collectNamespaceRecords, planNamespaceItems, applyNamespaceItem, resolveNamespaces } from "./settings.js";
|
|
2
|
+
/** UI 类 namespace 前缀名单(设计 §4.1;随新插件扩展,只影响「某一 namespace 归哪一边」,不影响数据完整性) */
|
|
3
|
+
export const KNOWN_UI_NAMESPACE_PREFIXES = [
|
|
4
|
+
'pet',
|
|
5
|
+
'dsh-better-sidebar',
|
|
6
|
+
'remote-web-ui',
|
|
7
|
+
'ui-onboarding',
|
|
8
|
+
'dsh-client-ui',
|
|
9
|
+
'skin',
|
|
10
|
+
'theme',
|
|
11
|
+
'layout',
|
|
12
|
+
'sidebar',
|
|
13
|
+
'appearance',
|
|
14
|
+
];
|
|
15
|
+
/** namespace 名是否属于 UI 类(大小写不敏感前缀匹配) */
|
|
16
|
+
export function isUiNamespace(name) {
|
|
17
|
+
const lower = name.toLowerCase();
|
|
18
|
+
return KNOWN_UI_NAMESPACE_PREFIXES.some((p) => lower.startsWith(p.toLowerCase()));
|
|
19
|
+
}
|
|
20
|
+
/** localStorage 等 Host 无通道的 UI 状态说明(纯说明,不含值;研究报告 §2.2/§4.4) */
|
|
21
|
+
export const UI_MIGRATION_NOTES = [
|
|
22
|
+
{
|
|
23
|
+
plugin: 'dsh-task-board',
|
|
24
|
+
storage: 'localStorage',
|
|
25
|
+
key: 'dsh.taskBoard.v1',
|
|
26
|
+
migratable: false,
|
|
27
|
+
reason: '任务看板数据存于浏览器 localStorage,Host 侧无访问通道,需在目标机器重新配置',
|
|
28
|
+
},
|
|
29
|
+
{
|
|
30
|
+
plugin: 'dsh-aionui-panel',
|
|
31
|
+
storage: 'localStorage',
|
|
32
|
+
key: 'aionui-panel.*',
|
|
33
|
+
migratable: false,
|
|
34
|
+
reason: '面板宽度/折叠状态存于浏览器 localStorage,Host 侧无访问通道,需在目标机器重新配置',
|
|
35
|
+
},
|
|
36
|
+
{
|
|
37
|
+
plugin: 'dsh-client-ui-*',
|
|
38
|
+
storage: 'localStorage',
|
|
39
|
+
key: '*',
|
|
40
|
+
migratable: false,
|
|
41
|
+
reason: '浏览器端 UI 状态无法经 Host API 迁移',
|
|
42
|
+
},
|
|
43
|
+
];
|
|
44
|
+
export class UiAdapter {
|
|
45
|
+
id = 'ui';
|
|
46
|
+
displayName = 'UI Preferences';
|
|
47
|
+
defaultIncluded = true;
|
|
48
|
+
portability = 'portable';
|
|
49
|
+
namespaces;
|
|
50
|
+
constructor(namespaces = []) {
|
|
51
|
+
this.namespaces = namespaces;
|
|
52
|
+
}
|
|
53
|
+
async export(ctx, _options) {
|
|
54
|
+
const warnings = [];
|
|
55
|
+
const all = await resolveNamespaces(this.namespaces, ctx);
|
|
56
|
+
const uiNames = all.filter((n) => isUiNamespace(n));
|
|
57
|
+
const namespaces = await collectNamespaceRecords(ctx, uiNames, warnings);
|
|
58
|
+
return {
|
|
59
|
+
sectionId: 'ui',
|
|
60
|
+
data: { version: 1, namespaces, uiMigrationNotes: UI_MIGRATION_NOTES },
|
|
61
|
+
counts: { namespaces: Object.keys(namespaces).length, notes: UI_MIGRATION_NOTES.length },
|
|
62
|
+
warnings,
|
|
63
|
+
};
|
|
64
|
+
}
|
|
65
|
+
async analyzeImport(data, ctx) {
|
|
66
|
+
return planNamespaceItems(data.namespaces, 'ui', ctx);
|
|
67
|
+
}
|
|
68
|
+
async applyItem(item, ctx) {
|
|
69
|
+
return applyNamespaceItem(item, 'ui', ctx);
|
|
70
|
+
}
|
|
71
|
+
async validate(data) {
|
|
72
|
+
const issues = [];
|
|
73
|
+
if (data === null || typeof data !== 'object') {
|
|
74
|
+
return { valid: false, issues: [{ path: '$', message: 'ui 数据必须是对象', severity: 'error' }] };
|
|
75
|
+
}
|
|
76
|
+
if (data.version !== 1) {
|
|
77
|
+
issues.push({ path: 'version', message: `version 必须为 1(收到 ${String(data.version)})`, severity: 'error' });
|
|
78
|
+
}
|
|
79
|
+
if (data.namespaces === null || typeof data.namespaces !== 'object') {
|
|
80
|
+
issues.push({ path: 'namespaces', message: '缺少 namespaces 对象', severity: 'error' });
|
|
81
|
+
}
|
|
82
|
+
if (data.uiMigrationNotes !== undefined && !Array.isArray(data.uiMigrationNotes)) {
|
|
83
|
+
issues.push({ path: 'uiMigrationNotes', message: 'uiMigrationNotes 必须是数组', severity: 'error' });
|
|
84
|
+
}
|
|
85
|
+
return { valid: issues.filter((i) => i.severity === 'error').length === 0, issues };
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
//# sourceMappingURL=ui.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ui.js","sourceRoot":"","sources":["../../src/adapters/ui.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import type { WorkspacesSection } from '../schema/types.ts';
|
|
2
|
+
import type { ApplyResult, ConfigAdapter, ExportOptions, ExportSection, HostContext, ImportContext, PlanItem, ValidationResult } from '../core/types.ts';
|
|
3
|
+
export declare class WorkspacesAdapter implements ConfigAdapter<WorkspacesSection> {
|
|
4
|
+
readonly id: "workspaces";
|
|
5
|
+
readonly displayName = "Workspaces";
|
|
6
|
+
readonly defaultIncluded = true;
|
|
7
|
+
readonly portability: "platformSpecific";
|
|
8
|
+
export(ctx: HostContext, _options: ExportOptions): Promise<ExportSection<WorkspacesSection>>;
|
|
9
|
+
analyzeImport(data: WorkspacesSection, ctx: ImportContext): Promise<PlanItem[]>;
|
|
10
|
+
applyItem(item: PlanItem, ctx: ImportContext): Promise<ApplyResult>;
|
|
11
|
+
validate(data: WorkspacesSection): Promise<ValidationResult>;
|
|
12
|
+
}
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* workspaces 分区 adapter(设计 §3.3/§11):
|
|
3
|
+
* 数据源 = ~/.dsh/storages/workspace.json 的 tables.workspaces(经 ctx.workspace 门面)。
|
|
4
|
+
* workspace.path 为绝对路径 → 跨设备必须 PathMapping(analyzeImport 生成 PathMapping 项,
|
|
5
|
+
* 映射由引擎 PathMapper 先行应用到 sections,applyItem 拿到的已是映射后数据)。
|
|
6
|
+
*/
|
|
7
|
+
import { isDeepStrictEqual } from 'node:util';
|
|
8
|
+
export class WorkspacesAdapter {
|
|
9
|
+
id = 'workspaces';
|
|
10
|
+
displayName = 'Workspaces';
|
|
11
|
+
defaultIncluded = true;
|
|
12
|
+
portability = 'platformSpecific';
|
|
13
|
+
async export(ctx, _options) {
|
|
14
|
+
const records = await ctx.workspace.listRecords();
|
|
15
|
+
return {
|
|
16
|
+
sectionId: 'workspaces',
|
|
17
|
+
data: { version: 1, workspaces: records },
|
|
18
|
+
counts: { workspaces: records.length },
|
|
19
|
+
warnings: [],
|
|
20
|
+
};
|
|
21
|
+
}
|
|
22
|
+
async analyzeImport(data, ctx) {
|
|
23
|
+
const items = [];
|
|
24
|
+
for (const rec of data.workspaces) {
|
|
25
|
+
const id = `workspace:${rec.id}`;
|
|
26
|
+
const existing = (await ctx.target.workspace.listRecords()).find((r) => r.id === rec.id);
|
|
27
|
+
if (!existing) {
|
|
28
|
+
items.push({
|
|
29
|
+
id, kind: 'Create', adapter: 'workspaces',
|
|
30
|
+
description: `创建工作区 ${rec.title ?? rec.id}(${rec.path})`, severity: 'info',
|
|
31
|
+
target: { adapter: 'workspaces', ref: rec.id },
|
|
32
|
+
});
|
|
33
|
+
}
|
|
34
|
+
else if (isDeepStrictEqual(existing, rec)) {
|
|
35
|
+
items.push({ id, kind: 'Skip', adapter: 'workspaces', description: `工作区 ${rec.id} 已一致`, severity: 'info' });
|
|
36
|
+
}
|
|
37
|
+
else {
|
|
38
|
+
items.push({
|
|
39
|
+
id, kind: 'Conflict', adapter: 'workspaces',
|
|
40
|
+
description: `工作区 ${rec.id} 与目标不同`,
|
|
41
|
+
detail: `current=${JSON.stringify(existing)} imported=${JSON.stringify(rec)}`.slice(0, 200),
|
|
42
|
+
severity: 'warning', target: { adapter: 'workspaces', ref: rec.id },
|
|
43
|
+
});
|
|
44
|
+
}
|
|
45
|
+
// 绝对路径 → 路径映射提示(oldPrefix 先用整条路径占位,newPrefix 由 UI 确认)
|
|
46
|
+
if (rec.path.startsWith('/') || /^[a-zA-Z]:[\\/]/.test(rec.path)) {
|
|
47
|
+
items.push({
|
|
48
|
+
id: `${id}:path`, kind: 'PathMapping', adapter: 'workspaces',
|
|
49
|
+
description: `路径需映射: ${rec.path}`, severity: 'warning',
|
|
50
|
+
pathMapping: { oldPrefix: rec.path, newPrefix: '', appliesTo: ['workspaces'] },
|
|
51
|
+
target: { adapter: 'workspaces', ref: rec.id },
|
|
52
|
+
});
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
return items;
|
|
56
|
+
}
|
|
57
|
+
async applyItem(item, ctx) {
|
|
58
|
+
// PathMapping 项:数据已由 PathMapper 应用到 sections,无需额外写入
|
|
59
|
+
if (item.kind === 'PathMapping')
|
|
60
|
+
return { ok: true };
|
|
61
|
+
const ref = item.target?.ref;
|
|
62
|
+
if (!ref)
|
|
63
|
+
return { ok: false, message: '缺少 target.ref' };
|
|
64
|
+
const data = ctx.sections.get('workspaces');
|
|
65
|
+
const rec = data?.workspaces.find((r) => r.id === ref);
|
|
66
|
+
if (!rec)
|
|
67
|
+
return { ok: false, message: `导入数据缺少工作区 ${ref}` };
|
|
68
|
+
await ctx.target.workspace.writeRecord(rec);
|
|
69
|
+
return { ok: true };
|
|
70
|
+
}
|
|
71
|
+
async validate(data) {
|
|
72
|
+
const issues = [];
|
|
73
|
+
if (data === null || typeof data !== 'object') {
|
|
74
|
+
return { valid: false, issues: [{ path: '$', message: 'workspaces 数据必须是对象', severity: 'error' }] };
|
|
75
|
+
}
|
|
76
|
+
if (data.version !== 1) {
|
|
77
|
+
issues.push({ path: 'version', message: `version 必须为 1(收到 ${String(data.version)})`, severity: 'error' });
|
|
78
|
+
}
|
|
79
|
+
if (!Array.isArray(data.workspaces)) {
|
|
80
|
+
issues.push({ path: 'workspaces', message: 'workspaces 必须是数组', severity: 'error' });
|
|
81
|
+
}
|
|
82
|
+
else {
|
|
83
|
+
for (const w of data.workspaces) {
|
|
84
|
+
if (w === null || typeof w !== 'object' || typeof w.id !== 'string' || typeof w.path !== 'string') {
|
|
85
|
+
issues.push({ path: 'workspaces[]', message: 'workspace 记录必须含字符串 id 与 path', severity: 'error' });
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
return { valid: issues.filter((i) => i.severity === 'error').length === 0, issues };
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
//# sourceMappingURL=workspaces.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"workspaces.js","sourceRoot":"","sources":["../../src/adapters/workspaces.ts"],"names":[],"mappings":"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"}
|