modelable 1.0.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.
Potentially problematic release.
This version of modelable might be problematic. Click here for more details.
- modelable/__init__.py +1 -0
- modelable/__main__.py +3 -0
- modelable/_pydantic_py314_compat.py +31 -0
- modelable/cli.py +41 -0
- modelable/commands/__init__.py +1 -0
- modelable/commands/apicurio.py +84 -0
- modelable/commands/codegen.py +241 -0
- modelable/commands/common.py +43 -0
- modelable/commands/compile.py +237 -0
- modelable/commands/create.py +164 -0
- modelable/commands/diff.py +82 -0
- modelable/commands/graph.py +53 -0
- modelable/commands/llm.py +564 -0
- modelable/commands/lsp.py +15 -0
- modelable/commands/runtime.py +37 -0
- modelable/commands/scenario.py +104 -0
- modelable/commands/spec.py +197 -0
- modelable/commands/workspace.py +240 -0
- modelable/compat/__init__.py +11 -0
- modelable/compat/checker.py +179 -0
- modelable/compat/diff.py +169 -0
- modelable/compiler/__init__.py +3 -0
- modelable/compiler/compiler.py +19 -0
- modelable/compiler/workspace.py +346 -0
- modelable/diagnostics/__init__.py +3 -0
- modelable/diagnostics/model.py +27 -0
- modelable/emitters/__init__.py +0 -0
- modelable/emitters/base.py +22 -0
- modelable/emitters/csharp.py +245 -0
- modelable/emitters/dbt_yaml.py +290 -0
- modelable/emitters/diagnostics.py +25 -0
- modelable/emitters/fhir.py +694 -0
- modelable/emitters/fhir_validator.py +36 -0
- modelable/emitters/go.py +334 -0
- modelable/emitters/java.py +264 -0
- modelable/emitters/json_schema.py +458 -0
- modelable/emitters/markdown.py +252 -0
- modelable/emitters/odcs.py +355 -0
- modelable/emitters/openlineage.py +315 -0
- modelable/emitters/openmetadata.py +258 -0
- modelable/emitters/python.py +282 -0
- modelable/emitters/rust.py +643 -0
- modelable/emitters/shapes.py +261 -0
- modelable/emitters/sql.py +266 -0
- modelable/emitters/targets.py +141 -0
- modelable/emitters/typescript.py +352 -0
- modelable/expressions/__init__.py +0 -0
- modelable/expressions/cel.py +547 -0
- modelable/governance/__init__.py +3 -0
- modelable/governance/checker.py +271 -0
- modelable/governance/por.py +46 -0
- modelable/grammar/__init__.py +1 -0
- modelable/grammar/modelable.lark +257 -0
- modelable/graph/__init__.py +5 -0
- modelable/graph/export.py +442 -0
- modelable/llm/__init__.py +43 -0
- modelable/llm/chat.py +255 -0
- modelable/llm/config.py +87 -0
- modelable/llm/context.py +194 -0
- modelable/llm/engine.py +976 -0
- modelable/llm/importers.py +1077 -0
- modelable/llm/provenance.py +84 -0
- modelable/llm/providers.py +182 -0
- modelable/llm/qa.py +126 -0
- modelable/llm/recommendations.py +33 -0
- modelable/llm/redaction.py +19 -0
- modelable/llm/render.py +279 -0
- modelable/llm/update_plan.py +101 -0
- modelable/llm/validation_help.py +10 -0
- modelable/lsp/__init__.py +3 -0
- modelable/lsp/__main__.py +4 -0
- modelable/lsp/code_actions.py +210 -0
- modelable/lsp/completion.py +480 -0
- modelable/lsp/definition.py +343 -0
- modelable/lsp/diagnostics.py +31 -0
- modelable/lsp/document_symbols.py +197 -0
- modelable/lsp/federation.py +261 -0
- modelable/lsp/folding.py +33 -0
- modelable/lsp/formatting.py +64 -0
- modelable/lsp/highlight.py +30 -0
- modelable/lsp/hover.py +370 -0
- modelable/lsp/inlay_hints.py +158 -0
- modelable/lsp/references.py +511 -0
- modelable/lsp/rename.py +564 -0
- modelable/lsp/semantic_tokens.py +412 -0
- modelable/lsp/server.py +370 -0
- modelable/lsp/workspace.py +83 -0
- modelable/lsp/workspace_symbols.py +104 -0
- modelable/parser/__init__.py +94 -0
- modelable/parser/ir.py +451 -0
- modelable/parser/parse.py +47 -0
- modelable/parser/transformer.py +798 -0
- modelable/parser/wire.py +68 -0
- modelable/planner/__init__.py +0 -0
- modelable/planner/lineage.py +91 -0
- modelable/planner/planner.py +134 -0
- modelable/planner/plans.py +122 -0
- modelable/py.typed +0 -0
- modelable/registry/__init__.py +9 -0
- modelable/registry/apicurio.py +166 -0
- modelable/registry/base.py +18 -0
- modelable/registry/factory.py +18 -0
- modelable/registry/index.py +419 -0
- modelable/registry/local.py +26 -0
- modelable/registry/oci.py +22 -0
- modelable/registry/resolver.py +213 -0
- modelable/registry/schema.sql +119 -0
- modelable/registry/signature.py +26 -0
- modelable/release.py +125 -0
- modelable/runtime/__init__.py +5 -0
- modelable/runtime/adapter/__init__.py +17 -0
- modelable/runtime/adapter/base.py +18 -0
- modelable/runtime/adapter/postgres.py +82 -0
- modelable/specs/__init__.py +23 -0
- modelable/specs/tracking.py +220 -0
- modelable/validation/__init__.py +3 -0
- modelable/validation/semantic.py +659 -0
- modelable-1.0.0.dist-info/METADATA +61 -0
- modelable-1.0.0.dist-info/RECORD +122 -0
- modelable-1.0.0.dist-info/WHEEL +4 -0
- modelable-1.0.0.dist-info/entry_points.txt +2 -0
- modelable-1.0.0.dist-info/licenses/LICENSE +201 -0
|
@@ -0,0 +1,352 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
import re
|
|
4
|
+
from pathlib import Path
|
|
5
|
+
|
|
6
|
+
from modelable.compiler.workspace import Workspace
|
|
7
|
+
from modelable.emitters.base import EmittedArtifact, compute_content_hash
|
|
8
|
+
from modelable.emitters.diagnostics import missing_metadata, type_loss
|
|
9
|
+
from modelable.parser.ir import (
|
|
10
|
+
ArrayType,
|
|
11
|
+
ComputedMapping,
|
|
12
|
+
DecimalType,
|
|
13
|
+
DirectMapping,
|
|
14
|
+
DomainDef,
|
|
15
|
+
EnumType,
|
|
16
|
+
FieldDef,
|
|
17
|
+
MapType,
|
|
18
|
+
ModelVersion,
|
|
19
|
+
NamedType,
|
|
20
|
+
ObjectType,
|
|
21
|
+
PrimitiveType,
|
|
22
|
+
ProjectionVersion,
|
|
23
|
+
RefType,
|
|
24
|
+
VersionExact,
|
|
25
|
+
VersionMin,
|
|
26
|
+
VersionPinned,
|
|
27
|
+
VersionRange,
|
|
28
|
+
)
|
|
29
|
+
from modelable.registry.resolver import ResolvedModelRef, resolve_model_ref
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
def emit_typescript(workspace: Workspace, out_dir: Path) -> list[EmittedArtifact]:
|
|
33
|
+
artifacts: list[EmittedArtifact] = []
|
|
34
|
+
for domain in workspace.mdl.domains:
|
|
35
|
+
for model_name, versions in domain.models.items():
|
|
36
|
+
for version in versions:
|
|
37
|
+
artifacts.append(_emit_model(domain, model_name, version, out_dir, workspace.mdl))
|
|
38
|
+
for projection_name, versions in domain.projections.items():
|
|
39
|
+
for version in versions:
|
|
40
|
+
artifacts.append(_emit_projection(domain, projection_name, version, out_dir, workspace.mdl))
|
|
41
|
+
return artifacts
|
|
42
|
+
|
|
43
|
+
|
|
44
|
+
def _artifact_id(domain: str, name: str, version: int) -> str:
|
|
45
|
+
return f"{domain}.{name}.v{version}"
|
|
46
|
+
|
|
47
|
+
|
|
48
|
+
def _pascalize(value: str) -> str:
|
|
49
|
+
parts = [part for part in re.split(r"[^A-Za-z0-9]+", value) if part]
|
|
50
|
+
return "".join(part[:1].upper() + part[1:] for part in parts)
|
|
51
|
+
|
|
52
|
+
|
|
53
|
+
def _stable_interface_name(domain: str, name: str, version: int) -> str:
|
|
54
|
+
return f"{_pascalize(domain)}{_pascalize(name)}V{version}"
|
|
55
|
+
|
|
56
|
+
|
|
57
|
+
def _iface_to_artifact_id(iface_name: str) -> str:
|
|
58
|
+
"""Reverse _stable_interface_name heuristically to produce an artifact id like 'address.Address.v1'."""
|
|
59
|
+
# Strip trailing Vn suffix
|
|
60
|
+
m = re.match(r"^(.+?)V(\d+)$", iface_name)
|
|
61
|
+
if not m:
|
|
62
|
+
return iface_name.lower()
|
|
63
|
+
body, ver = m.group(1), m.group(2)
|
|
64
|
+
# Re-split PascalCase token pairs into domain + model
|
|
65
|
+
parts = re.findall(r"[A-Z][a-z0-9]*", body)
|
|
66
|
+
if len(parts) >= 2:
|
|
67
|
+
domain = parts[0].lower()
|
|
68
|
+
model = "".join(parts[1:])
|
|
69
|
+
return f"{domain}.{model}.v{ver}"
|
|
70
|
+
return f"{body.lower()}.v{ver}"
|
|
71
|
+
|
|
72
|
+
|
|
73
|
+
def _collect_ref_imports(field_type, mdl, resolved_refs: dict[str, str]) -> None:
|
|
74
|
+
"""Recursively collect resolved RefType targets into resolved_refs."""
|
|
75
|
+
if isinstance(field_type, RefType):
|
|
76
|
+
target = field_type.target
|
|
77
|
+
if target not in resolved_refs:
|
|
78
|
+
try:
|
|
79
|
+
from modelable.parser.ir import VersionMin
|
|
80
|
+
|
|
81
|
+
resolved: ResolvedModelRef = resolve_model_ref(mdl, target, VersionMin(min_inclusive=1))
|
|
82
|
+
iface = _stable_interface_name(resolved.domain_name, resolved.model_name, resolved.version.version)
|
|
83
|
+
resolved_refs[target] = iface
|
|
84
|
+
except LookupError, ValueError:
|
|
85
|
+
pass
|
|
86
|
+
elif isinstance(field_type, ArrayType):
|
|
87
|
+
_collect_ref_imports(field_type.item, mdl, resolved_refs)
|
|
88
|
+
elif isinstance(field_type, MapType):
|
|
89
|
+
_collect_ref_imports(field_type.value, mdl, resolved_refs)
|
|
90
|
+
elif isinstance(field_type, ObjectType):
|
|
91
|
+
for f in field_type.fields:
|
|
92
|
+
_collect_ref_imports(f.type, mdl, resolved_refs)
|
|
93
|
+
|
|
94
|
+
|
|
95
|
+
def _emit_model(domain: DomainDef, model_name: str, version: ModelVersion, out_dir: Path, mdl=None) -> EmittedArtifact:
|
|
96
|
+
artifact_id = _artifact_id(domain.name, model_name, version.version)
|
|
97
|
+
interface_name = _stable_interface_name(domain.name, model_name, version.version)
|
|
98
|
+
|
|
99
|
+
# Resolve ref<X> fields to stable interface names; collect imports.
|
|
100
|
+
resolved_refs: dict[str, str] = {} # ref target → stable interface name
|
|
101
|
+
if mdl is not None:
|
|
102
|
+
for field in version.fields:
|
|
103
|
+
_collect_ref_imports(field.type, mdl, resolved_refs)
|
|
104
|
+
|
|
105
|
+
declaration_json_wire = version.wire_targets().get("json")
|
|
106
|
+
field_case = declaration_json_wire.field_case if declaration_json_wire is not None else None
|
|
107
|
+
|
|
108
|
+
import_lines: list[str] = []
|
|
109
|
+
for iface in sorted(set(resolved_refs.values())):
|
|
110
|
+
iface_id = _iface_to_artifact_id(iface)
|
|
111
|
+
import_lines.append(f'import type {{ {iface} }} from "./{iface_id}";')
|
|
112
|
+
|
|
113
|
+
meta_lines = _metadata_lines(
|
|
114
|
+
_domain_metadata_entries(
|
|
115
|
+
domain,
|
|
116
|
+
model_name,
|
|
117
|
+
version.version,
|
|
118
|
+
version.model_kind.value,
|
|
119
|
+
version.change_kind.value,
|
|
120
|
+
)
|
|
121
|
+
)
|
|
122
|
+
body_lines: list[str] = []
|
|
123
|
+
body_lines.append(f"export interface {interface_name} {{")
|
|
124
|
+
warnings: list[str] = []
|
|
125
|
+
for field in version.fields:
|
|
126
|
+
if isinstance(field.type, NamedType):
|
|
127
|
+
warnings.append(missing_metadata(f"{domain.name}.{model_name}.{field.name}"))
|
|
128
|
+
field_name = _apply_case(field.name, field_case) if field_case else field.name
|
|
129
|
+
body_lines.append(
|
|
130
|
+
f" {field_name}{'?' if field.optional else ''}: {_type_to_ts(field.type, wire_targets=field.wire_targets(), resolved_refs=resolved_refs)};"
|
|
131
|
+
)
|
|
132
|
+
body_lines.append("}")
|
|
133
|
+
body_lines.append(f"export type {model_name} = {interface_name};")
|
|
134
|
+
|
|
135
|
+
all_lines = import_lines + ([""] if import_lines else []) + meta_lines + body_lines
|
|
136
|
+
content = "\n".join(all_lines) + "\n"
|
|
137
|
+
return EmittedArtifact(
|
|
138
|
+
target="typescript",
|
|
139
|
+
ref=f"{domain.name}.{model_name}@{version.version}",
|
|
140
|
+
artifact_id=artifact_id,
|
|
141
|
+
path=out_dir / f"{artifact_id}.ts",
|
|
142
|
+
content=content,
|
|
143
|
+
content_hash=compute_content_hash(content),
|
|
144
|
+
warnings=warnings,
|
|
145
|
+
)
|
|
146
|
+
|
|
147
|
+
|
|
148
|
+
def _emit_projection(
|
|
149
|
+
domain: DomainDef,
|
|
150
|
+
projection_name: str,
|
|
151
|
+
version: ProjectionVersion,
|
|
152
|
+
out_dir: Path,
|
|
153
|
+
mdl,
|
|
154
|
+
) -> EmittedArtifact:
|
|
155
|
+
artifact_id = _artifact_id(domain.name, projection_name, version.version)
|
|
156
|
+
interface_name = _stable_interface_name(domain.name, projection_name, version.version)
|
|
157
|
+
lines = _metadata_lines(
|
|
158
|
+
_domain_metadata_entries(
|
|
159
|
+
domain,
|
|
160
|
+
projection_name,
|
|
161
|
+
version.version,
|
|
162
|
+
"projection",
|
|
163
|
+
source=f"{version.source.model}@{_version_label(version.source.version)}",
|
|
164
|
+
where=version.where,
|
|
165
|
+
group_by=", ".join(version.group_by) if version.group_by else None,
|
|
166
|
+
)
|
|
167
|
+
)
|
|
168
|
+
declaration_json_wire = version.wire_targets().get("json")
|
|
169
|
+
field_case = declaration_json_wire.field_case if declaration_json_wire is not None else None
|
|
170
|
+
lines.append(f"export interface {interface_name} {{")
|
|
171
|
+
warnings: list[str] = []
|
|
172
|
+
for field in version.fields:
|
|
173
|
+
field_type = _resolve_projection_field_type(field, version, mdl)
|
|
174
|
+
if field_type is None:
|
|
175
|
+
warnings.append(type_loss(f"{domain.name}.{projection_name}.{field.name}"))
|
|
176
|
+
elif isinstance(field_type, NamedType):
|
|
177
|
+
warnings.append(missing_metadata(f"{domain.name}.{projection_name}.{field.name}"))
|
|
178
|
+
field_name = _apply_case(field.name, field_case) if field_case else field.name
|
|
179
|
+
lines.append(f" {field_name}: {_type_to_ts(field_type, wire_targets=field.wire_targets())};")
|
|
180
|
+
lines.append("}")
|
|
181
|
+
lines.append(f"export type {projection_name} = {interface_name};")
|
|
182
|
+
return EmittedArtifact(
|
|
183
|
+
target="typescript",
|
|
184
|
+
ref=f"{domain.name}.{projection_name}@{version.version}",
|
|
185
|
+
artifact_id=artifact_id,
|
|
186
|
+
path=out_dir / f"{artifact_id}.ts",
|
|
187
|
+
content="\n".join(lines) + "\n",
|
|
188
|
+
content_hash=compute_content_hash("\n".join(lines) + "\n"),
|
|
189
|
+
warnings=warnings,
|
|
190
|
+
)
|
|
191
|
+
|
|
192
|
+
|
|
193
|
+
def _metadata_lines(entries: list[str]) -> list[str]:
|
|
194
|
+
lines = ["/**"]
|
|
195
|
+
lines.extend(f" * {entry}" for entry in entries)
|
|
196
|
+
lines.append(" */")
|
|
197
|
+
return lines
|
|
198
|
+
|
|
199
|
+
|
|
200
|
+
def _domain_metadata_entries(
|
|
201
|
+
domain: DomainDef,
|
|
202
|
+
name: str,
|
|
203
|
+
version: int,
|
|
204
|
+
kind: str,
|
|
205
|
+
change_kind: str | None = None,
|
|
206
|
+
source: str | None = None,
|
|
207
|
+
where: str | None = None,
|
|
208
|
+
group_by: str | None = None,
|
|
209
|
+
) -> list[str]:
|
|
210
|
+
entries = [f"@modelable domain: {domain.name}", f"@modelable name: {name}"]
|
|
211
|
+
if domain.owner is not None:
|
|
212
|
+
entries.append(f"@modelable owner: {domain.owner}")
|
|
213
|
+
if domain.contact is not None:
|
|
214
|
+
entries.append(f"@modelable contact: {domain.contact}")
|
|
215
|
+
if domain.description is not None:
|
|
216
|
+
entries.append(f"@modelable description: {domain.description}")
|
|
217
|
+
if change_kind is not None:
|
|
218
|
+
entries.append(f"@modelable kind: {kind}")
|
|
219
|
+
entries.append(f"@modelable version: {version}")
|
|
220
|
+
entries.append(f"@modelable changeKind: {change_kind}")
|
|
221
|
+
else:
|
|
222
|
+
entries.append(f"@modelable kind: {kind}")
|
|
223
|
+
entries.append(f"@modelable version: {version}")
|
|
224
|
+
if source is not None:
|
|
225
|
+
entries.append(f"@modelable source: {source}")
|
|
226
|
+
if where is not None:
|
|
227
|
+
entries.append(f"@modelable where: {where}")
|
|
228
|
+
if group_by is not None:
|
|
229
|
+
entries.append(f"@modelable groupBy: {group_by}")
|
|
230
|
+
return entries
|
|
231
|
+
|
|
232
|
+
|
|
233
|
+
def _resolve_projection_field_type(
|
|
234
|
+
field: FieldDef,
|
|
235
|
+
projection: ProjectionVersion,
|
|
236
|
+
mdl,
|
|
237
|
+
):
|
|
238
|
+
if not isinstance(field.mapping, DirectMapping):
|
|
239
|
+
return None
|
|
240
|
+
try:
|
|
241
|
+
source_domain, source_model = projection.source.model.rsplit(".", 1)
|
|
242
|
+
except ValueError:
|
|
243
|
+
return None
|
|
244
|
+
try:
|
|
245
|
+
resolved = resolve_model_ref(mdl, f"{source_domain}.{source_model}", projection.source.version)
|
|
246
|
+
except LookupError:
|
|
247
|
+
return None
|
|
248
|
+
source_mv = resolved.version
|
|
249
|
+
for src_field in source_mv.fields:
|
|
250
|
+
if src_field.name == field.mapping.source_field:
|
|
251
|
+
return src_field.type
|
|
252
|
+
return None
|
|
253
|
+
|
|
254
|
+
|
|
255
|
+
def _version_label(version_spec) -> str:
|
|
256
|
+
if isinstance(version_spec, VersionExact):
|
|
257
|
+
return str(version_spec.version)
|
|
258
|
+
if isinstance(version_spec, VersionRange):
|
|
259
|
+
return f">={version_spec.min_inclusive}<{version_spec.max_exclusive}"
|
|
260
|
+
if isinstance(version_spec, VersionMin):
|
|
261
|
+
return f">={version_spec.min_inclusive}"
|
|
262
|
+
if isinstance(version_spec, VersionPinned):
|
|
263
|
+
return f"{version_spec.version}#{version_spec.content_hash}"
|
|
264
|
+
return "?"
|
|
265
|
+
|
|
266
|
+
|
|
267
|
+
def _apply_case(value: str, case: str) -> str:
|
|
268
|
+
"""Convert an enum value string to the specified wire case convention."""
|
|
269
|
+
words = re.sub(r"([a-z])([A-Z])", r"\1_\2", value)
|
|
270
|
+
words_list = [w for w in re.split(r"[^A-Za-z0-9]+", words) if w]
|
|
271
|
+
if not words_list:
|
|
272
|
+
return value
|
|
273
|
+
if case == "SCREAMING_SNAKE_CASE":
|
|
274
|
+
return "_".join(w.upper() for w in words_list)
|
|
275
|
+
if case == "snake_case":
|
|
276
|
+
return "_".join(w.lower() for w in words_list)
|
|
277
|
+
if case == "camelCase":
|
|
278
|
+
return words_list[0].lower() + "".join(w.capitalize() for w in words_list[1:])
|
|
279
|
+
if case == "PascalCase":
|
|
280
|
+
return "".join(w.capitalize() for w in words_list)
|
|
281
|
+
return value
|
|
282
|
+
|
|
283
|
+
|
|
284
|
+
def _type_to_ts(
|
|
285
|
+
field_type,
|
|
286
|
+
*,
|
|
287
|
+
wire_targets: dict[str, object] | None = None,
|
|
288
|
+
resolved_refs: dict[str, str] | None = None,
|
|
289
|
+
) -> str:
|
|
290
|
+
json_wire = None
|
|
291
|
+
if wire_targets is not None:
|
|
292
|
+
json_wire = wire_targets.get("json")
|
|
293
|
+
if isinstance(field_type, PrimitiveType):
|
|
294
|
+
if (
|
|
295
|
+
json_wire is not None
|
|
296
|
+
and getattr(json_wire, "encoding", None) == "string"
|
|
297
|
+
and field_type.kind in {"int", "float"}
|
|
298
|
+
):
|
|
299
|
+
return "string"
|
|
300
|
+
mapping = {
|
|
301
|
+
"string": "string",
|
|
302
|
+
"int": "number",
|
|
303
|
+
"float": "number",
|
|
304
|
+
"bool": "boolean",
|
|
305
|
+
"date": "string",
|
|
306
|
+
"time": "string",
|
|
307
|
+
"timestamp": "string",
|
|
308
|
+
"uuid": "string",
|
|
309
|
+
"duration": "string",
|
|
310
|
+
"binary": "string",
|
|
311
|
+
"json": "unknown",
|
|
312
|
+
}
|
|
313
|
+
return mapping.get(field_type.kind, "unknown")
|
|
314
|
+
if isinstance(field_type, DecimalType):
|
|
315
|
+
return "string"
|
|
316
|
+
if isinstance(field_type, ArrayType):
|
|
317
|
+
item_ts = _type_to_ts(field_type.item)
|
|
318
|
+
if isinstance(field_type.item, EnumType):
|
|
319
|
+
return f"({item_ts})[]"
|
|
320
|
+
return f"{item_ts}[]"
|
|
321
|
+
if isinstance(field_type, MapType):
|
|
322
|
+
return f"Record<string, {_type_to_ts(field_type.value)}>"
|
|
323
|
+
if isinstance(field_type, RefType):
|
|
324
|
+
if resolved_refs and field_type.target in resolved_refs:
|
|
325
|
+
return resolved_refs[field_type.target]
|
|
326
|
+
return "string"
|
|
327
|
+
if isinstance(field_type, EnumType):
|
|
328
|
+
case = getattr(json_wire, "case", None) if json_wire is not None else None
|
|
329
|
+
overrides = getattr(json_wire, "overrides", {}) if json_wire is not None else {}
|
|
330
|
+
wire_values = []
|
|
331
|
+
for v in field_type.values:
|
|
332
|
+
if v in overrides:
|
|
333
|
+
wire_values.append(overrides[v])
|
|
334
|
+
elif case:
|
|
335
|
+
wire_values.append(_apply_case(v, case))
|
|
336
|
+
else:
|
|
337
|
+
wire_values.append(v)
|
|
338
|
+
values = " | ".join(repr(v) for v in wire_values)
|
|
339
|
+
return values or "string"
|
|
340
|
+
if isinstance(field_type, ObjectType):
|
|
341
|
+
inner = "; ".join(
|
|
342
|
+
f"{field.name}{'?' if field.optional else ''}: {_type_to_ts(field.type, wire_targets=field.wire_targets(), resolved_refs=resolved_refs)}"
|
|
343
|
+
for field in field_type.fields
|
|
344
|
+
)
|
|
345
|
+
return f"{{ {inner} }}"
|
|
346
|
+
if isinstance(field_type, NamedType):
|
|
347
|
+
return field_type.name
|
|
348
|
+
if field_type is None:
|
|
349
|
+
return "unknown"
|
|
350
|
+
if isinstance(field_type, ComputedMapping):
|
|
351
|
+
return "unknown"
|
|
352
|
+
return "unknown"
|
|
File without changes
|