Skip to content

Apollo 3 v2 - #863

Open
garrettjstevens wants to merge 6 commits into
mainfrom
v2
Open

garrettjstevens wants to merge 6 commits into
mainfrom
v2

Conversation

@garrettjstevens

Copy link
Copy Markdown
Contributor

This will be a branch for collecting various changes that will go into Apollo 3 v2. The v2 PRs will get merged in here, and then main will be fast-forwarded to this branch when it's time for the release.

@cmdcolin

Copy link
Copy Markdown
Contributor

FYI for moving to JBrowse 5.0.0-beta.18: core now depends on @jbrowse/mobx-state-tree@^6.10.0, so the ^6.9.0 ranges here leave two MST copies in yarn.lock and ~400 type errors. Bumping those ranges to ^6.10.0 (and @jbrowse/* to ^5.0.0-beta.18) typechecks clean and tests pass. Happy to open a PR against v2 if useful.

@garrettjstevens

Copy link
Copy Markdown
Contributor Author

@cmdcolin no worries, I always check for MST and MUI upgrades when doing a bump since they both tend to cause type errors if they fall out of sync.

garrettjstevens and others added 6 commits November 4, 2026 01:41
* Fix LGV block API usage after upstream rename to displayedRegionIndex

jbrowse-components renamed block.parentRegion to a displayedRegionIndex
lookup and bpToPx's regionNumber param to displayedRegionIndex. Update
all call sites to match.

Assisted-by: Claude Sonnet 4.6 <noreply@anthropic.com>

* fix(jbrowse-plugin-apollo): guard document access in GeneGlyph for worker context

This module loads in jbrowse's RPC worker (all configured plugins load
there unconditionally), where globalThis.document is undefined. The
module-level canvas pattern setup assumed document always exists, just
guarding the canvas.getContext result -- that worked while jbrowse's
worker provided a stub document, but jbrowse removed that polyfill, so
document.createElement now throws synchronously and crashes the whole
plugin load via importScripts (surfaced by Chrome as a generic
NetworkError, masking the real TypeError).

Guard the document access itself instead; these patterns are
main-thread-only rendering fills the worker never needs.

* Upgrade deps

* Fix JPA lint errors after deps update

* Fix JPA TS errors after deps update

* Extend built-in BaseResult

* Rever update of mui-icons

* Get context menu entries working again

* Fix trying to access canvas in webworker

* Temporarily use local packages for jbrowse core

* Fix lint

* Update core and mui-icons

* Update jbrowse to latest main

* Use nightly JBrowse in CI tests

* Fix some now-outdated Cypress selectors

* Move tooltip import

* Lint fixes

* Unskip tests

* Fix autocomlplete props

* Updates some tests

* More specific selector in test

* Handle menu now not closing on click in tests

* Update all mobx-related packages, latest JB main

* Copy over functions no longer provided by JBrowse

Also fix lint

* Update to latest JBrowse main

* Update cypress test screenshots

* Update to latest JBrowse main

* Update to React 19 to match JBrowse

* Update to latest JBrowse main

* Update to latest JBrowse main

* Update to latest JBrowse main

* Update to latest JBrowse main

* Update to latest JBrowse main

* Update to latest JBrowse main

* Update to new JBrowse JobsListModel

Also use JobsListModel types directly so future changes are caught more
easily

* Update moved "Show all regions..." menu item

* Update to latest JBrowse main

* Update to latest JBrowse main

* Add failing test to resize track

* Update location of show regions menu item in test

* Update to latest JBrowse main

* Update to latest JBrowse main

* Update to latest JBrowse main

* Update to latest JBrowse main

* Update to latest JBrowse main

* Update to published JBrowse 5.0.0-beta.2

* Update to published JBrowse 5.0.0-beta.3

* Update to published JBrowse 5.0.0-beta.4

* Update to published JBrowse 5.0.0-beta.8

* Update to published JBrowse 5.0.0-beta.9

* Fix test for moved "Show all regions" menu item

* Fix lint

* Update to published JBrowse 5.0.0-beta.10

* Add manual interop for JBrowse packages

* Add search result label for new search behavior

* Update Cypress tests for new JBrowse UI

* Update to published JBrowse 5.0.0-beta.11

* Update to published JBrowse 5.0.0-beta.13

* Update to published JBrowse 5.0.0-beta.15

* Update to published JBrowse 5.0.0-beta.17

* Update to published JBrowse 5.0.0-beta.18

* Update to published JBrowse 5.0.0-beta.19

* Update to published JBrowse 5.0.0-beta.20

---------

Co-authored-by: Colin <colin.diesh@gmail.com>
Assisted-by: Claude Sonnet 4.6 <noreply@anthropic.com>
* Echange websockets for server-sent events

* Add tests for server-sent events

* Don't answer own location request

The REQUEST_INFORMATION handler compared the sender's session ID to this
client's token, which never match, so every client (including the one
that asked) re-broadcast its location. Compare session IDs instead.

* Send user locations as JSON

The plugin sent its location list as the key of a form-encoded body,
which the server had to reassemble from the body's keys. An empty list
(sent when a tab is hidden or closed) came out as [0] instead of [].

Send a plain JSON array instead. The server still accepts the old
format so older plugin versions keep working.

* Keep refSeq change subscriptions until the event stream opens

The event stream is only created once the internet account initializes,
and features can be fetched before that. The driver skipped subscribing
when there was no stream yet, so that refSeq got no live updates until
its features were fetched again.

Track channel listeners in a ChannelSubscriptions object on the internet
account, which attaches them to the EventSource when it is created (and
would move them to a replacement EventSource).

* Add test to check that refNames match subscription
The collaboration server applied each change inside a MongoDB
transaction, and transactions only work on a replica set. Remove the
transactions so that a plain, single MongoDB instance is enough.

- Change handlers no longer take or use a ClientSession. ChangesService
  calls the handler, writes the change-log entry, and runs backend
  post-validation directly, without wrapping them in a transaction.
  Cleaning up temporary (status -1) documents after a failure is
  unchanged.
- Because a failed post-validation can no longer roll anything back,
  the parent/child boundary check now runs before saving. It is now a
  standalone checkChildFeatureBoundaries() function that the location
  start/end handlers call on the updated in-memory feature, and
  ParentChildValidation no longer does a database lookup during
  backendPostValidate.
- If writing the change-log entry fails after the handler's writes have
  been saved, log an error that says so.
- Drop the session parameter from Validation and ValidationSet
  backendPostValidate.
- Remove the replica set setup from the dev container, the CI MongoDB
  services, and the deploy compose file, which now runs a single mongo
  service with a ping health check.
- Update the docs to say that no replica set is needed, and simplify
  the example compose files and MONGODB_URI values to match.

Assisted-by: Claude Code:claude-opus-5-5
* Support multiple instances with PM2

* Check MongoDB and server events in the health check

/health now reports whether the server can reach MongoDB and is receiving
server-sent events from other server processes, so load balancers and
Kubernetes readiness probes stop sending traffic to a process that can't
serve it. /health/live only reports that the process is running, for use
as a liveness probe, so a MongoDB outage doesn't restart every process.

Assisted-by: Claude Code:claude-opus-5-5

* Shut down cleanly when the Docker container stops

yarn exits as soon as it gets SIGTERM, and when it is PID 1 that stops the
container before the server has finished shutting down, cutting off open
connections. Run node directly instead, and handle SIGTERM and SIGINT by
closing the app and exiting, rather than with Nest's shutdown hooks, which
exit by re-sending the signal to themselves, a signal that is ignored when
node is PID 1.

Assisted-by: Claude Code:claude-opus-5-5

* Document running several server containers

Explains what copies of the collaboration server need to share, the
health check endpoints, and proxy settings for live updates and uploads,
with examples for Docker Compose (behind nginx) and Kubernetes.

Assisted-by: Claude Code:claude-opus-5-5

* Test that docker images build and run in CI
* Add assemblyAccess service

Let a server plugin restrict users to particular assemblies through a new
Apollo-AssemblyAccess extension point, which evaluates to a map of user
email to the assembly names (or '*') they may access.

- AssemblyAccessService resolves a user's allowed assemblies. Admins are
  never restricted, a user the plugin doesn't mention gets no assemblies,
  and with no plugin registered nothing is restricted.
- AssemblyAccessGuard reads @AssemblyAccess metadata on each endpoint and
  rejects requests naming an assembly, refSeq, feature or change outside
  the user's assemblies. It responds 404 rather than 403, since the client
  discards its token and retries on a 403, and so as not to disclose that
  the assembly exists.
- The assembly, refSeq, feature, check, change, JBrowse config and export
  endpoints only return data from the user's assemblies.

Also add a developer guide page on restricting assembly access.

* Allow plugins to use MongoDB connection

Evaluate a new Apollo-MongoDB extension point once at startup, after
plugins are installed, passing the server's Mongoose connection, so a
plugin can keep its own data in Apollo's database.

* Add extension point for custom routes

Plugins can contribute HTTP routes through a new Apollo-RegisterRoutes
extension point, evaluated at startup with the Mongoose connection.
PluginRoutesController serves them under /plugin-routes, matching on
method and exact path, behind the usual authentication and the read-only
role. A handler that throws gets a 500 response.

Add the PluginRoute type to @apollo-annotation/common and a custom
routes page to the developer guide.

* Add new Apollo server-side plugin infrastructure

Server plugins were JBrowse-style plugin classes downloaded from
PLUGIN_URLS into a temporary directory, with untyped extension points.
Give the server its own Node-only plugin system:

- A server plugin is an ApolloServerPlugin (from
  @apollo-annotation/common) with a name and an install(registrar)
  method that registers typed hooks: Apollo-MongoDB,
  Apollo-RegisterRoutes, Apollo-AssemblyAccess,
  Apollo-RegisterCustomAuth, Apollo-RegisterChangeTypes,
  Apollo-RegisterChecks and Apollo-RegisterValidations.
- Plugins load from npm packages in PLUGIN_PACKAGES, or from
  Node-targeted ESM/CJS bundles in PLUGIN_URLS/PLUGIN_URLS_FILE. Fetched
  bundles are cached by content hash in PLUGIN_CACHE_DIR, and can be
  checked against sha256 hashes in PLUGIN_INTEGRITY. Anything that isn't
  a valid server plugin fails startup with a clear error.
- An error in a startup hook fails startup. An error in
  Apollo-AssemblyAccess, which runs on every request, denies access to
  every assembly instead of falling back to no restrictions.
- The custom auth handler types move to @apollo-annotation/common.

Update the configuration options and developer guide to match.

* Make sure apollo plugin is first in the client

When the JBrowse config stored on the server is merged into the
generated one, put the stored plugins array first if it lists the Apollo
plugin, so that Apollo's plugin is loaded before any plugin that builds
on it.

* Split out some internet account logic

Add the top-level admin menus from ApolloPlugin.configure() once any
Apollo internet account has the admin role, instead of from the internet
account's one-time startup. The internet account no longer needs to know
about the root model's menus.

Also stop the internet account's startup if it was destroyed while
fetching the last change sequence number.
…#851)

* Only provide PluginsService from PluginsModule

AuthenticationModule also listed PluginsService in its providers, which
created a second instance. Since PluginsService installs plugins in
onModuleInit, every plugin was installed twice and plugins that register
change types or checks crashed startup on the duplicate-name check.

Assisted-by: Claude Code:claude-opus-5-5

* Stop submitting changes that fail frontend post-validation

When frontend post-validation failed, ChangeManager tried to undo the
change but then went on to submit it to the backend anyway. The undo
itself was also a no-op, since it was rejected while the original change
was still marked in progress.

Now a failed post-validation reports the error, reverts the change in
the client data store directly (without re-validating the inverse, which
could otherwise be rejected the same way), and stops. Also report the
backend's validation message rather than the pre-validation one when the
backend rejects a change.

Assisted-by: Claude Code:claude-opus-5-5

* Pass a copy of the default reserved attribute keys to plugins

The Apollo-ReservedAttributeKeys extension point was handed the
module-level defaults object on every render, so a callback that mutated
it instead of returning a new object would keep adding to the defaults.

Assisted-by: Claude Code:claude-opus-5-5

* Fix validation and parsing of plugin environment variables

- Configuring only PLUGIN_URLS_FILE was rejected at startup, since
  PLUGIN_URLS defaulted to '' and the two were required to be exclusive
  (xor). They are now optional and mutually exclusive (oxor).
- PLUGIN_INTEGRITY and PLUGIN_CACHE_DIR are now part of the schema, and
  PLUGIN_INTEGRITY entries are validated at startup.
- PLUGIN_INTEGRITY entries are split on the last '=', so URLs with query
  strings work.
- PLUGIN_URLS entries are trimmed, like PLUGIN_PACKAGES entries already
  were.

The env schema moves to its own file so it can be tested without
loading the whole app module.

Assisted-by: Claude Code:claude-opus-5-5

* Only special-case the plugins array when merging JBrowse config

The custom arrayMerge applied to every array in the config, and when the
stored config already listed the Apollo plugin it was included twice.
Now only the plugins array is special-cased: the generated Apollo plugin
comes first and any Apollo entry from the stored config is dropped.
Other arrays are concatenated as before.

Assisted-by: Claude Code:claude-opus-5-5

* Cache URL-loaded server plugins inside the server package

Fetched plugin bundles were cached in the OS temp directory, where bare
imports like @apollo-annotation/common can't be resolved, so any plugin
that imported Apollo packages (rather than bundling its own copies)
failed to load. Cache them in .plugin-cache inside the server package by
default, so those imports resolve against the server's own dependencies,
and warn if PLUGIN_CACHE_DIR is set to a directory outside the package.

Assisted-by: Claude Code:claude-opus-5-5

* Move server-only feature helpers out of the shared change classes

FeatureChange had getFeatureFromId, addChild and findAndDeleteChildFeature
methods that operate on MongoDB feature documents, and
MergeTranscriptsChange had server-side merge methods. Since changes are
now executed by per-environment handlers, these belong with the server
handlers. They become plain functions in the collaboration server's
changes/featureTree.ts.

findAndDeleteChildFeature and generateNewIds were unused and are
removed.

Assisted-by: Claude Code:claude-opus-5-5

* Make apollo-common dependency-free with plain feature data types

apollo-common's public types referenced @apollo-annotation/mst, which was
only a dev dependency, and it depended at runtime on
@apollo-annotation/schemas (and so on NestJS and Mongoose) and
@jbrowse/core, plus a long list of UI peer dependencies, none of which
it used.

- Add plain AnnotationFeatureSnapshot and CheckResultSnapshot types (and
  a minimal FeatureNode shape for the feature-tree helpers) so Check and
  the change classes no longer need MST or Mongoose types. The built-in
  checks use them too.
- apollo-common now has no runtime dependencies. The server-only types
  it still exposes (NestJS, Express, Mongoose, schemas) are optional peer
  dependencies.

Assisted-by: Claude Code:claude-opus-5-5

* Use a minimal Logger type for changes instead of NestJS's

Change.logger was typed with NestJS's LoggerService, pulling a server
type into code shared with the client. It was also protected, which
makes TypeScript treat Change nominally: a change class from one copy of
@apollo-annotation/common (e.g. one bundled into a plugin, or a
different Yarn virtual instance) wasn't assignable to Change from
another copy. Use a small local Logger interface (satisfied by console
and NestJS loggers) and make the field public and readonly.

Assisted-by: Claude Code:claude-opus-5-5

* Add a @apollo-annotation/common/server entry point

Move the server plugin API (ApolloServerPlugin, the hooks, assembly
access, custom auth, plugin routes and Validation) under src/server and
export it from @apollo-annotation/common/server. The root entry point now
only has environment-neutral code (changes, checks and feature data), so
client code and client plugins no longer see types that need NestJS,
Express or Mongoose.

Assisted-by: Claude Code:claude-opus-5-5

* Add per-environment validation types

Introduce the validation model that will replace the single Validation
class with both frontend and backend methods:

- ChangeRule (@apollo-annotation/common): an environment-independent
  rule that only looks at the change, run on both client and server.
- ClientValidation (new @apollo-annotation/common/client entry point):
  pre/post validation in the client, with a client context.
- ServerValidation (@apollo-annotation/common/server): pre/post
  validation on the server, with the user, MongoDB connection and
  logger.

Validations return an error message, or nothing if the change is valid.
Add ServerValidationSet and ClientValidationSet to run them, using a
shared runValidations helper. Nothing uses them yet.

Assisted-by: Claude Code:claude-opus-5-5

* Switch to per-environment validations

Replace the single Validation class (with frontend and backend methods
that each environment half-ignored) and the shared validationRegistry
with the new validation model:

- Server: changes are checked by serverValidations (change rules, then
  ServerValidations). ParentChildValidation no longer did anything, since
  its check runs before saving, so it is removed and its
  checkChildFeatureBoundaries() helper moves to the server package.
- Client: ChangeManager checks changes with clientValidations.
  CoreValidation is now a ClientValidation in the client package (still
  client-only, as before).
- Request authorization, previously AuthorizationValidation run by
  ValidationGuard through backendPreValidate(context), is now a plain
  Nest guard (AuthorizationGuard).
- Apollo-RegisterValidations collects change rules and server
  validations.
- Remove both copies of Validation, the Context type,
  ValidationSet/validationRegistry and the unused possibleValues.

Assisted-by: Claude Code:claude-opus-5-5

* Make server-side change execution pluggable

Plugins could register a change class through Apollo-RegisterChangeTypes,
but the server only ran changes through a fixed table of built-in
handlers, so plugin changes always failed with a 422.

- Apollo-RegisterChangeTypes now collects ServerChangeTypes: the change
  class, a handler that applies it, and an optional requiredRole.
- A serverChangeTypes registry holds every change type and handler. The
  built-in handlers are registered into it by ChangeHandlersService, and
  ChangesService dispatches through it.
- The role needed to submit each change type comes from the registry
  instead of a hard-coded list, so plugin change types can be admin-only.

Assisted-by: Claude Code:claude-opus-5-5

* Make client-side change handling pluggable

The client applied changes through a fixed table of built-in handlers,
skipping any other change type. Add ClientChangeType (the change class
and an optional handler that applies it to the features loaded in the
client) to @apollo-annotation/common/client, and a clientChangeTypes
registry that the built-in change types are registered into and that
ChangeManager dispatches through.

The client handler gets a minimal ClientChangeDataStore, typed with
@apollo-annotation/mst, which is now an optional peer dependency of
@apollo-annotation/common for the /client entry point.

Assisted-by: Claude Code:claude-opus-5-5

* Let client plugins register change types, checks and validations

Apollo registered its built-in change types, checks and validations at
module load, and offered no way for other client plugins to add their
own. A plugin importing the registries got its own bundled copies of
them, so even that didn't work.

ApolloPlugin.configure() now evaluates three extension points, matching
the server hooks of the same names, and registers what other plugins
contribute into Apollo's own registries:

- Apollo-RegisterChangeTypes: Record<string, ClientChangeType>
- Apollo-RegisterChecks: Check[]
- Apollo-RegisterValidations: (ChangeRule | ClientValidation)[]

Plugins are configured again whenever JBrowse creates a new plugin
manager, so registering the same class under the same name again
replaces the earlier registration.

Assisted-by: Claude Code:claude-opus-5-5

* Add an Apollo-GetGlyph extension point

The glyph used to draw each feature in the linear annotation display was
chosen by a fixed chain of checks. Evaluate the Apollo-GetGlyph extension
point on the default choice, with props { feature, display, glyphs },
where glyphs are the built-in glyphs, so plugins can draw other feature
types with an existing glyph, wrap one, or provide their own.

The Glyph interface (generic over the display type) and related layout
types move to @apollo-annotation/common/client. @jbrowse/core is now an
optional peer dependency there, for its MenuItem and ContentBlock types.

Assisted-by: Claude Code:claude-opus-5-5

* Add an Apollo-FeatureContextMenuItems extension point

Feature context menus in the linear and six-frame annotation displays and
the tabular editor were built in three separate places, none of which
plugins could change short of overriding display state models. Pass
each feature's menu items through the Apollo-FeatureContextMenuItems
extension point, with props { feature, session, location }.

Props types for this and Apollo-GetGlyph are in
@apollo-annotation/common/client.

Assisted-by: Claude Code:claude-opus-5-5

* Add custom component slots to the feature details widget

The transcript details widget let plugins add components through
Apollo-TranscriptDetailsCustomComponent-* extension points, but the
feature details widget (used for genes and other features) had none.
Add Apollo-FeatureDetailsCustomComponent-* slots after the basic
information, and inside and after the attributes, sequence and related
features sections.

Both widgets share a helper for evaluating the slots, and the props type
their components get is exported from @apollo-annotation/common/client
as DetailsWidgetCustomComponentProps.

Assisted-by: Claude Code:claude-opus-5-5

* Remove the Apollo-extendAnnotationFeature extension point

The extended feature model was only used to look features up and for
the selected-feature reference. Features stored in the client data
store (and their children) were always the base AnnotationFeatureModel,
so views or actions a plugin added never existed on actual features.
Rather than keep an extension point that silently doesn't work, remove
it.

Assisted-by: Claude Code:claude-opus-5-5

* Register Apollo's client extension points with JBrowse's types

JBrowse 5 lets plugins add their extension points to its
ExtensionPointRegistry, which types addToExtensionPoint,
contributeToExtensionPoint and evaluateExtensionPoint. Declare every
Apollo client extension point there (in @apollo-annotation/common/client),
so a plugin's callbacks are type-checked against the extendee and props
Apollo actually passes, and Apollo's own evaluations are checked too.

The points that collect lists (Apollo-RegisterChecks,
Apollo-RegisterValidations, Apollo-FeatureContextMenuItems) become
accumulating points: plugins register with contributeToExtensionPoint and
return only their own entries, so they can't drop another plugin's.

Also export AttributeEditorProps and AttributeViewerProps from
@apollo-annotation/common/client; the built-in attribute editor and
viewer use them.

Assisted-by: Claude Code:claude-opus-5-5

* Add path parameters, roles and a context to plugin routes

Plugin routes could only match exact paths, always required the
read-only role, and their handlers only got the request and response,
with no way to know the user's assembly access.

- Route paths can have parameters and wildcards, matched with
  path-to-regexp as in Express 5 routes. Invalid paths fail at startup.
- A route can set the minimum role it needs (default 'readOnly'; 'none'
  makes it public). The controller now allows any role and checks the
  route's role itself.
- Handlers get a third argument with the path parameters, the user, the
  IDs of the assemblies they may access, the MongoDB connection and a
  logger.

Also match all plugin routes with {*path}, which avoids Nest's legacy
route conversion warning at startup.

Assisted-by: Claude Code:claude-opus-5-5

* Let plugin menu items and widget components submit changes

Context menu items and details widget components contributed by plugins
had no supported way to submit a change; they would have had to reach
into the session's data store for its ChangeManager. Pass them a
submitChange function that validates, applies and sends a change the
same way Apollo's own UI does.

Assisted-by: Claude Code:claude-opus-5-5

* Add an example plugin with client and server halves

packages/apollo-plugin-example shows the plugin APIs working together: a
custom change type with client and server handlers, a change rule and a
check run on both sides, a glyph override, a context menu item that
submits a change, and a server route that respects assembly access.

It has its own unit tests, and the Apollo JBrowse plugin and
collaboration server tests load it into the real plugin machinery to
check the APIs end to end. The example's tests also run in CI.

Assisted-by: Claude Code:claude-opus-5-5

* Add a plugin migration page to the developer guide

List the changes to the plugin API that may require changes to existing
plugins: package entry points, change types, validations, client
extension points, server routes and plugin configuration.

Assisted-by: Claude Code:claude-opus-5-5

* Rewrite the developer guide for the new plugin API

- Overview of client and server plugins and the @apollo-annotation/common
  entry points.
- New pages on server plugins (loading, every hook, failure behavior,
  what server code gets), client plugins (every Apollo extension point),
  custom change types, validations and checks.
- Update the custom routes page for path parameters, roles and the
  handler context, and the custom login page for redirects and the
  CustomAuthHandler type.

Assisted-by: Claude Code:claude-opus-5-5

* Require the admin role for assembly and JBrowse config changes

AddAssemblyFromExternalChange, AddAssemblyAliasesChange and
ImportJBrowseConfigChange only needed the user role, unlike the other
changes that manage assemblies and the server's JBrowse configuration.
Make them admin-only, and only show the "Save track to Apollo" and
"Remove track from Apollo" track menu items (which submit
ImportJBrowseConfigChanges) to admins.

Assisted-by: Claude Code:claude-opus-5-5

* Make bundled version of the example server plugin

The published Docker image can't load the example's server half with
PLUGIN_PACKAGES, since that only imports packages already in the
server's dependencies. Add a rolldown config that builds it as one
self-contained ES module (dist/server.bundle.js) that can be loaded with
PLUGIN_URLS. Only packages in the collaboration server's production
dependencies (@apollo-annotation/common and mongoose) are left external.

Update the developer guide and configuration docs to recommend
PLUGIN_URLS for the Docker image, explain what a bundle may leave
unbundled, and show how to build one.

Assisted-by: Claude Opus 5.5 <noreply@anthropic.com>

* Add more to the example plugin

Show more of the client plugin API:

- An "Add note" context menu item that opens a dialog, alongside "Clear
  notes" (now only offered when the feature has notes).
- Apollo-ReservedAttributeKeys, to offer "note" when adding an
  attribute.
- Apollo-AttributeEditorComponent and Apollo-AttributeViewerComponent,
  for a custom editor and viewer for notes.

ExampleNoteLengthRule now also checks notes set with Apollo's own
FeatureAttributeChange, and allows notes the feature already had, so a
feature with an over-long note can still be edited.

The development server now loads the example's server bundle and uses
its own database.

Assisted-by: Claude Opus 5.5 <noreply@anthropic.com>

* Add new command `apollo change submit`

Replace `apollo feature edit` with `apollo change submit`, since it
submits any change type, including custom ones added by plugins, not
only feature edits. The change JSON (one change or an array of them) can
be given as an argument, on stdin or with --change-json-file, and each
change must have a "typeName".

Assisted-by: Claude Opus 5.5 <noreply@anthropic.com>

* Add e2e Cypress tests for example plugin

Load both halves of the example plugin into a running collaboration
server and JBrowse and test them end to end: adding, clearing and
undoing notes, the note length rule on the client and server, the
custom route and its access check, and the short feature check.

The collaboration server's new cypress:start:example script starts it
with the example's server bundle and its own database, and the tests
add the client half to the JBrowse configuration stored in MongoDB. The
tests also run in CI. The development server goes back to the default
database without the example plugin.

Assisted-by: Claude Opus 5.5 <noreply@anthropic.com>

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants