ns-bitrig: run the NativeScript CLI against Bitrig's iOS simulators

ns-bitrig: NativeScript on Bitrig's simulators

Bitrig hosts its iOS simulators in its own device set (~/Library/Bitrig/Simulators); the NativeScript CLI only looks at Apple's default set, so ns run ios does not see them. ns-bitrig.sh runs the unmodified CLI with three process-local shims:

  • xcrun simctl … becomes xcrun simctl --set ~/Library/Bitrig/Simulators …;
  • open Simulator.app is skipped while Bitrig shows a booted device;
  • the CLI's installed-app lookup, which reads Apple's default simulator folder directly, asks simctl listapps in Bitrig's set instead.

Nothing in the CLI, the project or Bitrig is changed.

curl -fsSL https://gist.githubusercontent.com/nativescript-oss/9f265e6457048cd808e39ac87c035ae8/raw/ns-bitrig.sh -o ns-bitrig && chmod +x ns-bitrig
./ns-bitrig run ios        # boot one simulator in Bitrig first
./ns-bitrig debug ios --device 
./ns-bitrig devices ios    # lists the Bitrig simulators

Any ns command and flag passes through. BITRIG_SIM_SET overrides the device-set path. Tested with NativeScript CLI 9.1.2 on a fresh ns create app and an iPhone Duo simulator in Bitrig.

#!/bin/sh
# Runs the NativeScript CLI against the simulators Bitrig hosts.
#
# ns-bitrig.sh run ios # the one booted Bitrig simulator
# ns-bitrig.sh debug ios --device
# ns-bitrig.sh devices ios # what the CLI sees
#
# Bitrig keeps its simulators in their own device set
# (~/Library/Bitrig/Simulators), and the CLI only looks at Apple's default
# one. Three process-local shims fix that without touching the CLI or the
# project: `xcrun simctl` gets `--set`, `open Simulator.app` is skipped while
# Bitrig shows a booted device, and the CLI's installed-app lookup (which
# reads Apple's default folder directly) asks `simctl listapps` instead.
set -e
SET="${BITRIG_SIM_SET:-$HOME/Library/Bitrig/Simulators}"
[ -d "$SET" ] || { echo "ns-bitrig: no Bitrig simulators at $SET (set BITRIG_SIM_SET)" >&2; exit 1; }
NS=$(command -v ns) || { echo "ns-bitrig: the NativeScript CLI (ns) is not on PATH" >&2; exit 1; }
NS=$(node -e 'console.log(require("fs").realpathSync(process.argv[1]))' "$NS")
SHIM=$(mktemp -d "${TMPDIR:-/tmp}/ns-bitrig.XXXXXX")
cat > "$SHIM/xcrun" <<SH
#!/bin/sh
if [ "\$1" = "simctl" ]; then shift; exec /usr/bin/xcrun simctl --set "$SET" "\$@"; fi
exec /usr/bin/xcrun "\$@"
SH
cat > "$SHIM/open" <<SH
#!/bin/sh
case "\$*" in
*Simulator.app) /usr/bin/xcrun simctl --set "$SET" list devices booted | /usr/bin/grep -q '(Booted)' && exit 0 ;;
esac
exec /usr/bin/open "\$@"
SH
cat > "$SHIM/installed-apps.cjs" <<JS
const { createRequire } = require('node:module');
const { execFileSync } = require('node:child_process');
const { dirname, basename } = require('node:path');
try {
const common = createRequire('$NS')('ios-sim-portable/lib/iphone-simulator-common');
common.getInstalledApplications = (deviceId) => {
const plist = execFileSync('/usr/bin/xcrun', ['simctl', '--set', '$SET', 'listapps', deviceId]);
const apps = JSON.parse(execFileSync('/usr/bin/plutil', ['-convert', 'json', '-o', '-', '-'], { input: plist, encoding: 'utf8' }));
return Object.entries(apps).filter(([, app]) => app.Path).map(([id, app]) => ({ guid: basename(dirname(app.Path)), appIdentifier: id, path: app.Path }));
};
} catch (e) {
console.warn('ns-bitrig: could not patch the installed-app lookup (' + e.message + '); installs may be reported as missing');
}
JS
chmod +x "$SHIM/xcrun" "$SHIM/open"
# With no --device, use the one booted Bitrig simulator.
case " $* " in
*" --device "*|*" devices "*) ;;
*" ios"*)
booted=$(/usr/bin/xcrun simctl --set "$SET" list devices booted | sed -n 's/.*(\([0-9A-F-]\{36\}\)) (Booted).*/\1/p')
count=$(printf '%s' "$booted" | grep -c . || true)
[ "$count" = "1" ] || { echo "ns-bitrig: boot one simulator in Bitrig, or pass --device (booted: ${count:-0})" >&2; exit 1; }
set -- "$@" --device "$booted" ;;
esac
PATH="$SHIM:$PATH" exec node --require "$SHIM/installed-apps.cjs" "$NS" "$@"
添加评论
点赞收藏
点踩分享查看原文
评论
?
参与讨论