or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

analysis.mdcli.mdconfiguration.mdindex.mdlogging.mdservice.mdtesting.mdtypes.md
tile.json

analysis.mddocs/

0

# Code Analysis

1

2

Ice.js provides powerful static analysis utilities for dependency scanning, import analysis, and export discovery in JavaScript/TypeScript projects. These tools enable build optimization, dependency management, and codebase understanding.

3

4

## Capabilities

5

6

### Import Analysis

7

8

Analyze module imports in source files with support for aliases and relative imports.

9

10

```typescript { .api }

11

/**

12

* Analyze module imports in source files

13

* @param files - Array of file paths to analyze

14

* @param options - Analysis configuration options

15

* @returns Promise resolving to Set of imported modules or false on error

16

*/

17

function analyzeImports(files: string[], options: AnalyzeOptions): Promise<Set<string> | false>;

18

19

interface AnalyzeOptions {

20

/** Number of parallel analysis operations (default: 10) */

21

parallel?: number;

22

/** Whether to analyze relative imports (default: false) */

23

analyzeRelativeImport?: boolean;

24

/** Module path aliases for import resolution */

25

alias?: Record<string, string>;

26

}

27

```

28

29

**Usage Examples:**

30

31

```typescript

32

import { analyzeImports } from "@ice/app/analyze";

33

34

// Basic import analysis

35

const sourceFiles = [

36

'src/index.ts',

37

'src/components/App.tsx',

38

'src/utils/helpers.ts'

39

];

40

41

const imports = await analyzeImports(sourceFiles, {

42

parallel: 5,

43

analyzeRelativeImport: true,

44

alias: {

45

'@': './src',

46

'@components': './src/components'

47

}

48

});

49

50

if (imports) {

51

console.log('Discovered imports:', Array.from(imports));

52

// Output: ['react', 'react-dom', 'lodash', './utils/constants', '@/components/Button']

53

}

54

55

// Advanced analysis with custom options

56

const advancedImports = await analyzeImports(['src/**/*.{ts,tsx}'], {

57

parallel: 20,

58

analyzeRelativeImport: false, // Skip relative imports

59

alias: {

60

'@': './src',

61

'@lib': './src/lib',

62

'@components': './src/components',

63

'@utils': './src/utils'

64

}

65

});

66

```

67

68

### Dependency Scanning

69

70

Scan entry points and discover all dependencies including dynamic imports and conditional requires.

71

72

```typescript { .api }

73

/**

74

* Scan entry points and discover dependencies

75

* @param entries - Array of entry point file paths

76

* @param options - Scan configuration options

77

* @returns Promise resolving to dependency scan data

78

*/

79

function scanImports(entries: string[], options?: ScanOptions): Promise<Record<string, DepScanData>>;

80

81

interface ScanOptions {

82

/** Project root directory */

83

rootDir?: string;

84

/** Module path aliases */

85

alias?: Record<string, string>;

86

/** Existing dependency imports to merge with */

87

depImports?: Record<string, DepScanData>;

88

/** ESBuild plugins for custom file processing */

89

plugins?: Plugin[];

90

/** Patterns to exclude from scanning */

91

exclude?: string[];

92

/** Files to ignore during scanning */

93

ignores?: string[];

94

}

95

96

interface DepScanData {

97

/** Imported module specifiers */

98

imports: Set<string>;

99

/** Dynamic import specifiers */

100

dynamicImports: Set<string>;

101

/** Export names from the module */

102

exports: Set<string>;

103

/** File dependencies */

104

deps: Set<string>;

105

/** Whether the module has side effects */

106

hasSideEffects: boolean;

107

}

108

```

109

110

**Usage Examples:**

111

112

```typescript

113

import { scanImports } from "@ice/app/analyze";

114

115

// Basic dependency scanning

116

const entryPoints = ['src/index.ts', 'src/main.tsx'];

117

118

const dependencies = await scanImports(entryPoints, {

119

rootDir: process.cwd(),

120

alias: {

121

'@': './src',

122

'@components': './src/components'

123

},

124

exclude: ['**/*.test.*', '**/*.spec.*'],

125

ignores: ['node_modules', 'dist']

126

});

127

128

// Process scan results

129

Object.entries(dependencies).forEach(([file, data]) => {

130

console.log(`File: ${file}`);

131

console.log(' Imports:', Array.from(data.imports));

132

console.log(' Dynamic imports:', Array.from(data.dynamicImports));

133

console.log(' Exports:', Array.from(data.exports));

134

console.log(' Has side effects:', data.hasSideEffects);

135

});

136

137

// Advanced scanning with custom plugins

138

import { esbuild } from '@ice/bundles';

139

140

const advancedDeps = await scanImports(['src/index.ts'], {

141

rootDir: '/path/to/project',

142

plugins: [

143

{

144

name: 'custom-loader',

145

setup(build) {

146

build.onLoad({ filter: /\.custom$/ }, (args) => {

147

// Custom file processing logic

148

});

149

}

150

}

151

],

152

exclude: ['**/*.md', '**/*.json']

153

});

154

```

155

156

### Export Analysis

157

158

Analyze file exports to understand module interfaces and public APIs.

159

160

```typescript { .api }

161

/**

162

* Get file export information

163

* @param options - File analysis options

164

* @returns Promise resolving to array of export names

165

*/

166

function getFileExports(options: FileExportOptions): Promise<string[]>;

167

168

interface FileExportOptions {

169

/** File path (relative or absolute) */

170

file: string;

171

/** Project root directory */

172

rootDir: string;

173

}

174

```

175

176

**Usage Examples:**

177

178

```typescript

179

import { getFileExports } from "@ice/app/analyze";

180

181

// Analyze exports from a specific file

182

const exports = await getFileExports({

183

file: 'src/utils/helpers.ts',

184

rootDir: process.cwd()

185

});

186

187

console.log('Exported functions:', exports);

188

// Output: ['formatDate', 'validateEmail', 'debounce', 'throttle']

189

190

// Analyze exports from multiple files

191

const files = [

192

'src/components/Button.tsx',

193

'src/components/Input.tsx',

194

'src/hooks/useLocalStorage.ts'

195

];

196

197

const allExports = await Promise.all(

198

files.map(file => getFileExports({

199

file,

200

rootDir: process.cwd()

201

}))

202

);

203

204

files.forEach((file, index) => {

205

console.log(`${file}: [${allExports[index].join(', ')}]`);

206

});

207

```

208

209

### Module Resolution

210

211

Resolve module IDs with alias support for import path resolution.

212

213

```typescript { .api }

214

/**

215

* Resolve module ID with alias support

216

* @param id - Module identifier to resolve

217

* @param alias - Alias configuration with empty values for exclusion

218

* @returns Resolved module path or false if excluded

219

*/

220

function resolveId(id: string, alias: AliasWithEmpty): string | false;

221

222

/**

223

* Get absolute import path with alias resolution

224

* @param id - Module identifier

225

* @param importer - File path of the importing module

226

* @param alias - Alias configuration

227

* @returns Resolved absolute import path

228

*/

229

function getImportPath(id: string, importer: string, alias: Alias): string;

230

231

type Alias = Record<string, string>;

232

type AliasWithEmpty = Record<string, string | false>;

233

```

234

235

**Usage Examples:**

236

237

```typescript

238

import { resolveId, getImportPath } from "@ice/app/analyze";

239

240

// Basic module resolution with aliases

241

const aliasConfig = {

242

'@': './src',

243

'@components': './src/components',

244

'@utils': './src/utils',

245

'excluded-module$': false // Exclude this module

246

};

247

248

// Resolve various import paths

249

console.log(resolveId('@/components/Button', aliasConfig));

250

// Output: './src/components/Button'

251

252

console.log(resolveId('@utils/helpers', aliasConfig));

253

// Output: './src/utils/helpers'

254

255

console.log(resolveId('excluded-module', aliasConfig));

256

// Output: false (excluded)

257

258

// Get absolute import paths

259

const absolutePath = getImportPath(

260

'@/components/Button',

261

'/project/src/pages/Home.tsx',

262

{

263

'@': './src',

264

'@components': './src/components'

265

}

266

);

267

console.log(absolutePath);

268

// Output: '/project/src/components/Button'

269

```

270

271

### Build Optimization Analysis

272

273

Use analysis results for build optimization and bundle splitting.

274

275

```typescript { .api }

276

/**

277

* Analyze codebase for build optimization opportunities

278

*/

279

interface OptimizationAnalysis {

280

/** Unused dependencies that can be removed */

281

unusedDependencies: string[];

282

/** Large dependencies that should be code-split */

283

largeDependencies: Array<{ name: string; size: number }>;

284

/** Circular dependencies that need resolution */

285

circularDependencies: string[][];

286

/** Barrel files that can be optimized */

287

barrelFiles: string[];

288

}

289

```

290

291

**Usage Examples:**

292

293

