1import { exec } from "child_process";2import { Platform } from "obsidian";3
4const XATTR_PREFIX = "com.sublimated.";5const XATTR_SUFFIX = "#PS";6
7export interface FileMetadata {8 version: string | null;9 commit: string | null;10 url: string | null;11 contentHash: string | null;12 id: string | null;13 createdBy: string | null;14 modifiedBy: string | null;15 modifiedByType: string | null;16 syncStatus: string | null;17 space: string | null;18 branch: string | null;19 modifiedAt: string | null;20}21
22const ATTRS: (keyof FileMetadata)[] = [23 "version",24 "commit",25 "url",26 "contentHash",27 "id",28 "createdBy",29 "modifiedBy",30 "modifiedByType",31 "syncStatus",32 "space",33 "branch",34 "modifiedAt",35];36
37function attrToXattrName(attr: string): string {38 // camelCase → kebab-case: contentHash → content-hash39 const kebab = attr.replace(/[A-Z]/g, (c) => "-" + c.toLowerCase());40 return `${XATTR_PREFIX}${kebab}${XATTR_SUFFIX}`;41}42
43function readXattr(path: string, xattrName: string): Promise<string | null> {44 return new Promise((resolve) => {45 exec(46 `xattr -p ${JSON.stringify(xattrName)} ${JSON.stringify(path)}`,47 { timeout: 2000 },48 (err, stdout) => {49 if (err) {50 resolve(null);51 return;52 }53 resolve(stdout.trim() || null);54 }55 );56 });57}58
59export async function readFileMetadata(60 path: string61): Promise<FileMetadata | null> {62 if (!Platform.isMacOS) return null;63
64 const results = await Promise.all(65 ATTRS.map((attr) => readXattr(path, attrToXattrName(attr)))66 );67
68 // If no xattrs found at all, this isn't a sublimated file69 if (results.every((r) => r === null)) return null;70
71 const meta: FileMetadata = {72 version: null, commit: null, url: null, contentHash: null,73 id: null, createdBy: null, modifiedBy: null, modifiedByType: null,74 syncStatus: null, space: null, branch: null, modifiedAt: null,75 };76 ATTRS.forEach((attr, i) => {77 meta[attr] = results[i];78 });79 return meta;80}81
82export function isMacOS(): boolean {83 return Platform.isMacOS;84} v1 of v4
commit 6663a80
message create xattr.ts via macOS
author anton
date Apr 8, 2026
size 1.9 KB