diff --git a/src/cowboy_swagger.erl b/src/cowboy_swagger.erl index 4cccdb2..5342016 100644 --- a/src/cowboy_swagger.erl +++ b/src/cowboy_swagger.erl @@ -2,7 +2,7 @@ -module(cowboy_swagger). %% API --export([to_json/1]). +-export([to_json/1, add_definition/2]). %% Utilities -export([enc_json/1, dec_json/1]). @@ -19,6 +19,7 @@ , description => iodata() , required => boolean() , type => iodata() + , schema => iodata() }. -export_type([parameter_obj/0]). @@ -28,6 +29,20 @@ -type responses_definitions() :: #{binary() => response_obj()}. -export_type([response_obj/0, responses_definitions/0]). +-type parameter_definition_name () :: binary(). +-type property_obj() :: + #{binary() => + #{ type => binary() + , description => binary() + , example => binary() + }}. +-type parameters_definitions() :: + #{parameter_definition_name() => + #{ type => binary() + , properties => property_obj() + }}. +-export_type([parameter_definition_name/0, property_obj/0]). + %% Swagger map spec -opaque swagger_map() :: #{ description => iodata() @@ -60,6 +75,19 @@ to_json(Trails) -> basePath => ApiRoot}, enc_json(SwaggerSpec). +-spec add_definition( Name::parameter_definition_name() + , Properties::property_obj() + ) -> + ok. +add_definition(Name, Properties) -> + Definition = build_definition(Name, Properties), + SwaggerSpec = application:get_env(cowboy_swagger, global_spec, #{}), + ExistingDefinitions = maps:get(definitions, SwaggerSpec, #{}), + NewDefinitions = #{definitions => maps:merge( ExistingDefinitions + , Definition + )}, + application:set_env(cowboy_swagger, global_spec, NewDefinitions). + %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %% Utilities. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% @@ -175,3 +203,13 @@ validate_swagger_map_params(Params) -> validate_swagger_map_responses(Responses) -> F = fun(_K, V) -> V#{description => maps:get(description, V, <<"">>)} end, maps:map(F, Responses). + +%% @private +-spec build_definition( Name::parameter_definition_name() + , Properties::property_obj() + ) -> + parameters_definitions(). +build_definition(Name, Properties) -> + #{Name => #{ type => <<"object">> + , properties => Properties + }}. diff --git a/test/cowboy_swagger_SUITE.erl b/test/cowboy_swagger_SUITE.erl index 6171a1f..701e85c 100644 --- a/test/cowboy_swagger_SUITE.erl +++ b/test/cowboy_swagger_SUITE.erl @@ -9,7 +9,7 @@ ]). -export([all/0]). --export([to_json_test/1]). +-export([to_json_test/1, add_definition_test/1]). %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %% Common test @@ -120,6 +120,48 @@ to_json_test(_Config) -> 3 = maps:size(Paths), {comment, ""}. +-spec add_definition_test(Config::cowboy_swagger_test_utils:config()) -> + {comment, string()}. +add_definition_test(_Config) -> + ct:comment("Add first definition"), + Name1 = <<"CostumerDefinition">>, + Properties1 = + #{ <<"first_name">> => + #{ type => <<"string">> + , description => <<"User first name">> + , example => <<"Pepito">> + } + , <<"last_name">> => + #{ type => <<"string">> + , description => <<"User last name">> + , example => <<"Perez">> + } + }, + ok = cowboy_swagger:add_definition(Name1, Properties1), + {ok, SwaggerSpec} = application:get_env(cowboy_swagger, global_spec), + Definition1 = maps:get(definitions, SwaggerSpec), + + ct:comment("Add second definition"), + Name2 = <<"CarDefinition">>, + Properties2 = + #{ <<"brand">> => + #{ type => <<"string">> + , description => <<"Car brand">> + } + , <<"year">> => + #{ type => <<"string">> + , description => <<"Production time">> + , example => <<"1995">> + } + }, + ok = cowboy_swagger:add_definition(Name2, Properties2), + {ok, SwaggerSpec1} = application:get_env(cowboy_swagger, global_spec), + JsonDefinitions = maps:get(definitions, SwaggerSpec1), + true = maps:is_key(Name1, JsonDefinitions), + true = maps:is_key(Name2, JsonDefinitions), + + {comment, ""}. + %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %% Internal functions %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%