@hadss/hmrouter-plugin
Version:
HMRouter Compiler Plugin
265 lines (264 loc) • 12.7 kB
JavaScript
"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.CodeGenerationProcessor = void 0;
const micromatch_1 = __importDefault(require("micromatch"));
const ejs_1 = __importDefault(require("ejs"));
const framework_1 = require("../../framework");
const PluginError_1 = require("../error/PluginError");
const constants_1 = require("../constants");
class CodeGenerationProcessor {
constructor(context) {
this.sdkVersion = 0;
this.context = context;
}
execute() {
this.sdkVersion = this.getCompileSdkVersion();
framework_1.Logger.debug(this.context.node.getNodeName(), `Start to code generation...`);
this.context.generatedPaths = new Map();
this.context.getAnalyzeResults().forEach((result) => {
if (result.annotation === constants_1.AnnotationConstants.ROUTER_ANNOTATION) {
if (!result.sourceFilePath) {
throw PluginError_1.PluginError.create(PluginError_1.ErrorCode.ERROR_PAGE_SOURCE_FILE, this.context.config.moduleName, result.sourceFilePath);
}
let pageSourceFile = this.context.config
.getRelativeSourcePath(result.sourceFilePath)
.replaceAll(constants_1.FilePathConstants.FILE_SEPARATOR, constants_1.FilePathConstants.DELIMITER);
this.generatePageFile(result, pageSourceFile, this.matchedPath(pageSourceFile, this.context.config.customPageTemplate, this.context.config.getDefaultTplFilePath()));
}
});
}
extractVersion(compatibleSdkVersion) {
if (typeof compatibleSdkVersion === 'number') {
return compatibleSdkVersion;
}
else {
const match = compatibleSdkVersion.match(/\((\d+)\)/);
if (match && match[1]) {
return parseInt(match[1], 10);
}
const num = parseFloat(compatibleSdkVersion);
if (!isNaN(num) && num > constants_1.FilePathConstants.DEFAULT_VALUE) {
return num;
}
return constants_1.FilePathConstants.DEFAULT_VALUE;
}
}
getCompileSdkVersion() {
let json5FilePath = '';
let sdkVersion = constants_1.FilePathConstants.DEFAULT_VALUE;
let arrData = ['DEVECO_SDK_HOME', 'HOS_SDK_HOME', 'OHOS_SDK_HOME'];
for (let index = 0; index <= 4; index++) {
if (index < 3 && process.env[arrData[index]]) {
json5FilePath = framework_1.PluginFileUtil.pathResolve(process.env[arrData[index]], constants_1.FilePathConstants.SDK_HOME);
}
else if (index === 3) {
json5FilePath = framework_1.PluginFileUtil.pathResolve(framework_1.PluginStore.getInstance().get('projectFilePath'), constants_1.FilePathConstants.BUILD_PROFILE);
}
else if (index === 4) {
json5FilePath = framework_1.PluginFileUtil.pathResolve(framework_1.PluginStore.getInstance().get('projectFilePath'), constants_1.FilePathConstants.BUILD_PROFILE);
}
const sdkVer = this.getSdkVersion(json5FilePath, index);
if (sdkVer > constants_1.FilePathConstants.DEFAULT_VALUE) {
sdkVersion = sdkVer;
break;
}
}
return sdkVersion;
}
getSdkVersion(json5FilePath, index) {
if (framework_1.PluginFileUtil.exist(json5FilePath)) {
const data = framework_1.PluginFileUtil.readJson5(json5FilePath);
if (index < 3) {
return this.extractVersion(data.apiVersion);
}
else if (index === 3) {
if (data.app.products[0].compileSdkVersion) {
return this.extractVersion(data.app.products[0].compileSdkVersion);
}
}
else if (index === 4) {
if (data.app.products[0].compatibleSdkVersion) {
return this.extractVersion(data.app.products[0].compatibleSdkVersion);
}
}
}
return constants_1.FilePathConstants.DEFAULT_VALUE;
}
generatePageFile(result, pageSourceFile, tempFilePath) {
const templateModel = this.prepareTemplateModel(result, pageSourceFile);
tempFilePath = this.determineTemplatePath(result, tempFilePath);
const generatedFilePath = this.generateFile(templateModel, tempFilePath);
framework_1.Logger.info(this.context.node.getNodeName(), `Builder ${templateModel.generatorViewName}.ets has been generated in ${generatedFilePath}`);
const uniqueKey = `${result.name}#${result.pageUrl}`;
this.context.generatedPaths.set(uniqueKey, generatedFilePath);
}
matchedPath(filePath, customPageTemplate, defaultTplFilePath) {
for (const template of customPageTemplate) {
if (micromatch_1.default.isMatch(filePath, template.srcPath)) {
framework_1.Logger.debug(this.context.node.getNodeName(), `${filePath} detected matching template: ${template.templatePath}`);
return framework_1.PluginFileUtil.pathResolve(this.context.config.configDir, template.templatePath);
}
}
return defaultTplFilePath;
}
prepareTemplateModel(analyzeResult, pageSourceFile) {
let importPath = this.context.config
.getRelativeBuilderPath(pageSourceFile)
.replaceAll(constants_1.FilePathConstants.FILE_SEPARATOR, constants_1.FilePathConstants.DELIMITER)
.replaceAll(constants_1.FilePathConstants.ETS_SUFFIX, '');
let generatorViewName = constants_1.PrefixConstants.VIEW_NAME_PREFIX + analyzeResult.name + framework_1.StringUtil.stringToHashCode(analyzeResult.pageUrl);
let templateData = this.context.getTemplateData(analyzeResult.name);
return {
sdkVersion: this.sdkVersion,
pageUrl: analyzeResult.pageUrl,
componentName: analyzeResult.name,
dialog: !!analyzeResult.dialog,
isDefaultExport: !!templateData?.isDefaultExport,
importPath,
generatorViewName,
...templateData,
};
}
determineTemplatePath(analyzeResult, defaultTemplatePath) {
const libraryVersion = this.detectLibraryVersion();
framework_1.Logger.debug(this.context.node.getNodeName(), `Library version: ${libraryVersion}`);
if (analyzeResult.useNavDst === true) {
return framework_1.PluginFileUtil.pathResolve(__dirname, constants_1.FilePathConstants.PARENT_DELIMITER.repeat(3), constants_1.TemplateConstants.CUSTOM_BUILDER_TEMPLATE);
}
const templateType = this.determineTemplateType(libraryVersion);
if (templateType !== 'latest' && libraryVersion) {
framework_1.Logger.warn(this.context.node.getNodeName(), `[HMRouter Version Compatibility] Detected library version ${libraryVersion}, ` +
`which is below the minimum recommended version ${constants_1.VersionConstants.HMROUTER_MIN_VERSION_FOR_SDK_API}. ` +
`Automatically switched to compatible template (${templateType}). ` +
`Please upgrade /hmrouter to ${constants_1.VersionConstants.HMROUTER_MIN_VERSION_FOR_SDK_API} or higher for full feature support.`);
}
switch (templateType) {
case 'v1':
return framework_1.PluginFileUtil.pathResolve(__dirname, constants_1.FilePathConstants.PARENT_DELIMITER.repeat(3) + constants_1.TemplateConstants.V1_TEMPLATE);
case 'v1_1':
return framework_1.PluginFileUtil.pathResolve(__dirname, constants_1.FilePathConstants.PARENT_DELIMITER.repeat(3) + constants_1.TemplateConstants.V1_1_TEMPLATE);
case 'latest':
default:
return defaultTemplatePath;
}
}
determineTemplateType(libraryVersion) {
if (!libraryVersion) {
return 'v1';
}
const currentVersion = this.parseVersion(libraryVersion);
const v1_1Version = this.parseVersion(constants_1.VersionConstants.HMROUTER_MIN_VERSION_FOR_NAV_HELPER);
const v1_2Version = this.parseVersion(constants_1.VersionConstants.HMROUTER_MIN_VERSION_FOR_SDK_API);
if (!currentVersion || !v1_1Version || !v1_2Version) {
return 'v1';
}
if (this.compareVersions(currentVersion, v1_2Version) >= 0) {
return 'latest';
}
if (this.compareVersions(currentVersion, v1_1Version) >= 0) {
return 'v1_1';
}
return 'v1';
}
generateFile(templateModel, templatePath) {
if (!framework_1.PluginFileUtil.exist(templatePath)) {
throw PluginError_1.PluginError.create(PluginError_1.ErrorCode.TEMPLATE_NOT_FOUND, this.context.config.moduleName, templatePath);
}
const tpl = framework_1.PluginFileUtil.readFileSync(templatePath).toString();
const templateStr = ejs_1.default.render(tpl, templateModel);
const generatorFilePath = this.context.config.getGeneratedFilePath(templateModel.generatorViewName);
framework_1.PluginFileUtil.ensureFileSync(generatorFilePath);
framework_1.PluginFileUtil.writeFileSync(generatorFilePath, templateStr);
return this.context.config
.getBuilderFilePath(templateModel.generatorViewName)
.replaceAll(constants_1.FilePathConstants.FILE_SEPARATOR, constants_1.FilePathConstants.DELIMITER);
}
detectLibraryVersion() {
let libraryVersion = '';
const possiblePaths = this.getLibraryPossiblePaths();
for (const packagePath of possiblePaths) {
libraryVersion = this.detectLibraryVersion2(packagePath);
if (libraryVersion) {
break;
}
}
return libraryVersion;
}
detectLibraryVersion2(lockFilePath) {
try {
if (!framework_1.PluginFileUtil.exist(lockFilePath)) {
return '';
}
const lockFileData = framework_1.PluginFileUtil.readJson5(lockFilePath);
return this.extractHMRouterVersion(lockFileData.packages);
}
catch (error) {
return '';
}
}
extractHMRouterVersion(packages) {
if (!packages) {
return '';
}
const hmrouterPrefix = `${constants_1.VersionConstants.HMROUTER_ORGANIZATION}/${constants_1.VersionConstants.HMROUTER_LIB_NAME}@`;
for (const key of Object.keys(packages)) {
if (!key.startsWith(hmrouterPrefix)) {
continue;
}
const packageInfo = packages[key];
if (packageInfo && packageInfo[constants_1.VersionConstants.HMROUTER_VERSION_KEY]) {
return packageInfo[constants_1.VersionConstants.HMROUTER_VERSION_KEY];
}
}
return '';
}
getLibraryPossiblePaths() {
const paths = [];
paths.push(framework_1.PluginFileUtil.pathResolve(this.context.config.modulePath, constants_1.FilePathConstants.OH_PACKAGE_LOCK_FILE_NAME));
const projectRoot = framework_1.PluginStore.getInstance().get('projectFilePath');
if (projectRoot && projectRoot !== this.context.config.modulePath) {
paths.push(framework_1.PluginFileUtil.pathResolve(projectRoot, constants_1.FilePathConstants.OH_PACKAGE_LOCK_FILE_NAME));
}
return paths;
}
parseVersion(version) {
const match = version.match(/^(\d+)\.(\d+)\.(\d+)(-.*)?/);
if (!match) {
return null;
}
return {
major: parseInt(match[1], 10),
minor: parseInt(match[2], 10),
patch: parseInt(match[3], 10),
preRelease: match[4] || '',
};
}
compareVersions(v1, v2) {
if (v1.major !== v2.major) {
return v1.major < v2.major ? -1 : 1;
}
if (v1.minor !== v2.minor) {
return v1.minor < v2.minor ? -1 : 1;
}
if (v1.patch !== v2.patch) {
return v1.patch < v2.patch ? -1 : 1;
}
if (v1.preRelease && !v2.preRelease) {
return -1;
}
if (!v1.preRelease && v2.preRelease) {
return 1;
}
if (v1.preRelease < v2.preRelease) {
return -1;
}
if (v1.preRelease > v2.preRelease) {
return 1;
}
return 0;
}
}
exports.CodeGenerationProcessor = CodeGenerationProcessor;