@gravityforms/request
v6.1.0
Published
Utility to make WordPress REST API requests. It's a wrapper around window.fetch.
Readme
@gravityforms/request
HTTP request utilities for Gravity Forms products. Provides wrappers around window.fetch for common use cases including WordPress AJAX and the Hermes GraphQL-like API.
Installation
npm install @gravityforms/requestExports
| Export | Description |
|--------|-------------|
| get | Simple GET request wrapper |
| post | POST request with automatic form data encoding |
| createHermesClient | Factory for Hermes API client with template literals |
| serialize | Serialize JavaScript values for Hermes queries |
| raw | Mark strings for raw insertion without serialization |
| args | Helper for object argument serialization (combines raw + serialize) |
| request (default) | Configuration-based request handler |
post
The most commonly used export. Makes POST requests to WordPress AJAX endpoints with automatic form data encoding.
Usage
import endpoint from 'ajaxUrl'; // Webpack alias for WordPress ajaxurl
import { post } from '@gravityforms/request';
const saveData = async ( data ) => {
const response = await post( {
endpoint,
body: {
action: 'my_ajax_action',
security: window.myPlugin.nonce,
...data,
},
} );
if ( response?.data?.success ) {
console.log( 'Saved:', response.data );
} else {
console.error( 'Error:', response?.error || response?.data );
}
};Parameters
| Parameter | Type | Description |
|-----------|------|-------------|
| endpoint | string | The URL to POST to |
| body | object | Request body (automatically converted to FormData) |
| headers | object | Optional HTTP headers |
| options | object | Optional fetch options |
Response
{
data: { ... }, // Parsed JSON response
status: 200, // HTTP status code
}
// Or on error:
{
error: Error // Error object with .detail property
}get
Simple GET request wrapper.
Usage
import { get } from '@gravityforms/request';
const fetchData = async () => {
const response = await get( '/wp-json/my/v1/endpoint', {
headers: { 'X-Custom-Header': 'value' },
} );
return response.json();
};Parameters
| Parameter | Type | Description |
|-----------|------|-------------|
| endpoint | string | The URL to fetch |
| params | object | Optional fetch options |
Hermes Client
For interacting with the Hermes GraphQL-like API. Uses template literals for intuitive query construction.
createHermesClient
Creates a configured client with query and mutation functions.
import { createHermesClient, serialize, raw, args } from '@gravityforms/request';
const client = createHermesClient( {
endpoint: window.ajaxurl,
queryAction: 'gcrm_hermes_query',
mutationAction: 'gcrm_hermes_mutation',
security: window.gcrm.nonce,
onLoadingChange: ( isLoading ) => {
// Optional: track loading state
},
} );Configuration Options
| Option | Type | Required | Description |
|--------|------|----------|-------------|
| endpoint | string | Yes | AJAX endpoint URL |
| queryAction | string | Yes | WordPress action for queries |
| mutationAction | string | Yes | WordPress action for mutations |
| security | string | Yes | Security nonce |
| queryKey | string | No | Body key for queries (default: 'query') |
| mutationKey | string | No | Body key for mutations (default: 'mutation') |
| headers | object | No | Custom headers for all requests |
| options | object | No | Custom fetch options |
| onLoadingChange | function | No | Callback when loading state changes |
Query Examples
const { query, mutation } = client;
// Simple query
const contacts = await query`{
contact(limit: 10) {
id,
firstName,
lastName
}
}`;
// Query with interpolated values
const limit = 20;
const searchTerm = 'John';
const results = await query`{
contact(limit: ${ limit }, search: ${ searchTerm }) {
id,
firstName,
lastName,
email { address, isPrimary }
}
}`;
// Query with nested relationships
const deals = await query`{
deal(limit: ${ 50 }) {
id,
label,
value,
contact {
id,
firstName,
lastName
},
company {
id,
companyName
}
}
}`;Mutation Examples
// Insert
const newContact = await mutation`{
insert_contact(objects: ${ [ { firstName: 'John', lastName: 'Doe' } ] }) {
returning {
id,
firstName,
lastName
}
}
}`;
// Update
const contactId = '123';
await mutation`{
update_contact(id: ${ contactId }, firstName: "Jane", lastName: "Smith") {}
}`;
// Delete
const idsToDelete = [ '1', '2', '3' ];
await mutation`{
delete_contact(id: ${ idsToDelete }) {}
}`;
// Connect relationships
await mutation`{
connect_company_contact(objects: ${ [ { from: companyId, to: contactId } ] }) {}
}`;
// Disconnect relationships
await mutation`{
disconnect_company_contact(objects: ${ [ { from: companyId, to: contactId } ] }) {}
}`;serialize
Converts JavaScript values to Hermes query format. Used automatically in template literals but can be called directly for complex cases.
Type Handling
| JavaScript Type | Hermes Output |
|-----------------|---------------|
| null / undefined | null |
| boolean | true / false |
| number | 123 |
| string | "quoted string" |
| array | [item1, item2] |
| object | {key: value} |
Examples
import { serialize } from '@gravityforms/request';
serialize( 'hello' ); // "hello"
serialize( 42 ); // 42
serialize( true ); // true
serialize( null ); // null
serialize( [ 1, 2, 3 ] ); // [1, 2, 3]
serialize( { name: 'John' } ); // {name: "John"}args
Convenience function for building query/mutation argument strings from JavaScript objects. Combines serialize() and raw() for the common argument-building pattern.
Usage
import { args } from '@gravityforms/request';
// Instead of building argument strings manually:
const argsStr = Object.entries({ limit: 10, search: 'test' })
.map(([k, v]) => `${k}: ${serialize(v)}`)
.join(', ');
await query`{ contact(${ raw( argsStr ) }) { ... } }`;
// Use args() for cleaner syntax:
await query`{ contact(${ args({ limit: 10, search: 'test' }) }) { ... } }`;raw
Marks a string for raw insertion without serialization. Use this when you've pre-built an argument string.
Problem
// Without raw() - becomes: pipeline("limit: 1") - WRONG!
const argsStr = 'limit: 1';
await query`{ pipeline(${ argsStr }) { id } }`;Solution
import { raw } from '@gravityforms/request';
// With raw() - becomes: pipeline(limit: 1) - CORRECT!
const argsStr = 'limit: 1';
await query`{ pipeline(${ raw( argsStr ) }) { id } }`;Common Use Cases
// Dynamic argument strings
const buildArgs = ( filters ) => {
const parts = [];
if ( filters.limit ) parts.push( `limit: ${ filters.limit }` );
if ( filters.search ) parts.push( `search: ${ JSON.stringify( filters.search ) }` );
return parts.join( ', ' );
};
const argsStr = buildArgs( { limit: 20, search: 'test' } );
await query`{ contact(${ raw( argsStr ) }) { id, firstName } }`;
// Dynamic field/type names
const objectType = 'contact';
await mutation`{
delete_${ raw( objectType ) }(id: ${ ids }) {}
}`;
// Dynamic field names with serialize for values
const fieldName = 'firstName';
const value = 'John';
await mutation`{
update_contact(id: ${ id }, ${ raw( fieldName ) }: ${ value }) {}
}`;request (Default Export)
Configuration-based request handler. Requires endpoint configuration in gravityforms.config.js.
Configuration
In your project's gravityforms.config.js:
module.exports = {
requestConfig: {
endpoints: {
get_entries: {
path: '/wp-json/gf/v2/entries',
rest_params: '',
nonce: null,
},
save_form: {
path: '/wp-json/gf/v2/forms',
action: 'gf_save_form',
nonce: null,
},
},
},
};Usage
import request from '@gravityforms/request';
// GET request
const entries = await request( 'get_entries', endpoints, {
method: 'GET',
params: { form_id: 1 },
} );
// POST request
const result = await request( 'save_form', endpoints, {
method: 'POST',
body: { title: 'My Form', fields: [ ... ] },
} );React Integration
For React applications, use @gravityforms/react-utils which provides hooks and context:
import { useHermesTemplateContext, HermesTemplateProvider } from '@gravityforms/react-utils';
// In your app root
<HermesTemplateProvider
defaultProps={ {
endpoint: window.ajaxurl,
queryAction: 'gcrm_hermes_query',
mutationAction: 'gcrm_hermes_mutation',
security: window.gcrm.nonce,
} }
>
<App />
</HermesTemplateProvider>
// In components
const MyComponent = () => {
const { query, mutation, isLoading } = useHermesTemplateContext();
const fetchContacts = async () => {
const result = await query`{
contact(limit: 10) { id, firstName, lastName }
}`;
return result?.data?.data?.contact;
};
};Error Handling
All request functions return errors in a consistent format:
const response = await post( { endpoint, body } );
if ( response.error ) {
// Network error or exception
console.error( response.error.message );
console.error( response.error.detail ); // Contains endpoint, status, etc.
} else if ( ! response.data?.success ) {
// Server returned an error response
console.error( 'Request failed:', response.data );
} else {
// Success
console.log( 'Data:', response.data );
}Best Practices
- Always use
postfor WordPress AJAX - handles FormData encoding automatically - Include action and security nonce - required for WordPress AJAX handlers
- Use template literals for Hermes - clearer syntax that matches server expectations
- Use
raw()for dynamic field names - prevents unwanted string quoting - Check
response?.data?.success- standard WordPress AJAX success pattern - Provide user feedback - use snackbar or similar for success/error messages
import { post } from '@gravityforms/request';
import { useSnackbar } from '@gravityforms/components/react/admin/modules/SnackBar';
const addSnackbarMessage = useSnackbar();
const saveItem = async ( data ) => {
const response = await post( {
endpoint,
body: {
action: 'my_action',
security: nonce,
...data,
},
} );
if ( response?.data?.success ) {
addSnackbarMessage( 'Saved successfully!' );
} else {
addSnackbarMessage( 'Failed to save', 'error' );
}
};