@backtrace/javascript-cli
Version:
Backtrace CLI for working with Javascript files.
155 lines • 8.43 kB
JavaScript
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.addSourceToSourceMap = exports.addSourcesToSourcemaps = exports.addSourcesCmd = void 0;
const sourcemap_tools_1 = require("@backtrace/sourcemap-tools");
const path_1 = __importDefault(require("path"));
const Command_1 = require("../commands/Command");
const common_1 = require("../helpers/common");
const errorBehavior_1 = require("../helpers/errorBehavior");
const find_1 = require("../helpers/find");
const logs_1 = require("../helpers/logs");
const normalizePaths_1 = require("../helpers/normalizePaths");
const loadOptions_1 = require("../options/loadOptions");
exports.addSourcesCmd = new Command_1.Command({
name: 'add-sources',
description: 'Adds sources to sourcemap files',
})
.option({
name: 'path',
description: 'Path to sourcemap files to append sources to.',
defaultOption: true,
multiple: true,
alias: 'p',
})
.option({
name: 'include',
description: 'Includes specified paths.',
type: String,
multiple: true,
alias: 'i',
})
.option({
name: 'exclude',
description: 'Excludes specified paths.',
type: String,
multiple: true,
alias: 'x',
})
.option({
name: 'dry-run',
alias: 'n',
type: Boolean,
description: 'Does not modify the files at the end.',
})
.option({
name: 'force',
alias: 'f',
type: Boolean,
description: 'Processes files even if sourcesContent is not empty. Will overwrite existing sources.',
})
.option({
name: 'asset-error-behavior',
alias: 'e',
type: String,
description: `What to do when an asset fails. Can be one of: ${Object.keys(errorBehavior_1.ErrorBehaviors).join(', ')}.`,
})
.option({
name: 'source-error-behavior',
type: String,
description: `What to do when reading sourcepath fails. Can be one of: ${Object.keys(errorBehavior_1.ErrorBehaviors).join(', ')}.`,
})
.option({
name: 'pass-with-no-files',
type: Boolean,
description: 'Exits with zero exit code if no sourcemaps are found.',
})
.execute(addSourcesToSourcemaps);
/**
* Adds sources to sourcemaps found in path(s).
*/
async function addSourcesToSourcemaps({ opts, logger, getHelpMessage }) {
const sourceProcessor = new sourcemap_tools_1.SourceProcessor(new sourcemap_tools_1.DebugIdGenerator());
const configPath = opts.config ?? (await (0, loadOptions_1.findConfig)());
const configResult = await (0, loadOptions_1.loadOptionsForCommand)(configPath)('add-sources');
if (configResult.isErr()) {
return configResult;
}
const config = configResult.data;
opts = {
...config,
...opts,
path: opts.path ??
(config.path && configPath ? (0, normalizePaths_1.relativePaths)(config.path, path_1.default.dirname(configPath)) : process.cwd()),
};
logger.trace(`resolved options: \n${JSON.stringify(opts, null, ' ')}`);
const searchPaths = (0, normalizePaths_1.normalizePaths)(opts.path, process.cwd());
if (!searchPaths.length) {
logger.info(getHelpMessage());
return (0, sourcemap_tools_1.Err)('path must be specified');
}
const logDebug = (0, sourcemap_tools_1.log)(logger, 'debug');
const logTrace = (0, sourcemap_tools_1.log)(logger, 'trace');
const logAsset = (0, logs_1.createAssetLogger)(logger);
const logDebugAsset = logAsset('debug');
const logTraceAsset = logAsset('trace');
const assetErrorBehaviorResult = (0, errorBehavior_1.getErrorBehavior)(opts['asset-error-behavior'] ?? 'exit');
if (assetErrorBehaviorResult.isErr()) {
logger.info(getHelpMessage());
return assetErrorBehaviorResult;
}
const assetErrorBehavior = assetErrorBehaviorResult.data;
const sourceErrorBehaviorResult = (0, errorBehavior_1.getErrorBehavior)(opts['source-error-behavior'] ?? 'warn');
if (sourceErrorBehaviorResult.isErr()) {
logger.info(getHelpMessage());
return sourceErrorBehaviorResult;
}
const sourceErrorBehavior = sourceErrorBehaviorResult.data;
const handleFailedAsset = (0, errorBehavior_1.handleError)(assetErrorBehavior);
const logAssetBehaviorError = (asset) => (err, level) => (0, logs_1.createAssetLogger)(logger, level)(err)(asset);
const processAssetResult = (behavior) => (result) => {
const { succeeded, skipped, failed } = result.result;
if (failed.length) {
if ((0, errorBehavior_1.isFatal)(behavior)) {
return (0, sourcemap_tools_1.Err)(`failed to find source for ${failed[0]}` +
(failed.length > 1 ? ` (and ${failed.length} more)` : ''));
}
else if ((0, errorBehavior_1.shouldLog)(behavior)) {
for (const path of failed) {
logAsset(behavior)(`failed to find source for ${path}`)(result);
}
}
}
for (const path of skipped) {
logDebugAsset(`skipped source for ${path}`)(result);
}
for (const path of succeeded) {
logTraceAsset(`added source for ${path}`)(result);
}
return (0, sourcemap_tools_1.Ok)(result);
};
const addSourcesCommand = (asset) => (0, sourcemap_tools_1.pipe)(asset, logTraceAsset('reading sourcemap'), (0, common_1.readSourceMapFromPathOrFromSource)(sourceProcessor), sourcemap_tools_1.R.map(logDebugAsset('read sourcemap')), sourcemap_tools_1.R.map(logTraceAsset('adding source')), sourcemap_tools_1.R.map(addSourceToSourceMap(opts.force ?? false)), sourcemap_tools_1.R.map(processAssetResult(sourceErrorBehavior)), sourcemap_tools_1.R.map(logDebugAsset('source added')), sourcemap_tools_1.R.map(opts['dry-run']
? sourcemap_tools_1.Ok
: (0, sourcemap_tools_1.flow)(logTraceAsset('writing source and sourcemap'), common_1.writeAsset, sourcemap_tools_1.R.map(logDebugAsset('wrote source and sourcemap')))), sourcemap_tools_1.R.mapErr((error) => `${asset.name}: ${error}`), handleFailedAsset(logAssetBehaviorError(asset)));
const includePaths = (0, normalizePaths_1.normalizePaths)(opts.include);
const excludePaths = (0, normalizePaths_1.normalizePaths)(opts.exclude);
const { isIncluded, isExcluded } = await (0, find_1.buildIncludeExclude)(includePaths, excludePaths, logTrace);
return (0, sourcemap_tools_1.pipe)(searchPaths, find_1.findTuples, sourcemap_tools_1.R.map((0, sourcemap_tools_1.flow)((0, sourcemap_tools_1.map)(find_1.file2Or1FromTuple), logDebug((r) => `found ${r.length} files`), (0, sourcemap_tools_1.map)(logTrace((result) => `found file: ${result.path}`)), isIncluded ? (0, sourcemap_tools_1.filterAsync)(isIncluded) : sourcemap_tools_1.pass, isExcluded ? (0, sourcemap_tools_1.filterAsync)((0, sourcemap_tools_1.flow)(isExcluded, sourcemap_tools_1.not)) : sourcemap_tools_1.pass, (0, sourcemap_tools_1.filter)((t) => t.direct || (0, sourcemap_tools_1.matchSourceMapExtension)(t.path)), (0, sourcemap_tools_1.map)((t) => t.path), logDebug((r) => `found ${r.length} files for adding sources`), (0, sourcemap_tools_1.map)(logTrace((path) => `file to add sources to: ${path}`)), (0, sourcemap_tools_1.map)(common_1.toAsset), opts['pass-with-no-files'] ? sourcemap_tools_1.Ok : (0, sourcemap_tools_1.failIfEmpty)('no sourcemaps found'), sourcemap_tools_1.R.map((0, sourcemap_tools_1.flow)((0, sourcemap_tools_1.mapAsync)(addSourcesCommand), sourcemap_tools_1.R.flatMap)), sourcemap_tools_1.R.map(errorBehavior_1.filterBehaviorSkippedElements), sourcemap_tools_1.R.map((0, sourcemap_tools_1.map)(output(logger))))));
}
exports.addSourcesToSourcemaps = addSourcesToSourcemaps;
function addSourceToSourceMap(force) {
const sourceProcessor = new sourcemap_tools_1.SourceProcessor(new sourcemap_tools_1.DebugIdGenerator());
return async function addSourceToSourceMap(asset) {
return (0, sourcemap_tools_1.pipe)(asset, (asset) => sourceProcessor.addSourcesToSourceMap(asset.content, asset.path, force), sourcemap_tools_1.R.map((result) => ({ ...asset, content: result.sourceMap, result })));
};
}
exports.addSourceToSourceMap = addSourceToSourceMap;
function output(logger) {
return function output(asset) {
logger.output(asset.path);
return asset;
};
}
//# sourceMappingURL=add-sources.js.map
;