Skip to content

fix: DH-23199: Propagate loader details from package.json to the manifest.json - #8299

Open
mofojed wants to merge 6 commits into
deephaven:mainfrom
mofojed:DH-23199-js-plugins-package-loader-details
Open

fix: DH-23199: Propagate loader details from package.json to the manifest.json#8299
mofojed wants to merge 6 commits into
deephaven:mainfrom
mofojed:DH-23199-js-plugins-package-loader-details

Conversation

@mofojed

@mofojed mofojed commented Jul 29, 2026

Copy link
Copy Markdown
Member

@mofojed
mofojed requested a review from devinrsmith July 29, 2026 14:40
@mofojed mofojed self-assigned this Jul 29, 2026
@github-actions

github-actions Bot commented Jul 29, 2026

Copy link
Copy Markdown
Contributor

No docs changes detected for a3c8476

@devinrsmith devinrsmith left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Bit out of the loop and confused about the overall goals. https://github.com/deephaven-ent/iris/pull/4914 does not shed any light on it...

*
* @return the loader configuration
*/
public abstract Optional<Map<String, Object>> loader();

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is sort-of a builder-anti-pattern; that is, using a Map or Collection w/ optional. The pattern is preferably to just have an empty map when there is no value.

final ContentResponse manifestResponse = get(client, "js-plugins/manifest.json");
assertOk(manifestResponse, "application/json",
"{\"plugins\":[{\"name\":\"@deephaven_test/example1\",\"version\":\"0.1.0\",\"main\":\"dist/index.js\"},{\"name\":\"@deephaven_test/example2\",\"version\":\"0.2.0\",\"main\":\"dist/index.js\"}]}");
"{\"plugins\":[{\"name\":\"@deephaven_test/example1\",\"version\":\"0.1.0\",\"main\":\"dist/index.js\",\"loader\":{\"npm\":\"loader\"}},{\"name\":\"@deephaven_test/example2\",\"version\":\"0.2.0\",\"main\":\"dist/index.js\"}]}");

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This would be a good time to upgrade to Java 17 textblocks, which make it makes these sorts of strings much easier to read (no need to escape, can do multiple lines if necessary, etc).

*
* @return the loader configuration
*/
public abstract Optional<Map<String, Object>> loader();

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is the intention to support complex map values? Or, just strings? Or, is it supposed to be a Json value type?

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's a JSON value type, e.g. https://github.com/deephaven/deephaven-plugins/blob/aaa4b0581b0e378acf13ee13e764e486671dea39/plugins/pivot-builder/src/js/package.json#L20

The goal is to have additional metadata provided by the package.json that is included in the manifest.json, such that we can read that before loading the plugins (as there's an order to which the plugins can be loaded in).

@devinrsmith devinrsmith Jul 30, 2026

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Okay, so DH server doesn't care about the string keys at all? In that case, it should probably just be an Object if we are going to keep this design.

Comment on lines +68 to +71
@Nullable
@Parameter
@JsonProperty(LOADER)
public abstract Map<String, Object> loader();

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

With this additional parameter, I would upgrade this object from "Simple" to "Buildable" style, remove Nullability.

@SimpleStyle
abstract class NpmPackage {

static final String LOADER = "loader";

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm confused about this; is "loader" a standard field in package.json? Is this something we are adding to our plugin infra?

I don't see it https://docs.npmjs.com/cli/v12/configuring-npm/package-json.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It is not a standard field. It's a custom field for our purposes.

@mofojed mofojed changed the title fix: Propagate loader details from package.json to the manifest.json fix: DH-23199: Propagate loader details from package.json to the manifest.json Jul 30, 2026
@mofojed
mofojed requested a review from devinrsmith July 30, 2026 19:01
@mofojed mofojed added NoDocumentationNeeded NoReleaseNotesNeeded No release notes are needed. labels Aug 4, 2026
@mofojed
mofojed requested a review from vbabich August 4, 2026 14:08
mofojed and others added 6 commits August 6, 2026 12:54
Previously, the 'loader' field from a JS plugin's package.json was
silently dropped and never appeared in the served
js-plugins/manifest.json.

- JsPlugin gains an optional loader() property/builder method.
- NpmPackage/JsPluginFromNpmPackage read the 'loader' field from
  package.json (dev/npm-package registration path).
- JsPluginManifestEntry/JsPluginsFromManifest read/write the 'loader'
  field to/from manifest.json (resource-path registration path).
- JsPluginManifestEntry.from(JsPlugin) writes loader() when building
  the served manifest, covering both registration paths since all
  registered plugins funnel through it.
- Python glue (to_j_js_plugin) duck-types a loader attribute on the
  Python JsPlugin and forwards it to the Java builder, so dynamically
  registered Python plugins (e.g. deephaven.ui) can also opt-in.
- Updated JettyFlightRoundTripTest and JS plugin test fixtures to
  cover loader propagation across manifest, npm-package, and direct
  registration paths.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Previously the manifest.json produced by pack-plugins.sh was built
line-by-line via 'npm pkg get name version main', which meant any
'loader' field on a packed plugin's package.json was dropped.

Now each plugin's package.json is read directly once all plugins have
been downloaded and moved into place, and the manifest is assembled in
a single Node.js invocation. The optional 'loader' field is copied
through when present, matching the server-side manifest.json support
added in JsPluginManifestEntry.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
- Ran the following commands:

./gradlew docker-server-base:bumpImage
docker run --rm ghcr.io/deephaven/server-base:edge pip freeze > docker/server-jetty/src/main/server-jetty/requirements.txt
docker run --rm ghcr.io/deephaven/server-base:edge pip freeze > docker/server/src/main/server-netty/requirements.txt
@mofojed
mofojed force-pushed the DH-23199-js-plugins-package-loader-details branch from fbff55a to 81d288c Compare August 6, 2026 16:55
@mofojed
mofojed marked this pull request as ready for review August 6, 2026 16:56
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants