@@ -11,6 +11,7 @@ import {
11
11
import { createMetadataDecorator } from '@seedcompany/nest' ;
12
12
import { LazyGetter as Once } from 'lazy-get-decorator' ;
13
13
import { DateTime } from 'luxon' ;
14
+ import { type OmitIndexSignature } from 'type-fest' ;
14
15
import type {
15
16
ResourceDBMap ,
16
17
ResourceLike ,
@@ -29,6 +30,12 @@ import { getParentTypes } from './parent-types';
29
30
import { type MaybeSecured , type SecuredProps } from './secured-property' ;
30
31
import { type AbstractClassType } from './types' ;
31
32
33
+ // Merge with this to declare Relations types for Resources.
34
+ // Be sure to patch at runtime too.
35
+ // Don't reference this type directly, other than to declaration merge.
36
+ // eslint-disable-next-line @typescript-eslint/no-empty-interface
37
+ export interface DeclareResourceRelations { }
38
+
32
39
const GqlClassType = createMetadataDecorator ( {
33
40
key : CLASS_TYPE_METADATA ,
34
41
setter : ( type : ClassTypeVal ) => type ,
@@ -53,6 +60,14 @@ export const resolveByTypename =
53
60
} )
54
61
@DbLabel ( 'BaseNode' )
55
62
export abstract class Resource extends DataObject {
63
+ // eslint-disable-next-line @typescript-eslint/naming-convention
64
+ static readonly Relations =
65
+ ( ) : OmitIndexSignature < DeclareResourceRelations > => {
66
+ // eslint-disable-next-line @typescript-eslint/ban-ts-comment
67
+ // @ts -ignore -- runtime needs to be patched in.
68
+ return { } ;
69
+ } ;
70
+
56
71
readonly __typename ?: string ;
57
72
58
73
@IdField ( )
@@ -80,7 +95,10 @@ export type ResourceShape<T> = AbstractClassType<T> & {
80
95
// Default should probably be considered the props on Resource class.
81
96
BaseNodeProps ?: string [ ] ;
82
97
Relations ?: Thunk <
83
- Record < string , ResourceShape < any > | [ ResourceShape < any > ] | undefined >
98
+ Record <
99
+ string ,
100
+ ResourceShape < any > | readonly [ ResourceShape < any > ] | undefined
101
+ >
84
102
> ;
85
103
/**
86
104
* Define this resource as being a child of another.
@@ -397,7 +415,7 @@ export type SecuredPropsPlusExtraKey<
397
415
/* eslint-disable @typescript-eslint/ban-types -- {} is used to mean non-nullable, it's not an empty interface */
398
416
399
417
export type ExtraPropsFromRelationsKey < T extends ResourceShape < any > > = {
400
- [ R in RelKey < T > ] : RelOf < T > [ R ] extends Array < infer U >
418
+ [ R in RelKey < T > ] : RelOf < T > [ R ] extends ReadonlyArray < infer U >
401
419
? U extends ResourceShape < any >
402
420
? U [ 'Parent' ] extends { }
403
421
? never
@@ -411,7 +429,7 @@ export type ExtraPropsFromRelationsKey<T extends ResourceShape<any>> = {
411
429
} [ RelKey < T > ] ;
412
430
413
431
export type ChildSinglesKey < T extends ResourceShape < any > > = {
414
- [ R in RelKey < T > ] : RelOf < T > [ R ] extends any [ ]
432
+ [ R in RelKey < T > ] : RelOf < T > [ R ] extends readonly any [ ]
415
433
? never
416
434
: RelOf < T > [ R ] extends ResourceShape < any >
417
435
? RelOf < T > [ R ] [ 'Parent' ] extends { }
@@ -421,7 +439,7 @@ export type ChildSinglesKey<T extends ResourceShape<any>> = {
421
439
} [ RelKey < T > ] ;
422
440
423
441
export type ChildListsKey < T extends ResourceShape < any > > = {
424
- [ R in RelKey < T > ] : RelOf < T > [ R ] extends Array < infer U >
442
+ [ R in RelKey < T > ] : RelOf < T > [ R ] extends ReadonlyArray < infer U >
425
443
? U extends ResourceShape < any >
426
444
? U [ 'Parent' ] extends { }
427
445
? R
0 commit comments