Repository navigation
release: v4.5.3 (Develop v4 -> stage v4) - #653
Conversation
release: v4.5.1
v4.5.1 was published with only package.json, README.md and LICENSE. The package has no JS in it, so every consumer build fails on import while main, module, types and exports all point into dist/. The publish workflow dropped its `npm run build` step when it was rewritten on 15 Sept. Nothing else builds before publish: there is no prepack or prepublishOnly script, and with no `files` field npm falls back to .gitignore, which excludes dist. No build means an empty package. Hooking the build to prepack fixes it for every publish path rather than just the one workflow, so a later workflow edit cannot silently drop it again. A failing build now fails the publish instead of shipping nothing. Co-Authored-By: Claude <noreply@anthropic.com>
When npm-alpha-publish.yml was folded into this workflow the publish-alpha job came out identical to publish, losing the `--tag alpha` the old workflow had. An alpha release would move the `latest` dist-tag to the prerelease and hand it to every consumer on a caret range. This also restores the alpha channel as a rehearsal for a real publish: cut a prerelease, install it, confirm it resolves, then cut the release, all without touching `latest`. Co-Authored-By: Claude <noreply@anthropic.com>
A version tag is mutable, so the action owner or anyone who compromises that account can change what runs in CI without the ref changing here. Pinning to the commit sha behind v2.13.0 keeps the same code and removes that path. Co-Authored-By: Claude <noreply@anthropic.com>
…-publish fix(release): restore build before publish and the alpha dist-tag
Co-Authored-By: Claude <noreply@anthropic.com>
release: v4.5.2
…no listener
The visual builder registers the request-discussion-highlights listener
inside DiscussionPage, which Venus only mounts while the Discussions panel
is open. With the panel closed, which is the default, the send rejects with
NO_REQUEST_LISTENER_FOUND and nothing handles it. Next.js dev registers a
global unhandledrejection handler and renders the plain {code, message}
rejection as a runtime error overlay titled "[object Object]".
Handle the rejection at both send sites, since an absent receiver is the
expected state for this event rather than a failure.
Both branches of the isSSR check sent the same event, so the send is hoisted
out of the branch instead of being duplicated.
The spec mocked send as vi.fn(), which returns undefined rather than a
promise. Tests only passed because two later tests set mockResolvedValue and
vi.clearAllMocks does not reset implementations, so every test after them
inherited a promise. The base mock now matches the real contract.
Co-Authored-By: Claude <noreply@anthropic.com>
…a missing listener Swallowing every rejection hid genuine problems. NO_ACK_RECEIVED, WINDOW_CLOSED and CODE_RETURNED_ERROR would have been discarded as quietly as the expected missing listener. ignoreMissingListener returns silently only for NO_REQUEST_LISTENER_FOUND, which is the normal state while the Discussions panel is closed, and warns through PublicLogger for anything else. PublicLogger is already used across the SDK and is silent under NODE_ENV=test, so this adds no console noise in the common case. The helper lives in its own module because the spec mocks the visualBuilderPostMessage module wholesale; keeping it separate means tests exercise the real function rather than a mock. Co-Authored-By: Claude <noreply@anthropic.com>
…ver the observer send Review found that the helper's doc comment and its tests described rejection shapes the library does not produce. Verified against @contentstack/advanced-post-message 0.0.5: only the missing-listener reply carries a code. The closed-window path rejects with an uncoded Error, the no-ack timeout rejects with a bare string, and CODE_RETURNED_ERROR is logged on the receiving side and never sent back, so the sender never sees it. The handler already did the right thing for all of these, since an uncoded rejection warns. Only the doc comment and the tests were wrong, so the code check stays as the single rule and the comment now says so. Matching the no-ack case too would mean matching on a message string, and a receiver that never acks is worth a warning anyway. Also from review: - type the event parameter as VisualBuilderPostMessageEvents instead of string - restate the send mock contract in beforeEach so the spec no longer depends on implementations leaking between tests, and drop the hand-restore - add a spec for the debounced observer send, which had no coverage. The suite stubs MutationObserver globally in vitest.setup.ts, so the spec captures the observer callback and drives it directly. Co-Authored-By: Claude <noreply@anthropic.com>
Review pointed out that asserting `.catch` was called proves a handler was
attached, not which one: swapping ignoreMissingListener for `() => {}` kept
the tests green.
Asserting PublicLogger.warn stays silent on the missing-listener code does
not close that gap either, since a no-op catch is also silent. Verified by
mutation: with `() => {}` at both call sites, the silent-case assertions
still pass. What fails is a rejection the helper is supposed to warn about,
so each spec now has that case, using the uncoded string the library's
no-ack timeout actually rejects with.
Also from review: import VisualBuilderPostMessageEvents as a type in
postMessageErrors.ts, since it is only used in a type position.
Co-Authored-By: Claude <noreply@anthropic.com>
…y spy lifecycles Review found that every warn-branch assertion read only the message the helper builds from the event name, so dropping the error argument from PublicLogger.warn kept all of them green while the warning lost the part that says what failed. All four sites now assert the second argument. Verified by mutation: removing that argument fails all four. Also from review: - capture MutationObserver in beforeEach rather than at module scope. The setup file installs its stub in beforeAll, so the module-level read took jsdom's native implementation and afterEach restored the wrong one. - restore spies in the SSR block's afterEach. clearAllMocks leaves the implementation in place, so PublicLogger.warn stayed stubbed for the rest of the file once these tests had run. - assert the rejected value instead of toBeTruthy, which held regardless of what the code did. Co-Authored-By: Claude <noreply@anthropic.com>
…nhandled-rejection fix(visual-builder): handle rejection when discussion highlights has no listener
✅ Snyk checks have passed. No issues have been found so far.
💻 Catch issues earlier using the plugins for VS Code, JetBrains IDEs, Visual Studio, and Eclipse. |
🔒 Security Scan Results
⏱️ SLA Breach Summary
✅ BUILD PASSED - All security checks passed |
There was a problem hiding this comment.
Copilot review overview
🟢 Approval recommended
No unresolved issues were identified.
Review effort: Lite
Findings: None
What changed in this PR
Develop v4 adds safe handling for unavailable visual-builder postMessage listeners.
Changes:
- Adds reusable missing-listener rejection handling.
- Applies it to variant and mutation-triggered highlight requests.
- Adds unit and integration test coverage.
| File | Description |
|---|---|
src/visualBuilder/utils/postMessageErrors.ts |
Defines rejection filtering and warning behavior. |
src/visualBuilder/utils/__test__/postMessageErrors.test.ts |
Tests error handling behavior. |
src/visualBuilder/eventManager/useVariantsPostMessageEvent.ts |
Handles rejected highlight requests. |
src/visualBuilder/eventManager/useRecalculateVariantDataCSLPValues.ts |
Handles rejected observer-triggered requests. |
src/visualBuilder/eventManager/__test__/useVariantsPostMessageEvent.spec.ts |
Tests variant request rejection handling. |
src/visualBuilder/eventManager/__test__/useRecalculateVariantDataCSLPValues.spec.ts |
Tests observer request rejection handling. |
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
Coverage Report
File Coverage
|
||||||||||||||||||||||||||||||||||||||||||||||||||
hitesh-shetty-cstk
left a comment
There was a problem hiding this comment.
Automated review
What this changes: Two fire-and-forget REQUEST_DISCUSSION_HIGHLIGHTS sends now attach a rejection handler. A new ignoreMissingListener helper returns silently when the receiver replies that no listener is registered for the event, and warns through PublicLogger for anything else. In useVariantFieldsPostMessageEvent the send also moves out of the SSR and CSR branches into a single call after them.
Business impact: none identified. The handler being restructured is the GET_VARIANT_ID path, so an error here would show up as variant switching on the canvas going wrong: classes not reapplied after a variant change, or discussion highlights not refreshing. I compared the hoisted send against the original and it is behaviour preserving, since both branches sent unconditionally before. The existing SSR and CSR assertions for that send are untouched and still pass through the same code path.
Security: nothing beyond what the scanners cover. No origin or payload validation changes. The value handed to PublicLogger.warn comes from the post message library itself, either a { code, message } object it constructs, an Error, or a fixed string, so the new log line does not put entry or user content into the console.
Flow
sequenceDiagram
participant VB as Visual Builder (parent window)
participant SDK as Live Preview SDK (iframe)
VB->>SDK: GET_VARIANT_ID / VARIANT_PATCH
alt CSR
SDK->>SDK: updateVariantClasses() installs MutationObservers
SDK->>SDK: debounced requestDiscussionHighlights()
else SSR
SDK->>SDK: addVariantFieldClass(variant)
end
SDK->>VB: send REQUEST_DISCUSSION_HIGHLIGHTS
Note over SDK: changed here
alt Discussions panel mounted
VB-->>SDK: response, highlights recomputed
else panel closed, no listener
VB-->>SDK: reject { code: NO_REQUEST_LISTENER_FOUND }
SDK->>SDK: ignoreMissingListener returns, no log
else no ACK within 1s
VB--xSDK: reject (uncoded string)
SDK->>SDK: PublicLogger.warn
end
Findings: 0 blocker, 0 should fix, 1 nit. The nit is inline, on the new observer spec.
Since the finding count is low, here is what I checked against the dependency rather than assumed, so the verdict is reviewable:
ERROR_CODES.receiveEvent.noRequestListenerFoundis exactly the stringNO_REQUEST_LISTENER_FOUNDin@contentstack/advanced-post-message@0.0.5, and the receiver replies witherror: { code, message }when its request handler map has no entry for the type. The equality check in the helper matches the real wire value.sendis declared asPromise<ReturnType>, so.catchtype checks, andvisualBuilderPostMessage?.send(...).catch(...)short circuits as one chain when the manager is undefined. No new failure path when the SDK runs outside an iframe.- The no-ACK path rejects with a bare string after 1s and the closed-window path with an uncoded
Error. Neither carries acode, which is what the helper's JSDoc claims and what the tests pin. - On the builder side the listener is registered in an effect that unregisters when the Discussions panel unmounts, so the silent branch is the ordinary case and the warn branch needs the parent to stop acking altogether.
One thing I looked at and am leaving out of scope: the same unhandled rejection shape exists at the other fire-and-forget sends in this repo, SEND_VARIANT_AND_LOCALE in visualBuilder/index.ts, MOUSE_CLICK and FOCUS_FIELD in listeners/mouseClick.ts, and the two in utils/instanceHandlers.ts. Those are quiet today only because their listeners are registered once at builder level rather than with a panel, which is an assumption nothing enforces. A follow-up applying this helper there would be worth more than widening this PR.
Reviewer candidates:
- @karancs06 authored the two most recent commits on
useRecalculateVariantDataCSLPValues.tsand 3 of the last 30 onuseVariantsPostMessageEvent.ts. - @csAyushDubey authored 5 of the last 30 commits on
useVariantsPostMessageEvent.ts.
The heaviest author across these files is @hitesh-shetty-cstk, with 12 of the last 30 commits on useVariantsPostMessageEvent.ts and 6 of the last 13 on its spec. That is the account posting this automated review, so it is named here to consult rather than requested.
Not covered: I did not run the test suite, the type check, or the build, and I did not exercise the Discussions panel against a running builder. Dependencies are not installed in this environment, so the library behaviour above was read from the published package rather than observed. Whether the 200 ms debounce plus the direct send produces duplicate highlight recomputation in CSR is pre-existing and not something I measured.
Automated review by Claude Code. A human review is still required.
Generated by Claude Code
Co-Authored-By: Claude <noreply@anthropic.com>
Updated codeowners
Co-Authored-By: Claude <noreply@anthropic.com>
release: v4.5.3 (sync main into develop_v4)
🔒 Security Scan Results
⏱️ SLA Breach Summary
✅ BUILD PASSED - All security checks passed |
1 similar comment
🔒 Security Scan Results
⏱️ SLA Breach Summary
✅ BUILD PASSED - All security checks passed |
hitesh-shetty-cstk
left a comment
There was a problem hiding this comment.
Re-review after new commits (pass 2 of 4).
Automated review
What this changes: Nothing under src/ moved since the last pass. The delta is release tooling, arriving through two sync merges from main plus the version bump. npm-publish.yml is rewritten into separate publish and publish-alpha jobs triggered on release: published, npm-alpha-publish.yml is deleted, the coverage action is pinned to a commit sha, CODEOWNERS is rewritten, prepack now runs the build so dist ships in the tarball, and package.json with the README CDN pin move to 4.5.3.
Business impact: The release path, which is the one journey here that reaches customers directly. Worth stating up front: every workflow and CODEOWNERS commit in this delta is already on main and byte identical there, so this PR carries them down to stage_v4 rather than introducing them. It still matters, because v4.5.3 is cut from this branch. The blocker below does not affect v4.5.3. It affects the next prerelease, which under this repo's own tag convention would publish to the latest dist-tag and reach every consumer on a caret range, including the esm.sh snippet in the README.
Security: nothing beyond what the scanners cover. Three things I checked rather than assumed, since the publish job lost its NODE_AUTH_TOKEN in this delta:
- The tokenless shape is not a break. v4.5.2 published through this same workflow on 16 September, and the follow-up hotfix that restored the build proves the publish step ran and authenticated. OIDC trusted publishing is configured and working, which is also why
id-token: writeand the npm upgrade step are there. persist-credentials: falseand pinning the checkout torelease.tag_nameare both narrower than what they replace.- The one moving dependency left in the release path is
npm install -g npm@latest, flagged inline as a nit.
Flow
flowchart TD
A[GitHub Release published] --> B{"release.name ends with -alpha?"}
B -- "false" --> C["publish job<br/>npm publish --provenance"]:::changed
B -- "true" --> D["publish-alpha job<br/>npm publish --tag alpha"]:::changed
C --> E[latest dist-tag]
D --> F[alpha dist-tag]
G["release titled v4.6.0-alpha.0<br/>or left untitled"] -.-> H[gate reads false]:::risk
H -.-> C
classDef changed fill:#fff3cd,stroke:#d39e00
classDef risk fill:#f8d7da,stroke:#c82333
Findings: 1 blocker, 0 should fix, 1 nit. Both are inline on .github/workflows/npm-publish.yml.
Copilot posted the same alpha routing finding on this head a few minutes before this pass. I have kept mine because it adds the untitled-release case and the provenance note, not to restate the part it already covers. Its other open finding, about the version bump conflicting with the post-merge plan, is answered by the description as it now reads, which lists the bump as done and the release as the next step.
Two things I looked at and am not raising:
- The changelog now carries a proper
v4.5.3section with a real compare link, so the duplicate heading from the earlier pass is gone. - CODEOWNERS moves blanket ownership from
visual-preview-developerstoghost-pr-reviewersand puts.github/workflows/and CODEOWNERS itself behind the security team. That is a review governance change rather than a code defect, so it is a note rather than a finding, but it is the kind of thing worth being deliberate about since it changes who is pulled onto every future PR here.
Reviewer candidates: none requested. Reviewer assignment runs on the opening pass only, and this is pass 2. For the record, the release workflow in its current form is @Aravind-Kumar-cstk's (both consolidating commits) and @kirtesh-cstk's (the --tag alpha fix that the blocker extends). @kirtesh-cstk has already reviewed this PR, so the blocker is landing in front of the right person without a new request.
Not covered: I did not run the tests, the build, or the type check, and I cannot exercise a release without cutting one. I did not verify that the pinned vitest-coverage-report-action sha corresponds to the v2.13.0 tag in the comment beside it, because that repository is outside what I am allowed to read. I could not inspect the trusted publisher configuration on the registry side, so the conclusion that OIDC works rests on v4.5.2 having shipped through this workflow rather than on the npm settings themselves.
Automated review by Claude Code. A human review is still required.
Generated by Claude Code



