Standard OCaml encoders for the OpenAPI standard.
std_projection
std_projection
exists for three reasons.
1. Json_encoding does not allow more fields to be present than declared with (for example) Json_encoding.obj10
. Since OpenAPI generally has open types (field can be added), we need to transform ("project") the JSON to only have the fields declared. 2. JSON has three states for a field (present with non-null value, present with null value, absent) while canonical OCaml has two (None
and Some
). Json_encoding prevents optional nullable combinations but gives a mechanism to have three states with Some None
, Some Some _
and None
. Confer Nullables. That is not canonical OCaml which will confuse many OCaml-ers, but in rare situations a REST server may require a distinction between all three states. In all other situations, "present with null value" and "absent" are treated identically so std_projection
removes the null
fields from the JSON object. 3. OpenAPI has an additionalFields
property. The projection makes it simple, after projecting the known fields, to have every other field be the additional fields.
Types
val pp_type_array :
format:'a ->
'b ->
(Restapis_o.Open__.Format.formatter -> 'c -> unit) ->
Restapis_o.Open__.Format.formatter ->
'c ->
unit
val pp_type_option :
(Restapis_o.Open__.Format.formatter -> 'a -> unit) ->
Restapis_o.Open__.Format.formatter ->
'a ->
unit
val pp_type_additional :
(Restapis_o.Open__.Format.formatter -> 'a -> unit) ->
Restapis_o.Open__.Format.formatter ->
'a ->
unit
val pp_type_string :
format:string option ->
enum:'a ->
'b ->
Restapis_o.Open__.Format.formatter ->
unit ->
unit
val pp_type_integer :
format:string option ->
enum:'a ->
Json_schema.numeric_specs ->
Restapis_o.Open__.Format.formatter ->
unit ->
unit
val pp_type_boolean :
format:'a ->
enum:'b ->
Restapis_o.Open__.Format.formatter ->
unit ->
unit
val pp_encoder_array :
format:'a ->
'b ->
(Restapis_o.Open__.Format.formatter -> 'c -> unit) ->
Restapis_o.Open__.Format.formatter ->
'c ->
unit
val pp_encoder_option :
(Restapis_o.Open__.Format.formatter -> 'a -> unit) ->
Restapis_o.Open__.Format.formatter ->
'a ->
unit
val pp_encoder_additional :
(Restapis_o.Open__.Format.formatter -> 'a -> unit) ->
Restapis_o.Open__.Format.formatter ->
'a ->
unit
val pp_encoder_string :
format:string option ->
enum:Json_repr.any list option ->
'a ->
Restapis_o.Open__.Format.formatter ->
unit ->
unit
val pp_encoder_integer :
format:string option ->
enum:'a ->
Json_schema.numeric_specs ->
Restapis_o.Open__.Format.formatter ->
unit ->
unit
val pp_encoder_boolean :
format:'a ->
enum:'b ->
Restapis_o.Open__.Format.formatter ->
unit ->
unit
Functions
val pp_lambda :
typename:string option ->
varname:string ->
(Restapis_o.Open__.Format.formatter -> 'a -> unit) ->
Restapis_o.Open__.Format.formatter ->
'a ->
unit
Primitives
val primitive_never_optional :
format:string option ->
enum:Json_repr.any list option ->
[ `PrimitiveAny
| `PrimitiveBoolean
| `PrimitiveInteger of Json_schema.numeric_specs
| `PrimitiveNull
| `PrimitiveNumber of Json_schema.numeric_specs
| `PrimitiveString of Json_schema.string_specs ] ->
bool
Variants
caseize s
make a capitalized case name of the string s
.
s
may be a type name or an enumeration value.
For example, caseize "string list"
is "StringList"
.
Reserved OCaml Names
The following variant names and exceptions are in use by OCaml's standard library, and redefining them may cause generated code to fail at runtime in sometimes hard-to-understand ways. So they are all appended with an underscore:
None
Some
Error
Result
Ok
Invalid_argument
Not_found
And a few external modules ... which have the same capitalized casing as variants ... are used in the generated code (see "open__.ml"
) and can't conflict:
String
Option
List
Routes
Uri
Fun
Buffer
Format
Stringext
Map
Array
Printf
Float
Types
(an internally generated submodule)
For example, None
is represented as None_
.
Empty Strings
Empty strings are represented as Empty
.
Stripe uses an empty string as a variant often. For example at paths /v1/accounts post requestBody content application/x-www-form-urlencoded schema properties business_profile
:
"support_url": { "anyOf": [ { "type": "string" }, { "enum": [ "" ], "type": "string" } ] },
Duplicates
Duplicates need to be handled by the vendor extension. For example, Stripe's timezone
value "Etc/GMT+0"
is indistinguishable from "Etc/GMT-0"
.
val pp_type_enumeration :
caseize:(string -> string) ->
path:Json_query.path ->
[< `Boolean | `Integer | `String ] ->
Restapis_o.Open__.Format.formatter ->
Json_repr.any list ->
unit
val pp_encoder_enumeration :
sumtype_nonopt:[< `PrimitiveType of string | `TypeAlias of string ] ->
caseize:(string -> string) ->
casepath:(int -> Json_query.path) ->
[< `Boolean | `Integer | `String ] ->
Restapis_o.Open__.Format.formatter ->
Json_repr.any list ->
unit
val pp_encoder_union :
casename:(path:'a -> string) ->
casepath:(int -> 'b -> 'a) ->
sumtype_nonopt:[< `PrimitiveType of string | `TypeAlias of string ] ->
(Restapis_o.Open__.Format.formatter -> (int * 'b) -> unit) ->
Restapis_o.Open__.Format.formatter ->
'b list ->
unit
include DkCoder_Std.SCRIPT
__init context
is the entry point for running a script module. The DkCoder compiler will inject this function at the top and bottom of the script module. The top __init
does nothing, while the bottom __init
calls the prior __init
.
That means:
- calling the
__init
function guarantees that the script module is initialized; that is, all of the script module's side-effects (ex.let () = Format.printf "Hello world@."
) are executed before the__init
returns to the caller. - you can override the
__init
function by simply defining the__init
idempotently. That will shadow the top__init
and when the bottom__init
is executed your__init
will be called instead of the do-nothing top__init
.
Future versions of DkCoder will call __init
in dependency order for all `You
script modules. Your __init
function may be called several times.
__repl context
is the entry point for debugging a script module in a REPL. The DkCoder compiler will inject this function at the top and bottom of the script module. The top __repl
does nothing, while the bottom __repl
calls the prior __repl
.
That means:
- you can override the
__repl
function by simply defining the__repl
idempotently. That will shadow the top__repl
and when the bottom__repl
is executed your__repl
will be called instead of the do-nothing top__repl
.
The run-time module information for the script module.