Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings

AnandPilania/eloquentjs

Open more actions menu

Repository files navigation

EloquentJS

Laravel Eloquent for Node.js — modular, extensible, batteries-included.

// Reads like English.
const users = await User
  .where('active', true)
  .where('age', '>', 18)
  .with('posts', 'profile')
  .orderBy('name')
  .paginate(1, 20)

Tests License Node MCP


Packages

Package Version Description
@eloquentjs/core npm Base Model, QueryBuilder, Relations, Events, Casts
@eloquentjs/codegen npm Shared code generation — GraphQL SDL, TypeScript, OpenAPI, stubs
@eloquentjs/validator npm Full validation — async rules, fluent schema API, unique/exists, adapters
@eloquentjs/pgsql npm PostgreSQL driver (multi-connection, transactions)
@eloquentjs/sqlite npm SQLite driver (better-sqlite3, file or in-memory)
@eloquentjs/mongodb npm MongoDB driver
@eloquentjs/realtime npm WebSocket pub/sub — Pusher-protocol, auto-broadcast
@eloquentjs/graphql npm Auto-generate GraphQL schema + resolvers
@eloquentjs/api npm One-line REST CRUD routes (Express + Fastify)
@eloquentjs/mcp npm MCP server — 21 tools for AI agents (Claude, Cursor, Windsurf)
@eloquentjs/cli npm CLI — scaffold, migrate, seed, generate

Quick Start

npm install @eloquentjs/core @eloquentjs/pgsql
# Or: npm install @eloquentjs/core @eloquentjs/sqlite
npm install -g @eloquentjs/cli

# Initialize in your project
eloquent init

# Scaffold a model with everything
eloquent make:model User --all

# Run migrations
eloquent migrate

# Generate GraphQL schema, TypeScript types, and OpenAPI spec
npm install @eloquentjs/codegen
eloquent generate:graphql
eloquent generate:types
eloquent generate:openapi

# Add MCP server for AI agents (Claude.ai, Cursor, Windsurf)
npm install -g @eloquentjs/mcp
eloquent-mcp --cwd .

Feature Highlights

Model & Query Builder

import { Model } from '@eloquentjs/core'

class User extends Model {
  static table       = 'users'
  static fillable    = ['name', 'email', 'password']
  static hidden      = ['password']
  static softDeletes = true
  static casts       = { is_admin: 'boolean', settings: 'json', created_at: 'date' }

  posts()   { return this.hasMany(Post) }
  profile() { return this.hasOne(Profile) }
  roles()   { return this.belongsToMany(Role, 'user_roles') }

  getFullNameAttribute()  { return `${this.first_name} ${this.last_name}` }
  setPasswordAttribute(v) { return bcrypt.hashSync(v, 10) }

  static scopeActive(qb)   { return qb.where('active', true) }
  static async creating(u) { u.slug = slugify(u.name) }
}

await User.where('active', true).with('posts').orderBy('name').paginate(1, 20)
await User.whereIn('role', ['admin', 'editor']).get()
await User.whereBetween('age', [18, 65]).count()
await User.active().admins().latest().first()

// Global mass-assignment bypass
Model.unguard()
await User.create({ id: 99, name: 'Seed User', email: 'seed@example.com' })
Model.reguard()

// Or use the scoped helper to restore automatically
await Model.unguarded(async () => {
  await User.create({ id: 99, name: 'Seed User', email: 'seed@example.com' })
})

Validation

import { v, Rule } from '@eloquentjs/validator'

const schema = v.schema({
  name:     v.string().min(2).max(100),
  email:    v.string().email().unique('users', 'email'),  // async DB check
  password: v.string().min(8).confirmed(),
  age:      v.number().integer().min(18).optional(),
  role:     v.string().oneOf(['admin', 'editor', 'viewer']),
  address:  v.object({ city: v.string(), zip: v.string().digits(5) }),
})

const data = await schema.parseAsync(req.body)   // throws ValidationException on failure
const { success, errors } = await schema.safeParseAsync(req.body)  // never throws

// Express middleware
import { expressValidate } from '@eloquentjs/validator/adapters'
router.post('/users', expressValidate(schema, { async: true }), handler)
// req.validated contains only schema-defined fields

Relations

// Eager load — prevents N+1
await User.with('posts.comments.author').get()
await User.with({ posts: qb => qb.where('published', true) }).get()

// BelongsToMany pivot
await user.roles().attach(roleId, { assigned_at: new Date() })
await user.roles().sync([1, 2, 3])

// Polymorphic
class Comment extends Model {
  commentable() { return this.morphTo('commentable') }
}

