UNPKG

firebase-childrenkeys

Version:

Fetch children keys of Firebase Admin Database References via the REST API

66 lines (59 loc) 2.42 kB
'use strict'; const sleep = require('sleep-promise'); /** * Fetches the keys of the current reference's children without also fetching all the contents, * using the Firebase REST API. * * @param {Reference} ref A Firebase database reference. * @param {object} options An options object with the following items, all optional: * - maxTries: the maximum number of times to try to fetch the keys, in case of transient errors * (defaults to 1) * - retryInterval: the number of milliseconds to delay between retries (defaults to 1000) * @return A promise that resolves to an array of key strings. */ module.exports = async (ref, options = {}) => { const refIsNonNullObject = typeof ref === 'object' && ref !== null; if (!refIsNonNullObject || typeof ref.ref !== 'object' || typeof ref.ref.transaction !== 'function') { throw new Error( `Expected first argument passed to childrenKeys() to be a Firebase Database reference, but got "${ref}".` ); } else if (typeof options !== 'object' || options === null) { throw new Error( `Expected second argument passed to childrenKeys() to be an options object, but got "${options}".` ); } // The database property exists on Reference, but not Query. Doing ref.ref ensures we are dealing // with a Reference instance. const accessTokenObj = await ref.ref.database.app.options.credential.getAccessToken(); const url = new URL(ref.toString() + '.json'); url.searchParams.set('shallow', 'true'); url.searchParams.set('access_token', accessTokenObj.access_token); let tries = 0; async function tryRequest() { tries++; let data; try { const response = await fetch(url); data = await response.text(); if (!response.ok) throw new Error(`HTTP ${response.status}: ${data}`); } catch (error) { if (options.maxTries && tries < options.maxTries) { await sleep(options.retryInterval || 1000); return tryRequest(); } throw error; } let match; match = data.match(/"error"\s*:\s*"([^"]*)"/); if (match) throw new Error(`Failed to fetch children keys from Firebase REST API: ${match[1]}`); const regex = /"(.*?)"/g; const keys = []; // eslint-disable-next-line no-cond-assign while (match = regex.exec(data)) keys.push(match[1]); // don't unescape keys! return keys; } return tryRequest(); };