Skip to content

Releases: ahrefs/atd

4.2.0

26 Apr 04:44

Choose a tag to compare

CHANGES:

  • atdj: Top-level list aliases such as type items = item list are now
    supported. A wrapper class (e.g. Items) implementing Atdj is generated
    with the same interface as record classes: a no-arg constructor, a
    constructor from ArrayList<T>, a constructor from a JSON string, a
    package-private constructor from JSONArray, toJsonBuffer, toJson,
    and a public value field of type ArrayList<T>. List aliases used as
    record fields or sum-variant payloads are also handled correctly.

  • atdml: Generate jsonlike_of_foo serializer functions and Foo.to_jsonlike
    submodule bindings, completing the OCaml ↔ Atd_jsonlike.AST.t round-trip.
    JSON adapters are also supported: if the adapter module M provides
    restore_jsonlike, it is called after serialization by jsonlike_of_foo.

  • atd-jsonlike: Add Pos.zero and Loc.zero — zero-position / zero-location
    constants useful for constructing AST.t nodes programmatically when source
    location information is not available.

  • atd-yamlx: Add to_yamlx_value : Atd_jsonlike.AST.t -> YAMLx.value, the
    reverse of of_yamlx_value. Enables programmatic construction of YAML
    documents from ATD-typed OCaml values via jsonlike_of_foo.

4.1.0

12 Apr 03:27
fbadf0d

Choose a tag to compare

CHANGES:

  • Build: OCaml >= 4.14 is now required (previously 4.08). This aligns
    all packages with the yamlx dependency of atd-yamlx.

  • Testing: Add a standard JSON round-trip test suite (standard-tests/)
    that any code generator can opt into. The harness generates code from an
    ATD spec, compiles it, feeds JSON to stdin, and checks the output.
    atdml is the first backend to run these tests.

  • New package: atd-yamlx. Translates a parsed YAML value
    (YAMLx.value from the yamlx library) into Atd_jsonlike.AST.t,
    preserving source locations at every node so that ATD-generated reader
    functions (foo_of_jsonlike) can report precise file/line/column error
    messages when deserializing YAML configuration files.

    • of_yamlx_value returns (AST.t, string) result; the raising variant
      is of_yamlx_value_exn.
    • atd-yamlx/examples/ is a self-contained dune subproject demonstrating
      a typed YAML config reader built with atdml and atd-yamlx.
  • All backends: Add <json repr="object"> on sum types. Tagged variants are
    encoded as single-key JSON objects {"Constructor": payload} instead of the
    default ["Constructor", payload] arrays. Unit variants are unaffected
    ("Constructor" strings). This matches Serde's externally-tagged
    representation and produces idiomatic YAML (a single-key mapping rather than
    a two-element sequence). Supported in: atdml (OCaml), atdpy (Python),
    atdts (TypeScript), atdcpp (C++), atdd (D), atdj (Java), atds (Scala).
    atdml additionally generates of_jsonlike readers automatically.

  • New package: atd-jsonlike. Defines a generic JSON-like AST
    (Atd_jsonlike.AST.t) with source location information at every node.
    Intended as a target type for code generated by ATD tools, so that
    reader functions can report precise file/line/column error messages.
    Supports JSON numbers via Atd_jsonlike.Number.t, which stores all
    available representations (int, float, and literal string) for
    maximum flexibility.

  • atdml: Generate foo_of_jsonlike reader functions that accept an
    Atd_jsonlike.AST.t value and return a typed OCaml value, with error
    messages that include the original source location.

    • Default output is Yojson-based readers/writers only (no atd-jsonlike
      dependency unless explicitly requested).
    • New --mode MODE option (repeatable) selects what to generate.
      MODE is a mode name or comma-separated list of mode names.
      Valid modes: yojson, jsonlike, all (= yojson + jsonlike).
      Example: atdml --mode yojson,jsonlike foo.atd
    • JSON adapters (<json adapter.ocaml="M">) are supported for the jsonlike
      path: if the adapter module M provides normalize_jsonlike, it is called
      before deserialization by foo_of_jsonlike. Inline adapters
      (adapter.to_ocaml/adapter.from_ocaml) do not support jsonlike.

4.0.0

