@forest-fire/utility
Advanced tools
Comparing version 0.54.3 to 0.55.0
@@ -1,17 +0,202 @@ | ||
"use strict"; | ||
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { | ||
if (k2 === undefined) k2 = k; | ||
Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } }); | ||
}) : (function(o, m, k, k2) { | ||
if (k2 === undefined) k2 = k; | ||
o[k2] = m[k]; | ||
})); | ||
var __exportStar = (this && this.__exportStar) || function(m, exports) { | ||
for (var p in m) if (p !== "default" && !exports.hasOwnProperty(p)) __createBinding(exports, m, p); | ||
'use strict'; | ||
Object.defineProperty(exports, '__esModule', { value: true }); | ||
class FireError extends Error { | ||
constructor(message, | ||
/** | ||
* a type/subtype of the error or you can just state the "subtype" | ||
* and it will | ||
*/ | ||
classification = 'UniversalFire/error', statusCode = 400) { | ||
super(message); | ||
this.universalFire = true; | ||
this.kind = 'FireError'; | ||
const parts = classification.split('/'); | ||
const klass = this.constructor.name; | ||
this.name = parts.length === 2 ? classification : `${klass}/${parts[0]}`; | ||
this.code = parts.length === 2 ? parts[1] : parts[0]; | ||
this.kind = parts[0]; | ||
this.statusCode = statusCode; | ||
} | ||
} | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
__exportStar(require("./errors/index"), exports); | ||
__exportStar(require("./admin-sdk/index"), exports); | ||
__exportStar(require("./shared/index"), exports); | ||
__exportStar(require("./client-sdk/index"), exports); | ||
//# sourceMappingURL=index.js.map | ||
function isMockConfig(config) { | ||
return config && config.mocking === true; | ||
} | ||
var RealQueryOrderType; | ||
(function (RealQueryOrderType) { | ||
RealQueryOrderType["orderByChild"] = "orderByChild"; | ||
RealQueryOrderType["orderByKey"] = "orderByKey"; | ||
RealQueryOrderType["orderByValue"] = "orderByValue"; | ||
})(RealQueryOrderType || (RealQueryOrderType = {})); | ||
/** | ||
* Takes as input a variety of possible formats and converts it into | ||
* a Firebase service account (`IServiceAccount`). The input formats | ||
* which it accepts are: | ||
* | ||
* - an `IServiceAccount` object (_in which case nothing to be done_) | ||
* - a JSON encoded string of the `IServiceAccount` object | ||
* - a base64 encoded string of a `IServiceAccount` object (_possible but not recommended | ||
* as an ENV variable may run out of room to encode_) | ||
* - a base64 encoded GZIP of a `IServiceAccount` object (_this is ideal for ENV vars | ||
* which have limited length and must be string_) | ||
*/ | ||
function extractServiceAccount(config) { | ||
if (isMockConfig(config)) { | ||
return {}; | ||
} | ||
const serviceAccount = config && config.mocking !== true && config.serviceAccount | ||
? config.serviceAccount | ||
: process.env['FIREBASE_SERVICE_ACCOUNT']; | ||
if (!serviceAccount) { | ||
throw new FireError(`There was no service account defined (either passed in or in the FIREBASE_SERVICE_ACCOUNT ENV variable)!`, 'invalid-configuration'); | ||
} | ||
switch (typeof serviceAccount) { | ||
case 'object': | ||
if (serviceAccount.privateKey && serviceAccount.projectId) { | ||
return serviceAccount; | ||
} | ||
else { | ||
throw new FireError(`An attempt to use the Admin SDK failed because a service account object was passed in but it did NOT have the required properties of "privateKey" and "projectId".`, 'invalid-configuration'); | ||
} | ||
case 'string': | ||
// JSON | ||
if (looksLikeJson(serviceAccount)) { | ||
try { | ||
const data = JSON.parse(serviceAccount); | ||
if (data.private_key && data.type === 'service_account') { | ||
return data; | ||
} | ||
else { | ||
throw new FireError(`The configuration appeared to contain a JSON encoded representation of the service account but after decoding it the private_key and/or the type property were not correctly set.`, 'invalid-configuration'); | ||
} | ||
} | ||
catch (e) { | ||
throw new FireError(`The configuration appeared to contain a JSOn encoded representation but was unable to be parsed: ${e.message}`, 'invalid-configuration'); | ||
} | ||
} | ||
// BASE 64 | ||
try { | ||
const buffer = Buffer.from(serviceAccount, 'base64'); | ||
return JSON.parse(buffer.toString()); | ||
} | ||
catch (e) { | ||
throw new FireError(`Failed to convert a string based service account to IServiceAccount! The error was: ${e.message}`, 'invalid-configuration'); | ||
} | ||
default: | ||
throw new FireError(`Couldn't extract the serviceAccount from ENV variables! The configuration was:\n${(2)}`, 'invalid-configuration'); | ||
} | ||
} | ||
/** | ||
* extracts the Firebase **databaseURL** property either from the passed in | ||
* configuration or via the FIREBASE_DATABASE_URL environment variable. | ||
*/ | ||
function extractDataUrl(config) { | ||
if (isMockConfig(config)) { | ||
return 'https://mocking.com'; | ||
} | ||
const dataUrl = config && config.databaseURL | ||
? config.databaseURL | ||
: process.env['FIREBASE_DATABASE_URL']; | ||
if (!dataUrl) { | ||
throw new FireError(`There was no DATABASE URL provided! This needs to be passed in as part of the configuration or as the FIREBASE_DATABASE_URL environment variable.`, 'invalid-configuration'); | ||
} | ||
return dataUrl; | ||
} | ||
/** | ||
* Returns an array of named apps that are running under | ||
* Firebase's control (admin API) | ||
*/ | ||
function getRunningApps(apps) { | ||
return apps.filter((i) => i !== null).map((i) => i.name); | ||
} | ||
/** Gets the */ | ||
function getRunningFirebaseApp(name, apps) { | ||
const result = name | ||
? apps.find((i) => i && i.name === name) | ||
: undefined; | ||
if (!result) { | ||
throw new FireError(`Attempt to get the Firebase app named "${name}" failed`, 'invalid-app-name'); | ||
} | ||
return result; | ||
} | ||
function looksLikeJson(data) { | ||
return data.trim().slice(0, 1) === '{' && data.trim().slice(-1) === '}' | ||
? true | ||
: false; | ||
} | ||
function extractEncodedString(data) { | ||
if (!data) { | ||
return undefined; | ||
} | ||
let failedJsonParse = false; | ||
if (looksLikeJson(data)) { | ||
try { | ||
return JSON.parse(data); | ||
} | ||
catch (e) { | ||
// ignore and try BASE64 | ||
failedJsonParse = true; | ||
} | ||
} | ||
try { | ||
const buffer = Buffer.from(data, 'base64'); | ||
return JSON.parse(buffer.toString()); | ||
} | ||
catch (e) { | ||
if (failedJsonParse) { | ||
throw new FireError(`Failed to parse the passed in encoded string; it appeared to be a JSON string but both JSON and Base64 decoding failed!`, `parse-failed`); | ||
} | ||
else { | ||
throw new FireError(`Failed to parse the passed in the Base64 encoded string`, `parse-failed`); | ||
} | ||
} | ||
} | ||
function slashNotation(path) { | ||
return path.replace(/\./g, '/'); | ||
} | ||
function dotNotation(path) { | ||
path = path.slice(0, 1) === '/' ? path.slice(1) : path; | ||
return path ? path.replace(/\//g, '.') : undefined; | ||
} | ||
function determineDefaultAppName(config) { | ||
if (!config) { | ||
return '[DEFAULT]'; | ||
} | ||
return config.name | ||
? config.name | ||
: config.databaseURL | ||
? config.databaseURL.replace(/.*https:\W*([\w-]*)\.((.|\n)*)/g, '$1') | ||
: '[DEFAULT]'; | ||
} | ||
/** | ||
* Extracts the client configuration from ENV variables and processes it | ||
* through either BASE64 or JSON decoding. | ||
*/ | ||
function extractClientConfig() { | ||
return extractEncodedString(process.env.FIREBASE_CONFIG); | ||
} | ||
exports.FireError = FireError; | ||
exports.determineDefaultAppName = determineDefaultAppName; | ||
exports.dotNotation = dotNotation; | ||
exports.extractClientConfig = extractClientConfig; | ||
exports.extractDataUrl = extractDataUrl; | ||
exports.extractEncodedString = extractEncodedString; | ||
exports.extractServiceAccount = extractServiceAccount; | ||
exports.getRunningApps = getRunningApps; | ||
exports.getRunningFirebaseApp = getRunningFirebaseApp; | ||
exports.looksLikeJson = looksLikeJson; | ||
exports.slashNotation = slashNotation; |
@@ -1,5 +0,188 @@ | ||
export * from './errors/index'; | ||
export * from './admin-sdk/index'; | ||
export * from './shared/index'; | ||
export * from './client-sdk/index'; | ||
//# sourceMappingURL=index.js.map | ||
class FireError extends Error { | ||
constructor(message, | ||
/** | ||
* a type/subtype of the error or you can just state the "subtype" | ||
* and it will | ||
*/ | ||
classification = 'UniversalFire/error', statusCode = 400) { | ||
super(message); | ||
this.universalFire = true; | ||
this.kind = 'FireError'; | ||
const parts = classification.split('/'); | ||
const klass = this.constructor.name; | ||
this.name = parts.length === 2 ? classification : `${klass}/${parts[0]}`; | ||
this.code = parts.length === 2 ? parts[1] : parts[0]; | ||
this.kind = parts[0]; | ||
this.statusCode = statusCode; | ||
} | ||
} | ||
function isMockConfig(config) { | ||
return config && config.mocking === true; | ||
} | ||
var RealQueryOrderType; | ||
(function (RealQueryOrderType) { | ||
RealQueryOrderType["orderByChild"] = "orderByChild"; | ||
RealQueryOrderType["orderByKey"] = "orderByKey"; | ||
RealQueryOrderType["orderByValue"] = "orderByValue"; | ||
})(RealQueryOrderType || (RealQueryOrderType = {})); | ||
/** | ||
* Takes as input a variety of possible formats and converts it into | ||
* a Firebase service account (`IServiceAccount`). The input formats | ||
* which it accepts are: | ||
* | ||
* - an `IServiceAccount` object (_in which case nothing to be done_) | ||
* - a JSON encoded string of the `IServiceAccount` object | ||
* - a base64 encoded string of a `IServiceAccount` object (_possible but not recommended | ||
* as an ENV variable may run out of room to encode_) | ||
* - a base64 encoded GZIP of a `IServiceAccount` object (_this is ideal for ENV vars | ||
* which have limited length and must be string_) | ||
*/ | ||
function extractServiceAccount(config) { | ||
if (isMockConfig(config)) { | ||
return {}; | ||
} | ||
const serviceAccount = config && config.mocking !== true && config.serviceAccount | ||
? config.serviceAccount | ||
: process.env['FIREBASE_SERVICE_ACCOUNT']; | ||
if (!serviceAccount) { | ||
throw new FireError(`There was no service account defined (either passed in or in the FIREBASE_SERVICE_ACCOUNT ENV variable)!`, 'invalid-configuration'); | ||
} | ||
switch (typeof serviceAccount) { | ||
case 'object': | ||
if (serviceAccount.privateKey && serviceAccount.projectId) { | ||
return serviceAccount; | ||
} | ||
else { | ||
throw new FireError(`An attempt to use the Admin SDK failed because a service account object was passed in but it did NOT have the required properties of "privateKey" and "projectId".`, 'invalid-configuration'); | ||
} | ||
case 'string': | ||
// JSON | ||
if (looksLikeJson(serviceAccount)) { | ||
try { | ||
const data = JSON.parse(serviceAccount); | ||
if (data.private_key && data.type === 'service_account') { | ||
return data; | ||
} | ||
else { | ||
throw new FireError(`The configuration appeared to contain a JSON encoded representation of the service account but after decoding it the private_key and/or the type property were not correctly set.`, 'invalid-configuration'); | ||
} | ||
} | ||
catch (e) { | ||
throw new FireError(`The configuration appeared to contain a JSOn encoded representation but was unable to be parsed: ${e.message}`, 'invalid-configuration'); | ||
} | ||
} | ||
// BASE 64 | ||
try { | ||
const buffer = Buffer.from(serviceAccount, 'base64'); | ||
return JSON.parse(buffer.toString()); | ||
} | ||
catch (e) { | ||
throw new FireError(`Failed to convert a string based service account to IServiceAccount! The error was: ${e.message}`, 'invalid-configuration'); | ||
} | ||
default: | ||
throw new FireError(`Couldn't extract the serviceAccount from ENV variables! The configuration was:\n${(2)}`, 'invalid-configuration'); | ||
} | ||
} | ||
/** | ||
* extracts the Firebase **databaseURL** property either from the passed in | ||
* configuration or via the FIREBASE_DATABASE_URL environment variable. | ||
*/ | ||
function extractDataUrl(config) { | ||
if (isMockConfig(config)) { | ||
return 'https://mocking.com'; | ||
} | ||
const dataUrl = config && config.databaseURL | ||
? config.databaseURL | ||
: process.env['FIREBASE_DATABASE_URL']; | ||
if (!dataUrl) { | ||
throw new FireError(`There was no DATABASE URL provided! This needs to be passed in as part of the configuration or as the FIREBASE_DATABASE_URL environment variable.`, 'invalid-configuration'); | ||
} | ||
return dataUrl; | ||
} | ||
/** | ||
* Returns an array of named apps that are running under | ||
* Firebase's control (admin API) | ||
*/ | ||
function getRunningApps(apps) { | ||
return apps.filter((i) => i !== null).map((i) => i.name); | ||
} | ||
/** Gets the */ | ||
function getRunningFirebaseApp(name, apps) { | ||
const result = name | ||
? apps.find((i) => i && i.name === name) | ||
: undefined; | ||
if (!result) { | ||
throw new FireError(`Attempt to get the Firebase app named "${name}" failed`, 'invalid-app-name'); | ||
} | ||
return result; | ||
} | ||
function looksLikeJson(data) { | ||
return data.trim().slice(0, 1) === '{' && data.trim().slice(-1) === '}' | ||
? true | ||
: false; | ||
} | ||
function extractEncodedString(data) { | ||
if (!data) { | ||
return undefined; | ||
} | ||
let failedJsonParse = false; | ||
if (looksLikeJson(data)) { | ||
try { | ||
return JSON.parse(data); | ||
} | ||
catch (e) { | ||
// ignore and try BASE64 | ||
failedJsonParse = true; | ||
} | ||
} | ||
try { | ||
const buffer = Buffer.from(data, 'base64'); | ||
return JSON.parse(buffer.toString()); | ||
} | ||
catch (e) { | ||
if (failedJsonParse) { | ||
throw new FireError(`Failed to parse the passed in encoded string; it appeared to be a JSON string but both JSON and Base64 decoding failed!`, `parse-failed`); | ||
} | ||
else { | ||
throw new FireError(`Failed to parse the passed in the Base64 encoded string`, `parse-failed`); | ||
} | ||
} | ||
} | ||
function slashNotation(path) { | ||
return path.replace(/\./g, '/'); | ||
} | ||
function dotNotation(path) { | ||
path = path.slice(0, 1) === '/' ? path.slice(1) : path; | ||
return path ? path.replace(/\//g, '.') : undefined; | ||
} | ||
function determineDefaultAppName(config) { | ||
if (!config) { | ||
return '[DEFAULT]'; | ||
} | ||
return config.name | ||
? config.name | ||
: config.databaseURL | ||
? config.databaseURL.replace(/.*https:\W*([\w-]*)\.((.|\n)*)/g, '$1') | ||
: '[DEFAULT]'; | ||
} | ||
/** | ||
* Extracts the client configuration from ENV variables and processes it | ||
* through either BASE64 or JSON decoding. | ||
*/ | ||
function extractClientConfig() { | ||
return extractEncodedString(process.env.FIREBASE_CONFIG); | ||
} | ||
export { FireError, determineDefaultAppName, dotNotation, extractClientConfig, extractDataUrl, extractEncodedString, extractServiceAccount, getRunningApps, getRunningFirebaseApp, looksLikeJson, slashNotation }; |
{ | ||
"name": "@forest-fire/utility", | ||
"version": "0.54.3", | ||
"version": "0.55.0", | ||
"description": "Utility functions that are shared across the monorepo", | ||
"module": "dist/es/index.js", | ||
"main": "dist/cjs/index.js", | ||
"types": "dist/es/index.d.ts", | ||
"types": "dist/types/index.d.ts", | ||
"sideEffects": false, | ||
@@ -31,3 +31,3 @@ "files": [ | ||
"devDependencies": { | ||
"@forest-fire/types": "^0.54.3", | ||
"@forest-fire/types": "^0.55.0", | ||
"@types/chai": "^4.2.11", | ||
@@ -48,3 +48,3 @@ "@types/mocha": "^7.0.2", | ||
"license": "MIT", | ||
"gitHead": "2ad19f06f1f1019874debb347d0deac41386a8a7" | ||
"gitHead": "8c17b1f8352fb745773001119e5163cc0b35e803" | ||
} |
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
Major refactor
Supply chain riskPackage has recently undergone a major refactor. It may be unstable or indicate significant internal changes. Use caution when updating to versions that include significant changes.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
Environment variable access
Supply chain riskPackage accesses environment variables, which may be a sign of credential stuffing or data theft.
Found 3 instances in 1 package
0
20296
20
430
1