1- import { EntityManager , EntityMetadata , FindOptionsOrder , FindOptionsRelations , FindOptionsWhere } from 'typeorm'
1+ import {
2+ EntityManager ,
3+ EntityMetadata ,
4+ EntityNotFoundError ,
5+ FindOptionsOrder ,
6+ FindOptionsRelations ,
7+ FindOptionsWhere ,
8+ } from 'typeorm'
29import { EntityTarget } from 'typeorm/common/EntityTarget'
310import { ChangeWriter } from './utils/changeWriter'
411import { StateManager } from './utils/stateManager'
@@ -96,16 +103,10 @@ export class Store {
96103 this . cacheMode = cacheMode
97104 }
98105
99- /**
100- * @internal
101- */
102106 get _em ( ) {
103107 return this . em
104108 }
105109
106- /**
107- * @internal
108- */
109110 get _state ( ) {
110111 return this . state
111112 }
@@ -237,7 +238,7 @@ export class Store {
237238 private async _delete ( metadata : EntityMetadata , ids : string [ ] ) {
238239 this . logger ?. debug ( `delete ${ metadata . name } ${ ids . length } entities` )
239240 await this . changes ?. writeDelete ( metadata , ids )
240- await this . em . delete ( metadata . target , ids ) // TODO : should be split by chunks too?
241+ await this . em . delete ( metadata . target , ids ) // NOTE : should be split by chunks too?
241242 }
242243
243244 async count < E extends EntityLiteral > ( target : EntityTarget < E > , options ?: FindManyOptions < E > ) : Promise < number > {
@@ -250,16 +251,19 @@ export class Store {
250251 target : EntityTarget < E > ,
251252 where : FindOptionsWhere < E > | FindOptionsWhere < E > [ ]
252253 ) : Promise < number > {
253- return await this . performRead ( async ( ) => {
254- return await this . em . countBy ( target , where )
255- } )
254+ return await this . count ( target , { where} )
256255 }
257256
258257 async find < E extends EntityLiteral > ( target : EntityTarget < E > , options : FindManyOptions < E > ) : Promise < E [ ] > {
259258 return await this . performRead ( async ( ) => {
260259 const { cache, ...opts } = options
261260 const res = await this . em . find ( target , opts )
262- if ( cache ?? this . cacheMode === 'ALL' ) this . persistEntities ( target , res , options ?. relations )
261+ if ( cache ?? this . cacheMode === 'ALL' ) {
262+ const metadata = this . getEntityMetadata ( target )
263+ for ( const e of res ) {
264+ this . cacheEntity ( metadata , e )
265+ }
266+ }
263267 return res
264268 } )
265269 }
@@ -269,11 +273,7 @@ export class Store {
269273 where : FindOptionsWhere < E > | FindOptionsWhere < E > [ ] ,
270274 cache ?: boolean
271275 ) : Promise < E [ ] > {
272- return await this . performRead ( async ( ) => {
273- const res = await this . em . findBy ( target , where )
274- if ( cache ?? this . cacheMode === 'ALL' ) this . persistEntities ( target , res )
275- return res
276- } )
276+ return await this . find ( target , { where, cache} )
277277 }
278278
279279 async findOne < E extends EntityLiteral > (
@@ -283,8 +283,11 @@ export class Store {
283283 return await this . performRead ( async ( ) => {
284284 const { cache, ...opts } = options
285285 const res = await this . em . findOne ( target , opts ) . then ( noNull )
286- if ( res != null && ( cache ?? this . cacheMode === 'ALL' ) )
287- this . persistEntities ( target , res , options ?. relations )
286+ if ( cache ?? this . cacheMode === 'ALL' ) {
287+ const metadata = this . getEntityMetadata ( target )
288+ const idOrEntity = res || getIdFromWhere ( options . where )
289+ this . cacheEntity ( metadata , idOrEntity )
290+ }
288291 return res
289292 } )
290293 }
@@ -294,34 +297,23 @@ export class Store {
294297 where : FindOptionsWhere < E > | FindOptionsWhere < E > [ ] ,
295298 cache ?: boolean
296299 ) : Promise < E | undefined > {
297- return await this . performRead ( async ( ) => {
298- const res = await this . em . findOneBy ( target , where ) . then ( noNull )
299- if ( res != null && ( cache ?? this . cacheMode === 'ALL' ) ) this . persistEntities ( target , res )
300-
301- return res
302- } )
300+ return await this . findOne ( target , { where, cache} )
303301 }
304302
305303 async findOneOrFail < E extends EntityLiteral > ( target : EntityTarget < E > , options : FindOneOptions < E > ) : Promise < E > {
306- return await this . performRead ( async ( ) => {
307- const { cache, ...opts } = options
308- const res = await this . em . findOneOrFail ( target , opts )
309- if ( cache ?? this . cacheMode === 'ALL' ) this . persistEntities ( target , res , options ?. relations )
310-
311- return res
312- } )
304+ const res = await this . findOne ( target , options )
305+ if ( res == null ) throw new EntityNotFoundError ( target , options . where )
306+ return res
313307 }
314308
315309 async findOneByOrFail < E extends EntityLiteral > (
316310 target : EntityTarget < E > ,
317311 where : FindOptionsWhere < E > | FindOptionsWhere < E > [ ] ,
318312 cache ?: boolean
319313 ) : Promise < E > {
320- return await this . performRead ( async ( ) => {
321- const res = await this . em . findOneByOrFail ( target , where )
322- if ( cache || this . cacheMode === 'ALL' ) this . persistEntities ( target , res )
323- return res
324- } )
314+ const res = await this . findOneBy ( target , where , cache )
315+ if ( res == null ) throw new EntityNotFoundError ( target , where )
316+ return res
325317 }
326318
327319 async get < E extends EntityLiteral > ( target : EntityTarget < E > , id : string ) : Promise < E | undefined >
@@ -331,28 +323,18 @@ export class Store {
331323 idOrOptions : string | GetOptions < E >
332324 ) : Promise < E | undefined > {
333325 const { id, relations} = parseGetOptions ( idOrOptions )
334-
335326 const metadata = this . getEntityMetadata ( target )
336327 let entity = this . state . get < E > ( metadata , id , relations )
337328 if ( entity !== undefined ) return noNull ( entity )
338-
339329 return await this . findOne ( target , { where : { id} as any , relations, cache : true } )
340330 }
341331
342- async getOrFail < E extends EntityLiteral > ( entityClass : EntityTarget < E > , id : string ) : Promise < E >
343- async getOrFail < E extends EntityLiteral > ( entityClass : EntityTarget < E > , options : GetOptions < E > ) : Promise < E >
344- async getOrFail < E extends EntityLiteral > (
345- entityClass : EntityTarget < E > ,
346- idOrOptions : string | GetOptions < E >
347- ) : Promise < E > {
332+ async getOrFail < E extends EntityLiteral > ( target : EntityTarget < E > , id : string ) : Promise < E >
333+ async getOrFail < E extends EntityLiteral > ( target : EntityTarget < E > , options : GetOptions < E > ) : Promise < E >
334+ async getOrFail < E extends EntityLiteral > ( target : EntityTarget < E > , idOrOptions : string | GetOptions < E > ) : Promise < E > {
348335 const options = parseGetOptions ( idOrOptions )
349- let e = await this . get ( entityClass , options )
350-
351- if ( e == null ) {
352- const metadata = this . getEntityMetadata ( entityClass )
353- throw new Error ( `Missing entity ${ metadata . name } with id "${ options . id } "` )
354- }
355-
336+ let e = await this . get ( target , options )
337+ if ( e == null ) throw new EntityNotFoundError ( target , options . id )
356338 return e
357339 }
358340
@@ -365,89 +347,66 @@ export class Store {
365347
366348 this . pendingCommit = createFuture ( )
367349 try {
368- const { upserts, inserts, deletes, extraUpserts} = this . state . computeChangeSets ( )
350+ await this . state . performUpdate ( async ( { upserts, inserts, deletes, extraUpserts} ) => {
351+ for ( const { metadata, entities} of upserts ) {
352+ await this . _upsert ( metadata , entities )
353+ }
369354
370- for ( const { metadata, entities} of upserts ) {
371- await this . _upsert ( metadata , entities )
372- }
355+ for ( const { metadata, entities} of inserts ) {
356+ await this . _insert ( metadata , entities )
357+ }
373358
374- for ( const { metadata, entities } of inserts ) {
375- await this . _insert ( metadata , entities )
376- }
359+ for ( const { metadata, ids } of deletes ) {
360+ await this . _delete ( metadata , ids )
361+ }
377362
378- for ( const { metadata, ids} of deletes ) {
379- await this . _delete ( metadata , ids )
380- }
363+ for ( const { metadata, entities} of extraUpserts ) {
364+ await this . _upsert ( metadata , entities )
365+ }
366+ } )
381367
382- for ( const { metadata , entities } of extraUpserts ) {
383- await this . _upsert ( metadata , entities )
368+ if ( this . resetMode === 'FLUSH' || reset ) {
369+ this . reset ( )
384370 }
385-
386- this . state . clear ( )
387371 } finally {
388372 this . pendingCommit . resolve ( )
389373 this . pendingCommit = undefined
390374 }
391-
392- if ( this . resetMode === 'FLUSH' || reset ) {
393- this . reset ( )
394- }
395- }
396-
397- /**
398- * @internal
399- */
400- _close ( ) {
401- this . isClosed = true
402375 }
403376
404377 private async performRead < T > ( cb : ( ) => Promise < T > ) : Promise < T > {
405- this . assetNotClosed ( )
406-
378+ this . assertNotClosed ( )
407379 if ( this . flushMode === 'AUTO' || this . flushMode === 'ALWAYS' ) {
408380 await this . flush ( )
409381 }
410-
411382 return await cb ( )
412383 }
413384
414385 private async performWrite ( cb : ( ) => Promise < void > ) : Promise < void > {
386+ this . assertNotClosed ( )
415387 await this . pendingCommit ?. promise ( )
416-
417- this . assetNotClosed ( )
418-
419388 await cb ( )
420-
421389 if ( this . flushMode === 'ALWAYS' ) {
422390 await this . flush ( )
423391 }
424392 }
425393
426- private assetNotClosed ( ) {
394+ private assertNotClosed ( ) {
427395 assert ( ! this . isClosed , `too late to perform db updates, make sure you haven't forgot to await on db query` )
428396 }
429397
430- private persistEntities < E extends EntityLiteral > (
431- target : EntityTarget < E > ,
432- e : E | E [ ] ,
433- relationMask ?: FindOptionsRelations < any >
434- ) {
435- const metadata = this . getEntityMetadata ( target )
436-
437- e = Array . isArray ( e ) ? e : [ e ]
438- for ( const entity of e ) {
439- traverseEntity ( {
440- metadata,
441- entity,
442- relationMask : relationMask || null ,
443- cb : ( e , md ) => this . state ?. persist ( md , e ) ,
444- } )
398+ private cacheEntity < E extends EntityLiteral > ( metadata : EntityMetadata , entityOrId ?: E | string ) {
399+ if ( entityOrId == null ) {
400+ return
401+ } else if ( typeof entityOrId === 'string' ) {
402+ this . state . settle ( metadata , entityOrId )
403+ } else {
404+ traverseEntity ( metadata , entityOrId , ( e , md ) => this . state . persist ( md , e ) )
445405 }
446406 }
447407
448408 private getEntityMetadata ( target : EntityTarget < any > ) {
449- const em = this . em
450- return em . connection . getMetadata ( target )
409+ return this . em . connection . getMetadata ( target )
451410 }
452411}
453412
@@ -458,3 +417,7 @@ function parseGetOptions<E>(idOrOptions: string | GetOptions<E>): GetOptions<E>
458417 return idOrOptions
459418 }
460419}
420+
421+ function getIdFromWhere ( where ?: FindOptionsWhere < EntityLiteral > ) {
422+ return typeof where ?. id === 'string' ? where . id : undefined
423+ }
0 commit comments