Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 14 additions & 0 deletions .editorconfig
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
# editorconfig.org
root = true

[*]
indent_style = space
indent_size = 2
end_of_line = lf
charset = utf-8
trim_trailing_whitespace = true
insert_final_newline = true
max_line_length = 120

[*.md]
trim_trailing_whitespace = false
2 changes: 1 addition & 1 deletion .github/workflows/unit-test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,6 @@ jobs:
- name: Run linter
run: npm run lint
- run: npm run format:check
name: Run Prettier check
name: Run format check
- name: Run unit tests
run: npm run test
37 changes: 0 additions & 37 deletions .releaserc

This file was deleted.

5 changes: 0 additions & 5 deletions eslint.config.mjs

This file was deleted.

10 changes: 4 additions & 6 deletions lib/helpers.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
import path from 'node:path';

import {fs, plist} from '@appium/support';
import {exec} from 'teen_process';
import type {TeenProcessExecResult} from 'teen_process';
import {fs, plist} from '@appium/support';
import path from 'node:path';

export const XCRUN_TIMEOUT = 15000;

Expand All @@ -22,10 +23,7 @@ export async function runXcrunCommand(
} catch (err) {
if (err instanceof Error) {
// the true error can be hidden within the stderr
const stderr =
err && typeof err === 'object' && 'stderr' in err
? String((err as {stderr: unknown}).stderr)
: '';
const stderr = err && typeof err === 'object' && 'stderr' in err ? String((err as {stderr: unknown}).stderr) : '';
if (stderr) {
err.message = `${err.message}: ${stderr}`;
}
Expand Down
33 changes: 12 additions & 21 deletions lib/xcode.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
import {fs, logger, util} from '@appium/support';
import path from 'node:path';

import {fs, logger, util} from '@appium/support';
import {retry} from 'asyncbox';
import {exec} from 'teen_process';
import * as semver from 'semver';
import {exec} from 'teen_process';

import {runXcrunCommand, findAppPaths, XCRUN_TIMEOUT, readXcodePlist} from './helpers.js';
import type {XcodeVersion} from './types.js';

Expand All @@ -25,9 +27,7 @@ export async function getPathFromXcodeSelect(timeout: number = XCRUN_TIMEOUT): P
return `${prefix}. Consider installing Xcode to address this issue.`;
}

const proposals = xcodePaths.map(
(p) => ` sudo xcode-select -s "${path.join(p, 'Contents', 'Developer')}"`,
);
const proposals = xcodePaths.map((p) => ` sudo xcode-select -s "${path.join(p, 'Contents', 'Developer')}"`);
return (
`${prefix}. ` +
`Consider running${proposals.length > 1 ? ' any of' : ''}:\n${proposals.join('\n')}\nto address this issue.`
Expand All @@ -38,8 +38,7 @@ export async function getPathFromXcodeSelect(timeout: number = XCRUN_TIMEOUT): P
try {
({stdout} = await exec('xcode-select', ['--print-path'], {timeout}));
} catch (e) {
const stderr =
e && typeof e === 'object' && 'stderr' in e ? String((e as {stderr: unknown}).stderr) : '';
const stderr = e && typeof e === 'object' && 'stderr' in e ? String((e as {stderr: unknown}).stderr) : '';
const message = e instanceof Error ? e.message : String(e);
const msg =
`Cannot determine the path to Xcode by running 'xcode-select -p' command. ` +
Expand Down Expand Up @@ -93,8 +92,9 @@ export async function getPathFromDeveloperDir(): Promise<string> {
* @returns Full path to Xcode Developer subfolder timeout
* @throws {Error} If there was an error while retrieving the path.
*/
export const getPath = util.memoize((timeout: number = XCRUN_TIMEOUT): Promise<string> =>
process.env.DEVELOPER_DIR ? getPathFromDeveloperDir() : getPathFromXcodeSelect(timeout),
export const getPath = util.memoize(
(timeout: number = XCRUN_TIMEOUT): Promise<string> =>
process.env.DEVELOPER_DIR ? getPathFromDeveloperDir() : getPathFromXcodeSelect(timeout),
);

/**
Expand All @@ -107,11 +107,7 @@ export const getPath = util.memoize((timeout: number = XCRUN_TIMEOUT): Promise<s
* @throws {Error} If there was a failure while retrieving the version
*/
export async function getVersion(parse: false, retries?: number, timeout?: number): Promise<string>;
export async function getVersion(
parse: true,
retries?: number,
timeout?: number,
): Promise<XcodeVersion>;
export async function getVersion(parse: true, retries?: number, timeout?: number): Promise<XcodeVersion>;
export async function getVersion(
parse: boolean = false,
retries: number = DEFAULT_NUMBER_OF_RETRIES,
Expand Down Expand Up @@ -149,10 +145,7 @@ export async function getClangVersion(): Promise<string | null> {
try {
await fs.which('clang');
} catch {
log.info(
'Cannot find clang executable on the local system. ' +
'Are Xcode Command Line Tools installed?',
);
log.info('Cannot find clang executable on the local system. Are Xcode Command Line Tools installed?');
return null;
}
const {stdout} = await exec('clang', ['--version']);
Expand Down Expand Up @@ -238,9 +231,7 @@ export const getMaxTVOSSDK = util.memoize(async function getMaxTVOSSDK(
* @returns Xcode version
* @throws {Error} If there was a failure while retrieving the version
*/
async function getVersionWithoutRetry(
timeout: number = XCRUN_TIMEOUT,
): Promise<semver.SemVer | null> {
async function getVersionWithoutRetry(timeout: number = XCRUN_TIMEOUT): Promise<semver.SemVer | null> {
const developerPath = await getPath(timeout);
// we want to read the CFBundleShortVersionString from Xcode's plist.
const {CFBundleShortVersionString} = await readXcodePlist(developerPath);
Expand Down
6 changes: 6 additions & 0 deletions oxfmt.config.mjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
import appiumConfig, {defineConfig, ignorePatterns} from '@appium/oxc-config/oxfmt';

export default defineConfig({
...appiumConfig,
ignorePatterns: [...ignorePatterns],
});
6 changes: 6 additions & 0 deletions oxlint.config.mjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
import appiumConfig, {defineConfig, ignorePatterns} from '@appium/oxc-config/oxlint';

export default defineConfig({
extends: [appiumConfig],
ignorePatterns: [...ignorePatterns],
});
70 changes: 30 additions & 40 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,75 +1,65 @@
{
"name": "appium-xcode",
"version": "7.0.0",
"description": "Interact with Xcode",
"keywords": [
"appium",
"ios",
"xcode"
],
"version": "7.0.0",
"author": "Appium Contributors",
"bugs": {
"url": "https://github.com/appium/appium-xcode/issues"
},
"license": "Apache-2.0",
"author": "Appium Contributors",
"repository": {
"type": "git",
"url": "https://github.com/appium/appium-xcode.git"
},
"bugs": {
"url": "https://github.com/appium/appium-xcode/issues"
},
"engines": {
"node": "^20.19.0 || ^22.12.0 || >=24.0.0",
"npm": ">=10"
},
"main": "./build/lib/index.js",
"types": "./build/lib/index.d.ts",
"files": [
"lib",
"build/lib",
"CHANGELOG.md"
],
"dependencies": {
"@appium/support": "^7.2.2",
"asyncbox": "^6.0.1",
"semver": "^7.0.0",
"teen_process": "^4.0.4"
"type": "module",
"main": "./build/lib/index.js",
"types": "./build/lib/index.d.ts",
"exports": {
".": {
"types": "./build/lib/index.d.ts",
"import": "./build/lib/index.js"
},
"./package.json": "./package.json"
},
"scripts": {
"build": "tsc -b",
"clean": "npm run build -- --clean",
"rebuild": "npm run clean; npm run build",
"dev": "npm run build -- --watch",
"lint": "eslint .",
"lint:fix": "npm run lint -- --fix",
"format": "prettier -w ./lib ./test",
"format:check": "prettier --check ./lib ./test",
"lint": "oxlint -c oxlint.config.mjs .",
"lint:fix": "oxlint -c oxlint.config.mjs --fix .",
"format": "oxfmt -c oxfmt.config.mjs .",
"format:check": "oxfmt -c oxfmt.config.mjs --check .",
"prepare": "npm run build",
"test": "node --enable-source-maps --test --test-timeout=60000 \"./build/test/unit/**/*.spec.js\"",
"e2e-test": "node --enable-source-maps --test --test-force-exit --test-concurrency=1 --test-timeout=300000 \"./build/test/e2e/**/*.spec.js\""
},
"prettier": {
"bracketSpacing": false,
"printWidth": 100,
"singleQuote": true
"dependencies": {
"@appium/support": "^7.2.2",
"asyncbox": "^6.0.1",
"semver": "^7.0.0",
"teen_process": "^4.0.4"
},
"devDependencies": {
"@appium/eslint-config-appium-ts": "^3.0.0",
"@appium/tsconfig": "^1.0.0-rc.1",
"@appium/oxc-config": "^1.1.0",
"@appium/semantic-release-config": "^1.1.0",
"@appium/tsconfig": "^1.2.0",
"@appium/types": "^1.0.0-rc.1",
"@semantic-release/changelog": "^6.0.1",
"@semantic-release/git": "^10.0.1",
"@types/node": "^26.0.0",
"@types/semver": "^7.7.1",
"conventional-changelog-conventionalcommits": "^9.3.1",
"prettier": "^3.9.3",
"semantic-release": "^25.0.2",
"typescript": "^6.0.2"
"@types/semver": "^7.7.1"
},
"type": "module",
"exports": {
".": {
"types": "./build/lib/index.d.ts",
"import": "./build/lib/index.js"
},
"./package.json": "./package.json"
"engines": {
"node": "^20.19.0 || ^22.12.0 || >=24.0.0",
"npm": ">=10"
}
}
3 changes: 3 additions & 0 deletions release.config.mjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
import releaseConfig from '@appium/semantic-release-config';

export default releaseConfig();
6 changes: 4 additions & 2 deletions test/e2e/xcode.spec.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
import {fs, util} from '@appium/support';
import assert from 'node:assert/strict';
import * as xcode from '../../lib/xcode.js';
import {describe, it} from 'node:test';

import {fs, util} from '@appium/support';

import * as xcode from '../../lib/xcode.js';

// on slow machines and busy CI systems these can be slow and flakey
describe('xcode', {timeout: 30000}, function () {
describe('getPath', function () {
Expand Down
3 changes: 2 additions & 1 deletion test/unit/index.spec.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
import assert from 'node:assert/strict';
import xcode from '../../lib/index.js';
import {describe, it} from 'node:test';

import xcode from '../../lib/index.js';

describe('index', function () {
it('exported objects should exist', function () {
assert.ok(xcode);
Expand Down
5 changes: 1 addition & 4 deletions tsconfig.json
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,5 @@
"module": "NodeNext",
"moduleResolution": "NodeNext"
},
"include": [
"lib",
"test"
]
"include": ["lib", "test"]
}