Remove ember-modify-based-class-resource, derive from data instead - #193
Conversation
The Table was a class-based Resource. Two bundled copies of
ember-modify-based-class-resource register the same usable type twice, which
throws "type may not overlap with an existing usable" and blanks the page.
The table needs lifetime linking, not resources, so it is a plain class now:
`link(this, parent)` gives it the parent's owner and destruction, and every
value is derived from the config it was constructed with.
Preferences move from the `modify` hook to a cached getter, so a `preferences`
thunk that reads tracked data restores again on its own. Plugin instances now
survive that, instead of being thrown away whenever any consumed arg changed.
Breaking:
- `headlessTable` requires a parent object. The `@use headlessTable({...})`
form is gone.
- `table.args` is gone. Read `table.config`.
- The scroll container is no longer reset when the config changes.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
| */ | ||
| scrollContainerElement?: HTMLElement; | ||
| get #owner(): Owner | undefined { | ||
| const existing = getOwner(this); |
There was a problem hiding this comment.
link sets up teh owner, so we can getOwner + assert here, and return the owner, and no more
There was a problem hiding this comment.
Moved the assert into the owner getter, so plugins just reads it. Kept a fallback to the parent, because link alone does not cover every case.
A parent can receive its owner after the table is created. A class field initializes before setOwner runs on a manually constructed object, so link runs while getOwner(parent) is still undefined. 41 setups in the test suite do this:
ctx = new DefaultOptions(); // the table is built in a class field here
setOwner(ctx, this.owner);With getOwner(this) + assert and nothing else, that suite goes from 187 pass / 0 fail to 24 pass / 45 fail, every failure being The Table does not have an owner.
So the getter now is:
get #owner(): Owner {
let owner = getOwner(this);
if (!owner) {
owner = getOwner(this.#parent);
assert(`The Table does not have an owner. cannot create a plugin without an owner`, owner);
setOwner(this, owner);
}
return owner;
}Back to 187 pass / 0 fail. If you would rather drop the late-owner support and make those setups call setOwner before they build the table, say so and I will change the tests instead.
The plugins getter no longer asserts. The owner getter does, because that is where the lookup happens. `link` cannot be the only source of the owner. A parent can receive its owner after the table is created, since a class field initializes before `setOwner` runs on a manually constructed object. 41 test setups do exactly that. Reading the owner from the parent on first use covers them. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Removes
ember-modify-based-class-resourcefrom@universal-ember/table. TheTableis a plain class now, and every value is derived from the config that it was constructed with.This unblocks josemarluedke/frontile#415. Two bundled copies of
ember-modify-based-class-resourceregister the same usable type twice, which throwstype may not overlap with an existing usableand blanks the page. Apps no longer need the direct-dependency or Vite-alias workaround.What changed
Tableno longer extendsResource. The constructor takes(parent, config)and callslink(this, parent)fromreactiveweb/link, which gives the table the parent's owner and destroys it with the parent.modify()is gone.preferencesis a cached getter, so apreferencesthunk that reads tracked data restores again on its own.argsand rebuilt every plugin.ember-modify-based-class-resourceandember-resourcesare dropped fromdependencies. Nothing insrcimports either one.reactivewebbringsember-resourcesitself.Breaking changes
@use table = headlessTable({ ... })table = headlessTable(this, { ... })table.args.namedtable.configtable.resetScrollContainer()The two-argument
headlessTable(this, { ... })form is unchanged, so most consumers need no code change.frontileis one of them. The one-argument form asserts in development with a message that says what to do.Docs:
docs-app/src/templates/1-get-started/upgrading.gjs.md.Verification
pnpm turbo --filter test-app test: 187 pass, 0 fail. This covers the multi-table shared-preferences reactivity test, plus a new test for an owner that is assigned after construction.pnpm turbo lint: 4 packages pass, types and format included.pnpm turbo build:dist/-private/table.jsimportsreactivewebonly.Please label this
breaking.🤖 Generated with Claude Code