Description
👀 Highlights
2.0.0 is finally here! 🎉 This release modernizes the whole stack: standard ECMAScript decorators, pinia 3 & 4, Nuxt 4, Node 22 — plus a bunch of long requested query features. If you are upgrading from 1.x, read the migration guide.
⚡ Standard ECMAScript decorators
The decorators are now standard TC39 decorators — no more experimentalDecorators flag, TypeScript >= 5.2 required. Fields are declared with ! instead of declare:
class User extends Model {
static entity = 'users'
- @Uid() declare id: string
- @Str('') declare name: string
+ @Uid() id!: string
+ @Str('') name!: string
}A codemod migrates your models automatically. Bonus: decorated fields are now registered through decorator metadata, which is inherited along the class hierarchy — derived STI models finally see the decorated fields of their base classes.
🧰 New query & repository features
// Laravel style upserts
useRepo(User).updateOrCreate({ name: 'Jane Doe' }, { age: 41 })
const user = useRepo(User).firstOrCreate({ name: 'Jane Doe' }, { age: 40 })
// SQL LIKE filtering
useRepo(Project).whereLike('name', `%${query}%`).get()
// locale aware sorting
useRepo(Item).orderBy('name', 'asc', new Intl.Collator('lt')).get()fresh() now fires the saving/creating and saved/created lifecycle hooks (opt out with { raw: true }), single table inheritance resolves nested discriminators (Document -> File -> Video), and the axios plugin got persistBy: 'fresh' to make the API response the single source of truth.
🏗️ Modern stack
- pinia 3 & 4 supported (peer
>= 3), vue properly declared as peer dependency - Nuxt 4 support in
@pinia-orm/nuxtincl. automatic dependency optimization (no more "new dependencies optimized" dev server reloads) - Node >= 22.12 required — in sync with Nuxt 4 and current Vite
- Correctly measured bundle size: 11.75 kB min+brotli (the previously reported 16 kB accidentally included vue's reactivity system)
🐛 Long standing bugs fixed
- Mutators, casts and hidden fields are scoped per entity — no more leaking between models with same-named fields
- Global axios plugin config (
baseURL,dataKey) applies from the first repository use - Casts run before field type validation on save — no more bogus
is not a numberwarnings - Eager load callbacks compile for optional relations (
posts?: Post[]) - The query cache falls back to strong refs where
WeakRefis unavailable (Cloudflare Workers)
📚 Docs
New migration guide, a cookbook with Vue Query & axios recipes, and a version switcher to jump between the 1.x and 2.x documentation.
👉 Changelog
🚀 Enhancements
- pinia-orm: Add updateOrCreate & firstOrCreate repository methods (#2032)
- pinia-orm: Support Intl.Collator for locale aware sorting (#2033)
- pinia-orm: Add whereLike & orWhereLike query methods (#2034)
- axios: Support persistBy fresh to replace store data (#2035)
- pinia-orm: Fire lifecycle hooks in fresh() (#2036)
- pinia-orm: Hydrate recursively discriminated models (#2037)
- pinia-orm: ⚠️ Migrate to standard ECMAScript decorators (#2045)
- pinia-orm: ⚠️ Require node >= 22 and support pinia 4 (#2046)
- nuxt: Support Nuxt 4 and pre-bundle pinia-orm in dev (#2047)
🩹 Fixes
- pinia-orm:
hasManyThroughdoesn't work correctly with mulitple model instances (16950b0) - pinia-orm: Querying same Model without and with relations gives back always relations (#2023)
- pinia-orm: Scope decorator mutators, casts & hidden fields per entity (#2027)
- axios: Apply global plugin config on first repository use (#2028)
- pinia-orm: Apply casts before field type validation on save (#2029)
- pinia-orm: Accept eager load callback for optional relations (#2030)
- pinia-orm: Fall back to strong refs when WeakRef is unavailable (#2031)
- docs: Make the docs build run on node >= 19 (#2048)
- pinia-orm: Declare vue as peer dependency (#2052)
- deps: Repair lint after security overrides (#2058)
📖 Documentation
- axios: Fix broken links to configuration page (#2025)
- axios: Add Nuxt setup guide for the axios plugin (#2038)
- Add version switcher to the docs header (#2044)
- Add cookbook section with vue-query and axios recipes (#999)
- Refresh readme & add sponsors update workflow (#2049)
- Explain purpose and use case of load() (#2054)
🏡 Chore
🤖 CI
- Fix release pr lookup in the changelog workflow (#2039)
- Authenticate release pr lookup to avoid rate limits (#2041)
- Exclude sponsorkit cache from sponsor updates (#2050)
⚠️ Breaking Changes
- pinia-orm: ⚠️ Migrate to standard ECMAScript decorators (#2045)
- pinia-orm: ⚠️ Require node >= 22 and support pinia 4 (#2046)
❤️ Contributors
- Gregor Becker (@CodeDredd)
- Adam Kliment (@netmilk)