@expo/plist is a macOS Plist (Property List) parser/builder library for Node.js and browsers. It provides comprehensive functionality to convert between JavaScript objects and Apple's plist XML format, supporting all standard plist data types with robust error handling.
npm install @expo/plistMain usage (default import):
import plist from "@expo/plist";
// Use as: plist.parse() and plist.build()For CommonJS:
const plist = require("@expo/plist");
// Use as: plist.parse() and plist.build()Type-only imports (for TypeScript):
import type { PlistValue, PlistObject, PlistArray, PlistBuildOptions } from "@expo/plist";import plist from "@expo/plist";
// Parse XML plist string to JavaScript object
const xmlString = `<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>name</key>
<string>My App</string>
<key>version</key>
<integer>1</integer>
<key>enabled</key>
<true/>
</dict>
</plist>`;
const obj = plist.parse(xmlString);
// Result: { name: "My App", version: 1, enabled: true }
// Build JavaScript object to XML plist string
const data = {
name: "My App",
version: 1.2,
enabled: true,
created: new Date("2023-01-01T12:00:00Z"),
data: Buffer.from("hello", "utf8"),
items: ["item1", "item2"],
config: { debug: false }
};
const xml = plist.build(data);
// Result: Properly formatted plist XML stringParses a Plist XML string and converts it to a JavaScript object, supporting all standard plist data types.
/**
* Parses a Plist XML string. Returns an Object.
* @param xml - the XML String to decode
* @returns the decoded value from the Plist XML
* @throws Error if document is malformed (first element should be <plist>)
* @throws Error for missing values in dictionaries
* @throws Error for empty integer/real/date nodes
*/
function parse(xml: string): any;Usage Examples:
import plist from "@expo/plist";
// Parse basic types
const boolResult = plist.parse(`<?xml version="1.0"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0"><true/></plist>`);
// Result: true
// Parse complex nested structure
const complexXml = `<?xml version="1.0"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>stringValue</key>
<string>Hello World</string>
<key>numberValue</key>
<integer>42</integer>
<key>floatValue</key>
<real>3.14</real>
<key>boolValue</key>
<true/>
<key>dateValue</key>
<date>2023-01-01T12:00:00Z</date>
<key>dataValue</key>
<data>aGVsbG8=</data>
<key>arrayValue</key>
<array>
<string>item1</string>
<string>item2</string>
</array>
<key>dictValue</key>
<dict>
<key>nested</key>
<string>value</string>
</dict>
</dict>
</plist>`;
const result = plist.parse(complexXml);
// Result: Complete JavaScript object with all types properly convertedGenerates an XML plist string from a JavaScript object, with support for formatting options.
/**
* Generate an XML plist string from the input object.
* @param obj - the object to convert
* @param opts - optional options object (XMLToStringOptions from xmlbuilder)
* @returns converted plist XML string
*/
function build(obj: any, opts?: PlistBuildOptions): string;Usage Examples:
import plist from "@expo/plist";
// Build with default formatting (pretty: true)
const data = { name: "Test", value: 123 };
const xml = plist.build(data);
// Result: Formatted XML with indentation
// Build with custom options
const compactXml = plist.build(data, { pretty: false });
// Result: Compact XML without formatting
// Build complex object with all supported types
const complexData = {
stringValue: "Hello World",
integerValue: 42,
realValue: 3.14159,
booleanValue: true,
dateValue: new Date("2023-01-01T12:00:00Z"),
bufferValue: Buffer.from("hello", "utf8"),
arrayValue: ["item1", "item2", 123],
objectValue: {
nested: "value",
count: 5
}
};
const result = plist.build(complexData);
// Result: Complete plist XML with proper DOCTYPE and formatting/**
* Union type representing all possible plist values
*/
type PlistValue = string | number | boolean | Date | Buffer | PlistObject | PlistArray;
/**
* Interface for plist dictionary objects
*/
interface PlistObject {
readonly [x: string]: PlistValue;
}
/**
* Interface for plist array objects
*/
interface PlistArray extends ReadonlyArray<PlistValue> {}
/**
* Build options type (aliases XMLToStringOptions from xmlbuilder)
* Common options include:
* - pretty: boolean (default: true) - Enable/disable formatting
* - indent: string - Indentation string
* - newline: string - Newline character
*/
type PlistBuildOptions = XMLToStringOptions;The library supports bidirectional conversion of the following types:
| JavaScript Type | Plist XML Element | Notes |
|---|---|---|
string | <string> | Preserves all text content including whitespace |
number (integer) | <integer> | Whole numbers are automatically detected |
number (float) | <real> | Fractional numbers with full precision |
boolean | <true/> or <false/> | Boolean values as self-closing tags |
Date | <date> | ISO 8601 format (YYYY-MM-DDTHH:mm:ssZ) |
Buffer | <data> | Base64 encoded binary data |
ArrayBuffer | <data> | Base64 encoded binary data |
TypedArray | <data> | Base64 encoded binary data |
Array | <array> | Ordered lists of any plist values |
Object | <dict> | Key-value dictionaries |
undefined | ignored | Undefined values are omitted |
The library throws descriptive errors for various invalid conditions:
<plist><key> is not followed by a value<integer>, <real>, or <date> elementsimport plist from "@expo/plist";
try {
const result = plist.parse(invalidXml);
} catch (error) {
console.error("Parse error:", error.message);
// Handle parsing errors appropriately
}The build function is generally robust but may encounter issues with:
@xmldom/xmldom for XML DOM parsing with error handlingxmlbuilder for XML generation with formatting options