Skip to content

API: migrate package-defect handling to CM patches (Phase 1, #128)#176

Open
ryukzak wants to merge 14 commits into
mainfrom
feat/phase1-patch-helpers
Open

API: migrate package-defect handling to CM patches (Phase 1, #128)#176
ryukzak wants to merge 14 commits into
mainfrom
feat/phase1-patch-helpers

Conversation

@ryukzak

@ryukzak ryukzak commented Jun 5, 2026

Copy link
Copy Markdown
Collaborator

Phase 1 of the #128 migration (see docs/design/defect-handling-migration.md, PR #173): move the example preprocessPackage defect workarounds onto CanonicalManager's composable patches runtime (shipped in CM #14). Codegen-only; no CM changes.

Helpers + combinators — src/api/patches/

Unscoped transform helpers, scoped by nesting combinators:

  • Combinators: forPackage(match, handlers) and forResource(url, handlers) — scope a list of handlers (nest freely).
  • Transforms: injectDependency(deps), renameCanonical(renames), renameReferenceTarget(renames), swapBinding(swaps) (scoped via combinators); renamePackage(renames) and patchCodeSystem(url, codes) (self-matching).

APIBuilder

  • New patches?: PatchesInput constructor option — each phase accepts a single handler or a list — normalized to CM's Partial<Patches> (arrays). Warns if combined with an injected manager/register (which owns its own patch wiring).

Examples migrated off preprocessPackage

// kbv
patches: { package: forPackage("de.basisprofil.r4", [injectDependency({ "hl7.fhir.r4.core": "4.0.1" })]) }

// norge
patches: {
  package: [
    forPackage((pkg) => needsCoreDependency(pkg.name), [injectDependency({ "hl7.fhir.r4.core": "4.0.1" })]),
    renamePackage(packageNameFixes),
  ],
  resource: forResource(".../gd-RelatedPerson", [renameReferenceTarget({ /* Person→Patient ×3 */ })]),
}

// ccda (on its manual CM — nesting forPackage > forResource)
patches: { resource: [
  forPackage("hl7.cda.uv.core", [renameCanonical({ ".../IVL_TS": ".../IVL-TS" })]),
  forPackage("hl7.cda.us.ccda", [forResource(".../CarePlanAct", [swapBinding({ "<nlm>": "<v3-xDocumentActMood>" })])]),
  patchCodeSystem("http://hl7.org/fhir/bundle-type", ["bundle", "subscription-notification"]),
] }

kbv, norge, and ccda have no preprocessPackage left.

Notes

  • Pins CM to 0.0.24-canary… (the published build with the patches API) — interim; repin to the proper release once CM minor fixes for Type Schema Writing  #14 ships.
  • Follow-up: P1.7 — surface manager.report() in prettyReport.

Verification

  • Standard suite 238/0; cda 9/0; local-package 17/0.
  • test-on-the-fly-example (kbv 5/0, norge 3/0) and test-typescript-ccda-example (24/0) green — all three examples regenerate (Status: Success) and their generated code typechecks.
  • make all is green up to the pre-existing sql-on-fhir "Library not found" failure (fixed separately in PR API: fix SQL-on-FHIR generation by adding the missing hl7.fhir.r5.core dependency #175; unrelated to Phase 1) — it aborts there, so the example targets above were run directly to validate.

ryukzak added 14 commits June 5, 2026 14:36
Adds an optional `patches?: Partial<Patches>` constructor option, passed to the
CanonicalManager config; warns if set alongside an injected manager/register
(which owns its own patch wiring). No example changes yet.
…on (P1.1)

New src/api/patches/ helper module with injectDependency(match, deps) — a
PackagePatch that adds missing FHIR package dependencies to a matching manifest.
Migrates the dependency-injection blocks of the kbv-r4 and norge-r4 examples off
preprocessPackage onto CM's patches config (kbv's preprocessPackage is fully
removed; norge keeps its rename + resource fixes for P1.2/P1.3). Generated code
typechecks and example tests pass.
Switches @atomic-ehr/fhir-canonical-manager from 0.0.24 to the canary build that
ships the composable patches runtime, so the Phase-1 patch helpers resolve against
a published version (not a local link). To be repinned to the proper release once
CM #14 ships.
renamePackage(renames) — a PackagePatch that fixes manifest-name typos via an
old→new map. Migrates norge-r4's packageNameFixes off preprocessPackage onto
patches; norge's preprocessPackage now only handles the gd-RelatedPerson resource
fix (P1.3 next). Generated code typechecks.
Adds scoped resource-phase URL-rewrite helpers (shared blanket replace + a
ResourceScope of package/url). Migrates norge's gd-RelatedPerson Person->Patient
fix (renameReferenceTarget) — norge's preprocessPackage is now fully gone — and
ccda's IVL_TS->IVL-TS canonical typo (renameCanonical) onto its manual CM's
patches config. Both examples regenerate successfully; norge generated code
typechecks. ccda keeps preprocessPackage for CarePlanAct + bundle-type (P1.4/P1.5).
…1.5)

swapBinding(swaps, scope?) — swap a binding's ValueSet URL for an available one
(scoped URL replace). patchCodeSystem(url, codes) — add missing codes to a
CodeSystem. Migrates ccda's CarePlanAct ValueSet swap and bundle-type missing
codes; ccda's preprocessPackage is now fully removed. All three examples
(kbv/norge/ccda) regenerate successfully and their generated code typechecks.
…P1.6)

Adds nesting scope combinators forPackage(match, handlers) and forResource(url,
handlers); the transform helpers (injectDependency/renameCanonical/
renameReferenceTarget/swapBinding) drop their scope args and are scoped by the
combinators instead. APIBuilder.patches now accepts a single handler or a list
per phase (PatchesInput), normalized to CM's array form. Restyles all three
examples to the grouped/nested form, e.g.

  patches: { package: forPackage("de.basisprofil.r4", [injectDependency({ "hl7.fhir.r4.core": "4.0.1" })]) }

All three examples regenerate (Status: Success) and tests pass (kbv 5/0,
norge 3/0, ccda 24/0).
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant