Skip to content

Commit

Permalink
chore: Improve type declarations (#198)
Browse files Browse the repository at this point in the history
  • Loading branch information
mykola-mokhnach authored Sep 1, 2023
1 parent a74ad1a commit 314df12
Show file tree
Hide file tree
Showing 13 changed files with 65 additions and 66 deletions.
14 changes: 2 additions & 12 deletions .github/workflows/unit-test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -9,17 +9,9 @@ jobs:
outputs:
versions: ${{ steps.generate-matrix.outputs.versions }}
steps:
- name: Generate Node.js versions matrix
- name: Select 3 most recent LTS versions of Node.js
id: generate-matrix
run: |
sudo apt-get install -y lynx
lynx -dump https://endoflife.date/nodejs | grep -E -o '[0-9]+[( a-zA-Z]+LTS\)' | grep -E -o '([0-9]+)' > eol.list
cat eol.list
lts1=$(cat eol.list | head -1)
lts2=$(cat eol.list | head -2 | tail -1)
lts3=$(cat eol.list | head -3 | tail -1)
VERSIONS="[$lts1, $lts2, $lts3]"
echo "versions=${VERSIONS}" >> "$GITHUB_OUTPUT"
run: echo "versions=$(curl -s https://endoflife.date/api/nodejs.json | jq -c '[[.[] | select(.lts != false)][:3] | .[].cycle | tonumber]')" >> "$GITHUB_OUTPUT"

test:
needs:
Expand All @@ -33,8 +25,6 @@ jobs:
- uses: actions/setup-node@v3
with:
node-version: ${{ matrix.node-version }}
- run: npm i -g npm
name: Update NPM
- run: npm install --no-package-lock
name: Install dev dependencies
- run: npm run lint
Expand Down
18 changes: 9 additions & 9 deletions lib/helpers.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import semver from 'semver';

const DEFAULT_EXEC_TIMEOUT = 10 * 60 * 1000; // ms
const SIM_RUNTIME_NAME = 'com.apple.CoreSimulator.SimRuntime.';
export const DEFAULT_EXEC_TIMEOUT = 10 * 60 * 1000; // ms
export const SIM_RUNTIME_NAME = 'com.apple.CoreSimulator.SimRuntime.';

/**
* "Normalize" the version, since iOS uses 'major.minor' but the runtimes can
Expand All @@ -11,17 +11,17 @@ const SIM_RUNTIME_NAME = 'com.apple.CoreSimulator.SimRuntime.';
* @return {string} The version in 'major.minor' form
* @throws {Error} If the version not parseable by the `semver` package
*/
function normalizeVersion (version) {
export function normalizeVersion (version) {
const semverVersion = semver.coerce(version);
if (!semverVersion) {
throw new Error(`Unable to parse version '${version}'`);
}
return `${semverVersion.major}.${semverVersion.minor}`;
}

export {
DEFAULT_EXEC_TIMEOUT, SIM_RUNTIME_NAME,
normalizeVersion,
};

export const getXcrunBinary = () => process.env.XCRUN_BINARY || 'xcrun';
/**
* @returns {string}
*/
export function getXcrunBinary () {
return process.env.XCRUN_BINARY || 'xcrun';
}
49 changes: 29 additions & 20 deletions lib/simctl.js
Original file line number Diff line number Diff line change
Expand Up @@ -16,45 +16,50 @@ const DEFAULT_OPTS = {
logErrors: true,
};

/**
* @typedef {Object} XCRun
* @property {string?} path Full path to the xcrun script
*/

/**
* @typedef {Object} ExecOpts
* @property {string[]} args [[]] - The list of additional subcommand arguments.
* @property {string[]} [args=[]] - The list of additional subcommand arguments.
* It's empty by default.
* @property {Object} env [{}] - Environment variables mapping. All these variables
* @property {Record<string, any>} [env={}] - Environment variables mapping. All these variables
* will be passed Simulator and used in the executing function.
* @property {boolean} logErrors [true] - Set it to _false_ to throw execution errors
* @property {boolean} [logErrors=true] - Set it to _false_ to throw execution errors
* immediately without logging any additional information.
* @property {boolean} asynchronous [false] - Whether to execute the given command
* @property {boolean} [asynchronous=false] - Whether to execute the given command
* 'synchronously' or 'asynchronously'. Affects the returned result of the function.
* @property {string?} encoding - Explicitly sets streams encoding for the executed
* @property {string} [encoding] - Explicitly sets streams encoding for the executed
* command input and outputs.
* @property {string|string[]} architectures - One or more architecture names to be enforced while
* @property {string|string[]} [architectures] - One or more architecture names to be enforced while
* executing xcrun. See https://github.com/appium/appium/issues/18966 for more details.
*/


/**
* @typedef {Object} SimctlOpts
* @property {Object?} xcrun - The xcrun properties. Currently only one property
* @property {XCRun} [xcrun] - The xcrun properties. Currently only one property
* is supported, which is `path` and it by default contains `null`, which enforces
* the instance to automatically detect the full path to `xcrun` tool and to throw
* an exception if it cannot be detected. If the path is set upon instance creation
* then it is going to be used by `exec` and no autodetection will happen.
* @property {number} execTimeout [600000] - The maximum number of milliseconds
* @property {number} [execTimeout=600000] - The maximum number of milliseconds
* to wait for single synchronous xcrun command.
* @property {boolean} logErrors [true] - Whether to wire xcrun error messages
* @property {boolean} [logErrors=true] - Whether to wire xcrun error messages
* into debug log before throwing them.
* @property {string?} udid - The unique identifier of the current device, which is
* @property {string?} [udid] - The unique identifier of the current device, which is
* going to be implicitly passed to all methods, which require it. It can either be set
* upon instance creation if it is already known in advance or later when/if needed via the
* corresponding instance setter.
* @property {string?} devicesSetPath - Full path to the set of devices that you want to manage.
* @property {string?} [devicesSetPath] - Full path to the set of devices that you want to manage.
* By default this path usually equals to ~/Library/Developer/CoreSimulator/Devices
*/


class Simctl {
/** @type {any?} */
/** @type {XCRun} */
xcrun;

/** @type {number} */
Expand All @@ -64,15 +69,17 @@ class Simctl {
logErrors;

/**
* @param {Partial<SimctlOpts>} opts
* @param {SimctlOpts} [opts={}]
*/
constructor (opts = {}) {
opts = _.cloneDeep(opts);
_.defaultsDeep(opts, DEFAULT_OPTS);
for (const key of _.keys(DEFAULT_OPTS)) {
this[key] = opts[key];
}
/** @type {string?} */
this._udid = _.isNil(opts.udid) ? null : opts.udid;
/** @type {string?} */
this._devicesSetPath = _.isNil(opts.devicesSetPath) ? null : opts.devicesSetPath;
}

Expand Down Expand Up @@ -118,10 +125,10 @@ class Simctl {
* Execute the particular simctl command.
*
* @param {string} subcommand - One of available simctl subcommands.
* Execute `xcrun simctl` in Terminal to see the full list
* of available subcommands.
* @param {Partial<ExecOpts>} opts
* @return {Promise<import('teen_process').TeenProcessExecResult|import('teen_process').SubProcess>} Either the result of teen process's `exec` or
* Execute `xcrun simctl` in Terminal to see the full list of available subcommands.
* @param {ExecOpts} [opts={}]
* @return {Promise<import('teen_process').TeenProcessExecResult|import('teen_process').SubProcess>}
* Either the result of teen process's `exec` or
* `SubProcess` instance depending of `opts.asynchronous` value.
* @throws {Error} If the simctl subcommand command returns non-zero return code.
*/
Expand All @@ -135,7 +142,8 @@ class Simctl {
architectures,
} = opts;
// run a particular simctl command
args = ['simctl',
args = [
'simctl',
...(this.devicesSetPath ? ['--set', this.devicesSetPath] : []),
subcommand,
...args
Expand All @@ -145,7 +153,8 @@ class Simctl {
env = _.defaults(
_.mapKeys(env,
(value, key) => _.startsWith(key, SIMCTL_ENV_PREFIX) ? key : `${SIMCTL_ENV_PREFIX}${key}`),
process.env);
process.env
);

const execOpts = {
env,
Expand All @@ -157,7 +166,7 @@ class Simctl {
const xcrun = await this.requireXcrun();
try {
let execArgs = [xcrun, args, execOpts];
if (!_.isEmpty(architectures)) {
if (architectures?.length) {
const archArgs = _.flatMap(
(_.isArray(architectures) ? architectures : [architectures]).map((arch) => ['-arch', arch])
);
Expand Down
14 changes: 7 additions & 7 deletions lib/subcommands/bootstatus.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,13 +6,13 @@ const commands = {};

/**
* @typedef {Object} BootMonitorOptions
* @property {number} timeout [240000] - Simulator booting timeout in ms.
* @property {Function?} onWaitingDataMigration - This event is fired when data migration stage starts.
* @property {Function?} onWaitingSystemApp - This event is fired when system app wait stage starts.
* @property {Function?} onFinished - This event is fired when Simulator is fully booted.
* @property {Function?} onError - This event is fired when there was an error while monitoring the booting process
* @property {number} [timeout=240000] - Simulator booting timeout in ms.
* @property {Function} [onWaitingDataMigration] - This event is fired when data migration stage starts.
* @property {Function} [onWaitingSystemApp] - This event is fired when system app wait stage starts.
* @property {Function} [onFinished] - This event is fired when Simulator is fully booted.
* @property {Function} [onError] - This event is fired when there was an error while monitoring the booting process
* or when the timeout has expired.
* @property {boolean} shouldPreboot [false] Whether to preboot the Simulator
* @property {boolean} [shouldPreboot=false] Whether to preboot the Simulator
* if this command is called and it is not already in booted or booting state.
*/

Expand All @@ -22,7 +22,7 @@ const commands = {};
* until Simulator booting is completed.
* The method is only available since Xcode8.
*
* @param {Partial<BootMonitorOptions>} opts - Monitoring options.
* @param {BootMonitorOptions} [opts={}] - Monitoring options.
* @returns {Promise<import('teen_process').SubProcess>} The instance of the corresponding monitoring process.
* @throws {Error} If the Simulator fails to finish booting within the given timeout and onFinished
* property is not set.
Expand Down
6 changes: 3 additions & 3 deletions lib/subcommands/create.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,8 @@ const commands = {};

/**
* @typedef {Object} SimCreationOpts
* @property {string} platform [iOS] - Platform name in order to specify runtime such as 'iOS', 'tvOS', 'watchOS'
* @property {number} timeout [10000] - The maximum number of milliseconds to wait
* @property {string} [platform='iOS'] - Platform name in order to specify runtime such as 'iOS', 'tvOS', 'watchOS'
* @property {number} [timeout=10000] - The maximum number of milliseconds to wait
* unit device creation is completed.
*/

Expand All @@ -23,7 +23,7 @@ const commands = {};
* @param {string} name - The device name to be created.
* @param {string} deviceTypeId - Device type, for example 'iPhone 6'.
* @param {string} platformVersion - Platform version, for example '10.3'.
* @param {Partial<SimCreationOpts>} opts - Simulator options for creating devices.
* @param {SimCreationOpts} [opts={}] - Simulator options for creating devices.
* @return {Promise<string>} The UDID of the newly created device.
* @throws {Error} If the corresponding simctl subcommand command
* returns non-zero return code.
Expand Down
2 changes: 1 addition & 1 deletion lib/subcommands/erase.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ const commands = {};
* Reset the content and settings of the particular Simulator.
* It is required that Simulator is in _shutdown_ state.
*
* @param {number} timeout [10000] - The maximum number of milliseconds to wait
* @param {number} [timeout=10000] - The maximum number of milliseconds to wait
* unit device reset is completed.
* @throws {Error} If the corresponding simctl subcommand command
* returns non-zero return code.
Expand Down
2 changes: 1 addition & 1 deletion lib/subcommands/get_app_container.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ const commands = {};
* It is required that Simulator is in _booted_ state.
*
* @param {string} bundleId - Bundle identifier of an application.
* @param {string?} containerType - Which container type to return. Possible values
* @param {string?} [containerType=null] - Which container type to return. Possible values
* are 'app', 'data', 'groups', '<A specific App Group container>'.
* The default value is 'app'.
* @return {Promise<string>} Full path to the given application container on the local
Expand Down
6 changes: 3 additions & 3 deletions lib/subcommands/keychain.js
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ async function handleRawPayload (payload, onPayloadStored) {

/**
* @typedef {Object} CertOptions
* @property {boolean} raw [false] - whether the `cert` argument
* @property {boolean} [raw=false] - whether the `cert` argument
* is the path to the certificate on the local file system or
* a raw certificate content
*/
Expand All @@ -36,7 +36,7 @@ async function handleRawPayload (payload, onPayloadStored) {
* @param {string} cert the full path to a valid .cert file containing
* the certificate content or the certificate content itself, depending on
* options
* @param {Partial<CertOptions>} opts
* @param {CertOptions} [opts={}]
* @throws {Error} if the current SDK version does not support the command
* or there was an error while adding the certificate
* @throws {Error} If the `udid` instance property is unset
Expand All @@ -62,7 +62,7 @@ commands.addRootCertificate = async function addRootCertificate (cert, opts = {}
* @param {string} cert the full path to a valid .cert file containing
* the certificate content or the certificate content itself, depending on
* options
* @param {Partial<CertOptions>} opts
* @param {CertOptions} [opts={}]
* @throws {Error} if the current SDK version does not support the command
* or there was an error while adding the certificate
* @throws {Error} If the `udid` instance property is unset
Expand Down
2 changes: 1 addition & 1 deletion lib/subcommands/launch.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ const commands = {};
*
* @param {string} bundleId - Bundle identifier of the application,
* which is going to be removed.
* @param {number} tries [5] - The maximum number of retries before
* @param {number} [tries=5] - The maximum number of retries before
* throwing an exception.
* @return {Promise<string>} the actual command output
* @throws {Error} If the corresponding simctl subcommand command
Expand Down
10 changes: 5 additions & 5 deletions lib/subcommands/list.js
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ const commands = {};
* Parse the list of existing Simulator devices to represent
* it as convenient mapping.
*
* @param {string?} platform - The platform name, for example 'watchOS'.
* @param {string?} [platform] - The platform name, for example 'watchOS'.
* @return {Promise<Record<string, any>>} The resulting mapping. Each key is platform version,
* for example '10.3' and the corresponding value is an
* array of the matching {@link DeviceInfo} instances.
Expand Down Expand Up @@ -90,10 +90,10 @@ commands.getDevicesByParsing = async function getDevicesByParsing (platform) {
* Parse the list of existing Simulator devices to represent
* it as convenient mapping for the particular platform version.
*
* @param {string?} forSdk - The sdk version,
* @param {string?} [forSdk] - The sdk version,
* for which the devices list should be parsed,
* for example '10.3'.
* @param {string?} platform - The platform name, for example 'watchOS'.
* @param {string?} [platform] - The platform name, for example 'watchOS'.
* @return {Promise<Object|DeviceInfo[]>} If _forSdk_ is set then the list
* of devices for the particular platform version.
* Otherwise the same result as for {@link getDevicesByParsing}
Expand Down Expand Up @@ -176,7 +176,7 @@ commands.getDevices = async function getDevices (forSdk, platform) {
*
* @param {string} platformVersion - The platform version name,
* for example '10.3'.
* @param {string} platform - The platform name, for example 'watchOS'.
* @param {string} [platform='iOS'] - The platform name, for example 'watchOS'.
* @return {Promise<string>} The corresponding runtime name for the given
* platform version.
*/
Expand All @@ -199,7 +199,7 @@ commands.getRuntimeForPlatformVersionViaJson = async function getRuntimeForPlatf
*
* @param {string} platformVersion - The platform version name,
* for example '10.3'.
* @param {string} platform - The platform name, for example 'watchOS'.
* @param {string} [platform='iOS'] - The platform name, for example 'watchOS'.
* @return {Promise<string>} The corresponding runtime name for the given
* platform version.
*/
Expand Down
2 changes: 1 addition & 1 deletion lib/subcommands/pbcopy.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ const commands = {};
*
* @since Xcode SDK 8.1
* @param {string} content - The actual string content to be set.
* @param {string} encoding [utf8] - The encoding of the given pasteboard content.
* @param {string} [encoding='utf8'] - The encoding of the given pasteboard content.
* UTF-8 by default.
* @throws {Error} If the corresponding simctl subcommand command
* returns non-zero return code.
Expand Down
2 changes: 1 addition & 1 deletion lib/subcommands/pbpaste.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ const commands = {};
* It is required that Simulator is in _booted_ state.
*
* @since Xcode 8.1 SDK
* @param {string} encoding ['utf-8'] - The encoding of the returned pasteboard content.
* @param {string} [encoding='utf8'] - The encoding of the returned pasteboard content.
* UTF-8 by default.
* @return {Promise<string>} Current content of Simulator pasteboard or an empty string.
* @throws {Error} If the corresponding simctl subcommand command
Expand Down
4 changes: 2 additions & 2 deletions lib/subcommands/spawn.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ const commands = {};
* It is required that Simulator is in _booted_ state.
*
* @param {string|string[]} args - Spawn arguments
* @param {object} env [{}] - Additional environment variables mapping.
* @param {object} [env={}] - Additional environment variables mapping.
* @return {Promise<import('teen_process').TeenProcessExecResult>} Command execution result.
* @throws {Error} If the corresponding simctl subcommand command
* returns non-zero return code.
Expand All @@ -30,7 +30,7 @@ commands.spawnProcess = async function spawnProcess (args, env = {}) {
* on Simulator.
*
* @param {string|string[]} args - Spawn arguments
* @param {object} env [{}] - Additional environment variables mapping.
* @param {object} [env={}] - Additional environment variables mapping.
* @return {Promise<import('teen_process').SubProcess>} The instance of the process to be spawned.
* @throws {Error} If the `udid` instance property is unset
*/
Expand Down

0 comments on commit 314df12

Please sign in to comment.