feat(developer): use CompilerEvent for messages in all of kmc

Cleans up majority of remaining kmc-* modules to use CompilerEvent
messages instead of console.log and friends, adding
InfrastructureMessages class for kmc CLI messages.

Consolidates schema loading functions into a single `loadSchema`
function in the CompilerCallbacks interface and implementations.

Moves responsibility for instantiating NodeCompilerCallbacks out of
each individual BuildActivity and into higher level modules.

Fixes return value for failing builds.
This commit is contained in:
Marc Durdin 2023-04-24 07:26:43 +07:00
parent 34ae4a1397
commit cf4022ac8a
20 changed files with 171 additions and 128 deletions

View file

@ -18,7 +18,7 @@ export { default as LDMLKeyboardXMLSourceFileReader } from './ldml-keyboard/ldml
export * as Constants from './consts/virtual-key-constants.js';
export { CompilerCallbacks, CompilerEvent, CompilerErrorNamespace, CompilerErrorSeverity, CompilerMessageSpec, compilerErrorSeverityName } from './util/compiler-interfaces.js';
export { CompilerCallbacks, CompilerSchema, CompilerEvent, CompilerErrorNamespace, CompilerErrorSeverity, CompilerMessageSpec, compilerErrorSeverityName } from './util/compiler-interfaces.js';
export { CommonTypesMessages } from './util/common-events.js';
export * as TouchLayout from './keyman-touch-layout/keyman-touch-layout-file.js';

View file

