npm.io
6.1.0 • Published 8 months ago

@gravityforms/request

Licence
GPL-2.0-or-later
Version
6.1.0
Deps
5
Size
42 kB
Vulns
0
Weekly
0

@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/request

Exports

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

  1. Always use post for WordPress AJAX - handles FormData encoding automatically
  2. Include action and security nonce - required for WordPress AJAX handlers
  3. Use template literals for Hermes - clearer syntax that matches server expectations
  4. Use raw() for dynamic field names - prevents unwanted string quoting
  5. Check response?.data?.success - standard WordPress AJAX success pattern
  6. 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' );
    }
};

Keywords