Skip to content

feat(pinia-orm)!: migrate to standard ECMAScript decorators#2045

Merged
CodeDredd merged 2 commits into
mainfrom
feat/standard-decorators
Jul 20, 2026
Merged

feat(pinia-orm)!: migrate to standard ECMAScript decorators#2045
CodeDredd merged 2 commits into
mainfrom
feat/standard-decorators

Conversation

@CodeDredd

@CodeDredd CodeDredd commented Jul 20, 2026

Copy link
Copy Markdown
Owner

What (breaking, targeted at 2.0.0)

Migrates all property decorators from the legacy experimentalDecorators implementation to the standard TC39 decorators that TypeScript supports natively since 5.0 (metadata since 5.2). With 2.0.0 being a major release, this is the right moment to require them.

Requirements for users

  • TypeScript >= 5.2, experimentalDecorators removed from tsconfig (legacy calls hit a helpful error message at runtime)
  • esbuild >= 0.21 / current Vite & Nuxt toolchains (they transform standard decorators out of the box)

Breaking changes in model definitions

before after
@Attr('') declare name: string @Attr('') name!: string
subclass override @Attr('dog') declare type: string @Attr('dog') type = 'dog' (initializer, value unused)
@NonEnumerable hidden: string @NonEnumerable accessor hidden: string
fields() models typed with field!: type declare field: type (a real class field would wipe the hydrated value)

The docs Typescript guide is rewritten around these rules; all docs examples (37 pages), tests (38 files) and the nuxt3 playground are migrated.

How it works now

  • New Metadata.ts: decorators write into decorator metadata (Symbol.metadata, polyfilled) — field factories, mutators, casts, hidden fields, onDelete modes. initializeSchema() consumes it.
  • Field decorators return an initializer that keeps the hydrated value, so class fields (ES2022 useDefineForClassFields) no longer wipe what the Model constructor filled.
  • Metadata inherits along the prototype chain (copy-on-write), so decorated fields of base classes are now inherited by derived STI models — that never worked with the legacy entity-keyed registry.
  • Legacy invocation (with experimentalDecorators still on) throws a descriptive error instead of failing silently.

Behavior note

Extended models on the same entity (class ExtendedUser extends User without own entity) must be registered before the base class boots the entity — registration is now per class instead of leaking into a shared entity registry (adjusted in the has-many-through spec).

Verification

  • Full suite green: 427 pinia-orm + 25 axios tests (every test exercises the new decorators — 38 spec files migrated)
  • dts build, lint, size (16.18 kB / 16.5 kB) green
  • tsc --noEmit error count identical to baseline (53, all pre-existing)

Not merged on purpose — please review, this is the biggest 2.0.0 breaking change.

The property decorators now use the TC39 stage 3 decorator semantics
shipped with TypeScript 5. Requires TypeScript >= 5.2 without the
experimentalDecorators flag.

BREAKING CHANGES:
- decorated fields are declared with '!' instead of 'declare'
  (standard decorators cannot be applied to declare fields)
- subclass field overrides need an initializer instead of '!'
- NonEnumerable requires the accessor keyword
- fields() based models keep using 'declare' for type declarations

Decorators now register through decorator metadata (Symbol.metadata),
which is scoped per class and inherited along the prototype chain -
decorated fields of base classes are now visible on derived STI models
without re-declaring them.
@codecov-commenter

codecov-commenter commented Jul 20, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 99.34%. Comparing base (b1fdd17) to head (319a3f3).

Additional details and impacted files
@@            Coverage Diff             @@
##             main    #2045      +/-   ##
==========================================
+ Coverage   99.29%   99.34%   +0.05%     
==========================================
  Files          82       83       +1     
  Lines        3100     3185      +85     
  Branches      559      562       +3     
==========================================
+ Hits         3078     3164      +86     
+ Misses         16       15       -1     
  Partials        6        6              

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

Adds tests for the legacy-invocation error, programmatic setRegistry
and NonEnumerable on subclasses (coverage back above baseline), the
migration guide docs page and a codemod script that converts legacy
decorator model definitions to the standard syntax.
@CodeDredd
CodeDredd merged commit d28a885 into main Jul 20, 2026
12 of 13 checks passed
@CodeDredd
CodeDredd deleted the feat/standard-decorators branch July 20, 2026 16:19
@github-actions github-actions Bot mentioned this pull request Jul 20, 2026
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.

2 participants