Skip to content

TypeSchema/TS: introduce SnapshotProfileTypeSchema for the TS writer - #158

Merged
ryukzak merged 4 commits into
mainfrom
ts/snapshot-profile-type-schema
May 20, 2026
Merged

TypeSchema/TS: introduce SnapshotProfileTypeSchema for the TS writer#158
ryukzak merged 4 commits into
mainfrom
ts/snapshot-profile-type-schema

Conversation

@ryukzak

@ryukzak ryukzak commented May 12, 2026

Copy link
Copy Markdown
Collaborator

First PR in a sequence that moves profile method derivation from the TS writer into TypeSchema. This one only sets up the seam — no behavior change, output byte-identical.

New type

  • SnapshotProfileTypeSchema in src/typeschema/types.ts — a writer-ready profile shape with flat fields and merged extensions, tagged snapshotKind: "snapshot". Not part of the TypeSchema union (writer-internal value).
  • isSnapshotProfileTypeSchema guard.

New builder

  • src/typeschema/profile-snapshot.ts exports mkProfileSnapshot(tsIndex, profile). Today it wraps tsIndex.flatProfile() and tags the result; future PRs move method-derivation logic (factory info, slice defs, validation expressions) here.

TS writer migration

  • writer.ts:generateResourceModule builds the snapshot once per profile via mkProfileSnapshot instead of calling tsIndex.flatProfile inline.
  • All flatProfile: ProfileTypeSchema parameters across profile.ts / profile-slices.ts / profile-extensions.ts / profile-validation.ts become snapshot: SnapshotProfileTypeSchema.
  • ExtensionProfileInfo.flatProfile.snapshot.
  • tsProfileClassName / tsProfileModuleName / tsProfileModuleFileName widened to a structural { identifier: ProfileIdentifier } so they accept both raw profiles (used in generateProfileIndexFile) and snapshots. tsProfileModuleName now uses findLastSpecializationByIdentifier instead of findLastSpecialization, dropping its dependency on the TypeSchema union.

Verification

  • bun run typecheck clean
  • bunx biome check clean (only pre-existing warnings)
  • bun test 257/257 pass
  • R4 and US Core examples regenerate byte-identical

ryukzak added 4 commits May 20, 2026 16:07
…e index

Adds a writer-ready profile representation alongside the raw
ProfileTypeSchema. Snapshots are flattened (fields merged across the
hierarchy, extensions consolidated) and discriminated by
`identifier.kind === "profile-snapshot"`.

Type additions:
- SnapshotProfileIdentifier in the Identifier union.
- SnapshotProfileTypeSchema in the TypeSchema union.
- Guards: isSnapshotProfileIdentifier, isSnapshotProfileTypeSchema.
- Helper: snapshotIdentifier(id) — ProfileIdentifier → SnapshotProfileIdentifier.
- Export PrimitiveTypeSchema (was implicitly public via TypeSchema; the
  resolve overload signature now needs the name directly).

Index integration in mkTypeSchemaIndex:
- New `snapshotIndex` (parallel to nestedIndex) holds pre-built snapshots.
- Snapshots are eagerly built for every well-formed profile during index
  construction. Profiles whose hierarchy lacks a non-profile ancestor are
  skipped structurally via tryHierarchy + guard checks, so direct
  flatProfile callers still see the original exception path.
- New `collectSnapshotProfiles()` returns all built snapshots.
- `resolve` and `resolveType` route SnapshotProfileIdentifier (kind
  "profile-snapshot") to the snapshot store.
- Both functions are now overloaded — passing a specific identifier
  variant (Resource, Profile, Snapshot, Binding, ValueSet, Logical,
  Primitive, ComplexType; plus Nested for resolveType) narrows the
  return type without a cast. Implementation uses a named callable type
  (ResolveFn/ResolveTypeFn) to avoid circular type inference through
  TypeSchemaIndex.
- findLastSpecialization uses guard-based filter (skips both profile
  and profile-snapshot variants) so it composes when called via
  findLastSpecializationByIdentifier on a snapshot identifier.
- entityTree includes the "profile-snapshot" bucket so EntityTree stays
  exhaustive over Identifier["kind"].

Tree-shake short-circuit:
- treeShakeTypeSchema returns snapshots untouched (they're derived data;
  they never reach tree shaking in practice, but the typed switch needs
  to acknowledge them).
Pipes snapshots from the index through the writer end-to-end.

- writer.generate() now collects via tsIndex.collectSnapshotProfiles().
- generateResourceModule dispatches on isSnapshotProfileTypeSchema; the
  inline `tsIndex.resolve(...)` call inside the profile branch is gone —
  the iterated schema is already the snapshot.
- generateFhirPackageIndexFile and the per-package filter use
  isSnapshotProfileTypeSchema.
- generateProfileIndexFile signature takes SnapshotProfileTypeSchema[].
- resolveExtensionProfile resolves the snapshot via the overloaded
  resolve() — no cast — and returns it as `snapshot` on
  ExtensionProfileInfo (replacing the previous `flatProfile` field).
- All profile-generation helpers (factory info, slice defs, extension
  methods, validation, slice setters/getters) take
  `snapshot: SnapshotProfileTypeSchema` instead of `flatProfile: ProfileTypeSchema`.
- Name helpers (tsProfileModuleName/FileName/ClassName) narrow to
  SnapshotProfileTypeSchema. tsProfileModuleName switches to
  findLastSpecializationByIdentifier so it no longer depends on the
  TypeSchema union.

Drive-by: biome --write trimmed a redundant `!!canonicalUrl` (already
inside an `&&` chain).
@ryukzak
ryukzak force-pushed the ts/snapshot-profile-type-schema branch from 5c8b5f9 to 943a04d Compare May 20, 2026 14:08
@ryukzak
ryukzak merged commit 7dfdb09 into main May 20, 2026
37 checks passed
@ryukzak
ryukzak deleted the ts/snapshot-profile-type-schema branch May 20, 2026 18:05
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