EnergyPlus IDF and epJSON tooling for JavaScript and TypeScript. A sibling to the Python idfkit, not a transliteration of it.
Documentation · Tutorial · How-to guides · API reference
Documentation source lives in idfkit/idfkit-developers, not here. This repository publishes the TypeScript examples and the TypeDoc reference to it as a pinned
docs-YYYY.Nrelease; see CONTRIBUTING.md.
One site teaches both languages. js.idfkit.com is retired and redirects there.
| Package | What it is | npm |
|---|---|---|
packages/core | Parsing, the object model, references, writers | @idfkit/core |
packages/schemas | Content-addressed epJSON schemas, all 17 versions | @idfkit/schemas |
packages/weather | TMYx station index and browser EPW retrieval | @idfkit/weather |
It sits alongside @idfkit/engine,
which runs EnergyPlus itself in the browser via WebAssembly. This repository
handles the model; that one handles the simulation. See
How to run a simulation in the browser
for how the two fit together.
Important
The next release renames four exports and moves the generated types out of
@idfkit/core.
| Before | After |
|---|---|
IDFDocument | IdfDocument |
detectVersion(text) | getIdfVersion(text) |
detectEpJsonVersion(text) | getEpJsonVersion(text) |
doc.collection(type) | doc.all(type) |
import type { TypeMap } from '@idfkit/core/types' | import type { TypeMap } from '@idfkit/types-v26-1' |
Every one is a build-time failure naming the file and line, in plain JavaScript
as well as TypeScript, so nothing here reaches runtime. The type move is what
takes @idfkit/core from 6.7 MB unpacked to 286 KB. Full notes in the
changelog.
Status: beta, and first-tier only.
@idfkit/core,@idfkit/schemasand@idfkit/weatherare published at 0.1.0. The API is not yet stable.All thirteen first-tier capabilities exist here: parsing, the object model, references, writers, schema access, validation, introspection, documentation addresses, generated object types, parse diagnostics, the weather station index, weather file retrieval, and geocoding. Second- and third-tier capabilities are Python-only for now, and a few are permanently so.
That is a real difference between the two libraries and not a rounding error, so read Capability parity before assuming an operation you know from Python exists here. It lists every capability, its state in each language, and whether an absence is temporary or permanent.
npm install @idfkit/core @idfkit/schemasStatic per-version field types are opt-in and installed by name, so nobody pays 5.3 MB of declarations to parse a file. Everything below works without them, untyped.
npm install --save-dev @idfkit/types-v26-1The type packages are built and gated but not yet on the registry, so that install fails today. Drop the
TypeMapimport from the quickstart until they publish; the runtime behaviour is identical either way.
import{loadIdf,saveIdf}from'@idfkit/core/node';importtype{TypeMap}from'@idfkit/types-v26-1';constdoc=awaitloadIdf<TypeMap>('model.idf');for(constzoneofdoc.all('Zone')){console.log(zone.name,zone.ceiling_height);// typed, autocompleted}// Renaming rewrites every reference to the old name.doc.require('Zone','SPACE1-1').name='Open Office';awaitsaveIdf(doc,'model-renamed.idf');In a browser, load the schema yourself and keep the parse synchronous:
import{parseIdf,SchemaBundle,httpSource}from'@idfkit/core';constbundle=newSchemaBundle(httpSource('/schemas/'));constschema=awaitbundle.load('26.1.0');const{ document }=parseIdf(idfText,schema);Need a weather file too? @idfkit/weather
searches the climate.onebuilding.org TMYx station index and pulls EPW files
browser-side:
import{loadStationIndex,fetchEpw}from'@idfkit/weather';constindex=awaitloadStationIndex('/stations.json.gz');constepw=awaitfetchEpw(index.search('chicago ohare')[0].station);New to the library? Build your first model goes from nothing to a model on disk in about fifteen minutes.
Five decisions shape the API, each chosen over an obvious alternative:
| Decision | In short |
|---|---|
| A synchronous core with async edges | The same core runs in Node, a browser, a worker, and an edge runtime. |
Real accessors, not a Proxy | Editors can see the fields, V8 can optimize them, and the setter keeps the reference graph live. |
| Static types generated from the schema | 858 interfaces per version, so a misspelled field is a compile error. |
| Content-addressed schemas | All 17 versions in ~1 MB gzipped instead of 11.9 MB. |
| epJSON field names verbatim | zone_name. No name-conversion layer to get wrong. |
The conformance suite is the EnergyPlus example set, not hand-written fixtures. Every file is parsed, written, and re-parsed, and the two documents must be deeply equal.
files 760
clean 760
parse issues 0
roundtrip diff 0
objects 290,313
throughput ~36k objects/sec (parse + write + re-parse)
IDF is a positional format, so its edge cases corrupt a model quietly rather than
failing. Every such case the example set has surfaced is pinned in
packages/core/tests/regressions.test.ts. See How conformance is
established.
See CONTRIBUTING.md. The short version:
npm install
npm run format:check && npx tsc -p tsconfig.test.json && npm testMIT