diff --git a/.changes/dev-url-localhost-mobile.md b/.changes/dev-url-localhost-mobile.md new file mode 100644 index 000000000..f4a37061f --- /dev/null +++ b/.changes/dev-url-localhost-mobile.md @@ -0,0 +1,9 @@ +--- +"tauri-cli": patch:breaking +"@tauri-apps/cli": patch:breaking +--- + +`ios dev` and `android dev` now uses localhost for the development server unless running on an iOS device, +which still requires connecting to the public network address. To conditionally check this on your frontend +framework's configuration you can check for the existence of the `TAURI_DEV_HOST` +environment variable instead of checking if the target is iOS or Android (previous recommendation). diff --git a/examples/api/package.json b/examples/api/package.json index 8c9d326c7..ff6f40177 100644 --- a/examples/api/package.json +++ b/examples/api/package.json @@ -11,14 +11,14 @@ }, "dependencies": { "@tauri-apps/api": "../../tooling/api/dist", - "@zerodevx/svelte-json-view": "1.0.9" + "@zerodevx/svelte-json-view": "1.0.9", + "internal-ip": "^7.0.0" }, "devDependencies": { "@iconify-json/codicon": "^1.1.49", "@iconify-json/ph": "^1.1.13", "@sveltejs/vite-plugin-svelte": "^3.1.1", "@unocss/extractor-svelte": "^0.61.0", - "internal-ip": "^8.0.0", "svelte": "^4.2.18", "unocss": "^0.61.0", "vite": "^5.3.2" diff --git a/examples/api/vite.config.js b/examples/api/vite.config.js index d2ca239f7..96f70723c 100644 --- a/examples/api/vite.config.js +++ b/examples/api/vite.config.js @@ -7,7 +7,7 @@ import Unocss from 'unocss/vite' import { svelte } from '@sveltejs/vite-plugin-svelte' import { internalIpV4Sync } from 'internal-ip' -const mobile = !!/android|ios/.exec(process.env.TAURI_ENV_PLATFORM) +const host = process.env.TAURI_DEV_HOST // https://vitejs.dev/config/ export default defineConfig({ @@ -27,13 +27,13 @@ export default defineConfig({ clearScreen: false, // tauri expects a fixed port, fail if that port is not available server: { - host: mobile ? '0.0.0.0' : false, + host: host ? '0.0.0.0' : false, port: 1420, strictPort: true, - hmr: mobile + hmr: host ? { protocol: 'ws', - host: mobile ? internalIpV4Sync() : 'localhost', + host: internalIpV4Sync(), port: 1430 } : undefined, diff --git a/examples/api/yarn.lock b/examples/api/yarn.lock index 9c3c8ca48..bc6acf7ca 100644 --- a/examples/api/yarn.lock +++ b/examples/api/yarn.lock @@ -624,7 +624,7 @@ vitefu "^0.2.5" "@tauri-apps/api@../../tooling/api/dist": - version "2.0.0-beta.13" + version "2.0.0-beta.15" "@types/estree@*", "@types/estree@1.0.5", "@types/estree@^1.0.0", "@types/estree@^1.0.1": version "1.0.5" @@ -943,30 +943,6 @@ chokidar@^3.6.0: optionalDependencies: fsevents "~2.3.2" -cidr-regex@4.0.3: - version "4.0.3" - resolved "https://registry.yarnpkg.com/cidr-regex/-/cidr-regex-4.0.3.tgz#07b52c9762d1ff546a50740e92fc2b5b13a6d871" - integrity sha512-HOwDIy/rhKeMf6uOzxtv7FAbrz8zPjmVKfSpM+U7/bNBXC5rtOyr758jxcptiSx6ZZn5LOhPJT5WWxPAGDV8dw== - dependencies: - ip-regex "^5.0.0" - -cidr-tools@^6.4.1: - version "6.4.2" - resolved "https://registry.yarnpkg.com/cidr-tools/-/cidr-tools-6.4.2.tgz#c47fa24128497d7482f446e883c5e69befa33030" - integrity sha512-KZC8t2ipCqU2M+ISmTxRDGu9bku5MRU3V1cWyGEFJTZEzRhGvBJvVsbpZO5UAu12fExRFihtYGXAlgFFpmK9jw== - dependencies: - cidr-regex "4.0.3" - ip-bigint "7.3.0" - ip-regex "5.0.0" - string-natural-compare "3.0.1" - -clone-regexp@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/clone-regexp/-/clone-regexp-3.0.0.tgz#c6dd5c6b85482306778f3dc4ac2bb967079069c2" - integrity sha512-ujdnoq2Kxb8s3ItNBtnYeXdm07FcU0u8ARAT1lQ2YdMwQC+cdiXX8KoqMVuglztILivceTtp4ivqGSmEmhBUJw== - dependencies: - is-regexp "^3.0.0" - code-red@^1.0.3: version "1.0.4" resolved "https://registry.yarnpkg.com/code-red/-/code-red-1.0.4.tgz#59ba5c9d1d320a4ef795bc10a28bd42bfebe3e35" @@ -1005,11 +981,6 @@ consola@^3.2.3: resolved "https://registry.yarnpkg.com/consola/-/consola-3.2.3.tgz#0741857aa88cfa0d6fd53f1cff0375136e98502f" integrity sha512-I5qxpzLv+sJhTVEoLYNcTW+bThDCPsit0vLNKShZx6rLtpilNpmmeTPaeqJb9ZE9dV3DGaeby6Vuhrw38WjeyQ== -convert-hrtime@^5.0.0: - version "5.0.0" - resolved "https://registry.yarnpkg.com/convert-hrtime/-/convert-hrtime-5.0.0.tgz#f2131236d4598b95de856926a67100a0a97e9fa3" - integrity sha512-lOETlkIeYSJWcbbcvjRKGxVMXJR+8+OQb/mTPbA4ObPMytYIsUbuOE0Jzy60hjARYszq1id0j8KgVhC+WGZVTg== - convert-source-map@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/convert-source-map/-/convert-source-map-2.0.0.tgz#4b560f649fc4e918dd0ab75cf4961e8bc882d82a" @@ -1044,12 +1015,12 @@ deepmerge@^4.3.1: resolved "https://registry.yarnpkg.com/deepmerge/-/deepmerge-4.3.1.tgz#44b5f2147cd3b00d4b56137685966f26fd25dd4a" integrity sha512-3sUqbMEc77XqpdNO7FRyRog+eW3ph+GYCbj+rK+uYyRMuwsVy0rMiVtPn+QJlKFvWP/1PYpapqYn0Me2knFn+A== -default-gateway@^7.2.2: - version "7.2.2" - resolved "https://registry.yarnpkg.com/default-gateway/-/default-gateway-7.2.2.tgz#85e6d88fde0f58703bab7744ed9d5330fa6b3f6c" - integrity sha512-AD7TrdNNPXRZIGw63dw+lnGmT4v7ggZC5NHNJgAYWm5njrwoze1q5JSAW9YuLy2tjnoLUG/r8FEB93MCh9QJPg== +default-gateway@^6.0.3: + version "6.0.3" + resolved "https://registry.yarnpkg.com/default-gateway/-/default-gateway-6.0.3.tgz#819494c888053bdb743edbf343d6cdf7f2943a71" + integrity sha512-fwSOJsbbNzZ/CUFpqFBqYfYNLj1NbMPm8MMCIzHjC83iSJRBEGmDUxU+WP661BaBQImeC2yHwXtz+P/O9o+XEg== dependencies: - execa "^7.1.1" + execa "^5.0.0" defu@^6.1.4: version "6.1.4" @@ -1127,7 +1098,7 @@ estree-walker@^3.0.0, estree-walker@^3.0.3: dependencies: "@types/estree" "^1.0.0" -execa@^5.1.1: +execa@^5.0.0, execa@^5.1.1: version "5.1.1" resolved "https://registry.yarnpkg.com/execa/-/execa-5.1.1.tgz#f80ad9cbf4298f7bd1d4c9555c21e93741c411dd" integrity sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg== @@ -1142,21 +1113,6 @@ execa@^5.1.1: signal-exit "^3.0.3" strip-final-newline "^2.0.0" -execa@^7.1.1: - version "7.2.0" - resolved "https://registry.yarnpkg.com/execa/-/execa-7.2.0.tgz#657e75ba984f42a70f38928cedc87d6f2d4fe4e9" - integrity sha512-UduyVP7TLB5IcAQl+OzLyLcS/l32W/GLg+AhHJ+ow40FOk2U3SAllPwR44v4vmdFwIWqpdwxxpQbF1n5ta9seA== - dependencies: - cross-spawn "^7.0.3" - get-stream "^6.0.1" - human-signals "^4.3.0" - is-stream "^3.0.0" - merge-stream "^2.0.0" - npm-run-path "^5.1.0" - onetime "^6.0.0" - signal-exit "^3.0.7" - strip-final-newline "^3.0.0" - fast-glob@^3.3.2: version "3.3.2" resolved "https://registry.yarnpkg.com/fast-glob/-/fast-glob-3.3.2.tgz#a904501e57cfdd2ffcded45e99a54fef55e46129" @@ -1195,17 +1151,12 @@ fsevents@~2.3.2, fsevents@~2.3.3: resolved "https://registry.yarnpkg.com/fsevents/-/fsevents-2.3.3.tgz#cac6407785d03675a2a5e1a5305c697b347d90d6" integrity sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw== -function-timeout@^0.1.0: - version "0.1.1" - resolved "https://registry.yarnpkg.com/function-timeout/-/function-timeout-0.1.1.tgz#6bf71d3d24c894d43b2bec312cabb8c5add2e9da" - integrity sha512-0NVVC0TaP7dSTvn1yMiy6d6Q8gifzbvQafO46RtLG/kHJUBNd+pVRGOBoK44wNBvtSPUJRfdVvkFdD3p0xvyZg== - gensync@^1.0.0-beta.2: version "1.0.0-beta.2" resolved "https://registry.yarnpkg.com/gensync/-/gensync-1.0.0-beta.2.tgz#32a6ee76c3d7f52d46b2b1ae5d93fea8580a25e0" integrity sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg== -get-stream@^6.0.0, get-stream@^6.0.1: +get-stream@^6.0.0: version "6.0.1" resolved "https://registry.yarnpkg.com/get-stream/-/get-stream-6.0.1.tgz#a262d8eef67aced57c2852ad6167526a43cbf7b7" integrity sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg== @@ -1239,30 +1190,25 @@ human-signals@^2.1.0: resolved "https://registry.yarnpkg.com/human-signals/-/human-signals-2.1.0.tgz#dc91fcba42e4d06e4abaed33b3e7a3c02f514ea0" integrity sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw== -human-signals@^4.3.0: - version "4.3.1" - resolved "https://registry.yarnpkg.com/human-signals/-/human-signals-4.3.1.tgz#ab7f811e851fca97ffbd2c1fe9a958964de321b2" - integrity sha512-nZXjEF2nbo7lIw3mgYjItAfgQXog3OjJogSbKa2CQIIvSGWcKgeJnQlNXip6NglNzYH45nSRiEVimMvYL8DDqQ== - -internal-ip@^8.0.0: - version "8.0.0" - resolved "https://registry.yarnpkg.com/internal-ip/-/internal-ip-8.0.0.tgz#9c998de890def7571d81e4366179e89c63d197fe" - integrity sha512-e6c3zxr9COnnc29PIz9LffmALOt0XhIJdR7f83DyHcQksL3B40KGmU3Sr1lrHja3i7Zyqo+AbwKZ+nZiMvg/OA== +internal-ip@^7.0.0: + version "7.0.0" + resolved "https://registry.yarnpkg.com/internal-ip/-/internal-ip-7.0.0.tgz#5b1c6a9d7e188aa73a1b69717daf50c8d8ed774f" + integrity sha512-qE4TeD4brqC45Vq/+VASeMiS1KRyfBkR6HT2sh9pZVVCzSjPkaCEfKFU+dL0PRv7NHJtvoKN2r82G6wTfzorkw== dependencies: - cidr-tools "^6.4.1" - default-gateway "^7.2.2" - is-ip "^5.0.0" - p-event "^5.0.1" + default-gateway "^6.0.3" + ipaddr.js "^2.0.1" + is-ip "^3.1.0" + p-event "^4.2.0" -ip-bigint@7.3.0: - version "7.3.0" - resolved "https://registry.yarnpkg.com/ip-bigint/-/ip-bigint-7.3.0.tgz#31cdcc86134ac0d461780330bbbcff46ffa3117b" - integrity sha512-2qVAe0Q9+Y+5nGvmogwK9y4kefD5Ks5l/IG0Jo1lhU9gIF34jifhqrwXwzkIl+LC594Q6SyAlngs4p890xsXVw== +ip-regex@^4.0.0: + version "4.3.0" + resolved "https://registry.yarnpkg.com/ip-regex/-/ip-regex-4.3.0.tgz#687275ab0f57fa76978ff8f4dddc8a23d5990db5" + integrity sha512-B9ZWJxHHOHUhUjCPrMpLD4xEq35bUTClHM1S6CBU5ixQnkZmwipwgc96vAd7AAGM9TGHvJR+Uss+/Ak6UphK+Q== -ip-regex@5.0.0, ip-regex@^5.0.0: - version "5.0.0" - resolved "https://registry.yarnpkg.com/ip-regex/-/ip-regex-5.0.0.tgz#cd313b2ae9c80c07bd3851e12bf4fa4dc5480632" - integrity sha512-fOCG6lhoKKakwv+C6KdsOnGvgXnmgfmp0myi3bcNwj3qfwPAxRKWEuFhvEFF7ceYIz6+1jRZ+yguLFAmUNPEfw== +ipaddr.js@^2.0.1: + version "2.2.0" + resolved "https://registry.yarnpkg.com/ipaddr.js/-/ipaddr.js-2.2.0.tgz#d33fa7bac284f4de7af949638c9d68157c6b92e8" + integrity sha512-Ag3wB2o37wslZS19hZqorUnrnzSkpOVy+IiiDEiTqNubEYpYuHWIf6K4psgN2ZWKExS4xhVCrRVfb/wfW8fWJA== is-binary-path@~2.1.0: version "2.1.0" @@ -1283,13 +1229,12 @@ is-glob@^4.0.1, is-glob@~4.0.1: dependencies: is-extglob "^2.1.1" -is-ip@^5.0.0: - version "5.0.1" - resolved "https://registry.yarnpkg.com/is-ip/-/is-ip-5.0.1.tgz#bec44442c823e591aa6f4d6fb9081d6a9be17e44" - integrity sha512-FCsGHdlrOnZQcp0+XT5a+pYowf33itBalCl+7ovNXC/7o5BhIpG14M3OrpPPdBSIQJCm+0M5+9mO7S9VVTTCFw== +is-ip@^3.1.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/is-ip/-/is-ip-3.1.0.tgz#2ae5ddfafaf05cb8008a62093cf29734f657c5d8" + integrity sha512-35vd5necO7IitFPjd/YBeqwWnyDWbuLH9ZXQdMfDA8TEo7pv5X8yfrvVO3xbJbLUlERCMvf6X0hTUamQxCYJ9Q== dependencies: - ip-regex "^5.0.0" - super-regex "^0.2.0" + ip-regex "^4.0.0" is-number@^7.0.0: version "7.0.0" @@ -1303,21 +1248,11 @@ is-reference@^3.0.0, is-reference@^3.0.1: dependencies: "@types/estree" "*" -is-regexp@^3.0.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/is-regexp/-/is-regexp-3.1.0.tgz#0235eab9cda5b83f96ac4a263d8c32c9d5ad7422" - integrity sha512-rbku49cWloU5bSMI+zaRaXdQHXnthP6DZ/vLnfdSKyL4zUzuWnomtOEiZZOd+ioQ+avFo/qau3KPTc7Fjy1uPA== - is-stream@^2.0.0: version "2.0.1" resolved "https://registry.yarnpkg.com/is-stream/-/is-stream-2.0.1.tgz#fac1e3d53b97ad5a9d0ae9cef2389f5810a5c077" integrity sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg== -is-stream@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/is-stream/-/is-stream-3.0.0.tgz#e6bfd7aa6bef69f4f472ce9bb681e3e57b4319ac" - integrity sha512-LnQR4bZ9IADDRSkvpqMGvt/tEJWclzklNgSw48V5EAaAeDd6qGvN8ei6k5p0tvxSR171VmGyHuTiAOfxAbr8kA== - isexe@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/isexe/-/isexe-2.0.0.tgz#e8fbf374dc556ff8947a10dcb0572d633f2cfa10" @@ -1415,11 +1350,6 @@ mimic-fn@^2.1.0: resolved "https://registry.yarnpkg.com/mimic-fn/-/mimic-fn-2.1.0.tgz#7ed2c2ccccaf84d3ffcb7a69b57711fc2083401b" integrity sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg== -mimic-fn@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/mimic-fn/-/mimic-fn-4.0.0.tgz#60a90550d5cb0b239cca65d893b1a53b29871ecc" - integrity sha512-vqiC06CuhBTUdZH+RYl8sFrL096vA45Ok5ISO6sE/Mr1jRbGH4Csnhi8f3wKVl7x8mO4Au7Ir9D3Oyv1VYMFJw== - mlly@^1.4.2, mlly@^1.6.1, mlly@^1.7.0: version "1.7.1" resolved "https://registry.yarnpkg.com/mlly/-/mlly-1.7.1.tgz#e0336429bb0731b6a8e887b438cbdae522c8f32f" @@ -1467,13 +1397,6 @@ npm-run-path@^4.0.1: dependencies: path-key "^3.0.0" -npm-run-path@^5.1.0: - version "5.3.0" - resolved "https://registry.yarnpkg.com/npm-run-path/-/npm-run-path-5.3.0.tgz#e23353d0ebb9317f174e93417e4a4d82d0249e9f" - integrity sha512-ppwTtiJZq0O/ai0z7yfudtBpWIoxM8yE6nHi1X47eFR2EWORqfbu6CnPlNsjeN683eT0qG6H/Pyf9fCcvjnnnQ== - dependencies: - path-key "^4.0.0" - ofetch@^1.3.4: version "1.3.4" resolved "https://registry.yarnpkg.com/ofetch/-/ofetch-1.3.4.tgz#7ea65ced3c592ec2b9906975ae3fe1d26a56f635" @@ -1490,19 +1413,17 @@ onetime@^5.1.2: dependencies: mimic-fn "^2.1.0" -onetime@^6.0.0: - version "6.0.0" - resolved "https://registry.yarnpkg.com/onetime/-/onetime-6.0.0.tgz#7c24c18ed1fd2e9bca4bd26806a33613c77d34b4" - integrity sha512-1FlR+gjXK7X+AsAHso35MnyN5KqGwJRi/31ft6x0M194ht7S+rWAvd7PHss9xSKMzE0asv1pyIHaJYq+BbacAQ== +p-event@^4.2.0: + version "4.2.0" + resolved "https://registry.yarnpkg.com/p-event/-/p-event-4.2.0.tgz#af4b049c8acd91ae81083ebd1e6f5cae2044c1b5" + integrity sha512-KXatOjCRXXkSePPb1Nbi0p0m+gQAwdlbhi4wQKJPI1HsMQS9g+Sqp2o+QHziPr7eYJyOZet836KoHEVM1mwOrQ== dependencies: - mimic-fn "^4.0.0" + p-timeout "^3.1.0" -p-event@^5.0.1: - version "5.0.1" - resolved "https://registry.yarnpkg.com/p-event/-/p-event-5.0.1.tgz#614624ec02ae7f4f13d09a721c90586184af5b0c" - integrity sha512-dd589iCQ7m1L0bmC5NLlVYfy3TbBEsMUfWx9PyAgPeIcFZ/E2yaTZ4Rz4MiBmmJShviiftHVXOqfnfzJ6kyMrQ== - dependencies: - p-timeout "^5.0.2" +p-finally@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/p-finally/-/p-finally-1.0.0.tgz#3fbcfb15b899a44123b34b6dcc18b724336a2cae" + integrity sha512-LICb2p9CB7FS+0eR1oqWnHhp0FljGLZCWBE9aix0Uye9W8LTQPwMTYVGWQWIw9RdQiDg4+epXQODwIYJtSJaow== p-limit@^3.0.2: version "3.1.0" @@ -1518,10 +1439,12 @@ p-locate@^5.0.0: dependencies: p-limit "^3.0.2" -p-timeout@^5.0.2: - version "5.1.0" - resolved "https://registry.yarnpkg.com/p-timeout/-/p-timeout-5.1.0.tgz#b3c691cf4415138ce2d9cfe071dba11f0fee085b" - integrity sha512-auFDyzzzGZZZdHz3BtET9VEz0SE/uMEAx7uWfGPucfzEwwe/xH0iVeZibQmANYE/hp9T2+UUZT5m+BKyrDp3Ew== +p-timeout@^3.1.0: + version "3.2.0" + resolved "https://registry.yarnpkg.com/p-timeout/-/p-timeout-3.2.0.tgz#c7e17abc971d2a7962ef83626b35d635acf23dfe" + integrity sha512-rhIwUycgwwKcP9yTOOFK/AKsAopjjCakVqLHePO3CC6Mir1Z99xT+R63jZxAT5lFZLa2inS5h+ZS2GvR99/FBg== + dependencies: + p-finally "^1.0.0" path-exists@^4.0.0: version "4.0.0" @@ -1533,11 +1456,6 @@ path-key@^3.0.0, path-key@^3.1.0: resolved "https://registry.yarnpkg.com/path-key/-/path-key-3.1.1.tgz#581f6ade658cbba65a0d3380de7753295054f375" integrity sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q== -path-key@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/path-key/-/path-key-4.0.0.tgz#295588dc3aee64154f877adb9d780b81c554bf18" - integrity sha512-haREypq7xkM7ErfgIyA0z+Bj4AGKlMSdlQE2jvJo6huWD1EdkKYV+G/T4nq0YEF2vgTT8kqMFKo1uHn950r4SQ== - pathe@^1.1.2: version "1.1.2" resolved "https://registry.yarnpkg.com/pathe/-/pathe-1.1.2.tgz#6c4cb47a945692e48a1ddd6e4094d170516437ec" @@ -1651,7 +1569,7 @@ shebang-regex@^3.0.0: resolved "https://registry.yarnpkg.com/shebang-regex/-/shebang-regex-3.0.0.tgz#ae16f1644d873ecad843b0307b143362d4c42172" integrity sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A== -signal-exit@^3.0.3, signal-exit@^3.0.7: +signal-exit@^3.0.3: version "3.0.7" resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-3.0.7.tgz#a9a1767f8af84155114eaabd73f99273c8f59ad9" integrity sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ== @@ -1670,30 +1588,11 @@ source-map-js@^1.0.1, source-map-js@^1.2.0: resolved "https://registry.yarnpkg.com/source-map-js/-/source-map-js-1.2.0.tgz#16b809c162517b5b8c3e7dcd315a2a5c2612b2af" integrity sha512-itJW8lvSA0TXEphiRoawsCksnlf8SyvmFzIhltqAHluXd88pkCd+cXJVHTDwdCr0IzwptSm035IHQktUu1QUMg== -string-natural-compare@3.0.1: - version "3.0.1" - resolved "https://registry.yarnpkg.com/string-natural-compare/-/string-natural-compare-3.0.1.tgz#7a42d58474454963759e8e8b7ae63d71c1e7fdf4" - integrity sha512-n3sPwynL1nwKi3WJ6AIsClwBMa0zTi54fn2oLU6ndfTSIO05xaznjSf15PcBZU6FNWbmN5Q6cxT4V5hGvB4taw== - strip-final-newline@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/strip-final-newline/-/strip-final-newline-2.0.0.tgz#89b852fb2fcbe936f6f4b3187afb0a12c1ab58ad" integrity sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA== -strip-final-newline@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/strip-final-newline/-/strip-final-newline-3.0.0.tgz#52894c313fbff318835280aed60ff71ebf12b8fd" - integrity sha512-dOESqjYr96iWYylGObzd39EuNTa5VJxyvVAEm5Jnh7KGo75V43Hk1odPQkNDyXNmUR6k+gEiDVXnjB8HJ3crXw== - -super-regex@^0.2.0: - version "0.2.0" - resolved "https://registry.yarnpkg.com/super-regex/-/super-regex-0.2.0.tgz#dc1e071e55cdcf56930eb6271f73653a655b2642" - integrity sha512-WZzIx3rC1CvbMDloLsVw0lkZVKJWbrkJ0k1ghKFmcnPrW1+jWbgTkTEWVtD9lMdmI4jZEz40+naBxl1dCUhXXw== - dependencies: - clone-regexp "^3.0.0" - function-timeout "^0.1.0" - time-span "^5.1.0" - supports-color@^5.3.0: version "5.5.0" resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-5.5.0.tgz#e2e69a44ac8772f78a1ec0b35b689df6530efc8f" @@ -1726,13 +1625,6 @@ svelte@^4.2.18: magic-string "^0.30.4" periscopic "^3.1.0" -time-span@^5.1.0: - version "5.1.0" - resolved "https://registry.yarnpkg.com/time-span/-/time-span-5.1.0.tgz#80c76cf5a0ca28e0842d3f10a4e99034ce94b90d" - integrity sha512-75voc/9G4rDIJleOo4jPvN4/YC4GRZrY8yy1uU4lwrB3XEQbWve8zXoO5No4eFrGcTAMYyoY67p8jRQdtA1HbA== - dependencies: - convert-hrtime "^5.0.0" - to-fast-properties@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/to-fast-properties/-/to-fast-properties-2.0.0.tgz#dc5e698cbd079265bc73e0377681a4e4e83f616e" diff --git a/tooling/cli/Cargo.lock b/tooling/cli/Cargo.lock index f1581ba4e..4b8016cd9 100644 --- a/tooling/cli/Cargo.lock +++ b/tooling/cli/Cargo.lock @@ -498,9 +498,9 @@ dependencies = [ [[package]] name = "cargo-mobile2" -version = "0.12.2" +version = "0.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e97b88fcfd9ecf65a09ecc40fa8bd4a4f0118bbd9867e3c3f8766422c12a956a" +checksum = "06f70f6ff0db884929c9b3b7825031607e2800e40ce1569e8f9c6a58bd82eae8" dependencies = [ "colored", "core-foundation", diff --git a/tooling/cli/Cargo.toml b/tooling/cli/Cargo.toml index cc720012b..2c14d63ec 100644 --- a/tooling/cli/Cargo.toml +++ b/tooling/cli/Cargo.toml @@ -39,7 +39,7 @@ name = "cargo-tauri" path = "src/main.rs" [dependencies] -cargo-mobile2 = { version = "0.12.1", default-features = false } +cargo-mobile2 = { version = "0.13", default-features = false } jsonrpsee = { version = "0.22", features = [ "server" ] } jsonrpsee-core = "0.22" jsonrpsee-client-transport = { version = "0.22", features = [ "ws" ] } diff --git a/tooling/cli/src/dev.rs b/tooling/cli/src/dev.rs index bef0aedab..7597ed60e 100644 --- a/tooling/cli/src/dev.rs +++ b/tooling/cli/src/dev.rs @@ -21,7 +21,7 @@ use tauri_utils::platform::Target; use std::{ env::set_current_dir, - net::{IpAddr, Ipv4Addr}, + net::Ipv4Addr, process::{exit, Command, Stdio}, sync::{ atomic::{AtomicBool, Ordering}, @@ -75,9 +75,6 @@ pub struct Options { /// Disable the file watcher. #[clap(long)] pub no_watch: bool, - /// Force prompting for an IP to use to connect to the dev server on mobile. - #[clap(long)] - pub force_ip_prompt: bool, /// Disable the built-in dev server for static files. #[clap(long)] @@ -109,7 +106,7 @@ fn command_internal(mut options: Options) -> Result<()> { options.target.clone(), )?; - setup(&interface, &mut options, config, false)?; + setup(&interface, &mut options, config)?; let exit_on_panic = options.exit_on_panic; let no_watch = options.no_watch; @@ -118,67 +115,10 @@ fn command_internal(mut options: Options) -> Result<()> { }) } -pub fn local_ip_address(force: bool) -> &'static IpAddr { - static LOCAL_IP: OnceLock = OnceLock::new(); - LOCAL_IP.get_or_init(|| { - let prompt_for_ip = || { - let addresses: Vec = local_ip_address::list_afinet_netifas() - .expect("failed to list networks") - .into_iter() - .map(|(_, ipaddr)| ipaddr) - .filter(|ipaddr| match ipaddr { - IpAddr::V4(i) => i != &Ipv4Addr::LOCALHOST, - _ => false, - }) - .collect(); - match addresses.len() { - 0 => panic!("No external IP detected."), - 1 => { - let ipaddr = addresses.first().unwrap(); - *ipaddr - } - _ => { - let selected = dialoguer::Select::with_theme(&dialoguer::theme::ColorfulTheme::default()) - .with_prompt( - "Failed to detect external IP, What IP should we use to access your development server?", - ) - .items(&addresses) - .default(0) - .interact() - .expect("failed to select external IP"); - *addresses.get(selected).unwrap() - } - } - }; - - let ip = if force { - prompt_for_ip() - } else { - local_ip_address::local_ip().unwrap_or_else(|_| prompt_for_ip()) - }; - log::info!("Using {ip} to access the development server."); - ip - }) -} - -pub fn setup( - interface: &AppInterface, - options: &mut Options, - config: ConfigHandle, - mobile: bool, -) -> Result<()> { +pub fn setup(interface: &AppInterface, options: &mut Options, config: ConfigHandle) -> Result<()> { let tauri_path = tauri_dir(); set_current_dir(tauri_path).with_context(|| "failed to change current working directory")?; - let mut dev_url = config - .lock() - .unwrap() - .as_ref() - .unwrap() - .build - .dev_url - .clone(); - if let Some(before_dev) = config .lock() .unwrap() @@ -196,25 +136,7 @@ pub fn setup( } }; let cwd = script_cwd.unwrap_or_else(|| app_dir().clone()); - if let Some(mut before_dev) = script { - if before_dev.contains("$HOST") { - if mobile { - let local_ip_address = local_ip_address(options.force_ip_prompt).to_string(); - before_dev = before_dev.replace("$HOST", &local_ip_address); - if let Some(url) = &mut dev_url { - url.set_host(Some(&local_ip_address))?; - } - } else { - before_dev = before_dev.replace( - "$HOST", - if let Some(url) = &dev_url { - url.host_str().unwrap_or("127.0.0.1") - } else { - "127.0.0.1" - }, - ); - } - } + if let Some(before_dev) = script { log::info!(action = "Running"; "BeforeDevCommand (`{}`)", before_dev); let mut env = command_env(true); env.extend(interface.env()); @@ -326,12 +248,9 @@ pub fn setup( if let Some(FrontendDist::Directory(path)) = &frontend_dist { if path.exists() { let path = path.canonicalize()?; - let ip = if mobile { - *local_ip_address(options.force_ip_prompt) - } else { - Ipv4Addr::new(127, 0, 0, 1).into() - }; - let server_url = builtin_dev_server::start(path, ip, options.port)?; + + let server_url = + builtin_dev_server::start(path, Ipv4Addr::new(127, 0, 0, 1).into(), options.port)?; let server_url = format!("http://{server_url}"); dev_url = Some(server_url.parse().unwrap()); diff --git a/tooling/cli/src/mobile/android/dev.rs b/tooling/cli/src/mobile/android/dev.rs index caa231b4f..bb55b2ce7 100644 --- a/tooling/cli/src/mobile/android/dev.rs +++ b/tooling/cli/src/mobile/android/dev.rs @@ -4,7 +4,7 @@ use super::{ configure_cargo, delete_codegen_vars, device_prompt, ensure_init, env, get_app, get_config, - inject_assets, open_and_wait, setup_dev_config, MobileTarget, + inject_assets, open_and_wait, MobileTarget, }; use crate::{ dev::Options as DevOptions, @@ -22,6 +22,7 @@ use clap::{ArgAction, Parser}; use anyhow::Context; use cargo_mobile2::{ android::{ + adb, config::{Config as AndroidConfig, Metadata as AndroidMetadata}, device::Device, env::Env, @@ -63,9 +64,6 @@ pub struct Options { pub open: bool, /// Runs on the given device name pub device: Option, - /// Force prompting for an IP to use to connect to the dev server on mobile. - #[clap(long)] - pub force_ip_prompt: bool, /// Disable the built-in dev server for static files. #[clap(long)] pub no_dev_server: bool, @@ -87,7 +85,6 @@ impl From for DevOptions { no_dev_server_wait: options.no_dev_server_wait, no_dev_server: options.no_dev_server, port: options.port, - force_ip_prompt: options.force_ip_prompt, release_mode: options.release_mode, } } @@ -166,7 +163,7 @@ fn run_command(options: Options, noise_level: NoiseLevel) -> Result<()> { #[allow(clippy::too_many_arguments)] fn run_dev( mut interface: AppInterface, - mut options: Options, + options: Options, mut dev_options: DevOptions, tauri_config: ConfigHandle, device: Option, @@ -176,13 +173,7 @@ fn run_dev( metadata: &AndroidMetadata, noise_level: NoiseLevel, ) -> Result<()> { - setup_dev_config( - MobileTarget::Android, - &mut options.config, - options.force_ip_prompt, - )?; - - crate::dev::setup(&interface, &mut dev_options, tauri_config.clone(), true)?; + crate::dev::setup(&interface, &mut dev_options, tauri_config.clone())?; let interface_options = InterfaceOptions { debug: !dev_options.release_mode, @@ -216,6 +207,19 @@ fn run_dev( }, )?; + let dev_url = tauri_config + .lock() + .unwrap() + .as_ref() + .unwrap() + .build + .dev_url + .clone(); + if let Some(port) = dev_url.and_then(|url| url.port_or_known_default()) { + let forward = format!("tcp:{port}"); + adb::adb(&env, ["reverse", &forward, &forward]).run()?; + } + let open = options.open; let exit_on_panic = options.exit_on_panic; let no_watch = options.no_watch; diff --git a/tooling/cli/src/mobile/android/mod.rs b/tooling/cli/src/mobile/android/mod.rs index f78f5e599..1e29fe806 100644 --- a/tooling/cli/src/mobile/android/mod.rs +++ b/tooling/cli/src/mobile/android/mod.rs @@ -29,7 +29,7 @@ use sublime_fuzzy::best_match; use super::{ ensure_init, get_app, init::{command as init_command, configure_cargo}, - log_finished, read_options, setup_dev_config, CliOptions, OptionsHandle, Target as MobileTarget, + log_finished, read_options, CliOptions, OptionsHandle, Target as MobileTarget, MIN_DEVICE_MATCH_SCORE, }; use crate::{helpers::config::Config as TauriConfig, Result}; diff --git a/tooling/cli/src/mobile/ios/dev.rs b/tooling/cli/src/mobile/ios/dev.rs index e1ff215c9..45f632928 100644 --- a/tooling/cli/src/mobile/ios/dev.rs +++ b/tooling/cli/src/mobile/ios/dev.rs @@ -4,13 +4,13 @@ use super::{ configure_cargo, device_prompt, ensure_init, env, get_app, get_config, inject_assets, - merge_plist, open_and_wait, setup_dev_config, MobileTarget, + merge_plist, open_and_wait, MobileTarget, }; use crate::{ dev::Options as DevOptions, helpers::{ app_paths::tauri_dir, - config::{get as get_tauri_config, ConfigHandle}, + config::{get as get_tauri_config, reload as reload_config, ConfigHandle}, flock, }, interface::{AppInterface, AppSettings, Interface, MobileOptions, Options as InterfaceOptions}, @@ -21,18 +21,32 @@ use clap::{ArgAction, Parser}; use anyhow::Context; use cargo_mobile2::{ - apple::{config::Config as AppleConfig, device::Device}, + apple::{ + config::Config as AppleConfig, + device::{Device, DeviceKind}, + }, config::app::App, env::Env, opts::{NoiseLevel, Profile}, }; -use std::env::set_current_dir; +use std::{ + env::set_current_dir, + net::{IpAddr, Ipv4Addr}, + sync::OnceLock, +}; #[derive(Debug, Clone, Parser)] #[clap( about = "Run your app in development mode on iOS", - long_about = "Run your app in development mode on iOS with hot-reloading for the Rust code. It makes use of the `build.devUrl` property from your `tauri.conf.json` file. It also runs your `build.beforeDevCommand` which usually starts your frontend devServer." + long_about = "Run your app in development mode on iOS with hot-reloading for the Rust code. +It makes use of the `build.devUrl` property from your `tauri.conf.json` file. +It also runs your `build.beforeDevCommand` which usually starts your frontend devServer. + +When connected to a physical iOS device, the public network address must be used instead of `localhost` +for the devUrl property. Tauri makes that change automatically, but your dev server might need +a different configuration to listen on the public address. You can check the `TAURI_DEV_HOST` +environment variable to determine whether the public network should be used or not." )] pub struct Options { /// List of cargo features to activate @@ -61,6 +75,19 @@ pub struct Options { /// Force prompting for an IP to use to connect to the dev server on mobile. #[clap(long)] pub force_ip_prompt: bool, + /// Use the public network address for the development server. + /// + /// This option is particularly useful along the `--open` flag when you intend on running on a physical device. + /// + /// This replaces the devUrl configuration value to match the public network address host, + /// it is your responsability to set up your development server to listen on this address + /// by using 0.0.0.0 as host for instance. + /// + /// When this is set or when running on an iOS device the CLI sets the `TAURI_DEV_HOST` + /// environment variable so you can check this on your framework's configuration to expose the development server + /// on the public network address. + #[clap(long)] + pub host: bool, /// Disable the built-in dev server for static files. #[clap(long)] pub no_dev_server: bool, @@ -83,7 +110,6 @@ impl From for DevOptions { no_dev_server: options.no_dev_server, no_dev_server_wait: options.no_dev_server_wait, port: options.port, - force_ip_prompt: options.force_ip_prompt, } } } @@ -168,6 +194,105 @@ fn run_command(options: Options, noise_level: NoiseLevel) -> Result<()> { ) } +fn local_ip_address(force: bool) -> &'static IpAddr { + static LOCAL_IP: OnceLock = OnceLock::new(); + LOCAL_IP.get_or_init(|| { + let prompt_for_ip = || { + let addresses: Vec = local_ip_address::list_afinet_netifas() + .expect("failed to list networks") + .into_iter() + .map(|(_, ipaddr)| ipaddr) + .filter(|ipaddr| match ipaddr { + IpAddr::V4(i) => i != &Ipv4Addr::LOCALHOST, + _ => false, + }) + .collect(); + match addresses.len() { + 0 => panic!("No external IP detected."), + 1 => { + let ipaddr = addresses.first().unwrap(); + *ipaddr + } + _ => { + let selected = dialoguer::Select::with_theme(&dialoguer::theme::ColorfulTheme::default()) + .with_prompt( + "Failed to detect external IP, What IP should we use to access your development server?", + ) + .items(&addresses) + .default(0) + .interact() + .expect("failed to select external IP"); + *addresses.get(selected).unwrap() + } + } + }; + + let ip = if force { + prompt_for_ip() + } else { + local_ip_address::local_ip().unwrap_or_else(|_| prompt_for_ip()) + }; + log::info!("Using {ip} to access the development server."); + ip + }) +} + +fn use_network_address_for_dev_url( + config: &ConfigHandle, + config_extension: &mut Option, + force_ip_prompt: bool, +) -> crate::Result<()> { + let mut dev_url = config + .lock() + .unwrap() + .as_ref() + .unwrap() + .build + .dev_url + .clone(); + + if let Some(url) = &mut dev_url { + let localhost = match url.host() { + Some(url::Host::Domain(d)) => d == "localhost", + Some(url::Host::Ipv4(i)) => { + i == std::net::Ipv4Addr::LOCALHOST || i == std::net::Ipv4Addr::UNSPECIFIED + } + _ => false, + }; + + if localhost { + let ip = local_ip_address(force_ip_prompt).to_string(); + println!( + "Replacing devUrl host with {ip}. {}. {}.", + "If your frontend is not listening on that address, try configuring your development server to use 0.0.0.0 as host", + "When this is required, Tauri sets the TAURI_DEV_HOST environment variable" + ); + url.set_host(Some(&ip)).unwrap(); + + if let Some(c) = config_extension { + if let Some(build) = c + .0 + .as_object_mut() + .and_then(|root| root.get_mut("build")) + .and_then(|build| build.as_object_mut()) + { + build.insert("devUrl".into(), url.to_string().into()); + } + } else { + let mut build = serde_json::Map::new(); + build.insert("devUrl".into(), url.to_string().into()); + + config_extension.replace(crate::ConfigValue(serde_json::json!({ + "build": build + }))); + } + reload_config(config_extension.as_ref().map(|c| &c.0))?; + } + } + + Ok(()) +} + #[allow(clippy::too_many_arguments)] fn run_dev( mut interface: AppInterface, @@ -180,13 +305,18 @@ fn run_dev( config: &AppleConfig, noise_level: NoiseLevel, ) -> Result<()> { - setup_dev_config( - MobileTarget::Ios, - &mut options.config, - options.force_ip_prompt, - )?; + // when running on an actual device we must use the network IP + if options.host + || device + .as_ref() + .map(|device| !matches!(device.kind(), DeviceKind::Simulator)) + .unwrap_or(false) + { + std::env::set_var("TAURI_DEV_HOST", "true"); + use_network_address_for_dev_url(&tauri_config, &mut options.config, options.force_ip_prompt)?; + } - crate::dev::setup(&interface, &mut dev_options, tauri_config.clone(), true)?; + crate::dev::setup(&interface, &mut dev_options, tauri_config.clone())?; let app_settings = interface.app_settings(); let bin_path = app_settings.app_binary_path(&InterfaceOptions { diff --git a/tooling/cli/src/mobile/ios/mod.rs b/tooling/cli/src/mobile/ios/mod.rs index a921c43df..285a235cf 100644 --- a/tooling/cli/src/mobile/ios/mod.rs +++ b/tooling/cli/src/mobile/ios/mod.rs @@ -24,7 +24,7 @@ use sublime_fuzzy::best_match; use super::{ ensure_init, env, get_app, init::{command as init_command, configure_cargo}, - log_finished, read_options, setup_dev_config, CliOptions, OptionsHandle, Target as MobileTarget, + log_finished, read_options, CliOptions, OptionsHandle, Target as MobileTarget, MIN_DEVICE_MATCH_SCORE, }; use crate::{ diff --git a/tooling/cli/src/mobile/mod.rs b/tooling/cli/src/mobile/mod.rs index 509f60eff..3f1ba6397 100644 --- a/tooling/cli/src/mobile/mod.rs +++ b/tooling/cli/src/mobile/mod.rs @@ -3,12 +3,8 @@ // SPDX-License-Identifier: MIT use crate::{ - helpers::{ - app_paths::tauri_dir, - config::{get as get_config, reload as reload_config, Config as TauriConfig}, - }, + helpers::{app_paths::tauri_dir, config::Config as TauriConfig}, interface::{AppInterface, AppSettings, DevProcess, Interface, Options as InterfaceOptions}, - ConfigValue, }; use anyhow::{bail, Result}; use heck::ToSnekCase; @@ -152,59 +148,6 @@ impl Default for CliOptions { } } -fn setup_dev_config( - target: Target, - config_extension: &mut Option, - force_ip_prompt: bool, -) -> crate::Result<()> { - let config = get_config( - target.platform_target(), - config_extension.as_ref().map(|c| &c.0), - )?; - - let mut dev_url = config - .lock() - .unwrap() - .as_ref() - .unwrap() - .build - .dev_url - .clone(); - - if let Some(url) = &mut dev_url { - let localhost = match url.host() { - Some(url::Host::Domain(d)) => d == "localhost", - Some(url::Host::Ipv4(i)) => { - i == std::net::Ipv4Addr::LOCALHOST || i == std::net::Ipv4Addr::UNSPECIFIED - } - _ => false, - }; - if localhost { - let ip = crate::dev::local_ip_address(force_ip_prompt); - url.set_host(Some(&ip.to_string())).unwrap(); - if let Some(c) = config_extension { - if let Some(build) = c - .0 - .as_object_mut() - .and_then(|root| root.get_mut("build")) - .and_then(|build| build.as_object_mut()) - { - build.insert("devUrl".into(), url.to_string().into()); - } - } else { - config_extension.replace(crate::ConfigValue(serde_json::json!({ - "build": { - "devUrl": url - } - }))); - } - reload_config(config_extension.as_ref().map(|c| &c.0))?; - } - } - - Ok(()) -} - fn env_vars() -> HashMap { let mut vars = HashMap::new(); vars.insert("RUST_LOG_STYLE".into(), "always".into()); diff --git a/tooling/cli/templates/plugin/__example-api/tauri-app/vite.config.js b/tooling/cli/templates/plugin/__example-api/tauri-app/vite.config.js index 5651fcb1f..bfad25c62 100644 --- a/tooling/cli/templates/plugin/__example-api/tauri-app/vite.config.js +++ b/tooling/cli/templates/plugin/__example-api/tauri-app/vite.config.js @@ -1,8 +1,8 @@ import { defineConfig } from "vite"; import { svelte } from "@sveltejs/vite-plugin-svelte"; -import { internalIpV4Sync } from 'internal-ip' +import { internalIpV4Sync } from 'internal-ip'; -const mobile = !!/android|ios/.exec(process.env.TAURI_ENV_PLATFORM); +const host = process.env.TAURI_DEV_HOST; // https://vitejs.dev/config/ export default defineConfig({ @@ -13,10 +13,10 @@ export default defineConfig({ clearScreen: false, // tauri expects a fixed port, fail if that port is not available server: { - host: mobile ? "0.0.0.0" : false, + host: host ? "0.0.0.0" : false, port: 1420, strictPort: true, - hmr: mobile ? { + hmr: host ? { protocol: 'ws', host: internalIpV4Sync(), port: 1421