├── .gitignore ├── .prettierrc ├── Package.swift ├── Readme.md ├── Sources └── simulator-set-location │ └── main.swift ├── cli.js ├── index.js ├── license └── package.json /.gitignore: -------------------------------------------------------------------------------- 1 | # Logs 2 | logs 3 | *.log 4 | npm-debug.log* 5 | yarn-debug.log* 6 | yarn-error.log* 7 | 8 | .build 9 | simulator-set-location 10 | 11 | # Runtime data 12 | pids 13 | *.pid 14 | *.seed 15 | *.pid.lock 16 | 17 | # Directory for instrumented libs generated by jscoverage/JSCover 18 | lib-cov 19 | 20 | # Coverage directory used by tools like istanbul 21 | coverage 22 | 23 | # nyc test coverage 24 | .nyc_output 25 | 26 | # Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files) 27 | .grunt 28 | 29 | # Bower dependency directory (https://bower.io/) 30 | bower_components 31 | 32 | # node-waf configuration 33 | .lock-wscript 34 | 35 | # Compiled binary addons (http://nodejs.org/api/addons.html) 36 | build/Release 37 | 38 | # Dependency directories 39 | node_modules/ 40 | jspm_packages/ 41 | 42 | # Typescript v1 declaration files 43 | typings/ 44 | 45 | # Optional npm cache directory 46 | .npm 47 | 48 | # Optional eslint cache 49 | .eslintcache 50 | 51 | # Optional REPL history 52 | .node_repl_history 53 | 54 | # Output of 'npm pack' 55 | *.tgz 56 | 57 | # Yarn Integrity file 58 | .yarn-integrity 59 | 60 | # dotenv environment variables file 61 | .env 62 | dist 63 | .cache 64 | yarn.lock 65 | package-lock.json 66 | -------------------------------------------------------------------------------- /.prettierrc: -------------------------------------------------------------------------------- 1 | { 2 | "printWidth": 150, 3 | "singleQuote": true, 4 | "trailingComma": "none", 5 | "bracketSpacing": true, 6 | "tabWidth": 4, 7 | "jsxBracketSameLine": true, 8 | "parser": "babylon", 9 | "semi": true 10 | } 11 | -------------------------------------------------------------------------------- /Package.swift: -------------------------------------------------------------------------------- 1 | // swift-tools-version:4.0 2 | import PackageDescription 3 | 4 | let package = Package( 5 | name: "simulator-set-location", 6 | targets: [ 7 | .target( 8 | name: "simulator-set-location" 9 | ) 10 | ] 11 | ) 12 | -------------------------------------------------------------------------------- /Readme.md: -------------------------------------------------------------------------------- 1 | # ios-simulator-set-location 2 | 3 | > Set the location of the ios simulator via node or the command line 4 | 5 | 6 | ## Install 7 | 8 | ``` 9 | $ npm install ios-simulator-set-location 10 | ``` 11 | 12 | or if you want to use the cli 13 | 14 | ``` 15 | $ npm install ios-simulator-set-location -g 16 | ``` 17 | 18 | 19 | ## Usage 20 | 21 | ```js 22 | const setLocation = require('ios-simulator-set-location'); 23 | 24 | (async () => { 25 | const lat = 52.5243700; 26 | const lat = 13.4105300; 27 | 28 | // set optional device Name, defaults to all running devices 29 | const deviceName = 'iphone X'; 30 | await setLocation(lat, lat, deviceName); 31 | 32 | })(); 33 | ``` 34 | 35 | 36 | ## CLI 37 | 38 | ``` 39 | Usage 40 | $ ios-set-location lat lng -n deviceName 41 | 42 | Options 43 | --name, -n specify the simulator name (optional, defaults to active running devices) 44 | 45 | Examples 46 | $ ios-set-location 52.5243700 13.4105300 47 | ``` 48 | 49 | 50 | ## License 51 | 52 | MIT © [Steffen Müller](https://steffen.io) 53 | -------------------------------------------------------------------------------- /Sources/simulator-set-location/main.swift: -------------------------------------------------------------------------------- 1 | import CoreLocation 2 | import Foundation 3 | 4 | // This should be better validated, since I'm only calling it from node it should be fine 5 | let arguments = CommandLine.arguments 6 | if 3 < arguments.count { 7 | let latitude = Double(CommandLine.arguments[1]) ?? 0.0 8 | let longitude = Double(CommandLine.arguments[2]) ?? 0.0 9 | let deviceIdString = CommandLine.arguments[3] 10 | 11 | let deviceIds = deviceIdString.components(separatedBy: ",") 12 | let location = CLLocationCoordinate2D(latitude: latitude, longitude: longitude) 13 | 14 | let userInfo: [AnyHashable: Any] = [ 15 | "simulateLocationLatitude": location.latitude, 16 | "simulateLocationLongitude": location.longitude, 17 | "simulateLocationDevices": deviceIds, 18 | ] 19 | 20 | let notification = Notification(name: Notification.Name(rawValue: "com.apple.iphonesimulator.simulateLocation"), object: nil, userInfo: userInfo) 21 | DistributedNotificationCenter.default().post(notification) 22 | 23 | print("OK") 24 | 25 | } else { 26 | print("Usage: `simulator-set-location lat lng deviceIds` (comma separated) - example `52.5243700 13.4105300 2FF61CF3-3973-426D-AA85-DF3A1960B3F7`") 27 | exit(EXIT_FAILURE) 28 | } 29 | -------------------------------------------------------------------------------- /cli.js: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env node 2 | 3 | const meow = require('meow'); 4 | const setLocation = require('.'); 5 | 6 | const cli = meow( 7 | ` 8 | Usage 9 | $ ios-set-location lat lng -n deviceName 10 | 11 | Options 12 | --name, -n specify the simulator name (optional, defaults to active running devices) 13 | 14 | Examples 15 | $ ios-set-location 52.5243700 13.4105300 16 | 17 | `, 18 | { 19 | flags: { 20 | name: { 21 | type: 'string', 22 | alias: 'n' 23 | } 24 | } 25 | } 26 | ); 27 | 28 | const lat = cli.input[0]; 29 | const lng = cli.input[1]; 30 | if (!lat || !lng) { 31 | cli.showHelp(); 32 | } 33 | 34 | setLocation(lat, lng, cli.flags.name).then((devices) => { 35 | devices.forEach(device => { 36 | console.log(`Updated location to ${lat} ${lng} for ${device}`); 37 | }); 38 | }).catch(err => { 39 | console.log(err.message) 40 | process.exit(1); 41 | }); 42 | -------------------------------------------------------------------------------- /index.js: -------------------------------------------------------------------------------- 1 | const execa = require('execa'); 2 | const { flatten, values, first } = require('lodash'); 3 | const electronUtil = require('electron-util/node'); 4 | const path = require('path'); 5 | 6 | const bin = path.join(electronUtil.fixPathForAsarUnpack(__dirname), 'simulator-set-location'); 7 | 8 | const getRunningDevices = async () => { 9 | try { 10 | const getDevices = await execa('xcrun', ['simctl', 'list', '-j', 'devices']); 11 | const { devices } = JSON.parse(getDevices.stdout); 12 | const flatDevices = flatten(values(devices)); 13 | return flatDevices.filter(d => d.state === 'Booted'); 14 | } catch (e) { 15 | throw new Error('Could not get running devices - make sure you can have `xcrun` in your path'); 16 | } 17 | }; 18 | 19 | const setLocation = async (lat, lng, name) => { 20 | const devices = await getRunningDevices(); 21 | if (devices.length === 0) { 22 | throw new Error('There are not devices running'); 23 | } 24 | const deviceIds = devices.map(d => d.udid); 25 | const setLoc = await execa(bin, [lat, lng, deviceIds.join(',')]); 26 | if (setLoc.stdout === 'OK') { 27 | return deviceIds; 28 | } else { 29 | throw new Error('Could not set location') 30 | } 31 | }; 32 | 33 | module.exports = setLocation; 34 | -------------------------------------------------------------------------------- /license: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) Steffen Müller (mllrsohn.com) 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: 6 | 7 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 8 | 9 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 10 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "ios-simulator-set-location", 3 | "version": "1.0.0", 4 | "description": "Sets the geolocation of the ios simulator", 5 | "main": "index.js", 6 | "repository": "git@github.com:steffenmllr/ios-simulator-set-location.git", 7 | "author": "Steffen Müller", 8 | "license": "MIT", 9 | "engines": { 10 | "node": ">=8" 11 | }, 12 | "bin": { 13 | "ios-set-location": "./cli.js" 14 | }, 15 | "files": [ 16 | "index.js", 17 | "cli.js", 18 | "simulator-set-location" 19 | ], 20 | "scripts": { 21 | "build": "rm -fr .build && rm -rf simulator-set-location && swift build --configuration=release -Xswiftc -static-stdlib && mv .build/release/simulator-set-location ./simulator-set-location", 22 | "prepublish": "npm run build" 23 | }, 24 | "dependencies": { 25 | "electron-util": "^0.8.2", 26 | "execa": "^0.10.0", 27 | "lodash": "^4.17.10", 28 | "meow": "^5.0.0" 29 | }, 30 | "devDependencies": { 31 | "prettier": "^1.12.1" 32 | } 33 | } 34 | --------------------------------------------------------------------------------