codesys-typegen
v0.1.1
Published
Generate TypeScript types and runtime field metadata from CODESYS Structured Text declarations
Maintainers
Readme
codesys-typegen
Generate TypeScript interfaces and runtime field metadata from authored CODESYS Structured Text declarations with one command. No running PLC, CODESYS installation, or binary memory layout is required.
npm install --save-dev codesys-typegen
npx codesys-typegen --types plc/src/types --globals plc/src/globals --out src/generated/plc.tsWith Bun:
bun add --dev codesys-typegen
bunx codesys-typegen --types plc/src/types --globals plc/src/globals --out src/generated/plc.tsThe command recursively reads .st files in the two directories. --types and --out are required; --globals is optional. Each type file contains one or more TYPE ... END_TYPE declarations. Each globals file contains one VAR_GLOBAL or VAR_GLOBAL CONSTANT block; its filename supplies the GVL name. Keep programs, function blocks, and implementations outside these directories.
The output is one self-contained .ts module with:
- Named TypeScript interfaces for structs, type aliases, and numeric enum values/types.
PlcGlobals, a typed map of GVLs and their variables.- A named object for each integer constant GVL, such as
LineConstants. globalVariableLists, containing GVL descriptions, andsymbols, containing global variable names, types, and descriptions.typeFields, containing each declared type's leaf field paths, IEC types, and descriptions. Nested structures expand into dotted paths. Arrays of structs use their actual PLC indexes, including negative and nonzero lower bounds. Scalar arrays remain one field, including scanner byte buffers.
import type { ST_LineConveyor, PlcGlobals } from './generated/plc';
import { symbols, typeFields, LineConstants } from './generated/plc';
// TypeScript arrays use ordinary zero-based JS indexing. Runtime metadata retains
// the PLC bounds: e.g. Cards[1].Input.Sensor through Cards[128].Input.Sensor.
const conveyorFields = typeFields.ST_LineConveyor;Comments become JSDoc and runtime descriptions. Attributes are accepted but do not change the output's memory layout. Struct field initializers remain in PLC source; generation does not manufacture live/default PLC values. Byte buffers are number[]. IEC 64-bit integer types become bigint; smaller integers, real values, and supported time/date types become number. Runtime metadata retains the IEC type; TypeScript alone does not validate integer ranges, array lengths, string limits, or wire representations.
Source support
Supported declarations: nested named structs, aliases, numeric enums, scalar IEC types, STRING/WSTRING with a literal or constant length, and fixed arrays with one or more dimensions. Identifiers resolve case-insensitively. Leading line/block comments, nested block comments, attributes, multiple member names, and field initializers are accepted.
Integer constant GVLs and array bounds support decimal and 2#/8#/16# literals, qualified constant names, parentheses, and + - * / arithmetic. Integer division truncates toward zero. Enum members can use earlier members and integer GVL constants. Unknown/ambiguous constants, unknown types, duplicate declarations, cycles, invalid bounds, malformed syntax, and unsupported declarations fail generation.
This is a declaration generator, not a full ST compiler. Unions, pointers/references, inheritance, variable-length arrays, inline anonymous structs, non-integer constant GVLs, typed literal prefixes, and arbitrary PLC expressions in bounds are unsupported. Field initializers are skipped syntactically, not evaluated or compiled. CODESYS remains responsible for validating PLC behavior and initializers. Only pass exported interface declarations to this tool.
Drift checks
codesys-typegen --types plc/src/types --globals plc/src/globals --out src/generated/plc.ts --check--check exits with code 1 when output is missing or differs, without writing. Generation is deterministic, validates before writing, and replaces the output atomically. It never modifies PLC sources. Commit the generated file and exclude it from automatic formatting so exact drift checks remain stable.
Programmatic generation
import { generateTypes } from 'codesys-typegen/codegen';
const source = await generateTypes({ types: 'plc/src/types', globals: 'plc/src/globals' });The function returns the generated source without writing files.
Developing and publishing
Requires Node.js 20+ for the installed CLI; Bun is used for package development.
bun install
bun turbo run test tsc
bun pm packprepack builds the distributable Node CLI and declarations. The archive includes dist/, documentation, and the MIT license. Publish under the name codesys-typegen.
This project is a fork of jisotalo/iec-61131-3. Its existing runtime binary codec API is retained at the package root; see binary codec documentation. That API's packed-layout assumptions and legacy parser are independent of the declaration generator and are not used for type generation.
