@nativescript/vite 8.0.0-alpha.2 → 8.0.0-alpha.20

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (209) hide show
  1. package/configuration/angular.d.ts +34 -1
  2. package/configuration/angular.js +380 -34
  3. package/configuration/angular.js.map +1 -1
  4. package/configuration/base.js +171 -7
  5. package/configuration/base.js.map +1 -1
  6. package/configuration/solid.js +27 -1
  7. package/configuration/solid.js.map +1 -1
  8. package/configuration/typescript.js +1 -1
  9. package/configuration/typescript.js.map +1 -1
  10. package/helpers/angular/angular-linker.js +3 -12
  11. package/helpers/angular/angular-linker.js.map +1 -1
  12. package/helpers/angular/inject-component-hmr-registration.d.ts +112 -0
  13. package/helpers/angular/inject-component-hmr-registration.js +359 -0
  14. package/helpers/angular/inject-component-hmr-registration.js.map +1 -0
  15. package/helpers/angular/inject-hmr-vite-ignore.d.ts +75 -0
  16. package/helpers/angular/inject-hmr-vite-ignore.js +288 -0
  17. package/helpers/angular/inject-hmr-vite-ignore.js.map +1 -0
  18. package/helpers/angular/util.d.ts +1 -0
  19. package/helpers/angular/util.js +88 -0
  20. package/helpers/angular/util.js.map +1 -1
  21. package/helpers/commonjs-plugins.d.ts +5 -2
  22. package/helpers/commonjs-plugins.js +126 -0
  23. package/helpers/commonjs-plugins.js.map +1 -1
  24. package/helpers/config-as-json.js +10 -0
  25. package/helpers/config-as-json.js.map +1 -1
  26. package/helpers/dev-host.d.ts +274 -0
  27. package/helpers/dev-host.js +491 -0
  28. package/helpers/dev-host.js.map +1 -0
  29. package/helpers/global-defines.d.ts +51 -0
  30. package/helpers/global-defines.js +77 -0
  31. package/helpers/global-defines.js.map +1 -1
  32. package/helpers/logging.d.ts +1 -0
  33. package/helpers/logging.js +63 -3
  34. package/helpers/logging.js.map +1 -1
  35. package/helpers/main-entry.d.ts +3 -1
  36. package/helpers/main-entry.js +450 -125
  37. package/helpers/main-entry.js.map +1 -1
  38. package/helpers/nativeclass-transformer-plugin.d.ts +9 -2
  39. package/helpers/nativeclass-transformer-plugin.js +157 -14
  40. package/helpers/nativeclass-transformer-plugin.js.map +1 -1
  41. package/helpers/ns-core-url.d.ts +88 -0
  42. package/helpers/ns-core-url.js +191 -0
  43. package/helpers/ns-core-url.js.map +1 -0
  44. package/helpers/prelink-angular.js +1 -4
  45. package/helpers/prelink-angular.js.map +1 -1
  46. package/helpers/project.d.ts +35 -0
  47. package/helpers/project.js +120 -2
  48. package/helpers/project.js.map +1 -1
  49. package/helpers/resolver.js +9 -1
  50. package/helpers/resolver.js.map +1 -1
  51. package/helpers/solid-jsx-deps.d.ts +15 -0
  52. package/helpers/solid-jsx-deps.js +178 -0
  53. package/helpers/solid-jsx-deps.js.map +1 -0
  54. package/helpers/ts-config-paths.js +50 -2
  55. package/helpers/ts-config-paths.js.map +1 -1
  56. package/helpers/workers.d.ts +20 -19
  57. package/helpers/workers.js +620 -3
  58. package/helpers/workers.js.map +1 -1
  59. package/hmr/client/css-handler.d.ts +1 -0
  60. package/hmr/client/css-handler.js +34 -5
  61. package/hmr/client/css-handler.js.map +1 -1
  62. package/hmr/client/css-update-overlay.d.ts +18 -0
  63. package/hmr/client/css-update-overlay.js +27 -0
  64. package/hmr/client/css-update-overlay.js.map +1 -0
  65. package/hmr/client/hmr-pending-overlay.d.ts +27 -0
  66. package/hmr/client/hmr-pending-overlay.js +50 -0
  67. package/hmr/client/hmr-pending-overlay.js.map +1 -0
  68. package/hmr/client/index.js +483 -33
  69. package/hmr/client/index.js.map +1 -1
  70. package/hmr/client/utils.d.ts +5 -0
  71. package/hmr/client/utils.js +283 -12
  72. package/hmr/client/utils.js.map +1 -1
  73. package/hmr/client/vue-sfc-update-overlay.d.ts +82 -0
  74. package/hmr/client/vue-sfc-update-overlay.js +133 -0
  75. package/hmr/client/vue-sfc-update-overlay.js.map +1 -0
  76. package/hmr/entry-runtime.d.ts +2 -1
  77. package/hmr/entry-runtime.js +253 -66
  78. package/hmr/entry-runtime.js.map +1 -1
  79. package/hmr/frameworks/angular/client/index.d.ts +3 -1
  80. package/hmr/frameworks/angular/client/index.js +802 -10
  81. package/hmr/frameworks/angular/client/index.js.map +1 -1
  82. package/hmr/frameworks/angular/server/linker.js +1 -4
  83. package/hmr/frameworks/angular/server/linker.js.map +1 -1
  84. package/hmr/frameworks/angular/server/strategy.js +30 -6
  85. package/hmr/frameworks/angular/server/strategy.js.map +1 -1
  86. package/hmr/frameworks/typescript/server/strategy.js +8 -2
  87. package/hmr/frameworks/typescript/server/strategy.js.map +1 -1
  88. package/hmr/frameworks/vue/client/index.js +18 -42
  89. package/hmr/frameworks/vue/client/index.js.map +1 -1
  90. package/hmr/helpers/ast-normalizer.js +52 -5
  91. package/hmr/helpers/ast-normalizer.js.map +1 -1
  92. package/hmr/helpers/cjs-named-exports.d.ts +23 -0
  93. package/hmr/helpers/cjs-named-exports.js +152 -0
  94. package/hmr/helpers/cjs-named-exports.js.map +1 -0
  95. package/hmr/helpers/package-exports.d.ts +16 -0
  96. package/hmr/helpers/package-exports.js +396 -0
  97. package/hmr/helpers/package-exports.js.map +1 -0
  98. package/hmr/server/constants.js +13 -4
  99. package/hmr/server/constants.js.map +1 -1
  100. package/hmr/server/core-sanitize.d.ts +93 -8
  101. package/hmr/server/core-sanitize.js +222 -49
  102. package/hmr/server/core-sanitize.js.map +1 -1
  103. package/hmr/server/import-map.js +80 -22
  104. package/hmr/server/import-map.js.map +1 -1
  105. package/hmr/server/index.d.ts +2 -1
  106. package/hmr/server/index.js.map +1 -1
  107. package/hmr/server/ns-core-cjs-shape.d.ts +204 -0
  108. package/hmr/server/ns-core-cjs-shape.js +271 -0
  109. package/hmr/server/ns-core-cjs-shape.js.map +1 -0
  110. package/hmr/server/ns-rt-bridge.d.ts +51 -0
  111. package/hmr/server/ns-rt-bridge.js +131 -0
  112. package/hmr/server/ns-rt-bridge.js.map +1 -0
  113. package/hmr/server/perf-instrumentation.d.ts +114 -0
  114. package/hmr/server/perf-instrumentation.js +195 -0
  115. package/hmr/server/perf-instrumentation.js.map +1 -0
  116. package/hmr/server/runtime-graph-filter.d.ts +5 -0
  117. package/hmr/server/runtime-graph-filter.js +21 -0
  118. package/hmr/server/runtime-graph-filter.js.map +1 -0
  119. package/hmr/server/shared-transform-request.d.ts +12 -0
  120. package/hmr/server/shared-transform-request.js +144 -0
  121. package/hmr/server/shared-transform-request.js.map +1 -0
  122. package/hmr/server/vite-plugin.d.ts +21 -1
  123. package/hmr/server/vite-plugin.js +497 -58
  124. package/hmr/server/vite-plugin.js.map +1 -1
  125. package/hmr/server/websocket-angular-entry.d.ts +2 -0
  126. package/hmr/server/websocket-angular-entry.js +68 -0
  127. package/hmr/server/websocket-angular-entry.js.map +1 -0
  128. package/hmr/server/websocket-angular-hot-update.d.ts +78 -0
  129. package/hmr/server/websocket-angular-hot-update.js +413 -0
  130. package/hmr/server/websocket-angular-hot-update.js.map +1 -0
  131. package/hmr/server/websocket-core-bridge.d.ts +58 -0
  132. package/hmr/server/websocket-core-bridge.js +368 -0
  133. package/hmr/server/websocket-core-bridge.js.map +1 -0
  134. package/hmr/server/websocket-css-hot-update.d.ts +33 -0
  135. package/hmr/server/websocket-css-hot-update.js +65 -0
  136. package/hmr/server/websocket-css-hot-update.js.map +1 -0
  137. package/hmr/server/websocket-graph-upsert.d.ts +21 -0
  138. package/hmr/server/websocket-graph-upsert.js +33 -0
  139. package/hmr/server/websocket-graph-upsert.js.map +1 -0
  140. package/hmr/server/websocket-hmr-pending.d.ts +43 -0
  141. package/hmr/server/websocket-hmr-pending.js +55 -0
  142. package/hmr/server/websocket-hmr-pending.js.map +1 -0
  143. package/hmr/server/websocket-module-bindings.d.ts +6 -0
  144. package/hmr/server/websocket-module-bindings.js +471 -0
  145. package/hmr/server/websocket-module-bindings.js.map +1 -0
  146. package/hmr/server/websocket-module-specifiers.d.ts +101 -0
  147. package/hmr/server/websocket-module-specifiers.js +820 -0
  148. package/hmr/server/websocket-module-specifiers.js.map +1 -0
  149. package/hmr/server/websocket-ns-m-finalize.d.ts +22 -0
  150. package/hmr/server/websocket-ns-m-finalize.js +88 -0
  151. package/hmr/server/websocket-ns-m-finalize.js.map +1 -0
  152. package/hmr/server/websocket-ns-m-paths.d.ts +3 -0
  153. package/hmr/server/websocket-ns-m-paths.js +92 -0
  154. package/hmr/server/websocket-ns-m-paths.js.map +1 -0
  155. package/hmr/server/websocket-ns-m-request.d.ts +45 -0
  156. package/hmr/server/websocket-ns-m-request.js +196 -0
  157. package/hmr/server/websocket-ns-m-request.js.map +1 -0
  158. package/hmr/server/websocket-served-module-helpers.d.ts +36 -0
  159. package/hmr/server/websocket-served-module-helpers.js +644 -0
  160. package/hmr/server/websocket-served-module-helpers.js.map +1 -0
  161. package/hmr/server/websocket-txn.d.ts +6 -0
  162. package/hmr/server/websocket-txn.js +45 -0
  163. package/hmr/server/websocket-txn.js.map +1 -0
  164. package/hmr/server/websocket-vendor-unifier.d.ts +10 -0
  165. package/hmr/server/websocket-vendor-unifier.js +51 -0
  166. package/hmr/server/websocket-vendor-unifier.js.map +1 -0
  167. package/hmr/server/websocket-vue-sfc.d.ts +26 -0
  168. package/hmr/server/websocket-vue-sfc.js +1053 -0
  169. package/hmr/server/websocket-vue-sfc.js.map +1 -0
  170. package/hmr/server/websocket.d.ts +58 -75
  171. package/hmr/server/websocket.js +2230 -1802
  172. package/hmr/server/websocket.js.map +1 -1
  173. package/hmr/shared/package-classifier.d.ts +9 -0
  174. package/hmr/shared/package-classifier.js +58 -0
  175. package/hmr/shared/package-classifier.js.map +1 -0
  176. package/hmr/shared/runtime/boot-placeholder-ui.d.ts +69 -0
  177. package/hmr/shared/runtime/boot-placeholder-ui.js +101 -0
  178. package/hmr/shared/runtime/boot-placeholder-ui.js.map +1 -0
  179. package/hmr/shared/runtime/boot-progress.d.ts +40 -0
  180. package/hmr/shared/runtime/boot-progress.js +128 -0
  181. package/hmr/shared/runtime/boot-progress.js.map +1 -0
  182. package/hmr/shared/runtime/boot-timeline.d.ts +18 -0
  183. package/hmr/shared/runtime/boot-timeline.js +52 -0
  184. package/hmr/shared/runtime/boot-timeline.js.map +1 -0
  185. package/hmr/shared/runtime/browser-runtime-contract.d.ts +64 -0
  186. package/hmr/shared/runtime/browser-runtime-contract.js +54 -0
  187. package/hmr/shared/runtime/browser-runtime-contract.js.map +1 -0
  188. package/hmr/shared/runtime/dev-overlay.d.ts +78 -3
  189. package/hmr/shared/runtime/dev-overlay.js +1094 -26
  190. package/hmr/shared/runtime/dev-overlay.js.map +1 -1
  191. package/hmr/shared/runtime/module-provenance.js +1 -4
  192. package/hmr/shared/runtime/module-provenance.js.map +1 -1
  193. package/hmr/shared/runtime/root-placeholder.d.ts +1 -0
  194. package/hmr/shared/runtime/root-placeholder.js +1019 -151
  195. package/hmr/shared/runtime/root-placeholder.js.map +1 -1
  196. package/hmr/shared/runtime/session-bootstrap.d.ts +1 -0
  197. package/hmr/shared/runtime/session-bootstrap.js +309 -0
  198. package/hmr/shared/runtime/session-bootstrap.js.map +1 -0
  199. package/hmr/shared/runtime/vendor-bootstrap.js +1 -9
  200. package/hmr/shared/runtime/vendor-bootstrap.js.map +1 -1
  201. package/hmr/shared/vendor/manifest.d.ts +32 -0
  202. package/hmr/shared/vendor/manifest.js +411 -46
  203. package/hmr/shared/vendor/manifest.js.map +1 -1
  204. package/index.d.ts +1 -0
  205. package/index.js +5 -0
  206. package/index.js.map +1 -1
  207. package/package.json +9 -1
  208. package/runtime/core-aliases-early.js +94 -67
  209. package/runtime/core-aliases-early.js.map +1 -1
@@ -0,0 +1,491 @@
1
+ /**
2
+ * Canonical resolver for the Vite dev-server origin that a NativeScript
3
+ * device or simulator can actually reach.
4
+ *
5
+ * Why this exists. The Vite dev server commonly binds to `0.0.0.0`
6
+ * (the wildcard "all interfaces" address) so both the host browser and
7
+ * a sibling mobile device can hit it. That bind address is fine for
8
+ * the LISTENING socket — but it is NOT a routable hostname:
9
+ *
10
+ * - iOS Simulator shares the host's network stack, so `localhost` /
11
+ * `127.0.0.1` work from inside the simulator and even `0.0.0.0`
12
+ * sometimes resolves there. The simulator path is forgiving.
13
+ *
14
+ * - Android Emulator runs inside a virtual NIC with NAT (QEMU
15
+ * `slirp`). `0.0.0.0` and `localhost` / `127.0.0.1` refer to the
16
+ * EMULATOR ITSELF, not the development host. Two routable paths
17
+ * exist:
18
+ *
19
+ * (a) `adb reverse tcp:<port> tcp:<port>` — multiplexes the
20
+ * device-side `127.0.0.1:<port>` over the existing ADB
21
+ * transport to the host. This is the PREFERRED path: slirp
22
+ * is famously flaky under burst-connect load and drops
23
+ * ~80% of cold-boot module-loader fetches with
24
+ * `IOException: unexpected end of stream`. The ADB tunnel
25
+ * bypasses slirp entirely and is reliable. We try this
26
+ * automatically — see `tryEnableAdbReverse`. We emit the
27
+ * IPv4 literal `127.0.0.1` instead of `localhost` because
28
+ * Android API 36+ system images periodically ship without
29
+ * a `localhost` mapping in the resolver, and
30
+ * `UnknownHostException` fires before adb-reverse can do
31
+ * its job.
32
+ *
33
+ * (b) `10.0.2.2` (Genymotion: `10.0.3.2`) — slirp's host alias.
34
+ * Used as a fallback when ADB isn't available or the user
35
+ * opted out via `NS_HMR_NO_ADB_REVERSE=1`. Works, just less
36
+ * reliable than the ADB tunnel.
37
+ *
38
+ * - Physical Android devices over USB get the same automatic
39
+ * `adb reverse` treatment as emulators. Over Wi-Fi (no ADB
40
+ * tunnel), the user must opt out of adb reverse via
41
+ * `NS_HMR_NO_ADB_REVERSE=1` and supply a routable host via
42
+ * `NS_HMR_HOST=<ip>` or `NS_HMR_PREFER_LAN_HOST=1`.
43
+ *
44
+ * Without this normalization, `bundle.mjs` ships with statically
45
+ * embedded URLs like `http://0.0.0.0:5173/ns/core/xhr` and the very
46
+ * first dynamic import during Application boot fails with
47
+ * `status=0 (network unreachable)` on Android, killing the runtime
48
+ * before any user code runs.
49
+ *
50
+ * Resolution rules (highest precedence first):
51
+ *
52
+ * 1. `process.env.NS_HMR_HOST` — always wins. CI, tunneled setups,
53
+ * and remote devices use this to point at a known-good origin.
54
+ *
55
+ * 2. A concrete non-wildcard, non-loopback `host` arg — trust the
56
+ * developer's explicit choice (`server.host: '192.168.1.42'`
57
+ * already routes from any device on the LAN).
58
+ *
59
+ * 3. `process.env.NS_HMR_PREFER_LAN_HOST` truthy AND a LAN NIC is
60
+ * detected — emit the LAN IP. Opt-in for physical-device-over-
61
+ * Wi-Fi dev. Also disables the adb-reverse path below so the
62
+ * caller actually gets LAN routing.
63
+ *
64
+ * 4. Wildcard bind (`0.0.0.0`, `::`, `true`, empty) OR Android
65
+ * loopback — emit the platform-appropriate routable address.
66
+ * For Android, we first try `adb reverse tcp:<port> tcp:<port>`
67
+ * and emit `127.0.0.1` on success (bypasses slirp NAT entirely
68
+ * and avoids Android API 36+'s missing-`localhost`-from-resolver
69
+ * bug); on failure we fall back to `10.0.2.2`. iOS/visionOS get
70
+ * `localhost` directly. iOS/visionOS loopback passes through
71
+ * unchanged.
72
+ *
73
+ * Every dev-mode emitter that bakes a URL into `bundle.mjs` or sends
74
+ * one to a device-side fetch site MUST run through this helper so the
75
+ * device receives a single canonical, reachable origin.
76
+ */
77
+ import os from 'node:os';
78
+ import { execSync as nodeExecSync } from 'node:child_process';
79
+ const WILDCARD_HOSTS = new Set(['0.0.0.0', '::', '', 'true']);
80
+ const LOOPBACK_HOSTS = new Set(['localhost', '127.0.0.1', '::1']);
81
+ const adbReverseCache = new Map();
82
+ /**
83
+ * Returns the first non-internal IPv4 address on the host machine, or
84
+ * `undefined` if no LAN NIC is up. Pure wrapper around
85
+ * `os.networkInterfaces()` so callers and tests can stub it cleanly.
86
+ */
87
+ export function guessLanHost() {
88
+ try {
89
+ const nets = os.networkInterfaces();
90
+ for (const name of Object.keys(nets)) {
91
+ const addrs = nets[name] || [];
92
+ for (const addr of addrs) {
93
+ if (!addr)
94
+ continue;
95
+ // Node typings vary across versions; keep checks defensive.
96
+ const family = addr.family;
97
+ const internal = !!addr.internal;
98
+ const address = String(addr.address || '');
99
+ if (internal)
100
+ continue;
101
+ if (family !== 'IPv4' && family !== 4)
102
+ continue;
103
+ if (address && address !== '127.0.0.1')
104
+ return address;
105
+ }
106
+ }
107
+ }
108
+ catch { }
109
+ return undefined;
110
+ }
111
+ function normalizeHostInput(host) {
112
+ if (host === true)
113
+ return '0.0.0.0';
114
+ if (host === false || host == null)
115
+ return '';
116
+ const s = String(host).trim();
117
+ return s;
118
+ }
119
+ /**
120
+ * Whether the given host string is a wildcard "all interfaces" bind
121
+ * address rather than a routable hostname. `host` may be the literal
122
+ * string from a Vite config (`'0.0.0.0'`), an empty string, or `'true'`
123
+ * (some older Vite/CLI surfaces stringify the boolean).
124
+ */
125
+ export function isWildcardHost(host) {
126
+ return WILDCARD_HOSTS.has(host);
127
+ }
128
+ /**
129
+ * Whether the given host string is loopback. On Android the loopback
130
+ * address is the device itself, NOT the development host — so callers
131
+ * must remap it for Android consumers.
132
+ */
133
+ export function isLoopbackHost(host) {
134
+ return LOOPBACK_HOSTS.has(host);
135
+ }
136
+ function isTruthyEnvFlag(value) {
137
+ if (typeof value !== 'string')
138
+ return false;
139
+ const v = value.trim().toLowerCase();
140
+ if (!v)
141
+ return false;
142
+ return v !== '0' && v !== 'false' && v !== 'off' && v !== 'no';
143
+ }
144
+ /**
145
+ * Read-only view of the current `adb reverse` status for a given
146
+ * dev-server port. Returns `undefined` if `tryEnableAdbReverse` has
147
+ * never been called for that port.
148
+ */
149
+ export function getAdbReverseStatus(port) {
150
+ return adbReverseCache.get(port);
151
+ }
152
+ /**
153
+ * Test hook — clears the per-port cache so unit tests can exercise
154
+ * fresh "first call" behavior without leaking state between cases.
155
+ * NOT exported from the package barrel; spec files import via the
156
+ * file path directly.
157
+ */
158
+ export function __resetAdbReverseCacheForTests() {
159
+ adbReverseCache.clear();
160
+ }
161
+ /**
162
+ * Try to set up `adb reverse tcp:<port> tcp:<port>` for every
163
+ * connected Android device / emulator so device-side `localhost:port`
164
+ * routes through the ADB transport to the host's dev server.
165
+ *
166
+ * Why this beats `10.0.2.2`. The Android emulator's stock NAT is
167
+ * QEMU's `slirp` user-mode network stack, which is well-known to
168
+ * drop bursts of concurrent TCP setups to the host. In practice this
169
+ * surfaces as ~80% of synchronous module-loader fetches failing with
170
+ * `IOException: unexpected end of stream` — the connection establishes,
171
+ * the request goes out, and then slirp drops the response before
172
+ * okhttp can read the status line. The failures are random per-module
173
+ * across runs, retries help but don't eliminate them, and the symptom
174
+ * masquerades as a server-side bug.
175
+ *
176
+ * `adb reverse` bypasses the emulator NIC entirely — the device-side
177
+ * connection is multiplexed over the existing ADB USB / TCP channel
178
+ * to the host. It's the same mechanism React Native, Expo, and
179
+ * Flutter use for Android dev, and it works for both emulators and
180
+ * USB-connected physical devices.
181
+ *
182
+ * Caching. The result is cached per-port so repeat callers don't
183
+ * fork extra subprocesses. The cache is keyed on port (not platform)
184
+ * because the wildcard "Android-ness" of the call is already implied
185
+ * by the caller — only Android consumers hit this path.
186
+ *
187
+ * Failure modes (all surface as a cached `succeeded: false`):
188
+ * - `NS_HMR_NO_ADB_REVERSE=1` — explicit opt-out for unusual
189
+ * setups (e.g. Wi-Fi-connected device with no ADB tunnel, CI
190
+ * containers without ADB installed).
191
+ * - `adb` not on PATH — common in fresh dev machines that have
192
+ * the Android SDK installed but no shell init.
193
+ * - No connected devices — user started Vite before booting the
194
+ * emulator. We do NOT keep retrying after the first failure
195
+ * because the URL is baked into bundle.mjs at config-load time
196
+ * and there's no point in flipping it later.
197
+ * - "more than one device" — fatal for unqualified `adb reverse`,
198
+ * so we enumerate via `adb devices` and apply the reverse
199
+ * individually with `-s <serial>`. As long as at least one
200
+ * device gets the mapping we treat the whole call as a success.
201
+ */
202
+ export function tryEnableAdbReverse(opts) {
203
+ const cached = adbReverseCache.get(opts.port);
204
+ if (cached)
205
+ return cached;
206
+ const env = opts.env || process.env;
207
+ // Test-safety guard. When we're running inside vitest / jest /
208
+ // any other test runner AND the caller did NOT inject an explicit
209
+ // exec stub, refuse to spawn a real `adb` subprocess. Spec files
210
+ // that pass `env: {}` aren't expecting us to mutate the dev's real
211
+ // device state (set up an actual `adb reverse` mapping on
212
+ // `port:5173` they didn't ask for) just by exercising the host
213
+ // resolver. We DO NOT cache this skip — a subsequent call with a
214
+ // real `exec` stub from the same suite should still run.
215
+ const ambient = process.env;
216
+ const inTestRunner = ambient.VITEST === 'true' || ambient.NODE_ENV === 'test' || typeof ambient.JEST_WORKER_ID === 'string';
217
+ if (!opts.exec && inTestRunner) {
218
+ return { attempted: false, succeeded: false, devices: [], error: 'test environment (auto-skip)' };
219
+ }
220
+ const exec = opts.exec || ((cmd, o) => nodeExecSync(cmd, { timeout: o.timeout, stdio: ['ignore', 'pipe', 'pipe'] }).toString());
221
+ if (isTruthyEnvFlag(env.NS_HMR_NO_ADB_REVERSE)) {
222
+ const status = { attempted: false, succeeded: false, devices: [], error: 'opt-out via NS_HMR_NO_ADB_REVERSE' };
223
+ adbReverseCache.set(opts.port, status);
224
+ return status;
225
+ }
226
+ // First enumerate. We need this to (a) bail cleanly when there's
227
+ // no device at all and (b) handle the multi-device case which
228
+ // makes unqualified `adb reverse` ambiguous and refuse the call.
229
+ let devices = [];
230
+ try {
231
+ const raw = exec('adb devices', { timeout: 5000 });
232
+ devices = parseAdbDevicesOutput(raw);
233
+ }
234
+ catch (err) {
235
+ const status = {
236
+ attempted: true,
237
+ succeeded: false,
238
+ devices: [],
239
+ error: `adb not available: ${String(err?.message || err)}`,
240
+ };
241
+ adbReverseCache.set(opts.port, status);
242
+ return status;
243
+ }
244
+ if (devices.length === 0) {
245
+ const status = {
246
+ attempted: true,
247
+ succeeded: false,
248
+ devices: [],
249
+ error: 'no connected Android devices',
250
+ };
251
+ adbReverseCache.set(opts.port, status);
252
+ try {
253
+ console.warn(`[NativeScript] adb reverse skipped — no Android devices connected yet. Bundle URLs will use 10.0.2.2 (emulator NAT). For best reliability boot the emulator BEFORE \`ns run android\` so adb reverse can wire 127.0.0.1:${opts.port} through ADB instead.`);
254
+ }
255
+ catch { }
256
+ return status;
257
+ }
258
+ // Apply per-device so multi-device setups don't hit the "more
259
+ // than one device" failure. We tolerate per-device failures so
260
+ // long as at least one mapping landed — the user's target device
261
+ // is almost always the first connected one.
262
+ const successes = [];
263
+ const errors = [];
264
+ for (const serial of devices) {
265
+ try {
266
+ exec(`adb -s ${serial} reverse tcp:${opts.port} tcp:${opts.port}`, { timeout: 5000 });
267
+ successes.push(serial);
268
+ }
269
+ catch (err) {
270
+ errors.push(`${serial}: ${String(err?.message || err)}`);
271
+ }
272
+ }
273
+ const status = {
274
+ attempted: true,
275
+ succeeded: successes.length > 0,
276
+ devices: successes,
277
+ error: successes.length === 0 ? errors.join('; ') || 'all devices failed' : undefined,
278
+ };
279
+ adbReverseCache.set(opts.port, status);
280
+ // One-line user-facing receipt so the dev knows why bundle.mjs
281
+ // suddenly switched from `10.0.2.2` to `localhost`. We only log
282
+ // outside test runners (covered above) so spec output stays
283
+ // clean.
284
+ try {
285
+ if (status.succeeded) {
286
+ console.log(`[NativeScript] adb reverse tcp:${opts.port} tcp:${opts.port} → ${successes.join(', ')} (Android device-side 127.0.0.1:${opts.port} now tunnels to host — bypasses emulator NAT)`);
287
+ }
288
+ else if (errors.length > 0) {
289
+ console.warn(`[NativeScript] adb reverse failed for tcp:${opts.port} — falling back to 10.0.2.2 (slirp NAT). Module fetches may hit IOException: unexpected end of stream under load. Reasons: ${status.error}`);
290
+ }
291
+ }
292
+ catch {
293
+ // Logging is best-effort. We never want a console misbehavior
294
+ // to take down dev-server boot.
295
+ }
296
+ return status;
297
+ }
298
+ /**
299
+ * Parse the line-oriented output of `adb devices`:
300
+ *
301
+ * List of devices attached
302
+ * emulator-5554\tdevice
303
+ * ABCDEF12\tdevice
304
+ * somemodel\tunauthorized
305
+ *
306
+ * We keep only entries whose second column is exactly `device`
307
+ * (skip `unauthorized`, `offline`, `recovery`, etc. — none of those
308
+ * can accept an `adb reverse` command).
309
+ */
310
+ function parseAdbDevicesOutput(raw) {
311
+ const out = [];
312
+ const lines = String(raw || '').split(/\r?\n/);
313
+ for (const line of lines) {
314
+ const trimmed = line.trim();
315
+ if (!trimmed)
316
+ continue;
317
+ if (trimmed.startsWith('List of devices'))
318
+ continue;
319
+ if (trimmed.startsWith('*'))
320
+ continue; // daemon startup chatter
321
+ const parts = trimmed.split(/\s+/);
322
+ if (parts.length < 2)
323
+ continue;
324
+ if (parts[1] !== 'device')
325
+ continue;
326
+ out.push(parts[0]);
327
+ }
328
+ return out;
329
+ }
330
+ /**
331
+ * Pick the host string a device or simulator can actually reach.
332
+ *
333
+ * See the file-level comment for the full resolution-precedence
334
+ * narrative. Returns the chosen host alongside a `source` tag so
335
+ * callers (and logs) can explain why a given URL was emitted.
336
+ */
337
+ export function resolveDeviceReachableHost(opts) {
338
+ const env = opts.env || process.env;
339
+ const lanHostResolver = opts.lanHostResolver || guessLanHost;
340
+ // 1. Explicit env override always wins.
341
+ const envOverride = env.NS_HMR_HOST;
342
+ if (typeof envOverride === 'string' && envOverride.length > 0) {
343
+ return { host: envOverride, source: 'env' };
344
+ }
345
+ const raw = normalizeHostInput(opts.host);
346
+ // 2. Explicit non-wildcard, non-loopback host — trust the developer.
347
+ // Loopback addresses on Android still need remapping (see step 4),
348
+ // so we only short-circuit here for the truly routable case.
349
+ if (raw && !isWildcardHost(raw) && !isLoopbackHost(raw)) {
350
+ return { host: raw, source: 'explicit' };
351
+ }
352
+ // 3. Physical-device opt-in. The Android emulator default below
353
+ // (`10.0.2.2`) doesn't reach a real device on the LAN, so users
354
+ // running on hardware set `NS_HMR_PREFER_LAN_HOST=1` to pick up
355
+ // the host's LAN IP at build time. iOS/visionOS rarely needs
356
+ // this (the simulator stays on the loopback path) but the same
357
+ // opt-in works on those platforms for parity.
358
+ //
359
+ // `NS_HMR_PREFER_LAN_HOST` ALSO suppresses the adb-reverse path
360
+ // below — when the user has explicitly asked for LAN routing
361
+ // we don't want to silently bypass them with an ADB tunnel.
362
+ if (isTruthyEnvFlag(env.NS_HMR_PREFER_LAN_HOST)) {
363
+ const lan = lanHostResolver();
364
+ if (lan) {
365
+ return { host: lan, source: 'lan' };
366
+ }
367
+ // Fall through to the platform default when no LAN NIC was
368
+ // detected (e.g. running in a CI container) — better to fail
369
+ // at the always-works fallback than emit nothing.
370
+ }
371
+ // 4. Wildcard bind — fall back to the platform-appropriate routable
372
+ // address. We DELIBERATELY do NOT auto-pick a LAN IP here on
373
+ // Android: standard emulator NAT drops packets destined for the
374
+ // host's LAN IP, even when those IPs resolve fine from the
375
+ // host's own browser. `10.0.2.2` is the next-best fallback when
376
+ // adb reverse isn't available; otherwise the emulator slirp NAT
377
+ // drops a meaningful fraction of TCP setups under burst load and
378
+ // cold-boot hits `IOException: unexpected end of stream` for
379
+ // random modules each run.
380
+ if (isWildcardHost(raw)) {
381
+ return platformDefault(opts);
382
+ }
383
+ // 5. Loopback. iOS / visionOS keeps `localhost` (simulator network
384
+ // stack reaches the host); Android remaps to `10.0.2.2` /
385
+ // `localhost`-via-adb-reverse (loopback on Android refers to
386
+ // the EMULATOR ITSELF, not the host).
387
+ if (isLoopbackHost(raw)) {
388
+ if (opts.platform === 'android') {
389
+ return platformDefault(opts);
390
+ }
391
+ return { host: raw, source: 'explicit' };
392
+ }
393
+ // 6. Empty / unrecognised — fall back to platform default.
394
+ return platformDefault(opts);
395
+ }
396
+ function platformDefault(opts) {
397
+ if (opts.platform === 'android') {
398
+ // Try to bring up an `adb reverse` tunnel first. When that
399
+ // succeeds, `localhost` on the device routes through the
400
+ // existing ADB channel to the host's dev server — which
401
+ // sidesteps the QEMU slirp NAT entirely (see
402
+ // `tryEnableAdbReverse` for why that matters). When adb is
403
+ // unavailable, the device is disconnected, or the user opted
404
+ // out via `NS_HMR_NO_ADB_REVERSE`, we fall through to
405
+ // `10.0.2.2` so the cold boot still has *some* working path.
406
+ //
407
+ // We only attempt adb reverse when we know the port — without
408
+ // it we can't issue a valid `adb reverse` command. Older
409
+ // fixtures that call `resolveDeviceReachableHost` without a
410
+ // port still get the legacy `10.0.2.2` answer.
411
+ if (typeof opts.port === 'number' && Number.isFinite(opts.port)) {
412
+ const status = tryEnableAdbReverse({ port: opts.port, env: opts.env, exec: opts.adbExec });
413
+ if (status.succeeded) {
414
+ // Emit `127.0.0.1` (IPv4 literal) instead of `localhost`.
415
+ // Android API 36+ system images periodically ship without
416
+ // a `localhost` entry in the resolver's `/etc/hosts`, so
417
+ // `getaddrinfo("localhost")` throws
418
+ // `UnknownHostException: No address associated with
419
+ // hostname` BEFORE the TCP connect even starts. The IPv4
420
+ // literal bypasses DNS entirely and ADB reverse intercepts
421
+ // loopback traffic regardless of how it's spelled. This is
422
+ // the same workaround React Native, Expo, and Chrome
423
+ // DevTools port forwarding all use.
424
+ return { host: '127.0.0.1', source: 'adb-reverse' };
425
+ }
426
+ }
427
+ // Stock Android emulator host alias. Physical devices that
428
+ // can't use `adb reverse` need NS_HMR_HOST=<LAN IP> or
429
+ // NS_HMR_PREFER_LAN_HOST=1.
430
+ return { host: '10.0.2.2', source: 'platform-default' };
431
+ }
432
+ return { host: 'localhost', source: 'platform-default' };
433
+ }
434
+ /**
435
+ * Convenience wrapper that returns the full `protocol://host:port`
436
+ * origin string alongside the host-resolution metadata. The vast
437
+ * majority of callers want the assembled origin to splice into a
438
+ * `/ns/...` URL, so this saves them the trivial template string.
439
+ *
440
+ * When the resolved host already includes a `:port` suffix (a common
441
+ * shape for `NS_HMR_HOST=tunnel.example.com:5173`), we split it back
442
+ * out so the assembled origin never doubles up the port.
443
+ */
444
+ export function resolveDeviceReachableOrigin(opts) {
445
+ const protocol = opts.protocol === 'https' ? 'https' : 'http';
446
+ const requestedPort = typeof opts.port === 'number' && Number.isFinite(opts.port) ? opts.port : 5173;
447
+ // Forward the resolved port to the host resolver so the Android
448
+ // `platformDefault` step can attempt `adb reverse` for the same
449
+ // port the dev server is actually listening on.
450
+ const { host: rawHost, source } = resolveDeviceReachableHost({ ...opts, port: requestedPort });
451
+ const { host, port } = splitHostAndPort(rawHost, requestedPort);
452
+ return {
453
+ host,
454
+ source,
455
+ protocol,
456
+ port,
457
+ origin: `${protocol}://${host}:${port}`,
458
+ };
459
+ }
460
+ function splitHostAndPort(rawHost, fallbackPort) {
461
+ // Bracketed IPv6 — `[::1]:5173` — keep the brackets on the host so
462
+ // callers can splice it straight into a URL without re-escaping.
463
+ if (rawHost.startsWith('[')) {
464
+ const closing = rawHost.indexOf(']');
465
+ if (closing !== -1) {
466
+ const bracketed = rawHost.slice(0, closing + 1);
467
+ const rest = rawHost.slice(closing + 1);
468
+ if (rest.startsWith(':')) {
469
+ const parsed = Number(rest.slice(1));
470
+ if (Number.isFinite(parsed) && parsed > 0) {
471
+ return { host: bracketed, port: parsed };
472
+ }
473
+ }
474
+ return { host: bracketed, port: fallbackPort };
475
+ }
476
+ }
477
+ // `host:port` for IPv4 / DNS names. We deliberately do NOT split on
478
+ // the first colon when more than one is present (that would
479
+ // misinterpret an unbracketed IPv6 literal), and we leave the host
480
+ // alone if the trailing segment isn't a positive integer.
481
+ const colonCount = (rawHost.match(/:/g) || []).length;
482
+ if (colonCount === 1) {
483
+ const idx = rawHost.indexOf(':');
484
+ const candidatePort = Number(rawHost.slice(idx + 1));
485
+ if (Number.isFinite(candidatePort) && candidatePort > 0) {
486
+ return { host: rawHost.slice(0, idx), port: candidatePort };
487
+ }
488
+ }
489
+ return { host: rawHost, port: fallbackPort };
490
+ }
491
+ //# sourceMappingURL=dev-host.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"dev-host.js","sourceRoot":"","sources":["../../../../packages/vite/helpers/dev-host.ts"],"names":[],"mappings":"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"}
@@ -1,3 +1,50 @@
1
+ /**
2
+ * Opt-out flag for the HMR-applying progress overlay.
3
+ *
4
+ * Default: enabled. Set `NS_VITE_PROGRESS_OVERLAY=0` (or `false`) in
5
+ * the environment to suppress the overlay if a developer finds it
6
+ * distracting. We accept the same falsy spellings webpack-era tooling
7
+ * used (`0`, `false`, `off`, `no`) and treat anything else as
8
+ * enabled-by-default; this avoids surprising users who pass quoted
9
+ * truthy strings ("1", "true").
10
+ */
11
+ export declare function isHmrProgressOverlayEnabled(env?: NodeJS.ProcessEnv): boolean;
12
+ /**
13
+ * Kickstart-eligibility threshold for the parallel HMR prefetch
14
+ * (`__nsKickstartHmrPrefetch`).
15
+ *
16
+ * Why a threshold exists. The kickstart fetches the SERVER-computed
17
+ * inverse-dep closure (`evictPaths`) in parallel before V8 starts
18
+ * its module walk, which is a clean win when the closure size is
19
+ * close to what V8 will actually re-evaluate on the next import. For
20
+ * a typical Angular component edit (`*.component.ts` / `.html`) the
21
+ * closure contains ~5–30 modules and almost all of them sit on the
22
+ * live forward path from the entry, so fan-out beats sequential
23
+ * `HttpFetchText` calls by 3–5×.
24
+ *
25
+ * The picture inverts for `.ts` files with deep inverse-dep fan-in
26
+ * (constants files, design-system enums, shared utilities). The
27
+ * server faithfully reports the entire inverse closure (often
28
+ * 100–300 importers), but V8's forward walk on re-import only
29
+ * re-evaluates the ~20–30 modules that sit on the currently-rendered
30
+ * route's path. The kickstart's parallel wave then over-fetches the
31
+ * other ~70–270 importers — and Vite's single-threaded transform
32
+ * pipeline cannot keep up with 16-way concurrent demand, so each
33
+ * fetch's tail latency balloons. Net result: a "should-be-200ms"
34
+ * HMR cycle becomes 6+ seconds.
35
+ *
36
+ * The threshold short-circuits the kickstart when `evictPaths.length`
37
+ * exceeds the configured cap. The HMR cycle still completes
38
+ * correctly — V8 falls back to per-module synchronous fetches.
39
+ *
40
+ * Default: 32. Empirically chosen so component-shaped closures
41
+ * (typically 5–30) keep the kickstart speed-up while wide-fan-in
42
+ * leaf edits (typically 100+) skip it. Override with
43
+ * `NS_VITE_KICKSTART_MAX_URLS=N` (any non-negative integer) — `0`
44
+ * disables the kickstart entirely; `Infinity` removes the cap.
45
+ */
46
+ export declare const HMR_KICKSTART_DEFAULT_MAX_URLS = 32;
47
+ export declare function resolveHmrKickstartMaxUrls(env?: NodeJS.ProcessEnv): number;
1
48
  export declare function getGlobalDefines(opts: {
2
49
  platform: string;
3
50
  targetMode: string;
@@ -9,11 +56,15 @@ export declare function getGlobalDefines(opts: {
9
56
  __IOS__: string;
10
57
  __VISIONOS__: string;
11
58
  __APPLE__: string;
59
+ 'global.isAndroid': string;
60
+ 'global.isIOS': string;
12
61
  __DEV__: string;
13
62
  __COMMONJS__: boolean;
14
63
  __NS_WEBPACK__: boolean;
15
64
  __NS_ENV_VERBOSE__: string;
16
65
  __NS_TARGET_FLAVOR__: string;
66
+ __NS_HMR_PROGRESS_OVERLAY_ENABLED__: string;
67
+ __NS_HMR_KICKSTART_MAX_URLS__: string;
17
68
  __CSS_PARSER__: string;
18
69
  __UI_USE_XML_PARSER__: boolean;
19
70
  __UI_USE_EXTERNAL_RENDERER__: boolean;
@@ -1,6 +1,71 @@
1
1
  import { getProjectAppPath, getProjectAppVirtualPath } from './utils.js';
2
2
  const APP_ROOT_DIR = getProjectAppPath();
3
3
  const APP_ROOT_VIRTUAL = getProjectAppVirtualPath();
4
+ /**
5
+ * Opt-out flag for the HMR-applying progress overlay.
6
+ *
7
+ * Default: enabled. Set `NS_VITE_PROGRESS_OVERLAY=0` (or `false`) in
8
+ * the environment to suppress the overlay if a developer finds it
9
+ * distracting. We accept the same falsy spellings webpack-era tooling
10
+ * used (`0`, `false`, `off`, `no`) and treat anything else as
11
+ * enabled-by-default; this avoids surprising users who pass quoted
12
+ * truthy strings ("1", "true").
13
+ */
14
+ export function isHmrProgressOverlayEnabled(env = process.env) {
15
+ const raw = (env.NS_VITE_PROGRESS_OVERLAY ?? '').toString().trim().toLowerCase();
16
+ if (!raw)
17
+ return true;
18
+ return !['0', 'false', 'off', 'no'].includes(raw);
19
+ }
20
+ /**
21
+ * Kickstart-eligibility threshold for the parallel HMR prefetch
22
+ * (`__nsKickstartHmrPrefetch`).
23
+ *
24
+ * Why a threshold exists. The kickstart fetches the SERVER-computed
25
+ * inverse-dep closure (`evictPaths`) in parallel before V8 starts
26
+ * its module walk, which is a clean win when the closure size is
27
+ * close to what V8 will actually re-evaluate on the next import. For
28
+ * a typical Angular component edit (`*.component.ts` / `.html`) the
29
+ * closure contains ~5–30 modules and almost all of them sit on the
30
+ * live forward path from the entry, so fan-out beats sequential
31
+ * `HttpFetchText` calls by 3–5×.
32
+ *
33
+ * The picture inverts for `.ts` files with deep inverse-dep fan-in
34
+ * (constants files, design-system enums, shared utilities). The
35
+ * server faithfully reports the entire inverse closure (often
36
+ * 100–300 importers), but V8's forward walk on re-import only
37
+ * re-evaluates the ~20–30 modules that sit on the currently-rendered
38
+ * route's path. The kickstart's parallel wave then over-fetches the
39
+ * other ~70–270 importers — and Vite's single-threaded transform
40
+ * pipeline cannot keep up with 16-way concurrent demand, so each
41
+ * fetch's tail latency balloons. Net result: a "should-be-200ms"
42
+ * HMR cycle becomes 6+ seconds.
43
+ *
44
+ * The threshold short-circuits the kickstart when `evictPaths.length`
45
+ * exceeds the configured cap. The HMR cycle still completes
46
+ * correctly — V8 falls back to per-module synchronous fetches.
47
+ *
48
+ * Default: 32. Empirically chosen so component-shaped closures
49
+ * (typically 5–30) keep the kickstart speed-up while wide-fan-in
50
+ * leaf edits (typically 100+) skip it. Override with
51
+ * `NS_VITE_KICKSTART_MAX_URLS=N` (any non-negative integer) — `0`
52
+ * disables the kickstart entirely; `Infinity` removes the cap.
53
+ */
54
+ export const HMR_KICKSTART_DEFAULT_MAX_URLS = 32;
55
+ export function resolveHmrKickstartMaxUrls(env = process.env) {
56
+ const raw = (env.NS_VITE_KICKSTART_MAX_URLS ?? '').toString().trim();
57
+ if (!raw)
58
+ return HMR_KICKSTART_DEFAULT_MAX_URLS;
59
+ const lower = raw.toLowerCase();
60
+ if (lower === 'infinity' || lower === 'unlimited' || lower === 'none') {
61
+ return Number.POSITIVE_INFINITY;
62
+ }
63
+ const parsed = Number(raw);
64
+ if (!Number.isFinite(parsed) || parsed < 0) {
65
+ return HMR_KICKSTART_DEFAULT_MAX_URLS;
66
+ }
67
+ return Math.floor(parsed);
68
+ }
4
69
  export function getGlobalDefines(opts) {
5
70
  return {
6
71
  // Define platform flags for runtime checks
@@ -8,11 +73,23 @@ export function getGlobalDefines(opts) {
8
73
  __IOS__: JSON.stringify(opts.platform === 'ios'),
9
74
  __VISIONOS__: JSON.stringify(opts.platform === 'visionos'),
10
75
  __APPLE__: JSON.stringify(opts.platform === 'ios' || opts.platform === 'visionos'),
76
+ 'global.isAndroid': JSON.stringify(opts.platform === 'android'),
77
+ 'global.isIOS': JSON.stringify(opts.platform === 'ios' || opts.platform === 'visionos'),
11
78
  __DEV__: JSON.stringify(opts.targetMode === 'development'),
12
79
  __COMMONJS__: false,
13
80
  __NS_WEBPACK__: false,
14
81
  __NS_ENV_VERBOSE__: JSON.stringify(opts.verbose),
15
82
  __NS_TARGET_FLAVOR__: JSON.stringify(opts.flavor),
83
+ // whether to show the HMR in-progress overlay.
84
+ __NS_HMR_PROGRESS_OVERLAY_ENABLED__: JSON.stringify(isHmrProgressOverlayEnabled()),
85
+ // Eviction-set size cap for the parallel HMR kickstart.
86
+ // `JSON.stringify(Number.POSITIVE_INFINITY)` is the string
87
+ // "null", so we serialize Infinity ourselves to keep the
88
+ // build-time literal readable in source maps.
89
+ __NS_HMR_KICKSTART_MAX_URLS__: (() => {
90
+ const n = resolveHmrKickstartMaxUrls();
91
+ return Number.isFinite(n) ? String(n) : 'Infinity';
92
+ })(),
16
93
  __CSS_PARSER__: JSON.stringify('css-tree'),
17
94
  __UI_USE_XML_PARSER__: true,
18
95
  __UI_USE_EXTERNAL_RENDERER__: false,