diff --git a/run_flaschengeist b/run_flaschengeist index 4a89b5d..3d1ce1f 100644 --- a/run_flaschengeist +++ b/run_flaschengeist @@ -1,11 +1,14 @@ #!/usr/bin/python3 -import sys +import inspect import argparse import bjoern +import sqlalchemy +from sqlalchemy.orm import RelationshipProperty, ColumnProperty def install(arguments): from flaschengeist.app import create_app, install_all + app = create_app() with app.app_context(): install_all() @@ -13,6 +16,7 @@ def install(arguments): def run(arguments): from flaschengeist.app import create_app + app = create_app() with app.app_context(): if arguments.debug: @@ -21,18 +25,69 @@ def run(arguments): bjoern.run(app, arguments.host, arguments.port, reuse_port=True) -if __name__ == '__main__': +def export(arguments): + import flaschengeist.system.models as models + known = [] + done = [] + + def orm_type(attr): + if hasattr(attr, 'type'): + tt = attr.type + if isinstance(attr, ColumnProperty): + tt = attr.columns[0].type + elif isinstance(attr, RelationshipProperty): + proto = "{}" + if attr.key.endswith("s"): + proto = "Array<{}>" + return proto.format(attr.mapper.class_.__name__) + else: + raise TypeError("Couldn't inspect type.") + tt = tt.__str__().split("(")[0] + return {"INTEGER": "number", + "VARCHAR": "string", + "DATETIME": "Date"}[tt] + + def walker(mod, file): + if inspect.isclass(mod[1]) and mod[1].__module__.startswith(models.__name__) and mod[0] not in done: + mapper = sqlalchemy.inspect(mod[1], False) + if mapper is not None: + file.write("interface {} {{\n".format(mod[0])) + for desc in mapper.attrs: + file.write(" {}: {};\n".format(desc.key, orm_type(desc))) + file.write("}\n") + done.append(mod[0]) + + elif inspect.ismodule(mod[1]) and mod[1].__name__.startswith(models.__name__) and mod[1].__name__ not in known: + known.append(mod[1].__name__) + for cls in inspect.getmembers(mod[1], lambda x: inspect.isclass(x) or inspect.ismodule(x)): + walker(cls, file) + + from flaschengeist.app import create_app + + app = create_app() + with app.app_context(): + with open(arguments.file, "w") as file: + walker(("models", models), file) + + +if __name__ == "__main__": # create the top-level parser parser = argparse.ArgumentParser() - subparsers = parser.add_subparsers(help='sub-command help', dest="sub_command") + subparsers = parser.add_subparsers(help="sub-command help", dest="sub_command") subparsers.required = True - parser_run = subparsers.add_parser('run', help='run flaschengeist') + parser_run = subparsers.add_parser("run", help="run flaschengeist") parser_run.set_defaults(func=run) parser_run.add_argument("--host", help="set hostname to listen on", default="127.0.0.1") parser_run.add_argument("--port", help="set port to listen on", type=int, default=5000) parser_run.add_argument("--debug", help="run in debug mode", action="store_true") - parser_install = subparsers.add_parser('install', help='run database setup for flaschengeist and all installed plugins') + parser_install = subparsers.add_parser( + "install", help="run database setup for flaschengeist and all installed plugins" + ) parser_install.set_defaults(func=install) + parser_export = subparsers.add_parser("export", help="export models to typescript interfaces") + parser_export.set_defaults(func=export) + parser_export.add_argument("--file", help="Filename where to save", default="flaschengeist.d.ts") + args = parser.parse_args() args.func(args)