@@ -4,7 +4,8 @@ import { LazyGetter as Once } from 'lazy-get-decorator';
4
4
import { DateTime } from 'luxon' ;
5
5
import { keys as keysOf } from 'ts-transformer-keys' ;
6
6
import { inspect } from 'util' ;
7
- import { $ , abstractType , e } from '~/core/edgedb/reexports' ;
7
+ import type { ResourceDBMap , ResourceMap } from '~/core' ;
8
+ import { $ } from '~/core/edgedb/reexports' ;
8
9
import { ScopedRole } from '../components/authorization' ;
9
10
import { CalculatedSymbol } from './calculated.decorator' ;
10
11
import { DataObject } from './data-object' ;
@@ -36,7 +37,6 @@ export const resolveByTypename =
36
37
} )
37
38
@DbLabel ( 'BaseNode' )
38
39
export abstract class Resource extends DataObject {
39
- static readonly DB = abstractType ( e . Resource ) ;
40
40
static readonly Props : string [ ] = keysOf < Resource > ( ) ;
41
41
static readonly SecuredProps : string [ ] = [ ] ;
42
42
@@ -61,7 +61,6 @@ export abstract class Resource extends DataObject {
61
61
type Thunk < T > = T | ( ( ) => T ) ;
62
62
63
63
export type ResourceShape < T > = AbstractClassType < T > & {
64
- DB ?: $ . $expr_PathNode ;
65
64
Props : string [ ] ;
66
65
SecuredProps : string [ ] ;
67
66
// An optional list of props that exist on the BaseNode in the DB.
@@ -84,6 +83,9 @@ export type ResourceRelationsShape = ResourceShape<any>['Relations'];
84
83
* A helper class to query the static info of a resource in a typed way.
85
84
*/
86
85
export class EnhancedResource < T extends ResourceShape < any > > {
86
+ /** @internal */
87
+ static readonly dbTypes = new WeakMap < ResourceShape < any > , $ . $expr_PathNode > ( ) ;
88
+
87
89
private constructor ( readonly type : T ) { }
88
90
private static readonly refs = new WeakMap <
89
91
ResourceShape < any > ,
@@ -128,8 +130,8 @@ export class EnhancedResource<T extends ResourceShape<any>> {
128
130
: undefined ;
129
131
}
130
132
131
- get name ( ) {
132
- return this . type . name ;
133
+ get name ( ) : ResourceName < T > {
134
+ return this . type . name as any ;
133
135
}
134
136
135
137
/**
@@ -239,16 +241,16 @@ export class EnhancedResource<T extends ResourceShape<any>> {
239
241
return new Set ( props ) ;
240
242
}
241
243
242
- get db ( ) : T [ 'DB' ] & { } {
243
- const type = this . type . DB ;
244
+ get db ( ) : DBType < T > {
245
+ const type = EnhancedResource . dbTypes . get ( this . type ) ;
244
246
if ( ! type ) {
245
247
throw new ServerException ( `No DB type defined for ${ this . name } ` ) ;
246
248
}
247
- return type ;
249
+ return type as any ;
248
250
}
249
251
250
- get dbFQN ( ) : ( T [ 'DB' ] & { } ) [ '__element__' ] [ '__name__' ] {
251
- return this . db . __element__ . __name__ ;
252
+ get dbFQN ( ) : DBType < T > [ '__element__' ] [ '__name__' ] {
253
+ return this . db . __element__ . __name__ as any ;
252
254
}
253
255
254
256
@Once ( )
@@ -282,6 +284,25 @@ export const isResourceClass = <T>(
282
284
) : cls is ResourceShape < T > =>
283
285
'Props' in cls && Array . isArray ( cls . Props ) && cls . Props . length > 0 ;
284
286
287
+ export type ResourceName < TResourceStatic extends ResourceShape < any > > =
288
+ ResourceShape < any > extends TResourceStatic
289
+ ? string // short-circuit non-specific types
290
+ : {
291
+ [ Name in keyof ResourceMap ] : ResourceMap [ Name ] extends TResourceStatic // Only self or subclasses
292
+ ? TResourceStatic extends ResourceMap [ Name ] // Exclude subclasses
293
+ ? Name
294
+ : never
295
+ : never ;
296
+ } [ keyof ResourceMap ] &
297
+ string ;
298
+
299
+ export type DBType < TResourceStatic extends ResourceShape < any > > =
300
+ ResourceName < TResourceStatic > extends keyof ResourceDBMap
301
+ ? ResourceDBMap [ ResourceName < TResourceStatic > ] extends infer T extends $ . $expr_PathNode
302
+ ? T
303
+ : never
304
+ : never ;
305
+
285
306
export type MaybeUnsecuredInstance < TResourceStatic extends ResourceShape < any > > =
286
307
MaybeSecured < InstanceType < TResourceStatic > > ;
287
308
0 commit comments