fhir-openapi-translator 0.1.1 → 0.2.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.
- package/CHANGELOG.md +51 -0
- package/README.md +10 -6
- package/dist/{chunk-RR46JDST.js → chunk-RRAIF3A2.js} +181 -11
- package/dist/chunk-RRAIF3A2.js.map +1 -0
- package/dist/cli.js +31 -7
- package/dist/cli.js.map +1 -1
- package/dist/index.d.ts +36 -0
- package/dist/index.js +1 -1
- package/docs/REFERENCE.md +159 -32
- package/package.json +3 -2
- package/dist/chunk-RR46JDST.js.map +0 -1
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/types.ts","../src/ig/package.ts","../src/ig/minimize.ts","../src/definitions.ts","../src/ir/structureWalker.ts","../src/ig/profile.ts","../src/searchParams.ts","../src/backends/schemaJson.ts","../src/backends/structureDefinition.ts","../src/emit/schema.ts","../src/ir/registry.ts","../src/operations.ts","../src/paths.ts","../src/generate.ts","../src/capability.ts","../src/merge.ts"],"sourcesContent":["export type FhirVersion = \"r4\" | \"r4b\" | \"r5\";\r\n\r\nexport const FHIR_VERSIONS: readonly FhirVersion[] = [\"r4\", \"r4b\", \"r5\"];\r\n\r\nexport const FHIR_VERSION_NUMBERS: Record<FhirVersion, string> = {\r\n r4: \"4.0.1\",\r\n r4b: \"4.3.0\",\r\n r5: \"5.0.0\",\r\n};\r\n\r\nexport type OpenApiVersion = \"3.0.3\" | \"3.1.0\";\r\n\r\nexport type SourceBackend = \"schema-json\" | \"structure-def\";\r\n\r\nexport interface TrimOptions {\r\n /**\r\n * Replace the Narrative type (human-readable HTML in `Resource.text`) with a\r\n * generic object. Shrinks generated models that never render narratives.\r\n */\r\n excludeNarrative?: boolean;\r\n /**\r\n * Stub out schema definitions first reached deeper than this many hops from\r\n * a requested resource with a generic object. Bounds the size of the\r\n * dependency closure for codegen targets that struggle with large graphs.\r\n */\r\n maxDepth?: number;\r\n /**\r\n * Replace required-binding enums on code fields with plain strings (the\r\n * allowed codes are appended to the description). Codegen'd models then\r\n * tolerate servers that return codes outside the strict ValueSet — a common\r\n * reality with legacy data. `resourceType` discriminators keep their enum.\r\n */\r\n noEnums?: boolean;\r\n}\r\n\r\n/** An IG package resolved to profiles + terminology (see ig/package.ts). */\r\nexport interface IgContextLike {\r\n name: string;\r\n version: string;\r\n fhirVersion: FhirVersion;\r\n profiles: unknown[];\r\n profilesMissingSnapshot: string[];\r\n resolveValueSet: (valueSetUrl: string) => string[] | undefined;\r\n}\r\n\r\n/** Preset selections accepted by `--search-params`. */\r\nexport type SearchParamPreset = \"all\" | \"minimal\" | \"none\";\r\n\r\n/**\r\n * One resource's selection: a starting set, then adjustments.\r\n *\r\n * No fixed rule can encode which parameters matter for a given resource —\r\n * `Observation.based-on`, `CarePlan.goal` and `MedicationStatement.adherence`\r\n * are all central to their resource and none is common enough to curate\r\n * globally. So a preset is a starting point that `add`/`remove` tune, rather\r\n * than a take-it-or-leave-it list.\r\n */\r\nexport interface SearchParamRule {\r\n /** A preset, or an explicit list replacing it entirely. */\r\n base: SearchParamPreset | ReadonlySet<string>;\r\n /** Codes to add to the base. */\r\n add?: ReadonlySet<string>;\r\n /** Codes to drop from the base. */\r\n remove?: ReadonlySet<string>;\r\n}\r\n\r\n/**\r\n * Which resource-specific search parameters to emit. A `default` applies to\r\n * every resource; `byResource` overrides it per resource. The common result\r\n * parameters (`_id`, `_count`, ...) are always emitted regardless.\r\n */\r\nexport interface SearchParamSelection {\r\n default?: SearchParamRule;\r\n byResource?: ReadonlyMap<string, SearchParamRule>;\r\n}\r\n\r\n/** A parsed CapabilityStatement (see capability.ts). */\r\nexport interface CapabilityLike {\r\n fhirVersion?: string;\r\n resources: {\r\n type: string;\r\n interactions: Set<string>;\r\n searchParamCodes: Set<string>;\r\n operations: Set<string>;\r\n }[];\r\n}\r\n\r\nexport interface GenerateOptions {\r\n /**\r\n * FHIR resource names, e.g. [\"Patient\", \"Observation\"]. Optional when a\r\n * `capability` statement is given (its declared resources are used); when\r\n * both are set, generation is narrowed to the requested resources.\r\n */\r\n resources?: string[];\r\n fhirVersion: FhirVersion;\r\n /**\r\n * A parsed CapabilityStatement restricting generation to one server's\r\n * declared support (resources, interactions, search params, operations).\r\n * Use `loadCapabilityStatement` / `parseCapabilityStatement` to build it.\r\n */\r\n capability?: CapabilityLike;\r\n /**\r\n * IG package to apply profiles from: a local path (`.tgz` or unpacked\r\n * directory) loaded synchronously, or a pre-resolved IgContext (use the\r\n * async `loadIg` for registry coordinates). Required when `profiles` is set.\r\n */\r\n ig?: string | IgContextLike;\r\n /**\r\n * Profile ids, names, or canonical URLs to apply to their base resources.\r\n * Each profiled resource's schemas/paths reference the named profile schema.\r\n */\r\n profiles?: string[];\r\n /** Target OpenAPI version. Default: \"3.0.3\" (widest codegen support). */\r\n openApiVersion?: OpenApiVersion;\r\n /** Definition source backend. Default: \"schema-json\". */\r\n source?: SourceBackend;\r\n /**\r\n * Also emit the standard FHIR operations applicable to the requested\r\n * resources ($everything, $validate, ...) from the official\r\n * OperationDefinitions. Default: false.\r\n */\r\n operations?: boolean;\r\n /** Server base URL for the `servers` entry. Omitted when not given. */\r\n baseUrl?: string;\r\n /** Override the generated `info.title`. */\r\n title?: string;\r\n trim?: TrimOptions;\r\n /**\r\n * Restrict which resource-specific search parameters are emitted. Servers\r\n * commonly index only a subset, and every indexed parameter costs storage\r\n * and write throughput; this keeps the published contract matched to what a\r\n * deployment actually supports. Combined with `capability`, the two narrow\r\n * each other (the intersection is emitted).\r\n */\r\n searchParams?: SearchParamSelection;\r\n}\r\n\r\n/** A JSON-Schema-like node. Kept loose: definitions come from vendored files. */\r\nexport type JsonSchemaNode = { [key: string]: unknown };\r\n\r\n/** A generated OpenAPI document (3.0.3 or 3.1.0) as a plain object. */\r\nexport type OpenApiDocument = { [key: string]: unknown };\r\n","import { execFileSync } from \"node:child_process\";\r\nimport fs from \"node:fs\";\r\nimport os from \"node:os\";\r\nimport path from \"node:path\";\r\nimport {\r\n buildValueSetResolver,\r\n minimizeStructureDefinition,\r\n type RawStructureDefinition,\r\n type ValueSetResolver,\r\n} from \"./minimize.js\";\r\nimport type { MinStructureDefinition } from \"../definitions.js\";\r\nimport { FHIR_VERSIONS, type FhirVersion } from \"../types.js\";\r\n\r\n/** Maps an IG package's FHIR version string to our supported version keys. */\r\nconst FHIR_VERSION_BY_NUMBER: Record<string, FhirVersion> = {\r\n \"4.0.1\": \"r4\",\r\n \"4.0.0\": \"r4\",\r\n \"4.3.0\": \"r4b\",\r\n \"5.0.0\": \"r5\",\r\n};\r\n\r\nexport interface IgProfile {\r\n /** Versionless canonical URL. */\r\n url: string;\r\n id?: string;\r\n name: string;\r\n type: string;\r\n definition: MinStructureDefinition;\r\n}\r\n\r\nexport interface IgContext {\r\n name: string;\r\n version: string;\r\n fhirVersion: FhirVersion;\r\n profiles: IgProfile[];\r\n /** Names/URLs of constraint profiles that lack a snapshot (cannot be applied). */\r\n profilesMissingSnapshot: string[];\r\n resolveValueSet: ValueSetResolver;\r\n}\r\n\r\nexport interface LoadIgOptions {\r\n /** Resolve core bindings (e.g. administrative-gender) not defined in the IG. */\r\n coreValueSetFallback?: ValueSetResolver;\r\n /** Base directory for the registry download cache. Defaults to ~/.fhir-oas. */\r\n cacheDir?: string;\r\n fetchImpl?: typeof fetch;\r\n}\r\n\r\ninterface RawResource {\r\n resourceType?: string;\r\n url?: string;\r\n name?: string;\r\n id?: string;\r\n type?: string;\r\n kind?: string;\r\n derivation?: string;\r\n snapshot?: unknown;\r\n [key: string]: unknown;\r\n}\r\n\r\nconst REGISTRY_BASE = \"https://packages.fhir.org\";\r\n\r\n/**\r\n * Resolves the `--ig` input to an IgContext. Accepts a path to a package\r\n * tarball (`.tgz`), a path to an unpacked package directory, or a registry\r\n * coordinate (`name` or `name@version`) fetched from packages.fhir.org and\r\n * cached locally. Async because registry coordinates hit the network.\r\n */\r\nexport async function loadIg(input: string, options: LoadIgOptions = {}): Promise<IgContext> {\r\n if (isRegistryCoordinate(input)) {\r\n const tarball = await fetchFromRegistry(input, options);\r\n return buildContext(readFromTarball(tarball), options.coreValueSetFallback);\r\n }\r\n return loadIgSync(input, options);\r\n}\r\n\r\n/**\r\n * Synchronous IG loader for local inputs (a `.tgz` or an unpacked directory).\r\n * Registry coordinates require the async {@link loadIg} because they fetch\r\n * over the network.\r\n */\r\nexport function loadIgSync(input: string, options: LoadIgOptions = {}): IgContext {\r\n if (isRegistryCoordinate(input)) {\r\n throw new Error(\r\n `\"${input}\" looks like a registry package coordinate, which requires a network ` +\r\n `fetch. Use loadIg() (async) or the CLI, or download the package and pass a local path.`,\r\n );\r\n }\r\n const stat = fs.existsSync(input) ? fs.statSync(input) : undefined;\r\n if (!stat) {\r\n throw new Error(\r\n `--ig \"${input}\" is not a file or directory. Pass a package .tgz, an unpacked ` +\r\n `package directory, or a registry coordinate like hl7.fhir.us.core@5.0.1.`,\r\n );\r\n }\r\n const files = stat.isDirectory() ? readFromDirectory(input) : readFromTarball(input);\r\n return buildContext(files, options.coreValueSetFallback);\r\n}\r\n\r\n/** package.json plus every FHIR JSON resource, keyed by base filename. */\r\ninterface PackageFiles {\r\n packageJson: { name?: string; version?: string; \"fhir-version-list\"?: string[]; fhirVersions?: string[] };\r\n resources: RawResource[];\r\n}\r\n\r\nfunction isRegistryCoordinate(input: string): boolean {\r\n // A registry coordinate is a package id (optionally @version); it never\r\n // looks like a path and does not exist on disk.\r\n if (fs.existsSync(input)) return false;\r\n if (input.includes(\"/\") || input.includes(\"\\\\\") || input.endsWith(\".tgz\")) return false;\r\n return /^[a-z0-9][a-z0-9.\\-]*(@[\\w.\\-]+)?$/i.test(input);\r\n}\r\n\r\nfunction packageDir(root: string): string {\r\n const nested = path.join(root, \"package\");\r\n if (fs.existsSync(path.join(nested, \"package.json\"))) return nested;\r\n if (fs.existsSync(path.join(root, \"package.json\"))) return root;\r\n throw new Error(`No package.json found under \"${root}\" (looked in ./ and ./package)`);\r\n}\r\n\r\nfunction readFromDirectory(dir: string): PackageFiles {\r\n const base = packageDir(dir);\r\n const packageJson = JSON.parse(fs.readFileSync(path.join(base, \"package.json\"), \"utf8\"));\r\n const resources: RawResource[] = [];\r\n for (const file of fs.readdirSync(base).sort()) {\r\n if (!file.endsWith(\".json\") || file === \"package.json\" || file === \".index.json\") continue;\r\n try {\r\n resources.push(JSON.parse(fs.readFileSync(path.join(base, file), \"utf8\")));\r\n } catch {\r\n // Skip non-resource JSON (e.g. index files that aren't FHIR resources).\r\n }\r\n }\r\n return { packageJson, resources };\r\n}\r\n\r\n/**\r\n * Extracts a package tarball to an isolated temp directory (tar refuses\r\n * absolute/`..` members, and the destination is a private mkdtemp), reads the\r\n * JSON resources, then removes the directory.\r\n */\r\nfunction readFromTarball(tarballPath: string): PackageFiles {\r\n if (!fs.existsSync(tarballPath)) {\r\n throw new Error(`Package tarball not found: ${tarballPath}`);\r\n }\r\n const tmp = fs.mkdtempSync(path.join(os.tmpdir(), \"fhir-oas-ig-\"));\r\n try {\r\n execFileSync(\"tar\", [\"-xzf\", tarballPath, \"-C\", tmp], { stdio: \"pipe\" });\r\n return readFromDirectory(tmp);\r\n } finally {\r\n fs.rmSync(tmp, { recursive: true, force: true });\r\n }\r\n}\r\n\r\nasync function fetchFromRegistry(coordinate: string, options: LoadIgOptions): Promise<string> {\r\n const [name, version] = coordinate.split(\"@\");\r\n const cacheDir = path.join(options.cacheDir ?? path.join(os.homedir(), \".fhir-oas\"), \"packages\");\r\n const resolvedVersion = version ?? \"latest\";\r\n const cachePath = path.join(cacheDir, `${name}#${resolvedVersion}.tgz`);\r\n if (fs.existsSync(cachePath)) return cachePath;\r\n\r\n const url = `${REGISTRY_BASE}/${name}/${resolvedVersion}`;\r\n const doFetch = options.fetchImpl ?? fetch;\r\n let response: Response;\r\n try {\r\n response = await doFetch(url);\r\n } catch (cause) {\r\n throw new Error(\r\n `Failed to reach the FHIR package registry at ${url}: ${(cause as Error).message}. ` +\r\n `If you are offline or behind a restrictive proxy, download the package and pass ` +\r\n `--ig ./${name}.tgz instead.`,\r\n );\r\n }\r\n if (!response.ok) {\r\n throw new Error(\r\n `FHIR package registry returned ${response.status} for ${url}. ` +\r\n `Check the package name and version, or download it and pass --ig ./${name}.tgz.`,\r\n );\r\n }\r\n const buffer = Buffer.from(await response.arrayBuffer());\r\n fs.mkdirSync(cacheDir, { recursive: true });\r\n fs.writeFileSync(cachePath, buffer);\r\n return cachePath;\r\n}\r\n\r\nfunction detectFhirVersion(packageJson: PackageFiles[\"packageJson\"]): FhirVersion {\r\n const versions = packageJson[\"fhir-version-list\"] ?? packageJson.fhirVersions ?? [];\r\n for (const v of versions) {\r\n const mapped = FHIR_VERSION_BY_NUMBER[v];\r\n if (mapped) return mapped;\r\n }\r\n throw new Error(\r\n `Could not determine a supported FHIR version for IG package \"${packageJson.name}\" ` +\r\n `(found: ${versions.join(\", \") || \"none\"}). Supported: ${FHIR_VERSIONS.join(\", \")}.`,\r\n );\r\n}\r\n\r\nfunction buildContext(files: PackageFiles, coreFallback?: ValueSetResolver): IgContext {\r\n const fhirVersion = detectFhirVersion(files.packageJson);\r\n const terminology = files.resources.filter(\r\n (r) => r.resourceType === \"ValueSet\" || r.resourceType === \"CodeSystem\",\r\n );\r\n const resolveValueSet = buildValueSetResolver(terminology as never[], coreFallback);\r\n\r\n const profiles: IgProfile[] = [];\r\n const profilesMissingSnapshot: string[] = [];\r\n for (const r of files.resources) {\r\n if (\r\n r.resourceType === \"StructureDefinition\" &&\r\n r.derivation === \"constraint\" &&\r\n r.kind === \"resource\"\r\n ) {\r\n if (!r.snapshot) {\r\n profilesMissingSnapshot.push(r.name ?? r.url ?? \"unknown\");\r\n continue;\r\n }\r\n const sd = r as unknown as RawStructureDefinition;\r\n profiles.push({\r\n url: sd.url.split(\"|\")[0]!,\r\n id: sd.id,\r\n name: sd.name,\r\n type: sd.type,\r\n definition: minimizeStructureDefinition(sd, resolveValueSet),\r\n });\r\n }\r\n }\r\n profiles.sort((a, b) => a.url.localeCompare(b.url));\r\n\r\n return {\r\n name: files.packageJson.name ?? \"unknown\",\r\n version: files.packageJson.version ?? \"unknown\",\r\n fhirVersion,\r\n profiles,\r\n profilesMissingSnapshot,\r\n resolveValueSet,\r\n };\r\n}\r\n","import type { MinElement, MinElementType, MinStructureDefinition } from \"../definitions.js\";\r\n\r\n/**\r\n * Minimizes raw FHIR StructureDefinition / terminology resources loaded from\r\n * an IG package into the same `MinStructureDefinition` shape the vendored core\r\n * definitions use, so profile snapshots feed the shared structure walker.\r\n *\r\n * This mirrors the element-minimizing shape in scripts/update-definitions.mjs\r\n * (which vendors the core packages at build time). The two are kept separate\r\n * on purpose: this one runs at generation time on arbitrary IG packages and\r\n * additionally captures profile constraints (`fixed[x]`, `mustSupport`,\r\n * unenforced `pattern`/slicing), which the base definitions never need.\r\n */\r\n\r\n/** Above this size an enum stops helping codegen and starts hurting it. */\r\nconst MAX_ENUM_CODES = 150;\r\n\r\ninterface RawElement {\r\n path: string;\r\n min?: number;\r\n max?: string;\r\n short?: string;\r\n definition?: string;\r\n contentReference?: string;\r\n mustSupport?: boolean;\r\n slicing?: unknown;\r\n sliceName?: string;\r\n type?: { code: string; targetProfile?: string[]; extension?: RawExtension[] }[];\r\n binding?: { strength?: string; valueSet?: string };\r\n [key: string]: unknown;\r\n}\r\n\r\ninterface RawExtension {\r\n url: string;\r\n valueUrl?: string;\r\n}\r\n\r\nexport interface RawStructureDefinition {\r\n resourceType: string;\r\n name: string;\r\n id?: string;\r\n url: string;\r\n kind: string;\r\n type: string;\r\n abstract?: boolean;\r\n derivation?: string;\r\n baseDefinition?: string;\r\n fhirVersion?: string;\r\n snapshot?: { element: RawElement[] };\r\n}\r\n\r\nexport type ValueSetResolver = (valueSetUrl: string) => string[] | undefined;\r\n\r\nconst FHIR_TYPE_EXTENSION =\r\n \"http://hl7.org/fhir/StructureDefinition/structuredefinition-fhir-type\";\r\n\r\n/** Extracts the normalized `fixed[x]` value from a snapshot element, if any. */\r\nfunction fixedValue(el: RawElement): unknown {\r\n for (const key of Object.keys(el)) {\r\n if (key.startsWith(\"fixed\") && key.length > 5) return el[key];\r\n }\r\n return undefined;\r\n}\r\n\r\nfunction omittedConstraints(el: RawElement): string[] | undefined {\r\n const notes: string[] = [];\r\n if (el.slicing || el.sliceName) notes.push(\"slicing\");\r\n if (Object.keys(el).some((k) => k.startsWith(\"pattern\") && k.length > 7)) {\r\n notes.push(\"pattern\");\r\n }\r\n return notes.length > 0 ? notes : undefined;\r\n}\r\n\r\nfunction minimizeElement(el: RawElement, resolveValueSet?: ValueSetResolver): MinElement {\r\n const out: MinElement = { path: el.path, min: el.min ?? 0, max: el.max ?? \"*\" };\r\n if (el.short) out.short = el.short;\r\n if (el.definition) out.definition = el.definition;\r\n if (el.contentReference) out.contentReference = el.contentReference;\r\n if (el.type) {\r\n out.types = el.type.map((t) => {\r\n const type: MinElementType = { code: t.code };\r\n if (t.targetProfile) type.targetProfile = t.targetProfile;\r\n const fhirType = (t.extension ?? []).find((e) => e.url === FHIR_TYPE_EXTENSION);\r\n if (fhirType?.valueUrl) type.fhirType = fhirType.valueUrl;\r\n return type;\r\n });\r\n }\r\n if (el.binding?.strength === \"required\" && el.binding.valueSet) {\r\n out.binding = { strength: el.binding.strength, valueSet: el.binding.valueSet };\r\n const codes = resolveValueSet?.(el.binding.valueSet);\r\n if (codes) out.binding.codes = [...codes].sort();\r\n }\r\n const fixed = fixedValue(el);\r\n if (fixed !== undefined) out.fixed = fixed;\r\n if (el.mustSupport) out.mustSupport = true;\r\n const omitted = omittedConstraints(el);\r\n if (omitted) out.omittedConstraints = omitted;\r\n return out;\r\n}\r\n\r\nexport function minimizeStructureDefinition(\r\n sd: RawStructureDefinition,\r\n resolveValueSet?: ValueSetResolver,\r\n): MinStructureDefinition {\r\n return {\r\n name: sd.name,\r\n url: sd.url,\r\n kind: sd.kind as MinStructureDefinition[\"kind\"],\r\n type: sd.type,\r\n abstract: !!sd.abstract,\r\n baseDefinition: sd.baseDefinition,\r\n elements: (sd.snapshot?.element ?? []).map((el) => minimizeElement(el, resolveValueSet)),\r\n };\r\n}\r\n\r\ninterface RawValueSet {\r\n resourceType: string;\r\n url?: string;\r\n compose?: {\r\n include?: RawValueSetGroup[];\r\n exclude?: RawValueSetGroup[];\r\n };\r\n}\r\n\r\ninterface RawValueSetGroup {\r\n system?: string;\r\n concept?: { code: string }[];\r\n filter?: unknown[];\r\n valueSet?: string[];\r\n}\r\n\r\ninterface RawCodeSystem {\r\n resourceType: string;\r\n url?: string;\r\n content?: string;\r\n concept?: RawConcept[];\r\n}\r\n\r\ninterface RawConcept {\r\n code: string;\r\n concept?: RawConcept[];\r\n}\r\n\r\n/**\r\n * Builds a ValueSet URL -> flat code list resolver from the ValueSet and\r\n * CodeSystem resources available (IG-local plus, optionally, a fallback for\r\n * the vendored core terminology). Only simple composes are resolved; anything\r\n * with filters or valueSet imports is left unresolved, so the binding stays a\r\n * plain code — exactly the core behavior.\r\n */\r\nexport function buildValueSetResolver(\r\n resources: (RawValueSet | RawCodeSystem)[],\r\n fallback?: ValueSetResolver,\r\n): ValueSetResolver {\r\n const codeSystems = new Map<string, RawCodeSystem>();\r\n const valueSets = new Map<string, RawValueSet>();\r\n for (const r of resources) {\r\n if (r.resourceType === \"CodeSystem\" && r.url) codeSystems.set(r.url, r as RawCodeSystem);\r\n if (r.resourceType === \"ValueSet\" && r.url) valueSets.set(r.url, r as RawValueSet);\r\n }\r\n\r\n function conceptCodes(concepts: RawConcept[] | undefined, out: string[]): string[] {\r\n for (const c of concepts ?? []) {\r\n out.push(c.code);\r\n if (c.concept) conceptCodes(c.concept, out);\r\n }\r\n return out;\r\n }\r\n\r\n function resolveGroup(group: RawValueSetGroup): string[] | undefined {\r\n if (group.filter?.length || group.valueSet?.length) return undefined;\r\n if (group.concept?.length) return group.concept.map((c) => c.code);\r\n if (!group.system) return undefined;\r\n const cs = codeSystems.get(group.system);\r\n if (!cs || cs.content === \"not-present\" || !cs.concept) return undefined;\r\n return conceptCodes(cs.concept, []);\r\n }\r\n\r\n return function resolve(valueSetUrl: string): string[] | undefined {\r\n const versionless = valueSetUrl.split(\"|\")[0]!;\r\n const vs = valueSets.get(versionless);\r\n if (!vs?.compose?.include?.length) return fallback?.(valueSetUrl);\r\n const codes = new Set<string>();\r\n for (const group of vs.compose.include) {\r\n const groupCodes = resolveGroup(group);\r\n if (!groupCodes) return fallback?.(valueSetUrl);\r\n for (const code of groupCodes) codes.add(code);\r\n }\r\n for (const group of vs.compose.exclude ?? []) {\r\n const groupCodes = resolveGroup(group);\r\n if (!groupCodes) return fallback?.(valueSetUrl);\r\n for (const code of groupCodes) codes.delete(code);\r\n }\r\n if (codes.size === 0 || codes.size > MAX_ENUM_CODES) return fallback?.(valueSetUrl);\r\n return [...codes];\r\n };\r\n}\r\n","import { gunzipSync } from \"node:zlib\";\r\nimport fs from \"node:fs\";\r\nimport path from \"node:path\";\r\nimport { fileURLToPath } from \"node:url\";\r\nimport type { FhirVersion, JsonSchemaNode } from \"./types.js\";\r\n\r\n/**\r\n * The vendored `definitions/` directory sits at the package root, next to\r\n * `src/` (dev) or `dist/` (published build), so walking up from this module\r\n * finds it in both layouts.\r\n */\r\nfunction definitionsRoot(): string {\r\n let dir = path.dirname(fileURLToPath(import.meta.url));\r\n for (let i = 0; i < 5; i++) {\r\n const candidate = path.join(dir, \"definitions\");\r\n if (fs.existsSync(candidate)) return candidate;\r\n dir = path.dirname(dir);\r\n }\r\n throw new Error(\"Could not locate the vendored FHIR definitions directory\");\r\n}\r\n\r\nconst cache = new Map<string, unknown>();\r\n\r\nfunction loadGzJson(fhirVersion: FhirVersion, file: string): unknown {\r\n const key = `${fhirVersion}/${file}`;\r\n let value = cache.get(key);\r\n if (value === undefined) {\r\n const fullPath = path.join(definitionsRoot(), fhirVersion, `${file}.gz`);\r\n value = JSON.parse(gunzipSync(fs.readFileSync(fullPath)).toString(\"utf8\"));\r\n cache.set(key, value);\r\n }\r\n return value;\r\n}\r\n\r\nexport interface FhirJsonSchema {\r\n discriminator?: { propertyName: string; mapping: Record<string, string> };\r\n definitions: Record<string, JsonSchemaNode>;\r\n}\r\n\r\nexport function loadFhirSchema(fhirVersion: FhirVersion): FhirJsonSchema {\r\n return loadGzJson(fhirVersion, \"fhir.schema.json\") as FhirJsonSchema;\r\n}\r\n\r\nexport interface SearchParameter {\r\n name: string;\r\n code: string;\r\n base: string[];\r\n type: string;\r\n description?: string;\r\n /**\r\n * FHIRPath naming the element(s) searched. Simple dotted forms resolve to a\r\n * single element and let a token parameter's required-binding codes be\r\n * looked up; `where(...)`/`as(...)`/`|` forms name more than one and are\r\n * left alone. Absent on a few composite parameters.\r\n */\r\n expression?: string;\r\n}\r\n\r\nexport function loadSearchParameters(fhirVersion: FhirVersion): SearchParameter[] {\r\n const bundle = loadGzJson(fhirVersion, \"search-parameters.json\") as {\r\n entry?: { resource?: SearchParameter & { resourceType: string } }[];\r\n };\r\n return (bundle.entry ?? [])\r\n .map((e) => e.resource)\r\n .filter(\r\n // R4B ships a few draft codesystem-extensions-* SearchParameters with no\r\n // `base`; they can't be attached to any resource, so drop them here.\r\n (r): r is SearchParameter & { resourceType: string } =>\r\n r?.resourceType === \"SearchParameter\" && Array.isArray(r.base),\r\n );\r\n}\r\n\r\nexport interface MinOperationParameter {\r\n name: string;\r\n use: \"in\" | \"out\";\r\n min: number;\r\n max: string;\r\n /** Absent for multi-part parameters (they force POST + Parameters). */\r\n type?: string;\r\n documentation?: string;\r\n}\r\n\r\nexport interface MinOperationDefinition {\r\n name: string;\r\n code: string;\r\n url: string;\r\n description?: string;\r\n /** Applicable resource types; [\"Resource\"] means every resource. */\r\n resource: string[];\r\n system: boolean;\r\n type: boolean;\r\n instance: boolean;\r\n parameters: MinOperationParameter[];\r\n}\r\n\r\nexport function loadOperationDefinitions(fhirVersion: FhirVersion): MinOperationDefinition[] {\r\n return loadGzJson(fhirVersion, \"operation-definitions.json\") as MinOperationDefinition[];\r\n}\r\n\r\nexport interface MinElementType {\r\n code: string;\r\n targetProfile?: string[];\r\n fhirType?: string;\r\n}\r\n\r\nexport interface MinElement {\r\n path: string;\r\n min: number;\r\n max: string;\r\n short?: string;\r\n definition?: string;\r\n contentReference?: string;\r\n types?: MinElementType[];\r\n binding?: { strength: string; valueSet: string; codes?: string[] };\r\n /**\r\n * Value the element is fixed to by a profile (`fixed[x]`), normalized to a\r\n * JSON value. Only populated for profiles loaded from an IG package; the\r\n * vendored base definitions do not carry it.\r\n */\r\n fixed?: unknown;\r\n /** Profile `mustSupport` flag (surfaced in descriptions, not enforced). */\r\n mustSupport?: boolean;\r\n /**\r\n * Human labels for profile constraints this tool does not enforce in\r\n * OpenAPI (e.g. \"pattern\", \"slicing\"), surfaced in the property description\r\n * and `x-fhir-constraints-omitted`. IG profiles only.\r\n */\r\n omittedConstraints?: string[];\r\n}\r\n\r\nexport interface MinStructureDefinition {\r\n name: string;\r\n url: string;\r\n kind: \"resource\" | \"complex-type\" | \"primitive-type\";\r\n type: string;\r\n abstract: boolean;\r\n baseDefinition?: string;\r\n elements: MinElement[];\r\n}\r\n\r\nexport function loadStructureDefinitions(fhirVersion: FhirVersion): MinStructureDefinition[] {\r\n return loadGzJson(fhirVersion, \"structure-definitions.json\") as MinStructureDefinition[];\r\n}\r\n","import type { MinElement, MinStructureDefinition } from \"../definitions.js\";\r\nimport type { JsonSchemaNode } from \"../types.js\";\r\n\r\n/**\r\n * Walks a StructureDefinition snapshot into named IR schema definitions\r\n * (`#/definitions/<Name>` refs). Shared by the core structure-def backend\r\n * (base resources/types) and the profile applier (IG profiles), so the two\r\n * produce identical schema shapes and only differ in the constraints applied.\r\n */\r\nexport interface EmitOptions {\r\n /** Schema name for the root definition (e.g. \"Patient\" or \"USCorePatient\"). */\r\n rootName: string;\r\n /** Emit a `resourceType` discriminator property. */\r\n isResourceRoot: boolean;\r\n /**\r\n * Wire resourceType/description name. Defaults to the SD `type`. For a\r\n * profile this stays the base resource (\"Patient\") even though rootName is\r\n * the profile name, because resourceType on the wire is the base type.\r\n */\r\n resourceDisplayName?: string;\r\n /**\r\n * Apply profile constraints while walking: drop `max: \"0\"` elements and\r\n * turn `fixed[x]` into a `const`. Off for base definitions so their output\r\n * is unchanged.\r\n */\r\n profile?: boolean;\r\n}\r\n\r\ninterface ElementNode {\r\n element: MinElement;\r\n children: Map<string, ElementNode>;\r\n}\r\n\r\nfunction segmentToPascal(segment: string): string {\r\n return segment.charAt(0).toUpperCase() + segment.slice(1);\r\n}\r\n\r\nfunction isBackbone(el: MinElement): boolean {\r\n return (el.types ?? []).some((t) => t.code === \"BackboneElement\" || t.code === \"Element\");\r\n}\r\n\r\n/** Type codes from the FHIRPath system (used on `id`, `Extension.url`, ...). */\r\nfunction systemTypeSchema(code: string): JsonSchemaNode | undefined {\r\n if (!code.startsWith(\"http://hl7.org/fhirpath/System.\")) return undefined;\r\n const kind = code.slice(\"http://hl7.org/fhirpath/System.\".length);\r\n switch (kind) {\r\n case \"Boolean\":\r\n return { type: \"boolean\" };\r\n case \"Integer\":\r\n case \"Decimal\":\r\n return { type: \"number\" };\r\n default:\r\n return { type: \"string\" };\r\n }\r\n}\r\n\r\nfunction buildElementTree(sd: MinStructureDefinition): ElementNode | undefined {\r\n const rootPath = sd.type ?? sd.name;\r\n let root: ElementNode | undefined;\r\n const nodes = new Map<string, ElementNode>();\r\n for (const el of sd.elements) {\r\n const node: ElementNode = { element: el, children: new Map() };\r\n nodes.set(el.path, node);\r\n if (el.path === rootPath) {\r\n root = node;\r\n continue;\r\n }\r\n const parentPath = el.path.slice(0, el.path.lastIndexOf(\".\"));\r\n const segment = el.path.slice(el.path.lastIndexOf(\".\") + 1);\r\n nodes.get(parentPath)?.children.set(segment, node);\r\n }\r\n return root;\r\n}\r\n\r\n/**\r\n * Names a backbone reached by a `contentReference` (e.g. \"#Questionnaire.item\"\r\n * -> \"Questionnaire_Item\"). When walking a profile, a self-reference to the\r\n * base type root is remapped onto the profile's own name so the ref resolves\r\n * within the emitted profile schemas.\r\n */\r\nfunction contentReferenceName(reference: string, sd: MinStructureDefinition, rootName: string): string {\r\n // Two forms occur: the core definitions use \"#Observation.referenceRange\",\r\n // while IG snapshot generators emit the absolute canonical\r\n // \"http://hl7.org/fhir/StructureDefinition/Observation#Observation.referenceRange\".\r\n // Only the fragment names the element path.\r\n const hash = reference.lastIndexOf(\"#\");\r\n const path = hash >= 0 ? reference.slice(hash + 1) : reference;\r\n const [root, ...rest] = path.split(\".\");\r\n if (rest.length === 0) return root ?? path;\r\n const prefix = root === (sd.type ?? sd.name) ? rootName : (root ?? \"\");\r\n return [prefix, ...rest.map(segmentToPascal)].join(\"_\");\r\n}\r\n\r\nexport function emitStructureDefinitionSchemas(\r\n sd: MinStructureDefinition,\r\n definitions: Map<string, JsonSchemaNode>,\r\n opts: EmitOptions,\r\n): void {\r\n const root = buildElementTree(sd);\r\n if (!root) return;\r\n emitObjectDefinition(sd, opts.rootName, root, definitions, opts.isResourceRoot, opts);\r\n}\r\n\r\nfunction emitObjectDefinition(\r\n sd: MinStructureDefinition,\r\n name: string,\r\n node: ElementNode,\r\n definitions: Map<string, JsonSchemaNode>,\r\n isResourceRoot: boolean,\r\n opts: EmitOptions,\r\n): void {\r\n if (definitions.has(name)) return;\r\n const properties: Record<string, JsonSchemaNode> = {};\r\n const required: string[] = [];\r\n const displayName = opts.resourceDisplayName ?? sd.type ?? sd.name;\r\n\r\n if (isResourceRoot) {\r\n properties.resourceType = {\r\n description: `This is a ${displayName} resource`,\r\n const: displayName,\r\n };\r\n required.push(\"resourceType\");\r\n }\r\n\r\n // Reserve the name before recursing so cycles terminate.\r\n const definition: JsonSchemaNode = {\r\n ...(node.element.definition ? { description: node.element.definition } : {}),\r\n properties,\r\n additionalProperties: false,\r\n };\r\n definitions.set(name, definition);\r\n\r\n for (const [segment, child] of node.children) {\r\n emitProperty(sd, name, segment, child, properties, required, definitions, opts);\r\n }\r\n if (required.length > 0) definition.required = required.sort();\r\n}\r\n\r\nfunction emitProperty(\r\n sd: MinStructureDefinition,\r\n parentName: string,\r\n segment: string,\r\n node: ElementNode,\r\n properties: Record<string, JsonSchemaNode>,\r\n required: string[],\r\n definitions: Map<string, JsonSchemaNode>,\r\n opts: EmitOptions,\r\n): void {\r\n const el = node.element;\r\n // Profile constraint: an element constrained out (max 0) is removed.\r\n if (opts.profile && el.max === \"0\") return;\r\n\r\n const isArray = el.max === \"*\" || Number(el.max) > 1;\r\n const isChoice = segment.endsWith(\"[x]\");\r\n\r\n // In profile mode, annotate must-support and constraints not enforced in\r\n // OpenAPI (pattern, slicing) so they survive into generated docs.\r\n let description = el.definition ?? el.short;\r\n const omitted: string[] = [];\r\n if (opts.profile) {\r\n if (el.mustSupport) omitted.push(\"must-support\");\r\n if (el.omittedConstraints) omitted.push(...el.omittedConstraints);\r\n if (omitted.length > 0) {\r\n const note = `Profile constraints not enforced here: ${omitted.join(\", \")}.`;\r\n description = description ? `${description} ${note}` : note;\r\n }\r\n }\r\n\r\n const addProperty = (fieldName: string, schema: JsonSchemaNode, primitive: boolean) => {\r\n const annotated =\r\n omitted.length > 0 && !(\"$ref\" in schema)\r\n ? { ...schema, \"x-fhir-constraints-omitted\": omitted }\r\n : schema;\r\n properties[fieldName] = wrapCardinality(annotated, isArray, description);\r\n if (primitive) {\r\n properties[`_${fieldName}`] = wrapCardinality(\r\n { $ref: \"#/definitions/Element\" },\r\n isArray,\r\n `Extensions for ${fieldName}`,\r\n );\r\n }\r\n };\r\n\r\n if (isChoice) {\r\n const base = segment.slice(0, -3);\r\n for (const type of el.types ?? []) {\r\n const fieldName = base + segmentToPascal(type.code);\r\n const { schema, primitive } = schemaForTypeCode(type.code, el, opts);\r\n addProperty(fieldName, schema, primitive);\r\n }\r\n // Choice fields are never individually required: the constraint \"exactly\r\n // one of the expansions\" is not expressible in required[].\r\n return;\r\n }\r\n\r\n if (el.contentReference) {\r\n const target = contentReferenceName(el.contentReference, sd, opts.rootName);\r\n addProperty(segment, { $ref: `#/definitions/${target}` }, false);\r\n } else if (isBackbone(el) && node.children.size > 0) {\r\n const childName = `${parentName}_${segmentToPascal(segment)}`;\r\n emitObjectDefinition(sd, childName, node, definitions, false, opts);\r\n addProperty(segment, { $ref: `#/definitions/${childName}` }, false);\r\n } else {\r\n const type = (el.types ?? [])[0];\r\n if (!type) return; // extension-only or profiled-out element\r\n const { schema, primitive } = schemaForTypeCode(type.code, el, opts);\r\n addProperty(segment, schema, primitive);\r\n }\r\n\r\n if (el.min >= 1) required.push(segment);\r\n}\r\n\r\nfunction schemaForTypeCode(\r\n code: string,\r\n el: MinElement,\r\n opts: EmitOptions,\r\n): { schema: JsonSchemaNode; primitive: boolean } {\r\n const primitive = code.charAt(0) === code.charAt(0).toLowerCase();\r\n\r\n const system = systemTypeSchema(code);\r\n if (system) return { schema: system, primitive: false };\r\n if (code === \"Resource\" || code === \"DomainResource\") {\r\n return { schema: { $ref: \"#/definitions/ResourceList\" }, primitive: false };\r\n }\r\n // Profile constraint: a fixed value pins the element to a single constant.\r\n if (opts.profile && el.fixed !== undefined) {\r\n return { schema: { const: el.fixed }, primitive };\r\n }\r\n // Required bindings whose ValueSet was resolved become inline enums on\r\n // `code` elements, mirroring the official fhir.schema.json.\r\n if (code === \"code\" && el.binding?.codes?.length) {\r\n return { schema: { enum: el.binding.codes }, primitive: true };\r\n }\r\n return { schema: { $ref: `#/definitions/${code}` }, primitive };\r\n}\r\n\r\nfunction wrapCardinality(\r\n schema: JsonSchemaNode,\r\n isArray: boolean,\r\n description?: string,\r\n): JsonSchemaNode {\r\n const withDescription = (s: JsonSchemaNode) =>\r\n description && !(\"$ref\" in s) ? { description, ...s } : s;\r\n if (isArray) {\r\n return {\r\n ...(description ? { description } : {}),\r\n type: \"array\",\r\n items: schema,\r\n };\r\n }\r\n if (\"$ref\" in schema && description) {\r\n // JSON Schema draft-06/OAS 3.0 ignores siblings of $ref; nest description\r\n // via allOf only in 3.1. Keep plain $ref for compatibility.\r\n return schema;\r\n }\r\n return withDescription(schema);\r\n}\r\n","import { loadStructureDefinitions } from \"../definitions.js\";\r\nimport type { DefinitionRegistry } from \"../ir/registry.js\";\r\nimport { emitStructureDefinitionSchemas } from \"../ir/structureWalker.js\";\r\nimport type { FhirVersion, JsonSchemaNode } from \"../types.js\";\r\nimport type { IgContext, IgProfile } from \"./package.js\";\r\nimport type { ValueSetResolver } from \"./minimize.js\";\r\n\r\nexport interface AppliedProfile {\r\n /** Component schema name emitted for the profile (e.g. \"USCorePatient\"). */\r\n schemaName: string;\r\n /** Base resource type the profile constrains (e.g. \"Patient\"). */\r\n resourceType: string;\r\n /** Versionless canonical URL of the profile. */\r\n url: string;\r\n}\r\n\r\n/**\r\n * A ValueSet resolver backed by the vendored core definitions: base elements\r\n * already carry the resolved code list for their required binding, so core\r\n * ValueSets (e.g. administrative-gender) referenced by profile elements can be\r\n * resolved without shipping the core ValueSets themselves.\r\n */\r\nexport function buildCoreValueSetFallback(fhirVersion: FhirVersion): ValueSetResolver {\r\n const map = new Map<string, string[]>();\r\n for (const sd of loadStructureDefinitions(fhirVersion)) {\r\n for (const el of sd.elements) {\r\n if (el.binding?.codes?.length && el.binding.valueSet) {\r\n const key = el.binding.valueSet.split(\"|\")[0]!;\r\n if (!map.has(key)) map.set(key, el.binding.codes);\r\n }\r\n }\r\n }\r\n return (valueSetUrl) => map.get(valueSetUrl.split(\"|\")[0]!);\r\n}\r\n\r\nfunction sanitizeSchemaName(name: string): string {\r\n const cleaned = name.replace(/[^A-Za-z0-9_]/g, \"\");\r\n return /^[A-Za-z]/.test(cleaned) ? cleaned : `Profile${cleaned}`;\r\n}\r\n\r\n/** Finds a profile in the IG by canonical URL, id, or name (case-insensitive). */\r\nfunction findProfile(context: IgContext, requested: string): IgProfile {\r\n const needle = requested.toLowerCase();\r\n const matches = context.profiles.filter(\r\n (p) =>\r\n p.url.toLowerCase() === needle ||\r\n p.id?.toLowerCase() === needle ||\r\n p.name.toLowerCase() === needle,\r\n );\r\n if (matches.length === 1) return matches[0]!;\r\n if (matches.length > 1) {\r\n throw new Error(\r\n `Profile \"${requested}\" is ambiguous in ${context.name}; match by canonical URL. ` +\r\n `Candidates: ${matches.map((p) => p.url).join(\", \")}`,\r\n );\r\n }\r\n if (context.profilesMissingSnapshot.some((p) => p.toLowerCase() === needle)) {\r\n throw new Error(\r\n `Profile \"${requested}\" in ${context.name} has no snapshot. Snapshot generation is ` +\r\n `out of scope; use a snapshot-bearing release of the IG.`,\r\n );\r\n }\r\n const available = context.profiles.map((p) => p.id ?? p.name).sort();\r\n throw new Error(\r\n `Profile \"${requested}\" not found in ${context.name}@${context.version}. ` +\r\n `Available profiles: ${available.join(\", \") || \"none\"}`,\r\n );\r\n}\r\n\r\n/**\r\n * Emits the profiled schema (and its backbones) into the registry, applying\r\n * the profile's constraints, and returns how it maps onto the base resource.\r\n * Unconstrained elements resolve to base type refs, so the dependency closure\r\n * still draws from the vendored core registry.\r\n */\r\nexport function applyProfile(\r\n context: IgContext,\r\n requested: string,\r\n registry: DefinitionRegistry,\r\n): AppliedProfile {\r\n const profile = findProfile(context, requested);\r\n let schemaName = sanitizeSchemaName(profile.name);\r\n // Guard against collision with a base definition of a different shape.\r\n if (registry.definitions.has(schemaName) && schemaName !== profile.type) {\r\n schemaName = `${schemaName}Profile`;\r\n }\r\n\r\n emitStructureDefinitionSchemas(profile.definition, registry.definitions, {\r\n rootName: schemaName,\r\n isResourceRoot: true,\r\n resourceDisplayName: profile.type,\r\n profile: true,\r\n });\r\n\r\n const schema = registry.definitions.get(schemaName) as JsonSchemaNode | undefined;\r\n if (schema) schema[\"x-fhir-profile\"] = profile.url;\r\n\r\n return { schemaName, resourceType: profile.type, url: profile.url };\r\n}\r\n","import { loadSearchParameters, loadStructureDefinitions } from \"./definitions.js\";\r\nimport type { SearchParameter } from \"./definitions.js\";\r\nimport type {\r\n FhirVersion,\r\n SearchParamPreset,\r\n SearchParamRule,\r\n SearchParamSelection,\r\n} from \"./types.js\";\r\n\r\n/**\r\n * Search-value prefixes FHIR defines for ordered types (number, date,\r\n * quantity). They are part of the value, not the parameter name — `date=ge2021`\r\n * — so they cannot be modelled as separate parameters, but consumers need to\r\n * know the parameter accepts them.\r\n *\r\n * https://hl7.org/fhir/search.html#prefix\r\n */\r\nexport const SEARCH_PREFIXES = [\"eq\", \"ne\", \"gt\", \"lt\", \"ge\", \"le\", \"sa\", \"eb\", \"ap\"] as const;\r\n\r\n/** Search parameter types whose values may carry a prefix. */\r\nconst PREFIXABLE_TYPES = new Set([\"number\", \"date\", \"quantity\"]);\r\n\r\nexport function prefixesFor(searchParamType: string): readonly string[] | undefined {\r\n return PREFIXABLE_TYPES.has(searchParamType) ? SEARCH_PREFIXES : undefined;\r\n}\r\n\r\n/**\r\n * Required-binding codes by element path. Search parameters name their element\r\n * in `expression`, so a token parameter over a bound `code` element can be\r\n * described with the codes the version actually defines — which differ between\r\n * versions (Encounter.status gains `on-hold`/`completed` in R5) and which HL7's\r\n * own SearchParameter.description text reports only sporadically.\r\n */\r\nfunction requiredBindingCodes(fhirVersion: FhirVersion): Map<string, string[]> {\r\n const index = new Map<string, string[]>();\r\n for (const sd of loadStructureDefinitions(fhirVersion)) {\r\n for (const el of sd.elements) {\r\n if (el.binding?.strength === \"required\" && el.binding.codes?.length) {\r\n index.set(el.path, el.binding.codes);\r\n }\r\n }\r\n }\r\n return index;\r\n}\r\n\r\nconst bindingCache = new Map<FhirVersion, Map<string, string[]>>();\r\n\r\n/**\r\n * Codes a token search parameter accepts for one resource, or undefined when\r\n * they can't be determined.\r\n *\r\n * Parameters shared across resources carry a union expression\r\n * (\"Patient.gender | Person.gender | Practitioner.gender | ...\"), and each\r\n * branch may bind a different ValueSet — MedicationRequest.status and\r\n * MedicationDispense.status share a parameter but not a code list. The branch\r\n * matching the resource being generated is the one that applies, so it is\r\n * selected rather than the parameter being skipped.\r\n *\r\n * FHIRPath using `where(...)`, `as(...)`, `.resolve()` or similar is left\r\n * alone: it does not name a single element, and guessing would misreport.\r\n */\r\nexport function searchParamCodes(\r\n fhirVersion: FhirVersion,\r\n resource: string,\r\n type: string,\r\n expression: string | undefined,\r\n): string[] | undefined {\r\n if (type !== \"token\" || !expression) return undefined;\r\n\r\n const branch = expression\r\n .split(\"|\")\r\n .map((part) => part.trim())\r\n .find((part) => part.startsWith(`${resource}.`) || !expression.includes(\"|\"));\r\n if (!branch || !/^[A-Za-z]+(?:\\.[A-Za-z]+)+$/.test(branch)) return undefined;\r\n if (branch.split(\".\")[0] !== resource) return undefined;\r\n\r\n let index = bindingCache.get(fhirVersion);\r\n if (!index) {\r\n index = requiredBindingCodes(fhirVersion);\r\n bindingCache.set(fhirVersion, index);\r\n }\r\n return index.get(branch);\r\n}\r\n\r\n/**\r\n * Codes a majority of servers index regardless of resource type. This is the\r\n * first and strongest signal for the `minimal` preset, but it cannot be the\r\n * only one: a handful of resources name none of these (Linkage's parameters\r\n * are `author`/`item`/`source`), and a preset that silently selected nothing\r\n * for them would be indistinguishable from `none`.\r\n */\r\nconst COMMON_CODES = new Set([\r\n \"identifier\",\r\n \"status\",\r\n \"patient\",\r\n \"subject\",\r\n \"encounter\",\r\n \"code\",\r\n \"category\",\r\n \"date\",\r\n \"type\",\r\n \"url\",\r\n \"name\",\r\n]);\r\n\r\n/**\r\n * The branch of a search parameter's expression addressing this resource\r\n * directly, i.e. a top-level element (`Linkage.author`) rather than something\r\n * nested, chained or filtered (`Observation.component.value`,\r\n * `Bundle.entry.request.where(...)`). Direct parameters address the resource\r\n * itself and are the cheapest to index, which makes them the right fallback\r\n * when none of the common codes apply.\r\n */\r\nfunction directElementBranch(resource: string, expression: string | undefined): string | undefined {\r\n if (!expression) return undefined;\r\n const branch = expression\r\n .split(\"|\")\r\n .map((part) => part.trim())\r\n .find((part) => part.startsWith(`${resource}.`));\r\n return branch && /^[A-Za-z]+\\.[A-Za-z]+$/.test(branch) ? branch : undefined;\r\n}\r\n\r\n/**\r\n * The `minimal` selection for one resource, in three tiers so that every\r\n * resource defining any search parameter keeps at least one:\r\n *\r\n * 1. the common codes above, where the resource defines any;\r\n * 2. otherwise, parameters addressing a top-level element directly;\r\n * 3. otherwise, everything the resource defines.\r\n *\r\n * A resource that defines no search parameters at all (Binary,\r\n * OperationOutcome) yields nothing, because there is nothing to select.\r\n */\r\nfunction minimalCodes(resource: string, available: readonly SearchParameter[]): Set<string> {\r\n const common = available.filter((sp) => COMMON_CODES.has(sp.code));\r\n if (common.length > 0) return new Set(common.map((sp) => sp.code));\r\n\r\n const direct = available.filter((sp) => directElementBranch(resource, sp.expression));\r\n if (direct.length > 0) return new Set(direct.map((sp) => sp.code));\r\n\r\n return new Set(available.map((sp) => sp.code));\r\n}\r\n\r\nconst PRESETS = new Set<string>([\"all\", \"minimal\", \"none\"]);\r\n\r\n/**\r\n * Parses one selection.\r\n *\r\n * The grammar is a starting point followed by any number of adjustments, in\r\n * any order and freely mixed:\r\n *\r\n * <preset | code,code,...> [,+code | ,-code]...\r\n *\r\n * minimal a preset on its own\r\n * minimal,+based-on a preset, with a code added\r\n * minimal,+based-on,+goal,+focus any number may be added\r\n * all,-note,-derived-from a preset, with codes removed\r\n * minimal,+based-on,-category additions and removals together\r\n * none,+code,+date build a set up from nothing\r\n * code,date,subject an exact list, no preset involved\r\n */\r\nfunction parseOne(value: string): SearchParamRule {\r\n const parts = value\r\n .split(\",\")\r\n .map((part) => part.trim())\r\n .filter(Boolean);\r\n if (parts.length === 0) throw new Error(`--search-params: empty selection in \"${value}\"`);\r\n\r\n const add = new Set<string>();\r\n const remove = new Set<string>();\r\n const literal = new Set<string>();\r\n let preset: SearchParamPreset | undefined;\r\n\r\n for (const [index, part] of parts.entries()) {\r\n if (part.startsWith(\"+\") || part.startsWith(\"-\")) {\r\n const code = part.slice(1);\r\n if (!code) throw new Error(`--search-params: \"${part}\" names no parameter`);\r\n (part.startsWith(\"+\") ? add : remove).add(code);\r\n continue;\r\n }\r\n const lower = part.toLowerCase();\r\n if (PRESETS.has(lower)) {\r\n if (index !== 0) {\r\n throw new Error(\r\n `--search-params: preset \"${part}\" must come first in \"${value}\" ` +\r\n `(e.g. \"minimal,+${parts[0]}\").`,\r\n );\r\n }\r\n preset = lower as SearchParamPreset;\r\n continue;\r\n }\r\n literal.add(part);\r\n }\r\n\r\n if (preset && literal.size > 0) {\r\n throw new Error(\r\n `--search-params: \"${value}\" mixes the preset \"${preset}\" with bare codes ` +\r\n `${[...literal].map((c) => `\"${c}\"`).join(\", \")}. ` +\r\n `Prefix them with + to add to the preset, or drop the preset to list codes exactly.`,\r\n );\r\n }\r\n\r\n const rule: SearchParamRule = { base: preset ?? literal };\r\n if (add.size > 0) (rule as { add?: ReadonlySet<string> }).add = add;\r\n if (remove.size > 0) (rule as { remove?: ReadonlySet<string> }).remove = remove;\r\n return rule;\r\n}\r\n\r\n/**\r\n * Parses `--search-params` arguments. Each is either a bare selection applying\r\n * to every resource (`none`, `minimal,+goal`, `code,date`) or a\r\n * resource-scoped one (`Patient:name,birthdate`).\r\n */\r\nexport function parseSearchParamSpec(specs: readonly string[]): SearchParamSelection {\r\n const selection: SearchParamSelection = {};\r\n const byResource = new Map<string, SearchParamRule>();\r\n for (const spec of specs) {\r\n // A colon separates resource from codes. Codes never contain one, and a\r\n // resource name is always a leading capital, so the split is unambiguous.\r\n const colon = spec.indexOf(\":\");\r\n if (colon > 0 && /^[A-Z][A-Za-z]*$/.test(spec.slice(0, colon))) {\r\n const resource = spec.slice(0, colon);\r\n if (byResource.has(resource)) {\r\n throw new Error(`--search-params: ${resource} given more than once`);\r\n }\r\n byResource.set(resource, parseOne(spec.slice(colon + 1)));\r\n continue;\r\n }\r\n if (selection.default !== undefined) {\r\n throw new Error(\r\n `--search-params: more than one unscoped selection (\"${spec}\"). ` +\r\n \"Scope them per resource (Patient:name,birthdate) or pass a single list.\",\r\n );\r\n }\r\n selection.default = parseOne(spec);\r\n }\r\n if (byResource.size > 0) selection.byResource = byResource;\r\n return selection;\r\n}\r\n\r\n/**\r\n * Resolves a rule to the codes to emit for one resource, or undefined to emit\r\n * all of them. Every code named explicitly — in a list, an `+add` or a\r\n * `-remove` — must exist on the resource: silently ignoring a typo would\r\n * quietly shrink the published contract.\r\n */\r\nexport function resolveSearchParamCodes(\r\n selection: SearchParamSelection | undefined,\r\n fhirVersion: FhirVersion,\r\n resource: string,\r\n): ReadonlySet<string> | undefined {\r\n const rule = selection?.byResource?.get(resource) ?? selection?.default;\r\n if (rule === undefined) return undefined;\r\n if (rule.base === \"all\" && !rule.add && !rule.remove) return undefined;\r\n\r\n const available = loadSearchParameters(fhirVersion).filter((sp) => sp.base.includes(resource));\r\n const codes = new Set(available.map((sp) => sp.code));\r\n\r\n const named = [\r\n ...(typeof rule.base === \"string\" ? [] : rule.base),\r\n ...(rule.add ?? []),\r\n ...(rule.remove ?? []),\r\n ];\r\n const unknown = named.filter((code) => !codes.has(code));\r\n if (unknown.length > 0) {\r\n throw new Error(\r\n `--search-params: ${resource} has no search parameter ` +\r\n `${unknown.map((c) => `\"${c}\"`).join(\", \")} in ${fhirVersion.toUpperCase()}. ` +\r\n `Run \"fhir-oas generate ${resource} -f ${fhirVersion}\" to see the available codes.`,\r\n );\r\n }\r\n\r\n let selected: Set<string>;\r\n if (rule.base === \"all\") selected = new Set(codes);\r\n else if (rule.base === \"none\") selected = new Set();\r\n else if (rule.base === \"minimal\") selected = minimalCodes(resource, available);\r\n else selected = new Set(rule.base);\r\n\r\n for (const code of rule.add ?? []) selected.add(code);\r\n for (const code of rule.remove ?? []) selected.delete(code);\r\n return selected;\r\n}\r\n","import { loadFhirSchema, loadStructureDefinitions } from \"../definitions.js\";\r\nimport type { DefinitionRegistry } from \"../ir/registry.js\";\r\nimport type { FhirVersion, JsonSchemaNode } from \"../types.js\";\r\n\r\n/**\r\n * Builds the definition registry from the official `fhir.schema.json`\r\n * published with each FHIR release. This schema already has choice types\r\n * (value[x]) expanded and backbone elements flattened into named definitions\r\n * (e.g. `Patient_Contact`), so it maps directly onto the IR.\r\n *\r\n * One gap it does not cover: HL7 stopped inlining required-binding enums in\r\n * fhir.schema.json after R4, and even R4 only inlines some of them. The codes\r\n * are resolved at vendor time onto the StructureDefinition elements, so they\r\n * are applied here too — see applyBindingEnums.\r\n */\r\nexport function buildRegistryFromSchemaJson(fhirVersion: FhirVersion): DefinitionRegistry {\r\n const schema = loadFhirSchema(fhirVersion);\r\n const definitions = new Map<string, JsonSchemaNode>(Object.entries(schema.definitions));\r\n\r\n // Resource types are exactly the discriminator mapping keys; fall back to\r\n // \"has a resourceType const\" for robustness.\r\n let resourceNames: string[];\r\n if (schema.discriminator?.mapping) {\r\n resourceNames = Object.keys(schema.discriminator.mapping);\r\n } else {\r\n resourceNames = [...definitions.entries()]\r\n .filter(([, def]) => {\r\n const props = def.properties as Record<string, JsonSchemaNode> | undefined;\r\n return props?.resourceType !== undefined && \"const\" in (props.resourceType ?? {});\r\n })\r\n .map(([name]) => name);\r\n }\r\n\r\n applyBindingEnums(definitions, fhirVersion);\r\n\r\n return { fhirVersion, definitions, resourceNames };\r\n}\r\n\r\nconst lowerFirst = (s: string) => s.charAt(0).toLowerCase() + s.slice(1);\r\n\r\n/**\r\n * fhir.schema.json names flattened backbones `<Root>_<Segment>`; the element\r\n * paths they came from are `<Root>.<segment>`. Reverses that so a definition\r\n * and property can be looked up against the StructureDefinition elements.\r\n */\r\nfunction elementPathFor(definitionName: string, property: string): string {\r\n const [root, ...backbones] = definitionName.split(\"_\");\r\n return [root, ...backbones.map(lowerFirst), property].join(\".\");\r\n}\r\n\r\n/** element path -> resolved codes, for required bindings only. */\r\nfunction bindingCodeIndex(fhirVersion: FhirVersion): Map<string, string[]> {\r\n const index = new Map<string, string[]>();\r\n for (const sd of loadStructureDefinitions(fhirVersion)) {\r\n for (const el of sd.elements) {\r\n if (el.binding?.strength === \"required\" && el.binding.codes?.length) {\r\n index.set(el.path, el.binding.codes);\r\n }\r\n }\r\n }\r\n return index;\r\n}\r\n\r\n/**\r\n * Replaces plain `code` references with the inline enum for that element's\r\n * required binding. Only `code` targets are touched: Coding/CodeableConcept\r\n * carry their binding differently and stay as they are. Properties that\r\n * already have an enum (R4 ships many inline) are left alone.\r\n */\r\nfunction applyBindingEnums(\r\n definitions: Map<string, JsonSchemaNode>,\r\n fhirVersion: FhirVersion,\r\n): void {\r\n const codesByPath = bindingCodeIndex(fhirVersion);\r\n const isCodeRef = (node: JsonSchemaNode | undefined) =>\r\n !!node && node.$ref === \"#/definitions/code\";\r\n\r\n for (const [name, definition] of definitions) {\r\n const properties = definition.properties as Record<string, JsonSchemaNode> | undefined;\r\n if (!properties) continue;\r\n\r\n for (const [property, schema] of Object.entries(properties)) {\r\n const codes = codesByPath.get(elementPathFor(name, property));\r\n if (!codes) continue;\r\n\r\n const description = schema.description as string | undefined;\r\n const withDescription = (node: JsonSchemaNode) =>\r\n description ? { description, ...node } : node;\r\n\r\n if (isCodeRef(schema)) {\r\n properties[property] = withDescription({ enum: [...codes] });\r\n } else if (schema.type === \"array\" && isCodeRef(schema.items as JsonSchemaNode)) {\r\n properties[property] = withDescription({ type: \"array\", items: { enum: [...codes] } });\r\n }\r\n }\r\n }\r\n}\r\n","import {\r\n loadStructureDefinitions,\r\n type MinStructureDefinition,\r\n} from \"../definitions.js\";\r\nimport type { DefinitionRegistry } from \"../ir/registry.js\";\r\nimport { emitStructureDefinitionSchemas } from \"../ir/structureWalker.js\";\r\nimport type { FhirVersion, JsonSchemaNode } from \"../types.js\";\r\n\r\n/**\r\n * Builds the definition registry by walking StructureDefinition snapshots —\r\n * the canonical FHIR metadata, and the basis for profile support. Produces the\r\n * same IR shape as the fhir.schema.json backend: named definitions referencing\r\n * each other via `#/definitions/<Name>`.\r\n *\r\n * The per-snapshot walk lives in ../ir/structureWalker.ts so profiles loaded\r\n * from an IG package emit identically-shaped schemas.\r\n */\r\nexport function buildRegistryFromStructureDefinitions(\r\n fhirVersion: FhirVersion,\r\n): DefinitionRegistry {\r\n const sds = loadStructureDefinitions(fhirVersion);\r\n const definitions = new Map<string, JsonSchemaNode>();\r\n const resourceNames: string[] = [];\r\n\r\n const byName = new Map(sds.map((sd) => [sd.name, sd]));\r\n\r\n for (const sd of sds) {\r\n if (sd.kind === \"primitive-type\") {\r\n definitions.set(sd.name, primitiveSchema(sd));\r\n }\r\n }\r\n // `xhtml` (Narrative.div) has no StructureDefinition in the core packages.\r\n if (!definitions.has(\"xhtml\")) {\r\n definitions.set(\"xhtml\", {\r\n type: \"string\",\r\n description: \"XHTML narrative content\",\r\n });\r\n }\r\n\r\n for (const sd of sds) {\r\n if (sd.kind === \"primitive-type\" || sd.abstract) continue;\r\n emitStructureDefinitionSchemas(sd, definitions, {\r\n rootName: sd.name,\r\n isResourceRoot: sd.kind === \"resource\",\r\n });\r\n if (sd.kind === \"resource\") resourceNames.push(sd.name);\r\n }\r\n\r\n // Element/BackboneElement are abstract but referenced by primitive-extension\r\n // (`_field`) properties, so they need concrete definitions.\r\n for (const abstractName of [\"Element\", \"BackboneElement\"]) {\r\n const sd = byName.get(abstractName);\r\n if (sd && !definitions.has(abstractName)) {\r\n emitStructureDefinitionSchemas(sd, definitions, {\r\n rootName: sd.name,\r\n isResourceRoot: false,\r\n });\r\n }\r\n }\r\n\r\n resourceNames.sort();\r\n definitions.set(\"ResourceList\", {\r\n oneOf: resourceNames.map((name) => ({ $ref: `#/definitions/${name}` })),\r\n });\r\n\r\n return { fhirVersion, definitions, resourceNames };\r\n}\r\n\r\n/** Maps FHIR primitive type names to their JSON representation. */\r\nfunction primitiveJsonType(name: string): JsonSchemaNode {\r\n switch (name) {\r\n case \"boolean\":\r\n return { type: \"boolean\" };\r\n case \"decimal\":\r\n return { type: \"number\" };\r\n case \"integer\":\r\n case \"positiveInt\":\r\n case \"unsignedInt\":\r\n return { type: \"number\" };\r\n // integer64 (R5) is represented as a JSON string per the spec.\r\n default:\r\n return { type: \"string\" };\r\n }\r\n}\r\n\r\nfunction primitiveSchema(sd: MinStructureDefinition): JsonSchemaNode {\r\n const root = sd.elements[0];\r\n return {\r\n ...primitiveJsonType(sd.name),\r\n ...(root?.definition ? { description: root.definition } : {}),\r\n };\r\n}\r\n","import type { JsonSchemaNode, OpenApiVersion } from \"../types.js\";\r\n\r\nconst DEFINITIONS_REF = \"#/definitions/\";\r\nconst COMPONENTS_REF = \"#/components/schemas/\";\r\nconst NO_ENUMS_NOTE_MAX_CODES = 25;\r\n\r\nexport interface ConvertOptions {\r\n /** Strip source enums (required-binding codes), noting them in description. */\r\n noEnums?: boolean;\r\n}\r\n\r\n/**\r\n * Converts one JSON-Schema-shaped definition (draft-06 subset as used by\r\n * fhir.schema.json) into an OpenAPI schema object:\r\n * - rewrites `#/definitions/X` refs to `#/components/schemas/X`\r\n * - strips `pattern` from non-string types (fhir.schema.json puts regex\r\n * patterns on booleans/numbers, where the keyword is meaningless)\r\n * - drops JSON Schema bookkeeping keywords ($schema, id/$id, $comment)\r\n * - for 3.0.x, downconverts `const` to a single-value `enum`\r\n * - with `noEnums`, replaces source enums with plain strings, keeping the\r\n * allowed codes in the description; `const`-derived enums (resourceType\r\n * discriminators) are exempt\r\n */\r\nexport function convertSchema(\r\n node: JsonSchemaNode,\r\n target: OpenApiVersion,\r\n options: ConvertOptions = {},\r\n): JsonSchemaNode {\r\n return convertNode(node, target, options) as JsonSchemaNode;\r\n}\r\n\r\nfunction convertNode(node: unknown, target: OpenApiVersion, options: ConvertOptions): unknown {\r\n if (Array.isArray(node)) {\r\n return node.map((item) => convertNode(item, target, options));\r\n }\r\n if (!node || typeof node !== \"object\") return node;\r\n\r\n const out: JsonSchemaNode = {};\r\n const source = node as JsonSchemaNode;\r\n let strippedEnum: unknown[] | undefined;\r\n for (const [key, value] of Object.entries(source)) {\r\n switch (key) {\r\n case \"$schema\":\r\n case \"$comment\":\r\n // Draft-04/06 schema keywords. These are only keywords at schema-node\r\n // level: inside `properties` the same names are FHIR element names, and\r\n // nearly every FHIR element has an `id`. See the \"properties\" case.\r\n case \"id\":\r\n case \"$id\":\r\n break;\r\n case \"properties\": {\r\n // Keys here are property names, not schema keywords, so they are\r\n // preserved verbatim and only their values converted.\r\n const converted: JsonSchemaNode = {};\r\n for (const [propertyName, propertySchema] of Object.entries(\r\n (value ?? {}) as Record<string, unknown>,\r\n )) {\r\n converted[propertyName] = convertNode(propertySchema, target, options);\r\n }\r\n out.properties = converted;\r\n break;\r\n }\r\n case \"$ref\":\r\n out.$ref =\r\n typeof value === \"string\" && value.startsWith(DEFINITIONS_REF)\r\n ? COMPONENTS_REF + value.slice(DEFINITIONS_REF.length)\r\n : value;\r\n break;\r\n case \"const\":\r\n if (target === \"3.1.0\") out.const = value;\r\n else out.enum = [value];\r\n break;\r\n case \"enum\":\r\n if (options.noEnums && Array.isArray(value)) strippedEnum = value;\r\n else out.enum = value;\r\n break;\r\n case \"pattern\":\r\n if (source.type === undefined || source.type === \"string\") out.pattern = value;\r\n break;\r\n default:\r\n out[key] = convertNode(value, target, options);\r\n }\r\n }\r\n\r\n if (strippedEnum) {\r\n if (out.type === undefined && out.$ref === undefined) out.type = \"string\";\r\n const listed = strippedEnum.slice(0, NO_ENUMS_NOTE_MAX_CODES).join(\" | \");\r\n const ellipsis = strippedEnum.length > NO_ENUMS_NOTE_MAX_CODES ? \" | ...\" : \"\";\r\n const note = `Codes (FHIR required binding, not enforced here): ${listed}${ellipsis}`;\r\n out.description = out.description ? `${out.description} ${note}` : note;\r\n }\r\n return out;\r\n}\r\n","import type { FhirVersion, JsonSchemaNode, TrimOptions } from \"../types.js\";\r\n\r\n/**\r\n * Backend-neutral intermediate representation: a set of named,\r\n * JSON-Schema-shaped type definitions whose internal references use the\r\n * `#/definitions/<Name>` form (the convention of the official fhir.schema.json).\r\n * Both backends produce this shape; emitters consume it.\r\n */\r\nexport interface DefinitionRegistry {\r\n fhirVersion: FhirVersion;\r\n definitions: Map<string, JsonSchemaNode>;\r\n /** Concrete (non-abstract) resource type names, e.g. \"Patient\". */\r\n resourceNames: string[];\r\n}\r\n\r\nconst REF_PREFIX = \"#/definitions/\";\r\n\r\nexport function refName(ref: string): string | undefined {\r\n return ref.startsWith(REF_PREFIX) ? ref.slice(REF_PREFIX.length) : undefined;\r\n}\r\n\r\n/** Collects the names of all `#/definitions/...` references inside a schema node. */\r\nexport function collectRefs(node: unknown, out = new Set<string>()): Set<string> {\r\n if (Array.isArray(node)) {\r\n for (const item of node) collectRefs(item, out);\r\n } else if (node && typeof node === \"object\") {\r\n for (const [key, value] of Object.entries(node)) {\r\n if (key === \"$ref\" && typeof value === \"string\") {\r\n const name = refName(value);\r\n if (name) out.add(name);\r\n } else {\r\n collectRefs(value, out);\r\n }\r\n }\r\n }\r\n return out;\r\n}\r\n\r\nexport interface ClosureResult {\r\n /** Definition name -> schema, for the full dependency closure of the roots. */\r\n schemas: Map<string, JsonSchemaNode>;\r\n /** Names whose bodies were replaced by generic-object stubs via trimming. */\r\n stubbed: Set<string>;\r\n}\r\n\r\nfunction stubSchema(reason: string): JsonSchemaNode {\r\n return {\r\n type: \"object\",\r\n additionalProperties: true,\r\n description: reason,\r\n };\r\n}\r\n\r\n/**\r\n * `ResourceList` in fhir.schema.json is a oneOf over every resource type\r\n * (150-200 entries), referenced by e.g. `Bundle.entry.resource` and\r\n * `DomainResource.contained`. Following it verbatim would drag the entire\r\n * specification into every output, so it is narrowed to the resource types\r\n * actually requested (plus Bundle/OperationOutcome, which the generated REST\r\n * paths always use).\r\n */\r\nfunction narrowedResourceList(included: string[]): JsonSchemaNode {\r\n return {\r\n oneOf: included.map((name) => ({ $ref: `${REF_PREFIX}${name}` })),\r\n description:\r\n \"A contained/bundled FHIR resource. Narrowed by fhir-openapi-translator to the \" +\r\n \"resource types requested at generation time; servers may return other types.\",\r\n };\r\n}\r\n\r\n/**\r\n * Extracts the transitive dependency closure of `roots` from the registry via\r\n * breadth-first search. Cycles are fine: every definition is visited once and\r\n * mutual references remain as $refs. Trim options replace selected\r\n * definitions with stubs whose dependencies are not followed.\r\n */\r\nexport function extractClosure(\r\n registry: DefinitionRegistry,\r\n roots: string[],\r\n trim: TrimOptions = {},\r\n resourceListNarrowing: string[] = roots,\r\n): ClosureResult {\r\n const schemas = new Map<string, JsonSchemaNode>();\r\n const stubbed = new Set<string>();\r\n const maxDepth = trim.maxDepth;\r\n\r\n let frontier = [...new Set(roots)];\r\n let depth = 0;\r\n while (frontier.length > 0) {\r\n const next: string[] = [];\r\n for (const name of frontier) {\r\n if (schemas.has(name)) continue;\r\n const original = registry.definitions.get(name);\r\n if (!original) {\r\n throw new Error(`Unknown FHIR definition: ${name}`);\r\n }\r\n\r\n let schema: JsonSchemaNode = original;\r\n let followDeps = true;\r\n if (trim.excludeNarrative && name === \"Narrative\") {\r\n schema = stubSchema(\r\n \"Human-readable narrative. Excluded from this specification (--exclude-narrative).\",\r\n );\r\n followDeps = false;\r\n stubbed.add(name);\r\n } else if (maxDepth !== undefined && depth > maxDepth) {\r\n schema = stubSchema(\r\n `FHIR ${name}. Pruned from this specification by --max-depth ${maxDepth}.`,\r\n );\r\n followDeps = false;\r\n stubbed.add(name);\r\n } else if (name === \"ResourceList\") {\r\n schema = narrowedResourceList(\r\n [...new Set(resourceListNarrowing)].filter((n) => registry.definitions.has(n)),\r\n );\r\n }\r\n\r\n schemas.set(name, schema);\r\n if (followDeps) {\r\n for (const dep of collectRefs(schema)) {\r\n if (!schemas.has(dep)) next.push(dep);\r\n }\r\n }\r\n }\r\n frontier = next;\r\n depth++;\r\n }\r\n\r\n return { schemas, stubbed };\r\n}\r\n","import {\r\n loadOperationDefinitions,\r\n type MinOperationDefinition,\r\n type MinOperationParameter,\r\n} from \"./definitions.js\";\r\nimport type { FhirVersion, JsonSchemaNode } from \"./types.js\";\r\n\r\nconst FHIR_JSON = \"application/fhir+json\";\r\nconst SCHEMAS = \"#/components/schemas/\";\r\n\r\n/** FHIR primitive type names are lowercase-first; complex types are not. */\r\nfunction isPrimitive(type: string | undefined): boolean {\r\n return !!type && type.charAt(0) === type.charAt(0).toLowerCase();\r\n}\r\n\r\nfunction camelCode(code: string): string {\r\n return code.replace(/-([a-z])/g, (_, c: string) => c.toUpperCase());\r\n}\r\n\r\nfunction ref(schema: string) {\r\n return { $ref: `${SCHEMAS}${schema}` };\r\n}\r\n\r\nfunction fhirContent(schema: string) {\r\n return { [FHIR_JSON]: { schema: ref(schema) } };\r\n}\r\n\r\nfunction errorResponses() {\r\n return {\r\n default: {\r\n description: \"Error, with an OperationOutcome describing the problem\",\r\n content: fhirContent(\"OperationOutcome\"),\r\n },\r\n };\r\n}\r\n\r\nexport interface OperationPathsResult {\r\n paths: Record<string, JsonSchemaNode>;\r\n /** Schema names the operations reference, to add to the closure roots. */\r\n extraSchemaRoots: string[];\r\n}\r\n\r\n/**\r\n * Emits paths for the standard FHIR operations applicable to one resource\r\n * type, from the vendored OperationDefinitions.\r\n *\r\n * Method selection is deterministic per operation: GET with query parameters\r\n * when every `in` parameter is a primitive type (the spec-legal simple\r\n * invocation, and how e.g. $everything is used in practice); otherwise POST\r\n * with a Parameters request body. System-level-only operations are not\r\n * resource-scoped and are out of scope here.\r\n */\r\nexport interface OperationPathOptions {\r\n /** Maps a resource type to the schema name to reference (profile-aware). */\r\n schemaFor?: (resourceType: string) => string;\r\n /**\r\n * Restrict to operations whose code or canonical URL is in this set (e.g.\r\n * from a CapabilityStatement). Default: all operations applicable to the\r\n * resource.\r\n */\r\n only?: ReadonlySet<string>;\r\n}\r\n\r\nexport function buildOperationPaths(\r\n fhirVersion: FhirVersion,\r\n resource: string,\r\n knownResources: ReadonlySet<string>,\r\n options: OperationPathOptions = {},\r\n): OperationPathsResult {\r\n const schemaFor = options.schemaFor ?? ((r) => r);\r\n const paths: Record<string, JsonSchemaNode> = {};\r\n const extraSchemaRoots = new Set<string>();\r\n\r\n const applicable = loadOperationDefinitions(fhirVersion).filter(\r\n (op) =>\r\n (op.type || op.instance) &&\r\n (op.resource.includes(resource) || op.resource.includes(\"Resource\")) &&\r\n (!options.only || options.only.has(op.code) || options.only.has(op.url)),\r\n );\r\n\r\n for (const op of applicable) {\r\n const inParams = op.parameters.filter((p) => p.use === \"in\");\r\n const useGet = inParams.every((p) => isPrimitive(p.type));\r\n const responseSchema = schemaFor(responseSchemaName(op, knownResources));\r\n extraSchemaRoots.add(responseSchema);\r\n if (!useGet) extraSchemaRoots.add(\"Parameters\");\r\n\r\n const buildOperation = (level: \"Type\" | \"Instance\") => {\r\n const operation: JsonSchemaNode = {\r\n tags: [resource],\r\n summary: `$${op.code} (${level.toLowerCase()} level)`,\r\n ...(op.description ? { description: op.description } : {}),\r\n operationId: `${camelCode(op.code)}${resource}${level}`,\r\n externalDocs: { url: op.url },\r\n responses: {\r\n \"200\": {\r\n description: `Result of the $${op.code} operation`,\r\n content: fhirContent(responseSchema),\r\n },\r\n ...errorResponses(),\r\n },\r\n };\r\n if (useGet) {\r\n if (inParams.length > 0) operation.parameters = inParams.map(queryParameter);\r\n } else {\r\n operation.requestBody = {\r\n required: inParams.some((p) => p.min >= 1),\r\n content: fhirContent(\"Parameters\"),\r\n };\r\n }\r\n return operation;\r\n };\r\n\r\n const method = useGet ? \"get\" : \"post\";\r\n if (op.type) {\r\n paths[`/${resource}/$${op.code}`] = { [method]: buildOperation(\"Type\") };\r\n }\r\n if (op.instance) {\r\n paths[`/${resource}/{id}/$${op.code}`] = {\r\n parameters: [\r\n {\r\n name: \"id\",\r\n in: \"path\",\r\n required: true,\r\n description: `Logical id of the ${resource}`,\r\n schema: { type: \"string\", pattern: \"^[A-Za-z0-9\\\\-\\\\.]{1,64}$\" },\r\n },\r\n ],\r\n [method]: buildOperation(\"Instance\"),\r\n };\r\n }\r\n }\r\n\r\n return { paths, extraSchemaRoots: [...extraSchemaRoots].sort() };\r\n}\r\n\r\n/**\r\n * Exactly one `out` parameter named `return` typed as a resource maps to that\r\n * resource; every other output shape is a Parameters resource.\r\n */\r\nfunction responseSchemaName(\r\n op: MinOperationDefinition,\r\n knownResources: ReadonlySet<string>,\r\n): string {\r\n const outParams = op.parameters.filter((p) => p.use === \"out\");\r\n if (outParams.length === 1) {\r\n const only = outParams[0]!;\r\n if (only.name === \"return\" && only.type && knownResources.has(only.type)) {\r\n return only.type;\r\n }\r\n }\r\n return \"Parameters\";\r\n}\r\n\r\nfunction queryParameter(param: MinOperationParameter): JsonSchemaNode {\r\n const isArray = param.max === \"*\" || Number(param.max) > 1;\r\n const base: JsonSchemaNode = { type: \"string\" };\r\n return {\r\n name: param.name,\r\n in: \"query\",\r\n required: param.min >= 1,\r\n ...(param.documentation ? { description: param.documentation } : {}),\r\n // FHIR primitives serialize as strings in URLs; the FHIR type is kept\r\n // as an extension, consistent with search parameters.\r\n schema: isArray ? { type: \"array\", items: base } : base,\r\n ...(isArray ? { explode: true } : {}),\r\n \"x-fhir-type\": param.type,\r\n };\r\n}\r\n","import { loadSearchParameters } from \"./definitions.js\";\r\nimport { prefixesFor, searchParamCodes } from \"./searchParams.js\";\r\nimport type { FhirVersion, JsonSchemaNode } from \"./types.js\";\r\n\r\nconst FHIR_JSON = \"application/fhir+json\";\r\nconst SCHEMAS = \"#/components/schemas/\";\r\nconst PARAMETERS = \"#/components/parameters/\";\r\n\r\nfunction ref(schema: string) {\r\n return { $ref: `${SCHEMAS}${schema}` };\r\n}\r\n\r\nfunction fhirContent(schema: string) {\r\n return { [FHIR_JSON]: { schema: ref(schema) } };\r\n}\r\n\r\nfunction errorResponses() {\r\n return {\r\n default: {\r\n description: \"Error, with an OperationOutcome describing the problem\",\r\n content: fhirContent(\"OperationOutcome\"),\r\n },\r\n };\r\n}\r\n\r\nfunction idParameter(name: string, description: string) {\r\n return {\r\n name,\r\n in: \"path\",\r\n required: true,\r\n description,\r\n schema: { type: \"string\", pattern: \"^[A-Za-z0-9\\\\-\\\\.]{1,64}$\" },\r\n };\r\n}\r\n\r\n/**\r\n * Search parameters common to all resources plus the standard search result\r\n * parameters, emitted once under components/parameters and $ref'd from every\r\n * search operation. All are strings except _count: FHIR search values carry\r\n * prefixes/modifiers (e.g. `ge2020-01-01`, `:exact`), so stricter types would\r\n * reject valid requests.\r\n */\r\nconst COMMON_SEARCH_PARAMETERS: Record<string, { description: string; schema: JsonSchemaNode }> = {\r\n _id: { description: \"Logical id of this artifact\", schema: { type: \"string\" } },\r\n _lastUpdated: {\r\n description: \"When the resource version last changed (supports date prefixes, e.g. ge2021-01-01)\",\r\n schema: { type: \"string\" },\r\n },\r\n _tag: { description: \"Tags applied to this resource\", schema: { type: \"string\" } },\r\n _profile: { description: \"Profiles this resource claims to conform to\", schema: { type: \"string\" } },\r\n _security: { description: \"Security labels applied to this resource\", schema: { type: \"string\" } },\r\n _text: { description: \"Search on the narrative of the resource\", schema: { type: \"string\" } },\r\n _content: { description: \"Search on the entire content of the resource\", schema: { type: \"string\" } },\r\n _sort: { description: \"Sort order of the results (comma-separated parameter names, '-' prefix for descending)\", schema: { type: \"string\" } },\r\n _count: { description: \"Maximum number of results per page\", schema: { type: \"integer\", minimum: 0 } },\r\n _include: { description: \"Include referenced resources in the results\", schema: { type: \"string\" } },\r\n _revinclude: { description: \"Include resources that reference the matches in the results\", schema: { type: \"string\" } },\r\n _summary: {\r\n description: \"Return only a portion of each resource\",\r\n schema: { type: \"string\", enum: [\"true\", \"text\", \"data\", \"count\", \"false\"] },\r\n },\r\n _total: {\r\n description: \"Requested precision of the Bundle.total\",\r\n schema: { type: \"string\", enum: [\"none\", \"estimate\", \"accurate\"] },\r\n },\r\n _elements: { description: \"Restrict returned elements (comma-separated element names)\", schema: { type: \"string\" } },\r\n};\r\n\r\nexport function commonSearchParameterComponents(): Record<string, JsonSchemaNode> {\r\n const out: Record<string, JsonSchemaNode> = {};\r\n for (const [name, { description, schema }] of Object.entries(COMMON_SEARCH_PARAMETERS)) {\r\n out[name] = { name, in: \"query\", required: false, description, schema };\r\n }\r\n return out;\r\n}\r\n\r\n/** FHIR RESTful interaction codes (CapabilityStatement.rest.resource.interaction). */\r\nexport type FhirInteraction =\r\n | \"read\"\r\n | \"vread\"\r\n | \"update\"\r\n | \"patch\"\r\n | \"delete\"\r\n | \"history-instance\"\r\n | \"history-type\"\r\n | \"create\"\r\n | \"search-type\";\r\n\r\nexport const ALL_INTERACTIONS: readonly FhirInteraction[] = [\r\n \"read\",\r\n \"vread\",\r\n \"update\",\r\n \"patch\",\r\n \"delete\",\r\n \"history-instance\",\r\n \"history-type\",\r\n \"create\",\r\n \"search-type\",\r\n];\r\n\r\nexport interface ResourcePathOptions {\r\n /** Emit only these interactions. Default: all of them. */\r\n interactions?: ReadonlySet<FhirInteraction>;\r\n /**\r\n * Restrict resource-specific search parameters to these codes (the common\r\n * result parameters like `_id`/`_count` are always kept). Default: all\r\n * search parameters the FHIR version defines for the resource.\r\n */\r\n searchParamCodes?: ReadonlySet<string>;\r\n}\r\n\r\n/**\r\n * True when a description is nothing but a code list, e.g. Encounter-status's\r\n * \"planned | arrived | triaged | in-progress | onleave | finished | cancelled +\".\r\n * HL7 writes these by hand and they drift from the binding: the R4 example\r\n * omits `entered-in-error` and `unknown`, hinting at them with a trailing \"+\".\r\n * Such a description is replaced by the derived list rather than appended to,\r\n * so the codes are not reported twice in two different sets.\r\n */\r\nfunction isCodeListDescription(description: string): boolean {\r\n return description.includes(\"|\") && /^[A-Za-z0-9\\-.\\s|+]+$/.test(description);\r\n}\r\n\r\n/**\r\n * Describes a search parameter consistently, whatever HL7's own prose does.\r\n *\r\n * SearchParameter.description is written per parameter by different HL7 work\r\n * groups and is not uniform: Encounter-status spells its codes out,\r\n * Observation-status does not (\"The status of the observation\"), though both\r\n * are token parameters over a required binding. The accepted codes and\r\n * prefixes are therefore derived from the definitions, so every parameter of a\r\n * given kind reads the same way on every FHIR version.\r\n */\r\nfunction describeSearchParameter(\r\n description: string,\r\n codes: readonly string[] | undefined,\r\n prefixes: readonly string[] | undefined,\r\n): string {\r\n let base = description.trim();\r\n if (codes?.length && isCodeListDescription(base)) base = \"\";\r\n\r\n const notes: string[] = [];\r\n if (codes?.length) notes.push(`Accepted values: ${codes.join(\" | \")}.`);\r\n if (prefixes?.length) {\r\n notes.push(`Values may carry a comparison prefix (${prefixes.join(\", \")}), e.g. ge2021-01-01.`);\r\n }\r\n if (notes.length === 0) return base;\r\n if (base.length === 0) return notes.join(\" \");\r\n\r\n // Several descriptions are multi-line markdown listing every resource a\r\n // shared parameter covers. Appending inline there would read as part of the\r\n // last bullet, so keep the note in its own paragraph.\r\n const separator = base.includes(\"\\n\") ? \"\\n\\n\" : /[.?!]$/.test(base) ? \" \" : \". \";\r\n return `${base}${separator}${notes.join(\" \")}`;\r\n}\r\n\r\nfunction resourceSearchParameters(\r\n fhirVersion: FhirVersion,\r\n resource: string,\r\n only?: ReadonlySet<string>,\r\n): JsonSchemaNode[] {\r\n return loadSearchParameters(fhirVersion)\r\n .filter((sp) => sp.base.includes(resource) && (!only || only.has(sp.code)))\r\n .sort((a, b) => a.code.localeCompare(b.code))\r\n .map((sp) => {\r\n const codes = searchParamCodes(fhirVersion, resource, sp.type, sp.expression);\r\n const prefixes = prefixesFor(sp.type);\r\n return {\r\n name: sp.code,\r\n in: \"query\",\r\n required: false,\r\n description: describeSearchParameter(sp.description ?? \"\", codes, prefixes),\r\n // FHIR search values carry prefixes and modifiers, so all are strings.\r\n // The accepted values are advertised via x-fhir-search-values rather\r\n // than `enum`, which would reject the comma-OR (`status=final,amended`),\r\n // system|code and `:modifier` forms that FHIR search permits.\r\n schema: { type: \"string\" },\r\n \"x-fhir-search-type\": sp.type,\r\n ...(codes?.length ? { \"x-fhir-search-values\": codes } : {}),\r\n ...(prefixes?.length ? { \"x-fhir-search-prefixes\": prefixes } : {}),\r\n };\r\n });\r\n}\r\n\r\nconst historyParameters = () => [\r\n { $ref: `${PARAMETERS}_count` },\r\n {\r\n name: \"_since\",\r\n in: \"query\",\r\n required: false,\r\n description: \"Only include versions created at or after this instant\",\r\n schema: { type: \"string\", format: \"date-time\" },\r\n },\r\n];\r\n\r\n/**\r\n * FHIR RESTful API interactions for one resource type. By default every\r\n * standard interaction (search, create, read, vread, update, patch, delete,\r\n * and instance/type history) is emitted; `options.interactions` restricts the\r\n * set (e.g. from a CapabilityStatement), and empty path items are dropped.\r\n */\r\nexport function buildResourcePaths(\r\n fhirVersion: FhirVersion,\r\n resource: string,\r\n /** Schema referenced by request/response bodies; a profile name or the resource. */\r\n schemaName: string = resource,\r\n options: ResourcePathOptions = {},\r\n): Record<string, JsonSchemaNode> {\r\n const want = (interaction: FhirInteraction) =>\r\n !options.interactions || options.interactions.has(interaction);\r\n const body = () => fhirContent(schemaName);\r\n const idParam = () => idParameter(\"id\", `Logical id of the ${resource}`);\r\n const paths: Record<string, JsonSchemaNode> = {};\r\n\r\n const typeItem: Record<string, JsonSchemaNode> = {};\r\n if (want(\"search-type\")) {\r\n typeItem.get = {\r\n tags: [resource],\r\n summary: `Search for ${resource} resources`,\r\n operationId: `search${resource}`,\r\n parameters: [\r\n ...Object.keys(COMMON_SEARCH_PARAMETERS).map((name) => ({ $ref: `${PARAMETERS}${name}` })),\r\n ...resourceSearchParameters(fhirVersion, resource, options.searchParamCodes),\r\n ],\r\n responses: {\r\n \"200\": {\r\n description: `Bundle of matching ${resource} resources`,\r\n content: fhirContent(\"Bundle\"),\r\n },\r\n ...errorResponses(),\r\n },\r\n };\r\n }\r\n if (want(\"create\")) {\r\n typeItem.post = {\r\n tags: [resource],\r\n summary: `Create a ${resource} resource`,\r\n operationId: `create${resource}`,\r\n requestBody: { required: true, content: body() },\r\n responses: {\r\n \"201\": { description: `${resource} created`, content: body() },\r\n ...errorResponses(),\r\n },\r\n };\r\n }\r\n if (Object.keys(typeItem).length > 0) paths[`/${resource}`] = typeItem;\r\n\r\n const instanceItem: Record<string, JsonSchemaNode> = {};\r\n if (want(\"read\")) {\r\n instanceItem.get = {\r\n tags: [resource],\r\n summary: `Read a ${resource} resource by id`,\r\n operationId: `read${resource}`,\r\n responses: {\r\n \"200\": { description: `The ${resource} resource`, content: body() },\r\n ...errorResponses(),\r\n },\r\n };\r\n }\r\n if (want(\"update\")) {\r\n instanceItem.put = {\r\n tags: [resource],\r\n summary: `Update (or create) a ${resource} resource by id`,\r\n operationId: `update${resource}`,\r\n parameters: [\r\n {\r\n name: \"If-Match\",\r\n in: \"header\",\r\n required: false,\r\n description: \"Version-aware update: weak ETag of the version being updated\",\r\n schema: { type: \"string\" },\r\n },\r\n ],\r\n requestBody: { required: true, content: body() },\r\n responses: {\r\n \"200\": { description: `${resource} updated`, content: body() },\r\n \"201\": { description: `${resource} created`, content: body() },\r\n ...errorResponses(),\r\n },\r\n };\r\n }\r\n if (want(\"patch\")) {\r\n instanceItem.patch = {\r\n tags: [resource],\r\n summary: `Patch a ${resource} resource by id`,\r\n operationId: `patch${resource}`,\r\n requestBody: {\r\n required: true,\r\n content: {\r\n \"application/json-patch+json\": {\r\n schema: {\r\n type: \"array\",\r\n items: { type: \"object\", additionalProperties: true },\r\n description: \"JSON Patch operations (RFC 6902)\",\r\n },\r\n },\r\n },\r\n },\r\n responses: {\r\n \"200\": { description: `${resource} patched`, content: body() },\r\n ...errorResponses(),\r\n },\r\n };\r\n }\r\n if (want(\"delete\")) {\r\n instanceItem.delete = {\r\n tags: [resource],\r\n summary: `Delete a ${resource} resource by id`,\r\n operationId: `delete${resource}`,\r\n responses: { \"204\": { description: `${resource} deleted` }, ...errorResponses() },\r\n };\r\n }\r\n if (Object.keys(instanceItem).length > 0) {\r\n paths[`/${resource}/{id}`] = { parameters: [idParam()], ...instanceItem };\r\n }\r\n\r\n if (want(\"history-instance\")) {\r\n paths[`/${resource}/{id}/_history`] = {\r\n parameters: [idParam()],\r\n get: {\r\n tags: [resource],\r\n summary: `History of a ${resource} instance`,\r\n operationId: `history${resource}Instance`,\r\n parameters: historyParameters(),\r\n responses: {\r\n \"200\": { description: \"History bundle\", content: fhirContent(\"Bundle\") },\r\n ...errorResponses(),\r\n },\r\n },\r\n };\r\n }\r\n if (want(\"vread\")) {\r\n paths[`/${resource}/{id}/_history/{vid}`] = {\r\n parameters: [idParam(), idParameter(\"vid\", \"Version id of the resource\")],\r\n get: {\r\n tags: [resource],\r\n summary: `Read a specific version of a ${resource} resource`,\r\n operationId: `vread${resource}`,\r\n responses: {\r\n \"200\": { description: `The ${resource} resource version`, content: body() },\r\n ...errorResponses(),\r\n },\r\n },\r\n };\r\n }\r\n if (want(\"history-type\")) {\r\n paths[`/${resource}/_history`] = {\r\n get: {\r\n tags: [resource],\r\n summary: `History across all ${resource} resources`,\r\n operationId: `history${resource}Type`,\r\n parameters: historyParameters(),\r\n responses: {\r\n \"200\": { description: \"History bundle\", content: fhirContent(\"Bundle\") },\r\n ...errorResponses(),\r\n },\r\n },\r\n };\r\n }\r\n\r\n return paths;\r\n}\r\n","import { buildRegistryFromSchemaJson } from \"./backends/schemaJson.js\";\r\nimport { buildRegistryFromStructureDefinitions } from \"./backends/structureDefinition.js\";\r\nimport type { Capability, ResourceCapability } from \"./capability.js\";\r\nimport { convertSchema } from \"./emit/schema.js\";\r\nimport { loadIgSync, type IgContext } from \"./ig/package.js\";\r\nimport { applyProfile, buildCoreValueSetFallback } from \"./ig/profile.js\";\r\nimport { extractClosure, type DefinitionRegistry } from \"./ir/registry.js\";\r\nimport { buildOperationPaths } from \"./operations.js\";\r\nimport { buildResourcePaths, commonSearchParameterComponents } from \"./paths.js\";\r\nimport { resolveSearchParamCodes } from \"./searchParams.js\";\r\nimport {\r\n FHIR_VERSION_NUMBERS,\r\n FHIR_VERSIONS,\r\n type FhirVersion,\r\n type GenerateOptions,\r\n type JsonSchemaNode,\r\n type OpenApiDocument,\r\n type SourceBackend,\r\n} from \"./types.js\";\r\n\r\nfunction buildRegistry(fhirVersion: FhirVersion, source: SourceBackend): DefinitionRegistry {\r\n return source === \"structure-def\"\r\n ? buildRegistryFromStructureDefinitions(fhirVersion)\r\n : buildRegistryFromSchemaJson(fhirVersion);\r\n}\r\n\r\nfunction resolveResourceName(registry: DefinitionRegistry, requested: string): string {\r\n const match = registry.resourceNames.find(\r\n (name) => name.toLowerCase() === requested.toLowerCase(),\r\n );\r\n if (!match) {\r\n throw new Error(\r\n `Unknown FHIR ${registry.fhirVersion.toUpperCase()} resource: \"${requested}\". ` +\r\n `Run \"fhir-oas list --fhir-version ${registry.fhirVersion}\" to see available resources.`,\r\n );\r\n }\r\n return match;\r\n}\r\n\r\n/** Lists the resource type names available for a FHIR version. */\r\nexport function listResources(\r\n fhirVersion: FhirVersion,\r\n source: SourceBackend = \"schema-json\",\r\n): string[] {\r\n assertFhirVersion(fhirVersion);\r\n return [...buildRegistry(fhirVersion, source).resourceNames].sort();\r\n}\r\n\r\nfunction assertFhirVersion(fhirVersion: string): asserts fhirVersion is FhirVersion {\r\n if (!FHIR_VERSIONS.includes(fhirVersion as FhirVersion)) {\r\n throw new Error(\r\n `Unsupported FHIR version \"${fhirVersion}\". Supported: ${FHIR_VERSIONS.join(\", \")}`,\r\n );\r\n }\r\n}\r\n\r\n/** The FHIR version a CapabilityStatement fhirVersion string belongs to. */\r\nfunction assertCapabilityFhirVersion(capability: Capability, fhirVersion: FhirVersion): void {\r\n const declared = capability.fhirVersion;\r\n if (!declared) return; // statement omitted it; trust the caller's --fhir-version\r\n const expectedMajor = FHIR_VERSION_NUMBERS[fhirVersion].split(\".\").slice(0, 2).join(\".\");\r\n // R4 (4.0.x) and R4B (4.3.x) share major 4 but differ in minor; compare the\r\n // major.minor prefix, tolerating the statement carrying only \"4.0\" etc.\r\n const declaredPrefix = declared.split(\".\").slice(0, 2).join(\".\");\r\n if (declaredPrefix && expectedMajor && declaredPrefix !== expectedMajor) {\r\n throw new Error(\r\n `CapabilityStatement targets FHIR ${declared}, but generation is for ` +\r\n `${fhirVersion.toUpperCase()} (${FHIR_VERSION_NUMBERS[fhirVersion]}). ` +\r\n `Set --fhir-version to match the server.`,\r\n );\r\n }\r\n}\r\n\r\n/** Resolves options.ig to an IgContext: a local path is loaded synchronously. */\r\nfunction resolveIg(options: GenerateOptions): IgContext {\r\n const ig = options.ig;\r\n if (!ig) throw new Error(\"--profile requires --ig: point at the IG package.\");\r\n if (typeof ig === \"string\") {\r\n return loadIgSync(ig, { coreValueSetFallback: buildCoreValueSetFallback(options.fhirVersion) });\r\n }\r\n return ig as IgContext;\r\n}\r\n\r\n/**\r\n * Generates an OpenAPI document covering the requested FHIR resources: their\r\n * full schema dependency closure plus the standard FHIR RESTful interactions.\r\n */\r\nexport function generateOpenApi(options: GenerateOptions): OpenApiDocument {\r\n assertFhirVersion(options.fhirVersion);\r\n const openApiVersion = options.openApiVersion ?? \"3.0.3\";\r\n if (openApiVersion !== \"3.0.3\" && openApiVersion !== \"3.1.0\") {\r\n throw new Error(`Unsupported OpenAPI version \"${openApiVersion}\". Supported: 3.0.3, 3.1.0`);\r\n }\r\n\r\n const registry = buildRegistry(options.fhirVersion, options.source ?? \"schema-json\");\r\n\r\n // A CapabilityStatement restricts generation to one server's declared\r\n // surface: which resources, interactions, search params, and operations.\r\n const capability = options.capability as Capability | undefined;\r\n const capabilityByResource = new Map<string, ResourceCapability>();\r\n if (capability) {\r\n assertCapabilityFhirVersion(capability, options.fhirVersion);\r\n for (const cap of capability.resources) {\r\n const match = registry.resourceNames.find(\r\n (name) => name.toLowerCase() === cap.type.toLowerCase(),\r\n );\r\n // Skip resource types the FHIR version doesn't define (custom/unknown).\r\n if (match) capabilityByResource.set(match, cap);\r\n }\r\n }\r\n\r\n const requested = (options.resources ?? []).map((r) => resolveResourceName(registry, r));\r\n if (requested.length === 0 && capabilityByResource.size === 0) {\r\n throw new Error(\r\n capability\r\n ? \"The CapabilityStatement declares no resources this FHIR version supports.\"\r\n : \"At least one FHIR resource name (or a --capability statement) is required\",\r\n );\r\n }\r\n\r\n // Apply IG profiles (if any) into the registry, mapping each profiled base\r\n // resource to its emitted schema name. The base resource is auto-included.\r\n const schemaByResource = new Map<string, string>();\r\n // In capability mode, the resource set is the statement's (optionally\r\n // narrowed to the explicitly requested ones); otherwise it's the requested.\r\n const resourceSet = new Set<string>(\r\n capability\r\n ? requested.length > 0\r\n ? requested.filter((r) => capabilityByResource.has(r))\r\n : [...capabilityByResource.keys()]\r\n : requested,\r\n );\r\n if (options.profiles?.length) {\r\n const ig = resolveIg(options);\r\n if (ig.fhirVersion !== options.fhirVersion) {\r\n throw new Error(\r\n `IG package \"${ig.name}\" targets FHIR ${ig.fhirVersion.toUpperCase()}, but generation ` +\r\n `is for ${options.fhirVersion.toUpperCase()}. Use --fhir-version ${ig.fhirVersion}.`,\r\n );\r\n }\r\n for (const profileId of options.profiles) {\r\n const applied = applyProfile(ig, profileId, registry);\r\n const base = resolveResourceName(registry, applied.resourceType);\r\n if (schemaByResource.has(base)) {\r\n throw new Error(\r\n `Multiple profiles target ${base}; generate one profiled resource per run.`,\r\n );\r\n }\r\n schemaByResource.set(base, applied.schemaName);\r\n resourceSet.add(base);\r\n }\r\n } else if (options.ig) {\r\n throw new Error(\"--ig requires --profile: name the profile(s) to apply.\");\r\n }\r\n\r\n const resources = [...resourceSet];\r\n const schemaFor = (resource: string) => schemaByResource.get(resource) ?? resource;\r\n\r\n // Operations: in capability mode, emit exactly the operations each resource\r\n // declares (mapped to known OperationDefinitions); otherwise --operations\r\n // emits every applicable operation.\r\n const operationPaths: Record<string, JsonSchemaNode> = {};\r\n const operationRoots: string[] = [];\r\n if (capability || options.operations) {\r\n const knownResources = new Set(registry.resourceNames);\r\n for (const resource of resources) {\r\n const cap = capabilityByResource.get(resource);\r\n if (capability && (!cap || cap.operations.size === 0)) continue;\r\n const result = buildOperationPaths(options.fhirVersion, resource, knownResources, {\r\n schemaFor,\r\n only: cap?.operations,\r\n });\r\n Object.assign(operationPaths, result.paths);\r\n operationRoots.push(...result.extraSchemaRoots);\r\n }\r\n }\r\n\r\n // Closure roots use the profiled schema name where a resource is profiled,\r\n // so the base schema is only emitted if something else references it.\r\n // Bundle and OperationOutcome are always present: search/history responses\r\n // are Bundles and every error response is an OperationOutcome.\r\n const roots = [\r\n ...new Set([...resources.map(schemaFor), \"Bundle\", \"OperationOutcome\", ...operationRoots]),\r\n ];\r\n const { schemas } = extractClosure(registry, roots, options.trim ?? {}, roots);\r\n\r\n const componentSchemas: Record<string, JsonSchemaNode> = {};\r\n const convertOptions = { noEnums: options.trim?.noEnums };\r\n for (const name of [...schemas.keys()].sort()) {\r\n componentSchemas[name] = convertSchema(schemas.get(name)!, openApiVersion, convertOptions);\r\n }\r\n\r\n const paths: Record<string, JsonSchemaNode> = {};\r\n for (const resource of resources) {\r\n const cap = capabilityByResource.get(resource);\r\n // A CapabilityStatement says what the server supports; --search-params\r\n // narrows further. With both, emit only what satisfies each.\r\n const selected = resolveSearchParamCodes(options.searchParams, options.fhirVersion, resource);\r\n const searchParamCodes =\r\n cap?.searchParamCodes && selected\r\n ? new Set([...selected].filter((code) => cap.searchParamCodes.has(code)))\r\n : (selected ?? cap?.searchParamCodes);\r\n Object.assign(\r\n paths,\r\n buildResourcePaths(options.fhirVersion, resource, schemaFor(resource), {\r\n interactions: cap?.interactions,\r\n searchParamCodes,\r\n }),\r\n );\r\n }\r\n Object.assign(paths, operationPaths);\r\n\r\n const fhirNumber = FHIR_VERSION_NUMBERS[options.fhirVersion];\r\n const document: OpenApiDocument = {\r\n openapi: openApiVersion,\r\n info: {\r\n title:\r\n options.title ??\r\n `FHIR ${options.fhirVersion.toUpperCase()} REST API: ${resources.join(\", \")}`,\r\n description:\r\n `OpenAPI definition of the FHIR ${options.fhirVersion.toUpperCase()} (${fhirNumber}) ` +\r\n `RESTful interactions and JSON schemas for: ${resources.join(\", \")}. ` +\r\n \"Generated by fhir-openapi-translator from the official HL7 FHIR definitions. \" +\r\n \"Schema validity does not imply full FHIR conformance: profiles, terminology \" +\r\n \"bindings, and FHIRPath invariants are not represented.\",\r\n version: fhirNumber,\r\n },\r\n ...(options.baseUrl ? { servers: [{ url: options.baseUrl }] } : {}),\r\n tags: resources.map((resource) => ({\r\n name: resource,\r\n description: `Operations on the ${resource} resource`,\r\n })),\r\n paths,\r\n components: {\r\n parameters: commonSearchParameterComponents(),\r\n schemas: componentSchemas,\r\n },\r\n };\r\n return document;\r\n}\r\n","import fs from \"node:fs\";\r\nimport type { FhirInteraction } from \"./paths.js\";\r\n\r\n/**\r\n * Loads and parses a FHIR CapabilityStatement (a server's `/metadata`) into a\r\n * per-resource description of what the server actually supports, so a spec can\r\n * be generated to match exactly one server's surface rather than the full\r\n * standard interaction set.\r\n */\r\n\r\nexport interface ResourceCapability {\r\n type: string;\r\n interactions: Set<FhirInteraction>;\r\n /** Search parameter codes the server declares for this resource. */\r\n searchParamCodes: Set<string>;\r\n /** Operation codes and canonical URLs the server declares for this resource. */\r\n operations: Set<string>;\r\n}\r\n\r\nexport interface Capability {\r\n /** FHIR version string from the statement, e.g. \"4.0.1\" (may be undefined). */\r\n fhirVersion?: string;\r\n resources: ResourceCapability[];\r\n}\r\n\r\ninterface RawInteraction {\r\n code?: string;\r\n}\r\ninterface RawSearchParam {\r\n name?: string;\r\n}\r\ninterface RawOperation {\r\n name?: string;\r\n definition?: string;\r\n}\r\ninterface RawResource {\r\n type?: string;\r\n interaction?: RawInteraction[];\r\n searchParam?: RawSearchParam[];\r\n operation?: RawOperation[];\r\n}\r\ninterface RawCapabilityStatement {\r\n resourceType?: string;\r\n fhirVersion?: string;\r\n rest?: { mode?: string; resource?: RawResource[] }[];\r\n}\r\n\r\nconst KNOWN_INTERACTIONS = new Set<string>([\r\n \"read\",\r\n \"vread\",\r\n \"update\",\r\n \"patch\",\r\n \"delete\",\r\n \"history-instance\",\r\n \"history-type\",\r\n \"create\",\r\n \"search-type\",\r\n]);\r\n\r\nexport interface LoadCapabilityOptions {\r\n fetchImpl?: typeof fetch;\r\n}\r\n\r\n/**\r\n * Loads a CapabilityStatement from a local JSON file or an http(s) URL. A URL\r\n * that does not already end in `/metadata` has it appended, so a base server\r\n * URL works directly.\r\n */\r\nexport async function loadCapabilityStatement(\r\n input: string,\r\n options: LoadCapabilityOptions = {},\r\n): Promise<Capability> {\r\n let json: unknown;\r\n if (/^https?:\\/\\//i.test(input)) {\r\n const url = /\\/metadata\\/?$/.test(input) ? input : `${input.replace(/\\/$/, \"\")}/metadata`;\r\n const doFetch = options.fetchImpl ?? fetch;\r\n let response: Response;\r\n try {\r\n response = await doFetch(url, { headers: { Accept: \"application/fhir+json\" } });\r\n } catch (cause) {\r\n throw new Error(\r\n `Failed to fetch CapabilityStatement from ${url}: ${(cause as Error).message}. ` +\r\n `Save it locally (curl -H 'Accept: application/fhir+json' ${url} > metadata.json) ` +\r\n `and pass the file instead.`,\r\n );\r\n }\r\n if (!response.ok) {\r\n throw new Error(`CapabilityStatement request to ${url} returned ${response.status}.`);\r\n }\r\n json = await response.json();\r\n } else {\r\n if (!fs.existsSync(input)) throw new Error(`No such CapabilityStatement file: ${input}`);\r\n json = JSON.parse(fs.readFileSync(input, \"utf8\"));\r\n }\r\n return parseCapabilityStatement(json);\r\n}\r\n\r\nexport function parseCapabilityStatement(json: unknown): Capability {\r\n const statement = json as RawCapabilityStatement;\r\n if (statement?.resourceType !== \"CapabilityStatement\") {\r\n throw new Error(\r\n `Expected a CapabilityStatement resource, got \"${statement?.resourceType ?? \"unknown\"}\".`,\r\n );\r\n }\r\n\r\n // Merge resource entries across all `rest` blocks with mode \"server\".\r\n const byType = new Map<string, ResourceCapability>();\r\n for (const rest of statement.rest ?? []) {\r\n if (rest.mode && rest.mode !== \"server\") continue;\r\n for (const raw of rest.resource ?? []) {\r\n if (!raw.type) continue;\r\n let cap = byType.get(raw.type);\r\n if (!cap) {\r\n cap = {\r\n type: raw.type,\r\n interactions: new Set(),\r\n searchParamCodes: new Set(),\r\n operations: new Set(),\r\n };\r\n byType.set(raw.type, cap);\r\n }\r\n for (const i of raw.interaction ?? []) {\r\n if (i.code && KNOWN_INTERACTIONS.has(i.code)) cap.interactions.add(i.code as FhirInteraction);\r\n }\r\n for (const sp of raw.searchParam ?? []) {\r\n if (sp.name) cap.searchParamCodes.add(sp.name);\r\n }\r\n for (const op of raw.operation ?? []) {\r\n if (op.name) cap.operations.add(op.name);\r\n if (op.definition) cap.operations.add(op.definition);\r\n }\r\n }\r\n }\r\n\r\n if (byType.size === 0) {\r\n throw new Error(\r\n \"CapabilityStatement declares no server resources (rest[].resource). Nothing to generate.\",\r\n );\r\n }\r\n\r\n return {\r\n fhirVersion: statement.fhirVersion,\r\n resources: [...byType.values()].sort((a, b) => a.type.localeCompare(b.type)),\r\n };\r\n}\r\n","import { Document, parseDocument, isMap, type YAMLMap } from \"yaml\";\r\nimport type { OpenApiDocument } from \"./types.js\";\r\n\r\nexport interface MergeOptions {\r\n /** Overwrite conflicting entries instead of failing. */\r\n force?: boolean;\r\n}\r\n\r\nexport interface MergeConflict {\r\n /** e.g. \"components.schemas.Patient\" or \"paths./Patient/{id}\" */\r\n location: string;\r\n}\r\n\r\nexport class MergeConflictError extends Error {\r\n constructor(public readonly conflicts: MergeConflict[]) {\r\n super(\r\n \"Refusing to overwrite existing, differing entries (use --force to overwrite):\\n\" +\r\n conflicts.map((c) => ` - ${c.location}`).join(\"\\n\"),\r\n );\r\n this.name = \"MergeConflictError\";\r\n }\r\n}\r\n\r\n/** Top-level maps whose entries are merged key-by-key. */\r\nconst MERGED_SECTIONS: [string, string][] = [\r\n [\"paths\", \"\"],\r\n [\"components\", \"schemas\"],\r\n [\"components\", \"parameters\"],\r\n];\r\n\r\nfunction deepEqual(a: unknown, b: unknown): boolean {\r\n return JSON.stringify(a) === JSON.stringify(b);\r\n}\r\n\r\n/**\r\n * `ResourceList` is narrowed to the resource types requested at generation\r\n * time (see ir/registry.ts), so two generated specs legitimately differ in\r\n * it. Merging unions the two narrowings instead of conflicting. Returns\r\n * undefined when either side is not the expected oneOf-of-$refs shape.\r\n */\r\nfunction unionResourceList(existing: unknown, generated: unknown): unknown | undefined {\r\n const refsOf = (node: unknown): string[] | undefined => {\r\n if (!node || typeof node !== \"object\" || Array.isArray(node)) return undefined;\r\n const oneOf = (node as { oneOf?: unknown }).oneOf;\r\n if (!Array.isArray(oneOf)) return undefined;\r\n const refs: string[] = [];\r\n for (const item of oneOf) {\r\n if (!item || typeof item !== \"object\" || Object.keys(item).length !== 1) return undefined;\r\n const ref = (item as { $ref?: unknown }).$ref;\r\n if (typeof ref !== \"string\") return undefined;\r\n refs.push(ref);\r\n }\r\n return refs;\r\n };\r\n const existingRefs = refsOf(existing);\r\n const generatedRefs = refsOf(generated);\r\n if (!existingRefs || !generatedRefs) return undefined;\r\n return {\r\n ...(generated as Record<string, unknown>),\r\n oneOf: [...new Set([...existingRefs, ...generatedRefs])].map(($ref) => ({ $ref })),\r\n };\r\n}\r\n\r\ninterface MergePlan {\r\n doc: ReturnType<typeof parseDocument>;\r\n conflicts: MergeConflict[];\r\n additions: { path: (string | number)[]; value: unknown }[];\r\n}\r\n\r\n/**\r\n * Parses the existing YAML and computes what a merge would do: entries to add\r\n * (absent from the file, or ResourceList unions) and conflicting entries\r\n * (present with different content). Shared by merge and check.\r\n */\r\nfunction computeMergePlan(\r\n generated: OpenApiDocument,\r\n existingText: string,\r\n options: MergeOptions,\r\n): MergePlan {\r\n const doc = parseDocument(existingText);\r\n if (doc.errors.length > 0) {\r\n throw new Error(`Cannot parse existing YAML: ${doc.errors[0]?.message}`);\r\n }\r\n if (doc.contents !== null && !isMap(doc.contents)) {\r\n throw new Error(\"Existing file is not a YAML mapping; refusing to merge\");\r\n }\r\n\r\n const existingVersion = doc.getIn([\"openapi\"]);\r\n const generatedVersion = generated.openapi;\r\n if (existingVersion !== undefined && String(existingVersion) !== String(generatedVersion)) {\r\n throw new Error(\r\n `OpenAPI version mismatch: existing file declares ${String(existingVersion)}, ` +\r\n `generating ${String(generatedVersion)}. Regenerate with a matching --openapi-version.`,\r\n );\r\n }\r\n\r\n const conflicts: MergeConflict[] = [];\r\n const additions: { path: (string | number)[]; value: unknown }[] = [];\r\n\r\n // Top-level scalars/objects that only apply when absent.\r\n for (const key of [\"openapi\", \"info\", \"servers\"]) {\r\n if (generated[key] !== undefined && doc.getIn([key]) === undefined) {\r\n additions.push({ path: [key], value: generated[key] });\r\n }\r\n }\r\n\r\n // Tags: append missing tag names.\r\n const generatedTags = (generated.tags ?? []) as { name: string }[];\r\n if (generatedTags.length > 0) {\r\n const existingTags = doc.toJS()?.tags as { name: string }[] | undefined;\r\n if (existingTags === undefined) {\r\n additions.push({ path: [\"tags\"], value: generatedTags });\r\n } else {\r\n const existingNames = new Set(existingTags.map((t) => t?.name));\r\n let index = existingTags.length;\r\n for (const tag of generatedTags) {\r\n if (!existingNames.has(tag.name)) {\r\n additions.push({ path: [\"tags\", index++], value: tag });\r\n }\r\n }\r\n }\r\n }\r\n\r\n for (const [section, subsection] of MERGED_SECTIONS) {\r\n const generatedSection = subsection\r\n ? ((generated[section] as Record<string, unknown> | undefined)?.[subsection] as\r\n | Record<string, unknown>\r\n | undefined)\r\n : (generated[section] as Record<string, unknown> | undefined);\r\n if (!generatedSection) continue;\r\n const basePath = subsection ? [section, subsection] : [section];\r\n\r\n for (const [key, value] of Object.entries(generatedSection)) {\r\n const existing = doc.getIn([...basePath, key], true);\r\n if (existing === undefined) {\r\n additions.push({ path: [...basePath, key], value });\r\n } else {\r\n const existingJs =\r\n typeof (existing as YAMLMap)?.toJS === \"function\"\r\n ? (existing as YAMLMap).toJS(doc)\r\n : existing;\r\n if (!deepEqual(existingJs, value)) {\r\n if (section === \"components\" && subsection === \"schemas\" && key === \"ResourceList\") {\r\n const union = unionResourceList(existingJs, value);\r\n if (union !== undefined) {\r\n if (!deepEqual(existingJs, union)) {\r\n additions.push({ path: [...basePath, key], value: union });\r\n }\r\n continue;\r\n }\r\n }\r\n conflicts.push({ location: [...basePath, key].join(\".\") });\r\n if (options.force) additions.push({ path: [...basePath, key], value });\r\n }\r\n }\r\n }\r\n }\r\n\r\n return { doc, conflicts, additions };\r\n}\r\n\r\n/**\r\n * Merges a generated OpenAPI document into existing YAML text, preserving the\r\n * existing file's comments, anchors, and key order. Generated entries are\r\n * added alongside existing content; an existing entry with different content\r\n * is a conflict (all conflicts are reported; nothing is written unless every\r\n * conflict is resolved by `force`). Identical entries are left untouched, so\r\n * re-running the generator is idempotent.\r\n */\r\nexport function mergeIntoYaml(\r\n generated: OpenApiDocument,\r\n existingText: string,\r\n options: MergeOptions = {},\r\n): string {\r\n const { doc, conflicts, additions } = computeMergePlan(generated, existingText, options);\r\n if (doc.contents === null) {\r\n // Empty file: treat as a fresh write.\r\n return stringifyDocument(generated);\r\n }\r\n if (conflicts.length > 0 && !options.force) {\r\n throw new MergeConflictError(conflicts);\r\n }\r\n for (const { path, value } of additions) {\r\n doc.setIn(path, doc.createNode(value));\r\n }\r\n return doc.toString({ lineWidth: 0 });\r\n}\r\n\r\nexport interface SpecDiff {\r\n /** Entries the file lacks (dot paths), e.g. \"components.schemas.Patient\". */\r\n missing: string[];\r\n /** Entries present in the file but differing from generation. */\r\n changed: string[];\r\n /** True when the file already contains exactly what generation produces. */\r\n inSync: boolean;\r\n}\r\n\r\n/**\r\n * Compares existing spec text against a generated document without writing\r\n * anything — the CI drift guard behind `fhir-oas check`. The file is in sync\r\n * when a merge would be a no-op: nothing to add, nothing conflicting.\r\n */\r\nexport function diffAgainstYaml(generated: OpenApiDocument, existingText: string): SpecDiff {\r\n const { doc, conflicts, additions } = computeMergePlan(generated, existingText, {});\r\n if (doc.contents === null) {\r\n return { missing: [\"(entire document: file is empty)\"], changed: [], inSync: false };\r\n }\r\n const missing = additions.map((a) => a.path.join(\".\"));\r\n const changed = conflicts.map((c) => c.location);\r\n return { missing, changed, inSync: missing.length === 0 && changed.length === 0 };\r\n}\r\n\r\n/** Serializes a generated document to YAML text. */\r\nexport function stringifyDocument(generated: OpenApiDocument): string {\r\n const doc = new Document(generated);\r\n return doc.toString({ lineWidth: 0 });\r\n}\r\n"],"mappings":"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","names":["fs","path","path","ref","FHIR_JSON","SCHEMAS","ref","fhirContent","errorResponses","fhirContent","errorResponses","searchParamCodes","fs","ref","path"]}
|
package/dist/cli.js
CHANGED
|
@@ -8,16 +8,36 @@ import {
|
|
|
8
8
|
loadCapabilityStatement,
|
|
9
9
|
loadIg,
|
|
10
10
|
mergeIntoYaml,
|
|
11
|
+
parseSearchParamSpec,
|
|
11
12
|
stringifyDocument
|
|
12
|
-
} from "./chunk-
|
|
13
|
+
} from "./chunk-RRAIF3A2.js";
|
|
13
14
|
|
|
14
15
|
// src/cli.ts
|
|
15
16
|
import { Command, Option } from "commander";
|
|
17
|
+
import fs2 from "fs";
|
|
18
|
+
|
|
19
|
+
// src/version.ts
|
|
16
20
|
import fs from "fs";
|
|
21
|
+
import path from "path";
|
|
22
|
+
import { fileURLToPath } from "url";
|
|
23
|
+
function packageVersion() {
|
|
24
|
+
let dir = path.dirname(fileURLToPath(import.meta.url));
|
|
25
|
+
for (let i = 0; i < 5; i++) {
|
|
26
|
+
const candidate = path.join(dir, "package.json");
|
|
27
|
+
if (fs.existsSync(candidate)) {
|
|
28
|
+
const parsed = JSON.parse(fs.readFileSync(candidate, "utf8"));
|
|
29
|
+
if (parsed.version) return parsed.version;
|
|
30
|
+
}
|
|
31
|
+
dir = path.dirname(dir);
|
|
32
|
+
}
|
|
33
|
+
return "unknown";
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
// src/cli.ts
|
|
17
37
|
var program = new Command();
|
|
18
38
|
program.name("fhir-oas").description(
|
|
19
39
|
"Generate OpenAPI specifications for HL7 FHIR resources, for model codegen in any language."
|
|
20
|
-
);
|
|
40
|
+
).version(packageVersion(), "-V, --version", "print the fhir-oas version");
|
|
21
41
|
var fhirVersionOption = () => new Option("-f, --fhir-version <version>", "FHIR version").choices(["r4", "r4b", "r5"]).makeOptionMandatory();
|
|
22
42
|
var sourceOption = () => new Option("-s, --source <backend>", "definition source backend").choices(["schema-json", "structure-def"]).default("schema-json");
|
|
23
43
|
function addGenerationOptions(command) {
|
|
@@ -40,6 +60,9 @@ function addGenerationOptions(command) {
|
|
|
40
60
|
).option(
|
|
41
61
|
"--profile <id...>",
|
|
42
62
|
"profile id, name, or canonical URL to apply to its base resource (requires --ig)"
|
|
63
|
+
).option(
|
|
64
|
+
"--search-params <spec...>",
|
|
65
|
+
"limit resource-specific search parameters: a preset (all, minimal, none) optionally tuned (minimal,+based-on / all,-note), an exact code list (code,date,subject), or per-resource (Patient:minimal,+goal)"
|
|
43
66
|
).option(
|
|
44
67
|
"--capability <source>",
|
|
45
68
|
"CapabilityStatement file or server base/metadata URL: emit only its declared surface"
|
|
@@ -72,6 +95,7 @@ async function toGenerateOptions(resources, opts) {
|
|
|
72
95
|
ig,
|
|
73
96
|
profiles: opts.profile,
|
|
74
97
|
capability,
|
|
98
|
+
searchParams: opts.searchParams ? parseSearchParamSpec(opts.searchParams) : void 0,
|
|
75
99
|
trim: {
|
|
76
100
|
excludeNarrative: opts.excludeNarrative,
|
|
77
101
|
maxDepth: opts.maxDepth,
|
|
@@ -93,15 +117,15 @@ addGenerationOptions(
|
|
|
93
117
|
}
|
|
94
118
|
const document = generateOpenApi(await toGenerateOptions(resources, opts));
|
|
95
119
|
if (opts.mergeInto) {
|
|
96
|
-
const existing =
|
|
120
|
+
const existing = fs2.existsSync(opts.mergeInto) ? fs2.readFileSync(opts.mergeInto, "utf8") : "";
|
|
97
121
|
const merged = mergeIntoYaml(document, existing, { force: opts.force });
|
|
98
|
-
|
|
122
|
+
fs2.writeFileSync(opts.mergeInto, merged);
|
|
99
123
|
console.error(`Merged into ${opts.mergeInto}`);
|
|
100
124
|
return;
|
|
101
125
|
}
|
|
102
126
|
const text = opts.format === "json" ? JSON.stringify(document, null, 2) + "\n" : stringifyDocument(document);
|
|
103
127
|
if (opts.output) {
|
|
104
|
-
|
|
128
|
+
fs2.writeFileSync(opts.output, text);
|
|
105
129
|
console.error(`Wrote ${opts.output}`);
|
|
106
130
|
} else {
|
|
107
131
|
process.stdout.write(text);
|
|
@@ -116,11 +140,11 @@ addGenerationOptions(
|
|
|
116
140
|
).argument("[resources...]", "FHIR resource names the spec should cover (optional with --capability)")
|
|
117
141
|
).requiredOption("--file <file>", "spec file (YAML or JSON) to check").action(async (resources, opts) => {
|
|
118
142
|
try {
|
|
119
|
-
if (!
|
|
143
|
+
if (!fs2.existsSync(opts.file)) {
|
|
120
144
|
throw new Error(`No such file: ${opts.file}`);
|
|
121
145
|
}
|
|
122
146
|
const document = generateOpenApi(await toGenerateOptions(resources, opts));
|
|
123
|
-
const diff = diffAgainstYaml(document,
|
|
147
|
+
const diff = diffAgainstYaml(document, fs2.readFileSync(opts.file, "utf8"));
|
|
124
148
|
if (diff.inSync) {
|
|
125
149
|
console.log(`${opts.file} is in sync`);
|
|
126
150
|
return;
|
package/dist/cli.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/cli.ts"],"sourcesContent":["#!/usr/bin/env node\r\nimport { Command, Option } from \"commander\";\r\nimport fs from \"node:fs\";\r\nimport { generateOpenApi, listResources } from \"./generate.js\";\r\nimport { loadCapabilityStatement, type Capability } from \"./capability.js\";\r\nimport { loadIg, type IgContext } from \"./ig/package.js\";\r\nimport { buildCoreValueSetFallback } from \"./ig/profile.js\";\r\nimport { diffAgainstYaml, MergeConflictError, mergeIntoYaml, stringifyDocument } from \"./merge.js\";\r\nimport type { FhirVersion, GenerateOptions, OpenApiVersion, SourceBackend } from \"./types.js\";\r\n\r\nconst program = new Command();\r\n\r\nprogram\r\n .name(\"fhir-oas\")\r\n .description(\r\n \"Generate OpenAPI specifications for HL7 FHIR resources, for model codegen in any language.\",\r\n );\r\n\r\nconst fhirVersionOption = () =>\r\n new Option(\"-f, --fhir-version <version>\", \"FHIR version\")\r\n .choices([\"r4\", \"r4b\", \"r5\"])\r\n .makeOptionMandatory();\r\n\r\nconst sourceOption = () =>\r\n new Option(\"-s, --source <backend>\", \"definition source backend\")\r\n .choices([\"schema-json\", \"structure-def\"])\r\n .default(\"schema-json\");\r\n\r\n/** Options that shape the generated document, shared by generate and check. */\r\nfunction addGenerationOptions(command: Command): Command {\r\n return command\r\n .addOption(fhirVersionOption())\r\n .addOption(\r\n new Option(\"--openapi-version <version>\", \"target OpenAPI version\")\r\n .choices([\"3.0\", \"3.0.3\", \"3.1\", \"3.1.0\"])\r\n .default(\"3.0.3\"),\r\n )\r\n .addOption(sourceOption())\r\n .option(\"--base-url <url>\", \"server base URL to embed in the spec\")\r\n .option(\"--title <title>\", \"override the generated info.title\")\r\n .option(\r\n \"--operations\",\r\n \"include the standard FHIR operations ($everything, $validate, ...) for the requested resources\",\r\n false,\r\n )\r\n .option(\"--exclude-narrative\", \"replace the Narrative type with a generic object\", false)\r\n .option(\r\n \"--no-enums\",\r\n \"replace required-binding enums with plain strings (codes noted in descriptions)\",\r\n )\r\n .option(\r\n \"--max-depth <n>\",\r\n \"stub schema definitions deeper than n hops from the requested resources\",\r\n (value) => Number.parseInt(value, 10),\r\n )\r\n .option(\r\n \"--ig <package>\",\r\n \"IG package to apply profiles from: a local .tgz/directory or a registry coordinate (name@version)\",\r\n )\r\n .option(\r\n \"--profile <id...>\",\r\n \"profile id, name, or canonical URL to apply to its base resource (requires --ig)\",\r\n )\r\n .option(\r\n \"--capability <source>\",\r\n \"CapabilityStatement file or server base/metadata URL: emit only its declared surface\",\r\n );\r\n}\r\n\r\ninterface SharedCliOptions {\r\n fhirVersion: string;\r\n openapiVersion: string;\r\n source: string;\r\n baseUrl?: string;\r\n title?: string;\r\n operations: boolean;\r\n excludeNarrative: boolean;\r\n /** commander maps --no-enums here: undefined/true = keep, false = strip. */\r\n enums?: boolean;\r\n maxDepth?: number;\r\n ig?: string;\r\n profile?: string[];\r\n capability?: string;\r\n}\r\n\r\n/**\r\n * Resolves the shared generation options, loading the IG package (async, so\r\n * registry coordinates work) when profiles are requested.\r\n */\r\nasync function toGenerateOptions(\r\n resources: string[],\r\n opts: SharedCliOptions,\r\n): Promise<GenerateOptions> {\r\n if (opts.maxDepth !== undefined && (!Number.isInteger(opts.maxDepth) || opts.maxDepth < 0)) {\r\n throw new Error(\"--max-depth must be a non-negative integer\");\r\n }\r\n const openApiVersion: OpenApiVersion = opts.openapiVersion.startsWith(\"3.1\")\r\n ? \"3.1.0\"\r\n : \"3.0.3\";\r\n const fhirVersion = opts.fhirVersion as FhirVersion;\r\n\r\n let ig: IgContext | undefined;\r\n if (opts.ig) {\r\n ig = await loadIg(opts.ig, { coreValueSetFallback: buildCoreValueSetFallback(fhirVersion) });\r\n } else if (opts.profile?.length) {\r\n throw new Error(\"--profile requires --ig: point at the IG package.\");\r\n }\r\n\r\n let capability: Capability | undefined;\r\n if (opts.capability) {\r\n capability = await loadCapabilityStatement(opts.capability);\r\n }\r\n\r\n return {\r\n resources,\r\n fhirVersion,\r\n openApiVersion,\r\n source: opts.source as SourceBackend,\r\n operations: opts.operations,\r\n baseUrl: opts.baseUrl,\r\n title: opts.title,\r\n ig,\r\n profiles: opts.profile,\r\n capability,\r\n trim: {\r\n excludeNarrative: opts.excludeNarrative,\r\n maxDepth: opts.maxDepth,\r\n noEnums: opts.enums === false,\r\n },\r\n };\r\n}\r\n\r\naddGenerationOptions(\r\n program\r\n .command(\"generate\")\r\n .description(\"Generate an OpenAPI spec for one or more FHIR resources\")\r\n .argument(\r\n \"[resources...]\",\r\n 'FHIR resource names, e.g. \"Patient Observation\" (optional with --capability)',\r\n ),\r\n)\r\n .option(\"-o, --output <file>\", \"write a new spec file (YAML unless --format json)\")\r\n .option(\"--merge-into <file>\", \"merge into an existing YAML spec file\")\r\n .option(\"--force\", \"overwrite conflicting entries when merging\", false)\r\n .addOption(\r\n new Option(\"--format <format>\", \"output format for --output/stdout\")\r\n .choices([\"yaml\", \"json\"])\r\n .default(\"yaml\"),\r\n )\r\n .action(async (resources: string[], opts) => {\r\n try {\r\n if (opts.output && opts.mergeInto) {\r\n throw new Error(\"Use either --output or --merge-into, not both\");\r\n }\r\n const document = generateOpenApi(await toGenerateOptions(resources, opts));\r\n\r\n if (opts.mergeInto) {\r\n const existing = fs.existsSync(opts.mergeInto)\r\n ? fs.readFileSync(opts.mergeInto, \"utf8\")\r\n : \"\";\r\n const merged = mergeIntoYaml(document, existing, { force: opts.force });\r\n fs.writeFileSync(opts.mergeInto, merged);\r\n console.error(`Merged into ${opts.mergeInto}`);\r\n return;\r\n }\r\n\r\n const text =\r\n opts.format === \"json\"\r\n ? JSON.stringify(document, null, 2) + \"\\n\"\r\n : stringifyDocument(document);\r\n if (opts.output) {\r\n fs.writeFileSync(opts.output, text);\r\n console.error(`Wrote ${opts.output}`);\r\n } else {\r\n process.stdout.write(text);\r\n }\r\n } catch (error) {\r\n fail(error);\r\n }\r\n });\r\n\r\naddGenerationOptions(\r\n program\r\n .command(\"check\")\r\n .description(\r\n \"Verify that a committed spec file is in sync with what generation would produce (CI drift guard)\",\r\n )\r\n .argument(\"[resources...]\", \"FHIR resource names the spec should cover (optional with --capability)\"),\r\n)\r\n .requiredOption(\"--file <file>\", \"spec file (YAML or JSON) to check\")\r\n .action(async (resources: string[], opts) => {\r\n try {\r\n if (!fs.existsSync(opts.file)) {\r\n throw new Error(`No such file: ${opts.file}`);\r\n }\r\n const document = generateOpenApi(await toGenerateOptions(resources, opts));\r\n const diff = diffAgainstYaml(document, fs.readFileSync(opts.file, \"utf8\"));\r\n if (diff.inSync) {\r\n console.log(`${opts.file} is in sync`);\r\n return;\r\n }\r\n console.error(`${opts.file} is out of sync with generation:`);\r\n for (const location of diff.missing) console.error(` missing: ${location}`);\r\n for (const location of diff.changed) console.error(` changed: ${location}`);\r\n const modeFlags =\r\n (opts.capability ? ` --capability ${opts.capability}` : \"\") +\r\n (opts.ig ? ` --ig ${opts.ig}` : \"\") +\r\n (opts.profile?.length ? ` --profile ${opts.profile.join(\" \")}` : \"\") +\r\n (opts.operations ? \" --operations\" : \"\");\r\n console.error(\r\n `Regenerate with: fhir-oas generate ${resources.join(\" \")} --fhir-version ${opts.fhirVersion}${modeFlags} --merge-into ${opts.file}` +\r\n (diff.changed.length > 0 ? \" --force\" : \"\"),\r\n );\r\n process.exit(1);\r\n } catch (error) {\r\n fail(error);\r\n }\r\n });\r\n\r\nprogram\r\n .command(\"list\")\r\n .description(\"List the FHIR resource types for a version, or the profiles in an IG package\")\r\n .addOption(\r\n new Option(\"-f, --fhir-version <version>\", \"FHIR version (required unless --ig is given)\").choices(\r\n [\"r4\", \"r4b\", \"r5\"],\r\n ),\r\n )\r\n .addOption(sourceOption())\r\n .option(\"--ig <package>\", \"list the profiles in an IG package instead of core resources\")\r\n .action(async (opts) => {\r\n try {\r\n if (opts.ig) {\r\n const ig = await loadIg(opts.ig);\r\n for (const profile of ig.profiles) {\r\n console.log(`${profile.id ?? profile.name}\\t${profile.type}\\t${profile.url}`);\r\n }\r\n return;\r\n }\r\n if (!opts.fhirVersion) throw new Error(\"--fhir-version is required (or pass --ig to list profiles)\");\r\n for (const name of listResources(opts.fhirVersion as FhirVersion, opts.source)) {\r\n console.log(name);\r\n }\r\n } catch (error) {\r\n fail(error);\r\n }\r\n });\r\n\r\nfunction fail(error: unknown): never {\r\n if (error instanceof MergeConflictError) {\r\n console.error(error.message);\r\n } else {\r\n console.error(`error: ${error instanceof Error ? error.message : String(error)}`);\r\n }\r\n process.exit(1);\r\n}\r\n\r\nprogram.parseAsync();\r\n"],"mappings":"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","names":[]}
|
|
1
|
+
{"version":3,"sources":["../src/cli.ts","../src/version.ts"],"sourcesContent":["#!/usr/bin/env node\r\nimport { Command, Option } from \"commander\";\r\nimport fs from \"node:fs\";\r\nimport { generateOpenApi, listResources } from \"./generate.js\";\r\nimport { parseSearchParamSpec } from \"./searchParams.js\";\r\nimport { packageVersion } from \"./version.js\";\r\nimport { loadCapabilityStatement, type Capability } from \"./capability.js\";\r\nimport { loadIg, type IgContext } from \"./ig/package.js\";\r\nimport { buildCoreValueSetFallback } from \"./ig/profile.js\";\r\nimport { diffAgainstYaml, MergeConflictError, mergeIntoYaml, stringifyDocument } from \"./merge.js\";\r\nimport type { FhirVersion, GenerateOptions, OpenApiVersion, SourceBackend } from \"./types.js\";\r\n\r\nconst program = new Command();\r\n\r\nprogram\r\n .name(\"fhir-oas\")\r\n .description(\r\n \"Generate OpenAPI specifications for HL7 FHIR resources, for model codegen in any language.\",\r\n )\r\n .version(packageVersion(), \"-V, --version\", \"print the fhir-oas version\");\r\n\r\nconst fhirVersionOption = () =>\r\n new Option(\"-f, --fhir-version <version>\", \"FHIR version\")\r\n .choices([\"r4\", \"r4b\", \"r5\"])\r\n .makeOptionMandatory();\r\n\r\nconst sourceOption = () =>\r\n new Option(\"-s, --source <backend>\", \"definition source backend\")\r\n .choices([\"schema-json\", \"structure-def\"])\r\n .default(\"schema-json\");\r\n\r\n/** Options that shape the generated document, shared by generate and check. */\r\nfunction addGenerationOptions(command: Command): Command {\r\n return command\r\n .addOption(fhirVersionOption())\r\n .addOption(\r\n new Option(\"--openapi-version <version>\", \"target OpenAPI version\")\r\n .choices([\"3.0\", \"3.0.3\", \"3.1\", \"3.1.0\"])\r\n .default(\"3.0.3\"),\r\n )\r\n .addOption(sourceOption())\r\n .option(\"--base-url <url>\", \"server base URL to embed in the spec\")\r\n .option(\"--title <title>\", \"override the generated info.title\")\r\n .option(\r\n \"--operations\",\r\n \"include the standard FHIR operations ($everything, $validate, ...) for the requested resources\",\r\n false,\r\n )\r\n .option(\"--exclude-narrative\", \"replace the Narrative type with a generic object\", false)\r\n .option(\r\n \"--no-enums\",\r\n \"replace required-binding enums with plain strings (codes noted in descriptions)\",\r\n )\r\n .option(\r\n \"--max-depth <n>\",\r\n \"stub schema definitions deeper than n hops from the requested resources\",\r\n (value) => Number.parseInt(value, 10),\r\n )\r\n .option(\r\n \"--ig <package>\",\r\n \"IG package to apply profiles from: a local .tgz/directory or a registry coordinate (name@version)\",\r\n )\r\n .option(\r\n \"--profile <id...>\",\r\n \"profile id, name, or canonical URL to apply to its base resource (requires --ig)\",\r\n )\r\n .option(\r\n \"--search-params <spec...>\",\r\n \"limit resource-specific search parameters: a preset (all, minimal, none) \" +\r\n \"optionally tuned (minimal,+based-on / all,-note), an exact code list \" +\r\n \"(code,date,subject), or per-resource (Patient:minimal,+goal)\",\r\n )\r\n .option(\r\n \"--capability <source>\",\r\n \"CapabilityStatement file or server base/metadata URL: emit only its declared surface\",\r\n );\r\n}\r\n\r\ninterface SharedCliOptions {\r\n fhirVersion: string;\r\n openapiVersion: string;\r\n source: string;\r\n baseUrl?: string;\r\n title?: string;\r\n operations: boolean;\r\n excludeNarrative: boolean;\r\n /** commander maps --no-enums here: undefined/true = keep, false = strip. */\r\n enums?: boolean;\r\n maxDepth?: number;\r\n ig?: string;\r\n profile?: string[];\r\n capability?: string;\r\n searchParams?: string[];\r\n}\r\n\r\n/**\r\n * Resolves the shared generation options, loading the IG package (async, so\r\n * registry coordinates work) when profiles are requested.\r\n */\r\nasync function toGenerateOptions(\r\n resources: string[],\r\n opts: SharedCliOptions,\r\n): Promise<GenerateOptions> {\r\n if (opts.maxDepth !== undefined && (!Number.isInteger(opts.maxDepth) || opts.maxDepth < 0)) {\r\n throw new Error(\"--max-depth must be a non-negative integer\");\r\n }\r\n const openApiVersion: OpenApiVersion = opts.openapiVersion.startsWith(\"3.1\")\r\n ? \"3.1.0\"\r\n : \"3.0.3\";\r\n const fhirVersion = opts.fhirVersion as FhirVersion;\r\n\r\n let ig: IgContext | undefined;\r\n if (opts.ig) {\r\n ig = await loadIg(opts.ig, { coreValueSetFallback: buildCoreValueSetFallback(fhirVersion) });\r\n } else if (opts.profile?.length) {\r\n throw new Error(\"--profile requires --ig: point at the IG package.\");\r\n }\r\n\r\n let capability: Capability | undefined;\r\n if (opts.capability) {\r\n capability = await loadCapabilityStatement(opts.capability);\r\n }\r\n\r\n return {\r\n resources,\r\n fhirVersion,\r\n openApiVersion,\r\n source: opts.source as SourceBackend,\r\n operations: opts.operations,\r\n baseUrl: opts.baseUrl,\r\n title: opts.title,\r\n ig,\r\n profiles: opts.profile,\r\n capability,\r\n searchParams: opts.searchParams ? parseSearchParamSpec(opts.searchParams) : undefined,\r\n trim: {\r\n excludeNarrative: opts.excludeNarrative,\r\n maxDepth: opts.maxDepth,\r\n noEnums: opts.enums === false,\r\n },\r\n };\r\n}\r\n\r\naddGenerationOptions(\r\n program\r\n .command(\"generate\")\r\n .description(\"Generate an OpenAPI spec for one or more FHIR resources\")\r\n .argument(\r\n \"[resources...]\",\r\n 'FHIR resource names, e.g. \"Patient Observation\" (optional with --capability)',\r\n ),\r\n)\r\n .option(\"-o, --output <file>\", \"write a new spec file (YAML unless --format json)\")\r\n .option(\"--merge-into <file>\", \"merge into an existing YAML spec file\")\r\n .option(\"--force\", \"overwrite conflicting entries when merging\", false)\r\n .addOption(\r\n new Option(\"--format <format>\", \"output format for --output/stdout\")\r\n .choices([\"yaml\", \"json\"])\r\n .default(\"yaml\"),\r\n )\r\n .action(async (resources: string[], opts) => {\r\n try {\r\n if (opts.output && opts.mergeInto) {\r\n throw new Error(\"Use either --output or --merge-into, not both\");\r\n }\r\n const document = generateOpenApi(await toGenerateOptions(resources, opts));\r\n\r\n if (opts.mergeInto) {\r\n const existing = fs.existsSync(opts.mergeInto)\r\n ? fs.readFileSync(opts.mergeInto, \"utf8\")\r\n : \"\";\r\n const merged = mergeIntoYaml(document, existing, { force: opts.force });\r\n fs.writeFileSync(opts.mergeInto, merged);\r\n console.error(`Merged into ${opts.mergeInto}`);\r\n return;\r\n }\r\n\r\n const text =\r\n opts.format === \"json\"\r\n ? JSON.stringify(document, null, 2) + \"\\n\"\r\n : stringifyDocument(document);\r\n if (opts.output) {\r\n fs.writeFileSync(opts.output, text);\r\n console.error(`Wrote ${opts.output}`);\r\n } else {\r\n process.stdout.write(text);\r\n }\r\n } catch (error) {\r\n fail(error);\r\n }\r\n });\r\n\r\naddGenerationOptions(\r\n program\r\n .command(\"check\")\r\n .description(\r\n \"Verify that a committed spec file is in sync with what generation would produce (CI drift guard)\",\r\n )\r\n .argument(\"[resources...]\", \"FHIR resource names the spec should cover (optional with --capability)\"),\r\n)\r\n .requiredOption(\"--file <file>\", \"spec file (YAML or JSON) to check\")\r\n .action(async (resources: string[], opts) => {\r\n try {\r\n if (!fs.existsSync(opts.file)) {\r\n throw new Error(`No such file: ${opts.file}`);\r\n }\r\n const document = generateOpenApi(await toGenerateOptions(resources, opts));\r\n const diff = diffAgainstYaml(document, fs.readFileSync(opts.file, \"utf8\"));\r\n if (diff.inSync) {\r\n console.log(`${opts.file} is in sync`);\r\n return;\r\n }\r\n console.error(`${opts.file} is out of sync with generation:`);\r\n for (const location of diff.missing) console.error(` missing: ${location}`);\r\n for (const location of diff.changed) console.error(` changed: ${location}`);\r\n const modeFlags =\r\n (opts.capability ? ` --capability ${opts.capability}` : \"\") +\r\n (opts.ig ? ` --ig ${opts.ig}` : \"\") +\r\n (opts.profile?.length ? ` --profile ${opts.profile.join(\" \")}` : \"\") +\r\n (opts.operations ? \" --operations\" : \"\");\r\n console.error(\r\n `Regenerate with: fhir-oas generate ${resources.join(\" \")} --fhir-version ${opts.fhirVersion}${modeFlags} --merge-into ${opts.file}` +\r\n (diff.changed.length > 0 ? \" --force\" : \"\"),\r\n );\r\n process.exit(1);\r\n } catch (error) {\r\n fail(error);\r\n }\r\n });\r\n\r\nprogram\r\n .command(\"list\")\r\n .description(\"List the FHIR resource types for a version, or the profiles in an IG package\")\r\n .addOption(\r\n new Option(\"-f, --fhir-version <version>\", \"FHIR version (required unless --ig is given)\").choices(\r\n [\"r4\", \"r4b\", \"r5\"],\r\n ),\r\n )\r\n .addOption(sourceOption())\r\n .option(\"--ig <package>\", \"list the profiles in an IG package instead of core resources\")\r\n .action(async (opts) => {\r\n try {\r\n if (opts.ig) {\r\n const ig = await loadIg(opts.ig);\r\n for (const profile of ig.profiles) {\r\n console.log(`${profile.id ?? profile.name}\\t${profile.type}\\t${profile.url}`);\r\n }\r\n return;\r\n }\r\n if (!opts.fhirVersion) throw new Error(\"--fhir-version is required (or pass --ig to list profiles)\");\r\n for (const name of listResources(opts.fhirVersion as FhirVersion, opts.source)) {\r\n console.log(name);\r\n }\r\n } catch (error) {\r\n fail(error);\r\n }\r\n });\r\n\r\nfunction fail(error: unknown): never {\r\n if (error instanceof MergeConflictError) {\r\n console.error(error.message);\r\n } else {\r\n console.error(`error: ${error instanceof Error ? error.message : String(error)}`);\r\n }\r\n process.exit(1);\r\n}\r\n\r\nprogram.parseAsync();\r\n","import fs from \"node:fs\";\r\nimport path from \"node:path\";\r\nimport { fileURLToPath } from \"node:url\";\r\n\r\n/**\r\n * The package's own version, read from its package.json.\r\n *\r\n * Resolved at runtime rather than inlined at build time so the CLI cannot\r\n * report a version that disagrees with the installed package.json. The file\r\n * sits at the package root, next to `src/` when running from source and next\r\n * to `dist/` when published, so walking up from this module finds it in both\r\n * layouts — the same approach `definitionsRoot()` uses for `definitions/`.\r\n */\r\nexport function packageVersion(): string {\r\n let dir = path.dirname(fileURLToPath(import.meta.url));\r\n for (let i = 0; i < 5; i++) {\r\n const candidate = path.join(dir, \"package.json\");\r\n if (fs.existsSync(candidate)) {\r\n const parsed = JSON.parse(fs.readFileSync(candidate, \"utf8\")) as { version?: string };\r\n if (parsed.version) return parsed.version;\r\n }\r\n dir = path.dirname(dir);\r\n }\r\n // Better to report an honest unknown than to invent a number.\r\n return \"unknown\";\r\n}\r\n"],"mappings":"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","names":["fs","fs"]}
|
package/dist/index.d.ts
CHANGED
|
@@ -32,6 +32,34 @@ interface IgContextLike {
|
|
|
32
32
|
profilesMissingSnapshot: string[];
|
|
33
33
|
resolveValueSet: (valueSetUrl: string) => string[] | undefined;
|
|
34
34
|
}
|
|
35
|
+
/** Preset selections accepted by `--search-params`. */
|
|
36
|
+
type SearchParamPreset = "all" | "minimal" | "none";
|
|
37
|
+
/**
|
|
38
|
+
* One resource's selection: a starting set, then adjustments.
|
|
39
|
+
*
|
|
40
|
+
* No fixed rule can encode which parameters matter for a given resource —
|
|
41
|
+
* `Observation.based-on`, `CarePlan.goal` and `MedicationStatement.adherence`
|
|
42
|
+
* are all central to their resource and none is common enough to curate
|
|
43
|
+
* globally. So a preset is a starting point that `add`/`remove` tune, rather
|
|
44
|
+
* than a take-it-or-leave-it list.
|
|
45
|
+
*/
|
|
46
|
+
interface SearchParamRule {
|
|
47
|
+
/** A preset, or an explicit list replacing it entirely. */
|
|
48
|
+
base: SearchParamPreset | ReadonlySet<string>;
|
|
49
|
+
/** Codes to add to the base. */
|
|
50
|
+
add?: ReadonlySet<string>;
|
|
51
|
+
/** Codes to drop from the base. */
|
|
52
|
+
remove?: ReadonlySet<string>;
|
|
53
|
+
}
|
|
54
|
+
/**
|
|
55
|
+
* Which resource-specific search parameters to emit. A `default` applies to
|
|
56
|
+
* every resource; `byResource` overrides it per resource. The common result
|
|
57
|
+
* parameters (`_id`, `_count`, ...) are always emitted regardless.
|
|
58
|
+
*/
|
|
59
|
+
interface SearchParamSelection {
|
|
60
|
+
default?: SearchParamRule;
|
|
61
|
+
byResource?: ReadonlyMap<string, SearchParamRule>;
|
|
62
|
+
}
|
|
35
63
|
/** A parsed CapabilityStatement (see capability.ts). */
|
|
36
64
|
interface CapabilityLike {
|
|
37
65
|
fhirVersion?: string;
|
|
@@ -82,6 +110,14 @@ interface GenerateOptions {
|
|
|
82
110
|
/** Override the generated `info.title`. */
|
|
83
111
|
title?: string;
|
|
84
112
|
trim?: TrimOptions;
|
|
113
|
+
/**
|
|
114
|
+
* Restrict which resource-specific search parameters are emitted. Servers
|
|
115
|
+
* commonly index only a subset, and every indexed parameter costs storage
|
|
116
|
+
* and write throughput; this keeps the published contract matched to what a
|
|
117
|
+
* deployment actually supports. Combined with `capability`, the two narrow
|
|
118
|
+
* each other (the intersection is emitted).
|
|
119
|
+
*/
|
|
120
|
+
searchParams?: SearchParamSelection;
|
|
85
121
|
}
|
|
86
122
|
/** A generated OpenAPI document (3.0.3 or 3.1.0) as a plain object. */
|
|
87
123
|
type OpenApiDocument = {
|