dsh-server-connector 0.2.3 → 0.3.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/CHANGELOG.md +72 -0
- package/LICENSE +0 -0
- package/README.md +49 -7
- package/cordis.patch.yml +6 -6
- package/icon.svg +15 -15
- package/lib/audit.js +469 -455
- package/lib/client.js +2389 -1728
- package/lib/config.js +89 -0
- package/lib/index.js +316 -266
- package/lib/known-hosts.js +377 -377
- package/lib/pending.js +766 -753
- package/lib/policy.js +590 -590
- package/lib/pool.js +1496 -1464
- package/lib/registry.js +968 -968
- package/lib/routes.js +14 -13
- package/lib/tools.js +1367 -1357
- package/locale/en.json +6 -6
- package/locale/zh.json +6 -6
- package/package.json +105 -105
package/lib/config.js
ADDED
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
// dsh-server-connector — the global configuration (doc §10), as live data.
|
|
2
|
+
//
|
|
3
|
+
// Why this unit exists
|
|
4
|
+
// --------------------
|
|
5
|
+
// Every key of the plugin's `Config` is `.volatile()` (see `lib/index.js`), and
|
|
6
|
+
// that is what makes the settings page editable at all: DSH projects a plugin
|
|
7
|
+
// row into a settings form only through `volatileForm()`, which keeps a field
|
|
8
|
+
// only when it is marked volatile (`dsh-settings/lib/index.js`). Without a
|
|
9
|
+
// single volatile field the whole schema projects to `undefined`, the namespace
|
|
10
|
+
// never appears in `settings.describe()`, and `ctx.configForms.get(<row id>)`
|
|
11
|
+
// stays `unavailable` — which is exactly why this plugin's settings page used to
|
|
12
|
+
// render nine read-only numbers.
|
|
13
|
+
//
|
|
14
|
+
// A volatile field does not resolve to its value: schemastery wraps it with
|
|
15
|
+
// cosmokit's `createVolatile(default)`, the loader writes an edit **into that
|
|
16
|
+
// same cell** and emits `loader/volatile-update` instead of remounting the
|
|
17
|
+
// plugin. So the config object handed to `apply()` is a live view, and every
|
|
18
|
+
// consumer has to read through {@link readConfig} at the moment it uses a value.
|
|
19
|
+
// Snapshotting it at construction time is the bug this unit exists to prevent.
|
|
20
|
+
|
|
21
|
+
/** The documented §10 defaults, in one place. */
|
|
22
|
+
export const CONFIG_DEFAULTS = Object.freeze({
|
|
23
|
+
connectTimeoutMs: 15000,
|
|
24
|
+
commandTimeoutMs: 60000,
|
|
25
|
+
syncTimeoutMs: 20000,
|
|
26
|
+
maxOutputChars: 200000,
|
|
27
|
+
idleTimeoutMs: 600000,
|
|
28
|
+
auditEnabled: true,
|
|
29
|
+
auditMaxBytes: 0,
|
|
30
|
+
pendingTtlHours: 24,
|
|
31
|
+
maxListedServers: 8,
|
|
32
|
+
})
|
|
33
|
+
|
|
34
|
+
/** The nine key names, in schema order; the settings form and the tests read this. */
|
|
35
|
+
export const CONFIG_KEYS = /** @type {Array<keyof import('./index.js').PluginConfig>} */ (Object.keys(CONFIG_DEFAULTS))
|
|
36
|
+
|
|
37
|
+
/**
|
|
38
|
+
* Unwrap one configuration value.
|
|
39
|
+
*
|
|
40
|
+
* A `.volatile()` schema field resolves to a cosmokit cell (`{get()}`) rather
|
|
41
|
+
* than to its value, and the loader mutates that cell in place when the user
|
|
42
|
+
* edits the field. A plain value — a test's hand-built settings object, or an
|
|
43
|
+
* older host that resolved the schema itself — passes through untouched, so
|
|
44
|
+
* every caller may read through here unconditionally.
|
|
45
|
+
* @param {unknown} value
|
|
46
|
+
* @returns {unknown}
|
|
47
|
+
*/
|
|
48
|
+
export function unbox(value) {
|
|
49
|
+
if (value === null || typeof value !== 'object') return value
|
|
50
|
+
const candidate = /** @type {{get?: unknown}} */ (value)
|
|
51
|
+
if (typeof candidate.get !== 'function') return value
|
|
52
|
+
try {
|
|
53
|
+
return /** @type {{get: () => unknown}} */ (candidate).get()
|
|
54
|
+
} catch {
|
|
55
|
+
return undefined
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
/**
|
|
60
|
+
* Read the nine §10 values as plain data.
|
|
61
|
+
*
|
|
62
|
+
* The result is a *snapshot*: never cache it across turns. Call this where the
|
|
63
|
+
* value is used, so a live edit takes effect without a remount.
|
|
64
|
+
*
|
|
65
|
+
* The parameter is deliberately loose (`Record<string, unknown>`): the object a
|
|
66
|
+
* `Config` instance produces holds volatile *cells*, not values, so a stricter
|
|
67
|
+
* signature would make every caller cast.
|
|
68
|
+
* @param {Record<string, unknown>|null|undefined} config - the row config (volatile cells or plain values).
|
|
69
|
+
* @returns {import('./index.js').PluginConfig}
|
|
70
|
+
*/
|
|
71
|
+
export function readConfig(config) {
|
|
72
|
+
const source = config ?? {}
|
|
73
|
+
/** @param {keyof import('./index.js').PluginConfig} key */
|
|
74
|
+
const pick = (key) => {
|
|
75
|
+
const value = unbox(source[key])
|
|
76
|
+
return value === undefined || value === null ? CONFIG_DEFAULTS[key] : value
|
|
77
|
+
}
|
|
78
|
+
return {
|
|
79
|
+
connectTimeoutMs: /** @type {number} */ (pick('connectTimeoutMs')),
|
|
80
|
+
commandTimeoutMs: /** @type {number} */ (pick('commandTimeoutMs')),
|
|
81
|
+
syncTimeoutMs: /** @type {number} */ (pick('syncTimeoutMs')),
|
|
82
|
+
maxOutputChars: /** @type {number} */ (pick('maxOutputChars')),
|
|
83
|
+
idleTimeoutMs: /** @type {number} */ (pick('idleTimeoutMs')),
|
|
84
|
+
auditEnabled: /** @type {boolean} */ (pick('auditEnabled')),
|
|
85
|
+
auditMaxBytes: /** @type {number} */ (pick('auditMaxBytes')),
|
|
86
|
+
pendingTtlHours: /** @type {number} */ (pick('pendingTtlHours')),
|
|
87
|
+
maxListedServers: /** @type {number} */ (pick('maxListedServers')),
|
|
88
|
+
}
|
|
89
|
+
}
|