Skip to content

feat!: implement new plugins spec #168

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 2 commits into from
Feb 7, 2025
Merged

feat!: implement new plugins spec #168

merged 2 commits into from
Feb 7, 2025

Conversation

bowheart
Copy link
Collaborator

@bowheart bowheart commented Feb 7, 2025

@affects atoms, react, stores

Description

Implement the Zedux v2 plugin spec as per #119 with a few modifications after digging in:

No Ecosystem#send()

After starting to implement it, I realized the logic was 100% duplicated from signal events and worse, the events are harder to type at the ecosystem level. It would require new APIs, new docs, and duplicated code to accomplish something worse than what Zedux can already do.

The new recommendation is that addons create one or more atoms. Users can then either import those atom templates directly from the addon package to get() them or or use ecosystem.findAll('@my-addon-namespace'). As atoms, they'll be automatically fully typed. No new cruft.

The Events

The ecosystem events are:

  • change - fires whenever a signal(/atom)/selector change event fires
  • cycle - fires whenever a signal(/atom)/selector cycle event fires
  • invalidate - fires whenever an atom invalidate event fires
  • promiseChange - fires whenever an atom promiseChange event fires
  • edge - fires when an edge is added, removed, or updated (the event.action property denotes which)
  • error - fires when any atom or selector evaluation errors or an atom promise rejects
  • resetStart - fires when the ecosystem begins reset or destruction (the event.isDestroy property denotes which)
  • resetEnd - fires when the ecosystem finishes reset or destruction (the event.isDestroy property denotes which)
  • runStart - fires when an atom, mapped signal, or selector starts evaluating
  • runEnd - fires when an atom, mapped signal, or selector finishes evaluating

I debated a lot whether the edge event should be broken out into separate edgeAdd, edgeUpdate, edgeRemove events. I decided against it because those events should rarely be listened to - they're really only for full-on dev tools. And it's a slight micro-optimization for the dev tools to only register one event listener for those events instead of three.

Breaking Changes

These APIs have been removed:

  • Ecosystem#registerPlugin
  • Ecosystem#unregisterPlugin
  • Ecosystem#modBus
  • Ecosystem#_mods
  • The ZeduxPlugin class
  • The pluginActions object (accessed via the static ZeduxPlugin.actions property)

Additional Notes

The concept of a "plugin" is gone, really. I've stopped referring to these as plugins. They're simply "ecosystem events". Addon packages will typically listen to some ecosystem events and/or export some injectors/atoms/selectors.

The old store-based AtomInstance class in @zedux/stores does not fire some of the new events. I think it's unlikely people will need them to, at least initially. We can add those later if there's a demand for them.

I'm now planning on removing ecosystem.destroy() when the internalStore is removed. That will remove its primary function and make it sound misleading - ecosystem.destroy() will no longer put the ecosystem in a state where you can no longer use it. It's simply a reset that doesn't call onReady after resetting. Instead, .reset will take new parameters that tell it whether to remove ecosystem event listeners and/or not reInitialize. When that happens, the isDestroy property of reset events will go away.

The onReady ecosystem config option itself can also go away now.

// instead of
const ecosystem = createEcosystem({
  onReady: ecosystem => ecosystem.getNode(myInitialAtom)
})

// we can now do
const initializeEcosystem = (ecosystem: Ecosystem) => ecosystem.getNode(myInitialAtom)
const ecosystem = createEcosystem()

initializeEcosystem(ecosystem)
ecosystem.on('resetEnd', () => initializeEcosystem(ecosystem))

This isn't too much more code and, especially combined with resetStart, gives more control. For example, you can now capture and restore certain values after reset.

I will probably remove it.

Issues

Resolves #119

@david-trumid david-trumid merged commit c5eb951 into master Feb 7, 2025
2 checks passed
@david-trumid david-trumid deleted the josh/v2-plugins branch February 7, 2025 16:35
@bowheart bowheart mentioned this pull request Feb 3, 2025
53 tasks
@bowheart bowheart added this to the Zedux v2 milestone Feb 11, 2025
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.

New Plugin System
2 participants