@rightcapital/php-parser
Version:
TypeScript types for PHP Parser JSON representation
141 lines (140 loc) • 7.6 kB
JavaScript
#!/usr/bin/env ts-node
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
const node_fs_1 = require("node:fs");
const os = require("node:os");
const node_path_1 = require("node:path");
const path = require("node:path");
const _ = require("lodash");
const Mustache = require("mustache");
const constants_1 = require("../constants");
const cli_helpers_1 = require("./helpers/cli-helpers");
const file_path_helpers_1 = require("./helpers/file-path-helpers");
const node_retriever_helpers_1 = require("./helpers/node-retriever-helpers");
const type_generation_helpers_1 = require("./helpers/type-generation-helpers");
const PHP_PARSER_ROOT_PATH = (0, node_path_1.resolve)(constants_1.PROJECT_ROOT, 'vendor/nikic/php-parser/lib/PhpParser');
const PHP_PARSER_NODE_DIRECTORY_PATH = (0, node_path_1.resolve)(PHP_PARSER_ROOT_PATH, 'Node');
class GenerateType {
static main() {
const typesRootPath = file_path_helpers_1.FilePathHelpers.getTypesRootPath();
const nodeTypeRootPath = (0, node_path_1.resolve)(typesRootPath, 'node');
(0, node_fs_1.mkdirSync)(GenerateType.cliContext.temporaryNodeTypeRootPath, {
recursive: true,
});
GenerateType.walkSync(PHP_PARSER_NODE_DIRECTORY_PATH, GenerateType.generateTypeForNodeByFile);
const typesFileName = (0, node_path_1.resolve)(typesRootPath, 'types.ts');
const temporaryTypesFileName = (0, node_path_1.resolve)(typesRootPath, 'tmp-types.ts');
(0, node_fs_1.writeFileSync)(temporaryTypesFileName, type_generation_helpers_1.TypeGenerationHelpers.generateCombinationTypesFromNodes(GenerateType.cliContext), { encoding: 'utf8' });
(0, node_fs_1.rmSync)(nodeTypeRootPath, { recursive: true, force: true });
(0, node_fs_1.rmSync)(typesFileName, { force: true });
(0, node_fs_1.renameSync)(GenerateType.cliContext.temporaryNodeTypeRootPath, nodeTypeRootPath);
(0, node_fs_1.renameSync)(temporaryTypesFileName, typesFileName);
}
static generateTypeForNodeByFile(filePath) {
const fileRelativePath = path.relative(PHP_PARSER_NODE_DIRECTORY_PATH, filePath);
const filePathParts = filePath.split('/');
const directoryRelativePath = fileRelativePath
.split('/')
.slice(0, -1)
.map((part) => _.kebabCase(part))
.join('/');
const fileName = _.kebabCase(fileRelativePath
.split('/')
.pop()
.replace(/\.php$/, ''));
const ast = cli_helpers_1.CliHelpers.parsePhpFileToAst(filePath);
const classNode = node_retriever_helpers_1.NodeRetrieverHelpers.getRootClassNode(ast);
const uses = node_retriever_helpers_1.NodeRetrieverHelpers.getUsesMap(ast);
if (classNode) {
const properties = node_retriever_helpers_1.NodeRetrieverHelpers.getPropertiesFromClassNode(classNode, filePathParts, fileRelativePath, uses);
const uniqueImportDeclarationGeneratedStrings = [
...new Set(properties
.map((property) => property.typeGenerationPackage
.importDeclarationGeneratedStrings)
.flat()),
];
const parentNodeFilePath = file_path_helpers_1.FilePathHelpers.getFilePathFromNameNodeParts(node_retriever_helpers_1.NodeRetrieverHelpers.getPartsByName(classNode.extends.name), classNode.extends.nodeType, filePathParts, uses);
const fullyQualifiedNodeName = file_path_helpers_1.FilePathHelpers.getFullyQualifiedNodeNameByFilePath(fileRelativePath);
const parentNodeName = node_retriever_helpers_1.NodeRetrieverHelpers.getPartsByName(classNode.extends.name).at(-1);
const fullyQualifiedParentNodeName = file_path_helpers_1.FilePathHelpers.getFullyQualifiedParentNodeNameByFilePath(fileRelativePath, parentNodeFilePath, parentNodeName);
const nodeOutput = {
fileName,
filePath: path.join(directoryRelativePath, fileName),
filePathParts,
fullyQualifiedNodeName,
fullyQualifiedParentNodeName,
nodeName: classNode.name.name,
parentNodeParts: node_retriever_helpers_1.NodeRetrieverHelpers.getPartsByName(classNode.extends.name),
parentNodeName,
parentNodeFilePath,
properties,
uniqueImportDeclarationGeneratedStrings,
nodeType: node_retriever_helpers_1.NodeRetrieverHelpers.getGetTypeFunctionReturnValue(classNode),
uses,
};
GenerateType.appendNodeToContext(nodeOutput);
const templateFileName = path.resolve(constants_1.SRC_ROOT, 'templates/php-parser-node.mustache');
const templateFileContent = (0, node_fs_1.readFileSync)(templateFileName, 'utf8');
try {
if (directoryRelativePath) {
(0, node_fs_1.mkdirSync)(path.resolve(GenerateType.cliContext.temporaryNodeTypeRootPath, directoryRelativePath), {
recursive: true,
});
}
}
finally {
(0, node_fs_1.writeFileSync)((0, node_path_1.resolve)(GenerateType.cliContext.temporaryNodeTypeRootPath, directoryRelativePath, `${fileName}.ts`), Mustache.render(templateFileContent, nodeOutput));
}
}
}
static walkSync(directoryPath, callback) {
const fileNames = (0, node_fs_1.readdirSync)(directoryPath);
fileNames.forEach((fileName) => {
const filePath = path.join(directoryPath, fileName);
const stats = (0, node_fs_1.statSync)(filePath);
if (stats.isDirectory()) {
GenerateType.walkSync(filePath, callback);
}
else if (stats.isFile()) {
callback(filePath);
}
});
}
static appendNodeToContext(node) {
GenerateType.cliContext.allNodeNames.push(node.nodeName);
if (!(node.fullyQualifiedNodeName in GenerateType.cliContext.allNodes)) {
GenerateType.cliContext.allNodes[node.fullyQualifiedNodeName] = {
name: node.fullyQualifiedNodeName,
subNodeNames: [],
parentNodeName: '',
filePath: '',
properties: [],
nodeType: '',
};
}
if (!(node.fullyQualifiedParentNodeName in GenerateType.cliContext.allNodes)) {
GenerateType.cliContext.allNodes[node.fullyQualifiedParentNodeName] = {
name: node.fullyQualifiedParentNodeName,
subNodeNames: [],
parentNodeName: '',
filePath: '',
properties: [],
nodeType: '',
};
}
GenerateType.cliContext.allNodes[node.fullyQualifiedParentNodeName].subNodeNames.push(node.fullyQualifiedNodeName);
GenerateType.cliContext.allNodes[node.fullyQualifiedNodeName].parentNodeName = node.fullyQualifiedParentNodeName;
GenerateType.cliContext.allNodes[node.fullyQualifiedNodeName].filePath =
node.filePath;
GenerateType.cliContext.allNodes[node.fullyQualifiedNodeName].properties =
node.properties;
GenerateType.cliContext.allNodes[node.fullyQualifiedNodeName].nodeType =
node.nodeType;
}
}
GenerateType.cliContext = {
allNodeNames: [],
allNodes: {},
temporaryNodeTypeRootPath: (0, node_path_1.resolve)(os.tmpdir(), 'node'),
};
GenerateType.main();