ecs: schema-based ArchetypeRowOf/ArchetypeHandleOf for stripInternal services#123
Open
krisnye wants to merge 1 commit into
Open
ecs: schema-based ArchetypeRowOf/ArchetypeHandleOf for stripInternal services#123krisnye wants to merge 1 commit into
krisnye wants to merge 1 commit into
Conversation
…ernal services Consumers that keep a hand-written public service interface (not Database.Plugin.ToDatabase<typeof plugin>) and mark the plugin database type @internal could not name their public archetype rows: referencing the plugin db type serializes typeof plugin into the emitted .d.ts (TS7056), and deriving from the @internal type leaves a dangling reference to the stripped symbol (TS2305) — declaration emit never resolves a row *through* an @internal symbol, it preserves the reference. Add ArchetypeSchema / ArchetypeRowOf / ArchetypeHandleOf, which resolve an archetype's row from a small *public* schema ({ components, archetypes }) rather than the plugin database type. The emitted type then references only public symbols: no plugin type, no @internal symbol, self-contained, and downstream rows resolve to concrete columns. Add an end-to-end emit acceptance gate (scripts/emit-stripinternal, `pnpm check:emit`): emits a stripInternal fixture and type-checks a downstream consumer, asserting no TS7056, the @internal plugin/db type is stripped, the service .d.ts is self-contained, and rows resolve to exact concrete columns. The README documents the pattern plus the declaration-emit footguns surfaced while building the gate (reference the handle inline; no fenced code blocks in JSDoc above an exported type; don't let the schema be a module's lone export). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Description
Lets a consumer that keeps a hand-written public service interface (not
type Service = Database.Plugin.ToDatabase<typeof plugin>) and marks the plugin database type@internalderive its public archetype-handle types sodb.archetypesis assignable with no cast — and emit cleanly understripInternal: true.Why
Database.Archetype.RowOf(#122) doesn't cover thisDatabase.Archetype.RowOf<S, K>derives from the plugin database type. When that type is@internal(kept small / hides internals), declaration emit breaks two ways:typeof plugininto the consumer's.d.ts.@internal→ dangling/dropped. TypeScript never resolves a row through a stripped symbol — it preserves the reference, leaving a danglingimport type { … }→ downstream TS2305.I verified empirically that no extractor form can force inlining through an
@internalsymbol (named alias, inline anonymous, and deep-Expandall either dangle or get dropped). The only sound path is to reference a public symbol.What this adds
ArchetypeSchema/ArchetypeRowOf/ArchetypeHandleOf(insrc/ecs/store/archetype-row.ts) resolve an archetype's row from a small public schema ({ components, archetypes }) rather than the plugin database type — the same row asdb.archetypes[K], but the emitted type references only public symbols.db.archetypes.Track(from the@internaldb) assigns toTrackService["archetypes"]["Track"]with no cast; downstream resolvesTrackto its concrete columns.Acceptance gate
scripts/emit-stripinternal(pnpm check:emit) emits astripInternalfixture and type-checks a downstream consumer, asserting: no TS7056; the@internalplugin + db type are stripped; the service.d.tsis self-contained (no plugin/@internalreference, small); and rows resolve to exact concrete columns via a mutual-assignability gate (no dangling import).The README documents the pattern plus the declaration-emit footguns surfaced while building the gate (reference the handle inline; no fenced
```tsblocks withimport/export/interfacein JSDoc above an exported type; don't let the schema be a module's lone export).Verification
tsc -bclean; eslint clean; full suite (2531 tests) green.node scripts/emit-stripinternal/check.mjs→ PASS (all 9 assertions).Related PRs
Follows #122 (
Database.Archetype.RowOffor derived service types).