Skip to content

Conversation

@davidturnbull
Copy link
Contributor

@davidturnbull davidturnbull commented Oct 9, 2025

Summary

Refactor Lingo.dev Compiler API with dedicated framework-specific export paths for Vite and Next.js, improving developer experience with clearer imports and plugin usage patterns.

What changed

New framework-specific export paths

The compiler now provides dedicated, publicly-documented export paths instead of requiring framework-specific method access on a default export:

Before (old pattern):

import lingoCompiler from "lingo.dev/compiler";

// Using framework-specific methods
export default lingoCompiler.vite(config)(viteConfig);
export default lingoCompiler.next(config)(nextConfig);

After (new pattern):

// Direct, framework-specific imports
import { lingo } from "lingo.dev/compiler/vite";
import { withLingo } from "lingo.dev/compiler/next";

// Use as regular Vite plugins
plugins: [lingo(config), react(), ...]

// Use as Next.js configuration wrapper
export default withLingo(config)(nextConfig);

Structural changes

  • Created packages/compiler/src/vite.ts: Exports lingo() function that returns a Vite-compatible plugin. Automatically detects React Router and emits appropriate build events.
  • Created packages/compiler/src/next.ts: Exports withLingo() function with Next.js-specific configuration handling (Webpack, Turbopack, etc).
  • Refactored packages/compiler/src/unplugin.ts: Extracted core unplugin logic that was previously in index.ts.
  • Updated packages/compiler/src/index.ts: Now maintains backward compatibility by delegating to the new framework-specific modules.
  • Updated package exports: Added ./compiler/vite and ./compiler/next export paths in both packages/cli/package.json and packages/compiler/package.json.
  • Updated build config: Modified packages/cli/tsup.config.ts to build the new export paths.

Demo updates

All demo projects have been updated to use the new API:

  • demo/vite-project/vite.config.ts: Now uses lingo() as a regular plugin instead of the curried wrapper pattern
  • demo/react-router-app/vite.config.ts: Simplified to inline plugin format
  • demo/adonisjs/vite.config.ts: Uses new import path with cleaner plugin array
  • demo/next-app/next.config.ts: Uses withLingo() instead of lingoCompiler.next()

Why

  • Clearer mental model: Users import what they need for their framework rather than accessing nested methods
  • Better TypeScript support: Direct imports enable better IDE autocomplete and type checking
  • Familiar patterns: Follows standard conventions for framework plugins (similar to Tailwind, React Router, etc)
  • Backward compatible: Old API still works through re-exports in the default export
  • Easier to document: Framework-specific docs can point to specific import paths

Testing

To verify the new API works correctly:

  1. Verify package exports are built correctly:

    cd packages/compiler && pnpm build
    ls -la build/vite.* build/next.*
  2. Test Vite integration with demo project:

    cd demo/vite-project && pnpm install && pnpm dev
    # Verify compilation works in browser
  3. Test Next.js integration with demo project:

    cd demo/next-app && pnpm install && pnpm build
    # Verify build completes successfully
  4. Test React Router demo:

    cd demo/react-router-app && pnpm install && pnpm dev
    # Verify React Router framework is detected and build events are correct
  5. Verify backward compatibility:

    • Projects still using the old lingoCompiler.vite() and lingoCompiler.next() API should continue working
    • Check that the old pattern still functions correctly as a fallback

@davidturnbull davidturnbull requested a review from vrcprl October 20, 2025 22:49
@davidturnbull davidturnbull marked this pull request as ready for review October 20, 2025 22:49
davidturnbull and others added 9 commits October 21, 2025 12:15
Resolved conflicts in packages/compiler/src/index.ts by keeping the refactored structure that moves implementation to separate files (unplugin.ts, vite.ts, next.ts) while maintaining backward-compatible API.
- Align all packages to use vite ^6.0.0
- Add pnpm override to enforce single vite version
- Cast lingo plugin in adonisjs demo to avoid type conflicts from multiple @types/node versions
…ode version

The root cause was multiple @types/node versions (22.x and 24.x) in the monorepo
causing pnpm to install vite multiple times with different type definitions.
TypeScript treats Plugin types from different vite installations as incompatible.

Solution:
- Added @types/node: ^22.0.0 to pnpm overrides
- Removed workaround 'as any' cast from adonisjs vite.config.ts
- All packages now use unified @types/node@22.18.12

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
@davidturnbull davidturnbull force-pushed the davidt-compiler-init-api branch 2 times, most recently from 249b1ab to 101aaab Compare October 22, 2025 01:48
…conflicts

Root cause: Different packages in the monorepo have different @types/node versions,
causing pnpm to install multiple vite instances with incompatible Plugin type
definitions. TypeScript treats these as different types even when structurally identical.

Solution: Export vite plugin with `any` return type to avoid cross-package type conflicts
while maintaining full internal type safety through explicit parameter typing.

This is the idiomatic solution for plugin packages consumed across a monorepo with
varying dependency versions. No dependency version changes needed.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
@davidturnbull davidturnbull force-pushed the davidt-compiler-init-api branch from 101aaab to 57a0278 Compare October 22, 2025 01:53
davidturnbull and others added 10 commits October 22, 2025 12:56
Prevents pnpm from upgrading @noble/hashes from 1.5.0 to 2.0.1, which
requires Node >= 20.19.0. CI runs Node 20.12.2.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
When vite was added as devDependency to packages/compiler, pnpm re-resolved
all dependencies and upgraded:
- @noble/hashes 1.5.0 → 2.0.1 (requires Node >= 20.19.0, we have 20.12.2)
- @paralleldrive/cuid2 2.2.2 → 2.3.0 (ESM-only, breaks CJS builds)

Overrides force compatible versions.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
This reverts commit 5bd0773.
- Compiler: Vitest ^3, Vite ^6
- Compiler: add peerDependencies vite ^6
- SDK: replace cuid2 with crypto.randomUUID
- CLI/SDK: remove cuid2 dependency
- Core: align @types/node to ^20.19.23
- Root: drop overrides for vite, @noble/hashes, cuid2

Verified: compiler and sdk build; compiler tests pass
Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Copilot encountered an error and was unable to review this pull request. You can try again by re-requesting a review.

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