open-with-applications
Version:
A Node.js package to find applications that can open a file on macOS
190 lines (187 loc) • 6.8 kB
JavaScript
var __create = Object.create;
var __defProp = Object.defineProperty;
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
var __getOwnPropNames = Object.getOwnPropertyNames;
var __getProtoOf = Object.getPrototypeOf;
var __hasOwnProp = Object.prototype.hasOwnProperty;
var __export = (target, all) => {
for (var name in all)
__defProp(target, name, { get: all[name], enumerable: true });
};
var __copyProps = (to, from, except, desc) => {
if (from && typeof from === "object" || typeof from === "function") {
for (let key of __getOwnPropNames(from))
if (!__hasOwnProp.call(to, key) && key !== except)
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
}
return to;
};
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
// If the importer is in node compatibility mode or this is not an ESM
// file that has been converted to a CommonJS file using a Babel-
// compatible transform (i.e. "__esModule" has not been set), then set
// "default" to the CommonJS "module.exports" for node compatibility.
isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
mod
));
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
// src/index.ts
var index_exports = {};
__export(index_exports, {
Mac: () => Mac
});
module.exports = __toCommonJS(index_exports);
// src/findApplications/macos.ts
var import_ffi_rs = __toESM(require("ffi-rs"), 1);
var import_child_process = require("child_process");
var import_fs = __toESM(require("fs"), 1);
var import_path = __toESM(require("path"), 1);
var import_plist = __toESM(require("plist"), 1);
function getFileUTI(filePath) {
if (!import_fs.default.existsSync(filePath)) {
throw new Error(`File not found: ${filePath}`);
}
try {
const uti = (0, import_child_process.execSync)(`mdls -name kMDItemContentType -r "${filePath}"`, {
encoding: "utf8"
}).trim();
return uti || null;
} catch (err) {
console.error("Error getting UTI:", err);
return null;
}
}
function getAppPathFromBundleId(bundleId) {
try {
const appPath = (0, import_child_process.execSync)(
`mdfind "kMDItemCFBundleIdentifier == '${bundleId}'"`,
{ encoding: "utf8" }
).trim();
if (appPath) {
return appPath;
} else {
console.error(`Application with bundle ID '${bundleId}' not found.`);
return null;
}
} catch (err) {
console.error("Error searching for application:", err);
return null;
}
}
var getBundleIdentifiers = (uniformTypeIdentifier) => {
import_ffi_rs.default.open({
library: "CoreFoundation",
path: "/System/Library/Frameworks/CoreFoundation.framework/CoreFoundation"
});
import_ffi_rs.default.open({
library: "CoreServices",
path: "/System/Library/Frameworks/CoreServices.framework/CoreServices"
});
const CoreFoundation = import_ffi_rs.default.define({
CFStringCreateWithCString: {
library: "CoreFoundation",
retType: import_ffi_rs.default.DataType.U64,
paramsType: [import_ffi_rs.default.DataType.U64, import_ffi_rs.default.DataType.String, import_ffi_rs.default.DataType.U64]
},
CFRelease: {
library: "CoreFoundation",
retType: import_ffi_rs.default.DataType.Void,
paramsType: [import_ffi_rs.default.DataType.U64]
},
CFArrayGetCount: {
library: "CoreFoundation",
retType: import_ffi_rs.default.DataType.U64,
paramsType: [import_ffi_rs.default.DataType.U64]
},
CFArrayGetValueAtIndex: {
library: "CoreFoundation",
retType: import_ffi_rs.default.DataType.U64,
paramsType: [import_ffi_rs.default.DataType.U64, import_ffi_rs.default.DataType.U64]
// CFArrayRef, index
},
CFStringGetCStringPtr: {
library: "CoreFoundation",
retType: import_ffi_rs.default.DataType.String,
paramsType: [import_ffi_rs.default.DataType.U64, import_ffi_rs.default.DataType.U64]
// theString, buffer
}
});
const CoreServices = import_ffi_rs.default.define({
LSCopyAllRoleHandlersForContentType: {
library: "CoreServices",
retType: import_ffi_rs.default.DataType.U64,
paramsType: [import_ffi_rs.default.DataType.U64, import_ffi_rs.default.DataType.I32]
// CFStringRef, LSRolesMask
}
});
const kCFStringEncodingUTF8 = 134217984;
const kCFAllocatorDefault = 0;
const kLSRolesAll = 4294967295;
const cfString = CoreFoundation.CFStringCreateWithCString([
kCFAllocatorDefault,
uniformTypeIdentifier,
kCFStringEncodingUTF8
]);
const cfArray = CoreServices.LSCopyAllRoleHandlersForContentType([
cfString,
kLSRolesAll
]);
const bundleIDs = [];
if (cfArray !== 0) {
const count = CoreFoundation.CFArrayGetCount([cfArray]);
for (let i = 0; i < count; i++) {
const appCFString = CoreFoundation.CFArrayGetValueAtIndex([cfArray, i]);
const bundleID = CoreFoundation.CFStringGetCStringPtr([appCFString, 0]);
bundleIDs.push(bundleID);
}
CoreFoundation.CFRelease([cfArray]);
} else {
console.log("No apps found that can open .txt files.");
}
CoreFoundation.CFRelease([cfString]);
import_ffi_rs.default.close("CoreFoundation");
import_ffi_rs.default.close("CoreServices");
return bundleIDs;
};
var appPathToApplication = (appPath) => {
if (!appPath) return null;
try {
const infoPlistPath = import_path.default.join(appPath, "Contents", "Info.plist");
if (import_fs.default.existsSync(infoPlistPath)) {
const plistContent = import_fs.default.readFileSync(infoPlistPath, "utf8");
const parsedPlist = import_plist.default.parse(plistContent);
const name = parsedPlist.CFBundleDisplayName || parsedPlist.CFBundleName || "Unknown";
const iconPath = parsedPlist.CFBundleIconFile ? import_path.default.join(
appPath,
"Contents",
"Resources",
parsedPlist.CFBundleIconFile
) : null;
return {
name,
path: appPath,
iconPath
};
}
} catch (err) {
console.error("Error processing app path:", appPath, err);
}
return null;
};
var Mac = {
getApplications: (filePath) => {
const fileUTI = getFileUTI(filePath);
if (!fileUTI) {
throw new Error(`${filePath} has not valid UTI.`);
}
const bundleIdentifiers = getBundleIdentifiers(fileUTI);
const appPaths = bundleIdentifiers.map(getAppPathFromBundleId);
const applications = appPaths.map(appPathToApplication).filter((app) => app !== null);
return applications;
}
};
// Annotate the CommonJS export names for ESM import in node:
0 && (module.exports = {
Mac
});
;