degenerate 0.4.2
degenerate: ^0.4.2 copied to clipboard
Generate typesafe Dart API clients from OpenAPI 3.x specs. Produces idiomatic models, serialization, and HTTP clients with pluggable adapters.
Changelog #
Important user-facing changes only. For full details see commit log.
0.4.2 #
Bug fixes for enum parameter serialization, generated security helpers, and union parsing; anyOf + discriminator support.
Bug fixes #
- Enum path parameters interpolate their wire value (#7): a path parameter whose schema is a
$refstring enum produced debug strings likeColor(red)in request URLs. Path interpolation now uses the enum's underlying value, and every other parameter serialization site (query, header, cookie, deepObject fields, list items, multipart text fields) was hardened so non-string enums and non-string-backed extension types no longer generate uncompilable code. - apiKey schemes missing
inornameno longer emit uncompilable code (#8): the generator defaults a missingnameto the scheme key and a missing/invalidintoheader(each with a CLI warning), and thewith<Scheme>facade helper is only emitted when its matchingapply<Scheme>method exists. - Security requirement lists are explicitly typed (#9): operations opting out via
security: []emitted an untyped[]inferred asList<dynamic>; all requirement lists now carry an explicit<ApiSecurityRequirement>type argument. OneOf.parsefalls through onError, not justException(#10, thanks @josher8a): a variant'sfromJsonthat discriminates by casting (e.g.json['x'] as String) throws aTypeErrorwhen the payload is a different variant; trial-parsing previously aborted instead of trying the next variant.- Union variant names no longer collide with their referenced model: when the derived variant name
<UnionName><PascalCase(value)>matches the referenced schema's own class name (e.g. OpenAI's Realtime events), the wrapper now uses a$separator (RealtimeClientEvent$SessionUpdate), fixing ambiguous barrel exports and a self-recursivefromJson.
Improvements #
anyOf+discriminatorgenerates sealed unions (#10, thanks @josher8a): schemas usinganyOfwith a discriminator (allowed by the OpenAPI spec) now lower to the same sealed-class hierarchy asoneOfwhen every variant is a$ref, instead of an untaggedOneOfN. Affected schemas in regenerated clients change shape accordingly (e.g. OpenAI'sResponsesClientEvent).
0.4.1 #
Generated code is now lint-clean under very_good_analysis.
Breaking changes #
OneOf.parsecallback signature: callback parameter type changed fromObject?toObject(withjson!assertion in runtime). Callers passing nullable values to parse callbacks will need to add a!assertion.@immutableannotation: re-exported fromdegenerate_runtime. Generated model, enum, and union variant classes are now annotated@immutable.
Improvements #
- Lint-clean generated output: generated Dart code now passes
dart analyzewith zero issues undervery_good_analysisfor all tested specs (Stripe, GitHub, Cloudflare, Twilio, etc.).- Constructors ordered before fields/methods (
sort_constructors_first) - Required named parameters before optional (
always_put_required_named_parameters_first) - Files end with exactly one trailing newline (
eol_at_end_of_file) - Imports/exports sorted alphabetically (
directives_ordering) - Security scheme literals omit redundant default values and use
const(avoid_redundant_argument_values,prefer_const_constructors) - Raw strings and double-quoted strings used to avoid unnecessary escapes (
use_raw_strings,avoid_escaping_inner_quotes) - Identity map transforms like
.map((k, v) => MapEntry(k, v))are elided (unnecessary_lambdas) - Simple closures like
(e) => base64Encode(e)emit tearoffs (unnecessary_lambdas) - Empty model
fromJsonuses_for unused parameter andconstreturn (avoid_unused_constructor_parameters,prefer_const_constructors) - Doc comment
[references]escaped to avoid false Dart doc links (comment_references) - Fenced code blocks in doc comments get a language specifier (
missing_code_block_language_in_doc_comment) - Form-urlencoded body list literals are explicitly typed (
inference_failure_on_collection_literal) - Untagged union
fromJsoncasts accessor toMap<String, dynamic>for object variants (argument_type_not_assignable) - Extension type multipart serialization skips redundant
.toString()whentoJson()already returnsString(noop_primitive_operations)
- Constructors ordered before fields/methods (
0.4.0 #
Critical fixes for discriminated unions, streaming, and runtime ergonomics.
Breaking changes #
OneOftypes simplified: the sealed subclass hierarchy (OneOf2A,OneOf2B, etc.) is replaced by a singlefinal classper arity. Code usingis OneOf2Achecks must switch to matching on.valuetype instead. Named constructors.a(),.b(),.c()etc. provide concise construction with Dart's implicit context syntax (e.g.model: .b(.gpt4oMini)).
Bug fixes #
- Discriminator enum value extraction: inferred discriminator mappings now extract the actual enum value from referenced schemas (e.g.
'system'fromrole: enum: [system]) instead of using schema names. Fixes OpenAIChatCompletionRequestMessagedispatch and similar patterns. - Streaming interceptor bypass:
executeStreamingandexecuteJsonlStreamingnow run through the full interceptor chain (auth, retry, logging) before sending. Previously interceptors were completely bypassed for streaming requests, causing silent auth failures. - Mid-stream error wrapping: network errors during SSE/JSONL streaming (SocketException, etc.) are now wrapped in
ApiStreamErrorinstead of propagating as raw platform exceptions.
Improvements #
- OneOf variant deduplication: inline unions with duplicate variant types (e.g.
OneOf3<A, A, B>) are collapsed to remove redundant variants (OneOf2<A, B>). - Shorter discriminated union variant names: variant class names now use the discriminator enum value (
ChatCompletionRequestMessageSystem) instead of the full schema name (ChatCompletionRequestMessageChatCompletionRequestSystemMessage). - Added
example.mdwith real-world usage patterns (OpenAI, streaming, Riverpod, envelope unwrapping).
0.3.0 #
Major feature release: allOf composition, additionalProperties, streaming, and OAS 3.2 support.
New features #
additionalPropertiessupport: objects withadditionalPropertiesnow generate a typed overflowMap<String, T>field. Extra keys are preserved during fromJson/toJson round-trips instead of being silently dropped. Supports typed values, dynamic, and recursive self-references.allOfcomposition:allOfschemas that combine a$refwith extra inline properties now produce a merged object with all fields from both the ref target and the inline schema, instead of silently dropping the extra properties.--unwrap-fieldsCLI option: unwrap response envelopes by extracting a named field.--unwrap-fields=resultreturns theresulttype directly instead of the full{errors, messages, success, result}envelope — matching what Stainless generates for Cloudflare SDKs.- OAS 3.2
querymethod: the HTTP QUERY method (safe method with request body) is now a first-class operation. - OAS 3.2
additionalOperations: custom HTTP methods (COPY, LOCK, PURGE, etc.) via the path item'sadditionalOperationsmap. - Typed streaming via
itemSchema: SSE and JSONL responses withitemSchemanow returnStream<T>with typed deserialization instead ofvoid. - JSONL streaming:
application/jsonlandapplication/x-ndjsonmedia types are now supported with a dedicatedexecuteJsonlStreamingruntime method. - Integer and number enums: enum schemas with
type: integerortype: numbernow generate typed enums withint/doublevalues, not just string enums. content-based parameter schemas: parameters using the OAS 3.xcontentfield (instead ofschema) now have their schema correctly extracted.- OAuth2
deviceAuthorization: the device authorization flow type anddeviceAuthorizationUrlare now supported.
Bug fixes #
- String literal escaping:
$,\n,\r,\t, and Unicode bidi/zero-width characters are now properly escaped in generated string literals. - Object member name conflicts: fields and methods named
toString,hashCode,runtimeType, ornoSuchMethodare prefixed with$to avoid conflicts withObjectmembers. - Discriminator mapping keys: inferred
oneOfdiscriminator mappings now use the original schema names as switch keys, not the Dart type names. - Discriminator
toJsoncollision: union varianttoJsonspreads the variant first and sets the discriminator key last, so the discriminator always wins over fields with the same name. type: "null"handling:type: "null"now maps to nullabledynamicinstead ofString.canParsefor optional-only models: models with no required fields now check for at least one known property key instead of returningtrueunconditionally.- Latin character transliteration: accented characters are transliterated to ASCII (
café→cafe) instead of being stripped (caf). - Enum casing: leading
+/-before letters in enum values no longer corrupts casing (+NaN→naN, notNaN). - Query/header parameter key escaping:
$and special characters in parameter names are properly escaped in generated map key strings.
0.2.1 #
- Fix required-but-nullable query parameters generating invalid assignments (
String?assigned toMap<String, String>) - Add totem-web.json to snapshot testing
0.2.0 #
Breaking changes to CLI defaults and output structure.
- New default output: generated code goes to
lib/<name>/(waslib/src/generated/). The-nflag sets the package name (default:api_client) and is appended to the-obase directory. - Workspace mode (
--workspace): generates a standalone Dart package withpubspec.yamltopackages/<name>/(customizable with-o). Includesresolution: workspacefor Dart workspaces. - Flattened directory structure: removed the
src/directory from generated output. Models, APIs, client, and barrel file are now siblings (e.g.models/,apis/,client/,<name>.dart). Workspace mode wraps these underlib/. - No pubspec in default mode: the CLI prints the dependencies you need to add to your own
pubspec.yamlafter generation. - Post-generation instructions: the CLI now prints setup instructions (dependencies for default mode, workspace + dependency config for workspace mode).
- Unformatted output: generated code is no longer annotated with
// dart format off. Rundart formaton the output to apply your project's formatting preferences. - Dropped
collectiondependency: replacedListEqualitywith a built-inlistEqualsindegenerate_runtime. One fewer dependency for generated code. - Simplified file headers: generated files now contain only
// GENERATED CODE - DO NOT MODIFY BY HAND.
0.1.5 #
- Fix published package containing
workspacefield in pubspec.yaml, which causeddart run build_runnerfailures for users
0.1.4 #
- Add stdin pipe support (
-i -): generate fromcurl,cat, or any command (e.g.curl https://example.com/spec.json | degenerate -i - -o lib/src/api -n my_api)
0.1.3 #
- Fix runtime crash for required+nullable fields in fromJson (
type 'Null' is not a subtype of type 'String' in type cast) - Fix enum values with special characters (e.g.
[DONE]) generating PascalCase instead of lowerCamelCase
0.1.2 #
- Add GitHub Actions CI
- Add release script (
make release) - Make runtime packages publishable to pub.dev (version constraints instead of path deps)
0.1.1 #
- Fix README image on pub.dev
- Add GitHub Actions CI
- Add release script (
make release) - Make runtime packages publishable to pub.dev (version constraints instead of path deps)
0.1.0 #
- Initial version.