gtsocial-umbx

Unnamed repository; edit this file 'description' to name the repository.
Log | Files | Refs | README | LICENSE

README.md (5113B)


      1 # streams
      2 
      3 ActivityStreams vocabularies automatically code-generated with `astool`.
      4 
      5 ## Reference & Tutorial
      6 
      7 The [go-fed website](https://go-fed.org/) contains tutorials and reference
      8 materials, in addition to the rest of this README.
      9 
     10 ## How To Use
     11 
     12 ```
     13 go get github.com/go-fed/activity
     14 ```
     15 
     16 All generated types and properties are interfaces in
     17 `github.com/go-fed/streams/vocab`, but note that the constructors and supporting
     18 functions live in `github.com/go-fed/streams`.
     19 
     20 To create a type and set properties:
     21 
     22 ```golang
     23 var actorURL *url.URL = // ...
     24 
     25 // A new "Create" Activity.
     26 create := streams.NewActivityStreamsCreate()
     27 // A new "actor" property.
     28 actor := streams.NewActivityStreamsActorProperty()
     29 actor.AppendIRI(actorURL)
     30 // Set the "actor" property on the "Create" Activity.
     31 create.SetActivityStreamsActor(actor)
     32 ```
     33 
     34 To process properties on a type:
     35 
     36 ```golang
     37 // Returns true if the "Update" has at least one "object" with an IRI value.
     38 func hasObjectWithIRIValue(update vocab.ActivityStreamsUpdate) bool {
     39   objectProperty := update.GetActivityStreamsObject()
     40   // Any property may be nil if it was either empty in the original JSON or
     41   // never set on the golang type.
     42   if objectProperty == nil {
     43     return false
     44   }
     45   // The "object" property is non-functional: it could have multiple values. The
     46   // generated code has slightly different methods for a functional property
     47   // versus a non-functional one.
     48   //
     49   // While it may be easy to ignore multiple values in other languages
     50   // (accidentally or purposefully), go-fed is designed to make it hard to do
     51   // so.
     52   for iter := objectProperty.Begin(); iter != objectProperty.End(); iter = iter.Next() {
     53     // If this particular value is an IRI, return true.
     54     if iter.IsIRI() {
     55       return true
     56     }
     57   }
     58   // All values are literal embedded values and not IRIs.
     59   return false
     60 }
     61 ```
     62 
     63 The ActivityStreams type hierarchy of "extends" and "disjoint" is not the same
     64 as the Object Oriented definition of inheritance. It is also not the same as
     65 golang's interface duck-typing. Helper functions are provided to guarantee that
     66 an application's logic can correctly apply the type hierarchy.
     67 
     68 ```golang
     69 thing := // Pick a type from streams.NewActivityStreams<Type>()
     70 if streams.ActivityStreamsObjectIsDisjointWith(thing) {
     71   fmt.Printf("The \"Object\" type is Disjoint with the %T type.\n", thing)
     72 }
     73 if streams.ActivityStreamsLinkIsExtendedBy(thing) {
     74   fmt.Printf("The %T type Extends from the \"Link\" type.\n", thing)
     75 }
     76 if streams.ActivityStreamsActivityExtends(thing) {
     77   fmt.Printf("The \"Activity\" type extends from the %T type.\n", thing)
     78 }
     79 ```
     80 
     81 When given a generic JSON payload, it can be resolved to a concrete type by
     82 creating a `streams.JSONResolver` and giving it a callback function that accepts
     83 the interesting concrete type:
     84 
     85 ```golang
     86 // Callbacks must be in the form:
     87 //   func(context.Context, <TypeInterface>) error
     88 createCallback := func(c context.Context, create vocab.ActivityStreamsCreate) error {
     89   // Do something with 'create'
     90   fmt.Printf("createCallback called: %T\n", create)
     91   return nil
     92 }
     93 updateCallback := func(c context.Context, update vocab.ActivityStreamsUpdate) error {
     94   // Do something with 'update'
     95   fmt.Printf("updateCallback called: %T\n", update)
     96   return nil
     97 }
     98 jsonResolver, err := streams.NewJSONResolver(createCallback, updateCallback)
     99 if err != nil {
    100   // Something in the setup was wrong. For example, a callback has an
    101   // unsupported signature and would never be called
    102   panic(err)
    103 }
    104 // Create a context, which allows you to pass data opaquely through the
    105 // JSONResolver.
    106 c := context.Background()
    107 // Example 15 of the ActivityStreams specification.
    108 b := []byte(`{
    109   "@context": "https://www.w3.org/ns/activitystreams",
    110   "summary": "Sally created a note",
    111   "type": "Create",
    112   "actor": {
    113     "type": "Person",
    114     "name": "Sally"
    115   },
    116   "object": {
    117     "type": "Note",
    118     "name": "A Simple Note",
    119     "content": "This is a simple note"
    120   }
    121 }`)
    122 var jsonMap map[string]interface{}
    123 if err = json.Unmarshal(b, &jsonMap); err != nil {
    124   panic(err)
    125 }
    126 // The createCallback function will be called.
    127 err = jsonResolver.Resolve(c, jsonMap)
    128 if err != nil && !streams.IsUnmatchedErr(err) {
    129   // Something went wrong
    130   panic(err)
    131 } else if streams.IsUnmatchedErr(err) {
    132   // Everything went right but the callback didn't match or the ActivityStreams
    133   // type is one that wasn't code generated.
    134   fmt.Println("No match: ", err)
    135 }
    136 ```
    137 
    138 A `streams.TypeResolver` is similar but uses the golang types instead. It
    139 accepts the generic `vocab.Type`. This is the abstraction when needing to handle
    140 any ActivityStreams type. The function `ToType` can convert a JSON-decoded-map
    141 into this kind of value if needed.
    142 
    143 A `streams.PredicatedTypeResolver` lets you apply a boolean predicate function
    144 that acts as a check whether a callback is allowed to be invoked.
    145 
    146 ## FAQ
    147 
    148 ### Why Are Empty Properties Nil And Not Zero-Valued?
    149 
    150 Due to implementation design decisions, it would require a lot of plumbing to
    151 ensure this would work properly. It would also require allocation of a
    152 non-trivial amount of memory.