Big News: Socket raises $60M Series C at a $1B valuation to secure software supply chains for AI-driven development.Announcement
Sign In

@avanio/variable-util-node

Package Overview
Dependencies
Maintainers
3
Versions
37
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@avanio/variable-util-node - npm Package Compare versions

Comparing version
0.10.0
to
0.11.0
+109
dist/index.d.mts
import { ConfigLoader, Loadable, LoaderValue, IConfigLoaderProps, ValidateCallback, RecordConfigLoader } from '@avanio/variable-util';
import { ILoggerLike } from '@avanio/logger-like';
interface DockerSecretsConfigLoaderOptions {
/** force file name to lower case */
fileLowerCase: boolean;
/** path to docker secrets, default is '/run/secrets' */
path: string;
/** set to false if need errors */
isSilent: boolean;
/** optional logger */
logger: ILoggerLike | undefined;
/** set to true to disable loader, default is false */
disabled: boolean;
}
/**
* Loader for docker secrets, reads secrets from the `/run/secrets` directory.
* @since v0.8.0
*/
declare class DockerSecretsConfigLoader extends ConfigLoader<string | undefined, Partial<DockerSecretsConfigLoaderOptions>, DockerSecretsConfigLoaderOptions> {
readonly type: Lowercase<string>;
private valuePromises;
protected defaultOptions: DockerSecretsConfigLoaderOptions;
constructor(options: Loadable<Partial<DockerSecretsConfigLoaderOptions>>, type?: Lowercase<string>);
protected handleLoader(lookupKey: string, overrideKey?: string): Promise<LoaderValue>;
private filePath;
}
/**
* Options for the AbstractFileRecordLoader.
* @since v0.8.0
*/
interface AbstractFileRecordLoaderOptions<FileType extends string> extends IConfigLoaderProps {
fileType: FileType;
/** file name to load */
fileName: string;
/** set to false if need errors */
isSilent: boolean;
/** optional logger */
logger: ILoggerLike | undefined;
/** set to true to watch file for changes */
watch: boolean;
/** set to true to disable loader */
disabled: boolean;
/**
* optional validator for data (Record<string, string | undefined>)
*
* @example
* // using zod
* const stringRecordSchema = z.record(z.string().min(1), z.string());
* const validate: ValidateCallback<Record<string, string>> = async (data) => {
* const result = await stringRecordSchema.safeParseAsync(data);
* if (!result.success) {
* return {success: false, message: result.error.message};
* }
* return {success: true};
* };
*/
validate: ValidateCallback<Record<string, string | undefined>, Record<string, string | undefined>> | undefined;
}
/**
* Abstract class for loading records from a file.
* @since v0.8.0
*/
declare abstract class AbstractFileRecordLoader<Options extends AbstractFileRecordLoaderOptions<string> = AbstractFileRecordLoaderOptions<string>> extends RecordConfigLoader<string | undefined, Partial<Options>, Options> {
abstract readonly type: Lowercase<string>;
private watcher;
private timeout;
protected abstract defaultOptions: Options;
constructor(options: Loadable<Partial<Options>>);
/**
* If the loader is watching the file, it will stop watching.
*/
close(): Promise<void>;
protected handleLoader(rootKey: string, key?: string): Promise<LoaderValue>;
protected handleData(): Promise<Record<string, string | undefined>>;
/**
* Handle the parsing of the file.
*/
protected abstract handleParse(rawData: Buffer, options: Options): Record<string, string | undefined> | Promise<Record<string, string | undefined>>;
private handleFileWatch;
private handleFileChange;
}
/**
* A file-based configuration loader that reads a JSON file.
* @since v0.9.1
*/
declare class FileConfigLoader extends AbstractFileRecordLoader<AbstractFileRecordLoaderOptions<'json'>> {
readonly type: Lowercase<string>;
constructor(options: Loadable<Partial<AbstractFileRecordLoaderOptions<'json'>>>, type?: Lowercase<string>);
protected defaultOptions: AbstractFileRecordLoaderOptions<'json'>;
protected handleParse(rawData: Buffer): Record<string, string | undefined>;
}
/**
* Loader for dotenv files, using the `dotenv` packages parser.
* @since v0.6.1
*/
declare class DotEnvLoader extends AbstractFileRecordLoader {
readonly type: Lowercase<string>;
constructor(options: Loadable<Partial<AbstractFileRecordLoaderOptions<'env'>>>, type?: Lowercase<string>);
protected defaultOptions: AbstractFileRecordLoaderOptions<'env'>;
protected handleParse(rawData: Buffer): Record<string, string | undefined>;
}
declare function getError(error: unknown): Error;
export { AbstractFileRecordLoader, type AbstractFileRecordLoaderOptions, DockerSecretsConfigLoader, type DockerSecretsConfigLoaderOptions, DotEnvLoader, FileConfigLoader, getError };
{"version":3,"sources":["../src/index.ts","../src/DockerSecretsConfigLoader.ts","../src/AbstractFileRecordLoader.ts","../src/errorUtil.ts","../src/FileConfigLoader.ts","../src/DotEnvLoader.ts"],"sourcesContent":["export * from './DockerSecretsConfigLoader';\nexport * from './FileConfigLoader';\nexport * from './DotEnvLoader';\nexport * from './AbstractFileRecordLoader';\nexport * from './errorUtil';\n","import * as path from 'path';\nimport {ConfigLoader, type Loadable, type LoaderValue, VariableLookupError} from '@avanio/variable-util';\nimport {existsSync} from 'fs';\nimport type {ILoggerLike} from '@avanio/logger-like';\nimport {readFile} from 'fs/promises';\n\nexport interface DockerSecretsConfigLoaderOptions {\n\t/** force file name to lower case */\n\tfileLowerCase: boolean;\n\t/** path to docker secrets, default is '/run/secrets' */\n\tpath: string;\n\t/** set to false if need errors */\n\tisSilent: boolean;\n\t/** optional logger */\n\tlogger: ILoggerLike | undefined;\n\t/** set to true to disable loader, default is false */\n\tdisabled: boolean;\n}\n\n/**\n * Loader for docker secrets, reads secrets from the `/run/secrets` directory.\n * @since v0.8.0\n */\nexport class DockerSecretsConfigLoader extends ConfigLoader<string | undefined, Partial<DockerSecretsConfigLoaderOptions>, DockerSecretsConfigLoaderOptions> {\n\tpublic readonly type: Lowercase<string>;\n\tprivate valuePromises: Record<string, Promise<string | undefined> | undefined> = {};\n\tprotected defaultOptions: DockerSecretsConfigLoaderOptions = {\n\t\tdisabled: false,\n\t\tfileLowerCase: false,\n\t\tisSilent: true,\n\t\tlogger: undefined,\n\t\tpath: '/run/secrets',\n\t};\n\n\tpublic constructor(options: Loadable<Partial<DockerSecretsConfigLoaderOptions>>, type: Lowercase<string> = 'docker-secrets') {\n\t\tsuper(options);\n\t\tthis.getLoader = this.getLoader.bind(this);\n\t\tthis.type = type;\n\t}\n\n\tprotected async handleLoader(lookupKey: string, overrideKey?: string): Promise<LoaderValue> {\n\t\tconst options = await this.getOptions();\n\t\tif (options.disabled) {\n\t\t\treturn {type: this.type, result: undefined};\n\t\t}\n\t\tconst targetKey = overrideKey || lookupKey;\n\t\tconst filePath = this.filePath(targetKey, options);\n\t\tconst valuePromise = this.valuePromises[targetKey];\n\t\tconst seen = !!valuePromise; // if valuePromise exists, it means we have seen this key before\n\t\tif (!valuePromise) {\n\t\t\tif (!existsSync(filePath)) {\n\t\t\t\tif (!options.isSilent) {\n\t\t\t\t\tthrow new VariableLookupError(targetKey, `ConfigVariables[${this.type}]: ${lookupKey} from ${filePath} not found`);\n\t\t\t\t}\n\t\t\t\toptions.logger?.debug(`ConfigVariables[${this.type}]: ${lookupKey} from ${filePath} not found`);\n\t\t\t\tthis.valuePromises[targetKey] = Promise.resolve(undefined);\n\t\t\t} else {\n\t\t\t\tthis.valuePromises[targetKey] = readFile(filePath, 'utf8');\n\t\t\t}\n\t\t}\n\t\tconst value = await this.valuePromises[targetKey];\n\t\treturn {type: this.type, result: {path: filePath, value, seen}};\n\t}\n\n\tprivate filePath(key: string, options: DockerSecretsConfigLoaderOptions): string {\n\t\treturn path.join(path.resolve(options.path), options.fileLowerCase ? key.toLowerCase() : key);\n\t}\n}\n","import {existsSync, type FSWatcher, watch} from 'fs';\nimport {type IConfigLoaderProps, type Loadable, type LoaderValue, RecordConfigLoader, type ValidateCallback, VariableError} from '@avanio/variable-util';\nimport {getError} from './errorUtil';\nimport type {ILoggerLike} from '@avanio/logger-like';\nimport {readFile} from 'fs/promises';\n\n/**\n * Options for the AbstractFileRecordLoader.\n * @since v0.8.0\n */\nexport interface AbstractFileRecordLoaderOptions<FileType extends string> extends IConfigLoaderProps {\n\tfileType: FileType;\n\t/** file name to load */\n\tfileName: string;\n\t/** set to false if need errors */\n\tisSilent: boolean;\n\t/** optional logger */\n\tlogger: ILoggerLike | undefined;\n\t/** set to true to watch file for changes */\n\twatch: boolean;\n\t/** set to true to disable loader */\n\tdisabled: boolean;\n\t/**\n\t * optional validator for data (Record<string, string | undefined>)\n\t *\n\t * @example\n\t * // using zod\n\t * const stringRecordSchema = z.record(z.string().min(1), z.string());\n\t * const validate: ValidateCallback<Record<string, string>> = async (data) => {\n\t * const result = await stringRecordSchema.safeParseAsync(data);\n\t * if (!result.success) {\n\t * return {success: false, message: result.error.message};\n\t * }\n\t * return {success: true};\n\t * };\n\t */\n\tvalidate: ValidateCallback<Record<string, string | undefined>, Record<string, string | undefined>> | undefined;\n}\n\n/**\n * Abstract class for loading records from a file.\n * @since v0.8.0\n */\nexport abstract class AbstractFileRecordLoader<\n\tOptions extends AbstractFileRecordLoaderOptions<string> = AbstractFileRecordLoaderOptions<string>,\n> extends RecordConfigLoader<string | undefined, Partial<Options>, Options> {\n\tabstract readonly type: Lowercase<string>;\n\tprivate watcher: FSWatcher | undefined;\n\tprivate timeout: ReturnType<typeof setTimeout> | undefined;\n\n\tprotected abstract defaultOptions: Options;\n\n\tpublic constructor(options: Loadable<Partial<Options>>) {\n\t\tsuper(options);\n\t\tthis.getLoader = this.getLoader.bind(this);\n\t\tthis.handleFileChange = this.handleFileChange.bind(this);\n\t}\n\n\t/**\n\t * If the loader is watching the file, it will stop watching.\n\t */\n\tpublic async close(): Promise<void> {\n\t\tif (this.watcher) {\n\t\t\tconst {logger, fileName} = await this.getOptions();\n\t\t\tlogger?.debug(this.buildErrorStr(`closing file watcher for ${fileName}`));\n\t\t\tthis.watcher.close();\n\t\t}\n\t}\n\n\tprotected async handleLoader(rootKey: string, key?: string): Promise<LoaderValue> {\n\t\tconst {disabled, fileName} = await this.getOptions();\n\t\tif (disabled) {\n\t\t\treturn {type: this.type, result: undefined};\n\t\t}\n\t\tif (!this.dataPromise) {\n\t\t\tthis.dataPromise = this.handleData();\n\t\t}\n\t\tconst data = await this.dataPromise;\n\t\tconst targetKey = key || rootKey;\n\t\tconst currentValue = data[targetKey];\n\t\treturn {type: this.type, result: {value: currentValue, path: fileName, seen: this.handleSeen(targetKey, currentValue)}};\n\t}\n\n\tprotected async handleData(): Promise<Record<string, string | undefined>> {\n\t\tconst options = await this.getOptions();\n\t\toptions.logger?.debug(this.buildErrorStr(`loading file ${options.fileName}`));\n\t\t// if file is disabled, return empty object\n\t\tif (options.disabled) {\n\t\t\treturn {};\n\t\t}\n\t\tif (!existsSync(options.fileName)) {\n\t\t\tconst msg = this.buildErrorStr(`file ${options.fileName} not found`);\n\t\t\tif (options.isSilent) {\n\t\t\t\toptions.logger?.debug(msg);\n\t\t\t\treturn {};\n\t\t\t}\n\t\t\tthrow new VariableError(msg);\n\t\t}\n\t\ttry {\n\t\t\tconst data = await this.handleParse(await readFile(options.fileName), options);\n\t\t\tif (options.validate) {\n\t\t\t\treturn await options.validate(data);\n\t\t\t}\n\t\t\tthis.handleFileWatch(options); // add watch after successful load\n\t\t\treturn data;\n\t\t} catch (_err) {\n\t\t\tconst msg = this.buildErrorStr(`file ${options.fileName} is not a valid ${options.fileType}`);\n\t\t\tif (options.isSilent) {\n\t\t\t\toptions.logger?.info(msg);\n\t\t\t\treturn {};\n\t\t\t}\n\t\t\tthrow new VariableError(msg);\n\t\t}\n\t}\n\n\t/**\n\t * Handle the parsing of the file.\n\t */\n\tprotected abstract handleParse(rawData: Buffer, options: Options): Record<string, string | undefined> | Promise<Record<string, string | undefined>>;\n\n\tprivate handleFileWatch(options: Options): void {\n\t\tif (options.watch && !this.watcher) {\n\t\t\toptions.logger?.debug(this.buildErrorStr(`opening file watcher for ${options.fileName}`));\n\t\t\tthis.watcher = watch(options.fileName, () => {\n\t\t\t\tif (this.timeout) {\n\t\t\t\t\tclearTimeout(this.timeout);\n\t\t\t\t}\n\t\t\t\t// delay to prevent multiple reloads\n\t\t\t\tthis.timeout = setTimeout(() => {\n\t\t\t\t\tvoid this.handleFileChange(options);\n\t\t\t\t}, 200);\n\t\t\t});\n\t\t}\n\t}\n\n\tprivate async handleFileChange(options: Options): Promise<void> {\n\t\ttry {\n\t\t\toptions.logger?.debug(this.buildErrorStr(`file ${options.fileName} changed`));\n\t\t\tawait this.reload();\n\t\t} catch (err) {\n\t\t\toptions.logger?.error(this.buildErrorStr(`error reloading file ${options.fileName}: ${getError(err).message}`));\n\t\t}\n\t}\n}\n","export function getError(error: unknown): Error {\n\tif (error instanceof Error) {\n\t\treturn error;\n\t}\n\tif (typeof error === 'string') {\n\t\treturn new Error(error);\n\t}\n\treturn new Error(`Unknown error: ${JSON.stringify(error)}`);\n}\n","import {AbstractFileRecordLoader, type AbstractFileRecordLoaderOptions} from './AbstractFileRecordLoader';\nimport {type Loadable} from '@avanio/variable-util';\n\n/**\n * A file-based configuration loader that reads a JSON file.\n * @since v0.9.1\n */\nexport class FileConfigLoader extends AbstractFileRecordLoader<AbstractFileRecordLoaderOptions<'json'>> {\n\tpublic readonly type: Lowercase<string>;\n\n\tpublic constructor(options: Loadable<Partial<AbstractFileRecordLoaderOptions<'json'>>>, type: Lowercase<string> = 'file') {\n\t\tsuper(options);\n\t\tthis.type = type;\n\t}\n\n\tprotected defaultOptions: AbstractFileRecordLoaderOptions<'json'> = {\n\t\tdisabled: false,\n\t\tfileName: 'config.json',\n\t\tfileType: 'json',\n\t\tisSilent: true,\n\t\tlogger: undefined,\n\t\tvalidate: undefined,\n\t\twatch: false,\n\t};\n\n\tprotected handleParse(rawData: Buffer): Record<string, string | undefined> {\n\t\treturn JSON.parse(rawData.toString()) as Record<string, string | undefined>;\n\t}\n}\n","import {AbstractFileRecordLoader, type AbstractFileRecordLoaderOptions} from './AbstractFileRecordLoader';\nimport {type Loadable} from '@avanio/variable-util';\nimport {parse} from 'dotenv';\n\n/**\n * Loader for dotenv files, using the `dotenv` packages parser.\n * @since v0.6.1\n */\nexport class DotEnvLoader extends AbstractFileRecordLoader {\n\tpublic readonly type: Lowercase<string>;\n\n\tpublic constructor(options: Loadable<Partial<AbstractFileRecordLoaderOptions<'env'>>>, type: Lowercase<string> = 'dotenv') {\n\t\tsuper(options);\n\t\tthis.type = type;\n\t}\n\n\tprotected defaultOptions: AbstractFileRecordLoaderOptions<'env'> = {\n\t\tdisabled: false,\n\t\tfileName: '.env',\n\t\tfileType: 'env',\n\t\tisSilent: true,\n\t\tlogger: undefined,\n\t\tvalidate: undefined,\n\t\twatch: false,\n\t};\n\n\tprotected handleParse(rawData: Buffer): Record<string, string | undefined> {\n\t\treturn parse(rawData);\n\t}\n}\n"],"mappings":"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","names":["import_fs","import_variable_util","import_promises"]}
// src/DockerSecretsConfigLoader.ts
import * as path from "path";
import { ConfigLoader, VariableLookupError } from "@avanio/variable-util";
import { existsSync } from "fs";
import { readFile } from "fs/promises";
var DockerSecretsConfigLoader = class extends ConfigLoader {
type;
valuePromises = {};
defaultOptions = {
disabled: false,
fileLowerCase: false,
isSilent: true,
logger: void 0,
path: "/run/secrets"
};
constructor(options, type = "docker-secrets") {
super(options);
this.getLoader = this.getLoader.bind(this);
this.type = type;
}
async handleLoader(lookupKey, overrideKey) {
const options = await this.getOptions();
if (options.disabled) {
return { type: this.type, result: void 0 };
}
const targetKey = overrideKey || lookupKey;
const filePath = this.filePath(targetKey, options);
const valuePromise = this.valuePromises[targetKey];
const seen = !!valuePromise;
if (!valuePromise) {
if (!existsSync(filePath)) {
if (!options.isSilent) {
throw new VariableLookupError(targetKey, `ConfigVariables[${this.type}]: ${lookupKey} from ${filePath} not found`);
}
options.logger?.debug(`ConfigVariables[${this.type}]: ${lookupKey} from ${filePath} not found`);
this.valuePromises[targetKey] = Promise.resolve(void 0);
} else {
this.valuePromises[targetKey] = readFile(filePath, "utf8");
}
}
const value = await this.valuePromises[targetKey];
return { type: this.type, result: { path: filePath, value, seen } };
}
filePath(key, options) {
return path.join(path.resolve(options.path), options.fileLowerCase ? key.toLowerCase() : key);
}
};
// src/AbstractFileRecordLoader.ts
import { existsSync as existsSync2, watch } from "fs";
import { RecordConfigLoader, VariableError } from "@avanio/variable-util";
// src/errorUtil.ts
function getError(error) {
if (error instanceof Error) {
return error;
}
if (typeof error === "string") {
return new Error(error);
}
return new Error(`Unknown error: ${JSON.stringify(error)}`);
}
// src/AbstractFileRecordLoader.ts
import { readFile as readFile2 } from "fs/promises";
var AbstractFileRecordLoader = class extends RecordConfigLoader {
watcher;
timeout;
constructor(options) {
super(options);
this.getLoader = this.getLoader.bind(this);
this.handleFileChange = this.handleFileChange.bind(this);
}
/**
* If the loader is watching the file, it will stop watching.
*/
async close() {
if (this.watcher) {
const { logger, fileName } = await this.getOptions();
logger?.debug(this.buildErrorStr(`closing file watcher for ${fileName}`));
this.watcher.close();
}
}
async handleLoader(rootKey, key) {
const { disabled, fileName } = await this.getOptions();
if (disabled) {
return { type: this.type, result: void 0 };
}
if (!this.dataPromise) {
this.dataPromise = this.handleData();
}
const data = await this.dataPromise;
const targetKey = key || rootKey;
const currentValue = data[targetKey];
return { type: this.type, result: { value: currentValue, path: fileName, seen: this.handleSeen(targetKey, currentValue) } };
}
async handleData() {
const options = await this.getOptions();
options.logger?.debug(this.buildErrorStr(`loading file ${options.fileName}`));
if (options.disabled) {
return {};
}
if (!existsSync2(options.fileName)) {
const msg = this.buildErrorStr(`file ${options.fileName} not found`);
if (options.isSilent) {
options.logger?.debug(msg);
return {};
}
throw new VariableError(msg);
}
try {
const data = await this.handleParse(await readFile2(options.fileName), options);
if (options.validate) {
return await options.validate(data);
}
this.handleFileWatch(options);
return data;
} catch (_err) {
const msg = this.buildErrorStr(`file ${options.fileName} is not a valid ${options.fileType}`);
if (options.isSilent) {
options.logger?.info(msg);
return {};
}
throw new VariableError(msg);
}
}
handleFileWatch(options) {
if (options.watch && !this.watcher) {
options.logger?.debug(this.buildErrorStr(`opening file watcher for ${options.fileName}`));
this.watcher = watch(options.fileName, () => {
if (this.timeout) {
clearTimeout(this.timeout);
}
this.timeout = setTimeout(() => {
void this.handleFileChange(options);
}, 200);
});
}
}
async handleFileChange(options) {
try {
options.logger?.debug(this.buildErrorStr(`file ${options.fileName} changed`));
await this.reload();
} catch (err) {
options.logger?.error(this.buildErrorStr(`error reloading file ${options.fileName}: ${getError(err).message}`));
}
}
};
// src/FileConfigLoader.ts
var FileConfigLoader = class extends AbstractFileRecordLoader {
type;
constructor(options, type = "file") {
super(options);
this.type = type;
}
defaultOptions = {
disabled: false,
fileName: "config.json",
fileType: "json",
isSilent: true,
logger: void 0,
validate: void 0,
watch: false
};
handleParse(rawData) {
return JSON.parse(rawData.toString());
}
};
// src/DotEnvLoader.ts
import { parse } from "dotenv";
var DotEnvLoader = class extends AbstractFileRecordLoader {
type;
constructor(options, type = "dotenv") {
super(options);
this.type = type;
}
defaultOptions = {
disabled: false,
fileName: ".env",
fileType: "env",
isSilent: true,
logger: void 0,
validate: void 0,
watch: false
};
handleParse(rawData) {
return parse(rawData);
}
};
export {
AbstractFileRecordLoader,
DockerSecretsConfigLoader,
DotEnvLoader,
FileConfigLoader,
getError
};
//# sourceMappingURL=index.mjs.map
{"version":3,"sources":["../src/DockerSecretsConfigLoader.ts","../src/AbstractFileRecordLoader.ts","../src/errorUtil.ts","../src/FileConfigLoader.ts","../src/DotEnvLoader.ts"],"sourcesContent":["import * as path from 'path';\nimport {ConfigLoader, type Loadable, type LoaderValue, VariableLookupError} from '@avanio/variable-util';\nimport {existsSync} from 'fs';\nimport type {ILoggerLike} from '@avanio/logger-like';\nimport {readFile} from 'fs/promises';\n\nexport interface DockerSecretsConfigLoaderOptions {\n\t/** force file name to lower case */\n\tfileLowerCase: boolean;\n\t/** path to docker secrets, default is '/run/secrets' */\n\tpath: string;\n\t/** set to false if need errors */\n\tisSilent: boolean;\n\t/** optional logger */\n\tlogger: ILoggerLike | undefined;\n\t/** set to true to disable loader, default is false */\n\tdisabled: boolean;\n}\n\n/**\n * Loader for docker secrets, reads secrets from the `/run/secrets` directory.\n * @since v0.8.0\n */\nexport class DockerSecretsConfigLoader extends ConfigLoader<string | undefined, Partial<DockerSecretsConfigLoaderOptions>, DockerSecretsConfigLoaderOptions> {\n\tpublic readonly type: Lowercase<string>;\n\tprivate valuePromises: Record<string, Promise<string | undefined> | undefined> = {};\n\tprotected defaultOptions: DockerSecretsConfigLoaderOptions = {\n\t\tdisabled: false,\n\t\tfileLowerCase: false,\n\t\tisSilent: true,\n\t\tlogger: undefined,\n\t\tpath: '/run/secrets',\n\t};\n\n\tpublic constructor(options: Loadable<Partial<DockerSecretsConfigLoaderOptions>>, type: Lowercase<string> = 'docker-secrets') {\n\t\tsuper(options);\n\t\tthis.getLoader = this.getLoader.bind(this);\n\t\tthis.type = type;\n\t}\n\n\tprotected async handleLoader(lookupKey: string, overrideKey?: string): Promise<LoaderValue> {\n\t\tconst options = await this.getOptions();\n\t\tif (options.disabled) {\n\t\t\treturn {type: this.type, result: undefined};\n\t\t}\n\t\tconst targetKey = overrideKey || lookupKey;\n\t\tconst filePath = this.filePath(targetKey, options);\n\t\tconst valuePromise = this.valuePromises[targetKey];\n\t\tconst seen = !!valuePromise; // if valuePromise exists, it means we have seen this key before\n\t\tif (!valuePromise) {\n\t\t\tif (!existsSync(filePath)) {\n\t\t\t\tif (!options.isSilent) {\n\t\t\t\t\tthrow new VariableLookupError(targetKey, `ConfigVariables[${this.type}]: ${lookupKey} from ${filePath} not found`);\n\t\t\t\t}\n\t\t\t\toptions.logger?.debug(`ConfigVariables[${this.type}]: ${lookupKey} from ${filePath} not found`);\n\t\t\t\tthis.valuePromises[targetKey] = Promise.resolve(undefined);\n\t\t\t} else {\n\t\t\t\tthis.valuePromises[targetKey] = readFile(filePath, 'utf8');\n\t\t\t}\n\t\t}\n\t\tconst value = await this.valuePromises[targetKey];\n\t\treturn {type: this.type, result: {path: filePath, value, seen}};\n\t}\n\n\tprivate filePath(key: string, options: DockerSecretsConfigLoaderOptions): string {\n\t\treturn path.join(path.resolve(options.path), options.fileLowerCase ? key.toLowerCase() : key);\n\t}\n}\n","import {existsSync, type FSWatcher, watch} from 'fs';\nimport {type IConfigLoaderProps, type Loadable, type LoaderValue, RecordConfigLoader, type ValidateCallback, VariableError} from '@avanio/variable-util';\nimport {getError} from './errorUtil';\nimport type {ILoggerLike} from '@avanio/logger-like';\nimport {readFile} from 'fs/promises';\n\n/**\n * Options for the AbstractFileRecordLoader.\n * @since v0.8.0\n */\nexport interface AbstractFileRecordLoaderOptions<FileType extends string> extends IConfigLoaderProps {\n\tfileType: FileType;\n\t/** file name to load */\n\tfileName: string;\n\t/** set to false if need errors */\n\tisSilent: boolean;\n\t/** optional logger */\n\tlogger: ILoggerLike | undefined;\n\t/** set to true to watch file for changes */\n\twatch: boolean;\n\t/** set to true to disable loader */\n\tdisabled: boolean;\n\t/**\n\t * optional validator for data (Record<string, string | undefined>)\n\t *\n\t * @example\n\t * // using zod\n\t * const stringRecordSchema = z.record(z.string().min(1), z.string());\n\t * const validate: ValidateCallback<Record<string, string>> = async (data) => {\n\t * const result = await stringRecordSchema.safeParseAsync(data);\n\t * if (!result.success) {\n\t * return {success: false, message: result.error.message};\n\t * }\n\t * return {success: true};\n\t * };\n\t */\n\tvalidate: ValidateCallback<Record<string, string | undefined>, Record<string, string | undefined>> | undefined;\n}\n\n/**\n * Abstract class for loading records from a file.\n * @since v0.8.0\n */\nexport abstract class AbstractFileRecordLoader<\n\tOptions extends AbstractFileRecordLoaderOptions<string> = AbstractFileRecordLoaderOptions<string>,\n> extends RecordConfigLoader<string | undefined, Partial<Options>, Options> {\n\tabstract readonly type: Lowercase<string>;\n\tprivate watcher: FSWatcher | undefined;\n\tprivate timeout: ReturnType<typeof setTimeout> | undefined;\n\n\tprotected abstract defaultOptions: Options;\n\n\tpublic constructor(options: Loadable<Partial<Options>>) {\n\t\tsuper(options);\n\t\tthis.getLoader = this.getLoader.bind(this);\n\t\tthis.handleFileChange = this.handleFileChange.bind(this);\n\t}\n\n\t/**\n\t * If the loader is watching the file, it will stop watching.\n\t */\n\tpublic async close(): Promise<void> {\n\t\tif (this.watcher) {\n\t\t\tconst {logger, fileName} = await this.getOptions();\n\t\t\tlogger?.debug(this.buildErrorStr(`closing file watcher for ${fileName}`));\n\t\t\tthis.watcher.close();\n\t\t}\n\t}\n\n\tprotected async handleLoader(rootKey: string, key?: string): Promise<LoaderValue> {\n\t\tconst {disabled, fileName} = await this.getOptions();\n\t\tif (disabled) {\n\t\t\treturn {type: this.type, result: undefined};\n\t\t}\n\t\tif (!this.dataPromise) {\n\t\t\tthis.dataPromise = this.handleData();\n\t\t}\n\t\tconst data = await this.dataPromise;\n\t\tconst targetKey = key || rootKey;\n\t\tconst currentValue = data[targetKey];\n\t\treturn {type: this.type, result: {value: currentValue, path: fileName, seen: this.handleSeen(targetKey, currentValue)}};\n\t}\n\n\tprotected async handleData(): Promise<Record<string, string | undefined>> {\n\t\tconst options = await this.getOptions();\n\t\toptions.logger?.debug(this.buildErrorStr(`loading file ${options.fileName}`));\n\t\t// if file is disabled, return empty object\n\t\tif (options.disabled) {\n\t\t\treturn {};\n\t\t}\n\t\tif (!existsSync(options.fileName)) {\n\t\t\tconst msg = this.buildErrorStr(`file ${options.fileName} not found`);\n\t\t\tif (options.isSilent) {\n\t\t\t\toptions.logger?.debug(msg);\n\t\t\t\treturn {};\n\t\t\t}\n\t\t\tthrow new VariableError(msg);\n\t\t}\n\t\ttry {\n\t\t\tconst data = await this.handleParse(await readFile(options.fileName), options);\n\t\t\tif (options.validate) {\n\t\t\t\treturn await options.validate(data);\n\t\t\t}\n\t\t\tthis.handleFileWatch(options); // add watch after successful load\n\t\t\treturn data;\n\t\t} catch (_err) {\n\t\t\tconst msg = this.buildErrorStr(`file ${options.fileName} is not a valid ${options.fileType}`);\n\t\t\tif (options.isSilent) {\n\t\t\t\toptions.logger?.info(msg);\n\t\t\t\treturn {};\n\t\t\t}\n\t\t\tthrow new VariableError(msg);\n\t\t}\n\t}\n\n\t/**\n\t * Handle the parsing of the file.\n\t */\n\tprotected abstract handleParse(rawData: Buffer, options: Options): Record<string, string | undefined> | Promise<Record<string, string | undefined>>;\n\n\tprivate handleFileWatch(options: Options): void {\n\t\tif (options.watch && !this.watcher) {\n\t\t\toptions.logger?.debug(this.buildErrorStr(`opening file watcher for ${options.fileName}`));\n\t\t\tthis.watcher = watch(options.fileName, () => {\n\t\t\t\tif (this.timeout) {\n\t\t\t\t\tclearTimeout(this.timeout);\n\t\t\t\t}\n\t\t\t\t// delay to prevent multiple reloads\n\t\t\t\tthis.timeout = setTimeout(() => {\n\t\t\t\t\tvoid this.handleFileChange(options);\n\t\t\t\t}, 200);\n\t\t\t});\n\t\t}\n\t}\n\n\tprivate async handleFileChange(options: Options): Promise<void> {\n\t\ttry {\n\t\t\toptions.logger?.debug(this.buildErrorStr(`file ${options.fileName} changed`));\n\t\t\tawait this.reload();\n\t\t} catch (err) {\n\t\t\toptions.logger?.error(this.buildErrorStr(`error reloading file ${options.fileName}: ${getError(err).message}`));\n\t\t}\n\t}\n}\n","export function getError(error: unknown): Error {\n\tif (error instanceof Error) {\n\t\treturn error;\n\t}\n\tif (typeof error === 'string') {\n\t\treturn new Error(error);\n\t}\n\treturn new Error(`Unknown error: ${JSON.stringify(error)}`);\n}\n","import {AbstractFileRecordLoader, type AbstractFileRecordLoaderOptions} from './AbstractFileRecordLoader';\nimport {type Loadable} from '@avanio/variable-util';\n\n/**\n * A file-based configuration loader that reads a JSON file.\n * @since v0.9.1\n */\nexport class FileConfigLoader extends AbstractFileRecordLoader<AbstractFileRecordLoaderOptions<'json'>> {\n\tpublic readonly type: Lowercase<string>;\n\n\tpublic constructor(options: Loadable<Partial<AbstractFileRecordLoaderOptions<'json'>>>, type: Lowercase<string> = 'file') {\n\t\tsuper(options);\n\t\tthis.type = type;\n\t}\n\n\tprotected defaultOptions: AbstractFileRecordLoaderOptions<'json'> = {\n\t\tdisabled: false,\n\t\tfileName: 'config.json',\n\t\tfileType: 'json',\n\t\tisSilent: true,\n\t\tlogger: undefined,\n\t\tvalidate: undefined,\n\t\twatch: false,\n\t};\n\n\tprotected handleParse(rawData: Buffer): Record<string, string | undefined> {\n\t\treturn JSON.parse(rawData.toString()) as Record<string, string | undefined>;\n\t}\n}\n","import {AbstractFileRecordLoader, type AbstractFileRecordLoaderOptions} from './AbstractFileRecordLoader';\nimport {type Loadable} from '@avanio/variable-util';\nimport {parse} from 'dotenv';\n\n/**\n * Loader for dotenv files, using the `dotenv` packages parser.\n * @since v0.6.1\n */\nexport class DotEnvLoader extends AbstractFileRecordLoader {\n\tpublic readonly type: Lowercase<string>;\n\n\tpublic constructor(options: Loadable<Partial<AbstractFileRecordLoaderOptions<'env'>>>, type: Lowercase<string> = 'dotenv') {\n\t\tsuper(options);\n\t\tthis.type = type;\n\t}\n\n\tprotected defaultOptions: AbstractFileRecordLoaderOptions<'env'> = {\n\t\tdisabled: false,\n\t\tfileName: '.env',\n\t\tfileType: 'env',\n\t\tisSilent: true,\n\t\tlogger: undefined,\n\t\tvalidate: undefined,\n\t\twatch: false,\n\t};\n\n\tprotected handleParse(rawData: Buffer): Record<string, string | undefined> {\n\t\treturn parse(rawData);\n\t}\n}\n"],"mappings":"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","names":["existsSync","readFile","existsSync"]}
+109
-5

@@ -1,5 +0,109 @@

export * from './DockerSecretsConfigLoader';
export * from './FileConfigLoader';
export * from './DotEnvLoader';
export * from './AbstractFileRecordLoader';
export * from './errorUtil';
import { ConfigLoader, Loadable, LoaderValue, IConfigLoaderProps, ValidateCallback, RecordConfigLoader } from '@avanio/variable-util';
import { ILoggerLike } from '@avanio/logger-like';
interface DockerSecretsConfigLoaderOptions {
/** force file name to lower case */
fileLowerCase: boolean;
/** path to docker secrets, default is '/run/secrets' */
path: string;
/** set to false if need errors */
isSilent: boolean;
/** optional logger */
logger: ILoggerLike | undefined;
/** set to true to disable loader, default is false */
disabled: boolean;
}
/**
* Loader for docker secrets, reads secrets from the `/run/secrets` directory.
* @since v0.8.0
*/
declare class DockerSecretsConfigLoader extends ConfigLoader<string | undefined, Partial<DockerSecretsConfigLoaderOptions>, DockerSecretsConfigLoaderOptions> {
readonly type: Lowercase<string>;
private valuePromises;
protected defaultOptions: DockerSecretsConfigLoaderOptions;
constructor(options: Loadable<Partial<DockerSecretsConfigLoaderOptions>>, type?: Lowercase<string>);
protected handleLoader(lookupKey: string, overrideKey?: string): Promise<LoaderValue>;
private filePath;
}
/**
* Options for the AbstractFileRecordLoader.
* @since v0.8.0
*/
interface AbstractFileRecordLoaderOptions<FileType extends string> extends IConfigLoaderProps {
fileType: FileType;
/** file name to load */
fileName: string;
/** set to false if need errors */
isSilent: boolean;
/** optional logger */
logger: ILoggerLike | undefined;
/** set to true to watch file for changes */
watch: boolean;
/** set to true to disable loader */
disabled: boolean;
/**
* optional validator for data (Record<string, string | undefined>)
*
* @example
* // using zod
* const stringRecordSchema = z.record(z.string().min(1), z.string());
* const validate: ValidateCallback<Record<string, string>> = async (data) => {
* const result = await stringRecordSchema.safeParseAsync(data);
* if (!result.success) {
* return {success: false, message: result.error.message};
* }
* return {success: true};
* };
*/
validate: ValidateCallback<Record<string, string | undefined>, Record<string, string | undefined>> | undefined;
}
/**
* Abstract class for loading records from a file.
* @since v0.8.0
*/
declare abstract class AbstractFileRecordLoader<Options extends AbstractFileRecordLoaderOptions<string> = AbstractFileRecordLoaderOptions<string>> extends RecordConfigLoader<string | undefined, Partial<Options>, Options> {
abstract readonly type: Lowercase<string>;
private watcher;
private timeout;
protected abstract defaultOptions: Options;
constructor(options: Loadable<Partial<Options>>);
/**
* If the loader is watching the file, it will stop watching.
*/
close(): Promise<void>;
protected handleLoader(rootKey: string, key?: string): Promise<LoaderValue>;
protected handleData(): Promise<Record<string, string | undefined>>;
/**
* Handle the parsing of the file.
*/
protected abstract handleParse(rawData: Buffer, options: Options): Record<string, string | undefined> | Promise<Record<string, string | undefined>>;
private handleFileWatch;
private handleFileChange;
}
/**
* A file-based configuration loader that reads a JSON file.
* @since v0.9.1
*/
declare class FileConfigLoader extends AbstractFileRecordLoader<AbstractFileRecordLoaderOptions<'json'>> {
readonly type: Lowercase<string>;
constructor(options: Loadable<Partial<AbstractFileRecordLoaderOptions<'json'>>>, type?: Lowercase<string>);
protected defaultOptions: AbstractFileRecordLoaderOptions<'json'>;
protected handleParse(rawData: Buffer): Record<string, string | undefined>;
}
/**
* Loader for dotenv files, using the `dotenv` packages parser.
* @since v0.6.1
*/
declare class DotEnvLoader extends AbstractFileRecordLoader {
readonly type: Lowercase<string>;
constructor(options: Loadable<Partial<AbstractFileRecordLoaderOptions<'env'>>>, type?: Lowercase<string>);
protected defaultOptions: AbstractFileRecordLoaderOptions<'env'>;
protected handleParse(rawData: Buffer): Record<string, string | undefined>;
}
declare function getError(error: unknown): Error;
export { AbstractFileRecordLoader, type AbstractFileRecordLoaderOptions, DockerSecretsConfigLoader, type DockerSecretsConfigLoaderOptions, DotEnvLoader, FileConfigLoader, getError };
"use strict";
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
var desc = Object.getOwnPropertyDescriptor(m, k);
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
desc = { enumerable: true, get: function() { return m[k]; } };
var __create = Object.create;
var __defProp = Object.defineProperty;
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
var __getOwnPropNames = Object.getOwnPropertyNames;
var __getProtoOf = Object.getPrototypeOf;
var __hasOwnProp = Object.prototype.hasOwnProperty;
var __export = (target, all) => {
for (var name in all)
__defProp(target, name, { get: all[name], enumerable: true });
};
var __copyProps = (to, from, except, desc) => {
if (from && typeof from === "object" || typeof from === "function") {
for (let key of __getOwnPropNames(from))
if (!__hasOwnProp.call(to, key) && key !== except)
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
}
return to;
};
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
// If the importer is in node compatibility mode or this is not an ESM
// file that has been converted to a CommonJS file using a Babel-
// compatible transform (i.e. "__esModule" has not been set), then set
// "default" to the CommonJS "module.exports" for node compatibility.
isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
mod
));
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
// src/index.ts
var src_exports = {};
__export(src_exports, {
AbstractFileRecordLoader: () => AbstractFileRecordLoader,
DockerSecretsConfigLoader: () => DockerSecretsConfigLoader,
DotEnvLoader: () => DotEnvLoader,
FileConfigLoader: () => FileConfigLoader,
getError: () => getError
});
module.exports = __toCommonJS(src_exports);
// src/DockerSecretsConfigLoader.ts
var path = __toESM(require("path"));
var import_variable_util = require("@avanio/variable-util");
var import_fs = require("fs");
var import_promises = require("fs/promises");
var DockerSecretsConfigLoader = class extends import_variable_util.ConfigLoader {
type;
valuePromises = {};
defaultOptions = {
disabled: false,
fileLowerCase: false,
isSilent: true,
logger: void 0,
path: "/run/secrets"
};
constructor(options, type = "docker-secrets") {
super(options);
this.getLoader = this.getLoader.bind(this);
this.type = type;
}
async handleLoader(lookupKey, overrideKey) {
const options = await this.getOptions();
if (options.disabled) {
return { type: this.type, result: void 0 };
}
Object.defineProperty(o, k2, desc);
}) : (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" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
const targetKey = overrideKey || lookupKey;
const filePath = this.filePath(targetKey, options);
const valuePromise = this.valuePromises[targetKey];
const seen = !!valuePromise;
if (!valuePromise) {
if (!(0, import_fs.existsSync)(filePath)) {
if (!options.isSilent) {
throw new import_variable_util.VariableLookupError(targetKey, `ConfigVariables[${this.type}]: ${lookupKey} from ${filePath} not found`);
}
options.logger?.debug(`ConfigVariables[${this.type}]: ${lookupKey} from ${filePath} not found`);
this.valuePromises[targetKey] = Promise.resolve(void 0);
} else {
this.valuePromises[targetKey] = (0, import_promises.readFile)(filePath, "utf8");
}
}
const value = await this.valuePromises[targetKey];
return { type: this.type, result: { path: filePath, value, seen } };
}
filePath(key, options) {
return path.join(path.resolve(options.path), options.fileLowerCase ? key.toLowerCase() : key);
}
};
Object.defineProperty(exports, "__esModule", { value: true });
__exportStar(require("./DockerSecretsConfigLoader"), exports);
__exportStar(require("./FileConfigLoader"), exports);
__exportStar(require("./DotEnvLoader"), exports);
__exportStar(require("./AbstractFileRecordLoader"), exports);
__exportStar(require("./errorUtil"), exports);
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5kZXguanMiLCJzb3VyY2VSb290IjoiLi9zcmMvIiwic291cmNlcyI6WyJpbmRleC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7Ozs7Ozs7Ozs7Ozs7O0FBQUEsOERBQTRDO0FBQzVDLHFEQUFtQztBQUNuQyxpREFBK0I7QUFDL0IsNkRBQTJDO0FBQzNDLDhDQUE0QiJ9
// src/AbstractFileRecordLoader.ts
var import_fs2 = require("fs");
var import_variable_util2 = require("@avanio/variable-util");
// src/errorUtil.ts
function getError(error) {
if (error instanceof Error) {
return error;
}
if (typeof error === "string") {
return new Error(error);
}
return new Error(`Unknown error: ${JSON.stringify(error)}`);
}
// src/AbstractFileRecordLoader.ts
var import_promises2 = require("fs/promises");
var AbstractFileRecordLoader = class extends import_variable_util2.RecordConfigLoader {
watcher;
timeout;
constructor(options) {
super(options);
this.getLoader = this.getLoader.bind(this);
this.handleFileChange = this.handleFileChange.bind(this);
}
/**
* If the loader is watching the file, it will stop watching.
*/
async close() {
if (this.watcher) {
const { logger, fileName } = await this.getOptions();
logger?.debug(this.buildErrorStr(`closing file watcher for ${fileName}`));
this.watcher.close();
}
}
async handleLoader(rootKey, key) {
const { disabled, fileName } = await this.getOptions();
if (disabled) {
return { type: this.type, result: void 0 };
}
if (!this.dataPromise) {
this.dataPromise = this.handleData();
}
const data = await this.dataPromise;
const targetKey = key || rootKey;
const currentValue = data[targetKey];
return { type: this.type, result: { value: currentValue, path: fileName, seen: this.handleSeen(targetKey, currentValue) } };
}
async handleData() {
const options = await this.getOptions();
options.logger?.debug(this.buildErrorStr(`loading file ${options.fileName}`));
if (options.disabled) {
return {};
}
if (!(0, import_fs2.existsSync)(options.fileName)) {
const msg = this.buildErrorStr(`file ${options.fileName} not found`);
if (options.isSilent) {
options.logger?.debug(msg);
return {};
}
throw new import_variable_util2.VariableError(msg);
}
try {
const data = await this.handleParse(await (0, import_promises2.readFile)(options.fileName), options);
if (options.validate) {
return await options.validate(data);
}
this.handleFileWatch(options);
return data;
} catch (_err) {
const msg = this.buildErrorStr(`file ${options.fileName} is not a valid ${options.fileType}`);
if (options.isSilent) {
options.logger?.info(msg);
return {};
}
throw new import_variable_util2.VariableError(msg);
}
}
handleFileWatch(options) {
if (options.watch && !this.watcher) {
options.logger?.debug(this.buildErrorStr(`opening file watcher for ${options.fileName}`));
this.watcher = (0, import_fs2.watch)(options.fileName, () => {
if (this.timeout) {
clearTimeout(this.timeout);
}
this.timeout = setTimeout(() => {
void this.handleFileChange(options);
}, 200);
});
}
}
async handleFileChange(options) {
try {
options.logger?.debug(this.buildErrorStr(`file ${options.fileName} changed`));
await this.reload();
} catch (err) {
options.logger?.error(this.buildErrorStr(`error reloading file ${options.fileName}: ${getError(err).message}`));
}
}
};
// src/FileConfigLoader.ts
var FileConfigLoader = class extends AbstractFileRecordLoader {
type;
constructor(options, type = "file") {
super(options);
this.type = type;
}
defaultOptions = {
disabled: false,
fileName: "config.json",
fileType: "json",
isSilent: true,
logger: void 0,
validate: void 0,
watch: false
};
handleParse(rawData) {
return JSON.parse(rawData.toString());
}
};
// src/DotEnvLoader.ts
var import_dotenv = require("dotenv");
var DotEnvLoader = class extends AbstractFileRecordLoader {
type;
constructor(options, type = "dotenv") {
super(options);
this.type = type;
}
defaultOptions = {
disabled: false,
fileName: ".env",
fileType: "env",
isSilent: true,
logger: void 0,
validate: void 0,
watch: false
};
handleParse(rawData) {
return (0, import_dotenv.parse)(rawData);
}
};
// Annotate the CommonJS export names for ESM import in node:
0 && (module.exports = {
AbstractFileRecordLoader,
DockerSecretsConfigLoader,
DotEnvLoader,
FileConfigLoader,
getError
});
//# sourceMappingURL=index.js.map
+32
-39
{
"name": "@avanio/variable-util-node",
"version": "0.10.0",
"version": "0.11.0",
"description": "nodejs env util",
"main": "./dist/index.js",
"module": "./dist/index.mjs",
"types": "./dist/index.d.ts",
"exports": {
".": {
"types": "./dist/index.d.ts",
"require": "./dist/index.js",
"import": "./dist/index.mjs"
}
},
"private": false,

@@ -10,43 +19,19 @@ "engines": {

},
"scripts": {
"build": "tsc",
"prepublishOnly": "npm run validate && npm run test && npm run lint && npm run build",
"test": "mocha",
"lint": "eslint . --ext .ts",
"validate": "tsc --noEmit --project tsconfig.test.json"
},
"files": [
"dist"
],
"mocha": {
"exit": true,
"extension": [
"ts",
"js"
],
"recursive": true,
"require": [
"ts-node/register",
"source-map-support/register"
],
"reporters": [
"spec",
"mocha-junit-reporter"
]
},
"author": "mharj",
"license": "MIT",
"devDependencies": {
"@avanio/logger-like": "^0.2.5",
"@avanio/variable-util": "^0.10.0",
"@stylistic/eslint-plugin": "^2.9.0",
"@stylistic/eslint-plugin-ts": "^2.9.0",
"@avanio/logger-like": "^0.2.7",
"@avanio/variable-util": "^0.11.0",
"@stylistic/eslint-plugin": "^2.10.1",
"@stylistic/eslint-plugin-ts": "^2.10.1",
"@tsconfig/node18": "^18.2.4",
"@types/chai": "^4.3.20",
"@types/mocha": "^10.0.9",
"@types/node": "^18.19.55",
"@types/node": "^18.19.64",
"@types/sinon": "^17.0.3",
"@typescript-eslint/eslint-plugin": "^8.8.1",
"@typescript-eslint/parser": "^8.8.1",
"chai": "^4.5.0",
"@typescript-eslint/eslint-plugin": "^8.14.0",
"@typescript-eslint/parser": "^8.14.0",
"@vitest/coverage-v8": "^2.1.5",
"c8": "^10.1.2",
"dotenv": "^16.4.5",

@@ -59,14 +44,22 @@ "eslint": "^8.57.1",

"eslint-plugin-sonarjs": "^0.25.1",
"mocha": "^10.7.3",
"prettier": "^3.3.3",
"sinon": "^19.0.2",
"source-map-support": "^0.5.21",
"ts-node": "^10.9.2",
"typescript": "^5.6.3"
"tsup": "^8.3.5",
"typescript": "^5.6.3",
"vite": "^5.4.11",
"vitest": "^2.1.4"
},
"peerDependencies": {
"@avanio/logger-like": "^0.1 || ^0.2",
"@avanio/variable-util": "^0.8 || ^0.9 || ^0.10",
"@avanio/variable-util": "^0.11",
"dotenv": "^16"
},
"scripts": {
"build": "tsup src/index.ts --sourcemap --format cjs,esm --dts --clean",
"test": "vitest test --run --no-isolate --coverage",
"coverage": "vitest test --run --no-isolate --reporter=dot --coverage --coverage.reporter=lcov",
"lint": "eslint . --ext .ts",
"validate": "tsc --noEmit --project tsconfig.test.json"
}
}
}
import { type IConfigLoaderProps, type Loadable, type LoaderValue, RecordConfigLoader, type ValidateCallback } from '@avanio/variable-util';
import type { ILoggerLike } from '@avanio/logger-like';
/**
* Options for the AbstractFileRecordLoader.
* @since v0.8.0
*/
export interface AbstractFileRecordLoaderOptions<FileType extends string> extends IConfigLoaderProps {
fileType: FileType;
/** file name to load */
fileName: string;
/** set to false if need errors */
isSilent: boolean;
/** optional logger */
logger: ILoggerLike | undefined;
/** set to true to watch file for changes */
watch: boolean;
/** set to true to disable loader */
disabled: boolean;
/**
* optional validator for data (Record<string, string | undefined>)
*
* @example
* // using zod
* const stringRecordSchema = z.record(z.string().min(1), z.string());
* const validate: ValidateCallback<Record<string, string>> = async (data) => {
* const result = await stringRecordSchema.safeParseAsync(data);
* if (!result.success) {
* return {success: false, message: result.error.message};
* }
* return {success: true};
* };
*/
validate: ValidateCallback<Record<string, string | undefined>, Record<string, string | undefined>> | undefined;
}
/**
* Abstract class for loading records from a file.
* @since v0.8.0
*/
export declare abstract class AbstractFileRecordLoader<Options extends AbstractFileRecordLoaderOptions<string> = AbstractFileRecordLoaderOptions<string>> extends RecordConfigLoader<string | undefined, Partial<Options>, Options> {
abstract readonly type: string;
private watcher;
private timeout;
protected abstract defaultOptions: Options;
constructor(options: Loadable<Partial<Options>>);
/**
* If the loader is watching the file, it will stop watching.
*/
close(): Promise<void>;
protected handleLoader(rootKey: string, key?: string): Promise<LoaderValue>;
protected handleData(): Promise<Record<string, string | undefined>>;
/**
* Handle the parsing of the file.
*/
protected abstract handleParse(rawData: Buffer, options: Options): Record<string, string | undefined> | Promise<Record<string, string | undefined>>;
private handleFileWatch;
private handleFileChange;
}
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.AbstractFileRecordLoader = void 0;
const fs_1 = require("fs");
const variable_util_1 = require("@avanio/variable-util");
const errorUtil_1 = require("./errorUtil");
const promises_1 = require("fs/promises");
/**
* Abstract class for loading records from a file.
* @since v0.8.0
*/
class AbstractFileRecordLoader extends variable_util_1.RecordConfigLoader {
watcher;
timeout;
constructor(options) {
super(options);
this.getLoader = this.getLoader.bind(this);
this.handleFileChange = this.handleFileChange.bind(this);
}
/**
* If the loader is watching the file, it will stop watching.
*/
async close() {
if (this.watcher) {
const { logger, fileName } = await this.getOptions();
logger?.debug(this.buildErrorStr(`closing file watcher for ${fileName}`));
this.watcher.close();
}
}
async handleLoader(rootKey, key) {
const { disabled, fileName } = await this.getOptions();
if (disabled) {
return { type: this.type, result: undefined };
}
if (!this.dataPromise) {
this.dataPromise = this.handleData();
}
const data = await this.dataPromise;
const targetKey = key || rootKey;
const currentValue = data[targetKey];
return { type: this.type, result: { value: currentValue, path: fileName, seen: this.handleSeen(targetKey, currentValue) } };
}
async handleData() {
const options = await this.getOptions();
options.logger?.debug(this.buildErrorStr(`loading file ${options.fileName}`));
// if file is disabled, return empty object
if (options.disabled) {
return {};
}
if (!(0, fs_1.existsSync)(options.fileName)) {
const msg = this.buildErrorStr(`file ${options.fileName} not found`);
if (options.isSilent) {
options.logger?.debug(msg);
return {};
}
throw new variable_util_1.VariableError(msg);
}
try {
const data = await this.handleParse(await (0, promises_1.readFile)(options.fileName), options);
if (options.validate) {
return await options.validate(data);
}
this.handleFileWatch(options); // add watch after successful load
return data;
}
catch (_err) {
const msg = this.buildErrorStr(`file ${options.fileName} is not a valid ${options.fileType}`);
if (options.isSilent) {
options.logger?.info(msg);
return {};
}
throw new variable_util_1.VariableError(msg);
}
}
handleFileWatch(options) {
if (options.watch && !this.watcher) {
options.logger?.debug(this.buildErrorStr(`opening file watcher for ${options.fileName}`));
this.watcher = (0, fs_1.watch)(options.fileName, () => {
if (this.timeout) {
clearTimeout(this.timeout);
}
// delay to prevent multiple reloads
this.timeout = setTimeout(() => {
void this.handleFileChange(options);
}, 200);
});
}
}
async handleFileChange(options) {
try {
options.logger?.debug(this.buildErrorStr(`file ${options.fileName} changed`));
await this.reload();
}
catch (err) {
options.logger?.error(this.buildErrorStr(`error reloading file ${options.fileName}: ${(0, errorUtil_1.getError)(err).message}`));
}
}
}
exports.AbstractFileRecordLoader = AbstractFileRecordLoader;
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiQWJzdHJhY3RGaWxlUmVjb3JkTG9hZGVyLmpzIiwic291cmNlUm9vdCI6Ii4vc3JjLyIsInNvdXJjZXMiOlsiQWJzdHJhY3RGaWxlUmVjb3JkTG9hZGVyLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7OztBQUFBLDJCQUFxRDtBQUNyRCx5REFBeUo7QUFDekosMkNBQXFDO0FBRXJDLDBDQUFxQztBQW1DckM7OztHQUdHO0FBQ0gsTUFBc0Isd0JBRXBCLFNBQVEsa0NBQWlFO0lBRWxFLE9BQU8sQ0FBd0I7SUFDL0IsT0FBTyxDQUE0QztJQUkzRCxZQUFtQixPQUFtQztRQUNyRCxLQUFLLENBQUMsT0FBTyxDQUFDLENBQUM7UUFDZixJQUFJLENBQUMsU0FBUyxHQUFHLElBQUksQ0FBQyxTQUFTLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQyxDQUFDO1FBQzNDLElBQUksQ0FBQyxnQkFBZ0IsR0FBRyxJQUFJLENBQUMsZ0JBQWdCLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQyxDQUFDO0lBQzFELENBQUM7SUFFRDs7T0FFRztJQUNJLEtBQUssQ0FBQyxLQUFLO1FBQ2pCLElBQUksSUFBSSxDQUFDLE9BQU8sRUFBRSxDQUFDO1lBQ2xCLE1BQU0sRUFBQyxNQUFNLEVBQUUsUUFBUSxFQUFDLEdBQUcsTUFBTSxJQUFJLENBQUMsVUFBVSxFQUFFLENBQUM7WUFDbkQsTUFBTSxFQUFFLEtBQUssQ0FBQyxJQUFJLENBQUMsYUFBYSxDQUFDLDRCQUE0QixRQUFRLEVBQUUsQ0FBQyxDQUFDLENBQUM7WUFDMUUsSUFBSSxDQUFDLE9BQU8sQ0FBQyxLQUFLLEVBQUUsQ0FBQztRQUN0QixDQUFDO0lBQ0YsQ0FBQztJQUVTLEtBQUssQ0FBQyxZQUFZLENBQUMsT0FBZSxFQUFFLEdBQVk7UUFDekQsTUFBTSxFQUFDLFFBQVEsRUFBRSxRQUFRLEVBQUMsR0FBRyxNQUFNLElBQUksQ0FBQyxVQUFVLEVBQUUsQ0FBQztRQUNyRCxJQUFJLFFBQVEsRUFBRSxDQUFDO1lBQ2QsT0FBTyxF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
import { ConfigLoader, type Loadable, type LoaderValue } from '@avanio/variable-util';
import type { ILoggerLike } from '@avanio/logger-like';
export interface DockerSecretsConfigLoaderOptions {
/** force file name to lower case */
fileLowerCase: boolean;
/** path to docker secrets, default is '/run/secrets' */
path: string;
/** set to false if need errors */
isSilent: boolean;
/** optional logger */
logger: ILoggerLike | undefined;
/** set to true to disable loader, default is false */
disabled: boolean;
}
/**
* Loader for docker secrets, reads secrets from the `/run/secrets` directory.
* @since v0.8.0
*/
export declare class DockerSecretsConfigLoader extends ConfigLoader<string | undefined, Partial<DockerSecretsConfigLoaderOptions>, DockerSecretsConfigLoaderOptions> {
readonly type = "docker-secrets";
private valuePromises;
protected defaultOptions: DockerSecretsConfigLoaderOptions;
constructor(options: Loadable<Partial<DockerSecretsConfigLoaderOptions>>);
protected handleLoader(lookupKey: string, overrideKey?: string): Promise<LoaderValue>;
private filePath;
}
"use strict";
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
var desc = Object.getOwnPropertyDescriptor(m, k);
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
desc = { enumerable: true, get: function() { return m[k]; } };
}
Object.defineProperty(o, k2, desc);
}) : (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
o[k2] = m[k];
}));
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
Object.defineProperty(o, "default", { enumerable: true, value: v });
}) : function(o, v) {
o["default"] = v;
});
var __importStar = (this && this.__importStar) || function (mod) {
if (mod && mod.__esModule) return mod;
var result = {};
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
__setModuleDefault(result, mod);
return result;
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.DockerSecretsConfigLoader = void 0;
const path = __importStar(require("path"));
const variable_util_1 = require("@avanio/variable-util");
const fs_1 = require("fs");
const promises_1 = require("fs/promises");
/**
* Loader for docker secrets, reads secrets from the `/run/secrets` directory.
* @since v0.8.0
*/
class DockerSecretsConfigLoader extends variable_util_1.ConfigLoader {
type = 'docker-secrets';
valuePromises = {};
defaultOptions = {
disabled: false,
fileLowerCase: false,
isSilent: true,
logger: undefined,
path: '/run/secrets',
};
constructor(options) {
super(options);
this.getLoader = this.getLoader.bind(this);
}
async handleLoader(lookupKey, overrideKey) {
const options = await this.getOptions();
if (options.disabled) {
return { type: this.type, result: undefined };
}
const targetKey = overrideKey || lookupKey;
const filePath = this.filePath(targetKey, options);
const valuePromise = this.valuePromises[targetKey];
const seen = !!valuePromise; // if valuePromise exists, it means we have seen this key before
if (!valuePromise) {
if (!(0, fs_1.existsSync)(filePath)) {
if (!options.isSilent) {
throw new variable_util_1.VariableLookupError(targetKey, `ConfigVariables[${this.type}]: ${lookupKey} from ${filePath} not found`);
}
options.logger?.debug(`ConfigVariables[${this.type}]: ${lookupKey} from ${filePath} not found`);
this.valuePromises[targetKey] = Promise.resolve(undefined);
}
else {
this.valuePromises[targetKey] = (0, promises_1.readFile)(filePath, 'utf8');
}
}
const value = await this.valuePromises[targetKey];
return { type: this.type, result: { path: filePath, value, seen } };
}
filePath(key, options) {
return path.join(path.resolve(options.path), options.fileLowerCase ? key.toLowerCase() : key);
}
}
exports.DockerSecretsConfigLoader = DockerSecretsConfigLoader;
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiRG9ja2VyU2VjcmV0c0NvbmZpZ0xvYWRlci5qcyIsInNvdXJjZVJvb3QiOiIuL3NyYy8iLCJzb3VyY2VzIjpbIkRvY2tlclNlY3JldHNDb25maWdMb2FkZXIudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7QUFBQSwyQ0FBNkI7QUFDN0IseURBQXlHO0FBQ3pHLDJCQUE4QjtBQUU5QiwwQ0FBcUM7QUFlckM7OztHQUdHO0FBQ0gsTUFBYSx5QkFBMEIsU0FBUSw0QkFBNkc7SUFDM0ksSUFBSSxHQUFHLGdCQUFnQixDQUFDO0lBQ2hDLGFBQWEsR0FBNEQsRUFBRSxDQUFDO0lBQzFFLGNBQWMsR0FBcUM7UUFDNUQsUUFBUSxFQUFFLEtBQUs7UUFDZixhQUFhLEVBQUUsS0FBSztRQUNwQixRQUFRLEVBQUUsSUFBSTtRQUNkLE1BQU0sRUFBRSxTQUFTO1FBQ2pCLElBQUksRUFBRSxjQUFjO0tBQ3BCLENBQUM7SUFFRixZQUFtQixPQUE0RDtRQUM5RSxLQUFLLENBQUMsT0FBTyxDQUFDLENBQUM7UUFDZixJQUFJLENBQUMsU0FBUyxHQUFHLElBQUksQ0FBQyxTQUFTLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQyxDQUFDO0lBQzVDLENBQUM7SUFFUyxLQUFLLENBQUMsWUFBWSxDQUFDLFNBQWlCLEVBQUUsV0FBb0I7UUFDbkUsTUFBTSxPQUFPLEdBQUcsTUFBTSxJQUFJLENBQUMsVUFBVSxFQUFFLENBQUM7UUFDeEMsSUFBSSxPQUFPLENBQUMsUUFBUSxFQUFFLENBQUM7WUFDdEIsT0FBTyxFQUFDLElBQUksRUFBRSxJQUFJLENBQUMsSUFBSSxFQUFFLE1BQU0sRUFBRSxTQUFTLEVBQUMsQ0FBQztRQUM3QyxDQUFDO1FBQ0QsTUFBTSxTQUFTLEdBQUcsV0FBVyxJQUFJLFNBQVMsQ0FBQztRQUMzQyxNQUFNLFFBQVEsR0FBRyxJQUFJLENBQUMsUUFBUSxDQUFDLFNBQVMsRUFBRSxPQUFPLENBQUMsQ0FBQztRQUNuRCxNQUFNLFlBQVksR0FBRyxJQUFJLENBQUMsYUFBYSxDQUFDLFNBQVMsQ0FBQyxDQUFDO1FBQ25ELE1BQU0sSUFBSSxHQUFHLENBQUMsQ0FBQyxZQUFZLENBQUMsQ0FBQyxnRUFBZ0U7UUFDN0YsSUFBSSxDQUFDLFlBQVksRUFBRSxDQUFDO1lBQ25CLElBQUksQ0FBQyxJQUFBLGVBQVUsRUFBQyxRQUFRLENBQUMsRUFBRSxDQUFDO2dCQUMzQixJQUFJLENBQUMsT0FBTyxDQUFDLFFBQVEsRUFBRSxDQUFDO29CQUN2QixNQUFNLElBQUksbUNBQW1CLENBQUMsU0FBUyxFQUFFLG1CQUFtQixJQUFJLENBQUMsSUFBSSxNQUFNLFNBQVMsU0FBUyxRQUFRLFlBQVksQ0FBQyxDQUFDO2dCQUNwSCxDQUFDO2dCQUNELE9BQU8sQ0FBQyxNQUFNLEVBQUUsS0FBSyxDQUFDLG1CQUFtQixJQUFJLENBQUMsSUFBSSxNQUFNLFNBQVMsU0FBUyxRQUFRLFlBQVksQ0FBQyxDQUFDO2dCQUNoRyxJQUFJLENBQUMsYUFBYSxDQUFDLFNBQVMsQ0FBQyxHQUFHLE9BQU8sQ0FBQyxPQUFPLENBQUMsU0FBUyxDQUFDLENBQUM7WUFDNUQsQ0FBQztpQkFBTSxDQUFDO2dCQUNQLElBQUksQ0FBQyxhQUFhLENBQUMsU0FBUyxDQUFDLEdBQUcsSUFBQSxtQkFBUSxFQUFDLFFBQVEsRUFBRSxNQUFNLENBQUMsQ0FBQztZQUM1RCxDQUFDO1FBQ0YsQ0FBQztRQUNELE1BQU0sS0FBSyxHQUFHLE1BQU0sSUFBSSxDQUFDLGFBQWEsQ0FBQyxTQUFTLENBQUMsQ0FBQztRQUNsRCxPQUFPLEVBQUMsSUFBSSxFQUFFLElBQUksQ0FBQyxJQUFJLEVBQUUsTUFBTSxFQUFFLEVBQUMsSUFBSSxFQUFFLFFBQVEsRUFBRSxLQUFLLEVBQUUsSUFBSSxFQUFDLEVBQUMsQ0FBQztJQUNqRSxDQUFDO0lBRU8sUUFBUSxDQUFDLEdBQVcsRUFBRSxPQUF5QztRQUN0RSxPQUFPLElBQUksQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLE9BQU8sQ0FBQyxPQUFPLENBQUMsSUFBSSxDQUFDLEVBQUUsT0FBTyxDQUFDLGFBQWEsQ0FBQyxDQUFDLENBQUMsR0FBRyxDQUFDLFdBQVcsRUFBRSxDQUFDLENBQUMsQ0FBQyxHQUFHLENBQUMsQ0FBQztJQUMvRixDQUFDO0NBQ0Q7QUEzQ0QsOERBMkNDIn0=
import { AbstractFileRecordLoader, type AbstractFileRecordLoaderOptions } from './AbstractFileRecordLoader';
/**
* Loader for dotenv files, using the `dotenv` packages parser.
* @since v0.6.1
*/
export declare class DotEnvLoader extends AbstractFileRecordLoader {
readonly type = "dotenv";
protected defaultOptions: AbstractFileRecordLoaderOptions<'env'>;
protected handleParse(rawData: Buffer): Record<string, string | undefined>;
}
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.DotEnvLoader = void 0;
const AbstractFileRecordLoader_1 = require("./AbstractFileRecordLoader");
const dotenv_1 = require("dotenv");
/**
* Loader for dotenv files, using the `dotenv` packages parser.
* @since v0.6.1
*/
class DotEnvLoader extends AbstractFileRecordLoader_1.AbstractFileRecordLoader {
type = 'dotenv';
defaultOptions = {
disabled: false,
fileName: '.env',
fileType: 'env',
isSilent: true,
logger: undefined,
validate: undefined,
watch: false,
};
handleParse(rawData) {
return (0, dotenv_1.parse)(rawData);
}
}
exports.DotEnvLoader = DotEnvLoader;
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiRG90RW52TG9hZGVyLmpzIiwic291cmNlUm9vdCI6Ii4vc3JjLyIsInNvdXJjZXMiOlsiRG90RW52TG9hZGVyLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7OztBQUFBLHlFQUEwRztBQUMxRyxtQ0FBNkI7QUFFN0I7OztHQUdHO0FBQ0gsTUFBYSxZQUFhLFNBQVEsbURBQXdCO0lBQ3pDLElBQUksR0FBRyxRQUFRLENBQUM7SUFDdEIsY0FBYyxHQUEyQztRQUNsRSxRQUFRLEVBQUUsS0FBSztRQUNmLFFBQVEsRUFBRSxNQUFNO1FBQ2hCLFFBQVEsRUFBRSxLQUFLO1FBQ2YsUUFBUSxFQUFFLElBQUk7UUFDZCxNQUFNLEVBQUUsU0FBUztRQUNqQixRQUFRLEVBQUUsU0FBUztRQUNuQixLQUFLLEVBQUUsS0FBSztLQUNaLENBQUM7SUFFUSxXQUFXLENBQUMsT0FBZTtRQUNwQyxPQUFPLElBQUEsY0FBSyxFQUFDLE9BQU8sQ0FBQyxDQUFDO0lBQ3ZCLENBQUM7Q0FDRDtBQWZELG9DQWVDIn0=
export declare function getError(error: unknown): Error;
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.getError = getError;
function getError(error) {
if (error instanceof Error) {
return error;
}
if (typeof error === 'string') {
return new Error(error);
}
return new Error(`Unknown error: ${JSON.stringify(error)}`);
}
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZXJyb3JVdGlsLmpzIiwic291cmNlUm9vdCI6Ii4vc3JjLyIsInNvdXJjZXMiOlsiZXJyb3JVdGlsLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7O0FBQUEsNEJBUUM7QUFSRCxTQUFnQixRQUFRLENBQUMsS0FBYztJQUN0QyxJQUFJLEtBQUssWUFBWSxLQUFLLEVBQUUsQ0FBQztRQUM1QixPQUFPLEtBQUssQ0FBQztJQUNkLENBQUM7SUFDRCxJQUFJLE9BQU8sS0FBSyxLQUFLLFFBQVEsRUFBRSxDQUFDO1FBQy9CLE9BQU8sSUFBSSxLQUFLLENBQUMsS0FBSyxDQUFDLENBQUM7SUFDekIsQ0FBQztJQUNELE9BQU8sSUFBSSxLQUFLLENBQUMsa0JBQWtCLElBQUksQ0FBQyxTQUFTLENBQUMsS0FBSyxDQUFDLEVBQUUsQ0FBQyxDQUFDO0FBQzdELENBQUMifQ==
import { AbstractFileRecordLoader, type AbstractFileRecordLoaderOptions } from './AbstractFileRecordLoader';
/**
* A file-based configuration loader that reads a JSON file.
* @since v0.9.1
*/
export declare class FileConfigLoader extends AbstractFileRecordLoader<AbstractFileRecordLoaderOptions<'json'>> {
readonly type = "file";
protected defaultOptions: AbstractFileRecordLoaderOptions<'json'>;
protected handleParse(rawData: Buffer): Record<string, string | undefined>;
}
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.FileConfigLoader = void 0;
const AbstractFileRecordLoader_1 = require("./AbstractFileRecordLoader");
/**
* A file-based configuration loader that reads a JSON file.
* @since v0.9.1
*/
class FileConfigLoader extends AbstractFileRecordLoader_1.AbstractFileRecordLoader {
type = 'file';
defaultOptions = {
disabled: false,
fileName: 'config.json',
fileType: 'json',
isSilent: true,
logger: undefined,
validate: undefined,
watch: false,
};
handleParse(rawData) {
return JSON.parse(rawData.toString());
}
}
exports.FileConfigLoader = FileConfigLoader;
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiRmlsZUNvbmZpZ0xvYWRlci5qcyIsInNvdXJjZVJvb3QiOiIuL3NyYy8iLCJzb3VyY2VzIjpbIkZpbGVDb25maWdMb2FkZXIudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7O0FBQUEseUVBQTBHO0FBRTFHOzs7R0FHRztBQUNILE1BQWEsZ0JBQWlCLFNBQVEsbURBQWlFO0lBQ3RGLElBQUksR0FBRyxNQUFNLENBQUM7SUFDcEIsY0FBYyxHQUE0QztRQUNuRSxRQUFRLEVBQUUsS0FBSztRQUNmLFFBQVEsRUFBRSxhQUFhO1FBQ3ZCLFFBQVEsRUFBRSxNQUFNO1FBQ2hCLFFBQVEsRUFBRSxJQUFJO1FBQ2QsTUFBTSxFQUFFLFNBQVM7UUFDakIsUUFBUSxFQUFFLFNBQVM7UUFDbkIsS0FBSyxFQUFFLEtBQUs7S0FDWixDQUFDO0lBRVEsV0FBVyxDQUFDLE9BQWU7UUFDcEMsT0FBTyxJQUFJLENBQUMsS0FBSyxDQUFDLE9BQU8sQ0FBQyxRQUFRLEVBQUUsQ0FBdUMsQ0FBQztJQUM3RSxDQUFDO0NBQ0Q7QUFmRCw0Q0FlQyJ9