@@ -15,15 +15,13 @@ export const apply = ({
1515 materializedViews,
1616 functions,
1717 types,
18- arrayTypes,
1918} : {
2019 schemas : PostgresSchema [ ]
2120 tables : ( PostgresTable & { columns : unknown [ ] } ) [ ]
2221 views : ( PostgresView & { columns : unknown [ ] } ) [ ]
2322 materializedViews : ( PostgresMaterializedView & { columns : unknown [ ] } ) [ ]
2423 functions : PostgresFunction [ ]
2524 types : PostgresType [ ]
26- arrayTypes : PostgresType [ ]
2725} ) : string => {
2826 let output = `
2927export type Json = string | number | boolean | null | { [key: string]: Json } | Json[]
@@ -63,6 +61,15 @@ export interface Database {
6361 const schemaEnums = types
6462 . filter ( ( type ) => type . schema === schema . name && type . enums . length > 0 )
6563 . sort ( ( { name : a } , { name : b } ) => a . localeCompare ( b ) )
64+ const schemaDomainTypes = types
65+ . flatMap ( ( type ) => {
66+ const baseType =
67+ type . schema === schema . name &&
68+ type . base_type_id &&
69+ types . find ( ( { id } ) => id === type . base_type_id )
70+ return baseType ? [ { type, baseType } ] : [ ]
71+ } )
72+ . sort ( ( { type : { name : a } } , { type : { name : b } } ) => a . localeCompare ( b ) )
6673 const schemaCompositeTypes = types
6774 . filter ( ( type ) => type . schema === schema . name && type . attributes . length > 0 )
6875 . sort ( ( { name : a } , { name : b } ) => a . localeCompare ( b ) )
@@ -82,8 +89,9 @@ export interface Database {
8289 `${ JSON . stringify ( column . name ) } : ${ pgTypeToTsType (
8390 column . format ,
8491 types ,
85- schemas
86- ) } ${ column . is_nullable ? '| null' : '' } `
92+ schemas ,
93+ { nullable : column . is_nullable }
94+ ) } `
8795 ) ,
8896 ...schemaFunctions
8997 . filter ( ( fn ) => fn . argument_types === table . name )
@@ -93,7 +101,7 @@ export interface Database {
93101 fn . return_type ,
94102 types ,
95103 schemas
96- ) } | null `
104+ ) } `
97105 ) ,
98106 ] }
99107 }
@@ -117,11 +125,9 @@ export interface Database {
117125 output += ':'
118126 }
119127
120- output += pgTypeToTsType ( column . format , types , schemas )
121-
122- if ( column . is_nullable ) {
123- output += '| null'
124- }
128+ output += pgTypeToTsType ( column . format , types , schemas , {
129+ nullable : column . is_nullable ,
130+ } )
125131
126132 return output
127133 } ) }
@@ -136,11 +142,9 @@ export interface Database {
136142 return `${ output } ?: never`
137143 }
138144
139- output += `?: ${ pgTypeToTsType ( column . format , types , schemas ) } `
140-
141- if ( column . is_nullable ) {
142- output += '| null'
143- }
145+ output += `?: ${ pgTypeToTsType ( column . format , types , schemas , {
146+ nullable : column . is_nullable ,
147+ } ) } `
144148
145149 return output
146150 } ) }
@@ -163,8 +167,9 @@ export interface Database {
163167 `${ JSON . stringify ( column . name ) } : ${ pgTypeToTsType (
164168 column . format ,
165169 types ,
166- schemas
167- ) } ${ column . is_nullable ? '| null' : '' } `
170+ schemas ,
171+ { nullable : column . is_nullable }
172+ ) } `
168173 ) }
169174 }
170175 ${
@@ -179,7 +184,9 @@ export interface Database {
179184 return `${ output } ?: never`
180185 }
181186
182- output += `?: ${ pgTypeToTsType ( column . format , types , schemas ) } | null`
187+ output += `?: ${ pgTypeToTsType ( column . format , types , schemas , {
188+ nullable : true ,
189+ } ) } `
183190
184191 return output
185192 } ) }
@@ -198,7 +205,9 @@ export interface Database {
198205 return `${ output } ?: never`
199206 }
200207
201- output += `?: ${ pgTypeToTsType ( column . format , types , schemas ) } | null`
208+ output += `?: ${ pgTypeToTsType ( column . format , types , schemas , {
209+ nullable : true ,
210+ } ) } `
202211
203212 return output
204213 } ) }
@@ -239,17 +248,7 @@ export interface Database {
239248 }
240249
241250 const argsNameAndType = inArgs . map ( ( { name, type_id, has_default } ) => {
242- let type = arrayTypes . find ( ( { id } ) => id === type_id )
243- if ( type ) {
244- // If it's an array type, the name looks like `_int8`.
245- const elementTypeName = type . name . substring ( 1 )
246- return {
247- name,
248- type : `(${ pgTypeToTsType ( elementTypeName , types , schemas ) } )[]` ,
249- has_default,
250- }
251- }
252- type = types . find ( ( { id } ) => id === type_id )
251+ const type = types . find ( ( { id } ) => id === type_id )
253252 if ( type ) {
254253 return {
255254 name,
@@ -272,19 +271,13 @@ export interface Database {
272271 const tableArgs = args . filter ( ( { mode } ) => mode === 'table' )
273272 if ( tableArgs . length > 0 ) {
274273 const argsNameAndType = tableArgs . map ( ( { name, type_id } ) => {
275- let type = arrayTypes . find ( ( { id } ) => id === type_id )
274+ const type = types . find ( ( { id } ) => id === type_id )
276275 if ( type ) {
277- // If it's an array type, the name looks like `_int8`.
278- const elementTypeName = type . name . substring ( 1 )
279276 return {
280277 name,
281- type : `( ${ pgTypeToTsType ( elementTypeName , types , schemas ) } )[]` ,
278+ type : pgTypeToTsType ( type . name , types , schemas ) ,
282279 }
283280 }
284- type = types . find ( ( { id } ) => id === type_id )
285- if ( type ) {
286- return { name, type : pgTypeToTsType ( type . name , types , schemas ) }
287- }
288281 return { name, type : 'unknown' }
289282 } )
290283
@@ -308,8 +301,9 @@ export interface Database {
308301 `${ JSON . stringify ( column . name ) } : ${ pgTypeToTsType (
309302 column . format ,
310303 types ,
311- schemas
312- ) } ${ column . is_nullable ? '| null' : '' } `
304+ schemas ,
305+ { nullable : column . is_nullable }
306+ ) } `
313307 ) }
314308 }`
315309 }
@@ -340,6 +334,21 @@ export interface Database {
340334 )
341335 }
342336 }
337+ DomainTypes: {
338+ ${
339+ schemaDomainTypes . length === 0
340+ ? '[_ in never]: never'
341+ : schemaDomainTypes . map (
342+ ( { type : domain_ , baseType } ) =>
343+ `${ JSON . stringify ( domain_ . name ) } : ${ pgTypeToTsType (
344+ baseType . name ,
345+ types ,
346+ schemas ,
347+ { nullable : domain_ . is_nullable }
348+ ) } `
349+ )
350+ }
351+ }
343352 CompositeTypes: {
344353 ${
345354 schemaCompositeTypes . length === 0
@@ -377,58 +386,72 @@ export interface Database {
377386const pgTypeToTsType = (
378387 pgType : string ,
379388 types : PostgresType [ ] ,
380- schemas : PostgresSchema [ ]
389+ schemas : PostgresSchema [ ] ,
390+ opts : { nullable ?: boolean } = { }
381391) : string => {
382- if ( pgType === 'bool' ) {
383- return 'boolean'
384- } else if ( [ 'int2' , 'int4' , 'int8' , 'float4' , 'float8' , 'numeric' ] . includes ( pgType ) ) {
385- return 'number'
386- } else if (
387- [
388- 'bytea' ,
389- 'bpchar' ,
390- 'varchar' ,
391- 'date' ,
392- 'text' ,
393- 'citext' ,
394- 'time' ,
395- 'timetz' ,
396- 'timestamp' ,
397- 'timestamptz' ,
398- 'uuid' ,
399- 'vector' ,
400- ] . includes ( pgType )
401- ) {
402- return 'string'
403- } else if ( [ 'json' , 'jsonb' ] . includes ( pgType ) ) {
404- return 'Json'
405- } else if ( pgType === 'void' ) {
406- return 'undefined'
407- } else if ( pgType === 'record' ) {
408- return 'Record<string, unknown>'
409- } else if ( pgType . startsWith ( '_' ) ) {
410- return `(${ pgTypeToTsType ( pgType . substring ( 1 ) , types , schemas ) } )[]`
411- } else {
412- const enumType = types . find ( ( type ) => type . name === pgType && type . enums . length > 0 )
413- if ( enumType ) {
414- if ( schemas . some ( ( { name } ) => name === enumType . schema ) ) {
415- return `Database[${ JSON . stringify ( enumType . schema ) } ]['Enums'][${ JSON . stringify (
416- enumType . name
417- ) } ]`
392+ const type = types . find ( ( type ) => type . name === pgType )
393+ const strictTsType = pgTypeToStrictTsType ( )
394+ return strictTsType
395+ ? `${ strictTsType } ${ opts . nullable ?? type ?. is_nullable ? ' | null' : '' } `
396+ : 'unknown'
397+
398+ function pgTypeToStrictTsType ( ) {
399+ if ( pgType === 'bool' ) {
400+ return 'boolean'
401+ } else if ( [ 'int2' , 'int4' , 'int8' , 'float4' , 'float8' , 'numeric' ] . includes ( pgType ) ) {
402+ return 'number'
403+ } else if (
404+ [
405+ 'bytea' ,
406+ 'bpchar' ,
407+ 'varchar' ,
408+ 'date' ,
409+ 'text' ,
410+ 'citext' ,
411+ 'time' ,
412+ 'timetz' ,
413+ 'timestamp' ,
414+ 'timestamptz' ,
415+ 'uuid' ,
416+ 'vector' ,
417+ ] . includes ( pgType )
418+ ) {
419+ return 'string'
420+ } else if ( [ 'json' , 'jsonb' ] . includes ( pgType ) ) {
421+ return 'Json'
422+ } else if ( pgType === 'void' ) {
423+ return 'undefined'
424+ } else if ( pgType === 'record' ) {
425+ return 'Record<string, unknown>'
426+ } else if ( pgType . startsWith ( '_' ) ) {
427+ return `(${ pgTypeToTsType ( pgType . substring ( 1 ) , types , schemas ) } )[]`
428+ } else if ( type != null ) {
429+ if ( type . base_type_id != null ) {
430+ if ( schemas . some ( ( { name } ) => name === type . schema ) ) {
431+ return `Database[${ JSON . stringify ( type . schema ) } ]['DomainTypes'][${ JSON . stringify (
432+ type . name
433+ ) } ]`
434+ }
435+ return undefined
436+ }
437+
438+ if ( type . enums . length > 0 ) {
439+ if ( schemas . some ( ( { name } ) => name === type . schema ) ) {
440+ return `Database[${ JSON . stringify ( type . schema ) } ]['Enums'][${ JSON . stringify ( type . name ) } ]`
441+ }
442+ return type . enums . map ( ( variant ) => JSON . stringify ( variant ) ) . join ( '|' )
418443 }
419- return enumType . enums . map ( ( variant ) => JSON . stringify ( variant ) ) . join ( '|' )
420- }
421444
422- const compositeType = types . find ( ( type ) => type . name === pgType && type . attributes . length > 0 )
423- if ( compositeType ) {
424- if ( schemas . some ( ( { name } ) => name === compositeType . schema ) ) {
425- return `Database[${ JSON . stringify (
426- compositeType . schema
427- ) } ]['CompositeTypes'][${ JSON . stringify ( compositeType . name ) } ]`
445+ if ( type . attributes . length > 0 ) {
446+ if ( schemas . some ( ( { name } ) => name === type . schema ) ) {
447+ return `Database[${ JSON . stringify ( type . schema ) } ]['CompositeTypes'][${ JSON . stringify (
448+ type . name
449+ ) } ]`
450+ }
451+ return undefined
428452 }
429- return 'unknown'
430453 }
431454
432- return 'unknown'
455+ return undefined
433456 }
434457}
0 commit comments