wrapped in self-revealing module to avoid namespacing conflicts