@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 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-disable-amp-story.2",
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-disable-amp-story.1",
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 ((!isVisualStory && !enableAmp) || isAmpDisabled === "true") {
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: `/amp/story/${item.slug}`,
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
- return new Error();
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
- await this.getInfiniteScrollList({ storyId, type: "remoteConfig", offset: 5 });
79
- if (filteredItems instanceof Error) return new Error(`Infinite scroll collection amp-infinite-scroll returned falsy value`);
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 = filteredItems.length > 0 && this.formatData({
91
- itemsArr: filteredItems,
92
- type: "inline",
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
- res.set(
28
- "X-QT-Light-Pages-Url",
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/story/:slug"* returns amp story page
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/story/cricket/ipl-2021")
247
+ .get("/amp/cricket/ipl-2021")
248
248
  .expect(301)
249
249
  .expect("Location", "/cricket/ipl-2021")
250
250
  .end((err) => {