Skip to content

Commit 9b6f3b4

Browse files
committed
fix: typescript backbone classes generation
1 parent 7c2e8da commit 9b6f3b4

File tree

2 files changed

+32
-16
lines changed

2 files changed

+32
-16
lines changed

src/aidbox_sdk/generator/typescript.clj

+10-3
Original file line numberDiff line numberDiff line change
@@ -70,7 +70,9 @@
7070
(defn class-name
7171
"Generate class name from schema url."
7272
[url]
73-
(uppercase-first-letter (url->resource-name url)))
73+
(str/replace
74+
(uppercase-first-letter (url->resource-name url))
75+
#"_" ""))
7476

7577
(defn generate-polymorphic-property [{:keys [name required choices]}]
7678
(let [type (->> choices
@@ -80,11 +82,16 @@
8082
(str/join " | "))]
8183
(str name (when-not required "?") ": " type ";")))
8284

85+
(defn ->backbone-type [element]
86+
(str/replace (str (:base element) (uppercase-first-letter (:name element))) "_" ""))
87+
8388
(defn generate-property [{:keys [name array required type choices] :as element}]
8489
(if choices
8590
(generate-polymorphic-property element)
86-
(let [lang-type (->lang-type type)]
87-
(str name (when-not required "?") ": " lang-type (when array "[]") ";"))))
91+
(let [type' (if (= "BackboneElement" (:type element))
92+
(->backbone-type element)
93+
(->lang-type (:type element)))]
94+
(str name (when-not required "?") ": " type' (when array "[]") ";"))))
8895

8996
(defn generate-class
9097
"Generates TypeScript type from IR (intermediate representation) schema."

test/aidbox_sdk/generator/typescript_test.clj

+22-13
Original file line numberDiff line numberDiff line change
@@ -75,7 +75,7 @@
7575
(deftest test-generate-class
7676

7777
(testing "base"
78-
(is (= "export type Patient = DomainResource & {\n address?: Address[];\n managingOrganization?: Reference;\n name?: HumanName[];\n birthDate?: string;\n multipleBirth?: boolean | number;\n deceased?: string | boolean;\n photo?: Attachment[];\n link?: BackboneElement[];\n active?: boolean;\n communication?: BackboneElement[];\n identifier?: Identifier[];\n telecom?: ContactPoint[];\n generalPractitioner?: Reference[];\n gender?: string;\n maritalStatus?: CodeableConcept;\n contact?: BackboneElement[];\n};"
78+
(is (= "export type Patient = DomainResource & {\n address?: Address[];\n managingOrganization?: Reference;\n name?: HumanName[];\n birthDate?: string;\n multipleBirth?: boolean | number;\n deceased?: string | boolean;\n photo?: Attachment[];\n link?: PatientLink[];\n active?: boolean;\n communication?: PatientCommunication[];\n identifier?: Identifier[];\n telecom?: ContactPoint[];\n generalPractitioner?: Reference[];\n gender?: string;\n maritalStatus?: CodeableConcept;\n contact?: PatientContact[];\n};"
7979
(gen.typescript/generate-class (fixt/get-data :patient-ir-schema)))))
8080

8181
(testing "empty elements"
@@ -91,32 +91,31 @@
9191
:deps #{}}))))
9292

9393
(testing "with inner classes"
94-
(is (= "export type Patient_Link = BackboneElement & {\n type: string;\n other: Reference;\n};\n\nexport type Patient_Communication = BackboneElement & {\n language: CodeableConcept;\n preferred?: boolean;\n};\n\nexport type Patient_Contact = BackboneElement & {\n name?: HumanName;\n gender?: string;\n period?: Period;\n address?: Address;\n telecom?: ContactPoint[];\n organization?: Reference;\n relationship?: CodeableConcept[];\n};\n\nexport type Patient = DomainResource & {\n address?: Address[];\n managingOrganization?: Reference;\n name?: HumanName[];\n birthDate?: string;\n multipleBirth?: boolean | number;\n deceased?: string | boolean;\n photo?: Attachment[];\n link?: BackboneElement[];\n active?: boolean;\n communication?: BackboneElement[];\n identifier?: Identifier[];\n telecom?: ContactPoint[];\n generalPractitioner?: Reference[];\n gender?: string;\n maritalStatus?: CodeableConcept;\n contact?: BackboneElement[];\n};"
94+
(is (= "export type PatientLink = BackboneElement & {\n type: string;\n other: Reference;\n};\n\nexport type PatientCommunication = BackboneElement & {\n language: CodeableConcept;\n preferred?: boolean;\n};\n\nexport type PatientContact = BackboneElement & {\n name?: HumanName;\n gender?: string;\n period?: Period;\n address?: Address;\n telecom?: ContactPoint[];\n organization?: Reference;\n relationship?: CodeableConcept[];\n};\n\nexport type Patient = DomainResource & {\n address?: Address[];\n managingOrganization?: Reference;\n name?: HumanName[];\n birthDate?: string;\n multipleBirth?: boolean | number;\n deceased?: string | boolean;\n photo?: Attachment[];\n link?: PatientLink[];\n active?: boolean;\n communication?: PatientCommunication[];\n identifier?: Identifier[];\n telecom?: ContactPoint[];\n generalPractitioner?: Reference[];\n gender?: string;\n maritalStatus?: CodeableConcept;\n contact?: PatientContact[];\n};"
9595
(gen.typescript/generate-class (fixt/get-data :patient-ir-schema)
9696
(map gen.typescript/generate-class (:backbone-elements (fixt/get-data :patient-ir-schema))))))))
9797

98-
#_
99-
(deftest test-generate-datatypes
100-
(is
101-
(= [{:path (io/file "base/__init__.py"),
102-
:content
103-
"from pydantic import *\nfrom typing import Optional, List\n\nclass Coding(Element):\n code: Optional[str] = None\n system: Optional[str] = None\n display: Optional[str] = None\n version: Optional[str] = None\n user_selected: Optional[bool] = None"}]
104-
(sut/generate-datatypes generator [fixtures/coding-ir-schema]))))
98+
#_(deftest test-generate-datatypes
99+
(is
100+
(= [{:path (io/file "base/__init__.py"),
101+
:content
102+
"from pydantic import *\nfrom typing import Optional, List\n\nclass Coding(Element):\n code: Optional[str] = None\n system: Optional[str] = None\n display: Optional[str] = None\n version: Optional[str] = None\n user_selected: Optional[bool] = None"}]
103+
(sut/generate-datatypes generator [fixtures/coding-ir-schema]))))
105104

106105
(deftest test-generate-resources
107106
(is
108107
(= {:path (io/file "hl7-fhir-r4-core/Patient.ts"),
109108
:content
110-
"import { Address } from \"./Address\";\nimport { Attachment } from \"./Attachment\";\nimport { Period } from \"./Period\";\nimport { CodeableConcept } from \"./CodeableConcept\";\nimport { ContactPoint } from \"./ContactPoint\";\nimport { HumanName } from \"./HumanName\";\nimport { DomainResource } from \"./DomainResource\";\nimport { Reference } from \"./Reference\";\nimport { Identifier } from \"./Identifier\";\nimport { BackboneElement } from \"./BackboneElement\";\n\nexport type Patient_Link = BackboneElement & {\n type: string;\n other: Reference;\n};\n\nexport type Patient_Communication = BackboneElement & {\n language: CodeableConcept;\n preferred?: boolean;\n};\n\nexport type Patient_Contact = BackboneElement & {\n name?: HumanName;\n gender?: string;\n period?: Period;\n address?: Address;\n telecom?: ContactPoint[];\n organization?: Reference;\n relationship?: CodeableConcept[];\n};\n\nexport type Patient = DomainResource & {\n address?: Address[];\n managingOrganization?: Reference;\n name?: HumanName[];\n birthDate?: string;\n multipleBirth?: boolean | number;\n deceased?: string | boolean;\n photo?: Attachment[];\n link?: BackboneElement[];\n active?: boolean;\n communication?: BackboneElement[];\n identifier?: Identifier[];\n telecom?: ContactPoint[];\n generalPractitioner?: Reference[];\n gender?: string;\n maritalStatus?: CodeableConcept;\n contact?: BackboneElement[];\n};"}
111-
(sut/generate-resource-module generator (fixt/get-data :patient-ir-schema))
112-
113-
)))
109+
"import { Address } from \"./Address\";\nimport { Attachment } from \"./Attachment\";\nimport { Period } from \"./Period\";\nimport { CodeableConcept } from \"./CodeableConcept\";\nimport { ContactPoint } from \"./ContactPoint\";\nimport { HumanName } from \"./HumanName\";\nimport { DomainResource } from \"./DomainResource\";\nimport { Reference } from \"./Reference\";\nimport { Identifier } from \"./Identifier\";\nimport { BackboneElement } from \"./BackboneElement\";\n\nexport type PatientLink = BackboneElement & {\n type: string;\n other: Reference;\n};\n\nexport type PatientCommunication = BackboneElement & {\n language: CodeableConcept;\n preferred?: boolean;\n};\n\nexport type PatientContact = BackboneElement & {\n name?: HumanName;\n gender?: string;\n period?: Period;\n address?: Address;\n telecom?: ContactPoint[];\n organization?: Reference;\n relationship?: CodeableConcept[];\n};\n\nexport type Patient = DomainResource & {\n address?: Address[];\n managingOrganization?: Reference;\n name?: HumanName[];\n birthDate?: string;\n multipleBirth?: boolean | number;\n deceased?: string | boolean;\n photo?: Attachment[];\n link?: PatientLink[];\n active?: boolean;\n communication?: PatientCommunication[];\n identifier?: Identifier[];\n telecom?: ContactPoint[];\n generalPractitioner?: Reference[];\n gender?: string;\n maritalStatus?: CodeableConcept;\n contact?: PatientContact[];\n};"}
110+
(sut/generate-resource-module generator (fixt/get-data :patient-ir-schema)))))
114111

115112
#_(deftest test-generate-search-params
116113
(is
117114
(= [{:path (io/file "search/PatientSearchParameters.py"),
118115
:content
119116
"from typing import Optional\n\nclass PatientSearchParameters(DomainResourceSearchParameters):\n id: Optional[str] = None\n active: Optional[str] = None\n address: Optional[str] = None\n address_city: Optional[str] = None\n address_country: Optional[str] = None\n address_postalcode: Optional[str] = None\n address_state: Optional[str] = None\n address_use: Optional[str] = None\n age: Optional[str] = None\n birth_order_boolean: Optional[str] = None\n birthdate: Optional[str] = None\n death_date: Optional[str] = None\n deceased: Optional[str] = None\n email: Optional[str] = None\n ethnicity: Optional[str] = None\n family: Optional[str] = None\n gender: Optional[str] = None\n general_practitioner: Optional[str] = None\n given: Optional[str] = None\n identifier: Optional[str] = None\n language: Optional[str] = None\n link: Optional[str] = None\n mothers_maiden_name: Optional[str] = None\n name: Optional[str] = None\n organization: Optional[str] = None\n part_agree: Optional[str] = None\n phone: Optional[str] = None\n phonetic: Optional[str] = None\n race: Optional[str] = None\n telecom: Optional[str] = None"}]
117+
(sut/generate-search-params generator (fixt/get-data :patient-search-params-ir-schema))
118+
120119
(sut/generate-search-params generator fixtures/patient-search-params-ir-schemas))))
121120

122121
#_(deftest generate-constraints
@@ -143,3 +142,13 @@
143142
:content
144143
"from pydantic import *\nfrom typing import Optional, List\nfrom ..base import *\n\nclass Observation_ReferenceRange(BackboneElement):\n age: Optional[Range] = None\n low: Optional[Quantity] = None\n high: Optional[Quantity] = None\n text: Optional[str] = None\n type: Optional[CodeableConcept] = None\n applies_to: Optional[List[CodeableConcept]] = None\n\nclass Observation_Component_ReferenceRange(BackboneElement):\n age: Optional[Range] = None\n low: Optional[Quantity] = None\n high: Optional[Quantity] = None\n text: Optional[str] = None\n type: Optional[CodeableConcept] = None\n applies_to: Optional[List[CodeableConcept]] = None\n\nclass Observation_Component(BackboneElement):\n reference_range: Optional[List[Observation_Component_ReferenceRange]] = None\n interpretation: Optional[List[CodeableConcept]] = None\n value_time: Optional[str] = None\n value_quantity: Optional[Quantity] = None\n value_string: Optional[str] = None\n value_ratio: Optional[Ratio] = None\n value_boolean: Optional[bool] = None\n value_date_time: Optional[str] = None\n value_sampled_data: Optional[SampledData] = None\n code: CodeableConcept\n value_codeable_concept: Optional[CodeableConcept] = None\n value_period: Optional[Period] = None\n value_range: Optional[Range] = None\n value_integer: Optional[int] = None\n data_absent_reason: Optional[CodeableConcept] = None\n\nclass Hdlcholesterol(DomainResource):\n meta: Meta = Meta(profile=[\"http://hl7.org/fhir/StructureDefinition/hdlcholesterol\"])\n category: Optional[List[CodeableConcept]] = None\n reference_range: list[Observation_ReferenceRange] = []\n interpretation: Optional[List[CodeableConcept]] = None\n encounter: Optional[Reference] = None\n method: Optional[CodeableConcept] = None\n value_time: Optional[str] = None\n specimen: Optional[Reference] = None\n value_quantity: Optional[Quantity] = None\n value_string: Optional[str] = None\n value_ratio: Optional[Ratio] = None\n value_boolean: Optional[bool] = None\n value_date_time: Optional[str] = None\n component: Optional[List[Observation_Component]] = None\n note: Optional[List[Annotation]] = None\n value_sampled_data: Optional[SampledData] = None\n effective_date_time: Optional[str] = None\n status: str\n code: CodeableConcept\n identifier: Optional[List[Identifier]] = None\n effective_timing: Optional[Timing] = None\n value_codeable_concept: Optional[CodeableConcept] = None\n body_site: Optional[CodeableConcept] = None\n focus: Optional[List[Reference]] = None\n issued: Optional[str] = None\n value_period: Optional[Period] = None\n device: Optional[Reference] = None\n effective_instant: Optional[str] = None\n based_on: Optional[List[Reference]] = None\n value_range: Optional[Range] = None\n part_of: Optional[List[Reference]] = None\n value_integer: Optional[int] = None\n subject: Optional[Reference] = None\n performer: Optional[List[Reference]] = None\n data_absent_reason: Optional[CodeableConcept] = None\n effective_period: Optional[Period] = None"}]
145144
(sut/generate-constraints generator fixtures/observation-constraints-ir-schema))))
145+
146+
(comment
147+
(fixt/load-data!)
148+
149+
(fixt/get-data :patient-search-params-ir-schema)
150+
151+
@fixt/data
152+
153+
;
154+
)

0 commit comments

Comments
 (0)