A simple parser for Valve's KeyValue text file format (VDF) https://developer.valvesoftware.com/wiki/KeyValues. Written in JavaScript (TypeScript).
Support both returning an object OR piping readable stream to the parser streaming out key-value pairs.
Pick your favorite package manager. For example using npm
:
npm install @hinw/vdf-parser
import { VdfParser } from '@hinw/vdf-parser';
// file content: "key" { "nested_key" "value" }"
const filePath = 'input/sample.vdf';
const parser = new VdfParser();
const result = await parser.parseFile(filePath);
// assert.assertEqual(result, { key: { nested_key: 'value' } });
import stream from 'node:stream';
import { VdfParser } from '@hinw/vdf-parser';
const readStream = stream.Readable.from(`"key" { "nested_key" "value" }"`);
const parser = new VdfParser();
const result = await parser.parseStream(readStream);
// assert.assertEqual(result, { key: { nested_key: 'value' } });
import { VdfParser } from '@hinw/vdf-parser';
const input = `"key" { "nested_key" "value" }"`;
const parser = new VdfParser();
const result = await parser.parseText(input);
// assert.assertEqual(result, { key: { nested_key: 'value' } });
import fs from 'node:fs'
import { VdfParser } from '@hinw/vdf-parser';
// file content: "key" { "nested_key" "value" }"
const filePath = 'input/sample.vdf';
const parser = new VdfParser();
const fileStream = fs.createReadStream(filePath)
const parserStream = fileStream.pipe(parser)
for await (const pair of parserStream) {
// assert.assertEqual(pair, { keyParts: ['key', 'nested_key'], value: 'value' });
}
// You can build the object from the stream using async iterator interface:
const fileStream = fs.createReadStream(filePath)
const parserStream = fileStream.pipe(parser)
const result = await parser.condensePairsAsync(parserStream)
// Or you can store the pairs somewhere, and build it afterwards with normal iterator interface:
const fileStream = fs.createReadStream(filePath)
const parserStream = fileStream.pipe(parser)
const pairs = await Array.fromAsync(parserStream)
const result = parser.condensePairs(pairs)
By default, the parser will handle escape sequence. To disable this behavior, you can set disableEscape
to true
.
import { VdfParser } from '@hinw/vdf-parser';
const input = `"\\"quoted key\\"" "value"`;
const parser = new VdfParser({ disableEscape: true });
const result = await parser.parseText(input);
// assert.assertEqual(result, { '\\"quoted key\\"': 'value' });
If the values of the duplicated keys are all maps, they will be merged together
import { VdfParser } from '@hinw/vdf-parser';
const input = `"key" { "nested_key" "value" }" "key" { "nested_key_2" "value" }"`;
const parser = new VdfParser({ useLatestValue: true });
const result = await parser.parseText(input);
// assert.assertEqual(result, { key: { nested_key: 'value', nested_key_2: 'value' } });
By default, the parser will use the earliest seen value for the duplicated keys.
import { VdfParser } from '@hinw/vdf-parser';
const input = `"key" { "nested_key" "value" }" "key" "value"`;
const parser = new VdfParser();
const result = await parser.parseText(input);
// assert.assertEqual(result, { key: { nested_key: 'value' } });
However, you can set useLatestValue
to true
to use the latest seen value instead.
import { VdfParser } from '@hinw/vdf-parser';
const input = `"key" { "nested_key" "value" }" "key" "value"`;
const parser = new VdfParser({ useLatestValue: true });
const result = await parser.parseText(input);
// assert.assertEqual(result, { key: 'value' });
Since the VDF specification does not contain any type info, it would be a guess work to convert some value to a certain type. To keep this library simple, it would not provide an option to do auto type detection / conversion. In theory if the user is interested in using the values of a VDF they should know the schema of the file well and it is the responsibiliy for the user to convert the types instead of this library doing the guess work.