How to handle a version you do not know ahead of time¶
A viewer, a converter, or anything else that opens files it did not write cannot
hard-code 26.1.0. Loading the wrong schema does not throw — IDF is positional,
so a field-order difference mis-maps values into neighbouring slots and the parse
"succeeds" with a corrupted model.
In Node, this is already handled¶
loadIdf reads the version from the file, resolves it against the bundle, and
throws a useful error when there is no match:
import { loadIdf } from '@idfkit/core/node';
const doc = await loadIdf('whatever.idf');
doc.version; // '9.0.1', say
Nothing else is needed. The rest of this page is for when you are parsing text you obtained some other way.
Detect, resolve, load¶
Three steps, because each can fail differently:
import { detectVersion, parseIdf, resolveVersion, SchemaBundle, httpSource } from '@idfkit/core';
const bundle = new SchemaBundle(httpSource('/schemas/'));
const detected = detectVersion(text); // '9.0', or undefined
if (detected === undefined) {
throw new Error('No Version object; ask the user which release this is.');
}
const available = await bundle.versions();
const resolved = resolveVersion(detected, available);
if (resolved === undefined) {
throw new Error(`EnergyPlus ${detected} is not supported. Available: ${available.join(', ')}`);
}
const { document } = parseIdf(text, await bundle.load(resolved));
resolveVersion exists because IDF files write Version, 9.0; while schemas are
keyed 9.0.1. It matches on major and minor and takes the newest patch. When
nothing matches it returns undefined rather than guessing — see Supported
versions.
In Node, with your own text¶
schemaFor is the same three steps, exported for exactly this case:
import { parseIdf, detectVersion } from '@idfkit/core';
import { schemaFor } from '@idfkit/core/node';
const schema = await schemaFor(detectVersion(text));
const { document } = parseIdf(text, schema);
Files with no Version object¶
Fragments, snippets, and hand-written test inputs often have none. Pass version
explicitly:
version overrides detection entirely, so it also works as a "parse this as if
it were 26.1" escape hatch. Use it knowingly: that is precisely the mis-mapping
the resolution logic exists to prevent.
epJSON¶
Same shape, different detector:
import { detectEpJsonVersion, parseEpJson } from '@idfkit/core';
const schema = await schemaFor(detectEpJsonVersion(text));
const { document } = parseEpJson(text, schema);
Or loadEpJson(path) in Node, which does all of it.
Working across versions in one process¶
Hold one SchemaBundle. Loading a second version pays only for the definitions
it does not already share with the first, and definitions common to both are the
same frozen object — which also means the two versions share one object
prototype. See Content-addressed
schemas.
A document is bound to one version for its lifetime. There is no version-agnostic mode, because field order and reference lists genuinely differ between releases.