fhir-test-data 0.1.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/LICENSE +21 -0
- package/README.md +225 -0
- package/dist/chunk-CBIPVWLL.js +121 -0
- package/dist/chunk-CBIPVWLL.js.map +1 -0
- package/dist/chunk-T46LJ67Q.js +4302 -0
- package/dist/chunk-T46LJ67Q.js.map +1 -0
- package/dist/chunk-U2QJNKBG.js +40 -0
- package/dist/chunk-U2QJNKBG.js.map +1 -0
- package/dist/cli/index.d.ts +1 -0
- package/dist/cli/index.js +850 -0
- package/dist/cli/index.js.map +1 -0
- package/dist/core/faults/index.d.ts +33 -0
- package/dist/core/faults/index.js +14 -0
- package/dist/core/faults/index.js.map +1 -0
- package/dist/core/index.d.ts +115 -0
- package/dist/core/index.js +30 -0
- package/dist/core/index.js.map +1 -0
- package/dist/types-BvGNm2YJ.d.ts +132 -0
- package/package.json +102 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../src/cli/index.ts","../../src/cli/commands/generate.ts","../../src/core/annotations/index.ts","../../src/cli/commands/locales.ts","../../src/cli/commands/describe.ts"],"sourcesContent":["#!/usr/bin/env node\nimport { Command } from \"commander\";\nimport { registerGenerateCommand } from \"./commands/generate.js\";\nimport { registerLocalesCommand } from \"./commands/locales.js\";\nimport { registerDescribeCommand } from \"./commands/describe.js\";\n\nconst program = new Command();\n\nprogram\n .name(\"fhir-test-data\")\n .description(\"Generate valid FHIR R4 test resources with country-aware identifiers\")\n .version(\"0.1.0\");\n\nregisterGenerateCommand(program);\nregisterLocalesCommand(program);\nregisterDescribeCommand(program);\n\n// pnpm forwards its argument separator '--' as the first extra arg when\n// running `pnpm cli -- <args>`. Strip it so Commander can parse options normally.\nconst argv =\n process.argv[2] === \"--\"\n ? [...process.argv.slice(0, 2), ...process.argv.slice(3)]\n : process.argv;\n\nawait program.parseAsync(argv);\n","import { writeFileSync, mkdirSync } from \"node:fs\";\nimport { join } from \"node:path\";\nimport type { Command } from \"commander\";\nimport { createPatientBuilder } from \"@/core/builders/patient.js\";\nimport { createPractitionerBuilder } from \"@/core/builders/practitioner.js\";\nimport { createOrganizationBuilder } from \"@/core/builders/organization.js\";\nimport { createObservationBuilder } from \"@/core/builders/observation.js\";\nimport { createConditionBuilder } from \"@/core/builders/condition.js\";\nimport { createAllergyIntoleranceBuilder } from \"@/core/builders/allergy-intolerance.js\";\nimport { createMedicationStatementBuilder } from \"@/core/builders/medication-statement.js\";\nimport { createPractitionerRoleBuilder } from \"@/core/builders/practitioner-role.js\";\nimport { createBundleBuilder } from \"@/core/builders/bundle.js\";\nimport { deepMerge } from \"@/core/builders/utils.js\";\nimport { SUPPORTED_LOCALES, SUPPORTED_FHIR_VERSIONS } from \"@/core/types.js\";\nimport type { FhirVersion, Locale, FhirResource, AnnotatedResource } from \"@/core/types.js\";\nimport { injectFaults, FAULT_TYPES } from \"@/core/faults/index.js\";\nimport type { FaultType } from \"@/core/faults/index.js\";\nimport { createRng } from \"@/core/generators/rng.js\";\nimport { annotateResource } from \"@/core/annotations/index.js\";\nimport { getLocale } from \"@/locales/index.js\";\n\n// ---------------------------------------------------------------------------\n// Resource type → builder factory (lookup table replaces switch)\n// ---------------------------------------------------------------------------\n\ntype ResourceType =\n | \"patient\"\n | \"practitioner\"\n | \"practitioner-role\"\n | \"organization\"\n | \"observation\"\n | \"condition\"\n | \"allergy-intolerance\"\n | \"medication-statement\"\n | \"bundle\"\n | \"all\";\n\ntype ConcreteResourceType = Exclude<ResourceType, \"all\">;\n\nconst BUILDER_FACTORIES: Record<\n ConcreteResourceType,\n (locale: Locale, count: number, seed: number, fhirVersion: FhirVersion) => FhirResource[]\n> = {\n patient: (l, c, s, v) => createPatientBuilder().locale(l).count(c).seed(s).fhirVersion(v).build(),\n practitioner: (l, c, s, v) => createPractitionerBuilder().locale(l).count(c).seed(s).fhirVersion(v).build(),\n \"practitioner-role\": (l, c, s, v) => createPractitionerRoleBuilder().locale(l).count(c).seed(s).fhirVersion(v).build(),\n organization: (l, c, s, v) => createOrganizationBuilder().locale(l).count(c).seed(s).fhirVersion(v).build(),\n observation: (l, c, s, v) => createObservationBuilder().locale(l).count(c).seed(s).fhirVersion(v).build(),\n condition: (l, c, s, v) => createConditionBuilder().locale(l).count(c).seed(s).fhirVersion(v).build(),\n \"allergy-intolerance\": (l, c, s, v) => createAllergyIntoleranceBuilder().locale(l).count(c).seed(s).fhirVersion(v).build(),\n \"medication-statement\":(l, c, s, v) => createMedicationStatementBuilder().locale(l).count(c).seed(s).fhirVersion(v).build(),\n bundle: (l, c, s, v) => createBundleBuilder().locale(l).count(c).seed(s).fhirVersion(v).build(),\n};\n\nconst CONCRETE_RESOURCE_TYPES = Object.keys(BUILDER_FACTORIES) as ConcreteResourceType[];\nconst ALL_RESOURCE_TYPES: ResourceType[] = [...CONCRETE_RESOURCE_TYPES, \"all\"];\n\n// ---------------------------------------------------------------------------\n// Options\n// ---------------------------------------------------------------------------\n\ninterface GenerateOptions {\n locale: string;\n count: string;\n seed?: string;\n fhirVersion: string;\n output?: string;\n format: string;\n pretty: boolean;\n faults?: string;\n overrides?: string;\n annotate: boolean;\n}\n\n// ---------------------------------------------------------------------------\n// Fault parsing\n// ---------------------------------------------------------------------------\n\nfunction parseFaults(raw: string): FaultType[] | { error: string } {\n const types = raw.split(\",\").map((s) => s.trim()).filter(Boolean);\n const invalid = types.filter((t) => !FAULT_TYPES.includes(t as FaultType));\n if (invalid.length > 0) {\n return {\n error: `Unknown fault type(s): ${invalid.join(\", \")}. Valid types: ${FAULT_TYPES.join(\", \")}`,\n };\n }\n return types as FaultType[];\n}\n\n// ---------------------------------------------------------------------------\n// stdin overrides\n// ---------------------------------------------------------------------------\n\n/**\n * Read stdin to completion and parse as JSON.\n * Returns null if stdin is a TTY (interactive), empty, or not present.\n * Rejects if the data is present but not valid JSON.\n */\nasync function readStdinOverrides(): Promise<Record<string, unknown> | null> {\n if (process.stdin.isTTY) return null;\n return new Promise((resolve, reject) => {\n let data = \"\";\n process.stdin.setEncoding(\"utf8\");\n process.stdin.on(\"data\", (chunk: string) => {\n data += chunk;\n });\n process.stdin.on(\"end\", () => {\n if (!data.trim()) {\n resolve(null);\n return;\n }\n try {\n const parsed = JSON.parse(data) as Record<string, unknown>;\n resolve(parsed);\n } catch {\n reject(\n new Error(\n `stdin is not valid JSON. Received: ${data.slice(0, 120)}${data.length > 120 ? \"…\" : \"\"}`,\n ),\n );\n }\n });\n process.stdin.on(\"error\", reject);\n });\n}\n\n// ---------------------------------------------------------------------------\n// Output helpers\n// ---------------------------------------------------------------------------\n\nfunction formatIndex(i: number, total: number): string {\n const width = Math.max(3, String(total).length);\n return String(i + 1).padStart(width, \"0\");\n}\n\ntype OutputUnit = FhirResource | AnnotatedResource;\n\nfunction writeToOutput(\n units: OutputUnit[],\n resourceType: ConcreteResourceType,\n outputDir: string,\n format: string,\n annotate: boolean,\n): void {\n mkdirSync(outputDir, { recursive: true });\n\n // Derive file-name prefix from the actual FHIR resourceType when available.\n const firstResource = annotate\n ? (units[0] as AnnotatedResource | undefined)?.resource\n : (units[0] as FhirResource | undefined);\n const fhirType = (firstResource?.[\"resourceType\"] as string | undefined) ?? resourceType;\n\n if (format === \"ndjson\") {\n const content = units.map((u) => JSON.stringify(u)).join(\"\\n\") + \"\\n\";\n const filePath = join(outputDir, `${fhirType}.ndjson`);\n writeFileSync(filePath, content, \"utf8\");\n } else {\n for (let i = 0; i < units.length; i++) {\n const idx = formatIndex(i, units.length);\n const filePath = join(outputDir, `${fhirType}-${idx}.json`);\n writeFileSync(filePath, JSON.stringify(units[i], null, 2) + \"\\n\", \"utf8\");\n }\n }\n\n process.stderr.write(\n `Generated ${units.length} ${fhirType} resource${units.length === 1 ? \"\" : \"s\"} in ${outputDir}\\n`,\n );\n}\n\nfunction writeToStdout(\n units: OutputUnit[],\n format: string,\n pretty: boolean,\n forceCompact = false,\n): void {\n if (format === \"ndjson\" || forceCompact) {\n // NDJSON output: always compact (pipe-safe). --pretty is a no-op for NDJSON stdout.\n for (const u of units) {\n process.stdout.write(JSON.stringify(u) + \"\\n\");\n }\n } else if (units.length === 1) {\n const indent = pretty ? 2 : undefined;\n process.stdout.write(JSON.stringify(units[0], null, indent) + \"\\n\");\n } else {\n const indent = pretty ? 2 : undefined;\n process.stdout.write(JSON.stringify(units, null, indent) + \"\\n\");\n }\n}\n\n// ---------------------------------------------------------------------------\n// Main action\n// ---------------------------------------------------------------------------\n\nasync function runGenerate(resourceType: string, opts: GenerateOptions): Promise<void> {\n if (!ALL_RESOURCE_TYPES.includes(resourceType as ResourceType)) {\n process.stderr.write(\n `Error: unknown resource type \"${resourceType}\". Valid types: ${ALL_RESOURCE_TYPES.join(\", \")}\\n`,\n );\n process.exit(1);\n }\n\n if (!SUPPORTED_LOCALES.includes(opts.locale as Locale)) {\n process.stderr.write(\n `Error: unknown locale \"${opts.locale}\". Supported locales: ${SUPPORTED_LOCALES.join(\", \")}\\n`,\n );\n process.exit(1);\n }\n\n if (!SUPPORTED_FHIR_VERSIONS.includes(opts.fhirVersion as FhirVersion)) {\n process.stderr.write(\n `Error: unknown FHIR version \"${opts.fhirVersion}\". Supported versions: ${SUPPORTED_FHIR_VERSIONS.join(\", \")}\\n`,\n );\n process.exit(1);\n }\n\n // Parse faults before doing any work.\n let faults: FaultType[] = [];\n if (opts.faults !== undefined) {\n const parsed = parseFaults(opts.faults);\n if (\"error\" in parsed) {\n process.stderr.write(`Error: ${parsed.error}\\n`);\n process.exit(1);\n }\n faults = parsed;\n }\n\n // ---------------------------------------------------------------------------\n // Resolve overrides: stdin (base) deep-merged with --overrides flag (wins on conflict)\n // ---------------------------------------------------------------------------\n\n let overridesObj: Record<string, unknown> = {};\n\n try {\n const stdinOverrides = await readStdinOverrides();\n if (stdinOverrides !== null) {\n overridesObj = stdinOverrides;\n }\n } catch (err: unknown) {\n process.stderr.write(`Error: ${err instanceof Error ? err.message : String(err)}\\n`);\n process.exit(1);\n }\n\n if (opts.overrides !== undefined) {\n try {\n const cliOverrides = JSON.parse(opts.overrides) as Record<string, unknown>;\n overridesObj = deepMerge(overridesObj, cliOverrides) as Record<string, unknown>;\n } catch {\n process.stderr.write(\n `Error: --overrides value is not valid JSON. Received: ${opts.overrides.slice(0, 120)}\\n`,\n );\n process.exit(1);\n }\n }\n\n const hasOverrides = Object.keys(overridesObj).length > 0;\n\n // ---------------------------------------------------------------------------\n // Build resources\n // ---------------------------------------------------------------------------\n\n const locale = opts.locale as Locale;\n const fhirVersion = opts.fhirVersion as FhirVersion;\n const count = Number.parseInt(opts.count, 10);\n const seed =\n opts.seed !== undefined\n ? Number.parseInt(opts.seed, 10)\n : Math.floor(Math.random() * 0x7fffffff);\n const format = opts.format === \"ndjson\" ? \"ndjson\" : \"json\";\n const localeDefinition = getLocale(locale);\n\n const typesToGenerate: ConcreteResourceType[] =\n resourceType === \"all\" ? CONCRETE_RESOURCE_TYPES : [resourceType as ConcreteResourceType];\n\n // Pre-build Practitioner and Organization when running \"generate all\" so that\n // PractitionerRole references the exact same IDs already in the output.\n let coordinatedPractId: string | undefined;\n let coordinatedOrgId: string | undefined;\n if (resourceType === \"all\") {\n const [firstPract] = BUILDER_FACTORIES[\"practitioner\"](locale, count, seed, fhirVersion);\n const [firstOrg] = BUILDER_FACTORIES[\"organization\"](locale, count, seed, fhirVersion);\n coordinatedPractId = firstPract?.[\"id\"] as string | undefined;\n coordinatedOrgId = firstOrg?.[\"id\"] as string | undefined;\n }\n\n for (const type of typesToGenerate) {\n let resources: FhirResource[];\n if (\n type === \"practitioner-role\" &&\n coordinatedPractId !== undefined &&\n coordinatedOrgId !== undefined\n ) {\n resources = createPractitionerRoleBuilder()\n .locale(locale)\n .count(count)\n .seed(seed)\n .fhirVersion(fhirVersion)\n .practitionerId(coordinatedPractId)\n .organizationId(coordinatedOrgId)\n .build();\n } else {\n resources = BUILDER_FACTORIES[type](locale, count, seed, fhirVersion);\n }\n\n if (faults.length > 0) {\n // Use a separate RNG for fault injection so it doesn't affect generation\n // reproducibility. Seed it deterministically from the main seed.\n const faultRng = createRng(seed + 1);\n resources = resources.map((r) => injectFaults(r, faults, faultRng));\n }\n\n // Apply overrides (stdin + --overrides flag) to every resource.\n if (hasOverrides) {\n resources = resources.map(\n (r) => deepMerge(r as Record<string, unknown>, overridesObj) as FhirResource,\n );\n }\n\n // Wrap in annotations if requested.\n const units: OutputUnit[] = opts.annotate\n ? resources.map((r) => ({\n resource: r,\n notes: annotateResource(r, localeDefinition),\n }))\n : resources;\n\n if (opts.output !== undefined) {\n try {\n writeToOutput(units, type, opts.output, format, opts.annotate);\n } catch (err: unknown) {\n const message = err instanceof Error ? err.message : String(err);\n process.stderr.write(`Error writing output: ${message}\\n`);\n process.exit(2);\n }\n } else {\n writeToStdout(units, format, opts.pretty, typesToGenerate.length > 1);\n }\n }\n}\n\nexport function registerGenerateCommand(program: Command): void {\n program\n .command(\"generate <resource-type>\")\n .description(`Generate FHIR resources. Resource types: ${ALL_RESOURCE_TYPES.join(\", \")}`)\n .option(\"--locale <code>\", \"locale for identifiers and addresses\", \"us\")\n .option(\"--count <n>\", \"number of resources to generate\", \"1\")\n .option(\"--seed <n>\", \"seed for deterministic output\")\n .option(\n \"--fhir-version <version>\",\n `FHIR version to target: ${SUPPORTED_FHIR_VERSIONS.join(\" | \")}`,\n \"R4\",\n )\n .option(\"--output <dir>\", \"output directory (one file per resource)\")\n .option(\"--format <fmt>\", \"output format: json | ndjson\", \"json\")\n .option(\"--pretty\", \"pretty-print JSON (default for stdout)\", true)\n .option(\"--no-pretty\", \"compact JSON output\")\n .option(\n \"--faults <types>\",\n `comma-separated fault types to inject. Valid: ${FAULT_TYPES.join(\", \")}`,\n )\n .option(\n \"--overrides <json>\",\n \"JSON object to deep-merge into every generated resource (also readable from stdin)\",\n )\n .option(\n \"--annotate\",\n \"wrap each resource with a notes array explaining its fields in plain language\",\n false,\n )\n .action(runGenerate);\n}\n","/**\n * Reactive annotation generator.\n *\n * Given a generated FHIR resource and the locale that produced it, returns an\n * array of AnnotationNote objects explaining each field in plain language.\n *\n * Browser-safe: no Node.js imports, no I/O.\n */\nimport type { FhirResource, AnnotationNote, LocaleDefinition } from \"@/core/types.js\";\nimport { COMMON_LOINC_CODES } from \"@/core/data/loinc-codes.js\";\nimport { COMMON_SNOMED_CONDITIONS } from \"@/core/data/snomed-codes.js\";\nimport { COMMON_ALLERGY_CODES } from \"@/core/data/allergy-codes.js\";\nimport { COMMON_MEDICATION_CODES, US_RXNORM_MEDICATION_CODES } from \"@/core/data/medication-codes.js\";\n\n// ---------------------------------------------------------------------------\n// Shared field notes\n// ---------------------------------------------------------------------------\n\nconst SHARED_NOTES: AnnotationNote[] = [\n {\n path: \"id\",\n note: \"Unique resource identifier (UUID v4)\",\n },\n];\n\n// ---------------------------------------------------------------------------\n// Helpers\n// ---------------------------------------------------------------------------\n\nfunction identifierNotes(\n identifiers: Array<{ system?: string; value?: string }> | undefined,\n defs: LocaleDefinition[\"patientIdentifiers\"],\n): AnnotationNote[] {\n if (!identifiers) return [];\n const notes: AnnotationNote[] = [];\n identifiers.forEach((id, i) => {\n const def = defs.find((d) => d.system === id.system);\n if (!def) return;\n const algorithmClause = def.algorithm ? `, validated with ${def.algorithm}` : \"\";\n notes.push({\n path: `identifier[${i}].value`,\n note: `${def.name}${algorithmClause}`,\n });\n notes.push({\n path: `identifier[${i}].system`,\n note: `FHIR NamingSystem URI for ${def.name} (${def.system})`,\n });\n });\n return notes;\n}\n\nfunction nameNotes(\n names: Array<{ prefix?: string[] }> | undefined,\n): AnnotationNote[] {\n if (!names) return [];\n return [\n {\n path: \"name[0].use\",\n note: \"FHIR name use — 'official' is the primary legal name used in clinical records\",\n },\n {\n path: \"name[0].prefix\",\n note: \"Cultural or professional title prefix (e.g., Mr, Dr, Prof)\",\n },\n ];\n}\n\nfunction addressNotes(locale: LocaleDefinition): AnnotationNote[] {\n return [\n {\n path: \"address[0].country\",\n note: `ISO 3166-1 alpha-2 country code — ${locale.address.country} = ${locale.name}`,\n },\n {\n path: \"address[0].postalCode\",\n note: `Locale-appropriate postal code format for ${locale.name}`,\n },\n ];\n}\n\n// ---------------------------------------------------------------------------\n// Per-resource-type annotators\n// ---------------------------------------------------------------------------\n\nfunction annotatePatient(\n resource: FhirResource,\n locale: LocaleDefinition,\n): AnnotationNote[] {\n const identifiers = resource[\"identifier\"] as Array<{ system?: string; value?: string }> | undefined;\n const communication = resource[\"communication\"] as\n | Array<{ language?: { coding?: Array<{ code?: string }> } }>\n | undefined;\n const langCode = communication?.[0]?.language?.coding?.[0]?.code;\n\n return [\n ...SHARED_NOTES,\n ...identifierNotes(identifiers, locale.patientIdentifiers),\n ...nameNotes(resource[\"name\"] as Array<{ prefix?: string[] }> | undefined),\n {\n path: \"telecom\",\n note: \"Home phone number and email address in FHIR ContactPoint format\",\n },\n {\n path: \"gender\",\n note: \"FHIR administrative gender code (male | female | other | unknown)\",\n },\n {\n path: \"birthDate\",\n note: \"Patient date of birth — ISO 8601 format (YYYY-MM-DD)\",\n },\n ...addressNotes(locale),\n ...(langCode\n ? [\n {\n path: \"communication[0].language.coding[0].code\",\n note: `BCP 47 language tag — ${langCode} identifies the primary language for this locale`,\n },\n {\n path: \"communication[0].language.coding[0].system\",\n note: \"BCP 47 — IETF language tag standard (urn:ietf:bcp:47)\",\n },\n ]\n : []),\n ];\n}\n\nfunction annotatePractitioner(\n resource: FhirResource,\n locale: LocaleDefinition,\n): AnnotationNote[] {\n const identifiers = resource[\"identifier\"] as Array<{ system?: string; value?: string }> | undefined;\n return [\n ...SHARED_NOTES,\n ...identifierNotes(identifiers, locale.practitionerIdentifiers),\n ...nameNotes(resource[\"name\"] as Array<{ prefix?: string[] }> | undefined),\n {\n path: \"name[0].prefix\",\n note: \"Professional title prefix for practitioners (e.g., Dr, Prof)\",\n },\n {\n path: \"telecom\",\n note: \"Work email address in FHIR ContactPoint format\",\n },\n {\n path: \"gender\",\n note: \"FHIR administrative gender code (male | female | other | unknown)\",\n },\n {\n path: \"qualification[0].code.coding[0].code\",\n note: \"MD — Doctor of Medicine credential code\",\n },\n {\n path: \"qualification[0].code.coding[0].system\",\n note: \"http://terminology.hl7.org/CodeSystem/v2-0360 — HL7 degree/license/certificate code system\",\n },\n ];\n}\n\nfunction annotatePractitionerRole(\n _resource: FhirResource,\n): AnnotationNote[] {\n return [\n ...SHARED_NOTES,\n {\n path: \"active\",\n note: \"Whether this role relationship is currently active\",\n },\n {\n path: \"practitioner\",\n note: \"Reference to the Practitioner resource this role belongs to (urn:uuid: format)\",\n },\n {\n path: \"organization\",\n note: \"Reference to the Organization where this role is performed (urn:uuid: format)\",\n },\n {\n path: \"code[0].coding[0].code\",\n note: \"doctor — SNOMED CT code for general practitioner role\",\n },\n {\n path: \"code[0].coding[0].system\",\n note: \"SNOMED CT code system (http://snomed.info/sct)\",\n },\n ];\n}\n\nfunction annotateOrganization(\n resource: FhirResource,\n locale: LocaleDefinition,\n): AnnotationNote[] {\n const identifiers = resource[\"identifier\"] as Array<{ system?: string; value?: string }> | undefined;\n return [\n ...SHARED_NOTES,\n ...identifierNotes(identifiers, locale.organizationIdentifiers),\n {\n path: \"active\",\n note: \"Whether this organization is currently active — always true for generated resources\",\n },\n {\n path: \"type[0].coding[0].code\",\n note: \"prov — FHIR organization type code for healthcare provider\",\n },\n {\n path: \"type[0].coding[0].system\",\n note: \"http://terminology.hl7.org/CodeSystem/organization-type — HL7 organization type code system\",\n },\n {\n path: \"name\",\n note: \"Locale-appropriate hospital or organization name\",\n },\n ...addressNotes(locale),\n ];\n}\n\nfunction annotateObservation(\n resource: FhirResource,\n): AnnotationNote[] {\n const coding = (resource[\"code\"] as { coding?: Array<{ code?: string; system?: string }> } | undefined)\n ?.coding;\n const loincCode = coding?.[0]?.code;\n const loinc = loincCode ? COMMON_LOINC_CODES.find((c) => c.code === loincCode) : undefined;\n\n const vq = resource[\"valueQuantity\"] as\n | { value?: number; unit?: string; system?: string; code?: string }\n | undefined;\n\n const category = (resource[\"category\"] as Array<{ coding?: Array<{ code?: string }> }> | undefined)\n ?.[0]?.coding?.[0]?.code;\n\n const notes: AnnotationNote[] = [...SHARED_NOTES];\n\n if (loinc) {\n notes.push({\n path: \"code.coding[0].code\",\n note: `LOINC ${loinc.code} — ${loinc.display}`,\n });\n notes.push({\n path: \"code.coding[0].system\",\n note: \"LOINC — Logical Observation Identifiers Names and Codes (https://loinc.org)\",\n });\n notes.push({\n path: \"code.coding[0].display\",\n note: `Clinical display name for LOINC ${loinc.code}`,\n });\n }\n\n if (category) {\n notes.push({\n path: \"category[0].coding[0].code\",\n note: `${category} — FHIR observation category; groups this observation for clinical workflows`,\n });\n }\n\n notes.push({\n path: \"status\",\n note: \"FHIR observation status — 'final' indicates a completed, unmodified observation\",\n });\n\n notes.push({\n path: \"effectiveDateTime\",\n note: \"Date and time the observation was clinically relevant — ISO 8601 format\",\n });\n\n if (vq) {\n if (loinc) {\n notes.push({\n path: \"valueQuantity.value\",\n note: `${loinc.display} measurement — clinically plausible range: ${loinc.valueRange.min}–${loinc.valueRange.max}`,\n });\n notes.push({\n path: \"valueQuantity.unit\",\n note: `${loinc.unit} — UCUM code: ${loinc.unitCode}, per HL7 FHIR guidelines for units of measure`,\n });\n } else {\n notes.push({\n path: \"valueQuantity.value\",\n note: \"Observation measurement value\",\n });\n }\n notes.push({\n path: \"valueQuantity.system\",\n note: \"UCUM — Unified Code for Units of Measure (https://ucum.org), required by HL7 FHIR guidelines\",\n });\n }\n\n notes.push({\n path: \"subject\",\n note: \"Reference to the Patient this observation belongs to (urn:uuid: format)\",\n });\n\n return notes;\n}\n\nfunction annotateCondition(resource: FhirResource): AnnotationNote[] {\n const coding = (resource[\"code\"] as { coding?: Array<{ code?: string }> } | undefined)?.coding;\n const snomedCode = coding?.[0]?.code;\n const snomed = snomedCode\n ? COMMON_SNOMED_CONDITIONS.find((c) => c.code === snomedCode)\n : undefined;\n\n const notes: AnnotationNote[] = [...SHARED_NOTES];\n\n if (snomed) {\n notes.push({\n path: \"code.coding[0].code\",\n note: `SNOMED CT ${snomed.code} — ${snomed.display}`,\n });\n notes.push({\n path: \"code.coding[0].system\",\n note: \"SNOMED CT — Systematized Nomenclature of Medicine Clinical Terms (http://snomed.info/sct)\",\n });\n }\n\n notes.push({\n path: \"clinicalStatus.coding[0].code\",\n note: \"FHIR condition clinical status — 'active' or 'remission'; indicates current state of the condition\",\n });\n notes.push({\n path: \"verificationStatus.coding[0].code\",\n note: \"FHIR verification status — 'confirmed' indicates the condition has been clinically verified\",\n });\n notes.push({\n path: \"onsetDateTime\",\n note: \"Date when the condition was first clinically noted — ISO 8601 format\",\n });\n notes.push({\n path: \"subject\",\n note: \"Reference to the Patient this condition belongs to (urn:uuid: format)\",\n });\n\n return notes;\n}\n\nfunction annotateAllergyIntolerance(resource: FhirResource): AnnotationNote[] {\n const coding = (resource[\"code\"] as { coding?: Array<{ code?: string; system?: string }> } | undefined)\n ?.coding;\n const code = coding?.[0]?.code;\n const allergy = code ? COMMON_ALLERGY_CODES.find((c) => c.code === code) : undefined;\n\n const notes: AnnotationNote[] = [...SHARED_NOTES];\n\n if (allergy) {\n notes.push({\n path: \"code.coding[0].code\",\n note: `SNOMED CT ${allergy.code} — ${allergy.display}`,\n });\n notes.push({\n path: \"code.coding[0].system\",\n note: \"SNOMED CT — Systematized Nomenclature of Medicine Clinical Terms (http://snomed.info/sct)\",\n });\n notes.push({\n path: \"category\",\n note: `FHIR allergy category — ${allergy.category}: type of substance causing the reaction`,\n });\n }\n\n notes.push({\n path: \"type\",\n note: \"FHIR allergy type — 'allergy' (immune-mediated) or 'intolerance' (non-immune mechanism)\",\n });\n notes.push({\n path: \"criticality\",\n note: \"FHIR allergy criticality — potential severity: low | high | unable-to-assess\",\n });\n notes.push({\n path: \"patient\",\n note: \"Reference to the Patient this allergy record belongs to (urn:uuid: format)\",\n });\n notes.push({\n path: \"recordedDate\",\n note: \"Date when this allergy was first recorded — ISO 8601 format (YYYY-MM-DD)\",\n });\n\n return notes;\n}\n\nfunction annotateMedicationStatement(resource: FhirResource): AnnotationNote[] {\n // Handles both R4 (medicationCodeableConcept) and R5 (medication.concept)\n const r4Coding = (\n resource[\"medicationCodeableConcept\"] as\n | { coding?: Array<{ code?: string }> }\n | undefined\n )?.coding;\n const r5Coding = (\n (resource[\"medication\"] as { concept?: { coding?: Array<{ code?: string }> } } | undefined)\n ?.concept\n )?.coding;\n const coding = r4Coding ?? r5Coding;\n const code = coding?.[0]?.code;\n\n const allMeds = [...COMMON_MEDICATION_CODES, ...US_RXNORM_MEDICATION_CODES];\n const med = code ? allMeds.find((m) => m.code === code) : undefined;\n\n const resourceType = resource[\"resourceType\"] as string;\n const isR5 = resourceType === \"MedicationUsage\";\n\n const notes: AnnotationNote[] = [...SHARED_NOTES];\n\n if (med) {\n const codePath = isR5\n ? \"medication.concept.coding[0].code\"\n : \"medicationCodeableConcept.coding[0].code\";\n const systemPath = isR5\n ? \"medication.concept.coding[0].system\"\n : \"medicationCodeableConcept.coding[0].system\";\n\n notes.push({\n path: codePath,\n note: `${med.system.includes(\"rxnorm\") ? \"RxNorm\" : \"SNOMED CT\"} ${med.code} — ${med.display}; typical dose: ${med.typicalDoseMg}mg ${med.frequency}`,\n });\n notes.push({\n path: systemPath,\n note: med.system.includes(\"rxnorm\")\n ? \"RxNorm — US National Library of Medicine drug terminology (http://www.nlm.nih.gov/research/umls/rxnorm)\"\n : \"SNOMED CT — Systematized Nomenclature of Medicine Clinical Terms (http://snomed.info/sct)\",\n });\n }\n\n notes.push({\n path: \"status\",\n note: `FHIR ${isR5 ? \"MedicationUsage\" : \"MedicationStatement\"} status — 'active' or 'stopped'`,\n });\n notes.push({\n path: \"subject\",\n note: \"Reference to the Patient this medication record belongs to (urn:uuid: format)\",\n });\n\n return notes;\n}\n\nfunction annotateBundle(resource: FhirResource): AnnotationNote[] {\n const entries = resource[\"entry\"] as Array<{ resource?: FhirResource }> | undefined;\n const resourceTypes = entries\n ? [...new Set(entries.map((e) => e.resource?.resourceType).filter(Boolean))]\n : [];\n\n return [\n ...SHARED_NOTES,\n {\n path: \"type\",\n note: \"FHIR Bundle type — 'transaction' includes request entries; 'collection' is a plain grouping\",\n },\n {\n path: \"entry\",\n note: `Bundle entries — ${entries?.length ?? 0} resources: ${resourceTypes.join(\", \")}`,\n },\n {\n path: \"entry[*].fullUrl\",\n note: \"urn:uuid: format — temporary URIs used for cross-reference within the bundle\",\n },\n {\n path: \"entry[*].request\",\n note: \"FHIR transaction request metadata — method (PUT/POST) and URL for server processing\",\n },\n ];\n}\n\n// ---------------------------------------------------------------------------\n// Public API\n// ---------------------------------------------------------------------------\n\n/**\n * Generate human-readable annotation notes for a FHIR resource.\n *\n * @param resource The generated FHIR resource.\n * @param locale The locale used to generate it (provides identifier metadata).\n * @returns Array of AnnotationNote objects explaining each notable field.\n */\nexport function annotateResource(\n resource: FhirResource,\n locale: LocaleDefinition,\n): AnnotationNote[] {\n switch (resource.resourceType) {\n case \"Patient\":\n return annotatePatient(resource, locale);\n case \"Practitioner\":\n return annotatePractitioner(resource, locale);\n case \"PractitionerRole\":\n return annotatePractitionerRole(resource);\n case \"Organization\":\n return annotateOrganization(resource, locale);\n case \"Observation\":\n return annotateObservation(resource);\n case \"Condition\":\n return annotateCondition(resource);\n case \"AllergyIntolerance\":\n return annotateAllergyIntolerance(resource);\n case \"MedicationStatement\":\n case \"MedicationUsage\":\n return annotateMedicationStatement(resource);\n case \"Bundle\":\n return annotateBundle(resource);\n default:\n return [...SHARED_NOTES];\n }\n}\n","import type { Command } from \"commander\";\nimport { getAllLocales } from \"@/locales/index.js\";\n\n// ---------------------------------------------------------------------------\n// Options\n// ---------------------------------------------------------------------------\n\ninterface LocalesOptions {\n pretty: boolean;\n}\n\n// ---------------------------------------------------------------------------\n// Action\n// ---------------------------------------------------------------------------\n\nfunction runLocales(opts: LocalesOptions): void {\n const locales = getAllLocales().map((locale) => ({\n code: locale.code,\n name: locale.name,\n patientIdentifiers: locale.patientIdentifiers.map((id) => ({\n name: id.name,\n system: id.system,\n ...(id.algorithm !== undefined ? { algorithm: id.algorithm } : {}),\n })),\n practitionerIdentifiers: locale.practitionerIdentifiers.map((id) => ({\n name: id.name,\n system: id.system,\n ...(id.algorithm !== undefined ? { algorithm: id.algorithm } : {}),\n })),\n organizationIdentifiers: locale.organizationIdentifiers.map((id) => ({\n name: id.name,\n system: id.system,\n ...(id.algorithm !== undefined ? { algorithm: id.algorithm } : {}),\n })),\n }));\n\n const indent = opts.pretty ? 2 : undefined;\n process.stdout.write(JSON.stringify(locales, null, indent) + \"\\n\");\n}\n\n// ---------------------------------------------------------------------------\n// Registration\n// ---------------------------------------------------------------------------\n\nexport function registerLocalesCommand(program: Command): void {\n program\n .command(\"locales\")\n .description(\n \"List all supported locales with their identifier systems and check-digit algorithms\",\n )\n .option(\"--pretty\", \"pretty-print JSON (default for stdout)\", true)\n .option(\"--no-pretty\", \"compact JSON output\")\n .action(runLocales);\n}\n","import type { Command } from \"commander\";\nimport { SUPPORTED_LOCALES } from \"@/core/types.js\";\nimport type { Locale } from \"@/core/types.js\";\nimport { getLocale } from \"@/locales/index.js\";\n\n// ---------------------------------------------------------------------------\n// Static resource-type descriptions\n// ---------------------------------------------------------------------------\n\ntype DescribableResourceType =\n | \"patient\"\n | \"practitioner\"\n | \"practitioner-role\"\n | \"organization\"\n | \"observation\"\n | \"condition\"\n | \"allergy-intolerance\"\n | \"medication-statement\"\n | \"bundle\";\n\ninterface ResourceDescription {\n resourceType: string;\n description: string;\n fields: Record<string, string>;\n}\n\nconst RESOURCE_DESCRIPTIONS: Record<DescribableResourceType, ResourceDescription> = {\n patient: {\n resourceType: \"Patient\",\n description:\n \"FHIR Patient with locale-appropriate identifiers, names, address, and communication language\",\n fields: {\n id: \"UUID v4 — unique resource identifier\",\n identifier: \"Locale-specific patient identifiers (check-digit validated where applicable)\",\n \"name[0].use\": \"FHIR name use — 'official' is the primary legal name for clinical records\",\n \"name[0].family\": \"Family (last) name drawn from locale name pool\",\n \"name[0].given\": \"Given (first) name drawn from locale name pool\",\n \"name[0].prefix\": \"Cultural or professional title prefix (Mr, Mrs, Dr, etc.)\",\n \"telecom[0]\": \"Home phone number in locale-appropriate format (FHIR ContactPoint)\",\n \"telecom[1]\": \"Email address (FHIR ContactPoint)\",\n gender: \"FHIR administrative gender: male | female\",\n birthDate: \"Random date in adult age range — ISO 8601 format (YYYY-MM-DD)\",\n \"address[0]\": \"Locale-appropriate street address with city and postal code\",\n \"communication[0].language.coding[0].code\":\n \"BCP 47 language tag — primary language for the locale\",\n },\n },\n\n practitioner: {\n resourceType: \"Practitioner\",\n description:\n \"FHIR Practitioner with locale-appropriate identifiers, professional name, and MD qualification\",\n fields: {\n id: \"UUID v4 — unique resource identifier\",\n identifier: \"Locale-specific practitioner identifiers (check-digit validated where applicable)\",\n \"name[0].prefix\": \"Professional title prefix (Dr, Prof)\",\n \"name[0].family\": \"Family name drawn from locale name pool\",\n \"name[0].given\": \"Given name drawn from locale name pool\",\n \"telecom[0]\": \"Work email address (FHIR ContactPoint)\",\n gender: \"FHIR administrative gender: male | female\",\n \"qualification[0].code.coding[0].code\":\n \"MD — Doctor of Medicine credential code\",\n \"qualification[0].code.coding[0].system\":\n \"http://terminology.hl7.org/CodeSystem/v2-0360 — HL7 degree/license/certificate code system\",\n },\n },\n\n \"practitioner-role\": {\n resourceType: \"PractitionerRole\",\n description:\n \"FHIR PractitionerRole linking a Practitioner to an Organization with a coded role\",\n fields: {\n id: \"UUID v4 — unique resource identifier\",\n active: \"Whether this role relationship is currently active\",\n practitioner: \"Reference to the Practitioner (urn:uuid: format)\",\n organization: \"Reference to the Organization where this role is performed (urn:uuid: format)\",\n \"code[0].coding[0].code\": \"doctor — SNOMED CT code for general practitioner role\",\n \"code[0].coding[0].system\": \"SNOMED CT code system (http://snomed.info/sct)\",\n },\n },\n\n organization: {\n resourceType: \"Organization\",\n description:\n \"FHIR Organization (healthcare provider) with locale-appropriate identifiers and address\",\n fields: {\n id: \"UUID v4 — unique resource identifier\",\n identifier: \"Locale-specific organization identifiers\",\n active: \"Whether this organization is currently active — always true for generated resources\",\n \"type[0].coding[0].code\":\n \"prov — FHIR organization type code for healthcare provider\",\n \"type[0].coding[0].system\":\n \"http://terminology.hl7.org/CodeSystem/organization-type — HL7 organization type code system\",\n name: \"Locale-appropriate hospital or clinic name\",\n \"telecom[0]\": \"Main phone number (FHIR ContactPoint)\",\n \"address[0]\": \"Locale-appropriate street address with city and postal code\",\n },\n },\n\n observation: {\n resourceType: \"Observation\",\n description:\n \"FHIR Observation with a real LOINC code, value in a clinically plausible range, and HL7-consistent UCUM units\",\n fields: {\n id: \"UUID v4 — unique resource identifier\",\n status: \"FHIR observation status — 'final' indicates a completed, unmodified observation\",\n \"category[0].coding[0].code\":\n \"FHIR observation category — vital-signs or laboratory\",\n \"code.coding[0].code\": \"LOINC code identifying the observation type (https://loinc.org)\",\n \"code.coding[0].system\":\n \"LOINC — Logical Observation Identifiers Names and Codes (https://loinc.org)\",\n \"code.coding[0].display\": \"Human-readable LOINC display name\",\n subject: \"Reference to the Patient this observation belongs to (urn:uuid: format)\",\n effectiveDateTime:\n \"Date and time the observation was clinically relevant — ISO 8601 format\",\n \"valueQuantity.value\":\n \"Numeric measurement in a clinically plausible range for the LOINC code\",\n \"valueQuantity.unit\":\n \"Human-readable unit name (e.g., 'mmHg' for blood pressure)\",\n \"valueQuantity.system\":\n \"UCUM — Unified Code for Units of Measure (https://ucum.org), required by HL7 FHIR\",\n \"valueQuantity.code\":\n \"UCUM code for the unit (e.g., 'mm[Hg]'), machine-readable unit identifier\",\n },\n },\n\n condition: {\n resourceType: \"Condition\",\n description:\n \"FHIR Condition with a real SNOMED CT code, clinical status, and verification status\",\n fields: {\n id: \"UUID v4 — unique resource identifier\",\n \"clinicalStatus.coding[0].code\":\n \"FHIR condition clinical status — 'active' or 'remission'\",\n \"clinicalStatus.coding[0].system\":\n \"http://terminology.hl7.org/CodeSystem/condition-clinical\",\n \"verificationStatus.coding[0].code\":\n \"FHIR verification status — 'confirmed' indicates clinically verified\",\n \"code.coding[0].code\":\n \"SNOMED CT code identifying the clinical condition (https://snomed.info/sct)\",\n \"code.coding[0].system\":\n \"SNOMED CT — Systematized Nomenclature of Medicine Clinical Terms\",\n \"code.coding[0].display\": \"Human-readable SNOMED CT display name\",\n subject: \"Reference to the Patient this condition belongs to (urn:uuid: format)\",\n onsetDateTime: \"Date when the condition was first noted — ISO 8601 format\",\n },\n },\n\n \"allergy-intolerance\": {\n resourceType: \"AllergyIntolerance\",\n description:\n \"FHIR AllergyIntolerance with SNOMED CT coded substance, type, category, and criticality\",\n fields: {\n id: \"UUID v4 — unique resource identifier\",\n type: \"FHIR allergy type — 'allergy' (immune-mediated) or 'intolerance' (non-immune)\",\n category: \"FHIR allergy category — food | medication | environment | biologic\",\n criticality: \"Potential severity — low | high | unable-to-assess\",\n \"code.coding[0].code\":\n \"SNOMED CT code identifying the substance or reaction\",\n \"code.coding[0].system\":\n \"SNOMED CT — Systematized Nomenclature of Medicine Clinical Terms\",\n patient: \"Reference to the Patient this allergy record belongs to (urn:uuid: format)\",\n recordedDate: \"Date when this allergy was first recorded — ISO 8601 (YYYY-MM-DD)\",\n },\n },\n\n \"medication-statement\": {\n resourceType: \"MedicationStatement (R4/R4B) | MedicationUsage (R5)\",\n description:\n \"FHIR MedicationStatement (R4/R4B) or MedicationUsage (R5) with a SNOMED CT or RxNorm coded medication\",\n fields: {\n id: \"UUID v4 — unique resource identifier\",\n status: \"FHIR medication status — 'active' or 'stopped'\",\n \"medicationCodeableConcept.coding[0].code\":\n \"SNOMED CT or RxNorm code identifying the medication (R4/R4B only)\",\n \"medication.concept.coding[0].code\":\n \"SNOMED CT or RxNorm code identifying the medication (R5 MedicationUsage only)\",\n subject: \"Reference to the Patient this medication record belongs to (urn:uuid: format)\",\n \"effectivePeriod.start\": \"Start date of medication use — ISO 8601 format\",\n \"effectivePeriod.end\": \"End date of medication use — ISO 8601 format (may be absent for active)\",\n },\n },\n\n bundle: {\n resourceType: \"Bundle\",\n description:\n \"FHIR Bundle composing Patient, Practitioner, PractitionerRole, Organization, and clinical resources with automatic urn:uuid: reference wiring\",\n fields: {\n id: \"UUID v4 — unique bundle identifier\",\n type: \"FHIR Bundle type — transaction | collection | searchset | document\",\n \"entry[*].fullUrl\":\n \"urn:uuid: URIs used for cross-referencing resources within the bundle\",\n \"entry[*].resource\":\n \"Embedded FHIR resource — Patient, Practitioner, Organization, Observation, etc.\",\n \"entry[*].request\":\n \"Transaction request metadata — method and URL (transaction bundles only)\",\n \"entry[*].search\":\n \"Search mode metadata — match or include (searchset bundles only)\",\n },\n },\n};\n\nconst DESCRIBABLE_RESOURCE_TYPES = Object.keys(\n RESOURCE_DESCRIPTIONS,\n) as DescribableResourceType[];\n\n// ---------------------------------------------------------------------------\n// Options\n// ---------------------------------------------------------------------------\n\ninterface DescribeOptions {\n locale?: string;\n pretty: boolean;\n}\n\n// ---------------------------------------------------------------------------\n// Action\n// ---------------------------------------------------------------------------\n\nfunction runDescribe(resourceType: string, opts: DescribeOptions): void {\n if (!DESCRIBABLE_RESOURCE_TYPES.includes(resourceType as DescribableResourceType)) {\n process.stderr.write(\n `Error: unknown resource type \"${resourceType}\". Valid types: ${DESCRIBABLE_RESOURCE_TYPES.join(\", \")}\\n`,\n );\n process.exit(1);\n }\n\n if (opts.locale !== undefined && !SUPPORTED_LOCALES.includes(opts.locale as Locale)) {\n process.stderr.write(\n `Error: unknown locale \"${opts.locale}\". Supported locales: ${SUPPORTED_LOCALES.join(\", \")}\\n`,\n );\n process.exit(1);\n }\n\n const description = RESOURCE_DESCRIPTIONS[resourceType as DescribableResourceType];\n\n const output: Record<string, unknown> = {\n resourceType: description.resourceType,\n description: description.description,\n fields: description.fields,\n supportedLocales: [...SUPPORTED_LOCALES],\n };\n\n if (opts.locale !== undefined) {\n const locale = getLocale(opts.locale as Locale);\n output[\"localeDetail\"] = {\n code: locale.code,\n name: locale.name,\n patientIdentifiers: locale.patientIdentifiers.map((id) => ({\n name: id.name,\n system: id.system,\n ...(id.algorithm !== undefined ? { algorithm: id.algorithm } : {}),\n })),\n practitionerIdentifiers: locale.practitionerIdentifiers.map((id) => ({\n name: id.name,\n system: id.system,\n ...(id.algorithm !== undefined ? { algorithm: id.algorithm } : {}),\n })),\n organizationIdentifiers: locale.organizationIdentifiers.map((id) => ({\n name: id.name,\n system: id.system,\n ...(id.algorithm !== undefined ? { algorithm: id.algorithm } : {}),\n })),\n };\n }\n\n const indent = opts.pretty ? 2 : undefined;\n process.stdout.write(JSON.stringify(output, null, indent) + \"\\n\");\n}\n\n// ---------------------------------------------------------------------------\n// Registration\n// ---------------------------------------------------------------------------\n\nexport function registerDescribeCommand(program: Command): void {\n program\n .command(\"describe <resource-type>\")\n .description(\n `Describe what a resource type generates. Types: ${DESCRIBABLE_RESOURCE_TYPES.join(\", \")}`,\n )\n .option(\"--locale <code>\", \"include locale-specific identifier details for this locale\")\n .option(\"--pretty\", \"pretty-print JSON (default for stdout)\", true)\n .option(\"--no-pretty\", \"compact JSON output\")\n .action(runDescribe);\n}\n"],"mappings":"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","names":["program","program","program"]}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import { R as RandomFn, F as FhirResource } from '../../types-BvGNm2YJ.js';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Concrete fault types — each maps to a specific FHIR violation.
|
|
5
|
+
*/
|
|
6
|
+
type ConcreteFaultType = "missing-resource-type" | "invalid-resource-type" | "missing-id" | "invalid-gender" | "malformed-date" | "empty-name" | "wrong-type-on-field" | "duplicate-identifier" | "invalid-telecom-system";
|
|
7
|
+
/**
|
|
8
|
+
* Full fault type including the "random" convenience alias.
|
|
9
|
+
* "random" expands to one concrete fault chosen by the seeded RNG.
|
|
10
|
+
*/
|
|
11
|
+
type FaultType = ConcreteFaultType | "random";
|
|
12
|
+
/** All valid fault type strings, for CLI validation. */
|
|
13
|
+
declare const FAULT_TYPES: FaultType[];
|
|
14
|
+
/**
|
|
15
|
+
* A fault strategy receives a resource as a plain object and an RNG,
|
|
16
|
+
* and returns a new object with the fault applied. Never mutates the input.
|
|
17
|
+
*/
|
|
18
|
+
type FaultStrategy = (resource: Record<string, unknown>, rng: RandomFn) => Record<string, unknown>;
|
|
19
|
+
|
|
20
|
+
/**
|
|
21
|
+
* Apply a list of fault types to a FHIR resource.
|
|
22
|
+
*
|
|
23
|
+
* - "random" expands to one concrete fault chosen by the seeded RNG.
|
|
24
|
+
* - Duplicate fault types in the list are applied once each (deduped by type).
|
|
25
|
+
* - Faults targeting fields not present on the resource are silent no-ops.
|
|
26
|
+
* - The original resource is never mutated; a new object is returned.
|
|
27
|
+
*/
|
|
28
|
+
declare function injectFaults(resource: FhirResource, faults: FaultType[], rng: RandomFn): FhirResource;
|
|
29
|
+
|
|
30
|
+
declare const FAULT_REGISTRY: Record<ConcreteFaultType, FaultStrategy>;
|
|
31
|
+
declare const CONCRETE_FAULT_TYPES: ConcreteFaultType[];
|
|
32
|
+
|
|
33
|
+
export { CONCRETE_FAULT_TYPES, type ConcreteFaultType, FAULT_REGISTRY, FAULT_TYPES, type FaultStrategy, type FaultType, injectFaults };
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import {
|
|
2
|
+
CONCRETE_FAULT_TYPES,
|
|
3
|
+
FAULT_REGISTRY,
|
|
4
|
+
FAULT_TYPES,
|
|
5
|
+
injectFaults
|
|
6
|
+
} from "../../chunk-CBIPVWLL.js";
|
|
7
|
+
import "../../chunk-U2QJNKBG.js";
|
|
8
|
+
export {
|
|
9
|
+
CONCRETE_FAULT_TYPES,
|
|
10
|
+
FAULT_REGISTRY,
|
|
11
|
+
FAULT_TYPES,
|
|
12
|
+
injectFaults
|
|
13
|
+
};
|
|
14
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":[],"sourcesContent":[],"mappings":"","names":[]}
|
|
@@ -0,0 +1,115 @@
|
|
|
1
|
+
import { L as Locale, a as FhirVersion, F as FhirResource } from '../types-BvGNm2YJ.js';
|
|
2
|
+
export { A as AddressTemplate, b as AnnotatedResource, c as AnnotationNote, B as BuilderOptions, C as CityDefinition, d as FhirMeta, G as GeneratedFixture, I as IdentifierContext, e as IdentifierDefinition, f as LocaleDefinition, N as NamePool, R as RandomFn, g as ResourceBuilder, S as SUPPORTED_FHIR_VERSIONS, h as SUPPORTED_LOCALES, i as SUPPORTED_RESOURCE_TYPES, j as SupportedResourceType } from '../types-BvGNm2YJ.js';
|
|
3
|
+
|
|
4
|
+
interface PatientBuilder {
|
|
5
|
+
locale(locale: Locale): PatientBuilder;
|
|
6
|
+
count(count: number): PatientBuilder;
|
|
7
|
+
seed(seed: number): PatientBuilder;
|
|
8
|
+
fhirVersion(version: FhirVersion): PatientBuilder;
|
|
9
|
+
overrides(overrides: Record<string, unknown>): PatientBuilder;
|
|
10
|
+
build(): FhirResource[];
|
|
11
|
+
}
|
|
12
|
+
/** Create a new PatientBuilder with default options. */
|
|
13
|
+
declare function createPatientBuilder(): PatientBuilder;
|
|
14
|
+
|
|
15
|
+
interface PractitionerBuilder {
|
|
16
|
+
locale(locale: Locale): PractitionerBuilder;
|
|
17
|
+
count(count: number): PractitionerBuilder;
|
|
18
|
+
seed(seed: number): PractitionerBuilder;
|
|
19
|
+
fhirVersion(version: FhirVersion): PractitionerBuilder;
|
|
20
|
+
overrides(overrides: Record<string, unknown>): PractitionerBuilder;
|
|
21
|
+
build(): FhirResource[];
|
|
22
|
+
}
|
|
23
|
+
/** Create a new PractitionerBuilder with default options. */
|
|
24
|
+
declare function createPractitionerBuilder(): PractitionerBuilder;
|
|
25
|
+
|
|
26
|
+
interface PractitionerRoleBuilder {
|
|
27
|
+
locale(locale: Locale): PractitionerRoleBuilder;
|
|
28
|
+
count(count: number): PractitionerRoleBuilder;
|
|
29
|
+
seed(seed: number): PractitionerRoleBuilder;
|
|
30
|
+
fhirVersion(version: FhirVersion): PractitionerRoleBuilder;
|
|
31
|
+
/** Inject the ID of an already-built Practitioner so the reference is consistent. */
|
|
32
|
+
practitionerId(id: string): PractitionerRoleBuilder;
|
|
33
|
+
/** Inject the ID of an already-built Organization so the reference is consistent. */
|
|
34
|
+
organizationId(id: string): PractitionerRoleBuilder;
|
|
35
|
+
overrides(overrides: Record<string, unknown>): PractitionerRoleBuilder;
|
|
36
|
+
build(): FhirResource[];
|
|
37
|
+
}
|
|
38
|
+
/** Create a new PractitionerRoleBuilder with default options. */
|
|
39
|
+
declare function createPractitionerRoleBuilder(): PractitionerRoleBuilder;
|
|
40
|
+
|
|
41
|
+
interface OrganizationBuilder {
|
|
42
|
+
locale(locale: Locale): OrganizationBuilder;
|
|
43
|
+
count(count: number): OrganizationBuilder;
|
|
44
|
+
seed(seed: number): OrganizationBuilder;
|
|
45
|
+
fhirVersion(version: FhirVersion): OrganizationBuilder;
|
|
46
|
+
overrides(overrides: Record<string, unknown>): OrganizationBuilder;
|
|
47
|
+
build(): FhirResource[];
|
|
48
|
+
}
|
|
49
|
+
/** Create a new OrganizationBuilder with default options. */
|
|
50
|
+
declare function createOrganizationBuilder(): OrganizationBuilder;
|
|
51
|
+
|
|
52
|
+
interface ObservationBuilder {
|
|
53
|
+
locale(locale: Locale): ObservationBuilder;
|
|
54
|
+
count(count: number): ObservationBuilder;
|
|
55
|
+
seed(seed: number): ObservationBuilder;
|
|
56
|
+
subject(patientReference: string): ObservationBuilder;
|
|
57
|
+
category(category: "vital-signs" | "laboratory"): ObservationBuilder;
|
|
58
|
+
fhirVersion(version: FhirVersion): ObservationBuilder;
|
|
59
|
+
overrides(overrides: Record<string, unknown>): ObservationBuilder;
|
|
60
|
+
build(): FhirResource[];
|
|
61
|
+
}
|
|
62
|
+
/** Create a new ObservationBuilder with default options. */
|
|
63
|
+
declare function createObservationBuilder(): ObservationBuilder;
|
|
64
|
+
|
|
65
|
+
interface ConditionBuilder {
|
|
66
|
+
locale(locale: Locale): ConditionBuilder;
|
|
67
|
+
count(count: number): ConditionBuilder;
|
|
68
|
+
seed(seed: number): ConditionBuilder;
|
|
69
|
+
subject(patientReference: string): ConditionBuilder;
|
|
70
|
+
fhirVersion(version: FhirVersion): ConditionBuilder;
|
|
71
|
+
overrides(overrides: Record<string, unknown>): ConditionBuilder;
|
|
72
|
+
build(): FhirResource[];
|
|
73
|
+
}
|
|
74
|
+
/** Create a new ConditionBuilder with default options. */
|
|
75
|
+
declare function createConditionBuilder(): ConditionBuilder;
|
|
76
|
+
|
|
77
|
+
interface AllergyIntoleranceBuilder {
|
|
78
|
+
locale(locale: Locale): AllergyIntoleranceBuilder;
|
|
79
|
+
count(count: number): AllergyIntoleranceBuilder;
|
|
80
|
+
seed(seed: number): AllergyIntoleranceBuilder;
|
|
81
|
+
subject(patientReference: string): AllergyIntoleranceBuilder;
|
|
82
|
+
fhirVersion(version: FhirVersion): AllergyIntoleranceBuilder;
|
|
83
|
+
overrides(overrides: Record<string, unknown>): AllergyIntoleranceBuilder;
|
|
84
|
+
build(): FhirResource[];
|
|
85
|
+
}
|
|
86
|
+
/** Create a new AllergyIntoleranceBuilder with default options. */
|
|
87
|
+
declare function createAllergyIntoleranceBuilder(): AllergyIntoleranceBuilder;
|
|
88
|
+
|
|
89
|
+
interface MedicationStatementBuilder {
|
|
90
|
+
locale(locale: Locale): MedicationStatementBuilder;
|
|
91
|
+
count(count: number): MedicationStatementBuilder;
|
|
92
|
+
seed(seed: number): MedicationStatementBuilder;
|
|
93
|
+
subject(patientReference: string): MedicationStatementBuilder;
|
|
94
|
+
fhirVersion(version: FhirVersion): MedicationStatementBuilder;
|
|
95
|
+
overrides(overrides: Record<string, unknown>): MedicationStatementBuilder;
|
|
96
|
+
build(): FhirResource[];
|
|
97
|
+
}
|
|
98
|
+
/** Create a new MedicationStatementBuilder with default options. */
|
|
99
|
+
declare function createMedicationStatementBuilder(): MedicationStatementBuilder;
|
|
100
|
+
|
|
101
|
+
type BundleType = "transaction" | "document" | "collection" | "searchset";
|
|
102
|
+
interface BundleBuilder {
|
|
103
|
+
locale(locale: Locale): BundleBuilder;
|
|
104
|
+
count(count: number): BundleBuilder;
|
|
105
|
+
seed(seed: number): BundleBuilder;
|
|
106
|
+
type(bundleType: BundleType): BundleBuilder;
|
|
107
|
+
fhirVersion(version: FhirVersion): BundleBuilder;
|
|
108
|
+
clinicalResourcesPerPatient(count: number): BundleBuilder;
|
|
109
|
+
overrides(overrides: Record<string, unknown>): BundleBuilder;
|
|
110
|
+
build(): FhirResource[];
|
|
111
|
+
}
|
|
112
|
+
/** Create a new BundleBuilder with default options. */
|
|
113
|
+
declare function createBundleBuilder(): BundleBuilder;
|
|
114
|
+
|
|
115
|
+
export { type AllergyIntoleranceBuilder, type BundleBuilder, type BundleType, type ConditionBuilder, FhirResource, FhirVersion, Locale, type MedicationStatementBuilder, type ObservationBuilder, type OrganizationBuilder, type PatientBuilder, type PractitionerBuilder, type PractitionerRoleBuilder, createAllergyIntoleranceBuilder, createBundleBuilder, createConditionBuilder, createMedicationStatementBuilder, createObservationBuilder, createOrganizationBuilder, createPatientBuilder, createPractitionerBuilder, createPractitionerRoleBuilder };
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import {
|
|
2
|
+
SUPPORTED_FHIR_VERSIONS,
|
|
3
|
+
SUPPORTED_LOCALES,
|
|
4
|
+
SUPPORTED_RESOURCE_TYPES,
|
|
5
|
+
createAllergyIntoleranceBuilder,
|
|
6
|
+
createBundleBuilder,
|
|
7
|
+
createConditionBuilder,
|
|
8
|
+
createMedicationStatementBuilder,
|
|
9
|
+
createObservationBuilder,
|
|
10
|
+
createOrganizationBuilder,
|
|
11
|
+
createPatientBuilder,
|
|
12
|
+
createPractitionerBuilder,
|
|
13
|
+
createPractitionerRoleBuilder
|
|
14
|
+
} from "../chunk-T46LJ67Q.js";
|
|
15
|
+
import "../chunk-U2QJNKBG.js";
|
|
16
|
+
export {
|
|
17
|
+
SUPPORTED_FHIR_VERSIONS,
|
|
18
|
+
SUPPORTED_LOCALES,
|
|
19
|
+
SUPPORTED_RESOURCE_TYPES,
|
|
20
|
+
createAllergyIntoleranceBuilder,
|
|
21
|
+
createBundleBuilder,
|
|
22
|
+
createConditionBuilder,
|
|
23
|
+
createMedicationStatementBuilder,
|
|
24
|
+
createObservationBuilder,
|
|
25
|
+
createOrganizationBuilder,
|
|
26
|
+
createPatientBuilder,
|
|
27
|
+
createPractitionerBuilder,
|
|
28
|
+
createPractitionerRoleBuilder
|
|
29
|
+
};
|
|
30
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":[],"sourcesContent":[],"mappings":"","names":[]}
|
|
@@ -0,0 +1,132 @@
|
|
|
1
|
+
declare const SUPPORTED_RESOURCE_TYPES: readonly ["Patient", "Practitioner", "PractitionerRole", "Organization", "Observation", "Condition", "AllergyIntolerance", "MedicationStatement", "Bundle"];
|
|
2
|
+
type SupportedResourceType = (typeof SUPPORTED_RESOURCE_TYPES)[number];
|
|
3
|
+
declare const SUPPORTED_FHIR_VERSIONS: readonly ["R4", "R4B", "R5"];
|
|
4
|
+
type FhirVersion = (typeof SUPPORTED_FHIR_VERSIONS)[number];
|
|
5
|
+
declare const SUPPORTED_LOCALES: readonly ["us", "uk", "au", "ca", "de", "fr", "nl", "in", "jp", "kr", "sg", "br", "mx", "za"];
|
|
6
|
+
type Locale = (typeof SUPPORTED_LOCALES)[number];
|
|
7
|
+
interface FhirMeta {
|
|
8
|
+
versionId?: string;
|
|
9
|
+
lastUpdated?: string;
|
|
10
|
+
profile?: string[];
|
|
11
|
+
[key: string]: unknown;
|
|
12
|
+
}
|
|
13
|
+
/** Minimal FHIR resource shape. Index signature allows arbitrary FHIR fields. */
|
|
14
|
+
interface FhirResource {
|
|
15
|
+
resourceType: string;
|
|
16
|
+
id?: string;
|
|
17
|
+
meta?: FhirMeta;
|
|
18
|
+
[key: string]: unknown;
|
|
19
|
+
}
|
|
20
|
+
interface BuilderOptions {
|
|
21
|
+
locale: Locale;
|
|
22
|
+
count: number;
|
|
23
|
+
/** Seed for deterministic random generation. Same seed = same output. */
|
|
24
|
+
seed?: number;
|
|
25
|
+
/** FHIR version to target. Defaults to 'R4'. */
|
|
26
|
+
fhirVersion?: FhirVersion;
|
|
27
|
+
/** Partial overrides to merge into every generated resource. */
|
|
28
|
+
overrides?: Record<string, unknown>;
|
|
29
|
+
}
|
|
30
|
+
interface ResourceBuilder<T extends FhirResource> {
|
|
31
|
+
locale(locale: Locale): this;
|
|
32
|
+
count(count: number): this;
|
|
33
|
+
seed(seed: number): this;
|
|
34
|
+
overrides(overrides: Record<string, unknown>): this;
|
|
35
|
+
build(): T[];
|
|
36
|
+
}
|
|
37
|
+
/** A deterministic random number generator function. Returns [0, 1). */
|
|
38
|
+
type RandomFn = () => number;
|
|
39
|
+
/**
|
|
40
|
+
* Optional context passed from a resource builder to an identifier generator.
|
|
41
|
+
* Identifiers that encode demographic data (e.g. Korean RRN) use this to stay
|
|
42
|
+
* internally consistent with the generated resource. All other generators ignore it.
|
|
43
|
+
*/
|
|
44
|
+
interface IdentifierContext {
|
|
45
|
+
gender?: "male" | "female" | "other" | "unknown";
|
|
46
|
+
birthYear?: number;
|
|
47
|
+
}
|
|
48
|
+
interface IdentifierDefinition {
|
|
49
|
+
/** FHIR system URI (e.g., "https://fhir.nhs.uk/Id/nhs-number") */
|
|
50
|
+
system: string;
|
|
51
|
+
/** Human-readable name (e.g., "NHS Number") */
|
|
52
|
+
name: string;
|
|
53
|
+
/**
|
|
54
|
+
* Check-digit algorithm name, if applicable (e.g., "Modulus 11", "Luhn", "Verhoeff").
|
|
55
|
+
* Omitted for identifiers validated by format/range only.
|
|
56
|
+
*/
|
|
57
|
+
algorithm?: string;
|
|
58
|
+
/**
|
|
59
|
+
* Generate a valid identifier value.
|
|
60
|
+
* `context` is provided by the patient builder when demographic data is
|
|
61
|
+
* available. Implementations that don't need it can safely ignore the
|
|
62
|
+
* second parameter — TypeScript function arity compatibility allows this.
|
|
63
|
+
*/
|
|
64
|
+
generate: (rng: RandomFn, context?: IdentifierContext) => string;
|
|
65
|
+
/** Validate an identifier value */
|
|
66
|
+
validate: (value: string) => boolean;
|
|
67
|
+
}
|
|
68
|
+
/** A single human-readable note explaining a field in a generated resource. */
|
|
69
|
+
interface AnnotationNote {
|
|
70
|
+
/** JSONPath-style field reference (e.g., "identifier[0].value") */
|
|
71
|
+
path: string;
|
|
72
|
+
/** Plain-language explanation of the field and its value */
|
|
73
|
+
note: string;
|
|
74
|
+
}
|
|
75
|
+
/** A generated FHIR resource paired with human-readable field explanations. */
|
|
76
|
+
interface AnnotatedResource {
|
|
77
|
+
resource: FhirResource;
|
|
78
|
+
notes: AnnotationNote[];
|
|
79
|
+
}
|
|
80
|
+
interface CityDefinition {
|
|
81
|
+
name: string;
|
|
82
|
+
state?: string;
|
|
83
|
+
district?: string;
|
|
84
|
+
}
|
|
85
|
+
interface AddressTemplate {
|
|
86
|
+
/** Street name + number patterns */
|
|
87
|
+
streets: string[];
|
|
88
|
+
/** City definitions with matching state/postcode data */
|
|
89
|
+
cities: CityDefinition[];
|
|
90
|
+
/** Generate a valid postal code for the given state/region */
|
|
91
|
+
generatePostalCode: (rng: RandomFn, state?: string) => string;
|
|
92
|
+
/**
|
|
93
|
+
* Format a street address line. Defaults to "{number} {street}" if omitted.
|
|
94
|
+
* Override for locales that use "{street} {number}" order (DE, NL, FR).
|
|
95
|
+
*/
|
|
96
|
+
formatLine?: (number: number, street: string) => string;
|
|
97
|
+
/** ISO 3166-1 alpha-2 country code */
|
|
98
|
+
country: string;
|
|
99
|
+
}
|
|
100
|
+
interface NamePool {
|
|
101
|
+
given: {
|
|
102
|
+
male: string[];
|
|
103
|
+
female: string[];
|
|
104
|
+
};
|
|
105
|
+
family: string[];
|
|
106
|
+
/** Optional prefixes (e.g., "van", "de" for Dutch names) */
|
|
107
|
+
prefixes?: string[];
|
|
108
|
+
}
|
|
109
|
+
interface LocaleDefinition {
|
|
110
|
+
code: Locale;
|
|
111
|
+
/** Display name (e.g., "United Kingdom") */
|
|
112
|
+
name: string;
|
|
113
|
+
/** Patient identifier definitions for this locale */
|
|
114
|
+
patientIdentifiers: IdentifierDefinition[];
|
|
115
|
+
/** Practitioner identifier definitions for this locale */
|
|
116
|
+
practitionerIdentifiers: IdentifierDefinition[];
|
|
117
|
+
/** Organization identifier definitions for this locale */
|
|
118
|
+
organizationIdentifiers: IdentifierDefinition[];
|
|
119
|
+
/** Address generation data */
|
|
120
|
+
address: AddressTemplate;
|
|
121
|
+
/** Name pools */
|
|
122
|
+
names: NamePool;
|
|
123
|
+
}
|
|
124
|
+
interface GeneratedFixture<T extends FhirResource> {
|
|
125
|
+
resource: T;
|
|
126
|
+
/** Which locale was used to generate this resource */
|
|
127
|
+
locale: Locale;
|
|
128
|
+
/** The seed that produced this resource (for reproducibility) */
|
|
129
|
+
seed: number;
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
export { type AddressTemplate as A, type BuilderOptions as B, type CityDefinition as C, type FhirResource as F, type GeneratedFixture as G, type IdentifierContext as I, type Locale as L, type NamePool as N, type RandomFn as R, SUPPORTED_FHIR_VERSIONS as S, type FhirVersion as a, type AnnotatedResource as b, type AnnotationNote as c, type FhirMeta as d, type IdentifierDefinition as e, type LocaleDefinition as f, type ResourceBuilder as g, SUPPORTED_LOCALES as h, SUPPORTED_RESOURCE_TYPES as i, type SupportedResourceType as j };
|
package/package.json
ADDED
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "fhir-test-data",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "TypeScript library and CLI for generating valid FHIR R4/R4B/R5 test resources with country-aware identifiers",
|
|
5
|
+
"author": "Daniel Veronez",
|
|
6
|
+
"license": "MIT",
|
|
7
|
+
"homepage": "https://dnlbox.github.io/fhir-test-data/",
|
|
8
|
+
"keywords": [
|
|
9
|
+
"fhir",
|
|
10
|
+
"hl7",
|
|
11
|
+
"healthcare",
|
|
12
|
+
"fhir-test-data",
|
|
13
|
+
"test-data",
|
|
14
|
+
"fixtures",
|
|
15
|
+
"synthetic-data",
|
|
16
|
+
"r4",
|
|
17
|
+
"r4b",
|
|
18
|
+
"r5",
|
|
19
|
+
"fhir-r4",
|
|
20
|
+
"cli",
|
|
21
|
+
"identifiers",
|
|
22
|
+
"nhs",
|
|
23
|
+
"medicare",
|
|
24
|
+
"aadhaar",
|
|
25
|
+
"bsn",
|
|
26
|
+
"npi",
|
|
27
|
+
"typescript"
|
|
28
|
+
],
|
|
29
|
+
"repository": {
|
|
30
|
+
"type": "git",
|
|
31
|
+
"url": "https://github.com/dnlbox/fhir-test-data.git"
|
|
32
|
+
},
|
|
33
|
+
"bugs": {
|
|
34
|
+
"url": "https://github.com/dnlbox/fhir-test-data/issues"
|
|
35
|
+
},
|
|
36
|
+
"files": [
|
|
37
|
+
"dist/",
|
|
38
|
+
"README.md",
|
|
39
|
+
"LICENSE"
|
|
40
|
+
],
|
|
41
|
+
"type": "module",
|
|
42
|
+
"bin": {
|
|
43
|
+
"fhir-test-data": "./dist/cli/index.js"
|
|
44
|
+
},
|
|
45
|
+
"main": "./dist/core/index.js",
|
|
46
|
+
"types": "./dist/core/index.d.ts",
|
|
47
|
+
"exports": {
|
|
48
|
+
".": {
|
|
49
|
+
"import": "./dist/core/index.js",
|
|
50
|
+
"types": "./dist/core/index.d.ts"
|
|
51
|
+
},
|
|
52
|
+
"./faults": {
|
|
53
|
+
"import": "./dist/core/faults/index.js",
|
|
54
|
+
"types": "./dist/core/faults/index.d.ts"
|
|
55
|
+
}
|
|
56
|
+
},
|
|
57
|
+
"scripts": {
|
|
58
|
+
"build": "tsup",
|
|
59
|
+
"dev": "tsup --watch",
|
|
60
|
+
"cli": "tsx src/cli/index.ts",
|
|
61
|
+
"typecheck": "tsc --noEmit",
|
|
62
|
+
"lint": "eslint \"src/**/*.ts\" \"tests/**/*.ts\"",
|
|
63
|
+
"lint:fix": "eslint \"src/**/*.ts\" \"tests/**/*.ts\" --fix",
|
|
64
|
+
"format": "prettier --write .",
|
|
65
|
+
"test": "vitest run",
|
|
66
|
+
"test:watch": "vitest",
|
|
67
|
+
"test:coverage": "vitest run --coverage",
|
|
68
|
+
"docs:dev": "vitepress dev docs/site",
|
|
69
|
+
"docs:build": "vitepress build docs/site",
|
|
70
|
+
"docs:preview": "vitepress preview docs/site",
|
|
71
|
+
"prepublishOnly": "pnpm build && pnpm typecheck && pnpm test"
|
|
72
|
+
},
|
|
73
|
+
"dependencies": {
|
|
74
|
+
"commander": "^12.1.0",
|
|
75
|
+
"zod": "^3.25.76"
|
|
76
|
+
},
|
|
77
|
+
"devDependencies": {
|
|
78
|
+
"@types/node": "^20.19.37",
|
|
79
|
+
"@typescript-eslint/eslint-plugin": "^8.57.1",
|
|
80
|
+
"@typescript-eslint/parser": "^8.57.1",
|
|
81
|
+
"@vitest/coverage-v8": "^3.2.4",
|
|
82
|
+
"eslint": "^9.39.4",
|
|
83
|
+
"eslint-config-prettier": "^9.1.2",
|
|
84
|
+
"prettier": "^3.8.1",
|
|
85
|
+
"tsup": "^8.5.1",
|
|
86
|
+
"tsx": "^4.21.0",
|
|
87
|
+
"typescript": "^5.9.3",
|
|
88
|
+
"typescript-eslint": "^8.57.1",
|
|
89
|
+
"vitepress": "^1.6.4",
|
|
90
|
+
"vitest": "^3.2.4"
|
|
91
|
+
},
|
|
92
|
+
"packageManager": "pnpm@10.32.1",
|
|
93
|
+
"engines": {
|
|
94
|
+
"node": ">=20.0.0",
|
|
95
|
+
"pnpm": ">=9.0.0"
|
|
96
|
+
},
|
|
97
|
+
"pnpm": {
|
|
98
|
+
"onlyBuiltDependencies": [
|
|
99
|
+
"esbuild"
|
|
100
|
+
]
|
|
101
|
+
}
|
|
102
|
+
}
|