fhirpath-ts 0.0.0-bootstrap.0

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.
Files changed (414) hide show
  1. package/LICENSE +201 -0
  2. package/README.md +391 -0
  3. package/THIRD-PARTY-NOTICES.md +296 -0
  4. package/dist/analyzer/analyze-dto.d.ts +45 -0
  5. package/dist/analyzer/analyze-dto.d.ts.map +1 -0
  6. package/dist/analyzer/analyze-dto.js +147 -0
  7. package/dist/analyzer/analyze-dto.js.map +1 -0
  8. package/dist/analyzer/analyze.d.ts +98 -0
  9. package/dist/analyzer/analyze.d.ts.map +1 -0
  10. package/dist/analyzer/analyze.js +925 -0
  11. package/dist/analyzer/analyze.js.map +1 -0
  12. package/dist/analyzer/expression-policy.d.ts +210 -0
  13. package/dist/analyzer/expression-policy.d.ts.map +1 -0
  14. package/dist/analyzer/expression-policy.js +254 -0
  15. package/dist/analyzer/expression-policy.js.map +1 -0
  16. package/dist/analyzer/index.d.ts +3 -0
  17. package/dist/analyzer/index.d.ts.map +1 -0
  18. package/dist/analyzer/index.js +6 -0
  19. package/dist/analyzer/index.js.map +1 -0
  20. package/dist/analyzer/regex-safety.d.ts +10 -0
  21. package/dist/analyzer/regex-safety.d.ts.map +1 -0
  22. package/dist/analyzer/regex-safety.js +84 -0
  23. package/dist/analyzer/regex-safety.js.map +1 -0
  24. package/dist/analyzer/signatures.d.ts +72 -0
  25. package/dist/analyzer/signatures.d.ts.map +1 -0
  26. package/dist/analyzer/signatures.js +195 -0
  27. package/dist/analyzer/signatures.js.map +1 -0
  28. package/dist/api/bundle.d.ts +29 -0
  29. package/dist/api/bundle.d.ts.map +1 -0
  30. package/dist/api/bundle.js +108 -0
  31. package/dist/api/bundle.js.map +1 -0
  32. package/dist/api/cache.d.ts +10 -0
  33. package/dist/api/cache.d.ts.map +1 -0
  34. package/dist/api/cache.js +38 -0
  35. package/dist/api/cache.js.map +1 -0
  36. package/dist/api/column-signature.d.ts +53 -0
  37. package/dist/api/column-signature.d.ts.map +1 -0
  38. package/dist/api/column-signature.js +43 -0
  39. package/dist/api/column-signature.js.map +1 -0
  40. package/dist/api/compile.d.ts +120 -0
  41. package/dist/api/compile.d.ts.map +1 -0
  42. package/dist/api/compile.js +167 -0
  43. package/dist/api/compile.js.map +1 -0
  44. package/dist/api/constraints.d.ts +48 -0
  45. package/dist/api/constraints.d.ts.map +1 -0
  46. package/dist/api/constraints.js +52 -0
  47. package/dist/api/constraints.js.map +1 -0
  48. package/dist/api/dto.d.ts +134 -0
  49. package/dist/api/dto.d.ts.map +1 -0
  50. package/dist/api/dto.js +295 -0
  51. package/dist/api/dto.js.map +1 -0
  52. package/dist/api/engine.d.ts +136 -0
  53. package/dist/api/engine.d.ts.map +1 -0
  54. package/dist/api/engine.js +183 -0
  55. package/dist/api/engine.js.map +1 -0
  56. package/dist/api/evaluate.d.ts +7 -0
  57. package/dist/api/evaluate.d.ts.map +1 -0
  58. package/dist/api/evaluate.js +10 -0
  59. package/dist/api/evaluate.js.map +1 -0
  60. package/dist/api/project.d.ts +89 -0
  61. package/dist/api/project.d.ts.map +1 -0
  62. package/dist/api/project.js +150 -0
  63. package/dist/api/project.js.map +1 -0
  64. package/dist/api/tagged.d.ts +14 -0
  65. package/dist/api/tagged.d.ts.map +1 -0
  66. package/dist/api/tagged.js +13 -0
  67. package/dist/api/tagged.js.map +1 -0
  68. package/dist/cli/dto-check.d.ts +25 -0
  69. package/dist/cli/dto-check.d.ts.map +1 -0
  70. package/dist/cli/dto-check.js +77 -0
  71. package/dist/cli/dto-check.js.map +1 -0
  72. package/dist/cli/fhirpath-check.d.ts +3 -0
  73. package/dist/cli/fhirpath-check.d.ts.map +1 -0
  74. package/dist/cli/fhirpath-check.js +149 -0
  75. package/dist/cli/fhirpath-check.js.map +1 -0
  76. package/dist/cli/ts-loader.d.mts +3 -0
  77. package/dist/cli/ts-loader.d.mts.map +1 -0
  78. package/dist/cli/ts-loader.mjs +48 -0
  79. package/dist/cli/ts-loader.mjs.map +1 -0
  80. package/dist/engine/context.d.ts +173 -0
  81. package/dist/engine/context.d.ts.map +1 -0
  82. package/dist/engine/context.js +118 -0
  83. package/dist/engine/context.js.map +1 -0
  84. package/dist/engine/evaluator.d.ts +7 -0
  85. package/dist/engine/evaluator.d.ts.map +1 -0
  86. package/dist/engine/evaluator.js +196 -0
  87. package/dist/engine/evaluator.js.map +1 -0
  88. package/dist/engine/navigation.d.ts +11 -0
  89. package/dist/engine/navigation.d.ts.map +1 -0
  90. package/dist/engine/navigation.js +102 -0
  91. package/dist/engine/navigation.js.map +1 -0
  92. package/dist/engine/operators/collections.d.ts +12 -0
  93. package/dist/engine/operators/collections.d.ts.map +1 -0
  94. package/dist/engine/operators/collections.js +31 -0
  95. package/dist/engine/operators/collections.js.map +1 -0
  96. package/dist/engine/operators/comparison.d.ts +13 -0
  97. package/dist/engine/operators/comparison.d.ts.map +1 -0
  98. package/dist/engine/operators/comparison.js +77 -0
  99. package/dist/engine/operators/comparison.js.map +1 -0
  100. package/dist/engine/operators/equality.d.ts +19 -0
  101. package/dist/engine/operators/equality.d.ts.map +1 -0
  102. package/dist/engine/operators/equality.js +203 -0
  103. package/dist/engine/operators/equality.js.map +1 -0
  104. package/dist/engine/operators/index.d.ts +18 -0
  105. package/dist/engine/operators/index.d.ts.map +1 -0
  106. package/dist/engine/operators/index.js +30 -0
  107. package/dist/engine/operators/index.js.map +1 -0
  108. package/dist/engine/operators/logic.d.ts +8 -0
  109. package/dist/engine/operators/logic.d.ts.map +1 -0
  110. package/dist/engine/operators/logic.js +38 -0
  111. package/dist/engine/operators/logic.js.map +1 -0
  112. package/dist/engine/operators/math.d.ts +13 -0
  113. package/dist/engine/operators/math.d.ts.map +1 -0
  114. package/dist/engine/operators/math.js +198 -0
  115. package/dist/engine/operators/math.js.map +1 -0
  116. package/dist/engine/operators/strings.d.ts +8 -0
  117. package/dist/engine/operators/strings.d.ts.map +1 -0
  118. package/dist/engine/operators/strings.js +22 -0
  119. package/dist/engine/operators/strings.js.map +1 -0
  120. package/dist/engine/operators/types.d.ts +3 -0
  121. package/dist/engine/operators/types.d.ts.map +1 -0
  122. package/dist/engine/operators/types.js +15 -0
  123. package/dist/engine/operators/types.js.map +1 -0
  124. package/dist/engine/type-matching.d.ts +20 -0
  125. package/dist/engine/type-matching.d.ts.map +1 -0
  126. package/dist/engine/type-matching.js +122 -0
  127. package/dist/engine/type-matching.js.map +1 -0
  128. package/dist/errors.d.ts +25 -0
  129. package/dist/errors.d.ts.map +1 -0
  130. package/dist/errors.js +21 -0
  131. package/dist/errors.js.map +1 -0
  132. package/dist/eslint/index.d.ts +12 -0
  133. package/dist/eslint/index.d.ts.map +1 -0
  134. package/dist/eslint/index.js +316 -0
  135. package/dist/eslint/index.js.map +1 -0
  136. package/dist/fhir/html-checks.d.ts +7 -0
  137. package/dist/fhir/html-checks.d.ts.map +1 -0
  138. package/dist/fhir/html-checks.js +256 -0
  139. package/dist/fhir/html-checks.js.map +1 -0
  140. package/dist/fhir/model-navigation.d.ts +11 -0
  141. package/dist/fhir/model-navigation.d.ts.map +1 -0
  142. package/dist/fhir/model-navigation.js +142 -0
  143. package/dist/fhir/model-navigation.js.map +1 -0
  144. package/dist/functions/aggregate.d.ts +2 -0
  145. package/dist/functions/aggregate.d.ts.map +1 -0
  146. package/dist/functions/aggregate.js +127 -0
  147. package/dist/functions/aggregate.js.map +1 -0
  148. package/dist/functions/boundary.d.ts +2 -0
  149. package/dist/functions/boundary.d.ts.map +1 -0
  150. package/dist/functions/boundary.js +189 -0
  151. package/dist/functions/boundary.js.map +1 -0
  152. package/dist/functions/combining.d.ts +2 -0
  153. package/dist/functions/combining.d.ts.map +1 -0
  154. package/dist/functions/combining.js +13 -0
  155. package/dist/functions/combining.js.map +1 -0
  156. package/dist/functions/control.d.ts +2 -0
  157. package/dist/functions/control.d.ts.map +1 -0
  158. package/dist/functions/control.js +25 -0
  159. package/dist/functions/control.js.map +1 -0
  160. package/dist/functions/conversion.d.ts +3 -0
  161. package/dist/functions/conversion.d.ts.map +1 -0
  162. package/dist/functions/conversion.js +316 -0
  163. package/dist/functions/conversion.js.map +1 -0
  164. package/dist/functions/date-components.d.ts +2 -0
  165. package/dist/functions/date-components.d.ts.map +1 -0
  166. package/dist/functions/date-components.js +81 -0
  167. package/dist/functions/date-components.js.map +1 -0
  168. package/dist/functions/existence.d.ts +4 -0
  169. package/dist/functions/existence.d.ts.map +1 -0
  170. package/dist/functions/existence.js +97 -0
  171. package/dist/functions/existence.js.map +1 -0
  172. package/dist/functions/fhir.d.ts +2 -0
  173. package/dist/functions/fhir.d.ts.map +1 -0
  174. package/dist/functions/fhir.js +222 -0
  175. package/dist/functions/fhir.js.map +1 -0
  176. package/dist/functions/filtering.d.ts +2 -0
  177. package/dist/functions/filtering.d.ts.map +1 -0
  178. package/dist/functions/filtering.js +112 -0
  179. package/dist/functions/filtering.js.map +1 -0
  180. package/dist/functions/install.d.ts +18 -0
  181. package/dist/functions/install.d.ts.map +1 -0
  182. package/dist/functions/install.js +20 -0
  183. package/dist/functions/install.js.map +1 -0
  184. package/dist/functions/iteration.d.ts +7 -0
  185. package/dist/functions/iteration.d.ts.map +1 -0
  186. package/dist/functions/iteration.js +9 -0
  187. package/dist/functions/iteration.js.map +1 -0
  188. package/dist/functions/math.d.ts +2 -0
  189. package/dist/functions/math.d.ts.map +1 -0
  190. package/dist/functions/math.js +152 -0
  191. package/dist/functions/math.js.map +1 -0
  192. package/dist/functions/reflection.d.ts +2 -0
  193. package/dist/functions/reflection.d.ts.map +1 -0
  194. package/dist/functions/reflection.js +23 -0
  195. package/dist/functions/reflection.js.map +1 -0
  196. package/dist/functions/registry.d.ts +28 -0
  197. package/dist/functions/registry.d.ts.map +1 -0
  198. package/dist/functions/registry.js +46 -0
  199. package/dist/functions/registry.js.map +1 -0
  200. package/dist/functions/sort.d.ts +2 -0
  201. package/dist/functions/sort.d.ts.map +1 -0
  202. package/dist/functions/sort.js +48 -0
  203. package/dist/functions/sort.js.map +1 -0
  204. package/dist/functions/string.d.ts +2 -0
  205. package/dist/functions/string.d.ts.map +1 -0
  206. package/dist/functions/string.js +353 -0
  207. package/dist/functions/string.js.map +1 -0
  208. package/dist/functions/subsetting.d.ts +2 -0
  209. package/dist/functions/subsetting.d.ts.map +1 -0
  210. package/dist/functions/subsetting.js +72 -0
  211. package/dist/functions/subsetting.js.map +1 -0
  212. package/dist/functions/tree.d.ts +8 -0
  213. package/dist/functions/tree.d.ts.map +1 -0
  214. package/dist/functions/tree.js +109 -0
  215. package/dist/functions/tree.js.map +1 -0
  216. package/dist/functions/type-specifier.d.ts +8 -0
  217. package/dist/functions/type-specifier.d.ts.map +1 -0
  218. package/dist/functions/type-specifier.js +27 -0
  219. package/dist/functions/type-specifier.js.map +1 -0
  220. package/dist/functions/utility.d.ts +2 -0
  221. package/dist/functions/utility.d.ts.map +1 -0
  222. package/dist/functions/utility.js +76 -0
  223. package/dist/functions/utility.js.map +1 -0
  224. package/dist/functions/variables.d.ts +2 -0
  225. package/dist/functions/variables.d.ts.map +1 -0
  226. package/dist/functions/variables.js +35 -0
  227. package/dist/functions/variables.js.map +1 -0
  228. package/dist/index.d.ts +25 -0
  229. package/dist/index.d.ts.map +1 -0
  230. package/dist/index.js +11 -0
  231. package/dist/index.js.map +1 -0
  232. package/dist/lexer/lexer.d.ts +4 -0
  233. package/dist/lexer/lexer.d.ts.map +1 -0
  234. package/dist/lexer/lexer.js +318 -0
  235. package/dist/lexer/lexer.js.map +1 -0
  236. package/dist/lexer/tokens.d.ts +23 -0
  237. package/dist/lexer/tokens.d.ts.map +1 -0
  238. package/dist/lexer/tokens.js +40 -0
  239. package/dist/lexer/tokens.js.map +1 -0
  240. package/dist/model/provider.d.ts +36 -0
  241. package/dist/model/provider.d.ts.map +1 -0
  242. package/dist/model/provider.js +2 -0
  243. package/dist/model/provider.js.map +1 -0
  244. package/dist/parser/ast.d.ts +104 -0
  245. package/dist/parser/ast.d.ts.map +1 -0
  246. package/dist/parser/ast.js +2 -0
  247. package/dist/parser/ast.js.map +1 -0
  248. package/dist/parser/parser.d.ts +4 -0
  249. package/dist/parser/parser.d.ts.map +1 -0
  250. package/dist/parser/parser.js +299 -0
  251. package/dist/parser/parser.js.map +1 -0
  252. package/dist/parser/precedence.d.ts +24 -0
  253. package/dist/parser/precedence.d.ts.map +1 -0
  254. package/dist/parser/precedence.js +52 -0
  255. package/dist/parser/precedence.js.map +1 -0
  256. package/dist/parser/printer.d.ts +4 -0
  257. package/dist/parser/printer.d.ts.map +1 -0
  258. package/dist/parser/printer.js +112 -0
  259. package/dist/parser/printer.js.map +1 -0
  260. package/dist/r4/generated/resources-data.d.ts +3 -0
  261. package/dist/r4/generated/resources-data.d.ts.map +1 -0
  262. package/dist/r4/generated/resources-data.js +28628 -0
  263. package/dist/r4/generated/resources-data.js.map +1 -0
  264. package/dist/r4/generated/type-maps.d.ts +43153 -0
  265. package/dist/r4/generated/type-maps.d.ts.map +1 -0
  266. package/dist/r4/generated/type-maps.js +4 -0
  267. package/dist/r4/generated/type-maps.js.map +1 -0
  268. package/dist/r4/generated/types-data.d.ts +3 -0
  269. package/dist/r4/generated/types-data.d.ts.map +1 -0
  270. package/dist/r4/generated/types-data.js +2205 -0
  271. package/dist/r4/generated/types-data.js.map +1 -0
  272. package/dist/r4/index.d.ts +9 -0
  273. package/dist/r4/index.d.ts.map +1 -0
  274. package/dist/r4/index.js +94 -0
  275. package/dist/r4/index.js.map +1 -0
  276. package/dist/r4/model-data.d.ts +17 -0
  277. package/dist/r4/model-data.d.ts.map +1 -0
  278. package/dist/r4/model-data.js +2 -0
  279. package/dist/r4/model-data.js.map +1 -0
  280. package/dist/sites/index.d.ts +31 -0
  281. package/dist/sites/index.d.ts.map +1 -0
  282. package/dist/sites/index.js +205 -0
  283. package/dist/sites/index.js.map +1 -0
  284. package/dist/typed/infer.d.ts +234 -0
  285. package/dist/typed/infer.d.ts.map +1 -0
  286. package/dist/typed/infer.js +85 -0
  287. package/dist/typed/infer.js.map +1 -0
  288. package/dist/typed/perf-fixture.types.d.ts +136 -0
  289. package/dist/typed/perf-fixture.types.d.ts.map +1 -0
  290. package/dist/typed/perf-fixture.types.js +2 -0
  291. package/dist/typed/perf-fixture.types.js.map +1 -0
  292. package/dist/values/collection.d.ts +24 -0
  293. package/dist/values/collection.d.ts.map +1 -0
  294. package/dist/values/collection.js +51 -0
  295. package/dist/values/collection.js.map +1 -0
  296. package/dist/values/datetime.d.ts +54 -0
  297. package/dist/values/datetime.d.ts.map +1 -0
  298. package/dist/values/datetime.js +226 -0
  299. package/dist/values/datetime.js.map +1 -0
  300. package/dist/values/decimal.d.ts +48 -0
  301. package/dist/values/decimal.d.ts.map +1 -0
  302. package/dist/values/decimal.js +188 -0
  303. package/dist/values/decimal.js.map +1 -0
  304. package/dist/values/numeric.d.ts +24 -0
  305. package/dist/values/numeric.d.ts.map +1 -0
  306. package/dist/values/numeric.js +53 -0
  307. package/dist/values/numeric.js.map +1 -0
  308. package/dist/values/quantity.d.ts +49 -0
  309. package/dist/values/quantity.d.ts.map +1 -0
  310. package/dist/values/quantity.js +297 -0
  311. package/dist/values/quantity.js.map +1 -0
  312. package/dist/values/temporal-arithmetic.d.ts +17 -0
  313. package/dist/values/temporal-arithmetic.d.ts.map +1 -0
  314. package/dist/values/temporal-arithmetic.js +183 -0
  315. package/dist/values/temporal-arithmetic.js.map +1 -0
  316. package/dist/values/temporal-compare.d.ts +9 -0
  317. package/dist/values/temporal-compare.d.ts.map +1 -0
  318. package/dist/values/temporal-compare.js +59 -0
  319. package/dist/values/temporal-compare.js.map +1 -0
  320. package/dist/values/type-compat.d.ts +47 -0
  321. package/dist/values/type-compat.d.ts.map +1 -0
  322. package/dist/values/type-compat.js +100 -0
  323. package/dist/values/type-compat.js.map +1 -0
  324. package/dist/values/typed-value.d.ts +48 -0
  325. package/dist/values/typed-value.d.ts.map +1 -0
  326. package/dist/values/typed-value.js +117 -0
  327. package/dist/values/typed-value.js.map +1 -0
  328. package/dist/values/ucum.d.ts +14 -0
  329. package/dist/values/ucum.d.ts.map +1 -0
  330. package/dist/values/ucum.js +146 -0
  331. package/dist/values/ucum.js.map +1 -0
  332. package/package.json +137 -0
  333. package/src/analyzer/analyze-dto.ts +195 -0
  334. package/src/analyzer/analyze.ts +1181 -0
  335. package/src/analyzer/expression-policy.ts +434 -0
  336. package/src/analyzer/index.ts +23 -0
  337. package/src/analyzer/regex-safety.ts +85 -0
  338. package/src/analyzer/signatures.ts +260 -0
  339. package/src/api/bundle.ts +132 -0
  340. package/src/api/cache.ts +40 -0
  341. package/src/api/column-signature.ts +71 -0
  342. package/src/api/compile.ts +308 -0
  343. package/src/api/constraints.ts +104 -0
  344. package/src/api/dto.ts +445 -0
  345. package/src/api/engine.ts +328 -0
  346. package/src/api/evaluate.ts +11 -0
  347. package/src/api/project.ts +255 -0
  348. package/src/api/tagged.ts +35 -0
  349. package/src/cli/dto-check.ts +94 -0
  350. package/src/cli/fhirpath-check.ts +168 -0
  351. package/src/cli/ts-loader.mjs +49 -0
  352. package/src/engine/context.ts +282 -0
  353. package/src/engine/evaluator.ts +246 -0
  354. package/src/engine/navigation.ts +106 -0
  355. package/src/engine/operators/collections.ts +34 -0
  356. package/src/engine/operators/comparison.ts +82 -0
  357. package/src/engine/operators/equality.ts +232 -0
  358. package/src/engine/operators/index.ts +65 -0
  359. package/src/engine/operators/logic.ts +53 -0
  360. package/src/engine/operators/math.ts +225 -0
  361. package/src/engine/operators/strings.ts +25 -0
  362. package/src/engine/operators/types.ts +16 -0
  363. package/src/engine/type-matching.ts +148 -0
  364. package/src/errors.ts +33 -0
  365. package/src/eslint/index.ts +388 -0
  366. package/src/fhir/html-checks.ts +266 -0
  367. package/src/fhir/model-navigation.ts +148 -0
  368. package/src/functions/aggregate.ts +136 -0
  369. package/src/functions/boundary.ts +209 -0
  370. package/src/functions/combining.ts +15 -0
  371. package/src/functions/control.ts +25 -0
  372. package/src/functions/conversion.ts +349 -0
  373. package/src/functions/date-components.ts +88 -0
  374. package/src/functions/existence.ts +107 -0
  375. package/src/functions/fhir.ts +247 -0
  376. package/src/functions/filtering.ts +120 -0
  377. package/src/functions/install.ts +19 -0
  378. package/src/functions/iteration.ts +21 -0
  379. package/src/functions/math.ts +167 -0
  380. package/src/functions/reflection.ts +24 -0
  381. package/src/functions/registry.ts +72 -0
  382. package/src/functions/sort.ts +68 -0
  383. package/src/functions/string.ts +413 -0
  384. package/src/functions/subsetting.ts +89 -0
  385. package/src/functions/tree.ts +112 -0
  386. package/src/functions/type-specifier.ts +29 -0
  387. package/src/functions/utility.ts +82 -0
  388. package/src/functions/variables.ts +36 -0
  389. package/src/index.ts +30 -0
  390. package/src/lexer/lexer.ts +341 -0
  391. package/src/lexer/tokens.ts +69 -0
  392. package/src/model/provider.ts +36 -0
  393. package/src/parser/ast.ts +164 -0
  394. package/src/parser/parser.ts +321 -0
  395. package/src/parser/precedence.ts +52 -0
  396. package/src/parser/printer.ts +114 -0
  397. package/src/r4/generated/resources-data.ts +28631 -0
  398. package/src/r4/generated/type-maps.ts +22145 -0
  399. package/src/r4/generated/types-data.ts +2208 -0
  400. package/src/r4/index.ts +107 -0
  401. package/src/r4/model-data.ts +17 -0
  402. package/src/sites/index.ts +285 -0
  403. package/src/typed/infer.ts +433 -0
  404. package/src/typed/perf-fixture.types.ts +143 -0
  405. package/src/values/collection.ts +57 -0
  406. package/src/values/datetime.ts +285 -0
  407. package/src/values/decimal.ts +213 -0
  408. package/src/values/numeric.ts +63 -0
  409. package/src/values/quantity.ts +358 -0
  410. package/src/values/temporal-arithmetic.ts +231 -0
  411. package/src/values/temporal-compare.ts +65 -0
  412. package/src/values/type-compat.ts +133 -0
  413. package/src/values/typed-value.ts +151 -0
  414. package/src/values/ucum.ts +181 -0
