Skip to content
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
- [Using Abilities](docs/4.using-abilities.md)
- [REST API Reference](docs/5.rest-api.md)
- [Hooks](docs/6.hooks.md)
- [JavaScript/TypeScript Client](docs/7.javascript-client.md)
- [Contributing Guidelines](CONTRIBUTING.md)

## Inspiration
Expand Down
179 changes: 179 additions & 0 deletions docs/7.javascript-client.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,179 @@
# 7. JavaScript/TypeScript Client

The JavaScript client provides an interface for discovering and executing WordPress Abilities from the browser.

## Overview

The JavaScript client enables frontend code to interact with the Abilities API system. It can:

- Discover all registered abilities on your WordPress site
- Execute server-side PHP abilities
- Register and execute client-side JavaScript abilities

You can read more about installation and setup in the [package readme](../packages/client/README.md).

## Core API Functions

### getAbilities()

Returns an array of all registered abilities (both server-side and client-side).

**Parameters:** None

**Returns:** `Promise<Array>` - Array of ability objects

**Example:**

```javascript
import { getAbilities } from `@wordpress/abilities`;

const abilities = await getAbilities();
console.log(`Found ${abilities.length} abilities`);

// List all abilities
abilities.forEach(ability => {
console.log(`${ability.name}: ${ability.description}`);
});
```

### getAbility(name)

Retrieves a specific ability by name.

**Parameters:**
- `name` (string) - The ability name (e.g., 'my-plugin/get-posts')

**Returns:** `Promise<Object|null>` - The ability object or null if not found

**Example:**

```javascript
const ability = await getAbility('my-plugin/get-site-info');
if (ability) {
console.log('Label:', ability.label);
console.log('Description:', ability.description);
console.log('Input Schema:', ability.input_schema);
}
```

### executeAbility(name, input)

Executes an ability with the provided input data.

**Parameters:**
- `name` (string) - The ability name
- `input` (any, optional) - Input data for the ability

**Returns:** `Promise<any>` - The ability's output

**Example:**

```javascript
// Execute without input
const siteTitle = await executeAbility('my-plugin/get-site-title');
console.log('Site:', siteTitle);

// Execute with input parameters
const posts = await executeAbility('my-plugin/get-posts', {
category: 'news',
limit: 5
});
posts.forEach(post => console.log(post.title));
```

### registerAbility(ability)

Registers a client-side ability that runs in the browser.

**Parameters:**
- `ability` (object) - The ability configuration object

**Returns:** `void`

**Example:**

```javascript
// showNotification function
const showNotification = (message) => {
new Notification(message);
return { success: true, displayed: message };
}

// Register a notification ability which calls the showNotification function
registerAbility({
name: 'my-plugin/show-notification',
label: 'Show Notification',
description: 'Display a notification message to the user',
input_schema: {
type: 'object',
properties: {
message: { type: 'string' },
type: { type: 'string', enum: ['success', 'error', 'warning', 'info'] }
},
required: ['message']
},
callback: async ({ message, type = 'info' }) => {
// Show browser notification
if (!("Notification" in window)) {
alert("This browser does not support desktop notification");
return { success: false, error: 'Browser does not support notifications' };
}
if (Notification.permission !== 'granted') {
Notification.requestPermission().then((permission) => {
if (permission === "granted") {
return showNotification(message);
}
});
}
return showNotification(message);
},
permissionCallback: () => {
return !!wp.data.select('core').getCurrentUser();
}
});

// Use the registered ability
const result = await executeAbility('my-plugin/show-notification', {
message: 'Hello World!',
type: 'success'
});
```

### unregisterAbility(name)

Removes a previously registered client-side ability.

**Parameters:**
- `name` (string) - The ability name to unregister

**Example:**

```javascript
// Unregister an ability
unregisterAbility('my-plugin/old-ability');
```

## Error Handling

All functions return promises that may reject with specific error codes:

```javascript
try {
const result = await executeAbility('my-plugin/restricted-action', input);
console.log('Success:', result);
} catch (error) {
switch (error.code) {
case 'ability_permission_denied':
console.error('Permission denied:', error.message);
break;
case 'ability_invalid_input':
console.error('Invalid input:', error.message);
break;
case 'rest_ability_not_found':
console.error('Ability not found:', error.message);
break;
default:
console.error('Execution failed:', error.message);
}
}
```