17 Mar 03:38

Choose a tag to compare

CHANGES:

  • Build: Dune >= 3.18 (April 2025) is now required to build the ATD tools
    from source. (#445)

  • atdcat: read from stdin when no input file is given, like cat.

  • ATD: Experimental. Module support via new from ... import ... syntax.
    Types to be used must be listed explicitly; the full syntax is:

    from module.path <annots> [as alias] import type1 <annots>, type2, ...
    

    Key properties:

    • Imported types must be listed explicitly
      (e.g. from mylib import date, status).
    • Supported languages: OCaml (atdml, not atdgen), Python (atdpy),
      TypeScript (atdts)
    • Parameterized types declare their arity: from mylib import 'a list_ne.
    • The arity of each imported type is enforced at all use-sites within the
      importing file.
    • Aliases are plain names without annotations: from foo as f import t.
    • Language-specific name annotations go on the module path:
      <python name="..."> for atdpy, <ts name="..."> for atdts,
      <ocaml name="..."> for atdml.
    • atdpy: alias names that are Python keywords are automatically suffixed
      with _ (e.g. alias classclass_ in generated code).
    • atdts: Dotted module paths in import declarations are now mapped to
      path-separator form in the generated TypeScript import path.
      For example, import long.module.path generates
      import * as path from "./long/module/path" rather than "./path".
    • A warning is printed to stderr when an imported type name is never
      referenced in any type expression.

    Examples:

    (* Import specific types from a module *)
    from mylib.common import date, status
    
    (* Import with alias *)
    from long.module.path as ext import tag
    
    (* Override OCaml module name *)
    from mylib.common <ocaml name="Mylib_common"> import date
    
  • atdml: Experimental. New tool. Generates a single self-contained OCaml module (.ml +
    .mli) from a single .atd file, with JSON support via Yojson.Safe.t.
    No separate runtime library is required; the runtime helpers are inlined
    into each generated .ml. Atdml is the recommended successor to atdgen
    for OCaml JSON support.
    Supported features:

    • All primitive ATD types: unit, bool, int, float, string
    • abstract type, represented as Yojson.Safe.t
    • 'a list, 'a option, 'a nullable
    • Tuples: ('a * 'b * ...)
    • Records, including required fields, optional fields (?foo),
      and with-default fields (~foo) with implicit or explicit defaults
      (<ocaml default="...">)
    • <ocaml field_prefix="pre_"> on record types: prepends the given prefix
      to all OCaml record field names while keeping the labeled arguments of
      create_ unprefixed (e.g. create_point ~x ~y () : point). JSON field
      names are unaffected.
    • Classic sum types (regular OCaml variants) and polymorphic variants
      (<ocaml repr="poly">)
    • Parametric types
    • Mutually recursive types (detected automatically via topological sort;
      and is used only when strictly necessary)
    • wrap construct with <ocaml module="M"> or explicit
      <ocaml t="..." wrap="..." unwrap="...">
    • JSON adapters via <json adapter.ocaml="M"> (module providing normalize
      and restore) or <json adapter.to_ocaml="..." adapter.from_ocaml="...">
      (inline expressions); supported on sum types and records
    • <json name="..."> to override JSON field or constructor names
    • <ocaml name="..."> to rename variant constructors in OCaml
    • <ocaml attr="..."> to attach ppx attributes (e.g. [@@deriving show])
      to generated type definitions
    • <ocaml private> on any type definition forces private in the generated
      .mli; <ocaml public> on a primitive alias suppresses the default
      private, making the alias transparent to callers
    • Unparameterized aliases of primitive types (unit, bool, int,
      float, string) are generated as private in the .mli, preventing
      direct construction outside the module. A constructor function
      create_email : string -> email is generated (also exposed as
      val create in submodule Email). Coerce back with :>
      (e.g. (x :> string)).
    • <doc text="..."> documentation annotations, translated into ocamldoc
      (** ... *) comments in the generated code; supported on type definitions,
      record fields, variant constructors, and module-level head annotations
    • Automatic renaming of ATD type names that conflict with OCaml keywords
      or with the foo_of_yojson/yojson_of_foo naming scheme
    • Automatic renaming of record fields and variant constructors that conflict
      with OCaml keywords (e.g. endend_)
    • (string * 'a) list <json repr="object">: encode association lists as
      JSON objects {"key": value, ...} rather than arrays
    • Graceful handling of atdgen annotations not supported by atdml:
      <ocaml module="..."> on type definitions and <ocaml name="..."> on
      record fields emit a warning and are otherwise ignored
    • ~field: user_type with no OCaml default: warns and treats the field as
      required in JSON (no create_ function generated for that type)
    • Record creation functions are named create_foo (not make_foo),
      matching atdgen's convention
    • Stdin mode: reads ATD from stdin, writes a copy-pasteable
      module type Types = sig ... end / module Types : Types = struct ... end
      snippet to stdout
    • Each generated type gets a submodule (module Foo) bundling the type
      and its conversion functions

3.0.1

10 Dec 04:55
5cd9868

Choose a tag to compare

CHANGES:

  • atdgen: -j-std now implies -j like before to avoid breaking
    existing uses. A warning is now also printed to encourage migration (#443)

3.0.0

10 Dec 02:22

Choose a tag to compare

CHANGES:

  • atdgen: Add option -j-gen-modules to generate JSON generic submodules (#420)
  • atd-parser: improve (syntax) error messages (#426)
  • atdts: Add support for <ts from...> annotations
  • atdpy: Add support for <doc text=...> annotations, turning them
    into docstrings similar to the ocamldoc comments produced by atdgen.
  • atdgen: Remove option -j-std, now it's the default, one cannot
    generate extended-JSON (#425). Options -j-std and -std-json are
    still available as backward-compatibility no-ops unless
    environment variable ATDGEN_FAIL_DEPRECATED_OPTIONS is set to true in
    which case their use results in an exception.

2.16.0

23 Jan 01:56

Choose a tag to compare

CHANGES:

  • atdgen: Breaking change, migrate from Bucklescript to Melange (#375)
  • atdd: Workaround d compiler bug regarding declaration order when using aliases (#393)
    Algebraic data types (SumType) now uses alias this syntax.
  • atdgen: Add support for <json open_enum> in Melange (#401)
  • atdcpp: Initial Release (#404)
  • atdcpp: Use double c++ type as default floating point type (#411)
  • atdgen: Fix JSON I/O for inline records (#419)
  • atdgen: The deprecated atdgen library is no longer available.
    Use atdgen-runtime instead (#421)
  • atddiff: To ensure that all the intended types are checked when new
    type definitions are added to an ATD file, an --ignore
    option is now available. It makes atddiff fail if some types
    are neither selected via --types nor ignored via --ignore.

2.15.0

27 Oct 03:05

Choose a tag to compare

CHANGES:

  • atddiff: Breaking changes in the JSON output format of atddiff (#382)
  • atddiff: Fix atddiff --version output (#379)
  • atddiff: New experimental option --no-locations aimed at
    producing more stable results that allow diffing successive
    atddiff reports to spot new findings and ignore old ones (#377)

2.14.1

21 Oct 00:30

Choose a tag to compare

CHANGES:

  • atddiff: Fixed reports for new variant cases. They are now correctly
    reported as forward incompatibilities (#373)

2.14.0

19 Oct 22:59

Choose a tag to compare

CHANGES:

  • atdd: Fix various issues with the interoperability of user defined types,
    used in or outside of records (#355)
  • atdd: Generated .d files now have the suffix _atd.d (#355)
  • atddiff now supports options for filtering the findings based on the
    direction of the incompatibility (--backward, --forward) or based on the
    name of the affected types (--types) (#365)
  • atddiff: new option --output-format json for exporting the results to
    JSON (#360)

2.13.0

16 Oct 02:52

Choose a tag to compare

CHANGES:

  • atdts: Stop compiler errors on generated typescript (#348)
  • atdts: Don't fail on wrap constructs (#353)
  • atdcat: New option -remove-wraps which pretty-prints the type
    definitions without wrap constructs (#353)
  • atdd: Add dlang backend to generate D code from ATD definitions (#349)
  • new tool: atddiff. Compares two versions of an ATD file and reports
    possible incompatibilities in the JSON data. Atddiff ships as part of the
    atd package together with atdcat (#352, #358)