Commit d4c565e
* feat(plugins): auto-generate admin settings UI from settingsSchema
Plugins that declare `admin.settingsSchema` in definePlugin() now get
an auto-generated settings form in the admin, reachable via a gear
icon on the plugin card. Values persist to the plugin's KV store
(`settings:` prefix); secrets are write-only and never echoed back.
Both GET and PUT require `plugins:manage`.
Fixes #341
* fix: resolve settingsSchema for bypassed and runtime-installed plugins
Review follow-up: loadBypassedPlugins now forwards settingsSchema to
adaptSandboxEntry, and marketplace/registry plugins loaded at runtime
resolve their schema from the cached manifest via a new
getRuntimePluginSettingsSchema accessor (settings endpoint fallback +
hasSettings in the plugin list).
* fix(admin): cleared settings fields revert to schema default
Review follow-up: emptying a non-secret field now sends null so the
server deletes the stored value and the schema default applies again.
Previously the empty string was persisted and shadowed the default.
* test(plugins): cover runtime-installed plugin settings schema fallback
The settings route tests mocked getRuntimePluginSettingsSchema to always
return null, so the runtime-installed (marketplace) plugin fallback added
to fix the prior review gap was never exercised. Add a GET case where the
plugin is absent from configuredPlugins/sandboxedPluginEntries and the
runtime lookup supplies the schema, asserting 200 with the schema keys and
masked secrets.
* fix(admin): correct PluginSettings select items shape and toast usage
Addressing emdashbot review: Kumo Select.items expects a value->label
Record (or string[]), not {value,label}[] — building the record first so
the select trigger renders the chosen label. Also align with admin
conventions: use Toast.useToastManager() with type:"error" instead of
useKumoToastManager() + variant, and re-export the plugin-settings client
functions and SettingField from the api barrel.
* style: format
* fix(plugins): wrap settings update writes in a transaction
The update handler validated every field up front but then ran the
delete/set writes in a bare loop, so a failure partway through left the
options table half-updated. Wrap the write loop + read-back in
withTransaction (real transaction on SQLite/Postgres; degrades to a
direct run on D1, which is single-writer so per-statement atomicity
still holds), using a transaction-scoped OptionsRepository.
---------
Co-authored-by: emdashbot[bot] <emdashbot[bot]@users.noreply.github.com>
1 parent 1cd5c43 commit d4c565e
23 files changed
Lines changed: 1449 additions & 10 deletions
File tree
- .changeset
- docs/src/content/docs/plugins/creating-native-plugins
- packages
- admin
- src
- components
- lib/api
- tests/components
- core
- src
- api
- handlers
- astro
- integration
- routes/api/admin/plugins
- [id]
- plugins
- tests
- integration/api
- unit/api
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
| 1 | + | |
| 2 | + | |
| 3 | + | |
| 4 | + | |
| 5 | + | |
| 6 | + | |
Lines changed: 2 additions & 0 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
217 | 217 | | |
218 | 218 | | |
219 | 219 | | |
| 220 | + | |
| 221 | + | |
220 | 222 | | |
221 | 223 | | |
222 | 224 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
430 | 430 | | |
431 | 431 | | |
432 | 432 | | |
| 433 | + | |
| 434 | + | |
| 435 | + | |
| 436 | + | |
| 437 | + | |
| 438 | + | |
| 439 | + | |
| 440 | + | |
| 441 | + | |
| 442 | + | |
| 443 | + | |
433 | 444 | | |
434 | 445 | | |
435 | 446 | | |
436 | 447 | | |
437 | | - | |
| 448 | + | |
438 | 449 | | |
439 | 450 | | |
440 | | - | |
| 451 | + | |
441 | 452 | | |
442 | 453 | | |
443 | 454 | | |
| |||
0 commit comments