TypeScript library for working with Palm OS PDB and PRC files.
palm-pdb provides a TypeScript / JavaScript API for reading and writing Palm OS PDB and PRC files. It also provides out-of-the-box implementations of several PDB data formats, including those of the core Palm OS PIM applications (Memo Pad, Date Book, Address, To Do List) and PalmDOC.
While palm-pdb doesn't directly communicate with a Palm OS device, it can be used to parse PDB / PRC files backed up from a device, or to produce PDB / PRC files that can be synced to a device.
Install with:
npm install --save palm-pdb
Basic usage:
import {MemoDatabase, MemoRecord} from 'palm-pdb';
import fs from 'fs-extra';
// Let's read some memos!
const memoDb = MemoDatabase.from(await fs.readFile('MemoDB.pdb'));
const record = memoDb.records[0]!;
console.log(record.value); // "Hello world!"
console.log(
memoDb.appInfo!.getCategory(record.entry.attributes.category)!.label
); // "Personal"
// Let's add a new memo!
const newRecord = new MemoRecord();
newRecord.value = 'Look, new memo!';
newRecord.entry.attributes.category =
memoDb.appInfo!.getCategory('Personal')!.uniqId;
memoDb.records.push(newRecord);
await fs.writeFile('MemoDB.pdb', memoDb.serialize());
TypeScript is generally not required to use palm-pdb, especially if you just want to use the out-of-the-box implementations of common PDB data formats (Date Book, To Do List, PalmDOC, etc.).
If you'd like to implement custom PDB / PRC formats, then the following is optional but recommended:
- TypeScript 5.0 or higher;
- The
experimentalDecorators
setting should NOT be enabled intsconfig.json
.
The following sections provide a high level overview of the API. For more details, please see the generated documentation.
The Database class is the logical representation of a PDB / PRC file. Its member fields correspond to the high level structure described in the Palm File Format Specification:
header
: Standard structure (DatabaseHdrType) for basic metadata, such as name, creator and type information.appInfo
: Optional block for application settings or other data. The format is up to the application, but there is a standard structure (AppInfoType) for category settings that is used by all the built-in PIM applications.sortInfo
: Optional block for record ordering information. The format is up to the application.records
: An array of records (Record). Each record has an associatedentry
(EntryType) which is a standard structure containing metadata about each record. Otherwise the format is up to the application.
There are two sets of classes dervied from the ones described above, corresponding to the PDB and PRC formats respectively:
Base | PDB format | PRC format |
---|---|---|
Database | PdbDatabase | PrcDatabase |
Record | PdbRecord | PrcRecord |
EntryType | RecordEntryType | RsrcEntryType |
Implementations of specific formats derive from the above Pdb*
or Prc*
classes. See below for more information on implementing your own data formats based on these classes.
All of the classes described above implement the Serializable
interface from the serio library. A basic example illustrating the interface:
// Construct a new database
const db1 = new FooDatabase();
const rec1 = new FooRecord();
// Manipulate some fields
rec1.field1 = 3;
db1.records.push(rec1);
// Serialize to Buffer
const buf1 = db1.serialize();
// Deserialize a database from Buffer
const db2 = FooDatabase.from(buf1);
// The following achieves the same thing:
const db3 = new FooDatabase();
db3.deserialize(buf1);
Text in PDB / PRC files is generally stored in one of several pre-Unicode encodings, depending on the Palm OS language setting. The default encoding for the Latin alphabet is CP1252 (DEFAULT_ENCODING
), so that's what palm-pdb defaults to.
To select a different text encoding, pass in an encoding
name during serialization / deserialization:
// Deserialize a MemoDB file using GB2312 text encoding (Simplified Chinese):
const db1 = MemoDatabase.from(buffer, {encoding: 'gb2312'});
// Alternatively:
const db2 = new MemoDatabase();
db2.deserialize(buffer, {encoding: 'gb2312'});
// Serialize a MemoDB file using Shift-JIS text encoding (Japanese):
const buf1 = db3.serialize({encoding: 'shiftjis'});
If you are not sure what text encoding to specify, see here for the full list of text encodings supported by Palm OS. To find the encoding
value that corresponds to a particular text encoding, see the iconv-lite wiki.
Implementations of the following PDB formats are included in palm-pdb:
Data format used by the Memo Pad (a.k.a. Memos) application.
π MemoDatabase, MemoAppInfo, MemoRecord
Usage example: src/tests/memo-database.test.ts
Data format used by the Date Book (a.k.a. Calendar) application.
π DatebookDatabase, DatebookAppInfo, DatebookRecord
Usage example: src/tests/datebook-database.test.ts
Data format used by the To Do List (a.k.a. Tasks) application.
π ToDoDatabase, ToDoAppInfo, ToDoRecord
Usage example: src/tests/todo-database.test.ts
Data format used by the Address (a.k.a. Contacts) application.
π AddressDatabase, AddressAppInfo, AddressRecord
Usage example: src/tests/address-database.test.ts
Data format for text documents and eBooks.
π PalmDoc
Usage examples: src/bin/palmdoc.ts, src/tests/palmdoc-database.test.ts
The general outline for a PDB / PRC data format implementation looks like the following:
import {PdbRecord, PdbDatabase, DatabaseHdrType} from 'palm-pdb';
// 1. Define a Record class extending PdbRecord or PrcRecord.
class MyRecord extends PdbRecord {
// ...
}
// 2. Optionally, define an AppInfo class that implements the Serializable
// interface.
class MyAppInfo implements Serializable {
// ...
}
// 3. Optionally, define a SortInfo class that implements the Serializable
// interface.
class MySortInfo implements Serializable {
// ...
}
// 4. Finally, define a Database class that pulls together the above. It should
// extend PdbDatabase or PrcDatabase. The AppInfo and SortInfo arguments are
// optional.
class MyDatabase extends PdbDatabase.of(MyRecord, MyAppInfo, MySortInfo) {
// Set default header settings (optional)
header = DatabaseHdrType.with({
name: 'MyDB',
type: 'DATA',
creator: 'abcd',
});
}
There are three options for implementing a record format.
Using @field() decorators: This is the easiest option and should be preferred for most use cases. The PdbRecord and PrcRecord classes extend SObject, so you can use @field()
decorators to define fields that should be processed by the default serialize()
, deserialize()
and getSerializedLength()
implementations. For example, see the implementation for MemoRecord or ToDoRecord.
Custom implementation: You can also provide your own fully custom implementation of the Serializable interface, i.e. by overriding the methods serialize()
, deserialize()
, and getSerializedLength()
.
Exposing raw data: Finally, you could also directly use use RawPdbRecord or RawPrcRecord to expose the raw data for custom processing. For example, this is how the PalmDocDatabase is implemented, because its records (except the first one) are just chunks of text.
Similarly, the AppInfo and SortInfo blocks can be implemented in different ways. The only requirement is that they need to implement the Serializable interface. The easiest way would be to extend SObject and use @field()
decorators to define fields.
There is a standard format for storing category settings inside the AppInfo block, as described in the Palm File Format Specification. This format is used by the built-in PIM applications, and is called AppInfoType. See the implementation for MemoAppInfo for an example AppInfo block that makes use of AppInfoType.
Information regarding PDB / PRC data formats is based on the following sources:
- Palm File Format Specification
- Palm OS SDKs
- p5-Palm by Andrew Arensburger, Alessandro Zummo, Brian D. Foy, Christopher J. Madsen et al.
- pilot-link (archive) by David A. Desrosiers, JP Rosevear, Kenneth Albanowski et al.
Wherever possible, the names of classes and fields are derived from their equivalents in the official Palm OS SDKs and the Palm File Format Specification.
- Fix bug where PDB_EPOCH is accidentally overwritten
- Upgrade to serio 2.0 (see https://github.com/jichu4n/serio?tab=readme-ov-file#20)