mirror of
https://github.com/vrtmrz/obsidian-livesync.git
synced 2026-08-19 18:07:06 +00:00
Use the packaged Commonlib type import and add regression coverage for every Obsidian vault and storage write method. Verify that fractional timestamps are floored without mutating caller-owned options.
26 lines
1.3 KiB
TypeScript
26 lines
1.3 KiB
TypeScript
import type { UXDataWriteOptions } from "@vrtmrz/livesync-commonlib/compat/common/types";
|
|
|
|
/**
|
|
* Coerce the timestamp fields of a write-options object to integer milliseconds.
|
|
*
|
|
* On mobile, Obsidian forwards `mtime`/`ctime` to Capacitor's
|
|
* Filesystem.setTimes, whose native binding casts the value to a Java `Long`.
|
|
* A non-integer (float) timestamp makes that cast throw
|
|
* `ClassCastException: Double cannot be cast to Long`, which crashes the app on
|
|
* launch as soon as such a document is replicated in. Float timestamps can
|
|
* enter the database from any client that stores `fs.Stats.mtimeMs` without
|
|
* flooring. Flooring at the storage boundary guarantees every Obsidian write
|
|
* carries an integer, so a float timestamp already present in the mesh cannot
|
|
* brick the app.
|
|
*
|
|
* Returns a shallow copy so the caller's options object is not mutated; passes
|
|
* `undefined` through unchanged.
|
|
*/
|
|
export function toIntegerTimestamps(options?: UXDataWriteOptions): UXDataWriteOptions | undefined {
|
|
if (!options) return options;
|
|
const sanitized: UXDataWriteOptions = { ...options };
|
|
if (typeof sanitized.mtime === "number") sanitized.mtime = Math.floor(sanitized.mtime);
|
|
if (typeof sanitized.ctime === "number") sanitized.ctime = Math.floor(sanitized.ctime);
|
|
return sanitized;
|
|
}
|