Skip to content

feat(configurl): add typed registries and migrate consumers - #647

Open
fortuna wants to merge 22 commits into
mainfrom
feat/smart-configurl-registry
Open

fortuna wants to merge 22 commits into
mainfrom
feat/smart-configurl-registry

Conversation

@fortuna

@fortuna fortuna commented Oct 17, 2026 •

Copy link
Copy Markdown
Contributor

Configurl's shared provider container is limited to a fixed set of dialer and listener result types. Add typed registries so applications and component libraries can register and construct arbitrary Go result types, while preserving compatibility with the existing provider API.

Key benefits of supporting arbitrary types are:

  • Endpoint configurations. Libraries can register parsers for transport.StreamEndpoint and transport.PacketEndpoint, allowing a config URL to describe both the transport and its destination. The existing provider container cannot express endpoints, which limits composition when a component needs a connection to a specific destination.
  • Extension without permission. Other developers can define new result types and publish their parsers in their own libraries. Apps import those libraries and register the parsers directly, without changing the SDK or seeking approval from its maintainers. Extension is no longer limited to adding schemes for the SDK's predefined result types.
  • Composition beyond linear chains. Arbitrary result types can also represent intermediate structures, such as maps of named configurations. Discussion #656: Expressing branching configurations with configurl explores how libraries could use these to assemble Happy Eyeballs or TCP/UDP components while preserving the pipe-separated syntax. That proposal is future work enabled by this registry.

This PR targets main, which includes rollback #648. It adds the registry API and migrates SDK tools, examples, and existing SmartDialer/Mobileproxy construction to it. SmartDialer/Mobileproxy extension options remain in #649, stacked directly on this PR.

  • Registry exposes Lookup; MutableRegistry adds Register. Both methods use any to hold Parser[T] values. A component config parser receives (ctx, registry, config) and uses that registry for dependencies. Generic Register[T] checks signatures at compile time, and Lookup[T] returns the exact parser type. Low-level registration derives signature validation from Parser[any], substituting the component result type.
  • New[T] constructs from a config URL string; NewFromConfig[T] accepts a parsed *Config. NewFromConfig passes its registry to the parser, so lookup wrappers apply throughout nested component chains. Built-ins are named config parsers, registered directly as Register(registry, "disorder", parseDisorderDialer). Context remains available for cancellable initialization, including HTTP/3 packet-listener setup.
  • The empty registration name selects the base function for a nil config. RegisterBase is a convenience equivalent to Register(r, "", newInstance). To inject an existing component, register a function that returns it.
  • Unavailable config schemes, Go result types, bases, and disabled parsers return errors matching errors.ErrUnsupported, including nested dependency failures. Invalid syntax/options retain parsing errors, and parser/construction errors propagate unchanged. The legacy provider API uses the same classification while preserving existing error messages.
  • ProviderContainer, TypeRegistry, ExtensibleProvider, and their constructors, fields, and methods are deprecated with links to the replacement registry APIs. They remain source compatible. The released two-argument BuildFunc signature is unchanged; a private adapter binds the built-in parsers to the legacy providers. The package documentation preserves the component-network overview and key features, then introduces NewDefaultRegistry and New[T], and custom component documentation uses the registry throughout. A private adapter preserves live changes to original provider bases and registrations.
  • SDK tools, examples, and existing SmartDialer/Mobileproxy construction use NewDefaultRegistry, New[T], and RegisterBase. The connectivity tool preserves its tracing dialer lifetimes and per-operation tracing. Migrating these callers resolves the deprecation errors caused by introducing the deprecated provider APIs.

Validation: the full x module race suite and staticcheck pass, including dedicated compatibility tests for the original provider API. No lint rules or source suppressions are added. Tests cover arbitrary and exact result types, external registry implementations, named function preservation, explicit low-level conversions, invalid signatures and lookup types, nil functions/results, partial results with errors, captured versus live lookup, concurrent construction, and original provider compatibility. New regressions verify concurrent registry wrappers with distinct bases, nested dependency construction, and cancellation during initialization. The new package documentation example was executed successfully, and Go doc displays the deprecation notices. No module dependencies change.