```typescript

294

import { analyzeImports, scanImports, getFileExports } from "@ice/app/analyze";

295

import fs from 'fs';

296

import path from 'path';

297

298

// Comprehensive analysis for optimization

299

async function analyzeForOptimization(rootDir: string): Promise<OptimizationAnalysis> {

300

// Get all source files

301

const sourceFiles = getAllSourceFiles(rootDir);

302

303

// Analyze imports

304

const imports = await analyzeImports(sourceFiles, {

305

parallel: 10,

306

analyzeRelativeImport: true,

307

alias: {

308

'@': './src'

309

}

310

});

311

312

// Scan dependencies

313

const deps = await scanImports(['src/index.ts'], {

314

rootDir,

315

exclude: ['**/*.test.*']

316

});

317

318

// Find optimization opportunities

319

const analysis: OptimizationAnalysis = {

320

unusedDependencies: findUnusedDependencies(imports, deps),

321

largeDependencies: findLargeDependencies(imports),

322

circularDependencies: findCircularDependencies(deps),

323

barrelFiles: findBarrelFiles(sourceFiles)

324

};

325

326

return analysis;

327

}

328

329

function getAllSourceFiles(rootDir: string): string[] {

330

// Implementation to recursively find all source files

331

// This is a simplified example

332

const glob = require('fast-glob');

333

return glob.sync('src/**/*.{ts,tsx,js,jsx}', { cwd: rootDir });

334

}

335

336

function findUnusedDependencies(imports: Set<string>, deps: any): string[] {

337

// Logic to identify unused dependencies

338

return [];

339

}

340

341

function findLargeDependencies(imports: Set<string>): Array<{ name: string; size: number }> {

342

// Logic to identify large dependencies

343

return [];

344

}

345

346

function findCircularDependencies(deps: any): string[][] {

347

// Logic to detect circular dependencies

348

return [];

349

}

350

351

function findBarrelFiles(files: string[]): string[] {

352

// Logic to identify barrel files (index.ts files that only re-export)

353

return files.filter(file => path.basename(file) === 'index.ts');

354

}

355

```

356

357

### Integration with Build Pipeline

358

359

Integrate analysis tools with custom build pipelines.

360

361

```typescript { .api }

362

/**

363

* Integration example with build pipeline

364

*/

365

interface BuildAnalysisOptions {

366

rootDir: string;

367

entryPoints: string[];

368

alias: Record<string, string>;

369

outputPath: string;

370

}

371

```

372

373

**Usage Examples:**

374

375

```typescript

376

import { analyzeImports, scanImports } from "@ice/app/analyze";

377

import fs from 'fs-extra';

378

379

class BuildAnalyzer {

380

private options: BuildAnalysisOptions;

381

382

constructor(options: BuildAnalysisOptions) {

383

this.options = options;

384

}

385

386

async analyze(): Promise<void> {

387

const { rootDir, entryPoints, alias, outputPath } = this.options;

388

389

// Perform comprehensive analysis

390

const [imports, dependencies] = await Promise.all([

391

this.analyzeAllImports(),

392

this.scanAllDependencies()

393

]);

394

395

// Generate analysis report

396

const report = {

397

timestamp: new Date().toISOString(),

398

rootDir,

399

entryPoints,

400

imports: Array.from(imports || []),

401

dependencies: this.processDependencies(dependencies),

402

statistics: this.calculateStatistics(imports, dependencies)

403

};

404

405

// Save report

406

await fs.writeJson(path.join(outputPath, 'analysis-report.json'), report, {

407

spaces: 2

408

});

409

410

console.log(`Analysis complete. Report saved to ${outputPath}/analysis-report.json`);

411

}

412

413

private async analyzeAllImports(): Promise<Set<string> | false> {

414

const sourceFiles = await this.getAllSourceFiles();

415

416

return analyzeImports(sourceFiles, {

417

parallel: 15,

418

analyzeRelativeImport: true,

419

alias: this.options.alias

420

});

421

}

422

423

private async scanAllDependencies(): Promise<Record<string, DepScanData>> {

424

return scanImports(this.options.entryPoints, {

425

rootDir: this.options.rootDir,

426

alias: this.options.alias,

427

exclude: ['**/*.test.*', '**/*.spec.*', '**/*.stories.*']

428

});

429

}

430

431

private async getAllSourceFiles(): Promise<string[]> {

432

const glob = require('fast-glob');

433

return glob.sync('src/**/*.{ts,tsx,js,jsx}', {

434

cwd: this.options.rootDir

435

});

436

}

437

438

private processDependencies(deps: Record<string, DepScanData>) {

439

return Object.entries(deps).map(([file, data]) => ({

440

file,

441

imports: Array.from(data.imports),

442

dynamicImports: Array.from(data.dynamicImports),

443

exports: Array.from(data.exports),

444

hasSideEffects: data.hasSideEffects

445

}));

446

}

447

448

private calculateStatistics(imports: Set<string> | false, deps: Record<string, DepScanData>) {

449

return {

450

totalImports: imports ? imports.size : 0,

451

totalFiles: Object.keys(deps).length,

452

averageImportsPerFile: imports && Object.keys(deps).length > 0

453

? imports.size / Object.keys(deps).length

454

: 0

455

};

456

}

457

}

458

459

// Usage

460

const analyzer = new BuildAnalyzer({

461

rootDir: process.cwd(),

462

entryPoints: ['src/index.ts', 'src/main.tsx'],

463

alias: {

464

'@': './src',

465

'@components': './src/components',

466

'@utils': './src/utils'

467

},

468

outputPath: './analysis'

469

});

470

471

await analyzer.analyze();

472

```

473

474

These analysis tools provide deep insights into codebase structure, dependencies, and optimization opportunities, enabling data-driven build optimization and better understanding of project architecture.