Skip to content

Commit

Permalink
fix: resource-name for typescript
Browse files Browse the repository at this point in the history
  • Loading branch information
krvital committed Sep 26, 2024
1 parent eb57cf3 commit fad2cd1
Show file tree
Hide file tree
Showing 8 changed files with 108 additions and 30 deletions.
8 changes: 5 additions & 3 deletions src/aidbox_sdk/converter.clj
Original file line number Diff line number Diff line change
Expand Up @@ -86,13 +86,13 @@
:else (if type (str "Base." type) "string")))

(defn- derive-basic-type [name element]
(get-type name (url->resource-name (:type element))))
(get-type name (str/replace (or (url->resource-name (:type element)) "") #"-" "")))

(defn- transform-element [name element required]
(->> (derive-basic-type name element)))

(defn- resolve-backbone-elements [[k, v]]
(if (= (url->resource-name (:type v)) "BackboneElement") (vector k, v) (vector)))
(if (= (:type v) "BackboneElement") (vector k, v) (vector)))

(defn- collect-types [parent-name required [k v]]
(if (contains? v :choices)
Expand Down Expand Up @@ -127,6 +127,7 @@
(seq (:elements schema)))
backbone-elements (remove empty? (:backbone-elements data))]
(-> data
(assoc :resource-name name)
(assoc :backbone-elements
(if (empty? backbone-elements)
[]
Expand Down Expand Up @@ -337,7 +338,8 @@
(apply-patterns (:url constraint)
(filter #(contains? (last %) :pattern)
(:elements constraint)))
((fn [schema] (update schema :deps set/union #{"Meta"})))))
((fn [schema] (update schema :deps set/union #{"Meta"})))
((fn [schema] (assoc schema :resource-name (url->resource-name (:url constraint)) )))))

(defn convert-constraints [constraint-schemas base-schemas]
(let [base-schemas (vector->map base-schemas)]
Expand Down
4 changes: 4 additions & 0 deletions src/aidbox_sdk/generator/helpers.clj
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,10 @@
(defn ->snake-case [s]
(str/join "_" (map str/lower-case (words s))))

(defn ->camel-case [s]
(str/join (into [(first (words s))]
(map str/capitalize (rest (words s))))))

(defn uppercase-first-letter
"NOTE: Do not confuse with `capitalize` and `->pascal-case` functions.
Capitalize function lowercasing all letters after first.
Expand Down
55 changes: 33 additions & 22 deletions src/aidbox_sdk/generator/typescript.clj
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
(ns aidbox-sdk.generator.typescript
(:require
[aidbox-sdk.generator :as generator]
[aidbox-sdk.generator.helpers :refer [->pascal-case uppercase-first-letter]]
[aidbox-sdk.generator.helpers :refer [->pascal-case uppercase-first-letter
->camel-case]]
[aidbox-sdk.generator.utils :as u]
[clojure.java.io :as io]
[clojure.string :as str])
Expand All @@ -19,16 +20,19 @@
(defn url->resource-name [reference]
(last (str/split (str reference) #"/")))

(defn resource-name->class-name [rn]
(->pascal-case rn))

(defn datatypes-file-path []
(io/file "datatypes.ts"))

(defn resource-file-path [ir-schema]
(io/file (package->directory (:package ir-schema))
(str (->pascal-case (url->resource-name (:url ir-schema))) ".ts")))
(str (->pascal-case (:resource-name ir-schema)) ".ts")))

(defn constraint-file-path [ir-schema name]
(io/file (package->directory (:package ir-schema))
(str (->pascal-case (url->resource-name name)) ".ts")))
(str (->pascal-case (:resource-name ir-schema)) ".ts")))

(defn search-param-filepath [ir-schema]
(io/file "search" (str (:name ir-schema) "SearchParameters.ts")))
Expand Down Expand Up @@ -68,11 +72,9 @@
fhir-type))

(defn class-name
"Generate class name from schema url."
[url]
(str/replace
(uppercase-first-letter (url->resource-name url))
#"_|-" ""))
"Generate class name from schema resource name."
[resource-name]
(->pascal-case resource-name))

(defn generate-polymorphic-property [{:keys [name required choices]}]
(let [type (->> choices
Expand All @@ -83,7 +85,7 @@
(str name (when-not required "?") ": " type ";")))

(defn ->backbone-type [element]
(str/replace (str (:base element) (uppercase-first-letter (:name element))) "_" ""))
(str/replace (str (:base element) (uppercase-first-letter (:name element))) #"[_-]" ""))

(defn generate-property [{:keys [name array required type choices profile] :as element}]
(cond choices
Expand All @@ -101,9 +103,14 @@
(defn generate-class
"Generates TypeScript type from IR (intermediate representation) schema."
[ir-schema & [inner-classes]]
(let [base-class (url->resource-name (:base ir-schema))
schema-name (or (:url ir-schema) (:name ir-schema))
class-name' (class-name schema-name)
(let [base-class (class-name (or (:base-resource-name ir-schema)
;; need for BackboneElement
(:base ir-schema)
""))
class-name' (class-name (or (:resource-name ir-schema)
;; need for BackboneElement
(:name ir-schema)
""))
properties (->> (:elements ir-schema)
(remove #(:choice-option %))
(map generate-property)
Expand Down Expand Up @@ -144,7 +151,9 @@
(defn- path->name [path]
(str/replace path #"(\.ts)|[\.\/]" ""))

(defn generate-deps [deps]
(defn generate-deps
"Takes a list of resource names and generates import declarations."
[deps]
(->> deps
(map (fn [{:keys [module members]}]
(if (seq members)
Expand All @@ -156,7 +165,11 @@
[& {:keys [deps classes]
:or {classes []}}]
(->> (conj []
(generate-deps deps)
(->> deps
(map class-name)
(map (fn [d] {:module (str "./" d) :members [d]}))
generate-deps)

classes)
(flatten)
(str/join "\n\n")))
Expand All @@ -168,24 +181,22 @@
(map (fn [ir-schema]
{:path (resource-file-path ir-schema)
:content (generate-module
:deps (map (fn [d] {:module (str "./" d) :members [d]})
(:deps ir-schema))
:deps (:deps ir-schema)
:classes [(generate-class ir-schema (map generate-class (:backbone-elements ir-schema)))])})
ir-schemas)))

(generate-resource-module [_ ir-schema]
{:path (resource-file-path ir-schema)
:content (generate-module
{:deps (map (fn [d] {:module (str "./" d) :members [d]})
(:deps ir-schema))
{:deps (:deps ir-schema)
:classes [(generate-class ir-schema
(map generate-class (:backbone-elements ir-schema)))]})})

(generate-search-params [_ ir-schemas] []
(map (fn [ir-schema]
{:path (search-param-filepath ir-schema)
:content (generate-module
:deps []
:deps (:deps ir-schema)
:classes [(generate-class
{:name (format "%sSearchParameters" (:name ir-schema))
:base (when (:base ir-schema)
Expand All @@ -197,11 +208,11 @@
(mapv (fn [[constraint-name schema]]
{:path (constraint-file-path schema constraint-name)
:content (generate-module
:deps (map (fn [d] {:module (str "./" d) :members [d]})
(:deps schema))
:deps (:deps schema)
:classes (generate-class (assoc schema :url constraint-name)
(map generate-class (:backbone-elements schema))))})
ir-schemas))
(generate-sdk-files [this] (generator/prepare-sdk-files :typescript)))

(generate-sdk-files [_] (generator/prepare-sdk-files :typescript)))

(def generator (->TypeScriptCodeGenerator))
2 changes: 2 additions & 0 deletions test/aidbox_sdk/fixtures/extension_ir_schema.edn
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@
:derivation "specialization",
:name "Extension",
:type "Extension",
:resource-name "Extension"
:base-resource-name "Element"
:elements
[{:name "valueBase64Binary",
:base "Extension",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
:derivation "constraint",
:name "Extension",
:type "Extension",
:resource-name "organization-preferred-Contact"
:elements
[{:name "url",
:base "Extension",
Expand Down
1 change: 1 addition & 0 deletions test/aidbox_sdk/fixtures/patient_ir_schema.edn
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
:derivation "specialization",
:name "Patient",
:type "Patient",
:resource-name "Patient"
:elements
[{:name "multipleBirthBoolean",
:base "Patient",
Expand Down
2 changes: 2 additions & 0 deletions test/aidbox_sdk/fixtures/patient_nationality_ir_schema.edn
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@
{:package "hl7.fhir.r4.core",
:derivation "specialization",
:name "Extension",
:resource-name "patient-nationality"
:base-resource-name "Element"
:type "Extension",
:elements
[{:name "meta",
Expand Down
65 changes: 60 additions & 5 deletions test/aidbox_sdk/generator/typescript_test.clj
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
(ns aidbox-sdk.generator.typescript-test
(:require
[aidbox-sdk.fixtures :as fixt]
[aidbox-sdk.fixtures.schemas :as fixtures]
[aidbox-sdk.generator :as sut]
[aidbox-sdk.generator.typescript :refer [generator] :as gen.typescript]
[clojure.java.io :as io]
[clojure.string :as str]
[clojure.test :refer [deftest is testing use-fixtures]]))

(use-fixtures :once fixt/prepare-examples)
Expand Down Expand Up @@ -65,7 +65,7 @@
)

(testing "element with meta"
(is (= "meta: Meta = { profile: \"http://hl7.org/fhir/StructureDefinition/vitalsigns\" }"
(is (= "meta: Meta & { profile: [\"http://hl7.org/fhir/StructureDefinition/vitalsigns\"] }"
(gen.typescript/generate-property {:name "meta",
:required true,
:value "Meta",
Expand Down Expand Up @@ -96,7 +96,24 @@

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

(testing "empty elements"
Expand All @@ -106,13 +123,51 @@
:type "Base",
:elements (),
:url "http://hl7.org/fhir/StructureDefinition/Base",
:resource-name "Base"
:base-resource-name nil,
:backbone-elements (),
:base nil,
:deps #{}}))))

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

Expand Down Expand Up @@ -167,7 +222,7 @@
(comment
(fixt/load-data!)

(fixt/get-data :patient-search-params-ir-schema)
(fixt/get-data :patient-ir-schema)

@fixt/data

Expand Down

0 comments on commit fad2cd1

Please sign in to comment.