Created
June 26, 2017 18:07
-
-
Save Xe/73019f01cf8fb06a0f68654331e13300 to your computer and use it in GitHub Desktop.
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
{ | |
"swagger": "2.0", | |
"info": { | |
"title": "schema.proto", | |
"version": "version not set" | |
}, | |
"schemes": [ | |
"http", | |
"https" | |
], | |
"consumes": [ | |
"application/json" | |
], | |
"produces": [ | |
"application/json" | |
], | |
"paths": { | |
"/api/v1/applications": { | |
"post": { | |
"summary": "New creates a new oAuth2 application with the given settings.", | |
"operationId": "New", | |
"responses": { | |
"200": { | |
"description": "", | |
"schema": { | |
"$ref": "#/definitions/dblogApplication" | |
} | |
} | |
}, | |
"tags": [ | |
"Applications" | |
] | |
} | |
}, | |
"/api/v1/blogs/create": { | |
"post": { | |
"summary": "Create lets a user create a new blog.", | |
"operationId": "Create", | |
"responses": { | |
"200": { | |
"description": "", | |
"schema": { | |
"$ref": "#/definitions/dblogBlogInfo" | |
} | |
} | |
}, | |
"tags": [ | |
"Blogs" | |
] | |
} | |
}, | |
"/api/v1/blogs/{id}": { | |
"delete": { | |
"summary": "Delete lets a user destroy a blog and all it's related content.", | |
"operationId": "Delete", | |
"responses": { | |
"200": { | |
"description": "", | |
"schema": { | |
"$ref": "#/definitions/protobufEmpty" | |
} | |
} | |
}, | |
"parameters": [ | |
{ | |
"name": "id", | |
"in": "path", | |
"required": true, | |
"type": "string" | |
} | |
], | |
"tags": [ | |
"Blogs" | |
] | |
}, | |
"patch": { | |
"summary": "Update lets a user update a blog.", | |
"operationId": "Update", | |
"responses": { | |
"200": { | |
"description": "", | |
"schema": { | |
"$ref": "#/definitions/dblogBlogInfo" | |
} | |
} | |
}, | |
"parameters": [ | |
{ | |
"name": "id", | |
"in": "path", | |
"required": true, | |
"type": "string" | |
} | |
], | |
"tags": [ | |
"Blogs" | |
] | |
} | |
}, | |
"/api/v1/feeds": { | |
"get": { | |
"summary": "List lists all of the feeds that a user has created.", | |
"operationId": "List", | |
"responses": { | |
"200": { | |
"description": "", | |
"schema": { | |
"$ref": "#/definitions/dblogFeedList" | |
} | |
} | |
}, | |
"tags": [ | |
"Feeds" | |
] | |
}, | |
"post": { | |
"summary": "New allows a user to create a new Feed.", | |
"operationId": "New", | |
"responses": { | |
"200": { | |
"description": "", | |
"schema": { | |
"$ref": "#/definitions/dblogFeedInfo" | |
} | |
} | |
}, | |
"tags": [ | |
"Feeds" | |
] | |
} | |
}, | |
"/api/v1/feeds/{id}": { | |
"get": { | |
"summary": "Fetch lets a user fetch a historical backlog of feed items, optionally\npaginated by the last ID loaded by the client.", | |
"operationId": "Fetch", | |
"responses": { | |
"200": { | |
"description": "", | |
"schema": { | |
"$ref": "#/definitions/dblogFeed" | |
} | |
} | |
}, | |
"parameters": [ | |
{ | |
"name": "id", | |
"in": "path", | |
"required": true, | |
"type": "string" | |
}, | |
{ | |
"name": "last_id", | |
"in": "query", | |
"required": false, | |
"type": "string" | |
}, | |
{ | |
"name": "number_of_posts", | |
"in": "query", | |
"required": false, | |
"type": "integer", | |
"format": "int32" | |
} | |
], | |
"tags": [ | |
"Feeds" | |
] | |
}, | |
"delete": { | |
"summary": "Delete lets a user destroy a feed.", | |
"operationId": "Delete", | |
"responses": { | |
"200": { | |
"description": "", | |
"schema": { | |
"$ref": "#/definitions/protobufEmpty" | |
} | |
} | |
}, | |
"parameters": [ | |
{ | |
"name": "id", | |
"in": "path", | |
"required": true, | |
"type": "string" | |
} | |
], | |
"tags": [ | |
"Feeds" | |
] | |
}, | |
"patch": { | |
"summary": "Update lets a user update a feed, allowing them to change the filtering\nrules or other settings.", | |
"operationId": "Update", | |
"responses": { | |
"200": { | |
"description": "", | |
"schema": { | |
"$ref": "#/definitions/dblogFeedInfo" | |
} | |
} | |
}, | |
"parameters": [ | |
{ | |
"name": "id", | |
"in": "path", | |
"required": true, | |
"type": "string" | |
} | |
], | |
"tags": [ | |
"Feeds" | |
] | |
} | |
}, | |
"/api/v1/posts": { | |
"get": { | |
"summary": "List lists a subset of the posts that a user has created.", | |
"operationId": "List", | |
"responses": { | |
"200": { | |
"description": "", | |
"schema": { | |
"$ref": "#/definitions/dblogPostList" | |
} | |
} | |
}, | |
"parameters": [ | |
{ | |
"name": "last_id", | |
"in": "query", | |
"required": false, | |
"type": "string" | |
}, | |
{ | |
"name": "number_of_posts", | |
"in": "query", | |
"required": false, | |
"type": "integer", | |
"format": "int32" | |
} | |
], | |
"tags": [ | |
"Posts" | |
] | |
} | |
}, | |
"/api/v1/posts/new": { | |
"post": { | |
"summary": "New lets a user create a new blogpost.", | |
"operationId": "New", | |
"responses": { | |
"200": { | |
"description": "", | |
"schema": { | |
"$ref": "#/definitions/dblogPost" | |
} | |
} | |
}, | |
"tags": [ | |
"Posts" | |
] | |
} | |
}, | |
"/api/v1/posts/{id}": { | |
"delete": { | |
"summary": "Delete lets a user remove a blogpost.", | |
"operationId": "Delete", | |
"responses": { | |
"200": { | |
"description": "", | |
"schema": { | |
"$ref": "#/definitions/protobufEmpty" | |
} | |
} | |
}, | |
"parameters": [ | |
{ | |
"name": "id", | |
"in": "path", | |
"required": true, | |
"type": "string" | |
} | |
], | |
"tags": [ | |
"Posts" | |
] | |
}, | |
"patch": { | |
"summary": "Update allows a user to edit a post.", | |
"operationId": "Update", | |
"responses": { | |
"200": { | |
"description": "", | |
"schema": { | |
"$ref": "#/definitions/dblogPost" | |
} | |
} | |
}, | |
"parameters": [ | |
{ | |
"name": "id", | |
"in": "path", | |
"required": true, | |
"type": "string" | |
} | |
], | |
"tags": [ | |
"Posts" | |
] | |
} | |
}, | |
"/api/v1/posts/{id}/reblog": { | |
"post": { | |
"summary": "Reblog lets a user copy a blogpost into their blog (with attribution) and\noptionally reply to the content.", | |
"operationId": "Reblog", | |
"responses": { | |
"200": { | |
"description": "", | |
"schema": { | |
"$ref": "#/definitions/dblogPost" | |
} | |
} | |
}, | |
"parameters": [ | |
{ | |
"name": "id", | |
"in": "path", | |
"required": true, | |
"type": "string" | |
} | |
], | |
"tags": [ | |
"Posts" | |
] | |
} | |
}, | |
"/api/v1/users/follow": { | |
"post": { | |
"summary": "Follow allows a user to follow a given blog by ID.", | |
"operationId": "Follow", | |
"responses": { | |
"200": { | |
"description": "", | |
"schema": { | |
"$ref": "#/definitions/protobufEmpty" | |
} | |
} | |
}, | |
"tags": [ | |
"Users" | |
] | |
} | |
}, | |
"/api/v1/users/login": { | |
"post": { | |
"summary": "Login authenticates a given user using an application secret and credentials.", | |
"operationId": "Login", | |
"responses": { | |
"200": { | |
"description": "", | |
"schema": { | |
"$ref": "#/definitions/dblogUserSession" | |
} | |
} | |
}, | |
"tags": [ | |
"Users" | |
] | |
} | |
}, | |
"/api/v1/users/logout": { | |
"post": { | |
"summary": "Logout destroys a given UserSession.", | |
"operationId": "Logout", | |
"responses": { | |
"200": { | |
"description": "", | |
"schema": { | |
"$ref": "#/definitions/protobufEmpty" | |
} | |
} | |
}, | |
"tags": [ | |
"Users" | |
] | |
} | |
}, | |
"/api/v1/users/register": { | |
"post": { | |
"summary": "Register creates a new user account and returns a session token.", | |
"operationId": "Register", | |
"responses": { | |
"200": { | |
"description": "", | |
"schema": { | |
"$ref": "#/definitions/dblogUserSession" | |
} | |
} | |
}, | |
"tags": [ | |
"Users" | |
] | |
} | |
}, | |
"/api/v1/users/unfollow": { | |
"post": { | |
"summary": "Unfollow allows a user to stop folowing a given blog by ID.", | |
"operationId": "Unfollow", | |
"responses": { | |
"200": { | |
"description": "", | |
"schema": { | |
"$ref": "#/definitions/protobufEmpty" | |
} | |
} | |
}, | |
"tags": [ | |
"Users" | |
] | |
} | |
}, | |
"/api/v1/users/{id}": { | |
"get": { | |
"summary": "GetInfo retrieves user information.", | |
"operationId": "GetInfo", | |
"responses": { | |
"200": { | |
"description": "", | |
"schema": { | |
"$ref": "#/definitions/dblogUserInfo" | |
} | |
} | |
}, | |
"parameters": [ | |
{ | |
"name": "id", | |
"in": "path", | |
"required": true, | |
"type": "string" | |
} | |
], | |
"tags": [ | |
"Users" | |
] | |
}, | |
"patch": { | |
"summary": "UpdateInfo updates user information.", | |
"operationId": "UpdateInfo", | |
"responses": { | |
"200": { | |
"description": "", | |
"schema": { | |
"$ref": "#/definitions/dblogUserInfo" | |
} | |
} | |
}, | |
"parameters": [ | |
{ | |
"name": "id", | |
"in": "path", | |
"required": true, | |
"type": "string" | |
} | |
], | |
"tags": [ | |
"Users" | |
] | |
} | |
} | |
}, | |
"definitions": { | |
"dblogApplication": { | |
"type": "object", | |
"properties": { | |
"id": { | |
"type": "string" | |
}, | |
"name": { | |
"type": "string" | |
}, | |
"redirect_url": { | |
"type": "string" | |
}, | |
"display_name": { | |
"type": "string" | |
}, | |
"icon_url": { | |
"type": "string" | |
}, | |
"client_id": { | |
"type": "string" | |
}, | |
"secret_token": { | |
"type": "string" | |
} | |
}, | |
"description": "Application is an oAuth2 application." | |
}, | |
"dblogBlogInfo": { | |
"type": "object", | |
"properties": { | |
"id": { | |
"type": "string" | |
}, | |
"name": { | |
"type": "string" | |
}, | |
"avatar": { | |
"type": "string" | |
}, | |
"description": { | |
"type": "string" | |
}, | |
"domain": { | |
"type": "array", | |
"items": { | |
"type": "string" | |
} | |
}, | |
"private": { | |
"type": "boolean", | |
"format": "boolean" | |
}, | |
"password": { | |
"type": "string" | |
}, | |
"created_at": { | |
"type": "string" | |
}, | |
"updated_at": { | |
"type": "string" | |
}, | |
"nsfw": { | |
"type": "boolean", | |
"format": "boolean" | |
} | |
} | |
}, | |
"dblogCreateBlogRequest": { | |
"type": "object", | |
"properties": { | |
"name": { | |
"type": "string" | |
}, | |
"avatar": { | |
"type": "string" | |
}, | |
"description": { | |
"type": "string" | |
}, | |
"domain": { | |
"type": "string" | |
}, | |
"private": { | |
"type": "boolean", | |
"format": "boolean" | |
}, | |
"password": { | |
"type": "string" | |
} | |
} | |
}, | |
"dblogCriteria": { | |
"type": "string", | |
"enum": [ | |
"TAG", | |
"KEYWORD", | |
"USER_BIO", | |
"USER_ID", | |
"CONTENT_WARNING", | |
"NSFW", | |
"BLOG_ID", | |
"HOMESERVER" | |
], | |
"default": "TAG" | |
}, | |
"dblogDeleteBlogRequest": { | |
"type": "object", | |
"properties": { | |
"id": { | |
"type": "string" | |
}, | |
"confirm_name": { | |
"type": "string" | |
} | |
} | |
}, | |
"dblogDeleteFeedRequest": { | |
"type": "object", | |
"properties": { | |
"id": { | |
"type": "string" | |
} | |
} | |
}, | |
"dblogDeletePostRequest": { | |
"type": "object", | |
"properties": { | |
"id": { | |
"type": "string" | |
} | |
} | |
}, | |
"dblogFeed": { | |
"type": "object", | |
"properties": { | |
"id": { | |
"type": "string" | |
}, | |
"name": { | |
"type": "string" | |
}, | |
"url_name": { | |
"type": "string" | |
}, | |
"posts": { | |
"type": "array", | |
"items": { | |
"$ref": "#/definitions/dblogPost" | |
} | |
} | |
} | |
}, | |
"dblogFeedInfo": { | |
"type": "object", | |
"properties": { | |
"id": { | |
"type": "string" | |
}, | |
"name": { | |
"type": "string" | |
}, | |
"url_name": { | |
"type": "string" | |
}, | |
"description": { | |
"type": "string" | |
}, | |
"filters": { | |
"type": "array", | |
"items": { | |
"$ref": "#/definitions/dblogFilter" | |
} | |
}, | |
"visibility": { | |
"$ref": "#/definitions/dblogVisibility" | |
} | |
} | |
}, | |
"dblogFeedList": { | |
"type": "object", | |
"properties": { | |
"feed_info": { | |
"type": "array", | |
"items": { | |
"$ref": "#/definitions/dblogFeedInfo" | |
} | |
} | |
} | |
}, | |
"dblogFetchFeedRequest": { | |
"type": "object", | |
"properties": { | |
"id": { | |
"type": "string" | |
}, | |
"last_id": { | |
"type": "string" | |
}, | |
"number_of_posts": { | |
"type": "integer", | |
"format": "int32" | |
} | |
} | |
}, | |
"dblogFilter": { | |
"type": "object", | |
"properties": { | |
"display": { | |
"type": "boolean", | |
"format": "boolean" | |
}, | |
"criteria": { | |
"$ref": "#/definitions/dblogCriteria" | |
}, | |
"terms": { | |
"type": "array", | |
"items": { | |
"type": "string" | |
} | |
} | |
} | |
}, | |
"dblogFollowRequest": { | |
"type": "object", | |
"properties": { | |
"blog_id": { | |
"type": "string" | |
} | |
}, | |
"description": "FollowRequest is used when a user is subscribing to a blog." | |
}, | |
"dblogGetInfoRequest": { | |
"type": "object", | |
"properties": { | |
"id": { | |
"type": "string" | |
} | |
}, | |
"description": "GetInfoRequest lets a user query information about a given user by ID." | |
}, | |
"dblogLoginRequest": { | |
"type": "object", | |
"properties": { | |
"client_id": { | |
"type": "string" | |
}, | |
"secret_token": { | |
"type": "string" | |
}, | |
"email": { | |
"type": "string" | |
}, | |
"password": { | |
"type": "string" | |
}, | |
"two_factor_value": { | |
"type": "string" | |
} | |
}, | |
"description": "LoginRequest contains information for a user logging in to an existing user\naccount." | |
}, | |
"dblogNewAppRequest": { | |
"type": "object", | |
"properties": { | |
"email": { | |
"type": "string" | |
}, | |
"redirect_url": { | |
"type": "string" | |
}, | |
"name": { | |
"type": "string" | |
}, | |
"display_name": { | |
"type": "string" | |
}, | |
"icon_url": { | |
"type": "string" | |
} | |
}, | |
"description": "NewAppRequest contains parameters for a new oAuth2 application." | |
}, | |
"dblogNewFeedRequest": { | |
"type": "object", | |
"properties": { | |
"name": { | |
"type": "string" | |
}, | |
"description": { | |
"type": "string" | |
}, | |
"filters": { | |
"type": "array", | |
"items": { | |
"$ref": "#/definitions/dblogFilter" | |
} | |
}, | |
"visibility": { | |
"$ref": "#/definitions/dblogVisibility" | |
} | |
} | |
}, | |
"dblogNewPostRequest": { | |
"type": "object", | |
"properties": { | |
"blog_id": { | |
"type": "string" | |
}, | |
"in_reply_to": { | |
"type": "string" | |
}, | |
"title": { | |
"type": "string" | |
}, | |
"body": { | |
"type": "string" | |
}, | |
"type": { | |
"$ref": "#/definitions/dblogPostType" | |
}, | |
"attachments": { | |
"type": "array", | |
"items": { | |
"type": "string" | |
} | |
}, | |
"tags": { | |
"type": "array", | |
"items": { | |
"type": "string" | |
} | |
}, | |
"content_warning": { | |
"type": "string" | |
}, | |
"visibility": { | |
"$ref": "#/definitions/dblogVisibility" | |
}, | |
"nsfw": { | |
"type": "boolean", | |
"format": "boolean" | |
}, | |
"callout": { | |
"type": "string" | |
}, | |
"pseudonym": { | |
"type": "string" | |
}, | |
"metadata": { | |
"type": "object", | |
"additionalProperties": { | |
"type": "string" | |
} | |
} | |
} | |
}, | |
"dblogPost": { | |
"type": "object", | |
"properties": { | |
"id": { | |
"type": "string" | |
}, | |
"blog_id": { | |
"type": "string" | |
}, | |
"permalink": { | |
"type": "string" | |
}, | |
"title": { | |
"type": "string" | |
}, | |
"body": { | |
"type": "string" | |
}, | |
"type": { | |
"$ref": "#/definitions/dblogPostType" | |
}, | |
"attachments": { | |
"type": "array", | |
"items": { | |
"type": "string" | |
} | |
}, | |
"tags": { | |
"type": "array", | |
"items": { | |
"type": "string" | |
} | |
}, | |
"created_at": { | |
"type": "string" | |
}, | |
"updated_at": { | |
"type": "string" | |
}, | |
"reblog_users": { | |
"type": "array", | |
"items": { | |
"type": "string" | |
} | |
}, | |
"favorited_users": { | |
"type": "array", | |
"items": { | |
"type": "string" | |
} | |
}, | |
"content_warning": { | |
"type": "string" | |
}, | |
"visibility": { | |
"$ref": "#/definitions/dblogVisibility" | |
}, | |
"nsfw": { | |
"type": "boolean", | |
"format": "boolean" | |
}, | |
"callout": { | |
"type": "string" | |
}, | |
"pseudonym": { | |
"type": "string" | |
}, | |
"author_id": { | |
"type": "string" | |
}, | |
"metadata": { | |
"type": "object", | |
"additionalProperties": { | |
"type": "string" | |
} | |
} | |
} | |
}, | |
"dblogPostList": { | |
"type": "object", | |
"properties": { | |
"posts": { | |
"type": "array", | |
"items": { | |
"$ref": "#/definitions/dblogPost" | |
} | |
} | |
} | |
}, | |
"dblogPostListRequest": { | |
"type": "object", | |
"properties": { | |
"last_id": { | |
"type": "string" | |
}, | |
"number_of_posts": { | |
"type": "integer", | |
"format": "int32" | |
} | |
} | |
}, | |
"dblogPostType": { | |
"type": "string", | |
"enum": [ | |
"BASIC", | |
"MARKDOWN", | |
"CONVERSATION" | |
], | |
"default": "BASIC" | |
}, | |
"dblogReblogPostRequest": { | |
"type": "object", | |
"properties": { | |
"id": { | |
"type": "string" | |
}, | |
"blog_id": { | |
"type": "string" | |
} | |
} | |
}, | |
"dblogRegisterRequest": { | |
"type": "object", | |
"properties": { | |
"client_id": { | |
"type": "string" | |
}, | |
"secret_token": { | |
"type": "string" | |
}, | |
"email": { | |
"type": "string" | |
}, | |
"password": { | |
"type": "string" | |
}, | |
"two_factor_name": { | |
"type": "string" | |
}, | |
"two_factor_value": { | |
"type": "string" | |
} | |
}, | |
"description": "RegisterRequest contains information for a user registering a new user account." | |
}, | |
"dblogUpdateBlogRequest": { | |
"type": "object", | |
"properties": { | |
"id": { | |
"type": "string" | |
}, | |
"name": { | |
"type": "string" | |
}, | |
"avatar": { | |
"type": "string" | |
}, | |
"description": { | |
"type": "string" | |
}, | |
"domain": { | |
"type": "array", | |
"items": { | |
"type": "string" | |
} | |
}, | |
"private": { | |
"type": "boolean", | |
"format": "boolean" | |
}, | |
"password": { | |
"type": "string" | |
}, | |
"nsfw": { | |
"type": "boolean", | |
"format": "boolean" | |
} | |
} | |
}, | |
"dblogUpdateFeedRequest": { | |
"type": "object", | |
"properties": { | |
"id": { | |
"type": "string" | |
}, | |
"name": { | |
"type": "string" | |
}, | |
"url_name": { | |
"type": "string" | |
}, | |
"description": { | |
"type": "string" | |
}, | |
"filters": { | |
"type": "array", | |
"items": { | |
"$ref": "#/definitions/dblogFilter" | |
} | |
}, | |
"visibility": { | |
"$ref": "#/definitions/dblogVisibility" | |
} | |
} | |
}, | |
"dblogUpdateInfoRequest": { | |
"type": "object", | |
"properties": { | |
"id": { | |
"type": "string" | |
}, | |
"name": { | |
"type": "string" | |
}, | |
"avatar": { | |
"type": "string" | |
}, | |
"bio": { | |
"type": "string" | |
}, | |
"metadata": { | |
"type": "object", | |
"additionalProperties": { | |
"type": "string" | |
} | |
} | |
}, | |
"description": "UpdateInfoRequest is used when a user is updating their information." | |
}, | |
"dblogUpdatePostRequest": { | |
"type": "object", | |
"properties": { | |
"id": { | |
"type": "string" | |
}, | |
"title": { | |
"type": "string" | |
}, | |
"body": { | |
"type": "string" | |
}, | |
"attachments": { | |
"type": "array", | |
"items": { | |
"type": "string" | |
} | |
}, | |
"tags": { | |
"type": "array", | |
"items": { | |
"type": "string" | |
} | |
}, | |
"content_warning": { | |
"type": "string" | |
}, | |
"nsfw": { | |
"type": "boolean", | |
"format": "boolean" | |
}, | |
"callout": { | |
"type": "string" | |
}, | |
"metadata": { | |
"type": "object", | |
"additionalProperties": { | |
"type": "string" | |
} | |
} | |
} | |
}, | |
"dblogUserInfo": { | |
"type": "object", | |
"properties": { | |
"id": { | |
"type": "string" | |
}, | |
"name": { | |
"type": "string" | |
}, | |
"avatar": { | |
"type": "string" | |
}, | |
"bio": { | |
"type": "string" | |
}, | |
"blogs": { | |
"type": "array", | |
"items": { | |
"$ref": "#/definitions/dblogBlogInfo" | |
} | |
}, | |
"metadata": { | |
"type": "object", | |
"additionalProperties": { | |
"type": "string" | |
} | |
} | |
}, | |
"description": "UserInfo has basic information about a user and the list of their blogs." | |
}, | |
"dblogUserSession": { | |
"type": "object", | |
"properties": { | |
"session_key": { | |
"type": "string" | |
}, | |
"user_info": { | |
"$ref": "#/definitions/dblogUserInfo" | |
} | |
}, | |
"description": "UserSession contains a session key and information about the user account\nthat was just created or logged into." | |
}, | |
"dblogVisibility": { | |
"type": "string", | |
"enum": [ | |
"PUBLIC", | |
"FOLLOWERS_ONLY", | |
"SERVER_LOCAL", | |
"JUST_ME" | |
], | |
"default": "PUBLIC" | |
}, | |
"protobufEmpty": { | |
"type": "object", | |
"description": "service Foo {\n rpc Bar(google.protobuf.Empty) returns (google.protobuf.Empty);\n }\n\nThe JSON representation for `Empty` is empty JSON object `{}`.", | |
"title": "A generic empty message that you can re-use to avoid defining duplicated\nempty messages in your APIs. A typical example is to use it as the request\nor the response type of an API method. For instance:" | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment