The vocabulary/lexicon generation
Generating code should start from a Go struct with annotations, or from a JSON-LD context document.
The steps should be something like this:
Structure
We need to validate the struct’s compatibility with the Vanilla AP objects:
- the properties must match the position and type of one of the
Object,Actor,IntransitiveActivity,Activity,Link, etc. - the struct must validate against the JSON-LD contexts that the developer chooses for them.
Helper functions
Generate helper functions in the lexicon package:
- Initializer function:
vocab.New<Type>- Perhaps fluent API builders - with generics - would provide a better UX?
lexicon.Builder[lexicon.Object]().Type(lexicon.NoteType)(an example of how something like that would look like is in the FedBOX integration tests)
- Perhaps fluent API builders - with generics - would provide a better UX?
- Implement
LinkOrIRIinterface methodGetLink(). - Implement
ActivityObjectinterface methods:GetID()andGetType(). - Implement
HasRecipientsinterface method:Recipients() - If it contains
BtoandBCCrecipient properties, implementClean()method. - Generate function type
With<Type>Fnthat’s used as parameters forOn<StructName> - Generate functions:
On<StructName>, andTo<StructName>- Perhaps change
To<StructName>to return*StructName, boolinstead of error
- Perhaps change
- Generate
MarshalJSON/UnmarshalJSON,GobEncode/GobDecode - Add type switch cases to the
IsObject,IsActor,IsActivity,IsIntransitiveActivity,IsLink - Add type switch cases to the
ToObject,ToActor,ToActivity,ToIntransitiveActivity,ToLink - Add type switch cases to the
IsNilfunction.
One thing we need to consider is that the Tombstone object can be used as any of the other object types, because it’s the artefact of a Delete activity. So an object reconstituted after a Delete could be used in places as a specific Actor type, for example.
Types constraints
Accumulate types for generated objects and add their types to the slices for:
ActorTypes: struct has Inbox/Outbox propertiesActivityTypes: struct has Actor/Object propertiesIntransitiveActivityTypes: struct has Actor property but no Object propertyLinkTypes: no ID property, but has a Href property.CollectionTypes: struct hasItems/OrderedItemsandTotalItems(perhapsNext?).ObjectTypes: what’s left? - This is the default when there’s nothing else annotated.
Accumulate types into the interfaces that can be used by generic code (Actors, Objects, etc).
Codecs for the data types
As we already mentioned, since we know the structure of the generated data types, the package should include the encoding/decoding functionality for at least two types of representations:
- JSON-LD in compacted or expanded form - which can then be manipulated by using a JSON-LD encoder, for example compacting it for dispatch to the regular Fediverse
- Binary - which can be used as a storage blob
JSON-LD
We have already done some preliminary work for facilitating the generation of Go code from JSON-LD contexts.
It’s uncertain if the contexts are able to provide enough information in order to generate a full type for Go, so the fallback option is to generate from type stubs written as Go code.
Eg:
type Example struct {
vocab.Object `` // Hint to the generator that we want to extend an object
NewProperty vocab.Item `` // a New Property
}
Expanded
The data types will need to include annotations for the expanded property names, or some mapping method.
Compacted
The simple method for encoding will most likely need the property name and the corresponding value.
Binary
This should probably not be a gob dependent encoding, as it requires registering data types with it.
Since we control the implementations for all the types that are likely to appear, we can rely on a manual method for binary encoding.