Skip to content

Commit

Permalink
Adding the beginnings of the push API handler, and some refactoring
Browse files Browse the repository at this point in the history
  • Loading branch information
csulham committed Mar 19, 2024
1 parent 14d2624 commit c26cec2
Show file tree
Hide file tree
Showing 7 changed files with 144 additions and 31 deletions.
6 changes: 3 additions & 3 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@
"react-dom": "^18"
},
"devDependencies": {
"@types/node": "^20",
"@types/node": "^20.11.30",
"@types/react": "^18",
"@types/react-dom": "^18",
"autoprefixer": "^10.0.1",
Expand Down
79 changes: 79 additions & 0 deletions pages/api/onPublishEnd.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
// Import the Next.js API route handler
import { NextApiRequest, NextApiResponse } from 'next';
import { graphqlRequest, GraphQLRequest } from '@/util/GraphQLQuery';

// Define the API route handler
export default async function onPublishEnd(req: NextApiRequest, res: NextApiResponse) {
// Check if the api_key query parameter matches the WEBHOOK_API_KEY environment variable
if (req.query.api_key !== process.env.WEBHOOK_API_KEY) {
return res.status(401).json({ message: 'Unauthorized' });
}

// If the request method is not POST, return an error
if (req.method !== 'POST') {
return res.status(405).json({ message: 'Method not allowed' });
}

let data;
try {
// Try to parse the JSON data from the request body
//console.log('Req body:\n' + JSON.stringify(req.body));
data = req.body;
} catch (error) {
console.log('Bad Request: ', error);
return res.status(400).json({ message: 'Bad Request. Check incoming data.' });
}

// Loop over all the entries in updates
for (const update of data.updates) {
// Check if the entity_definition is LayoutData
if (update.entity_definition === 'LayoutData') {
// Extract the GUID portion of the identifier
const guid = update.identifier.split('-')[0]

try {
// Create the GraphQL request
const request: GraphQLRequest = {
query: itemQuery,
variables: { id: guid },
};
console.log('Getting GQL Data for item ' + guid);
// Invoke the GraphQL query with the request
const result = await graphqlRequest(request);

console.log('Item Data:\n' + JSON.stringify(result));

// TODO: Handle the result of the GraphQL query
// 1. Make sure we got some data from GQL
// 2. Check if it's in the right site (the webhook fires for every site) by comparing the path
// 3. Send the json data to the Yext Push API endpoint

} catch (error) {
// If an error occurs while invoking the GraphQL query, return a 500 error
return res.status(500).json({ message: 'Internal Server Error: GraphQL query failed' })
}
}
}

// Send a response
return res.status(200).json({ message: 'Webhook event received' })
}

const itemQuery = `
query ($id: String!) {
item(path: $id, language: "en") {
id
name
path
url {
path
url
}
fields {
name
jsonValue
}
}
}
`;
1 change: 1 addition & 0 deletions pages/api/yextCrawl.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import type { NextApiRequest, NextApiResponse } from 'next';
import { graphqlRequest, GraphQLRequest } from '@/util/GraphQLQuery';

type ResponseData = {
message: string;
Expand Down
29 changes: 2 additions & 27 deletions pages/api/yextQuery.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import type { NextApiRequest, NextApiResponse } from 'next';
import { GetDate } from '@/util/GetDate';

type ResponseData = {
message: string;
Expand All @@ -20,7 +21,7 @@ export default async function handler(req: NextApiRequest, res: NextApiResponse<
sort: req.query.sort?.toString() ?? '',
};

console.log('Yext Query Incoming params: \n' + JSON.stringify(incomingParams));
//console.log('Yext Query Incoming params: \n' + JSON.stringify(incomingParams));

if (isNaN(incomingParams.numResults) || incomingParams.numResults < 1) {
// Ensure this is a number, otherwise set to 9.
Expand Down Expand Up @@ -106,26 +107,6 @@ function GetTaxonomyFilterClause(name: string, values?: string): string {
return JSON.stringify(filterClause);
}

function GetDate(): string {
const today = new Date();
const yyyy = today.getFullYear();
const mm = today.getMonth() + 1; // Months start at 0!
const dd = today.getDate();
let MM = mm.toString();
let DD = dd.toString();

if (dd < 10) {
DD = '0' + dd;
}

if (mm < 10) {
MM = '0' + mm;
}

// Return date in YYYYMMDD format for Yext param
return yyyy + MM + DD;
}

/**
* @description Data structure that should be serialized into URL query parameters for a Yext entities API search.
* Page parameter starts at 1.
Expand All @@ -135,14 +116,8 @@ function GetDate(): string {
* Incorrect: params.Topics = '{AC5AB52E-0319-4166-9847-B31CC071CA7E},{C4FA9F40-8CE1-4725-B180-13EC9E09D21F}'
*/
export type YextSearchParams = {
//audience?: string;
//authors?: string;
//blogCategories?: string;
contentTypes?: string;
//eventTypes?: string;
locations?: string;
//memberStatus?: string;
//products?: string;
topics?: string;
page: number;
numResults: number;
Expand Down
19 changes: 19 additions & 0 deletions util/GetDate.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
export function GetDate(): string {
const today = new Date();
const yyyy = today.getFullYear();
const mm = today.getMonth() + 1; // Months start at 0!
const dd = today.getDate();
let MM = mm.toString();
let DD = dd.toString();

if (dd < 10) {
DD = '0' + dd;
}

if (mm < 10) {
MM = '0' + mm;
}

// Return date in YYYYMMDD format for Yext param
return yyyy + MM + DD;
}
39 changes: 39 additions & 0 deletions util/GraphQLQuery.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
import fetch from 'node-fetch';

export interface GraphQLRequest {
query: string;
variables?: Record<string, any>;
}

// Define the expected shape of the GraphQL response data
interface GraphQLResponse {
data?: any;
errors?: { message: string }[];
}

export async function graphqlRequest(request: GraphQLRequest): Promise<any> {
const endpoint = process.env.GRAPH_QL_ENDPOINT ?? '';
const apiKey = process.env.SITECORE_API_KEY ?? '';

const response = await fetch(endpoint, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'sc_apikey': apiKey
},
body: JSON.stringify(request),
});

if (!response.ok) {
throw new Error(`GraphQL request failed: ${response.status} ${response.statusText}`);
}

// Type the body variable using the GraphQLResponse interface
const body = await response.json() as GraphQLResponse;

if (body.errors) {
throw new Error(`GraphQL request failed: ${body.errors.map(error => error.message).join(', ')}`);
}

return body.data;
}

0 comments on commit c26cec2

Please sign in to comment.