sera-2 1.15.0__py3-none-any.whl → 1.16.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,15 +1,16 @@
|
|
1
1
|
from __future__ import annotations
|
2
2
|
|
3
3
|
import re
|
4
|
-
from typing import Any, Callable
|
4
|
+
from typing import Any, Callable, Optional
|
5
5
|
|
6
|
-
from codegen.models import AST, PredefinedFn, Program, expr, stmt
|
6
|
+
from codegen.models import AST, ImportHelper, PredefinedFn, Program, expr, stmt
|
7
7
|
from codegen.models.var import DeferredVar
|
8
8
|
from loguru import logger
|
9
9
|
|
10
10
|
from sera.misc import (
|
11
11
|
assert_isinstance,
|
12
12
|
assert_not_null,
|
13
|
+
identity,
|
13
14
|
to_camel_case,
|
14
15
|
to_pascal_case,
|
15
16
|
to_snake_case,
|
@@ -25,6 +26,11 @@ from sera.models import (
|
|
25
26
|
)
|
26
27
|
from sera.typing import is_set
|
27
28
|
|
29
|
+
TS_GLOBAL_IDENTS = {
|
30
|
+
"normalizers.normalizeNumber": "sera-db.normalizers",
|
31
|
+
"normalizers.normalizeOptionalNumber": "sera-db.normalizers",
|
32
|
+
}
|
33
|
+
|
28
34
|
|
29
35
|
def make_typescript_data_model(schema: Schema, target_pkg: Package):
|
30
36
|
"""Generate TypeScript data model from the schema. The data model aligns with the public data model in Python, not the database model."""
|
@@ -259,6 +265,8 @@ def make_typescript_data_model(schema: Schema, target_pkg: Package):
|
|
259
265
|
program.import_("mobx.action", True)
|
260
266
|
program.import_("sera-db.validators", True)
|
261
267
|
|
268
|
+
import_helper = ImportHelper(program, TS_GLOBAL_IDENTS)
|
269
|
+
|
262
270
|
program.root(
|
263
271
|
stmt.LineBreak(),
|
264
272
|
stmt.TypescriptStatement(
|
@@ -331,12 +339,15 @@ def make_typescript_data_model(schema: Schema, target_pkg: Package):
|
|
331
339
|
|
332
340
|
if isinstance(prop, DataProperty):
|
333
341
|
tstype = prop.get_data_model_datatype().get_typescript_type()
|
342
|
+
original_tstype = tstype
|
343
|
+
|
334
344
|
if idprop is not None and prop.name == idprop.name:
|
335
345
|
# use id type alias
|
336
346
|
tstype = TsTypeWithDep(
|
337
347
|
f"{cls.name}Id",
|
338
348
|
deps=[f"@.models.{pkg.dir.name}.{cls.name}.{cls.name}Id"],
|
339
349
|
)
|
350
|
+
original_tstype = tstype
|
340
351
|
elif tstype.type not in schema.enums:
|
341
352
|
# for none id & none enum properties, we need to include a type for "invalid" value
|
342
353
|
tstype = _inject_type_for_invalid_value(tstype)
|
@@ -344,6 +355,7 @@ def make_typescript_data_model(schema: Schema, target_pkg: Package):
|
|
344
355
|
if prop.is_optional:
|
345
356
|
# convert type to optional
|
346
357
|
tstype = tstype.as_optional_type()
|
358
|
+
original_tstype = original_tstype.as_optional_type()
|
347
359
|
|
348
360
|
for dep in tstype.deps:
|
349
361
|
program.import_(dep, True)
|
@@ -400,6 +412,11 @@ def make_typescript_data_model(schema: Schema, target_pkg: Package):
|
|
400
412
|
expr.ExprIdent("record"), expr.ExprIdent(propname)
|
401
413
|
)
|
402
414
|
|
415
|
+
if original_tstype.type != tstype.type:
|
416
|
+
norm_func = get_norm_func(original_tstype, import_helper)
|
417
|
+
else:
|
418
|
+
norm_func = identity
|
419
|
+
|
403
420
|
ser_args.append(
|
404
421
|
(
|
405
422
|
expr.ExprIdent(prop.name),
|
@@ -420,14 +437,18 @@ def make_typescript_data_model(schema: Schema, target_pkg: Package):
|
|
420
437
|
),
|
421
438
|
expr.ExprIdent("isValid"),
|
422
439
|
),
|
423
|
-
|
424
|
-
|
440
|
+
norm_func(
|
441
|
+
PredefinedFn.attr_getter(
|
442
|
+
expr.ExprIdent("this"), expr.ExprIdent(propname)
|
443
|
+
)
|
425
444
|
),
|
426
445
|
expr.ExprIdent("undefined"),
|
427
446
|
)
|
428
447
|
if prop.is_optional
|
429
|
-
else
|
430
|
-
|
448
|
+
else norm_func(
|
449
|
+
PredefinedFn.attr_getter(
|
450
|
+
expr.ExprIdent("this"), expr.ExprIdent(propname)
|
451
|
+
)
|
431
452
|
)
|
432
453
|
),
|
433
454
|
)
|
@@ -455,14 +476,19 @@ def make_typescript_data_model(schema: Schema, target_pkg: Package):
|
|
455
476
|
),
|
456
477
|
expr.ExprIdent("isValid"),
|
457
478
|
),
|
458
|
-
|
459
|
-
|
479
|
+
norm_func(
|
480
|
+
PredefinedFn.attr_getter(
|
481
|
+
expr.ExprIdent("this"),
|
482
|
+
expr.ExprIdent(propname),
|
483
|
+
)
|
460
484
|
),
|
461
485
|
expr.ExprIdent("undefined"),
|
462
486
|
)
|
463
487
|
if prop.is_optional
|
464
|
-
else
|
465
|
-
|
488
|
+
else norm_func(
|
489
|
+
PredefinedFn.attr_getter(
|
490
|
+
expr.ExprIdent("this"), expr.ExprIdent(propname)
|
491
|
+
)
|
466
492
|
)
|
467
493
|
),
|
468
494
|
)
|
@@ -1086,6 +1112,9 @@ def make_typescript_data_model(schema: Schema, target_pkg: Package):
|
|
1086
1112
|
|
1087
1113
|
program = Program()
|
1088
1114
|
prop_defs: list[tuple[DataProperty | ObjectProperty, expr.Expr, expr.Expr]] = []
|
1115
|
+
prop_normalizers: list[tuple[expr.Expr, expr.Expr]] = []
|
1116
|
+
|
1117
|
+
import_helper = ImportHelper(program, TS_GLOBAL_IDENTS)
|
1089
1118
|
|
1090
1119
|
for prop in cls.properties.values():
|
1091
1120
|
# we must include private properties that are needed during upsert for our forms.
|
@@ -1126,6 +1155,11 @@ def make_typescript_data_model(schema: Schema, target_pkg: Package):
|
|
1126
1155
|
),
|
1127
1156
|
),
|
1128
1157
|
]
|
1158
|
+
|
1159
|
+
norm_func = get_normalizer(tstype, import_helper)
|
1160
|
+
if norm_func is not None:
|
1161
|
+
# we have a normalizer for this type
|
1162
|
+
prop_normalizers.append((expr.ExprIdent(propname), norm_func))
|
1129
1163
|
else:
|
1130
1164
|
assert isinstance(prop, ObjectProperty)
|
1131
1165
|
if prop.target.db is not None:
|
@@ -1340,6 +1374,10 @@ def make_typescript_data_model(schema: Schema, target_pkg: Package):
|
|
1340
1374
|
expr.ExprIdent("validators"),
|
1341
1375
|
expr.ExprIdent(f"draft{cls.name}Validators"),
|
1342
1376
|
),
|
1377
|
+
(
|
1378
|
+
expr.ExprIdent("normalizers"),
|
1379
|
+
PredefinedFn.dict(prop_normalizers),
|
1380
|
+
),
|
1343
1381
|
]
|
1344
1382
|
+ (
|
1345
1383
|
[
|
@@ -1500,3 +1538,35 @@ def _inject_type_for_invalid_value(tstype: TsTypeWithDep) -> TsTypeWithDep:
|
|
1500
1538
|
return tstype
|
1501
1539
|
|
1502
1540
|
raise NotImplementedError(tstype.type)
|
1541
|
+
|
1542
|
+
|
1543
|
+
def get_normalizer(
|
1544
|
+
tstype: TsTypeWithDep, import_helper: ImportHelper
|
1545
|
+
) -> Optional[expr.ExprIdent]:
|
1546
|
+
if tstype.type == "number":
|
1547
|
+
return import_helper.use("normalizers.normalizeNumber")
|
1548
|
+
if tstype.type == "number | undefined":
|
1549
|
+
return import_helper.use("normalizers.normalizeOptionalNumber")
|
1550
|
+
|
1551
|
+
assert "number" not in tstype.type, tstype.type
|
1552
|
+
return None
|
1553
|
+
|
1554
|
+
|
1555
|
+
def get_norm_func(
|
1556
|
+
tstype: TsTypeWithDep, import_helper: ImportHelper
|
1557
|
+
) -> Callable[[expr.Expr], expr.Expr]:
|
1558
|
+
"""
|
1559
|
+
Get the normalizer function for the given TypeScript type.
|
1560
|
+
If no normalizer is available, return None.
|
1561
|
+
"""
|
1562
|
+
norm_func = get_normalizer(tstype, import_helper)
|
1563
|
+
if norm_func is not None:
|
1564
|
+
|
1565
|
+
def modify_expr(value: expr.Expr) -> expr.Expr:
|
1566
|
+
return expr.ExprFuncCall(
|
1567
|
+
norm_func,
|
1568
|
+
[value],
|
1569
|
+
)
|
1570
|
+
|
1571
|
+
return modify_expr
|
1572
|
+
return identity # Return the value as is if no normalizer is available
|
sera/misc/__init__.py
CHANGED
sera/misc/_utils.py
CHANGED
@@ -19,10 +19,10 @@ sera/make/make_app.py,sha256=n9NtW73O3s_5Q31VHIRmnd-jEIcpDO7ksAsOdovde2s,5999
|
|
19
19
|
sera/make/make_python_api.py,sha256=iXGbKQ3IJvsY1ur_fhurr_THFNnH66E3Wl85o0emUbw,26853
|
20
20
|
sera/make/make_python_model.py,sha256=cRb-fuHX0WH7XPAAliu6lycC0iEjE5kcKg4bBU40GwQ,61275
|
21
21
|
sera/make/make_python_services.py,sha256=0ZpWLwQ7Nwfn8BXAikAB4JRpNknpSJyJgY5b1cjtxV4,2073
|
22
|
-
sera/make/make_typescript_model.py,sha256=
|
23
|
-
sera/misc/__init__.py,sha256=
|
22
|
+
sera/make/make_typescript_model.py,sha256=1ouYFCeqOlwEzsGBiXUn4VZtLJjJW7GSacdOSlQzhjI,67012
|
23
|
+
sera/misc/__init__.py,sha256=mPKkik00j3tO_m45VPDJBjm8K85NpymRPl36Kh4hBn8,473
|
24
24
|
sera/misc/_formatter.py,sha256=aCGYL08l8f3aLODHxSocxBBwkRYEo3K1QzCDEn3suj0,1685
|
25
|
-
sera/misc/_utils.py,sha256=
|
25
|
+
sera/misc/_utils.py,sha256=pGYv8p7m7opiDTLYbsPrhF0YA4WjFff7beMQQZ9NnEs,4095
|
26
26
|
sera/models/__init__.py,sha256=vJC5Kzo_N7wd16ocNPy1VvAZDGNiWeiAhWJ4ihATKvA,780
|
27
27
|
sera/models/_class.py,sha256=1J4Bd_LanzhhDWwZFHWGtFYD7lupe_alaB3D02ebNDI,2862
|
28
28
|
sera/models/_collection.py,sha256=ZnQEriKC4X88Zz48Kn1AVZKH-1_l8OgWa-zf2kcQOOE,1414
|
@@ -36,6 +36,6 @@ sera/models/_parse.py,sha256=MaGZty29lsVUFumWqNanIjAwptBNOMbVZMXLZ2A9_2g,12317
|
|
36
36
|
sera/models/_property.py,sha256=2rSLs9JjSesrxrEugE7krYaBQOivKU882I8mZN94FlI,7017
|
37
37
|
sera/models/_schema.py,sha256=VxJEiqgVvbXgcSUK4UW6JnRcggk4nsooVSE6MyXmfNY,1636
|
38
38
|
sera/typing.py,sha256=Fl4-UzLJu1GdLLk_g87fA7nT9wQGelNnGzag6dg_0gs,980
|
39
|
-
sera_2-1.
|
40
|
-
sera_2-1.
|
41
|
-
sera_2-1.
|
39
|
+
sera_2-1.16.0.dist-info/METADATA,sha256=wZvclB-3wd_K5sN9Q64s832aMVXueS3p2xbDJKCplnk,852
|
40
|
+
sera_2-1.16.0.dist-info/WHEEL,sha256=b4K_helf-jlQoXBBETfwnf4B04YC67LOev0jo4fX5m8,88
|
41
|
+
sera_2-1.16.0.dist-info/RECORD,,
|
File without changes
|