dsh-connect 0.9.0 → 0.9.2

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 (54) hide show
  1. package/README.i18n.yaml +2 -2
  2. package/README.md +119 -18
  3. package/README.zh.md +87 -13
  4. package/client/client.js +18 -15
  5. package/client/client.js.map +2 -2
  6. package/client/settings-client.mjs +22 -13
  7. package/lib/channels/dingtalk/index.d.ts +49 -49
  8. package/lib/channels/dingtalk/index.d.ts.map +1 -1
  9. package/lib/channels/feishu/adapter.d.ts +8 -1
  10. package/lib/channels/feishu/adapter.d.ts.map +1 -1
  11. package/lib/channels/feishu/adapter.js +120 -39
  12. package/lib/channels/feishu/adapter.js.map +1 -1
  13. package/lib/channels/feishu/index.d.ts +27 -27
  14. package/lib/channels/feishu/index.d.ts.map +1 -1
  15. package/lib/channels/telegram/index.d.ts +13 -13
  16. package/lib/channels/telegram/index.d.ts.map +1 -1
  17. package/lib/channels/web/adapter.d.ts +3 -1
  18. package/lib/channels/web/adapter.d.ts.map +1 -1
  19. package/lib/channels/web/adapter.js +3 -1
  20. package/lib/channels/web/adapter.js.map +1 -1
  21. package/lib/channels/web/index.d.ts +5 -5
  22. package/lib/channels/web/index.d.ts.map +1 -1
  23. package/lib/index.d.ts +42 -58
  24. package/lib/index.d.ts.map +1 -1
  25. package/lib/index.js +162 -57
  26. package/lib/index.js.map +1 -1
  27. package/lib/interaction.d.ts +90 -50
  28. package/lib/interaction.d.ts.map +1 -1
  29. package/lib/interaction.js +233 -272
  30. package/lib/interaction.js.map +1 -1
  31. package/lib/retry.d.ts.map +1 -1
  32. package/lib/retry.js +7 -1
  33. package/lib/retry.js.map +1 -1
  34. package/lib/service.d.ts.map +1 -1
  35. package/lib/service.js +0 -2
  36. package/lib/service.js.map +1 -1
  37. package/lib/settings/legacy-import.d.ts +190 -0
  38. package/lib/settings/legacy-import.d.ts.map +1 -0
  39. package/lib/settings/legacy-import.js +373 -0
  40. package/lib/settings/legacy-import.js.map +1 -0
  41. package/lib/settings/namespace.d.ts +204 -116
  42. package/lib/settings/namespace.d.ts.map +1 -1
  43. package/lib/settings/namespace.js +235 -148
  44. package/lib/settings/namespace.js.map +1 -1
  45. package/lib/settings/settings-model.d.ts.map +1 -1
  46. package/lib/settings/settings-model.js +10 -1
  47. package/lib/settings/settings-model.js.map +1 -1
  48. package/lib/settings/settings-service.d.ts +13 -0
  49. package/lib/settings/settings-service.d.ts.map +1 -1
  50. package/lib/settings/settings-service.js +73 -4
  51. package/lib/settings/settings-service.js.map +1 -1
  52. package/lib/types.d.ts +14 -1
  53. package/lib/types.d.ts.map +1 -1
  54. package/package.json +12 -11
