Skip to content

refactor(realtime): type the socket event-handler boundary with @sim/realtime-protocol#5208

Merged
waleedlatif1 merged 2 commits into
stagingfrom
refactor/socket-event-typing
Jun 25, 2026
Merged

refactor(realtime): type the socket event-handler boundary with @sim/realtime-protocol#5208
waleedlatif1 merged 2 commits into
stagingfrom
refactor/socket-event-typing

Conversation

@waleedlatif1

Copy link
Copy Markdown
Collaborator

Summary

Replaces the (data: any) socket event-handler types in socket-provider.tsx with precise wire types, closing the realtime transport boundary that the AI/collaborative editor depends on. Adds a shared, pure-type module packages/realtime-protocol/src/events.ts (+ a ./events subpath export) holding the broadcast shapes, since the realtime server emits them.

Typing only — zero logic/behavior change. Each event type was verified against the actual apps/realtime emit site AND the consumers (no field declared that the server omits, none missing that a consumer reads). any in the file dropped 33→11 (the 11 remaining are pre-existing, out-of-scope store internals).

Notable correctness details: cursor-update/selection-update are flat presence objects; workflow-deployed omits message; workflow-operation.payload is unknown (consumers dispatch on operation/target, never deref it untyped). events.ts is distinct from schemas.ts — it types the outbound broadcast, not the inbound op envelope (no duplication).

Type of Change

  • Refactor (type-safety; no behavior change)

Testing

  • tsc 0 (app + package), Biome clean, check:boundaries + check:realtime-prune pass, 14/14 socket tests.
  • Adversarially audited line-by-line: behavior-preserving, every type matches the server emit shape, no unsafe casts, all 5 consumers compile + behave.

Checklist

  • Code follows project style guidelines
  • Self-reviewed my changes
  • No new warnings introduced
  • I confirm that I have read and agree to the terms outlined in the Contributor License Agreement (CLA)

…realtime-protocol

