From 488edfdfc9a3564005e55513c78a4c895742a9a7 Mon Sep 17 00:00:00 2001 From: Reena Singh <45616864+ReenaSingh07@users.noreply.github.com> Date: Fri, 22 Nov 2024 16:38:45 +0530 Subject: [PATCH] feat(Preview): support home page & collection page preview (#97) --- collection-loader.js | 117 +++++++++++++++++++++++++------------------ index.js | 72 +++++++++++++++++++------- package-lock.json | 4 +- package.json | 2 +- 4 files changed, 125 insertions(+), 70 deletions(-) diff --git a/collection-loader.js b/collection-loader.js index 9666208..925d0e8 100644 --- a/collection-loader.js +++ b/collection-loader.js @@ -1,42 +1,42 @@ -const get = require("lodash/get"); -const flatMap = require("lodash/flatMap"); +const get = require('lodash/get') +const flatMap = require('lodash/flatMap') -function loadCollectionItems( +function loadCollectionItems ( client, collections, - { storyFields, storyLimits = {}, defaultNestedLimit, customLayouts = [] } + { storyFields, storyLimits = {}, defaultNestedLimit, customLayouts = [], previewId = '', qtInternalAppsKey = '' } ) { const bulkRequestBody = collections.reduce((acc, collection, index) => { - let limit = storyLimits[get(collection, ["associated-metadata", "layout"], "")]; - const customLayout = get(customLayouts, [index]); + let limit = storyLimits[get(collection, ['associated-metadata', 'layout'], '')] + const customLayout = get(customLayouts, [index]) if (customLayout) { - limit = get(customLayout, ["storyLimit"]); + limit = get(customLayout, ['storyLimit']) } - if (!limit && get(collection, ["childCollectionLimit"])) { - limit = get(collection, ["childCollectionLimit"]); + if (!limit && get(collection, ['childCollectionLimit'])) { + limit = get(collection, ['childCollectionLimit']) } if (!limit && defaultNestedLimit) { - limit = defaultNestedLimit; + limit = defaultNestedLimit } return Object.assign(acc, { [`${collection.slug}-${index}`]: { - _type: "collection", + _type: 'collection', slug: collection.slug, - "story-fields": storyFields, + 'story-fields': storyFields, limit: limit } - }); - }, {}); - - return client.getInBulk({ requests: bulkRequestBody }).then(response => response.results); + }) + }, {}) + const opts = { previewId, qtInternalAppsKey } + return client.getInBulk({ requests: bulkRequestBody }, opts).then(response => response.results) } // Ugly. This function updates all the items in place. // However, this is way more readable than a pure version -function updateItemsInPlace( +function updateItemsInPlace ( client, depth, items, @@ -46,43 +46,47 @@ function updateItemsInPlace( defaultNestedLimit, nestedCollectionLimit, collectionOfCollectionsIndexes = [], - customLayouts = [] + customLayouts = [], + previewId = "", + qtInternalAppsKey = "" } ) { - const collections = items.filter(item => item && item.type == "collection"); + const collections = items.filter(item => item && item.type == 'collection') - if (depth == 0 || collections.length == 0) return Promise.resolve(); + if (depth == 0 || collections.length == 0) return Promise.resolve() return loadCollectionItems(client, collections, { storyFields, storyLimits, defaultNestedLimit, - customLayouts + customLayouts, + previewId, + qtInternalAppsKey }).then(collectionSlugToCollection => { collections.forEach((collection, index) => { - const slugWithIndex = `${collection.slug}-${index}`; - collection.summary = get(collectionSlugToCollection, [slugWithIndex, "summary"], ""); - collection.automated = get(collectionSlugToCollection, [slugWithIndex, "automated"]); - collection["collection-cache-keys"] = get( + const slugWithIndex = `${collection.slug}-${index}` + collection.summary = get(collectionSlugToCollection, [slugWithIndex, 'summary'], '') + collection.automated = get(collectionSlugToCollection, [slugWithIndex, 'automated']) + collection['collection-cache-keys'] = get( collectionSlugToCollection, - [slugWithIndex, "collection-cache-keys"], + [slugWithIndex, 'collection-cache-keys'], [] - ); - collection.items = get(collectionSlugToCollection, [slugWithIndex, "items"], []); + ) + collection.items = get(collectionSlugToCollection, [slugWithIndex, 'items'], []) if (nestedCollectionLimit && collection.items) { - const customLayout = get(customLayouts, [index]); + const customLayout = get(customLayouts, [index]) collection.items.forEach((item, index) => { - if (item.type === "collection") { + if (item.type === 'collection') { if (customLayout && customLayout.nestedCollectionLimit) { - item.childCollectionLimit = get(customLayout, ["nestedCollectionLimit", index]); - } else if (nestedCollectionLimit[get(collection, ["associated-metadata", "layout"])]) { + item.childCollectionLimit = get(customLayout, ['nestedCollectionLimit', index]) + } else if (nestedCollectionLimit[get(collection, ['associated-metadata', 'layout'])]) { item.childCollectionLimit = - nestedCollectionLimit[get(collection, ["associated-metadata", "layout"])][index]; + nestedCollectionLimit[get(collection, ['associated-metadata', 'layout'])][index] } } - }); + }) } - }); + }) if (collectionOfCollectionsIndexes.length) { const updatedCollections = collections @@ -91,21 +95,30 @@ function updateItemsInPlace( return updateItemsInPlace(client, 1, childCollection.items, { storyFields, storyLimits, - defaultNestedLimit - }); - }); - return Promise.all(updatedCollections).then(collections => collections); + defaultNestedLimit, + previewId, + qtInternalAppsKey + }) + }) + return Promise.all(updatedCollections).then(collections => collections) } else { - return updateItemsInPlace(client, depth - 1, flatMap(collections, collection => collection.items), { - storyFields, - storyLimits, - defaultNestedLimit - }); + return updateItemsInPlace( + client, + depth - 1, + flatMap(collections, collection => collection.items), + { + storyFields, + storyLimits, + defaultNestedLimit, + previewId, + qtInternalAppsKey + } + ) } - }); + }) } -function loadNestedCollectionData( +function loadNestedCollectionData ( client, collection, { @@ -115,7 +128,9 @@ function loadNestedCollectionData( defaultNestedLimit, nestedCollectionLimit, collectionOfCollectionsIndexes, - customLayouts + customLayouts, + previewId, + qtInternalAppsKey } ) { return updateItemsInPlace(client, depth, collection.items, { @@ -124,8 +139,10 @@ function loadNestedCollectionData( defaultNestedLimit, nestedCollectionLimit, collectionOfCollectionsIndexes, - customLayouts - }).then(() => collection); + customLayouts, + previewId, + qtInternalAppsKey + }).then(() => collection) } -module.exports = { loadNestedCollectionData }; +module.exports = { loadNestedCollectionData } diff --git a/index.js b/index.js index d51c25c..3855260 100644 --- a/index.js +++ b/index.js @@ -222,7 +222,7 @@ class Story extends BaseAPI { * @param {Object} requests * @see {@link https://developers.quintype.com/swagger/#/story/post_api_v1_c_request POST /api/v1/bulk-request} API documentation for a list of parameters and fields */ - static getInBulk(client, requests) { + static getInBulk(client, requests, opts = {}) { function wrapResult(result) { if (!result.stories) return result; return Object.assign({}, result, { @@ -231,9 +231,12 @@ class Story extends BaseAPI { } return client - .getInBulk({ - requests: mapValues(r => Object.assign({ _type: "stories" }, r), requests) - }) + .getInBulk( + { + requests: mapValues(r => Object.assign({ _type: "stories" }, r), requests) + }, + opts + ) .then(response => BulkResults.build(mapValues(result => wrapResult(result), response["results"]))); } } @@ -355,13 +358,15 @@ class Collection extends BaseAPI { customLayouts = [] } = options; const storyFields = _.get(params, ["story-fields"], DEFAULT_STORY_FIELDS); - if (!slug) { return Promise.resolve(null); } - + const opts = + options?.previewId && options?.qtInternalAppsKey + ? { previewId: options?.previewId, qtInternalAppsKey: options?.qtInternalAppsKey } + : {}; return client - .getCollectionBySlug(slug, params) + .getCollectionBySlug(slug, params, opts) .then(response => { const collection = response ? response["collection"] || response : null; return ( @@ -373,7 +378,9 @@ class Collection extends BaseAPI { defaultNestedLimit, nestedCollectionLimit, collectionOfCollectionsIndexes, - customLayouts + customLayouts, + previewId: options?.previewId || "", + qtInternalAppsKey: options?.qtInternalAppsKey || "" }) ); }) @@ -919,7 +926,15 @@ class Client { return this.request("/api/v1/preview/story/" + publicPreviewKey).catch(e => catch404(e, {})); } - getCollectionBySlug(slug, params) { + getCollectionBySlug(slug, params, opts = {}) { + if (opts?.previewId && opts?.qtInternalAppsKey) { + return this.request(`/api/v1/preview/${opts?.previewId}/collections/${slug}`, { + qs: params, + headers: { + "qt-internal-apps-key": opts?.qtInternalAppsKey + } + }).catch(e => catch404(e, null)); + } return this.request("/api/v1/collections/" + slug, { qs: params }).catch(e => catch404(e, null)); @@ -1041,10 +1056,9 @@ class Client { }); } - async getInBulk(requests) { + async getInBulk(requests, opts = {}) { const config = await this.getConfig(); const requestHash = hash({ ...requests, ...{ publisherId: config["publisher-id"] } }); - async function getBulkLocation() { const response = await this.request("/api/v1/bulk-request", { method: ENABLE_AXIOS ? "post" : "POST", @@ -1056,20 +1070,44 @@ class Client { simple: false, resolveWithFullResponse: true }); + if (response.statusCode === 303 && response.caseless.get("Location")) { const contentLocation = response.caseless.get("Location"); await memoryCache.set(requestHash, contentLocation, BULK_REQ_TTL_CACHE); return contentLocation; - } else { - throw new Error(`Could Not Convert POST bulk to a get, got status ${response.statusCode}`); } + throw new Error(`Could Not Convert POST bulk to a get, got status ${response.statusCode}`); + } + + async function getBulkPreviewData() { + const response = await this.request(`/api/v1/preview/${opts?.previewId}/bulk-request`, { + method: ENABLE_AXIOS ? "post" : "POST", + ...(ENABLE_AXIOS && { data: requests }), + ...(!ENABLE_AXIOS && { body: requests }), + headers: { + "content-type": "text/plain", + "qt-internal-apps-key": opts?.qtInternalAppsKey + }, + simple: false, + resolveWithFullResponse: true + }); + if (response.statusCode === 200) { + const data = response.toJSON(); + return data?.body; + } + throw new Error(`Could Not Convert POST bulk to a get, got status ${response.statusCode}`); } - let cachedRequestHash = await memoryCache.get(requestHash); - if (!cachedRequestHash) { - cachedRequestHash = await getBulkLocation.bind(this)(); + if (opts?.qtInternalAppsKey && opts?.previewId) { + const data = await getBulkPreviewData.bind(this)(); + return data; + } else { + let cachedRequestHash = await memoryCache.get(requestHash); + if (!cachedRequestHash) { + cachedRequestHash = await getBulkLocation.bind(this)(); + } + return this.request(cachedRequestHash); } - return this.request(cachedRequestHash); } getAmpStoryBySlug(slug) { diff --git a/package-lock.json b/package-lock.json index 2a550eb..100a5fd 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "@quintype/backend", - "version": "2.5.1", + "version": "2.5.2-collection-preview.2", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "@quintype/backend", - "version": "2.5.1", + "version": "2.5.2-collection-preview.2", "license": "ISC", "dependencies": { "axios": "^0.21.1", diff --git a/package.json b/package.json index 52e2c2a..fabf971 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@quintype/backend", - "version": "2.5.1", + "version": "2.5.2-collection-preview.2", "description": "client for accessing quintype API", "main": "index.js", "scripts": {