Spaces:
Running
Running
; | |
Object.defineProperty(exports, "__esModule", { value: true }); | |
exports.lilconfigSync = exports.lilconfig = exports.defaultLoaders = void 0; | |
const path = require("path"); | |
const fs = require("fs"); | |
const os = require("os"); | |
const fsReadFileAsync = fs.promises.readFile; | |
function getDefaultSearchPlaces(name) { | |
return [ | |
'package.json', | |
`.${name}rc.json`, | |
`.${name}rc.js`, | |
`${name}.config.js`, | |
`.${name}rc.cjs`, | |
`${name}.config.cjs`, | |
]; | |
} | |
function getSearchPaths(startDir, stopDir) { | |
return startDir | |
.split(path.sep) | |
.reduceRight((acc, _, ind, arr) => { | |
const currentPath = arr.slice(0, ind + 1).join(path.sep); | |
if (!acc.passedStopDir) | |
acc.searchPlaces.push(currentPath || path.sep); | |
if (currentPath === stopDir) | |
acc.passedStopDir = true; | |
return acc; | |
}, { searchPlaces: [], passedStopDir: false }).searchPlaces; | |
} | |
exports.defaultLoaders = Object.freeze({ | |
'.js': require, | |
'.json': require, | |
'.cjs': require, | |
noExt(_, content) { | |
return JSON.parse(content); | |
}, | |
}); | |
function getExtDesc(ext) { | |
return ext === 'noExt' ? 'files without extensions' : `extension "${ext}"`; | |
} | |
function getOptions(name, options = {}) { | |
const conf = { | |
stopDir: os.homedir(), | |
searchPlaces: getDefaultSearchPlaces(name), | |
ignoreEmptySearchPlaces: true, | |
transform: (x) => x, | |
packageProp: [name], | |
...options, | |
loaders: { ...exports.defaultLoaders, ...options.loaders }, | |
}; | |
conf.searchPlaces.forEach(place => { | |
const key = path.extname(place) || 'noExt'; | |
const loader = conf.loaders[key]; | |
if (!loader) { | |
throw new Error(`No loader specified for ${getExtDesc(key)}, so searchPlaces item "${place}" is invalid`); | |
} | |
if (typeof loader !== 'function') { | |
throw new Error(`loader for ${getExtDesc(key)} is not a function (type provided: "${typeof loader}"), so searchPlaces item "${place}" is invalid`); | |
} | |
}); | |
return conf; | |
} | |
function getPackageProp(props, obj) { | |
if (typeof props === 'string' && props in obj) | |
return obj[props]; | |
return ((Array.isArray(props) ? props : props.split('.')).reduce((acc, prop) => (acc === undefined ? acc : acc[prop]), obj) || null); | |
} | |
function getSearchItems(searchPlaces, searchPaths) { | |
return searchPaths.reduce((acc, searchPath) => { | |
searchPlaces.forEach(fileName => acc.push({ | |
fileName, | |
filepath: path.join(searchPath, fileName), | |
loaderKey: path.extname(fileName) || 'noExt', | |
})); | |
return acc; | |
}, []); | |
} | |
function validateFilePath(filepath) { | |
if (!filepath) | |
throw new Error('load must pass a non-empty string'); | |
} | |
function validateLoader(loader, ext) { | |
if (!loader) | |
throw new Error(`No loader specified for extension "${ext}"`); | |
if (typeof loader !== 'function') | |
throw new Error('loader is not a function'); | |
} | |
function lilconfig(name, options) { | |
const { ignoreEmptySearchPlaces, loaders, packageProp, searchPlaces, stopDir, transform, } = getOptions(name, options); | |
return { | |
async search(searchFrom = process.cwd()) { | |
const searchPaths = getSearchPaths(searchFrom, stopDir); | |
const result = { | |
config: null, | |
filepath: '', | |
}; | |
const searchItems = getSearchItems(searchPlaces, searchPaths); | |
for (const { fileName, filepath, loaderKey } of searchItems) { | |
try { | |
await fs.promises.access(filepath); | |
} | |
catch (_a) { | |
continue; | |
} | |
const content = String(await fsReadFileAsync(filepath)); | |
const loader = loaders[loaderKey]; | |
if (fileName === 'package.json') { | |
const pkg = await loader(filepath, content); | |
const maybeConfig = getPackageProp(packageProp, pkg); | |
if (maybeConfig != null) { | |
result.config = maybeConfig; | |
result.filepath = filepath; | |
break; | |
} | |
continue; | |
} | |
const isEmpty = content.trim() === ''; | |
if (isEmpty && ignoreEmptySearchPlaces) | |
continue; | |
if (isEmpty) { | |
result.isEmpty = true; | |
result.config = undefined; | |
} | |
else { | |
validateLoader(loader, loaderKey); | |
result.config = await loader(filepath, content); | |
} | |
result.filepath = filepath; | |
break; | |
} | |
if (result.filepath === '' && result.config === null) | |
return transform(null); | |
return transform(result); | |
}, | |
async load(filepath) { | |
validateFilePath(filepath); | |
const absPath = path.resolve(process.cwd(), filepath); | |
const { base, ext } = path.parse(absPath); | |
const loaderKey = ext || 'noExt'; | |
const loader = loaders[loaderKey]; | |
validateLoader(loader, loaderKey); | |
const content = String(await fsReadFileAsync(absPath)); | |
if (base === 'package.json') { | |
const pkg = await loader(absPath, content); | |
return transform({ | |
config: getPackageProp(packageProp, pkg), | |
filepath: absPath, | |
}); | |
} | |
const result = { | |
config: null, | |
filepath: absPath, | |
}; | |
const isEmpty = content.trim() === ''; | |
if (isEmpty && ignoreEmptySearchPlaces) | |
return transform({ | |
config: undefined, | |
filepath: absPath, | |
isEmpty: true, | |
}); | |
result.config = isEmpty | |
? undefined | |
: await loader(absPath, content); | |
return transform(isEmpty ? { ...result, isEmpty, config: undefined } : result); | |
}, | |
}; | |
} | |
exports.lilconfig = lilconfig; | |
function lilconfigSync(name, options) { | |
const { ignoreEmptySearchPlaces, loaders, packageProp, searchPlaces, stopDir, transform, } = getOptions(name, options); | |
return { | |
search(searchFrom = process.cwd()) { | |
const searchPaths = getSearchPaths(searchFrom, stopDir); | |
const result = { | |
config: null, | |
filepath: '', | |
}; | |
const searchItems = getSearchItems(searchPlaces, searchPaths); | |
for (const { fileName, filepath, loaderKey } of searchItems) { | |
try { | |
fs.accessSync(filepath); | |
} | |
catch (_a) { | |
continue; | |
} | |
const loader = loaders[loaderKey]; | |
const content = String(fs.readFileSync(filepath)); | |
if (fileName === 'package.json') { | |
const pkg = loader(filepath, content); | |
const maybeConfig = getPackageProp(packageProp, pkg); | |
if (maybeConfig != null) { | |
result.config = maybeConfig; | |
result.filepath = filepath; | |
break; | |
} | |
continue; | |
} | |
const isEmpty = content.trim() === ''; | |
if (isEmpty && ignoreEmptySearchPlaces) | |
continue; | |
if (isEmpty) { | |
result.isEmpty = true; | |
result.config = undefined; | |
} | |
else { | |
validateLoader(loader, loaderKey); | |
result.config = loader(filepath, content); | |
} | |
result.filepath = filepath; | |
break; | |
} | |
if (result.filepath === '' && result.config === null) | |
return transform(null); | |
return transform(result); | |
}, | |
load(filepath) { | |
validateFilePath(filepath); | |
const absPath = path.resolve(process.cwd(), filepath); | |
const { base, ext } = path.parse(absPath); | |
const loaderKey = ext || 'noExt'; | |
const loader = loaders[loaderKey]; | |
validateLoader(loader, loaderKey); | |
const content = String(fs.readFileSync(absPath)); | |
if (base === 'package.json') { | |
const pkg = loader(absPath, content); | |
return transform({ | |
config: getPackageProp(packageProp, pkg), | |
filepath: absPath, | |
}); | |
} | |
const result = { | |
config: null, | |
filepath: absPath, | |
}; | |
const isEmpty = content.trim() === ''; | |
if (isEmpty && ignoreEmptySearchPlaces) | |
return transform({ | |
filepath: absPath, | |
config: undefined, | |
isEmpty: true, | |
}); | |
result.config = isEmpty ? undefined : loader(absPath, content); | |
return transform(isEmpty ? { ...result, isEmpty, config: undefined } : result); | |
}, | |
}; | |
} | |
exports.lilconfigSync = lilconfigSync; | |