Skip to content

TypeSchema: kind-key the TypeSchemaIndex slot - #160

Closed
ryukzak wants to merge 1 commit into
mainfrom
ts/index-kind-keyed
Closed

TypeSchema: kind-key the TypeSchemaIndex slot#160
ryukzak wants to merge 1 commit into
mainfrom
ts/index-kind-keyed

Conversation

@ryukzak

@ryukzak ryukzak commented May 12, 2026

Copy link
Copy Markdown
Collaborator

Preparatory refactor for the SnapshotProfileTypeSchema work in #158.

Why

Today the index is Record<url, Record<pkg, TypeSchema>> — one entry per [url, package] slot. The upcoming SnapshotProfileTypeSchema shares url + package with the raw ProfileTypeSchema it's built from (they differ only by identifier.kind), so both can't live in the same slot. The current snapshot work (#158) sidesteps this with a parallel `snapshotIndex` — workable but adds bookkeeping.

This PR makes the slot kind-keyed so any future schema variant sharing url+package can coexist with its base. No current functional benefit; lands as pure preparation.

What

  • _schemaIndex shape: Record<url, Record<pkg, Partial<Record<kind, TypeSchema>>>>.
  • append() keys writes by identifier.kind; duplicate check moves to the kind-keyed slot.
  • resolve(id) and resolveType(id) look up by id.kind, with a fallback to whatever's at the slot when the requested kind isn't present. The fallback preserves pre-refactor behavior — some IRs (CDA, specifically) declare dependency identifiers with a different kind than the actual stored schema, and the old slot-only lookup tolerated that.
  • resolveByUrl picks the first entry from the slot (single kind today; the caller has no kind to disambiguate).

Verification

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

Restructures the index from `Record<url, Record<pkg, TypeSchema>>` to
`Record<url, Record<pkg, Partial<Record<kind, TypeSchema>>>>` so multiple
schemas can co-exist at the same url+package, discriminated by
`identifier.kind`. No current consumer benefits — every slot still holds
exactly one entry today — but this removes the URL/package collision that
would otherwise block storing additional kind variants alongside their
base.

- append() now keys the slot by identifier.kind; duplicate check moves to
  the kind-keyed slot.
- resolve() and resolveType() look up by id.kind, with a fallback to
  whatever's at the slot when the requested kind isn't present. The
  fallback preserves pre-refactor behavior: some IRs (e.g. CDA) declare
  dependency identifiers with a different `kind` than the actual stored
  schema, and the old slot-only lookup tolerated that.
- resolveByUrl picks the first entry from the slot (single kind today;
  caller has no kind to disambiguate).
@ryukzak
ryukzak force-pushed the ts/index-kind-keyed branch from 78d27ad to 1c3e1ab Compare May 13, 2026 13:27
@ryukzak

ryukzak commented May 20, 2026

Copy link
Copy Markdown
Collaborator Author

Closing — the separate `snapshotIndex` approach (in #158) is the better solution after reflection:

  • Mirrors the existing `nestedIndex` pattern that's already established for the same reason (URL collisions between parent specializations and their nested types).
  • Cleaner per-index types — no `Partial<Record<kind, TypeSchema>>` indirection layer at the storage level.
  • No need for the same-slot fallback workaround. That fallback was masking a real semantic: `resolve(id)` lookups that don't care about `kind` (and the CDA case where dependency identifiers carry a different `kind` than the stored schema). Treating that as the natural behavior of a slot-only index — rather than as a fallback inside a kind-keyed index — is more honest.
  • Reads stay simple — no fall-through logic in the hot path.

Snapshots will live in their own `snapshotIndex` parallel to `nestedIndex`. #158 already implements this.

@ryukzak ryukzak closed this May 20, 2026
@ryukzak
ryukzak deleted the ts/index-kind-keyed branch May 20, 2026 07:30
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