@app-config/extensions
Advanced tools
Comparing version 2.1.8 to 2.2.0
@@ -7,2 +7,8 @@ import { ParsingExtension } from '@app-config/core'; | ||
export declare function unescape$Directives(): ParsingExtension; | ||
/** Try an operation, with a fallback ($try, $value and $fallback) */ | ||
export declare function tryDirective(): ParsingExtension; | ||
/** Checks a condition, uses then/else */ | ||
export declare function ifDirective(): ParsingExtension; | ||
/** Checks if two values are equal */ | ||
export declare function eqDirective(): ParsingExtension; | ||
/** Uses another file as overriding values, layering them on top of current file */ | ||
@@ -9,0 +15,0 @@ export declare function overrideDirective(): ParsingExtension; |
import { join, dirname, resolve, isAbsolute } from 'path'; | ||
import isEqual from 'lodash.isequal'; | ||
import { forKey, validateOptions, validationFunction, } from '@app-config/extension-utils'; | ||
import { ParsedValue, AppConfigError, NotFoundError, FailedToSelectSubObject, InObject, } from '@app-config/core'; | ||
import { ParsedValue, AppConfigError, NotFoundError, FailedToSelectSubObject, Fallbackable, InObject, } from '@app-config/core'; | ||
import { currentEnvironment, defaultAliases, FileSource, } from '@app-config/node'; | ||
@@ -21,2 +22,51 @@ import { logger } from '@app-config/logging'; | ||
} | ||
/** Try an operation, with a fallback ($try, $value and $fallback) */ | ||
export function tryDirective() { | ||
return forKey('$try', validateOptions((SchemaBuilder) => SchemaBuilder.emptySchema() | ||
.addProperty('$value', SchemaBuilder.fromJsonSchema({})) | ||
.addProperty('$fallback', SchemaBuilder.fromJsonSchema({})) | ||
.addBoolean('$unsafe', {}, false), (value) => async (parse) => { | ||
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment | ||
const { $value, $fallback, $unsafe } = value; | ||
try { | ||
return await parse($value, { shouldFlatten: true }); | ||
} | ||
catch (error) { | ||
if (error instanceof Fallbackable || $unsafe) { | ||
return parse($fallback, { shouldFlatten: true }); | ||
} | ||
throw error; | ||
} | ||
}, { lazy: true })); | ||
} | ||
/** Checks a condition, uses then/else */ | ||
export function ifDirective() { | ||
return forKey('$if', validateOptions((SchemaBuilder) => SchemaBuilder.emptySchema() | ||
.addProperty('$check', SchemaBuilder.fromJsonSchema({})) | ||
.addProperty('$then', SchemaBuilder.fromJsonSchema({})) | ||
.addProperty('$else', SchemaBuilder.fromJsonSchema({})), (value) => async (parse) => { | ||
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment | ||
const { $check, $then, $else } = value; | ||
const condition = (await parse($check)).toJSON(); | ||
if (condition) { | ||
return parse($then, { shouldFlatten: true }); | ||
} | ||
return parse($else, { shouldFlatten: true }); | ||
}, { lazy: true })); | ||
} | ||
/** Checks if two values are equal */ | ||
export function eqDirective() { | ||
return forKey('$eq', validateOptions((SchemaBuilder) => SchemaBuilder.arraySchema(SchemaBuilder.fromJsonSchema({})), (values) => async (parse) => { | ||
for (const a of values) { | ||
for (const b of values) { | ||
if (a === b) | ||
continue; | ||
if (isEqual(a, b)) | ||
continue; | ||
return parse(false, { shouldFlatten: true }); | ||
} | ||
} | ||
return parse(true, { shouldFlatten: true }); | ||
})); | ||
} | ||
/** Uses another file as overriding values, layering them on top of current file */ | ||
@@ -110,10 +160,33 @@ export function overrideDirective() { | ||
throw new AppConfigError('$substitute was given an array'); | ||
const { $name: variableName, $fallback: fallback, $allowNull: allowNull } = value; | ||
validateString(variableName, [...ctx, key, [InObject, '$name']]); | ||
const resolvedValue = process.env[variableName]; | ||
const { $name, $fallback, $allowNull, $parseInt, $parseFloat, $parseBool } = value; | ||
const name = (await parse($name)).toJSON(); | ||
validateString(name, [...ctx, key, [InObject, '$name']]); | ||
const resolvedValue = process.env[name]; | ||
if (resolvedValue) { | ||
const parseInt = (await parse($parseInt)).toJSON(); | ||
if (parseInt) { | ||
const parsed = Number.parseInt(resolvedValue, 10); | ||
if (Number.isNaN(parsed)) { | ||
throw new AppConfigError(`Failed to parseInt(${resolvedValue})`); | ||
} | ||
return parse(parsed, { shouldFlatten: true }); | ||
} | ||
const parseFloat = (await parse($parseFloat)).toJSON(); | ||
if (parseFloat) { | ||
const parsed = Number.parseFloat(resolvedValue); | ||
if (Number.isNaN(parsed)) { | ||
throw new AppConfigError(`Failed to parseFloat(${resolvedValue})`); | ||
} | ||
return parse(parsed, { shouldFlatten: true }); | ||
} | ||
const parseBool = (await parse($parseBool)).toJSON(); | ||
if (parseBool) { | ||
const parsed = resolvedValue.toLowerCase() !== 'false' && resolvedValue !== '0'; | ||
return parse(parsed, { shouldFlatten: true }); | ||
} | ||
return parse(resolvedValue, { shouldFlatten: true }); | ||
} | ||
if (fallback !== undefined) { | ||
const fallbackValue = (await parse(fallback)).toJSON(); | ||
if ($fallback !== undefined) { | ||
const fallbackValue = (await parse($fallback)).toJSON(); | ||
const allowNull = (await parse($allowNull)).toJSON(); | ||
if (allowNull) { | ||
@@ -127,6 +200,3 @@ validateStringOrNull(fallbackValue, [...ctx, key, [InObject, '$fallback']]); | ||
} | ||
if (!resolvedValue) { | ||
throw new AppConfigError(`$substitute could not find ${variableName} environment variable`); | ||
} | ||
return parse(resolvedValue, { shouldFlatten: true }); | ||
throw new AppConfigError(`$substitute could not find ${name} environment variable`); | ||
}); | ||
@@ -133,0 +203,0 @@ } |
@@ -7,2 +7,8 @@ import { ParsingExtension } from '@app-config/core'; | ||
export declare function unescape$Directives(): ParsingExtension; | ||
/** Try an operation, with a fallback ($try, $value and $fallback) */ | ||
export declare function tryDirective(): ParsingExtension; | ||
/** Checks a condition, uses then/else */ | ||
export declare function ifDirective(): ParsingExtension; | ||
/** Checks if two values are equal */ | ||
export declare function eqDirective(): ParsingExtension; | ||
/** Uses another file as overriding values, layering them on top of current file */ | ||
@@ -9,0 +15,0 @@ export declare function overrideDirective(): ParsingExtension; |
@@ -13,5 +13,9 @@ "use strict"; | ||
}; | ||
var __importDefault = (this && this.__importDefault) || function (mod) { | ||
return (mod && mod.__esModule) ? mod : { "default": mod }; | ||
}; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
exports.environmentVariableSubstitution = exports.timestampDirective = exports.envDirective = exports.extendsSelfDirective = exports.extendsDirective = exports.overrideDirective = exports.unescape$Directives = exports.markAllValuesAsSecret = void 0; | ||
exports.environmentVariableSubstitution = exports.timestampDirective = exports.envDirective = exports.extendsSelfDirective = exports.extendsDirective = exports.overrideDirective = exports.eqDirective = exports.ifDirective = exports.tryDirective = exports.unescape$Directives = exports.markAllValuesAsSecret = void 0; | ||
const path_1 = require("path"); | ||
const lodash_isequal_1 = __importDefault(require("lodash.isequal")); | ||
const extension_utils_1 = require("@app-config/extension-utils"); | ||
@@ -38,2 +42,54 @@ const core_1 = require("@app-config/core"); | ||
exports.unescape$Directives = unescape$Directives; | ||
/** Try an operation, with a fallback ($try, $value and $fallback) */ | ||
function tryDirective() { | ||
return extension_utils_1.forKey('$try', extension_utils_1.validateOptions((SchemaBuilder) => SchemaBuilder.emptySchema() | ||
.addProperty('$value', SchemaBuilder.fromJsonSchema({})) | ||
.addProperty('$fallback', SchemaBuilder.fromJsonSchema({})) | ||
.addBoolean('$unsafe', {}, false), (value) => async (parse) => { | ||
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment | ||
const { $value, $fallback, $unsafe } = value; | ||
try { | ||
return await parse($value, { shouldFlatten: true }); | ||
} | ||
catch (error) { | ||
if (error instanceof core_1.Fallbackable || $unsafe) { | ||
return parse($fallback, { shouldFlatten: true }); | ||
} | ||
throw error; | ||
} | ||
}, { lazy: true })); | ||
} | ||
exports.tryDirective = tryDirective; | ||
/** Checks a condition, uses then/else */ | ||
function ifDirective() { | ||
return extension_utils_1.forKey('$if', extension_utils_1.validateOptions((SchemaBuilder) => SchemaBuilder.emptySchema() | ||
.addProperty('$check', SchemaBuilder.fromJsonSchema({})) | ||
.addProperty('$then', SchemaBuilder.fromJsonSchema({})) | ||
.addProperty('$else', SchemaBuilder.fromJsonSchema({})), (value) => async (parse) => { | ||
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment | ||
const { $check, $then, $else } = value; | ||
const condition = (await parse($check)).toJSON(); | ||
if (condition) { | ||
return parse($then, { shouldFlatten: true }); | ||
} | ||
return parse($else, { shouldFlatten: true }); | ||
}, { lazy: true })); | ||
} | ||
exports.ifDirective = ifDirective; | ||
/** Checks if two values are equal */ | ||
function eqDirective() { | ||
return extension_utils_1.forKey('$eq', extension_utils_1.validateOptions((SchemaBuilder) => SchemaBuilder.arraySchema(SchemaBuilder.fromJsonSchema({})), (values) => async (parse) => { | ||
for (const a of values) { | ||
for (const b of values) { | ||
if (a === b) | ||
continue; | ||
if (lodash_isequal_1.default(a, b)) | ||
continue; | ||
return parse(false, { shouldFlatten: true }); | ||
} | ||
} | ||
return parse(true, { shouldFlatten: true }); | ||
})); | ||
} | ||
exports.eqDirective = eqDirective; | ||
/** Uses another file as overriding values, layering them on top of current file */ | ||
@@ -132,10 +188,33 @@ function overrideDirective() { | ||
throw new core_1.AppConfigError('$substitute was given an array'); | ||
const { $name: variableName, $fallback: fallback, $allowNull: allowNull } = value; | ||
validateString(variableName, [...ctx, key, [core_1.InObject, '$name']]); | ||
const resolvedValue = process.env[variableName]; | ||
const { $name, $fallback, $allowNull, $parseInt, $parseFloat, $parseBool } = value; | ||
const name = (await parse($name)).toJSON(); | ||
validateString(name, [...ctx, key, [core_1.InObject, '$name']]); | ||
const resolvedValue = process.env[name]; | ||
if (resolvedValue) { | ||
const parseInt = (await parse($parseInt)).toJSON(); | ||
if (parseInt) { | ||
const parsed = Number.parseInt(resolvedValue, 10); | ||
if (Number.isNaN(parsed)) { | ||
throw new core_1.AppConfigError(`Failed to parseInt(${resolvedValue})`); | ||
} | ||
return parse(parsed, { shouldFlatten: true }); | ||
} | ||
const parseFloat = (await parse($parseFloat)).toJSON(); | ||
if (parseFloat) { | ||
const parsed = Number.parseFloat(resolvedValue); | ||
if (Number.isNaN(parsed)) { | ||
throw new core_1.AppConfigError(`Failed to parseFloat(${resolvedValue})`); | ||
} | ||
return parse(parsed, { shouldFlatten: true }); | ||
} | ||
const parseBool = (await parse($parseBool)).toJSON(); | ||
if (parseBool) { | ||
const parsed = resolvedValue.toLowerCase() !== 'false' && resolvedValue !== '0'; | ||
return parse(parsed, { shouldFlatten: true }); | ||
} | ||
return parse(resolvedValue, { shouldFlatten: true }); | ||
} | ||
if (fallback !== undefined) { | ||
const fallbackValue = (await parse(fallback)).toJSON(); | ||
if ($fallback !== undefined) { | ||
const fallbackValue = (await parse($fallback)).toJSON(); | ||
const allowNull = (await parse($allowNull)).toJSON(); | ||
if (allowNull) { | ||
@@ -149,6 +228,3 @@ validateStringOrNull(fallbackValue, [...ctx, key, [core_1.InObject, '$fallback']]); | ||
} | ||
if (!resolvedValue) { | ||
throw new core_1.AppConfigError(`$substitute could not find ${variableName} environment variable`); | ||
} | ||
return parse(resolvedValue, { shouldFlatten: true }); | ||
throw new core_1.AppConfigError(`$substitute could not find ${name} environment variable`); | ||
}); | ||
@@ -155,0 +231,0 @@ } |
{ | ||
"name": "@app-config/extensions", | ||
"description": "Common parsing extensions for @app-config", | ||
"version": "2.1.8", | ||
"version": "2.2.0", | ||
"license": "MPL-2.0", | ||
@@ -33,10 +33,12 @@ "author": { | ||
"dependencies": { | ||
"@app-config/core": "^2.1.8", | ||
"@app-config/extension-utils": "^2.1.8", | ||
"@app-config/logging": "^2.1.8", | ||
"@app-config/node": "^2.1.8", | ||
"@app-config/utils": "^2.1.8" | ||
"@app-config/core": "^2.2.0", | ||
"@app-config/extension-utils": "^2.2.0", | ||
"@app-config/logging": "^2.2.0", | ||
"@app-config/node": "^2.2.0", | ||
"@app-config/utils": "^2.2.0", | ||
"lodash.isequal": "4" | ||
}, | ||
"devDependencies": { | ||
"@app-config/test-utils": "^2.1.8" | ||
"@app-config/test-utils": "^2.2.0", | ||
"@types/lodash.isequal": "4" | ||
}, | ||
@@ -43,0 +45,0 @@ "prettier": "@lcdev/prettier", |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Environment variable access
Supply chain riskPackage accesses environment variables, which may be a sign of credential stuffing or data theft.
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 1 instance in 1 package
60611
679
6
2
+ Addedlodash.isequal@4
+ Addedlodash.isequal@4.5.0(transitive)
Updated@app-config/core@^2.2.0
Updated@app-config/logging@^2.2.0
Updated@app-config/node@^2.2.0
Updated@app-config/utils@^2.2.0