{"id":16482320,"url":"https://github.com/uesteibar/scribano","last_synced_at":"2025-09-07T08:38:48.132Z","repository":{"id":85652948,"uuid":"170867405","full_name":"uesteibar/scribano","owner":"uesteibar","description":"Automatically build AsyncAPI documentation for your RabbitMQ messages","archived":false,"fork":false,"pushed_at":"2023-02-25T00:38:40.000Z","size":135,"stargazers_count":9,"open_issues_count":4,"forks_count":1,"subscribers_count":1,"default_branch":"master","last_synced_at":"2025-04-04T15:21:20.444Z","etag":null,"topics":["asyncapi","documentation-generator","documentation-tool","event-driven-architecture","microservices","rabbitmq"],"latest_commit_sha":null,"homepage":"https://cloud.docker.com/repository/docker/uesteibar/scribano","language":"Go","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/uesteibar.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2019-02-15T13:15:09.000Z","updated_at":"2023-03-18T07:50:20.000Z","dependencies_parsed_at":"2024-06-20T11:14:09.152Z","dependency_job_id":"b64acd3c-63e2-46a4-8a2f-44c0a865f6b8","html_url":"https://github.com/uesteibar/scribano","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/uesteibar/scribano","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/uesteibar%2Fscribano","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/uesteibar%2Fscribano/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/uesteibar%2Fscribano/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/uesteibar%2Fscribano/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/uesteibar","download_url":"https://codeload.github.com/uesteibar/scribano/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/uesteibar%2Fscribano/sbom","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":268799748,"owners_count":24309320,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","status":"online","status_checked_at":"2025-08-04T02:00:09.867Z","response_time":79,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["asyncapi","documentation-generator","documentation-tool","event-driven-architecture","microservices","rabbitmq"],"created_at":"2024-10-11T13:10:23.018Z","updated_at":"2025-08-04T23:10:14.535Z","avatar_url":"https://github.com/uesteibar.png","language":"Go","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Scribano\n\n[![Codacy Badge](https://api.codacy.com/project/badge/Grade/b5b934e0789c40389c5213e679ffef8a)](https://app.codacy.com/app/uesteibar/scribano?utm_source=github.com\u0026utm_medium=referral\u0026utm_content=uesteibar/scribano\u0026utm_campaign=Badge_Grade_Dashboard)\n[![CircleCI](https://circleci.com/gh/uesteibar/scribano/tree/master.svg?style=svg)](https://circleci.com/gh/uesteibar/scribano/tree/master)\n\nBuilds an [asyncapi](https://www.asyncapi.com/) documentation for your microservices\ncommunicating through [rabbitmq](https://www.rabbitmq.com/).\n\nIt listens to all published amqp messages and keeps an updated asyncapi\ncompliant documentation served at `/asyncapi`.\n\nSample configuration can be found [here](https://github.com/uesteibar/scribano/blob/master/fixtures/test/yaml_config.yml).\n\n## How does it work?\n\nScribano will subscribe to a set of configured RabbitMQ exchanges, and will start\nconsuming events from there.\n\nWhen a message is consumed, scribano will infer a structure for the content.\nFor example, after consuming a message on the `some.key` routing key with the following payload:\n```json\n{\n  \"name\": \"infer type\",\n  \"age\": 27,\n  \"grade\": 9.5,\n  \"canDrive\": false,\n  \"birthDate\": \"1991-08-29\",\n  \"lastLogin\": \"2015-06-10T13:23:30-08:00\",\n  \"address\": null,\n  \"emptyHash\": {},\n  \"fines\": [],\n  \"emptyHashes\": [{}],\n  \"matrix\": [\n    [1, 2, 3],\n    [3, 2, 1]\n  ],\n  \"friends\": [\n    { \"name\": \"pepe\" },\n    { \"name\": \"gotera\" }\n  ],\n  \"car\": {\n    \"brand\": \"mercedes\"\n  }\n}\n```\n\nThe following spec will be served on `/asyncapi`\n\n```\n{\n  \"asyncapi\": \"1.0.0\",\n  \"info\": {\n    \"title\": \"\",\n    \"version\": \"\"\n  },\n  \"topics\": {\n    \"some.key\": {\n      \"publish\": {\n        \"$ref\": \"#/components/messages/SomeKey\"\n      },\n      \"x-exchange\": \"/my-exchange\"\n    }\n  },\n  \"components\": {\n    \"messages\": {\n      \"SomeKey\": {\n        \"payload\": {\n          \"type\": \"object\",\n          \"properties\": {\n            \"name\": {\n              \"type\": \"string\"\n            },\n            \"age\": {\n              \"type\": \"integer\"\n            },\n            \"grade\": {\n              \"type\": \"number\"\n            },\n            \"birthDate\": {\n              \"type\": \"string\",\n              \"format\": \"date\"\n            },\n            \"lastLogin\": {\n              \"type\": \"string\",\n              \"format\": \"date-time\"\n            },\n            \"address\": {\n              \"type\": \"string\"\n            },\n            \"emptyHash\": {\n              \"type\": \"object\"\n            },\n            \"fines\": {\n              \"type\": \"array\",\n              \"items\": {\n                \"type\": \"string\"\n              }\n            },\n            \"emptyHashes\": {\n              \"type\": \"array\",\n              \"items\": {\n                \"type\": \"object\"\n              }\n            },\n            \"matrix\": {\n              \"type\": \"array\",\n              \"items\": {\n                \"type\": \"array\",\n                \"items\": {\n                  \"type\": \"integer\"\n                }\n              }\n            },\n            \"friends\": {\n              \"type\": \"array\",\n              \"items\": {\n                \"type\": \"object\",\n                \"properties\": {\n                  \"birthDate\": {\n                    \"type\": \"string\",\n                    \"format\": \"date\"\n                  },\n                  \"name\": {\n                    \"type\": \"string\"\n                  }\n                }\n              }\n            },\n            \"car\": {\n              \"type\": \"object\",\n              \"properties\": {\n                \"brand\": {\n                  \"type\": \"string\"\n                }\n              }\n            }\n          }\n        }\n      }\n    }\n  }\n}\n```\n\n### Type inference\n\n|            value            | inferred type |   format  |                                  notes                                 |\n|:---------------------------:|:-------------:|:---------:|:----------------------------------------------------------------------:|\n|        \"some string\"        |     string    |           |                                                                        |\n|         \"1991-08-29\"        |     string    |    date   | Format must match exactly, otherwise it is considered a regular string |\n| \"2015-06-10T13:23:30-08:00\" |     string    | date-time | Format must match exactly, otherwise it is considered a regular string |\n|         true / false        |    boolean    |           |                                                                        |\n|            [...]            |     array     |           | Type for the array values is inferred by checking on the first element |\n|            {...}            |     object    |           |     Types for the fields inside the object are checked recursively     |\n|             null            |     string    |           |                                                                        |\n\n### Optional fields\n\nFields are set as optional using the custom `x-optional: true` attribute.\n\nWhen a fields is received in a message and then not received in a\nsubsequent message, it is considered optional as the presence of that\nfield cannot be guaranteed.\n\nWhen a field is received in a message and was never previously received,\nit is also considered optional.\n\n\n## Running locally\n\nInstall dependencies\n```\ngo mod download\n```\n\nLoad environmental variables\n```\nsource .env.dev\n```\n\n```\ngo run main.go -f fixtures/test/yaml_config.yml\n```\n\nYou can also fetch the configuration from a url\n```\ngo run main.go -u https://raw.githubusercontent.com/uesteibar/scribano/master/fixtures/test/yaml_config.yml\n```\n\n## Running on docker\n\n```\ndocker run -e PG_URL='postgresql://postgres:postgres@localhost:5433/asyncapi' uesteibar/scribano ./scribano -u https://raw.githubusercontent.com/uesteibar/scribano/master/fixtures/test/yaml_config.yml\n```\n\n### Running tests\n\nStart the rabbitmq server\n\n```\ndocker-compose up -d\n```\n\nRun the tests\n\n```\nmake test\n```\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fuesteibar%2Fscribano","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fuesteibar%2Fscribano","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fuesteibar%2Fscribano/lists"}