Documentation ¶
Overview ¶
This is a lightweight Redmine API client.
It doesn't do a lot of things, you might probably only be interested in the scrolling feature Scroll.
Index ¶
- Constants
- Variables
- func ApiEndpointURL[E Entities](ac *ApiConfig, page int) (u string, err error)
- func BuildApiUrl(base, endpoint string, v *url.Values, p int) (string, error)
- func Scroll[E Entities](ac *ApiConfig) (<-chan E, <-chan error)
- type ApiConfig
- type ApiResponse
- type Date
- type Entities
- type Issue
- type Pagination
- type Project
- type TimeEntriesFilter
- type TimeEntry
- type User
Constants ¶
const ( ProjectsApiEndpoint = "/projects.json" IssuesApiEndpoint = "/issues.json" TimeEntriesEndpoint = "/time_entries.json" )
Variables ¶
var ( JsonDecodeError = errors.New("JSON decode error") IoReadError = errors.New("io.ReadAll error") UrlJoinPathError = errors.New("url.JoinPath error") UrlParseError = errors.New("url.Parse error") ApiEndpointUrlFatalError = errors.New("cannot build API endpoint url") ApiNewRequestFatalError = errors.New("cannot create a new request with given url") HttpError = errors.New("http error") )
There are some custom error types, from low level to high level errors which are aggregates of first ones.
Typically you should be expect only these high level errors in errChan:
- JsonDecodeError: errors related to unmarshaling redmine server response
- IoReadError: errors related to read input
- HttpError: errors related to network layer
- ApiEndpointUrlFatalError: fatal errors that means that most probably the url of redmine api is malformed or bogus, please check it
- ApiNewRequestFatalError: actually will not be thrown (see the comments in code)
Functions ¶
func ApiEndpointURL ¶
Construct the final URL for http requests depending on redmine entities (projects, issues or time entries) and pagination, filtration.
func BuildApiUrl ¶
Add pagination query string to URL.
func Scroll ¶
Scroll over Redmine API paginated responses. It going through all available data, so it may generate a lot of http requests (depending on a size of data and pagination limit).
The pagination of redmine is based on offset&limit, but in URL you may use query string param ?page=, e.g. for 53 issues and limit=25 it will be three requests:
- 0 25 53 - [0, 25] /issues.json?page=1 or omitted page number: /issues.json
- 25 25 53 - [25, 50] /issues.json?page=2
- 50 25 53 - [50, 53] /issues.json?page=3
This function do this automatically and send all the data to channel, if any error occurs, it will be send to the second, errors channel.
Types ¶
type ApiConfig ¶
type ApiConfig struct { Url string Token string LogEnabled bool TimeEntriesFilter }
Config of Redmine REST API client: url, token, logging and time entries filtration.
type ApiResponse ¶
type ApiResponse[E Entities] struct { Items []E Pagination }
Redmine API items response container.
func DecodeResp ¶
func DecodeResp[E Entities](body io.ReadCloser) (*ApiResponse[E], error)
Decode JSON Redmine API response to package types.
type Date ¶
A date type is needed for proper parsing (unmarshaling) of redmine date format used in JSON.
func (*Date) UnmarshalJSON ¶
Unmarshaling redmine dates.
type Entities ¶
Data type constraint, a quick glance at which will let you know the supported data types for fetching from redmine server.
type Issue ¶
type Issue struct { Id int `json:"id"` Subject string `json:"subject"` Desc string `json:"description"` Project `json:"project"` }
A Redmine issue entity.
type Pagination ¶
type Project ¶
type Project struct { Id int `json:"id"` Name string `json:"name"` Ident string `json:"identifier"` Desc string `json:"description"` // TODO correct parsing date time // CreatedOn time.Time `json:"created_on"` // UpdatedOn time.Time `json:"updated_on"` IsPublic bool `json:"is_public"` }
A Redmine project entity.
type TimeEntriesFilter ¶
Time Entries filtration by range of dates and user id.