0
# Core Lifecycle Management
1
2
Core lifecycle management for CLI tool execution, handling the complete flow from initialization through environment preparation to final execution with automatic configuration discovery and process management.
3
4
## Capabilities
5
6
### Liftoff Constructor
7
8
Creates a new Liftoff instance configured for launching CLI applications with specified options for configuration discovery, module resolution, and process management.
9
10
```javascript { .api }
11
/**
12
* Creates a new Liftoff instance for launching CLI applications
13
* @param opts - Configuration options for the CLI launcher
14
*/
15
function Liftoff(opts: LiftoffOptions): Liftoff;
16
17
interface LiftoffOptions {
18
/** Name of the CLI tool (automatically sets processTitle, moduleName, configName if not specified) */
19
name?: string;
20
/** Title to set for the process (required if name not provided) */
21
processTitle?: string;
22
/** Name of the local module to find and require (required if name not provided) */
23
moduleName?: string;
24
/** Base name of configuration files to search for (required if name not provided) */
25
configName?: string;
26
/** File extensions and their corresponding loader modules */
27
extensions?: { [ext: string]: string | null };
28
/** V8 flags to apply during process respawn */
29
v8flags?: string[] | ((callback: (err: Error | null, flags?: string[]) => void) => void);
30
/** Function to handle shell completions */
31
completions?: (type: string) => void;
32
/** Array of configuration file search specifications */
33
configFiles?: ConfigFileSpec[];
34
/** Additional search paths for configuration discovery */
35
searchPaths?: string[];
36
}
37
38
interface ConfigFileSpec {
39
/** Base name of the config file to search for */
40
name?: string;
41
/** Path to search in (required) */
42
path: string;
43
/** File extensions to try when searching */
44
extensions?: string[] | { [ext: string]: string | null };
45
/** Base directory for resolving relative paths */
46
cwd?: string;
47
/** Whether to search up the directory tree */
48
findUp?: boolean;
49
}
50
```
51
52
**Usage Examples:**
53
54
```javascript
55
const Liftoff = require('liftoff');
56
57
// Simple configuration using name sugar
58
const MyApp = new Liftoff({
59
name: 'myapp' // Sets processTitle, moduleName, and configName automatically
60
});
61
62
// Advanced configuration with custom options
63
const AdvancedApp = new Liftoff({
64
processTitle: 'my-advanced-cli',
65
moduleName: 'my-advanced-cli',
66
configName: 'advancedfile',
67
extensions: {
68
'.js': null,
69
'.json': null,
70
'.coffee': 'coffee-script/register',
71
'.ts': 'ts-node/register'
72
},
73
v8flags: ['--harmony', '--experimental-modules'],
74
configFiles: [
75
{ name: '.myapprc', path: '~' },
76
{ name: 'myappfile', path: '.', findUp: true }
77
]
78
});
79
```
80
81
### Prepare Method
82
83
Prepares the execution environment by building the environment object and invoking the callback with the calculated environment, setting the process title and context.
84
85
```javascript { .api }
86
/**
87
* Prepares the execution environment and invokes callback
88
* @param opts - Options for environment building
89
* @param callback - Function called with prepared environment
90
*/
91
prepare(opts: EnvironmentOptions, callback: (env: Environment) => void): void;
92
93
interface EnvironmentOptions {
94
/** Override current working directory */
95
cwd?: string;
96
/** Explicit path to configuration file (skip discovery) */
97
configPath?: string;
98
/** Modules to preload before execution */
99
preload?: string | string[];
100
/** Completion data for shell completions */
101
completion?: any;
102
}
103
```
104
105
**Usage Examples:**
106
107
```javascript
108
const MyApp = new Liftoff({ name: 'myapp' });
109
110
// Basic preparation
111
MyApp.prepare({}, function(env) {
112
console.log('Environment prepared:', env);
113
// env contains cwd, configPath, modulePath, etc.
114
});
115
116
// Preparation with options
117
MyApp.prepare({
118
cwd: './my-project',
119
preload: ['babel-register'],
120
configPath: './custom-config.js'
121
}, function(env) {
122
// Continue with execution
123
MyApp.execute(env, function(env, argv) {
124
console.log('Application started');
125
});
126
});
127
```
128
129
### Execute Method
130
131
Starts the application based on the prepared environment, handling v8 flag detection, process respawning if needed, and module preloading before invoking the final callback.
132
133
```javascript { .api }
134
/**
135
* Execute application with prepared environment
136
* @param env - Environment object from prepare()
137
* @param callback - Function called after execution setup (not called if completion mode)
138
* @note If env.completion is truthy and completions function is defined, executes completion mode instead
139
*/
140
execute(env: Environment, callback: (env: Environment, argv: string[]) => void): void;
141
142
/**
143
* Execute application with forced flags
144
* @param env - Environment object from prepare()
145
* @param forcedFlags - Additional flags to force process respawn
146
* @param callback - Function called after execution setup (not called if completion mode)
147
* @note If env.completion is truthy and completions function is defined, executes completion mode instead
148
*/
149
execute(env: Environment, forcedFlags: string[], callback: (env: Environment, argv: string[]) => void): void;
150
```
151
152
**Usage Examples:**
153
154
```javascript
155
const MyApp = new Liftoff({ name: 'myapp' });
156
157
MyApp.prepare({}, function(env) {
158
// Basic execution
159
MyApp.execute(env, function(env, argv) {
160
console.log('CLI arguments:', argv);
161
console.log('Config path:', env.configPath);
162
console.log('Module path:', env.modulePath);
163
164
// Your CLI application logic here
165
if (env.configPath) {
166
const config = require(env.configPath);
167
console.log('Loaded config:', config);
168
}
169
});
170
});
171
172
// Execution with forced flags
173
MyApp.prepare({}, function(env) {
174
MyApp.execute(env, ['--trace-deprecation'], function(env, argv) {
175
// Application runs with additional --trace-deprecation flag
176
console.log('Running with forced flags');
177
});
178
});
179
```
180
181
### Complete Lifecycle Example
182
183
```javascript
184
const Liftoff = require('liftoff');
185
const path = require('path');
186
187
// Create CLI tool launcher
188
const MyTool = new Liftoff({
189
name: 'mytool',
190
extensions: {
191
'.js': null,
192
'.json': null,
193
'.coffee': 'coffee-script/register'
194
},
195
v8flags: ['--harmony']
196
});
197
198
// Set up event listeners for debugging
199
MyTool.on('preload:before', function(name) {
200
console.log('Loading module:', name);
201
});
202
203
MyTool.on('preload:success', function(name, module) {
204
console.log('Successfully loaded:', name);
205
});
206
207
MyTool.on('respawn', function(flags, child) {
208
console.log('Respawned with flags:', flags);
209
console.log('Child PID:', child.pid);
210
});
211
212
// Parse command line arguments
213
const argv = require('minimist')(process.argv.slice(2));
214
215
// Complete lifecycle
216
MyTool.prepare({
217
cwd: argv.cwd,
218
configPath: argv.mytoolfile,
219
preload: argv.preload
220
}, function(env) {
221
// Environment is prepared, now execute
222
MyTool.execute(env, function(env, argv) {
223
// Main application logic
224
console.log('MyTool started successfully!');
225
console.log('Working directory:', env.cwd);
226
console.log('Config file:', env.configPath || 'none found');
227
console.log('Local module:', env.modulePath || 'none found');
228
229
// Load configuration if available
230
if (env.configPath) {
231
try {
232
const config = require(env.configPath);
233
console.log('Configuration loaded:', config);
234
} catch (e) {
235
console.error('Failed to load config:', e.message);
236
}
237
}
238
239
// Your CLI tool implementation here
240
runMyTool(env, argv);
241
});
242
});
243
244
function runMyTool(env, argv) {
245
// Implementation of your CLI tool
246
console.log('Running with arguments:', argv);
247
}
248
```