Replace the (data: any) event-handler types in socket-provider.tsx with
precise broadcast types that mirror the exact payloads emitted by the
realtime Socket.IO server (apps/realtime/src/handlers/** and rooms/**).

Add @sim/realtime-protocol/events with the canonical wire types for the
broadcast/confirmation events the server emits: WorkflowOperationBroadcast,
SubblockUpdateBroadcast, VariableUpdateBroadcast, CursorUpdateBroadcast,
SelectionUpdateBroadcast, the four workflow-lifecycle broadcasts, and
OperationConfirmed/Failed. Typing change only; zero runtime/logic changes.
Store-internal any (rehydrate state, subblock map, emit payloads) is left
untouched as out of scope.
@waleedlatif1 waleedlatif1 requested a review from a team as a code owner June 25, 2026 03:30
@vercel

vercel Bot commented Jun 25, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

1 Skipped Deployment
Project Deployment Actions Updated (UTC)
docs Skipped Skipped Jun 25, 2026 3:36am

Request Review

@cursor

cursor Bot commented Jun 25, 2026

Copy link
Copy Markdown

PR Summary

Low Risk
Type-only refactor on the client socket layer; collaborative behavior and wire format are unchanged.

Overview
Introduces @sim/realtime-protocol/events, a shared module of Socket.IO server→client broadcast shapes (workflow ops, subblock/variable updates, presence, lifecycle, operation ack/fail), and wires socket-provider.tsx to use them end-to-end.

All on* registration APIs, internal handler refs, and socketInstance.on(...) listeners move from (data: any) to the specific *Broadcast interfaces. workflow-operation.payload and similar opaque fields stay unknown so the transport does not pretend to narrow collaborative edits. No runtime or protocol behavior changes—compile-time safety only.

Reviewed by Cursor Bugbot for commit 881caa3. Configure here.

@waleedlatif1

Copy link
Copy Markdown
Collaborator Author

@greptile review

@waleedlatif1

Copy link
Copy Markdown
Collaborator Author

@cursor review

@cursor cursor Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

✅ Bugbot reviewed your changes and found no new issues!

Comment @cursor review or bugbot run to trigger another review on this PR

Reviewed by Cursor Bugbot for commit 60e355a. Configure here.

@greptile-apps

greptile-apps Bot commented Jun 25, 2026

Copy link
Copy Markdown
Contributor

Greptile Summary

This PR replaces (data: any) socket event-handler parameter types in socket-provider.tsx with precise wire types sourced from a new packages/realtime-protocol/src/events.ts module, and exposes that module via a new ./events subpath export in the package manifest. It is a pure type-safety refactor with no runtime behavior change.

  • New events.ts file: Introduces eleven typed broadcast interfaces (WorkflowOperationBroadcast, CursorUpdateBroadcast, etc.) verified against the actual emit(...) call sites in both redis-manager.ts and memory-manager.ts; payload and value fields left as unknown since the transport never dereferences them.
  • socket-provider.tsx: Replaces all eleven (data: any) handler signatures — in the context type, the eventHandlers ref, the socketInstance.on(...) listeners, and the useCallback wrappers — with the corresponding typed broadcast interfaces; any usage in the file drops from 33 to 11, with the remaining 11 being pre-existing store internals.

Confidence Score: 5/5

Safe to merge — typing-only change with zero runtime behavior modification.

Every declared field in the eleven new broadcast interfaces was verified against the actual server emit call sites in redis-manager.ts, memory-manager.ts, presence.ts, operations.ts, subblocks.ts, and variables.ts. All shapes match exactly: WorkflowDeployedBroadcast correctly omits message; cursor is CursorPosition | null to cover the cursor-leave signal; opaque payload and value fields are unknown; avatarUrl matches UserSession. The subpath export follows the existing pattern.

No files require special attention.

Important Files Changed

Filename Overview
packages/realtime-protocol/src/events.ts New file defining eleven broadcast interfaces; types verified against all server emit sites. cursor: CursorPosition
packages/realtime-protocol/package.json Adds a ./events subpath export following the identical pattern used by the existing ./constants and ./schemas exports. No structural concerns.
apps/sim/app/workspace/providers/socket-provider.tsx Replaces all (data: any) handler signatures with precise broadcast types across the context interface, eventHandlers ref, socketInstance.on listeners, and useCallback wrappers. Purely additive type information; logic is untouched.

Reviews (3): Last reviewed commit: "fix(realtime): type cursor-update broadc..." | Re-trigger Greptile

Comment thread packages/realtime-protocol/src/events.ts
The client emits 'cursor-update' with { cursor: null } when a remote user's
cursor leaves the canvas, and the server re-broadcasts it verbatim, so receivers
genuinely get cursor: null. Type CursorUpdateBroadcast.cursor as
CursorPosition | null to match the wire. (selection stays non-null — it signals
absence via type: 'none', never null.)
@greptile-apps

greptile-apps Bot commented Jun 25, 2026

Copy link
Copy Markdown
Contributor

Greptile Summary

This PR replaces (data: any) handler signatures on all 11 socket event listeners in socket-provider.tsx with precise wire types from a new packages/realtime-protocol/src/events.ts module, and exposes that module via a new ./events subpath export. The types were verified against the actual server emit sites across memory-manager.ts, redis-manager.ts, operations.ts, presence.ts, subblocks.ts, and variables.ts — all shapes match.

  • packages/realtime-protocol/src/events.ts: New pure-type module defining 11 broadcast interfaces (WorkflowOperationBroadcast, SubblockUpdateBroadcast, VariableUpdateBroadcast, CursorUpdateBroadcast, SelectionUpdateBroadcast, WorkflowDeletedBroadcast, WorkflowRevertedBroadcast, WorkflowUpdatedBroadcast, WorkflowDeployedBroadcast, OperationConfirmedBroadcast, OperationFailedBroadcast).
  • packages/realtime-protocol/package.json: Adds a ./events subpath export, consistent with the existing ./constants and ./schemas exports.
  • apps/sim/app/workspace/providers/socket-provider.tsx: All (data: any) handler parameters replaced with the corresponding broadcast types at both the SocketContextType interface and the useRef/useCallback/socketInstance.on(...) sites.

Confidence Score: 5/5

Pure type annotation change with zero runtime impact; all 11 broadcast interfaces verified against the actual server emit sites.

Every interface in events.ts was cross-checked against the emit objects in memory-manager.ts, redis-manager.ts, operations.ts, presence.ts, subblocks.ts, and variables.ts — shapes match exactly, including the intentional omission of message from WorkflowDeployedBroadcast. The new subpath export follows the identical pattern used by ./constants and ./schemas. No logic paths were altered; the only observable effect is that TypeScript now knows the wire shape at the provider boundary.

No files require special attention. The one observation — phantom userId destructuring in use-collaborative-workflow.ts — is pre-existing and unaffected by this PR.

Important Files Changed

Filename Overview
packages/realtime-protocol/src/events.ts New file defining 11 outbound broadcast interfaces; all shapes verified against memory-manager.ts, redis-manager.ts, operations.ts, presence.ts, subblocks.ts, and variables.ts emit sites — exact match, including the intentional omission of message from WorkflowDeployedBroadcast and unknown payload for WorkflowOperationBroadcast.
packages/realtime-protocol/package.json Adds ./events subpath export pointing to ./src/events.ts, following the identical pattern already used by ./constants and ./schemas.
apps/sim/app/workspace/providers/socket-provider.tsx Purely additive type annotations replacing (data: any) with the corresponding broadcast types at the SocketContextType interface, eventHandlers ref, socketInstance.on(...) callbacks, and all 11 useCallback wrappers; no logic changes.

Sequence Diagram

%%{init: {'theme': 'neutral'}}%%
sequenceDiagram
    participant Server as Realtime Server<br/>(ops/presence/rooms)
    participant Provider as SocketProvider<br/>(socket-provider.tsx)
    participant Consumer as Consumer<br/>(use-collaborative-workflow.ts)

    Note over Provider: Typed boundary introduced by this PR

    Server->>Provider: 'workflow-operation' (WorkflowOperationBroadcast)
    Provider->>Consumer: onWorkflowOperation(handler)

    Server->>Provider: 'subblock-update' (SubblockUpdateBroadcast)
    Provider->>Consumer: onSubblockUpdate(handler)

    Server->>Provider: 'variable-update' (VariableUpdateBroadcast)
    Provider->>Consumer: onVariableUpdate(handler)

    Server->>Provider: 'cursor-update' (CursorUpdateBroadcast)
    Provider->>Consumer: onCursorUpdate(handler)

    Server->>Provider: 'selection-update' (SelectionUpdateBroadcast)
    Provider->>Consumer: onSelectionUpdate(handler)

    Server->>Provider: 'workflow-deleted' (WorkflowDeletedBroadcast)
    Provider->>Consumer: onWorkflowDeleted(handler)

    Server->>Provider: 'workflow-reverted' (WorkflowRevertedBroadcast)
    Provider->>Consumer: onWorkflowReverted(handler)

    Server->>Provider: 'workflow-updated' (WorkflowUpdatedBroadcast)
    Provider->>Consumer: onWorkflowUpdated(handler)

    Server->>Provider: 'workflow-deployed' (WorkflowDeployedBroadcast)
    Provider->>Consumer: onWorkflowDeployed(handler)

    Server->>Provider: 'operation-confirmed' (OperationConfirmedBroadcast)
    Provider->>Consumer: onOperationConfirmed(handler)

    Server->>Provider: 'operation-failed' (OperationFailedBroadcast)
    Provider->>Consumer: onOperationFailed(handler)
Loading
%%{init: {'theme': 'base', 'themeVariables': {"darkMode": true, "background": "#0d1117", "primaryColor": "#21262d", "primaryTextColor": "#e6edf3", "primaryBorderColor": "#8b949e", "lineColor": "#8b949e", "textColor": "#e6edf3", "edgeLabelBackground": "#161b22", "actorBkg": "#21262d", "actorBorder": "#8b949e", "actorTextColor": "#e6edf3", "actorLineColor": "#8b949e", "signalColor": "#8b949e", "signalTextColor": "#e6edf3", "noteBkgColor": "#373320", "noteBorderColor": "#d4a72c", "noteTextColor": "#f0e6c0", "labelBoxBkgColor": "#21262d", "labelBoxBorderColor": "#8b949e", "labelTextColor": "#e6edf3", "loopTextColor": "#e6edf3", "activationBkgColor": "#30363d", "activationBorderColor": "#8b949e"}}}%%
sequenceDiagram
    participant Server as Realtime Server<br/>(ops/presence/rooms)
    participant Provider as SocketProvider<br/>(socket-provider.tsx)
    participant Consumer as Consumer<br/>(use-collaborative-workflow.ts)

    Note over Provider: Typed boundary introduced by this PR

    Server->>Provider: 'workflow-operation' (WorkflowOperationBroadcast)
    Provider->>Consumer: onWorkflowOperation(handler)

    Server->>Provider: 'subblock-update' (SubblockUpdateBroadcast)
    Provider->>Consumer: onSubblockUpdate(handler)

    Server->>Provider: 'variable-update' (VariableUpdateBroadcast)
    Provider->>Consumer: onVariableUpdate(handler)

    Server->>Provider: 'cursor-update' (CursorUpdateBroadcast)
    Provider->>Consumer: onCursorUpdate(handler)

    Server->>Provider: 'selection-update' (SelectionUpdateBroadcast)
    Provider->>Consumer: onSelectionUpdate(handler)

    Server->>Provider: 'workflow-deleted' (WorkflowDeletedBroadcast)
    Provider->>Consumer: onWorkflowDeleted(handler)

    Server->>Provider: 'workflow-reverted' (WorkflowRevertedBroadcast)
    Provider->>Consumer: onWorkflowReverted(handler)

    Server->>Provider: 'workflow-updated' (WorkflowUpdatedBroadcast)
    Provider->>Consumer: onWorkflowUpdated(handler)

    Server->>Provider: 'workflow-deployed' (WorkflowDeployedBroadcast)
    Provider->>Consumer: onWorkflowDeployed(handler)

    Server->>Provider: 'operation-confirmed' (OperationConfirmedBroadcast)
    Provider->>Consumer: onOperationConfirmed(handler)

    Server->>Provider: 'operation-failed' (OperationFailedBroadcast)
    Provider->>Consumer: onOperationFailed(handler)
Loading

Reviews (2): Last reviewed commit: "fix(realtime): type cursor-update broadc..." | Re-trigger Greptile

@waleedlatif1

Copy link
Copy Markdown
Collaborator Author

@greptile review

@waleedlatif1

Copy link
Copy Markdown
Collaborator Author

@cursor review

@cursor cursor Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

✅ Bugbot reviewed your changes and found no new issues!

Comment @cursor review or bugbot run to trigger another review on this PR

Reviewed by Cursor Bugbot for commit 881caa3. Configure here.

@waleedlatif1 waleedlatif1 merged commit e748a64 into staging Jun 25, 2026
16 checks passed
@waleedlatif1 waleedlatif1 deleted the refactor/socket-event-typing branch June 25, 2026 03:43
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.

1 participant