Skip to content

Modernize tooling: tsdx → tsup, vitest, ESM exports, CI#483

Merged
adeelraza merged 6 commits into
masterfrom
modernize-tooling
Jul 6, 2026
Merged

Modernize tooling: tsdx → tsup, vitest, ESM exports, CI#483
adeelraza merged 6 commits into
masterfrom
modernize-tooling

Conversation

@adeelraza

@adeelraza adeelraza commented Jul 6, 2026

Copy link
Copy Markdown
Contributor

Why

The repo's toolchain had drifted: tsdx has been abandoned for years, there was no ESM entry point, no CI, and @unlayer/types floated on latest. This PR is the foundation pass — build, packaging, tests, and repo automation — so follow-ups (demo modernization, release automation) have something solid to build on.

What changed

Build & packaging

  • tsdx 0.14 → tsup (ESM + CJS + declaration files). The bundle now ships a 'use client' banner, so it works out of the box in Next.js App Router / RSC apps (How to Edit custom options on nextjs #458).
  • Proper exports map with per-condition types (index.d.mts / index.d.ts), sideEffects: false, module field. Verified with publint and @arethetypeswrong/cli — all green across node10/node16/bundler resolution modes.
  • @unlayer/types pinned to ^1.448.0 instead of latest (fixes Pin unlayer-types Dependency to a Fixed Version Instead of latest #469).
  • TypeScript 4.9 → 6.0, dev/test deps on React 19, engines.node >= 18 (was >= 10).
  • React peer range corrected from >=15 to >=16.8 — the component uses hooks, so React 15/16.7 never worked.
  • Removed the husky v4-style config that husky 8 silently ignored (the pre-commit hook never ran); linting moves to CI.

Bug fixes (found while migrating)

  • Unmount cleanup captured the first-render editor state (always null), so editor.destroy() was never called on unmount. Now tracked via a ref.
  • The event-listener effect depended on Object.keys(methodProps).join(',') — array indices, not prop names — so it re-ran on the count of on* props rather than their identity. Now methodProps.join(',').

Tests

  • jest-via-tsdx → vitest; the single smoke test grew to 5 tests covering editor creation options, ref exposure, onLoad, on* event registration, onReady wiring, and destroy-on-unmount (which catches the bug above).

Repo automation

  • GitHub Actions CI: lint + typecheck + build, and a test matrix across Node 20/22/24 × React 18/19 (React 18 leg verified locally).
  • Dependabot for npm and github-actions (weekly, dev deps grouped).
  • Issue templates: a structured bug-report form for wrapper bugs, with contact links routing editor-behavior questions to Unlayer support/docs.

README

  • Usage example no longer uses render from react-dom (removed in React 19) — now createRoot.
  • Added a Next.js / RSC note, CI badge, fixed the license badge pointing at a nonexistent main branch.

Release plan

  • Ships as 2.0.0 (version bumped in this PR): the exports map, ES2019 output, peer-range narrowing, and engines bump are breaking under semver. CHANGELOG.md and a README upgrade guide are included.
  • Not included (possible follow-ups): rebuilding the demo (still on Parcel 1 / TS 3.4) and release automation (release-please/changesets + CHANGELOG).

🤖 Generated with Claude Code

adeelraza and others added 2 commits July 6, 2026 22:44
- Replace abandoned tsdx 0.14 with tsup (ESM + CJS + dts, 'use client'
  banner for React Server Components environments) and vitest
- Add proper package.json exports map with per-condition types,
  sideEffects: false, and engines >= 18 (was >= 10)
- Pin @unlayer/types to ^1.448.0 instead of "latest" (#469)
- Bump TypeScript 4.9 → 6.0, React dev deps to 19, correct react peer
  range to >=16.8 (component uses hooks)
- Fix unmount cleanup never destroying the editor (stale closure) and
  the event-listener effect depending on array indices instead of names
- Expand tests: editor creation, ref/onLoad, event registration, destroy
- Add GitHub Actions CI (Node 20/22/24 × React 18/19), dependabot, and
  issue templates routing editor questions to Unlayer support
- Remove dead husky v4-style config that husky 8 never executed
- README: createRoot instead of removed react-dom render, Next.js note,
  CI badge

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
- Enforce vitest coverage thresholds (95% stmts/lines, 90% branches/funcs)
- Cover loadScript.ts directly (injection dedupe, callback queue, custom URL)
- Scope test discovery to test/ and coverage to src/
- Upload lcov to Codecov from CI; add coverage badge to README

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@codecov

codecov Bot commented Jul 6, 2026

Copy link
Copy Markdown

Welcome to Codecov 🎉

Once you merge this PR into your default branch, you're all set! Codecov will compare coverage reports and display results in all future pull requests.

Thanks for integrating Codecov - We've got you covered ☂️

- unlayer.com/help was a 404; support links now point to unlayer.com/contact
- Update docs.unlayer.com URLs to their post-restructure destinations
- Use https for the video thumbnail image

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@adeelraza
adeelraza force-pushed the modernize-tooling branch from 82d8df2 to 04fef4c Compare July 6, 2026 19:33
adeelraza and others added 2 commits July 6, 2026 23:34
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
The main suite can't run on React <18 (@testing-library/react requires
18+), so these render with the legacy ReactDOM.render API directly and
cover mount + createEditor, ref/onLoad, and destroy-on-unmount. CI runs
them via npm run test:legacy on react@16 and react@17.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

@ivoIturrieta ivoIturrieta 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.

Looking great!

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@adeelraza
adeelraza merged commit 905f629 into master Jul 6, 2026
13 checks passed
@adeelraza
adeelraza deleted the modernize-tooling branch July 6, 2026 19:58
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.

Pin unlayer-types Dependency to a Fixed Version Instead of latest

2 participants