@quintype/framework 7.33.6 → 7.34.0-amp-chart-beat-changes.2

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,20 +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.33.6](https://github.com/quintype/quintype-node-framework/compare/v7.33.5...v7.33.6) (2025-03-17)
5
+ ## [7.34.0-amp-chart-beat-changes.1](https://github.com/quintype/quintype-node-framework/compare/v7.33.2-amp-chart-beat-changes.2...v7.34.0-amp-chart-beat-changes.1) (2025-04-05)
6
6
 
7
7
 
8
- ### Bug Fixes
9
-
10
- * **FCM:** remove deprecated server key & use firebase admin to register to topic ([#458](https://github.com/quintype/quintype-node-framework/issues/458)) ([b179dd4](https://github.com/quintype/quintype-node-framework/commit/b179dd4594e94cf5639b020b1991a061c6c11105))
11
-
12
- ### [7.33.5](https://github.com/quintype/quintype-node-framework/compare/v7.33.4...v7.33.5) (2025-02-13)
13
-
14
- ### [7.33.4](https://github.com/quintype/quintype-node-framework/compare/v7.33.3...v7.33.4) (2025-02-13)
15
-
16
- ### [7.33.3](https://github.com/quintype/quintype-node-framework/compare/v7.33.2...v7.33.3) (2025-02-13)
8
+ ### Features
17
9
 
18
- ### [7.33.2](https://github.com/quintype/quintype-node-framework/compare/v7.33.1...v7.33.2) (2025-02-13)
10
+ * add support to instagram reels embed in amp ([d24b175](https://github.com/quintype/quintype-node-framework/commit/d24b17528ae3ccb8cbf20ff7da3b3c71f9df7f92))
11
+ * add support to instagram reels embed in amp ([a3212a7](https://github.com/quintype/quintype-node-framework/commit/a3212a7d814332b64d5c665b7d5a45e7883db2d6))
19
12
 
20
13
  ### [7.33.1](https://github.com/quintype/quintype-node-framework/compare/v7.33.0...v7.33.1) (2025-01-20)
21
14
 
package/README.md CHANGED
@@ -171,7 +171,7 @@ startApp(renderApplication,
171
171
  ```js
172
172
  isomorphicRoutes(app, {
173
173
  ...
174
- fcmServiceCreds: (config) => <ServiceCreds> || fcmServiceCreds: <ServiceCreds> {(function|object)}
174
+ fcmServerKey: (config) => <ServerKey> || fcmServerKey: <ServerKey> {(function|string)}
175
175
  ...
176
176
  });
177
177
 
@@ -13,13 +13,14 @@ export function initializeFCM(firebaseConfig) {
13
13
  appId: firebaseConfig.appId,
14
14
  });
15
15
  const messaging = m.getMessaging(app);
16
- return m.getToken(messaging, { vapidKey: firebaseConfig.vapidKey });
16
+ return m.getToken(messaging);
17
+ // No need to refresh token https://github.com/firebase/firebase-js-sdk/issues/4132
17
18
  })
18
19
  .then((token) => {
19
20
  return registerFCMTopic(token);
20
21
  })
21
22
  .catch((err) => {
22
- console.error(`Fcm initialization error: ${err}`);
23
+ console.error(err);
23
24
  });
24
25
  }
25
26
 
package/package.json CHANGED
@@ -1,10 +1,10 @@
1
1
  {
2
2
  "name": "@quintype/framework",
3
- "version": "7.33.6",
3
+ "version": "7.34.0-amp-chart-beat-changes.2",
4
4
  "description": "Libraries to help build Quintype Node.js apps",
5
5
  "main": "index.js",
6
6
  "engines": {
7
- "node": "^20.0.0",
7
+ "node": "^16.0.0",
8
8
  "npm": "^8.5.0"
9
9
  },
10
10
  "scripts": {
@@ -30,24 +30,22 @@
30
30
  },
31
31
  "homepage": "https://github.com/quintype/quintype-node-framework#readme",
32
32
  "dependencies": {
33
- "@ampproject/toolbox-optimizer": "2.8.3",
34
- "@grpc/grpc-js": "^1.12.5",
35
- "@jsdoc/salty": "^0.2.9",
36
- "@quintype/amp": "^2.20.0",
37
- "@quintype/backend": "^2.7.0",
33
+ "@ampproject/toolbox-optimizer": "^2.4.0",
34
+ "@quintype/amp": "^2.21.0-also-in-package-story-element.0",
35
+ "@quintype/backend": "^1.25.3",
38
36
  "@quintype/components": "^3.5.0",
39
37
  "@quintype/prerender-node": "^3.2.26",
40
38
  "@quintype/seo": "^1.46.1",
41
39
  "atob": "^2.1.2",
42
- "babel-plugin-react-css-modules": "^5.2.6",
40
+ "babel-plugin-react-css-modules": "^0.0.0",
43
41
  "chalk": "^4.1.2",
44
42
  "cluster": "^0.7.7",
45
43
  "compression": "^1.7.4",
46
44
  "ejs": "^3.1.6",
47
45
  "express": "^4.17.1",
48
- "firebase": "^10.6.0",
49
- "firebase-admin": "^13.1.0",
46
+ "firebase": "^11.6.0",
50
47
  "get-youtube-id": "^1.0.1",
48
+ "grpc": "^1.21.1",
51
49
  "http-proxy": "^1.18.1",
52
50
  "js-yaml": "^4.1.0",
53
51
  "lodash": "^4.17.21",
@@ -59,15 +57,16 @@
59
57
  "react-redux": "^7.2.5",
60
58
  "react-router": "^5.2.1",
61
59
  "redux": "^4.1.1",
62
- "request-promise": "^4.2.6",
60
+ "request-promise": "^4.2.2",
63
61
  "sleep-promise": "^9.1.0",
62
+ "taffydb": "^2.7.3",
64
63
  "winston": "3.3.3"
65
64
  },
66
65
  "devDependencies": {
67
66
  "@babel/eslint-parser": "^7.15.7",
68
67
  "@loadable/component": "^5.15.0",
69
68
  "@loadable/server": "^5.15.1",
70
- "@quintype/build": "^4.0.1",
69
+ "@quintype/build": "^1.8.0",
71
70
  "babel-plugin-quintype-assets": "^1.1.1",
72
71
  "babel-plugin-transform-es2015-modules-commonjs": "^6.26.2",
73
72
  "babel-plugin-transform-object-rest-spread": "^6.26.0",
@@ -75,7 +74,7 @@
75
74
  "babel-preset-es2015-tree-shaking": "^1.0.1",
76
75
  "babel-preset-react": "^6.24.1",
77
76
  "babel-register": "^6.26.0",
78
- "better-docs": "^2.7.3",
77
+ "better-docs": "^1.2.2",
79
78
  "eslint": "^7.32.0",
80
79
  "eslint-config-prettier": "^8.3.0",
81
80
  "eslint-config-standard": "^16.0.3",
@@ -85,14 +84,14 @@
85
84
  "eslint-plugin-promise": "^5.1.0",
86
85
  "eslint-plugin-react": "^7.26.1",
87
86
  "eslint-plugin-standard": "^4.1.0",
88
- "gh-pages": "^3.2.3",
87
+ "gh-pages": "^6.3.0",
89
88
  "history": "^5.0.1",
90
89
  "husky": "^7.0.2",
91
- "jsdoc": "^3.6.7",
90
+ "jsdoc": "^4.0.4",
92
91
  "jsdom": "^17.0.0",
93
92
  "jsdom-global": "3.0.2",
94
93
  "lint-staged": "^11.2.0",
95
- "mocha": "^9.1.2",
94
+ "mocha": "^11.1.0",
96
95
  "nyc": "^15.1.0",
97
96
  "onchange": "^7.1.0",
98
97
  "path": "^0.12.7",
@@ -122,8 +121,5 @@
122
121
  "npx eslint --fix",
123
122
  "git add"
124
123
  ]
125
- },
126
- "overrides": {
127
- "grpc": "@grpc/grpc-js"
128
124
  }
129
125
  }
@@ -57,7 +57,10 @@ async function ampStoryPageHandler(
57
57
  const story = await Story.getStoryBySlug(client, req.params["0"]);
58
58
  const isAmpDisabled = get(story, ["metadata", "story-attributes", "disable-amp-for-single-story", "0"], "false");
59
59
 
60
- if (!isVisualStory && (!enableAmp || isAmpDisabled === "true")) {
60
+ const getDisableAmpUnit = get(opts, ["disableAmpUnit"], false);
61
+ const disableAmpUnit = typeof getDisableAmpUnit === "function" && opts.disableAmpUnit(story);
62
+
63
+ if (disableAmpUnit || (!isVisualStory && (!enableAmp || isAmpDisabled === "true"))) {
61
64
  const ampPageBasePath = getAmpPageBasePath(opts, config);
62
65
  const redirectUrl = `/${req.params[0]}`.startsWith(ampPageBasePath)
63
66
  ? `/${req.params[0]}`.replace(ampPageBasePath, "")
@@ -1,34 +1,38 @@
1
- const { get } = require('lodash')
2
- const admin = require('firebase-admin')
3
- const logger = require('../logger')
1
+ const { get } = require("lodash");
2
+ const request = require("request-promise");
4
3
 
5
- exports.registerFCMTopic = async function registerFCM (
4
+ exports.registerFCMTopic = async function registerFCM(
6
5
  req,
7
6
  res,
8
7
  next,
9
- { config, client, publisherConfig, fcmServiceCreds }
8
+ { config, client, publisherConfig, fcmServerKey }
10
9
  ) {
11
-
12
- const token = get(req, ['body', 'token'], null)
10
+ const token = get(req, ["body", "token"], null);
13
11
  if (!token) {
14
- res.status(400).send('No Token Found')
15
- return
12
+ res.status(400).send("No Token Found");
13
+ return;
16
14
  }
17
15
 
18
- const serviceAccount = typeof fcmServiceCreds === 'function' ? await fcmServiceCreds(config) : fcmServiceCreds
16
+ const serverKey = typeof fcmServerKey === "function" ? await fcmServerKey(config) : fcmServerKey;
19
17
 
20
- if (!admin.apps.length) {
21
- admin.initializeApp({ credential: admin.credential.cert(serviceAccount) })
18
+ if (!serverKey) {
19
+ res.status(500).send("Server Key is not available");
20
+ return;
22
21
  }
23
-
22
+ const url = `https://iid.googleapis.com/iid/v1/${token}/rel/topics/all`;
24
23
  try {
25
- await admin.messaging().subscribeToTopic(token, 'all')
26
- res.status(200).send('Topic Registered Successfully')
27
- return
24
+ await request({
25
+ uri: url,
26
+ method: "POST",
27
+ headers: {
28
+ Authorization: `key=${serverKey}`,
29
+ "content-type": "application/json",
30
+ },
31
+ });
32
+ res.status(200).send("Registration Done Suceessfuly");
33
+ return;
28
34
  } catch (error) {
29
- const publisherId = get(config, ["config" , "publisher-id"], "");
30
- res.status(500).send(`FCM Subscription Failed: ${error}`)
31
- logger.error(`Fcm register to topic error for publisher ${publisherId}: ${error}`);
32
- return
35
+ res.status(500).send("FCM Subscription Failed");
36
+ return;
33
37
  }
34
- }
38
+ };
package/server/routes.js CHANGED
@@ -6,29 +6,29 @@
6
6
  * @category Server
7
7
  * @module routes
8
8
  */
9
- const { match } = require('path-to-regexp')
10
- const { generateServiceWorker } = require('./handlers/generate-service-worker')
9
+ const { match } = require("path-to-regexp");
10
+ const { generateServiceWorker } = require("./handlers/generate-service-worker");
11
11
  const {
12
12
  handleIsomorphicShell,
13
13
  handleIsomorphicDataLoad,
14
14
  handleIsomorphicRoute,
15
15
  handleStaticRoute,
16
- notFoundHandler
17
- } = require('./handlers/isomorphic-handler')
18
-
19
- const { oneSignalImport } = require('./handlers/one-signal')
20
- const { customRouteHandler } = require('./handlers/custom-route-handler')
21
- const { handleManifest, handleAssetLink } = require('./handlers/json-manifest-handlers')
22
- const { redirectStory } = require('./handlers/story-redirect')
23
- const { simpleJsonHandler } = require('./handlers/simple-json-handler')
24
- const { makePickComponentSync } = require('../isomorphic/impl/make-pick-component-sync')
25
- const { registerFCMTopic } = require('./handlers/fcm-registration-handler')
26
- const { triggerWebengageNotifications } = require('./handlers/webengage-notifications')
27
- const rp = require('request-promise')
28
- const bodyParser = require('body-parser')
29
- const get = require('lodash/get')
30
- const { URL } = require('url')
31
- const prerender = require('@quintype/prerender-node')
16
+ notFoundHandler,
17
+ } = require("./handlers/isomorphic-handler");
18
+
19
+ const { oneSignalImport } = require("./handlers/one-signal");
20
+ const { customRouteHandler } = require("./handlers/custom-route-handler");
21
+ const { handleManifest, handleAssetLink } = require("./handlers/json-manifest-handlers");
22
+ const { redirectStory } = require("./handlers/story-redirect");
23
+ const { simpleJsonHandler } = require("./handlers/simple-json-handler");
24
+ const { makePickComponentSync } = require("../isomorphic/impl/make-pick-component-sync");
25
+ const { registerFCMTopic } = require("./handlers/fcm-registration-handler");
26
+ const { triggerWebengageNotifications } = require("./handlers/webengage-notifications");
27
+ const rp = require("request-promise");
28
+ const bodyParser = require("body-parser");
29
+ const get = require("lodash/get");
30
+ const { URL } = require("url");
31
+ const prerender = require("@quintype/prerender-node");
32
32
 
33
33
  /**
34
34
  * *upstreamQuintypeRoutes* connects various routes directly to the upstream API server.
@@ -43,7 +43,7 @@ const prerender = require('@quintype/prerender-node')
43
43
  * @param {boolean} opts.forwardFavicon Forward favicon requests to the CMS (default false)
44
44
  * @param {boolean} opts.isSitemapUrlEnabled To enable /news_sitemap/today and /news_sitemap/yesterday sitemap news url (default /news_sitemap.xml)
45
45
  */
46
- exports.upstreamQuintypeRoutes = function upstreamQuintypeRoutes (
46
+ exports.upstreamQuintypeRoutes = function upstreamQuintypeRoutes(
47
47
  app,
48
48
  {
49
49
  forwardAmp = false,
@@ -51,138 +51,138 @@ exports.upstreamQuintypeRoutes = function upstreamQuintypeRoutes (
51
51
  extraRoutes = [],
52
52
  sMaxAge,
53
53
  maxAge,
54
- config = require('./publisher-config'),
55
- getClient = require('./api-client').getClient,
56
- isSitemapUrlEnabled = false
54
+ config = require("./publisher-config"),
55
+ getClient = require("./api-client").getClient,
56
+ isSitemapUrlEnabled = false,
57
57
  } = {}
58
58
  ) {
59
- const host = config.sketches_host
60
- const get = require('lodash/get')
61
- const apiProxy = require('http-proxy').createProxyServer({
59
+ const host = config.sketches_host;
60
+ const get = require("lodash/get");
61
+ const apiProxy = require("http-proxy").createProxyServer({
62
62
  target: host,
63
- ssl: host.startsWith('https') ? { servername: host.replace(/^https:\/\//, '') } : undefined
64
- })
63
+ ssl: host.startsWith("https") ? { servername: host.replace(/^https:\/\//, "") } : undefined,
64
+ });
65
65
 
66
- apiProxy.on('proxyReq', (proxyReq, req, res, options) => {
67
- proxyReq.setHeader('Host', getClient(req.hostname).getHostname())
68
- })
66
+ apiProxy.on("proxyReq", (proxyReq, req, res, options) => {
67
+ proxyReq.setHeader("Host", getClient(req.hostname).getHostname());
68
+ });
69
69
 
70
- const _sMaxAge = get(config, ['publisher', 'upstreamRoutesSmaxage'], sMaxAge)
71
- const _maxAge = get(config, ['publisher', 'upstreamRoutesMaxage'], maxAge)
70
+ const _sMaxAge = get(config, ["publisher", "upstreamRoutesSmaxage"], sMaxAge);
71
+ const _maxAge = get(config, ["publisher", "upstreamRoutesMaxage"], maxAge);
72
72
 
73
73
  parseInt(_sMaxAge) > 0 &&
74
- apiProxy.on('proxyRes', function (proxyRes, req) {
75
- const pathName = get(req, ['originalUrl'], '').split('?')[0]
76
- const checkForExcludeRoutes = excludeRoutes.some(path => {
77
- const matchFn = match(path, { decode: decodeURIComponent })
78
- return matchFn(pathName)
79
- })
80
- const getCacheControl = get(proxyRes, ['headers', 'cache-control'], '')
81
- if (!checkForExcludeRoutes && getCacheControl.includes('public')) {
82
- proxyRes.headers['cache-control'] = getCacheControl.replace(/s-maxage=\d*/g, `s-maxage=${_sMaxAge}`)
74
+ apiProxy.on("proxyRes", function (proxyRes, req) {
75
+ const pathName = get(req, ["originalUrl"], "").split("?")[0];
76
+ const checkForExcludeRoutes = excludeRoutes.some((path) => {
77
+ const matchFn = match(path, { decode: decodeURIComponent });
78
+ return matchFn(pathName);
79
+ });
80
+ const getCacheControl = get(proxyRes, ["headers", "cache-control"], "");
81
+ if (!checkForExcludeRoutes && getCacheControl.includes("public")) {
82
+ proxyRes.headers["cache-control"] = getCacheControl.replace(/s-maxage=\d*/g, `s-maxage=${_sMaxAge}`);
83
83
  }
84
- })
84
+ });
85
85
  parseInt(_maxAge) > 0 &&
86
- apiProxy.on('proxyRes', function (proxyRes, req) {
87
- const pathName = get(req, ['originalUrl'], '').split('?')[0]
88
- const checkForExcludeRoutes = excludeRoutes.some(path => {
89
- const matchFn = match(path, { decode: decodeURIComponent })
90
- return matchFn(pathName)
91
- })
92
- const getCacheControl = get(proxyRes, ['headers', 'cache-control'], '')
93
- if (!checkForExcludeRoutes && getCacheControl.includes('public')) {
94
- proxyRes.headers['cache-control'] = getCacheControl.replace(/max-age=\d*/g, `max-age=${_maxAge}`)
86
+ apiProxy.on("proxyRes", function (proxyRes, req) {
87
+ const pathName = get(req, ["originalUrl"], "").split("?")[0];
88
+ const checkForExcludeRoutes = excludeRoutes.some((path) => {
89
+ const matchFn = match(path, { decode: decodeURIComponent });
90
+ return matchFn(pathName);
91
+ });
92
+ const getCacheControl = get(proxyRes, ["headers", "cache-control"], "");
93
+ if (!checkForExcludeRoutes && getCacheControl.includes("public")) {
94
+ proxyRes.headers["cache-control"] = getCacheControl.replace(/max-age=\d*/g, `max-age=${_maxAge}`);
95
95
  }
96
- })
96
+ });
97
97
 
98
- const sketchesProxy = (req, res) => apiProxy.web(req, res)
98
+ const sketchesProxy = (req, res) => apiProxy.web(req, res);
99
99
 
100
- app.get('/ping', (req, res) => {
100
+ app.get("/ping", (req, res) => {
101
101
  getClient(req.hostname)
102
102
  .getConfig()
103
- .then(() => res.send('pong'))
104
- .catch(() => res.status(503).send({ error: { message: 'Config not loaded' } }))
105
- })
103
+ .then(() => res.send("pong"))
104
+ .catch(() => res.status(503).send({ error: { message: "Config not loaded" } }));
105
+ });
106
106
 
107
107
  // Mention the routes which don't want to override the s-maxage value and max-age value
108
108
  const excludeRoutes = [
109
- '/qlitics.js',
110
- '/api/v1/breaking-news',
111
- '/stories.rss',
112
- '/api/v1/collections/:slug.rss',
113
- '/api/v1/advanced-search',
114
- '/api/instant-articles.rss'
115
- ]
116
-
117
- app.all('/api/*', sketchesProxy)
118
- app.all('*/api/*', sketchesProxy)
119
- app.all('/login', sketchesProxy)
120
- app.all('/qlitics.js', sketchesProxy)
121
- app.all('/auth.form', sketchesProxy)
122
- app.all('/auth.callback', sketchesProxy)
123
- app.all('/auth', sketchesProxy)
124
- app.all('/admin/*', sketchesProxy)
125
- app.all('/sitemap.xml', sketchesProxy)
126
- app.all('/sitemap/*', sketchesProxy)
127
- app.all('/feed', sketchesProxy)
128
- app.all('/rss-feed', sketchesProxy)
129
- app.all('/stories.rss', sketchesProxy)
130
- app.all('/sso-login', sketchesProxy)
131
- app.all('/sso-signup', sketchesProxy)
109
+ "/qlitics.js",
110
+ "/api/v1/breaking-news",
111
+ "/stories.rss",
112
+ "/api/v1/collections/:slug.rss",
113
+ "/api/v1/advanced-search",
114
+ "/api/instant-articles.rss",
115
+ ];
116
+
117
+ app.all("/api/*", sketchesProxy);
118
+ app.all("*/api/*", sketchesProxy);
119
+ app.all("/login", sketchesProxy);
120
+ app.all("/qlitics.js", sketchesProxy);
121
+ app.all("/auth.form", sketchesProxy);
122
+ app.all("/auth.callback", sketchesProxy);
123
+ app.all("/auth", sketchesProxy);
124
+ app.all("/admin/*", sketchesProxy);
125
+ app.all("/sitemap.xml", sketchesProxy);
126
+ app.all("/sitemap/*", sketchesProxy);
127
+ app.all("/feed", sketchesProxy);
128
+ app.all("/rss-feed", sketchesProxy);
129
+ app.all("/stories.rss", sketchesProxy);
130
+ app.all("/sso-login", sketchesProxy);
131
+ app.all("/sso-signup", sketchesProxy);
132
132
  if (isSitemapUrlEnabled) {
133
- app.all('/news_sitemap/today.xml', sketchesProxy)
134
- app.all('/news_sitemap/yesterday.xml', sketchesProxy)
133
+ app.all("/news_sitemap/today.xml", sketchesProxy);
134
+ app.all("/news_sitemap/yesterday.xml", sketchesProxy);
135
135
  } else {
136
- app.all('/news_sitemap.xml', sketchesProxy)
136
+ app.all("/news_sitemap.xml", sketchesProxy);
137
137
  }
138
138
  if (forwardAmp) {
139
- app.get('/amp/*', sketchesProxy)
139
+ app.get("/amp/*", sketchesProxy);
140
140
  }
141
141
  if (forwardFavicon) {
142
- app.get('/favicon.ico', sketchesProxy)
142
+ app.get("/favicon.ico", sketchesProxy);
143
143
  }
144
144
 
145
- extraRoutes.forEach(route => app.all(route, sketchesProxy))
146
- }
145
+ extraRoutes.forEach((route) => app.all(route, sketchesProxy));
146
+ };
147
147
 
148
148
  // istanbul ignore next
149
- function renderServiceWorkerFn (res, layout, params, callback) {
150
- return res.render(layout, params, callback)
149
+ function renderServiceWorkerFn(res, layout, params, callback) {
150
+ return res.render(layout, params, callback);
151
151
  }
152
152
 
153
153
  // istanbul ignore next
154
- function toFunction (value, toRequire) {
154
+ function toFunction(value, toRequire) {
155
155
  if (value === true) {
156
- value = require(toRequire)
156
+ value = require(toRequire);
157
157
  }
158
158
 
159
- if (typeof value === 'function') {
160
- return value
159
+ if (typeof value === "function") {
160
+ return value;
161
161
  }
162
- return () => value
162
+ return () => value;
163
163
  }
164
164
 
165
- function getDomainSlug (publisherConfig, hostName) {
165
+ function getDomainSlug(publisherConfig, hostName) {
166
166
  if (!publisherConfig.domain_mapping) {
167
- return undefined
167
+ return undefined;
168
168
  }
169
- return publisherConfig.domain_mapping[hostName] || null
169
+ return publisherConfig.domain_mapping[hostName] || null;
170
170
  }
171
171
 
172
- function withConfigPartial (
172
+ function withConfigPartial(
173
173
  getClient,
174
174
  logError,
175
- publisherConfig = require('./publisher-config'),
176
- configWrapper = config => config
175
+ publisherConfig = require("./publisher-config"),
176
+ configWrapper = (config) => config
177
177
  ) {
178
- return function withConfig (f, staticParams) {
178
+ return function withConfig(f, staticParams) {
179
179
  return function (req, res, next) {
180
- const domainSlug = getDomainSlug(publisherConfig, req.hostname)
181
- const client = getClient(req.hostname)
180
+ const domainSlug = getDomainSlug(publisherConfig, req.hostname);
181
+ const client = getClient(req.hostname);
182
182
  return client
183
183
  .getConfig()
184
- .then(config => configWrapper(config, domainSlug, { req }))
185
- .then(config =>
184
+ .then((config) => configWrapper(config, domainSlug, { req }))
185
+ .then((config) =>
186
186
  f(
187
187
  req,
188
188
  res,
@@ -190,52 +190,52 @@ function withConfigPartial (
190
190
  Object.assign({}, staticParams, {
191
191
  config,
192
192
  client,
193
- domainSlug
193
+ domainSlug,
194
194
  })
195
195
  )
196
196
  )
197
- .catch(logError)
198
- }
199
- }
197
+ .catch(logError);
198
+ };
199
+ };
200
200
  }
201
201
 
202
- exports.withError = function withError (handler, logError) {
202
+ exports.withError = function withError(handler, logError) {
203
203
  return async (req, res, next, opts) => {
204
204
  try {
205
- await handler(req, res, next, opts)
205
+ await handler(req, res, next, opts);
206
206
  } catch (e) {
207
- logError(e)
208
- res.status(500)
209
- res.end()
207
+ logError(e);
208
+ res.status(500);
209
+ res.end();
210
210
  }
211
- }
212
- }
211
+ };
212
+ };
213
213
 
214
- function convertToDomain (path) {
214
+ function convertToDomain(path) {
215
215
  if (!path) {
216
- return path
216
+ return path;
217
217
  }
218
- return new URL(path).origin
218
+ return new URL(path).origin;
219
219
  }
220
220
 
221
- function wrapLoadDataWithMultiDomain (publisherConfig, f, configPos) {
222
- return async function loadDataWrapped () {
223
- const { domainSlug } = arguments[arguments.length - 1]
224
- const config = arguments[configPos]
225
- const primaryHostUrl = convertToDomain(config['sketches-host'])
226
- const domain = (config.domains || []).find(d => d.slug === domainSlug) || {
227
- 'host-url': primaryHostUrl
228
- }
229
- const result = await f.apply(this, arguments)
221
+ function wrapLoadDataWithMultiDomain(publisherConfig, f, configPos) {
222
+ return async function loadDataWrapped() {
223
+ const { domainSlug } = arguments[arguments.length - 1];
224
+ const config = arguments[configPos];
225
+ const primaryHostUrl = convertToDomain(config["sketches-host"]);
226
+ const domain = (config.domains || []).find((d) => d.slug === domainSlug) || {
227
+ "host-url": primaryHostUrl,
228
+ };
229
+ const result = await f.apply(this, arguments);
230
230
  return Object.assign(
231
231
  {
232
232
  domainSlug,
233
- currentHostUrl: convertToDomain(domain['host-url']),
234
- primaryHostUrl
233
+ currentHostUrl: convertToDomain(domain["host-url"]),
234
+ primaryHostUrl,
235
235
  },
236
236
  result
237
- )
238
- }
237
+ );
238
+ };
239
239
  }
240
240
 
241
241
  /**
@@ -257,15 +257,15 @@ function wrapLoadDataWithMultiDomain (publisherConfig, f, configPos) {
257
257
  * @param {module:routes~Handler} handler The Handler to run
258
258
  * @param {Object} opts Options that will be passed to the handler. These options will be merged with a *config* and *client*
259
259
  */
260
- function getWithConfig (app, route, handler, opts = {}) {
261
- const configWrapper = opts.configWrapper
260
+ function getWithConfig(app, route, handler, opts = {}) {
261
+ const configWrapper = opts.configWrapper;
262
262
  const {
263
- getClient = require('./api-client').getClient,
264
- publisherConfig = require('./publisher-config'),
265
- logError = require('./logger').error
266
- } = opts
267
- const withConfig = withConfigPartial(getClient, logError, publisherConfig, configWrapper)
268
- app.get(route, withConfig(handler, opts))
263
+ getClient = require("./api-client").getClient,
264
+ publisherConfig = require("./publisher-config"),
265
+ logError = require("./logger").error,
266
+ } = opts;
267
+ const withConfig = withConfigPartial(getClient, logError, publisherConfig, configWrapper);
268
+ app.get(route, withConfig(handler, opts));
269
269
  }
270
270
 
271
271
  /**
@@ -304,12 +304,12 @@ function getWithConfig (app, route, handler, opts = {}) {
304
304
  * @param {boolean|function} shouldEncodeAmpUri If set to true, then for every story-page request the slug will be encoded, in case of a vernacular slug this should be set to false. Receives path as param (default: true)
305
305
  * @param {number} sMaxAge Overrides the s-maxage value, the default value is set to 900 seconds. We can set `isomorphicRoutesSmaxage: 900` under `publisher` in publisher.yml config file that comes from BlackKnight or pass sMaxAge as a param.
306
306
  * @param {number} maxAge Overrides the max-age value, the default value is set to 15 seconds. We can set `isomorphicRoutesMaxage: 15` under `publisher` in publisher.yml config file that comes from BlackKnight or pass maxAge as a param.
307
- * @param {(object|function)} fcmServiceCreds FCM service creds is used for registering FCM Topic.
307
+ * @param {(string|function)} fcmServerKey FCM serverKey is used for registering FCM Topic.
308
308
  * @param {string} appLoadingPlaceholder This string gets injected into the app container when the page is loaded via service worker. Can be used to show skeleton layouts, animations or other progress indicators before it is replaced by the page content.
309
309
  * @param {boolean|function} enableExternalStories If set to true, then for every request an external story api call is made and renders the story-page if the story is found. (default: false)
310
310
  * @param {string|function} externalIdPattern This string specifies the external id pattern the in the url. Mention `EXTERNAL_ID` to specify the position of external id in the url. Ex: "/parent-section/child-section/EXTERNAL_ID"
311
311
  */
312
- exports.isomorphicRoutes = function isomorphicRoutes (
312
+ exports.isomorphicRoutes = function isomorphicRoutes(
313
313
  app,
314
314
  {
315
315
  generateRoutes,
@@ -320,7 +320,7 @@ exports.isomorphicRoutes = function isomorphicRoutes (
320
320
  seo,
321
321
  manifestFn,
322
322
  assetLinkFn,
323
- ampPageBasePath = '/amp/story',
323
+ ampPageBasePath = "/amp/story",
324
324
 
325
325
  oneSignalServiceWorkers = false,
326
326
  staticRoutes = [],
@@ -334,73 +334,73 @@ exports.isomorphicRoutes = function isomorphicRoutes (
334
334
  mobileConfigFields = {},
335
335
  templateOptions = false,
336
336
  lightPages = false,
337
- cdnProvider = 'cloudflare',
338
- serviceWorkerPaths = ['/service-worker.js'],
339
- maxConfigVersion = config => get(config, ['theme-attributes', 'cache-burst'], 0),
340
- configWrapper = config => config,
337
+ cdnProvider = "cloudflare",
338
+ serviceWorkerPaths = ["/service-worker.js"],
339
+ maxConfigVersion = (config) => get(config, ["theme-attributes", "cache-burst"], 0),
340
+ configWrapper = (config) => config,
341
341
 
342
342
  // The below are primarily for testing
343
- logError = require('./logger').error,
344
- assetHelper = require('./asset-helper'),
345
- getClient = require('./api-client').getClient,
343
+ logError = require("./logger").error,
344
+ assetHelper = require("./asset-helper"),
345
+ getClient = require("./api-client").getClient,
346
346
  renderServiceWorker = renderServiceWorkerFn,
347
- publisherConfig = require('./publisher-config'),
347
+ publisherConfig = require("./publisher-config"),
348
348
  redirectUrls = [],
349
- prerenderServiceUrl = '',
349
+ prerenderServiceUrl = "",
350
350
  redirectToLowercaseSlugs = false,
351
351
  shouldEncodeAmpUri,
352
352
  sMaxAge = 900,
353
353
  maxAge = 15,
354
- appLoadingPlaceholder = '',
355
- fcmServiceCreds = {},
354
+ appLoadingPlaceholder = "",
355
+ fcmServerKey = "",
356
356
  webengageConfig = {},
357
- externalIdPattern = '',
357
+ externalIdPattern = "",
358
358
  enableExternalStories = false,
359
- lazyLoadImageMargin
359
+ lazyLoadImageMargin,
360
360
  }
361
361
  ) {
362
- const withConfig = withConfigPartial(getClient, logError, publisherConfig, configWrapper)
362
+ const withConfig = withConfigPartial(getClient, logError, publisherConfig, configWrapper);
363
363
 
364
- const _sMaxAge = parseInt(get(publisherConfig, ['publisher', 'isomorphicRoutesSmaxage'], sMaxAge))
364
+ const _sMaxAge = parseInt(get(publisherConfig, ["publisher", "isomorphicRoutesSmaxage"], sMaxAge));
365
365
 
366
- const _maxAge = parseInt(get(publisherConfig, ['publisher', 'isomorphicRoutesMaxage'], maxAge))
366
+ const _maxAge = parseInt(get(publisherConfig, ["publisher", "isomorphicRoutesMaxage"], maxAge));
367
367
 
368
- pickComponent = makePickComponentSync(pickComponent)
369
- loadData = wrapLoadDataWithMultiDomain(publisherConfig, loadData, 2)
370
- loadErrorData = wrapLoadDataWithMultiDomain(publisherConfig, loadErrorData, 1)
368
+ pickComponent = makePickComponentSync(pickComponent);
369
+ loadData = wrapLoadDataWithMultiDomain(publisherConfig, loadData, 2);
370
+ loadErrorData = wrapLoadDataWithMultiDomain(publisherConfig, loadErrorData, 1);
371
371
 
372
372
  if (prerenderServiceUrl) {
373
373
  app.use((req, res, next) => {
374
374
  if (req.query.prerender) {
375
375
  try {
376
376
  // eslint-disable-next-line global-require
377
- prerender.set('protocol', 'https')
378
- prerender.set('prerenderServiceUrl', prerenderServiceUrl)(req, res, next)
377
+ prerender.set("protocol", "https");
378
+ prerender.set("prerenderServiceUrl", prerenderServiceUrl)(req, res, next);
379
379
  } catch (e) {
380
- logError(e)
380
+ logError(e);
381
381
  }
382
382
  } else {
383
- next()
383
+ next();
384
384
  }
385
- })
385
+ });
386
386
  }
387
387
 
388
388
  app.use((req, res, next) => {
389
- const origin = req.headers.origin
390
- const allowedOriginRegex = /^https?:\/\/([a-zA-Z0-9-]+\.)*quintype\.com$/
389
+ const origin = req.headers.origin;
390
+ const allowedOriginRegex = /^https?:\/\/([a-zA-Z0-9-]+\.)*quintype\.com$/;
391
391
 
392
392
  if (allowedOriginRegex.test(origin)) {
393
- res.setHeader('Access-Control-Allow-Origin', origin)
394
- res.setHeader('Access-Control-Allow-Methods', 'GET')
395
- res.setHeader('Access-Control-Allow-Headers', 'Content-Type, Authorization')
393
+ res.setHeader("Access-Control-Allow-Origin", origin);
394
+ res.setHeader("Access-Control-Allow-Methods", "GET");
395
+ res.setHeader("Access-Control-Allow-Headers", "Content-Type, Authorization");
396
396
 
397
- if (req.method === 'OPTIONS') {
398
- res.sendStatus(204)
399
- return
397
+ if (req.method === "OPTIONS") {
398
+ res.sendStatus(204);
399
+ return;
400
400
  }
401
401
  }
402
- next()
403
- })
402
+ next();
403
+ });
404
404
 
405
405
  if (serviceWorkerPaths.length > 0) {
406
406
  app.get(
@@ -409,36 +409,36 @@ exports.isomorphicRoutes = function isomorphicRoutes (
409
409
  generateRoutes,
410
410
  assetHelper,
411
411
  renderServiceWorker,
412
- maxConfigVersion
412
+ maxConfigVersion,
413
413
  })
414
- )
414
+ );
415
415
  }
416
416
 
417
417
  if (oneSignalServiceWorkers) {
418
418
  app.get(
419
- '/OneSignalSDKWorker.js',
419
+ "/OneSignalSDKWorker.js",
420
420
  withConfig(generateServiceWorker, {
421
421
  generateRoutes,
422
422
  renderServiceWorker,
423
423
  assetHelper,
424
424
  appendFn: oneSignalImport,
425
- maxConfigVersion
425
+ maxConfigVersion,
426
426
  })
427
- )
427
+ );
428
428
  app.get(
429
- '/OneSignalSDKUpdaterWorker.js',
429
+ "/OneSignalSDKUpdaterWorker.js",
430
430
  withConfig(generateServiceWorker, {
431
431
  generateRoutes,
432
432
  renderServiceWorker,
433
433
  assetHelper,
434
434
  appendFn: oneSignalImport,
435
- maxConfigVersion
435
+ maxConfigVersion,
436
436
  })
437
- )
437
+ );
438
438
  }
439
439
 
440
440
  app.get(
441
- '/shell.html',
441
+ "/shell.html",
442
442
  withConfig(handleIsomorphicShell, {
443
443
  seo,
444
444
  renderLayout,
@@ -448,11 +448,11 @@ exports.isomorphicRoutes = function isomorphicRoutes (
448
448
  logError,
449
449
  preloadJs,
450
450
  maxConfigVersion,
451
- appLoadingPlaceholder
451
+ appLoadingPlaceholder,
452
452
  })
453
- )
453
+ );
454
454
  app.get(
455
- '/route-data.json',
455
+ "/route-data.json",
456
456
  withConfig(handleIsomorphicDataLoad, {
457
457
  generateRoutes,
458
458
  loadData,
@@ -465,27 +465,27 @@ exports.isomorphicRoutes = function isomorphicRoutes (
465
465
  redirectToLowercaseSlugs,
466
466
  sMaxAge: _sMaxAge,
467
467
  maxAge: _maxAge,
468
- networkOnly: true
468
+ networkOnly: true,
469
469
  })
470
- )
470
+ );
471
471
 
472
- app.post('/register-fcm-topic', bodyParser.json(), withConfig(registerFCMTopic, { publisherConfig, fcmServiceCreds }))
472
+ app.post("/register-fcm-topic", bodyParser.json(), withConfig(registerFCMTopic, { publisherConfig, fcmServerKey }));
473
473
 
474
474
  if (webengageConfig.enableWebengage) {
475
475
  app.post(
476
- '/integrations/webengage/trigger-notification',
476
+ "/integrations/webengage/trigger-notification",
477
477
  bodyParser.json(),
478
478
  withConfig(triggerWebengageNotifications, webengageConfig)
479
- )
479
+ );
480
480
  }
481
481
 
482
482
  if (manifestFn) {
483
- app.get('/manifest.json', withConfig(handleManifest, { manifestFn, logError }))
483
+ app.get("/manifest.json", withConfig(handleManifest, { manifestFn, logError }));
484
484
  }
485
485
 
486
486
  if (mobileApiEnabled) {
487
487
  app.get(
488
- '/mobile-data.json',
488
+ "/mobile-data.json",
489
489
  withConfig(handleIsomorphicDataLoad, {
490
490
  generateRoutes,
491
491
  loadData,
@@ -499,25 +499,25 @@ exports.isomorphicRoutes = function isomorphicRoutes (
499
499
  cdnProvider,
500
500
  redirectToLowercaseSlugs,
501
501
  sMaxAge: _sMaxAge,
502
- maxAge: _maxAge
502
+ maxAge: _maxAge,
503
503
  })
504
- )
504
+ );
505
505
  }
506
506
 
507
507
  if (assetLinkFn) {
508
- app.get('/.well-known/assetlinks.json', withConfig(handleAssetLink, { assetLinkFn, logError }))
508
+ app.get("/.well-known/assetlinks.json", withConfig(handleAssetLink, { assetLinkFn, logError }));
509
509
  }
510
510
 
511
511
  if (templateOptions) {
512
512
  app.get(
513
- '/template-options.json',
513
+ "/template-options.json",
514
514
  withConfig(simpleJsonHandler, {
515
- jsonData: toFunction(templateOptions, './impl/template-options')
515
+ jsonData: toFunction(templateOptions, "./impl/template-options"),
516
516
  })
517
- )
517
+ );
518
518
  }
519
519
 
520
- staticRoutes.forEach(route => {
520
+ staticRoutes.forEach((route) => {
521
521
  app.get(
522
522
  route.path,
523
523
  withConfig(
@@ -533,16 +533,16 @@ exports.isomorphicRoutes = function isomorphicRoutes (
533
533
  oneSignalServiceWorkers,
534
534
  publisherConfig,
535
535
  sMaxAge: _sMaxAge,
536
- maxAge: _maxAge
536
+ maxAge: _maxAge,
537
537
  },
538
538
  route
539
539
  )
540
540
  )
541
- )
542
- })
541
+ );
542
+ });
543
543
 
544
544
  app.get(
545
- '/*',
545
+ "/*",
546
546
  withConfig(handleIsomorphicRoute, {
547
547
  generateRoutes,
548
548
  loadData,
@@ -566,17 +566,17 @@ exports.isomorphicRoutes = function isomorphicRoutes (
566
566
  ampPageBasePath,
567
567
  externalIdPattern,
568
568
  enableExternalStories,
569
- lazyLoadImageMargin
569
+ lazyLoadImageMargin,
570
570
  })
571
- )
571
+ );
572
572
 
573
573
  if (redirectRootLevelStories) {
574
- app.get('/:storySlug', withConfig(redirectStory, { logError, cdnProvider, sMaxAge: _sMaxAge, maxAge: _maxAge }))
574
+ app.get("/:storySlug", withConfig(redirectStory, { logError, cdnProvider, sMaxAge: _sMaxAge, maxAge: _maxAge }));
575
575
  }
576
576
 
577
577
  if (handleCustomRoute) {
578
578
  app.get(
579
- '/*',
579
+ "/*",
580
580
  withConfig(customRouteHandler, {
581
581
  loadData,
582
582
  renderLayout,
@@ -584,27 +584,27 @@ exports.isomorphicRoutes = function isomorphicRoutes (
584
584
  seo,
585
585
  cdnProvider,
586
586
  sMaxAge: _sMaxAge,
587
- maxAge: _maxAge
587
+ maxAge: _maxAge,
588
588
  })
589
- )
589
+ );
590
590
  }
591
591
 
592
592
  if (handleNotFound) {
593
593
  app.get(
594
- '/*',
594
+ "/*",
595
595
  withConfig(notFoundHandler, {
596
596
  renderLayout,
597
597
  pickComponent,
598
598
  loadErrorData,
599
599
  logError,
600
600
  seo,
601
- assetHelper
601
+ assetHelper,
602
602
  })
603
- )
603
+ );
604
604
  }
605
- }
605
+ };
606
606
 
607
- exports.getWithConfig = getWithConfig
607
+ exports.getWithConfig = getWithConfig;
608
608
 
609
609
  /**
610
610
  * *proxyGetRequest* can be used to forward requests to another host, and cache the results on our CDN. This can be done as follows in `app/server/app.js`.
@@ -624,52 +624,52 @@ exports.getWithConfig = getWithConfig
624
624
  * @param opts.cacheControl The cache control header to set on proxied requests (default: *"public,max-age=15,s-maxage=240,stale-while-revalidate=300,stale-if-error=3600"*)
625
625
  */
626
626
  exports.proxyGetRequest = function (app, route, handler, opts = {}) {
627
- const { logError = require('./logger').error } = opts
628
- const { cacheControl = 'public,max-age=15,s-maxage=240,stale-while-revalidate=300,stale-if-error=3600' } = opts
627
+ const { logError = require("./logger").error } = opts;
628
+ const { cacheControl = "public,max-age=15,s-maxage=240,stale-while-revalidate=300,stale-if-error=3600" } = opts;
629
629
 
630
- getWithConfig(app, route, proxyHandler, opts)
630
+ getWithConfig(app, route, proxyHandler, opts);
631
631
 
632
- async function proxyHandler (req, res, next, { config, client }) {
632
+ async function proxyHandler(req, res, next, { config, client }) {
633
633
  try {
634
- const result = await handler(req.params, { config, client })
635
- if (typeof result === 'string' && result.startsWith('http')) {
636
- sendResult(await rp(result, { json: true }))
634
+ const result = await handler(req.params, { config, client });
635
+ if (typeof result === "string" && result.startsWith("http")) {
636
+ sendResult(await rp(result, { json: true }));
637
637
  } else {
638
- sendResult(result)
638
+ sendResult(result);
639
639
  }
640
640
  } catch (e) {
641
- logError(e)
642
- sendResult(null)
641
+ logError(e);
642
+ sendResult(null);
643
643
  }
644
644
 
645
- function sendResult (result) {
645
+ function sendResult(result) {
646
646
  if (result) {
647
- res.setHeader('Cache-Control', cacheControl)
648
- res.setHeader('Vary', 'Accept-Encoding')
649
- res.json(result)
647
+ res.setHeader("Cache-Control", cacheControl);
648
+ res.setHeader("Vary", "Accept-Encoding");
649
+ res.json(result);
650
650
  } else {
651
- res.status(503)
652
- res.end()
651
+ res.status(503);
652
+ res.end();
653
653
  }
654
654
  }
655
655
  }
656
- }
656
+ };
657
657
 
658
658
  // This could also be done using express's mount point, but /ping stops working
659
659
  exports.mountQuintypeAt = function (app, mountAt) {
660
660
  app.use(function (req, res, next) {
661
- const mountPoint = typeof mountAt === 'function' ? mountAt(req.hostname) : mountAt
661
+ const mountPoint = typeof mountAt === "function" ? mountAt(req.hostname) : mountAt;
662
662
 
663
663
  if (mountPoint && req.url.startsWith(mountPoint)) {
664
- req.url = req.url.slice(mountPoint.length) || '/'
665
- next()
666
- } else if (mountPoint && req.url !== '/ping') {
667
- res.status(404).send(`Not Found: Quintype has been mounted at ${mountPoint}`)
664
+ req.url = req.url.slice(mountPoint.length) || "/";
665
+ next();
666
+ } else if (mountPoint && req.url !== "/ping") {
667
+ res.status(404).send(`Not Found: Quintype has been mounted at ${mountPoint}`);
668
668
  } else {
669
- next()
669
+ next();
670
670
  }
671
- })
672
- }
671
+ });
672
+ };
673
673
 
674
674
  /**
675
675
  * *ampRoutes* handles all the amp page routes using the *[@quintype/amp](https://developers.quintype.com/quintype-node-amp)* library
@@ -677,9 +677,30 @@ exports.mountQuintypeAt = function (app, mountAt) {
677
677
  * GET - "/amp/:slug"* returns amp story page
678
678
  * GET - "/amp/api/v1/amp-infinite-scroll" returns the infinite scroll config JSON. Passed to <amp-next-page> component's `src` attribute
679
679
  *
680
- * To disable amp version for a specific story, you need to create a story attribute in bold with the slug {disable-amp-for-single-story} and values {true} and {false}. Set its value to "true" in the story which you want to disable amp. Please make sure to name the attributes and values in the exact same way as mentioned
680
+ * To disable amp version for a "specific story", you need to create a story attribute in bold with the slug {disable-amp-for-single-story} and values {true} and {false}. Set its value to "true" in the story which you want to disable amp. Please make sure to name the attributes and values in the exact same way as mentioned
681
681
  * attribute slug: "disable-amp-for-single-story" values: "true" , "false". This will redirect '<amp-page-base-path>/:slug' to the non-amp page
682
682
  *
683
+ * To disable the AMP version for a specific story template or section, pass opts.disableAmpUnit as a function that always returns a boolean value. When the function returns true, AMP will be disabled for the specified scenario.
684
+ * Note: Ensure that disableAmpUnit is always a function and returns a boolean value, as demonstrated below.
685
+ *
686
+ * Under app/server/app.js
687
+ *
688
+ * ``` const getTemplate = (story) => {
689
+ * return story.["story-template"] === "template-name";
690
+ * };
691
+ *
692
+ * ....
693
+ *
694
+ * ampRoutes(app, {
695
+ * seo: generateSeo,
696
+ * disableAmpUnit: (story) => getTemplate(story),
697
+ * featureConfig: {
698
+ * .....
699
+ * }
700
+ * ...
701
+ * .....
702
+ * })```
703
+ *
683
704
  * @param {Express} app Express app to add the routes to
684
705
  * @param {Object} opts Options object used to configure amp. Passing this is optional
685
706
  * @param {Object} opts.templates An object that's used to pass custom templates. Each key corresponds to the template name and corresponding value is the template
@@ -692,9 +713,9 @@ exports.mountQuintypeAt = function (app, mountAt) {
692
713
  *
693
714
  */
694
715
  exports.ampRoutes = (app, opts = {}) => {
695
- const { ampStoryPageHandler, storyPageInfiniteScrollHandler } = require('./amp/handlers')
716
+ const { ampStoryPageHandler, storyPageInfiniteScrollHandler } = require("./amp/handlers");
696
717
 
697
- getWithConfig(app, '/amp/api/v1/amp-infinite-scroll', storyPageInfiniteScrollHandler, opts)
698
- getWithConfig(app, '/ampstories/*', ampStoryPageHandler, { ...opts, isVisualStory: true })
699
- getWithConfig(app, '/*', ampStoryPageHandler, opts)
700
- }
718
+ getWithConfig(app, "/amp/api/v1/amp-infinite-scroll", storyPageInfiniteScrollHandler, opts);
719
+ getWithConfig(app, "/ampstories/*", ampStoryPageHandler, { ...opts, isVisualStory: true });
720
+ getWithConfig(app, "/*", ampStoryPageHandler, opts);
721
+ };