Low-level DMG file operations including mounting, unmounting, and executing tasks on mounted volumes. These utilities provide the foundation for DMG manipulation and content management using macOS hdiutil commands.
Safely attaches a DMG file, executes a task on the mounted volume, and ensures proper cleanup even if the task fails.
/**
* Attach DMG file, execute task on mounted volume, then detach
* Provides automatic cleanup even if the task throws an error
* @param dmgPath - Path to the DMG file to attach
* @param readWrite - Whether to mount in read-write mode (true) or read-only (false)
* @param task - Function to execute with the mounted volume path (e.g., "/Volumes/VolumeName")
* @returns Promise resolving to the task result
* @throws Error if DMG cannot be mounted or device not found
*/
function attachAndExecute<T>(
dmgPath: string,
readWrite: boolean,
task: (volumePath: string) => Promise<T>
): Promise<T>;Usage Examples:
import { attachAndExecute } from "dmg-builder";
// Read-only access to examine DMG contents
const fileList = await attachAndExecute(
"/path/to/installer.dmg",
false, // read-only
async (volumePath) => {
const fs = require("fs-extra");
return await fs.readdir(volumePath);
}
);
// Read-write access to modify DMG contents
await attachAndExecute(
"/path/to/installer.dmg",
true, // read-write
async (volumePath) => {
const fs = require("fs-extra");
await fs.writeFile(`${volumePath}/.DS_Store`, dsStoreData);
await fs.copy("/source/files", `${volumePath}/ExtraFiles`);
}
);Safely detaches a mounted DMG volume with automatic retry logic for transient failures.
/**
* Detach/unmount a DMG volume by device name
* Includes retry logic for busy volumes with force unmount fallback
* @param name - Device name to detach (e.g., "/dev/disk2")
* @returns Promise resolving to hdiutil output or null
* @throws Error if detachment fails after retries
*/
function detach(name: string): Promise<string | null>;Usage Examples:
import { detach } from "dmg-builder";
// Detach a specific device
await detach("/dev/disk2");
// Manual volume management (not recommended - use attachAndExecute instead)
const attachResult = await hdiUtil(["attach", "-noverify", "/path/to/file.dmg"]);
const deviceMatch = /^(\/dev\/\w+)/.exec(attachResult || "");
if (deviceMatch) {
try {
// ... do work with mounted volume
} finally {
await detach(deviceMatch[1]);
}
}Utility functions for locating DMG Builder resources and templates.
/**
* Get path to DMG template directory containing default resources
* @returns Absolute path to templates directory
*/
function getDmgTemplatePath(): string;
/**
* Get path to DMG vendor directory containing Python scripts and dependencies
* @returns Absolute path to vendor directory
*/
function getDmgVendorPath(): string;Usage Examples:
import { getDmgTemplatePath, getDmgVendorPath } from "dmg-builder";
// Access default background template
const templatePath = getDmgTemplatePath();
const backgroundPath = `${templatePath}/background.tiff`;
// Access Python dmgbuild scripts
const vendorPath = getDmgVendorPath();
const pythonScript = `${vendorPath}/run_dmgbuild.py`;Utilities for processing and converting background images for DMG use.
/**
* Transform background image to TIFF format if needed
* Handles retina images by combining standard and @2x versions
* @param file - Path to background image file
* @param tmpDir - Temporary directory manager for intermediate files
* @returns Promise resolving to path of processed TIFF file
*/
function transformBackgroundFileIfNeed(file: string, tmpDir: TmpDir): Promise<string>;
/**
* Get image dimensions using macOS sips tool
* @param background - Path to image file
* @returns Promise resolving to object with width and height properties
* @throws Error if sips command fails or cannot parse dimensions
*/
function getImageSizeUsingSips(background: string): Promise<{width: number, height: number}>;Usage Examples:
import { transformBackgroundFileIfNeed, getImageSizeUsingSips } from "dmg-builder";
import { TmpDir } from "builder-util";
const tmpDir = new TmpDir("dmg-background");
// Convert PNG to TIFF and handle retina images
const backgroundPath = await transformBackgroundFileIfNeed(
"/path/to/background.png",
tmpDir
);
// Get dimensions for window sizing
const { width, height } = await getImageSizeUsingSips(backgroundPath);
console.log(`Background size: ${width}x${height}`);Internal utility for serializing strings for AppleScript usage in DMG customization.
/**
* Serialize string data for AppleScript resource format
* Used internally for license button text and other DMG resources
* @param data - String data to serialize
* @returns Formatted string for AppleScript resource usage
*/
function serializeString(data: string): string;The attachAndExecute function uses intelligent mount path detection:
hdiutil attach with appropriate flags/^(\/dev\/\w+)/hdiutil info to find corresponding mount path in /Volumes/The detach function implements robust retry logic:
-quiet flag-force flag for stubborn volumesBackground processing handles macOS-specific requirements:
image.png + image@2x.png using tiffutil -cathidpichecksips tool to extract pixel dimensions for window sizingCommon error scenarios and handling:
All functions include appropriate error messages and throw descriptive errors for debugging.