@oaklean/cli
Version:
A command-line interface that provides utilities for parsing, inspecting, and converting the .oak file format, as well as interfaces used in the @oaklean suite.
228 lines • 21.1 kB
JavaScript
;
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
var desc = Object.getOwnPropertyDescriptor(m, k);
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
desc = { enumerable: true, get: function() { return m[k]; } };
}
Object.defineProperty(o, k2, desc);
}) : (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
o[k2] = m[k];
}));
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
Object.defineProperty(o, "default", { enumerable: true, value: v });
}) : function(o, v) {
o["default"] = v;
});
var __importStar = (this && this.__importStar) || (function () {
var ownKeys = function(o) {
ownKeys = Object.getOwnPropertyNames || function (o) {
var ar = [];
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
return ar;
};
return ownKeys(o);
};
return function (mod) {
if (mod && mod.__esModule) return mod;
var result = {};
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
__setModuleDefault(result, mod);
return result;
};
})();
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
return new (P || (P = Promise))(function (resolve, reject) {
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
step((generator = generator.apply(thisArg, _arguments || [])).next());
});
};
Object.defineProperty(exports, "__esModule", { value: true });
const fs = __importStar(require("fs"));
const glob_1 = require("glob");
const profiler_core_1 = require("@oaklean/profiler-core");
const commander_1 = require("commander");
class CodeParsingCommands {
constructor() {
const parseCommand = commander_1.program
.command('parse')
.description('commands to parse javascript or typescript files');
parseCommand
.command('toPST')
.description('Converts a given javascript/typescript file and extracts the ProgramStructureTree from it and stores it into a file')
.argument('<input>', 'input file path')
.argument('<output>', 'output file path')
.action(this.convertToProgramStructureTree.bind(this));
parseCommand
.command('verify-identifiers')
.alias('vi')
.description('Parses all source files (.js, .ts, .jsx, .tsx) within a given path and verifies that all identifiers are valid and unique')
.argument('<input>', 'input file path')
.option('--t262', 'Specifies whether files should be ignored that contain a "$DONOTEVALUATE();", this is useful for test262 source files')
.action(this.verifySourceFilesIdentifiers.bind(this));
const externalResourceCommand = commander_1.program
.command('external-resource')
.alias('er')
.description('commands to interact with external resource files ' +
`(${profiler_core_1.EXTERNAL_RESOURCE_HELPER_FILE_EXTENSION})`);
externalResourceCommand
.command('verify-identifiers')
.alias('vi')
.description('Parses all source files in all resource files within a given path and verifies that all identifiers are valid and unique')
.argument('<input>', `File path to the directory containing the ${profiler_core_1.EXTERNAL_RESOURCE_HELPER_FILE_EXTENSION} files`)
.action(this.verifyIdentifiers.bind(this));
externalResourceCommand
.command('extract')
.alias('e')
.description('Extract a file from a resource file and stores it into a separate file')
.argument('<input>', `File path to the ${profiler_core_1.EXTERNAL_RESOURCE_HELPER_FILE_EXTENSION} file`)
.argument('<file>', 'File to extract from the resource file (scriptID or file path)')
.option('-o, --output <output>', 'Path to store the file (default: execute directory + code.ts)', undefined)
.action(this.extractFile.bind(this));
}
static init() {
return new CodeParsingCommands();
}
convertToProgramStructureTree(input, output) {
return __awaiter(this, void 0, void 0, function* () {
let inputPath = new profiler_core_1.UnifiedPath(input);
if (inputPath.isRelative()) {
inputPath = new profiler_core_1.UnifiedPath(process.cwd()).join(inputPath);
}
let outputPath = new profiler_core_1.UnifiedPath(output);
if (outputPath.isRelative()) {
outputPath = new profiler_core_1.UnifiedPath(process.cwd()).join(outputPath);
}
const programStructureTree = profiler_core_1.TypescriptParser.parseFile(inputPath);
programStructureTree.storeToFile(outputPath);
});
}
verifyCode(code, addToDebug) {
if (code === null) {
return;
}
const tmpName = (addToDebug.scriptID !== undefined
? addToDebug.scriptID
: addToDebug.filePath) || 'tmp.ts';
profiler_core_1.TypescriptParser.parseSource(new profiler_core_1.UnifiedPath(tmpName), code, 'TSX', (filePath, node, identifier, loc, duplicateLoc) => {
profiler_core_1.LoggerHelper.warn('Duplicated identifier found:', Object.assign(Object.assign({}, addToDebug), { identifier, original: loc, duplicate: duplicateLoc }));
});
}
verifySourceFilesIdentifiers(input, options) {
return __awaiter(this, void 0, void 0, function* () {
let inputPath = new profiler_core_1.UnifiedPath(input);
if (inputPath.isRelative()) {
inputPath = new profiler_core_1.UnifiedPath(process.cwd()).join(inputPath);
}
const globPattern = inputPath
.join('**', '*.{js,ts,jsx,tsx}')
.toPlatformString();
if (fs.existsSync(inputPath.toPlatformString())) {
const filePaths = (0, glob_1.sync)(globPattern.toString(), { dot: true });
filePaths.map((filePath) => new profiler_core_1.UnifiedPath(filePath));
for (const filePath of filePaths) {
if (fs.statSync(filePath).isDirectory()) {
continue;
}
if (filePath.endsWith('.d.ts')) {
continue; // Skip declaration files
}
const sourceFilePath = new profiler_core_1.UnifiedPath(filePath);
let code = fs.readFileSync(sourceFilePath.toPlatformString(), 'utf-8');
if (options.t262 !== undefined && code.includes('$DONOTEVALUATE();')) {
code = code.split('$DONOTEVALUATE();')[0];
}
try {
this.verifyCode(code, {
resourceFile: inputPath.toPlatformString(),
filePath: sourceFilePath.toString()
});
}
catch (error) {
profiler_core_1.LoggerHelper.error(`Error parsing file ${sourceFilePath.toPlatformString()}:`, error);
continue;
}
}
}
else {
profiler_core_1.LoggerHelper.error(`Input path does not exist: ${inputPath.toPlatformString()}`);
return;
}
});
}
verifyIdentifiers(input) {
return __awaiter(this, void 0, void 0, function* () {
let inputPath = new profiler_core_1.UnifiedPath(input);
if (inputPath.isRelative()) {
inputPath = new profiler_core_1.UnifiedPath(process.cwd()).join(inputPath);
}
const exportAssetHelper = new profiler_core_1.ExportAssetHelper(inputPath);
const cwdPath = new profiler_core_1.UnifiedPath(process.cwd());
const externalResourcePaths = exportAssetHelper.allExternalResourcePathsInOutputDir();
for (const externalResourcePath of externalResourcePaths) {
const relativePath = cwdPath.pathTo(externalResourcePath);
const resourceFile = profiler_core_1.ExternalResourceHelper.loadFromFile(new profiler_core_1.UnifiedPath(process.cwd()), externalResourcePath);
if (resourceFile === undefined) {
profiler_core_1.LoggerHelper.error(`Could not load resource file: ${relativePath.toPlatformString()}`);
continue;
}
const scriptIDs = resourceFile.scriptIDs;
const filePaths = resourceFile.loadedFilePaths;
for (const scriptID of scriptIDs) {
const code = yield resourceFile.sourceCodeFromScriptID(scriptID);
this.verifyCode(code, {
resourceFile: relativePath.toPlatformString(),
scriptID
});
}
for (const filePath of filePaths) {
const code = yield resourceFile.sourceCodeFromPath(filePath, filePath);
this.verifyCode(code, {
resourceFile: relativePath.toPlatformString(),
filePath
});
}
}
});
}
extractFile(input, file, options) {
return __awaiter(this, void 0, void 0, function* () {
let inputPath = new profiler_core_1.UnifiedPath(input);
if (inputPath.isRelative()) {
inputPath = new profiler_core_1.UnifiedPath(process.cwd()).join(inputPath);
}
let outputPath = new profiler_core_1.UnifiedPath(options.output !== undefined ? options.output : 'code.ts');
if (outputPath.isRelative()) {
outputPath = new profiler_core_1.UnifiedPath(process.cwd()).join(outputPath);
}
const cwdPath = new profiler_core_1.UnifiedPath(process.cwd());
const relativeInputPath = cwdPath.pathTo(inputPath);
const resourceFile = profiler_core_1.ExternalResourceHelper.loadFromFile(new profiler_core_1.UnifiedPath(process.cwd()), inputPath);
if (resourceFile === undefined) {
profiler_core_1.LoggerHelper.error(`Could not load resource file: ${relativeInputPath.toPlatformString()}`);
return;
}
let code = '';
if (resourceFile.scriptIDs.includes(file)) {
code = yield resourceFile.sourceCodeFromScriptID(file);
}
else if (resourceFile.loadedFilePaths.includes(file)) {
code = yield resourceFile.sourceCodeFromPath(file, file);
}
else {
profiler_core_1.LoggerHelper.error(`File ${file} not found in resource file: ${relativeInputPath.toPlatformString()}`);
}
if (code === null) {
profiler_core_1.LoggerHelper.error(`File '${file}' is marked as missing (was not present during profiling)`);
return;
}
profiler_core_1.PermissionHelper.writeFileWithUserPermission(outputPath, code);
});
}
}
exports.default = CodeParsingCommands;
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiQ29kZVBhcnNpbmdDb21tYW5kcy5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy9jb21tYW5kcy9Db2RlUGFyc2luZ0NvbW1hbmRzLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7O0FBQUEsdUNBQXdCO0FBRXhCLCtCQUEyQjtBQUMzQiwwREFVK0I7QUFDL0IseUNBQW1DO0FBRW5DLE1BQXFCLG1CQUFtQjtJQUN2QztRQUNDLE1BQU0sWUFBWSxHQUFHLG1CQUFPO2FBQzFCLE9BQU8sQ0FBQyxPQUFPLENBQUM7YUFDaEIsV0FBVyxDQUFDLGtEQUFrRCxDQUFDLENBQUE7UUFFakUsWUFBWTthQUNWLE9BQU8sQ0FBQyxPQUFPLENBQUM7YUFDaEIsV0FBVyxDQUNYLHFIQUFxSCxDQUNySDthQUNBLFFBQVEsQ0FBQyxTQUFTLEVBQUUsaUJBQWlCLENBQUM7YUFDdEMsUUFBUSxDQUFDLFVBQVUsRUFBRSxrQkFBa0IsQ0FBQzthQUN4QyxNQUFNLENBQUMsSUFBSSxDQUFDLDZCQUE2QixDQUFDLElBQUksQ0FBQyxJQUFJLENBQUMsQ0FBQyxDQUFBO1FBRXZELFlBQVk7YUFDVixPQUFPLENBQUMsb0JBQW9CLENBQUM7YUFDN0IsS0FBSyxDQUFDLElBQUksQ0FBQzthQUNYLFdBQVcsQ0FDWCwySEFBMkgsQ0FDM0g7YUFDQSxRQUFRLENBQUMsU0FBUyxFQUFFLGlCQUFpQixDQUFDO2FBQ3RDLE1BQU0sQ0FDTixRQUFRLEVBQ1IsdUhBQXVILENBQ3ZIO2FBQ0EsTUFBTSxDQUFDLElBQUksQ0FBQyw0QkFBNEIsQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLENBQUMsQ0FBQTtRQUV0RCxNQUFNLHVCQUF1QixHQUFHLG1CQUFPO2FBQ3JDLE9BQU8sQ0FBQyxtQkFBbUIsQ0FBQzthQUM1QixLQUFLLENBQUMsSUFBSSxDQUFDO2FBQ1gsV0FBVyxDQUNYLG9EQUFvRDtZQUNuRCxJ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