Here's one that doesn't need a package.
You'll need makeHeader(consumer, token, request) which works for me with Node's https.request but should also work for Axios.
const crypto = require('crypto');
const { stringify: qStringify } = require('querystring');
const { httpOptions, fetch } = require('./fetch');
function nonce() {
  return crypto.randomBytes(16).toString('hex');
}
function sign(baseStr, key) {
  return crypto.createHmac('sha1', key).update(baseStr).digest('base64');
}
function percentEncode(str) {
  const notEscapedRe = /[!'()*]/g;
  return encodeURIComponent(str).replace(notEscapedRe, (c) => `%${c.charCodeAt(0).toString(16)}`);
}
function makeObjStr(parameters, quote = '"', split = ',') {
  const ordered = Object.fromEntries(Object.entries(parameters).sort());
  return Object.entries(ordered).map(([key, value]) => `${percentEncode(key)}=${quote}${percentEncode(value)}${quote}`).join(split);
}
function authHeader(parameters) {
  return { Authorization: `OAuth ${makeObjStr(parameters)}` };
}
function makeHeader(consumer, token, request) {
  const oauthData = {
    oauth_consumer_key: consumer.key,
    oauth_token: token.key,
    oauth_nonce: nonce(),
    oauth_signature_method: 'HMAC-SHA1',
    oauth_timestamp: Math.floor(Date.now() / 1000),
    oauth_version: '1.0',
  };
  const baseStr = [
    request.method.toUpperCase(),
    percentEncode(request.url),
    percentEncode(makeObjStr({ ...request.data, ...oauthData }, '', '&')),
  ].join('&');
  const signingKey = [percentEncode(consumer.secret), percentEncode(token.secret)].join('&');
  return authHeader({
    ...oauthData,
    oauth_signature: sign(baseStr, signingKey),
  });
}
function oAuth1Fetch({
  consumer, token, hostname, path, query = {},
}) {
  const request = {
    method: 'GET',
    url: `https://${hostname}${path}`,
    data: query,
  };
  return fetch({
    ...httpOptions,
    headers: makeHeader(consumer, token, request),
    hostname,
    path: `${path}?${qStringify(query)}`,
  });
}
module.exports = {
  oAuth1Fetch,
};
Here's my fetch:
const { Agent, request } = require('https');
const httpOptions = {
  agent: new Agent({ keepAlive: true }),
  'User-Agent': `AWS Lambda Node/${process.version} surflog.app`,
  // Accept: 'application/json',
};
function fetch(options) {
  return new Promise((resolve, reject) => {
    const req = request(options, (res) => {
      const data = [];
      res.on('data', (chunk) => data.push(chunk));
      res.on('end', () => {
        const result = Buffer.concat(data).toString();
        console.log(res.statusCode);
        if (res.statusCode >= 200 && res.statusCode < 300) {
          resolve(result);
        } else {
          reject(result);
        }
      });
    });
    req.setTimeout(6000, (err) => {
      console.warn(err);
      console.warn('Timeout', options.hostname);
    });
    req.on('error', reject);
    req.end();
  });
}
module.exports = {
  httpOptions,
  fetch,
};
An example:
oAuth1Fetch({
  consumer: {
    key: 'xyz',
    secret: 'xyz',
  },
  token: {
    key: 'xyz',
    secret: 'xyz',
  },
  hostname: 'apis.garmin.com',
  path: '/wellness-api/rest/backfill/activities',
  query: {
    summaryStartTimeInSeconds: 1609459200,
    summaryEndTimeInSeconds: 1609459200 + 7776000,
  },
}).then(console.log).catch(console.error);