fr_acdd 0.7.0
fr_acdd: ^0.7.0 copied to clipboard
Contract annotations and shared BFF DTO export for FlowR contract-first pages.
fr_acdd #
Pure Dart annotations and extraction utilities for FlowR contract-first pages.
fr_acdd reads @FrAcddPage, @FrAcddDto, and @FrAcddField annotations
from a Dart contract library, extracts a shared BFF analysis, and then renders
the final artifact as either:
protojson5request/response snippets rendered inside a Markdown document (recommended output suffix:.md)
Recommended DTO preset:
@FrAcddDto(kind: FrAcddDtoKind.root)
@FrAcddFreezed
class NotificationsBootstrapBffRsp with _$NotificationsBootstrapBffRsp {
const factory NotificationsBootstrapBffRsp({
required String title,
}) = _NotificationsBootstrapBffRsp;
}
Use XxxBffReq for every API request DTO, XxxBffRsp for every API response
DTO, and XxxDto for transfer data used only inside those boundaries. Keep
component state separate as XxxModel.
Use @FrAcddFreezed, @FrAcddFreezedJSON, or @Freezed(...) for extractable
DTOs. Keep page-local state on non-DTO models without @FrAcddDto. When the
page is scaffolded by fr-mvvm-contract, that usually means FlowR's exported
@FrState preset; use @FrStateJson only when the state model truly needs
fromJson(), and use plain @Freezed(...) when the state model holds
runtime-only or non-JSON-serializable fields.
@FrAcddFreezed is the minimal extraction preset, not a claim that every DTO
already crosses a runtime JSON boundary. It keeps fromJson/toJson disabled
by default. If an extracted DTO also needs runtime JSON serialization, keep
@FrAcddDto and prefer @FrAcddFreezedJSON. That preset still requires the
usual generated factory Xxx.fromJson(...) plus a .g.dart part in the
owning contract library. Use explicit @Freezed(...) only when you need JSON
serialization with custom Freezed options beyond the preset.
Route, Figma, and API split metadata are copied from the contract doc comments
when the page follows the fr-mvvm-contract convention:
/// Figma: https://www.figma.com/file/...
/// Route: AppRouter.notifications
/// Models:
/// - [NotificationsModel]: component state
/// BFF-UI-API:
/// - GET <BASE>/notifications-page/bootstrap
/// [NotificationsBootstrapBffReq], [NotificationsBootstrapBffRsp]
/// - GET <BASE>/notifications-page/tabs
/// [NotificationsTabsBffReq], [NotificationsTabsBffRsp]
@FrAcddPage(
mode: FrAcddMode.bff,
namespace: 'notifications_page',
)
class NotificationsPage extends StatelessWidget {
const NotificationsPage({super.key});
}
CLI:
fvm dart run fr_acdd:extract_bff --format proto --input path/to/xxx.dart --output path/to/xxx.proto
fvm dart run fr_acdd:extract_bff --format json5 --input path/to/xxx.dart --output path/to/xxx.md
--input must name the Dart library shell that declares its authored
part files. The extractor reads the shell and every authored part as one
contract library. It skips generated .freezed.dart and .g.dart parts, so
they may be absent during contract extraction; any other declared part must
exist. Passing an individual part of file is an error.
FrAcddMode only expresses the contract mode:
apibff
The --format flag only selects the derived output format. Do not encode
proto or json5 as contract modes.
If the contract comment omits the BFF-UI-API: section, fr_acdd will infer
suggested BFF API branches from the root DTO UX shape instead of assuming one
page equals one API. Legacy BFF-API: input remains readable and generated
output is normalized to canonical BFF-UI-API:.
For proto export, every included root or nested field must declare
@FrAcddField(tag: ...). The extractor will fail fast when tags are missing,
duplicated, or use the reserved range 19000-19999.
For json5 export, tags are not required. If a field annotation would be just
@FrAcddField(), omit it entirely.
wireName defaults to the Dart field name. Omit it unless the exported wire
field must differ from the contract field name.
nestedRef is usually inferred from Dart field types, including DTO objects,
lists, sets, and maps. Only set it explicitly when inference would be
ambiguous.
Use @FrAcddField(...) only when the field needs tag, wireName,
nestedRef, or include: false.
@FrAcddDto is only for backend-transfer DTOs. Keep page-local state in
unannotated page models or view-model members instead of trying to encode local
state as a DTO kind.