7a918bb9f4eaf1d7b588152d35290268ced89aa5
[squeep-indieauth-helper] / lib / common.js
1 'use strict';
2
3 /**
4 * Pick out useful got response fields.
5 * @param {GotResponse} res
6 * @returns {Object}
7 */
8 const gotResponseLogData = (res) => {
9 const data = pick(res, [
10 'statusCode',
11 'statusMessage',
12 'headers',
13 'body',
14 'error',
15 ]);
16 if (typeof res.body === 'string') {
17 data.body = logTruncate(data.body, 100);
18 } else if (res.body instanceof Buffer) {
19 data.body = `<Buffer ${res.body.byteLength} bytes>`;
20 }
21 data.elapsedTimeMs = res?.timings?.phases?.total;
22 if (res?.redirectUrls?.length) {
23 data.redirectUrls = res.redirectUrls;
24 }
25 if (res?.retryCount) {
26 data.retryCount = res.retryCount;
27 }
28 return data;
29 };
30
31
32 /**
33 * Limit length of string to keep logs sane
34 * @param {String} str
35 * @param {Number} len
36 * @returns {String}
37 */
38 const logTruncate = (str, len) => {
39 if (typeof str !== 'string' || str.toString().length <= len) {
40 return str;
41 }
42 return str.toString().slice(0, len) + `... (${str.toString().length} bytes)`;
43 };
44
45
46 /**
47 * Return a new object with selected props.
48 * @param {Object} obj
49 * @param {String[]} props
50 */
51 const pick = (obj, props) => {
52 return props.reduce((acc, prop) => {
53 if (prop in obj) {
54 acc[prop] = obj[prop]; // eslint-disable-line security/detect-object-injection
55 }
56 return acc;
57 }, {});
58 };
59
60
61 /**
62 * Return a set containing non-shared items between two sets.
63 * @param {Set} a
64 * @param {Set} b
65 * @returns {Set}
66 */
67 const setSymmetricDifference = (a, b) => {
68 const d = new Set(a);
69 for (const x of b) {
70 if (d.has(x)) {
71 d.delete(x);
72 } else {
73 d.add(x);
74 }
75 }
76 return d;
77 };
78
79
80 /**
81 * URL objects have weird names.
82 * @param {String} component
83 * @returns {String}
84 */
85 const properURLComponentName = (component) => {
86 // eslint-disable-next-line security/detect-object-injection
87 return {
88 hash: 'fragment',
89 protocol: 'scheme',
90 }[component] || component;
91 }
92
93
94 module.exports = {
95 gotResponseLogData,
96 logTruncate,
97 pick,
98 setSymmetricDifference,
99 properURLComponentName,
100 };