mmzk-env-0.5.0.0: CHANGELOG.md
# Revision history for mmzk-env
## 0.5.0.0 -- 2026-07-01
### Value-level schema redesign (breaking)
The witness-column system has been replaced with a value-level schema
pattern. Schema records now use the `Col` column family instead of
`Column`/`Di`:
```haskell
-- Before:
data Config c = Config
{ port :: Di (DefaultNum 5432) c Int
, host :: Di (DefaultString "localhost") c Text }
-- After:
data Config c = Config
{ port :: Col c Int
, host :: Col c Text }
```
`Col 'Dec a = String -> Either String a` — each field in the declaration
record holds a parser function. `Col 'Res a = a` — unchanged.
`validateEnvW` now takes the schema value explicitly instead of a type
application:
```haskell
-- Before:
validateEnvW @(Config 'Dec)
-- After:
validateEnvW myConfig -- myConfig :: Config 'Dec
validateEnvWDefault @Config -- auto-derive from TypeParser instances
```
`parseRecordW` likewise takes the schema value:
```haskell
-- Before:
parseRecordW @(Config 'Dec) envMap
-- After:
parseRecordW myConfig envMap
```
`Column`, `Di`, and the old type-application-only `parseRecordW`/`validateEnvW`
are removed.
### New exports in `Data.Env.RecordParserW`
* `Col` — type family replacing `Column`/`Di`.
* `typeParser @T` — builds the standard `String -> Either String T` parser
from the `TypeParser T` instance.
* `f \`orElse\` d` — sets the fallback value when the env variable is
absent or empty; designed for infix: `typeParser @Int \`orElse\` 5432`.
* `fromTypeParserW @W` — bridges an existing `TypeParserW` witness into a
field function.
* `HasDefaultSchema` / `defaultSchema @T` — generically derives a
`T 'Dec` value whose every field uses `typeParser`.
* `validateEnvWDefault @T` — shorthand for
`validateEnvW (defaultSchema @T)`.
### `TypeParser` and `TypeParserW` unchanged
`TypeParser`, `TypeParserW`, and all witness modules (`DefaultNum`,
`DefaultString`, `DefaultBool`) are unchanged. Witnesses remain usable
via `fromTypeParserW`.
## 0.4.0.0 -- 2026-04-16
**Breaking changes:**
* `validateEnv`, `validateEnvWith`, `validateEnvW`, `validateEnvWWith`, `parseRecord`, and `parseRecordW` now return `Either ParseError a` instead of `Either String a`. Code that matches on `Left err` where `err :: String` must be updated to use `renderParseError err` (or pattern-match on `ParseError`/`FieldError`).
* `TypeParser` gains a new method `parseMissing :: Either String a` (default: `Left "missing required environment variable"`). Custom `TypeParser` instances that handled the empty-string case inside `parseType` to supply a default **must** move that logic to `parseMissing` — `parseType ""` is no longer called for absent environment variables.
* `TypeParserW` gains a new method `parseMissingW :: Proxy p -> Either String a` (default: `parseTypeW proxy ""`). Custom `TypeParserW` instances that relied on `parseTypeW proxy ""` being called for absent variables are unaffected by the default; however, the same caveat as `parseMissing` applies if an instance overrides `parseTypeW` for the empty-string case.
**New exports:**
* `Data.Env.ParseError` is now an exposed module exporting `ParseError(..)`, `FieldError(..)`, `renderParseError`, and `renderFieldError`. All are also re-exported from `Data.Env`.
**Improved error messages:**
* All field failures are now collected in a single pass (no short-circuiting on the first error). `ParseError` is a list of `FieldError` values, one per failing field, in field-declaration order.
* Missing required environment variables now produce `"missing required environment variable"` instead of a gigaparsec parse error on an empty string.
* Base type parsers (`String`, `Int`, `Word`, `Bool`, numeric fixed-width types) now use `P.label` to produce readable expected-descriptions (e.g. `expected an integer`) instead of raw token expectations.
* `renderParseError` formats errors with the field name on its own header line followed by the detail indented below; multiple failures are numbered.
* `EnumParser` error messages now read `invalid value "x"; expected one of: A, B, C` instead of the previous format.
## 0.3.0.0 -- 2026-03-22
* Fixed `DefaultBool` to follow the proper witness pattern:
* Changed from a newtype with `TypeParser` to a phantom type with `TypeParserW`.
* Added second type parameter (consistent with `DefaultNum` and `DefaultString`) enabling use with the `Di` type alias.
* `DefaultBool` now accepts `True`, `False`, `true`, `false`, `T`, `F`, `t`, `f`, `1`, `0`.
## 0.2.1.1 -- 2026-03-22
* Added `DefaultBool` for `Bool` fields with a type-level default value.
* Added `DataKinds` to default extensions.
## 0.2.1.0 -- 2025-11-30
* Add the missing `validateEnvW` and `validateEnvWWith` functions for validating environment variables with witness types.
* Add `DefaultString` witness type for providing default string values.
* Add more texts and examples.
## 0.2.0.0 -- 2025-11-29
* Witnessed record parsing (witness types carry type-level information that determines parsing behaviour):
* Add `RecordParserW` for witnessed record parsing.
* Add `TypeParserW` for witnessed type parsing.
* Add `DefaultNum` witness type for providing default numeric values.
* Add convenient `Maybe` result variants for parsers.
* Add runnable example executables in `app/`:
* `quickstart-example`: Basic environment validation example.
* `enum-example`: Enumerated type parsing example.
* `newtype-example`: Custom parser with newtype wrapper example.
* `witness-example`: Witness types with default values example.
* Add more tests.
* Heavy refactoring.
## 0.1.2.0 -- 2025-11-16
* Add support for parsing `Text`.
## 0.1.1.1 -- 2025-09-29
* Fix typo in the cabal file.
## 0.1.1.0 -- 2025-09-28
* Added support for parsing enumerated types using `EnumParser`.
* Updated documentation to include examples of enum parsing.
## 0.1.0.0 -- 2025-08-03
* First version. Released on an unsuspecting world.