Developer documentation follow-ups remain held until the final API is released in the x module.

Base automatically changed from refactor/configurl-registry to main October 19, 2026 11:23
@fortuna fortuna changed the title feat(smart): support custom config URL components feat(configurl): support derived registries in SmartDialer Oct 20, 2026
@fortuna fortuna changed the title feat(configurl): support derived registries in SmartDialer feat(configurl): add typed registries for SmartDialer extensions Oct 21, 2026
@fortuna
fortuna force-pushed the feat/smart-configurl-registry branch from c6213d5 to e47f2ac Compare October 21, 2026 19:28
@fortuna
fortuna changed the base branch from main to revert/configurl-registry-rename October 21, 2026 19:28
@fortuna
fortuna force-pushed the feat/smart-configurl-registry branch from e47f2ac to 41218bc Compare October 21, 2026 22:00
@fortuna fortuna changed the title feat(configurl): add typed registries for SmartDialer extensions feat(configurl): add typed parser registries Oct 21, 2026
@fortuna
fortuna added this pull request to stack #650 October 21, 2026 22:48
Base automatically changed from revert/configurl-registry-rename to main October 22, 2026 09:54
Introduce Registry and MutableRegistry with typed construction and registration helpers. Share built-in parsers with the original provider APIs through a private adapter while preserving existing provider behavior.
Use New for config URL strings and NewFromConfig for parsed configs. Update built-in dependency construction, tests, and Go documentation.
@fortuna
fortuna force-pushed the feat/smart-configurl-registry branch from 06f1d98 to d7d15e0 Compare October 22, 2026 09:54
@fortuna
fortuna force-pushed the feat/smart-configurl-registry branch from 5ac5fa1 to 65a79ee Compare October 23, 2026 18:08
@fortuna
fortuna removed this pull request from stack #650 October 23, 2026 18:12
@fortuna
fortuna added this pull request to stack #653 October 23, 2026 18:12
@fortuna
fortuna marked this pull request as ready for review October 23, 2026 18:15
@fortuna

fortuna commented Oct 23, 2026

Copy link
Copy Markdown
Contributor Author

The deprecation warnings are breaking the CI, but they are fixed in #652. The idea is to merge the two stacked PRs together.

@greptile-apps

greptile-apps Bot commented Oct 23, 2026 •

Copy link
Copy Markdown

RetriggerView in GreptileConfidence Score: 5/5

[Medium impact] The PR appears safe to merge; no actionable compatibility or behavior failures were found.

Summary

Adds typed registries for constructing components from config URLs while keeping the released provider API available.

  • Callers build config URL components by exact result type and scheme.
  • The old provider API stays available while pointing callers to registries.
  • SDK tools and dialers build transports through typed registries.

Diagram

%%{init: {'theme': 'neutral'}}%%
flowchart TD
  Caller["New[T](ctx, registry, text)"] --> Parse["ParseConfig"]
  Parse --> Construct["NewFromConfig[T]"]
  Construct --> Lookup["Lookup exact type and scheme"]
  Lookup --> Parser["Parser[T](ctx, registry, config)"]
  Parser --> Dependency["Construct dependency with the same registry"]
  Dependency --> Construct
  Parser --> Result["Return component"]
Loading

Reviews (2) · Last reviewed commit: "docs(configurl): restore Cloudflare DoH ..." · Reviewed by Greptile

@fortuna
fortuna removed this pull request from stack #653 October 29, 2026 22:37
@fortuna fortuna changed the title feat(configurl): add typed parser registries feat(configurl): add typed registries and migrate consumers Oct 29, 2026
@fortuna
fortuna added this pull request to stack #655 October 29, 2026 22:38
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants