CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/npm-xcode

Parser utility for xcodeproj/project.pbxproj files that allows editing and writing back Xcode project files

Overview
Eval results
Files

project-parsing.mddocs/

Project Parsing and Writing

Core functionality for loading and saving Xcode project files with support for both asynchronous and synchronous operations.

Capabilities

Project Parsing

Parse Xcode project files (.pbxproj) into a manipulable JavaScript object structure.

/**
 * Parse project file asynchronously using worker process
 * Uses a forked child process to avoid blocking the main thread
 * @param {function} callback - Callback function(err, project)
 */
parse(callback);

/**
 * Parse project file synchronously
 * Blocks execution until parsing is complete
 * @returns {pbxProject} Self for chaining
 */
parseSync();

Usage Examples:

const xcode = require('xcode');
const proj = xcode.project('path/to/project.pbxproj');

// Asynchronous parsing (recommended for large projects)
proj.parse(function(err) {
    if (err) {
        console.error('Parse error:', err);
        return;
    }
    
    console.log('Project parsed successfully');
    console.log('Product name:', proj.productName);
    
    // Project is ready for manipulation
    proj.addSourceFile('MyNewFile.m');
});

// Synchronous parsing (simpler but blocking)
try {
    proj.parseSync();
    console.log('Project loaded:', proj.productName);
} catch (err) {
    console.error('Parse error:', err);
}

Project Writing

Serialize project data back to the pbxproj file format for saving to disk.

/**
 * Write project data to string format
 * Converts the internal project structure back to pbxproj format
 * @param {object} options - Formatting options for output control
 * @returns {string} Serialized project data ready for file writing
 */
writeSync(options);

Usage Examples:

const fs = require('fs');

// Basic writing
const projectData = proj.writeSync();
fs.writeFileSync('project.pbxproj', projectData);

// Writing with formatting options
const projectData = proj.writeSync({
    omitEmptyValues: true,  // Remove empty arrays/objects
    omitBuildFileSection: false,  // Keep build file section
    omitGroupChildren: false  // Keep group children arrays
});
fs.writeFileSync('project.pbxproj', projectData);

Writer Options

/**
 * Options for controlling project serialization
 */
interface WriterOptions {
  /** Remove empty values from output to reduce file size */
  omitEmptyValues?: boolean;
  
  /** Exclude build file section from output */
  omitBuildFileSection?: boolean;
  
  /** Exclude group children arrays from output */
  omitGroupChildren?: boolean;
}

Error Handling

The parsing operations can throw or return several types of errors:

// Common error scenarios
proj.parse(function(err) {
    if (err) {
        if (err.name === 'SyntaxError') {
            console.error('Invalid pbxproj file format:', err.message);
        } else if (err.code) {
            console.error('System error:', err.code, err.message);
        } else {
            console.error('Unknown parsing error:', err);
        }
    }
});

// Synchronous error handling
try {
    proj.parseSync();
} catch (err) {
    if (err.name === 'SyntaxError') {
        throw new Error('Invalid project file format');
    }
    throw err;
}

Project Data Structure

After parsing, the project data is available in the hash property:

/**
 * Parsed project data structure
 */
interface ProjectHash {
  /** Project metadata and configuration */
  project: {
    /** Root object UUID */
    rootObject: string;
    
    /** Project object sections */
    objects: {
      /** Project configuration */
      PBXProject: object;
      
      /** Build files */
      PBXBuildFile: object;
      
      /** File references */
      PBXFileReference: object;
      
      /** Groups */
      PBXGroup: object;
      
      /** Native targets */
      PBXNativeTarget: object;
      
      /** Build configurations */
      XCBuildConfiguration: object;
      
      /** Configuration lists */
      XCConfigurationList: object;
      
      /** Build phases */
      PBXSourcesBuildPhase: object;
      PBXResourcesBuildPhase: object;
      PBXFrameworksBuildPhase: object;
      PBXCopyFilesBuildPhase?: object;
      PBXShellScriptBuildPhase?: object;
      
      /** Target dependencies */
      PBXTargetDependency?: object;
      PBXContainerItemProxy?: object;
      
      /** Variant groups for localization */
      PBXVariantGroup?: object;
      
      /** Core Data version groups */
      XCVersionGroup?: object;
    };
  };
}

Usage Examples:

// Access parsed data directly
proj.parse(function(err) {
    if (err) throw err;
    
    // Access project sections
    const buildFiles = proj.hash.project.objects.PBXBuildFile;
    const fileReferences = proj.hash.project.objects.PBXFileReference;
    const groups = proj.hash.project.objects.PBXGroup;
    
    // Count files in project
    const buildFileCount = Object.keys(buildFiles).filter(key => !key.endsWith('_comment')).length;
    console.log('Build files in project:', buildFileCount);
    
    // Find specific groups
    for (let key in groups) {
        if (!key.endsWith('_comment')) {
            const group = groups[key];
            console.log('Group:', group.name, 'Children:', group.children?.length || 0);
        }
    }
});

Install with Tessl CLI

npx tessl i tessl/npm-xcode

docs

build-configuration.md

build-phases.md

file-management.md

frameworks-libraries.md

group-management.md

index.md

project-parsing.md

target-management.md

tile.json