Skip to content

[WC-3452] Add pusher module to the repo#2258

Open
r0b1n wants to merge 5 commits into
mainfrom
feat/pusher-module
Open

[WC-3452] Add pusher module to the repo#2258
r0b1n wants to merge 5 commits into
mainfrom
feat/pusher-module

Conversation

@r0b1n

@r0b1n r0b1n commented Jun 9, 2026

Copy link
Copy Markdown
Collaborator

This adds pusher module to the repo, has old widget as an asses to copy into the module.

@r0b1n r0b1n requested a review from a team as a code owner June 9, 2026 14:19
@github-actions

This comment has been minimized.

Comment thread packages/modules/pusher/assets/Pusher_widget_legacy_1.2.0.mpk Outdated
@r0b1n r0b1n force-pushed the feat/pusher-module branch from 9e445e5 to 0455139 Compare June 9, 2026 15:36
@github-actions

This comment has been minimized.

@github-actions

This comment has been minimized.

@github-actions

This comment has been minimized.

gjulivan
gjulivan previously approved these changes Jun 11, 2026
@r0b1n r0b1n force-pushed the feat/pusher-module branch from 4cd3a12 to 56a23fa Compare June 11, 2026 12:25
@github-actions

This comment has been minimized.

@github-actions

Copy link
Copy Markdown
Contributor

AI Code Review

🔶 Changes requested — one or more medium-severity items must be addressed


What was reviewed

File Change
packages/pluggableWidgets/pusher-web/src/Pusher.editorConfig.ts Added check() validator, updated getCaption()
packages/pluggableWidgets/pusher-web/src/Pusher.tsx Refactored from single event to multi-handler eventHandlers list
packages/pluggableWidgets/pusher-web/src/Pusher.xml Replaced notifyActionName+notifyEventAction with eventHandlers object list
packages/pluggableWidgets/pusher-web/src/package.xml Version bump 2.0.0 → 4.0.0
packages/pluggableWidgets/pusher-web/src/utils/PusherListener.ts Refactored to multi-event bind_global pattern
packages/pluggableWidgets/pusher-web/src/utils/getChannelName.ts Removed as any cast
packages/pluggableWidgets/pusher-web/typings/PusherProps.d.ts Updated types from ListValue to DynamicValue<ObjectItem>, added EventHandlersType
packages/modules/pusher/ New module package (build scripts, CHANGELOG, package.json)
packages/pluggableWidgets/pusher-web/package.json Version bump 2.0.0 → 4.0.0

Skipped (out of scope): pnpm-lock.yaml, LICENSE, README.md


Findings

🚨 High — Debug dump of all widget values shipped in production check() output

File: packages/pluggableWidgets/pusher-web/src/Pusher.editorConfig.ts lines 32–36
Problem: An unconditional errors.push always emits a warning containing JSON.stringify(values) — the full widget configuration — as a visible Studio Pro warning message. This looks like a leftover debug statement. It will expose all property values (including any secret-adjacent configuration) to every app developer who opens Studio Pro, and it permanently pollutes the validation output with noise, making the legitimate duplicate-name check harder to see. It must be removed before merge.
Fix:

// Delete these lines entirely:
errors.push({
    property: "eventHandlers",
    severity: "warning",
    message: JSON.stringify(values)
});

🔶 Medium — Stale closure for onEvent callbacks in useMemo

File: packages/pluggableWidgets/pusher-web/src/Pusher.tsx lines 27–35
Problem: The eventBindings array is built inside useMemo and captures handler.action by closure. Because canExecute and action references can change between renders (Mendix refreshes ActionValue objects), and because PusherListener.subscribe() only replaces the eventHandlersMap entries on every render (not just channel changes), the stale-closure risk exists when useMemo does NOT recompute (i.e. when eventHandlers array identity is stable but the inner action.canExecute has changed). The filter handler.action?.canExecute means a handler whose action becomes executable after the initial memo run will be silently dropped.

