Sequelize Guard
Back to Blog

5 Years Later: sequelize-guard Goes Full TypeScript (with AI as Co-Pilot)

The journey of rewriting a 5-year-old JavaScript authorization library in TypeScript, and how AI helped modernize an open-source project while preserving its battle-tested architecture.

Pankaj Vaghela
typescriptopen-sourcesystem-designaisequelize

5 Years Later: sequelize-guard Goes Full TypeScript (with AI as Co-Pilot)

Back in 2019, I open-sourced sequelize-guard—a lightweight authorization library that brings Laravel-style permissions to Sequelize.js in Node.js. It was born out of a real need: managing role-based access control without drowning in complexity.

Today, I'm proud to ship v6: fully rewritten in TypeScript with a modern documentation site!

This post is about the journey, the lessons learned about system design, and how AI became an invaluable co-pilot in modernizing open-source software.

The Genesis: Why sequelize-guard Exists

Authorization is one of those problems that seems simple until you actually implement it. You need roles, permissions, caching, audit trails, and a clean API that doesn't make developers want to tear their hair out.

I wanted something that felt as intuitive as Laravel's authorization system but worked seamlessly with Sequelize in Node.js. The result was sequelize-guard:

await user.can('edit:post'); // Simple, readable, powerful

Clean separation of roles, permissions, and caching. Event-driven hooks for auditing. A fluent API that reads like natural language.

System Design That Stands the Test of Time

Here's the thing about good architecture: it ages well.

The original JavaScript codebase was built with longevity in mind. Even after 5 years, multiple Sequelize major versions (v5 → v6), and the entire JavaScript ecosystem evolving around it, the core logic ported to TypeScript almost unchanged.

What Made It Last?

1. Strong Abstractions

The library was built around clear concepts:

  • Roles as containers for permissions
  • Permissions as action-resource pairs
  • Caching layer as a separate concern
  • Event system for extensibility

These abstractions didn't leak. They didn't depend on Sequelize internals more than necessary. They just... worked.

2. Fluent, Readable API

// This API design from 2019 still feels modern in 2024
user.can('edit:post')
user.isA('admin')
user.isAnyOf(['admin', 'editor'])

When your API reads like natural language, it doesn't age. It doesn't need "modernizing" because it was already intuitive.

3. Event-Driven Architecture

guard.on('permission:checked', (event) => {
  // Audit logging, analytics, whatever you need
});

By emitting events at key points, the library became extensible without modification. Users could hook into the authorization flow without touching the core.

The Lesson: Invest in strong abstractions early. They make migrations painless and keep your code relevant for years.

Maintainability in Open Source

JavaScript moves quickly. What felt state-of-the-art in 2019 looked a bit dated by 2024.

The v6 rewrite wasn't just about adding types—it was about setting the project up for the next several years.

The Modernization Checklist

  • TypeScript with strict generics for models & permissions
  • Dual ESM + CommonJS support for maximum compatibility
  • Vitest for testing (goodbye Jest config hell)
  • Vite for blazing-fast builds
  • Typedoc for auto-generated API documentation
  • 99% backward compatible (breaking changes only where absolutely necessary)

Why This Matters

Open source projects thrive when they keep evolving at a sustainable pace. A modern toolchain makes it easier for maintainers and contributors to keep improving things without constant friction.

By modernizing the toolchain, I aimed to make sure that:

  • New contributors can jump in with familiar tools
  • The library works smoothly with modern Node.js projects (ESM)
  • TypeScript users get first-class support
  • The documentation stays fresh and accurate

The Lesson: A little ongoing maintenance goes a long way. Investing in your tooling and architecture makes it much easier for your project to keep growing over time.

LLMs as Open-Source Superchargers

Here's where it gets interesting.

I approached this massive rewrite by treating Claude and GPT-4 as my co-pilots. I gave them the old JavaScript codebase and a clear task:

"Migrate to strict TypeScript. Keep 100% behavior. Add generics. Update tests."

What AI Crushed

The Repetitive Work:

  • Type definitions across hundreds of lines of code
  • Converting modules from CommonJS to ESM
  • Migrating test suites from Jest to Vitest
  • Generating boilerplate for generic types
  • Updating configuration files for modern tooling

This is the kind of work that's tedious, error-prone, soul-crushing and easy to get wrong when you're tired. AI handled it with remarkable consistency.

What I Still Owned

The High-Value Work:

  • Core architecture decisions
  • Handling complex edge cases specific to Sequelize
  • Designing the generic type system for models
  • Setting up CI/CD pipelines
  • Building and deploying the documentation site
  • Reviewing and validating AI-generated code

The Truth About AI-Assisted Development

AI didn't replace me. It removed the noise so I could focus purely on quality, correctness, and architecture.

Think of it like this:

  • Before AI: 70% grunt work, 30% creative problem-solving
  • With AI: 20% grunt work, 80% creative problem-solving

The work became more intellectually engaging. I spent less time typing boilerplate and more time thinking about design.

The Lesson: AI is a helpful force multiplier for maintainers. It doesn't replace expertise—it gives you more space to use it.

The Result: Battle-Tested, Type-Safe, Future-Proof

sequelize-guard v6 is everything the original was, but better:

// Now with compile-time type checking!
await user.can('delete:user'); // TypeScript knows this is valid

// Generic support for your models
const guard = new SequelizeGuard<MyUserModel>(sequelize);

// Full IntelliSense support
user.assignRole('admin'); // Autocomplete works perfectly

What Users Get

  • Type Safety: Catch permission errors at compile time
  • Better DX: IntelliSense, autocomplete, inline documentation
  • Modern Tooling: Works with ESM, Vite, and modern Node.js
  • Same Great API: If you used v5, v6 feels familiar
  • Comprehensive Docs: sequelize-guard.js.org

A Message to Open-Source Maintainers

If you have an open-source gem sitting quietly in your GitHub repos, it's never too late to modernize.

The tools are better than ever:

  • TypeScript makes refactoring safer
  • AI can help carry the grunt work
  • Modern build tools (Vite, Vitest) are faster and simpler
  • Documentation generators (Typedoc, VitePress) are incredible

The community is here. People still care about well-designed libraries that solve real problems.

If your project feels a bit behind on tooling, that's okay—it happens to every codebase. A small round of improvements can give it new life.

Try It Out

If you use Sequelize + Node.js, I'd love for you to try sequelize-guard v6:

I'd especially love to hear your thoughts on the new type system and developer experience.


About the Author: Pankaj Vaghela is a software engineer passionate about system design, open source, and building tools that make developers' lives easier. With over a decade of experience in full-stack development, he specializes in creating scalable solutions and contributing to the open-source community. Learn more at pankajvaghela.in or connect on GitHub.