laravel-raom-nuxt
v0.3.1
Published
Nuxt module providing a typed object-mapper for Laravel REST API backends. Offers model classes with decorator-based field/key/relation metadata (@Resource, @Field, @Key), identity map, query builder, and relation builders (HasMany, BelongsTo, BelongsToMa
Readme
Laravel REST API Object Mapper 🚀
TypeScript/Nuxt module providing an ORM-like developer experience for APIs exposed by lomkit/laravel-rest-api.
Authored by edepauw.
Why an ORM-like Architecture for REST APIs?
Traditional ORMs abstract SQL databases. This module applies the same idea to REST resources: models communicate with an HTTP API instead of a DB.
The transport changes (SQL → HTTP), but the developer model stays familiar:
- decorator-based domain models
- typed relation builders
- expressive query builder
- identity map for in-memory consistency
Business logic stays in models; network details remain an infrastructure concern.
Packaging Direction 📦
Today this project is a Nuxt module.
Long-term target:
- a framework-agnostic core package (SDK)
- a thin Nuxt integration on top
Vision ✨
- 🧩 Decorator-based model system (
@Resource,@Field,@Key) - 🗺️ Identity Map — one primary key = one in-memory instance
- 🔎 Expressive typed Query Builder
- 🧪 Fake query mode (
User.fake().findByKey(1)) for dev/tests without a backend - 🔄 Proxy-based dirty tracking with deferred relation mutations (
attach,detach,sync,toggle,create) - 🧬 Morph relation support (planned)
Current Status ⚠️
The core architecture is implemented and covered by an automated test suite (88 tests passing). The module is still under active development and not yet considered production-ready.
- ✅ Decorator metadata (
@Resource,@Field,@Key) - ✅ Identity Map + hydration
- ✅ Proxy-based dirty tracking (
_fields/_changes) - ✅
save()with deferred commit on mutation success - ✅ Relation builders:
HasMany,BelongsTo,HasOne,BelongsToMany - ✅ Relation operations:
attach,detach,sync,toggle,create - ✅ Nested/recursive relation mutation payloads
- ✅ Query Builder (filters, sorts, includes, pagination)
- 🚧 Fake engine (planned)
- 🚧 Morph relations (planned)
- 🚧 Lifecycle hooks (planned)
Usage Example 🛠️
Relations are declared as typed property initializers. No @Relation decorator is needed — relation builders self-register their metadata at bootstrap time.
import {
Model,
Resource,
Field,
Key,
HasMany,
BelongsTo,
} from 'laravel-rest-api-object-mapper/runtime'
@Resource('users', { limits: [1, 10, 25, 50] })
class User extends Model {
@Key()
@Field()
id!: number
@Field()
firstname!: string
@Field()
lastname!: string
posts = HasMany(() => Post, 'posts')
}
@Resource('posts')
class Post extends Model {
@Key()
@Field()
id!: number
@Field()
title!: string
author = BelongsTo(() => User, 'author')
}// Query
const user = await User.query()
.where('firstname', 'like', 'Eli%')
.include('posts', (q) => q.orderBy('id', 'desc'))
.findByKey(1)
// Field mutation — tracked in _changes, committed only on save success
user.firstname = 'Test'
await user.save()
// Relation mutations — deferred until save()
user.posts.attach(post)
user.posts.detach(3)
user.posts.sync(10, { withoutDetaching: true })
await user.save()Identity Map 🧠
Without an identity map, multiple API calls can produce multiple JS instances for the same resource.
With the identity map:
- ✅ One primary key maps to one instance in memory
- ✅ Mutations are visible everywhere in the app
- ✅ Hydration reuses existing instances
Fake Mode (Planned) 🎭
Identical read/write API, no network calls.
await User.query().findByKey(1) // real
await User.fake().findByKey(1) // fake — same API, in-memoryBenefits: frontend dev without a live backend, fast deterministic tests, factory-based scenarios.
Product Roadmap 🗺️
Phase 1 - Solid Core ✅
- Decorator metadata behavior
- Hydration + Identity Map sync
- HTTP client layer
Phase 2 - ORM Mutations ✅
save()with dirty tracking- Create / update / delete lifecycle
- Relation mutation operations (
attach,detach,sync,toggle,create)
Phase 3 - Relation System 🚧
- Morph relation support (
morphTo,morphMany,morphOne) - Relation hydration + mutation parity across all relation kinds
Phase 4 - Fake Engine 🚧
fake()andFakeQueryBuilder- In-memory factories / seeders
- API parity guarantee between real and fake modes
Phase 5 - DX & Quality
- Strong autocomplete for fields and relations
- Debug tooling (payload trace, hooks, optional devtools integration)
- Integration tests with
lomkit/laravel-rest-api
Phase 6 - Production Readiness
- Query caching + smart invalidation
- Optimistic UI + rollback strategies
- Pagination completeness + revalidation
Additional Feature Ideas 💡
- Offline-first mutation queue + replay
- Lifecycle events (
beforeSave,afterHydrate,afterDelete) - Local policy/gate pre-check helpers for UX
- Typed Laravel error normalization
- Model code generation from API schema
Installation 📦
npx nuxt module add laravel-rest-api-object-mapperLocal Development 👩💻
# Install dependencies
npm install
# Prepare module stubs
npm run dev:prepare
# Playground
npm run dev
npm run dev:build
# Quality checks
npm run lint
npm run test
npm run test:watchContributing 🤝
Contributions are welcome, especially around:
- fake engine + factories
- morph relation support
- lifecycle hooks
- integration tests with
lomkit/laravel-rest-api
