@mindful-web/marko-web 1.28.0 → 1.42.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.
Files changed (129) hide show
  1. package/components/bot-scores.marko +12 -0
  2. package/components/bot-scores.marko.js +40 -0
  3. package/components/browser-component/script.marko.js +2 -2
  4. package/components/browser-component.marko.js +2 -2
  5. package/components/deferred-stylesheet.marko.js +2 -2
  6. package/components/document/components/body-wrapper.marko.js +2 -2
  7. package/components/document/components/error.marko.js +2 -2
  8. package/components/document/components/live-reload.marko.js +2 -2
  9. package/components/document/components/polyfill.marko.js +2 -2
  10. package/components/document/components/styles.marko.js +2 -2
  11. package/components/document/container.marko.js +2 -2
  12. package/components/document/index.marko +2 -0
  13. package/components/document/index.marko.js +20 -15
  14. package/components/element/array.marko.js +2 -2
  15. package/components/element/audio.marko.js +2 -2
  16. package/components/element/block.marko.js +2 -2
  17. package/components/element/clear.marko.js +2 -2
  18. package/components/element/components/image.marko.js +2 -2
  19. package/components/element/components/text.marko.js +2 -2
  20. package/components/element/content/address1.marko.js +2 -2
  21. package/components/element/content/address2.marko.js +2 -2
  22. package/components/element/content/audio.marko.js +2 -2
  23. package/components/element/content/authors.marko.js +2 -2
  24. package/components/element/content/body.marko.js +2 -2
  25. package/components/element/content/byline.marko.js +2 -2
  26. package/components/element/content/city-state-zip.marko.js +2 -2
  27. package/components/element/content/contributors.marko.js +2 -2
  28. package/components/element/content/country.marko.js +2 -2
  29. package/components/element/content/embed-code.marko.js +2 -2
  30. package/components/element/content/end-date.marko.js +2 -2
  31. package/components/element/content/ends.marko.js +2 -2
  32. package/components/element/content/fax.marko.js +2 -2
  33. package/components/element/content/images.marko.js +2 -2
  34. package/components/element/content/mobile.marko.js +2 -2
  35. package/components/element/content/name.marko.js +2 -2
  36. package/components/element/content/phone.marko.js +2 -2
  37. package/components/element/content/photographers.marko.js +2 -2
  38. package/components/element/content/public-email.marko.js +2 -2
  39. package/components/element/content/published.marko.js +2 -2
  40. package/components/element/content/short-name.marko.js +2 -2
  41. package/components/element/content/sidebar-stubs.marko.js +2 -2
  42. package/components/element/content/sidebars.marko.js +2 -2
  43. package/components/element/content/source.marko.js +2 -2
  44. package/components/element/content/sponsors.marko.js +2 -2
  45. package/components/element/content/start-date.marko.js +2 -2
  46. package/components/element/content/starts.marko.js +2 -2
  47. package/components/element/content/teaser.marko.js +2 -2
  48. package/components/element/content/title.marko.js +2 -2
  49. package/components/element/content/tollfree.marko.js +2 -2
  50. package/components/element/content/transcript.marko.js +2 -2
  51. package/components/element/content/website-deck.marko.js +2 -2
  52. package/components/element/content/website.marko.js +2 -2
  53. package/components/element/date.marko.js +2 -2
  54. package/components/element/image/caption.marko.js +2 -2
  55. package/components/element/image/credit.marko.js +2 -2
  56. package/components/element/image/display-name.marko.js +2 -2
  57. package/components/element/image/slider.marko.js +2 -2
  58. package/components/element/img.marko.js +2 -2
  59. package/components/element/index.marko.js +2 -2
  60. package/components/element/link.marko.js +2 -2
  61. package/components/element/magazine-issue/description.marko.js +2 -2
  62. package/components/element/magazine-issue/digital-edition-url.marko.js +2 -2
  63. package/components/element/magazine-issue/name.marko.js +2 -2
  64. package/components/element/magazine-issue/pdf-url.marko.js +2 -2
  65. package/components/element/magazine-publication/cancel-url.marko.js +2 -2
  66. package/components/element/magazine-publication/change-address-url.marko.js +2 -2
  67. package/components/element/magazine-publication/description.marko.js +2 -2
  68. package/components/element/magazine-publication/einquiry-url.marko.js +2 -2
  69. package/components/element/magazine-publication/name.marko.js +2 -2
  70. package/components/element/magazine-publication/renewal-url.marko.js +2 -2
  71. package/components/element/magazine-publication/reprints-url.marko.js +2 -2
  72. package/components/element/magazine-publication/subscribe-url.marko.js +2 -2
  73. package/components/element/obj-array.marko.js +2 -2
  74. package/components/element/obj-audio.marko.js +2 -2
  75. package/components/element/obj-date.marko.js +2 -2
  76. package/components/element/obj-nodes.marko.js +2 -2
  77. package/components/element/obj-text.marko.js +2 -2
  78. package/components/element/obj.marko.js +2 -2
  79. package/components/element/picture.marko.js +2 -2
  80. package/components/element/text.marko.js +2 -2
  81. package/components/element/website-section/description.marko.js +2 -2
  82. package/components/element/website-section/hierarchy.marko.js +2 -2
  83. package/components/element/website-section/name.marko.js +2 -2
  84. package/components/font/google.marko.js +2 -2
  85. package/components/font/link.marko.js +2 -2
  86. package/components/font/typekit.marko.js +2 -2
  87. package/components/load-more/index.marko.js +2 -2
  88. package/components/load-more/trigger.marko.js +2 -2
  89. package/components/marko.json +3 -0
  90. package/components/node/body.marko.js +2 -2
  91. package/components/node/element.marko.js +2 -2
  92. package/components/node/footer.marko.js +2 -2
  93. package/components/node/header.marko.js +2 -2
  94. package/components/node/image-inner-wrapper.marko.js +2 -2
  95. package/components/node/image-wrapper.marko.js +2 -2
  96. package/components/node/image.marko.js +2 -2
  97. package/components/node/index.marko.js +2 -2
  98. package/components/node-list/body.marko.js +2 -2
  99. package/components/node-list/element.marko.js +2 -2
  100. package/components/node-list/footer.marko.js +2 -2
  101. package/components/node-list/header.marko.js +2 -2
  102. package/components/node-list/index.marko.js +2 -2
  103. package/components/node-list/node.marko.js +2 -2
  104. package/components/node-list/nodes.marko.js +2 -2
  105. package/components/page/container.marko.js +2 -2
  106. package/components/page/description.marko.js +2 -2
  107. package/components/page/image.marko.js +2 -2
  108. package/components/page/layouts/content.marko.js +2 -2
  109. package/components/page/layouts/default.marko.js +2 -2
  110. package/components/page/layouts/dynamic-page.marko.js +2 -2
  111. package/components/page/layouts/magazine-issue.marko.js +2 -2
  112. package/components/page/layouts/magazine-publication.marko.js +2 -2
  113. package/components/page/layouts/website-section.marko.js +2 -2
  114. package/components/page/metadata/components/common.marko.js +2 -2
  115. package/components/page/metadata/content.marko.js +2 -2
  116. package/components/page/metadata/default.marko.js +2 -2
  117. package/components/page/metadata/dynamic-page.marko.js +2 -2
  118. package/components/page/metadata/magazine-issue.marko.js +2 -2
  119. package/components/page/metadata/magazine-publication.marko.js +2 -2
  120. package/components/page/metadata/website-section.marko.js +2 -2
  121. package/components/page/rel-canonical.marko.js +2 -2
  122. package/components/page/title.marko.js +2 -2
  123. package/components/page/wrapper.marko.js +2 -2
  124. package/components/resolve/page.marko.js +2 -2
  125. package/components/rss/website-section.marko.js +2 -2
  126. package/express/bot-scores.js +108 -0
  127. package/express/index.js +9 -0
  128. package/express/website-context.js +9 -2
  129. package/package.json +2 -2
