openapi_enum_patch 0.1.0
openapi_enum_patch: ^0.1.0 copied to clipboard
Give real names to the integer enums swagger_parser generates from OpenAPI, fill in the enum files it skips, and audit which enums still need naming.
openapi_enum_patch #
Give real names to the integer enums swagger_parser generates, fill in
the enum files it skips, and audit which enums still need naming.
The problem #
OpenAPI carries no member names for integer enums — only the numbers. So a generated client ends up like this:
if (account.status == CrmEnumsAccountStatus.value2) { … }
There is no way to fix that from the schema alone, and no swagger_parser
option for it. This package lets you supply the names once, in a YAML file, and
reapplies them automatically after every regeneration.
if (account.status == CrmEnumsAccountStatus.disabled) { … }
It also tells you which enums you have not named yet — the part that otherwise silently rots as the API grows.
Install #
dart pub add --dev openapi_enum_patch
Use #
Two commands wrap your existing generation step:
dart run openapi_enum_patch normalize # before swagger_parser
dart run swagger_parser
dart run openapi_enum_patch patch # after swagger_parser
dart run build_runner build --delete-conflicting-outputs
| Command | When | What it does |
|---|---|---|
normalize |
Before | Fixes {version} path templates and bare schema names |
patch |
After | Writes skipped enum files, applies overrides, prints the audit |
audit |
Any time | Prints the audit only, changing nothing |
| Option | Default |
|---|---|
-r, --root |
. |
-c, --config |
swagger_tools/swagger_parser.yaml |
-o, --overrides |
swagger_tools/enum_overrides.yaml |
--strict |
off — exit non-zero when the audit is not clean |
The schema list, output directory and use_flutter_compute are read straight
out of your swagger_parser.yaml, so nothing is configured twice.
Naming enums #
enums:
"CRM.Enums.AccountStatus":
names:
0: active
1: archived
2: disabled
extra: # values the API returns but the schema does not declare yet
- 3
Values without a name still generate as valueN. Names colliding with a Dart
reserved word get a $ suffix. String enums never need an override — their
member names come from the values.
The audit #
Every patch run ends with a coverage report:
── Enum override audit ──────────────────────────────────────────
MISSING OVERRIDE (2): integer enums generate as value0, value1, …
- CRM.Enums.BSCDepositStatus (CrmEnumsBscDepositStatus) values: [0, 1, 2]
- SocialService.InvestorStatus (SocialServiceInvestorStatus) values: [0, 1]
MISSING NAMES (1): override exists but does not name every value
- CRM.Enums.AccountStatus (CrmEnumsAccountStatus) unnamed: [3]
STALE NAMES (1): override names a value absent from the schema
- CRM.Enums.AccountStatus (CrmEnumsAccountStatus) unknown: [9]
─────────────────────────────────────────────────────────────────
- MISSING OVERRIDE — no entry at all. Add one.
- MISSING NAMES — the entry exists but does not cover every value.
- STALE NAMES — names a value the schema dropped, usually after a refresh.
Remove it, or move it to
extraif the API still returns it.
Only enums actually generated for your project are considered, so unused schema
enums stay quiet. The audit is report-only unless you pass --strict, which
makes it a CI gate.
What normalize fixes #
{version} path templates. Some services export
/api/v{version}/Plan/List with a required version path parameter. An
include_paths filter written with a concrete version never matches the
templated key, so the route is silently skipped — and if it did match,
{version} would leak into every generated method signature. normalize
substitutes the concrete version (read from info.version) and drops the
parameter.
Bare schema names. Most services export fully-qualified component names
(IBService.AccountTypes.AccountTypeResult), which become prefixed file names.
Services that export bare names (AccountData) produce unprefixed files that
collide with another service's models. normalize prepends <SchemeName>. to
every schema and rewrites all matching $refs.
replacement_rulescannot do this: it applies to class definitions but not to$ref-resolved type names, so definitions and references would diverge and imports would break.
Both passes are idempotent — re-downloading a schema and re-running is safe.
Why patch generates files at all #
swagger_parser only emits model files for schemas used in a request or
response body. An enum used solely as a query parameter gets imported by
the generated client but never written, which fails the build. patch detects
those dangling imports and synthesises the file from the schema.
Library API #
import 'package:openapi_enum_patch/openapi_enum_patch.dart';
final config = SwaggerParserConfig.parse(configYaml);
final overrides = EnumOverrides.parse(overridesYaml);
final patcher = EnumPatcher(root: '.', config: config);
final result = patcher.patch(overrides);
print(const AuditFormatter().format(result.report));
To target a serializer other than dart_mappable, implement EnumEmitter and
pass it to EnumPatcher; the registry, override and audit machinery is
unchanged. RegistryBuilder, EnumAuditor and SchemaNormalizer are all pure
and usable on their own.
Scope #
This package covers what is general to any OpenAPI + swagger_parser
project: enum naming, the audit, missing-file synthesis, and schema
normalisation.
It deliberately does not ship the regex fix-ups a given project may need for
a specific combination of swagger_parser, retrofit and dart_mappable
versions — those patch bugs that come and go between releases, and applying them
blindly to another project's output would do harm. Keep those in your own repo.
License #
MIT