signalk-container-helper 0.2.0 → 0.2.2

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.
Files changed (3) hide show
  1. package/CHANGELOG.md +15 -0
  2. package/README.md +70 -2
  3. package/package.json +2 -2
package/CHANGELOG.md CHANGED
@@ -1,3 +1,18 @@
1
+ # v0.2.2
2
+
3
+ Maintenance release — dependency updates only, no changes to the library's public API or runtime behaviour.
4
+
5
+ - **TypeScript 6** — the dev toolchain moves from `^5.5.0` to `^6.0.3`; the emitted declarations and ESM output are unchanged, and the full build, 96-test suite, and lint chain pass under the new compiler
6
+ - **`signalk-container` type source bumped 1.23.2 → 1.25.2** — the contract test that pins this library's type mirror against `signalk-container/types` still passes, so the mirrored `ContainerManagerApi` / `ContainerConfig` / `UpdateServiceApi` surface has not drifted against the newer manager
7
+ - Dev-dependency refresh: `eslint` 10.7.0 → 10.8.0, `typescript-eslint` 8.65.0 → 8.66.0, `globals` 17.7.0 → 17.9.0, `@types/react` 19.2.17 → 19.2.18
8
+ - CI: `actions/checkout` and `actions/setup-node` bumped to v7 in the publish workflow
9
+
10
+ # v0.2.1
11
+
12
+ Docs-only release.
13
+
14
+ - **README: "ESM plugins must build an ESM remote"** — Signal K injects each configurator panel's script tag based on the plugin's package.json `type` field, so `"type": "module"` plugins (like this library, and therefore most of its consumers) must build their panel as an ESM Module Federation container (`experiments.outputModule` + `output.module` + `library: { type: "module" }`); the classic `var` remote the CommonJS reference plugins use loads silently into module scope and fails at panel-open time with the misleading _'Module "…" is not available. Make sure the webapp is installed.'_ The new section documents the server's injection logic, both mismatch failure modes, the webpack recipe, a `get`/`init` verification one-liner, and links [signalk-piper](https://github.com/hoeken/signalk-piper) as a working ESM example — plus a matching panel-conventions bullet, and the "no changes to the standard webpack config" claim is now scoped to loaders
15
+
1
16
  # v0.2.0
2
17
 
3
18
  - **New `signalk-container-helper/ui` entrypoint** — browser-side React building blocks for plugin config panels, packaging the pieces the reference plugins (`signalk-grafana`, `signalk-questdb`, `mayara-server-signalk-plugin`) had each been hand-copying: the shared inline-style vocabulary (`panelStyles`, `stateColors`), components (`StatusCard`, `VersionSelect`, `UpdateControls`, `Button`, `CollapsibleSection`, and friends), fetch-and-poll hooks (`useStatusPoll`, `useVersions`, `useUpdateFlow`) with self-scheduling polls and stale-response drops, version-dropdown view logic (`deriveVersionsView`) that handles both structured and legacy `/api/versions` shapes and falls back to the running tag so a rate-limited GitHub fetch never blanks the select, and `formatUpdateMessage` typed against `UpdateCheckResult` to match `registerUpdateRoutes`' contract
package/README.md CHANGED
@@ -222,8 +222,9 @@ shared as a singleton). The standard webpack config runs `babel-loader` with
222
222
  `exclude: /node_modules/`, so a library shipping raw JSX would break the
223
223
  build. This entrypoint therefore ships **tsc-compiled `React.createElement`
224
224
  JS (no JSX)** that webpack bundles directly, and its `import "react"` resolves
225
- to the host Admin UI's shared React singleton. No changes to the standard
226
- webpack config are needed.
225
+ to the host Admin UI's shared React singleton. No loader changes are needed —
226
+ but the remote's output format must match your package's module type (next
227
+ section).
227
228
 
