Skip to content

Commit 4f604fd

Browse files
committed
fix(pinia-orm): Querying same Model without and with relations gives back always relations
1 parent dff982c commit 4f604fd

File tree

5 files changed

+66
-24
lines changed

5 files changed

+66
-24
lines changed

packages/pinia-orm/src/query/Query.ts

Lines changed: 30 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -106,6 +106,8 @@ export class Query<M extends Model = Model> {
106106

107107
protected getNewHydrated = false
108108

109+
protected hydrationKey?: string
110+
109111
/**
110112
* Hydrated models. They are stored to prevent rerendering of child components.
111113
*/
@@ -114,28 +116,29 @@ export class Query<M extends Model = Model> {
114116
/**
115117
* Create a new query instance.
116118
*/
117-
constructor (database: Database, model: M, cache: WeakCache<string, Collection<M> | GroupedCollection<M>> | undefined, hydratedData: Map<string, M>, pinia?: Pinia) {
119+
constructor (database: Database, model: M, cache: WeakCache<string, Collection<M> | GroupedCollection<M>> | undefined, hydratedData: Map<string, M>, pinia?: Pinia, hydrationKey?: string) {
118120
this.database = database
119121
this.model = model
120122
this.pinia = pinia
121123
this.cache = cache
122124
this.hydratedDataCache = hydratedData
123125
this.getNewHydrated = false
126+
this.hydrationKey = hydrationKey
124127
}
125128

126129
/**
127130
* Create a new query instance for the given model.
128131
*/
129132
newQuery (model: string): Query<M> {
130133
this.getNewHydrated = true
131-
return new Query<M>(this.database, this.database.getModel(model), this.cache, this.hydratedDataCache, this.pinia)
134+
return new Query<M>(this.database, this.database.getModel(model), this.cache, this.hydratedDataCache, this.pinia, this.hydrationKey)
132135
}
133136

134137
/**
135138
* Create a new query instance with constraints for the given model.
136139
*/
137140
newQueryWithConstraints (model: string): Query<M> {
138-
const newQuery = new Query<M>(this.database, this.database.getModel(model), this.cache, this.hydratedDataCache, this.pinia)
141+
const newQuery = new Query<M>(this.database, this.database.getModel(model), this.cache, this.hydratedDataCache, this.pinia, this.hydrationKey)
139142

140143
// Copy query constraints
141144
newQuery.eagerLoad = { ...this.eagerLoad }
@@ -153,7 +156,7 @@ export class Query<M extends Model = Model> {
153156
* Create a new query instance from the given relation.
154157
*/
155158
newQueryForRelation (relation: Relation): Query<M> {
156-
return new Query<M>(this.database, relation.getRelated() as M, this.cache, new Map<string, M>(), this.pinia)
159+
return new Query<M>(this.database, relation.getRelated() as M, this.cache, new Map<string, M>(), this.pinia, this.hydrationKey)
157160
}
158161

159162
/**
@@ -482,20 +485,12 @@ export class Query<M extends Model = Model> {
482485
*/
483486
get<T extends 'group' | 'collection' = 'collection'>(triggerHook?: boolean): T extends 'group' ? GroupedCollection<M> : Collection<M>
484487
get (triggerHook = true): Collection<M> | GroupedCollection<M> {
488+
this.hydrationKey = this.hydrationKey ?? this.generateHydrationKey()
485489
if (!this.fromCache || !this.cache) { return this.internalGet(triggerHook) }
486490

487491
const key = this.cacheConfig.key
488492
? this.cacheConfig.key + JSON.stringify(this.cacheConfig.params)
489-
: generateKey(this.model.$entity(), {
490-
where: this.wheres,
491-
groups: this.groups,
492-
orders: this.orders,
493-
eagerLoads: this.eagerLoad,
494-
skip: this.skip,
495-
take: this.take,
496-
hidden: this.hidden,
497-
visible: this.visible,
498-
})
493+
: this.hydrationKey
499494
const result = this.cache.get(key)
500495

501496
if (result) { return result }
@@ -582,6 +577,19 @@ export class Query<M extends Model = Model> {
582577
return models.filter(model => comparator(model))
583578
}
584579

580+
protected generateHydrationKey (): string {
581+
return generateKey(this.model.$entity(), {
582+
where: this.wheres,
583+
groups: this.groups,
584+
orders: this.orders,
585+
eagerLoads: this.eagerLoad,
586+
skip: this.skip,
587+
take: this.take,
588+
hidden: this.hidden,
589+
visible: this.visible,
590+
})
591+
}
592+
585593
/**
586594
* Get comparator for the where clause.
587595
*/
@@ -1019,8 +1027,7 @@ export class Query<M extends Model = Model> {
10191027
const isDeleting = currentModel.$self().deleting(currentModel)
10201028

10211029
if (isDeleting === false) { notDeletableIds.push(currentModel.$getIndexId()) } else {
1022-
this.hydratedDataCache.delete('set' + this.model.$entity() + currentModel.$getIndexId())
1023-
this.hydratedDataCache.delete('get' + this.model.$entity() + currentModel.$getIndexId())
1030+
this.hydratedDataCache.delete(this.model.$entity() + currentModel.$getIndexId())
10241031
afterHooks.push(() => currentModel.$self().deleted(currentModel))
10251032
this.checkAndDeleteRelations(currentModel)
10261033
}
@@ -1066,11 +1073,11 @@ export class Query<M extends Model = Model> {
10661073
*/
10671074
protected getHydratedModel (record: Element, options?: ModelOptions): M {
10681075
const id = this.model.$entity() + this.model.$getKey(record, true)
1069-
const operationId = options?.operation + id
1076+
const operationId = id
10701077
let savedHydratedModel = this.hydratedDataCache.get(operationId)
10711078

1072-
if (options?.action === 'update') {
1073-
this.hydratedDataCache.delete('get' + id)
1079+
if (options?.action === 'update' || this.hydrationKey === undefined) {
1080+
this.hydratedDataCache.delete(id)
10741081
savedHydratedModel = undefined
10751082
}
10761083

@@ -1081,10 +1088,12 @@ export class Query<M extends Model = Model> {
10811088

10821089
const modelByType = this.model.$types()[record[this.model.$typeKey()]]
10831090
const getNewInsance = (newOptions?: ModelOptions) => (modelByType ? modelByType.newRawInstance() as M : this.model)
1084-
.$newInstance(record, { relations: false, ...(options || {}), ...newOptions })
1091+
.$newInstance(record, { ...(options || {}), ...newOptions, relations: false })
10851092
const hydratedModel = getNewInsance()
10861093

1087-
if (isEmpty(this.eagerLoad) && options?.operation !== 'set') { this.hydratedDataCache.set(operationId, hydratedModel) }
1094+
if (isEmpty(this.eagerLoad) && options?.operation !== 'set' && this.hydrationKey !== undefined) {
1095+
this.hydratedDataCache.set(operationId, hydratedModel)
1096+
}
10881097

10891098
return hydratedModel
10901099
}

packages/pinia-orm/tests/feature/hooks/creating.spec.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,7 @@ describe('feature/hooks/creating', () => {
4949
{ id: 2, name: 'John Doe 2', age: 40 },
5050
])
5151

52-
expect(useRepo(User).hydratedDataCache.size).toBe(2)
52+
expect(useRepo(User).hydratedDataCache.size).toBe(0)
5353
expect(creatingMethod).toHaveBeenCalledTimes(2)
5454
expect(updatingMethod).toHaveBeenCalledTimes(0)
5555
expect(savingMethod).toHaveBeenCalledTimes(2)

packages/pinia-orm/tests/feature/relations/constraints/constraints.spec.ts

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -120,4 +120,37 @@ describe('feature/relations/constraints/constraints', () => {
120120
expect(users[1].phone!.type!.id).toBe(2)
121121
expect(users[2].phone!.type).toBe(null)
122122
})
123+
124+
it('loads with and without relations correctly', () => {
125+
const usersRepo = useRepo(User)
126+
const phonesRepo = useRepo(Phone)
127+
const typesRepo = useRepo(Type)
128+
usersRepo.cache()?.clear()
129+
130+
usersRepo.save([
131+
{ id: 1, name: 'John Doe', roles: [{ id: 1, pivot: { level: 1 }, phone: { id: 4, number: '999' } }, { id: 2 }, { id: 4 }] },
132+
{ id: 2, name: 'John Doe', roles: [{ id: 1, pivot: { level: 2 } }] },
133+
{ id: 3, name: 'Johnny Doe' },
134+
])
135+
136+
phonesRepo.save([
137+
{ id: 1, userId: 1, number: '123' },
138+
{ id: 2, userId: 2, number: '345' },
139+
{ id: 3, userId: 3, number: '789' },
140+
])
141+
typesRepo.save([
142+
{ id: 1, phoneId: 1, name: 'iPhone' },
143+
{ id: 2, phoneId: 2, name: 'Android' },
144+
])
145+
146+
const users2 = usersRepo.get()
147+
const users = usersRepo
148+
.with('roles', (query) => {
149+
query.with('phone')
150+
})
151+
.get()
152+
153+
expect(users[0].roles.length).toBe(3)
154+
expect(users2[0].roles).toBe(undefined)
155+
})
123156
})

packages/pinia-orm/tests/unit/model/Model_Meta_Field.spec.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@ describe('unit/model/Model_Meta_Field', () => {
4444
username: 'JD',
4545
})
4646

47-
await new Promise(resolve => setTimeout(resolve, 1500))
47+
await new Promise(resolve => setTimeout(resolve, 2000))
4848

4949
userRepo.save({
5050
id: 1,

packages/pinia-orm/tests/unit/repository/Repository.spec.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -108,7 +108,7 @@ describe('unit/repository/Repository', () => {
108108
expect(userRepo.hydratedDataCache.size).toBe(0)
109109

110110
userRepo.piniaStore().save({ 1: { id: 1, name: 'John' } })
111-
expect(userRepo.hydratedDataCache.size).toBe(1)
111+
expect(userRepo.hydratedDataCache.size).toBe(0)
112112

113113
userRepo.piniaStore().update({ 1: { id: 1, name: 'John 2' } })
114114
expect(userRepo.hydratedDataCache.size).toBe(0)

0 commit comments

Comments
 (0)