import server.models.models from server.models.models import Jsonifiable from neomodel import StructuredNode, StringProperty, RelationshipManager, \ UniqueIdProperty, DateProperty, StructuredRel, DateTimeProperty, StructuredRel, \ Property, RelationshipDefinition import json from typing import Type, Tuple, Dict, List, Optional, Generator def constructor(cls: Type[StructuredNode]) -> str: return 'constructor(json) {\n' + \ f' super(json)\n' + \ ' }' def get_set_attr(name, attr) -> str: if RelationshipDefinition in attr.__class__.__mro__: return f""" get_{name}() {{ return this._get_relation('{name}') }} link_{name}(ref) {{ return this._link_relation('{name}', ref) }} unlink_{name}(ref) {{ return this._unlink_relation('{name}', ref) }} """ else: return f""" get_{name}() {{ return this.json.{name} }} """ + f""" set_{name}(new_val) {{ this._set('{name}', new_val) }} """ if name != 'uid' else '' def all_attrs(cls): return '\n'.join([ get_set_attr(name, val) for name, val in get_relevant_attributes(cls)]) def js_representation(cls: Type[StructuredNode]) -> str: props, rels = get_properties_and_relations(cls) return f"""models.{cls.__name__} = class {cls.__name__} extends StructuredNode {{ {constructor(cls)} {all_attrs(cls)} }} StructuredNode.registerClassDefinition(models.{cls.__name__}, {json.dumps(props)}, {json.dumps(rels)}) """ def get_relevant_attributes(cls: Type[StructuredNode]) -> Generator[None, Tuple[str, Property], None]: for name, value in vars(cls).items(): if name[0] == '_' or name[0].isupper() and not isinstance(value, (RelationshipDefinition, Property)): continue yield name, value def get_properties_and_relations(cls) -> Tuple[Dict[str, dict], Dict[str, dict]]: props = dict() rels = dict() for name, value in get_relevant_attributes(cls): if isinstance(value, RelationshipDefinition): target_cls = value._raw_class.__name__ if not isinstance(value._raw_class, str) else value._raw_class rels[name] = { 'field': name, 'target': target_cls, 'cardinality': value.manager.__name__ } elif isinstance(value, Property): props[name] = { 'field': name, 'type': value.__class__.__name__, 'required': value.required } return props, rels if __name__ == '__main__': reps = list() reps.append("// This file was generated by running js_conversion.py\n" + "// It converts the neomodel declaration of this element into js classes.\n" + "(() => {\nconst models = window.models || {}") for name, cls in vars(server.models.models).items(): if hasattr(cls, '__mro__') and StructuredNode in cls.__mro__ and StructuredNode != cls.__mro__[0]: reps.append(js_representation(cls)) reps.append('window.models = models;\n})()') print('\n\n\n'.join(reps))