-
Notifications
You must be signed in to change notification settings - Fork 18
Add client-only ability registration #69
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
Conversation
The following accounts have interacted with this PR and/or linked issues. I will continue to update these lists as activity occurs. You can also manually ask me to refresh this list by adding the If you're merging code through a pull request on GitHub, copy and paste the following into the bottom of the merge commit message.
To understand the WordPress project's expectations around crediting contributors, please review the Contributor Attribution page in the Core Handbook. |
Codecov Report❌ Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## add/client-library #69 +/- ##
========================================================
+ Coverage 77.89% 81.78% +3.88%
Complexity 103 103
========================================================
Files 9 15 +6
Lines 552 741 +189
Branches 0 75 +75
========================================================
+ Hits 430 606 +176
- Misses 122 135 +13
Flags with carried forward coverage won't be shown. Click here to find out more. ☔ View full report in Codecov by Sentry. 🚀 New features to boost your workflow:
|
Do we need permission callbacks on the client as well?
Probably the best choice. Curious, how big does this make the bundle?
What do mean with "already part of the ecosystem"? It's a mere dev dependency in Gutenberg for use in some tests. It's not in any of the published packages. That's a big difference and not really an argument for picking this dependency. |
ce5aa40
to
082dfdf
Compare
It's also used in WordPress Playground and a few other utils too. I included it to say we have opted to use it in other places, which to me is worth considering over another package. I haven't looked at the bundle size (yet), but I personally think it is worth it instead of needing to hit a |
I was thinking about this as well and it's worth discussing. I think it would be nice to avoid needing to hit the REST API for running these, but maybe just providing a callback is enough? I'm open to ideas here! |
https://bundlephobia.com/package/[email protected] ![]() It's a very reasonable size for the functionality it provides. In the long run we could reuse the logic in Gutenberg to validate block attributes schema in the development mode.
It looks like on the server, we will enforce permission callbacks to increase the security as explained by @johnbillion in: It still might be valuable to have a way to define permission callbacks that checks whether a user can do something in the UI that's only for priviliged users so they have more streamlined experience. Otherwise we risk AI shows too often an message about failed attempe to do something it is not allowed to do. Similarily, @galatanovidiu in this comment #62 (comment) proposed a new property that does more high-level checks whether certain abilities should be filtered out if it's known upfront (without providing specific input) they aren't allowed to use them. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is shaping up nicely. I left my feedback for consideration and to better understand some decisions made.
43ed397
to
fabe5af
Compare
e6510f5
to
398612b
Compare
398612b
to
36da8ae
Compare
Regarding permissions, I have added a permissionCallback in f7a3dd2. It will run before an ability is executed. The implementation is intentionally left up to the user. This could be a simple JS based check, or they could hit the API or use nonces. The server permission callback will also still run when the REST API endpoint is called. |
All PR feedback has been handled correctly now. I'll continue fixing the tests and any other things pointed out in #70. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
All the feedback I shared was addressed. It looks good to land from my side.
* Add testing & linting infa * Remove uncessary combined checks * Add client tests * test: Use proper TypeScript types instead of 'as any' in tests * Fix typescript check for extra server check * test: update tests for client-only abilities API changes * chore: add build:client and dev:client scripts to root package.json * fix: formatting * fix: prettier issues * fix: apply Prettier formatting to README and validation.ts * deps: remove @types/wordpress__api-fetch since types are already shipped * fix: move validation to the store * fix: validate ability name uses same format as server * tests: clean up CI checks * deps: fix dev dependencies and remove extra package-lock.json * fix: rename main dev and build commands * fix: better match server validation rules for schema * Fix remaining validation issues Co-authored-by: emdashcodes <[email protected]> Co-authored-by: gziolo <[email protected]> Co-authored-by: justlevine <[email protected]> Co-authored-by: jonathanbossenger <[email protected]>
This PR follows up on #60 and introduces client-side only abilities. This allows for new integrations that deal with things like UI elements, navigation, and client-side data (such as the block editor). In addition to our AI efforts, it's also meant as a way that the command palette can execute client-side abilities in the future.
It adds two new methods to manage the client-only abilities
registerAbility
andunregisterAbility
.registerAbility
takes the same shape aswp_register_ability
in addition to a client side callback function. A callback can take the providedinput_schema
, do an action, and return the providedoutput_schema
.Here is a simple example:
unregisterAbility
is a convenience method for removing client-side only abilities.Client-side abilities are saved in the store alongside server-side ones. They are marked specifically with a location property which is used to either call the callback or call the REST endpoint.
The input and output schemas are validated using Ajv and the
ajv-formats
plugin.I have configured Ajv to support the intersection of rules that JSON Schema draft-04, WordPress (a subset of JSON Schema draft-04), and providers like OpenAI and Anthropic support.
Ajv is already in use by Gutenberg so it is already part of the ecosystem.
Testing
I have created a dummy plugin that registers a few different abilities as an example: client-abilities-demo.zip
Open the developer console and paste the following:
await wp.abilities.listAbilities()
You should see the client side abilities (and any other server side abilities you registered) listed.
Paste in the following:
await wp.abilities.executeAbility('demo/get-current-user')
See that you get a simple user response object back.
Paste in the following:
See that you are redirected to the users.php screen.
Paste in the following:
See that a UI notice briefly shows on the user page.
Now we can test registering and unregistering our own ability:
Now test the ability:
See that the various responses and different console types are executed.
To test the validation, you can change the return type and see what happens if you try to return a different type or something invalid against the schema.
Finally, you can unregister the client-side ability:
wp.abilities.unregisterAbility('demo/console-log');
. Trying to execute it again will throw an error.Next Steps (not addressed in this PR)
Tests & CI setup for the whole client package have been added in #70