@quintype/framework 7.22.0-disable-amp-story.2 → 7.22.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +7 -0
- package/package.json +2 -2
- package/server/amp/handlers/infinite-scroll.js +2 -0
- package/server/amp/handlers/story-page.js +4 -3
- package/server/amp/helpers/get-amp-page-base-path.js +10 -0
- package/server/amp/helpers/infinite-scroll.js +22 -21
- package/server/handlers/isomorphic-handler.js +2 -0
- package/server/impl/light-page-impl.js +4 -10
- package/server/routes.js +7 -7
- package/test/integration/amp-handler-test.js +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,13 @@
|
|
|
2
2
|
|
|
3
3
|
All notable changes to this project will be documented in this file. See [standard-version](https://github.com/conventional-changelog/standard-version) for commit guidelines.
|
|
4
4
|
|
|
5
|
+
## [7.22.0](https://github.com/quintype/quintype-node-framework/compare/v7.21.2...v7.22.0) (2023-12-01)
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
### Features
|
|
9
|
+
|
|
10
|
+
* add support to configure amp story page path through featureConfig ([#403](https://github.com/quintype/quintype-node-framework/issues/403)) ([876e89a](https://github.com/quintype/quintype-node-framework/commit/876e89aeb1b4fadc9c071ffb7dcf824fc419a963))
|
|
11
|
+
|
|
5
12
|
### [7.21.2](https://github.com/quintype/quintype-node-framework/compare/v7.21.1...v7.21.2) (2023-11-15)
|
|
6
13
|
|
|
7
14
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@quintype/framework",
|
|
3
|
-
"version": "7.22.0
|
|
3
|
+
"version": "7.22.0",
|
|
4
4
|
"description": "Libraries to help build Quintype Node.js apps",
|
|
5
5
|
"main": "index.js",
|
|
6
6
|
"engines": {
|
|
@@ -35,7 +35,7 @@
|
|
|
35
35
|
"@quintype/backend": "^2.3.3",
|
|
36
36
|
"@quintype/components": "^3.3.0",
|
|
37
37
|
"@quintype/prerender-node": "^3.2.26",
|
|
38
|
-
"@quintype/seo": "^1.43.0-
|
|
38
|
+
"@quintype/seo": "^1.43.0-config-amp-story-path.1",
|
|
39
39
|
"atob": "^2.1.2",
|
|
40
40
|
"babel-plugin-react-css-modules": "^5.2.6",
|
|
41
41
|
"chalk": "^4.1.2",
|
|
@@ -11,6 +11,8 @@ async function storyPageInfiniteScrollHandler(req, res, next, { client, config,
|
|
|
11
11
|
const infiniteScrollSource = get(opts, ["featureConfig", "infiniteScroll", "source"], "collection");
|
|
12
12
|
|
|
13
13
|
const infiniteScrollAmp = new InfiniteScrollAmp({
|
|
14
|
+
opts,
|
|
15
|
+
config,
|
|
14
16
|
ampConfig,
|
|
15
17
|
publisherConfig: config,
|
|
16
18
|
client,
|
|
@@ -47,10 +47,8 @@ async function ampStoryPageHandler(
|
|
|
47
47
|
if (typeof redirectUrls === "function" || (redirectUrls && Object.keys(redirectUrls).length > 0)) {
|
|
48
48
|
await getRedirectUrl(req, res, next, { redirectUrls, config });
|
|
49
49
|
}
|
|
50
|
-
const story = await Story.getStoryBySlug(client, req.params["0"]);
|
|
51
|
-
const isAmpDisabled = get(story, ["metadata", "story-attributes", "disable-amp-for-single-story", "0"], "false");
|
|
52
50
|
|
|
53
|
-
if (
|
|
51
|
+
if (!isVisualStory && !enableAmp) {
|
|
54
52
|
return res.redirect(301, `/${req.params[0]}`);
|
|
55
53
|
}
|
|
56
54
|
|
|
@@ -59,6 +57,7 @@ async function ampStoryPageHandler(
|
|
|
59
57
|
const { ampifyStory, unsupportedStoryElementsPresent } = ampLibrary;
|
|
60
58
|
// eslint-disable-next-line no-return-await
|
|
61
59
|
const ampConfig = await config.memoizeAsync("amp-config", async () => await AmpConfig.getAmpConfig(client));
|
|
60
|
+
const story = await Story.getStoryBySlug(client, req.params["0"]);
|
|
62
61
|
let relatedStoriesCollection;
|
|
63
62
|
let relatedStories = [];
|
|
64
63
|
|
|
@@ -100,6 +99,8 @@ async function ampStoryPageHandler(
|
|
|
100
99
|
infiniteScrollInlineConfig = await inlineConfig();
|
|
101
100
|
} else {
|
|
102
101
|
const infiniteScrollAmp = new InfiniteScrollAmp({
|
|
102
|
+
opts,
|
|
103
|
+
config,
|
|
103
104
|
ampConfig,
|
|
104
105
|
publisherConfig: config,
|
|
105
106
|
client,
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
const get = require("lodash/get");
|
|
2
|
+
|
|
3
|
+
function getAmpPageBasePath(opts = {}, config) {
|
|
4
|
+
let ampPageBasePath = get(opts, ["featureConfig", "ampPageBasePath"], "/amp/story");
|
|
5
|
+
ampPageBasePath = typeof ampPageBasePath === "function" ? ampPageBasePath(config) : ampPageBasePath;
|
|
6
|
+
|
|
7
|
+
return ampPageBasePath;
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
module.exports = { getAmpPageBasePath };
|
|
@@ -1,6 +1,10 @@
|
|
|
1
|
+
const { getAmpPageBasePath } = require("./get-amp-page-base-path");
|
|
2
|
+
|
|
1
3
|
class InfiniteScrollAmp {
|
|
2
|
-
constructor({ ampConfig, client, publisherConfig, queryParams, infiniteScrollSource }) {
|
|
4
|
+
constructor({ config = {}, opts = {}, ampConfig, client, publisherConfig, queryParams, infiniteScrollSource }) {
|
|
3
5
|
this.client = client;
|
|
6
|
+
this.opts = opts;
|
|
7
|
+
this.config = config;
|
|
4
8
|
this.publisherConfig = publisherConfig;
|
|
5
9
|
this.queryParams = queryParams;
|
|
6
10
|
this.infiniteScrollSource = infiniteScrollSource;
|
|
@@ -19,18 +23,17 @@ class InfiniteScrollAmp {
|
|
|
19
23
|
|
|
20
24
|
getFilteredApiItems(relatedStories) {
|
|
21
25
|
return relatedStories.filter(
|
|
22
|
-
(story) =>
|
|
23
|
-
story.access !== "subscription" &&
|
|
24
|
-
story["story-template"] !== "visual-story"
|
|
26
|
+
(story) => story.access !== "subscription" && story["story-template"] !== "visual-story"
|
|
25
27
|
);
|
|
26
28
|
}
|
|
27
29
|
|
|
28
30
|
formatData({ itemsArr, type }) {
|
|
29
31
|
// formats configuration as per need of amp infinite scroll
|
|
32
|
+
const ampPageBasePath = getAmpPageBasePath(this.opts, this.config);
|
|
30
33
|
const arr = itemsArr.map((item) => ({
|
|
31
34
|
image: this.getImagePath(item),
|
|
32
35
|
title: item.headline,
|
|
33
|
-
url:
|
|
36
|
+
url: `${ampPageBasePath}/${item.slug}`,
|
|
34
37
|
}));
|
|
35
38
|
switch (type) {
|
|
36
39
|
case "inline":
|
|
@@ -57,40 +60,38 @@ class InfiniteScrollAmp {
|
|
|
57
60
|
};
|
|
58
61
|
if (this.infiniteScrollSource === "relatedStoriesApi") {
|
|
59
62
|
const relatedStoriesList = await this.client.getRelatedStories(storyId, null, params);
|
|
60
|
-
if (!relatedStoriesList || !relatedStoriesList["related-stories"].length)
|
|
61
|
-
|
|
62
|
-
return filteredItems = this.getFilteredApiItems(relatedStoriesList["related-stories"]);
|
|
63
|
+
if (!relatedStoriesList || !relatedStoriesList["related-stories"].length) return new Error();
|
|
64
|
+
return (filteredItems = this.getFilteredApiItems(relatedStoriesList["related-stories"]));
|
|
63
65
|
} else {
|
|
64
66
|
const collection = await this.client.getCollectionBySlug("amp-infinite-scroll");
|
|
65
67
|
if (!collection || (collection.items && !collection.items.length) || collection.error || collection === null)
|
|
66
68
|
return new Error();
|
|
67
|
-
const collectionItems = this.getFilteredCollItems(collection, storyId).map(items => items.story);
|
|
68
|
-
return filteredItems = type === "inlineConfig"
|
|
69
|
-
? collectionItems.slice(0, 5)
|
|
70
|
-
: collectionItems.slice(5);
|
|
69
|
+
const collectionItems = this.getFilteredCollItems(collection, storyId).map((items) => items.story);
|
|
70
|
+
return (filteredItems = type === "inlineConfig" ? collectionItems.slice(0, 5) : collectionItems.slice(5));
|
|
71
71
|
}
|
|
72
72
|
}
|
|
73
73
|
|
|
74
74
|
async getResponse() {
|
|
75
75
|
const { "story-id": storyId } = this.queryParams;
|
|
76
76
|
if (!storyId) return new Error(`Query param "story-id" missing`);
|
|
77
|
-
const filteredItems =
|
|
78
|
-
|
|
79
|
-
|
|
77
|
+
const filteredItems = await this.getInfiniteScrollList({ storyId, type: "remoteConfig", offset: 5 });
|
|
78
|
+
if (filteredItems instanceof Error)
|
|
79
|
+
return new Error(`Infinite scroll collection amp-infinite-scroll returned falsy value`);
|
|
80
80
|
const formattedData = this.formatData({ itemsArr: filteredItems });
|
|
81
81
|
return JSON.stringify(formattedData);
|
|
82
82
|
}
|
|
83
83
|
|
|
84
84
|
async getInitialInlineConfig({ storyId }) {
|
|
85
85
|
if (!storyId) return new Error("Required params for getInitialInlineConfig missing");
|
|
86
|
-
const filteredItems =
|
|
87
|
-
await this.getInfiniteScrollList({ storyId, type: "inlineConfig", offset: 0, limit: 5 });
|
|
86
|
+
const filteredItems = await this.getInfiniteScrollList({ storyId, type: "inlineConfig", offset: 0, limit: 5 });
|
|
88
87
|
|
|
89
88
|
if (filteredItems instanceof Error) return null;
|
|
90
|
-
const formattedData =
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
89
|
+
const formattedData =
|
|
90
|
+
filteredItems.length > 0 &&
|
|
91
|
+
this.formatData({
|
|
92
|
+
itemsArr: filteredItems,
|
|
93
|
+
type: "inline",
|
|
94
|
+
});
|
|
94
95
|
return JSON.stringify(formattedData);
|
|
95
96
|
}
|
|
96
97
|
}
|
|
@@ -426,6 +426,7 @@ exports.handleIsomorphicRoute = function handleIsomorphicRoute(
|
|
|
426
426
|
publisherConfig,
|
|
427
427
|
sMaxAge,
|
|
428
428
|
maxAge,
|
|
429
|
+
ampPageBasePath,
|
|
429
430
|
}
|
|
430
431
|
) {
|
|
431
432
|
const url = urlLib.parse(req.url, true);
|
|
@@ -457,6 +458,7 @@ exports.handleIsomorphicRoute = function handleIsomorphicRoute(
|
|
|
457
458
|
client,
|
|
458
459
|
req,
|
|
459
460
|
shouldEncodeAmpUri,
|
|
461
|
+
ampPageBasePath,
|
|
460
462
|
});
|
|
461
463
|
}
|
|
462
464
|
|
|
@@ -3,13 +3,9 @@ const _ = require("lodash");
|
|
|
3
3
|
function addLightPageHeaders(
|
|
4
4
|
result,
|
|
5
5
|
lightPages,
|
|
6
|
-
{ config, res, client, req, shouldEncodeAmpUri = true }
|
|
6
|
+
{ config, res, client, req, shouldEncodeAmpUri = true, ampPageBasePath }
|
|
7
7
|
) {
|
|
8
|
-
const isAmpSupported = _.get(
|
|
9
|
-
result,
|
|
10
|
-
["data", "story", "is-amp-supported"],
|
|
11
|
-
false
|
|
12
|
-
);
|
|
8
|
+
const isAmpSupported = _.get(result, ["data", "story", "is-amp-supported"], false);
|
|
13
9
|
|
|
14
10
|
if (typeof lightPages === "function" && !lightPages(config)) {
|
|
15
11
|
return;
|
|
@@ -24,10 +20,8 @@ function addLightPageHeaders(
|
|
|
24
20
|
path = shouldEncodeAmpUri ? encodeURIComponent(path) : path;
|
|
25
21
|
}
|
|
26
22
|
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
`${req.protocol}://${req.hostname}/amp/story/${path}`
|
|
30
|
-
);
|
|
23
|
+
const ampPagePath = typeof ampPageBasePath === "function" ? ampPageBasePath(config) : ampPageBasePath;
|
|
24
|
+
res.set("X-QT-Light-Pages-Url", `${req.protocol}://${req.hostname}${ampPagePath}/${path}`);
|
|
31
25
|
}
|
|
32
26
|
}
|
|
33
27
|
|
package/server/routes.js
CHANGED
|
@@ -70,7 +70,7 @@ exports.upstreamQuintypeRoutes = function upstreamQuintypeRoutes(
|
|
|
70
70
|
const _sMaxAge = get(config, ["publisher", "upstreamRoutesSmaxage"], sMaxAge);
|
|
71
71
|
const _maxAge = get(config, ["publisher", "upstreamRoutesMaxage"], maxAge);
|
|
72
72
|
|
|
73
|
-
parseInt(_sMaxAge) > 0
|
|
73
|
+
parseInt(_sMaxAge) > 0 &&
|
|
74
74
|
apiProxy.on("proxyRes", function (proxyRes, req) {
|
|
75
75
|
const pathName = get(req, ["originalUrl"], "").split("?")[0];
|
|
76
76
|
const checkForExcludeRoutes = excludeRoutes.some((path) => {
|
|
@@ -79,8 +79,7 @@ exports.upstreamQuintypeRoutes = function upstreamQuintypeRoutes(
|
|
|
79
79
|
});
|
|
80
80
|
const getCacheControl = get(proxyRes, ["headers", "cache-control"], "");
|
|
81
81
|
if (!checkForExcludeRoutes && getCacheControl.includes("public")) {
|
|
82
|
-
proxyRes.headers["cache-control"] = getCacheControl
|
|
83
|
-
.replace(/s-maxage=\d*/g, `s-maxage=${_sMaxAge}`);
|
|
82
|
+
proxyRes.headers["cache-control"] = getCacheControl.replace(/s-maxage=\d*/g, `s-maxage=${_sMaxAge}`);
|
|
84
83
|
}
|
|
85
84
|
});
|
|
86
85
|
parseInt(_maxAge) > 0 &&
|
|
@@ -92,8 +91,7 @@ exports.upstreamQuintypeRoutes = function upstreamQuintypeRoutes(
|
|
|
92
91
|
});
|
|
93
92
|
const getCacheControl = get(proxyRes, ["headers", "cache-control"], "");
|
|
94
93
|
if (!checkForExcludeRoutes && getCacheControl.includes("public")) {
|
|
95
|
-
proxyRes.headers["cache-control"] = getCacheControl
|
|
96
|
-
.replace(/max-age=\d*/g, `max-age=${_maxAge}`);
|
|
94
|
+
proxyRes.headers["cache-control"] = getCacheControl.replace(/max-age=\d*/g, `max-age=${_maxAge}`);
|
|
97
95
|
}
|
|
98
96
|
});
|
|
99
97
|
|
|
@@ -319,6 +317,7 @@ exports.isomorphicRoutes = function isomorphicRoutes(
|
|
|
319
317
|
seo,
|
|
320
318
|
manifestFn,
|
|
321
319
|
assetLinkFn,
|
|
320
|
+
ampPageBasePath = "/amp/story",
|
|
322
321
|
|
|
323
322
|
oneSignalServiceWorkers = false,
|
|
324
323
|
staticRoutes = [],
|
|
@@ -541,6 +540,7 @@ exports.isomorphicRoutes = function isomorphicRoutes(
|
|
|
541
540
|
publisherConfig,
|
|
542
541
|
sMaxAge: _sMaxAge,
|
|
543
542
|
maxAge: _maxAge,
|
|
543
|
+
ampPageBasePath,
|
|
544
544
|
})
|
|
545
545
|
);
|
|
546
546
|
|
|
@@ -648,7 +648,7 @@ exports.mountQuintypeAt = function (app, mountAt) {
|
|
|
648
648
|
/**
|
|
649
649
|
* *ampRoutes* handles all the amp page routes using the *[@quintype/amp](https://developers.quintype.com/quintype-node-amp)* library
|
|
650
650
|
* routes matched:
|
|
651
|
-
* GET - "/amp
|
|
651
|
+
* GET - "/amp/:slug"* returns amp story page
|
|
652
652
|
* GET - "/amp/api/v1/amp-infinite-scroll" returns the infinite scroll config JSON. Passed to <amp-next-page> component's `src` attribute
|
|
653
653
|
*
|
|
654
654
|
* @param {Express} app Express app to add the routes to
|
|
@@ -665,7 +665,7 @@ exports.mountQuintypeAt = function (app, mountAt) {
|
|
|
665
665
|
exports.ampRoutes = (app, opts = {}) => {
|
|
666
666
|
const { ampStoryPageHandler, storyPageInfiniteScrollHandler } = require("./amp/handlers");
|
|
667
667
|
|
|
668
|
-
getWithConfig(app, "/amp/story/*", ampStoryPageHandler, opts);
|
|
669
668
|
getWithConfig(app, "/amp/api/v1/amp-infinite-scroll", storyPageInfiniteScrollHandler, opts);
|
|
669
|
+
getWithConfig(app, "/amp/*", ampStoryPageHandler, opts);
|
|
670
670
|
getWithConfig(app, "/ampstories/*", ampStoryPageHandler, { ...opts, isVisualStory: true });
|
|
671
671
|
};
|
|
@@ -244,7 +244,7 @@ describe("ampStoryPageHandler integration tests", () => {
|
|
|
244
244
|
enableAmp: false,
|
|
245
245
|
});
|
|
246
246
|
supertest(app)
|
|
247
|
-
.get("/amp/
|
|
247
|
+
.get("/amp/cricket/ipl-2021")
|
|
248
248
|
.expect(301)
|
|
249
249
|
.expect("Location", "/cricket/ipl-2021")
|
|
250
250
|
.end((err) => {
|