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

group-management.mddocs/

Group Management

Project organization system for managing file groups, variant groups, and hierarchical project structure with support for custom groups and localization.

Capabilities

Group Creation and Management

Create and manage PBXGroup structures for organizing files in the Xcode project navigator.

/**
 * Create new PBXGroup with files
 * @param {string[]} filePathsArray - Array of file paths to include in group
 * @param {string} name - Group name displayed in Xcode
 * @param {string} path - Group path on filesystem (optional)
 * @param {string} sourceTree - Source tree type (default: "<group>")
 * @returns {object} Group object with UUID and group data
 */
addPbxGroup(filePathsArray, name, path, sourceTree);

/**
 * Remove PBXGroup by name
 * @param {string} groupName - Name of group to remove
 */
removePbxGroup(groupName);

/**
 * Create new PBXGroup with UUID generation
 * @param {string} name - Group name
 * @param {string} pathName - Optional path for group
 * @returns {string} Generated UUID for the new group
 */
pbxCreateGroup(name, pathName);

Usage Examples:

// Create group with files
const sourceGroup = proj.addPbxGroup(
    ['src/Model.m', 'src/View.m', 'src/Controller.m'],
    'MVC Components',
    'src'
);
console.log('Created group with UUID:', sourceGroup.uuid);

// Create empty group and add files later
const utilsGroupUuid = proj.pbxCreateGroup('Utilities', 'utils');
proj.addFile('utils/Helper.m', utilsGroupUuid);
proj.addFile('utils/Constants.h', utilsGroupUuid);

// Remove group
proj.removePbxGroup('Old Components');

Variant Group Management

Create and manage PBXVariantGroup for localization and file variants.

/**
 * Create new PBXVariantGroup for localization
 * @param {string} name - Variant group name
 * @returns {string} Generated UUID for the variant group
 */
pbxCreateVariantGroup(name);

/**
 * Add localization variant group with build phase integration
 * @param {string} name - Name of the localization group
 * @returns {object} Variant group object with build phase integration
 */
addLocalizationVariantGroup(name);

Usage Examples:

// Create variant group for localization
const localizedStrings = proj.addLocalizationVariantGroup('Localizable.strings');

// Create empty variant group
const imageVariantUuid = proj.pbxCreateVariantGroup('AppIcon.png');

// Add localized files to variant group
proj.addFile('en.lproj/Localizable.strings', localizedStrings.fileRef);
proj.addFile('es.lproj/Localizable.strings', localizedStrings.fileRef);

Group Access and Search

Find and access existing groups in the project structure.

/**
 * Find group by name
 * @param {string} name - Group name to search for
 * @returns {object|null} Group object or null if not found
 */
pbxGroupByName(name);

/**
 * Get group by UUID key
 * @param {string} key - Group UUID
 * @returns {object} Group object
 */
getPBXGroupByKey(key);

/**
 * Get variant group by UUID key
 * @param {string} key - Variant group UUID
 * @returns {object} Variant group object
 */
getPBXVariantGroupByKey(key);

/**
 * Find group key by search criteria
 * @param {object} criteria - Search criteria (name, path, or both)
 * @returns {string|null} Group UUID or null if not found
 */
findPBXGroupKey(criteria);

/**
 * Find variant group key by search criteria
 * @param {object} criteria - Search criteria
 * @returns {string|null} Variant group UUID or null if not found
 */
findPBXVariantGroupKey(criteria);

Usage Examples:

// Find existing groups
const resourcesGroup = proj.pbxGroupByName('Resources');
if (resourcesGroup) {
    console.log('Resources group children:', resourcesGroup.children.length);
}

// Search by criteria
const sourceGroupKey = proj.findPBXGroupKey({ name: 'Sources', path: 'src' });
const docGroupKey = proj.findPBXGroupKey({ path: 'Documentation' });

// Access group by UUID
const group = proj.getPBXGroupByKey(sourceGroupKey);
console.log('Group name:', group.name);

File-to-Group Operations

Add and remove files to/from specific groups.

