@endo/env-options
Advanced tools
Comparing version 1.0.1 to 1.1.0
{ | ||
"name": "@endo/env-options", | ||
"version": "1.0.1", | ||
"version": "1.1.0", | ||
"private": null, | ||
@@ -29,5 +29,5 @@ "description": "Reading environment options.", | ||
"build": "exit 0", | ||
"lint": "yarn lint:types && yarn lint:js", | ||
"lint": "yarn lint:types && yarn lint:eslint", | ||
"lint-fix": "eslint --fix .", | ||
"lint:js": "eslint .", | ||
"lint:eslint": "eslint .", | ||
"lint:types": "tsc", | ||
@@ -47,3 +47,3 @@ "build:types": "tsc --build tsconfig.build.json", | ||
"prettier": "^3.0.0", | ||
"typescript": "~5.2.2" | ||
"typescript": "~5.3.3" | ||
}, | ||
@@ -88,5 +88,5 @@ "files": [ | ||
"typeCoverage": { | ||
"atLeast": 72.22 | ||
"atLeast": 74.44 | ||
}, | ||
"gitHead": "c02aec92c3caa417d6bdf3c4f555f0b2694d9f9e" | ||
"gitHead": "373f9eebab66c94ed42350473c90fb25e6054f0a" | ||
} |
@@ -37,4 +37,3 @@ # Parameterizing Modules with Environment Options | ||
```js | ||
import { makeEnvironmentCaptor } from '@endo/env-options'; | ||
const { getEnvironmentOption } = makeEnvironmentCaptor(globalThis); | ||
import { getEnvironmentOption } from '@endo/env-options'; | ||
const FooBarOption = getEnvironmentOption('FOO_BAR', 'absent'); | ||
@@ -46,4 +45,4 @@ ``` | ||
`globalThis.process.env.FOO_BAR`, if present. | ||
If setting is either absent or `undefined`, the default `'absent'` | ||
would be used instead. | ||
If value is either absent or `undefined`, the second argument, | ||
such as `'absent'`, would be used instead. | ||
@@ -55,4 +54,38 @@ In either case, reflecting Unix environment variable expectations, | ||
The `makeEnvironmentCaptor` function also returns a | ||
`getCapturedEnvironmentOptionNames` function for use to give feedback about | ||
```js | ||
const ENABLED = | ||
getEnvironmentOption('TRACK_TURNS', 'disabled', ['enabled']) === 'enabled'; | ||
``` | ||
`getEnvironmentOption` also takes an optional third argument, which if present | ||
is an exhaustive list of allowed strings other than the default. If present | ||
and the actual environment option is neither the default nor one of these | ||
allowed strings, then an error is thrown explaining the problem. | ||
```js | ||
const DEBUG_VALUES = getEnvironmentOptionsList('DEBUG'); | ||
const DEBUG_AGORIC = environmentOptionsListHas('DEBUG', 'agoric'); | ||
``` | ||
Another common convention is for the value of an option to be a | ||
comma (`','`) separated list of strings. `getEnvironmentOptionsList` will | ||
return this list, or an empty list if the option is absent. | ||
`environmentOptionsListHas` will test if this list contains a specific | ||
value, or return false if the option is absent. | ||
(Compat note: https://github.com/Agoric/agoric-sdk/issues/8096 explains that | ||
for `DEBUG` specifically, some existing uses split on colon (`':'`) rather | ||
than comma. Once these are fixed, then these uses can be switched to use | ||
`getEnvironmentOptionsList` or `environmentOptionsListHas`.) | ||
## Tracking used option names | ||
The `'@endo/env-options'` module also exports a lower-level | ||
`makeEnvironmentCaptor` that you can apply to whatever object you wish to treat | ||
as a global(having a "process" property with its own "env" record), | ||
such as the global of another compartment. It returns an entagled | ||
pair of a `getEnvironmentOption` function as above, and a | ||
`getCapturedEnvironmentOptionNames` function that returns an array of | ||
the option names used by that `getEnvironmentOption` function. This is | ||
useful to give feedback about | ||
which environment variables were actually read, for diagnostic purposes. | ||
@@ -67,2 +100,4 @@ For example, the | ||
getEnvironmentOption, | ||
getEnvironmentOptionsList, | ||
environmentOptionsListHas, | ||
getCapturedEnvironmentOptionNames, | ||
@@ -69,0 +104,0 @@ } = makeEnvironmentCaptor(globalThis); |
@@ -1,5 +0,24 @@ | ||
export function makeEnvironmentCaptor(aGlobal: object): Readonly<{ | ||
getEnvironmentOption: (optionName: string, defaultSetting: string) => string; | ||
export function makeEnvironmentCaptor(aGlobal: object, dropNames?: boolean | undefined): Readonly<{ | ||
getEnvironmentOption: (optionName: string, defaultSetting: string, optOtherValues?: string[] | undefined) => string; | ||
getEnvironmentOptionsList: (optionName: string) => string[]; | ||
environmentOptionsListHas: (optionName: any, element: any) => any; | ||
getCapturedEnvironmentOptionNames: () => readonly any[]; | ||
}>; | ||
/** | ||
* Gets an environment option by name and returns the option value or the | ||
* given default. | ||
* | ||
* @param {string} optionName | ||
* @param {string} defaultSetting | ||
* @param {string[]} [optOtherValues] | ||
* If provided, the option value must be included or match `defaultSetting`. | ||
* @returns {string} | ||
*/ | ||
export function getEnvironmentOption(optionName: string, defaultSetting: string, optOtherValues?: string[] | undefined): string; | ||
/** | ||
* @param {string} optionName | ||
* @returns {string[]} | ||
*/ | ||
export function getEnvironmentOptionsList(optionName: string): string[]; | ||
export function environmentOptionsListHas(optionName: any, element: any): any; | ||
//# sourceMappingURL=env-options.d.ts.map |
@@ -0,1 +1,2 @@ | ||
/* global globalThis */ | ||
// @ts-check | ||
@@ -20,2 +21,4 @@ | ||
const arrayPush = uncurryThis(Array.prototype.push); | ||
const arrayIncludes = uncurryThis(Array.prototype.includes); | ||
const stringSplit = uncurryThis(String.prototype.split); | ||
@@ -41,4 +44,6 @@ const q = JSON.stringify; | ||
* @param {object} aGlobal | ||
* @param {boolean} [dropNames] Defaults to false. If true, don't track | ||
* names used. | ||
*/ | ||
export const makeEnvironmentCaptor = aGlobal => { | ||
export const makeEnvironmentCaptor = (aGlobal, dropNames = false) => { | ||
const capturedEnvironmentOptionNames = []; | ||
@@ -52,9 +57,13 @@ | ||
* @param {string} defaultSetting | ||
* @param {string[]} [optOtherValues] | ||
* If provided, the option value must be included or match `defaultSetting`. | ||
* @returns {string} | ||
*/ | ||
const getEnvironmentOption = (optionName, defaultSetting) => { | ||
// eslint-disable-next-line @endo/no-polymorphic-call | ||
const getEnvironmentOption = ( | ||
optionName, | ||
defaultSetting, | ||
optOtherValues = undefined, | ||
) => { | ||
typeof optionName === 'string' || | ||
Fail`Environment option name ${q(optionName)} must be a string.`; | ||
// eslint-disable-next-line @endo/no-polymorphic-call | ||
typeof defaultSetting === 'string' || | ||
@@ -67,20 +76,27 @@ Fail`Environment option default setting ${q( | ||
let setting = defaultSetting; | ||
const globalProcess = aGlobal.process; | ||
if (globalProcess && typeof globalProcess === 'object') { | ||
const globalEnv = globalProcess.env; | ||
if (globalEnv && typeof globalEnv === 'object') { | ||
if (optionName in globalEnv) { | ||
const globalProcess = aGlobal.process || undefined; | ||
const globalEnv = | ||
(typeof globalProcess === 'object' && globalProcess.env) || undefined; | ||
if (typeof globalEnv === 'object') { | ||
if (optionName in globalEnv) { | ||
if (!dropNames) { | ||
arrayPush(capturedEnvironmentOptionNames, optionName); | ||
const optionValue = globalEnv[optionName]; | ||
// eslint-disable-next-line @endo/no-polymorphic-call | ||
typeof optionValue === 'string' || | ||
Fail`Environment option named ${q( | ||
optionName, | ||
)}, if present, must have a corresponding string value, got ${q( | ||
optionValue, | ||
)}`; | ||
setting = optionValue; | ||
} | ||
const optionValue = globalEnv[optionName]; | ||
// eslint-disable-next-line @endo/no-polymorphic-call | ||
typeof optionValue === 'string' || | ||
Fail`Environment option named ${q( | ||
optionName, | ||
)}, if present, must have a corresponding string value, got ${q( | ||
optionValue, | ||
)}`; | ||
setting = optionValue; | ||
} | ||
} | ||
optOtherValues === undefined || | ||
setting === defaultSetting || | ||
arrayIncludes(optOtherValues, setting) || | ||
Fail`Unrecognized ${q(optionName)} value ${q( | ||
setting, | ||
)}. Expected one of ${q([defaultSetting, ...optOtherValues])}`; | ||
return setting; | ||
@@ -90,2 +106,15 @@ }; | ||
/** | ||
* @param {string} optionName | ||
* @returns {string[]} | ||
*/ | ||
const getEnvironmentOptionsList = optionName => { | ||
const option = getEnvironmentOption(optionName, ''); | ||
return freeze(option === '' ? [] : stringSplit(option, ',')); | ||
}; | ||
freeze(getEnvironmentOptionsList); | ||
const environmentOptionsListHas = (optionName, element) => | ||
arrayIncludes(getEnvironmentOptionsList(optionName), element); | ||
const getCapturedEnvironmentOptionNames = () => { | ||
@@ -96,4 +125,19 @@ return freeze([...capturedEnvironmentOptionNames]); | ||
return freeze({ getEnvironmentOption, getCapturedEnvironmentOptionNames }); | ||
return freeze({ | ||
getEnvironmentOption, | ||
getEnvironmentOptionsList, | ||
environmentOptionsListHas, | ||
getCapturedEnvironmentOptionNames, | ||
}); | ||
}; | ||
freeze(makeEnvironmentCaptor); | ||
/** | ||
* For the simple case, where the global in question is `globalThis` and no | ||
* reporting of option names is desired. | ||
*/ | ||
export const { | ||
getEnvironmentOption, | ||
getEnvironmentOptionsList, | ||
environmentOptionsListHas, | ||
} = makeEnvironmentCaptor(globalThis, true); |
Sorry, the diff of this file is not supported yet
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
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
28044
147
117