Live Preview SDK v4.5.3: develop_v4 to stage_v4
Summary
Promotes develop_v4 into stage_v4 with the v4.5.3 release content: a fix for an unhandled promise rejection in the Visual Builder discussion-highlights messaging, the v4.5.2 release commits synced back from main (#658), and the v4.5.3 version bump. After this merges, stage_v4 is level with develop_v4 and ready for the final stage_v4 to main release PR.
What's changed
Fixes
ignoreMissingListenerhelper insrc/visualBuilder/utils/postMessageErrors.tsswallows the library's missing-listener rejection and logs a console warning for any other send failure. Both send sites use it:useVariantsPostMessageEventanduseRecalculateVariantDataCSLPValues.Tests
Synced from main (v4.5.2 release, via #658)
prepacksodistships in the published tarball, prereleases publish under thealphadist-tag, and the retired alpha-publish workflow file is removed.vitest-coverage-report-actionpinned to a commit sha.Chores
4.5.3; CHANGELOG regenerated viaauto-changelogwith av4.5.3section for the pending fix.@contentstack/live-preview-utils@4.5.3.Release path
develop_v4develop_v4tostage_v4)stage_v4tomainrelease PRv4.5.3frommain(tag created via the Release UI), which triggers thenpm-publishworkflow@contentstack/live-preview-utils@4.5.3on npm and thathttps://esm.sh/@contentstack/live-preview-utils@4.5.3resolves🤖 Generated with Claude Code