/**
 * Add file to existing PBXGroup
 * @param {object|string} file - File object or group key
 * @param {string} groupKey - Target group UUID
 */
addToPbxGroup(file, groupKey);

/**
 * Remove file from PBXGroup
 * @param {object} file - File object to remove
 * @param {string} groupKey - Source group UUID
 */
removeFromPbxGroup(file, groupKey);

/**
 * Add file to PBXVariantGroup
 * @param {object} file - File object to add
 * @param {string} groupKey - Target variant group UUID
 */
addToPbxVariantGroup(file, groupKey);

/**
 * Remove file from PBXVariantGroup
 * @param {object} file - File object to remove
 * @param {string} groupKey - Source variant group UUID
 */
removeFromPbxVariantGroup(file, groupKey);

Usage Examples:

// Add file to existing group
const sourceFile = proj.addFile('NewClass.m', null); // Create without group
const sourcesGroupKey = proj.findPBXGroupKey({ name: 'Sources' });
proj.addToPbxGroup(sourceFile, sourcesGroupKey);

// Add file to variant group for localization
const localizedFile = proj.addFile('en.lproj/Main.strings', null);
const stringsVariantKey = proj.findPBXVariantGroupKey({ name: 'Main.strings' });
proj.addToPbxVariantGroup(localizedFile, stringsVariantKey);

// Remove file from group
proj.removeFromPbxGroup(sourceFile, sourcesGroupKey);

Default Group Management

Access and manage standard Xcode groups.

// Standard group access methods (internal but commonly used)

/**
 * Add file to Plugins group (creates if doesn't exist)
 * @param {object} file - File object to add
 */
addToPluginsPbxGroup(file);

/**
 * Add file to Resources group (creates if doesn't exist)
 * @param {object} file - File object to add
 */
addToResourcesPbxGroup(file);

/**
 * Add file to Frameworks group (creates if doesn't exist)
 * @param {object} file - File object to add
 */
addToFrameworksPbxGroup(file);

/**
 * Add file to Products group (creates if doesn't exist)
 * @param {object} file - File object to add
 */
addToProductsPbxGroup(file);

Usage Examples:

// These are typically called automatically by higher-level methods
// but can be used directly for custom organization

// Add framework to Frameworks group
const framework = { fileRef: 'UUID', basename: 'MyFramework.framework' };
proj.addToFrameworksPbxGroup(framework);

// Add resource to Resources group
const resource = { fileRef: 'UUID', basename: 'icon.png' };
proj.addToResourcesPbxGroup(resource);

Localization and Region Management

Manage known regions for localization support.

/**
 * Add known region for localization
 * @param {string} name - Region code (e.g., 'en', 'es', 'fr')
 */
addKnownRegion(name);

/**
 * Remove known region
 * @param {string} name - Region code to remove
 */
removeKnownRegion(name);

/**
 * Check if region is known
 * @param {string} name - Region code to check
 * @returns {boolean} True if region is known
 */
hasKnownRegion(name);

Usage Examples:

// Add localization regions
proj.addKnownRegion('en');
proj.addKnownRegion('es');
proj.addKnownRegion('fr');

// Check if region exists
if (!proj.hasKnownRegion('de')) {
    proj.addKnownRegion('de');
    console.log('Added German localization');
}

// Remove unused region
proj.removeKnownRegion('old-region');

Group Structure Types

/**
 * Group structure definitions
 */
interface PBXGroup {
  /** Group type identifier */
  isa: 'PBXGroup';
  
  /** Array of child file/group references */
  children: GroupChild[];
  
  /** Group name displayed in Xcode */
  name?: string;
  
  /** Filesystem path (optional) */
  path?: string;
  
  /** Source tree type */
  sourceTree: string;
}

interface PBXVariantGroup {
  /** Variant group type identifier */
  isa: 'PBXVariantGroup';
  
  /** Array of variant file references */
  children: GroupChild[];
  
  /** Variant group name */
  name: string;
  
  /** Source tree type */
  sourceTree: string;
}

interface GroupChild {
  /** Reference UUID */
  value: string;
  
  /** Display comment/name */
  comment: string;
}

Search Criteria Options

/**
 * Search criteria for finding groups
 */
interface GroupSearchCriteria {
  /** Group name to match */
  name?: string;
  
  /** Group path to match */
  path?: string;
}

Usage Examples:

// Search by name only
const resourcesKey = proj.findPBXGroupKey({ name: 'Resources' });

// Search by path only
const srcKey = proj.findPBXGroupKey({ path: 'src' });

// Search by both name and path
const specificKey = proj.findPBXGroupKey({ 
    name: 'Custom Sources', 
    path: 'custom/src' 
});

Advanced Group Patterns

Hierarchical Group Structure:

// Create nested group structure
const mainGroupKey = proj.pbxCreateGroup('Application');
const modelsGroupKey = proj.pbxCreateGroup('Models', 'src/models');
const viewsGroupKey = proj.pbxCreateGroup('Views', 'src/views');

// Add sub-groups to main group
proj.addToPbxGroup(modelsGroupKey, mainGroupKey);
proj.addToPbxGroup(viewsGroupKey, mainGroupKey);

// Add files to sub-groups
proj.addFile('src/models/User.m', modelsGroupKey);
proj.addFile('src/views/UserView.m', viewsGroupKey);

Localization Setup:

// Set up complete localization structure
const supportedLanguages = ['en', 'es', 'fr', 'de'];

// Add known regions
supportedLanguages.forEach(lang => {
    proj.addKnownRegion(lang);
});

// Create localized strings variant group
const stringsGroup = proj.addLocalizationVariantGroup('Localizable.strings');

// Add localized files
supportedLanguages.forEach(lang => {
    const localizedFile = proj.addFile(`${lang}.lproj/Localizable.strings`, null);
    proj.addToPbxVariantGroup(localizedFile, stringsGroup.fileRef);
});

Low-Level Group Operations

Advanced methods for direct group manipulation at the PBX level, useful for custom group types and specialized operations.

/**
 * Add file or group to any PBXGroup type
 * Generic method that works with PBXGroup, PBXVariantGroup, etc.
 * @param {object|string} file - File object or group key to add
 * @param {string} groupKey - Target group UUID
 * @param {string} groupType - PBX group type (PBXGroup, PBXVariantGroup)
 */
addToPbxGroupType(file, groupKey, groupType);

/**
 * Remove file or group from any PBXGroup type
 * Generic removal method for all group types
 * @param {object|string} file - File object or group key to remove
 * @param {string} groupKey - Target group UUID  
 * @param {string} groupType - PBX group type (PBXGroup, PBXVariantGroup)
 */
removeFromPbxGroupAndType(file, groupKey, groupType);

/**
 * Get group object by key and type
 * Direct access to group objects in project structure
 * @param {string} key - Group UUID
 * @param {string} groupType - PBX group type
 * @returns {object|undefined} Group object or undefined if not found
 */
getPBXGroupByKeyAndType(key, groupType);

/**
 * Get any PBX object section by name
 * Generic access to project object sections
 * @param {string} name - Section name (PBXGroup, PBXFileReference, etc.)
 * @returns {object} Section object containing all items of that type
 */
getPBXObject(name);

Usage Examples:

// Direct group type manipulation
proj.addToPbxGroupType(file, groupKey, 'PBXVariantGroup');
proj.removeFromPbxGroupAndType(file, groupKey, 'PBXGroup');

// Access specific section types
const allGroups = proj.getPBXObject('PBXGroup');
const allFileRefs = proj.getPBXObject('PBXFileReference');

// Direct group access by type
const variantGroup = proj.getPBXGroupByKeyAndType(groupKey, 'PBXVariantGroup');
const regularGroup = proj.getPBXGroupByKeyAndType(groupKey, 'PBXGroup');

// Advanced group manipulation
Object.keys(allGroups).forEach(groupKey => {
    if (!groupKey.endsWith('_comment')) {
        const group = allGroups[groupKey];
        console.log(`Group ${group.name} has ${group.children.length} children`);
    }
});

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