or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

configuration.mdcore-lifecycle.mdenvironment-building.mdevents.mdindex.md
tile.json

environment-building.mddocs/

0

# Environment Building

1

2

Environment building functionality that discovers configuration files, resolves module paths, and prepares the complete runtime context with all necessary metadata for CLI tool execution.

3

4

## Capabilities

5

6

### Build Environment Method

7

8

Builds the execution environment by discovering configuration files, resolving local module paths, and preparing all runtime metadata needed for CLI tool execution.

9

10

```javascript { .api }

11

/**

12

* Builds the execution environment with configuration and module resolution

13

* @param opts - Options for environment building

14

* @returns Environment object with discovered paths and configuration

15

*/

16

buildEnvironment(opts?: EnvironmentOptions): Environment;

17

18

interface EnvironmentOptions {

19

/** Override current working directory for this execution */

20

cwd?: string;

21

/** Explicit path to configuration file (skips discovery) */

22

configPath?: string;

23

/** Modules to preload before execution (string or array) */

24

preload?: string | string[];

25

/** Completion data for shell completions */

26

completion?: any;

27

}

28

29

interface Environment {

30

/** Current working directory resolved for this execution */

31

cwd: string;

32

/** Array of module names that will be preloaded */

33

preload: string[];

34

/** Regex or array of config file names that were searched for */

35

configNameSearch: RegExp | string[];

36

/** Full absolute path to found configuration file */

37

configPath: string | null;

38

/** Directory containing the configuration file */

39

configBase: string | null;

40

/** Full absolute path to the local module */

41

modulePath: string | null;

42

/** Contents of the local module's package.json */

43

modulePackage: object;

44

/** Array of found configuration file paths (null for not found) */

45

configFiles: (string | null)[];

46

/** Array of loaded configuration objects in same order as configFiles */

47

config: object[];

48

}

49

```

50

51

**Usage Examples:**

52

53

```javascript

54

const Liftoff = require('liftoff');

55

56

const MyApp = new Liftoff({

57

name: 'myapp',

58

configFiles: [

59

{ name: 'myappfile', path: '.', findUp: true },

60

{ name: '.myapprc', path: '~' }

61

],

62

extensions: {

63

'.js': null,

64

'.json': null,

65

'.yaml': 'js-yaml-loader'

66

}

67

});

68

69

// Build environment with defaults

70

const env = MyApp.buildEnvironment();

71

console.log('Current directory:', env.cwd);

72

console.log('Config found at:', env.configPath);

73

console.log('Local module at:', env.modulePath);

74

75

// Build environment with custom options

76

const customEnv = MyApp.buildEnvironment({

77

cwd: './my-project',

78

preload: ['babel-register', 'source-map-support/register'],

79

configPath: './custom-config.js'

80

});

81

82

console.log('Custom environment:', customEnv);

83

```

84

85

### Configuration Discovery

86

87

The environment building process automatically discovers configuration files based on the configured search patterns and file extensions.

88

89

**Configuration File Search Process:**

90

91

1. **Search Path Resolution**: Uses `searchPaths` from constructor options, with `cwd` added first

92

2. **File Name Generation**: Creates file name patterns from `configName` + `extensions`

93

3. **File System Search**: Searches each path for matching configuration files

94

4. **Path Resolution**: Resolves found files to absolute paths

95

5. **Loader Registration**: Registers appropriate loaders for found file extensions

96

97

**Configuration Loading Process:**

98

99

1. **File Reading**: Loads each found configuration file

100

2. **Extension Processing**: Applies registered loaders for custom extensions

101

3. **Inheritance Handling**: Processes `extends` properties for configuration inheritance

102

4. **Circular Detection**: Prevents infinite loops in configuration inheritance

103

5. **Merge Strategy**: Deep merges configurations with later configs taking precedence

104

105

```javascript

106

// Example of discovered configuration structure

107

const env = MyApp.buildEnvironment();

108

109

// env.configFiles might contain:

110

// [

111

// '/path/to/project/myappfile.js', // Primary config

112

// '/home/user/.myapprc.json', // User config

113

// null // Config not found

114

// ]

115

116

// env.config contains loaded config objects:

117

// [

118

// { setting: 'value', extends: './base.js' }, // Loaded and processed

119

// { userSetting: 'userValue' }, // User config

120

// {} // Empty for missing config

121

// ]

122

```

123

124

### Module Resolution

125

126

The environment building process locates and resolves local modules that correspond to the CLI tool, enabling version-specific execution.

127

128

**Module Resolution Process:**

