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