Skip to content

Commit 134cc0e

Browse files
authored
feat(simplestorage): add ListResult type and enhance List with pagination (#14)
Add ContentDisposition and URL fields to Object struct to make it a strict superset of the TypeScript SDK Item type. Change List function to return *ListResult instead of []Object, matching the TypeScript list() function semantics with Items, NextToken, and HasMore fields for proper pagination support. Add new ClientOption functions: - WithDelimiter for grouping keys - WithPrefix for filtering keys by prefix - WithPaginationToken for pagination continuation BREAKING CHANGE: List() signature changed from List(ctx, prefix, opts) to List(ctx, opts). Use WithPrefix(prefix) option instead. Assisted-by: GLM 4.7 via Claude Code Signed-off-by: Xe Iaso <xe@tigrisdata.com>
1 parent 535c666 commit 134cc0e

1 file changed

Lines changed: 66 additions & 21 deletions

File tree

simplestorage/client.go

Lines changed: 66 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -57,15 +57,39 @@ func WithMaxKeys(maxKeys int32) ClientOption {
5757
}
5858
}
5959

60+
// WithDelimiter sets a delimiter for grouping keys in List calls.
61+
func WithDelimiter(delimiter string) ClientOption {
62+
return func(co *ClientOptions) {
63+
co.Delimiter = aws.String(delimiter)
64+
}
65+
}
66+
67+
// WithPrefix sets the prefix to filter keys in List calls.
68+
func WithPrefix(prefix string) ClientOption {
69+
return func(co *ClientOptions) {
70+
co.Prefix = aws.String(prefix)
71+
}
72+
}
73+
74+
// WithPaginationToken sets the pagination token to continue listing objects.
75+
func WithPaginationToken(token string) ClientOption {
76+
return func(co *ClientOptions) {
77+
co.PaginationToken = aws.String(token)
78+
}
79+
}
80+
6081
// ClientOptions is the collection of options that are set for individual Tigris
6182
// calls.
6283
type ClientOptions struct {
6384
BucketName string
6485
S3Options []func(*s3.Options)
6586

6687
// List options
67-
StartAfter *string
68-
MaxKeys *int32
88+
StartAfter *string
89+
MaxKeys *int32
90+
Delimiter *string
91+
Prefix *string
92+
PaginationToken *string
6993
}
7094

7195
// defaults populates client options from the global Options.
@@ -130,14 +154,23 @@ func New(ctx context.Context, options ...Option) (*Client, error) {
130154
// Some calls may not populate all fields. Ensure that the values are valid before
131155
// consuming them.
132156
type Object struct {
133-
Bucket string // Bucket the object is in
134-
Key string // Key for the object
135-
ContentType string // MIME type for the object or application/octet-stream
136-
Etag string // Entity tag for the object (usually a checksum)
137-
Version string // Version tag for the object
138-
Size int64 // Size of the object in bytes or 0 if unknown
139-
LastModified time.Time // Creation date of the object
140-
Body io.ReadCloser // Body of the object so it can be read, don't forget to close it.
157+
Bucket string // Bucket the object is in
158+
Key string // Key for the object
159+
ContentType string // MIME type for the object or application/octet-stream
160+
ContentDisposition string // Content disposition of the object (inline or attachment)
161+
Etag string // Entity tag for the object (usually a checksum)
162+
Version string // Version tag for the object
163+
Size int64 // Size of the object in bytes or 0 if unknown
164+
LastModified time.Time // Creation date of the object
165+
URL string // Public or presigned URL for the object
166+
Body io.ReadCloser // Body of the object so it can be read, don't forget to close it.
167+
}
168+
169+
// ListResult contains the result of a List operation, including pagination information.
170+
type ListResult struct {
171+
Items []Object // List of objects
172+
NextToken string // Pagination token for the next page
173+
HasMore bool // Whether there are more objects to list
141174
}
142175

143176
// Get fetches the contents of an object and its metadata from Tigris.
@@ -226,8 +259,12 @@ func (c *Client) Delete(ctx context.Context, key string, opts ...ClientOption) e
226259
return nil
227260
}
228261

229-
// List returns a list of objects matching a key prefix.
230-
func (c *Client) List(ctx context.Context, prefix string, opts ...ClientOption) ([]Object, error) {
262+
// List returns a list of objects matching the given criteria.
263+
//
264+
// The returned ListResult contains pagination information; use NextToken with
265+
// WithPaginationToken() to fetch the next page. HasMore indicates whether
266+
// additional objects are available.
267+
func (c *Client) List(ctx context.Context, opts ...ClientOption) (*ListResult, error) {
231268
o := new(ClientOptions).defaults(c.options)
232269

233270
for _, doer := range opts {
@@ -237,25 +274,33 @@ func (c *Client) List(ctx context.Context, prefix string, opts ...ClientOption)
237274
resp, err := c.cli.ListObjectsV2(
238275
ctx,
239276
&s3.ListObjectsV2Input{
240-
Bucket: aws.String(o.BucketName),
241-
Prefix: aws.String(prefix),
242-
243-
MaxKeys: o.MaxKeys,
244-
StartAfter: o.StartAfter,
277+
Bucket: aws.String(o.BucketName),
278+
Delimiter: o.Delimiter,
279+
Prefix: o.Prefix,
280+
MaxKeys: o.MaxKeys,
281+
ContinuationToken: o.PaginationToken,
282+
StartAfter: o.StartAfter,
245283
},
246284
o.S3Options...,
247285
)
248286

249287
if err != nil {
250-
return nil, fmt.Errorf("simplestorage: can't list %s/%s: %v", o.BucketName, prefix, err)
288+
return nil, fmt.Errorf("simplestorage: can't list %s: %v", o.BucketName, err)
251289
}
252290

253-
var result []Object
291+
result := &ListResult{
292+
Items: make([]Object, 0, len(resp.Contents)),
293+
HasMore: lower(resp.IsTruncated, false),
294+
}
295+
296+
if resp.NextContinuationToken != nil {
297+
result.NextToken = *resp.NextContinuationToken
298+
}
254299

255300
for _, obj := range resp.Contents {
256-
result = append(result, Object{
301+
result.Items = append(result.Items, Object{
257302
Bucket: o.BucketName,
258-
Key: *obj.Key,
303+
Key: lower(obj.Key, ""),
259304
Etag: lower(obj.ETag, ""),
260305
Size: lower(obj.Size, 0),
261306
LastModified: lower(obj.LastModified, time.Time{}),

0 commit comments

Comments
 (0)