KaiselConfig<R>? decode(Uri) is synchronous, so a deep link whose destination depends on asynchronous state cannot be expressed.
Realistic cases: consulting secure storage before deciding where a link lands, checking a remotely-evaluated feature flag, resolving an entitlement, or reading a cached profile to choose between two stacks.
Concrete impact
An app migrating 28 deep-link destinations got away with it only because every handler happened to be synchronous. To keep it that way safely it had to add a runtime guard, since the failure would otherwise be silent:
final handled = resolve(mapping, builder, uri, isPending: isPending);
if (handled is! bool) {
logger.error($destination registered an async handler, but decoding is synchronous);
continue;
}
That check exists purely because the type system allows FutureOr<bool> there while decode cannot await it. A contributor adding an async destination would otherwise get a silently skipped deep link.
Precedent inside kaisel
Guards are already FutureOr<List<R>>, so asynchrony is clearly acceptable elsewhere in the pipeline. RouteInformationParser.parseRouteInformation is itself async, so the surrounding Flutter API accommodates it.
Suggestion
FutureOr<KaiselConfig<R>?> decode(Uri uri);
Sync codecs keep returning a value directly; async ones become expressible. KaiselRouteInformationParser already sits on an async boundary, so the await has somewhere natural to go.
KaiselConfig<R>? decode(Uri)is synchronous, so a deep link whose destination depends on asynchronous state cannot be expressed.Realistic cases: consulting secure storage before deciding where a link lands, checking a remotely-evaluated feature flag, resolving an entitlement, or reading a cached profile to choose between two stacks.
Concrete impact
An app migrating 28 deep-link destinations got away with it only because every handler happened to be synchronous. To keep it that way safely it had to add a runtime guard, since the failure would otherwise be silent:
That check exists purely because the type system allows
FutureOr<bool>there whiledecodecannot await it. A contributor adding an async destination would otherwise get a silently skipped deep link.Precedent inside kaisel
Guards are already
FutureOr<List<R>>, so asynchrony is clearly acceptable elsewhere in the pipeline.RouteInformationParser.parseRouteInformationis itself async, so the surrounding Flutter API accommodates it.Suggestion
Sync codecs keep returning a value directly; async ones become expressible.
KaiselRouteInformationParseralready sits on an async boundary, so the await has somewhere natural to go.