@@ -0,0 +1,108 @@
1
+ const { asyncRoute, cleanPath } = require('@mindful-web/utils');
2
+ const fetch = require('node-fetch');
3
+ const { extname } = require('path');
4
+
5
+ const { error } = console;
6
+
7
+ module.exports = function botScores({
8
+ apiKey,
9
+ app,
10
+ enabled,
11
+ url,
12
+ }) {
13
+ const hasRequiredProps = Boolean(apiKey && url);
14
+ const isEnabled = hasRequiredProps ? enabled : false;
15
+
16
+ app.post('/__bmsc', asyncRoute(async (req, res) => {
17
+ if (!isEnabled) return;
18
+ const env = process.env.NODE_ENV;
19
+ const showInfo = env === 'development' || req.query.debug === 'true';
20
+ try {
21
+ // remove incoming host header
22
+ const { host, ...headers } = req.headers;
23
+ const response = await fetch(`${cleanPath(url)}/collect`, {
24
+ method: 'POST',
25
+ headers: {
26
+ ...headers,
27
+ ...(env === 'development' && {
28
+ origin: `https://${app.locals.config.website('host')}`,
29
+ }),
30
+ authorization: `Bearer ${apiKey}`,
31
+ 'x-env': env,
32
+ },
33
+ body: JSON.stringify({}),
34
+ });
35
+ if (!response.ok) throw new Error(`Bad response: ${response.status}`);
36
+ const info = showInfo ? await response.json() : undefined;
37
+
38
+ res.send({ ok: true, info });
39
+ } catch (e) {
40
+ // @todo better logging
41
+ error(`error collecting bot score info: ${e.message}`);
42
+ res.send({ ok: false, ...(showInfo && { info: e.message }) });
43
+ }
44
+ }));
45
+
46
+ return (_, res, next) => {
47
+ /** @type {BotScores} */
48
+ const $botScores = {
49
+ buildFetchHeaders() {
50
+ const [org] = app.locals.tenantKey.split('_');
51
+ return {
52
+ 'content-type': 'application/json',
53
+ 'x-host': app.locals.config.website('host'),
54
+ 'x-org-key': org,
55
+ 'x-requested-with': 'XMLHttpRequest',
56
+ 'x-token': this.token,
57
+ };
58
+ },
59
+ enabled: isEnabled,
60
+ isValidRequestPath: (path) => {
61
+ if (!path) return false;
62
+ if (path.startsWith('/__') || path.startsWith('/dist') || path.startsWith('/print/content')) return false;
63
+ if (extname(path)) return false;
64
+ return true;
65
+ },
66
+ loadToken: async () => {
67
+ if (!isEnabled) return;
68
+ if ($botScores.token) return;
69
+ try {
70
+ const response = await fetch(`${cleanPath(url)}/token`, {
71
+ method: 'GET',
72
+ headers: { authorization: `Bearer ${apiKey}` },
73
+ });
74
+ if (!response.ok) throw new Error(`Bad response: ${response.status}`);
75
+ const { token } = await response.json();
76
+ $botScores.token = token;
77
+ } catch (e) {
78
+ // @todo better logging
79
+ error(`error retrieving bot scores token: ${e.message}`);
80
+ }
81
+ },
82
+ };
83
+ res.locals.$botScores = $botScores;
84
+ next();
85
+ };
86
+ };
87
+
88
+ /**
89
+ * @typedef BotScores
90
+ * @prop {BuildFetchHeadersFn} buildFetchHeaders
91
+ * @prop {boolean} enabled
92
+ * @prop {IsValidRequestPathFn} isValidRequestPath
93
+ * @prop {BotScoresLoadTokenFn} loadToken
94
+ * @prop {string} [token]
95
+ */
96
+ /**
97
+ * @callback BotScoresLoadTokenFn
98
+ * @returns {Promise<void>}
99
+ */
100
+ /**
101
+ * @callback BuildFetchHeadersFn
102
+ * @return {Record<string, string>}
103
+ */
104
+ /**
105
+ * @callback IsValidRequestPathFn
106
+ * @param {string} path
107
+ * @return {boolean}
108
+ */
package/express/index.js CHANGED
@@ -7,6 +7,7 @@ const path = require('path');
7
7
  const helmet = require('helmet');
