0.0.3 • Published 2 years ago

@vennekilde/go-a2s-template v0.0.3

Weekly downloads
-
License
Apache-2.0
Repository
-
Last release
2 years ago

go-a2s-template

Examples

Asyncapi Streetlights API

As a example, the AsyncAPI streetlights api has been generated and can be found here: Generated API for AsyncAPI Streetlights

API Interface

Publish

    endpoint := client.S().Example().Endpoint()
    
    msg := endpoint.NewEndpointPubMsg()
    msg.Message.Payload.Text = "Hello World"
    
    err = endpoint.Publish(&msg, nil)
    if err != nil {
        t.Error(err)
    }

Subscribe

    endpoint := client.S().Example().Endpoint()

    sub, err := endpoint.Subscribe(
        func(msg *example.EndpointSubMsg) {
            // Do something with the received message.
            fmt.Println("%#v", msg)
        },
        nil,
    )
    if err != nil {
        panic(err)
    }
    defer sub.Unsubscribe()

Request

    endpoint := client.S().Example().Endpoint()

    requestMsg := endpoint.ReqMsg()
    requestMsg.Message.Payload.RequestText = "Hello World"
    
    replyMsg, err := endpoint.Request(&requestMsg, nil)
    if err != nil {
        t.Error(err)
    }
    fmt.Println("Received reply: %#v", replyMsg)

Reply

    sub, err := endpoint.Reply(
        func(request *example.EndpointReqMsg, reply *example.EndpointRepMsg) {
            // Do something with the received request.
            fmt.Println("Received reply: %#v", replyMsg)
    
            // Fill out reply with the response data.
            // The reply message will be sent once this function ends
            reply.Message.Payload.ReplyText = "World"
        },
        nil,
    )
    if err != nil {
        t.Error(err)
    }

Supported Transmission Clients

FeatureNATS (Default)
Channels
Parameters
Headers⚠️ No type generation, but can send any http.Header

Supported Message Codecs

Channel Properties

PropertyNATS (Default)
parameters✅ *
publish
subscribe
request
reply

* Parameters are supported for basic types (string, integer, etc), but not supported for objects.

Message Properties

PropertyNATS (Default)
headers?
payload

Schema

The focus has been entirely on being able to transcode the messages, while none has been placed on the validation aspect or limiting the range a variable can take.

Schema Types

TypeJSON (Default)
String
Enum
Boolean
Integer
Long
Float
Double
Date
DateTime
Byte
Binary
Password
Object

Schema Properties

PropertyJSON (Default)
required
enum
properties
additionalProperties
items
OneOf⚠️ *
AllOf⚠️ *
AnyOf⚠️ *
multipleOf
maximum
exclusiveMaximum
minimum
exclusiveMinimum
maxLength
minLength
pattern
maxItems
minItems
uniqueItems
maxProperties
minProperties
const
if / then / else
readOnly
writeOnly
patternProperties
additionalItems
propertyNames
contains
Not

* OneOf, AllOf & AnyOf only supports Object types. Additionally, there is no support for clashing field types, meaning that if two fields have the same name, but different types, the generated code will not function as intended, if it even compiles.Supported Schema Properties

Known limitations

JSON Codec limitations

Floating point precision

The GoJay JSON decoder appears to only be accurate down to the 6th and 15th decimal place for float32 and float64 respectively.

Likely, if you need better precision than this, you should probably not use floating points in the first place, but it is a weird issue that needs to be looked into and does make testing a little more tricky.

Go versions prior to 1.17 will experience issues with inaccurate encoding of floats due to https://github.com/golang/go/issues/36657.

How To Use

ag asyncapi.yaml ./tools/go-a2s-template -o gen/go-a2s-client --install --param moduleName=a2sclient --param modulePath=github.com/org/project

This will generate a Go module named github.com/org/project/a2sclient inside the folder gen/go-a2s-client relative to your current path

You can include the generated module in your code as any other Go module. An easy fast way would be to add replace github.com/org/project/a2sclient => ./gen/go-a2s-client to your go.mod

Parameters

ParameterTypeRequiredDefaultDescription
moduleNameStringYesName that will be used to name the generated go module
modulePathStringYesSource control path of the module without the name. e.g github.com/example/
perspectiveStringNoWhich perspective to take when generating. See #Perspective section below.
genProtocolCodeBooleanNotrueGenerate protocol specific code
genTestsBooleanNotrueGenerate tests
struct:genCodecsBooleanNotrueEnable or disable generation of encoders & decoders
struct:genSchemasBooleanNotrueEnable or disable generation of schema structs
struct:genMessagesBooleanNotrueEnable or disable generation of message structs
struct:messagesPathStringNomessageRelative path to message structs. Does not change where messages are generated, only the import parts.
struct:schemasPathStringNoschemaRelative path to schema structs. Does not change where schemas are generated, only the import parts.
go:genGoPGSQLBooleanNotrueGenerate go-pg sql fields
go:genAsModuleBooleanNotrueGO: Generate as go module

Perspective

The default perspective will interpret the asyncapi file, such that if a channel is defined with a publish message. The generated client will have logic for publishing that message.

The same is true for if a channel contains a subscribe message, in which case the generated client will have logic for subscribing to the channel for receiving that message.

This logic can be reversed by setting the option perspective to reverse, effectively creating a mirror client to the none-reversed client.

You can use this to generate both the "sender" and the "receiver" from a single asyncapi file.

Generated API

AsyncAPI Spec Extensions

To de-clutter the generated API, you can specify a prefix and a version number, which will be used as a prefix for the channel.

ParameterTypeRequiredDefaultDescription
x-versionStringNoName that will be used to name the generated go module
x-prefixString / NumberNoSource control path of the module without the name. e.g github.com/example/

Example: The channel smartylighting/streetlights/1/0/action/{streetlightId}/turn/on can be defined as

action/{streetlightId}/turn/on:
  x-version: 1.0
  x-prefix: smartylighting/streetlights

Built in Error Handeling

To simplify exchange of error messages, this has been built into the client so you do not have to bloat your asyncapi spec with one of syntax and added logic to handle receiving multiple payload types.

Instead if both you and the recipient have enabled the feature, the publisher will add a header called GOA2S-LERR to indicate that it is capable of listening for published errors.

If the recipient also has the feature enable, it might respond to the reply channel with the header GOA2S-ISERR to indicate, that this reply is not a part of the standard message flow, but is instead an error and should be processed as such.

example

Template Development

Typescript Filters

Typescript is used in order to improve the maintainability of the filters and add better type awareness to the IDE.

The Typescript filters has to be transpiled to Javascript, as AsyncAPI does not understand native Typescript.

Typescript transpilation

The Typescript filters & hooks are transpiled by running the following command

make compile-filters