packages feed

mmzk-env-0.6.0.0: CHANGELOG.md

# Revision history for mmzk-env


## 0.6.0.0 -- 2026-09-06

**Breaking changes:**

* `TypeParserW` no longer re-exports `Solo`; import it from `Data.Tuple` instead.

* `EnumParser` no longer derives `Eq`.

**New exports:**

* `Data.Env` gains pure variants of the top-level validators: `validateEnvFromMap`, `validateEnvFromMapWith`, `validateEnvWFromMap`, `validateEnvWFromMapWith`, and `validateEnvWDefaultFromMap`. These validate against a simulated `Map String String` environment instead of the real process environment — no `MonadIO`, no `setEnv`/`unsetEnv`, safe for parallel tests.

* `Data.Env.ExtractFields` gains `extractFieldsFromMap` and `extractFieldsFromMapCamelCaseToUpperSnake`, pure variants of `getEnvRaw` and `getEnvRawCamelCaseToUpperSnake` that read from a supplied `Map` instead of the real process environment. `camelToUpperSnake` is now exported.

**Other changes:**

* The `TypeParserW` pair instance is generalised from `(TypeParserW p1 String, TypeParserW p2 String) => TypeParserW (p1, p2) String` to `(TypeParserW p1 String, TypeParserW p2 a) => TypeParserW (p1, p2) a`: the first witness preprocesses the raw string (e.g. trims or validates it), and its output is fed to the second witness, which resolves the final value of any type. Composite witnesses that previously resolved to `String` are unaffected.

* `EnumParser`'s `parseMissing` message now lists the valid constructor names, and invalid-value messages use plain quotes instead of `show`, which escaped internal quotes and backslashes confusingly.

* The `Validation` applicative for error accumulation, previously duplicated in `RecordParser` and `RecordParserW`, is extracted into a shared internal module `Data.Env.Internal.Validation`. It is not exported from the library API.

* Removed the unused generic `default parseType` from `TypeParser` (`GTypeParser` had no instances and was never exported).

* `ParseError` and `FieldError` now derive `Ord`.

* New `ValidateEnvSpec` test suite covering the top-level interface and the pure `*FromMap` variants.


## 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.