Skip to content

Instantly share code, notes, and snippets.

@rostyq
Created December 27, 2022 11:25
Show Gist options
  • Save rostyq/bad289bb0a9241aa484e6780b34378a7 to your computer and use it in GitHub Desktop.
Save rostyq/bad289bb0a9241aa484e6780b34378a7 to your computer and use it in GitHub Desktop.
Convert Firebase SDK Config to environment file.
from pathlib import Path
from typing import TypedDict, Literal, NotRequired, TYPE_CHECKING, Optional
from argparse import Namespace
if TYPE_CHECKING:
from _typeshed import SupportsWrite
class Config(TypedDict):
projectId: str
appId: str
storageBucket: str
locationId: str
apiKey: str
authDomain: str
messagingSenderId: str
measurementId: str
class Result(TypedDict):
fileName: Literal["google-config.js"]
fileContents: str
sdkConfig: Config
class Output(TypedDict):
status: Literal["success", "error"]
result: NotRequired[Result]
error: NotRequired[str]
class Args(Namespace):
platform: Literal["ios", "android", "web"]
out: Optional[Path]
prefix: Optional[str]
def get_env_names_map() -> Config:
from re import compile
pattern = compile(r"(?<!^)(?=[A-Z])")
return {
name: pattern.sub("_", name).upper() for name in Config.__annotations__.keys()
}
def get_config(platform: Literal["ios", "android", "web"]) -> Config:
from subprocess import check_output, CalledProcessError
from json import loads, JSONDecodeError
try:
output = check_output(
["firebase", "--json", "apps:sdkconfig", platform], shell=True
)
output: Output = loads(output)
except CalledProcessError as error:
output: Output = loads(error.output)
except JSONDecodeError as error:
raise Exception(output)
if output["status"] == "error":
raise Exception(output["error"])
return output["result"]["sdkConfig"]
def compose_env_file(
config: Config, prefix: str | None, file: Optional["SupportsWrite"]
):
def compose_env_var(name: str, key: str) -> str:
return f"{name}={config[key]}"
if prefix is None:
convert = lambda key, name, _prefix: compose_env_var(name, key)
else:
convert = lambda key, name, prefix: f"{prefix}_{compose_env_var(name, key)}"
for key, name in get_env_names_map().items():
print(convert(key, name, prefix), end="\n", file=file)
def get_args() -> Args:
from argparse import ArgumentParser
parser = ArgumentParser(description="Convert Firebase SDK Config to environment file.")
parser.add_argument("platform", help="platform", choices=["ios", "android", "web"])
parser.add_argument("-o", "--out", type=Path, help="output file path")
parser.add_argument("-p", "--prefix", type=lambda s: str(s).upper(), help="prefix for env variables")
return parser.parse_args(namespace=Args())
def main():
args = get_args()
file = None if args.out is None else args.out.open("w")
try:
compose_env_file(get_config(args.platform), args.prefix, file)
finally:
if file is not None:
file.close()
if __name__ == "__main__":
main()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment