Launch your command line tool with ease by handling configuration discovery, local module resolution, and process management.
—
Pending
Does it follow best practices?
Impact
Pending
No eval scenarios have been run
Pending
The risk profile of this skill
Environment building functionality that discovers configuration files, resolves module paths, and prepares the complete runtime context with all necessary metadata for CLI tool execution.
Builds the execution environment by discovering configuration files, resolving local module paths, and preparing all runtime metadata needed for CLI tool execution.
/**
* Builds the execution environment with configuration and module resolution
* @param opts - Options for environment building
* @returns Environment object with discovered paths and configuration
*/
buildEnvironment(opts?: EnvironmentOptions): Environment;
interface EnvironmentOptions {
/** Override current working directory for this execution */
cwd?: string;
/** Explicit path to configuration file (skips discovery) */
configPath?: string;
/** Modules to preload before execution (string or array) */
preload?: string | string[];
/** Completion data for shell completions */
completion?: any;
}
interface Environment {
/** Current working directory resolved for this execution */
cwd: string;
/** Array of module names that will be preloaded */
preload: string[];
/** Regex or array of config file names that were searched for */
configNameSearch: RegExp | string[];
/** Full absolute path to found configuration file */
configPath: string | null;
/** Directory containing the configuration file */
configBase: string | null;
/** Full absolute path to the local module */
modulePath: string | null;
/** Contents of the local module's package.json */
modulePackage: object;
/** Array of found configuration file paths (null for not found) */
configFiles: (string | null)[];
/** Array of loaded configuration objects in same order as configFiles */
config: object[];
}Usage Examples:
const Liftoff = require('liftoff');
const MyApp = new Liftoff({
name: 'myapp',
configFiles: [
{ name: 'myappfile', path: '.', findUp: true },
{ name: '.myapprc', path: '~' }
],
extensions: {
'.js': null,
'.json': null,
'.yaml': 'js-yaml-loader'
}
});
// Build environment with defaults
const env = MyApp.buildEnvironment();
console.log('Current directory:', env.cwd);
console.log('Config found at:', env.configPath);
console.log('Local module at:', env.modulePath);
// Build environment with custom options
const customEnv = MyApp.buildEnvironment({
cwd: './my-project',
preload: ['babel-register', 'source-map-support/register'],
configPath: './custom-config.js'
});
console.log('Custom environment:', customEnv);The environment building process automatically discovers configuration files based on the configured search patterns and file extensions.
Configuration File Search Process:
searchPaths from constructor options, with cwd added firstconfigName + extensionsConfiguration Loading Process:
extends properties for configuration inheritance// Example of discovered configuration structure
const env = MyApp.buildEnvironment();
// env.configFiles might contain:
// [
// '/path/to/project/myappfile.js', // Primary config
// '/home/user/.myapprc.json', // User config
// null // Config not found
// ]
// env.config contains loaded config objects:
// [
// { setting: 'value', extends: './base.js' }, // Loaded and processed
// { userSetting: 'userValue' }, // User config
// {} // Empty for missing config
// ]The environment building process locates and resolves local modules that correspond to the CLI tool, enabling version-specific execution.
Module Resolution Process:
configBase (config file directory) or cwd as starting pointresolve.sync() to find the local modulepackage.json// Example module resolution results
const env = MyApp.buildEnvironment();
console.log(env.modulePath); // '/project/node_modules/myapp/index.js'
console.log(env.modulePackage); // Contents of myapp's package.json
// {
// "name": "myapp",
// "version": "2.1.0",
// "main": "index.js",
// "dependencies": { ... }
// }Determines the appropriate working directory for CLI tool execution based on configuration file location and explicit options.
Working Directory Resolution Rules:
opts.cwd provided, use as-is for config search but preserve for executionprocess.cwd() if no config found and no explicit CWDconst MyApp = new Liftoff({ name: 'myapp' });
// Working directory follows config file
const env1 = MyApp.buildEnvironment();
// If config found at /project/subdir/myappfile.js
// Then env1.cwd === '/project/subdir'
// Explicit working directory
const env2 = MyApp.buildEnvironment({ cwd: '/custom/path' });
// env2.cwd === '/custom/path' (absolute)
// Config search limited to /custom/path only
// Relative working directory
const env3 = MyApp.buildEnvironment({ cwd: './relative' });
// env3.cwd === path.resolve(process.cwd(), './relative')Manages the list of modules that should be preloaded before CLI tool execution, combining options from multiple sources.
Preload Sources (in priority order):
buildEnvironment() optionspreload propertyPreload Processing:
const MyApp = new Liftoff({
name: 'myapp',
configFiles: [{ name: 'myappfile', path: '.' }]
});
// Config file contains: { preload: ['coffee-script/register'] }
const env = MyApp.buildEnvironment({
preload: ['babel-register', 'source-map-support/register']
});
// env.preload will be:
// ['babel-register', 'source-map-support/register', 'coffee-script/register']Environment building includes comprehensive error handling for common failure scenarios while maintaining graceful degradation.
Handled Error Scenarios:
null for config paths when files not foundnull for module paths when local module not foundconst MyApp = new Liftoff({ name: 'myapp' });
try {
const env = MyApp.buildEnvironment();
// Check for successful discoveries
if (env.configPath) {
console.log('Config loaded from:', env.configPath);
} else {
console.log('No configuration file found');
}
if (env.modulePath) {
console.log('Local module found at:', env.modulePath);
} else {
console.log('No local module found, using global');
}
} catch (error) {
if (error.message.includes('circular extend')) {
console.error('Configuration has circular inheritance');
} else if (error.message.includes('Unable to locate')) {
console.error('Configuration extends missing file');
} else {
console.error('Environment building failed:', error.message);
}
}