@@ -0,0 +1,373 @@
1
+ /**
2
+ * One-shot migration of the pre-0.2 pane settings into the `connect` profile entry.
3
+ *
4
+ * Before 0.2 this plugin's pane settings lived in `$DSH_HOME/settings.yaml`
5
+ * under a `dsh-connect:` section, keyed by plugin *name*. The 0.2 host does not
6
+ * know that section and will not import it: `SettingsForms.importLegacyDocument()`
7
+ * renames the document to `settings.yaml.imported` and then calls
8
+ * `update(section, values)` for every top-level section, where the only renamed
9
+ * keys are the base-bundle ones (`ui-onboarding` → `ui-settings-general`, …).
10
+ * `dsh-connect` reaches `update("dsh-connect", …)` — an entry that does not
11
+ * exist — and is dropped with a warning. The user's channels keep working (their
12
+ * config is in the profile patch) but every pane-only choice silently reverts to
13
+ * its default the first time the pane is opened. This module recovers it.
14
+ *
15
+ * Three properties make the migration safe to run unattended:
16
+ *
17
+ * - **It merges, it does not replace.** `SettingsForms.replace()` resets every
18
+ * live field to its *inherited* layer and then applies the supplied ones, so a
19
+ * section carrying only the legacy keys would clear every pane field the
20
+ * legacy document happens not to mention — `channels` included, which is how a
21
+ * migration ends up disabling every adapter. The section handed to
22
+ * `replace()` is therefore always complete: what is in force now, with the
23
+ * legacy values layered on top.
24
+ * - **It is one-shot.** A marker beside the profile entry records that the
25
+ * import ran, including the benign "there was nothing to import" case, so the
26
+ * legacy document is never re-applied over later user edits. Nothing is marked
27
+ * unless the outcome is final: a document that is missing is marked, a document
28
+ * that is *there but unreadable* is not (see `LegacySkipReason`).
29
+ * - **It never blocks or breaks the load.** A missing parser, an unparseable
30
+ * document or a refused write degrades to one warning line and leaves both
31
+ * files untouched for a retry after the cause is fixed.
32
+ *
33
+ * Secrets cannot travel through it: the legacy section is projected by
34
+ * `sectionOf()`, which keeps declared non-secret keys only, and a parse failure
35
+ * is reported without quoting the document (a YAML error message contains the
36
+ * offending source lines, and the section it would quote holds an `appSecret`).
37
+ * Anything else in that file stays where it is.
38
+ * @module dsh-connect/settings/legacy-import
39
+ */
40
+ import { mkdirSync, readFileSync, writeFileSync } from "node:fs";
41
+ import { homedir } from "node:os";
42
+ import { dirname, join } from "node:path";
43
+ import { LEGACY_CONNECT_SECTION, mergeSections, sectionOf } from "./namespace.js";
44
+ /**
45
+ * Name of the one-shot marker written beside the profile entry.
46
+ *
47
+ * Namespaced and dotted rather than a plain `${patchPath}.legacy-imported`
48
+ * because the profile directory is shared: every plugin's entry lives in that
49
+ * one `cordis.patch.yml`, so a bare suffix would be a file every plugin with a
50
+ * migration of its own would fight over — and the first one to write it would
51
+ * silently cancel the others.
52
+ */
53
+ export const LEGACY_IMPORT_MARKER = ".dsh-connect-legacy-imported";
54
+ /**
55
+ * Resolve the Harness home with the same precedence as the host's own
56
+ * `resolveDshHome()`: an explicit path (the host hands us `profileContext.home`,
57
+ * which also covers a configured non-env home), then `$DSH_HOME` — whitespace
58
+ * only counts as unset, so a blank override never resolves the home to the
59
+ * filesystem root — then `~/.dsh`. A `~` in either of the first two is expanded.
60
+ */
61
+ export function resolveHarnessHome(explicit) {
62
+ const usable = (value) => typeof value === "string" && value.trim().length > 0;
63
+ if (usable(explicit))
64
+ return expandHome(explicit);
65
+ if (usable(process.env.DSH_HOME))
66
+ return expandHome(process.env.DSH_HOME);
67
+ return join(homedir(), ".dsh");
68
+ }
69
+ /**
70
+ * Trim, and expand a leading `~` the way a shell would.
71
+ *
72
+ * `DSH_HOME=~/.dsh` is a natural thing to write in a shell profile and a
73
+ * perfectly literal string to Node: left alone, the migration reads a directory
74
+ * named `~` under the process cwd, finds nothing there, and marks itself done —
75
+ * silently, permanently, against a home that does not exist. Only the two `~`
76
+ * forms are rewritten, so an absolute path is returned exactly as it was given
77
+ * (which is also what keeps `profileContext.home` whole).
78
+ */
79
+ function expandHome(value) {
80
+ const trimmed = value.trim();
81
+ if (trimmed === "~")
82
+ return homedir();
83
+ if (trimmed.startsWith("~/") || trimmed.startsWith("~\\"))
84
+ return join(homedir(), trimmed.slice(2));
85
+ return trimmed;
86
+ }
87
+ /**
88
+ * The documents to try, in order.
89
+ *
90
+ * `settings.yaml` first: if the host has not run its own legacy import yet, the
91
+ * section is still there. Then `settings.yaml.imported`, which is where the host
92
+ * puts the document after renaming it — the read has to tolerate both because
93
+ * the host's import waits for the loader to settle and may run before or after
94
+ * ours. Finally the JSON state file this plugin used as its own fallback store:
95
+ * its values are unreachable once the live peer exists (`settings-service`
96
+ * prefers `live.read()` whenever it is present), so a user who only ever saved
97
+ * through the fallback path would otherwise lose them silently. That file is
98
+ * written flat — `persist()` stringifies the config itself, with no
99
+ * `dsh-connect` wrapper — so it is read as a section, not as a document.
100
+ */
101
+ export function legacyCandidates(options) {
102
+ const home = resolveHarnessHome(options.home);
103
+ const candidates = [
104
+ { path: join(home, "settings.yaml"), shape: "document" },
105
+ { path: join(home, "settings.yaml.imported"), shape: "document" },
106
+ ];
107
+ if (typeof options.statePath === "string" && options.statePath.trim().length > 0) {
108
+ candidates.push({ path: options.statePath, shape: "section" });
109
+ }
110
+ return candidates;
111
+ }
112
+ /**
113
+ * Where the one-shot marker goes: beside the profile entry this import writes to.
114
+ *
115
+ * The anchor matters more than it looks. The marker means "this *profile entry*
116
+ * has already consumed the home's legacy document", so it has to move exactly
117
+ * when that entry moves and not otherwise:
118
+ *
119
+ * - **Not the state file.** `${statePath}.legacy-imported` — what this did until
120
+ * 0.9.2 — hangs off a path the user controls (`stateDir`, the
121
+ * `DSH_CONNECT_STATE_DIR` override, `settingsStatePath`) and can delete. Move
122
+ * the state directory, or delete one JSON file, and the next boot believes no
123
+ * import ever ran, re-reads `settings.yaml.imported` (the host's rename keeps
124
+ * the `dsh-connect:` section intact) and layers the legacy values back over
125
+ * everything changed in the pane since. That is the one outcome the marker
126
+ * exists to prevent, reachable by tidying up a directory.
127
+ * - **Not the harness home.** `$DSH_HOME` is shared by every profile, so a
128
+ * marker there would let a second profile skip an import it never ran. The
129
+ * profile directory is per-profile; it only moves if the profile itself does,
130
+ * which is the one case where re-importing is right.
131
+ *
132
+ * The state-file suffix survives as a fallback for a caller with no entry path
133
+ * (a host too old to hand one over), where it is still better than no marker.
134
+ */
135
+ export function legacyMarkerPath(options) {
136
+ if (typeof options.markerPath === "string" && options.markerPath.trim().length > 0)
137
+ return options.markerPath;
138
+ if (typeof options.entryPath === "string" && options.entryPath.trim().length > 0) {
139
+ return join(dirname(options.entryPath), LEGACY_IMPORT_MARKER);
140
+ }
141
+ if (typeof options.statePath === "string" && options.statePath.trim().length > 0) {
142
+ return `${options.statePath}.legacy-imported`;
143
+ }
144
+ return undefined;
145
+ }
146
+ /**
147
+ * Read a file, telling "not there" apart from "could not be read".
148
+ *
149
+ * Only `ENOENT` and `ENOTDIR` count as absence — `ENOTDIR` because pointing the
150
+ * home at a regular file makes every child path under it yield that code, which
151
+ * is an absence just as much as a missing directory is. Everything else
152
+ * (permissions, a path that is a directory, an I/O error) is a failure the
153
+ * caller must not mistake for an absence: see `LegacySkipReason`.
154
+ */
155
+ function readFileOutcome(path) {
156
+ try {
157
+ return { kind: "text", text: readFileSync(path, "utf8") };
158
+ }
159
+ catch (error) {
160
+ const code = error?.code;
161
+ if (code === "ENOENT" || code === "ENOTDIR")
162
+ return { kind: "absent" };
163
+ return { kind: "unreadable", detail: message(error) };
164
+ }
165
+ }
166
+ /**
167
+ * A parse failure described without quoting the document.
168
+ *
169
+ * The `yaml` package's error message carries the offending source *lines*, and
170
+ * the document being parsed is the one holding `appSecret` — so reporting it
171
+ * verbatim would copy a credential into a boot warning. Its `code` and position
172
+ * are everything a user needs to find the fault in a file they already have
173
+ * open, so those are what is reported. Anything else keeps its first line only,
174
+ * for the same reason.
175
+ */
176
+ function parseFailureDetail(error) {
177
+ if (typeof error === "object" && error !== null) {
178
+ const { code, linePos } = error;
179
+ if (typeof code === "string") {
180
+ const at = linePos?.[0];
181
+ return at === undefined ? code : `${code} at line ${at.line}, column ${at.col}`;
182
+ }
183
+ }
184
+ return message(error).split("\n", 1)[0] ?? "";
185
+ }
186
+ /** Parse YAML/JSON text, or throw a message fit for the warning line. */
187
+ async function parseDocument(source) {
188
+ let parser;
189
+ try {
190
+ parser = (await import("yaml"));
191
+ }
192
+ catch (error) {
193
+ throw new TaggedError("parser-missing", `the "yaml" package is unavailable (${message(error)})`);
194
+ }
195
+ try {
196
+ return parser.parse(source);
197
+ }
198
+ catch (error) {
199
+ throw new TaggedError("unparseable", parseFailureDetail(error));
200
+ }
201
+ }
202
+ /** An error carrying the outcome it should produce. */
203
+ class TaggedError extends Error {
204
+ tag;
205
+ constructor(tag, detail) {
206
+ super(detail);
207
+ this.tag = tag;
208
+ }
209
+ }
210
+ function message(error) {
211
+ return error instanceof Error ? error.message : String(error);
212
+ }
213
+ function isPlainObject(value) {
214
+ return typeof value === "object" && value !== null && !Array.isArray(value);
215
+ }
216
+ /**
217
+ * Project an object that *is* a pane section onto the declared keys, or
218
+ * `undefined` when nothing usable is left.
219
+ *
220
+ * `defaultChannels: false` because every caller here is reading a *source*, not
221
+ * writing: an absent `channels` key must stay absent so the in-force value keeps
222
+ * applying. The caller decides what to do about the omissions — which, given
223
+ * `mergeSections`, means the current list survives.
224
+ */
225
+ function projectSection(raw) {
226
+ if (!isPlainObject(raw))
227
+ return undefined;
228
+ const section = sectionOf(raw, { defaultChannels: false });
229
+ return Object.keys(section).length > 0 ? section : undefined;
230
+ }
231
+ /**
232
+ * Extract the pane section from a parsed `settings.yaml`-style document: the
233
+ * `dsh-connect` mapping, projected onto declared keys, or `undefined` when the
234
+ * document has no such section (or carries nothing usable under it).
235
+ */
236
+ export function sectionFromDocument(document) {
237
+ if (!isPlainObject(document))
238
+ return undefined;
239
+ return projectSection(document[LEGACY_CONNECT_SECTION]);
240
+ }
241
+ /**
242
+ * Extract the pane section from this plugin's own JSON state file, whose top
243
+ * level is already the section. A `dsh-connect` wrapper is tolerated as well,
244
+ * since pasting values across from the host document is a natural thing to have
245
+ * done — but the flat form is the one the file is actually written in.
246
+ */
247
+ export function sectionOfStateDocument(document) {
248
+ if (!isPlainObject(document))
249
+ return undefined;
250
+ const nested = document[LEGACY_CONNECT_SECTION];
251
+ return projectSection(isPlainObject(nested) ? nested : document);
252
+ }
253
+ /**
254
+ * Record that the import ran.
255
+ *
256
+ * Best effort — a read-only home must not fail the boot — but not silent: the
257
+ * failure is not the harmless one it looks like. Without the marker the next
258
+ * start re-runs the whole migration, and a re-run layers the legacy values back
259
+ * over everything the user has changed in the pane since. The import it belongs
260
+ * to did its job; saying so is the difference between a user who can look at
261
+ * that warning and one whose settings revert on the next restart for no visible
262
+ * reason.
263
+ */
264
+ function markAndReport(marker, body, warn) {
265
+ try {
266
+ mkdirSync(dirname(marker), { recursive: true });
267
+ writeFileSync(marker, body, "utf8");
268
+ }
269
+ catch (error) {
270
+ warn(`could not write the one-shot import marker at ${marker} (${message(error)}); ` +
271
+ `the migration will run again on the next start and may re-apply the legacy settings over newer pane changes`);
272
+ }
273
+ }
274
+ /**
275
+ * Import the pre-0.2 pane settings into the profile entry, once.
276
+ *
277
+ * Never rejects: every failure path is reported through the returned result and
278
+ * (for the ones a user can act on) a single warning line.
279
+ */
280
+ export async function importLegacySection(options) {
281
+ const { write, current, logger } = options;
282
+ const warn = (text) => logger?.warn?.(`connect: ${text}`);
283
+ const marker = legacyMarkerPath(options);
284
+ if (marker !== undefined) {
285
+ const seen = readFileOutcome(marker);
286
+ if (seen.kind === "unreadable") {
287
+ // Treated as present rather than absent on purpose: re-running would layer
288
+ // the legacy values back over whatever the user has changed since, which is
289
+ // the one outcome the marker exists to prevent.
290
+ warn(`the import marker at ${marker} could not be read (${seen.detail}); treating the one-shot migration as already done rather than re-applying the legacy settings over newer changes`);
291
+ return { imported: false, skipped: "already-imported" };
292
+ }
293
+ if (seen.kind === "text")
294
+ return { imported: false, skipped: "already-imported" };
295
+ }
296
+ if (write === undefined) {
297
+ // No store to write to. Nothing is marked, so a host that gains a settings
298
+ // service later still gets the migration.
299
+ return { imported: false, skipped: "not-live" };
300
+ }
301
+ const reads = legacyCandidates(options).map((candidate) => ({ candidate, read: readFileOutcome(candidate.path) }));
302
+ const unreadable = reads.flatMap((entry) => entry.read.kind === "unreadable" ? [{ path: entry.candidate.path, detail: entry.read.detail }] : []);
303
+ if (unreadable.length > 0) {
304
+ // Deliberately not folded into `no-document`: this is the one branch where
305
+ // the user's settings may be sitting in a file we failed to open, so nothing
306
+ // is imported *and nothing is marked* — the next start tries again. Saying
307
+ // which file and why is the whole point of splitting the outcome; the usual
308
+ // causes are a permission, a path that is not what it looks like (a directory
309
+ // named `settings.yaml`), or a `~` nobody expanded.
310
+ for (const entry of unreadable) {
311
+ warn(`could not read the legacy settings candidate at ${entry.path} (${entry.detail}); nothing was imported and nothing was marked, so the migration retries on the next start`);
312
+ }
313
+ return { imported: false, skipped: "unreadable" };
314
+ }
315
+ if (reads.every((entry) => entry.read.kind === "absent")) {
316
+ if (marker !== undefined)
317
+ markAndReport(marker, `dsh-connect: no legacy settings document found\n`, warn);
318
+ return { imported: false, skipped: "no-document" };
319
+ }
320
+ let source;
321
+ let legacy;
322
+ for (const { candidate, read } of reads) {
323
+ if (read.kind !== "text")
324
+ continue;
325
+ let document;
326
+ try {
327
+ document = await parseDocument(read.text);
328
+ }
329
+ catch (error) {
330
+ // A malformed document stops the whole migration rather than falling
331
+ // through to the next candidate. The next *document* is the same file the
332
+ // host renamed, so it is a stale copy of the one that just failed, and the
333
+ // state file holds the same user's older settings — importing either in
334
+ // place of the section the user is looking at would be a silent
335
+ // substitution, and the one they would least expect. Nothing is marked, so
336
+ // fixing the file and restarting retries the whole thing.
337
+ const tag = error instanceof TaggedError ? error.tag : "unparseable";
338
+ warn(tag === "parser-missing"
339
+ ? `the legacy settings at ${candidate.path} were not imported: ${message(error)}; reinstall dsh-connect to restore the migration`
340
+ : `the legacy settings at ${candidate.path} could not be parsed (${message(error)}); the ${LEGACY_CONNECT_SECTION} section was left in place — fix it and restart to import it`);
341
+ return { imported: false, skipped: tag };
342
+ }
343
+ const found = candidate.shape === "section" ? sectionOfStateDocument(document) : sectionFromDocument(document);
344
+ if (found !== undefined) {
345
+ source = candidate.path;
346
+ legacy = found;
347
+ break;
348
+ }
349
+ }
350
+ if (legacy === undefined || source === undefined) {
351
+ if (marker !== undefined) {
352
+ markAndReport(marker, `dsh-connect: no ${LEGACY_CONNECT_SECTION} section to import\n`, warn);
353
+ }
354
+ return { imported: false, skipped: "no-section" };
355
+ }
356
+ // Complete section: what is in force now, with the legacy values on top. See
357
+ // the module doc — a partial section would reset every field it omits.
358
+ const section = mergeSections(current, legacy);
359
+ try {
360
+ await write(section);
361
+ }
362
+ catch (error) {
363
+ warn(`could not import the legacy ${LEGACY_CONNECT_SECTION} settings from ${source} into this plugin's profile entry (${message(error)}); ` +
364
+ `the section was left in place — fix the cause and restart to import it`);
365
+ return { imported: false, source, skipped: "write-failed" };
366
+ }
367
+ if (marker !== undefined) {
368
+ markAndReport(marker, `dsh-connect: imported the ${LEGACY_CONNECT_SECTION} section from ${source}\n`, warn);
369
+ }
370
+ logger?.info?.(`connect: imported the legacy ${LEGACY_CONNECT_SECTION} settings from ${source}`);
371
+ return { imported: true, source, section };
372
+ }
373
+ //# sourceMappingURL=legacy-import.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"legacy-import.js","sourceRoot":"","sources":["../../src/settings/legacy-import.ts"],"names":[],"mappings":"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"}