Declare, unify, and forward public APIs across Julia versions.
Republic.jl manages Julia's public visibility across module boundaries and Julia versions. It provides:
@public— declare names as public API, equivalent to thepublickeyword introduced in 1.11@republic— forward upstream names into your module's public API@reexport— shorthand for@republic reexport=truepublic_names— returns public-but-not-exported namesexported_names— returns exported names
The main use case for forwarding is lightweight *Core or *Base packages, whose types and functions you want to surface as part of your package's API. This also works for heavier packages whose interfaces you may be implementing, but prefer a qualified @republic import to avoid clutter.
using Republic: @public
@public foo # single name
@public foo, bar, baz # multiple names
@public @my_macro # macro name@public replaces @compat public from Compat.jl, tracking declarations for cross-version discovery via public_names(mod).
@republic preserves using/import semantics and has three orthogonal, composable flags:
inherit— discover and import public-only names from upstream (default:false)reexport— re-export exported names instead of marking thempublic(default:false)republic— mark imported names aspublic(default:true)
@republic preserves Julia's native using/import distinction:
usingbrings names into scope for use (no method extension)importbrings names into scope for extension (methods can be added)
With inherit=true, this extends to wildcard discovery:
@republic inherit=true using Foo # all API names available, using semantics
@republic inherit=true import Foo # all API names available, import semantics (method extension)Marks what you bring in as public. No wildcard name discovery.
@republic using Foo # exported names → public
@republic using Foo: bar, baz # specific names → public
@republic import Foo: bar # import semantics + publicDiscovers public-only names upstream, imports them, and marks them public.
@republic inherit=true using Foo # all API names → public (using semantics)
@republic inherit=true import Foo # all API names → public (import semantics)Re-exports exported names (instead of marking them public). Replaces Reexport.jl.
@republic reexport=true using Foo # exported → re-export
@reexport using Foo # equivalent shorthandSuppresses the public marking. Useful with inherit=true for importing the full upstream public API without forwarding it.
@republic republic=false inherit=true using Foo # import full API, keep private
@republic republic=false inherit=true import Foo # same, with import semantics@republic reexport=true inherit=true using Foo # re-export + inherit public
@reexport inherit=true using Foo # equivalent shorthandJulia does not allow a name to be marked both public and exported. Republic respects pre-existing declarations:
module MyPackage
using Republic
export bar # already exported
@republic inherit=true using Foo # skips `public bar`
endmodule MyPackage
using Republic
@public bar # already public
@republic reexport=true using Foo # skips `export bar`
endThe default behavior of @republic changed in v2.0:
| v1.x | v2.0 equivalent |
|---|---|
@republic using Foo |
@republic inherit=true using Foo |
@republic reexport=true using Foo |
@republic reexport=true inherit=true using Foo |
The v1.x default performed wildcard discovery. In v2.0, the baseline is explicit — use inherit=true to opt into discovery. reexport=true no longer implies inherit.
Republic.jl is derived from Reexport.jl by Simon Kornblith (MIT License).
Republic.jl v2 was inspired by @public from CUDACore.jl.