diff --git a/apps/emqx_conf/src/emqx_conf.erl b/apps/emqx_conf/src/emqx_conf.erl index 122998eeb..0bd319503 100644 --- a/apps/emqx_conf/src/emqx_conf.erl +++ b/apps/emqx_conf/src/emqx_conf.erl @@ -31,13 +31,6 @@ -export([dump_schema/2, reformat_schema_dump/2]). -export([schema_module/0]). -%% TODO: move to emqx_dashboard when we stop building api schema at build time --export([ - hotconf_schema_json/0, - bridge_schema_json/0, - hocon_schema_to_spec/2 -]). - %% for rpc -export([get_node_and_config/1]). @@ -456,17 +449,6 @@ warn_bad_namespace(Namespace) -> ok end. -%% TODO: move this function to emqx_dashboard when we stop generating this JSON at build time. -hotconf_schema_json() -> - SchemaInfo = #{title => <<"EMQX Hot Conf API Schema">>, version => <<"0.1.0">>}, - gen_api_schema_json_iodata(emqx_mgmt_api_configs, SchemaInfo). - -%% TODO: move this function to emqx_dashboard when we stop generating this JSON at build time. -bridge_schema_json() -> - Version = <<"0.1.0">>, - SchemaInfo = #{title => <<"EMQX Data Bridge API Schema">>, version => Version}, - gen_api_schema_json_iodata(emqx_bridge_api, SchemaInfo). - %% @doc return the root schema module. -spec schema_module() -> module(). schema_module() -> @@ -506,57 +488,6 @@ make_desc_resolver(Lang) -> unicode:characters_to_binary(Desc) end. -gen_api_schema_json_iodata(SchemaMod, SchemaInfo) -> - emqx_dashboard_swagger:gen_api_schema_json_iodata( - SchemaMod, - SchemaInfo, - fun ?MODULE:hocon_schema_to_spec/2 - ). - --define(TO_REF(_N_, _F_), iolist_to_binary([to_bin(_N_), ".", to_bin(_F_)])). --define(TO_COMPONENTS_SCHEMA(_M_, _F_), - iolist_to_binary([ - <<"#/components/schemas/">>, - ?TO_REF(emqx_dashboard_swagger:namespace(_M_), _F_) - ]) -). - -hocon_schema_to_spec(?R_REF(Module, StructName), _LocalModule) -> - {#{<<"$ref">> => ?TO_COMPONENTS_SCHEMA(Module, StructName)}, [{Module, StructName}]}; -hocon_schema_to_spec(?REF(StructName), LocalModule) -> - {#{<<"$ref">> => ?TO_COMPONENTS_SCHEMA(LocalModule, StructName)}, [{LocalModule, StructName}]}; -hocon_schema_to_spec(Type, LocalModule) when ?IS_TYPEREFL(Type) -> - {typename_to_spec(typerefl:name(Type), LocalModule), []}; -hocon_schema_to_spec(?ARRAY(Item), LocalModule) -> - {Schema, Refs} = hocon_schema_to_spec(Item, LocalModule), - {#{type => array, items => Schema}, Refs}; -hocon_schema_to_spec(?ENUM(Items), _LocalModule) -> - {#{type => enum, symbols => Items}, []}; -hocon_schema_to_spec(?MAP(Name, Type), LocalModule) -> - {Schema, SubRefs} = hocon_schema_to_spec(Type, LocalModule), - { - #{ - <<"type">> => object, - <<"properties">> => #{<<"$", (to_bin(Name))/binary>> => Schema} - }, - SubRefs - }; -hocon_schema_to_spec(?UNION(Types, _DisplayName), LocalModule) -> - {OneOf, Refs} = lists:foldl( - fun(Type, {Acc, RefsAcc}) -> - {Schema, SubRefs} = hocon_schema_to_spec(Type, LocalModule), - {[Schema | Acc], SubRefs ++ RefsAcc} - end, - {[], []}, - hoconsc:union_members(Types) - ), - {#{<<"oneOf">> => OneOf}, Refs}; -hocon_schema_to_spec(Atom, _LocalModule) when is_atom(Atom) -> - {#{type => enum, symbols => [Atom]}, []}. - -typename_to_spec(TypeStr, Module) -> - emqx_conf_schema_types:readable_dashboard(Module, TypeStr). - join_format(Snippets) -> case [S || S <- Snippets, S =/= undefined] of [] -> diff --git a/apps/emqx_dashboard/src/emqx_dashboard_schema_api.erl b/apps/emqx_dashboard/src/emqx_dashboard_schema_api.erl index 9b5c45e71..41f516c7a 100644 --- a/apps/emqx_dashboard/src/emqx_dashboard_schema_api.erl +++ b/apps/emqx_dashboard/src/emqx_dashboard_schema_api.erl @@ -33,6 +33,14 @@ -define(TAGS, [<<"dashboard">>]). -define(BAD_REQUEST, 'BAD_REQUEST'). +-define(TO_REF(_N_, _F_), iolist_to_binary([to_bin(_N_), ".", to_bin(_F_)])). +-define(TO_COMPONENTS_SCHEMA(_M_, _F_), + iolist_to_binary([ + <<"#/components/schemas/">>, + ?TO_REF(emqx_dashboard_swagger:namespace(_M_), _F_) + ]) +). + %%-------------------------------------------------------------------- %% minirest API and schema %%-------------------------------------------------------------------- @@ -77,14 +85,22 @@ get_schema(get, _) -> {400, ?BAD_REQUEST, <<"unknown">>}. gen_schema(hotconf) -> - emqx_conf:hotconf_schema_json(); + hotconf_schema_json(); gen_schema(bridges) -> - emqx_conf:bridge_schema_json(); + bridge_schema_json(); gen_schema(actions) -> actions_schema_json(); gen_schema(connectors) -> connectors_schema_json(). +hotconf_schema_json() -> + SchemaInfo = #{title => <<"EMQX Hot Conf API Schema">>, version => <<"0.1.0">>}, + gen_api_schema_json_iodata(emqx_mgmt_api_configs, SchemaInfo). + +bridge_schema_json() -> + SchemaInfo = #{title => <<"EMQX Data Bridge API Schema">>, version => <<"0.1.0">>}, + gen_api_schema_json_iodata(emqx_bridge_api, SchemaInfo). + actions_schema_json() -> SchemaInfo = #{title => <<"EMQX Data Actions API Schema">>, version => <<"0.1.0">>}, %% Note: this will be moved to `emqx_actions' application in the future. @@ -98,5 +114,46 @@ gen_api_schema_json_iodata(SchemaMod, SchemaInfo) -> emqx_dashboard_swagger:gen_api_schema_json_iodata( SchemaMod, SchemaInfo, - fun emqx_conf:hocon_schema_to_spec/2 + fun hocon_schema_to_spec/2 ). + +hocon_schema_to_spec(?R_REF(Module, StructName), _LocalModule) -> + {#{<<"$ref">> => ?TO_COMPONENTS_SCHEMA(Module, StructName)}, [{Module, StructName}]}; +hocon_schema_to_spec(?REF(StructName), LocalModule) -> + {#{<<"$ref">> => ?TO_COMPONENTS_SCHEMA(LocalModule, StructName)}, [{LocalModule, StructName}]}; +hocon_schema_to_spec(Type, LocalModule) when ?IS_TYPEREFL(Type) -> + {typename_to_spec(typerefl:name(Type), LocalModule), []}; +hocon_schema_to_spec(?ARRAY(Item), LocalModule) -> + {Schema, Refs} = hocon_schema_to_spec(Item, LocalModule), + {#{type => array, items => Schema}, Refs}; +hocon_schema_to_spec(?ENUM(Items), _LocalModule) -> + {#{type => enum, symbols => Items}, []}; +hocon_schema_to_spec(?MAP(Name, Type), LocalModule) -> + {Schema, SubRefs} = hocon_schema_to_spec(Type, LocalModule), + { + #{ + <<"type">> => object, + <<"properties">> => #{<<"$", (to_bin(Name))/binary>> => Schema} + }, + SubRefs + }; +hocon_schema_to_spec(?UNION(Types, _DisplayName), LocalModule) -> + {OneOf, Refs} = lists:foldl( + fun(Type, {Acc, RefsAcc}) -> + {Schema, SubRefs} = hocon_schema_to_spec(Type, LocalModule), + {[Schema | Acc], SubRefs ++ RefsAcc} + end, + {[], []}, + hoconsc:union_members(Types) + ), + {#{<<"oneOf">> => OneOf}, Refs}; +hocon_schema_to_spec(Atom, _LocalModule) when is_atom(Atom) -> + {#{type => enum, symbols => [Atom]}, []}. + +typename_to_spec(TypeStr, Module) -> + emqx_conf_schema_types:readable_dashboard(Module, TypeStr). + +to_bin(List) when is_list(List) -> iolist_to_binary(List); +to_bin(Boolean) when is_boolean(Boolean) -> Boolean; +to_bin(Atom) when is_atom(Atom) -> atom_to_binary(Atom, utf8); +to_bin(X) -> X.