Skip to content

Commit

Permalink
Prepare for v0.1.0 release (#43)
Browse files Browse the repository at this point in the history
The `client.New()` now takes just the outline api server URL and creates
base path internally freeing user from the burden of crafting proper
base path.

The change is also reflected in the `cli` where we also simplify global
flags to `--server` and `--key`.

Update README accordingly.
  • Loading branch information
rsjethani committed Aug 12, 2023
1 parent 66a32e6 commit e73af9c
Show file tree
Hide file tree
Showing 5 changed files with 44 additions and 47 deletions.
10 changes: 4 additions & 6 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ Go client and cli for [outline](https://www.getoutline.com/).
### Create a client

```go
cl := outline.New("https://base.url/api", &http.Client{}, "api key")
cl := outline.New("https://server.url", &http.Client{}, "api key")
```

> **Note**: You can create a new API key in your outline **account settings**.
Expand Down Expand Up @@ -89,11 +89,9 @@ go build -o outline ./cli

### Required flags

Any command requires the flags `baseUrl` and `apiKey`.
You can simply add them with `--baseUrl https://base.Url/api`
and `--apiKey sup3rS3cre7Ap1K3Y`.

> **Note**: The `baseUrl` is the URL to your outline instance, followed by `/api`.
Any command requires the flags `server` and `key`.
You can simply add them with `--server https://server.url`
and `--key sup3rS3cre7Ap1K3Y`.

### Collections

Expand Down
11 changes: 3 additions & 8 deletions client.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@ package outline

import (
"net/http"
"strings"

"github.com/dghubble/sling"
"github.com/ioki-mobility/go-outline/internal/common"
Expand All @@ -17,13 +16,9 @@ type Client struct {
base *sling.Sling
}

// New creates and returns a new per server client.
func New(baseURL string, hc *http.Client, apiKey string) *Client {
if !strings.HasSuffix(baseURL, "/") {
baseURL = baseURL + "/"
}

sl := sling.New().Client(hc).Base(baseURL)
// New creates and returns a new (per server) client.
func New(serverURL string, hc *http.Client, apiKey string) *Client {
sl := sling.New().Client(hc).Base(common.BaseURL(serverURL))
sl.Set(common.HdrKeyAuthorization, common.HdrValueAuthorization(apiKey))
sl.Set(common.HdrKeyContentType, common.HdrValueContentType)
sl.Set(common.HdrKeyAccept, common.HdrValueAccept)
Expand Down
36 changes: 18 additions & 18 deletions internal/cli/cli.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,8 @@ import (
)

const (
flagNameBaseUrl = "baseUrl"
flagNameApiKey = "apiKey"
flagServerURL = "server"
flagApiKey = "key"
)

func Run() error {
Expand All @@ -26,10 +26,10 @@ func Run() error {
func rootCmd() *cobra.Command {
rootCmd := &cobra.Command{Use: "outline"}

var apiKeyFlag string
var baseUrlFlag string
rootCmd.PersistentFlags().StringVar(&baseUrlFlag, flagNameBaseUrl, "", "The base url to the outline API instance (should include /api/ as suffix)")
rootCmd.PersistentFlags().StringVar(&apiKeyFlag, flagNameApiKey, "", "The outline apiKey")
var apiKey string
var serverURL string
rootCmd.PersistentFlags().StringVar(&serverURL, flagServerURL, "", "The outline API server url")
rootCmd.PersistentFlags().StringVar(&apiKey, flagApiKey, "", "The outline api key")

return rootCmd
}
Expand Down Expand Up @@ -61,13 +61,13 @@ func collectionCmdDocs(rootCmd *cobra.Command) *cobra.Command {
Long: "Get a summary of associated documents (and children)",
Args: cobra.MinimumNArgs(1),
RunE: func(cmd *cobra.Command, args []string) error {
baseUrl, err := rootCmd.Flags().GetString(flagNameBaseUrl)
baseUrl, err := rootCmd.Flags().GetString(flagServerURL)
if err != nil {
return fmt.Errorf("required flag '%s' not set: %w", flagNameBaseUrl, err)
return fmt.Errorf("required flag '%s' not set: %w", flagServerURL, err)
}
apiKey, err := rootCmd.Flags().GetString(flagNameApiKey)
apiKey, err := rootCmd.Flags().GetString(flagApiKey)
if err != nil {
return fmt.Errorf("required flag '%s' not set: %w", flagNameApiKey, err)
return fmt.Errorf("required flag '%s' not set: %w", flagApiKey, err)
}

client := outline.New(baseUrl, &http.Client{}, apiKey)
Expand Down Expand Up @@ -95,13 +95,13 @@ func collectionCmdInfo(rootCmd *cobra.Command) *cobra.Command {
Long: "Get information about the collection",
Args: cobra.MinimumNArgs(1),
RunE: func(cmd *cobra.Command, args []string) error {
baseUrl, err := rootCmd.Flags().GetString(flagNameBaseUrl)
baseUrl, err := rootCmd.Flags().GetString(flagServerURL)
if err != nil {
return fmt.Errorf("required flag '%s' not set: %w", flagNameBaseUrl, err)
return fmt.Errorf("required flag '%s' not set: %w", flagServerURL, err)
}
apiKey, err := rootCmd.Flags().GetString(flagNameApiKey)
apiKey, err := rootCmd.Flags().GetString(flagApiKey)
if err != nil {
return fmt.Errorf("required flag '%s' not set: %w", flagNameApiKey, err)
return fmt.Errorf("required flag '%s' not set: %w", flagApiKey, err)
}

client := outline.New(baseUrl, &http.Client{}, apiKey)
Expand Down Expand Up @@ -129,13 +129,13 @@ func collectionCmdCreate(rootCmd *cobra.Command) *cobra.Command {
Long: "Creates a collection with the given name and prints the result as json to stdout",
Args: cobra.MinimumNArgs(1),
RunE: func(cmd *cobra.Command, args []string) error {
baseUrl, err := rootCmd.Flags().GetString(flagNameBaseUrl)
baseUrl, err := rootCmd.Flags().GetString(flagServerURL)
if err != nil {
return fmt.Errorf("required flag '%s' not set: %w", flagNameBaseUrl, err)
return fmt.Errorf("required flag '%s' not set: %w", flagServerURL, err)
}
apiKey, err := rootCmd.Flags().GetString(flagNameApiKey)
apiKey, err := rootCmd.Flags().GetString(flagApiKey)
if err != nil {
return fmt.Errorf("required flag '%s' not set: %w", flagNameApiKey, err)
return fmt.Errorf("required flag '%s' not set: %w", flagApiKey, err)
}

client := outline.New(baseUrl, &http.Client{}, apiKey)
Expand Down
4 changes: 4 additions & 0 deletions internal/common/common.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,10 @@ func HdrValueAuthorization(key string) string {
return "Bearer " + key
}

func BaseURL(server string) string {
return server + "/api/"
}

func CollectionsStructureEndpoint() string {
return "collections.documents"
}
Expand Down
30 changes: 15 additions & 15 deletions package_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,8 +21,8 @@ import (
)

const (
testApiKey string = "api key"
testBaseURL string = "https://localhost.123"
testApiKey string = "api key"
testServerURL string = "https://localhost.123"
)

func TestClientCollectionsStructure_failed(t *testing.T) {
Expand Down Expand Up @@ -70,7 +70,7 @@ func TestClientCollectionsStructure_failed(t *testing.T) {
t.Run(name, func(t *testing.T) {
hc := &http.Client{}
hc.Transport = test.rt
cl := outline.New(testBaseURL, hc, testApiKey)
cl := outline.New(testServerURL, hc, testApiKey)
col, err := cl.Collections().DocumentStructure("collection id").Do(context.Background())
assert.Nil(t, col)
require.NotNil(t, err)
Expand All @@ -87,7 +87,7 @@ func TestClientCollectionsStructure(t *testing.T) {
hc.Transport = &testutils.MockRoundTripper{RoundTripFn: func(r *http.Request) (*http.Response, error) {
// Assert request method and URL.
assert.Equal(t, http.MethodPost, r.Method)
u, err := url.JoinPath(testBaseURL, common.CollectionsStructureEndpoint())
u, err := url.JoinPath(common.BaseURL(testServerURL), common.CollectionsStructureEndpoint())
require.NoError(t, err)
assert.Equal(t, u, r.URL.String())

Expand All @@ -102,7 +102,7 @@ func TestClientCollectionsStructure(t *testing.T) {
}, nil
}}

cl := outline.New(testBaseURL, hc, testApiKey)
cl := outline.New(testServerURL, hc, testApiKey)
got, err := cl.Collections().DocumentStructure("collection id").Do(context.Background())
require.NoError(t, err)

Expand Down Expand Up @@ -159,7 +159,7 @@ func TestClientCollectionsGet_failed(t *testing.T) {
t.Run(name, func(t *testing.T) {
hc := &http.Client{}
hc.Transport = test.rt
cl := outline.New(testBaseURL, hc, testApiKey)
cl := outline.New(testServerURL, hc, testApiKey)
col, err := cl.Collections().Get("collection id").Do(context.Background())
assert.Nil(t, col)
require.NotNil(t, err)
Expand All @@ -176,7 +176,7 @@ func TestClientCollectionsGet(t *testing.T) {
hc.Transport = &testutils.MockRoundTripper{RoundTripFn: func(r *http.Request) (*http.Response, error) {
// Assert request method and URL.
assert.Equal(t, http.MethodPost, r.Method)
u, err := url.JoinPath(testBaseURL, common.CollectionsGetEndpoint())
u, err := url.JoinPath(common.BaseURL(testServerURL), common.CollectionsGetEndpoint())
require.NoError(t, err)
assert.Equal(t, u, r.URL.String())

Expand All @@ -191,7 +191,7 @@ func TestClientCollectionsGet(t *testing.T) {
}, nil
}}

cl := outline.New(testBaseURL, hc, testApiKey)
cl := outline.New(testServerURL, hc, testApiKey)
got, err := cl.Collections().Get("collection id").Do(context.Background())
require.NoError(t, err)

Expand All @@ -214,7 +214,7 @@ func TestClientCollectionsList(t *testing.T) {

if requestCount.Load() == 1 {
// Assert URL when asking first page.
u, err := url.JoinPath(testBaseURL, common.CollectionsListEndpoint())
u, err := url.JoinPath(common.BaseURL(testServerURL), common.CollectionsListEndpoint())
require.NoError(t, err)
assert.Equal(t, u, r.URL.String())

Expand All @@ -228,7 +228,7 @@ func TestClientCollectionsList(t *testing.T) {

// Assert URL when asking second page (first page had 2 items).
// NOTE: There is some hard coding here but that is okay, no need to over-engineer as of now.
u, err := url.JoinPath(testBaseURL, common.CollectionsListEndpoint())
u, err := url.JoinPath(common.BaseURL(testServerURL), common.CollectionsListEndpoint())
require.NoError(t, err)
assert.Equal(t, u+"?offset=2", r.URL.String())

Expand All @@ -240,7 +240,7 @@ func TestClientCollectionsList(t *testing.T) {
}, nil
}}

cl := outline.New(testBaseURL, hc, testApiKey)
cl := outline.New(testServerURL, hc, testApiKey)

collectionsListFnCalled := atomic.Uint32{}
err := cl.Collections().List().Do(context.Background(), func(c *outline.Collection, err error) (bool, error) {
Expand All @@ -258,7 +258,7 @@ func TestClientCollectionsCreate(t *testing.T) {
hc.Transport = &testutils.MockRoundTripper{RoundTripFn: func(r *http.Request) (*http.Response, error) {
// Assert request method and URL.
assert.Equal(t, http.MethodPost, r.Method)
u, err := url.JoinPath(testBaseURL, common.CollectionsCreateEndpoint())
u, err := url.JoinPath(common.BaseURL(testServerURL), common.CollectionsCreateEndpoint())
require.NoError(t, err)
assert.Equal(t, u, r.URL.String())

Expand All @@ -273,7 +273,7 @@ func TestClientCollectionsCreate(t *testing.T) {
}, nil
}}

cl := outline.New(testBaseURL, hc, testApiKey)
cl := outline.New(testServerURL, hc, testApiKey)
got, err := cl.Collections().
Create("new collection").
PermissionRead().
Expand All @@ -297,7 +297,7 @@ func TestDocumentsClientCreate(t *testing.T) {
hc.Transport = &testutils.MockRoundTripper{RoundTripFn: func(r *http.Request) (*http.Response, error) {
// Assert request method and URL.
assert.Equal(t, http.MethodPost, r.Method)
u, err := url.JoinPath(testBaseURL, common.DocumentsCreateEndpoint())
u, err := url.JoinPath(common.BaseURL(testServerURL), common.DocumentsCreateEndpoint())
require.NoError(t, err)
assert.Equal(t, u, r.URL.String())

Expand All @@ -312,7 +312,7 @@ func TestDocumentsClientCreate(t *testing.T) {
}, nil
}}

cl := outline.New(testBaseURL, hc, testApiKey)
cl := outline.New(testServerURL, hc, testApiKey)
var collectionId outline.CollectionID = "collection id"
got, err := cl.Documents().Create("🎉 Welcome to Acme Inc", collectionId).Text("Some text").Publish(true).Do(context.Background())
require.NoError(t, err)
Expand Down

0 comments on commit e73af9c

Please sign in to comment.