From f05e9322f56e7191ccea0140aa0edc8b4239da35 Mon Sep 17 00:00:00 2001 From: Gregor Becker Date: Sun, 19 Jul 2026 23:23:41 +0200 Subject: [PATCH] fix(pinia-orm): apply casts before field type validation on save Casts for the 'set' operation ran after $fillField, so the type check warned about the raw input value (e.g. 'Field notes:organization_id - 10191 is not a number') even though the cast converts it right after. The cast now runs before the field is filled, so validation sees the casted value. Values filled from the attribute default still pass through the cast afterwards, as before. fixes #2003 --- packages/pinia-orm/src/model/Model.ts | 9 +++++- .../unit/model/Model_Casts_Number.spec.ts | 30 +++++++++++++++++++ 2 files changed, 38 insertions(+), 1 deletion(-) diff --git a/packages/pinia-orm/src/model/Model.ts b/packages/pinia-orm/src/model/Model.ts index d7a45b67b..b7f8901ff 100644 --- a/packages/pinia-orm/src/model/Model.ts +++ b/packages/pinia-orm/src/model/Model.ts @@ -826,11 +826,18 @@ export class Model { if (cast && operation === 'get') { value = cast.get(value) } + // Apply the cast before the field is filled so the type check + // validates the casted value instead of the raw input. + if (cast && operation === 'set' && value !== undefined) { + value = options.action === 'update' ? cast.get(value) : cast.set(value) + } + let keyValue = this.$fillField(key, attr, value) if (mutator && typeof mutator !== 'function' && operation === 'set' && mutator.set) { keyValue = mutator.set(keyValue) } - if (cast && operation === 'set') { + // Values filled by the attribute default still need to pass the cast. + if (cast && operation === 'set' && value === undefined) { keyValue = options.action === 'update' ? cast.get(keyValue) : cast.set(keyValue) } diff --git a/packages/pinia-orm/tests/unit/model/Model_Casts_Number.spec.ts b/packages/pinia-orm/tests/unit/model/Model_Casts_Number.spec.ts index bb28bb388..50863739d 100644 --- a/packages/pinia-orm/tests/unit/model/Model_Casts_Number.spec.ts +++ b/packages/pinia-orm/tests/unit/model/Model_Casts_Number.spec.ts @@ -92,4 +92,34 @@ describe('unit/model/Model_Casts_Number', () => { expect(userRepo.find(1)?.count).toBe(444) }) + + it('should not warn about a wrong type when the cast converts the value on save', () => { + const warningSpy = vi.spyOn(console, 'warn') + warningSpy.mockClear() + + class User extends Model { + static entity = 'users' + + @Attr(0) id!: number + + @Cast(() => NumberCast) + @Num(null) + count!: number | null + } + + const userRepo = useRepo(User) + userRepo.save({ + id: 1, + count: '10191', + }) + + assertState({ + users: { + 1: { id: 1, count: 10191 }, + }, + }) + + expect(userRepo.find(1)?.count).toBe(10191) + expect(warningSpy).not.toHaveBeenCalled() + }) })