@atomic-ehr/codegen 0.0.1-canary.20251106145509.e3b1f82 → 0.0.1-canary.20251107091824.7605d36
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/dist/cli/index.js +23 -23
- package/dist/index.d.ts +62 -13
- package/dist/index.js +260 -255
- package/dist/index.js.map +1 -1
- package/package.json +2 -1
package/dist/index.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import * as fs from 'fs';
|
|
2
2
|
import fs__default, { existsSync, mkdirSync } from 'fs';
|
|
3
|
-
import * as
|
|
3
|
+
import * as afs3 from 'fs/promises';
|
|
4
4
|
import { readdir, stat, unlink, readFile, writeFile, access, mkdir, rm } from 'fs/promises';
|
|
5
5
|
import * as Path4 from 'path';
|
|
6
6
|
import Path4__default, { join, resolve, dirname, relative } from 'path';
|
|
@@ -8,6 +8,7 @@ import { CanonicalManager } from '@atomic-ehr/fhir-canonical-manager';
|
|
|
8
8
|
import * as fhirschema from '@atomic-ehr/fhirschema';
|
|
9
9
|
import { isStructureDefinition } from '@atomic-ehr/fhirschema';
|
|
10
10
|
import pc from 'picocolors';
|
|
11
|
+
import * as YAML from 'yaml';
|
|
11
12
|
|
|
12
13
|
var __defProp = Object.defineProperty;
|
|
13
14
|
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
@@ -1397,7 +1398,24 @@ var init_IndexBuilder = __esm({
|
|
|
1397
1398
|
});
|
|
1398
1399
|
|
|
1399
1400
|
// src/typeschema/types.ts
|
|
1401
|
+
var extractNameFromCanonical = (canonical, dropFragment = true) => {
|
|
1402
|
+
let localName = canonical.split("/").pop();
|
|
1403
|
+
if (!localName) return void 0;
|
|
1404
|
+
if (dropFragment && localName.includes("#")) {
|
|
1405
|
+
localName = localName.split("#")[0];
|
|
1406
|
+
}
|
|
1407
|
+
if (!localName) return void 0;
|
|
1408
|
+
if (/^\d/.test(localName)) {
|
|
1409
|
+
localName = `number_${localName}`;
|
|
1410
|
+
}
|
|
1411
|
+
return localName;
|
|
1412
|
+
};
|
|
1400
1413
|
var packageMetaToFhir = (packageMeta) => `${packageMeta.name}#${packageMeta.version}`;
|
|
1414
|
+
var npmToPackageMeta = (fhir) => {
|
|
1415
|
+
const [name, version] = fhir.split("@");
|
|
1416
|
+
if (!name) throw new Error(`Invalid FHIR package meta: ${fhir}`);
|
|
1417
|
+
return { name, version: version ?? "latest" };
|
|
1418
|
+
};
|
|
1401
1419
|
var packageMetaToNpm = (packageMeta) => `${packageMeta.name}@${packageMeta.version}`;
|
|
1402
1420
|
var enrichFHIRSchema = (schema, packageMeta) => {
|
|
1403
1421
|
if (!packageMeta) {
|
|
@@ -1447,10 +1465,10 @@ var isChoiceDeclarationField = (field) => {
|
|
|
1447
1465
|
return field.choices !== void 0;
|
|
1448
1466
|
};
|
|
1449
1467
|
var isValueSet = (res) => {
|
|
1450
|
-
return res
|
|
1468
|
+
return res?.resourceType === "ValueSet";
|
|
1451
1469
|
};
|
|
1452
1470
|
var isCodeSystem = (res) => {
|
|
1453
|
-
return res
|
|
1471
|
+
return res?.resourceType === "CodeSystem";
|
|
1454
1472
|
};
|
|
1455
1473
|
var enrichValueSet = (vs, packageMeta) => {
|
|
1456
1474
|
if (!vs.url) throw new Error("ValueSet must have a URL");
|
|
@@ -1587,12 +1605,15 @@ function mkNestedTypes(register, fhirSchema, logger) {
|
|
|
1587
1605
|
} else {
|
|
1588
1606
|
baseName = element.type;
|
|
1589
1607
|
}
|
|
1608
|
+
const baseUrl = register.ensureSpecializationCanonicalUrl(baseName);
|
|
1609
|
+
const baseFs = register.resolveFs(fhirSchema.package_meta, baseUrl);
|
|
1610
|
+
if (!baseFs) throw new Error(`Could not resolve base type ${baseName}`);
|
|
1590
1611
|
const base = {
|
|
1591
1612
|
kind: "complex-type",
|
|
1592
|
-
package:
|
|
1593
|
-
version:
|
|
1613
|
+
package: baseFs.package_meta.name,
|
|
1614
|
+
version: baseFs.package_meta.version,
|
|
1594
1615
|
name: baseName,
|
|
1595
|
-
url:
|
|
1616
|
+
url: baseUrl
|
|
1596
1617
|
};
|
|
1597
1618
|
const fields = transformNestedElements(register, fhirSchema, path, element.elements, logger);
|
|
1598
1619
|
const nestedType = {
|
|
@@ -1656,8 +1677,9 @@ function isExcluded(register, fhirSchema, path) {
|
|
|
1656
1677
|
var buildReferences = (register, fhirSchema, element) => {
|
|
1657
1678
|
if (!element.refers) return void 0;
|
|
1658
1679
|
return element.refers.map((ref) => {
|
|
1659
|
-
const curl = register.ensureSpecializationCanonicalUrl(
|
|
1680
|
+
const curl = register.ensureSpecializationCanonicalUrl(ref);
|
|
1660
1681
|
const fs4 = register.resolveFs(fhirSchema.package_meta, curl);
|
|
1682
|
+
if (!fs4) throw new Error(`Failed to resolve fs for ${curl}`);
|
|
1661
1683
|
return mkIdentifier(fs4);
|
|
1662
1684
|
});
|
|
1663
1685
|
};
|
|
@@ -1666,9 +1688,12 @@ function buildFieldType(register, fhirSchema, path, element, logger) {
|
|
|
1666
1688
|
const refPath = element.elementReference.slice(1).filter((_, i) => i % 2 === 1);
|
|
1667
1689
|
return mkNestedIdentifier(register, fhirSchema, refPath, logger);
|
|
1668
1690
|
} else if (element.type) {
|
|
1669
|
-
const url = register.ensureSpecializationCanonicalUrl(
|
|
1691
|
+
const url = register.ensureSpecializationCanonicalUrl(element.type);
|
|
1670
1692
|
const fieldFs = register.resolveFs(fhirSchema.package_meta, url);
|
|
1671
|
-
if (!fieldFs)
|
|
1693
|
+
if (!fieldFs)
|
|
1694
|
+
throw new Error(
|
|
1695
|
+
`Could not resolve field type: '${element.type}' (from '${fhirSchema.url}' in '${packageMetaToFhir(fhirSchema.package_meta)}')`
|
|
1696
|
+
);
|
|
1672
1697
|
return mkIdentifier(fieldFs);
|
|
1673
1698
|
} else if (element.choices) {
|
|
1674
1699
|
return void 0;
|
|
@@ -1690,8 +1715,10 @@ var mkField = (register, fhirSchema, path, element, logger) => {
|
|
|
1690
1715
|
enumValues = buildEnum(register, fhirSchema, element, logger);
|
|
1691
1716
|
}
|
|
1692
1717
|
}
|
|
1718
|
+
const fieldType = buildFieldType(register, fhirSchema, path, element, logger);
|
|
1719
|
+
if (!fieldType) logger?.warn(`Field type not found for ${path.join(".")}`);
|
|
1693
1720
|
return {
|
|
1694
|
-
type:
|
|
1721
|
+
type: fieldType,
|
|
1695
1722
|
required: isRequired(register, fhirSchema, path),
|
|
1696
1723
|
excluded: isExcluded(register, fhirSchema, path),
|
|
1697
1724
|
reference: buildReferences(register, fhirSchema, element),
|
|
@@ -1711,8 +1738,9 @@ function isNestedElement(element) {
|
|
|
1711
1738
|
return isBackbone || isElement || elementsWithoutType;
|
|
1712
1739
|
}
|
|
1713
1740
|
function mkNestedField(register, fhirSchema, path, element, logger) {
|
|
1741
|
+
const nestedIdentifier = mkNestedIdentifier(register, fhirSchema, path, logger);
|
|
1714
1742
|
return {
|
|
1715
|
-
type:
|
|
1743
|
+
type: nestedIdentifier,
|
|
1716
1744
|
array: element.array || false,
|
|
1717
1745
|
required: isRequired(register, fhirSchema, path),
|
|
1718
1746
|
excluded: isExcluded(register, fhirSchema, path)
|
|
@@ -1868,19 +1896,6 @@ function extractFieldDependencies(fields) {
|
|
|
1868
1896
|
}
|
|
1869
1897
|
return deps;
|
|
1870
1898
|
}
|
|
1871
|
-
function deduplicateDependencies(deps) {
|
|
1872
|
-
const seen = /* @__PURE__ */ new Set();
|
|
1873
|
-
const unique = [];
|
|
1874
|
-
for (const dep of deps) {
|
|
1875
|
-
const key = dep.url;
|
|
1876
|
-
if (!seen.has(key)) {
|
|
1877
|
-
seen.add(key);
|
|
1878
|
-
unique.push(dep);
|
|
1879
|
-
}
|
|
1880
|
-
}
|
|
1881
|
-
unique.sort((a, b) => a.name.localeCompare(b.name));
|
|
1882
|
-
return unique;
|
|
1883
|
-
}
|
|
1884
1899
|
function isExtensionSchema(fhirSchema, _identifier) {
|
|
1885
1900
|
if (fhirSchema.base === "Extension" || fhirSchema.base === "http://hl7.org/fhir/StructureDefinition/Extension") {
|
|
1886
1901
|
return true;
|
|
@@ -1907,62 +1922,6 @@ async function transformValueSet(register, valueSet, logger) {
|
|
|
1907
1922
|
compose: !concept ? valueSet.compose : void 0
|
|
1908
1923
|
};
|
|
1909
1924
|
}
|
|
1910
|
-
async function transformExtension(fhirSchema, register, logger) {
|
|
1911
|
-
try {
|
|
1912
|
-
const identifier = mkIdentifier(fhirSchema);
|
|
1913
|
-
let base;
|
|
1914
|
-
if (fhirSchema.base && fhirSchema.base !== "Extension") {
|
|
1915
|
-
const baseUrl = fhirSchema.base.includes("/") ? fhirSchema.base : `http://hl7.org/fhir/StructureDefinition/${fhirSchema.base}`;
|
|
1916
|
-
const baseName = fhirSchema.base.split("/").pop() || fhirSchema.base;
|
|
1917
|
-
base = {
|
|
1918
|
-
kind: "complex-type",
|
|
1919
|
-
package: "hl7.fhir.r4.core",
|
|
1920
|
-
version: "4.0.1",
|
|
1921
|
-
name: baseName,
|
|
1922
|
-
url: baseUrl
|
|
1923
|
-
};
|
|
1924
|
-
} else {
|
|
1925
|
-
base = {
|
|
1926
|
-
kind: "complex-type",
|
|
1927
|
-
package: "hl7.fhir.r4.core",
|
|
1928
|
-
version: "4.0.1",
|
|
1929
|
-
name: "Extension",
|
|
1930
|
-
url: "http://hl7.org/fhir/StructureDefinition/Extension"
|
|
1931
|
-
};
|
|
1932
|
-
}
|
|
1933
|
-
const extensionSchema = {
|
|
1934
|
-
identifier,
|
|
1935
|
-
base,
|
|
1936
|
-
description: fhirSchema.description,
|
|
1937
|
-
dependencies: [],
|
|
1938
|
-
metadata: {
|
|
1939
|
-
isExtension: true
|
|
1940
|
-
// Mark as extension for file organization
|
|
1941
|
-
}
|
|
1942
|
-
};
|
|
1943
|
-
if (base) {
|
|
1944
|
-
extensionSchema.dependencies.push(base);
|
|
1945
|
-
}
|
|
1946
|
-
if (fhirSchema.elements) {
|
|
1947
|
-
const fields = mkFields(register, fhirSchema, [], fhirSchema.elements, logger);
|
|
1948
|
-
if (fields && Object.keys(fields).length > 0) {
|
|
1949
|
-
extensionSchema.fields = fields;
|
|
1950
|
-
extensionSchema.dependencies.push(...extractFieldDependencies(fields));
|
|
1951
|
-
}
|
|
1952
|
-
}
|
|
1953
|
-
const nestedTypes = mkNestedTypes(register, fhirSchema, logger);
|
|
1954
|
-
if (nestedTypes && nestedTypes.length > 0) {
|
|
1955
|
-
extensionSchema.nested = nestedTypes;
|
|
1956
|
-
extensionSchema.dependencies.push(...extractNestedDependencies(nestedTypes));
|
|
1957
|
-
}
|
|
1958
|
-
extensionSchema.dependencies = deduplicateDependencies(extensionSchema.dependencies);
|
|
1959
|
-
extensionSchema.dependencies = extensionSchema.dependencies.filter((dep) => dep.url !== identifier.url);
|
|
1960
|
-
return extensionSchema;
|
|
1961
|
-
} catch (error) {
|
|
1962
|
-
console.warn(`Failed to transform extension ${fhirSchema.name}: ${error}`);
|
|
1963
|
-
return null;
|
|
1964
|
-
}
|
|
1965
|
-
}
|
|
1966
1925
|
function extractDependencies(identifier, base, fields, nestedTypes) {
|
|
1967
1926
|
const deps = [];
|
|
1968
1927
|
if (base) deps.push(base);
|
|
@@ -1987,10 +1946,12 @@ function transformFhirSchemaResource(register, fhirSchema, logger) {
|
|
|
1987
1946
|
if (fhirSchema.base && fhirSchema.type !== "Element") {
|
|
1988
1947
|
const baseFs = register.resolveFs(
|
|
1989
1948
|
fhirSchema.package_meta,
|
|
1990
|
-
register.ensureSpecializationCanonicalUrl(fhirSchema.
|
|
1949
|
+
register.ensureSpecializationCanonicalUrl(fhirSchema.base)
|
|
1991
1950
|
);
|
|
1992
1951
|
if (!baseFs) {
|
|
1993
|
-
throw new Error(
|
|
1952
|
+
throw new Error(
|
|
1953
|
+
`Base resource not found '${fhirSchema.base}' for <${fhirSchema.url}> from ${packageMetaToFhir(fhirSchema.package_meta)}`
|
|
1954
|
+
);
|
|
1994
1955
|
}
|
|
1995
1956
|
base = mkIdentifier(baseFs);
|
|
1996
1957
|
}
|
|
@@ -2009,16 +1970,16 @@ function transformFhirSchemaResource(register, fhirSchema, logger) {
|
|
|
2009
1970
|
return [typeSchema, ...bindingSchemas];
|
|
2010
1971
|
}
|
|
2011
1972
|
async function transformFhirSchema(register, fhirSchema, logger) {
|
|
2012
|
-
const
|
|
2013
|
-
mkIdentifier(fhirSchema)
|
|
2014
|
-
|
|
2015
|
-
|
|
2016
|
-
|
|
2017
|
-
|
|
2018
|
-
|
|
2019
|
-
|
|
1973
|
+
const schemas = transformFhirSchemaResource(register, fhirSchema, logger);
|
|
1974
|
+
if (isExtensionSchema(fhirSchema, mkIdentifier(fhirSchema))) {
|
|
1975
|
+
const schema = schemas[0];
|
|
1976
|
+
if (!schema) throw new Error(`Expected schema to be defined`);
|
|
1977
|
+
schema.metadata = {
|
|
1978
|
+
isExtension: true
|
|
1979
|
+
// Mark as extension for file organization
|
|
1980
|
+
};
|
|
2020
1981
|
}
|
|
2021
|
-
return
|
|
1982
|
+
return schemas;
|
|
2022
1983
|
}
|
|
2023
1984
|
var TypeSchemaCache = class {
|
|
2024
1985
|
cache = /* @__PURE__ */ new Map();
|
|
@@ -2362,7 +2323,7 @@ function createLogger(options = {}) {
|
|
|
2362
2323
|
}
|
|
2363
2324
|
var readPackageJSON = async (workDir, packageMeta) => {
|
|
2364
2325
|
const packageJSONFileName = Path4.join(workDir, "node_modules", packageMeta.name, "package.json");
|
|
2365
|
-
const packageJSON = JSON.parse(await
|
|
2326
|
+
const packageJSON = JSON.parse(await afs3.readFile(packageJSONFileName, "utf8"));
|
|
2366
2327
|
return packageJSON;
|
|
2367
2328
|
};
|
|
2368
2329
|
var readPackageDependencies = async (workDir, packageMeta) => {
|
|
@@ -2376,69 +2337,50 @@ var readPackageDependencies = async (workDir, packageMeta) => {
|
|
|
2376
2337
|
return [];
|
|
2377
2338
|
};
|
|
2378
2339
|
var mkEmptyPkgIndex = (pkg) => {
|
|
2379
|
-
return {
|
|
2340
|
+
return {
|
|
2341
|
+
pkg,
|
|
2342
|
+
canonicalResolution: {},
|
|
2343
|
+
fhirSchemas: {},
|
|
2344
|
+
valueSets: {}
|
|
2345
|
+
};
|
|
2380
2346
|
};
|
|
2381
|
-
var mkPackageAwareResolver = async (manager, pkg, deep
|
|
2382
|
-
const options = {};
|
|
2383
|
-
const deps = await readPackageDependencies("tmp/fhir", pkg);
|
|
2384
|
-
for (const dep of deps) {
|
|
2385
|
-
const depOptions = mkPackageAwareResolver(manager, dep, deep);
|
|
2386
|
-
Object.assign(options, depOptions);
|
|
2387
|
-
}
|
|
2347
|
+
var mkPackageAwareResolver = async (manager, pkg, deep, acc, logger) => {
|
|
2388
2348
|
const pkgId = packageMetaToFhir(pkg);
|
|
2389
|
-
|
|
2349
|
+
logger?.info(`${" ".repeat(deep * 2)}+ ${pkgId}`);
|
|
2350
|
+
if (acc[pkgId]) return acc[pkgId];
|
|
2351
|
+
const index = mkEmptyPkgIndex(pkg);
|
|
2390
2352
|
for (const resource of await manager.search({ package: pkg })) {
|
|
2391
2353
|
const rawUrl = resource.url;
|
|
2392
2354
|
if (!rawUrl) continue;
|
|
2393
2355
|
if (!(isStructureDefinition(resource) || isValueSet(resource) || isCodeSystem(resource))) continue;
|
|
2394
2356
|
const url = rawUrl;
|
|
2395
|
-
if (
|
|
2396
|
-
|
|
2397
|
-
|
|
2398
|
-
|
|
2399
|
-
|
|
2400
|
-
|
|
2401
|
-
|
|
2402
|
-
|
|
2403
|
-
|
|
2404
|
-
packageMeta: deepRes.packageMeta
|
|
2405
|
-
});
|
|
2406
|
-
}
|
|
2407
|
-
}
|
|
2408
|
-
}
|
|
2409
|
-
options[pkgId].canonicalResolution[url].push({ deep, packageMeta: pkg, resource });
|
|
2410
|
-
options[pkgId].canonicalResolution[url].sort((a, b) => a.deep - b.deep);
|
|
2411
|
-
const name = resource.name;
|
|
2412
|
-
if (name && isStructureDefinition(resource) && (resource.derivation === "specialization" || resource.derivation === void 0)) {
|
|
2413
|
-
if (!options[pkgId].nameResolution[name]) {
|
|
2414
|
-
options[pkgId].nameResolution[name] = resource.url;
|
|
2415
|
-
} else {
|
|
2416
|
-
throw new Error(`Duplicate name ${name} in package ${pkgId}`);
|
|
2417
|
-
}
|
|
2357
|
+
if (index.canonicalResolution[url]) logger?.dry_warn(`Duplicate canonical URL: ${url} at ${pkgId}.`);
|
|
2358
|
+
index.canonicalResolution[url] = [{ deep, pkg, pkgId, resource }];
|
|
2359
|
+
}
|
|
2360
|
+
const deps = await readPackageDependencies("tmp/fhir", pkg);
|
|
2361
|
+
for (const depPkg of deps) {
|
|
2362
|
+
const { canonicalResolution } = await mkPackageAwareResolver(manager, depPkg, deep + 1, acc, logger);
|
|
2363
|
+
for (const [surl, resolutions] of Object.entries(canonicalResolution)) {
|
|
2364
|
+
const url = surl;
|
|
2365
|
+
index.canonicalResolution[url] = [...index.canonicalResolution[url] || [], ...resolutions];
|
|
2418
2366
|
}
|
|
2419
2367
|
}
|
|
2420
|
-
|
|
2421
|
-
|
|
2422
|
-
|
|
2423
|
-
|
|
2424
|
-
|
|
2425
|
-
const resource = resolver[pkgId].nameResolution[name];
|
|
2426
|
-
return resource;
|
|
2368
|
+
for (const resolutionOptions of Object.values(index.canonicalResolution)) {
|
|
2369
|
+
resolutionOptions.sort((a, b) => a.deep - b.deep);
|
|
2370
|
+
}
|
|
2371
|
+
acc[pkgId] = index;
|
|
2372
|
+
return index;
|
|
2427
2373
|
};
|
|
2428
|
-
var packageAgnosticResolveCanonical = (resolver, url,
|
|
2374
|
+
var packageAgnosticResolveCanonical = (resolver, url, _logger) => {
|
|
2429
2375
|
const options = Object.values(resolver).flatMap((pkg) => pkg.canonicalResolution[url]);
|
|
2430
2376
|
if (!options) throw new Error(`No canonical resolution found for ${url} in any package`);
|
|
2431
|
-
if (options.length > 1)
|
|
2432
|
-
logger?.dry_warn(
|
|
2433
|
-
`Multiple canonical resolutions found for ${url} in: ${JSON.stringify(options, void 0, 2)}`
|
|
2434
|
-
);
|
|
2435
2377
|
return options[0]?.resource;
|
|
2436
2378
|
};
|
|
2437
|
-
var registerFromManager = async (manager, { logger, fallbackPackageForNameResolution }) => {
|
|
2438
|
-
const packages = await manager.packages();
|
|
2379
|
+
var registerFromManager = async (manager, { logger, fallbackPackageForNameResolution, focusedPackages }) => {
|
|
2380
|
+
const packages = focusedPackages ?? await manager.packages();
|
|
2439
2381
|
const resolver = {};
|
|
2440
2382
|
for (const pkg of packages) {
|
|
2441
|
-
|
|
2383
|
+
await mkPackageAwareResolver(manager, pkg, 0, resolver, logger);
|
|
2442
2384
|
}
|
|
2443
2385
|
for (const { pkg, canonicalResolution } of Object.values(resolver)) {
|
|
2444
2386
|
const pkgId = packageMetaToFhir(pkg);
|
|
@@ -2446,19 +2388,21 @@ var registerFromManager = async (manager, { logger, fallbackPackageForNameResolu
|
|
|
2446
2388
|
let counter = 0;
|
|
2447
2389
|
logger?.info(`FHIR Schema conversion for '${packageMetaToFhir(pkg)}' begins...`);
|
|
2448
2390
|
for (const [_url, options] of Object.entries(canonicalResolution)) {
|
|
2449
|
-
const
|
|
2450
|
-
if (!
|
|
2391
|
+
const resolition = options[0];
|
|
2392
|
+
if (!resolition) throw new Error(`Resource not found`);
|
|
2393
|
+
const resource = resolition.resource;
|
|
2394
|
+
const resourcePkg = resolition.pkg;
|
|
2451
2395
|
if (isStructureDefinition(resource)) {
|
|
2452
|
-
const rfs = enrichFHIRSchema(fhirschema.translate(resource),
|
|
2396
|
+
const rfs = enrichFHIRSchema(fhirschema.translate(resource), resourcePkg);
|
|
2453
2397
|
counter++;
|
|
2454
2398
|
resolver[pkgId].fhirSchemas[rfs.url] = rfs;
|
|
2455
2399
|
}
|
|
2456
2400
|
if (isValueSet(resource)) {
|
|
2457
|
-
const rvs = enrichValueSet(resource,
|
|
2401
|
+
const rvs = enrichValueSet(resource, resourcePkg);
|
|
2458
2402
|
resolver[pkgId].valueSets[rvs.url] = rvs;
|
|
2459
2403
|
}
|
|
2460
2404
|
}
|
|
2461
|
-
logger?.
|
|
2405
|
+
logger?.info(`FHIR Schema conversion for '${packageMetaToFhir(pkg)}' completed: ${counter} successful`);
|
|
2462
2406
|
}
|
|
2463
2407
|
const resolveFs = (pkg, canonicalUrl) => {
|
|
2464
2408
|
return resolver[packageMetaToFhir(pkg)]?.fhirSchemas[canonicalUrl] || fallbackPackageForNameResolution && resolver[packageMetaToFhir(fallbackPackageForNameResolution)]?.fhirSchemas[canonicalUrl];
|
|
@@ -2466,14 +2410,19 @@ var registerFromManager = async (manager, { logger, fallbackPackageForNameResolu
|
|
|
2466
2410
|
const resolveVs = (pkg, canonicalUrl) => {
|
|
2467
2411
|
return resolver[packageMetaToFhir(pkg)]?.valueSets[canonicalUrl] || fallbackPackageForNameResolution && resolver[packageMetaToFhir(fallbackPackageForNameResolution)]?.valueSets[canonicalUrl];
|
|
2468
2412
|
};
|
|
2469
|
-
const ensureSpecializationCanonicalUrl = (
|
|
2413
|
+
const ensureSpecializationCanonicalUrl = (name) => name.match(/^[a-zA-Z0-9]+$/) && `http://hl7.org/fhir/StructureDefinition/${name}` || name;
|
|
2470
2414
|
const resolveFsGenealogy = (pkg, canonicalUrl) => {
|
|
2471
2415
|
let fs4 = resolveFs(pkg, canonicalUrl);
|
|
2472
|
-
if (fs4 === void 0) throw new Error(`Failed to resolve FHIR Schema
|
|
2416
|
+
if (fs4 === void 0) throw new Error(`Failed to resolve FHIR Schema: '${canonicalUrl}'`);
|
|
2473
2417
|
const genealogy = [fs4];
|
|
2474
2418
|
while (fs4?.base) {
|
|
2475
|
-
|
|
2476
|
-
|
|
2419
|
+
const pkg2 = fs4.package_meta;
|
|
2420
|
+
const baseUrl = ensureSpecializationCanonicalUrl(fs4.base);
|
|
2421
|
+
fs4 = resolveFs(pkg2, baseUrl);
|
|
2422
|
+
if (fs4 === void 0)
|
|
2423
|
+
throw new Error(
|
|
2424
|
+
`Failed to resolve FHIR Schema base for '${canonicalUrl}'. Problem: '${baseUrl}' from '${packageMetaToFhir(pkg2)}'`
|
|
2425
|
+
);
|
|
2477
2426
|
genealogy.push(fs4);
|
|
2478
2427
|
}
|
|
2479
2428
|
return genealogy;
|
|
@@ -2501,11 +2450,10 @@ var registerFromManager = async (manager, { logger, fallbackPackageForNameResolu
|
|
|
2501
2450
|
};
|
|
2502
2451
|
return {
|
|
2503
2452
|
...manager,
|
|
2504
|
-
|
|
2453
|
+
testAppendFs(fs4) {
|
|
2505
2454
|
const rfs = enrichFHIRSchema(fs4);
|
|
2506
2455
|
const pkgId = packageMetaToFhir(rfs.package_meta);
|
|
2507
2456
|
if (!resolver[pkgId]) resolver[pkgId] = mkEmptyPkgIndex(rfs.package_meta);
|
|
2508
|
-
resolver[pkgId].nameResolution[rfs.name] = rfs.url;
|
|
2509
2457
|
resolver[pkgId].fhirSchemas[rfs.url] = rfs;
|
|
2510
2458
|
},
|
|
2511
2459
|
resolveFs,
|
|
@@ -2513,16 +2461,17 @@ var registerFromManager = async (manager, { logger, fallbackPackageForNameResolu
|
|
|
2513
2461
|
resolveFsSpecializations,
|
|
2514
2462
|
ensureSpecializationCanonicalUrl,
|
|
2515
2463
|
resolveSd: (_pkg, canonicalUrl) => {
|
|
2516
|
-
const res = packageAgnosticResolveCanonical(resolver, canonicalUrl
|
|
2464
|
+
const res = packageAgnosticResolveCanonical(resolver, canonicalUrl);
|
|
2517
2465
|
if (isStructureDefinition(res)) return res;
|
|
2518
2466
|
return void 0;
|
|
2519
2467
|
},
|
|
2520
2468
|
allFs: () => Object.values(resolver).flatMap((pkgIndex) => Object.values(pkgIndex.fhirSchemas)),
|
|
2521
2469
|
allVs: () => Object.values(resolver).flatMap((pkgIndex) => Object.values(pkgIndex.valueSets)),
|
|
2522
2470
|
resolveVs,
|
|
2523
|
-
resolveAny: (canonicalUrl) => packageAgnosticResolveCanonical(resolver, canonicalUrl
|
|
2471
|
+
resolveAny: (canonicalUrl) => packageAgnosticResolveCanonical(resolver, canonicalUrl),
|
|
2524
2472
|
resolveElementSnapshot,
|
|
2525
|
-
getAllElementKeys
|
|
2473
|
+
getAllElementKeys,
|
|
2474
|
+
resolver
|
|
2526
2475
|
};
|
|
2527
2476
|
};
|
|
2528
2477
|
var resolveFsElementGenealogy = (genealogy, path) => {
|
|
@@ -2567,10 +2516,10 @@ var TypeSchemaGenerator = class {
|
|
|
2567
2516
|
}
|
|
2568
2517
|
}
|
|
2569
2518
|
async registerFromPackageMetas(packageMetas) {
|
|
2570
|
-
const packageNames = packageMetas.map(
|
|
2519
|
+
const packageNames = packageMetas.map(packageMetaToFhir);
|
|
2571
2520
|
this.logger?.step(`Loading FHIR packages: ${packageNames.join(", ")}`);
|
|
2572
2521
|
await this.manager.init();
|
|
2573
|
-
return registerFromManager(this.manager, {});
|
|
2522
|
+
return registerFromManager(this.manager, { focusedPackages: packageMetas });
|
|
2574
2523
|
}
|
|
2575
2524
|
generateFhirSchemas(structureDefinitions) {
|
|
2576
2525
|
this.logger?.progress(`Converting ${structureDefinitions.length} StructureDefinitions to FHIRSchemas`);
|
|
@@ -3013,9 +2962,29 @@ var TypeSchemaParser = class {
|
|
|
3013
2962
|
};
|
|
3014
2963
|
|
|
3015
2964
|
// src/typeschema/index.ts
|
|
2965
|
+
var codeableReferenceInR4 = "Use CodeableReference which is not provided by FHIR R4.";
|
|
2966
|
+
var availabilityInR4 = "Use Availability which is not provided by FHIR R4.";
|
|
2967
|
+
var skipMe = {
|
|
2968
|
+
"hl7.fhir.uv.extensions.r4#1.0.0": {
|
|
2969
|
+
"http://hl7.org/fhir/StructureDefinition/extended-contact-availability": availabilityInR4,
|
|
2970
|
+
"http://hl7.org/fhir/StructureDefinition/immunization-procedure": codeableReferenceInR4,
|
|
2971
|
+
"http://hl7.org/fhir/StructureDefinition/specimen-additive": codeableReferenceInR4,
|
|
2972
|
+
"http://hl7.org/fhir/StructureDefinition/workflow-barrier": codeableReferenceInR4,
|
|
2973
|
+
"http://hl7.org/fhir/StructureDefinition/workflow-protectiveFactor": codeableReferenceInR4,
|
|
2974
|
+
"http://hl7.org/fhir/StructureDefinition/workflow-reason": codeableReferenceInR4
|
|
2975
|
+
},
|
|
2976
|
+
"hl7.fhir.r5.core#5.0.0": {
|
|
2977
|
+
"http://hl7.org/fhir/StructureDefinition/shareablecodesystem": "FIXME: CodeSystem.concept.concept defined by ElementReference. FHIR Schema generator output broken value in it, so we just skip it for now."
|
|
2978
|
+
}
|
|
2979
|
+
};
|
|
3016
2980
|
var generateTypeSchemas = async (register, logger) => {
|
|
3017
2981
|
const fhirSchemas = [];
|
|
3018
2982
|
for (const fhirSchema of register.allFs()) {
|
|
2983
|
+
const pkgId = packageMetaToFhir(fhirSchema.package_meta);
|
|
2984
|
+
if (skipMe[pkgId]?.[fhirSchema.url]) {
|
|
2985
|
+
logger?.dry_warn(`Skip ${fhirSchema.url} from ${pkgId}. Reason: ${skipMe[pkgId]?.[fhirSchema.url]}`);
|
|
2986
|
+
continue;
|
|
2987
|
+
}
|
|
3019
2988
|
fhirSchemas.push(...await transformFhirSchema(register, fhirSchema, logger));
|
|
3020
2989
|
}
|
|
3021
2990
|
for (const vsSchema of register.allVs()) {
|
|
@@ -3050,23 +3019,9 @@ var uppercaseFirstLetter = (str) => {
|
|
|
3050
3019
|
var uppercaseFirstLetterOfEach = (strings) => {
|
|
3051
3020
|
return strings.map((str) => uppercaseFirstLetter(str));
|
|
3052
3021
|
};
|
|
3053
|
-
|
|
3054
|
-
|
|
3055
|
-
|
|
3056
|
-
return false;
|
|
3057
|
-
}
|
|
3058
|
-
if (Array.isArray(obj1) && Array.isArray(obj2)) {
|
|
3059
|
-
if (obj1.length !== obj2.length) return false;
|
|
3060
|
-
return obj1.every((item, index) => deepEqual(item, obj2[index]));
|
|
3061
|
-
}
|
|
3062
|
-
if (Array.isArray(obj1) || Array.isArray(obj2)) {
|
|
3063
|
-
return false;
|
|
3064
|
-
}
|
|
3065
|
-
const keys1 = Object.keys(obj1);
|
|
3066
|
-
const keys2 = Object.keys(obj2);
|
|
3067
|
-
if (keys1.length !== keys2.length) return false;
|
|
3068
|
-
return keys1.every((key) => keys2.includes(key) && deepEqual(obj1[key], obj2[key]));
|
|
3069
|
-
}
|
|
3022
|
+
var typeSchemaInfo = (schema) => {
|
|
3023
|
+
return `<${schema.identifier.url}> from ${schema.identifier.package}#${schema.identifier.version}`;
|
|
3024
|
+
};
|
|
3070
3025
|
var FileSystemWriter = class {
|
|
3071
3026
|
opts;
|
|
3072
3027
|
currentDir;
|
|
@@ -3080,12 +3035,14 @@ var FileSystemWriter = class {
|
|
|
3080
3035
|
return this.opts.logger;
|
|
3081
3036
|
}
|
|
3082
3037
|
cd(path, gen) {
|
|
3038
|
+
const prev = this.currentDir;
|
|
3083
3039
|
this.currentDir = path.startsWith("/") ? Path4.join(this.opts.outputDir, path) : Path4.join(this.currentDir, path);
|
|
3084
3040
|
if (!fs.existsSync(this.currentDir)) {
|
|
3085
3041
|
fs.mkdirSync(this.currentDir, { recursive: true });
|
|
3086
3042
|
}
|
|
3087
3043
|
this.logger()?.debug(`cd '${this.currentDir}'`);
|
|
3088
3044
|
gen();
|
|
3045
|
+
this.currentDir = prev;
|
|
3089
3046
|
}
|
|
3090
3047
|
cat(fn, gen) {
|
|
3091
3048
|
if (this.currentFileDescriptor) throw new Error("Can't open file in file");
|
|
@@ -3098,6 +3055,7 @@ var FileSystemWriter = class {
|
|
|
3098
3055
|
gen();
|
|
3099
3056
|
} finally {
|
|
3100
3057
|
if (this.currentFileDescriptor) {
|
|
3058
|
+
fs.fsyncSync(this.currentFileDescriptor);
|
|
3101
3059
|
fs.closeSync(this.currentFileDescriptor);
|
|
3102
3060
|
}
|
|
3103
3061
|
this.currentFileDescriptor = void 0;
|
|
@@ -3512,19 +3470,21 @@ var CSharp = class extends Writer {
|
|
|
3512
3470
|
fs__default.copyFileSync(sourceFile, destFile);
|
|
3513
3471
|
}
|
|
3514
3472
|
};
|
|
3515
|
-
|
|
3516
|
-
// src/typeschema/utils.ts
|
|
3517
3473
|
var groupByPackages = (typeSchemas) => {
|
|
3518
3474
|
const grouped = {};
|
|
3519
3475
|
for (const ts of typeSchemas) {
|
|
3520
|
-
const
|
|
3521
|
-
if (!grouped[
|
|
3522
|
-
|
|
3523
|
-
}
|
|
3524
|
-
grouped[packageName].push(ts);
|
|
3476
|
+
const pkgName = ts.identifier.package;
|
|
3477
|
+
if (!grouped[pkgName]) grouped[pkgName] = [];
|
|
3478
|
+
grouped[pkgName].push(ts);
|
|
3525
3479
|
}
|
|
3526
|
-
for (const [
|
|
3527
|
-
|
|
3480
|
+
for (const [packageName, typeSchemas2] of Object.entries(grouped)) {
|
|
3481
|
+
const dict = {};
|
|
3482
|
+
for (const ts of typeSchemas2) {
|
|
3483
|
+
dict[JSON.stringify(ts.identifier)] = ts;
|
|
3484
|
+
}
|
|
3485
|
+
const tmp = Object.values(dict);
|
|
3486
|
+
tmp.sort((a, b) => a.identifier.name.localeCompare(b.identifier.name));
|
|
3487
|
+
grouped[packageName] = tmp;
|
|
3528
3488
|
}
|
|
3529
3489
|
return grouped;
|
|
3530
3490
|
};
|
|
@@ -3564,7 +3524,8 @@ var mkTypeSchemaIndex = (schemas, logger) => {
|
|
|
3564
3524
|
if (index[url][schema.identifier.package] && pkg !== "shared") {
|
|
3565
3525
|
const r1 = JSON.stringify(schema.identifier, void 0, 2);
|
|
3566
3526
|
const r2 = JSON.stringify(index[url][pkg]?.identifier, void 0, 2);
|
|
3567
|
-
throw new Error(`Duplicate schema: ${r1} and ${r2}`);
|
|
3527
|
+
if (r1 !== r2) throw new Error(`Duplicate schema: ${r1} and ${r2}`);
|
|
3528
|
+
return;
|
|
3568
3529
|
}
|
|
3569
3530
|
index[url][pkg] = schema;
|
|
3570
3531
|
};
|
|
@@ -3622,7 +3583,10 @@ var mkTypeSchemaIndex = (schemas, logger) => {
|
|
|
3622
3583
|
if (!schema2.fields) continue;
|
|
3623
3584
|
for (const [fieldName, fieldConstraints] of Object.entries(schema2.fields)) {
|
|
3624
3585
|
if (mergedFields[fieldName]) {
|
|
3625
|
-
mergedFields[fieldName] = {
|
|
3586
|
+
mergedFields[fieldName] = {
|
|
3587
|
+
...mergedFields[fieldName],
|
|
3588
|
+
...fieldConstraints
|
|
3589
|
+
};
|
|
3626
3590
|
} else {
|
|
3627
3591
|
mergedFields[fieldName] = { ...fieldConstraints };
|
|
3628
3592
|
}
|
|
@@ -3647,6 +3611,26 @@ var mkTypeSchemaIndex = (schemas, logger) => {
|
|
|
3647
3611
|
return schema.fields?.meta !== void 0;
|
|
3648
3612
|
});
|
|
3649
3613
|
};
|
|
3614
|
+
const exportTree = async (filename) => {
|
|
3615
|
+
const tree = {};
|
|
3616
|
+
for (const [pkgId, shemas] of Object.entries(groupByPackages(schemas))) {
|
|
3617
|
+
tree[pkgId] = { complexTypes: {}, resources: {}, profiles: {} };
|
|
3618
|
+
for (const schema of shemas) {
|
|
3619
|
+
schema.identifier;
|
|
3620
|
+
if (isResourceTypeSchema(schema)) {
|
|
3621
|
+
tree[pkgId].resources[schema.identifier.url] = {};
|
|
3622
|
+
}
|
|
3623
|
+
if (isProfileTypeSchema(schema)) {
|
|
3624
|
+
tree[pkgId].profiles[schema.identifier.url] = {};
|
|
3625
|
+
}
|
|
3626
|
+
if (isComplexTypeTypeSchema(schema)) {
|
|
3627
|
+
tree[pkgId].complexTypes[schema.identifier.url] = {};
|
|
3628
|
+
}
|
|
3629
|
+
}
|
|
3630
|
+
}
|
|
3631
|
+
const raw = filename.endsWith(".yaml") ? YAML.stringify(tree) : JSON.stringify(tree, void 0, 2);
|
|
3632
|
+
await afs3.writeFile(filename, raw);
|
|
3633
|
+
};
|
|
3650
3634
|
return {
|
|
3651
3635
|
_schemaIndex: index,
|
|
3652
3636
|
_relations: relations,
|
|
@@ -3661,7 +3645,8 @@ var mkTypeSchemaIndex = (schemas, logger) => {
|
|
|
3661
3645
|
findLastSpecialization,
|
|
3662
3646
|
findLastSpecializationByIdentifier,
|
|
3663
3647
|
flatProfile,
|
|
3664
|
-
isWithMetaField
|
|
3648
|
+
isWithMetaField,
|
|
3649
|
+
exportTree
|
|
3665
3650
|
};
|
|
3666
3651
|
};
|
|
3667
3652
|
|
|
@@ -4179,7 +4164,7 @@ var BaseGenerator = class {
|
|
|
4179
4164
|
* This is the main method that orchestrates the entire generation process
|
|
4180
4165
|
* @param schemas - Array of TypeSchema documents
|
|
4181
4166
|
*/
|
|
4182
|
-
async generate(schemas) {
|
|
4167
|
+
async generate({ schemas }) {
|
|
4183
4168
|
return this.errorBoundary.withErrorBoundary(
|
|
4184
4169
|
async () => {
|
|
4185
4170
|
this.generationStartTime = performance.now();
|
|
@@ -4219,7 +4204,7 @@ var BaseGenerator = class {
|
|
|
4219
4204
|
return result;
|
|
4220
4205
|
};
|
|
4221
4206
|
try {
|
|
4222
|
-
const result = await this.generate(schemas);
|
|
4207
|
+
const result = await this.generate({ schemas, index: null });
|
|
4223
4208
|
result.forEach((file) => {
|
|
4224
4209
|
const mockResult = mockWriteResults.get(file.filename);
|
|
4225
4210
|
if (mockResult) {
|
|
@@ -5527,10 +5512,10 @@ ${nestedInterfaces}`;
|
|
|
5527
5512
|
/**
|
|
5528
5513
|
* Override generate to clean directory first
|
|
5529
5514
|
*/
|
|
5530
|
-
async generate(
|
|
5515
|
+
async generate(input) {
|
|
5531
5516
|
await this.fileManager.cleanDirectory();
|
|
5532
5517
|
this.logger.debug("Cleaned output directory before generation");
|
|
5533
|
-
return super.generate(
|
|
5518
|
+
return super.generate(input);
|
|
5534
5519
|
}
|
|
5535
5520
|
/**
|
|
5536
5521
|
* Run post-generation hooks - generate utility files
|
|
@@ -5730,15 +5715,8 @@ var tsModuleFileName = (id) => {
|
|
|
5730
5715
|
};
|
|
5731
5716
|
var canonicalToName2 = (canonical, dropFragment = true) => {
|
|
5732
5717
|
if (!canonical) return void 0;
|
|
5733
|
-
|
|
5718
|
+
const localName = extractNameFromCanonical(canonical, dropFragment);
|
|
5734
5719
|
if (!localName) return void 0;
|
|
5735
|
-
if (dropFragment && localName.includes("#")) {
|
|
5736
|
-
localName = localName.split("#")[0];
|
|
5737
|
-
}
|
|
5738
|
-
if (!localName) return void 0;
|
|
5739
|
-
if (/^\d/.test(localName)) {
|
|
5740
|
-
localName = `number_${localName}`;
|
|
5741
|
-
}
|
|
5742
5720
|
return normalizeTsName(localName);
|
|
5743
5721
|
};
|
|
5744
5722
|
var tsResourceName = (id) => {
|
|
@@ -5794,12 +5772,14 @@ var TypeScript = class extends Writer {
|
|
|
5794
5772
|
if (["complex-type", "resource", "logical"].includes(dep.kind)) {
|
|
5795
5773
|
imports.push({
|
|
5796
5774
|
tsPackage: `../${kebabCase(dep.package)}/${pascalCase(dep.name)}`,
|
|
5797
|
-
name: uppercaseFirstLetter(dep.name)
|
|
5775
|
+
name: uppercaseFirstLetter(dep.name),
|
|
5776
|
+
dep
|
|
5798
5777
|
});
|
|
5799
5778
|
} else if (isNestedIdentifier(dep)) {
|
|
5800
5779
|
imports.push({
|
|
5801
5780
|
tsPackage: `../${kebabCase(dep.package)}/${pascalCase(canonicalToName2(dep.url) ?? "")}`,
|
|
5802
|
-
name: tsResourceName(dep)
|
|
5781
|
+
name: tsResourceName(dep),
|
|
5782
|
+
dep
|
|
5803
5783
|
});
|
|
5804
5784
|
} else {
|
|
5805
5785
|
skipped.push(dep);
|
|
@@ -5807,6 +5787,7 @@ var TypeScript = class extends Writer {
|
|
|
5807
5787
|
}
|
|
5808
5788
|
imports.sort((a, b) => a.name.localeCompare(b.name));
|
|
5809
5789
|
for (const dep of imports) {
|
|
5790
|
+
this.debugComment(dep.dep);
|
|
5810
5791
|
this.tsImportType(dep.tsPackage, dep.name);
|
|
5811
5792
|
}
|
|
5812
5793
|
for (const dep of skipped) {
|
|
@@ -5849,7 +5830,9 @@ var TypeScript = class extends Writer {
|
|
|
5849
5830
|
if (isResourceTypeSchema(schema)) {
|
|
5850
5831
|
const possibleResourceTypes = [schema.identifier];
|
|
5851
5832
|
possibleResourceTypes.push(...tsIndex.resourceChildren(schema.identifier));
|
|
5852
|
-
this.lineSM(
|
|
5833
|
+
this.lineSM(
|
|
5834
|
+
`resourceType: ${possibleResourceTypes.sort((a, b) => a.name.localeCompare(b.name)).map((e) => `"${e.name}"`).join(" | ")}`
|
|
5835
|
+
);
|
|
5853
5836
|
this.line();
|
|
5854
5837
|
}
|
|
5855
5838
|
if (!schema.fields) return;
|
|
@@ -5891,6 +5874,7 @@ var TypeScript = class extends Writer {
|
|
|
5891
5874
|
}
|
|
5892
5875
|
}
|
|
5893
5876
|
generateProfileType(tsIndex, flatProfile) {
|
|
5877
|
+
this.debugComment("flatProfile", flatProfile);
|
|
5894
5878
|
const tsName = tsResourceName(flatProfile.identifier);
|
|
5895
5879
|
this.debugComment("identifier", flatProfile.identifier);
|
|
5896
5880
|
this.debugComment("base", flatProfile.base);
|
|
@@ -5928,6 +5912,8 @@ var TypeScript = class extends Writer {
|
|
|
5928
5912
|
tsType = tsResourceName(field.type);
|
|
5929
5913
|
} else if (isPrimitiveIdentifier(field.type)) {
|
|
5930
5914
|
tsType = resolvePrimitiveType(field.type.name);
|
|
5915
|
+
} else if (field.type === void 0) {
|
|
5916
|
+
throw new Error(`Undefined type for '${fieldName}' field at ${typeSchemaInfo(flatProfile)}`);
|
|
5931
5917
|
} else {
|
|
5932
5918
|
tsType = field.type.name;
|
|
5933
5919
|
}
|
|
@@ -6093,17 +6079,20 @@ var writerToGenerator = (writerGen) => {
|
|
|
6093
6079
|
});
|
|
6094
6080
|
};
|
|
6095
6081
|
return {
|
|
6096
|
-
generate: async (
|
|
6097
|
-
const tsIndex = mkTypeSchemaIndex(schemas);
|
|
6082
|
+
generate: async ({ index: tsIndex }) => {
|
|
6098
6083
|
writerGen.generate(tsIndex);
|
|
6099
6084
|
return getGeneratedFiles();
|
|
6100
6085
|
},
|
|
6101
6086
|
setOutputDir: (outputDir) => writerGen.opts.outputDir = outputDir,
|
|
6102
|
-
build: async (
|
|
6087
|
+
build: async (_input) => getGeneratedFiles()
|
|
6103
6088
|
};
|
|
6104
6089
|
};
|
|
6105
|
-
var normalizeFileName = (str) =>
|
|
6106
|
-
|
|
6090
|
+
var normalizeFileName = (str) => {
|
|
6091
|
+
const res = str.replace(/[^a-zA-Z0-9\-_.@#()]/g, "");
|
|
6092
|
+
if (res.length === 0) return "unknown";
|
|
6093
|
+
return res;
|
|
6094
|
+
};
|
|
6095
|
+
var APIBuilder = class {
|
|
6107
6096
|
schemas = [];
|
|
6108
6097
|
options;
|
|
6109
6098
|
generators = /* @__PURE__ */ new Map();
|
|
@@ -6124,7 +6113,8 @@ var APIBuilder = class _APIBuilder {
|
|
|
6124
6113
|
typeSchemaConfig: options.typeSchemaConfig,
|
|
6125
6114
|
manager: options.manager || null,
|
|
6126
6115
|
throwException: options.throwException || false,
|
|
6127
|
-
typeSchemaOutputDir: options.typeSchemaOutputDir
|
|
6116
|
+
typeSchemaOutputDir: options.typeSchemaOutputDir,
|
|
6117
|
+
exportTypeTree: options.exportTypeTree
|
|
6128
6118
|
};
|
|
6129
6119
|
this.typeSchemaConfig = options.typeSchemaConfig;
|
|
6130
6120
|
this.logger = options.logger || createLogger({
|
|
@@ -6139,24 +6129,18 @@ var APIBuilder = class _APIBuilder {
|
|
|
6139
6129
|
this.packages.push(packageMetaToNpm({ name: packageName, version: version || "latest" }));
|
|
6140
6130
|
return this;
|
|
6141
6131
|
}
|
|
6142
|
-
/**
|
|
6143
|
-
* Load TypeSchema from files
|
|
6144
|
-
*/
|
|
6145
6132
|
fromFiles(...filePaths) {
|
|
6146
6133
|
this.logger.debug(`Loading from ${filePaths.length} TypeSchema files`);
|
|
6147
6134
|
const operation = this.loadFromFiles(filePaths);
|
|
6148
6135
|
this.pendingOperations.push(operation);
|
|
6149
6136
|
return this;
|
|
6150
6137
|
}
|
|
6151
|
-
/**
|
|
6152
|
-
* Load TypeSchema from TypeSchema objects
|
|
6153
|
-
*/
|
|
6154
6138
|
fromSchemas(schemas) {
|
|
6155
6139
|
this.logger.debug(`Adding ${schemas.length} TypeSchemas to generation`);
|
|
6156
6140
|
this.schemas = [...this.schemas, ...schemas];
|
|
6157
6141
|
return this;
|
|
6158
6142
|
}
|
|
6159
|
-
|
|
6143
|
+
typescriptDepricated(options = {}) {
|
|
6160
6144
|
const typesOutputDir = `${this.options.outputDir}/types`;
|
|
6161
6145
|
const generator = new TypeScriptGenerator({
|
|
6162
6146
|
outputDir: typesOutputDir,
|
|
@@ -6181,12 +6165,13 @@ var APIBuilder = class _APIBuilder {
|
|
|
6181
6165
|
this.logger.debug(`Configured TypeScript generator (${options.moduleFormat || "esm"})`);
|
|
6182
6166
|
return this;
|
|
6183
6167
|
}
|
|
6184
|
-
|
|
6168
|
+
typescript(opts) {
|
|
6185
6169
|
const writerOpts = {
|
|
6186
6170
|
outputDir: Path4.join(this.options.outputDir, "/types"),
|
|
6187
6171
|
tabSize: 4,
|
|
6188
6172
|
withDebugComment: false,
|
|
6189
|
-
commentLinePrefix: "//"
|
|
6173
|
+
commentLinePrefix: "//",
|
|
6174
|
+
exportTypeTree: this.options.exportTypeTree
|
|
6190
6175
|
};
|
|
6191
6176
|
const effectiveOpts = { logger: this.logger, ...writerOpts, ...opts };
|
|
6192
6177
|
const generator = writerToGenerator(new TypeScript(effectiveOpts));
|
|
@@ -6245,63 +6230,70 @@ var APIBuilder = class _APIBuilder {
|
|
|
6245
6230
|
this.options.cleanOutput = enabled;
|
|
6246
6231
|
return this;
|
|
6247
6232
|
}
|
|
6233
|
+
writeTypeTree(filename) {
|
|
6234
|
+
this.options.exportTypeTree = filename;
|
|
6235
|
+
return this;
|
|
6236
|
+
}
|
|
6248
6237
|
writeTypeSchemas(target) {
|
|
6249
6238
|
this.options.typeSchemaOutputDir = target;
|
|
6250
6239
|
return this;
|
|
6251
6240
|
}
|
|
6252
|
-
static async isIdenticalTo(path, tsJSON) {
|
|
6253
|
-
if (!await afs2.exists(path)) return false;
|
|
6254
|
-
const json = await afs2.readFile(path);
|
|
6255
|
-
const ts1 = JSON.parse(json.toString());
|
|
6256
|
-
const ts2 = JSON.parse(tsJSON);
|
|
6257
|
-
return deepEqual(ts1, ts2);
|
|
6258
|
-
}
|
|
6259
6241
|
async writeTypeSchemasToSeparateFiles(typeSchemas, outputDir) {
|
|
6260
|
-
|
|
6261
|
-
|
|
6262
|
-
const
|
|
6263
|
-
this.logger.info(`Writing TypeSchema files to ${outputDir}...`);
|
|
6242
|
+
await afs3.mkdir(outputDir, { recursive: true });
|
|
6243
|
+
this.logger.info(`Writing TypeSchema files to ${outputDir}/...`);
|
|
6244
|
+
const files = {};
|
|
6264
6245
|
for (const ts of typeSchemas) {
|
|
6265
|
-
const
|
|
6266
|
-
const
|
|
6246
|
+
const pkg = { name: ts.identifier.package, version: ts.identifier.version };
|
|
6247
|
+
const pkgPath = normalizeFileName(packageMetaToFhir(pkg));
|
|
6248
|
+
const name = normalizeFileName(`${ts.identifier.name}(${extractNameFromCanonical(ts.identifier.url)})`);
|
|
6267
6249
|
const json = JSON.stringify(ts, null, 2);
|
|
6268
|
-
const baseName = Path4.join(outputDir,
|
|
6269
|
-
|
|
6270
|
-
if (
|
|
6271
|
-
|
|
6272
|
-
|
|
6273
|
-
|
|
6274
|
-
|
|
6275
|
-
|
|
6276
|
-
|
|
6277
|
-
|
|
6278
|
-
|
|
6279
|
-
|
|
6250
|
+
const baseName = Path4.join(outputDir, pkgPath, name);
|
|
6251
|
+
if (!files[baseName]) files[baseName] = [];
|
|
6252
|
+
if (!files[baseName]?.some((e) => e === json)) {
|
|
6253
|
+
files[baseName].push(json);
|
|
6254
|
+
}
|
|
6255
|
+
}
|
|
6256
|
+
for (const [baseName, jsons] of Object.entries(files)) {
|
|
6257
|
+
await Promise.all(
|
|
6258
|
+
jsons.map(async (json, index) => {
|
|
6259
|
+
let fullName;
|
|
6260
|
+
if (index === 0) {
|
|
6261
|
+
fullName = `${baseName}.typeschema.json`;
|
|
6262
|
+
} else {
|
|
6263
|
+
fullName = `${baseName}-${index}.typeschema.json`;
|
|
6264
|
+
}
|
|
6265
|
+
await afs3.mkdir(Path4.dirname(fullName), { recursive: true });
|
|
6266
|
+
await afs3.writeFile(fullName, json);
|
|
6267
|
+
})
|
|
6268
|
+
);
|
|
6280
6269
|
}
|
|
6281
6270
|
}
|
|
6282
6271
|
async writeTypeSchemasToSingleFile(typeSchemas, outputFile) {
|
|
6272
|
+
this.logger.info(`Writing TypeSchema files to: ${outputFile}`);
|
|
6283
6273
|
if (this.options.cleanOutput && fs.existsSync(outputFile)) fs.rmSync(outputFile);
|
|
6284
|
-
await
|
|
6274
|
+
await afs3.mkdir(Path4.dirname(outputFile), { recursive: true });
|
|
6285
6275
|
this.logger.info(`Writing TypeSchemas to one file ${outputFile}...`);
|
|
6286
6276
|
for (const ts of typeSchemas) {
|
|
6287
6277
|
const json = JSON.stringify(ts, null, 2);
|
|
6288
|
-
await
|
|
6278
|
+
await afs3.appendFile(outputFile, `${json}
|
|
6279
|
+
`);
|
|
6289
6280
|
}
|
|
6290
6281
|
}
|
|
6291
6282
|
async tryWriteTypeSchema(typeSchemas) {
|
|
6292
6283
|
if (!this.options.typeSchemaOutputDir) return;
|
|
6293
6284
|
try {
|
|
6294
|
-
this.
|
|
6295
|
-
if (Path4.extname(this.options.typeSchemaOutputDir) === ".ndjson")
|
|
6285
|
+
if (Path4.extname(this.options.typeSchemaOutputDir) === ".ndjson") {
|
|
6296
6286
|
await this.writeTypeSchemasToSingleFile(typeSchemas, this.options.typeSchemaOutputDir);
|
|
6297
|
-
else
|
|
6298
|
-
|
|
6287
|
+
} else {
|
|
6288
|
+
await this.writeTypeSchemasToSeparateFiles(typeSchemas, this.options.typeSchemaOutputDir);
|
|
6289
|
+
}
|
|
6290
|
+
this.logger.info(`Writing TypeSchema - DONE`);
|
|
6299
6291
|
} catch (error) {
|
|
6300
|
-
if (this.options.throwException) throw error;
|
|
6301
6292
|
this.logger.error(
|
|
6302
6293
|
"Failed to write TypeSchema output",
|
|
6303
6294
|
error instanceof Error ? error : new Error(String(error))
|
|
6304
6295
|
);
|
|
6296
|
+
if (this.options.throwException) throw error;
|
|
6305
6297
|
}
|
|
6306
6298
|
}
|
|
6307
6299
|
async generate() {
|
|
@@ -6316,10 +6308,18 @@ var APIBuilder = class _APIBuilder {
|
|
|
6316
6308
|
};
|
|
6317
6309
|
this.logger.debug(`Starting generation with ${this.generators.size} generators`);
|
|
6318
6310
|
if (this.options.cleanOutput) {
|
|
6319
|
-
this.logger.info(`Cleaning
|
|
6311
|
+
this.logger.info(`Cleaning outputs...`);
|
|
6320
6312
|
try {
|
|
6313
|
+
this.logger.info(`Clean ${this.options.outputDir}`);
|
|
6321
6314
|
fs.rmSync(this.options.outputDir, { recursive: true, force: true });
|
|
6322
|
-
|
|
6315
|
+
if (this.options.typeSchemaOutputDir) {
|
|
6316
|
+
this.logger.info(`Clean ${this.options.typeSchemaOutputDir}`);
|
|
6317
|
+
fs.rmSync(this.options.typeSchemaOutputDir, { recursive: true, force: true });
|
|
6318
|
+
}
|
|
6319
|
+
if (this.options.exportTypeTree) {
|
|
6320
|
+
this.logger.info(`Clean ${this.options.exportTypeTree}`);
|
|
6321
|
+
fs.rmSync(this.options.exportTypeTree, { recursive: true, force: true });
|
|
6322
|
+
}
|
|
6323
6323
|
} catch (error) {
|
|
6324
6324
|
this.logger.warn(
|
|
6325
6325
|
`Error cleaning output directory: ${error instanceof Error ? error.message : String(error)}`
|
|
@@ -6333,11 +6333,16 @@ var APIBuilder = class _APIBuilder {
|
|
|
6333
6333
|
workingDir: "tmp/fhir"
|
|
6334
6334
|
});
|
|
6335
6335
|
await manager.init();
|
|
6336
|
-
const register = await registerFromManager(manager, {
|
|
6336
|
+
const register = await registerFromManager(manager, {
|
|
6337
|
+
logger: this.logger,
|
|
6338
|
+
focusedPackages: this.packages.map(npmToPackageMeta)
|
|
6339
|
+
});
|
|
6337
6340
|
const typeSchemas = await generateTypeSchemas(register, this.logger);
|
|
6338
6341
|
await this.tryWriteTypeSchema(typeSchemas);
|
|
6342
|
+
const tsIndex = mkTypeSchemaIndex(typeSchemas);
|
|
6343
|
+
if (this.options.exportTypeTree) await tsIndex.exportTree(this.options.exportTypeTree);
|
|
6339
6344
|
this.logger.debug(`Executing ${this.generators.size} generators`);
|
|
6340
|
-
await this.executeGenerators(result, typeSchemas);
|
|
6345
|
+
await this.executeGenerators(result, { schemas: typeSchemas, index: tsIndex });
|
|
6341
6346
|
this.logger.info("Generation completed successfully");
|
|
6342
6347
|
result.success = result.errors.length === 0;
|
|
6343
6348
|
this.logger.debug(`Generation completed: ${result.filesGenerated.length} files`);
|
|
@@ -6404,11 +6409,11 @@ var APIBuilder = class _APIBuilder {
|
|
|
6404
6409
|
this.cache.setMany(schemas);
|
|
6405
6410
|
}
|
|
6406
6411
|
}
|
|
6407
|
-
async executeGenerators(result,
|
|
6412
|
+
async executeGenerators(result, input) {
|
|
6408
6413
|
for (const [type, generator] of this.generators.entries()) {
|
|
6409
6414
|
this.logger.info(`Generating ${type}...`);
|
|
6410
6415
|
try {
|
|
6411
|
-
const files = await generator.generate(
|
|
6416
|
+
const files = await generator.generate(input);
|
|
6412
6417
|
result.filesGenerated.push(...files.map((f) => f.path || f.filename));
|
|
6413
6418
|
this.logger.info(`Generating ${type} finished successfully`);
|
|
6414
6419
|
} catch (error) {
|
|
@@ -6441,7 +6446,7 @@ function createAPIFromConfig(config) {
|
|
|
6441
6446
|
builder.fromFiles(...config.files);
|
|
6442
6447
|
}
|
|
6443
6448
|
if (config.typescript) {
|
|
6444
|
-
builder.
|
|
6449
|
+
builder.typescriptDepricated(config.typescript);
|
|
6445
6450
|
}
|
|
6446
6451
|
return builder;
|
|
6447
6452
|
}
|
|
@@ -6449,13 +6454,13 @@ async function generateTypesFromPackage(packageName, outputDir, options = {}) {
|
|
|
6449
6454
|
return createAPI({
|
|
6450
6455
|
outputDir,
|
|
6451
6456
|
verbose: options.verbose
|
|
6452
|
-
}).fromPackage(packageName, options.version).
|
|
6457
|
+
}).fromPackage(packageName, options.version).typescriptDepricated().generate();
|
|
6453
6458
|
}
|
|
6454
6459
|
async function generateTypesFromFiles(inputFiles, outputDir, options = {}) {
|
|
6455
6460
|
return createAPI({
|
|
6456
6461
|
outputDir,
|
|
6457
6462
|
verbose: options.verbose
|
|
6458
|
-
}).fromFiles(...inputFiles).
|
|
6463
|
+
}).fromFiles(...inputFiles).typescriptDepricated().generate();
|
|
6459
6464
|
}
|
|
6460
6465
|
var DEFAULT_CONFIG = {
|
|
6461
6466
|
outputDir: "./generated",
|