-
-
Notifications
You must be signed in to change notification settings - Fork 16
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
016e7ca
commit cfdc109
Showing
66 changed files
with
19,250 additions
and
1,635 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,4 @@ | ||
node_modules | ||
test/temp | ||
output | ||
__transpiled |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,116 @@ | ||
env: | ||
node: true | ||
es6: true | ||
jest/globals: true | ||
|
||
plugins: | ||
- sonarjs | ||
- jest | ||
- react | ||
|
||
extends: | ||
- eslint:recommended | ||
- plugin:jest/recommended | ||
- plugin:react/recommended | ||
- plugin:sonarjs/recommended | ||
- plugin:security/recommended | ||
|
||
parserOptions: | ||
ecmaVersion: 2018 | ||
sourceType: module | ||
ecmaFeatures: | ||
jsx: true | ||
settings: | ||
react: | ||
version: detect | ||
|
||
rules: | ||
# Ignore Rules | ||
strict: 0 | ||
no-underscore-dangle: 0 | ||
no-mixed-requires: 0 | ||
no-process-exit: 0 | ||
no-warning-comments: 0 | ||
curly: 0 | ||
no-multi-spaces: 0 | ||
no-alert: 0 | ||
consistent-return: 0 | ||
consistent-this: [0, self] | ||
func-style: 0 | ||
max-nested-callbacks: 0 | ||
camelcase: 0 | ||
|
||
# Warnings | ||
no-debugger: 1 | ||
no-empty: 1 | ||
no-invalid-regexp: 1 | ||
no-unused-expressions: 1 | ||
no-native-reassign: 1 | ||
no-fallthrough: 1 | ||
sonarjs/cognitive-complexity: 1 | ||
|
||
# Errors | ||
eqeqeq: 2 | ||
no-undef: 2 | ||
no-dupe-keys: 2 | ||
no-empty-character-class: 2 | ||
no-self-compare: 2 | ||
valid-typeof: 2 | ||
no-unused-vars: [2, { "args": "none" }] | ||
handle-callback-err: 2 | ||
no-shadow-restricted-names: 2 | ||
no-new-require: 2 | ||
no-mixed-spaces-and-tabs: 2 | ||
block-scoped-var: 2 | ||
no-else-return: 2 | ||
no-throw-literal: 2 | ||
no-void: 2 | ||
radix: 2 | ||
wrap-iife: [2, outside] | ||
no-shadow: 0 | ||
no-use-before-define: [2, nofunc] | ||
no-path-concat: 2 | ||
valid-jsdoc: [0, {requireReturn: false, requireParamDescription: false, requireReturnDescription: false}] | ||
|
||
# stylistic errors | ||
no-spaced-func: 2 | ||
semi-spacing: 2 | ||
quotes: [2, 'single'] | ||
key-spacing: [2, { beforeColon: false, afterColon: true }] | ||
indent: [2, 2] | ||
no-lonely-if: 2 | ||
no-floating-decimal: 2 | ||
brace-style: [2, 1tbs, { allowSingleLine: true }] | ||
comma-style: [2, last] | ||
no-multiple-empty-lines: [2, {max: 1}] | ||
no-nested-ternary: 2 | ||
operator-assignment: [2, always] | ||
padded-blocks: [2, never] | ||
quote-props: [2, as-needed] | ||
keyword-spacing: [2, {'before': true, 'after': true, 'overrides': {}}] | ||
space-before-blocks: [2, always] | ||
array-bracket-spacing: [2, never] | ||
computed-property-spacing: [2, never] | ||
space-in-parens: [2, never] | ||
space-unary-ops: [2, {words: true, nonwords: false}] | ||
wrap-regex: 2 | ||
linebreak-style: [2, unix] | ||
semi: [2, always] | ||
arrow-spacing: [2, {before: true, after: true}] | ||
no-class-assign: 2 | ||
no-const-assign: 2 | ||
no-dupe-class-members: 2 | ||
no-this-before-super: 2 | ||
no-var: 2 | ||
object-shorthand: [2, always] | ||
prefer-arrow-callback: 2 | ||
prefer-const: 2 | ||
prefer-spread: 2 | ||
prefer-template: 2 | ||
|
||
# React | ||
react/jsx-uses-react: off | ||
react/react-in-jsx-scope: off | ||
react/display-name: off | ||
react/prop-types: off | ||
react/jsx-key: off |
This file was deleted.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -5,3 +5,6 @@ node_modules/* | |
|
||
# Generated AsyncAPI output | ||
test/output/* | ||
output/* | ||
.DS_Store | ||
__transpiled |
Validating CODEOWNERS rules …
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
# This file provides an overview of code owners in this repository. | ||
|
||
# Each line is a file pattern followed by one or more owners. | ||
# The last matching pattern has the most precedence. | ||
# For more details, read the following article on GitHub: https://help.github.com/articles/about-codeowners/. | ||
|
||
# The default owners are automatically added as reviewers when you open a pull request unless different owners are specified in the file. | ||
* @anandsunderraman @smoya @github-actions[bot] |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,107 @@ | ||
- [Overview](#overview) | ||
- [Technical requirements](#technical-requirements) | ||
- [Supported protocols](#supported-protocols) | ||
- [How to use the template](#how-to-use-the-template) | ||
* [CLI](#cli) | ||
- [Template configuration](#template-configuration) | ||
|
||
|
||
## Overview | ||
|
||
This template generates a Go module that uses [watermill](https://github.com/ThreeDotsLabs/watermill) as the messaging middleware | ||
|
||
## Technical requirements | ||
|
||
- 1.1.0 =< [Generator](https://github.com/asyncapi/generator/) < 2.0.0, | ||
- Generator specific [requirements](https://github.com/asyncapi/generator/#requirements) | ||
|
||
## Supported protocols | ||
|
||
Currently this template supports AMQP subscribers | ||
|
||
## How to use the template | ||
|
||
This template must be used with the AsyncAPI Generator. You can find all available options [here](https://github.com/asyncapi/generator/). | ||
|
||
### CLI | ||
|
||
This template has been tested to generate an AMQP subscriber for [this asyncapi.yaml file](./test/asyncapi.yaml) | ||
|
||
#### Run the following command to generate a Go module | ||
|
||
```bash | ||
npm install -g @asyncapi/generator | ||
# clone this repository and navigate to this repository | ||
ag test/asyncapi.yaml @asyncapi/go-watermill-template -o /path/to/generated-code -p moduleName=your-go-module-name | ||
``` | ||
|
||
Following are the options that can be passed to the generator | ||
|
||
1. moduleName: name of the go module to be generated | ||
|
||
#### How to use the generated code | ||
|
||
The above code currently generates a Go module that has a AMQP subscriber. | ||
|
||
##### Pre-requisites | ||
To run the generated code the following needs to be installed | ||
|
||
1. go 1.16 + | ||
2. rabbitmq-server OR docker | ||
|
||
##### Running the code | ||
|
||
1. Navigate to the path where the code was generated | ||
2. Run the following commands to download the dependencies | ||
```bash | ||
go mod download | ||
go mod tidy | ||
``` | ||
3. Currently the code does not utilize the server bindings to generate the server URI. It is currently hardcoded to point to a local instance of `rabbitmq`. It is hardcoded as `"amqp://guest:guest@localhost:5672/"` at `<generated-code>/config/server.go`. Change it as per your rabbitmq instance requirements | ||
4. Finally to execute the code run | ||
```bash | ||
go run main.go | ||
``` | ||
5. Running local instance of `rabbitmq`, navigate to it using `http://localhost:15672/` with username and password `guest`/ `guest` (These are default rabbitmq credentials). | ||
FYI one can start an instance of `rabbitmq` using `docker` as follow | ||
``` | ||
docker run -d -p 15672:15672 -p 5672:5672 rabbitmq:3-management | ||
``` | ||
6. Create a queue as per the AsyncAPI spec. | ||
This can be done either of the following ways | ||
- Using the UI: Refer to this [article](https://www.cloudamqp.com/blog/part3-rabbitmq-for-beginners_the-management-interface.html) that walks through the process of how this can be done in the UI / RabbitMQ Admin | ||
- `cURL` request. Default rabbitmq user is `guest` and password is `guest` | ||
``` | ||
curl --user <rabbit-user>:<rabbit-password> -X PUT \ | ||
http://localhost:15672/api/queues/%2f/<queue-name> \ | ||
-H 'cache-control: no-cache' \ | ||
-H 'content-type: application/json' \ | ||
-d '{ | ||
"auto_delete":false, | ||
"durable":true | ||
}' | ||
``` | ||
7. Publish a message to the queue as per the AsyncAPI spec. This can be done either of the following ways | ||
- Using the UI: Refer to this [article](https://www.cloudamqp.com/blog/part3-rabbitmq-for-beginners_the-management-interface.html) that walks through the process of how this can be done in the UI / RabbitMQ Admin | ||
- `cURL` request. Default rabbitmq user is `guest` and password is `guest` | ||
``` | ||
curl --user <rabbit-user>:<rabbit-password> -X POST \ | ||
http://localhost:15672/api/exchanges/%2f/amq.default/publish \ | ||
-H 'cache-control: no-cache' \ | ||
-H 'content-type: application/json' \ | ||
-d ' { | ||
"properties":{}, | ||
"routing_key":"light/measured", | ||
"payload":"{\"id\":1,\"lumens\":2,\"sentAt\":\"2021-09-21\"}", | ||
"payload_encoding":"string" | ||
}' | ||
``` | ||
8. Check the output at the terminal where `go run main.go` was running and the published message should be printed | ||
|
||
## Template configuration | ||
|
||
You can configure this template by passing different parameters in the Generator CLI: `-p PARAM1_NAME=PARAM1_VALUE -p PARAM2_NAME=PARAM2_VALUE` | ||
|
||
|Name|Description|Required|Example| | ||
|---|---|---|---| | ||
|moduleName|Name for the generated Go module|false|`my-app`| |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,42 @@ | ||
import { render } from '@asyncapi/generator-react-sdk'; | ||
import { pascalCase } from './common'; | ||
|
||
const subscriptionFunction = (channelName, operation, message) => ` | ||
// ${operation} subscription handler for ${channelName}. | ||
func ${operation}(msg *message.Message) error { | ||
log.Printf("received message payload: %s", string(msg.Payload)) | ||
var lm ${message} | ||
err := json.Unmarshal(msg.Payload, &lm) | ||
if err != nil { | ||
log.Printf("error unmarshalling message: %s, err is: %s", msg.Payload, err) | ||
} | ||
return nil | ||
} | ||
`; | ||
|
||
function SubscriptionHandlers({ channels }) { | ||
return Object.entries(channels) | ||
.map(([channelName, channel]) => { | ||
if (channel.hasPublish()) { | ||
const operation = pascalCase(channel.publish().id()); | ||
const message = pascalCase(channel.publish().message(0).payload().$id()); | ||
return subscriptionFunction(channelName, operation, message); | ||
} | ||
return ''; | ||
}); | ||
} | ||
|
||
export function Handlers({ moduleName, channels}) { | ||
return ` | ||
package asyncapi | ||
import ( | ||
"encoding/json" | ||
"log" | ||
"github.com/ThreeDotsLabs/watermill/message" | ||
) | ||
${render(<SubscriptionHandlers channels={channels} />)} | ||
`; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,52 @@ | ||
import { render } from '@asyncapi/generator-react-sdk'; | ||
import { pascalCase } from './common'; | ||
|
||
const addHandlerFunction = (queue, operation) => ` | ||
r.AddNoPublisherHandler( | ||
"${operation}", // handler name, must be unique | ||
"${queue}", // topic from which we will read events | ||
s, | ||
${operation}, | ||
) | ||
`; | ||
|
||
function AMQPRouterRules({ channels }) { | ||
return Object.entries(channels) | ||
.map(([channelName, channel]) => { | ||
if (channel.hasPublish()) { | ||
const operation = pascalCase(channel.publish().id()); | ||
const queue = channel.bindings().amqp.queue.name; | ||
return addHandlerFunction(queue, operation); | ||
} | ||
return ''; | ||
}); | ||
} | ||
|
||
export function Router({moduleName, channels, subscriberFlags}) { | ||
let amqpRules = ''; | ||
if (subscriberFlags.hasAMQPSub) { | ||
amqpRules = ` | ||
// ConfigureAMQPSubscriptionHandlers configures the router with the subscription handler. | ||
func ConfigureAMQPSubscriptionHandlers(r *message.Router, s message.Subscriber) { | ||
${render(<AMQPRouterRules channels={channels} />)} | ||
} | ||
`; | ||
} | ||
|
||
return ` | ||
package asyncapi | ||
import ( | ||
"github.com/ThreeDotsLabs/watermill" | ||
"github.com/ThreeDotsLabs/watermill/message" | ||
) | ||
// GetRouter returns a watermill router. | ||
func GetRouter() (*message.Router, error){ | ||
logger := watermill.NewStdLogger(false, false) | ||
return message.NewRouter(message.RouterConfig{}, logger) | ||
} | ||
${amqpRules} | ||
`; | ||
} |
Oops, something went wrong.