Skip to content

Custom Run Event for Watch API#989

Open
Jtsoco wants to merge 2 commits into
live-codes:developfrom
Jtsoco:add-watch-event-run
Open

Custom Run Event for Watch API#989
Jtsoco wants to merge 2 commits into
live-codes:developfrom
Jtsoco:add-watch-event-run

Conversation

@Jtsoco
Copy link
Copy Markdown

@Jtsoco Jtsoco commented Jun 3, 2026

feat: create a custom run event to enable watching for when code is run inside embedded playground

What type of PR is this? (check all applicable)

  • ✨ Feature
  • 🐛 Bug Fix
  • 📝 Documentation Update
  • 🎨 Style
  • ♻️ Code Refactor
  • 🔥 Performance Improvements
  • ✅ Test
  • 🤖 Build
  • 🔁 CI
  • 📦 Chore (Release)
  • ⏩ Revert
  • 🌐 Internationalization / Translation

Description

This PR adds a new run custom event so embedded playground consumers can watch for code execution through the SDK watch API.

LiveCodes currently supports watchable events such as code, console, and tests, but does not expose a dedicated run event. This is especially useful when autoupdate is false and consumers need to react when execution happens.

Implementation follows existing event flow patterns:

dispatch run from the app when run is triggered
forward the event through the embed message channel
map it to SDK watch(run)
add SDK tests for the new watch path

Validation:

tests pass locally
manually verified with watch(run) in Storybook during development

Related Tickets & Documents

Fixes Issue #988

Added tests?

  • 👍 yes
  • 🙅 no, because they aren't needed
  • 🙋 no, because I need help

Added to documentations?

  • 📓 docs (./docs)
  • 📕 storybook (./storybook)
  • 📜 README.md
  • 🙅 no documentation needed

Thank you for taking the time to look at my PR. I'm excited to contribute to a project as great as live-codes.

Summary by CodeRabbit

  • New Features

    • Added support for watching "run" events via playground.watch('run', ...) to detect when code executes and receive { code, config }.
  • Documentation

    • Updated TypeScript and examples to document the new "run" watch event and its callback shape.
  • Tests

    • Added test coverage for the new "run" watch event behavior.

@netlify
Copy link
Copy Markdown

netlify Bot commented Jun 3, 2026

Deploy Preview for livecodes ready!

Name Link
🔨 Latest commit 3b13cc8
🔍 Latest deploy log https://app.netlify.com/projects/livecodes/deploys/6a21348f50bea800086febc5
😎 Deploy Preview https://deploy-preview-989--livecodes.netlify.app
📱 Preview on mobile
Toggle QR Code...

QR Code

Use your smartphone camera to open QR code link.
🤖 Make changes Run an agent on this branch

To edit notification comments on pull requests, go to your Netlify project configuration.

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented Jun 3, 2026

Review Change Stack

Walkthrough

A new run custom event is added to the playground's event system. The event fires when code is executed and is accessible via the playground.watch('run', callback) SDK method. The feature spans type definitions, core emission, SDK wiring, embed forwarding, tests, and documentation.

Changes

Run Event Feature

Layer / File(s) Summary
Run event type contracts
src/sdk/models.ts, src/sdk/internal.ts, src/livecodes/events/custom-events.ts
Add WatchRun type; extend WatchFns union and CustomEvents with 'livecodes-run'; add customEvents.run mapping.
Core run event emission
src/livecodes/core.ts
Add sdkWatchers.run publisher and conditionally dispatch customEvents.run (detail: { code, config }) to document and parent from run() when subscribers exist.
SDK event wiring for run
src/sdk/index.ts
Include run in sdkEvents allowlist and map incoming livecodes-run messages to SDK run event for watcher callbacks.
Embed iframe run event forwarding
src/livecodes/main.ts
Register customEvents.run in embed-mode event forwarding to postMessage to parent.
Run event tests and documentation
src/sdk/__tests__/createPlayground.spec.ts, docs/docs/sdk/js-ts.mdx, .agents/skills/livecodes/sdk-methods/SKILL.md
Add test verifying playground.watch('run', ...) receives payload; add TypeScript overload and docs/examples showing callback signature and code.result usage.

Sequence Diagram

sequenceDiagram
  participant Playground as run()
  participant SDKWatchers as sdkWatchers.run
  participant Document as document
  participant Embed as iframe (embed)
  participant Parent as parent window
  Playground->>SDKWatchers: check subscribers
  alt has subscribers
    Playground->>Document: dispatchEvent(livecodes-run { code, config })
    Document->>Embed: embed listener forwards via postMessage (livecodes-run)
    Embed->>Parent: postMessage mapped to SDK `run` event
  end
  Parent->>Parent: SDK invokes watcher callbacks with { code, config }
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Possibly related issues

  • #988: Adds the same run custom event and playground.watch('run', ...) support across customEvents, SDK mapping, and run dispatch.
🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title 'Custom Run Event for Watch API' directly and clearly describes the main change: adding a new watchable 'run' event to the SDK's watch API.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 2

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
src/sdk/models.ts (1)

1317-1324: ⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

Update the public watch() doc block to include run.

WatchFns now exposes 'run', but the API.watch JSDoc later in this file still lists only the previous six events. That leaves the generated API docs out of sync with the shipped type surface.

Also applies to: 1382-1385

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/sdk/models.ts` around lines 1317 - 1324, Update the public JSDoc for
API.watch to reflect the current WatchFns type by adding the 'run' event to the
listed events (in addition to load, ready, code, console, tests, destroy);
locate the JSDoc block that documents API.watch (references: WatchFns and
API.watch) and amend its example/description to include 'run' so the generated
docs match the exported type (also update the other occurrence noted around the
second JSDoc at the later location).
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@docs/docs/sdk/js-ts.mdx`:
- Line 544: Fix the malformed inline-code formatting for the playground event
label by closing the missing backtick around the run label: find the bullet that
starts with `"run": Called when the playground is run.` and change it to use
proper inline code formatting (e.g., `run`: Called when the playground is run.)
so the `run` event renders correctly in the docs.

In `@src/livecodes/core.ts`:
- Around line 1255-1259: The run event is being dispatched before the new result
is committed; move the dispatch of customEvents.run (the block checking
sdkWatchers.run.hasSubscribers() and calling
document.dispatchEvent(parent.dispatchEvent)) so it only fires after
getResultPage() and the awaited createIframe(...) complete successfully — i.e.,
after the result page is created and the iframe is created/attached and the new
output is committed; reference sdkWatchers.run, customEvents.run,
getResultPage(), and createIframe() when updating the code.

---

Outside diff comments:
In `@src/sdk/models.ts`:
- Around line 1317-1324: Update the public JSDoc for API.watch to reflect the
current WatchFns type by adding the 'run' event to the listed events (in
addition to load, ready, code, console, tests, destroy); locate the JSDoc block
that documents API.watch (references: WatchFns and API.watch) and amend its
example/description to include 'run' so the generated docs match the exported
type (also update the other occurrence noted around the second JSDoc at the
later location).
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro

Run ID: d295e4ee-1d8b-4bec-890a-94cb6e5e4bf8

📥 Commits

Reviewing files that changed from the base of the PR and between be1cfdb and 2405d2a.

📒 Files selected for processing (8)
  • docs/docs/sdk/js-ts.mdx
  • src/livecodes/core.ts
  • src/livecodes/events/custom-events.ts
  • src/livecodes/main.ts
  • src/sdk/__tests__/createPlayground.spec.ts
  • src/sdk/index.ts
  • src/sdk/internal.ts
  • src/sdk/models.ts

Comment thread docs/docs/sdk/js-ts.mdx Outdated
Comment thread src/livecodes/core.ts Outdated
@hatemhosny
Copy link
Copy Markdown
Collaborator

Thank you @Jtsoco

I have a few suggestions:

  • We should emit run event with the same data payload like the code event. This allows subscribers to get access to the result page HTML, the editors code and config object in the event payload without having to call getCode or getConfig
export type WatchRun = (
  event: 'run',
  fn: (data: { code: Code; config: Config }) => void,
) => { remove: () => void };

Also considering the timing issue as mentioned by @coderabbitai, this would be my suggestion for the updated run function:

const run = async (editorId?: EditorId, runTests?: boolean) => {
  setLoading(true);
  if (editorId !== 'style') {
    toolsPane?.console?.clear(/* silent= */ true);
  }
  const config = getConfig();
  const shouldRunTests = (runTests ?? config.autotest) && Boolean(config.tests?.content?.trim());
  const result = await getResultPage({ sourceEditor: editorId, runTests: shouldRunTests });
  await createIframe(UI.getResultElement(), result);
  updateCompiledCode();
  if (sdkWatchers.run.hasSubscribers()) {
    const runEvent = new CustomEvent(customEvents.run, {
      detail: { code: getCachedCode(), config },
    });
    document.dispatchEvent(runEvent);
    parent.dispatchEvent(runEvent);
  }
};
  • Another stylistic suggestion for consistency and readability is to move the run event after code/change (not after destroy) in all instances in code/docs/tests. For example:
- const sdkEvents: SDKEvent[] = ['load', 'ready', 'code', 'console', 'tests', 'destroy', 'run'];
+ const sdkEvents: SDKEvent[] = ['load', 'ready', 'code', 'run', 'console', 'tests', 'destroy'];
- - `"run": Called when the playground is run.
+ - `"run"`: Called when the playground is run.

Update the public watch() doc block to include run.

WatchFns now exposes 'run', but the API.watch JSDoc later in this file still lists only the previous six events. That leaves the generated API docs out of sync with the shipped type surface.

Thank you very much.

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented Jun 3, 2026

Tip

For best results, initiate chat on the files or code changes.

@hatemhosny, thanks for the thorough and well-structured review! Happy to confirm the two items you attributed to me:

  1. Timing issue — dispatching the run event before await createIframe(...) means subscribers fire before the result page is fully rendered. Your suggested placement (after createIframe + updateCompiledCode) is the correct fix, and bundling getCachedCode() + config into the event detail at that point ensures the payload reflects the final, post-render state.

  2. Docs typo — the missing closing backtick in "run": is confirmed.

Here is a consolidated checklist for @Jtsoco:

# What to change Where
1 Update WatchRun callback signature to fn: (data: { code: Code; config: Config }) => void src/sdk/models.ts
2 Move run event dispatch to after createIframe + updateCompiledCode; pass { code: getCachedCode(), config } as detail src/livecodes/core.ts
3 Reorder run to sit after code (before console) in sdkEvents arrays, customEvents usage, docs, and tests all affected files
4 Fix missing closing backtick: `"run"`: Called when the playground is run. docs/docs/sdk/js-ts.mdx
5 Update API.watch JSDoc block to list run alongside the other six watchable events src/sdk/models.ts
6 Add run event entry to the SDK methods skill .agents/skills/livecodes/sdk-methods/SKILL.md

Also worth noting: the new test in createPlayground.spec.ts should be updated to assert the callback receives the { code, config } payload once the signature is updated (point 1).

…rder events, change timing of event dispatch
@sonarqubecloud
Copy link
Copy Markdown

sonarqubecloud Bot commented Jun 4, 2026

Quality Gate Failed Quality Gate failed

Failed conditions
41.7% Duplication on New Code (required ≤ 3%)

See analysis details on SonarQube Cloud

@Jtsoco
Copy link
Copy Markdown
Author

Jtsoco commented Jun 4, 2026

@hatemhosny Thank you very much for your feedback!
I've implemented changes as you've suggested

  • added a payload to the run event
  • changed the timing of dispatching the run event
  • reordered run to be before destroy and after code
  • updated the docs

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In @.agents/skills/livecodes/sdk-methods/SKILL.md:
- Around line 91-94: The example adds a runWatcher via playground.watch('run',
...) but the cleanup section doesn't remove it (and omits removing
testsWatcher); update the "Remove watchers when done" section to
dispose/unregister all watchers created by playground.watch — specifically call
the appropriate removal on runWatcher and testsWatcher (in the same style used
for other watchers created from playground.watch) so every watcher created is
cleaned up.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro

Run ID: d13f39be-b11f-4430-8ab8-aea0aa48cbb2

📥 Commits

Reviewing files that changed from the base of the PR and between 2405d2a and 3b13cc8.

📒 Files selected for processing (9)
  • .agents/skills/livecodes/sdk-methods/SKILL.md
  • docs/docs/sdk/js-ts.mdx
  • src/livecodes/core.ts
  • src/livecodes/events/custom-events.ts
  • src/livecodes/main.ts
  • src/sdk/__tests__/createPlayground.spec.ts
  • src/sdk/index.ts
  • src/sdk/internal.ts
  • src/sdk/models.ts
🚧 Files skipped from review as they are similar to previous changes (6)
  • src/livecodes/main.ts
  • src/sdk/tests/createPlayground.spec.ts
  • src/sdk/internal.ts
  • src/sdk/index.ts
  • src/livecodes/events/custom-events.ts
  • docs/docs/sdk/js-ts.mdx

Comment on lines +91 to +94
// Watch for code execution
const runWatcher = playground.watch('run', ({ code, config }) => {
console.log('Playground ran. Result HTML:', code.result);
});
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

Update cleanup example to remove all created watchers.

This snippet introduces runWatcher, but the "Remove watchers when done" section does not remove it (and also omits testsWatcher). Please include all watcher removals to keep the example internally consistent.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In @.agents/skills/livecodes/sdk-methods/SKILL.md around lines 91 - 94, The
example adds a runWatcher via playground.watch('run', ...) but the cleanup
section doesn't remove it (and omits removing testsWatcher); update the "Remove
watchers when done" section to dispose/unregister all watchers created by
playground.watch — specifically call the appropriate removal on runWatcher and
testsWatcher (in the same style used for other watchers created from
playground.watch) so every watcher created is cleaned up.

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