palm-sync is a modern, cross-platform toolkit for HotSync with Palm OS devices, built with TypeScript.
palm-sync provides a new implementation of Palm HotSync protocols in TypeScript, and supports Node.js and browser environments. It aspires to be the foundation for a new generation of Palm OS synchronization tools for modern operating systems.
OS | Node.js 18+ | Browser (Chromium) | |||
---|---|---|---|---|---|
Serial | USB | Network | Serial | USB | |
Windows | Y | Y | Y | Y | Y |
macOS | Y | Y | Y | Y | Y |
Linux | Y | Y | Y | Y | Y |
ChromeOS | Y | Y | Y | Y | Y |
Android | N/A | N/A | N/A | N | Y |
Not supported:
- Operating systems: iOS, iPadOS
- Connections: Bluetooth, IR
For more information, please see Connecting Palm OS Devices.
You can try out palm-sync right in your browser! The web demo allows you to do a simple HotSync with a Palm OS device via USB or serial.
👉 jichu4n.github.io/palm-sync/web-demo
Requirements:
- Palm OS device connected via USB or serial, including via serial-to-USB adapter.
- A Chromium-based browser such as Google Chrome or Microsoft Edge, running on Windows, macOS, Linux, ChromeOS, or Android (USB only). See Connecting Palm OS Devices for OS-specific setup.
npm install --save palm-sync
Example conduit to list the databases on a Palm device:
// ./src/list-dbs.ts
import {
DlpConnection,
DlpReadDBListFlags,
DlpReadDBListReqType,
} from 'palm-sync';
export async function run(dlpConnection: DlpConnection) {
const readDbListResp = await dlpConnection.execute(
DlpReadDBListReqType.with({
srchFlags: DlpReadDBListFlags.with({ram: true, multiple: true}),
})
);
const dbNames = readDbListResp.dbInfo.map(({name}) => name);
console.log(dbNames.join('\n'));
}
# Run tsc to produce ./dist/list-dbs.js
npm run build
# Wait for HotSync connection over USB and run specified conduit.
# - For serial, use `--serial /dev/ttyXXX` (`--serial COMn` on Windows)
# - For network HotSync (port 14238), use `--net`
# - For serial-over-network (POSE and other emulators), use `--serial:net`
# to listen on port 6416
./node_modules/.bin/palm-sync run --usb ./dist/list-dbs.js
Now connect and initiate HotSync on the Palm OS device! See Connecting Palm OS Devices for OS-specific setup.
For a general introduction to HotSync's architecture, please first read 👉 How Palm OS HotSync Works. This will help provide context for the APIs discussed below.
palm-sync's API is organized into the following main components:
- Sync servers - Interfacing with OS / hardware and managing the sync process.
- Protocols - Implements the various communication protocols in the HotSync protocol stack.
- Sync utils - Common sync logic and helpers.
- Conduits - General purpose conduits.
Additionally, palm-sync depends on the following sister projects:
- palm-pdb - Manipulating Palm OS databases and related data structures.
- serio - Serializing / deserializing binary data.
The SyncServer
class represents a daemon that listens for incoming HotSync connections. A SyncServer
is responsible for interfacing with the underlying hardware, setting up a transport protocol stack and passing control to the configured conduit. The various subclasses of SyncServer
correspond to different types of connections.
A SyncServer
doesn't perform conduit logic (i.e. business logic for data synchronization) itself. Instead, it takes in a SyncFn
which it passes control to when a HotSync connection is established. The SyncFn
is responsible for performing the desired conduit logic over the DLP protocol. This provides a clean connection-agnostic abstraction for conduit logic.
Connection type | Node.js | Browser (Chromium) |
---|---|---|
UsbSyncServer |
Yes - usb |
Yes - WebUSB API |
SerialSyncServer |
Yes - serialport |
No |
WebSerialSyncServer |
No | Yes - Web Serial API |
NetworkSyncServer |
Yes - net |
No |
SerialOverNetworkSyncServer |
Yes - net |
No |
To create a SyncServer
:
createSyncServer()
- Main entrypoint to create aSyncServer
instance. The caller can usestart()
andstop()
to manage the server lifecycle, and subscribe to itsconnect
anddisconnect
events.createSyncServerAndRunSync()
- Convenience function to run a single HotSync operation - create and start aSyncServer
instance, run a conduit, and stop the server.
The DlpConnection
class represents a connection to a Palm device over the DLP protocol. It provides a high-level API for executing DLP commands, which is the primary way conduits interact with a connected Palm device.
For the full list of supported DLP commands, see the list of subclasses of DlpRequest
. palm-sync provides request and response type definitions for all DLP commands up to DLP version 1.2 (Palm OS 3.0). It does not currently support commands introduced in DLP version 1.3 (Palm OS 4.0) and later.
Under the hood, a DlpConnection
wraps one of two possible transport protocol stacks, which themselves are implemented as transform streams wrapping the underlying raw data streams. The SyncServer
subclass for each connection type is responsible for setting up the appropriate transport stack and constructing DlpConnection
s. Conduit logic generally does not need to directly interact with the transport protocol stacks.
palm-sync provides a collection of utility functions to help with common conduit tasks. Some key utilities include:
These functions provide a generic implementation of Palm OS's two-way synchronization logic.
fastSync()
andfastSyncDb()
slowSync()
andslowSyncDb()
TODO
palm-sync uses the debug
library for logging messages. All messages are logged under the palm-sync
namespace.
To enable verbose logging, set the DEBUG
environment variable to palm-sync:*
or call debug.enable('palm-sync:*')
to enable logging programmatically. You can capture logs by overriding debug.log
. See debug
documentation for more information.
Note that on Web, you will need to import debug
from palm-sync
itself as it is bundled with the library using Browserify. See log-store.ts
for an example.