From ccee739c34d957ce5b084c22306cbaf161ebba7e Mon Sep 17 00:00:00 2001 From: YevheniiKotyrlo <44449990+YevheniiKotyrlo@users.noreply.github.com> Date: Sat, 14 Mar 2026 18:54:21 +0200 Subject: [PATCH] =?UTF-8?q?=F0=9F=A4=96=20Merge=20PR=20#74597=20Add=20type?= =?UTF-8?q?s=20for=20xcode=20by=20@YevheniiKotyrlo?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- types/xcode/.npmignore | 5 + types/xcode/index.d.ts | 346 ++++++++++++++++++++++++++++++++++ types/xcode/package.json | 17 ++ types/xcode/tsconfig.json | 19 ++ types/xcode/xcode-tests.ts | 377 +++++++++++++++++++++++++++++++++++++ 5 files changed, 764 insertions(+) create mode 100644 types/xcode/.npmignore create mode 100644 types/xcode/index.d.ts create mode 100644 types/xcode/package.json create mode 100644 types/xcode/tsconfig.json create mode 100644 types/xcode/xcode-tests.ts diff --git a/types/xcode/.npmignore b/types/xcode/.npmignore new file mode 100644 index 00000000000000..93e307400a5456 --- /dev/null +++ b/types/xcode/.npmignore @@ -0,0 +1,5 @@ +* +!**/*.d.ts +!**/*.d.cts +!**/*.d.mts +!**/*.d.*.ts diff --git a/types/xcode/index.d.ts b/types/xcode/index.d.ts new file mode 100644 index 00000000000000..52850208e4d118 --- /dev/null +++ b/types/xcode/index.d.ts @@ -0,0 +1,346 @@ +export type UUID = string; + +/** + * A section within the pbxproj objects dict. + * Keys are UUIDs mapping to object records, or `${uuid}_comment` keys mapping to strings. + */ +export type PbxprojSection = Record | string>; + +/** Known section names within `hash.project.objects`. */ +export interface PbxprojObjects { + PBXBuildFile: PbxprojSection; + PBXFileReference: PbxprojSection; + PBXGroup: PbxprojSection; + PBXNativeTarget: PbxprojSection; + PBXProject: PbxprojSection; + XCBuildConfiguration: PbxprojSection; + XCConfigurationList: PbxprojSection; + PBXSourcesBuildPhase?: PbxprojSection; + PBXResourcesBuildPhase?: PbxprojSection; + PBXFrameworksBuildPhase?: PbxprojSection; + PBXVariantGroup?: PbxprojSection; + XCVersionGroup?: PbxprojSection; + PBXCopyFilesBuildPhase?: PbxprojSection; + PBXShellScriptBuildPhase?: PbxprojSection; + PBXContainerItemProxy?: PbxprojSection; + PBXTargetDependency?: PbxprojSection; + [sectionName: string]: PbxprojSection | undefined; +} + +/** The full parsed .pbxproj structure, stored as `XcodeProject.hash`. */ +export interface PbxprojHash { + headComment?: string; + project: { + archiveVersion: string; + objectVersion: string; + rootObject: UUID; + rootObject_comment?: string; + classes: Record; + objects: PbxprojObjects; + }; +} + +export interface PBXFile { + basename: string; + lastKnownFileType?: string; + group?: string; + customFramework?: boolean; + dirname?: string; + path?: string; + fileEncoding?: number; + defaultEncoding?: number; + explicitFileType?: string; + sourceTree: string; + includeInIndex: number; + settings?: { ATTRIBUTES?: string[]; COMPILER_FLAGS?: string }; + plugin?: boolean; + uuid?: UUID; + fileRef?: UUID; + target?: string; + /** Child model files, set by addDataModelDocument. */ + models?: PBXFile[]; + /** Current version model file, set by addDataModelDocument. */ + currentModel?: PBXFile; + [key: string]: unknown; +} + +export interface PBXGroup { + isa: string; + children: Array<{ value: UUID; comment?: string }>; + name?: string; + path?: string; + sourceTree: string; + [key: string]: unknown; +} + +export interface PBXNativeTarget { + isa: string; + buildConfigurationList: UUID; + buildPhases: Array<{ value: UUID; comment?: string }>; + buildRules: unknown[]; + dependencies: Array<{ value: UUID; comment?: string }>; + name: string; + productName: string; + productReference: UUID; + productType: string; + [key: string]: unknown; +} + +export interface PBXProject { + isa: string; + attributes: Record; + buildConfigurationList: UUID; + compatibilityVersion: string; + developmentRegion: string; + hasScannedForEncodings: number; + knownRegions: string[]; + mainGroup: UUID; + productRefGroup: UUID; + projectDirPath: string; + projectRoot: string; + targets: Array<{ value: UUID; comment?: string }>; + [key: string]: unknown; +} + +export interface XCBuildConfiguration { + isa: string; + baseConfigurationReference?: UUID; + buildSettings: Record; + name: string; + [key: string]: unknown; +} + +export interface XCConfigurationList { + isa: string; + buildConfigurations: Array<{ value: UUID; comment?: string }>; + defaultConfigurationIsVisible: number; + defaultConfigurationName: string; + [key: string]: unknown; +} + +export interface BuildPhaseObject { + isa: string; + buildActionMask: number; + files: Array<{ value: UUID; comment: string }>; + runOnlyForDeploymentPostprocessing: number; + name?: string; + /** PBXShellScriptBuildPhase */ + inputPaths?: string[]; + /** PBXShellScriptBuildPhase */ + outputPaths?: string[]; + /** PBXShellScriptBuildPhase */ + shellPath?: string; + /** PBXShellScriptBuildPhase */ + shellScript?: string; + /** PBXCopyFilesBuildPhase */ + dstPath?: string; + /** PBXCopyFilesBuildPhase */ + dstSubfolderSpec?: number; + [key: string]: unknown; +} + +export interface PBXFileOptions { + lastKnownFileType?: string; + defaultEncoding?: number; + customFramework?: boolean; + explicitFileType?: string; + weak?: boolean; + compilerFlags?: string; + embed?: boolean; + sign?: boolean; + link?: boolean; + sourceTree?: string; + target?: string; + group?: string; + plugin?: boolean; + variantGroup?: boolean; +} + +export interface WriteOptions { + omitEmptyValues?: boolean; +} + +/** + * Serialized error from child process worker (not an Error instance). + * `parse()` runs in a forked process via `child_process.fork()` with JSON serialization, + * so only own enumerable properties survive. PEG parser errors carry `message`/`name`; + * filesystem errors carry `code`/`errno`. + */ +export interface ParseError { + /** Present for PEG parser syntax errors. */ + message?: string; + /** "SyntaxError" for PEG parser errors. */ + name?: string; + /** Filesystem error code (e.g., "ENOENT"). */ + code?: string; + [key: string]: unknown; +} + +export interface XcodeProject { + filepath: string; + hash: PbxprojHash; + readonly productName: string | undefined; + + parse(callback?: (err: ParseError | null, results?: unknown) => void): this; + parseSync(): this; + writeSync(options?: WriteOptions): string; + allUuids(): UUID[]; + generateUuid(): UUID; + + // File management + addPluginFile(path: string, opt?: PBXFileOptions): PBXFile | null; + removePluginFile(path: string, opt?: PBXFileOptions): PBXFile; + addProductFile(targetPath: string, opt?: PBXFileOptions): PBXFile; + removeProductFile(path: string, opt?: PBXFileOptions): PBXFile; + addSourceFile(path: string, opt?: PBXFileOptions, group?: string): PBXFile | false; + removeSourceFile(path: string, opt?: PBXFileOptions, group?: string): PBXFile; + addHeaderFile(path: string, opt?: PBXFileOptions, group?: string): PBXFile | null; + removeHeaderFile(path: string, opt?: PBXFileOptions, group?: string): PBXFile; + addResourceFile(path: string, opt?: PBXFileOptions, group?: string): PBXFile | false; + removeResourceFile(path: string, opt?: PBXFileOptions, group?: string): PBXFile; + addFramework(path: string, opt?: PBXFileOptions): PBXFile | false; + removeFramework(path: string, opt?: PBXFileOptions): PBXFile; + addCopyfile(path: string, opt?: PBXFileOptions): PBXFile; + removeCopyfile(path: string, opt?: PBXFileOptions): PBXFile; + addStaticLibrary(path: string, opt?: PBXFileOptions): PBXFile | false; + hasFile(filePath: string): PBXFile | false; + addFile(path: string, group?: string, opt?: PBXFileOptions): PBXFile | null; + removeFile(path: string, group?: string, opt?: PBXFileOptions): PBXFile; + addDataModelDocument(filePath: string, group?: string, opt?: PBXFileOptions): PBXFile | null; + + // Section manipulation + addToPbxBuildFileSection(file: PBXFile): void; + removeFromPbxBuildFileSection(file: PBXFile): void; + addToPbxFileReferenceSection(file: PBXFile): void; + removeFromPbxFileReferenceSection(file: PBXFile): PBXFile; + addToXcVersionGroupSection(file: PBXFile): void; + + // Group management + addPbxGroup( + filePathsArray: string[], + name: string, + path: string, + sourceTree?: string, + ): { uuid: UUID; pbxGroup: PBXGroup }; + removePbxGroup(groupName: string): void; + addToPluginsPbxGroup(file: PBXFile): void; + removeFromPluginsPbxGroup(file: PBXFile): void; + addToResourcesPbxGroup(file: PBXFile): void; + removeFromResourcesPbxGroup(file: PBXFile): void; + addToFrameworksPbxGroup(file: PBXFile): void; + removeFromFrameworksPbxGroup(file: PBXFile): void; + addToProductsPbxGroup(file: PBXFile): void; + removeFromProductsPbxGroup(file: PBXFile): void; + addToPbxGroupType(file: PBXFile | string, groupKey: string, groupType: string): void; + addToPbxVariantGroup(file: PBXFile | string, groupKey: string): void; + addToPbxGroup(file: PBXFile | string, groupKey: string): void; + pbxCreateGroupWithType(name: string, pathName: string | undefined, groupType: string): UUID; + pbxCreateVariantGroup(name: string): UUID; + pbxCreateGroup(name: string, pathName: string): UUID; + removeFromPbxGroupAndType(file: PBXFile, groupKey: string, groupType: string): void; + removeFromPbxGroup(file: PBXFile, groupKey: string): void; + removeFromPbxVariantGroup(file: PBXFile, groupKey: string): void; + getPBXGroupByKeyAndType(key: string, groupType: string): PBXGroup | undefined; + getPBXGroupByKey(key: string): PBXGroup | undefined; + getPBXVariantGroupByKey(key: string): PBXGroup | undefined; + findPBXGroupKeyAndType(criteria: Record, groupType: string): string | undefined; + findPBXGroupKey(criteria: Record): string | undefined; + findPBXVariantGroupKey(criteria: Record): string | undefined; + addLocalizationVariantGroup(name: string): { uuid: UUID; fileRef: UUID; basename: string }; + + // Build phase management + addToPbxEmbedFrameworksBuildPhase(file: PBXFile): void; + removeFromPbxEmbedFrameworksBuildPhase(file: PBXFile): void; + addToPbxSourcesBuildPhase(file: PBXFile): void; + removeFromPbxSourcesBuildPhase(file: PBXFile): void; + addToPbxResourcesBuildPhase(file: PBXFile): void; + removeFromPbxResourcesBuildPhase(file: PBXFile): void; + addToPbxFrameworksBuildPhase(file: PBXFile): void; + removeFromPbxFrameworksBuildPhase(file: PBXFile): void; + addToPbxCopyfilesBuildPhase(file: PBXFile): void; + removeFromPbxCopyfilesBuildPhase(file: PBXFile): void; + addBuildPhase( + filePathsArray: string[], + buildPhaseType: string, + comment: string, + target?: UUID, + optionsOrFolderType?: string | Record, + subfolderPath?: string, + ): { uuid: UUID; buildPhase: BuildPhaseObject }; + + // Target management + addToPbxProjectSection(target: { uuid: UUID; pbxNativeTarget: PBXNativeTarget }): void; + addToPbxNativeTargetSection(target: { uuid: UUID; pbxNativeTarget: PBXNativeTarget }): void; + addXCConfigurationList( + configurationObjectsArray: XCBuildConfiguration[], + defaultConfigurationName: string, + comment?: string, + ): { uuid: UUID; xcConfigurationList: XCConfigurationList }; + addTargetDependency( + target: UUID, + dependencyTargets: UUID[], + ): { uuid: UUID; target: PBXNativeTarget } | undefined; + addTarget( + name: string, + type: string, + subfolder?: string, + bundleId?: string, + ): { uuid: UUID; pbxNativeTarget: PBXNativeTarget }; + + // Section accessors + pbxProjectSection(): Record; + pbxBuildFileSection(): PbxprojSection; + pbxXCBuildConfigurationSection(): Record; + pbxFileReferenceSection(): PbxprojSection; + pbxNativeTargetSection(): Record; + xcVersionGroupSection(): PbxprojSection; + pbxXCConfigurationList(): Record; + getPBXObject(name: string): PbxprojSection | undefined; + + // Section lookups + pbxGroupByName(name: string): PBXGroup | null; + pbxTargetByName(name: string): PBXNativeTarget | null; + findTargetKey(name: string): string | null; + pbxItemByComment(name: string, pbxSectionName: string): Record | null; + pbxSourcesBuildPhaseObj(target?: UUID): BuildPhaseObject | null; + pbxResourcesBuildPhaseObj(target?: UUID): BuildPhaseObject | null; + pbxFrameworksBuildPhaseObj(target?: UUID): BuildPhaseObject | null; + pbxEmbedFrameworksBuildPhaseObj(target?: UUID): BuildPhaseObject | null; + pbxCopyfilesBuildPhaseObj(target?: UUID): BuildPhaseObject | null; + buildPhase(group: string, target?: UUID): string | undefined; + buildPhaseObject(name: string, group: string, target?: UUID): BuildPhaseObject | null; + + // Build settings + addBuildProperty(prop: string, value: string | string[] | number, buildName?: string): void; + removeBuildProperty(prop: string, buildName?: string): void; + updateBuildProperty(prop: string, value: string | string[] | number, build?: string, targetName?: string): void; + updateProductName(name: string): void; + getBuildProperty(prop: string, build?: string, targetName?: string): string | string[] | number | undefined; + getBuildConfigByName(name: string): Record; + addToFrameworkSearchPaths(file: PBXFile): void; + removeFromFrameworkSearchPaths(file: PBXFile): void; + addToLibrarySearchPaths(file: PBXFile | string): void; + removeFromLibrarySearchPaths(file: PBXFile): void; + addToHeaderSearchPaths(file: PBXFile | string): void; + removeFromHeaderSearchPaths(file: PBXFile): void; + addToOtherLinkerFlags(flag: string): void; + removeFromOtherLinkerFlags(flag: string): void; + addToBuildSettings(buildSetting: string, value: unknown): void; + removeFromBuildSettings(buildSetting: string): void; + + // Project queries + getFirstProject(): { uuid: UUID; firstProject: PBXProject }; + getFirstTarget(): { uuid: UUID; firstTarget: PBXNativeTarget }; + getTarget(productType: string): { uuid: UUID; target: PBXNativeTarget } | null; + + // Known regions + addKnownRegion(name: string): void; + removeKnownRegion(name: string): void; + hasKnownRegion(name: string): boolean; + + // Target attributes + addTargetAttribute(prop: string, value: unknown, target?: { uuid: UUID }): void; + removeTargetAttribute(prop: string, target?: { uuid: UUID }): void; +} + +export function project(projectPath: string): XcodeProject; diff --git a/types/xcode/package.json b/types/xcode/package.json new file mode 100644 index 00000000000000..0470da94d3f365 --- /dev/null +++ b/types/xcode/package.json @@ -0,0 +1,17 @@ +{ + "private": true, + "name": "@types/xcode", + "version": "3.0.9999", + "projects": [ + "https://github.com/apache/cordova-node-xcode" + ], + "devDependencies": { + "@types/xcode": "workspace:." + }, + "owners": [ + { + "name": "Yevhenii Kotyrlo", + "githubUsername": "YevheniiKotyrlo" + } + ] +} diff --git a/types/xcode/tsconfig.json b/types/xcode/tsconfig.json new file mode 100644 index 00000000000000..d2a5e712ee18a4 --- /dev/null +++ b/types/xcode/tsconfig.json @@ -0,0 +1,19 @@ +{ + "compilerOptions": { + "module": "node16", + "lib": [ + "es6" + ], + "noImplicitAny": true, + "noImplicitThis": true, + "strictNullChecks": true, + "strictFunctionTypes": true, + "types": [], + "noEmit": true, + "forceConsistentCasingInFileNames": true + }, + "files": [ + "index.d.ts", + "xcode-tests.ts" + ] +} diff --git a/types/xcode/xcode-tests.ts b/types/xcode/xcode-tests.ts new file mode 100644 index 00000000000000..69f0153c268d1f --- /dev/null +++ b/types/xcode/xcode-tests.ts @@ -0,0 +1,377 @@ +import xcode = require("xcode"); + +// $ExpectType XcodeProject +const project = xcode.project("/path/to/MyApp.xcodeproj/project.pbxproj"); + +// Parse +// $ExpectType XcodeProject +project.parseSync(); + +project.parse((err, results) => { + if (err) { + // Serialized from child process — not an Error instance + // $ExpectType string | undefined + const message = err.message; + // $ExpectType string | undefined + const name = err.name; + // $ExpectType string | undefined + const code = err.code; + // Index signature for other serialized properties (e.g., errno, syscall) + // $ExpectType unknown + const errno = err.errno; + } +}); + +// Write +// $ExpectType string +const output = project.writeSync(); + +const outputWithOptions = project.writeSync({ omitEmptyValues: true }); + +// Properties +// $ExpectType string +project.filepath; + +// $ExpectType string | undefined +project.productName; + +// Hash structure +// $ExpectType PbxprojHash +const hash = project.hash; + +// $ExpectType PbxprojObjects +const objects = hash.project.objects; + +// $ExpectType PbxprojSection +const buildFiles = objects.PBXBuildFile; + +// $ExpectType string +const rootObject = hash.project.rootObject; + +// UUID generation +// $ExpectType string[] +project.allUuids(); + +// $ExpectType string +project.generateUuid(); + +// File management +const sourceFile = project.addSourceFile("src/main.m"); +if (sourceFile !== false) { + // $ExpectType string + sourceFile.basename; + + // $ExpectType string + sourceFile.sourceTree; +} + +const headerFile = project.addHeaderFile("include/header.h", { target: "MyTarget" }, "Headers"); +if (headerFile !== null) { + // $ExpectType string + headerFile.basename; +} + +const framework = project.addFramework("UIKit.framework", { weak: true, link: true }); +if (framework !== false) { + // $ExpectType string + framework.basename; +} + +const resourceFile = project.addResourceFile("Assets.xcassets"); +if (resourceFile !== false) { + // $ExpectType string | undefined + resourceFile.uuid; +} + +const pluginFile = project.addPluginFile("MyPlugin.m"); +if (pluginFile !== null) { + // $ExpectType string | undefined + pluginFile.fileRef; +} + +const staticLib = project.addStaticLibrary("libMyLib.a"); +if (staticLib !== false) { + // $ExpectType string + staticLib.basename; +} + +const dataModel = project.addDataModelDocument("Model.xcdatamodeld", "Resources"); +if (dataModel !== null) { + // $ExpectType PBXFile[] | undefined + dataModel.models; + + // $ExpectType PBXFile | undefined + dataModel.currentModel; +} + +const hasIt = project.hasFile("src/main.m"); +if (hasIt !== false) { + // $ExpectType string + hasIt.basename; +} + +project.addFile("newfile.m", "Sources", { compilerFlags: "-fobjc-arc" }); +project.removeFile("old.m", "Sources"); +project.addCopyfile("resource.txt"); +project.removeCopyfile("resource.txt"); +project.addProductFile("MyApp.app"); +project.removeProductFile("MyApp.app"); +project.removeSourceFile("old.m"); +// $ExpectType PBXFile +project.removeHeaderFile("old.h"); +project.removeFramework("UIKit.framework"); +project.removeResourceFile("old.xcassets"); + +// Section manipulation +const file: xcode.PBXFile = { + basename: "test.m", + sourceTree: "\"\"", + includeInIndex: 0, +}; +project.addToPbxBuildFileSection(file); +project.removeFromPbxBuildFileSection(file); +project.addToPbxFileReferenceSection(file); + +// $ExpectType PBXFile +project.removeFromPbxFileReferenceSection(file); +project.addToXcVersionGroupSection(file); + +// Group management +const group = project.addPbxGroup(["file1.m", "file2.m"], "MyGroup", "src", "\"\""); +// $ExpectType string +group.uuid; +// $ExpectType PBXGroup +group.pbxGroup; + +project.removePbxGroup("MyGroup"); +project.addToPluginsPbxGroup(file); +project.removeFromPluginsPbxGroup(file); +project.addToResourcesPbxGroup(file); +project.removeFromResourcesPbxGroup(file); +project.addToFrameworksPbxGroup(file); +project.removeFromFrameworksPbxGroup(file); +project.addToProductsPbxGroup(file); +project.removeFromProductsPbxGroup(file); + +project.addToPbxGroupType(file, "ABC123", "PBXGroup"); +project.addToPbxGroupType("filename.m", "ABC123", "PBXGroup"); +project.addToPbxVariantGroup(file, "ABC123"); +project.addToPbxGroup(file, "ABC123"); +project.addToPbxGroup("filename.m", "ABC123"); + +// $ExpectType string +project.pbxCreateGroupWithType("NewGroup", "path/to", "PBXGroup"); +project.pbxCreateGroupWithType("NewGroup", undefined, "PBXVariantGroup"); + +// $ExpectType string +project.pbxCreateVariantGroup("Localizable.strings"); + +// $ExpectType string +project.pbxCreateGroup("Sources", "src"); + +project.removeFromPbxGroupAndType(file, "ABC123", "PBXGroup"); +project.removeFromPbxGroup(file, "ABC123"); +project.removeFromPbxVariantGroup(file, "ABC123"); + +const pbxGroup = project.getPBXGroupByKey("ABC123"); +if (pbxGroup !== undefined) { + // $ExpectType string + pbxGroup.isa; + // $ExpectType { value: string; comment?: string | undefined; }[] + pbxGroup.children; +} + +project.getPBXGroupByKeyAndType("ABC123", "PBXGroup"); +project.getPBXVariantGroupByKey("ABC123"); + +const groupKey = project.findPBXGroupKey({ name: "Sources" }); +project.findPBXGroupKeyAndType({ name: "Sources" }, "PBXGroup"); +project.findPBXVariantGroupKey({ name: "Localizable.strings" }); + +const locGroup = project.addLocalizationVariantGroup("Localizable.strings"); +// $ExpectType string +locGroup.uuid; +// $ExpectType string +locGroup.fileRef; +// $ExpectType string +locGroup.basename; + +// Build phases +project.addToPbxSourcesBuildPhase(file); +project.removeFromPbxSourcesBuildPhase(file); +project.addToPbxResourcesBuildPhase(file); +project.removeFromPbxResourcesBuildPhase(file); +project.addToPbxFrameworksBuildPhase(file); +project.removeFromPbxFrameworksBuildPhase(file); +project.addToPbxEmbedFrameworksBuildPhase(file); +project.removeFromPbxEmbedFrameworksBuildPhase(file); +project.addToPbxCopyfilesBuildPhase(file); +project.removeFromPbxCopyfilesBuildPhase(file); + +const buildPhase = project.addBuildPhase(["file.m"], "PBXSourcesBuildPhase", "Sources"); +// $ExpectType string +buildPhase.uuid; +// $ExpectType BuildPhaseObject +buildPhase.buildPhase; + +const buildPhaseWithTarget = project.addBuildPhase( + ["script.sh"], + "PBXShellScriptBuildPhase", + "Run Script", + "TARGET_UUID", + { shellPath: "/bin/sh", shellScript: "echo hello" }, +); + +// Build phase accessors +const sourcesBP = project.pbxSourcesBuildPhaseObj(); +if (sourcesBP != null) { + // $ExpectType string + sourcesBP.isa; + // $ExpectType { value: string; comment: string; }[] + sourcesBP.files; +} + +project.pbxResourcesBuildPhaseObj("TARGET_UUID"); +project.pbxFrameworksBuildPhaseObj(); +project.pbxEmbedFrameworksBuildPhaseObj(); +project.pbxCopyfilesBuildPhaseObj(); + +const bpKey = project.buildPhase("PBXSourcesBuildPhase"); +const bpObj = project.buildPhaseObject("PBXSourcesBuildPhase", "Sources"); + +// Target management +const target = project.addTarget("MyExtension", "app_extension", "Extensions", "com.example.ext"); +// $ExpectType string +target.uuid; +// $ExpectType PBXNativeTarget +target.pbxNativeTarget; + +project.addToPbxProjectSection(target); +project.addToPbxNativeTargetSection(target); + +const dep = project.addTargetDependency("TARGET1", ["TARGET2"]); +if (dep !== undefined) { + // $ExpectType string + dep.uuid; + // $ExpectType PBXNativeTarget + dep.target; +} + +const configList = project.addXCConfigurationList( + [{ isa: "XCBuildConfiguration", buildSettings: { PRODUCT_NAME: "MyApp" }, name: "Release" }], + "Release", + "Build configuration list", +); +// $ExpectType string +configList.uuid; +// $ExpectType XCConfigurationList +configList.xcConfigurationList; + +// Section accessors +const projectSection = project.pbxProjectSection(); +const projectEntry = projectSection["ABC123"]; +if (typeof projectEntry !== "string") { + // $ExpectType PBXProject + projectEntry; +} + +const buildFileSection = project.pbxBuildFileSection(); +const configSection = project.pbxXCBuildConfigurationSection(); +const configEntry = configSection["ABC123"]; +if (typeof configEntry !== "string") { + // $ExpectType XCBuildConfiguration + configEntry; +} + +const fileRefSection = project.pbxFileReferenceSection(); +const nativeTargetSection = project.pbxNativeTargetSection(); +const nativeTargetEntry = nativeTargetSection["ABC123"]; +if (typeof nativeTargetEntry !== "string") { + // $ExpectType PBXNativeTarget + nativeTargetEntry; +} + +const versionGroupSection = project.xcVersionGroupSection(); +const configListSection = project.pbxXCConfigurationList(); +const customSection = project.getPBXObject("PBXCustomSection"); + +// Section lookups +const foundGroup = project.pbxGroupByName("Sources"); +if (foundGroup !== null) { + // $ExpectType string + foundGroup.isa; +} +const foundTarget = project.pbxTargetByName("MyApp"); +if (foundTarget !== null) { + // $ExpectType string + foundTarget.name; +} +const targetKey = project.findTargetKey("MyApp"); +const item = project.pbxItemByComment("main.m", "PBXBuildFile"); + +// Build settings +project.addBuildProperty("SWIFT_VERSION", "5.0"); +project.addBuildProperty("SWIFT_VERSION", "5.0", "Release"); +project.addBuildProperty("HEADER_SEARCH_PATHS", ["$(inherited)", "src/include"]); +project.addBuildProperty("IPHONEOS_DEPLOYMENT_TARGET", 15); +project.removeBuildProperty("SWIFT_VERSION"); +project.removeBuildProperty("SWIFT_VERSION", "Release"); +project.updateBuildProperty("PRODUCT_NAME", "MyApp"); +project.updateBuildProperty("PRODUCT_NAME", "MyApp", "Release"); +project.updateBuildProperty("PRODUCT_NAME", "MyApp", "Release", "MyTarget"); +project.updateBuildProperty("HEADER_SEARCH_PATHS", ["$(inherited)", "src/include"]); +project.updateBuildProperty("IPHONEOS_DEPLOYMENT_TARGET", 15); +project.updateProductName("NewAppName"); + +const buildProp = project.getBuildProperty("PRODUCT_NAME"); +const buildPropForConfig = project.getBuildProperty("PRODUCT_NAME", "Release"); +const buildPropForTarget = project.getBuildProperty("PRODUCT_NAME", "Release", "MyTarget"); + +const configByName = project.getBuildConfigByName("Release"); + +project.addToFrameworkSearchPaths(file); +project.removeFromFrameworkSearchPaths(file); +project.addToLibrarySearchPaths(file); +project.addToLibrarySearchPaths("/usr/local/lib"); +project.removeFromLibrarySearchPaths(file); +project.addToHeaderSearchPaths(file); +project.addToHeaderSearchPaths("$(SRCROOT)/include"); +project.removeFromHeaderSearchPaths(file); +project.addToOtherLinkerFlags("-lz"); +project.removeFromOtherLinkerFlags("-lz"); +project.addToBuildSettings("CUSTOM_SETTING", "value"); +project.addToBuildSettings("CUSTOM_SETTING", 42); +project.removeFromBuildSettings("CUSTOM_SETTING"); + +// Project queries +const firstProject = project.getFirstProject(); +// $ExpectType string +firstProject.uuid; +// $ExpectType PBXProject +firstProject.firstProject; + +const firstTarget = project.getFirstTarget(); +// $ExpectType string +firstTarget.uuid; +// $ExpectType PBXNativeTarget +firstTarget.firstTarget; + +const appTarget = project.getTarget("com.apple.product-type.application"); +if (appTarget !== null) { + // $ExpectType string + appTarget.uuid; + // $ExpectType PBXNativeTarget + appTarget.target; +} + +// Known regions +project.addKnownRegion("fr"); +project.removeKnownRegion("fr"); +// $ExpectType boolean +project.hasKnownRegion("en"); + +// Target attributes +project.addTargetAttribute("SystemCapabilities", { "com.apple.Push": { enabled: 1 } }); +project.addTargetAttribute("DevelopmentTeam", "ABC123", project.getFirstTarget()); +project.removeTargetAttribute("SystemCapabilities"); +project.removeTargetAttribute("SystemCapabilities", project.getFirstTarget());