├── README.md ├── bin └── unmap ├── index.js └── package.json /README.md: -------------------------------------------------------------------------------- 1 | # unmap 2 | 3 | [![latest version published to npm](https://badge.fury.io/js/unmap.svg)](https://www.npmjs.com/package/unmap) 4 | 5 | Unpack a JavaScript Source Map back into a filesystem structure. 6 | 7 | ```shell 8 | npm install -g unmap 9 | ``` 10 | 11 | ```console 12 | Usage: unmap [options] lib.js.map [lib2.js.map [...]] 13 | 14 | Options: 15 | --help Print this help message 16 | --version Print version 17 | --sourceRoot string Override "sourceRoot" field 18 | --output path Output directory (default: current directory) 19 | ``` 20 | 21 | 22 | ## License 23 | 24 | Copyright 2019–2020 Christopher Brown. 25 | [MIT Licensed](https://chbrown.github.io/licenses/MIT/#2019-2020). 26 | -------------------------------------------------------------------------------- /bin/unmap: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env node 2 | const path = require('path') 3 | 4 | const parseArgs = require('minimist') 5 | 6 | const {dumpFile} = require('..') 7 | 8 | const argv = parseArgs(process.argv.slice(2), { 9 | boolean: ['help', 'version'], 10 | string: ['output', 'sourceRoot'], 11 | alias: { 12 | help: 'h', 13 | version: 'v', 14 | output: 'o', 15 | }, 16 | default: { 17 | output: process.cwd(), 18 | }, 19 | }) 20 | 21 | if (argv.help) { 22 | console.log(`Usage: unmap [options] lib.js.map [lib2.js.map [...]] 23 | 24 | Options: 25 | --help Print this help message 26 | --version Print version 27 | --sourceRoot string Override "sourceRoot" field 28 | --output path Output directory (default: current directory)`) 29 | process.exit() 30 | } 31 | if (argv.version) { 32 | console.log(require('../package').version) 33 | process.exit() 34 | } 35 | 36 | const inputs = argv._ 37 | if (!inputs.length && !process.stdin.isTTY) { 38 | console.error('Reading source map from /dev/stdin') 39 | inputs.push('-') 40 | } 41 | 42 | const dumpFilePromises = inputs.map(input => { 43 | const filepath = (input == '-') ? '/dev/stdin/' : input 44 | return dumpFile(filepath, path.resolve(argv.output), argv.sourceRoot) 45 | }) 46 | 47 | Promise.all(dumpFilePromises).then(dumpFileResults => { 48 | dumpFileResults.forEach(dumpFileResult => { 49 | dumpFileResult.forEach(filepath => console.error(filepath)) 50 | }) 51 | }, error => { 52 | console.log(error.toString()) 53 | }) 54 | -------------------------------------------------------------------------------- /index.js: -------------------------------------------------------------------------------- 1 | const path = require('path') 2 | const fs = require('fs').promises 3 | 4 | async function spit(filepath, data) { 5 | const dirpath = path.dirname(filepath) 6 | await fs.mkdir(dirpath, {recursive: true}) 7 | return fs.writeFile(filepath, data) 8 | } 9 | 10 | /** 11 | Write sourceContent to //. 12 | 13 | Returns (a Promise of) the written filepath (on success). 14 | */ 15 | async function dumpSource(source, sourceContent, sourceRoot, dirpath) { 16 | const safeSource = source.replace(/[\x00-\x1f\x80-\x9f\?<>\\:\*\|"]/g, '') 17 | 18 | const sourcePath = path.normalize(safeSource) 19 | const sourceFilepath = path.join(dirpath, sourceRoot, sourcePath) 20 | 21 | await spit(sourceFilepath, sourceContent) 22 | 23 | return sourceFilepath 24 | } 25 | 26 | /** 27 | Traverse a JavaScript Source Map, writing output into . 28 | 29 | Returns (a Promise of) a list of strings of written filepaths. 30 | */ 31 | function dumpSourceMap({sources, sourcesContent, sourceRoot}, dirpath) { 32 | const sourcePromises = sources.map((source, i) => { 33 | const sourceContent = sourcesContent[i] 34 | return dumpSource(source, sourceContent, sourceRoot, dirpath) 35 | }) 36 | return Promise.all(sourcePromises) 37 | } 38 | 39 | /** 40 | Read a JavaScript Source Map from , overriding the "sourceRoot" field 41 | with if provided, and write output into . 42 | 43 | Returns (a Promise of) a list of strings of written filepaths. 44 | */ 45 | async function dumpFile(filepath, dirpath, sourceRoot) { 46 | const sourceMapData = await fs.readFile(filepath) 47 | const sourceMap = JSON.parse(sourceMapData) 48 | if (sourceRoot) { 49 | Object.assign(sourceMap, {sourceRoot}) 50 | } 51 | return dumpSourceMap(sourceMap, dirpath) 52 | } 53 | 54 | module.exports = { 55 | dumpSource, 56 | dumpSourceMap, 57 | dumpFile, 58 | } 59 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "unmap", 3 | "version": "1.1.0", 4 | "description": "Unpack a JavaScript Source Map back into a filesystem structure", 5 | "repository": "github:chbrown/unmap", 6 | "homepage": "https://github.com/chbrown/unmap", 7 | "author": "Christopher Brown ", 8 | "license": "MIT", 9 | "dependencies": { 10 | "minimist": "^1.2.0" 11 | }, 12 | "bin": { 13 | "unmap": "bin/unmap" 14 | } 15 | } 16 | --------------------------------------------------------------------------------