228
229
  ```bash
229
230
  npm install signalk-container-helper react
@@ -232,6 +233,68 @@ npm install signalk-container-helper react
232
233
  (`react` can be a devDependency of your plugin — it is only used at bundle
233
234
  time; at runtime the Admin UI provides the singleton.)
234
235
 
236
+ ### ESM plugins must build an ESM remote
237
+
238
+ The server injects each panel's script tag based on the **plugin's**
239
+ package.json `type` field:
240
+
241
+ ```js
242
+ moduleInfo.type === "module"
243
+ ? `<script type="module" src="/${moduleInfo.name}/remoteEntry.js"></script>`
244
+ : `<script src="/${moduleInfo.name}/remoteEntry.js"></script>`;
245
+ ```
246
+
247
+ The remote's output format must match, and the failure modes on a mismatch
248
+ are unhelpful, so get this right up front:
249
+
250
+ - **CommonJS plugin** (the reference plugins): the classic remote —
251
+ `library: { type: "var", name: "<name with [-@/] → _>" }` — which lands on
252
+ `window` when the plain script tag runs.
253
+ - **`"type": "module"` plugin** (likely yours — this library is ESM-only):
254
+ the Admin UI loads the panel with a dynamic `import()` and requires real
255
+ `get`/`init` module exports. A copied `var` remote loads silently into
256
+ module scope — no window global, no exports — and the panel dies with
257
+ _'Module "…" is not available. Make sure the webapp is installed.'_ even
258
+ though discovery and serving worked. Build an **ESM container** instead:
259
+
260
+ ```js
261
+ // webpack.config.cjs (an ESM package needs the .cjs extension, or an ESM config)
262
+ module.exports = {
263
+ // ...
264
+ experiments: { outputModule: true },
265
+ output: {
266
+ path: path.resolve(__dirname, "public"),
267
+ module: true,
268
+ clean: false,
269
+ },
270
+ plugins: [
271
+ new ModuleFederationPlugin({
272
+ name: "your_plugin_name",
273
+ library: { type: "module" }, // no global var name
274
+ filename: "remoteEntry.js",
275
+ exposes: {
276
+ "./PluginConfigurationPanel":
277
+ "./src/configpanel/PluginConfigurationPanel",
278
+ },
279
+ shared: {
280
+ react: { singleton: true, requiredVersion: "^19" },
281
+ "react-dom": { singleton: true, requiredVersion: "^19" },
282
+ },
283
+ }),
284
+ ],
285
+ };
286
+ ```
287
+
288
+ Chunks emit as `.mjs`; verify the container shape with
289
+ `node -e 'import("./public/remoteEntry.js").then((m) => console.log(typeof m.get, typeof m.init))'`
290
+ (both must print `function`).
291
+
292
+ The mismatch breaks in the other direction too: a CJS package emitting an ESM
293
+ remote throws a `SyntaxError` when the browser executes `export` syntax from
294
+ a plain script tag. A working ESM example is
295
+ [signalk-piper](https://github.com/hoeken/signalk-piper)'s
296
+ `webpack.config.cjs`.
297
+
235
298
  ### Example panel
236
299
 
237
300
  ```jsx
@@ -360,6 +423,11 @@ Adopt these even where you don't use the components:
360
423
  checked 3h ago", don't paint the panel red.
361
424
  - **Persist the requested tag, not the resolved one** after an update, so
362
425
  floating tags like `latest` keep auto-tracking.
426
+ - **Match the remote's module format to your package's `type` field.** The
427
+ server injects `<script type="module">` for `"type": "module"` plugins and
428
+ a plain script tag otherwise; the wrong webpack `library` type fails only
429
+ at panel-open time, with a misleading "webapp is not installed" error (see
430
+ [ESM plugins must build an ESM remote](#esm-plugins-must-build-an-esm-remote)).
363
431
 
364
432
  ## API overview
365
433
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "signalk-container-helper",
3
- "version": "0.2.0",
3
+ "version": "0.2.2",
4
4
  "description": "Helper library for Signal K plugins that manage containers via the signalk-container plugin",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",
@@ -75,7 +75,7 @@
75
75
  "globals": "^17.4.0",
76
76
  "prettier": "^3.8.1",
77
77
  "signalk-container": "^1.23.2",
78
- "typescript": "^5.5.0",
78
+ "typescript": "^6.0.3",
79
79
  "typescript-eslint": "^8.58.0",
80
80
  "vitest": "^4.1.10"
81
81
  }