-
Notifications
You must be signed in to change notification settings - Fork 106
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat: added vercel support for deployments + domains
- Loading branch information
1 parent
c8d29f7
commit eaad08d
Showing
4 changed files
with
457 additions
and
0 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
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,141 @@ | ||
package vercel | ||
|
||
import ( | ||
"bytes" | ||
"encoding/json" | ||
"fmt" | ||
"io" | ||
"net/http" | ||
"net/url" | ||
"time" | ||
|
||
"github.com/pkg/errors" | ||
) | ||
|
||
type vercelClient struct { | ||
config *newClientConfig | ||
url string | ||
httpClient *http.Client | ||
} | ||
|
||
type newClientConfig struct { | ||
Token string | ||
Teamid string | ||
} | ||
|
||
func newAPIClient(config newClientConfig) *vercelClient { | ||
return &vercelClient{ | ||
config: &config, | ||
url: "https://api.vercel.com", | ||
httpClient: &http.Client{ | ||
Transport: &http.Transport{}, | ||
Timeout: 60 * time.Second, | ||
}, | ||
} | ||
} | ||
|
||
type apiRequest struct { | ||
Method string | ||
Path string | ||
Body interface{} | ||
Query url.Values | ||
ResponseTarget interface{} | ||
} | ||
|
||
func newApiRequest(method string, path string, ResponseTarget interface{}) apiRequest { | ||
return apiRequest{ | ||
Method: method, | ||
Path: path, | ||
Body: nil, | ||
Query: url.Values{}, | ||
ResponseTarget: ResponseTarget, | ||
} | ||
} | ||
|
||
// Call the Vercel API and unmarshal its response directly | ||
func (c *vercelClient) Call(req apiRequest) error { | ||
path := req.Path | ||
query := req.Query.Encode() | ||
if query != "" { | ||
path = fmt.Sprintf("%s?%s", path, query) | ||
} | ||
|
||
httpResponse, err := c.request(req.Method, path, req.Body) | ||
if err != nil { | ||
return err | ||
} | ||
defer httpResponse.Body.Close() | ||
if req.ResponseTarget == nil { | ||
return nil | ||
} | ||
err = json.NewDecoder(httpResponse.Body).Decode(req.ResponseTarget) | ||
if err != nil { | ||
return errors.Wrap(err, "unable to decode response body") | ||
} | ||
return nil | ||
} | ||
|
||
// Perform a request and return its response | ||
func (c *vercelClient) request(method string, path string, body interface{}) (*http.Response, error) { | ||
payload, err := marshalBody(body) | ||
if err != nil { | ||
return nil, errors.Wrap(err, "unable to marshal request body") | ||
} | ||
req, err := http.NewRequest(method, fmt.Sprintf("%s%s", c.url, path), payload) | ||
if err != nil { | ||
return nil, errors.Wrap(err, "unable to create request") | ||
} | ||
req.Header.Set("User-Agent", "cloudlist-go") | ||
req.Header.Set("Content-Type", "application/json") | ||
req.Header.Set("Authorization", fmt.Sprintf("Bearer %s", c.config.Token)) | ||
|
||
res, err := c.httpClient.Do(req) | ||
if err != nil { | ||
return nil, errors.Wrap(err, "unable to perform request") | ||
} | ||
if res.StatusCode < 200 || res.StatusCode >= 300 { | ||
var responseBody map[string]interface{} | ||
err = json.NewDecoder(res.Body).Decode(&responseBody) | ||
if err != nil { | ||
return nil, fmt.Errorf("response returned status code %d, path: %s", res.StatusCode, path) | ||
} | ||
|
||
// Try to prettyprint the response body | ||
// If that is not possible we return the raw body | ||
pretty, err := json.MarshalIndent(responseBody, "", " ") | ||
if err != nil { | ||
return nil, fmt.Errorf("response returned status code %d: %+v, path: %s", res.StatusCode, responseBody, path) | ||
} | ||
return nil, fmt.Errorf("response returned status code %d: %+v, path: %s", res.StatusCode, string(pretty), path) | ||
} | ||
return res, nil | ||
|
||
} | ||
|
||
// JSON marshal the body if present | ||
func marshalBody(body interface{}) (io.Reader, error) { | ||
var payload io.Reader = nil | ||
if body != nil { | ||
b, err := json.Marshal(body) | ||
if err != nil { | ||
return nil, err | ||
} | ||
payload = bytes.NewBuffer(b) | ||
} | ||
return payload, nil | ||
} | ||
|
||
// Endpoints implementations below | ||
// ------------------------------ | ||
|
||
func (c *vercelClient) ListProjects(req ListProjectsRequest) (res ListProjectsResponse, err error) { | ||
apiRequest := newApiRequest("GET", "/v8/projects", &res) | ||
if c.config.Teamid != "" { | ||
apiRequest.Query.Add("teamId", c.config.Teamid) | ||
} | ||
err = c.Call(apiRequest) | ||
if err != nil { | ||
return ListProjectsResponse{}, fmt.Errorf("unable to fetch projects: %w", err) | ||
} | ||
return res, nil | ||
} |
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,206 @@ | ||
package vercel | ||
|
||
type ListProjectsRequest struct { | ||
// Limit the number of projects returned. | ||
// Required: No | ||
Limit int64 `json:"limit,omitempty"` | ||
|
||
// The updatedAt point64where the list should start. | ||
// Required: No | ||
Since int64 `json:"since,omitempty"` | ||
|
||
// The updatedAt point64where the list should end. | ||
// Required: No | ||
Until int64 `json:"until,omitempty"` | ||
|
||
// Search projects by the name field. | ||
// Required: No | ||
Search string `json:"string,omitempty"` | ||
} | ||
|
||
type ListProjectsResponse struct { | ||
Projects []Project `json:"projects"` | ||
} | ||
|
||
// Project houses all the information vercel offers about a project via their api | ||
type Project struct { | ||
Accountid string `json:"accountid"` | ||
Alias []struct { | ||
ConfiguredBy string `json:"configuredBy"` | ||
ConfiguredChangedAt int64 `json:"configuredChangedAt"` | ||
CreatedAt int64 `json:"createdAt"` | ||
Deployment struct { | ||
Alias []string `json:"alias"` | ||
AliasAssigned int64 `json:"aliasAssigned"` | ||
Builds []interface{} `json:"builds"` | ||
CreatedAt int64 `json:"createdAt"` | ||
CreatedIn string `json:"createdIn"` | ||
Creator struct { | ||
Uid string `json:"uid"` | ||
Email string `json:"email"` | ||
Username string `json:"username"` | ||
GithubLogin string `json:"githubLogin"` | ||
} `json:"creator"` | ||
DeploymentHostname string `json:"deploymentHostname"` | ||
Forced bool `json:"forced"` | ||
Id string `json:"id"` | ||
Meta struct { | ||
GithubCommitRef string `json:"githubCommitRef"` | ||
GithubRepo string `json:"githubRepo"` | ||
GithubOrg string `json:"githubOrg"` | ||
GithubCommitSha string `json:"githubCommitSha"` | ||
GithubRepoid string `json:"githubRepoid"` | ||
GithubCommitMessage string `json:"githubCommitMessage"` | ||
GithubCommitAuthorLogin string `json:"githubCommitAuthorLogin"` | ||
GithubDeployment string `json:"githubDeployment"` | ||
GithubCommitOrg string `json:"githubCommitOrg"` | ||
GithubCommitAuthorName string `json:"githubCommitAuthorName"` | ||
GithubCommitRepo string `json:"githubCommitRepo"` | ||
GithubCommitRepoid string `json:"githubCommitRepoid"` | ||
} `json:"meta"` | ||
Name string `json:"name"` | ||
Plan string `json:"plan"` | ||
Private bool `json:"private"` | ||
ReadyState string `json:"readyState"` | ||
Target string `json:"target"` | ||
Teamid string `json:"teamid"` | ||
Type string `json:"type"` | ||
URL string `json:"url"` | ||
Userid string `json:"userid"` | ||
WithCache bool `json:"withCache"` | ||
} `json:"deployment"` | ||
Domain string `json:"domain"` | ||
Environment string `json:"environment"` | ||
Target string `json:"target"` | ||
} `json:"alias"` | ||
Analytics struct { | ||
Id string `json:"id"` | ||
EnabledAt int64 `json:"enabledAt"` | ||
DisabledAt int64 `json:"disabledAt"` | ||
CanceledAt int64 `json:"canceledAt"` | ||
} `json:"analytics"` | ||
AutoExposeSystemEnvs bool `json:"autoExposeSystemEnvs"` | ||
BuildCommand string `json:"buildCommand"` | ||
CreatedAt int64 `json:"createdAt"` | ||
DevCommand string `json:"devCommand"` | ||
DirectoryListing bool `json:"directoryListing"` | ||
Env []struct { | ||
Type string `json:"type"` | ||
Id string `json:"id"` | ||
Key string `json:"key"` | ||
Value string `json:"value"` | ||
Target []string `json:"target"` | ||
Configurationid interface{} `json:"configurationid"` | ||
UpdatedAt int64 `json:"updatedAt"` | ||
CreatedAt int64 `json:"createdAt"` | ||
} `json:"env"` | ||
Framework string `json:"framework"` | ||
Id string `json:"id"` | ||
InstallCommand string `json:"installCommand"` | ||
Name string `json:"name"` | ||
NodeVersion string `json:"nodeVersion"` | ||
OutputDirectory string `json:"outputDirectory"` | ||
PublicSource bool `json:"publicSource"` | ||
RootDirectory string `json:"rootDirectory"` | ||
ServerlessFunctionRegion string `json:"serverlessFunctionRegion"` | ||
SourceFilesOutsideRootDirectory bool `json:"sourceFilesOutsideRootDirectory"` | ||
UpdatedAt int64 `json:"updatedAt"` | ||
Link struct { | ||
Type string `json:"type"` | ||
Repo string `json:"repo"` | ||
Repoid int64 `json:"repoid"` | ||
Org string `json:"org"` | ||
GitCredentialid string `json:"gitCredentialid"` | ||
CreatedAt int64 `json:"createdAt"` | ||
UpdatedAt int64 `json:"updatedAt"` | ||
Sourceless bool `json:"sourceless"` | ||
ProductionBranch string `json:"productionBranch"` | ||
DeployHooks []interface{} `json:"deployHooks"` | ||
ProjectName string `json:"projectName"` | ||
ProjectNamespace string `json:"projectNamespace"` | ||
Owner string `json:"owner"` | ||
Slug string `json:"slug"` | ||
} `json:"link"` | ||
LatestDeployments []struct { | ||
Alias []string `json:"alias"` | ||
AliasAssigned int64 `json:"aliasAssigned"` | ||
Builds []interface{} `json:"builds"` | ||
CreatedAt int64 `json:"createdAt"` | ||
CreatedIn string `json:"createdIn"` | ||
Creator struct { | ||
Uid string `json:"uid"` | ||
Email string `json:"email"` | ||
Username string `json:"username"` | ||
GithubLogin string `json:"githubLogin"` | ||
} `json:"creator"` | ||
DeploymentHostname string `json:"deploymentHostname"` | ||
Forced bool `json:"forced"` | ||
Id string `json:"id"` | ||
Meta struct { | ||
GithubCommitRef string `json:"githubCommitRef"` | ||
GithubRepo string `json:"githubRepo"` | ||
GithubOrg string `json:"githubOrg"` | ||
GithubCommitSha string `json:"githubCommitSha"` | ||
GithubCommitAuthorLogin string `json:"githubCommitAuthorLogin"` | ||
GithubCommitMessage string `json:"githubCommitMessage"` | ||
GithubRepoid string `json:"githubRepoid"` | ||
GithubDeployment string `json:"githubDeployment"` | ||
GithubCommitOrg string `json:"githubCommitOrg"` | ||
GithubCommitAuthorName string `json:"githubCommitAuthorName"` | ||
GithubCommitRepo string `json:"githubCommitRepo"` | ||
GithubCommitRepoid string `json:"githubCommitRepoid"` | ||
} `json:"meta"` | ||
Name string `json:"name"` | ||
Plan string `json:"plan"` | ||
Private bool `json:"private"` | ||
ReadyState string `json:"readyState"` | ||
Target interface{} `json:"target"` | ||
Teamid string `json:"teamid"` | ||
Type string `json:"type"` | ||
URL string `json:"url"` | ||
Userid string `json:"userid"` | ||
WithCache bool `json:"withCache"` | ||
} `json:"latestDeployments"` | ||
Targets struct { | ||
Production struct { | ||
Alias []string `json:"alias"` | ||
AliasAssigned int64 `json:"aliasAssigned"` | ||
Builds []interface{} `json:"builds"` | ||
CreatedAt int64 `json:"createdAt"` | ||
CreatedIn string `json:"createdIn"` | ||
Creator struct { | ||
Uid string `json:"uid"` | ||
Email string `json:"email"` | ||
Username string `json:"username"` | ||
GithubLogin string `json:"githubLogin"` | ||
} `json:"creator"` | ||
DeploymentHostname string `json:"deploymentHostname"` | ||
Forced bool `json:"forced"` | ||
Id string `json:"id"` | ||
Meta struct { | ||
GithubCommitRef string `json:"githubCommitRef"` | ||
GithubRepo string `json:"githubRepo"` | ||
GithubOrg string `json:"githubOrg"` | ||
GithubCommitSha string `json:"githubCommitSha"` | ||
GithubRepoid string `json:"githubRepoid"` | ||
GithubCommitMessage string `json:"githubCommitMessage"` | ||
GithubCommitAuthorLogin string `json:"githubCommitAuthorLogin"` | ||
GithubDeployment string `json:"githubDeployment"` | ||
GithubCommitOrg string `json:"githubCommitOrg"` | ||
GithubCommitAuthorName string `json:"githubCommitAuthorName"` | ||
GithubCommitRepo string `json:"githubCommitRepo"` | ||
GithubCommitRepoid string `json:"githubCommitRepoid"` | ||
} `json:"meta"` | ||
Name string `json:"name"` | ||
Plan string `json:"plan"` | ||
Private bool `json:"private"` | ||
ReadyState string `json:"readyState"` | ||
Target string `json:"target"` | ||
Teamid string `json:"teamid"` | ||
Type string `json:"type"` | ||
URL string `json:"url"` | ||
Userid string `json:"userid"` | ||
WithCache bool `json:"withCache"` | ||
} `json:"production"` | ||
} `json:"targets"` | ||
} |
Oops, something went wrong.