Additionally, eventHandlers is an array prop — its identity changes on every render in Mendix, so useMemo will recompute every render anyway, making the optimisation ineffective. Either stabilise the deps with a deep-equality comparison or accept the recompute and document it.
Fix: Compute eventBindings outside useMemo (or use a ref-based stable callback pattern), and remove the canExecute filter from the subscription builder — let executeAction handle the guard (it already checks canExecute internally):

// Remove the canExecute filter — executeAction() already guards it:
const eventBindings = eventHandlers
    .filter(handler => handler.actionName)
    .map(handler => ({
        eventName: handler.actionName,
        onEvent: () => executeAction(handler.action)
    }));

🔶 Medium — No unit tests added for new multi-handler behaviour

File: packages/pluggableWidgets/pusher-web/src/ (no __tests__/ directory changes in diff)
Problem: The refactor significantly changes behaviour: single event → list of event handlers, ListValueDynamicValue<ObjectItem>, new duplicate-name validation. None of this is covered by new or updated tests. Per repo convention, behaviour changes require unit tests (src/**/__tests__/*.spec.ts).
Fix: Add tests covering at minimum:

  • check() returns a Problem for duplicate action names and no problem for unique names.
  • Pusher component does not subscribe when channelName is undefined.
  • Pusher component subscribes with the correct eventBindings when handlers are configured.
  • PusherListener.subscribe() updates eventHandlersMap without resubscribing when channel is unchanged.

🔶 Medium — objectSource typing mismatch between XML and generated typings

File: packages/pluggableWidgets/pusher-web/typings/PusherProps.d.ts line 22 vs packages/pluggableWidgets/pusher-web/src/Pusher.xml
Problem: The XML still declares objectSource as type="object" (single object context, line 7 of Pusher.xml), which matches DynamicValue<ObjectItem>. The old typings had it as ListValue. The typings file header says "WARNING: All changes made to this file will be overwritten" — meaning this file is auto-generated from the XML. The manual change to DynamicValue<ObjectItem> is correct only if the XML also declares it as a single-object property. Verify the XML reflects the intended property type; if it does, the generated typings should reflect this automatically — do not edit the typings file by hand.


⚠️ Low — bind_global receives internal Pusher system events

File: packages/pluggableWidgets/pusher-web/src/utils/PusherListener.ts lines 57–63
Note: bind_global intercepts every event on the channel including Pusher internal events (pusher:subscription_succeeded, pusher:member_added, etc.). The handler already guards with eventHandlersMap.get(eventName) — so unknown events are silently ignored, which is fine. But the pusher:subscription_error handler is bound separately (line 66) after bind_global, so it will be called twice if the error event name leaks through the global handler. Confirm this is safe or filter system events in the global callback:

this.globalCallback = (eventName: string, _data: unknown) => {
    if (eventName.startsWith("pusher:")) return; // skip internal events
    const handler = this.eventHandlersMap.get(eventName);
    if (handler) handler();
};

⚠️ Low — Missing pusher-web CHANGELOG entry

File: packages/pluggableWidgets/pusher-web/ (no CHANGELOG.md in diff)
Note: The widget has a breaking API change (properties renamed/restructured, version bumped 2.0.0 → 4.0.0). A CHANGELOG entry in packages/pluggableWidgets/pusher-web/CHANGELOG.md is required per repo convention. Run pnpm -w changelog inside the widget package or add the entry manually.


Positives

  • The switch from a single (data: unknown) => void callback to a Map-based dispatch in PusherListener is a clean design: the channel is subscribed once, and handler updates are O(1) map replacements without channel teardown.
  • Removing the as any cast in getChannelName.ts tightens the type safety correctly.
  • The check() duplicate-action-name validator is a useful Studio Pro-time guard that prevents silent event shadowing at configuration time.
  • The new module package (packages/modules/pusher/) follows the existing module conventions precisely — correct mxpackage shape, marketplace metadata, script structure matching other modules like web-actions.

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.

3 participants