diff --git a/.release-please-manifest.json b/.release-please-manifest.json
index 65f558e..656a2ef 100644
--- a/.release-please-manifest.json
+++ b/.release-please-manifest.json
@@ -1,3 +1,3 @@
{
- ".": "2.0.0"
+ ".": "2.1.0"
}
\ No newline at end of file
diff --git a/.stats.yml b/.stats.yml
index 96e30e1..333dfb4 100644
--- a/.stats.yml
+++ b/.stats.yml
@@ -1,4 +1,4 @@
configured_endpoints: 43
-openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/imagekit-inc%2Fimagekit-c7ad6f552b38f2145781847f8b390fa1ec43068d64e45a33012a97a9299edc10.yml
-openapi_spec_hash: 50f281e91210ad5018ac7e4eee216f56
-config_hash: 74a8263b80c732a2b016177e7d56bb9c
+openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/imagekit-inc%2Fimagekit-9d184cb502ab32a85db2889c796cdfebe812f2a55a604df79c85dd4b5e7e2add.yml
+openapi_spec_hash: a9aa620376fce66532c84f9364209b0b
+config_hash: 71cab8223bb5610c6c7ca6e9c4cc1f89
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 488241b..c32654d 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,5 +1,37 @@
# Changelog
+## 2.1.0 (2026-01-05)
+
+Full Changelog: [v2.0.0...v2.1.0](https://github.com/imagekit-developer/imagekit-go/compare/v2.0.0...v2.1.0)
+
+### Features
+
+* **api:** add GetImageAttributesOptions and ResponsiveImageAttributes schemas; update resource references in main.yaml; remove dummy endpoint ([41072da](https://github.com/imagekit-developer/imagekit-go/commit/41072da63cd2ba891a911d932af3bc8b70c90588))
+* **api:** fix go sdk breaking changes ([6cbddff](https://github.com/imagekit-developer/imagekit-go/commit/6cbddffab95c89b964fc29ce119ceb70d7ebded5))
+* **encoder:** support bracket encoding form-data object members ([cb3e557](https://github.com/imagekit-developer/imagekit-go/commit/cb3e5572b00fe978ee93d595cc4d8775edccbc89))
+
+
+### Bug Fixes
+
+* **client:** correctly specify Accept header with */* instead of empty ([21a30a4](https://github.com/imagekit-developer/imagekit-go/commit/21a30a4d60b4b2da84d2314ddf6bcf76759da64d))
+* **client:** properly marshal embedded structs ([e55e614](https://github.com/imagekit-developer/imagekit-go/commit/e55e614fab629dfab68d7249e53ef602dd1a36b3))
+* **docs:** update go get command to include version path in README.md ([d7d4c82](https://github.com/imagekit-developer/imagekit-go/commit/d7d4c829ebccafd1242d79a03651f1189c9f24d0))
+* **mcp:** correct code tool API endpoint ([b32395e](https://github.com/imagekit-developer/imagekit-go/commit/b32395e36a3fdd2f8e37313a303a68135f13400f))
+* rename param to avoid collision ([5067fd4](https://github.com/imagekit-developer/imagekit-go/commit/5067fd4adfe3a7108f3799f270c4211ade385882))
+* skip usage tests that don't work with Prism ([429ad75](https://github.com/imagekit-developer/imagekit-go/commit/429ad75eb8c267b44a9c8e4f2c542344189563e3))
+
+
+### Chores
+
+* add float64 to valid types for RegisterFieldValidator ([2dc3cae](https://github.com/imagekit-developer/imagekit-go/commit/2dc3cae63386dc6b8c7743af3fdb0a9c4ed93ef5))
+* bump gjson version ([87ad44d](https://github.com/imagekit-developer/imagekit-go/commit/87ad44d7016dcb641158e26cc4f0d08e89770dc5))
+* elide duplicate aliases ([2f9eee1](https://github.com/imagekit-developer/imagekit-go/commit/2f9eee11c82bd0b6641dec1f0c20042863ad169f))
+* **internal:** codegen related update ([2fdd961](https://github.com/imagekit-developer/imagekit-go/commit/2fdd961c6a458140239af2e88cf1b1ecf7dc27f2))
+* **internal:** codegen related update ([8877b4f](https://github.com/imagekit-developer/imagekit-go/commit/8877b4fbdce39a56785613a1172dda44399c6fe7))
+* **internal:** codegen related update ([d83769d](https://github.com/imagekit-developer/imagekit-go/commit/d83769df0486737f479694acc9421415fb11c523))
+* **internal:** codegen related update ([63165ac](https://github.com/imagekit-developer/imagekit-go/commit/63165ac51ec10df842ed8f9496c82294b4f9e61e))
+* **internal:** grammar fix (it's -> its) ([e35e192](https://github.com/imagekit-developer/imagekit-go/commit/e35e1922f7ad2541ed116db557bcedd8c9c088de))
+
## 2.0.0 (2025-10-05)
Full Changelog: [v0.0.1...v2.0.0](https://github.com/imagekit-developer/imagekit-go/compare/v0.0.1...v2.0.0)
diff --git a/LICENSE b/LICENSE
index e7a4d16..2027861 100644
--- a/LICENSE
+++ b/LICENSE
@@ -186,7 +186,7 @@
same "printed page" as the copyright notice for easier
identification within third-party archives.
- Copyright 2025 Image Kit
+ Copyright 2026 Image Kit
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
diff --git a/README.md b/README.md
index 58286aa..e6e4c3a 100644
--- a/README.md
+++ b/README.md
@@ -42,6 +42,15 @@ For additional details, refer to the [ImageKit REST API documentation](https://i
- [Semantic versioning](#semantic-versioning)
- [Contributing](#contributing)
+## MCP Server
+
+Use the Image Kit MCP Server to enable AI assistants to interact with this API, allowing them to explore endpoints, make test requests, and use documentation to help integrate this SDK into your application.
+
+[](https://cursor.com/en-US/install-mcp?name=%40imagekit%2Fapi-mcp&config=eyJjb21tYW5kIjoibnB4IiwiYXJncyI6WyIteSIsIkBpbWFnZWtpdC9hcGktbWNwIl19)
+[](https://vscode.stainless.com/mcp/%7B%22name%22%3A%22%40imagekit%2Fapi-mcp%22%2C%22command%22%3A%22npx%22%2C%22args%22%3A%5B%22-y%22%2C%22%40imagekit%2Fapi-mcp%22%5D%7D)
+
+> Note: You may need to set environment variables in your MCP client.
+
## Installation
@@ -59,7 +68,7 @@ Or to pin the version:
```sh
-go get -u 'github.com/imagekit-developer/imagekit-go@v2.0.0'
+go get -u 'github.com/imagekit-developer/imagekit-go/v2@v2.1.0'
```
@@ -167,7 +176,7 @@ custom := param.Override[imagekit.FooParams](12)
### Request unions
-Unions are represented as a struct with fields prefixed by "Of" for each of it's variants,
+Unions are represented as a struct with fields prefixed by "Of" for each of its variants,
only one field can be non-zero. The non-zero field will be serialized.
Sub-properties of the union can be accessed via methods on the union struct.
diff --git a/accountorigin.go b/accountorigin.go
index 79a8d4a..52888b2 100644
--- a/accountorigin.go
+++ b/accountorigin.go
@@ -74,7 +74,7 @@ func (r *AccountOriginService) List(ctx context.Context, opts ...option.RequestO
// any URL‑endpoints, the API will return an error.
func (r *AccountOriginService) Delete(ctx context.Context, id string, opts ...option.RequestOption) (err error) {
opts = slices.Concat(r.Options, opts)
- opts = append([]option.RequestOption{option.WithHeader("Accept", "")}, opts...)
+ opts = append([]option.RequestOption{option.WithHeader("Accept", "*/*")}, opts...)
if id == "" {
err = errors.New("missing required id parameter")
return
diff --git a/accounturlendpoint.go b/accounturlendpoint.go
index 7991a84..dbd0224 100644
--- a/accounturlendpoint.go
+++ b/accounturlendpoint.go
@@ -75,7 +75,7 @@ func (r *AccountURLEndpointService) List(ctx context.Context, opts ...option.Req
// URL‑endpoint created by ImageKit during account creation.
func (r *AccountURLEndpointService) Delete(ctx context.Context, id string, opts ...option.RequestOption) (err error) {
opts = slices.Concat(r.Options, opts)
- opts = append([]option.RequestOption{option.WithHeader("Accept", "")}, opts...)
+ opts = append([]option.RequestOption{option.WithHeader("Accept", "*/*")}, opts...)
if id == "" {
err = errors.New("missing required id parameter")
return
diff --git a/aliases.go b/aliases.go
index be8fe53..33ed8d6 100644
--- a/aliases.go
+++ b/aliases.go
@@ -40,6 +40,13 @@ type ExtensionAutoTaggingParam = shared.ExtensionAutoTaggingParam
// This is an alias to an internal type.
type ExtensionAIAutoDescriptionParam = shared.ExtensionAIAutoDescriptionParam
+// Options for generating responsive image attributes including `src`, `srcSet`,
+// and `sizes` for HTML `
` elements. This schema extends `SrcOptions` to add
+// support for responsive image generation with breakpoints.
+//
+// This is an alias to an internal type.
+type GetImageAttributesOptionsParam = shared.GetImageAttributesOptionsParam
+
// This is an alias to an internal type.
type ImageOverlayParam = shared.ImageOverlayParam
@@ -133,6 +140,12 @@ type OverlayTimingEndUnionParam = shared.OverlayTimingEndUnionParam
// This is an alias to an internal type.
type OverlayTimingStartUnionParam = shared.OverlayTimingStartUnionParam
+// Resulting set of attributes suitable for an HTML `
` element. Useful for
+// enabling responsive image loading with `srcSet` and `sizes`.
+//
+// This is an alias to an internal type.
+type ResponsiveImageAttributesParam = shared.ResponsiveImageAttributesParam
+
// This is an alias to an internal type.
type SolidColorOverlayParam = shared.SolidColorOverlayParam
diff --git a/api.md b/api.md
index d1fe4eb..2589aa8 100644
--- a/api.md
+++ b/api.md
@@ -2,10 +2,12 @@
- shared.BaseOverlayParam
- shared.ExtensionsParam
+- shared.GetImageAttributesOptionsParam
- shared.ImageOverlayParam
- shared.OverlayUnionParam
- shared.OverlayPositionParam
- shared.OverlayTimingParam
+- shared.ResponsiveImageAttributesParam
- shared.SolidColorOverlayParam
- shared.SolidColorOverlayTransformationParam
- shared.SrcOptionsParam
@@ -18,6 +20,12 @@
- shared.TransformationPosition
- shared.VideoOverlayParam
+# Dummy
+
+Methods:
+
+- client.Dummy.New(ctx context.Context, body imagekit.DummyNewParams) error
+
# CustomMetadataFields
Response Types:
diff --git a/dummy.go b/dummy.go
index 9f26efb..80449e4 100644
--- a/dummy.go
+++ b/dummy.go
@@ -38,7 +38,7 @@ func NewDummyService(opts ...option.RequestOption) (r DummyService) {
// and is not intended for public consumption.
func (r *DummyService) New(ctx context.Context, body DummyNewParams, opts ...option.RequestOption) (err error) {
opts = slices.Concat(r.Options, opts)
- opts = append([]option.RequestOption{option.WithHeader("Accept", "")}, opts...)
+ opts = append([]option.RequestOption{option.WithHeader("Accept", "*/*")}, opts...)
path := "v1/dummy/test"
err = requestconfig.ExecuteNewRequest(ctx, http.MethodPost, path, body, nil, opts...)
return
@@ -48,15 +48,22 @@ type DummyNewParams struct {
BaseOverlay shared.BaseOverlayParam `json:"baseOverlay,omitzero"`
// Array of extensions to be applied to the asset. Each extension can be configured
// with specific parameters based on the extension type.
- Extensions shared.ExtensionsParam `json:"extensions,omitzero"`
- ImageOverlay shared.ImageOverlayParam `json:"imageOverlay,omitzero"`
+ Extensions shared.ExtensionsParam `json:"extensions,omitzero"`
+ // Options for generating responsive image attributes including `src`, `srcSet`,
+ // and `sizes` for HTML `
` elements. This schema extends `SrcOptions` to add
+ // support for responsive image generation with breakpoints.
+ GetImageAttributesOptions shared.GetImageAttributesOptionsParam `json:"getImageAttributesOptions,omitzero"`
+ ImageOverlay shared.ImageOverlayParam `json:"imageOverlay,omitzero"`
// Specifies an overlay to be applied on the parent image or video. ImageKit
// supports overlays including images, text, videos, subtitles, and solid colors.
// See
// [Overlay using layers](https://imagekit.io/docs/transformations#overlay-using-layers).
- Overlay shared.OverlayUnionParam `json:"overlay,omitzero"`
- OverlayPosition shared.OverlayPositionParam `json:"overlayPosition,omitzero"`
- OverlayTiming shared.OverlayTimingParam `json:"overlayTiming,omitzero"`
+ Overlay shared.OverlayUnionParam `json:"overlay,omitzero"`
+ OverlayPosition shared.OverlayPositionParam `json:"overlayPosition,omitzero"`
+ OverlayTiming shared.OverlayTimingParam `json:"overlayTiming,omitzero"`
+ // Resulting set of attributes suitable for an HTML `
` element. Useful for
+ // enabling responsive image loading with `srcSet` and `sizes`.
+ ResponsiveImageAttributes shared.ResponsiveImageAttributesParam `json:"responsiveImageAttributes,omitzero"`
SolidColorOverlay shared.SolidColorOverlayParam `json:"solidColorOverlay,omitzero"`
SolidColorOverlayTransformation shared.SolidColorOverlayTransformationParam `json:"solidColorOverlayTransformation,omitzero"`
// Options for generating ImageKit URLs with transformations. See the
diff --git a/dummy_test.go b/dummy_test.go
index 0548e6a..96a9a1c 100644
--- a/dummy_test.go
+++ b/dummy_test.go
@@ -69,6 +69,168 @@ func TestDummyNewWithOptionalParams(t *testing.T) {
}, shared.ExtensionUnionParam{
OfAIAutoDescription: &shared.ExtensionAIAutoDescriptionParam{},
}},
+ GetImageAttributesOptions: shared.GetImageAttributesOptionsParam{
+ SrcOptionsParam: shared.SrcOptionsParam{
+ Src: "/my-image.jpg",
+ URLEndpoint: "https://ik.imagekit.io/demo",
+ ExpiresIn: imagekit.Float(0),
+ QueryParameters: map[string]string{
+ "foo": "string",
+ },
+ Signed: imagekit.Bool(true),
+ Transformation: []shared.TransformationParam{{
+ AIChangeBackground: imagekit.String("aiChangeBackground"),
+ AIDropShadow: shared.TransformationAIDropShadowUnionParam{
+ OfTransformationAIDropShadowBoolean: imagekit.Bool(true),
+ },
+ AIEdit: imagekit.String("aiEdit"),
+ AIRemoveBackground: true,
+ AIRemoveBackgroundExternal: true,
+ AIRetouch: true,
+ AIUpscale: true,
+ AIVariation: true,
+ AspectRatio: shared.TransformationAspectRatioUnionParam{
+ OfString: imagekit.String("4:3"),
+ },
+ AudioCodec: shared.TransformationAudioCodecAac,
+ Background: imagekit.String("red"),
+ Blur: imagekit.Float(10),
+ Border: imagekit.String("5_FF0000"),
+ ColorProfile: imagekit.Bool(true),
+ ContrastStretch: true,
+ Crop: shared.TransformationCropForce,
+ CropMode: shared.TransformationCropModePadResize,
+ DefaultImage: imagekit.String("defaultImage"),
+ Dpr: imagekit.Float(2),
+ Duration: shared.TransformationDurationUnionParam{
+ OfFloat: imagekit.Float(0),
+ },
+ EndOffset: shared.TransformationEndOffsetUnionParam{
+ OfFloat: imagekit.Float(0),
+ },
+ Flip: shared.TransformationFlipH,
+ Focus: imagekit.String("center"),
+ Format: shared.TransformationFormatAuto,
+ Gradient: shared.TransformationGradientUnionParam{
+ OfTransformationGradientBoolean: imagekit.Bool(true),
+ },
+ Grayscale: true,
+ Height: shared.TransformationHeightUnionParam{
+ OfFloat: imagekit.Float(200),
+ },
+ Lossless: imagekit.Bool(true),
+ Metadata: imagekit.Bool(true),
+ Named: imagekit.String("named"),
+ Opacity: imagekit.Float(0),
+ Original: imagekit.Bool(true),
+ Overlay: shared.OverlayUnionParam{
+ OfText: &shared.TextOverlayParam{
+ BaseOverlayParam: shared.BaseOverlayParam{
+ Position: shared.OverlayPositionParam{
+ Focus: shared.OverlayPositionFocusCenter,
+ X: shared.OverlayPositionXUnionParam{
+ OfFloat: imagekit.Float(0),
+ },
+ Y: shared.OverlayPositionYUnionParam{
+ OfFloat: imagekit.Float(0),
+ },
+ },
+ Timing: shared.OverlayTimingParam{
+ Duration: shared.OverlayTimingDurationUnionParam{
+ OfFloat: imagekit.Float(0),
+ },
+ End: shared.OverlayTimingEndUnionParam{
+ OfFloat: imagekit.Float(0),
+ },
+ Start: shared.OverlayTimingStartUnionParam{
+ OfFloat: imagekit.Float(0),
+ },
+ },
+ },
+ Text: "text",
+ Encoding: "auto",
+ Transformation: []shared.TextOverlayTransformationParam{{
+ Alpha: imagekit.Float(1),
+ Background: imagekit.String("background"),
+ Flip: shared.TextOverlayTransformationFlipH,
+ FontColor: imagekit.String("fontColor"),
+ FontFamily: imagekit.String("fontFamily"),
+ FontSize: shared.TextOverlayTransformationFontSizeUnionParam{
+ OfFloat: imagekit.Float(0),
+ },
+ InnerAlignment: shared.TextOverlayTransformationInnerAlignmentLeft,
+ LineHeight: shared.TextOverlayTransformationLineHeightUnionParam{
+ OfFloat: imagekit.Float(0),
+ },
+ Padding: shared.TextOverlayTransformationPaddingUnionParam{
+ OfFloat: imagekit.Float(0),
+ },
+ Radius: shared.TextOverlayTransformationRadiusUnionParam{
+ OfFloat: imagekit.Float(0),
+ },
+ Rotation: shared.TextOverlayTransformationRotationUnionParam{
+ OfFloat: imagekit.Float(0),
+ },
+ Typography: imagekit.String("typography"),
+ Width: shared.TextOverlayTransformationWidthUnionParam{
+ OfFloat: imagekit.Float(0),
+ },
+ }},
+ },
+ },
+ Page: shared.TransformationPageUnionParam{
+ OfFloat: imagekit.Float(0),
+ },
+ Progressive: imagekit.Bool(true),
+ Quality: imagekit.Float(80),
+ Radius: shared.TransformationRadiusUnionParam{
+ OfFloat: imagekit.Float(20),
+ },
+ Raw: imagekit.String("raw"),
+ Rotation: shared.TransformationRotationUnionParam{
+ OfFloat: imagekit.Float(90),
+ },
+ Shadow: shared.TransformationShadowUnionParam{
+ OfTransformationShadowBoolean: imagekit.Bool(true),
+ },
+ Sharpen: shared.TransformationSharpenUnionParam{
+ OfTransformationSharpenBoolean: imagekit.Bool(true),
+ },
+ StartOffset: shared.TransformationStartOffsetUnionParam{
+ OfFloat: imagekit.Float(0),
+ },
+ StreamingResolutions: []shared.StreamingResolution{shared.StreamingResolution240},
+ Trim: shared.TransformationTrimUnionParam{
+ OfTransformationTrimBoolean: imagekit.Bool(true),
+ },
+ UnsharpMask: shared.TransformationUnsharpMaskUnionParam{
+ OfTransformationUnsharpMaskBoolean: imagekit.Bool(true),
+ },
+ VideoCodec: shared.TransformationVideoCodecH264,
+ Width: shared.TransformationWidthUnionParam{
+ OfFloat: imagekit.Float(300),
+ },
+ X: shared.TransformationXUnionParam{
+ OfFloat: imagekit.Float(0),
+ },
+ XCenter: shared.TransformationXCenterUnionParam{
+ OfFloat: imagekit.Float(0),
+ },
+ Y: shared.TransformationYUnionParam{
+ OfFloat: imagekit.Float(0),
+ },
+ YCenter: shared.TransformationYCenterUnionParam{
+ OfFloat: imagekit.Float(0),
+ },
+ Zoom: imagekit.Float(0),
+ }},
+ TransformationPosition: shared.TransformationPositionPath,
+ },
+ DeviceBreakpoints: []float64{640, 750, 828, 1080, 1200, 1920, 2048, 3840},
+ ImageBreakpoints: []float64{16, 32, 48, 64, 96, 128, 256, 384},
+ Sizes: imagekit.String("(min-width: 768px) 50vw, 100vw"),
+ Width: imagekit.Float(400),
+ },
ImageOverlay: shared.ImageOverlayParam{
BaseOverlayParam: shared.BaseOverlayParam{
Position: shared.OverlayPositionParam{
@@ -316,6 +478,12 @@ func TestDummyNewWithOptionalParams(t *testing.T) {
OfFloat: imagekit.Float(0),
},
},
+ ResponsiveImageAttributes: shared.ResponsiveImageAttributesParam{
+ Src: "https://ik.imagekit.io/demo/image.jpg?tr=w-3840",
+ Sizes: imagekit.String("100vw"),
+ SrcSet: imagekit.String("https://ik.imagekit.io/demo/image.jpg?tr=w-640 640w, https://ik.imagekit.io/demo/image.jpg?tr=w-1080 1080w, https://ik.imagekit.io/demo/image.jpg?tr=w-1920 1920w"),
+ Width: imagekit.Float(400),
+ },
SolidColorOverlay: shared.SolidColorOverlayParam{
BaseOverlayParam: shared.BaseOverlayParam{
Position: shared.OverlayPositionParam{
diff --git a/file.go b/file.go
index 95a44c3..a35ca04 100644
--- a/file.go
+++ b/file.go
@@ -72,7 +72,7 @@ func (r *FileService) Update(ctx context.Context, fileID string, body FileUpdate
// the cache using purge cache API.
func (r *FileService) Delete(ctx context.Context, fileID string, opts ...option.RequestOption) (err error) {
opts = slices.Concat(r.Options, opts)
- opts = append([]option.RequestOption{option.WithHeader("Accept", "")}, opts...)
+ opts = append([]option.RequestOption{option.WithHeader("Accept", "*/*")}, opts...)
if fileID == "" {
err = errors.New("missing required fileId parameter")
return
diff --git a/go.mod b/go.mod
index 11f9670..a0e1ba6 100644
--- a/go.mod
+++ b/go.mod
@@ -3,8 +3,8 @@ module github.com/imagekit-developer/imagekit-go/v2
go 1.22
require (
- github.com/standard-webhooks/standard-webhooks/libraries v0.0.0-20250711233419-a173a6c0125c
- github.com/tidwall/gjson v1.14.4
+ github.com/standard-webhooks/standard-webhooks/libraries v0.0.0-20251210175704-b03a68fe8b19
+ github.com/tidwall/gjson v1.18.0
github.com/tidwall/sjson v1.2.5
)
diff --git a/go.sum b/go.sum
index 318dc77..f1261e2 100644
--- a/go.sum
+++ b/go.sum
@@ -1,8 +1,8 @@
-github.com/standard-webhooks/standard-webhooks/libraries v0.0.0-20250711233419-a173a6c0125c h1:Mm99t6GdFMtZOwyyvu3q8gXeZX0sqnjvimTC9QCJwQc=
-github.com/standard-webhooks/standard-webhooks/libraries v0.0.0-20250711233419-a173a6c0125c/go.mod h1:L1MQhA6x4dn9r007T033lsaZMv9EmBAdXyU/+EF40fo=
+github.com/standard-webhooks/standard-webhooks/libraries v0.0.0-20251210175704-b03a68fe8b19 h1:8rMUmsyom6y/10iTAgqkfv8zHVKxVQxFwlOb42V23cA=
+github.com/standard-webhooks/standard-webhooks/libraries v0.0.0-20251210175704-b03a68fe8b19/go.mod h1:L1MQhA6x4dn9r007T033lsaZMv9EmBAdXyU/+EF40fo=
github.com/tidwall/gjson v1.14.2/go.mod h1:/wbyibRr2FHMks5tjHJ5F8dMZh3AcwJEMf5vlfC0lxk=
-github.com/tidwall/gjson v1.14.4 h1:uo0p8EbA09J7RQaflQ1aBRffTR7xedD2bcIVSYxLnkM=
-github.com/tidwall/gjson v1.14.4/go.mod h1:/wbyibRr2FHMks5tjHJ5F8dMZh3AcwJEMf5vlfC0lxk=
+github.com/tidwall/gjson v1.18.0 h1:FIDeeyB800efLX89e5a8Y0BNH+LOngJyGrIWxG2FKQY=
+github.com/tidwall/gjson v1.18.0/go.mod h1:/wbyibRr2FHMks5tjHJ5F8dMZh3AcwJEMf5vlfC0lxk=
github.com/tidwall/match v1.1.1 h1:+Ho715JplO36QYgwN9PGYNhgZvoUSc9X2c80KVTi+GA=
github.com/tidwall/match v1.1.1/go.mod h1:eRSPERbgtNPcGhD8UCthc6PmLEQXEWd3PRB5JTxsfmM=
github.com/tidwall/pretty v1.2.0/go.mod h1:ITEVvHYasfjBbM0u2Pg8T2nJnzm8xPwvNhhsoaGGjNU=
diff --git a/internal/apiform/encoder.go b/internal/apiform/encoder.go
index 1d6afb2..58f5621 100644
--- a/internal/apiform/encoder.go
+++ b/internal/apiform/encoder.go
@@ -60,6 +60,7 @@ type encoderField struct {
type encoderEntry struct {
reflect.Type
dateFormat string
+ arrayFmt string
root bool
}
@@ -77,6 +78,7 @@ func (e *encoder) typeEncoder(t reflect.Type) encoderFunc {
entry := encoderEntry{
Type: t,
dateFormat: e.dateFormat,
+ arrayFmt: e.arrayFmt,
root: e.root,
}
@@ -178,34 +180,9 @@ func (e *encoder) newPrimitiveTypeEncoder(t reflect.Type) encoderFunc {
}
}
-func arrayKeyEncoder(arrayFmt string) func(string, int) string {
- var keyFn func(string, int) string
- switch arrayFmt {
- case "comma", "repeat":
- keyFn = func(k string, _ int) string { return k }
- case "brackets":
- keyFn = func(key string, _ int) string { return key + "[]" }
- case "indices:dots":
- keyFn = func(k string, i int) string {
- if k == "" {
- return strconv.Itoa(i)
- }
- return k + "." + strconv.Itoa(i)
- }
- case "indices:brackets":
- keyFn = func(k string, i int) string {
- if k == "" {
- return strconv.Itoa(i)
- }
- return k + "[" + strconv.Itoa(i) + "]"
- }
- }
- return keyFn
-}
-
func (e *encoder) newArrayTypeEncoder(t reflect.Type) encoderFunc {
itemEncoder := e.typeEncoder(t.Elem())
- keyFn := arrayKeyEncoder(e.arrayFmt)
+ keyFn := e.arrayKeyEncoder()
return func(key string, v reflect.Value, writer *multipart.Writer) error {
if keyFn == nil {
return fmt.Errorf("apiform: unsupported array format")
@@ -303,13 +280,10 @@ func (e *encoder) newStructTypeEncoder(t reflect.Type) encoderFunc {
})
return func(key string, value reflect.Value, writer *multipart.Writer) error {
- if key != "" {
- key = key + "."
- }
-
+ keyFn := e.objKeyEncoder(key)
for _, ef := range encoderFields {
field := value.FieldByIndex(ef.idx)
- err := ef.fn(key+ef.tag.name, field, writer)
+ err := ef.fn(keyFn(ef.tag.name), field, writer)
if err != nil {
return err
}
@@ -405,6 +379,43 @@ func (e *encoder) newReaderTypeEncoder() encoderFunc {
}
}
+func (e encoder) arrayKeyEncoder() func(string, int) string {
+ var keyFn func(string, int) string
+ switch e.arrayFmt {
+ case "comma", "repeat":
+ keyFn = func(k string, _ int) string { return k }
+ case "brackets":
+ keyFn = func(key string, _ int) string { return key + "[]" }
+ case "indices:dots":
+ keyFn = func(k string, i int) string {
+ if k == "" {
+ return strconv.Itoa(i)
+ }
+ return k + "." + strconv.Itoa(i)
+ }
+ case "indices:brackets":
+ keyFn = func(k string, i int) string {
+ if k == "" {
+ return strconv.Itoa(i)
+ }
+ return k + "[" + strconv.Itoa(i) + "]"
+ }
+ }
+ return keyFn
+}
+
+func (e encoder) objKeyEncoder(parent string) func(string) string {
+ if parent == "" {
+ return func(child string) string { return child }
+ }
+ switch e.arrayFmt {
+ case "brackets":
+ return func(child string) string { return parent + "[" + child + "]" }
+ default:
+ return func(child string) string { return parent + "." + child }
+ }
+}
+
// Given a []byte of json (may either be an empty object or an object that already contains entries)
// encode all of the entries in the map to the json byte array.
func (e *encoder) encodeMapEntries(key string, v reflect.Value, writer *multipart.Writer) error {
@@ -413,10 +424,6 @@ func (e *encoder) encodeMapEntries(key string, v reflect.Value, writer *multipar
value reflect.Value
}
- if key != "" {
- key = key + "."
- }
-
pairs := []mapPair{}
iter := v.MapRange()
@@ -434,8 +441,9 @@ func (e *encoder) encodeMapEntries(key string, v reflect.Value, writer *multipar
})
elementEncoder := e.typeEncoder(v.Type().Elem())
+ keyFn := e.objKeyEncoder(key)
for _, p := range pairs {
- err := elementEncoder(key+string(p.key), p.value, writer)
+ err := elementEncoder(keyFn(p.key), p.value, writer)
if err != nil {
return err
}
diff --git a/internal/apiform/form_test.go b/internal/apiform/form_test.go
index 3b95794..86cb43d 100644
--- a/internal/apiform/form_test.go
+++ b/internal/apiform/form_test.go
@@ -123,6 +123,18 @@ type StructUnion struct {
param.APIUnion
}
+type MultipartMarshalerParent struct {
+ Middle MultipartMarshalerMiddleNext `form:"middle"`
+}
+
+type MultipartMarshalerMiddleNext struct {
+ MiddleNext MultipartMarshalerMiddle `form:"middleNext"`
+}
+
+type MultipartMarshalerMiddle struct {
+ Child int `form:"child"`
+}
+
var tests = map[string]struct {
buf string
val any
@@ -366,6 +378,19 @@ true
},
},
},
+ "recursive_struct,brackets": {
+ `--xxx
+Content-Disposition: form-data; name="child[name]"
+
+Alex
+--xxx
+Content-Disposition: form-data; name="name"
+
+Robert
+--xxx--
+`,
+ Recursive{Name: "Robert", Child: &Recursive{Name: "Alex"}},
+ },
"recursive_struct": {
`--xxx
@@ -529,6 +554,30 @@ Content-Disposition: form-data; name="union"
Union: UnionTime(time.Date(2010, 05, 23, 0, 0, 0, 0, time.UTC)),
},
},
+ "deeply-nested-struct,brackets": {
+ `--xxx
+Content-Disposition: form-data; name="middle[middleNext][child]"
+
+10
+--xxx--
+`,
+ MultipartMarshalerParent{
+ Middle: MultipartMarshalerMiddleNext{
+ MiddleNext: MultipartMarshalerMiddle{
+ Child: 10,
+ },
+ },
+ },
+ },
+ "deeply-nested-map,brackets": {
+ `--xxx
+Content-Disposition: form-data; name="middle[middleNext][child]"
+
+10
+--xxx--
+`,
+ map[string]any{"middle": map[string]any{"middleNext": map[string]any{"child": 10}}},
+ },
}
func TestEncode(t *testing.T) {
@@ -553,7 +602,7 @@ func TestEncode(t *testing.T) {
}
raw := buf.Bytes()
if string(raw) != strings.ReplaceAll(test.buf, "\n", "\r\n") {
- t.Errorf("expected %+#v to serialize to '%s' but got '%s'", test.val, test.buf, string(raw))
+ t.Errorf("expected %+#v to serialize to '%s' but got '%s' (with format %s)", test.val, test.buf, string(raw), arrayFmt)
}
})
}
diff --git a/internal/apijson/enum.go b/internal/apijson/enum.go
index 18b218a..5bef11c 100644
--- a/internal/apijson/enum.go
+++ b/internal/apijson/enum.go
@@ -29,7 +29,7 @@ type validatorFunc func(reflect.Value) exactness
var validators sync.Map
var validationRegistry = map[reflect.Type][]validationEntry{}
-func RegisterFieldValidator[T any, V string | bool | int](fieldName string, values ...V) {
+func RegisterFieldValidator[T any, V string | bool | int | float64](fieldName string, values ...V) {
var t T
parentType := reflect.TypeOf(t)
diff --git a/internal/version.go b/internal/version.go
index fef6622..436f832 100644
--- a/internal/version.go
+++ b/internal/version.go
@@ -2,4 +2,4 @@
package internal
-const PackageVersion = "2.0.0" // x-release-please-version
+const PackageVersion = "2.1.0" // x-release-please-version
diff --git a/packages/respjson/respjson.go b/packages/respjson/respjson.go
index cc0088c..9e61c5c 100644
--- a/packages/respjson/respjson.go
+++ b/packages/respjson/respjson.go
@@ -5,7 +5,7 @@ package respjson
// Use [Field.Valid] to check if an optional value was null or omitted.
//
// A Field will always occur in the following structure, where it
-// mirrors the original field in it's parent struct:
+// mirrors the original field in its parent struct:
//
// type ExampleObject struct {
// Foo bool `json:"foo"`
diff --git a/shared/shared.go b/shared/shared.go
index 831548c..98859b1 100644
--- a/shared/shared.go
+++ b/shared/shared.go
@@ -196,6 +196,50 @@ func (r *ExtensionAIAutoDescriptionParam) UnmarshalJSON(data []byte) error {
return apijson.UnmarshalRoot(data, r)
}
+// Options for generating responsive image attributes including `src`, `srcSet`,
+// and `sizes` for HTML `
` elements. This schema extends `SrcOptions` to add
+// support for responsive image generation with breakpoints.
+type GetImageAttributesOptionsParam struct {
+ // Custom list of **device-width breakpoints** in pixels. These define common
+ // screen widths for responsive image generation.
+ //
+ // Defaults to `[640, 750, 828, 1080, 1200, 1920, 2048, 3840]`. Sorted
+ // automatically.
+ DeviceBreakpoints []float64 `json:"deviceBreakpoints,omitzero"`
+ // Custom list of **image-specific breakpoints** in pixels. Useful for generating
+ // small variants (e.g., placeholders or thumbnails).
+ //
+ // Merged with `deviceBreakpoints` before calculating `srcSet`. Defaults to
+ // `[16, 32, 48, 64, 96, 128, 256, 384]`. Sorted automatically.
+ ImageBreakpoints []float64 `json:"imageBreakpoints,omitzero"`
+ // The value for the HTML `sizes` attribute (e.g., `"100vw"` or
+ // `"(min-width:768px) 50vw, 100vw"`).
+ //
+ // - If it includes one or more `vw` units, breakpoints smaller than the
+ // corresponding percentage of the smallest device width are excluded.
+ // - If it contains no `vw` units, the full breakpoint list is used.
+ //
+ // Enables a width-based strategy and generates `w` descriptors in `srcSet`.
+ Sizes param.Opt[string] `json:"sizes,omitzero"`
+ // The intended display width of the image in pixels, used **only when the `sizes`
+ // attribute is not provided**.
+ //
+ // Triggers a DPR-based strategy (1x and 2x variants) and generates `x` descriptors
+ // in `srcSet`.
+ //
+ // Ignored if `sizes` is present.
+ Width param.Opt[float64] `json:"width,omitzero"`
+ SrcOptionsParam
+}
+
+func (r GetImageAttributesOptionsParam) MarshalJSON() (data []byte, err error) {
+ type shadow struct {
+ *GetImageAttributesOptionsParam
+ MarshalJSON bool `json:"-"` // Prevent inheriting [json.Marshaler] from the embedded field
+ }
+ return param.MarshalObject(r, shadow{&r, false})
+}
+
type ImageOverlayParam struct {
// Specifies the relative path to the image used as an overlay.
Input string `json:"input,required"`
@@ -216,8 +260,11 @@ type ImageOverlayParam struct {
}
func (r ImageOverlayParam) MarshalJSON() (data []byte, err error) {
- type shadow ImageOverlayParam
- return param.MarshalObject(r, (*shadow)(&r))
+ type shadow struct {
+ *ImageOverlayParam
+ MarshalJSON bool `json:"-"` // Prevent inheriting [json.Marshaler] from the embedded field
+ }
+ return param.MarshalObject(r, shadow{&r, false})
}
func OverlayParamOfText(text string) OverlayUnionParam {
@@ -623,6 +670,32 @@ func (u *OverlayTimingStartUnionParam) asAny() any {
return nil
}
+// Resulting set of attributes suitable for an HTML `
` element. Useful for
+// enabling responsive image loading with `srcSet` and `sizes`.
+//
+// The property Src is required.
+type ResponsiveImageAttributesParam struct {
+ // URL for the _largest_ candidate (assigned to plain `src`).
+ Src string `json:"src,required" format:"uri"`
+ // `sizes` returned (or synthesised as `100vw`). The value for the HTML `sizes`
+ // attribute.
+ Sizes param.Opt[string] `json:"sizes,omitzero"`
+ // Candidate set with `w` or `x` descriptors. Multiple image URLs separated by
+ // commas, each with a descriptor.
+ SrcSet param.Opt[string] `json:"srcSet,omitzero"`
+ // Width as a number (if `width` was provided in the input options).
+ Width param.Opt[float64] `json:"width,omitzero"`
+ paramObj
+}
+
+func (r ResponsiveImageAttributesParam) MarshalJSON() (data []byte, err error) {
+ type shadow ResponsiveImageAttributesParam
+ return param.MarshalObject(r, (*shadow)(&r))
+}
+func (r *ResponsiveImageAttributesParam) UnmarshalJSON(data []byte) error {
+ return apijson.UnmarshalRoot(data, r)
+}
+
type SolidColorOverlayParam struct {
// Specifies the color of the block using an RGB hex code (e.g., `FF0000`), an RGBA
// code (e.g., `FFAABB50`), or a color name (e.g., `red`). If an 8-character value
@@ -640,8 +713,11 @@ type SolidColorOverlayParam struct {
}
func (r SolidColorOverlayParam) MarshalJSON() (data []byte, err error) {
- type shadow SolidColorOverlayParam
- return param.MarshalObject(r, (*shadow)(&r))
+ type shadow struct {
+ *SolidColorOverlayParam
+ MarshalJSON bool `json:"-"` // Prevent inheriting [json.Marshaler] from the embedded field
+ }
+ return param.MarshalObject(r, shadow{&r, false})
}
type SolidColorOverlayTransformationParam struct {
@@ -874,8 +950,11 @@ type SubtitleOverlayParam struct {
}
func (r SubtitleOverlayParam) MarshalJSON() (data []byte, err error) {
- type shadow SubtitleOverlayParam
- return param.MarshalObject(r, (*shadow)(&r))
+ type shadow struct {
+ *SubtitleOverlayParam
+ MarshalJSON bool `json:"-"` // Prevent inheriting [json.Marshaler] from the embedded field
+ }
+ return param.MarshalObject(r, shadow{&r, false})
}
// Subtitle styling options.
@@ -964,8 +1043,11 @@ type TextOverlayParam struct {
}
func (r TextOverlayParam) MarshalJSON() (data []byte, err error) {
- type shadow TextOverlayParam
- return param.MarshalObject(r, (*shadow)(&r))
+ type shadow struct {
+ *TextOverlayParam
+ MarshalJSON bool `json:"-"` // Prevent inheriting [json.Marshaler] from the embedded field
+ }
+ return param.MarshalObject(r, shadow{&r, false})
}
type TextOverlayTransformationParam struct {
@@ -2134,6 +2216,9 @@ type VideoOverlayParam struct {
}
func (r VideoOverlayParam) MarshalJSON() (data []byte, err error) {
- type shadow VideoOverlayParam
- return param.MarshalObject(r, (*shadow)(&r))
+ type shadow struct {
+ *VideoOverlayParam
+ MarshalJSON bool `json:"-"` // Prevent inheriting [json.Marshaler] from the embedded field
+ }
+ return param.MarshalObject(r, shadow{&r, false})
}
diff --git a/usage_test.go b/usage_test.go
index 9e38cfd..6792db9 100644
--- a/usage_test.go
+++ b/usage_test.go
@@ -27,6 +27,7 @@ func TestUsage(t *testing.T) {
option.WithPrivateKey("My Private Key"),
option.WithPassword("My Password"),
)
+ t.Skip("Prism tests are disabled")
response, err := client.Files.Upload(context.TODO(), imagekit.FileUploadParams{
File: io.Reader(bytes.NewBuffer([]byte("https://www.example.com/public-url.jpg"))),
FileName: "file-name.jpg",
diff --git a/webhook.go b/webhook.go
index 6984cf2..192b6ca 100644
--- a/webhook.go
+++ b/webhook.go
@@ -1552,13 +1552,16 @@ func (r *VideoTransformationReadyEventTimings) UnmarshalJSON(data []byte) error
// [UploadPreTransformErrorEvent], [UploadPostTransformSuccessEvent],
// [UploadPostTransformErrorEvent].
//
+// Use the [UnsafeUnwrapWebhookEventUnion.AsAny] method to switch on the variant.
+//
// Use the methods beginning with 'As' to cast the union to one of its variants.
type UnsafeUnwrapWebhookEventUnion struct {
// This field is from variant [VideoTransformationAcceptedEvent],
// [VideoTransformationReadyEvent], [VideoTransformationErrorEvent],
// [UploadPreTransformSuccessEvent], [UploadPreTransformErrorEvent],
// [UploadPostTransformSuccessEvent], [UploadPostTransformErrorEvent].
- ID string `json:"id"`
+ ID string `json:"id"`
+ // Any of nil, nil, nil, nil, nil, nil, nil.
Type string `json:"type"`
CreatedAt time.Time `json:"created_at"`
// This field is a union of [VideoTransformationAcceptedEventData],
@@ -1890,13 +1893,16 @@ func (r *UnsafeUnwrapWebhookEventUnionRequestTransformation) UnmarshalJSON(data
// [UploadPreTransformErrorEvent], [UploadPostTransformSuccessEvent],
// [UploadPostTransformErrorEvent].
//
+// Use the [UnwrapWebhookEventUnion.AsAny] method to switch on the variant.
+//
// Use the methods beginning with 'As' to cast the union to one of its variants.
type UnwrapWebhookEventUnion struct {
// This field is from variant [VideoTransformationAcceptedEvent],
// [VideoTransformationReadyEvent], [VideoTransformationErrorEvent],
// [UploadPreTransformSuccessEvent], [UploadPreTransformErrorEvent],
// [UploadPostTransformSuccessEvent], [UploadPostTransformErrorEvent].
- ID string `json:"id"`
+ ID string `json:"id"`
+ // Any of nil, nil, nil, nil, nil, nil, nil.
Type string `json:"type"`
CreatedAt time.Time `json:"created_at"`
// This field is a union of [VideoTransformationAcceptedEventData],