Make dependencies peer. LAzy load YN so that if the feature is not used the dependency is ignored'
This commit is contained in:
parent
eb190da262
commit
64920a7a24
8 changed files with 111 additions and 77 deletions
28
src/booleanConverter.ts
Normal file
28
src/booleanConverter.ts
Normal file
|
@ -0,0 +1,28 @@
|
|||
import * as yn from 'yn';
|
||||
|
||||
import { BooleanConverter, ConfigOptions } from "./types"
|
||||
|
||||
export const booleanConverter: BooleanConverter = (options: ConfigOptions, log: (...args: any[]) => void) => {
|
||||
const convertPredicate = (key: string): boolean => {
|
||||
if (key) {
|
||||
if (Array.isArray(options.convertToBoolean)) {
|
||||
if (options.convertToBoolean.includes(key)) {
|
||||
return true;
|
||||
}
|
||||
} else if (options.convertToBoolean === key) {
|
||||
return true;
|
||||
}
|
||||
if (typeof options.convertToBooleanPredicate === 'function' && options.convertToBooleanPredicate(key)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
Object.entries(process.env).forEach(([key, value]) => {
|
||||
if (convertPredicate(key)) {
|
||||
const boolValue = yn(value) ? 'true' : '';
|
||||
process.env[key] = boolValue;
|
||||
log('Environment variable converted into string boolean value:', key, "original:", value, 'newValue:', boolValue);
|
||||
}
|
||||
});
|
||||
}
|
46
src/dotenvMulti.ts
Normal file
46
src/dotenvMulti.ts
Normal file
|
@ -0,0 +1,46 @@
|
|||
import * as fs from 'fs';
|
||||
import * as path from 'path';
|
||||
|
||||
import * as dotenv from 'dotenv';
|
||||
import * as dotenvExpand from 'dotenv-expand';
|
||||
|
||||
import { BooleanConverter, ConfigOptions } from "./types"
|
||||
import { Lazy } from "./lazy"
|
||||
|
||||
const lazyBoolConverter = new Lazy<BooleanConverter>(() => require('./booleanConverter').booleanConverter);
|
||||
|
||||
export function config(options: ConfigOptions = {}): void {
|
||||
const log = options.debug ? console.log : (() => {});
|
||||
|
||||
// Same logic as create-react-app for resolving env files
|
||||
// https://github.com/facebook/create-react-app/blob/master/packages/react-scripts/config/env.js
|
||||
const NODE_ENV = (process.env.NODE_ENV || 'unknown').toLowerCase();
|
||||
const appDirectory = fs.realpathSync(process.cwd());
|
||||
const dotenvFilePath: string = path.resolve(appDirectory, '.env');
|
||||
|
||||
const dotenvFiles = [
|
||||
`${ dotenvFilePath }.${ NODE_ENV }.local`,
|
||||
`${ dotenvFilePath }.${ NODE_ENV }`,
|
||||
NODE_ENV !== 'test' && `${ dotenvFilePath }.local`,
|
||||
dotenvFilePath,
|
||||
].filter(i => i) as string[]; // this cast is safe due to the identity filter
|
||||
|
||||
log('Environment files to check:', dotenvFiles.join());
|
||||
|
||||
const propsConfigured = {};
|
||||
dotenvFiles.forEach((dotenvFile) => {
|
||||
if (fs.existsSync(dotenvFile)) {
|
||||
const {parsed} = dotenvExpand(dotenv.config({path: dotenvFile, debug: options.debug || undefined }));
|
||||
Object.assign(propsConfigured, parsed);
|
||||
}
|
||||
});
|
||||
|
||||
log('Environment variables loaded from dotenvs:', Object.keys(propsConfigured).length);
|
||||
log('\t', propsConfigured);
|
||||
|
||||
const runBoolConverter: boolean = !!(options.convertToBooleanPredicate || options.convertToBoolean);
|
||||
log('Environment variable boolean converter will run:', runBoolConverter);
|
||||
if (runBoolConverter) {
|
||||
lazyBoolConverter.get()(options, log);
|
||||
}
|
||||
}
|
71
src/index.ts
71
src/index.ts
|
@ -1,69 +1,2 @@
|
|||
import * as fs from 'fs';
|
||||
import * as path from 'path';
|
||||
|
||||
import * as dotenv from 'dotenv';
|
||||
import * as dotenvExpand from 'dotenv-expand';
|
||||
import * as yn from 'yn';
|
||||
|
||||
export interface ConfigOptions {
|
||||
convertToBooleanPredicate?: (variable: string) => boolean;
|
||||
convertToBoolean?: string | string[];
|
||||
debug?: boolean;
|
||||
}
|
||||
|
||||
export function config(options: ConfigOptions = {}): void {
|
||||
const log = options.debug ? console.log : (() => {});
|
||||
|
||||
// Same logic as create-react-app for resolving env files
|
||||
// https://github.com/facebook/create-react-app/blob/master/packages/react-scripts/config/env.js
|
||||
const NODE_ENV = (process.env.NODE_ENV || 'unknown').toLowerCase();
|
||||
const appDirectory = fs.realpathSync(process.cwd());
|
||||
const dotenvFilePath: string = path.resolve(appDirectory, '.env');
|
||||
|
||||
const dotenvFiles = [
|
||||
`${ dotenvFilePath }.${ NODE_ENV }.local`,
|
||||
`${ dotenvFilePath }.${ NODE_ENV }`,
|
||||
NODE_ENV !== 'test' && `${ dotenvFilePath }.local`,
|
||||
dotenvFilePath,
|
||||
].filter(i => i) as string[]; // this cast is safe due to the identity filter
|
||||
|
||||
log('Environment files to check:', dotenvFiles.join());
|
||||
|
||||
const propsConfigured = {};
|
||||
dotenvFiles.forEach((dotenvFile) => {
|
||||
if (fs.existsSync(dotenvFile)) {
|
||||
const {parsed} = dotenvExpand(dotenv.config({path: dotenvFile, debug: options.debug || undefined }));
|
||||
Object.assign(propsConfigured, parsed);
|
||||
}
|
||||
});
|
||||
|
||||
log('Environment variables loaded from dotenvs:', Object.keys(propsConfigured).length);
|
||||
log('\t', propsConfigured);
|
||||
|
||||
const runBoolConverter: boolean = !!(options.convertToBooleanPredicate || options.convertToBoolean);
|
||||
log('Environment variable boolean converter will run:', runBoolConverter);
|
||||
if (runBoolConverter) {
|
||||
const convertPredicate = (key: string): boolean => {
|
||||
if (key) {
|
||||
if (Array.isArray(options.convertToBoolean)) {
|
||||
if (options.convertToBoolean.includes(key)) {
|
||||
return true;
|
||||
}
|
||||
} else if (options.convertToBoolean === key) {
|
||||
return true;
|
||||
}
|
||||
if (typeof options.convertToBooleanPredicate === 'function' && options.convertToBooleanPredicate(key)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
Object.entries(process.env).forEach(([key, value]) => {
|
||||
if (convertPredicate(key)) {
|
||||
const boolValue = yn(value) ? 'true' : '';
|
||||
process.env[key] = boolValue;
|
||||
log('Environment variable converted into string boolean value:', key, "original:", value, 'newValue:', boolValue);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
export * from './dotenvMulti'
|
||||
export * from './types';
|
||||
|
|
12
src/lazy.ts
Normal file
12
src/lazy.ts
Normal file
|
@ -0,0 +1,12 @@
|
|||
export class Lazy<T> {
|
||||
private instance: T | undefined = undefined;
|
||||
|
||||
constructor(private readonly factory: () => any) {}
|
||||
|
||||
get (): T {
|
||||
if (!this.instance) {
|
||||
this.instance = this.factory();
|
||||
}
|
||||
return this.instance as T;
|
||||
}
|
||||
}
|
9
src/types.ts
Normal file
9
src/types.ts
Normal file
|
@ -0,0 +1,9 @@
|
|||
export interface ConfigOptions {
|
||||
convertToBooleanPredicate?: (variable: string) => boolean;
|
||||
convertToBoolean?: string | string[];
|
||||
debug?: boolean;
|
||||
}
|
||||
|
||||
export interface BooleanConverter {
|
||||
(options: ConfigOptions, log: (...args: any[]) => void): void;
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue