fhirpath-ts 0.2.0 → 0.2.2
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.
- package/README.md +12 -5
- package/dist/analyzer/analyze-dto.d.ts.map +1 -1
- package/dist/analyzer/analyze-dto.js +14 -8
- package/dist/analyzer/analyze-dto.js.map +1 -1
- package/dist/analyzer/analyze.d.ts +23 -12
- package/dist/analyzer/analyze.d.ts.map +1 -1
- package/dist/analyzer/analyze.js +138 -46
- package/dist/analyzer/analyze.js.map +1 -1
- package/dist/analyzer/declarations.d.ts +6 -0
- package/dist/analyzer/declarations.d.ts.map +1 -1
- package/dist/analyzer/declarations.js +7 -0
- package/dist/analyzer/declarations.js.map +1 -1
- package/dist/analyzer/expression-policy.d.ts +88 -14
- package/dist/analyzer/expression-policy.d.ts.map +1 -1
- package/dist/analyzer/expression-policy.js +296 -41
- package/dist/analyzer/expression-policy.js.map +1 -1
- package/dist/analyzer/operator-rules.d.ts.map +1 -1
- package/dist/analyzer/operator-rules.js +7 -6
- package/dist/analyzer/operator-rules.js.map +1 -1
- package/dist/analyzer/signatures.d.ts +49 -0
- package/dist/analyzer/signatures.d.ts.map +1 -1
- package/dist/analyzer/signatures.js +76 -31
- package/dist/analyzer/signatures.js.map +1 -1
- package/dist/analyzer/source-options.d.ts +17 -0
- package/dist/analyzer/source-options.d.ts.map +1 -0
- package/dist/analyzer/source-options.js +3 -0
- package/dist/analyzer/source-options.js.map +1 -0
- package/dist/api/dto.d.ts +9 -4
- package/dist/api/dto.d.ts.map +1 -1
- package/dist/api/dto.js +14 -3
- package/dist/api/dto.js.map +1 -1
- package/dist/api/strict.d.ts.map +1 -1
- package/dist/api/strict.js +8 -3
- package/dist/api/strict.js.map +1 -1
- package/dist/cli/dto-check.d.ts +9 -0
- package/dist/cli/dto-check.d.ts.map +1 -1
- package/dist/cli/dto-check.js +49 -6
- package/dist/cli/dto-check.js.map +1 -1
- package/dist/cli/fhirpath-check.js +161 -31
- package/dist/cli/fhirpath-check.js.map +1 -1
- package/dist/eslint/index.d.ts.map +1 -1
- package/dist/eslint/index.js +13 -8
- package/dist/eslint/index.js.map +1 -1
- package/dist/r4/generated/resources-data.d.ts +6 -2
- package/dist/r4/generated/resources-data.d.ts.map +1 -1
- package/dist/r4/generated/resources-data.js +626 -28627
- package/dist/r4/generated/resources-data.js.map +1 -1
- package/dist/r4/generated/types-data.d.ts +6 -2
- package/dist/r4/generated/types-data.d.ts.map +1 -1
- package/dist/r4/generated/types-data.js +84 -2204
- package/dist/r4/generated/types-data.js.map +1 -1
- package/dist/r4/index.d.ts.map +1 -1
- package/dist/r4/index.js +10 -4
- package/dist/r4/index.js.map +1 -1
- package/dist/r4/model-data.d.ts +17 -0
- package/dist/r4/model-data.d.ts.map +1 -1
- package/dist/r4/model-data.js +118 -1
- package/dist/r4/model-data.js.map +1 -1
- package/dist/sites/index.d.ts +31 -2
- package/dist/sites/index.d.ts.map +1 -1
- package/dist/sites/index.js +351 -30
- package/dist/sites/index.js.map +1 -1
- package/dist/typed/infer.d.ts +2 -0
- package/dist/typed/infer.d.ts.map +1 -1
- package/package.json +1 -1
- package/src/analyzer/analyze-dto.ts +19 -9
- package/src/analyzer/analyze.ts +186 -54
- package/src/analyzer/declarations.ts +12 -0
- package/src/analyzer/expression-policy.ts +423 -47
- package/src/analyzer/operator-rules.ts +7 -6
- package/src/analyzer/signatures.ts +100 -36
- package/src/analyzer/source-options.ts +19 -0
- package/src/api/dto.ts +35 -9
- package/src/api/strict.ts +8 -3
- package/src/cli/dto-check.ts +56 -6
- package/src/cli/fhirpath-check.ts +180 -34
- package/src/eslint/index.ts +15 -12
- package/src/r4/generated/resources-data.ts +624 -28628
- package/src/r4/generated/types-data.ts +82 -2205
- package/src/r4/index.ts +11 -5
- package/src/r4/model-data.ts +127 -0
- package/src/sites/index.ts +428 -40
- package/src/typed/infer.ts +2 -2
package/src/r4/index.ts
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import { FhirPathEngine } from '../api/engine.ts'
|
|
2
2
|
import type { ElementInfo, ModelProvider } from '../model/provider.ts'
|
|
3
|
-
import {
|
|
4
|
-
import {
|
|
5
|
-
import type
|
|
3
|
+
import { R4_RESOURCES_COMPACT } from './generated/resources-data.ts'
|
|
4
|
+
import { R4_DATA_TYPES_COMPACT } from './generated/types-data.ts'
|
|
5
|
+
import { CompactTypeTable, type GeneratedElement, type GeneratedType } from './model-data.ts'
|
|
6
6
|
|
|
7
7
|
// One canonical FHIR-primitive → System map lives in values/typed-value.ts;
|
|
8
8
|
// re-exported here because the model subpath is where consumers look for it.
|
|
@@ -12,8 +12,11 @@ export type { GeneratedElement, GeneratedType } from './model-data.ts'
|
|
|
12
12
|
const NAMESPACE = 'FHIR'
|
|
13
13
|
const PREFIX = `${NAMESPACE}.`
|
|
14
14
|
|
|
15
|
+
const RESOURCES = new CompactTypeTable(R4_RESOURCES_COMPACT)
|
|
16
|
+
const DATA_TYPES = new CompactTypeTable(R4_DATA_TYPES_COMPACT)
|
|
17
|
+
|
|
15
18
|
function lookupType(name: string): GeneratedType | undefined {
|
|
16
|
-
return
|
|
19
|
+
return RESOURCES.get(name) ?? DATA_TYPES.get(name)
|
|
17
20
|
}
|
|
18
21
|
|
|
19
22
|
function localName(canonical: string): string {
|
|
@@ -85,7 +88,10 @@ export const r4Model: ModelProvider = {
|
|
|
85
88
|
}
|
|
86
89
|
current = definition.b
|
|
87
90
|
}
|
|
88
|
-
|
|
91
|
+
// The tables carry each inherited element only on the type that declares
|
|
92
|
+
// it, so the walk yields own elements before inherited ones; sorting gives
|
|
93
|
+
// callers one stable order independent of where an element is declared.
|
|
94
|
+
return names.sort()
|
|
89
95
|
},
|
|
90
96
|
|
|
91
97
|
isSubtypeOf(type: string, base: string): boolean {
|
package/src/r4/model-data.ts
CHANGED
|
@@ -15,3 +15,130 @@ export interface GeneratedType {
|
|
|
15
15
|
b?: string
|
|
16
16
|
e: Record<string, GeneratedElement>
|
|
17
17
|
}
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* The generated tables ship as one compact string instead of an object literal:
|
|
21
|
+
* the string is smaller to download and cheaper to decode than a large literal
|
|
22
|
+
* is to parse, and `CompactTypeTable` decodes one type at a time so only the
|
|
23
|
+
* types an application touches are ever materialized.
|
|
24
|
+
*
|
|
25
|
+
* Format, one line per type:
|
|
26
|
+
*
|
|
27
|
+
* Name|Base|element:type1,type2*^<Target1,Target2;element2:type
|
|
28
|
+
*
|
|
29
|
+
* `*` marks a collection (`a: 1`), `^` a choice element (`c: 1`), and `<`
|
|
30
|
+
* starts the Reference target list (`r`). An empty Base segment means the type
|
|
31
|
+
* has no base. Elements identical to the nearest ancestor's entry are omitted
|
|
32
|
+
* by the generator; lookups walk the base chain (see index.ts).
|
|
33
|
+
*/
|
|
34
|
+
const RESERVED_IN_COMPACT = /[|;:,*^<\n\\`$]/
|
|
35
|
+
|
|
36
|
+
function assertCompactSafe(name: string): string {
|
|
37
|
+
if (RESERVED_IN_COMPACT.test(name)) {
|
|
38
|
+
throw new Error(`name contains a character reserved by the compact model encoding: ${name}`)
|
|
39
|
+
}
|
|
40
|
+
return name
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
/** Encodes a generated table into the compact string form (generator-side; see the format above). */
|
|
44
|
+
export function encodeCompactTypes(types: Record<string, GeneratedType>): string {
|
|
45
|
+
const lines: string[] = []
|
|
46
|
+
for (const [name, type] of Object.entries(types)) {
|
|
47
|
+
const elements = Object.entries(type.e).map(([element, info]) => {
|
|
48
|
+
let entry = `${assertCompactSafe(element)}:${info.t.map(assertCompactSafe).join(',')}`
|
|
49
|
+
if (info.a === 1) {
|
|
50
|
+
entry += '*'
|
|
51
|
+
}
|
|
52
|
+
if (info.c === 1) {
|
|
53
|
+
entry += '^'
|
|
54
|
+
}
|
|
55
|
+
if (info.r !== undefined) {
|
|
56
|
+
entry += `<${info.r.map(assertCompactSafe).join(',')}`
|
|
57
|
+
}
|
|
58
|
+
return entry
|
|
59
|
+
})
|
|
60
|
+
lines.push(`${assertCompactSafe(name)}|${assertCompactSafe(type.b ?? '')}|${elements.join(';')}`)
|
|
61
|
+
}
|
|
62
|
+
return lines.join('\n')
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
/** Decodes the segment after the second `|` of a line. */
|
|
66
|
+
function decodeTypeLine(line: string): GeneratedType {
|
|
67
|
+
const baseStart = line.indexOf('|') + 1
|
|
68
|
+
const baseEnd = line.indexOf('|', baseStart)
|
|
69
|
+
const base = line.slice(baseStart, baseEnd)
|
|
70
|
+
const e: Record<string, GeneratedElement> = {}
|
|
71
|
+
const body = line.slice(baseEnd + 1)
|
|
72
|
+
if (body !== '') {
|
|
73
|
+
for (const entry of body.split(';')) {
|
|
74
|
+
const colon = entry.indexOf(':')
|
|
75
|
+
const name = entry.slice(0, colon)
|
|
76
|
+
let rest = entry.slice(colon + 1)
|
|
77
|
+
const element: GeneratedElement = { t: [] }
|
|
78
|
+
const targetsStart = rest.indexOf('<')
|
|
79
|
+
if (targetsStart >= 0) {
|
|
80
|
+
element.r = rest.slice(targetsStart + 1).split(',')
|
|
81
|
+
rest = rest.slice(0, targetsStart)
|
|
82
|
+
}
|
|
83
|
+
if (rest.endsWith('^')) {
|
|
84
|
+
element.c = 1
|
|
85
|
+
rest = rest.slice(0, -1)
|
|
86
|
+
}
|
|
87
|
+
if (rest.endsWith('*')) {
|
|
88
|
+
element.a = 1
|
|
89
|
+
rest = rest.slice(0, -1)
|
|
90
|
+
}
|
|
91
|
+
element.t = rest.split(',')
|
|
92
|
+
e[name] = element
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
return base === '' ? { e } : { b: base, e }
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
/** Eagerly decodes a whole table; for build scripts, not the runtime path. */
|
|
99
|
+
export function decodeCompactTypes(encoded: string): Record<string, GeneratedType> {
|
|
100
|
+
const types: Record<string, GeneratedType> = {}
|
|
101
|
+
for (const line of encoded.split('\n')) {
|
|
102
|
+
types[line.slice(0, line.indexOf('|'))] = decodeTypeLine(line)
|
|
103
|
+
}
|
|
104
|
+
return types
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
/**
|
|
108
|
+
* Lazy view over a compact-encoded table. The line index is built on first
|
|
109
|
+
* lookup and each type is decoded once, on demand, so importing the model costs
|
|
110
|
+
* almost nothing until an expression actually navigates it.
|
|
111
|
+
*/
|
|
112
|
+
export class CompactTypeTable {
|
|
113
|
+
private readonly encoded: string
|
|
114
|
+
private index: Map<string, string> | undefined
|
|
115
|
+
private readonly decoded = new Map<string, GeneratedType>()
|
|
116
|
+
|
|
117
|
+
constructor(encoded: string) {
|
|
118
|
+
this.encoded = encoded
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
get(name: string): GeneratedType | undefined {
|
|
122
|
+
const cached = this.decoded.get(name)
|
|
123
|
+
if (cached !== undefined) {
|
|
124
|
+
return cached
|
|
125
|
+
}
|
|
126
|
+
const line = this.lines().get(name)
|
|
127
|
+
if (line === undefined) {
|
|
128
|
+
return undefined
|
|
129
|
+
}
|
|
130
|
+
const type = decodeTypeLine(line)
|
|
131
|
+
this.decoded.set(name, type)
|
|
132
|
+
return type
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
private lines(): Map<string, string> {
|
|
136
|
+
if (this.index === undefined) {
|
|
137
|
+
this.index = new Map()
|
|
138
|
+
for (const line of this.encoded.split('\n')) {
|
|
139
|
+
this.index.set(line.slice(0, line.indexOf('|')), line)
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
return this.index
|
|
143
|
+
}
|
|
144
|
+
}
|