UNPKG

@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.

926 lines (925 loc) 45.5 kB
import { RootUrlService } from './root-url.service'; import { ServiceMetadata } from './service-metadata'; import { ODataFilterSerializer } from './services/odata-filter-serializer'; import { RENDERER_NAME, getProxyHeaders } from '../proxy/headers'; import { ErrorCodeException } from './errors/error-code.exception'; import { Tracer } from '@progress/sitefinity-nextjs-sdk/diagnostics/empty'; import { QueryParamNames } from './query-params-names'; import { getAdditionalFetchDataServerContext, getHostServerContext, getQueryParamsServerContext } from '../services/server-context'; import { getServerSideCookie } from '../server-side-cookie'; import { MovingDirection } from './args/change-location-priority.args'; export class RestClient { static contextQueryParams; static getItemWithFallback(args) { let queryParams = { sf_fallback_prop_names: '*', $select: '*' }; const wholeUrl = `${RestClient.buildItemBaseUrl(args.type)}(${args.id})/Default.GetItemWithFallback()${RestClient.buildQueryParams(RestClient.getQueryParams(args, queryParams))}`; return this.sendRequest({ url: wholeUrl, additionalFetchData: args.additionalFetchData, traceContext: args.traceContext }, true); } static getTaxons(args) { const queryParams = { 'showEmpty': args.showEmpty.toString(), '$orderby': args.orderBy, '@param': `[${(args.taxaIds || []).map(x => `'${x}'`).toString()}]` }; const taxonomy = ServiceMetadata.taxonomies.find(x => x.Id === args.taxonomyId); if (!taxonomy) { throw `The taxonomy with id ${args.taxonomyId} does not exist`; } const action = `Default.GetTaxons(taxonomyId=${args.taxonomyId},selectedTaxaIds=@param,selectionMode='${args.selectionMode}',contentType='${args.contentType}')`; const wholeUrl = `${RestClient.buildItemBaseUrl(taxonomy['TaxaUrl'])}/${action}${RestClient.buildQueryParams(RestClient.getQueryParams(undefined, queryParams))}`; return this.sendRequest({ url: wholeUrl, additionalFetchData: args.additionalFetchData, traceContext: args.traceContext }).then(x => x.value); } static getSearchMetadata() { const serviceUrl = RootUrlService.getServerCmsServiceUrl(); const wholeUrl = `${serviceUrl}/Default.GetSearchMetadata()`; return this.sendRequest({ url: wholeUrl }); } static getItemWithStatus(args) { let queryParams = { $select: '*' }; const wholeUrl = `${RestClient.buildItemBaseUrl(args.type)}(${args.id})/Default.GetItemWithStatus()${RestClient.buildQueryParams(RestClient.getQueryParams(args, queryParams))}`; return this.sendRequest({ url: wholeUrl, additionalFetchData: args.additionalFetchData, traceContext: args.traceContext }); } static getItem(args) { const filteredSimpleFields = this.getSimpleFields(args.type, args.fields || ['*']); const filteredRelatedFields = this.getRelatedFields(args.type, args.fields || []); let queryParams = { '$select': filteredSimpleFields.join(','), '$expand': filteredRelatedFields.join(',') }; const wholeUrl = `${this.buildItemBaseUrl(args.type)}(${args.id})${this.buildQueryParams(RestClient.getQueryParams(args, queryParams))}`; return this.sendRequest({ url: wholeUrl, additionalFetchData: args.additionalFetchData, traceContext: args.traceContext }); } static getSharedContent(args) { let queryParams = { sf_fallback_prop_names: 'Content' }; if (args.cultureName) { queryParams['sf_culture'] = args.cultureName; } const wholeUrl = `${RestClient.buildItemBaseUrl(RestSdkTypes.GenericContent)}/Default.GetItemById(itemId=${args.id})${RestClient.buildQueryParams(RestClient.getQueryParams(undefined, queryParams))}`; return this.sendRequest({ url: wholeUrl, additionalFetchData: args.additionalFetchData, traceContext: args.traceContext }, true); } static getItems(args) { const filteredSimpleFields = this.getSimpleFields(args.type, args.fields || []); const filteredRelatedFields = this.getRelatedFields(args.type, args.fields || []); let queryParams = { '$count': args.count, '$orderby': args.orderBy && args.orderBy.length > 0 ? args.orderBy.map(x => `${x.Name} ${x.Type}`) : null, '$select': filteredSimpleFields.join(','), '$expand': filteredRelatedFields.join(','), '$skip': args.skip, '$top': args.take, '$filter': args.filter ? new ODataFilterSerializer().serialize({ Type: args.type, Filter: args.filter }) : null }; const wholeUrl = `${this.buildItemBaseUrl(args.type)}${this.buildQueryParams(RestClient.getQueryParams(args, queryParams))}`; return this.sendRequest({ url: wholeUrl, additionalFetchData: args.additionalFetchData, traceContext: args.traceContext }).then((x) => { return { Items: x.value, TotalCount: x['@odata.count'] }; }); } static createItem(args) { let taxonomyPrefix = 'Taxonomy_'; if (args.type.startsWith(taxonomyPrefix)) { const actualTaxonomyType = args.type.substring(taxonomyPrefix.length); const taxonomy = ServiceMetadata.taxonomies.find(x => x['Name'] === actualTaxonomyType); if (!taxonomy) { throw `Taxonomy with the name ${taxonomy} does not exist`; } args.type = taxonomy['TaxaUrl']; args.data['TaxonomyId'] = taxonomy.Id; } const wholeUrl = `${RestClient.buildItemBaseUrl(args.type)}${RestClient.buildQueryParams(RestClient.getQueryParams(args, undefined))}`; return RestClient.sendRequest({ url: wholeUrl, data: args.data, method: 'POST', headers: args.additionalHeaders }).then((x) => { return x; }); } static scheduleItem(args) { const wholeUrl = `${RestClient.buildItemBaseUrl(args.type)}(${args.id})/Default.Operation()${RestClient.buildQueryParams(RestClient.getQueryParams(args, undefined))}`; return RestClient.sendRequest({ url: wholeUrl, data: { action: 'Schedule', actionParameters: { PublicationDate: args.publicationDate.toISOString(), ExpirationDate: args.expirationDate?.toISOString() } }, method: 'POST', headers: args.additionalHeaders }); } static updateItem(args) { const wholeUrl = `${RestClient.buildItemBaseUrl(args.type)}(${args.id})${RestClient.buildQueryParams(RestClient.getQueryParams(args, undefined))}`; return RestClient.sendRequest({ url: wholeUrl, data: args.data, method: 'PATCH', headers: args.additionalHeaders }); } static deleteItem(args) { const wholeUrl = `${RestClient.buildItemBaseUrl(args.type)}(${args.id})${RestClient.buildQueryParams(RestClient.getQueryParams(args, undefined))}`; return RestClient.sendRequest({ url: wholeUrl, method: 'DELETE', headers: args.additionalHeaders }).then((x) => { return x; }); } static publishItem(args) { const wholeUrl = `${RestClient.buildItemBaseUrl(args.type)}(${args.id})/Default.Operation()${RestClient.buildQueryParams(RestClient.getQueryParams(args, undefined))}`; return RestClient.sendRequest({ url: wholeUrl, data: { action: 'Publish', actionParameters: {} }, method: 'POST', headers: args.additionalHeaders }); } static saveDraftItem(args) { const wholeUrl = `${RestClient.buildItemBaseUrl(args.type)}(${args.id})/operation${RestClient.buildQueryParams(RestClient.getQueryParams(args, undefined))}`; return RestClient.sendRequest({ url: wholeUrl, data: { action: 'SaveDraft', actionParameters: {} }, method: 'POST', headers: args.additionalHeaders }); } static syncPage(args) { const wholeUrl = `${RestClient.buildItemBaseUrl(args.type)}(${args.id})${RestClient.buildQueryParams(RestClient.getQueryParams(args, undefined))}`; return RestClient.sendRequest({ url: wholeUrl, data: Object.assign({}, args.data, { EnableSync: true }), method: 'PATCH', headers: args.additionalHeaders }); } static lockItem(args) { const wholeUrl = `${RestClient.buildItemBaseUrl(args.type)}(${args.id})/Default.SaveTemp()${RestClient.buildQueryParams(RestClient.getQueryParams(args, undefined))}`; return RestClient.sendRequest({ url: wholeUrl, data: Object.assign({}, args.data), method: 'POST', headers: args.additionalHeaders }); } static relateItem(args) { const wholeUrl = `${RestClient.buildItemBaseUrl(args.type)}(${args.id})/${args.relationName}/$ref${RestClient.buildQueryParams(RestClient.getQueryParams(args, undefined))}`; const relatedTypeName = ServiceMetadata.getRelatedType(args.type, args.relationName); if (!relatedTypeName) { throw `Cannot find the type behind the field -> ${args.relationName}`; } let relatedItemUri = `${RestClient.buildItemBaseUrl(relatedTypeName)}(${args.relatedItemId})`; if (args.relatedItemProvider) { relatedItemUri = relatedItemUri + `?sf_provider=${args.relatedItemProvider}`; } return RestClient.sendRequest({ url: wholeUrl, data: { '@odata.id': relatedItemUri }, method: 'POST', headers: args.additionalHeaders }); } static lockPage(args) { const wholeUrl = `${RestClient.buildItemBaseUrl(args.type)}(${args.id})/Default.Lock()${RestClient.buildQueryParams(RestClient.getQueryParams(args, undefined))}`; return RestClient.sendRequest({ url: wholeUrl, data: { state: { Version: args.version } }, method: 'POST', headers: args.additionalHeaders }); } static createWidget(args) { const wholeUrl = `${RestClient.buildItemBaseUrl(args.type)}(${args.id})/Default.AddWidget()${RestClient.buildQueryParams(RestClient.getQueryParams(args, undefined))}`; const properties = []; if (args.properties) { Object.keys(args.properties).forEach((x) => { properties.push({ Name: x, Value: args.properties[x] }); }); } const dto = { widget: { Id: null, Name: args.name, SiblingKey: args.siblingKey, ParentPlaceholderKey: args.parentPlaceholderKey, PlaceholderName: args.placeholderName, Properties: properties } }; return RestClient.sendRequest({ url: wholeUrl, data: dto, method: 'POST', headers: args.additionalHeaders }); } static updateWidget(page, propertyValues) { const wholeUrl = `${RestClient.buildItemBaseUrl(RestSdkTypes.Pages)}(${page.Id})/Default.SetProperties()${RestClient.buildQueryParams(RestClient.getQueryParams(propertyValues, undefined))}`; return RestClient.sendRequest({ url: wholeUrl, data: propertyValues, method: 'POST', headers: propertyValues.additionalHeaders }); } static uploadItem(args) { const wholeUrl = `${RestClient.buildItemBaseUrl(args.type)}${RestClient.buildQueryParams(RestClient.getQueryParams(args, undefined))}`; const headers = args.additionalHeaders || {}; const data = Object.assign({}, args.fields, { Title: args.title, ParentId: args.parentId, UrlName: args.urlName }); headers['X-Sf-Properties'] = JSON.stringify(data); headers['X-File-Name'] = args.fileName; headers['Content-Type'] = args.contentType; headers['Content-Length'] = args.binaryData.length.toString(); headers['Content-Encoding'] = 'base64'; headers['DirectUpload'] = true.toString(); return RestClient.sendRequest({ url: wholeUrl, data: args.binaryData, method: 'POST', headers }).then((x) => { return x; }); } static performSearch(args) { const query = { ['indexCatalogue']: args.indexCatalogue, ['searchQuery']: encodeURIComponent(args.searchQuery).toLowerCase(), ['wordsMode']: args.wordsMode, ['$orderBy']: args.orderBy, ['sf_culture']: args.culture, ['$skip']: args.skip?.toString(), ['$top']: args.take?.toString(), ['searchFields']: args.searchFields, ['highlightedFields']: args.highlightedFields, ['resultsForAllSites']: '', ['scoringInfo']: args.scoringInfo, ['filter']: args.filter, ['indexFields']: args.indexFields }; if (!!args.resultsForAllSites) { if (args.resultsForAllSites === true) { query['resultsForAllSites'] = '1'; } else { query['resultsForAllSites'] = '2'; } } const serviceUrl = RootUrlService.getServerCmsServiceUrl(); const wholeUrl = `${serviceUrl}/Default.PerformSearch()${RestClient.buildQueryParams(RestClient.getQueryParams(undefined, query))}`; const searchResultsDocumentsDefaultKeys = ['HighLighterResult', 'Language', 'Provider', 'Link', 'Title', 'ContentType', 'Id', 'ThumbnailUrl']; return RestClient.sendRequest({ url: wholeUrl, additionalFetchData: args.additionalFetchData, traceContext: args.traceContext }).then(x => { const mappedSearchResults = x.SearchResults.map(searchResult => { const document = { HighLighterResult: searchResult.HighLighterResult, Language: searchResult.Language, Provider: searchResult.Provider, Link: searchResult.Link, Title: searchResult.Title, ContentType: searchResult.ContentType, Id: searchResult.Id, ThumbnailUrl: searchResult.ThumbnailUrl, IndexedFields: new Map() }; Object.keys(searchResult) .filter(p => !p.includes('@odata.type')) .forEach(propertyName => { // exclude the default properties and the odata typevalue properties if (!searchResultsDocumentsDefaultKeys.includes(propertyName)) { document.IndexedFields.set(propertyName, searchResult[propertyName]); } }); return document; }); return { totalCount: x.TotalCount, searchResults: mappedSearchResults }; }); } static getSearchSuggestions(args) { const query = { ['indexName']: args.indexCatalogue, ['searchQuery']: encodeURIComponent(args.searchQuery).toLowerCase(), ['sf_culture']: args.culture, ['siteId']: args.culture, ['scoringInfo']: args.scoringInfo, ['suggestionFields']: args.suggestionFields, ['resultsForAllSites']: '' }; if (!!args.resultsForAllSites) { if (args.resultsForAllSites === true) { query['resultsForAllSites'] = 'True'; } else { query['resultsForAllSites'] = 'False'; } } const serviceUrl = RootUrlService.getServerCmsServiceUrl(); const wholeUrl = `${serviceUrl}/Default.GetSuggestions()${RestClient.buildQueryParams(RestClient.getQueryParams(undefined, query))}`; return RestClient.sendRequest({ url: wholeUrl, additionalFetchData: args.additionalFetchData, traceContext: args.traceContext }); } static getFacatebleFields(args) { const serviceUrl = RootUrlService.getServerCmsServiceUrl(); const wholeUrl = `${serviceUrl}/Default.GetFacetableFields(indexCatalogName='${args.indexCatalogue}')`; return RestClient.sendRequest({ url: wholeUrl, additionalFetchData: args.additionalFetchData, traceContext: args.traceContext }).then(x => x.value); } static async getFacets(args) { const facetsStr = JSON.stringify(args.facets); const additionalQueryParams = { ['searchQuery']: encodeURIComponent(args.searchQuery)?.toLowerCase(), ['sf_culture']: args.culture, ['indexCatalogName']: args.indexCatalogue, ['filter']: args.filter, ['resultsForAllSites']: args.resultsForAllSites, ['searchFields']: args.searchFields, ['facetFields']: facetsStr }; const serviceUrl = RootUrlService.getServerCmsServiceUrl(); const wholeUrl = `${serviceUrl}/Default.GetFacets()${RestClient.buildQueryParams(RestClient.getQueryParams(undefined, additionalQueryParams))}`; return RestClient.sendRequest({ url: wholeUrl, additionalFetchData: args.additionalFetchData, traceContext: args.traceContext }).then(x => x.value); } static getResetPasswordModel(token, traceContext) { const serviceUrl = RootUrlService.getServerCmsServiceUrl(); const wholeUrl = `${serviceUrl}/Default.GetResetPasswordModel()`; return RestClient.sendRequest({ url: wholeUrl, data: { securityToken: token }, method: 'POST', traceContext }); } static getRegistrationSettings(args) { const serviceUrl = RootUrlService.getServerCmsServiceUrl(); const wholeUrl = `${serviceUrl}/Default.RegistrationSettings()`; return RestClient.sendRequest({ url: wholeUrl, additionalFetchData: args.additionalFetchData, traceContext: args.traceContext }); } static activateAccount(encryptedParam, traceContext) { const serviceUrl = RootUrlService.getServerCmsServiceUrl(); const wholeUrl = `${serviceUrl}/Default.AccountActivation()${RestClient.buildQueryParams({ qs: encodeURIComponent(encryptedParam) })}`; return RestClient.sendRequest({ url: wholeUrl, traceContext }, true); } static getExternalProviders(args) { const serviceUrl = RootUrlService.getServerCmsServiceUrl(); const wholeUrl = `${serviceUrl}/Default.GetExternalProviders()`; return RestClient.sendRequest({ url: wholeUrl, additionalFetchData: args.additionalFetchData, traceContext: args.traceContext }).then((x) => x.value); } static getCurrentUser(args) { const wholeUrl = `${RestClient.buildItemBaseUrl('users')}/current`; return RestClient.sendRequest({ url: wholeUrl, method: 'GET', additionalFetchData: args?.additionalFetchData, traceContext: args?.traceContext }).then((x) => { return x.value; }); } static getCurrentSite(args) { const wholeUrl = `${RestClient.buildItemBaseUrl('sites')}/current`; return RestClient.sendRequest({ url: wholeUrl, method: 'GET', additionalFetchData: args?.additionalFetchData, traceContext: args?.traceContext }).then((x) => { return x.value; }); } static getSites(args) { const wholeUrl = `${RestClient.buildItemBaseUrl('sites')}`; return RestClient.sendRequest({ url: wholeUrl, method: 'GET', additionalFetchData: args?.additionalFetchData, traceContext: args?.traceContext }).then((x) => { return x.value; }); } static getNavigation(args) { let queryMap = { 'selectionModeString': args.selectionMode, 'showParentPage': args.showParentPage ? args.showParentPage.toString() : undefined, 'sf_page_node': args.currentPage, 'selectedPages': args.selectedPages && args.selectedPages.length > 0 ? JSON.stringify(args.selectedPages) : undefined, 'levelsToInclude': args.levelsToInclude ? args.levelsToInclude.toString() : 'all', 'selectedPageId': args.selectedPageId }; const wholeUrl = `${RestClient.buildItemBaseUrl(RestSdkTypes.Pages)}/Default.HierarhicalByLevelsResponse()${RestClient.buildQueryParams(RestClient.getQueryParams(undefined, queryMap))}`; return this.sendRequest({ url: wholeUrl, additionalFetchData: args.additionalFetchData, traceContext: args.traceContext }).then((x) => { return x.value; }); } static getBreadcrumb(args) { let queryMap = {}; Object.keys(args).filter(x => args[x]).map((x) => { if (x === 'detailItemInfo') { queryMap[x] = JSON.stringify(args[x]); } else { queryMap[x] = args[x].toString(); } }); const wholeUrl = `${RestClient.buildItemBaseUrl(RestSdkTypes.Pages)}/Default.GetBreadcrumb()${RestClient.buildQueryParams(RestClient.getQueryParams(undefined, queryMap))}`; return this.sendRequest({ url: wholeUrl, additionalFetchData: args.additionalFetchData, traceContext: args.traceContext }).then((x) => { return x.value; }); } static setHomePage(args) { const wholeUrl = `${RestClient.buildItemBaseUrl(RestSdkTypes.Pages)}/Default.SetHomePage()${RestClient.buildQueryParams(RestClient.getQueryParams(args, undefined))}`; return this.sendRequest({ url: wholeUrl, data: { pageId: args.id }, method: 'POST', headers: args.additionalHeaders }); } static async getPreviewLink(args) { const wholeUrl = `${RestClient.buildItemBaseUrl(args.type)}(${args.id})/Default.Operation()${RestClient.buildQueryParams(RestClient.getQueryParams(undefined, args.additionalQueryParams))}`; return this.sendRequest({ url: wholeUrl, data: { 'action': 'Preview' }, method: 'POST', headers: args.additionalHeaders }); } static async getPageSharePreviewLink(pageId) { const wholeUrl = `${RestClient.buildItemBaseUrl(RestSdkTypes.Pages)}(${pageId})/Default.SharePreviewLink()${RestClient.buildQueryParams(RestClient.getQueryParams())}`; return this.sendRequest({ url: wholeUrl, method: 'GET' }); } static async getContentLocations(args) { const wholeUrl = `${RootUrlService.getClientCmsUrl()}/Sitefinity/Services/LocationService/${RestClient.buildQueryParams({ itemType: args.type, provider: args.provider })}`; return this.sendRequest({ url: wholeUrl, method: 'GET', headers: args.additionalHeaders, additionalFetchData: args.additionalFetchData }); } static async getDisplayPages(args) { const wholeUrl = `${RestClient.buildItemBaseUrl(args.type)}(${args.id})/DisplayPages${RestClient.buildQueryParams(RestClient.getQueryParams(undefined, args.additionalQueryParams))}`; return this.sendRequest({ url: wholeUrl, method: 'GET', headers: args.additionalHeaders, additionalFetchData: args.additionalFetchData }); } static async getProviders(args) { const wholeUrl = `${RestClient.buildItemBaseUrl(args.type)}/sfproviders`; return this.sendRequest({ url: wholeUrl, method: 'GET', headers: args.additionalHeaders, additionalFetchData: args.additionalFetchData }).then((x) => { return x.value; }); } static async changeLocationPriority(args) { const direction = args.direction || MovingDirection.Top; const directionCode = direction.toString(); const wholeUrl = `${RootUrlService.getClientCmsUrl()}/Sitefinity/Services/LocationService/${RestClient.buildQueryParams({ 'id': args.id, 'direction': directionCode })}`; return this.sendRequest({ url: wholeUrl, method: 'PUT', headers: args.additionalHeaders }); } static async getFormLayout(args) { const wholeUrl = `${RestClient.buildItemBaseUrl(RestSdkTypes.Form)}(${args.id})/Default.Model()${RestClient.buildQueryParams(RestClient.getQueryParams(undefined, args.additionalQueryParams))}`; return RestClient.sendRequest({ url: wholeUrl, headers: args.additionalHeaders, additionalFetchData: args.additionalFetchData, traceContext: args.traceContext }); } static async getWidgetModel(args) { args.additionalQueryParams = args.additionalQueryParams || {}; args.additionalQueryParams.sfwidgetsegment = args.widgetSegmentId || ''; args.additionalQueryParams.segment = args.segmentId || ''; const wholeUrl = `${RestClient.buildItemBaseUrl(args.type)}(${args.id})/Default.HierarchicalWidgetModel(componentId='${args.widgetId}')${RestClient.buildQueryParams(RestClient.getQueryParams(undefined, args.additionalQueryParams))}`; return RestClient.sendRequest({ url: wholeUrl, headers: args.additionalHeaders, additionalFetchData: args.additionalFetchData, traceContext: args.traceContext }); } static async getLazyWidget(args) { args.additionalQueryParams = args.additionalQueryParams || {}; args.additionalQueryParams.sfwidgetsegment = args.widgetSegmentId || ''; args.additionalQueryParams.segment = args.segmentId || ''; let lazyComponentsUrl = `${RestClient.buildItemBaseUrl(args.type)}(${args.id})/Default.LazyComponents()${RestClient.buildQueryParams(RestClient.getQueryParams(undefined, args.additionalQueryParams))}`; return RestClient.sendRequest({ url: lazyComponentsUrl, headers: args.additionalHeaders, additionalFetchData: args.additionalFetchData }).then(x => x.Components.find(y => y.Id === args.widgetId)); } static async getLazyWidgets(args) { let url = encodeURIComponent(args.url); let concatChar = '?'; if (url.indexOf('?')) { concatChar = '&'; } let lazyComponentsUrl = RootUrlService.getServerCmsServiceUrl() + `/Default.LazyComponents(url=@param)?@param='${url}'${concatChar}correlationId=${args.correlationId}`; const headers = { 'Cookie': args.cookie }; const referrer = args.referrer; if (referrer && referrer.length > 0) { headers['SF_URL_REFERER'] = referrer; } else { headers['SF_NO_URL_REFERER'] = 'true'; } return RestClient.sendRequest({ url: lazyComponentsUrl, headers, additionalFetchData: args.additionalFetchData }).then(x => x.Components); } static async getPageLayout(args) { const pagePath = args.pagePath; let headers = args.additionalHeaders || {}; if (args.cookie) { headers['Cookie'] = args.cookie; } if (typeof window === 'undefined' || process.env.NODE_ENV === 'test') { const host = getHostServerContext(); const proxyHeaders = getProxyHeaders(host); Object.keys(proxyHeaders).forEach((header) => { headers[header] = proxyHeaders[header]; }); } const queryParams = args.queryParams || {}; if (args.relatedFields) { queryParams['$expand'] = args.relatedFields.join(','); } let sysParamsQueryString = RestClient.buildQueryParams(queryParams); let url = `${pagePath}${sysParamsQueryString}`; if (!pagePath.includes('http') && !pagePath.includes('https')) { if (!url.startsWith('/')) { url = '/' + url; } url = RootUrlService.getServerCmsUrl() + url; } let requestData = { url: url, headers: headers, method: 'GET' }; let requestInit = { headers, method: requestData.method, redirect: 'manual' }; const additionalFetchData = getAdditionalFetchDataServerContext(); if (additionalFetchData) { requestInit = Object.assign(requestInit, additionalFetchData); } if (args.additionalFetchData) { requestInit = Object.assign(requestInit, args.additionalFetchData); } let httpLayoutResponse = null; try { httpLayoutResponse = await Tracer.withContext(() => fetch(requestData.url, requestInit), args.traceContext); } catch (error) { if (error instanceof ErrorCodeException && error.code === 'NotFound') { throw error; } if (error instanceof ErrorCodeException && error.code === 'Unauthorized') { throw `Could not authorize fetching layout for url '${pagePath}'. Contact your system administator or check your access token.`; } } if (!httpLayoutResponse) { throw 'Error while fetching the page'; } if (httpLayoutResponse.status === 302 && httpLayoutResponse.headers.has('urlparameters')) { let urlParameters = httpLayoutResponse.headers.get('urlparameters').split('/'); args.pagePath = httpLayoutResponse.headers.get('location'); const layoutRecursive = await this.getPageLayout(args); layoutRecursive.layout.UrlParameters = urlParameters; return layoutRecursive; } if ((httpLayoutResponse.status === 301 || httpLayoutResponse.status === 302)) { const location = httpLayoutResponse.headers.get('location'); if (!args.followRedirects) { return { isRedirect: true, redirect: { Location: location, Permenant: httpLayoutResponse.status === 301 } }; } else { args.pagePath = location; const layoutRecursive = await this.getPageLayout(args); return layoutRecursive; } } if (httpLayoutResponse.status === 404) { throw new ErrorCodeException('NotFound', 'page not found'); } const layoutResponse = await RestClient.handleApiResponse(httpLayoutResponse, requestData, true); const cacheControl = httpLayoutResponse.headers.get('Cache-Control'); if (cacheControl && layoutResponse) { layoutResponse.CacheControl = cacheControl; } return { isRedirect: false, layout: layoutResponse }; } static async getTemplates(args) { const wholeUrl = `${RootUrlService.getServerCmsUrl()}/sf/system/${args.type}/Default.GetPageTemplates(selectedPages=[${args.selectedPages.map(x => `'${x}'`).join(',')}])${RestClient.buildQueryParams(RestClient.getQueryParams(undefined, args.additionalQueryParams))}`; return RestClient.sendRequest({ url: wholeUrl, headers: args.additionalHeaders, additionalFetchData: args.additionalFetchData }).then(x => x.value); } static async getTemplatesStatistics(args) { args.additionalQueryParams = args.additionalQueryParams || {}; args.additionalQueryParams['@param'] = `[${args.templateNames.map(x => `'${x}'`).join(',')}]`; const wholeUrl = `${RootUrlService.getServerCmsUrl()}/sf/system/pages/Default.GetTemplateStatistics(templateNames=@param, renderer='${RENDERER_NAME}')${RestClient.buildQueryParams(RestClient.getQueryParams(undefined, args.additionalQueryParams))}`; return RestClient.sendRequest({ url: wholeUrl, headers: args.additionalHeaders, additionalFetchData: args.additionalFetchData }).then(x => x.value); } static getSimpleFields(type, fields) { let star = '*'; if (fields != null && fields.length === 1 && fields[0] === star) { return [star]; } let simpleFields = ServiceMetadata.getSimpleFields(type); return fields.filter(x => simpleFields.some(y => y === x)); } static getRelatedFields(type, fields) { let star = '*'; if (fields != null && fields.length === 1 && fields[0] === star) { return [star]; } const result = []; const relatedFields = ServiceMetadata.getRelationFields(type); const pattern = /(?<fieldName>.+?)\((?<nested>.+)\)/; fields.forEach((field) => { const fieldMatch = field.match(pattern); if (!fieldMatch && relatedFields.some(x => x === field)) { result.push(field); } else if (fieldMatch && fieldMatch.groups) { const fieldName = fieldMatch.groups['fieldName']; if (relatedFields.some(x => x === fieldName)) { const innerFields = fieldMatch.groups['nested']; const relatedFieldsInput = this.parseInnerFields(innerFields.replaceAll(' ', '')); const relatedTypeName = ServiceMetadata.getRelatedType(type, fieldName); if (relatedTypeName) { let relatedSimpleFields = ServiceMetadata.getSimpleFields(relatedTypeName); relatedSimpleFields = relatedFieldsInput.filter(x => relatedSimpleFields.some(y => y === x)); let simpleFieldsJoined = null; if (relatedSimpleFields.length > 0) { simpleFieldsJoined = relatedSimpleFields.join(','); simpleFieldsJoined = `$select=${simpleFieldsJoined}`; } const relatedRelationFields = RestClient.getRelatedFields(relatedTypeName, relatedFieldsInput); let relatedRelationFieldsJoined = null; if (relatedRelationFields.length > 0) { relatedRelationFieldsJoined = relatedRelationFields.join(','); relatedRelationFieldsJoined = `$expand=${relatedRelationFieldsJoined}`; } let resultString = null; if (relatedRelationFieldsJoined && simpleFieldsJoined) { resultString = `${fieldName}(${simpleFieldsJoined};${relatedRelationFieldsJoined})`; } else if (relatedRelationFieldsJoined) { resultString = `${fieldName}(${relatedRelationFieldsJoined})`; } else if (simpleFieldsJoined) { resultString = `${fieldName}(${simpleFieldsJoined})`; } if (resultString) { result.push(resultString); } } } } }); return result; } static parseInnerFields(input) { const allFields = []; let fieldStartIndex = 0; let charIterator = 0; let openingBraceCounter = 0; let closingBraceCounter = 0; for (let i = 0; i < input.length; i++) { charIterator++; const character = input[i]; if (character === '(') { openingBraceCounter++; } if (character === ')') { closingBraceCounter++; } if (character === ',') { if (openingBraceCounter > 0 && openingBraceCounter === closingBraceCounter) { let relatedField = input.substring(fieldStartIndex, fieldStartIndex + charIterator - fieldStartIndex - 1).trim(); allFields.push(relatedField); fieldStartIndex = charIterator; openingBraceCounter = 0; closingBraceCounter = 0; } else if (openingBraceCounter === 0 && closingBraceCounter === 0) { let basicField = input.substring(fieldStartIndex, fieldStartIndex + charIterator - fieldStartIndex - 1).trim(); allFields.push(basicField); fieldStartIndex = charIterator; } } } if (fieldStartIndex < charIterator) { let lastField = input.substring(fieldStartIndex, fieldStartIndex + charIterator - fieldStartIndex).trim(); allFields.push(lastField); } return allFields; } static buildQueryParams(queryParams) { if (!queryParams) { return ''; } if (!queryParams) { queryParams = {}; } if (typeof window === 'undefined') { const queryParamsFromServerContext = getQueryParamsServerContext(); queryParams = Object.assign({}, queryParamsFromServerContext || {}, queryParams); } else { queryParams = Object.assign({}, RestClient.contextQueryParams || {}, queryParams); } let result = ''; Object.keys(queryParams).forEach((key) => { const value = queryParams[key]; if (value) { result += `${key}=${value}&`; } }); if (result !== '') { result = '?' + result; result = result.substring(0, result.length - 1); } return result; } static addAuthHeaders(cookie, headers) { if (!!cookie) { headers['Cookie'] = cookie; } else if (process.env['SF_ACCESS_KEY']) { headers['X-SF-Access-Key'] = process.env['SF_ACCESS_KEY']; } } static getQueryParams(args, queryParams) { let queryParamsFromArgs = {}; if (args) { queryParamsFromArgs = { [QueryParamNames.Provider]: args.provider, [QueryParamNames.Culture]: args.culture }; } if (typeof window === 'undefined') { const queryParamsFromServerContext = getQueryParamsServerContext(); return Object.assign({}, queryParamsFromServerContext || {}, queryParamsFromArgs, args?.additionalQueryParams || {}, queryParams || {}); } return Object.assign({}, RestClient.contextQueryParams || {}, queryParamsFromArgs, args?.additionalQueryParams || {}, queryParams || {}); } static buildHeaders(requestData) { let headers = { 'X-Requested-With': 'react' }; if ((requestData.method === 'POST' || requestData.method === 'PATCH') && !headers['Content-Type']) { headers['Content-Type'] = 'application/json'; } if (typeof window === 'undefined') { const host = getHostServerContext() || requestData.headers?.host; const proxyHeaders = getProxyHeaders(host); Object.keys(proxyHeaders).forEach((headerKey) => { headers[headerKey] = proxyHeaders[headerKey]; }); } if (!requestData.headers) { return headers; } return Object.assign(headers, requestData.headers); } static async sendRequest(request, throwErrorAsJson) { const headers = this.buildHeaders(request); if (process.env.NODE_ENV === 'test') { RestClient.addAuthHeaders(undefined, headers); } if (typeof window === 'undefined') { const cookie = await getServerSideCookie(); RestClient.addAuthHeaders(cookie, headers); } request.method = request.method || 'GET'; let args = { headers, method: request.method }; if (request.data && headers['Content-Type'] === 'application/json') { args.body = JSON.stringify(request.data); } if (headers['Content-Encoding'] === 'base64') { args.body = request.data; } if (process.env.SF_SDK_CACHE_REVALIDATE) { const duration = parseInt(process.env.SF_SDK_CACHE_REVALIDATE, 10); if (Number.isInteger(duration)) { const revalidateFetchData = { next: { revalidate: duration } }; args = Object.assign(args, revalidateFetchData); } else if (process.env.SF_SDK_CACHE_REVALIDATE.toLowerCase() === 'false') { const revalidateFetchData = { next: { revalidate: false } }; args = Object.assign(args, revalidateFetchData); } } else if (process.env.SF_SDK_CACHE) { const cacheFetchData = { cache: process.env.SF_SDK_CACHE }; args = Object.assign(args, cacheFetchData); } const additionalFetchData = getAdditionalFetchDataServerContext(); if (additionalFetchData) { args = Object.assign(args, additionalFetchData); } if (request.additionalFetchData) { args = Object.assign(args, request.additionalFetchData); } return Tracer.withContext(() => { return fetch(request.url, args).then((x => { return RestClient.handleApiResponse(x, request, throwErrorAsJson); })); }, request.traceContext); } static buildItemBaseUrl(itemType) { let serviceUrl = null; if (typeof window === 'undefined') { serviceUrl = RootUrlService.getServerCmsServiceUrl(); } else { serviceUrl = RootUrlService.getClientServiceUrl(); } const setName = ServiceMetadata.getSetNameFromType(itemType); return `${serviceUrl}/${setName}`; } static handleApiResponse(x, request, throwErrorAsJson) { const contentTypeHeader = x.headers.get('content-type'); if (contentTypeHeader) { if (x.status > 399) { if (contentTypeHeader.indexOf('application/json') !== -1) { return x.json().then((y) => { if (throwErrorAsJson && y.error && y.error.code && y.error.message) { throw new ErrorCodeException(y.error.code, y.error.message); } let responseMessage = ''; if (y.error) { if (y.error.code && y.error.message) { responseMessage = `${y.error.code}: ${y.error.message}`; } else if (y.error.message) { responseMessage = y.error.message; } } else if (y.Message) { responseMessage = y.Message; } else { responseMessage = JSON.stringify(y); } const message = `${request.method} ${request.url} failed. Response -> ${responseMessage}`; throw message; }); } return x.text().then((html) => { const message = `${request.method} ${request.url} failed. Response -> ${x.status}: ${x.statusText} ${html}`; throw message; }); } if (contentTypeHeader.indexOf('application/json') !== -1) { return x.json().then(x => x); } } return Promise.resolve(undefined); } } export class RestSdkTypes { static Video = 'Telerik.Sitefinity.Libraries.Model.Video'; static Image = 'Telerik.Sitefinity.Libraries.Model.Image'; static Document = 'Telerik.Sitefinity.Libraries.Model.Document'; static DocumentLibrary = 'Telerik.Sitefinity.Libraries.Model.DocumentLibrary'; static News = 'Telerik.Sitefinity.News.Model.NewsItem'; static Taxonomies = 'Telerik.Sitefinity.Taxonomies.Model.Taxonomy'; static Tags = 'Taxonomy_Tags'; static Categories = 'Taxonomy_Categories'; static GenericContent = 'Telerik.Sitefinity.GenericContent.Model.ContentItem'; static Pages = 'Telerik.Sitefinity.Pages.Model.PageNode'; static PageTemplates = 'Telerik.Sitefinity.Pages.Model.PageTemplate'; static Form = 'Telerik.Sitefinity.Forms.Model.FormDescription'; static Site = 'Telerik.Sitefinity.Multisite.Model.Site'; static Blog = 'Telerik.Sitefinity.Blogs.Model.Blog'; static Event = 'Telerik.Sitefinity.Events.Model.Event'; static Calendar = 'Telerik.Sitefinity.Events.Model.Calendar'; static BlogPost = 'Telerik.Sitefinity.Blogs.Model.BlogPost'; static Author = 'Telerik.Sitefinity.DynamicTypes.Model.Authors.Author'; }