8
8
  const { nanoid } = require('nanoid');
9
9
  const apollo = require('./apollo');
10
+ const botScores = require('./bot-scores');
10
11
  const graphqlProxy = require('./graphql-proxy');
11
12
  const embeddedMedia = require('./embedded-media');
12
13
  const loadObject = require('./load-object');
@@ -116,6 +117,14 @@ module.exports = (config = {}) => {
116
117
  });
117
118
  }
118
119
 
120
+ // must be loaded _before_ website context
121
+ app.use(botScores({
122
+ apiKey: process.env.BOT_SCORES_API_KEY,
123
+ app,
124
+ enabled: process.env.BOT_SCORES_DISABLE !== 'true',
125
+ url: process.env.BOT_SCORES_URL,
126
+ }));
127
+
119
128
  // Set website context.
120
129
  app.use(websiteContext(app.locals.config));
121
130
 
@@ -3,8 +3,15 @@ const { asyncRoute } = require('@mindful-web/utils');
3
3
  const { setDayjsLocale } = require('@mindful-web/dayjs/utils');
4
4
 
5
5
  module.exports = (coreConfig) => asyncRoute(async (req, res, next) => {
6
- const { apollo } = res.locals;
7
- const websiteContext = await loadWebsite(apollo);
6
+ /** @type {{ apollo: any; $botScores?: import("./bot-scores").BotScores }} */
7
+ const { apollo, $botScores } = res.locals;
8
+ const [websiteContext] = await Promise.all([
9
+ loadWebsite(apollo),
10
+ (async () => {
11
+ if (!$botScores || !$botScores.isValidRequestPath(req.path)) return null;
12
+ return $botScores.loadToken();
13
+ })(),
14
+ ]);
8
15
  coreConfig.setWebsiteContext(websiteContext);
9
16
 
10
17
  const locale = coreConfig.website('date.locale');
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@mindful-web/marko-web",
3
- "version": "1.28.0",
3
+ "version": "1.42.0",
4
4
  "description": "Core Marko+Express components for Mindful Web websites",
5
5
  "author": "Jacob Bare <jacob@parameter1.com>",
6
6
  "main": "index.js",
@@ -60,5 +60,5 @@
60
60
  "publishConfig": {
61
61
  "access": "public"
62
62
  },
63
- "gitHead": "49740ec41e40566786bb521ab657f418c0538609"
63
+ "gitHead": "278285910cc076501cd92f2c942e08aeea7a77cf"
64
64
  }