@progress/sitefinity-nextjs-sdk
Version:
Provides OOB widgets developed using the Next.js framework, which includes an abstraction layer for Sitefinity communication. Additionally, it offers an expanded API, typings, and tools for further development and integration.
162 lines (161 loc) • 6.09 kB
JavaScript
import { RootUrlService } from '../../../rest-sdk';
const ERROR_MESSAGES = {
SERVICE_UNAVAILABLE: 'Service unavailable',
TOO_MANY_REQUESTS: 'Too many requests',
PAYMENT_REQUIRED: 'Payment required'
};
const DEFAULT_ERROR_CONFIG = {
message: ERROR_MESSAGES.SERVICE_UNAVAILABLE,
errorType: 'ServiceError'
};
const ERROR_STATUS_MAP = {
429: {
message: ERROR_MESSAGES.TOO_MANY_REQUESTS,
allowErrorSurfacing: false, // explicitly set, but false by default
errorType: 'QuotaExceeded'
},
402: {
message: ERROR_MESSAGES.PAYMENT_REQUIRED,
allowErrorSurfacing: false,
errorType: 'QuotaExceeded'
}
};
function normalizeErrorResponse(status, responseText) {
let responseData = null;
if (responseText) {
try {
responseData = JSON.parse(responseText);
}
catch (e) {
responseData = null;
}
}
const statusConfig = ERROR_STATUS_MAP[status] || DEFAULT_ERROR_CONFIG;
const errorData = {
errorMessage: statusConfig.message,
errorType: statusConfig.errorType
};
if (statusConfig.allowErrorSurfacing) {
if (responseData?.errorMessage) {
errorData.errorMessage = responseData.errorMessage;
}
else if (responseData?.message) {
errorData.errorMessage = responseData.message;
}
else if (responseText) {
errorData.errorMessage = responseText;
}
}
return errorData;
}
export class DGEServiceConnector {
static async fetchDataStream(params, onData, onError, onComplete) {
const serviceUrl = RootUrlService.getWebServicePath();
const apiUrl = `/${serviceUrl}/DynamicExperience/content`;
const url = !params.variationId ? apiUrl : `${apiUrl}?variationId=${params.variationId}`;
const response = await fetch(url, {
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify(params)
});
if (!response.ok) {
let responseText = '';
try {
responseText = await response.text();
}
catch (e) {
responseText = '';
}
onError?.(normalizeErrorResponse(response.status, responseText));
return;
}
if (!response.body) {
onError?.({
errorMessage: DEFAULT_ERROR_CONFIG.message,
errorType: DEFAULT_ERROR_CONFIG.errorType
});
return;
}
// Get a reader from the stream
const reader = response.body.getReader();
const decoder = new TextDecoder();
let parsingStreamingCollection = false;
let collectedData = '';
// Read the stream
while (true) {
const { done, value } = await reader.read();
if (done) {
break;
}
// Convert the Uint8Array to a string
const chunk = decoder.decode(value, { stream: true });
collectedData += chunk;
try {
// For streaming enumerable collection
let trimmedChunk = chunk.trim();
if (parsingStreamingCollection || trimmedChunk.startsWith('[')) {
if (trimmedChunk.startsWith('[') && trimmedChunk.endsWith(']')) {
// Single complete array in one chunk
const parsedData = JSON.parse(trimmedChunk);
parsedData.forEach((item) => onData?.(item));
continue;
}
parsingStreamingCollection = true;
if (trimmedChunk.startsWith('[')) {
trimmedChunk = trimmedChunk.substring(1).trim(); // Remove starting '['
}
if (trimmedChunk.startsWith(',')) {
trimmedChunk = trimmedChunk.substring(1).trim(); // Remove starting ','
}
if (trimmedChunk.endsWith(']')) {
trimmedChunk = trimmedChunk.substring(0, trimmedChunk.length - 1).trim(); // Remove ending ']'
parsingStreamingCollection = false;
}
if (trimmedChunk) {
const parsedData = JSON.parse(trimmedChunk);
onData?.(parsedData);
continue;
}
}
// Check if the chunk contains multiple JSON objects
// (For APIs that send multiple JSON objects separated by newlines)
if (chunk.includes('\n')) {
const jsonObjects = chunk.trim().split('\n');
for (const jsonStr of jsonObjects) {
if (jsonStr.trim()) {
const parsedData = JSON.parse(jsonStr);
onData?.(parsedData);
continue;
}
}
}
else {
// For a single JSON object in the chunk
const parsedData = JSON.parse(chunk);
onData?.(parsedData);
continue;
}
}
catch (error) {
console.error('Error parsing JSON chunk:', error);
}
}
let parsedCollectedData = [];
try {
parsedCollectedData = JSON.parse(collectedData);
}
catch (error) {
console.error('Error parsing collected JSON data:', error);
// Show an error in the UI if the complete collected data fails to parse.
onError?.({
errorMessage: DEFAULT_ERROR_CONFIG.message,
errorType: DEFAULT_ERROR_CONFIG.errorType
});
return;
}
onComplete?.(parsedCollectedData);
return;
}
}