Repository navigation
Plugin host for atomic-plugins drive apps: several destination tables, store.getMany, theme (consolidates #1748, #1750, #1768) - #2148
Closed
michielbdejong wants to merge 4 commits into
Closed
michielbdejong wants to merge 4 commits into
michielbdejong wants to merge 4 commits into
Conversation
A plugin's manifest `destination` can now declare keyed `tables` beside
(or instead of) its single `table`. Set up creates each one beneath the
plugin with its own row class and default view, and stores
`tables: { <key>: { table, rowClass } }` in the plugin's config next to
the unchanged `{ table, rowClass, properties }`. A drive app shown as a
view of any of those tables gets the same map from `store.getData()`.
This is what the money app needs for statements and closing balances
(atomic-plugins#148, M-7 and M-12).
- provisionDestination moves from FileImport into @tomic/lib
(plugin-destination.ts), with destinationTablesFor for the host's
`data` op. Set up resumes: a release that adds a key creates only that
table.
- The server now checks `destination` with the browser's rules and
messages instead of only requiring a map. Both parsers are held to new
shared fixtures in testdata/plugin-manifest/.
- A single-table manifest keeps its config, its table localId and its
release id; the single-table fixture's id is pinned, and so is the
stored bytes of an app package carrying it.
- Docs: creating-plugins.md describes `accepts`, `destination.table`
and `destination.tables`.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Ported from #1768 onto develop. Hand edits while
resolving: `manifest.rs` and `plugin-manifest.ts` keep develop's operation
URL check; the `atomic-proxy:` parsing (#1725) that sat next to this change
in the stack is left out. The `.po` catalogs are develop's, settled
separately.
(cherry picked from commit e739bf7)
Reads up to 100 resources in one round trip, each exactly as `get` reads it, through the person's store; an unreadable subject is reported in its place. Used by atomic-plugins' issue-tracker, money and notion drive apps. Ported from #1748 (97eff29) onto develop's plugin contract (#1970). Hand edits while resolving: kept develop's Store-shaped `query`, `search` and `getContext` in view-client.js and added `getMany` beside them, passing the title to `makeResource` like `getResource` does; dropped the openExternal/openResource/proxy.disconnect pieces this commit carried as context (types, docs, TESTING_COVERAGE, hostStore.test), which wait on the questions on #1726. (cherry picked from commit 97eff29) Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Apps had no success colour and guessed dark mode from the background colour.
- The theme gets `colors.success`: #237a42 in light mode, #4cc27a in dark.
Frames get it as `--t-color-success`.
- The frame stylesheet sets `color-scheme: light | dark` on `:root`, and the
theme message now carries `colorScheme`, both from the built theme's
`darkMode` (the host's actual setting, including "auto"). FrameBridge
keeps it across a ready message and a reload. AppFrame and packaged
plugin views both send it.
- view-client: `store.getTheme()` returns `{ colorScheme }`. Before any
message has arrived it reads the applied `color-scheme` back.
`store.onThemeChange(handler)` fires once per real switch.
- `ColorScheme` and `ThemeMessage` in `@tomic/plugin`; documented in
custom-views.md.
Closes #1738
Ported from #1750 (2923ce1, with the theme-test
rename from 62187a1) onto develop's plugin contract (#1970). Hand edits
while resolving: AppFrame keeps develop's host UI next to the frame's
colour scheme; pluginRPC keeps develop's HostUI import beside the
ColorScheme one; view-client.js keeps develop's ASKS_THE_PERSON and
`point` and adds the theme listener; the openExternal/openResource methods
and docs this commit carried as context are left out (they wait on #1726).
(cherry picked from commit 2923ce1)
(cherry picked from commit 62187a1)
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
pnpm clean-translations after the #1768 port: the new "Set up creates {0} tables" message, the renamed placeholder of the single-table one, and a msgstr develop's catalogs were missing. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
michielbdejong
marked this pull request as ready for review
October 9, 2026 00:00
This was referenced Oct 9, 2026
joepio
added a commit
that referenced
this pull request
Oct 9, 2026
Combines #2148 (plugin host stack with destination tables) with the message catalogs re-extracted.
Member
|
Landed on develop through #2169 (batch with the message catalogs re-extracted), merged as b214af0 on a green run of the exact head. This head (6126887) is fully contained, so closing. Generated by Claude Code |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Consolidates the parts of the plugin-host stack (#1702–#1934) that atomic-plugins' drive apps need now and that don't depend on the open #1970 questions on #1726. Rebased onto current
develop, nothing merged from the old stack base. Decided by Michiel (Decision Inbox Q-101), on @joepio's request on #1726 for one PR instead of the stack.The inventory, the CLOSE list and the four #1970 questions are on #1726: #1726 (comment)
What's in it
destinationcan declare keyedtablesbeside (or instead of) its singletable. Set up creates each table with its own row class and default view, and storestables: { <key>: { table, rowClass } }in the config. A drive app shown on one of them gets the same map fromstore.getData().provisionDestinationmoves into@tomic/lib(plugin-destination.ts). The server now validatesdestinationwith the browser's rules, and both are held to new shared fixtures intestdata/plugin-manifest/.e739bf750)destination.tables.statements(integrations/money/plugin.ts), which feeds the Money app's Imports tab and closing balances.store.getMany(subjects): up to 100 reads in one round trip, each exactly likeget, with an unreadable subject reported in its place.store.getTheme()/store.onThemeChange(handler)({ colorScheme }),--t-color-success, and the host passing an explicitcolorSchemeto app frames and packaged views.Commit by commit: one commit per PR, cherry-picked with
-x. The hand edits made while resolving against develop are named in each commit message. Then one commit that settles the.pocatalogs.Notes on the port
atomic-proxy:operation URLs (atomic-proxy: URLs for plugins, resolved to the delegated connection on the configured proxy (#1700, answer 4) #1725). Those are left out:manifest.rsandplugin-manifest.tskeep develop's operation URL check.view-client.js:getMany,getThemeandonThemeChangesit besidegetResource,query,searchandui.*. TheopenExternal,openResourceandproxy.disconnectcode these commits carried as context is left out.pluginRPC.tsx. It was only two adjacent imports (One plugin contract: a Store-shaped API and host UI for every plugin view #1970'suseHostUIand theColorSchemetype), so it resolved without a design choice. Packaged views get the colour scheme through the samesetStyle(css, colorScheme)as app frames.getApp,getDataandproxy.store.test.ts's parity list for the shared contract is unchanged.What waits on #1726
The rest of the NEED set touches #1970's design, so it waits for Joep's answers to the questions on #1726:
openExternal/openResourceproxy.disconnectThis PR doesn't replace those PRs.
Flags
None needed. Everything here is additive:
destination.tablesgets the same config, the same tablelocalIdand the same release id as before. The single-table fixture's id is pinned, and so are the stored bytes of an app package carrying it.colorSchemeis an extra field on the style message, which older frames ignore.Review guide (Joep, Polle, Michiel)
getManyreads each subject through the signed-in person's store, so it has the same rights asget.hostStore.ts).validate_destinationinserver/src/plugins/manifest.rsnow rejects destinations the browser already rejected. Before, the server only required a map.Object.prototypenames are refused as keys.useFrameColorSchemeinuseCreateThemeVars.ts, andFrameBridge.setStyle.Replaces
The rest of the CLOSE list is in the #1726 comment linked above. The branches stay.
Local checks
pnpm run -r buildpnpm run lint(the pre-commit hook on each commit)tsc --noEmitand the per-package typecheck@tomic/plugin,AppPage,PluginRuns, and the lib manifest, destination and app-package testscargo fmt --checkcargo clippy(CI's feature set)cargo test -p atomic-server --libcargo test -p atomic_lib --features db-redb --lib: 698 of 699 passed.db::compaction::startup_compaction_shrinks_a_bloated_store_and_keeps_every_resourcefailed once on a size bound while the machine was busy, then passed when run alone. This PR doesn't touchlib/.No UI change beyond FileImport's Set up line, which now names several tables when a manifest declares them. No screenshots taken.
CI
Green on
6126887: run 37828791674, with full e2e on Mancave.The earlier runs on the same commit failed on tests this PR doesn't touch:
recovery-assisted.test.tstimed out. It also failed on another branch's run that morning.a_canvas_syncs_to_a_second_device_through_the_bridgefailed. It passes locally 3/3.search.spec.ts › scoped searchfailed. The same test failed in another branch's run at the same time.🤖 Generated with Claude Code