@pmouli/isy-matter-server
Version:
Service to expose an ISY device as a Matter Border router
483 lines (417 loc) • 30.4 kB
text/typescript
import { type Node, createWrappedNode, IndentationText, Project, QuoteKind, ScriptTarget, SourceFile, TextChange } from 'ts-morph';
import ts, { type Declaration, factory, idText, Statement } from 'typescript';
import type { Driver } from '../Definitions/Global/Drivers.js';
import { UnitOfMeasure } from '../Definitions/Global/UOM.js';
import { types } from 'util';
import { Family } from '../Definitions/index.js';
import { CommandDefinition, DataTypeDefinition, DriverDefinition, NodeClassDefinition, ParameterDefinition } from '../Model/ClassDefinition.js';
import { EnumDefinitionMap } from '../Model/EnumDefinition.js';
import { CodeFactory } from './CodeFactory.js';
import { createMemberName } from './EnumFactory.js';
// #region Type aliases (1)
type GeneratedNodeClass<T extends Family> = {
family: T;
name: string;
id: string;
path: string;
statements: any;
sourceFile: SourceFile;
};
// #endregion Type aliases (1)
// #region Classes (1)
export class NodeClassFactory extends CodeFactory {
// #region Properties (2)
public static _basePath: string;
public static project = new Project({
//@ts-ignore
compilerOptions: { target: ScriptTarget.ESNext, module: ts.ModuleKind.Node18 },
manipulationSettings: {
usePrefixAndSuffixTextForRename: true,
quoteKind: QuoteKind.Single,
useTrailingCommas: false,
indentationText: IndentationText.Tab,
newLineKind: ts.NewLineKind.CarriageReturnLineFeed,
insertSpaceAfterOpeningAndBeforeClosingNonemptyBraces: true
}
});
static instance: NodeClassFactory = new NodeClassFactory(ts.factory);
// #endregion Properties (2)
// #region Public Static Getters And Setters (2)
public static get basePath() {
return (this._basePath ??= './');
}
public static set basePath(value: string) {
this._basePath = value;
}
// #endregion Public Static Getters And Setters (2)
// #region Public Static Methods (4)
public static buildNodeClasses<T extends Family>(map: { [x: string]: NodeClassDefinition<T> }): GeneratedNodeClass<T>[] {
return Object.values(map)
.filter((p) => !p.equivalentTo)
.map((p) => {
try {
return NodeClassFactory.instance.createNodeClass(p);
} catch (e) {
console.error(e);
}
});
}
public createNodeClass<T extends Family>(nodeClassDef: NodeClassDefinition<T>) {
let path = `${NodeClassFactory.basePath}/${Family[nodeClassDef.family]}/Generated/${nodeClassDef.name}.ts`;
let sf = ts.createSourceFile(path, '', ts.ScriptTarget.ES2024, true, ts.ScriptKind.TS);
//@ts-expect-error
sf.statements = [
this.createImportDeclaration('../../../Definitions/Global/index.js', ['Family', ' UnitOfMeasure']),
this.createImportDeclaration('../../../Model/NodeInfo.js', ['NodeInfo'], true),
this.createImportDeclaration('../../../ISY.js', ['ISY']),
this.createImportDeclaration('../../../ISYNode.js', ['ISYNode']),
this.createImportDeclaration('../../ISYDeviceNode.js', ['ISYDeviceNode']),
this.createImportDeclaration('../index.js', ['Base']),
this.createImportDeclaration('../../../Definitions/Global/Drivers.js', ['Driver']),
this.createImportDeclaration('type-fest', ['IntRange'], true),
this.createImportDeclaration('../../../Model/DriverState,js', ['DriverState'], true),
factory.createImportDeclaration(undefined, factory.createImportClause(false, undefined, factory.createNamedImports([factory.createImportSpecifier(false, undefined, factory.createIdentifier(Family[nodeClassDef.family]))])), factory.createStringLiteral('../../../Definitions/index.js'), undefined),
this.createImportDeclaration('../../NodeFactory.js', ['NodeFactory']),
factory.createVariableStatement(undefined, factory.createVariableDeclarationList([factory.createVariableDeclaration(factory.createIdentifier('nodeDefId'), undefined, undefined, factory.createStringLiteral(nodeClassDef.id))], ts.NodeFlags.Const)),
factory.createTypeAliasDeclaration(undefined, factory.createIdentifier('Commands'), undefined, factory.createTypeReferenceNode(this.createQualifiedName(nodeClassDef.name, 'Commands', 'Type'))),
factory.createTypeAliasDeclaration(undefined, factory.createIdentifier('Drivers'), undefined, factory.createTypeReferenceNode(this.createQualifiedName(nodeClassDef.name, 'Drivers', 'Type'), undefined)),
factory.createClassDeclaration(
[factory.createToken(ts.SyntaxKind.ExportKeyword)],
factory.createIdentifier(`${nodeClassDef.name}`),
undefined,
[factory.createHeritageClause(ts.SyntaxKind.ExtendsKeyword, [factory.createExpressionWithTypeArguments(factory.createIdentifier('Base'), [factory.createTypeReferenceNode(factory.createIdentifier('Drivers'), undefined), factory.createTypeReferenceNode(factory.createIdentifier('Commands'), undefined)])]), factory.createHeritageClause(ts.SyntaxKind.ImplementsKeyword, [factory.createExpressionWithTypeArguments(factory.createPropertyAccessExpression(factory.createIdentifier(nodeClassDef.name), factory.createIdentifier('Interface')), undefined)])],
[
factory.createPropertyDeclaration([factory.createToken(ts.SyntaxKind.PublicKeyword), factory.createToken(ts.SyntaxKind.OverrideKeyword), factory.createToken(ts.SyntaxKind.ReadonlyKeyword)], factory.createIdentifier('commands'), undefined, undefined, factory.createObjectLiteralExpression([...Object.values(nodeClassDef.commands).map((c) => factory.createPropertyAssignment(factory.createIdentifier(c.id), factory.createPropertyAccessExpression(factory.createThis(), factory.createIdentifier(c.name))))], true)),
// factory.createPropertyDeclaration(
// [factory.createToken(ts.SyntaxKind.PublicKeyword)],
// factory.createIdentifier("drivers"),
// undefined,
// factory.createTypeReferenceNode(factory.createIdentifier("Drivers"), undefined),
// factory.createObjectLiteralExpression([], false)
// ),
factory.createPropertyDeclaration([factory.createToken(ts.SyntaxKind.StaticKeyword), factory.createToken(ts.SyntaxKind.OverrideKeyword)], factory.createIdentifier('nodeDefId'), undefined, undefined, factory.createStringLiteral(nodeClassDef.id)),
NodeClassFactory.instance.createPropertyDeclaration('implements', factory.createArrayLiteralExpression(nodeClassDef.implementedBy ? [NodeClassFactory.instance.createStringLiteral(nodeClassDef.id)].concat(!nodeClassDef.implements || nodeClassDef.implements.length == 0 ? [] : nodeClassDef.implements?.map((p) => factory.createStringLiteral(p))) : [NodeClassFactory.instance.createStringLiteral(nodeClassDef.id)]), NodeClassFactory.instance.createModifiers(ts.ModifierFlags.Static | ts.ModifierFlags.Override)),
factory.createPropertyDeclaration([factory.createToken(ts.SyntaxKind.DeclareKeyword), factory.createToken(ts.SyntaxKind.ReadonlyKeyword)], factory.createIdentifier('nodeDefId'), undefined, nodeClassDef.equivalents ? NodeClassFactory.instance.createUnionTypeNode(...[NodeClassFactory.instance.createLiteralTypeNode(nodeClassDef.id)].concat(!nodeClassDef.equivalents || nodeClassDef.equivalents.length == 0 ? [] : nodeClassDef.equivalents?.map((p) => factory.createLiteralTypeNode(factory.createStringLiteral(p))))) : NodeClassFactory.instance.createLiteralTypeNode(nodeClassDef.id), undefined),
factory.createConstructorDeclaration(undefined, [factory.createParameterDeclaration(undefined, undefined, factory.createIdentifier('isy'), undefined, factory.createTypeReferenceNode(factory.createIdentifier('ISY'), undefined), undefined), factory.createParameterDeclaration(undefined, undefined, factory.createIdentifier('nodeInfo'), undefined, factory.createTypeReferenceNode(factory.createIdentifier('NodeInfo'), [this.createTypeReferenceNode(Family[nodeClassDef.family], 'Family')]), undefined)], factory.createBlock([factory.createExpressionStatement(factory.createCallExpression(factory.createSuper(), undefined, [factory.createIdentifier('isy'), factory.createIdentifier('nodeInfo')])), ...Object.values(nodeClassDef.drivers).map((p) => NodeClassFactory.instance.createDriverInitializationStatement(p))], true)),
...Object.values(nodeClassDef.commands).map((p) => NodeClassFactory.instance.createCommandMethodDeclaration(p)),
...Object.values(nodeClassDef.drivers).map((p) => NodeClassFactory.instance.createDriverGetDeclaration(p))
]
),
factory.createExpressionStatement(factory.createCallExpression(factory.createPropertyAccessExpression(factory.createIdentifier('NodeFactory'), factory.createIdentifier('register')), undefined, [factory.createIdentifier(`${nodeClassDef.name}`)])),
...(nodeClassDef.equivalents ? nodeClassDef.equivalents?.map((p) => factory.createExpressionStatement(factory.createCallExpression(factory.createPropertyAccessExpression(factory.createIdentifier('NodeFactory'), factory.createIdentifier('register')), undefined, [factory.createIdentifier(`${nodeClassDef.name}`), factory.createStringLiteral(p)]))) : []),
factory.createModuleDeclaration(
[factory.createToken(ts.SyntaxKind.ExportKeyword)],
factory.createIdentifier(nodeClassDef.name),
factory.createModuleBlock([
factory.createInterfaceDeclaration(
[factory.createToken(ts.SyntaxKind.ExportKeyword)],
factory.createIdentifier('Interface'),
undefined,
[factory.createHeritageClause(ts.SyntaxKind.ExtendsKeyword, [factory.createExpressionWithTypeArguments(factory.createIdentifier('Omit'), [NodeClassFactory.instance.createTypeReferenceNode('InstanceType', NodeClassFactory.instance.factory.createTypeQueryNode(factory.createIdentifier(`${nodeClassDef.name}`))), factory.createTypeOperatorNode(ts.SyntaxKind.KeyOfKeyword, factory.createTypeReferenceNode(factory.createIdentifier('ISYDeviceNode'), [factory.createKeywordTypeNode(ts.SyntaxKind.AnyKeyword), factory.createKeywordTypeNode(ts.SyntaxKind.AnyKeyword), factory.createKeywordTypeNode(ts.SyntaxKind.AnyKeyword), factory.createKeywordTypeNode(ts.SyntaxKind.AnyKeyword)]))])])],
[
/*factory.createPropertySignature(
undefined,
factory.createIdentifier('nodeDefId'),
undefined,
nodeClassDef.equivalents ?
NodeClassFactory.instance.createUnionTypeNode(
...[NodeClassFactory.instance.createLiteralTypeNode(nodeClassDef.id)].concat(
!nodeClassDef.equivalents || nodeClassDef.equivalents.length == 0 ? [] : nodeClassDef.equivalents?.map((p) => factory.createLiteralTypeNode(factory.createStringLiteral(p)))
)
)
: NodeClassFactory.instance.createLiteralTypeNode(nodeClassDef.id)
)*/
]
),
factory.createFunctionDeclaration(
[factory.createToken(ts.SyntaxKind.ExportKeyword)],
undefined,
factory.createIdentifier('is'),
undefined,
[factory.createParameterDeclaration(undefined, undefined, factory.createIdentifier('node'), undefined, factory.createTypeReferenceNode(factory.createIdentifier('ISYNode'), [factory.createKeywordTypeNode(ts.SyntaxKind.AnyKeyword), factory.createKeywordTypeNode(ts.SyntaxKind.AnyKeyword), factory.createKeywordTypeNode(ts.SyntaxKind.AnyKeyword), factory.createKeywordTypeNode(ts.SyntaxKind.AnyKeyword)]), undefined)],
factory.createTypePredicateNode(undefined, factory.createIdentifier('node'), factory.createTypeReferenceNode(factory.createIdentifier(`${nodeClassDef.name}`), undefined)),
NodeClassFactory.instance.createBlock(true, NodeClassFactory.instance.createReturnStatement(factory.createCallExpression(factory.createPropertyAccessExpression(factory.createArrayLiteralExpression(nodeClassDef.equivalents ? [NodeClassFactory.instance.createStringLiteral(nodeClassDef.id)].concat(!nodeClassDef.equivalents || nodeClassDef.equivalents.length == 0 ? [] : nodeClassDef.equivalents?.map((p) => factory.createStringLiteral(p))) : [NodeClassFactory.instance.createStringLiteral(nodeClassDef.id)]), 'includes'), undefined, [factory.createPropertyAccessExpression(factory.createIdentifier('node'), factory.createIdentifier('nodeDefId'))])))
),
factory.createFunctionDeclaration(
[factory.createToken(ts.SyntaxKind.ExportKeyword)],
undefined,
factory.createIdentifier('isImplementedBy'),
undefined,
[factory.createParameterDeclaration(undefined, undefined, factory.createIdentifier('node'), undefined, NodeClassFactory.instance.createTypeReferenceNode('ISYNode', NodeClassFactory.instance.createKeywordTypeNode(ts.SyntaxKind.AnyKeyword), NodeClassFactory.instance.createKeywordTypeNode(ts.SyntaxKind.AnyKeyword), NodeClassFactory.instance.createKeywordTypeNode(ts.SyntaxKind.AnyKeyword), NodeClassFactory.instance.createKeywordTypeNode(ts.SyntaxKind.AnyKeyword)), undefined)],
factory.createTypePredicateNode(undefined, factory.createIdentifier('node'), factory.createTypeReferenceNode(factory.createIdentifier(`${nodeClassDef.name}`), undefined)),
NodeClassFactory.instance.createBlock(
true,
factory.createReturnStatement(factory.createCallExpression(factory.createPropertyAccessExpression(factory.createArrayLiteralExpression(nodeClassDef.implementedBy ? [NodeClassFactory.instance.createStringLiteral(nodeClassDef.id)].concat(!nodeClassDef.implementedBy || nodeClassDef.implementedBy.length == 0 ? [] : nodeClassDef.implementedBy?.map((p) => factory.createStringLiteral(p))) : [NodeClassFactory.instance.createStringLiteral(nodeClassDef.id)]), 'includes'), undefined, [factory.createPropertyAccessExpression(factory.createIdentifier('node'), factory.createIdentifier('nodeDefId'))]))
)
),
factory.createFunctionDeclaration([factory.createToken(ts.SyntaxKind.ExportKeyword)], undefined, factory.createIdentifier('create'), undefined, [factory.createParameterDeclaration(undefined, undefined, factory.createIdentifier('isy'), undefined, factory.createTypeReferenceNode(factory.createIdentifier('ISY'), undefined), undefined), factory.createParameterDeclaration(undefined, undefined, factory.createIdentifier('nodeInfo'), undefined, factory.createTypeReferenceNode(factory.createIdentifier('NodeInfo'), [this.createTypeReferenceNode(Family[nodeClassDef.family], 'Family')]), undefined)], undefined, factory.createBlock([factory.createReturnStatement(factory.createNewExpression(factory.createIdentifier(`${nodeClassDef.name}`), undefined, [factory.createIdentifier('isy'), factory.createIdentifier('nodeInfo')]))], true)),
factory.createVariableStatement([factory.createToken(ts.SyntaxKind.ExportKeyword)], factory.createVariableDeclarationList([factory.createVariableDeclaration(factory.createIdentifier('Node'), undefined, undefined, factory.createIdentifier(`${nodeClassDef.name}`))], ts.NodeFlags.Const)),
this.createVariableStatement(
'Class',
factory.createIdentifier(`${nodeClassDef.name}`),
true
),
this.createModuleDeclaration('Commands', this.createModuleBlock(factory.createTypeAliasDeclaration([factory.createToken(ts.SyntaxKind.ExportKeyword)], factory.createIdentifier('Type'), undefined, factory.createTypeLiteralNode([...Object.values(nodeClassDef.commands).map(NodeClassFactory.instance.createCommandSignature)]))), ts.ModifierFlags.Export),
this.factory.createEnumDeclaration([factory.createToken(ts.SyntaxKind.ExportKeyword)], factory.createIdentifier('Commands'), [...Object.values(nodeClassDef.commands).map((p) => factory.createEnumMember(p.name, this.createLiteral(p.id)))]),
this.createModuleDeclaration('Drivers', this.createModuleBlock(factory.createTypeAliasDeclaration([factory.createToken(ts.SyntaxKind.ExportKeyword)], factory.createIdentifier('Type'), undefined, factory.createTypeLiteralNode([...Object.values(nodeClassDef.drivers).map(NodeClassFactory.instance.createDriverSignature)]))), ts.ModifierFlags.Export),
this.factory.createEnumDeclaration([factory.createToken(ts.SyntaxKind.ExportKeyword)], factory.createIdentifier('Drivers'), [...Object.values(nodeClassDef.drivers).map((p) => factory.createEnumMember(p.name, this.createLiteral(p.id)))])
]),
ts.NodeFlags.Namespace
)
];
//let f = createWrappedNode(sf);
let p = ts.createPrinter({ newLine: ts.NewLineKind.LineFeed });
// p.printFile()
let f = NodeClassFactory.project.createSourceFile(path, p.printFile(sf), { overwrite: true });
f.formatText({
indentSize: 1,
insertSpaceAfterOpeningAndBeforeClosingNonemptyBraces: true,
insertSpaceAfterCommaDelimiter: true,
insertSpaceAfterSemicolonInForStatements: true,
insertSpaceBeforeAndAfterBinaryOperators: true,
insertSpaceAfterConstructor: true,
newLineCharacter: '\n',
trimTrailingWhitespace: true,
ensureNewLineAtEndOfFile: true,
indentStyle: ts.IndentStyle.Smart
});
f.fixUnusedIdentifiers();
let currentKind = ts.SyntaxKind.Unknown;
for (const s of f.getStatements()) {
if (currentKind.valueOf() != s.getKind().valueOf()) {
if (currentKind != ts.SyntaxKind.Unknown) {
s.prependWhitespace('\n');
}
currentKind = s.getKind().valueOf();
}
}
f.insertText(0, '/* THIS FILE WAS AUTOMATICALLY GENERATED. DO NOT EDIT DIRECTLY. */\n\n');
return {
family: nodeClassDef.family,
name: nodeClassDef.name,
id: nodeClassDef.id,
path,
statements: sf.statements,
sourceFile: f
};
}
public static generateAll(): { family: Family; path: string; statements: ts.Statement[] }[] {
let modules = [];
for (const family of NodeClassDefinition.Map.keys()) {
var t = this.generateClassesForFamily(family);
modules.push(NodeClassFactory.buildClassIndex(family, t));
}
return modules;
}
public static generateClassesForFamily<T extends Family>(family: T): GeneratedNodeClass<T>[] {
return NodeClassFactory.buildNodeClasses<T>(NodeClassDefinition.Map.get(family) as { [x: string]: NodeClassDefinition<T> });
}
// #region Functions (12)
static buildClassIndex<T extends Family>(family: T, classes: GeneratedNodeClass<T>[]) {
return {
family,
path: `/${Family[family]}/Generated/index.ts`,
statements: [...classes.map((p) => factory.createExportDeclaration(undefined, false, undefined, factory.createStringLiteral(`./${p.name}.js`), undefined))]
};
}
createCommandArguments(def: CommandDefinition) {
let c = [factory.createStringLiteral(def.id)];
let n = [];
let r: ParameterDefinition[] = [];
if (def.parameters) {
for (let p of def.parameters) {
let p2 = p;
if (!p2?.id || p2.id == 'value') {
n.push(this.createUOMParameterArgument(p2));
//.push(factory.createIdentifier(p2.name ?? 'value'));
} else {
r.push(p2);
}
}
}
let fnl = [
...c,
...n,
...(r.length > 0 ?
[
factory.createObjectLiteralExpression(
r.map((q) => factory.createPropertyAssignment(factory.createIdentifier(q.id ?? 'value'), this.createUOMParameterArgument(q))),
false
)
]
: [])
];
return fnl.length > 0 ? fnl : undefined;
}
createUOMParameterArgument(parent: ParameterDefinition) {
if (parent.dataType.length == 1) {
let dt = parent.dataType[0];
return factory.createArrayLiteralExpression([factory.createIdentifier(parent.name), factory.createPropertyAccessChain(factory.createIdentifier('UnitOfMeasure'), undefined, factory.createIdentifier(UnitOfMeasure[dt.uom] ?? 'Unknown'))]);
}
return factory.createIdentifier(parent.name ?? 'value');
}
createCommandMethodArguments(def: CommandDefinition): ts.ParameterDeclaration[] {
let p1: ts.ParameterDeclaration[] = [];
let p2: ts.ParameterDeclaration[] = [];
for (let p of def.parameters) {
if (p.optional) {
p2.push(this.createParameterDeclarationSignature(p));
} else {
p1.push(this.createParameterDeclarationSignature(p));
}
}
return [...p1, ...p2];
}
createCommandSignatureArguments(def: CommandDefinition): ts.ParameterDeclaration[] {
let p1: ts.ParameterDeclaration[] = [];
let p2: ts.ParameterDeclaration[] = [];
for (let p of def.parameters) {
if (p.optional) {
p2.push(this.createParameterSignature(p));
} else {
p1.push(this.createParameterSignature(p));
}
}
return [...p1, ...p2];
}
createCommandMethodDeclaration(def: CommandDefinition) {
return factory.createMethodDeclaration([factory.createToken(ts.SyntaxKind.AsyncKeyword)], undefined, factory.createIdentifier(def.name), undefined, undefined, def.parameters ? this.createCommandMethodArguments(def) : [], undefined, factory.createBlock([factory.createReturnStatement(factory.createCallExpression(factory.createPropertyAccessExpression(factory.createThis(), factory.createIdentifier('sendCommand')), undefined, NodeClassFactory.instance.createCommandArguments(def)))]));
}
addUOMType(def: DataTypeDefinition, typeNode: ts.TypeNode) {
return factory.createTupleTypeNode([typeNode, factory.createTypeReferenceNode(factory.createQualifiedName(factory.createIdentifier('UnitOfMeasure'), factory.createIdentifier(UnitOfMeasure[def.uom])), undefined)]);
}
/*addMaybeUOMType(def: DataTypeDefinition, typeNode: ts.TypeNode) {
return factory.createTypeParameterDeclaration(typeNode, factory.createTypeReferenceNode(factory.createQualifiedName(factory.createIdentifier('UnitOfMeasure'), factory.createIdentifier(UnitOfMeasure[def.uom])), undefined));
}*/
createCommandParameterType(def: DataTypeDefinition, parent: ParameterDefinition): ts.TypeNode {
if (def.enum) {
{
if (EnumDefinitionMap.has(parent.classDef.family)) {
var enumDef = EnumDefinitionMap.get(parent.classDef.family)[def.indexId];
// ?? EnumDefinitionMap[Family.Global]?[def.indexId]
if (enumDef) {
return factory.createTypeReferenceNode(factory.createQualifiedName(factory.createIdentifier(Family[parent.classDef.family]), factory.createIdentifier(enumDef.name)), undefined);
}
}
if (def.values) {
return NodeClassFactory.instance.createUnionTypeNode(...Object.keys(def.values).map((p) => factory.createLiteralTypeNode(factory.createNumericLiteral(p))));
}
// return NodeClassFactory.instance.createUnionTypeNode(...
// Object.values(def.values).map((p) => factory.createTypeReferenceNode(
// factory.createQualifiedName(
// factory.createIdentifier("UnitOfMeasure"),
// factory.createIdentifier(UnitOfMeasure)
// ),
// undefined
// )))
}
}
return factory.createKeywordTypeNode(ts.SyntaxKind.NumberKeyword);
}
createCommandSignature(def: CommandDefinition) {
const that = this;
return factory.createPropertySignature(
undefined,
factory.createIdentifier(def.id),
undefined,
factory.createIntersectionTypeNode([
factory.createParenthesizedType(
factory.createFunctionTypeNode(
undefined,
def.parameters ? NodeClassFactory.instance.createCommandSignatureArguments(def) : [],
factory.createTypeReferenceNode(factory.createIdentifier('Promise'), [factory.createKeywordTypeNode(ts.SyntaxKind.BooleanKeyword)])
)
),
factory.createTypeLiteralNode([factory.createPropertySignature(undefined, factory.createIdentifier('label'), undefined, factory.createLiteralTypeNode(factory.createStringLiteral(def.label))), factory.createPropertySignature(undefined, factory.createIdentifier('name'), undefined, factory.createLiteralTypeNode(factory.createStringLiteral(def.name)))])
])
);
}
createDriverGetDeclaration(def: DriverDefinition) {
return factory.createGetAccessorDeclaration([factory.createToken(ts.SyntaxKind.PublicKeyword)], factory.createIdentifier(def.name), [], NodeClassFactory.instance.createUnionTypeNode(...def.dataType?.map((p) => NodeClassFactory.instance.createDriverReturnType(p, def))), factory.createBlock([factory.createReturnStatement(factory.createPropertyAccessChain(factory.createPropertyAccessExpression(factory.createPropertyAccessExpression(factory.createThis(), factory.createIdentifier('drivers')), factory.createIdentifier(def.id)), factory.createToken(ts.SyntaxKind.QuestionDotToken), factory.createIdentifier('value')))], true));
}
createDriverInitializationStatement(def: DriverDefinition): ts.Statement {
return factory.createExpressionStatement(
factory.createBinaryExpression(
factory.createPropertyAccessExpression(factory.createPropertyAccessExpression(factory.createThis(), factory.createIdentifier('drivers')), factory.createIdentifier(def.id)),
factory.createToken(ts.SyntaxKind.EqualsToken),
factory.createCallExpression(factory.createPropertyAccessExpression(factory.createIdentifier('Driver'), factory.createIdentifier('create')), undefined, [factory.createStringLiteral(def.id), factory.createThis(), factory.createElementAccessExpression(factory.createPropertyAccessExpression(factory.createIdentifier('nodeInfo'), factory.createIdentifier('state')), this.createStringLiteral(def.id)), factory.createObjectLiteralExpression([factory.createPropertyAssignment(factory.createIdentifier('uom'), factory.createPropertyAccessExpression(factory.createIdentifier('UnitOfMeasure'), factory.createIdentifier(UnitOfMeasure[def.dataType[0]?.uom] ?? 'Unknown'))), factory.createPropertyAssignment(factory.createIdentifier('label'), factory.createStringLiteral(def.label)), factory.createPropertyAssignment(factory.createIdentifier('name'), factory.createStringLiteral(def.name))], false)])
)
);
}
createDriverPropertyReturnType(def: DataTypeDefinition, parent: DriverDefinition): ts.TypeNode {
if (def.enum) {
{
if (EnumDefinitionMap.has(parent.classDef.family)) {
var enumDef = EnumDefinitionMap.get(parent.classDef.family)[def.indexId];
// ?? EnumDefinitionMap[Family.Global]?[def.indexId]
if (enumDef) {
return factory.createTypeReferenceNode(factory.createQualifiedName(factory.createIdentifier(Family[parent.classDef.family]), factory.createIdentifier(enumDef.name)), undefined);
}
}
if (def.values) {
return NodeClassFactory.instance.createUnionTypeNode(...Object.keys(def.values).map((p) => factory.createLiteralTypeNode(factory.createNumericLiteral(p))));
}
// return NodeClassFactory.instance.createUnionTypeNode(...
// Object.values(def.values).map((p) => factory.createTypeReferenceNode(
// factory.createQualifiedName(
// factory.createIdentifier("UnitOfMeasure"),
// factory.createIdentifier(UnitOfMeasure)
// ),
// undefined
// )))
}
}
if ('min' in def && 'max' in def && def.max < 1000 && def.min >= 0 && Number.isInteger(def.min) && Number.isInteger(def.max)) {
return factory.createTypeReferenceNode(factory.createIdentifier('IntRange'), [factory.createLiteralTypeNode(this.createLiteral(def.min)), factory.createLiteralTypeNode(this.createLiteral(def.max))]);
}
return factory.createKeywordTypeNode(ts.SyntaxKind.NumberKeyword);
}
createDriverSignature(def: DriverDefinition) {
return factory.createPropertySignature(
undefined,
factory.createIdentifier(def.id),
undefined,
factory.createTypeLiteralNode([factory.createPropertySignature(undefined, factory.createIdentifier('uom'), undefined, def.dataType ? NodeClassFactory.instance.createUnionTypeNode(...def.dataType?.map((p) => NodeClassFactory.instance.createTypeNodeForUOM(p.uom))) : factory.createKeywordTypeNode(ts.SyntaxKind.NumberKeyword)), factory.createPropertySignature(undefined, factory.createIdentifier('value'), undefined, def.dataType ? NodeClassFactory.instance.createUnionTypeNode(...def.dataType.map((p) => NodeClassFactory.instance.createDriverReturnType(p, def))) : factory.createKeywordTypeNode(ts.SyntaxKind.NumberKeyword)), factory.createPropertySignature(undefined, factory.createIdentifier('label'), undefined, factory.createLiteralTypeNode(factory.createStringLiteral(def.label))), factory.createPropertySignature(undefined, factory.createIdentifier('name'), undefined, factory.createLiteralTypeNode(factory.createStringLiteral(def.name)))])
);
}
createDriverReturnType(def: DataTypeDefinition, parent: DriverDefinition): ts.TypeNode {
if (def.enum) {
{
if (EnumDefinitionMap.has(parent.classDef.family)) {
var enumDef = EnumDefinitionMap.get(parent.classDef.family)[def.indexId];
// ?? EnumDefinitionMap[Family.Global]?[def.indexId]
if (enumDef) {
return factory.createTypeReferenceNode(factory.createQualifiedName(factory.createIdentifier(Family[parent.classDef.family]), factory.createIdentifier(enumDef.name)), undefined);
}
}
if (def.values) {
return NodeClassFactory.instance.createUnionTypeNode(...Object.keys(def.values).map((p) => factory.createLiteralTypeNode(factory.createNumericLiteral(p))));
}
// return NodeClassFactory.instance.createUnionTypeNode(...
// Object.values(def.values).map((p) => factory.createTypeReferenceNode(
// factory.createQualifiedName(
// factory.createIdentifier("UnitOfMeasure"),
// factory.createIdentifier(UnitOfMeasure)
// ),
// undefined
// )))
}
}
if ('min' in def && 'max' in def && def.max < 1000 && def.min >= 0) {
return factory.createTypeReferenceNode(factory.createIdentifier('IntRange'), [factory.createLiteralTypeNode(this.createLiteral(def.min)), factory.createLiteralTypeNode(this.createLiteral(def.max))]);
}
return factory.createKeywordTypeNode(ts.SyntaxKind.NumberKeyword);
}
createParameterDeclarationSignature(def: ParameterDefinition) {
return factory.createParameterDeclaration(undefined, undefined, factory.createIdentifier(def.name ?? 'value'), def.optional ? factory.createToken(ts.SyntaxKind.QuestionToken) : undefined, def.dataType ? NodeClassFactory.instance.createUnionTypeNode(...def.dataType?.map((p) => NodeClassFactory.instance.createCommandParameterType(p, def))) : factory.createKeywordTypeNode(ts.SyntaxKind.NumberKeyword), undefined);
}
createParameterSignature(def: ParameterDefinition) {
return factory.createParameterDeclaration(undefined, undefined, factory.createIdentifier(def.id ?? 'value'), def.optional ? factory.createToken(ts.SyntaxKind.QuestionToken) : undefined, def.dataType ? NodeClassFactory.instance.createUnionTypeNode(...def.dataType?.map((p) => NodeClassFactory.instance.createCommandParameterType(p, def))) : factory.createKeywordTypeNode(ts.SyntaxKind.NumberKeyword), undefined);
}
createTypeNodeForUOM(uom: number): ts.TypeNode {
return NodeClassFactory.instance.createTypeReferenceNode(UnitOfMeasure[uom] ?? 'Unknown', 'UnitOfMeasure');
}
// #endregion Public Static Methods (4)
}
// #endregion Classes (1)
// #endregion Functions (12)