11"""Parser: TypeORM entity schema → SchemaForge IR."""
2+
23from __future__ import annotations
34
45import contextlib
@@ -92,9 +93,8 @@ def _split_entities(self, text: str) -> list[str]:
9293 stripped = line .strip ()
9394 # Detect @Entity, @ViewEntity, or bare class extends pattern
9495 if (
95- (stripped .startswith ("@" ) or stripped .startswith ("export class" ))
96- and (stripped .startswith ("export class" ) or "class " in stripped )
97- ):
96+ stripped .startswith ("@" ) or stripped .startswith ("export class" )
97+ ) and (stripped .startswith ("export class" ) or "class " in stripped ):
9898 in_class = True
9999 current = line + "\n "
100100 brace_depth = 0
@@ -144,11 +144,13 @@ def _parse_entity(self, block: str) -> Table | None:
144144 stripped = line .strip ()
145145
146146 # Multi-line @Column decorator
147- if stripped .startswith ("@PrimaryGeneratedColumn" ) or \
148- stripped .startswith ("@PrimaryColumn" ) or \
149- stripped .startswith ("@Column" ) or \
150- stripped .startswith ("@Index" ) or \
151- stripped .startswith ("@Unique" ):
147+ if (
148+ stripped .startswith ("@PrimaryGeneratedColumn" )
149+ or stripped .startswith ("@PrimaryColumn" )
150+ or stripped .startswith ("@Column" )
151+ or stripped .startswith ("@Index" )
152+ or stripped .startswith ("@Unique" )
153+ ):
152154 decorator_lines = [stripped ]
153155 # Collect multi-line decorator
154156 depth = stripped .count ("(" ) - stripped .count (")" )
@@ -172,8 +174,9 @@ def _parse_entity(self, block: str) -> Table | None:
172174 field_line = next_line
173175 break
174176
175- if decorator_text .startswith ("@PrimaryGeneratedColumn" ) or \
176- decorator_text .startswith ("@PrimaryColumn" ):
177+ if decorator_text .startswith (
178+ "@PrimaryGeneratedColumn"
179+ ) or decorator_text .startswith ("@PrimaryColumn" ):
177180 col = self ._parse_column_with_decorator (
178181 decorator_text , field_line , is_pk = True
179182 )
@@ -259,7 +262,7 @@ def _parse_column_with_decorator(
259262 raw_default = options ["default" ]
260263 if isinstance (raw_default , str ) and raw_default .startswith ("() => " ):
261264 # Function default (CURRENT_TIMESTAMP, etc.)
262- fn_name = raw_default .replace ("() => " , "" ).strip ().strip ('" \' ' )
265+ fn_name = raw_default .replace ("() => " , "" ).strip ().strip (" \" '" )
263266 if fn_name .upper () in ("CURRENT_TIMESTAMP" , "NOW()" , "UUID" ):
264267 pass # Skip DB-managed defaults
265268 else :
@@ -272,7 +275,7 @@ def _parse_column_with_decorator(
272275 try :
273276 col .default = float (raw_default )
274277 except ValueError :
275- col .default = raw_default .strip ('" \' ' )
278+ col .default = raw_default .strip (" \" '" )
276279
277280 # Handle custom type
278281 if col_type == ColumnType .CUSTOM and col_type_str :
@@ -307,7 +310,7 @@ def _parse_decorator_options(self, decorator: str) -> dict[str, str]:
307310 # If it's a plain string (type name), handle it
308311 inner_stripped = inner .strip ()
309312 if inner_stripped .startswith ('"' ) or inner_stripped .startswith ("'" ):
310- options ["type" ] = inner_stripped .strip ('" \' ' )
313+ options ["type" ] = inner_stripped .strip (" \" '" )
311314 return options
312315
313316 # If it's an object literal { ... }
@@ -326,7 +329,7 @@ def _parse_inline_options(self, decorator: str) -> dict[str, str]:
326329 if inner :
327330 # Could be a string or inline object
328331 if inner .startswith ('"' ) or inner .startswith ("'" ):
329- return {"type" : inner .strip ('" \' ' )}
332+ return {"type" : inner .strip (" \" '" )}
330333 if inner .startswith ("{" ):
331334 obj_inner = inner [1 :- 1 ].strip ()
332335 return self ._parse_key_value_pairs (obj_inner )
@@ -431,9 +434,7 @@ def _parse_index_decorator(self, decorator: str) -> Index | None:
431434 # Try to extract columns from array
432435 arr_match = re .search (r"\[([^\]]+)\]" , inner )
433436 if arr_match :
434- columns = [
435- c .strip ().strip ('"\' ' ) for c in arr_match .group (1 ).split ("," )
436- ]
437+ columns = [c .strip ().strip ("\" '" ) for c in arr_match .group (1 ).split ("," )]
437438 else :
438439 # Single field index — name is in quotes
439440 name_match = re .search (r'["\'](\w+)["\']' , inner )
0 commit comments