@@ -241,7 +241,7 @@ it('applies relation to records created before the relation is defined', async (
241241 } )
242242} )
243243
244- it ( 'supports creating unique one-to-one relations' , async ( ) => {
244+ it ( 'supports creating unique one-way one- to-one relations' , async ( ) => {
245245 const userSchema = z . object ( { id : z . number ( ) } )
246246 const postSchema = z . object ( {
247247 title : z . string ( ) ,
@@ -290,7 +290,7 @@ it('supports creating unique one-to-one relations', async () => {
290290 } )
291291} )
292292
293- it ( 'supports updating unique one-to-one relations' , async ( ) => {
293+ it ( 'supports updating unique one-way one- to-one relations' , async ( ) => {
294294 const userSchema = z . object ( { id : z . number ( ) } )
295295 const postSchema = z . object ( {
296296 title : z . string ( ) ,
@@ -328,7 +328,7 @@ it('supports updating unique one-to-one relations', async () => {
328328 } )
329329} )
330330
331- it ( 'errors when creating a unique relation with a foreign record that has already been associated ' , async ( ) => {
331+ it ( 'errors when creating a unique one-way relation referencing a taken foreign record' , async ( ) => {
332332 const userSchema = z . object ( { id : z . number ( ) } )
333333 const postSchema = z . object ( {
334334 title : z . string ( ) ,
@@ -360,7 +360,7 @@ it('errors when creating a unique relation with a foreign record that has alread
360360 )
361361} )
362362
363- it ( 'errors when updating a unique relation with a foreign record that has already been associated ' , async ( ) => {
363+ it ( 'errors when updating a unique one-way relation referencing a taken foreign record' , async ( ) => {
364364 const userSchema = z . object ( { id : z . number ( ) } )
365365 const postSchema = z . object ( {
366366 title : z . string ( ) ,
@@ -398,3 +398,168 @@ it('errors when updating a unique relation with a foreign record that has alread
398398 ) ,
399399 )
400400} )
401+
402+ it ( 'supports creating unique two-way one-to-one relations' , async ( ) => {
403+ const userSchema = z . object ( {
404+ id : z . number ( ) ,
405+ get favoritePost ( ) {
406+ return postSchema
407+ } ,
408+ } )
409+ const postSchema = z . object ( {
410+ title : z . string ( ) ,
411+ get author ( ) {
412+ return userSchema . optional ( )
413+ } ,
414+ } )
415+
416+ const users = new Collection ( { schema : userSchema } )
417+ const posts = new Collection ( { schema : postSchema } )
418+
419+ users . defineRelations ( ( { one } ) => ( {
420+ favoritePost : one ( posts , { unique : true } ) ,
421+ } ) )
422+ posts . defineRelations ( ( { one } ) => ( {
423+ author : one ( users , { unique : true } ) ,
424+ } ) )
425+
426+ const user = await users . create ( {
427+ id : 1 ,
428+ favoritePost : await posts . create ( { title : 'First' } ) ,
429+ } )
430+ expect ( user . favoritePost ) . toEqual ( { title : 'First' , author : user } )
431+ expect ( posts . findFirst ( ( q ) => q . where ( { author : { id : 1 } } ) ) ) . toEqual ( {
432+ title : 'First' ,
433+ author : user ,
434+ } )
435+ } )
436+
437+ it ( 'errors when creating a unique two-way relation referencing a taken foreign record' , async ( ) => {
438+ const userSchema = z . object ( {
439+ id : z . number ( ) ,
440+ get favoritePost ( ) {
441+ return postSchema . optional ( )
442+ } ,
443+ } )
444+ const postSchema = z . object ( {
445+ title : z . string ( ) ,
446+ get author ( ) {
447+ return userSchema . optional ( )
448+ } ,
449+ } )
450+
451+ const users = new Collection ( { schema : userSchema } )
452+ const posts = new Collection ( { schema : postSchema } )
453+
454+ users . defineRelations ( ( { one } ) => ( {
455+ favoritePost : one ( posts , { unique : true } ) ,
456+ } ) )
457+ posts . defineRelations ( ( { one } ) => ( {
458+ author : one ( users , { unique : true } ) ,
459+ } ) )
460+
461+ const user = await users . create ( {
462+ id : 1 ,
463+ favoritePost : await posts . create ( { title : 'First' } ) ,
464+ } )
465+
466+ await expect (
467+ users . create ( { id : 2 , favoritePost : user . favoritePost } ) ,
468+ ) . rejects . toThrow (
469+ new RelationError (
470+ `Failed to create a unique relation at "favoritePost": the foreign record is already associated with another owner` ,
471+ RelationErrorCodes . FORBIDDEN_UNIQUE_CREATE ,
472+ {
473+ path : [ 'favoritePost' ] ,
474+ ownerCollection : users ,
475+ foreignCollections : [ posts ] ,
476+ options : { unique : true } ,
477+ } ,
478+ ) ,
479+ )
480+
481+ await expect ( posts . create ( { title : 'Second' , author : user } ) ) . rejects . toThrow (
482+ new RelationError (
483+ `Failed to create a unique relation at "author": the foreign record is already associated with another owner` ,
484+ RelationErrorCodes . FORBIDDEN_UNIQUE_CREATE ,
485+ {
486+ path : [ 'author' ] ,
487+ ownerCollection : posts ,
488+ foreignCollections : [ users ] ,
489+ options : { unique : true } ,
490+ } ,
491+ ) ,
492+ )
493+ } )
494+
495+ it ( 'errors when updating a unique two-way relation referencing a taken foreign record' , async ( ) => {
496+ const userSchema = z . object ( {
497+ id : z . number ( ) ,
498+ get favoritePost ( ) {
499+ return postSchema
500+ } ,
501+ } )
502+ const postSchema = z . object ( {
503+ title : z . string ( ) ,
504+ get author ( ) {
505+ return userSchema . optional ( )
506+ } ,
507+ } )
508+
509+ const users = new Collection ( { schema : userSchema } )
510+ const posts = new Collection ( { schema : postSchema } )
511+
512+ users . defineRelations ( ( { one } ) => ( {
513+ favoritePost : one ( posts , { unique : true } ) ,
514+ } ) )
515+ posts . defineRelations ( ( { one } ) => ( {
516+ author : one ( users , { unique : true } ) ,
517+ } ) )
518+
519+ const firstUser = await users . create ( {
520+ id : 1 ,
521+ favoritePost : await posts . create ( { title : 'First' } ) ,
522+ } )
523+ const secondUser = await users . create ( {
524+ id : 2 ,
525+ favoritePost : await posts . create ( { title : 'Second' } ) ,
526+ } )
527+
528+ await expect (
529+ users . update ( secondUser , {
530+ data ( user ) {
531+ user . favoritePost = firstUser . favoritePost
532+ } ,
533+ } ) ,
534+ ) . rejects . toThrow (
535+ new RelationError (
536+ `Failed to update a unique relation at "favoritePost": the foreign record is already associated with another owner` ,
537+ RelationErrorCodes . FORBIDDEN_UNIQUE_UPDATE ,
538+ {
539+ path : [ 'favoritePost' ] ,
540+ ownerCollection : users ,
541+ foreignCollections : [ posts ] ,
542+ options : { unique : true } ,
543+ } ,
544+ ) ,
545+ )
546+
547+ await expect (
548+ posts . update ( ( q ) => q . where ( { author : { id : 2 } } ) , {
549+ data ( post ) {
550+ post . author = firstUser
551+ } ,
552+ } ) ,
553+ ) . rejects . toThrow (
554+ new RelationError (
555+ `Failed to update a unique relation at "author": the foreign record is already associated with another owner` ,
556+ RelationErrorCodes . FORBIDDEN_UNIQUE_UPDATE ,
557+ {
558+ path : [ 'author' ] ,
559+ ownerCollection : posts ,
560+ foreignCollections : [ users ] ,
561+ options : { unique : true } ,
562+ } ,
563+ ) ,
564+ )
565+ } )
0 commit comments