@ -66,6 +66,13 @@ export enum CompilerErrorNamespace {
Infrastructure = 0x5000,
};
export type CompilerSchema =
'ldml-keyboard' |
'ldml-keyboardtest' |
'kvks' |
'kpj';
// | 'keyman-touch-layout.clean'; TODO this has the wrong name pattern, .spec.json instead of .schema.json
/**
* Abstract interface for callbacks, to abstract out file i/o
*/
@ -76,11 +83,9 @@ export interface CompilerCallbacks {
* @param filename
*/
loadFile(baseFilename: string, filename: string | URL): Buffer;
loadLdmlKeyboardSchema(): Buffer;
loadLdmlKeyboardTestSchema(): Buffer;
loadSchema(schema: CompilerSchema): Buffer;
reportMessage(event: CompilerEvent): void;
loadKvksJsonSchema(): Buffer;
loadKpjJsonSchema(): Buffer;
debug(msg: string): void;
};
/**

View file

@ -1,6 +1,7 @@
import path from "path";
import fs from "fs";
import { fileURLToPath } from "url";
import { CompilerSchema } from "../../src/util/compiler-interfaces.js";
/**
* Builds a path to the fixture with the given path components.
@ -13,11 +14,8 @@ export function makePathToFixture(...components: string[]): string {
return fileURLToPath(new URL(path.join('..', '..', '..', 'test', 'fixtures', ...components), import.meta.url));
}
export function loadKvksJsonSchema(): Buffer {
return fs.readFileSync(new URL(path.join('..', '..', 'src', 'kvks.schema.json'), import.meta.url));
}
export function loadKeymanTouchLayoutCleanJsonSchema(): Buffer {
// TODO: this has the Wrong Name Pattern!
return fs.readFileSync(new URL(path.join('..', '..', 'src', 'keyman-touch-layout.clean.spec.json'), import.meta.url));
}
@ -26,14 +24,6 @@ export function loadFile(baseFilename: string, filename: string | URL): Buffer {
return fs.readFileSync(filename);
}
export function loadLdmlKeyboardSchema(): Buffer {
return fs.readFileSync(new URL(path.join('..', '..', 'src', 'ldml-keyboard.schema.json'), import.meta.url));
}
export function loadLdmlKeyboardTestDataSchema(): Buffer {
return fs.readFileSync(new URL(path.join('..', '..', 'src', 'ldml-keyboardtest.schema.json'), import.meta.url));
}
export function loadKpjJsonSchema(): Buffer {
return fs.readFileSync(new URL(path.join('..', '..', 'src', 'kpj.schema.json'), import.meta.url));
export function loadSchema(schema: CompilerSchema): Buffer {
return fs.readFileSync(new URL(path.join('..', '..', 'src', schema + '.schema.json'), import.meta.url));
}

View file

@ -1,8 +1,8 @@
import 'mocha';
import {assert} from 'chai';
import {loadLdmlKeyboardSchema, loadFile, makePathToFixture, loadLdmlKeyboardTestDataSchema} from '../helpers/index.js';
import { loadFile, makePathToFixture, loadSchema } from '../helpers/index.js';
import LDMLKeyboardXMLSourceFileReader from '../../src/ldml-keyboard/ldml-keyboard-xml-reader.js';
import { CompilerCallbacks, CompilerEvent } from '../../src/util/compiler-interfaces.js';
import { CompilerCallbacks, CompilerEvent, CompilerSchema } from '../../src/util/compiler-interfaces.js';
import { LDMLKeyboardXMLSourceFile } from '../../src/ldml-keyboard/ldml-keyboard-xml.js';
import { LDMLKeyboardTestDataXMLSourceFile } from '../ldml-keyboard/ldml-keyboard-testdata-xml.js';
@ -13,21 +13,24 @@ import { LDMLKeyboardTestDataXMLSourceFile } from '../ldml-keyboard/ldml-keyboar
* A CompilerCallbacks implementation for testing
*/
class TestCompilerCallbacks implements CompilerCallbacks {
loadKpjJsonSchema(): Buffer {
throw new Error('loadKpjJsonSchema not implemented.'); // not needed for this test
}
loadLdmlKeyboardTestSchema(): Buffer {
return loadLdmlKeyboardTestDataSchema();
}
loadLdmlKeyboardSchema(): Buffer {
return loadLdmlKeyboardSchema();
}
loadKvksJsonSchema(): Buffer {
throw new Error('loadKvksJsonSchema not implemented.');
loadSchema(schema: CompilerSchema): Buffer {
switch(schema) {
case 'kpj':
throw new Error('loadKpjJsonSchema not implemented.'); // not needed for this test
case 'kvks':
throw new Error('loadKvksJsonSchema not implemented.');
case 'ldml-keyboard':
return loadSchema(schema);
case 'ldml-keyboardtest':
return loadSchema(schema);
}
}
clear() {
this.messages = [];
}
debug(msg: string): void {
console.debug(msg);
}
messages: CompilerEvent[] = [];
loadFile(baseFilename: string, filename: string | URL): Buffer {
try {
@ -128,9 +131,9 @@ export function testReaderCases(cases : CompilationCase[]) {
}
// special case for an expected exception
if (testcase.throws) {
assert.throws(() => reader.validate(source, loadLdmlKeyboardSchema()), testcase.throws);
assert.throws(() => reader.validate(source, loadSchema('ldml-keyboard')), testcase.throws);
} else {
assert.doesNotThrow(() => reader.validate(source, loadLdmlKeyboardSchema()), `validating ${testcase.subpath}`);
assert.doesNotThrow(() => reader.validate(source, loadSchema('ldml-keyboard')), `validating ${testcase.subpath}`);
// if we expected errors or warnings, show them
if (testcase.errors) {
assert.includeDeepMembers(callbacks.messages, testcase.errors, 'expected errors to be included');

View file

@ -1,5 +1,5 @@
import * as fs from 'fs';
import { CompilerEvent, CompilerCallbacks } from '@keymanapp/common-types';
import { CompilerEvent, CompilerCallbacks, CompilerSchema } from '@keymanapp/common-types';
// TODO: schemas are only used by kmc-keyboard for now, so this works at this
// time, but it's a little fragile if we need them elsewhere in the future
@ -9,10 +9,20 @@ const SCHEMA_BASE = '../../../../kmc-keyboard/build/src/';
* A CompilerCallbacks implementation for testing
*/
export class TestCompilerCallbacks implements CompilerCallbacks {
/* TestCompilerCallbacks */
messages: CompilerEvent[] = [];
clear() {
this.messages = [];
}
messages: CompilerEvent[] = [];
hasMessage(code: number): boolean {
return this.messages.find((item) => item.code == code) === undefined ? false : true;
}
/* CompilerCallbacks */
loadFile(baseFilename: string, filename: string | URL): Buffer {
// TODO: translate filename based on the baseFilename
try {
@ -25,23 +35,16 @@ export class TestCompilerCallbacks implements CompilerCallbacks {
}
}
}
hasMessage(code: number): boolean {
return this.messages.find((item) => item.code == code) === undefined ? false : true;
}
reportMessage(event: CompilerEvent): void {
// console.log(event.message);
this.messages.push(event);
}
loadLdmlKeyboardSchema(): Buffer {
return fs.readFileSync(new URL(SCHEMA_BASE + 'ldml-keyboard.schema.json', import.meta.url));
loadSchema(schema: CompilerSchema): Buffer {
return fs.readFileSync(new URL(SCHEMA_BASE + schema + '.schema.json', import.meta.url));
}
loadKvksJsonSchema(): Buffer {
return fs.readFileSync(new URL(SCHEMA_BASE + 'kvks.schema.json', import.meta.url));
}
loadKpjJsonSchema(): Buffer {
return fs.readFileSync(new URL(SCHEMA_BASE + 'kpj.schema.json', import.meta.url));
}
loadLdmlKeyboardTestSchema(): Buffer {
return fs.readFileSync(new URL(SCHEMA_BASE + 'ldml-keyboardtest.schema.json', import.meta.url));
debug(msg: string) {
console.debug(msg);
}
};

View file

@ -66,7 +66,7 @@ export default class Compiler {
return null;
}
try {
if (!reader.validate(source, this.callbacks.loadLdmlKeyboardSchema())) {
if (!reader.validate(source, this.callbacks.loadSchema('ldml-keyboard'))) {
return null;
}
} catch(e) {
@ -98,7 +98,7 @@ export default class Compiler {
// TODO-LDML: The unboxed data doesn't match the schema anymore. Skipping validation, for now.
// try {
// if (!reader.validate(source, this.callbacks.loadLdmlKeyboardTestSchema())) {
// if (!reader.validate(source, this.callbacks.loadSchema('ldml-keyboard-test'))) {
// return null;
// }
// } catch(e) {

View file

@ -54,7 +54,7 @@ export function loadSectionFixture(compilerClass: typeof SectionCompiler, filena
const source = reader.load(data);
assert.isNotNull(source);
if (!reader.validate(source, callbacks.loadLdmlKeyboardSchema())) {
if (!reader.validate(source, callbacks.loadSchema('ldml-keyboard'))) {
return null; // mimic kmc behavior - bail if validate fails
}

View file

@ -3,6 +3,8 @@ import { Command } from 'commander';
import { BuildActivityOptions } from './build/BuildActivity.js';
import { buildActivities } from './build/buildActivities.js';
import { BuildProject } from './build/BuildProject.js';
import { NodeCompilerCallbacks } from 'src/messages/NodeCompilerCallbacks.js';
import { InfrastructureMessages } from 'src/messages/messages.js';
export function declareBuild(program: Command) {
program
@ -13,43 +15,59 @@ export function declareBuild(program: Command) {
.option('--no-compiler-version', 'Exclude compiler version metadata from output')
.option('-w, --compiler-warnings-as-errors', 'Causes warnings to fail the build')
.option('--no-warn-deprecated-code', 'Turn off warnings for deprecated code styles')
.action((infiles: string[], options: any) => {
let p = [];
if(!infiles.length) {
console.debug('Assuming infile == .');
p.push(build('.', options));
.action(async (filenames: string[], options: any) => {
if(!filenames.length) {
// If there are no filenames provided, then we are building the current
// folder ('.') as a project-style build
filenames.push('.');
}
for(let infile of infiles) {
p.push(build(infile, options));
for(let filename of filenames) {
if(!await build(filename, options)) {
// Once a file fails to build, we bail on subsequent builds
// TODO: is this the most appropriate semantics?
process.exit(1);
}
}
return Promise.all(p).then();
});
}
async function build(infile: string, options: BuildActivityOptions): Promise<boolean> {
console.log(`Building ${infile}`);
async function build(filename: string, options: BuildActivityOptions): Promise<boolean> {
let callbacks = new NodeCompilerCallbacks();
if(!fs.existsSync(infile)) {
// TODO: consolidate errors
console.error(`File ${infile} does not exist`);
process.exit(2);
}
try {
callbacks.reportMessage(InfrastructureMessages.Info_BuildingFile({filename}));
// If infile is a directory, then we treat that as a project and build it
if(fs.statSync(infile).isDirectory()) {
return (new BuildProject()).build(infile, options);
}
// Otherwise, if it's one of our known file extensions, we build it
let extensions: string[] = [];
for(let build of buildActivities) {
if(infile.toLowerCase().endsWith(build.sourceExtension)) {
return build.build(infile, options);
if(!fs.existsSync(filename)) {
callbacks.reportMessage(InfrastructureMessages.Error_FileDoesNotExist({filename}));
return false;
}
extensions.push(build.sourceExtension);
}
// TODO: consolidate errors
console.error(`Unrecognised input file ${infile}, expecting ${extensions.join(', ')}, or project folder`);
process.exit(2);
let builder = null;
// If infile is a directory, then we treat that as a project and build it
if(fs.statSync(filename).isDirectory()) {
builder = new BuildProject();
} else {
// Otherwise, if it's one of our known file extensions, we build it
let extensions: string[] = [];
builder = buildActivities.find(build => { extensions.push(build.sourceExtension); return filename.toLowerCase().endsWith(build.sourceExtension) });
if(!builder) {
callbacks.reportMessage(InfrastructureMessages.Error_FileTypeNotRecognized({filename, extensions: extensions.join(', ')}));
return false;
}
}
let result = await builder.build(filename, callbacks, options);
if(result) {
callbacks.reportMessage(InfrastructureMessages.Info_FileBuiltSuccessfully({filename}));
} else {
callbacks.reportMessage(InfrastructureMessages.Info_FileNotBuiltSuccessfully({filename}));
}
return result;
} catch(e) {
callbacks.reportMessage(InfrastructureMessages.Fatal_UnexpectedException({e}));
return false;
}
}

View file

@ -1,3 +1,4 @@
import { CompilerCallbacks } from "@keymanapp/common-types";
import { escapeRegExp } from "../../util/escapeRegExp.js";
export interface BuildActivityOptions {
@ -13,7 +14,7 @@ export abstract class BuildActivity {
public abstract get sourceExtension(): string;
public abstract get compiledExtension(): string;
public abstract get description(): string;
public abstract build(infile: string, options: BuildActivityOptions): Promise<boolean>;
public abstract build(infile: string, callbacks: CompilerCallbacks, options: BuildActivityOptions): Promise<boolean>;
protected getOutputFilename(infile: string, options: BuildActivityOptions): string {
return options.outFile ?
options.outFile :

View file

@ -2,21 +2,19 @@ import * as path from 'path';
import { BuildActivity, BuildActivityOptions } from './BuildActivity.js';
import { Compiler } from '@keymanapp/kmc-kmn';
import { platform } from 'os';
import { NodeCompilerCallbacks } from '../../util/NodeCompilerCallbacks.js';
import { CompilerCallbacks } from '@keymanapp/common-types';
export class BuildKmnKeyboard extends BuildActivity {
public get name(): string { return 'Keyman keyboard'; }
public get sourceExtension(): string { return '.kmn'; }
public get compiledExtension(): string { return '.kmx'; }
public get description(): string { return 'Build a Keyman keyboard'; }
public async build(infile: string, options: BuildActivityOptions): Promise<boolean> {
public async build(infile: string, callbacks: CompilerCallbacks, options: BuildActivityOptions): Promise<boolean> {
let compiler = new Compiler();
if(!await compiler.init()) {
return false;
}
const callbacks = new NodeCompilerCallbacks();
// We need to resolve paths to absolute paths before calling kmc-kmn
let outfile = this.getOutputFilename(infile, options);

View file

@ -2,7 +2,6 @@ import * as path from 'path';
import * as fs from 'fs';
import * as kmc from '@keymanapp/kmc-keyboard';
import { KvkFileWriter, CompilerCallbacks } from '@keymanapp/common-types';
import { NodeCompilerCallbacks } from '../../util/NodeCompilerCallbacks.js';
import { BuildActivity, BuildActivityOptions } from './BuildActivity.js';
export class BuildLdmlKeyboard extends BuildActivity {
@ -10,10 +9,10 @@ export class BuildLdmlKeyboard extends BuildActivity {
public get sourceExtension(): string { return '.xml'; }
public get compiledExtension(): string { return '.kmx'; }
public get description(): string { return 'Build a LDML keyboard'; }
public async build(infile: string, options: BuildActivityOptions): Promise<boolean> {
public async build(infile: string, callbacks: CompilerCallbacks, options: BuildActivityOptions): Promise<boolean> {
// TODO-LDML: consider hardware vs touch -- touch-only layout will not have a .kvk
// Compile:
let [kmx,kvk,kmw] = buildLdmlKeyboardToMemory(infile, options);
let [kmx,kvk,kmw] = buildLdmlKeyboardToMemory(infile, callbacks, options);
// Output:
const fileBaseName = options.outFile ?? infile;
@ -43,7 +42,7 @@ export class BuildLdmlKeyboard extends BuildActivity {
}
}
function buildLdmlKeyboardToMemory(inputFilename: string, options: BuildActivityOptions): [Uint8Array, Uint8Array, Uint8Array] {
function buildLdmlKeyboardToMemory(inputFilename: string, callbacks: CompilerCallbacks, options: BuildActivityOptions): [Uint8Array, Uint8Array, Uint8Array] {
let compilerOptions: kmc.CompilerOptions = {
debug: options.debug ?? false,
addCompilerVersion: options.compilerVersion ?? true,
@ -51,8 +50,7 @@ function buildLdmlKeyboardToMemory(inputFilename: string, options: BuildActivity
// TODO: treatWarningsAsErrors: options.treatWarningsAsErrors,
}
const c: CompilerCallbacks = new NodeCompilerCallbacks();
const k = new kmc.Compiler(c, options);
const k = new kmc.Compiler(callbacks, options);
let source = k.load(inputFilename);
if (!source) {
return [null, null, null];

View file

@ -1,19 +1,17 @@
import * as fs from 'fs';
import { BuildActivity, BuildActivityOptions } from './BuildActivity.js';
import { compileModel } from '@keymanapp/kmc-model';
import { NodeCompilerCallbacks } from '../../util/NodeCompilerCallbacks.js';
import { CompilerCallbacks } from '@keymanapp/common-types';
export class BuildModel extends BuildActivity {
public get name(): string { return 'Lexical model'; }
public get sourceExtension(): string { return '.model.ts'; }
public get compiledExtension(): string { return '.model.js'; }
public get description(): string { return 'Build a lexical model'; }
public async build(infile: string, options: BuildActivityOptions): Promise<boolean> {
public async build(infile: string, callbacks: CompilerCallbacks, options: BuildActivityOptions): Promise<boolean> {
let outputFilename: string = this.getOutputFilename(infile, options);
let code = null;
const callbacks = new NodeCompilerCallbacks();
// Compile:
try {
code = compileModel(infile, callbacks);

View file

@ -2,15 +2,13 @@ import * as fs from 'fs';
import { BuildActivity, BuildActivityOptions } from './BuildActivity.js';
import KmpCompiler from '@keymanapp/kmc-package';
import { CompilerCallbacks } from '@keymanapp/common-types';
import { NodeCompilerCallbacks } from '../../util/NodeCompilerCallbacks.js';
export class BuildPackage extends BuildActivity {
public get name(): string { return 'Package'; }
public get sourceExtension(): string { return '.kps'; }
public get compiledExtension(): string { return '.kmp'; }
public get description(): string { return 'Build a Keyman package'; }
public async build(infile: string, options: BuildActivityOptions): Promise<boolean> {
const c: CompilerCallbacks = new NodeCompilerCallbacks();
public async build(infile: string, callbacks: CompilerCallbacks, options: BuildActivityOptions): Promise<boolean> {
const outfile = this.getOutputFilename(infile, options);
@ -19,7 +17,7 @@ export class BuildPackage extends BuildActivity {
//
const kpsString: string = fs.readFileSync(infile, 'utf8');
const kmpCompiler = new KmpCompiler(c);
const kmpCompiler = new KmpCompiler(callbacks);
const kmpJsonData = kmpCompiler.transformKpsToKmpObject(kpsString, infile);
if(!kmpJsonData) {
return false;

View file

@ -1,10 +1,10 @@
import * as path from 'path';
import * as fs from 'fs';
import { CompilerCallbacks, KeymanDeveloperProject, KPJFileReader } from '@keymanapp/common-types';
import { NodeCompilerCallbacks } from '../../util/NodeCompilerCallbacks.js';
import { KeymanDeveloperProjectFile } from '../../../../../../common/web/types/src/kpj/keyman-developer-project.js';
import { BuildActivity, BuildActivityOptions } from './BuildActivity.js';
import { buildActivities } from './buildActivities.js';
import { InfrastructureMessages } from 'src/messages/messages.js';
const PROJECT_EXTENSION = '.kpj';
@ -13,27 +13,27 @@ export class BuildProject extends BuildActivity {
public get sourceExtension(): string { return PROJECT_EXTENSION; }
public get compiledExtension(): string { return null; }
public get description(): string { return 'Build a keyboard or lexical model project'; }
public async build(infile: string, options: BuildActivityOptions): Promise<boolean> {
let builder = new ProjectBuilder(infile, options);
public async build(infile: string, callbacks: CompilerCallbacks, options: BuildActivityOptions): Promise<boolean> {
let builder = new ProjectBuilder(infile, callbacks, options);
return builder.run();
}
}
class ProjectBuilder {
callbacks: CompilerCallbacks = new NodeCompilerCallbacks();
callbacks: CompilerCallbacks;
infile: string;
options: BuildActivityOptions;
project: KeymanDeveloperProject;
constructor(infile: string, options: BuildActivityOptions) {
constructor(infile: string, callbacks: CompilerCallbacks, options: BuildActivityOptions) {
this.infile = path.resolve(infile);
this.callbacks = callbacks;
this.options = options;
}
async run(): Promise<boolean> {
if(this.options.outFile) {
// TODO: callbacks.reportMessage
console.error('--out-file should not be specified for project builds');
this.callbacks.reportMessage(InfrastructureMessages.Error_OutFileNotValidForProjects());
return false;
}
@ -90,7 +90,7 @@ class ProjectBuilder {
const kpjData = this.callbacks.loadFile(null, this.infile);
const reader = new KPJFileReader();
const kpj = reader.read(kpjData);
const schema = this.callbacks.loadKpjJsonSchema();
const schema = this.callbacks.loadSchema('kpj');
try {
reader.validate(kpj, schema);
} catch(e) {
@ -121,7 +121,7 @@ class ProjectBuilder {
fs.mkdirSync(path.dirname(options.outFile), {recursive:true});
let result = await activity.build(infile, options);
let result = await activity.build(infile, this.callbacks, options);
if(result) {
console.log(`${path.basename(infile )} built successfully.`);
} else {

View file

@ -2,7 +2,7 @@ import * as fs from 'fs';
import * as path from 'path';
import * as kmc from '@keymanapp/kmc-keyboard';
import { CompilerCallbacks, LDMLKeyboardTestDataXMLSourceFile } from '@keymanapp/common-types';
import { NodeCompilerCallbacks } from '../../util/NodeCompilerCallbacks.js';
import { NodeCompilerCallbacks } from '../../messages/NodeCompilerCallbacks.js';
export interface BuildTestDataOptions {
outFile?: string;

View file

@ -8,7 +8,7 @@ import { Command } from 'commander';
import { compileModel } from '@keymanapp/kmc-model';
import { SysExits } from './util/sysexits.js';
import KEYMAN_VERSION from "@keymanapp/keyman-version";
import { NodeCompilerCallbacks } from './util/NodeCompilerCallbacks.js';
import { NodeCompilerCallbacks } from './messages/NodeCompilerCallbacks.js';
let inputFilename: string;
const program = new Command();

View file

@ -10,7 +10,7 @@ import KmpCompiler from '@keymanapp/kmc-package';
import { ModelInfoOptions as ModelInfoOptions, writeMergedModelMetadataFile } from '@keymanapp/kmc-model-info';
import { SysExits } from './util/sysexits.js';
import KEYMAN_VERSION from "@keymanapp/keyman-version";
import { NodeCompilerCallbacks } from './util/NodeCompilerCallbacks.js';
import { NodeCompilerCallbacks } from './messages/NodeCompilerCallbacks.js';
let inputFilename: string;
const program = new Command();

View file

@ -8,7 +8,7 @@ import { Command } from 'commander';
import KmpCompiler from '@keymanapp/kmc-package';
import { SysExits } from './util/sysexits.js';
import KEYMAN_VERSION from "@keymanapp/keyman-version";
import { NodeCompilerCallbacks } from './util/NodeCompilerCallbacks.js';
import { NodeCompilerCallbacks } from './messages/NodeCompilerCallbacks.js';
let inputFilename: string;
const program = new Command();

View file

@ -1,5 +1,5 @@
import * as fs from 'fs';
import { CompilerCallbacks, CompilerEvent, compilerErrorSeverityName } from '@keymanapp/common-types';
import { CompilerCallbacks, CompilerSchema, CompilerEvent, compilerErrorSeverityName } from '@keymanapp/common-types';
/**
* Concrete implementation for CLI use
@ -27,20 +27,12 @@ export class NodeCompilerCallbacks implements CompilerCallbacks {
}
}
loadLdmlKeyboardSchema(): Buffer {
let schemaPath = new URL('ldml-keyboard.schema.json', import.meta.url);
return fs.readFileSync(schemaPath);
debug(msg: string) {
console.debug(msg);
}
loadLdmlKeyboardTestSchema(): Buffer {
let schemaPath = new URL('ldml-keyboardtest.schema.json', import.meta.url);
return fs.readFileSync(schemaPath);
}
loadKvksJsonSchema(): Buffer {
let schemaPath = new URL('kvks.schema.json', import.meta.url);
return fs.readFileSync(schemaPath);
}
loadKpjJsonSchema(): Buffer {
let schemaPath = new URL('kpj.schema.json', import.meta.url);
loadSchema(schema: CompilerSchema) {
let schemaPath = new URL(schema + '.schema.json', import.meta.url);
return fs.readFileSync(schemaPath);
}
}

View file

@ -0,0 +1,39 @@
import { CompilerErrorNamespace, CompilerErrorSeverity, CompilerMessageSpec as m } from "@keymanapp/common-types";
const Namespace = CompilerErrorNamespace.Infrastructure;
const SevInfo = CompilerErrorSeverity.Info | Namespace;
// const SevHint = CompilerErrorSeverity.Hint | Namespace;
// const SevWarn = CompilerErrorSeverity.Warn | Namespace;
const SevError = CompilerErrorSeverity.Error | Namespace;
const SevFatal = CompilerErrorSeverity.Fatal | Namespace;
export class InfrastructureMessages {
static Fatal_UnexpectedException = (o:{e: any}) => m(this.FATAL_UnexpectedException,
`Unexpected exception: ${(o.e ?? 'unknown error').toString()}\n\nCall stack:\n${(o.e instanceof Error ? o.e.stack : (new Error()).stack)}`);
static FATAL_UnexpectedException = SevFatal | 0x0001;
static Info_BuildingFile = (o:{filename:string}) => m(this.INFO_BuildingFile,
`Building ${o.filename}`);
static INFO_BuildingFile = SevInfo | 0x0002;
static Error_FileDoesNotExist = (o:{filename:string}) => m(this.ERROR_FileDoesNotExist,
`File ${o.filename} does not exist`);
static ERROR_FileDoesNotExist = SevError | 0x0003;
static Error_FileTypeNotRecognized = (o:{filename: string, extensions: string}) => m(this.ERROR_FileTypeNotRecognized,
`Unrecognised input file ${o.filename}, expecting ${o.extensions}, or project folder`);
static ERROR_FileTypeNotRecognized = SevError | 0x0004;
static Error_OutFileNotValidForProjects = () => m(this.ERROR_OutFileNotValidForProjects,
`--out-file should not be specified for project builds`);
static ERROR_OutFileNotValidForProjects = SevError | 0x0005;
static Info_FileBuiltSuccessfully = (o:{filename:string}) => m(this.INFO_FileBuiltSuccessfully,
`${o.filename} built successfully.`);
static INFO_FileBuiltSuccessfully = SevInfo | 0x0006;
static Info_FileNotBuiltSuccessfully = (o:{filename:string}) => m(this.INFO_FileNotBuiltSuccessfully,
`${o.filename} failed to build.`);
static INFO_FileNotBuiltSuccessfully = SevInfo | 0x0007;
}