@@ -4,7 +4,7 @@ import { DMMF } from '@prisma/generator-helper';
44
55import { Delegate } from './delegate' ;
66import { Data , Delegates , generateDelegates } from './prismock' ;
7- import { FindWhereArgs } from './types ' ;
7+ import { RelationshipStore } from './relationship-store ' ;
88
99type GetData = ( ) => Data ;
1010type SetData = ( data : Data ) => void ;
@@ -120,209 +120,3 @@ export function createPrismock(instance: PrismaModule) {
120120}
121121
122122export const PrismockClient = createPrismock ( Prisma ) ;
123-
124- type RelationshipEntry = { a : number ; b : number } ;
125-
126- type Relationship = {
127- name : string ;
128- a : { name : string ; type : string } ;
129- b : { name : string ; type : string } ;
130- values : RelationshipEntry [ ] ;
131- } ;
132-
133- type RelationActionParams = {
134- relationshipName : string ;
135- fieldName : string ;
136- id : number ;
137- values : { id : number } | { id : number } [ ] ;
138- } ;
139-
140- type MatchParams = {
141- type : string ;
142- name : string ;
143- itemId : number ;
144- where : FindWhereArgs ;
145- } ;
146-
147- class RelationshipStore {
148- private relationships : Record < string , Relationship > ;
149- constructor ( models : DMMF . Model [ ] ) {
150- this . relationships = { } ;
151- this . populateRelationships ( models ) ;
152- }
153-
154- getRelationships ( ) {
155- return this . relationships ;
156- }
157-
158- findRelationship ( name : string ) {
159- return this . relationships [ name ] ;
160- }
161-
162- findRelationshipBy ( type : string , name : string ) {
163- return Object . values ( this . relationships ) . find (
164- ( { a, b } ) => ( a . type === type && b . name === name ) || ( b . type === type && a . name === name ) ,
165- ) ;
166- }
167-
168- match ( { type, name, itemId, where } : MatchParams ) {
169- const relationship = this . findRelationshipBy ( type , name ) ;
170- if ( ! relationship ) {
171- return 0 ;
172- }
173- if ( where . none && ! relationship . values . length ) {
174- return 1 ;
175- }
176-
177- const [ valueField , targetField ] = this . getRelationshipFieldNames ( relationship , type ) ;
178- const found = relationship . values . find ( ( x ) => {
179- if ( where . some ) {
180- return x [ valueField ] === itemId && x [ targetField ] === ( where . some as { id : number } ) . id ;
181- }
182- if ( where . none ) {
183- return x [ valueField ] !== itemId || x [ targetField ] !== ( where . none as { id : number } ) . id ;
184- }
185- return false ;
186- } ) ;
187- if ( ! found ) {
188- return - 1 ;
189- }
190- return 1 ;
191- }
192-
193- getRelationshipIds ( name : string , type : string , id : FindWhereArgs | number ) {
194- const relationship = this . findRelationship ( name ) ;
195- if ( ! relationship ) {
196- return false ;
197- }
198- if ( this . isSymmetrical ( relationship ) ) {
199- return this . extractSymmetricalValues ( relationship , id ) ;
200- }
201- const [ valueField ] = this . getRelationshipFieldNames ( relationship , type ) ;
202- return relationship . values . map ( ( x ) => x [ valueField ] ) ;
203- }
204-
205- connectToRelationship ( { relationshipName, fieldName, id, values } : RelationActionParams ) {
206- const relationship = this . findRelationship ( relationshipName ) ;
207- if ( ! relationship ) {
208- return ;
209- }
210- if ( ! Array . isArray ( values ) ) {
211- const value = this . getActionValue ( { relationship, fieldName, id, value : values } ) ;
212- relationship . values = relationship . values . find ( ( x ) => this . matchEntry ( x , value ) )
213- ? relationship . values
214- : [ ...relationship . values , value ] ;
215- return ;
216- }
217- relationship . values = [
218- ...relationship . values ,
219- ...values
220- . map ( ( x ) => this . getActionValue ( { relationship, fieldName, id, value : x } ) )
221- . map ( ( x ) => ( relationship . values . find ( ( y ) => this . matchEntry ( x , y ) ) ? null : x ) )
222- . filter ( ( x ) => ! ! x ) ,
223- ] ;
224- }
225-
226- disconnectFromRelation ( { relationshipName, fieldName, id, values } : RelationActionParams ) {
227- const relationship = this . findRelationship ( relationshipName ) ;
228- if ( ! relationship ) {
229- return ;
230- }
231- if ( ! Array . isArray ( values ) ) {
232- const value = this . getActionValue ( { relationship, fieldName, id, value : values } ) ;
233- relationship . values = relationship . values . filter ( ( x ) => this . matchEntry ( x , value ) ) ;
234- return ;
235- }
236- relationship . values = relationship . values . filter (
237- ( x ) =>
238- ! values
239- . map ( ( x ) => this . getActionValue ( { relationship, fieldName, id, value : x } ) )
240- . find ( ( y ) => this . matchEntry ( x , y ) ) ,
241- ) ;
242- }
243-
244- resetValues ( ) {
245- Object . values ( this . relationships ) . forEach ( ( x ) => ( x . values = [ ] ) ) ;
246- }
247-
248- private getRelationshipFieldNames ( { a } : Relationship , type : string ) : [ 'a' , 'b' ] | [ 'b' , 'a' ] {
249- return a . type === type ? [ 'a' , 'b' ] : [ 'b' , 'a' ] ;
250- }
251-
252- private matchEntry ( x : RelationshipEntry , y : RelationshipEntry ) {
253- return x . a === y . a && x . b === y . b ;
254- }
255-
256- private isSymmetrical ( { a, b } : Relationship ) {
257- return a . type === b . type ;
258- }
259-
260- private extractSymmetricalValues ( { values } : Relationship , id : FindWhereArgs | number ) {
261- if ( typeof id === 'number' ) {
262- return values . filter ( ( { a, b } ) => a === id || b === id ) . map ( ( { a, b } ) => ( a === id ? b : a ) ) ;
263- }
264- return ( id . in as number [ ] ) . some ( ( id ) =>
265- values . filter ( ( { a, b } ) => a === id || b === id ) . map ( ( { a, b } ) => ( a === id ? b : a ) ) ,
266- ) ;
267- }
268-
269- private getActionValue ( {
270- relationship,
271- fieldName,
272- id,
273- value,
274- } : {
275- relationship : Relationship ;
276- fieldName : string ;
277- id : number ;
278- value : { id : number } ;
279- } ) {
280- if ( relationship . a . name === fieldName ) {
281- return { a : value . id , b : id } ;
282- }
283- return { a : id , b : value . id } ;
284- }
285-
286- private populateRelationships ( models : DMMF . Model [ ] ) {
287- this . relationships = Object . entries (
288- this . groupBy (
289- models . flatMap ( ( x ) => x . fields ) ,
290- ( x ) => x . relationName as string ,
291- ) ,
292- )
293- . filter (
294- ( [ key , fields ] ) =>
295- key !== 'undefined' &&
296- fields . every ( ( { relationFromFields : from , relationToFields : to } ) => ! from ?. length && ! to ?. length ) ,
297- )
298- . map ( ( [ _ , fields ] ) => fields . sort ( ( a , b ) => ( ( a ?. name as string ) > ( b ?. name as string ) ? 1 : - 1 ) ) )
299- . reduce (
300- ( memo , [ a , b ] ) => ( {
301- ...memo ,
302- [ a ?. relationName as string ] : {
303- name : a ?. relationName as string ,
304- values : [ ] ,
305- a : {
306- name : a ?. name as string ,
307- type : a ?. type as string ,
308- } ,
309- b : {
310- name : b ?. name as string ,
311- type : b ?. type as string ,
312- } ,
313- } ,
314- } ) ,
315- { } ,
316- ) ;
317- }
318-
319- private groupBy < T > ( array : T [ ] , aggregator : ( item : T ) => string ) : Record < string , T [ ] > {
320- return array . reduce ( ( memo , item ) => {
321- const key = aggregator ( item ) ;
322- return {
323- ...memo ,
324- [ key ] : memo [ key ] ? [ ...memo [ key ] , item ] : [ item ] ,
325- } ;
326- } , { } as Record < string , T [ ] > ) ;
327- }
328- }
0 commit comments