diff --git a/.release-please-manifest.json b/.release-please-manifest.json
index a26ebfc..54c4d98 100644
--- a/.release-please-manifest.json
+++ b/.release-please-manifest.json
@@ -1,3 +1,3 @@
{
- ".": "0.14.0"
+ ".": "0.14.1"
}
\ No newline at end of file
diff --git a/.stats.yml b/.stats.yml
index 0af2575..f577dd0 100644
--- a/.stats.yml
+++ b/.stats.yml
@@ -1,4 +1,4 @@
-configured_endpoints: 51
-openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/kernel%2Fkernel-8a6175a75caa75c3de5400edf97a34e526ac3f62c63955375437461581deb0c2.yml
-openapi_spec_hash: 1a880e4ce337a0e44630e6d87ef5162a
-config_hash: 49c2ff978aaa5ccb4ce324a72f116010
+configured_endpoints: 57
+openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/kernel%2Fkernel-936db268b3dcae5d64bd5d590506d8134304ffcbf67389eb9b1555b3febfd4cb.yml
+openapi_spec_hash: 145485087adf1b28c052bacb4df68462
+config_hash: 15cd063f8e308686ac71bf9ee9634625
diff --git a/CHANGELOG.md b/CHANGELOG.md
index a2006a3..d5aaaec 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,5 +1,13 @@
# Changelog
+## 0.14.1 (2025-10-07)
+
+Full Changelog: [v0.14.0...v0.14.1](https://github.com/onkernel/kernel-go-sdk/compare/v0.14.0...v0.14.1)
+
+### Features
+
+* WIP browser extensions ([22323cd](https://github.com/onkernel/kernel-go-sdk/commit/22323cdf2376bf2016cf1ebd1384f4c1b5ca6752))
+
## 0.14.0 (2025-10-03)
Full Changelog: [v0.13.0...v0.14.0](https://github.com/onkernel/kernel-go-sdk/compare/v0.13.0...v0.14.0)
diff --git a/README.md b/README.md
index df317d7..a8036ef 100644
--- a/README.md
+++ b/README.md
@@ -28,7 +28,7 @@ Or to pin the version:
```sh
-go get -u 'github.com/onkernel/kernel-go-sdk@v0.14.0'
+go get -u 'github.com/onkernel/kernel-go-sdk@v0.14.1'
```
diff --git a/api.md b/api.md
index 5e755f8..9093b83 100644
--- a/api.md
+++ b/api.md
@@ -75,6 +75,7 @@ Methods:
- client.Browsers.List(ctx context.Context) ([]kernel.BrowserListResponse, error)
- client.Browsers.Delete(ctx context.Context, body kernel.BrowserDeleteParams) error
- client.Browsers.DeleteByID(ctx context.Context, id string) error
+- client.Browsers.UploadExtensions(ctx context.Context, id string, body kernel.BrowserUploadExtensionsParams) error
## Replays
@@ -175,3 +176,18 @@ Methods:
- client.Proxies.Get(ctx context.Context, id string) (kernel.ProxyGetResponse, error)
- client.Proxies.List(ctx context.Context) ([]kernel.ProxyListResponse, error)
- client.Proxies.Delete(ctx context.Context, id string) error
+
+# Extensions
+
+Response Types:
+
+- kernel.ExtensionListResponse
+- kernel.ExtensionUploadResponse
+
+Methods:
+
+- client.Extensions.List(ctx context.Context) ([]kernel.ExtensionListResponse, error)
+- client.Extensions.Delete(ctx context.Context, idOrName string) error
+- client.Extensions.Download(ctx context.Context, idOrName string) (http.Response, error)
+- client.Extensions.DownloadFromChromeStore(ctx context.Context, query kernel.ExtensionDownloadFromChromeStoreParams) (http.Response, error)
+- client.Extensions.Upload(ctx context.Context, body kernel.ExtensionUploadParams) (kernel.ExtensionUploadResponse, error)
diff --git a/browser.go b/browser.go
index afe9db9..1afa4ce 100644
--- a/browser.go
+++ b/browser.go
@@ -3,15 +3,19 @@
package kernel
import (
+ "bytes"
"context"
"encoding/json"
"errors"
"fmt"
+ "io"
+ "mime/multipart"
"net/http"
"net/url"
"slices"
"time"
+ "github.com/onkernel/kernel-go-sdk/internal/apiform"
"github.com/onkernel/kernel-go-sdk/internal/apijson"
"github.com/onkernel/kernel-go-sdk/internal/apiquery"
"github.com/onkernel/kernel-go-sdk/internal/requestconfig"
@@ -97,6 +101,20 @@ func (r *BrowserService) DeleteByID(ctx context.Context, id string, opts ...opti
return
}
+// Loads one or more unpacked extensions and restarts Chromium on the browser
+// instance.
+func (r *BrowserService) UploadExtensions(ctx context.Context, id string, body BrowserUploadExtensionsParams, opts ...option.RequestOption) (err error) {
+ opts = slices.Concat(r.Options, opts)
+ opts = append([]option.RequestOption{option.WithHeader("Accept", "")}, opts...)
+ if id == "" {
+ err = errors.New("missing required id parameter")
+ return
+ }
+ path := fmt.Sprintf("browsers/%s/extensions", id)
+ err = requestconfig.ExecuteNewRequest(ctx, http.MethodPost, path, body, nil, opts...)
+ return
+}
+
// Optional persistence configuration for the browser session.
type BrowserPersistence struct {
// Unique identifier for the persistent browser session.
@@ -325,6 +343,8 @@ type BrowserNewParams struct {
// seconds, so the actual timeout behavior you will see is +/- 5 seconds around the
// specified value.
TimeoutSeconds param.Opt[int64] `json:"timeout_seconds,omitzero"`
+ // List of browser extensions to load into the session. Provide each by id or name.
+ Extensions []BrowserNewParamsExtension `json:"extensions,omitzero"`
// Optional persistence configuration for the browser session.
Persistence BrowserPersistenceParam `json:"persistence,omitzero"`
// Profile selection for the browser session. Provide either id or name. If
@@ -342,6 +362,25 @@ func (r *BrowserNewParams) UnmarshalJSON(data []byte) error {
return apijson.UnmarshalRoot(data, r)
}
+// Extension selection for the browser session. Provide either id or name of an
+// extension uploaded to Kernel.
+type BrowserNewParamsExtension struct {
+ // Extension ID to load for this browser session
+ ID param.Opt[string] `json:"id,omitzero"`
+ // Extension name to load for this browser session (instead of id). Must be 1-255
+ // characters, using letters, numbers, dots, underscores, or hyphens.
+ Name param.Opt[string] `json:"name,omitzero"`
+ paramObj
+}
+
+func (r BrowserNewParamsExtension) MarshalJSON() (data []byte, err error) {
+ type shadow BrowserNewParamsExtension
+ return param.MarshalObject(r, (*shadow)(&r))
+}
+func (r *BrowserNewParamsExtension) UnmarshalJSON(data []byte) error {
+ return apijson.UnmarshalRoot(data, r)
+}
+
// Profile selection for the browser session. Provide either id or name. If
// specified, the matching profile will be loaded into the browser session.
// Profiles must be created beforehand.
@@ -378,3 +417,45 @@ func (r BrowserDeleteParams) URLQuery() (v url.Values, err error) {
NestedFormat: apiquery.NestedQueryFormatBrackets,
})
}
+
+type BrowserUploadExtensionsParams struct {
+ // List of extensions to upload and activate
+ Extensions []BrowserUploadExtensionsParamsExtension `json:"extensions,omitzero,required"`
+ paramObj
+}
+
+func (r BrowserUploadExtensionsParams) MarshalMultipart() (data []byte, contentType string, err error) {
+ buf := bytes.NewBuffer(nil)
+ writer := multipart.NewWriter(buf)
+ err = apiform.MarshalRoot(r, writer)
+ if err == nil {
+ err = apiform.WriteExtras(writer, r.ExtraFields())
+ }
+ if err != nil {
+ writer.Close()
+ return nil, "", err
+ }
+ err = writer.Close()
+ if err != nil {
+ return nil, "", err
+ }
+ return buf.Bytes(), writer.FormDataContentType(), nil
+}
+
+// The properties Name, ZipFile are required.
+type BrowserUploadExtensionsParamsExtension struct {
+ // Folder name to place the extension under /home/kernel/extensions/
+ Name string `json:"name,required"`
+ // Zip archive containing an unpacked Chromium extension (must include
+ // manifest.json)
+ ZipFile io.Reader `json:"zip_file,omitzero,required" format:"binary"`
+ paramObj
+}
+
+func (r BrowserUploadExtensionsParamsExtension) MarshalJSON() (data []byte, err error) {
+ type shadow BrowserUploadExtensionsParamsExtension
+ return param.MarshalObject(r, (*shadow)(&r))
+}
+func (r *BrowserUploadExtensionsParamsExtension) UnmarshalJSON(data []byte) error {
+ return apijson.UnmarshalRoot(data, r)
+}
diff --git a/browser_test.go b/browser_test.go
index 0c0c4e3..1817275 100644
--- a/browser_test.go
+++ b/browser_test.go
@@ -3,8 +3,10 @@
package kernel_test
import (
+ "bytes"
"context"
"errors"
+ "io"
"os"
"testing"
@@ -27,6 +29,10 @@ func TestBrowserNewWithOptionalParams(t *testing.T) {
option.WithAPIKey("My API Key"),
)
_, err := client.Browsers.New(context.TODO(), kernel.BrowserNewParams{
+ Extensions: []kernel.BrowserNewParamsExtension{{
+ ID: kernel.String("id"),
+ Name: kernel.String("name"),
+ }},
Headless: kernel.Bool(false),
InvocationID: kernel.String("rr33xuugxj9h0bkf1rdt2bet"),
Persistence: kernel.BrowserPersistenceParam{
@@ -143,3 +149,35 @@ func TestBrowserDeleteByID(t *testing.T) {
t.Fatalf("err should be nil: %s", err.Error())
}
}
+
+func TestBrowserUploadExtensions(t *testing.T) {
+ t.Skip("Prism tests are disabled")
+ baseURL := "http://localhost:4010"
+ if envURL, ok := os.LookupEnv("TEST_API_BASE_URL"); ok {
+ baseURL = envURL
+ }
+ if !testutil.CheckTestServer(t, baseURL) {
+ return
+ }
+ client := kernel.NewClient(
+ option.WithBaseURL(baseURL),
+ option.WithAPIKey("My API Key"),
+ )
+ err := client.Browsers.UploadExtensions(
+ context.TODO(),
+ "id",
+ kernel.BrowserUploadExtensionsParams{
+ Extensions: []kernel.BrowserUploadExtensionsParamsExtension{{
+ Name: "name",
+ ZipFile: io.Reader(bytes.NewBuffer([]byte("some file contents"))),
+ }},
+ },
+ )
+ if err != nil {
+ var apierr *kernel.Error
+ if errors.As(err, &apierr) {
+ t.Log(string(apierr.DumpRequest(true)))
+ }
+ t.Fatalf("err should be nil: %s", err.Error())
+ }
+}
diff --git a/client.go b/client.go
index ec155ff..0e27e7b 100644
--- a/client.go
+++ b/client.go
@@ -23,6 +23,7 @@ type Client struct {
Browsers BrowserService
Profiles ProfileService
Proxies ProxyService
+ Extensions ExtensionService
}
// DefaultClientOptions read from the environment (KERNEL_API_KEY,
@@ -53,6 +54,7 @@ func NewClient(opts ...option.RequestOption) (r Client) {
r.Browsers = NewBrowserService(opts...)
r.Profiles = NewProfileService(opts...)
r.Proxies = NewProxyService(opts...)
+ r.Extensions = NewExtensionService(opts...)
return
}
diff --git a/extension.go b/extension.go
new file mode 100644
index 0000000..204b126
--- /dev/null
+++ b/extension.go
@@ -0,0 +1,212 @@
+// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+
+package kernel
+
+import (
+ "bytes"
+ "context"
+ "errors"
+ "fmt"
+ "io"
+ "mime/multipart"
+ "net/http"
+ "net/url"
+ "slices"
+ "time"
+
+ "github.com/onkernel/kernel-go-sdk/internal/apiform"
+ "github.com/onkernel/kernel-go-sdk/internal/apijson"
+ "github.com/onkernel/kernel-go-sdk/internal/apiquery"
+ "github.com/onkernel/kernel-go-sdk/internal/requestconfig"
+ "github.com/onkernel/kernel-go-sdk/option"
+ "github.com/onkernel/kernel-go-sdk/packages/param"
+ "github.com/onkernel/kernel-go-sdk/packages/respjson"
+)
+
+// ExtensionService contains methods and other services that help with interacting
+// with the kernel API.
+//
+// Note, unlike clients, this service does not read variables from the environment
+// automatically. You should not instantiate this service directly, and instead use
+// the [NewExtensionService] method instead.
+type ExtensionService struct {
+ Options []option.RequestOption
+}
+
+// NewExtensionService generates a new service that applies the given options to
+// each request. These options are applied after the parent client's options (if
+// there is one), and before any request-specific options.
+func NewExtensionService(opts ...option.RequestOption) (r ExtensionService) {
+ r = ExtensionService{}
+ r.Options = opts
+ return
+}
+
+// List extensions owned by the caller's organization.
+func (r *ExtensionService) List(ctx context.Context, opts ...option.RequestOption) (res *[]ExtensionListResponse, err error) {
+ opts = slices.Concat(r.Options, opts)
+ path := "extensions"
+ err = requestconfig.ExecuteNewRequest(ctx, http.MethodGet, path, nil, &res, opts...)
+ return
+}
+
+// Delete an extension by its ID or by its name.
+func (r *ExtensionService) Delete(ctx context.Context, idOrName string, opts ...option.RequestOption) (err error) {
+ opts = slices.Concat(r.Options, opts)
+ opts = append([]option.RequestOption{option.WithHeader("Accept", "")}, opts...)
+ if idOrName == "" {
+ err = errors.New("missing required id_or_name parameter")
+ return
+ }
+ path := fmt.Sprintf("extensions/%s", idOrName)
+ err = requestconfig.ExecuteNewRequest(ctx, http.MethodDelete, path, nil, nil, opts...)
+ return
+}
+
+// Download the extension as a ZIP archive by ID or name.
+func (r *ExtensionService) Download(ctx context.Context, idOrName string, opts ...option.RequestOption) (res *http.Response, err error) {
+ opts = slices.Concat(r.Options, opts)
+ opts = append([]option.RequestOption{option.WithHeader("Accept", "application/octet-stream")}, opts...)
+ if idOrName == "" {
+ err = errors.New("missing required id_or_name parameter")
+ return
+ }
+ path := fmt.Sprintf("extensions/%s", idOrName)
+ err = requestconfig.ExecuteNewRequest(ctx, http.MethodGet, path, nil, &res, opts...)
+ return
+}
+
+// Returns a ZIP archive containing the unpacked extension fetched from the Chrome
+// Web Store.
+func (r *ExtensionService) DownloadFromChromeStore(ctx context.Context, query ExtensionDownloadFromChromeStoreParams, opts ...option.RequestOption) (res *http.Response, err error) {
+ opts = slices.Concat(r.Options, opts)
+ opts = append([]option.RequestOption{option.WithHeader("Accept", "application/octet-stream")}, opts...)
+ path := "extensions/from_chrome_store"
+ err = requestconfig.ExecuteNewRequest(ctx, http.MethodGet, path, query, &res, opts...)
+ return
+}
+
+// Upload a zip file containing an unpacked browser extension. Optionally provide a
+// unique name for later reference.
+func (r *ExtensionService) Upload(ctx context.Context, body ExtensionUploadParams, opts ...option.RequestOption) (res *ExtensionUploadResponse, err error) {
+ opts = slices.Concat(r.Options, opts)
+ path := "extensions"
+ err = requestconfig.ExecuteNewRequest(ctx, http.MethodPost, path, body, &res, opts...)
+ return
+}
+
+// A browser extension uploaded to Kernel.
+type ExtensionListResponse struct {
+ // Unique identifier for the extension
+ ID string `json:"id,required"`
+ // Timestamp when the extension was created
+ CreatedAt time.Time `json:"created_at,required" format:"date-time"`
+ // Size of the extension archive in bytes
+ SizeBytes int64 `json:"size_bytes,required"`
+ // Timestamp when the extension was last used
+ LastUsedAt time.Time `json:"last_used_at,nullable" format:"date-time"`
+ // Optional, easier-to-reference name for the extension. Must be unique within the
+ // organization.
+ Name string `json:"name,nullable"`
+ // JSON contains metadata for fields, check presence with [respjson.Field.Valid].
+ JSON struct {
+ ID respjson.Field
+ CreatedAt respjson.Field
+ SizeBytes respjson.Field
+ LastUsedAt respjson.Field
+ Name respjson.Field
+ ExtraFields map[string]respjson.Field
+ raw string
+ } `json:"-"`
+}
+
+// Returns the unmodified JSON received from the API
+func (r ExtensionListResponse) RawJSON() string { return r.JSON.raw }
+func (r *ExtensionListResponse) UnmarshalJSON(data []byte) error {
+ return apijson.UnmarshalRoot(data, r)
+}
+
+// A browser extension uploaded to Kernel.
+type ExtensionUploadResponse struct {
+ // Unique identifier for the extension
+ ID string `json:"id,required"`
+ // Timestamp when the extension was created
+ CreatedAt time.Time `json:"created_at,required" format:"date-time"`
+ // Size of the extension archive in bytes
+ SizeBytes int64 `json:"size_bytes,required"`
+ // Timestamp when the extension was last used
+ LastUsedAt time.Time `json:"last_used_at,nullable" format:"date-time"`
+ // Optional, easier-to-reference name for the extension. Must be unique within the
+ // organization.
+ Name string `json:"name,nullable"`
+ // JSON contains metadata for fields, check presence with [respjson.Field.Valid].
+ JSON struct {
+ ID respjson.Field
+ CreatedAt respjson.Field
+ SizeBytes respjson.Field
+ LastUsedAt respjson.Field
+ Name respjson.Field
+ ExtraFields map[string]respjson.Field
+ raw string
+ } `json:"-"`
+}
+
+// Returns the unmodified JSON received from the API
+func (r ExtensionUploadResponse) RawJSON() string { return r.JSON.raw }
+func (r *ExtensionUploadResponse) UnmarshalJSON(data []byte) error {
+ return apijson.UnmarshalRoot(data, r)
+}
+
+type ExtensionDownloadFromChromeStoreParams struct {
+ // Chrome Web Store URL for the extension.
+ URL string `query:"url,required" json:"-"`
+ // Target operating system for the extension package. Defaults to linux.
+ //
+ // Any of "win", "mac", "linux".
+ Os ExtensionDownloadFromChromeStoreParamsOs `query:"os,omitzero" json:"-"`
+ paramObj
+}
+
+// URLQuery serializes [ExtensionDownloadFromChromeStoreParams]'s query parameters
+// as `url.Values`.
+func (r ExtensionDownloadFromChromeStoreParams) URLQuery() (v url.Values, err error) {
+ return apiquery.MarshalWithSettings(r, apiquery.QuerySettings{
+ ArrayFormat: apiquery.ArrayQueryFormatComma,
+ NestedFormat: apiquery.NestedQueryFormatBrackets,
+ })
+}
+
+// Target operating system for the extension package. Defaults to linux.
+type ExtensionDownloadFromChromeStoreParamsOs string
+
+const (
+ ExtensionDownloadFromChromeStoreParamsOsWin ExtensionDownloadFromChromeStoreParamsOs = "win"
+ ExtensionDownloadFromChromeStoreParamsOsMac ExtensionDownloadFromChromeStoreParamsOs = "mac"
+ ExtensionDownloadFromChromeStoreParamsOsLinux ExtensionDownloadFromChromeStoreParamsOs = "linux"
+)
+
+type ExtensionUploadParams struct {
+ // ZIP file containing the browser extension.
+ File io.Reader `json:"file,omitzero,required" format:"binary"`
+ // Optional unique name within the organization to reference this extension.
+ Name param.Opt[string] `json:"name,omitzero"`
+ paramObj
+}
+
+func (r ExtensionUploadParams) MarshalMultipart() (data []byte, contentType string, err error) {
+ buf := bytes.NewBuffer(nil)
+ writer := multipart.NewWriter(buf)
+ err = apiform.MarshalRoot(r, writer)
+ if err == nil {
+ err = apiform.WriteExtras(writer, r.ExtraFields())
+ }
+ if err != nil {
+ writer.Close()
+ return nil, "", err
+ }
+ err = writer.Close()
+ if err != nil {
+ return nil, "", err
+ }
+ return buf.Bytes(), writer.FormDataContentType(), nil
+}
diff --git a/extension_test.go b/extension_test.go
new file mode 100644
index 0000000..af2089a
--- /dev/null
+++ b/extension_test.go
@@ -0,0 +1,161 @@
+// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+
+package kernel_test
+
+import (
+ "bytes"
+ "context"
+ "errors"
+ "io"
+ "net/http"
+ "net/http/httptest"
+ "os"
+ "testing"
+
+ "github.com/onkernel/kernel-go-sdk"
+ "github.com/onkernel/kernel-go-sdk/internal/testutil"
+ "github.com/onkernel/kernel-go-sdk/option"
+)
+
+func TestExtensionList(t *testing.T) {
+ t.Skip("Prism tests are disabled")
+ baseURL := "http://localhost:4010"
+ if envURL, ok := os.LookupEnv("TEST_API_BASE_URL"); ok {
+ baseURL = envURL
+ }
+ if !testutil.CheckTestServer(t, baseURL) {
+ return
+ }
+ client := kernel.NewClient(
+ option.WithBaseURL(baseURL),
+ option.WithAPIKey("My API Key"),
+ )
+ _, err := client.Extensions.List(context.TODO())
+ if err != nil {
+ var apierr *kernel.Error
+ if errors.As(err, &apierr) {
+ t.Log(string(apierr.DumpRequest(true)))
+ }
+ t.Fatalf("err should be nil: %s", err.Error())
+ }
+}
+
+func TestExtensionDelete(t *testing.T) {
+ t.Skip("Prism tests are disabled")
+ baseURL := "http://localhost:4010"
+ if envURL, ok := os.LookupEnv("TEST_API_BASE_URL"); ok {
+ baseURL = envURL
+ }
+ if !testutil.CheckTestServer(t, baseURL) {
+ return
+ }
+ client := kernel.NewClient(
+ option.WithBaseURL(baseURL),
+ option.WithAPIKey("My API Key"),
+ )
+ err := client.Extensions.Delete(context.TODO(), "id_or_name")
+ if err != nil {
+ var apierr *kernel.Error
+ if errors.As(err, &apierr) {
+ t.Log(string(apierr.DumpRequest(true)))
+ }
+ t.Fatalf("err should be nil: %s", err.Error())
+ }
+}
+
+func TestExtensionDownload(t *testing.T) {
+ server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
+ w.WriteHeader(200)
+ w.Write([]byte("abc"))
+ }))
+ defer server.Close()
+ baseURL := server.URL
+ client := kernel.NewClient(
+ option.WithBaseURL(baseURL),
+ option.WithAPIKey("My API Key"),
+ )
+ resp, err := client.Extensions.Download(context.TODO(), "id_or_name")
+ if err != nil {
+ var apierr *kernel.Error
+ if errors.As(err, &apierr) {
+ t.Log(string(apierr.DumpRequest(true)))
+ }
+ t.Fatalf("err should be nil: %s", err.Error())
+ }
+ defer resp.Body.Close()
+
+ b, err := io.ReadAll(resp.Body)
+ if err != nil {
+ var apierr *kernel.Error
+ if errors.As(err, &apierr) {
+ t.Log(string(apierr.DumpRequest(true)))
+ }
+ t.Fatalf("err should be nil: %s", err.Error())
+ }
+ if !bytes.Equal(b, []byte("abc")) {
+ t.Fatalf("return value not %s: %s", "abc", b)
+ }
+}
+
+func TestExtensionDownloadFromChromeStoreWithOptionalParams(t *testing.T) {
+ server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
+ w.WriteHeader(200)
+ w.Write([]byte("abc"))
+ }))
+ defer server.Close()
+ baseURL := server.URL
+ client := kernel.NewClient(
+ option.WithBaseURL(baseURL),
+ option.WithAPIKey("My API Key"),
+ )
+ resp, err := client.Extensions.DownloadFromChromeStore(context.TODO(), kernel.ExtensionDownloadFromChromeStoreParams{
+ URL: "url",
+ Os: kernel.ExtensionDownloadFromChromeStoreParamsOsWin,
+ })
+ if err != nil {
+ var apierr *kernel.Error
+ if errors.As(err, &apierr) {
+ t.Log(string(apierr.DumpRequest(true)))
+ }
+ t.Fatalf("err should be nil: %s", err.Error())
+ }
+ defer resp.Body.Close()
+
+ b, err := io.ReadAll(resp.Body)
+ if err != nil {
+ var apierr *kernel.Error
+ if errors.As(err, &apierr) {
+ t.Log(string(apierr.DumpRequest(true)))
+ }
+ t.Fatalf("err should be nil: %s", err.Error())
+ }
+ if !bytes.Equal(b, []byte("abc")) {
+ t.Fatalf("return value not %s: %s", "abc", b)
+ }
+}
+
+func TestExtensionUploadWithOptionalParams(t *testing.T) {
+ t.Skip("Prism tests are disabled")
+ baseURL := "http://localhost:4010"
+ if envURL, ok := os.LookupEnv("TEST_API_BASE_URL"); ok {
+ baseURL = envURL
+ }
+ if !testutil.CheckTestServer(t, baseURL) {
+ return
+ }
+ client := kernel.NewClient(
+ option.WithBaseURL(baseURL),
+ option.WithAPIKey("My API Key"),
+ )
+ _, err := client.Extensions.Upload(context.TODO(), kernel.ExtensionUploadParams{
+ File: io.Reader(bytes.NewBuffer([]byte("some file contents"))),
+ Name: kernel.String("name"),
+ })
+ if err != nil {
+ var apierr *kernel.Error
+ if errors.As(err, &apierr) {
+ t.Log(string(apierr.DumpRequest(true)))
+ }
+ t.Fatalf("err should be nil: %s", err.Error())
+ }
+}
diff --git a/internal/version.go b/internal/version.go
index 870e575..15be922 100644
--- a/internal/version.go
+++ b/internal/version.go
@@ -2,4 +2,4 @@
package internal
-const PackageVersion = "0.14.0" // x-release-please-version
+const PackageVersion = "0.14.1" // x-release-please-version