Skip to content

feat(ecs): surface base-plugin computeds inside derived computed factories#124

Merged
krisnye merged 5 commits into
mainfrom
krisnye/computed-db
Jun 9, 2026
Merged

feat(ecs): surface base-plugin computeds inside derived computed factories#124
krisnye merged 5 commits into
mainfrom
krisnye/computed-db

Conversation

@krisnye

@krisnye krisnye commented Jun 9, 2026

Copy link
Copy Markdown
Collaborator

Description

FullDBForPlugin hardcoded the computed-factory db's computed slot (CV) to unknown, which erased the extends / imports base's already-resolved computeds — not just the current plugin's in-progress ones. As a result, a derived plugin's computed factory could not compose on a base plugin's computed.

This PR sets that slot to FromComputedFactories<XP['computed']>. XP is AmbientPlugin<XP, IP> at the call sites, so it surfaces the base + imports computeds (all fully constructed — no circularity). The current plugin's own CVF is never a parameter to the type, so in-progress siblings stay hidden — the same rule actions/systems already follow.

const base = createPlugin({
  resources: { n: { default: 10 } },
  computed: { doubled: (db) => Observe.withMap(db.observe.resources.n, (v) => v * 2) },
});

const derived = createPlugin({
  extends: base,
  computed: {
    // now fully typed — previously db.computed was `unknown`
    quadrupled: (db) => Observe.withMap(db.computed.doubled, (v) => v * 2),
  },
});

Also

  • Added type-tests for both directions: base composition works; an in-progress sibling stays hidden.
  • Dropped Database.Plugin.ToComputedDb (introduced earlier in this branch). It was a computed: unknown mirror of the old factory context; now that factories see the base's resolved computeds it no longer mirrors anything, and its residual "strip computed" use is a near-duplicate of ToDatabase. The rare call site can use Omit<ToDatabase<P>, 'computed'> inline.
  • Version bump to 0.9.68.

Verification

  • tsc -b clean (incl. @ts-expect-error assertions in the new tests)
  • pnpm lint clean
  • Full @adobe/data suite: 2584 passed

krisnye and others added 3 commits June 9, 2026 08:34
…thout Omit hack

bump: 0.9.68

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…ories

FullDBForPlugin hardcoded the computed-factory db's CV slot to `unknown`,
which erased the extends/imports base's already-resolved computeds — not
just the current plugin's in-progress ones. A derived plugin's computed
factory therefore could not compose on a base plugin's computed.

Set CV to FromComputedFactories<XP['computed']>. XP is AmbientPlugin<XP, IP>
at the call sites, so this surfaces the base + imports computeds (all fully
constructed — no circularity). The current plugin's own CVF is never a
parameter to this type, so in-progress siblings stay hidden, matching the
rule actions/systems already follow.

Adds type-tests for both directions (base composition works; sibling stays
hidden) and corrects the ToComputedDb doc now that factories see base
computeds rather than `unknown`.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
With computed factories now seeing the base plugin's resolved computeds,
the computed-erased alias no longer mirrors the factory context — the db a
factory receives is no longer `computed: unknown`. Its only residual use
(strip computed to break a type cycle) is speculative, has no consumer, and
is a near-duplicate of ToDatabase; the rare call site can write
`Omit<ToDatabase<P>, 'computed'>` inline.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
@krisnye krisnye changed the title feat(ecs): export Database.Plugin.ToComputedDb feat(ecs): surface base-plugin computeds inside derived computed factories Jun 9, 2026
krisnye and others added 2 commits June 9, 2026 09:08
`pnpm run lint` / `pnpm run typecheck` now work from the repo root
(recursive, matching the existing `build`/`test` pattern) — no need to know
which package to cd into. Removed the phantom `lint` scripts from data-sync
and data-persistence: they had no eslint config or dependency and always
errored, which would otherwise break the recursive root lint. CI already
lints only @adobe/data, so nothing relied on them.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…cleanly

Adds a compile-time test for a common app pattern: computed factories
authored as standalone functions (annotated with the exported
`Database.Plugin.ToDatabase<typeof basePlugin>`) aggregated into one
`computed: {}` block in a createPlugin call. Covers a plain resource read, a
factory composing on a base computed, and a parameterized computed; asserts
the aggregated result types exactly, with no `Omit` and no cast.

Verified load-bearing: reverting the FullDBForPlugin CV slot to `unknown`
breaks this exact assignment with TS2322 (`unknown` not assignable to the
factory's `computed`), which is the contravariance failure that forced the
old `Omit<ToDatabase<...>, 'computed'>` workaround.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
@krisnye krisnye force-pushed the krisnye/computed-db branch from 6d6f466 to 8734bbf Compare June 9, 2026 16:17
@krisnye krisnye merged commit 4a4e7e0 into main Jun 9, 2026
3 checks passed
@krisnye krisnye deleted the krisnye/computed-db branch June 9, 2026 16:20
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