Hi!
Are there any existing tools that can take some Daml templates, and for each one, output what that template looks like (with associated types) in its corresponding JSON representation for the HTTP API?
Given the following example, I guess I’m looking for something like
Input:
template Role
with
operator : Party
provider : Party
observers : Set Party
where
signatory operator, provider
observer observers
key (operator, provider) : (Party, Party)
maintainer key._1
controller provider can
nonconsuming OfferRegulatorService : ContractId Regulator.Offer
with
customer : Party
do
create Regulator.Offer with ..
Output:
// v1/create
{
payload: {
"operator": string,
"provider": string,
"observers": {
"map": [
[
string,
{}
]
]
}
},
templateId: "72390a820b1bbb8dbf035bb070f93fab5a801d356aef049adbf8132e522b8e02:Marketplace.Regulator.Role:Role"
}
// v1/exercise (for OfferRegulatorService)
{
argument: {
"customer": string
},
choice: "OfferRegulatorService",
contractId: string,
templateId: "72390a820b1bbb8dbf035bb070f93fab5a801d356aef049adbf8132e522b8e02:Marketplace.Regulator.Role:Role"
}
3 Likes
Hi @Alex_Matson,
To make it a bit more concrete: What you’re asking for is effectively a DAR → JSON Schema or maybe even openapi generator.
This does not currently exist. The former is relatively easy to build, the latter requires some changes to the JSON API to make it nicely usable: The way openAPI is structured the response and request types can only depend on the URL. So to say that the request type should be a specific template, the template needs to be part of the URL. Otherwise your schema can only say "/v1/create expects a dam-lf value as the payload” which is significantly less useful.
2 Likes
Yes, exactly.
I did make a first attempt at hand-crafting an OpenAPI document to represent the JSON schemas, but ran into the issue you mention where only one path is allowed. Using oneOf
for the request content is possible, but becomes much less useful for the purposes of documentation. (Also, not to mention that handwriting schemas for a medium to large Daml application would be quite tedious ;P)
A DAR → JSON Schema generator should suffice for my use case. How should I go about writing one? Should I look at some of the existing code generators (i.e., the JS codegen) for inspiration, and maybe try to modify them? Or is there a simpler way?
Thanks!
2 Likes
The TypeScript code generator is probably a good starting point. The code for that is in here daml/TsCodeGenMain.hs at 993591e53bd6cef1c0a2bb144e9aeda7b00215ea · digital-asset/daml · GitHub. Hopefully writing a JSON schema codegen is much simpler.
3 Likes
For reference, for your Role
template, daml codegen js
outputs
export declare type Role = {
operator: damlTypes.Party;
provider: damlTypes.Party;
observers: pkg97b883cd8a2b7f49f90d5d39c981cf6e110cf1f1c64427a28a6d58ec88c43657.DA.Set.Types.Set<damlTypes.Party>;
};
// dereferencing Set:
export declare type Set<k> = {
map: damlTypes.Map<k, {}>;
};
// damlTypes are all hand-written in language-support/ts/daml-types/index.ts
export type Party = string;
export interface Map<K, V> {
get: (k: K) => V | undefined;
has: (k: K) => boolean;
set: (k: K, v: V) => Map<K, V>;
delete: (k: K) => Map<K, V>;
keys: () => Iterator<K, undefined, undefined>;
values: () => Iterator<V, undefined, undefined>;
entries: () => Iterator<[K, V], undefined, undefined>;
entriesArray: () => [K, V][];
forEach: <T, U>(f: (value: V, key: K, map: Map<K, V>) => T, u?: U) => void;
}
So you have a couple differences:
- The codegen output takes advantage of TypeScript dereferencing. This includes recursive types, which make it so you can’t naively expand type declarations to get rid of this indirection.
data SomeList a = SomeList { uncons : Optional (a, SomeList a) }
-- makes
export declare type SomeList<a> = {
uncons: damlTypes.Optional<pkg40f452260bef3f29dede136108fc08a88d5a5250310281067087da6f0baddff7.DA.Types.Tuple2<a, SomeList<a>>>;
};
- Most structures in TypeScript match the JSON format, but there are a few exceptions where actual codec-ing is being done, such as with Map.
Nevertheless, it’s a good starting point, as @cocreature said.
2 Likes