Analyze and debug space usage through source maps
—
Comprehensive error system with specific error codes for different failure scenarios and validation issues.
Custom error class for application-specific errors with error codes and cause tracking.
class AppError extends Error {
/** Error code identifier */
code?: ErrorCode;
/** Original error that caused this error */
cause?: Error;
constructor(errorContext: ErrorContext, error?: NodeJS.ErrnoException);
}
type ErrorCode =
| 'Unknown'
| 'NoBundles'
| 'NoSourceMap'
| 'OneSourceSourceMap'
| 'UnmappedBytes'
| 'InvalidMappingLine'
| 'InvalidMappingColumn'
| 'CannotSaveFile'
| 'CannotCreateTempFile'
| 'CannotOpenTempFile'
| 'CannotOpenCoverageFile'
| 'NoCoverageMatches';Usage Examples:
import { explore } from "source-map-explorer";
try {
const result = await explore("bundle.js");
} catch (error) {
// Error handling - note that AppError is not exported from main library
console.error(`Error: ${error.message}`);
if (error.code) {
console.error(`Error code: ${error.code}`);
}
if (error.cause) {
console.error("Caused by:", error.cause.message);
}
}Error messages are generated internally by the library and provide detailed context about failures. The library uses a consistent error message format that includes specific details based on the error type.
Errors related to invalid or missing input data.
type InputErrorCode =
| 'NoBundles' // No bundles provided for analysis
| 'NoSourceMap'; // Source map not found or invalidNoBundles Error:
NoSourceMap Error:
Usage Examples:
try {
// This will throw NoBundles error
const result = await explore([]);
} catch (error) {
if (error instanceof AppError && error.code === 'NoBundles') {
console.error("No bundles provided for analysis");
}
}
try {
// This might throw NoSourceMap error
const result = await explore("bundle-without-sourcemap.js");
} catch (error) {
if (error instanceof AppError && error.code === 'NoSourceMap') {
console.error("Source map not found - make sure bundle includes source map");
}
}Errors related to invalid or problematic source map data.
type ValidationErrorCode =
| 'OneSourceSourceMap' // Source map contains only one source file
| 'InvalidMappingLine' // Mapping references invalid line number
| 'InvalidMappingColumn'; // Mapping references invalid column numberOneSourceSourceMap Warning:
Invalid Mapping Errors:
noBorderChecks: true optionUsage Examples:
import { explore } from "source-map-explorer";
const result = await explore("single-file-bundle.js");
// Check for warnings
const warnings = result.errors.filter(e => e.isWarning);
warnings.forEach(warning => {
if (warning.code === 'OneSourceSourceMap') {
console.warn("Bundle maps to only one source file - consider analyzing multiple bundles");
}
});
// Handle validation errors with relaxed checking
try {
const result = await explore("problematic-bundle.js", {
noBorderChecks: true // Disable strict validation
});
} catch (error) {
if (error instanceof AppError &&
(error.code === 'InvalidMappingLine' || error.code === 'InvalidMappingColumn')) {
console.error("Source map has invalid mappings - try noBorderChecks: true");
}
}Errors related to file operations and I/O.
type FileSystemErrorCode =
| 'CannotSaveFile' // Unable to save output file
| 'CannotCreateTempFile' // Unable to create temporary file
| 'CannotOpenTempFile'; // Unable to open temporary file in browserFile Save Errors:
Temporary File Errors:
Usage Examples:
try {
const result = await explore("bundle.js", {
output: { format: "html", filename: "/read-only/analysis.html" }
});
} catch (error) {
if (error instanceof AppError && error.code === 'CannotSaveFile') {
console.error("Cannot save output file - check permissions and disk space");
}
}Errors related to Chrome DevTools coverage data integration.
type CoverageErrorCode =
| 'CannotOpenCoverageFile' // Coverage file not found or unreadable
| 'NoCoverageMatches'; // No coverage data matches bundle filesCoverage File Errors:
Coverage Matching Errors:
Usage Examples:
try {
const result = await explore("bundle.js", {
coverage: "non-existent-coverage.json"
});
} catch (error) {
if (error instanceof AppError && error.code === 'CannotOpenCoverageFile') {
console.error("Coverage file not found - check path and permissions");
}
}
// Handle coverage matching issues
const result = await explore("bundle.js", {
coverage: "coverage.json"
});
const coverageErrors = result.errors.filter(e => e.code === 'NoCoverageMatches');
if (coverageErrors.length > 0) {
console.warn("Coverage data doesn't match bundle files - check URL patterns");
}Analysis can partially succeed with some bundles failing. Errors are collected in the result object:
const result = await explore(["good-bundle.js", "bad-bundle.js"]);
// Check for partial failures
if (result.bundles.length > 0 && result.errors.length > 0) {
console.log(`Analyzed ${result.bundles.length} bundles successfully`);
console.log(`${result.errors.length} bundles failed`);
// Process successful results
result.bundles.forEach(bundle => {
console.log(`${bundle.bundleName}: ${bundle.totalBytes} bytes`);
});
// Handle failed bundles
result.errors.forEach(error => {
console.error(`Failed to analyze ${error.bundleName}: ${error.message}`);
});
}
// Check for complete failure
if (result.bundles.length === 0) {
console.error("All bundles failed to analyze");
throw new Error("Analysis failed completely");
}For problematic source maps, disable strict validation:
const result = await explore("problematic-bundle.js", {
noBorderChecks: true // Skip mapping boundary validation
});Try different input approaches if one fails:
async function analyzeWithFallback(bundlePath: string) {
try {
// Try with automatic source map detection
return await explore(bundlePath);
} catch (error) {
if (error instanceof AppError && error.code === 'NoSourceMap') {
try {
// Try with explicit source map
return await explore({
code: bundlePath,
map: bundlePath + '.map'
});
} catch (secondError) {
// Try inline source map only
return await explore(bundlePath, { excludeSourceMapComment: false });
}
}
throw error;
}
}Graceful handling of coverage integration issues:
async function analyzeWithOptionalCoverage(bundlePath: string, coveragePath?: string) {
const baseOptions = {
output: { format: "html" as const }
};
if (coveragePath) {
try {
return await explore(bundlePath, {
...baseOptions,
coverage: coveragePath
});
} catch (error) {
if (error instanceof AppError &&
(error.code === 'CannotOpenCoverageFile' || error.code === 'NoCoverageMatches')) {
console.warn("Coverage integration failed, continuing without coverage data");
return await explore(bundlePath, baseOptions);
}
throw error;
}
}
return await explore(bundlePath, baseOptions);
}Install with Tessl CLI
npx tessl i tessl/npm-source-map-explorer