CHANGELOG.md

# Changelog

All notable changes to this project will be documented in this file.

The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).

## [0.6.1] - 2026-02-11

### Changed

- List operators with a single value (no commas) now pass through as a string instead of a single-element list. This allows Flop to apply its own parsing, such as whitespace splitting for `like_and`/`like_or`/`ilike_and`/`ilike_or`.

## [0.6.0] - 2026-02-11

### Added

- Comma-separated value parsing for list operators (`in`, `not_in`, `like_and`, `like_or`, `ilike_and`, `ilike_or`). For example, `status[in]=draft,published` is now equivalent to `status[in][]=draft&status[in][]=published`. The bracket `[]` syntax still works and serves as an escape hatch for values that contain commas.
- Operator reference table with SQL examples in `FlopRest.Operators` moduledoc.

## [0.5.0] - 2026-02-05

### Changed

- **Breaking**: Renamed cursor pagination params `starting_after` → `after` and `ending_before` → `before` for brevity.

## [0.4.0] - 2025-02-04

### Added

- `FlopRest.normalize/2` with `:for` option for schema-aware filtering. When a schema is provided, only fields in the schema's `filterable` list become filters. Non-filterable params are kept in the result at the root level for custom handling.
- `FlopRest.Filters.extract/2` accepts a `MapSet` of filterable field names and returns a `{filters, extra_params}` tuple.

## [0.3.0] - 2025-02-04

### Changed

- **Breaking**: `to_query/1,2` now returns a map with string keys instead of a keyword list. This is more consistent since operator keys like `"amount[gte]"` don't map cleanly to atoms.

## [0.2.0] - 2025-02-04

### Added

- `FlopRest.to_query/1,2` to convert Flop structs back to REST-style query params
- `FlopRest.build_path/2,3` to build URL paths with REST-style query strings (merges with existing query params)
- `FlopRest.Operators.to_rest/1` for reverse operator mapping (Flop → REST)
- `FlopRest.Pagination.to_rest/1` for reverse pagination transformation
- `FlopRest.Sorting.to_rest/1` for reverse sorting transformation
- `FlopRest.Filters.to_rest/1` for reverse filter transformation
- Accepts both `Flop.t()` and `Flop.Meta.t()` structs

### Changed

- Added `flop` and `plug` as runtime dependencies
- `limit` alone now defaults to cursor-based pagination (`first`) instead of offset-based. This ensures Flop returns cursor metadata for use with `after`/`before`. To use offset-based pagination, include `offset` (e.g., `offset=0&limit=25`).

## [0.1.0] - 2025-02-03

### Added

- Initial release of FlopRest
- `FlopRest.normalize/1` to transform REST-style query params to Flop format
- Filter transformation with support for:
  - Bare values as equality filters (`status=published`)
  - Nested operator syntax (`amount[gte]=100`)
  - All Flop operators: `eq`, `ne`, `lt`, `lte`, `gt`, `gte`, `in`, `not_in`, `contains`, `not_contains`, `like`, `not_like`, `like_and`, `like_or`, `ilike`, `not_ilike`, `ilike_and`, `ilike_or`, `empty`, `not_empty`, `search`
  - Unknown operators passed through for Flop validation
- Sorting transformation:
  - Comma-separated fields (`sort=name,-created_at`)
  - `-` prefix for descending order
  - `+` or no prefix for ascending order
- Pagination support for all three Flop pagination types:
  - Cursor-based (Stripe-style): `limit`, `after`, `before`
  - Page-based: `page`, `page_size`
  - Offset-based: `offset`, `limit`

[0.6.1]: https://github.com/guess/flop_rest/releases/tag/v0.6.1
[0.6.0]: https://github.com/guess/flop_rest/releases/tag/v0.6.0
[0.5.0]: https://github.com/guess/flop_rest/releases/tag/v0.5.0
[0.4.0]: https://github.com/guess/flop_rest/releases/tag/v0.4.0
[0.3.0]: https://github.com/guess/flop_rest/releases/tag/v0.3.0
[0.2.0]: https://github.com/guess/flop_rest/releases/tag/v0.2.0
[0.1.0]: https://github.com/guess/flop_rest/releases/tag/v0.1.0