1+ /*
2+ * Copyright 2023 Fluence Labs Limited
3+ *
4+ * Licensed under the Apache License, Version 2.0 (the "License");
5+ * you may not use this file except in compliance with the License.
6+ * You may obtain a copy of the License at
7+ *
8+ * http://www.apache.org/licenses/LICENSE-2.0
9+ *
10+ * Unless required by applicable law or agreed to in writing, software
11+ * distributed under the License is distributed on an "AS IS" BASIS,
12+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+ * See the License for the specific language governing permissions and
14+ * limitations under the License.
15+ */
16+
17+ import { ArrowType , ArrowWithoutCallbacks , NonArrowType , ProductType } from '@fluencelabs/interfaces' ;
18+ import { match , P } from 'ts-pattern' ;
19+ import { getFuncArgs } from './utils.js' ;
20+
21+ export function genTypeName ( t : NonArrowType | ProductType < NonArrowType > | ArrowWithoutCallbacks , name : string ) : readonly [ string | undefined , string ] {
22+ const genType = typeToTs ( t ) ;
23+ return match ( t )
24+ . with (
25+ { tag : 'nil' } ,
26+ ( ) => [ undefined , 'void' ] as const
27+ ) . with (
28+ { tag : 'struct' } ,
29+ ( ) => [ `export type ${ name } = ${ genType } ` , name ] as const
30+ ) . with (
31+ { tag : P . union ( 'labeledProduct' , 'unlabeledProduct' ) } ,
32+ ( item ) => {
33+ const args = item . tag === 'labeledProduct'
34+ ? Object . values ( item . fields )
35+ : item . items ;
36+
37+ if ( args . length === 1 ) {
38+ return genTypeName ( args [ 0 ] , name ) ;
39+ }
40+
41+ return [ `export type ${ name } = ${ genType } ` , name ] as const ;
42+ } ,
43+ ) . otherwise ( ( ) => [ undefined , genType ] as const ) ;
44+ }
45+
46+ export function typeToTs ( t : NonArrowType | ArrowWithoutCallbacks | ProductType < NonArrowType > ) : string {
47+ return match ( t )
48+ . with (
49+ { tag : 'nil' } ,
50+ ( ) => 'null'
51+ ) . with (
52+ { tag : 'option' } ,
53+ ( { type } ) => typeToTs ( type ) + ' | null'
54+ ) . with (
55+ { tag : 'scalar' } ,
56+ ( { name } ) => match ( name )
57+ . with ( P . union ( 'u8' , 'u16' , 'u32' , 'u64' , 'i8' , 'i16' , 'i32' , 'i64' , 'f32' , 'f64' ) , ( ) => 'number' )
58+ . with ( 'bool' , ( ) => 'boolean' )
59+ . with ( 'string' , ( ) => 'string' )
60+ . with ( P . _ , ( ) => 'any' ) . exhaustive ( )
61+ ) . with (
62+ { tag : 'array' } ,
63+ ( { type } ) => typeToTs ( type ) + '[]'
64+ ) . with (
65+ { tag : 'struct' } ,
66+ ( { fields } ) => `{ ${ Object . entries ( fields ) . map ( ( [ field , type ] ) => `${ field } : ${ typeToTs ( type ) } ;` ) . join ( ' ' ) } }`
67+ ) . with (
68+ { tag : 'labeledProduct' } ,
69+ ( { fields } ) => `{ ${ Object . entries ( fields ) . map ( ( [ field , type ] ) => `${ field } : ${ typeToTs ( type ) } ;` ) . join ( ' ' ) } }`
70+ ) . with (
71+ { tag : 'unlabeledProduct' } ,
72+ ( { items } ) => `[${ items . map ( item => typeToTs ( item ) ) . join ( ', ' ) } ]`
73+ ) . with (
74+ { tag : 'arrow' } ,
75+ ( { tag, domain, codomain } ) => {
76+ const retType = codomain . tag === 'nil'
77+ ? 'void'
78+ : codomain . items . length === 1
79+ ? typeToTs ( codomain . items [ 0 ] )
80+ : typeToTs ( codomain ) ;
81+
82+ const args = getFuncArgs ( domain ) . map ( ( [ name , type ] ) => ( [ name , typeToTs ( type ) ] ) ) ;
83+
84+ const generic = args . length === 0 ? 'null' : args . map ( ( [ name ] ) => `'${ name } '` ) . join ( ' | ' ) ;
85+ args . push ( [ 'callParams' , `CallParams$$<${ generic } >` ] ) ;
86+
87+ const funcArgs = args . map ( ( [ name , type ] ) => `${ name } : ${ type } ` ) . join ( ', ' ) ;
88+
89+ return `(${ funcArgs } ) => ${ retType } | Promise<${ retType } >` ;
90+ }
91+ ) . with (
92+ { tag : 'topType' } ,
93+ ( ) => 'unknown'
94+ ) . with (
95+ { tag : 'bottomType' } ,
96+ ( ) => 'never'
97+ ) . exhaustive ( ) ;
98+ }
0 commit comments