129

130

1. **Base Directory**: Uses `configBase` (config file directory) or `cwd` as starting point

131

2. **Module Search**: Uses Node.js `resolve.sync()` to find the local module

132

3. **Package Discovery**: Locates and loads the module's `package.json`

133

4. **Path Resolution**: Resolves to absolute paths for module and package

134

5. **Development Mode**: Handles cases where config and module are in same directory (self-development)

135

136

```javascript

137

// Example module resolution results

138

const env = MyApp.buildEnvironment();

139

140

console.log(env.modulePath); // '/project/node_modules/myapp/index.js'

141

console.log(env.modulePackage); // Contents of myapp's package.json

142

// {

143

// "name": "myapp",

144

// "version": "2.1.0",

145

// "main": "index.js",

146

// "dependencies": { ... }

147

// }

148

```

149

150

### Working Directory Resolution

151

152

Determines the appropriate working directory for CLI tool execution based on configuration file location and explicit options.

153

154

**Working Directory Resolution Rules:**

155

156

1. **Explicit CWD**: If `opts.cwd` provided, use as-is for config search but preserve for execution

157

2. **Config-based CWD**: If config found and no explicit CWD, use config's directory

158

3. **Default CWD**: Use `process.cwd()` if no config found and no explicit CWD

159

4. **Search Paths**: When explicit CWD provided, only search in that directory

160

161

```javascript

162

const MyApp = new Liftoff({ name: 'myapp' });

163

164

// Working directory follows config file

165

const env1 = MyApp.buildEnvironment();

166

// If config found at /project/subdir/myappfile.js

167

// Then env1.cwd === '/project/subdir'

168

169

// Explicit working directory

170

const env2 = MyApp.buildEnvironment({ cwd: '/custom/path' });

171

// env2.cwd === '/custom/path' (absolute)

172

// Config search limited to /custom/path only

173

174

// Relative working directory

175

const env3 = MyApp.buildEnvironment({ cwd: './relative' });

176

// env3.cwd === path.resolve(process.cwd(), './relative')

177

```

178

179

### Preload Module Handling

180

181

Manages the list of modules that should be preloaded before CLI tool execution, combining options from multiple sources.

182

183

**Preload Sources (in priority order):**

184

185

1. **Environment Options**: Modules specified in `buildEnvironment()` options

186

2. **Configuration Files**: Modules specified in config file `preload` property

187

3. **Default**: Empty array if no preloads specified

188

189

**Preload Processing:**

190

191

- Converts string values to single-item arrays

192

- Concatenates arrays from different sources

193

- Filters for unique module names

194

- Validates that config-based preloads are strings or string arrays

195

196

```javascript

197

const MyApp = new Liftoff({

198

name: 'myapp',

199

configFiles: [{ name: 'myappfile', path: '.' }]

200

});

201

202

// Config file contains: { preload: ['coffee-script/register'] }

203

204

const env = MyApp.buildEnvironment({

205

preload: ['babel-register', 'source-map-support/register']

206

});

207

208

// env.preload will be:

209

// ['babel-register', 'source-map-support/register', 'coffee-script/register']

210

```

211

212

### Error Handling

213

214

Environment building includes comprehensive error handling for common failure scenarios while maintaining graceful degradation.

215

216

**Handled Error Scenarios:**

217

218

- **Missing Configuration**: Returns `null` for config paths when files not found

219

- **Module Resolution Failure**: Returns `null` for module paths when local module not found

220

- **Invalid Extensions**: Gracefully handles unregistered file extensions

221

- **Circular Extends**: Throws descriptive error for circular configuration inheritance

222

- **Invalid Config Files**: Throws error for malformed configuration files

223

- **Missing Extended Files**: Throws error with path information for missing extended configs

224

225

```javascript

226

const MyApp = new Liftoff({ name: 'myapp' });

227

228

try {

229

const env = MyApp.buildEnvironment();

230

231

// Check for successful discoveries

232

if (env.configPath) {

233

console.log('Config loaded from:', env.configPath);

234

} else {

235

console.log('No configuration file found');

236

}

237

238

if (env.modulePath) {

239

console.log('Local module found at:', env.modulePath);

240

} else {

241

console.log('No local module found, using global');

242

}

243

244

} catch (error) {

245

if (error.message.includes('circular extend')) {

246

console.error('Configuration has circular inheritance');

247

} else if (error.message.includes('Unable to locate')) {

248

console.error('Configuration extends missing file');

249

} else {

250

console.error('Environment building failed:', error.message);

251

}

252

}

253

```