package/src/api/dto.ts ADDED
@@ -0,0 +1,445 @@
1
+ import '../functions/install.ts'
2
+
3
+ import { mergeEnvKeys, normalizeEnvKeys } from '../engine/context.ts'
4
+ import { FhirPathTypeError } from '../errors.ts'
5
+ import { functions as builtinFunctions } from '../functions/registry.ts'
6
+ import type { ModelProvider } from '../model/provider.ts'
7
+ import type { FhirTypeName } from '../typed/infer.ts'
8
+ import { canonicalFocusType, typesOverlap } from '../values/type-compat.ts'
9
+ import type { TypedValue } from '../values/typed-value.ts'
10
+ import { toSubjects } from './bundle.ts'
11
+ import { columnSignature, criteriaSignature } from './column-signature.ts'
12
+ import type { AnyExpression, Compiler, CustomFunction, EvaluateOptions, SingleCustomFunction } from './compile.ts'
13
+ import type { ColumnOptions, ColumnResult, ProjectionColumn } from './project.ts'
14
+
15
+ /** The object forms of ProjectionColumn — what a `@column`/`@criteria` decorator records. */
16
+ export type ColumnSpec = Exclude<ProjectionColumn, string>
17
+
18
+ /**
19
+ * Ties `pick` to the table's row keys: with a table `choices`, `pick` must name
20
+ * a row field; without one, `pick` is rejected outright. Applied as a validation
21
+ * intersection on the options parameter, so a `pick` typo is a compile error at
22
+ * the decorator.
23
+ */
24
+ type PickConstraint<Options> = Options extends { choices: readonly (infer Row extends { code: string })[] }
25
+ ? { pick?: keyof Row & string }
26
+ : { pick?: never }
27
+
28
+ /** TypeScript error data for a DTO field that cannot hold its column result. */
29
+ export interface ColumnTypeMismatch<Declared, Inferred> {
30
+ readonly __brand: 'fhirpath-ts: the declared field type cannot hold what this column yields'
31
+ readonly declared: Declared
32
+ readonly inferred: Inferred
33
+ }
34
+
35
+ /** Accepts unknown inference; `analyzeDto` checks an explicit column `type`. */
36
+ type Checked<Inferred, Declared> = unknown extends Inferred
37
+ ? (initial: Declared) => Declared
38
+ : [Inferred] extends [Declared]
39
+ ? (initial: Declared) => Declared
40
+ : ColumnTypeMismatch<Declared, Inferred>
41
+
42
+ /** Every DTO instance carries the type its columns read, which is also their inference root. */
43
+ export interface DtoInstance {
44
+ readonly fhirType: string
45
+ }
46
+
47
+ /** The inference root for a DTO's columns: the `fhirType` of the class they are declared on. */
48
+ type RootOf<This> = This extends { readonly fhirType: infer Root extends string } ? Root : 'opaque'
49
+
50
+ /** A checked field decorator for a column whose value type is already fixed (a criteria). */
51
+ type ColumnDecorator<Value> = <This extends DtoInstance, Declared>(
52
+ target: undefined,
53
+ context: ClassFieldDecoratorContext<This, Declared>
54
+ ) => Checked<Value, Declared>
55
+
56
+ /** A checked field decorator whose column value depends on the root it lands on. */
57
+ type PathDecorator<Column extends { path: string }> = <This extends DtoInstance, Declared>(
58
+ target: undefined,
59
+ context: ClassFieldDecoratorContext<This, Declared>
60
+ ) => Checked<ColumnResult<Column, RootOf<This>>, Declared>
61
+
62
+ /**
63
+ * Environment values owned by a DTO. Declare them as `static env`, with keys
64
+ * written with or without `%`. They apply only to that DTO's column bodies.
65
+ * Subclasses merge values by key; annotate a base field as `DtoEnv` when a
66
+ * subclass should override only part of the record.
67
+ */
68
+ export type DtoEnv = Record<string, unknown>
69
+
70
+ /** Base class returned by `defineDto()`, with the FHIR type used for column inference. */
71
+ export type DtoBase<Root extends string> = (new () => { readonly fhirType: Root }) & { readonly fhirType: Root }
72
+
73
+ /** A DTO class: a `defineDto()` base, or any class extending one. */
74
+ export type DtoClass = (new () => DtoInstance) & { readonly fhirType: string }
75
+
76
+ /** The DTO instance type returned by projection, including getters and methods. */
77
+ export type DtoRow<C extends DtoClass> = InstanceType<C>
78
+
79
+ /** Data a DTO reads in addition to the projected resource. DTO-owned values use `static env`. */
80
+ export interface DtoOptions {
81
+ /** Per-row bindings the columns read (EvaluateOptions.vars semantics; may reference per-call env). */
82
+ vars?: Record<string, AnyExpression | readonly TypedValue[]>
83
+ /** Environment names supplied by `project()`, declared so DTO checks can resolve them. */
84
+ callerEnv?: readonly string[]
85
+ }
86
+
87
+ /** Everything a DTO class was declared with; `project()`, the engine, and `analyzeDto` all read it from here. */
88
+ export interface DtoDefinition {
89
+ readonly fhirType: string
90
+ /** A decorator always records an object form, so a consumer never has to handle the plain-string column. */
91
+ readonly columns: Readonly<Record<string, ColumnSpec>>
92
+ /** The `static env` fields down the class chain, merged per name with the most derived winning. */
93
+ readonly env: Record<string, unknown> | undefined
94
+ readonly vars: Record<string, AnyExpression | readonly TypedValue[]> | undefined
95
+ /** Env names the projecting call supplies (see DtoOptions.callerEnv). */
96
+ readonly callerEnv: readonly string[] | undefined
97
+ }
98
+
99
+ /** The `fhirType`/`vars` a `defineDto()` base was created with, by that base class. */
100
+ const bases = new WeakMap<object, { fhirType: string } & DtoOptions>()
101
+
102
+ /**
103
+ * Columns by the class that declared them. A field decorator runs before its
104
+ * class exists, so it records through the initializer it returns, where `this`
105
+ * is the instance being built and `this.constructor` the class — `dtoDefinition`
106
+ * instantiates each DTO once to collect them.
107
+ */
108
+ const declaredColumns = new WeakMap<object, Record<string, ColumnSpec>>()
109
+
110
+ /** Definitions already collected, keyed by the DTO class. */
111
+ const definitions = new WeakMap<object, DtoDefinition>()
112
+
113
+ /** The DTO class whose field initializers may record columns during definition collection. */
114
+ let collecting: object | undefined
115
+
116
+ /**
117
+ * Creates a DTO base for one FHIR resource or datatype. The type becomes the
118
+ * context for relative column paths. Subclasses may add decorated fields,
119
+ * getters, methods, and shared base columns.
120
+ */
121
+ export function defineDto<const Root extends FhirTypeName>(fhirType: Root, options: DtoOptions = {}): DtoBase<Root> {
122
+ const base = class {
123
+ /** On the prototype, so it stays out of a projected row's own keys. */
124
+ get fhirType(): Root {
125
+ return fhirType
126
+ }
127
+ }
128
+ // A readable name for project()/registration errors; a subclass replaces it.
129
+ Object.defineProperty(base, 'name', { value: `${fhirType}Dto` })
130
+ Object.defineProperty(base, 'fhirType', { value: fhirType, enumerable: true })
131
+ bases.set(base, { fhirType, ...options })
132
+ return base as unknown as DtoBase<Root>
133
+ }
134
+
135
+ /** Records one column against the class being collected, and does nothing at any other time. */
136
+ function recordColumn(instance: object, name: string, spec: ColumnSpec): void {
137
+ const cls = instance.constructor as object
138
+ if (cls !== collecting) {
139
+ return
140
+ }
141
+ const own = declaredColumns.get(cls) ?? {}
142
+ own[name] = spec
143
+ declaredColumns.set(cls, own)
144
+ }
145
+
146
+ /** The decorator both `column()` and `criteria()` return: record on construction, leave the field empty. */
147
+ function fieldDecorator(spec: ColumnSpec): (target: undefined, context: ClassFieldDecoratorContext) => unknown {
148
+ return (_target, context) => {
149
+ if (context.static || context.private) {
150
+ throw new FhirPathTypeError(`Column '${String(context.name)}' must be a public instance field`)
151
+ }
152
+ const name = String(context.name)
153
+ return function (this: object): undefined {
154
+ recordColumn(this, name, spec)
155
+ return undefined
156
+ }
157
+ }
158
+ }
159
+
160
+ /**
161
+ * Declares one column of a DTO: the expression it reads, relative to the
162
+ * class's `fhirType`, plus the same options a `project()` column takes —
163
+ * `type`, `as`, `choices`/`pick`, `enum`, `default`, `collection`. The field's
164
+ * declared type is checked against what the expression yields, and is the type
165
+ * a projected row holds there.
166
+ */
167
+ export function column<const Expr extends string>(path: Expr): PathDecorator<{ path: Expr }>
168
+ export function column<const Expr extends string, const Options extends ColumnOptions>(
169
+ path: Expr,
170
+ options: Options & PickConstraint<Options>
171
+ ): PathDecorator<{ path: Expr } & Options>
172
+ export function column(path: string, options?: ColumnOptions): unknown {
173
+ return fieldDecorator({ path, ...options })
174
+ }
175
+
176
+ /**
177
+ * Declares a Boolean criteria column. It uses `FhirPathEngine.test()` rules: one
178
+ * Boolean returns itself, empty returns `false`, and several values are an
179
+ * error. A registered criteria function keeps the same behavior.
180
+ */
181
+ export function criteria<const Expr extends string>(expr: Expr): ColumnDecorator<boolean>
182
+ export function criteria(expr: string): unknown {
183
+ return fieldDecorator({ test: expr })
184
+ }
185
+
186
+ /** A class and the classes it extends, most derived first. */
187
+ function* classChain(cls: object): Generator<{ readonly name: string }> {
188
+ for (let current: unknown = cls; typeof current === 'function'; current = Object.getPrototypeOf(current)) {
189
+ yield current as { readonly name: string }
190
+ }
191
+ }
192
+
193
+ /** The `defineDto()` base a class descends from, with the fhirType/vars it fixed. */
194
+ function baseOf(cls: object): ({ fhirType: string } & DtoOptions) | undefined {
195
+ for (const current of classChain(cls)) {
196
+ const base = bases.get(current)
197
+ if (base !== undefined) {
198
+ return base
199
+ }
200
+ }
201
+ return undefined
202
+ }
203
+
204
+ /**
205
+ * Merges each class's own `static env`, from the base to the most derived class.
206
+ * A getter is read once while the definition is collected. An empty result has
207
+ * no environment overlay.
208
+ */
209
+ function declaredEnv(cls: DtoClass): Record<string, unknown> | undefined {
210
+ const declared: Record<string, unknown>[] = []
211
+ for (const current of classChain(cls)) {
212
+ const own = staticEnv(current)
213
+ if (own !== undefined) {
214
+ declared.unshift(own)
215
+ }
216
+ }
217
+ const merged = Object.assign({}, ...declared.map(normalizeEnvKeys)) as Record<string, unknown>
218
+ return Object.keys(merged).length === 0 ? undefined : merged
219
+ }
220
+
221
+ /**
222
+ * One class's own `static env`, as a field or a getter, checked for the shape
223
+ * the engine can bind. Names the class that declared it, which is the one to
224
+ * edit even when the projected DTO is several subclasses below.
225
+ */
226
+ function staticEnv(cls: { readonly name: string }): Record<string, unknown> | undefined {
227
+ const declared = Object.getOwnPropertyDescriptor(cls, 'env')
228
+ if (declared === undefined) {
229
+ return undefined
230
+ }
231
+ const own: unknown = declared.get === undefined ? declared.value : declared.get.call(cls)
232
+ if (own === undefined) {
233
+ return undefined
234
+ }
235
+ if (typeof own !== 'object' || own === null || Array.isArray(own)) {
236
+ throw new FhirPathTypeError(
237
+ `DTO ${cls.name} declares a static 'env' that is not a record of variables; ` +
238
+ 'write it as { name: value }, the same shape as EvaluateOptions.env'
239
+ )
240
+ }
241
+ return own as Record<string, unknown>
242
+ }
243
+
244
+ /**
245
+ * Whether a value is a DTO class — one `defineDto()` produced, or a subclass of
246
+ * one. Lets tooling pick the DTOs out of a module's exports (see the
247
+ * `fhirpath-check` CLI) without instantiating anything that is not one.
248
+ */
249
+ export function isDtoClass(value: unknown): value is DtoClass {
250
+ return typeof value === 'function' && baseOf(value) !== undefined
251
+ }
252
+
253
+ /** Collects and caches a DTO's type, columns, environment, variables, and caller environment names. */
254
+ export function dtoDefinition(cls: DtoClass): DtoDefinition {
255
+ const cached = definitions.get(cls)
256
+ if (cached !== undefined) {
257
+ return cached
258
+ }
259
+ const base = baseOf(cls)
260
+ if (base === undefined) {
261
+ throw new FhirPathTypeError(
262
+ `${cls.name || 'The class'} is not a DTO class; extend defineDto('<fhirType>') to declare one`
263
+ )
264
+ }
265
+ // A field initializer may collect another DTO. Restore the outer class so its
266
+ // remaining fields are still recorded.
267
+ const outer = collecting
268
+ collecting = cls
269
+ try {
270
+ new cls()
271
+ } finally {
272
+ collecting = outer
273
+ }
274
+ // Copied, so the definition cannot be reached through the collection map.
275
+ const columns = { ...declaredColumns.get(cls) }
276
+ if (Object.keys(columns).length === 0) {
277
+ throw new FhirPathTypeError(`DTO ${cls.name} declares no columns; add a @column field`)
278
+ }
279
+ /* v8 ignore start -- TypeScript rejects a field that shadows the base's fhirType; this only fires for an untyped host (the demo playground runs transpile-only code) */
280
+ if ('fhirType' in columns) {
281
+ throw new FhirPathTypeError(`DTO ${cls.name} declares a column named 'fhirType', which every row already carries`)
282
+ }
283
+ /* v8 ignore stop */
284
+ const definition: DtoDefinition = {
285
+ fhirType: base.fhirType,
286
+ columns,
287
+ env: declaredEnv(cls),
288
+ vars: base.vars,
289
+ callerEnv: base.callerEnv,
290
+ }
291
+ definitions.set(cls, definition)
292
+ return definition
293
+ }
294
+
295
+ /**
296
+ * Adds DTO columns to the engine's function table. Each function keeps its DTO
297
+ * input type and environment. Same-name functions become overloads when their
298
+ * input types do not overlap.
299
+ */
300
+ export function withDtos(defaults: EvaluateOptions, dtos: readonly DtoClass[], compile: Compiler): EvaluateOptions {
301
+ if (dtos.length === 0) {
302
+ return defaults
303
+ }
304
+ const { model } = defaults
305
+ if (model === undefined) {
306
+ // The model selects a column from the call focus and separates same-name columns.
307
+ throw new FhirPathTypeError(
308
+ `Registering DTOs (${dtos.map(dto => dto.name).join(', ')}) needs a model; ` +
309
+ 'a column is written for one type, and without a model the engine cannot check a call against it. ' +
310
+ 'Pass model to the engine, or project the DTO without registering it.'
311
+ )
312
+ }
313
+ const functions: Record<string, CustomFunction> = { ...defaults.functions }
314
+ for (const dto of dtos) {
315
+ const definition = dtoDefinition(dto)
316
+ for (const [name, spec] of Object.entries(definition.columns)) {
317
+ // Without this, createContext fails later and names the function rather
318
+ // than the field that caused it.
319
+ if (builtinFunctions.has(name)) {
320
+ throw new FhirPathTypeError(
321
+ `DTO ${dto.name} declares a column named '${name}', which is a built-in function; rename the field`
322
+ )
323
+ }
324
+ functions[name] = declaredWith(
325
+ functions[name],
326
+ columnFunction(spec, compile, definition),
327
+ model,
328
+ () => `DTO ${dto.name} redefines the function '${name}'`
329
+ )
330
+ }
331
+ }
332
+ return { ...defaults, functions }
333
+ }
334
+
335
+ /** Adds a column declaration when its focus type distinguishes it from every existing declaration. */
336
+ function declaredWith(
337
+ existing: CustomFunction | undefined,
338
+ column: SingleCustomFunction,
339
+ model: ModelProvider,
340
+ blamed: () => string
341
+ ): CustomFunction {
342
+ if (existing === undefined) {
343
+ return column
344
+ }
345
+ const declared = 'overloads' in existing ? existing.overloads : [existing]
346
+ for (const other of declared) {
347
+ const reason = indistinguishable(model, other, column)
348
+ if (reason !== undefined) {
349
+ throw new FhirPathTypeError(`${blamed()}: ${reason}`)
350
+ }
351
+ }
352
+ return { overloads: [...declared, column] }
353
+ }
354
+
355
+ /**
356
+ * Explains why focus-only dispatch cannot separate two declarations. Each side
357
+ * must declare input types, and those types must not overlap.
358
+ */
359
+ function indistinguishable(model: ModelProvider, a: SingleCustomFunction, b: SingleCustomFunction): string | undefined {
360
+ const wanted = canonicalTypes(model, a.signature?.input?.types)
361
+ const claimed = canonicalTypes(model, b.signature?.input?.types)
362
+ if (wanted === undefined || claimed === undefined) {
363
+ return 'a declaration that names no input type answers every call, so nothing else may share its name'
364
+ }
365
+ const overlap = wanted.flatMap(one =>
366
+ claimed.filter(other => typesOverlap(model, one, other)).map(other => [one, other])
367
+ )
368
+ const pair = overlap[0]
369
+ if (pair === undefined) {
370
+ return undefined
371
+ }
372
+ // Equal types make the field name ambiguous, even though the type itself is clear.
373
+ return pair[0] === pair[1] ? `both are written for ${pair[0]}` : `a focus can be both ${pair[0]} and ${pair[1]}`
374
+ }
375
+
376
+ /** Declared input types as the model names them, or undefined when the name declares none the model knows. */
377
+ function canonicalTypes(model: ModelProvider, types: readonly string[] | undefined): string[] | undefined {
378
+ if (types === undefined) {
379
+ return undefined
380
+ }
381
+ const canonical = types
382
+ .map(type => canonicalFocusType(model, type))
383
+ .filter((type): type is string => type !== undefined)
384
+ return canonical.length === 0 ? undefined : canonical
385
+ }
386
+
387
+ /**
388
+ * Converts a DTO column into a typed expression function with the DTO's local
389
+ * environment. Criteria functions also carry the criteria Boolean rule. DTO
390
+ * variables remain projection-only because function calls have no row.
391
+ */
392
+ function columnFunction(spec: ColumnSpec, compile: Compiler, dto: DtoDefinition): SingleCustomFunction {
393
+ const { fhirType, env } = dto
394
+ if ('test' in spec) {
395
+ return {
396
+ expression: compile(spec.test),
397
+ criteria: true,
398
+ signature: criteriaSignature(fhirType),
399
+ ...(env !== undefined && { env }),
400
+ }
401
+ }
402
+ const signature = columnSignature(spec, fhirType)
403
+ return {
404
+ expression: compile(spec.path),
405
+ ...(signature !== undefined && { signature }),
406
+ ...(env !== undefined && { env }),
407
+ }
408
+ }
409
+
410
+ /**
411
+ * Checks each resource against the DTO type before projection. Without this
412
+ * check, a wrong resource could produce a typed row filled with defaults.
413
+ * Datatype inputs have no `resourceType` to check.
414
+ */
415
+ export function assertInputMatchesDto(input: unknown, dto: DtoClass): void {
416
+ const { fhirType } = dtoDefinition(dto)
417
+ toSubjects(input).forEach((subject, index) => {
418
+ const resourceType = (subject.value as { resourceType?: unknown } | null | undefined)?.resourceType
419
+ if (typeof resourceType === 'string' && resourceType !== fhirType) {
420
+ throw new FhirPathTypeError(
421
+ `project(): row ${index} is a ${resourceType}, but ${dto.name} declares fhirType '${fhirType}'`
422
+ )
423
+ }
424
+ })
425
+ }
426
+
427
+ /**
428
+ * Merges DTO options with call options. DTO environment values win so projected
429
+ * and registered columns read the same value. Call variables win because they
430
+ * may replace a DTO's row binding.
431
+ */
432
+ export function dtoCallOptions(dto: DtoClass, options: EvaluateOptions | undefined): EvaluateOptions | undefined {
433
+ const { env, vars } = dtoDefinition(dto)
434
+ if (env === undefined && vars === undefined) {
435
+ return options
436
+ }
437
+ const merged: EvaluateOptions = { ...options }
438
+ if (env !== undefined) {
439
+ merged.env = mergeEnvKeys(options?.env, env)
440
+ }
441
+ if (vars !== undefined) {
442
+ merged.vars = mergeEnvKeys(vars, options?.vars)
443
+ }
444
+ return merged
445
+ }