Events & Observers

class UserObserver {
  creating(user) { user.uuid = crypto.randomUUID() }
  created(user)  { WelcomeEmail.send(user) }
  deleting(user) { user.posts().delete() }
}
HookRegistry.observe(User, new UserObserver())

Realtime

import { createRealtimeServer } from '@eloquentjs/realtime'
const rt = createRealtimeServer({ port: 6001 })
rt.broadcastFrom(User)   // broadcasts User:created/updated/deleted

GraphQL

import { buildSchema, buildSchemaFromDir } from '@eloquentjs/graphql'

const { typeDefs, resolvers } = buildSchema([User, Post, Comment], {
  subscriptions: true,
  auth: async (ctx) => authenticateFromToken(ctx.req.headers.authorization),
})

// Or auto-load all models from a directory
const { typeDefs, resolvers } = await buildSchemaFromDir('./app/models')

// CLI generation
eloquent generate:graphql --out=schema.graphql
eloquent generate:graphql --pagination=relay

REST API

import { apiRouter, resource } from '@eloquentjs/api'
app.use('/api', apiRouter([
  resource(User, {
    middleware:  [authRequired],
    with:        ['profile'],
    searchable:  ['name', 'email'],
    sortable:    ['name', 'created_at'],
    policy:      async (req, model, action) => action === 'destroy' ? req.user.is_admin : true,
  }),
  resource(Post, { only: ['index', 'show', 'store'] }),
]))
// GET /api/users?page=1&search=alice&sort=-created_at&with=profile

MCP Server for AI Agents

// Start the MCP server — AI agents get 21 tools to work with your models
eloquent-mcp --cwd /path/to/project

// Tools available to the agent:
// list_models, describe_model, describe_database_schema
// generate_model, generate_migration, generate_graphql_schema
// query_model, run_migrations, migration_status
// get_help, get_method_signature, get_examples
// nlp_query, nlp_crud, ... (21 total)

Configure in your AI tool — see @eloquentjs/mcp for setup instructions for Claude.ai, Cursor, and Windsurf.


AI Agent Files

The agent-files/ directory contains ready-to-use files for AI coding assistants:

File For
CLAUDE.md Claude.ai — drop in project root, auto-loaded
GEMINI.md Gemini-based tools
.cursorrules Cursor — drop in project root
.windsurfrules Windsurf — drop in project root
copilot-instructions.md GitHub Copilot — copy to .github/copilot-instructions.md
skills/db-skill.md Deep DB patterns for any agent
skills/api-skill.md REST API patterns
skills/mcp-skill.md MCP tool reference and setup

Repository Structure

eloquentjs/
├── packages/
│   ├── core/          @eloquentjs/core
│   ├── codegen/       @eloquentjs/codegen
│   ├── validator/     @eloquentjs/validator
│   ├── pgsql/         @eloquentjs/pgsql
│   ├── mongodb/       @eloquentjs/mongodb
│   ├── realtime/      @eloquentjs/realtime
│   ├── graphql/       @eloquentjs/graphql
│   ├── api/           @eloquentjs/api
│   ├── mcp/           @eloquentjs/mcp
│   └── cli/           @eloquentjs/cli
├── tests/
│   └── unit/          702 tests, 12 suites, all passing
├── agent-files/       CLAUDE.md, .cursorrules, skills/...
├── .github/
│   └── workflows/     CI + Release automation
├── scripts/
│   ├── release.js     Version bump + changelog
│   ├── publish.js     npm publish orchestration
│   └── check-versions.js  Version consistency check
└── CHANGELOG.md

Development

git clone https://github.com/your-org/eloquentjs.git
cd eloquentjs && npm install

npm test                                           # run all 700 tests
npm run test:coverage                              # with coverage report
npm test -- --testPathPattern=MCP                  # single suite
npm run check:versions                             # verify all packages at same version

Releasing

All packages share one version number. Full process in RELEASING.md.

npm run release:patch    # 1.0.0 → 1.0.1
npm run release:minor    # 1.0.0 → 1.1.0
npm run release:major    # 1.0.0 → 2.0.0
npm run release:alpha    # 1.0.0 → 1.0.1-alpha.0
npm run release:beta     # 1.0.0 → 1.0.1-beta.0
npm run publish:all      # publish all 11 packages to npm

Contributing

  1. Fork → branch: git checkout -b feat/my-feature
  2. Write tests: npm test
  3. Commit via Conventional Commits: feat(core): add X
  4. Open a Pull Request

License

MIT © EloquentJS Contributors

Morty Proxy This is a proxified and sanitized view of the page, visit original site.