
Security News
The Hidden Blast Radius of the Axios Compromise
The Axios compromise shows how time-dependent dependency resolution makes exposure harder to detect and contain.
@datadog/apps-function-query
Advanced tools
Simple, type-safe client for executing backend functions in Datadog Apps. Designed to work seamlessly with react-query or any state management solution.
npm install @datadog/apps-function-query react-query
# or
yarn add @datadog/apps-function-query react-query
This package provides a single, focused function executeBackendFunction that:
/__dd/executeActionimport { useQuery } from 'react-query';
import { executeBackendFunction } from '@datadog/apps-function-query';
interface TestResult {
sum: number;
}
function MyComponent() {
const { data, isLoading, error } = useQuery(['testWithImport', 5, 7], () =>
executeBackendFunction<TestResult, [number, number]>(
'testWithImport',
[5, 7],
),
);
if (isLoading) return <div>Loading...</div>;
if (error) return <div>Error: {error.message}</div>;
return <div>Sum: {data?.sum}</div>;
}
executeBackendFunction<TData, TArgs>(functionName, args)Executes a backend function by sending a POST request to /__dd/executeAction.
TData: The return type of the backend functionTArgs (optional): A tuple type for the function arguments (e.g., [string, number])functionName (string): The name of the backend function to executeargs (TArgs): Array of arguments to pass to the functionReturns a Promise<TData> that resolves to the function's return value.
BackendFunctionError: When the request fails or the function returns an errorimport { executeBackendFunction } from '@datadog/apps-function-query';
// Direct function call (without React)
async function calculate() {
try {
const result = await executeBackendFunction<
{ sum: number },
[number, number]
>('testWithImport', [5, 7]);
console.log('Sum:', result.sum); // 12
} catch (error) {
console.error('Failed:', error);
}
}
import { useQuery, useMutation } from 'react-query';
import { executeBackendFunction } from '@datadog/apps-function-query';
// Query example
function UserProfile({ userId }: { userId: string }) {
const { data, isLoading } = useQuery(['user', userId], () =>
executeBackendFunction<UserData, [string]>('getUser', [userId]),
);
if (isLoading) return <div>Loading...</div>;
return <div>{data?.name}</div>;
}
// Mutation example
function CreateUserForm() {
const mutation = useMutation((newUser: CreateUserRequest) =>
executeBackendFunction<CreateUserResult, [CreateUserRequest]>(
'createUser',
[newUser],
),
);
return (
<button
onClick={() =>
mutation.mutate({
name: 'John',
email: 'john@example.com',
})
}
>
Create User
</button>
);
}
import { useQuery } from 'react-query';
import { executeBackendFunction } from '@datadog/apps-function-query';
function LiveData() {
const { data } = useQuery(
['liveData'],
() => executeBackendFunction<DataResult>('getLiveData', []),
{
refetchInterval: 5000, // Refetch every 5 seconds
retry: 3, // Retry 3 times on failure
},
);
return <div>Value: {data?.value}</div>;
}
import { useQuery } from 'react-query';
import { executeBackendFunction } from '@datadog/apps-function-query';
function UserPosts({ userId }: { userId?: string }) {
// Only fetch user when userId is available
const { data: user } = useQuery(
['user', userId],
() => executeBackendFunction<User, [string]>('getUser', [userId!]),
{ enabled: !!userId },
);
// Only fetch posts after user is loaded
const { data: posts } = useQuery(
['posts', user?.id],
() =>
executeBackendFunction<Post[], [string]>('getUserPosts', [
user!.id,
]),
{ enabled: !!user },
);
return <div>{posts?.length} posts</div>;
}
import { useQuery } from 'react-query';
import { executeBackendFunction } from '@datadog/apps-function-query';
function SearchResults({ searchTerm }: { searchTerm: string }) {
const { data, refetch } = useQuery(
['search', searchTerm],
() =>
executeBackendFunction<SearchResult, [string]>('search', [
searchTerm,
]),
{
enabled: false, // Don't run automatically
},
);
return (
<div>
<button onClick={() => refetch()}>Search</button>
{data && <div>Results: {data.items.length}</div>}
</div>
);
}
Full type safety for both return types and arguments:
interface UserData {
id: string;
name: string;
email: string;
}
// ✅ Correct usage
const { data } = useQuery(['user', 'user-123'], () =>
executeBackendFunction<UserData, [string]>('getUser', ['user-123']),
);
// TypeScript knows data is UserData | undefined
console.log(data?.name); // ✅ OK
console.log(data?.foo); // ❌ Error: Property 'foo' does not exist
// ❌ Type error - wrong argument type
const { data: invalid } = useQuery(
['add', 5, '7'],
() => executeBackendFunction<number, [number, number]>('add', [5, '7']),
// Error: Type 'string' is not assignable to type 'number'
);
import { useQuery } from 'react-query';
import {
executeBackendFunction,
BackendFunctionError,
} from '@datadog/apps-function-query';
function MyComponent() {
const { error } = useQuery(['getData'], () =>
executeBackendFunction<Data>('getData', []),
);
if (error) {
if (error instanceof BackendFunctionError) {
console.log('Function:', error.functionName);
console.log('Status:', error.statusCode);
console.log('Message:', error.message);
}
return <div>Error: {error.message}</div>;
}
return <div>Success!</div>;
}
Configure react-query for optimal performance:
import { QueryClient, QueryClientProvider } from 'react-query';
const queryClient = new QueryClient({
defaultOptions: {
queries: {
staleTime: 5000, // Data is fresh for 5 seconds
cacheTime: 300000, // Cache for 5 minutes
retry: 2, // Retry failed requests twice
refetchOnWindowFocus: false,
},
},
});
function App() {
return (
<QueryClientProvider client={queryClient}>
<YourApp />
</QueryClientProvider>
);
}
import useSWR from 'swr';
import { executeBackendFunction } from '@datadog/apps-function-query';
function MyComponent() {
const { data, error } = useSWR(['getUser', 'user-123'], ([_, userId]) =>
executeBackendFunction<UserData, [string]>('getUser', [userId]),
);
if (error) return <div>Failed to load</div>;
if (!data) return <div>Loading...</div>;
return <div>{data.name}</div>;
}
import { createApi, fetchBaseQuery } from '@reduxjs/toolkit/query/react';
import { executeBackendFunction } from '@datadog/apps-function-query';
export const api = createApi({
baseQuery: async ({ functionName, args }) => {
try {
const data = await executeBackendFunction(functionName, args);
return { data };
} catch (error) {
return { error };
}
},
endpoints: (builder) => ({
getUser: builder.query<UserData, string>({
query: (userId) => ({ functionName: 'getUser', args: [userId] }),
}),
}),
});
Apache-2.0
FAQs
Client library for executing backend functions in Datadog Apps
We found that @datadog/apps-function-query demonstrated a healthy version release cadence and project activity because the last version was released less than a year ago. It has 1 open source maintainer collaborating on the project.
Did you know?

Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.

Security News
The Axios compromise shows how time-dependent dependency resolution makes exposure harder to detect and contain.

Research
A supply chain attack on Axios introduced a malicious dependency, plain-crypto-js@4.2.1, published minutes earlier and absent from the project’s GitHub releases.

Research
Malicious versions of the Telnyx Python SDK on PyPI delivered credential-stealing malware via a multi-stage supply chain attack.