Skip to content

Commit ea3cbe3

Browse files
authored
Merge pull request #15 from JuliaPostgresORM/generate-typescript
Add generation of typescript model and support for array of custom types
2 parents aa082da + c5a0a99 commit ea3cbe3

File tree

5 files changed

+79
-7
lines changed

5 files changed

+79
-7
lines changed

Project.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
name = "PostgresORM"
22
uuid = "748b5efa-ed57-4836-b183-a38105a77fdd"
33
authors = ["Vincent Laugier <vincent.laugier@gmail.com>"]
4-
version = "0.1.6"
4+
version = "0.1.7"
55

66
[deps]
77
DataFrames = "a93c6f00-e57d-5684-b7b6-d8193f3e46c0"

src/Controller/coreORM.utils.part1.jl

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,7 @@ function util_get_entity_props_for_db_actions(entity::IEntity,
7272
columns_selection_and_mapping,
7373
entity_type)
7474
props = util_replace_enums_by_id_if_needed(props, orm_module, dbconn)
75+
props = util_replace_empty_vector_of_enums_by_missing(props)
7576
props = util_replace_dict_types(props, orm_module, dbconn)
7677

7778
end
@@ -114,6 +115,7 @@ function util_get_entity_props_for_comparison(entity::IEntity,
114115
columns_selection_and_mapping,
115116
entity_type)
116117
props = util_replace_enums_by_id_if_needed(props,orm_module,dbconn)
118+
props = util_replace_empty_vector_of_enums_by_missing(props)
117119
props = util_replace_dict_types(props,orm_module,dbconn)
118120

119121
return(props)
@@ -421,6 +423,8 @@ function util_dict2entity(props_dict::Dict{Symbol,T},
421423
# @info props_dict[fsymbol]
422424
props_dict[fsymbol] =
423425
PostgresORMUtil.postgresql_string_array_2_string_vector(props_dict[fsymbol])
426+
elseif ftype <: Vector{T} where T <: Base.Enums.Enum
427+
props_dict[fsymbol] = string2vector_of_enums(ftype,props_dict[fsymbol])
424428
elseif ftype <: Enum
425429

426430
if ismissing(props_dict[fsymbol])
@@ -899,6 +903,23 @@ function util_replace_enums_by_id_if_needed(props::Dict,
899903
return props
900904
end
901905

906+
"""
907+
util_replace_empty_vector_of_enums_by_missing(props::Dict)
908+
909+
Replace empty vector of an enum by missing. This allows developers to avoid testing both for
910+
nullity and emptiness of the property
911+
"""
912+
function util_replace_empty_vector_of_enums_by_missing(props::Dict)
913+
for (prop_symbol, prop_val) in props
914+
if typeof(prop_val) <: Vector{T} where T <: Base.Enums.Enum
915+
if isempty(prop_val)
916+
props[prop_symbol] = missing
917+
end
918+
end
919+
end
920+
return props
921+
end
922+
902923
function util_replace_dict_types(props::Dict,
903924
orm_module::Module,
904925
dbconn::LibPQ.Connection)

src/PostgresORM.jl

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@ module PostgresORM
3939
# include("./web-api-definition.jl")
4040
# end
4141

42-
greet() = return ("Hello World!")
42+
greet() = return ("Hello World from PostgresORM!")
4343

4444
module PostgresORMUtil
4545
using ..PostgresORM
@@ -48,7 +48,8 @@ module PostgresORM
4848
export opendbconn, closedbconn, dict2namedtuple, namedtuple2dict, tovector,
4949
get_nonmissing_typeof_uniontype, dataframe2vector_of_namedtuples,
5050
dataframerow2namedtuple, getdictvalues, getpropertiesvalues,
51-
setpropertiesvalues!, remove_spaces_and_split, diff_dict, string2enum,
51+
setpropertiesvalues!, remove_spaces_and_split, diff_dict,
52+
string2enum, string2vector_of_enums,
5253
int2enum, enum2int, dictstringkeys2symbol, dictnothingvalues2missing,
5354
getproperties_asdict, string2zoneddatetime
5455

@@ -108,8 +109,9 @@ module PostgresORM
108109
using ..CRUDType
109110
using ..PostgresORMUtil, ..SchemaInfo
110111
# using .ModificationORM # no need (because ModificationORM is a children module ?)
111-
using Tables, DataFrames, Query, LibPQ, Dates, UUIDs, TickTock
112+
using Tables, DataFrames, Query, LibPQ, Dates, TimeZones, UUIDs, TickTock
112113
include("./Tool/Tool.jl")
114+
include("./Tool/Tool-typescript.jl")
113115

114116
end # module Tool
115117

src/PostgresORMUtil/utils.jl

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -137,6 +137,27 @@ function string2enum(enumType::DataType,str::String)
137137

138138
end
139139

140+
"""
141+
"""
142+
function string2vector_of_enums(vectorOfEnumsTypes::Type{Vector{T}},
143+
str::Union{String,Missing}) where T <: Base.Enums.Enum
144+
enumType = eltype(vectorOfEnumsTypes)
145+
146+
if ismissing(str)
147+
return missing
148+
end
149+
150+
# If no element in the array return an empty array
151+
if str == "{}"
152+
return T[]
153+
end
154+
155+
chop(str,head = 1,tail = 1) |> n -> split(n,",") |>
156+
n -> string.(n) |>
157+
n -> string2enum.(enumType,n)
158+
159+
end
160+
140161
function string2zoneddatetime(str)
141162
# eg. "2019-09-03T11:00:00.000Z"
142163
date_match_GMT =

src/Tool/Tool.jl

Lines changed: 31 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -76,11 +76,14 @@ function build_field_name(str_arr::Vector{String},
7676
return field_name
7777
end
7878

79-
function get_fieldtype_from_coltype(coltype::String,elttype::String
79+
function get_fieldtype_from_coltype(coltype::String,
80+
elttype::String,
81+
customtypes::Dict,
8082
;tablename::String = "",
8183
colname::String = "")
8284

8385
attrtype = missing
86+
customtypes_names = keys(customtypes) |> collect |> n -> string.(n)
8487

8588
if (coltype == "character"
8689
|| coltype == "character varying"
@@ -110,6 +113,9 @@ function get_fieldtype_from_coltype(coltype::String,elttype::String
110113
elseif (coltype == "ARRAY")
111114
if (elttype == "_text" || elttype == "_varchar")
112115
attrtype = "Vector{String}"
116+
elseif elttype[2:end] in customtypes_names
117+
elttype = elttype[2:end] # remove the leading underscore
118+
attrtype = "Vector{$(build_enum_name_w_module(elttype))}"
113119
else
114120
error("Unknown array type[$elttype] for table[$tablename] column[$colname]")
115121
end
@@ -140,6 +146,7 @@ function generate_julia_code(dbconn::LibPQ.Connection,
140146

141147
end
142148

149+
143150
function generate_object_model(
144151
dbconn::LibPQ.Connection,
145152
lang_code::String
@@ -222,6 +229,7 @@ function generate_object_model(
222229
manytoone_field[:is_manytoone] = true
223230
end
224231
manytoone_field[:is_onetomany] = false
232+
manytoone_field[:is_enum] = false
225233

226234
# Build a field name by one of the following options:
227235
# Case 1: The FK is composed of one column only. In this case we use
@@ -304,12 +312,19 @@ function generate_object_model(
304312
id_field[:is_manytoone] = false
305313
id_field[:is_onetoone] = false
306314
id_field[:is_onetomany] = false
315+
id_field[:is_enum] = false
307316
field_name = build_field_name(pkcol,lang_code)
308317
id_field[:name] = field_name
309318

310319
field_type =
311320
get_fieldtype_from_coltype(tabledef[:cols][pkcol][:type],
312-
tabledef[:cols][pkcol][:elttype_if_array])
321+
tabledef[:cols][pkcol][:elttype_if_array],
322+
custom_types)
323+
324+
# Check if it is an enum
325+
if tabledef[:cols][pkcol][:type] == "USER-DEFINED"
326+
id_field[:is_enum] = true
327+
end
313328

314329
id_field[:field_type] = field_type
315330
push!(struct_id_fields, id_field)
@@ -329,14 +344,21 @@ function generate_object_model(
329344
basic_field[:is_manytoone] = false
330345
basic_field[:is_onetoone] = false
331346
basic_field[:is_onetomany] = false
347+
basic_field[:is_enum] = false
332348
field_name = build_field_name(colname,lang_code)
333349
basic_field[:name] = field_name
334350

335351
field_type =
336352
get_fieldtype_from_coltype(coldef[:type],
337-
coldef[:elttype_if_array]
353+
coldef[:elttype_if_array],
354+
custom_types
338355
;tablename = table, colname = colname)
339356

357+
# Check if it is an enum
358+
if coldef[:type] == "USER-DEFINED"
359+
basic_field[:is_enum] = true
360+
end
361+
340362
basic_field[:field_type] = field_type
341363
push!(struct_basic_fields, basic_field)
342364

@@ -362,6 +384,7 @@ function generate_object_model(
362384
onetomany_field[:is_manytoone] = false
363385
onetomany_field[:is_onetoone] = false
364386
onetomany_field[:is_onetomany] = true
387+
onetomany_field[:is_enum] = false
365388
onetomany_type_name_w_module = manytoone_field[:field_type] # Public.Staff
366389

367390
# Build a field_name using one of the following options:
@@ -496,6 +519,11 @@ function generate_structs_from_object_model(object_model::Dict, outdir::String)
496519
f[:field_type]
497520
end
498521
str = " $field_name::Union{Missing,$field_type}\n"
522+
523+
if f[:name] == "policeOfficerRequests"
524+
@info "$(f[:name]) -> $str"
525+
end
526+
499527
_struct[:struct_content] *= str
500528
end
501529

0 commit comments

Comments
 (0)