@keymanapp/kmc
Version:
Keyman Developer compiler command line tools
117 lines • 5.61 kB
JavaScript
import * as path from 'path';
import * as fs from 'fs';
import { CompilerFileCallbacks } from '@keymanapp/developer-utils';
import { KeymanDeveloperProjectType } from '@keymanapp/developer-utils';
import { BuildActivity } from './BuildActivity.js';
import { buildActivities, buildKeyboardInfoActivity, buildModelInfoActivity } from './buildActivities.js';
import { InfrastructureMessages } from '../../messages/infrastructureMessages.js';
import { loadProject } from '../../util/projectLoader.js';
import { getOption } from '@keymanapp/developer-utils';
export class BuildProject extends BuildActivity {
get name() { return 'Project'; }
get sourceExtension() { return ".kpj" /* KeymanFileTypes.Source.Project */; }
get compiledExtension() { return null; }
get description() { return 'Build a keyboard or lexical model project'; }
async build(infile, outfile, callbacks, options) {
if (outfile) {
callbacks.reportMessage(InfrastructureMessages.Error_OutFileNotValidForProjects());
return false;
}
let builder = new ProjectBuilder(infile, callbacks, options);
return builder.run();
}
}
class ProjectBuilder {
callbacks;
infile;
options;
project;
constructor(infile, callbacks, options) {
this.infile = path.resolve(infile);
this.callbacks = new CompilerFileCallbacks(infile, options, callbacks);
this.options = options;
}
async run() {
this.project = await loadProject(this.infile, this.callbacks);
if (!this.project) {
return false;
}
// Give a hint if the project is v1.0
if (this.project.options.version != '2.0') {
if (getOption("prompt to upgrade projects", true)) {
this.callbacks.reportMessage(InfrastructureMessages.Hint_ProjectIsVersion10());
}
}
// Go through the various file types and build them
for (let builder of buildActivities) {
if (builder.sourceExtension == ".kpj" /* KeymanFileTypes.Source.Project */) {
// We don't support nested projects
continue;
}
if (!await this.buildProjectTargets(builder)) {
return false;
}
}
// Build project metadata
if (this.options.forPublishing || !this.project.options.skipMetadataFiles) {
let activity = null;
// Determine activity type first of all by examining files in the project
// Then if that is inconclusive, examine the declared project type
if (this.project.isKeyboardProject()) {
activity = buildKeyboardInfoActivity;
}
else if (this.project.isLexicalModelProject()) {
activity = buildModelInfoActivity;
}
else if (this.project.options.projectType == KeymanDeveloperProjectType.Keyboard) {
activity = buildKeyboardInfoActivity;
}
else if (this.project.options.projectType == KeymanDeveloperProjectType.LexicalModel) {
activity = buildModelInfoActivity;
}
else {
// If we get here, then we are not sure what type of project this is, so
// we'll assume keyboard
activity = buildKeyboardInfoActivity;
}
if (!await (this.buildProjectTargets(activity))) {
return false;
}
}
return true;
}
async buildProjectTargets(activity) {
if (activity.sourceExtension == ".kpj" /* KeymanFileTypes.Source.Project */) {
return await this.buildTarget(this.project.projectFile, activity);
}
let result = true;
for (let file of this.project.files) {
if (file.fileType.toLowerCase() == activity.sourceExtension) {
result = await this.buildTarget(file, activity) && result;
}
}
return result;
}
async buildTarget(file, activity) {
const options = { ...this.options };
const outfile = this.project.resolveOutputFilePath(file, activity.sourceExtension, activity.compiledExtension);
options.checkFilenameConventions = this.project.options.checkFilenameConventions ?? this.options.checkFilenameConventions;
const infile = this.project.resolveInputFilePath(file);
const buildFilename = path.relative(process.cwd(), infile).replace(/\\/g, '/');
const callbacks = new CompilerFileCallbacks(buildFilename, options, this.callbacks);
callbacks.reportMessage(InfrastructureMessages.Info_BuildingFile({ filename: infile, relativeFilename: buildFilename }));
fs.mkdirSync(path.dirname(outfile), { recursive: true });
let result = await activity.build(infile, outfile, callbacks, options);
// check if we had a message that causes the build to be a failure
// note: command line option here, if set, overrides project setting
result = result && !callbacks.hasFailureMessage(this.options.compilerWarningsAsErrors ?? this.project.options.compilerWarningsAsErrors);
if (result) {
callbacks.reportMessage(InfrastructureMessages.Info_FileBuiltSuccessfully({ filename: infile, relativeFilename: buildFilename }));
}
else {
callbacks.reportMessage(InfrastructureMessages.Info_FileNotBuiltSuccessfully({ filename: infile, relativeFilename: buildFilename }));
}
return result;
}
}
//# sourceMappingURL=BuildProject.js.map