UNPKG

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
"use strict"; 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 });