@nativescript/vite 8.0.0-alpha.3 → 8.0.0-alpha.31

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 (356) hide show
  1. package/README.md +51 -11
  2. package/configuration/angular.d.ts +34 -1
  3. package/configuration/angular.js +373 -163
  4. package/configuration/angular.js.map +1 -1
  5. package/configuration/base.js +184 -14
  6. package/configuration/base.js.map +1 -1
  7. package/configuration/javascript.js +5 -72
  8. package/configuration/javascript.js.map +1 -1
  9. package/configuration/solid.js +27 -1
  10. package/configuration/solid.js.map +1 -1
  11. package/configuration/typescript.js +5 -75
  12. package/configuration/typescript.js.map +1 -1
  13. package/helpers/app-components.d.ts +2 -1
  14. package/helpers/app-components.js.map +1 -1
  15. package/helpers/app-css-state.d.ts +8 -0
  16. package/helpers/app-css-state.js +8 -0
  17. package/helpers/app-css-state.js.map +1 -0
  18. package/helpers/bundler-context.d.ts +11 -0
  19. package/helpers/bundler-context.js +71 -0
  20. package/helpers/bundler-context.js.map +1 -0
  21. package/helpers/config-as-json.js +10 -0
  22. package/helpers/config-as-json.js.map +1 -1
  23. package/helpers/dev-host.d.ts +341 -0
  24. package/helpers/dev-host.js +617 -0
  25. package/helpers/dev-host.js.map +1 -0
  26. package/helpers/esbuild-platform-resolver.js +4 -1
  27. package/helpers/esbuild-platform-resolver.js.map +1 -1
  28. package/helpers/global-defines.d.ts +51 -0
  29. package/helpers/global-defines.js +77 -0
  30. package/helpers/global-defines.js.map +1 -1
  31. package/helpers/hmr-scope.d.ts +26 -0
  32. package/helpers/hmr-scope.js +67 -0
  33. package/helpers/hmr-scope.js.map +1 -0
  34. package/helpers/init.js +0 -18
  35. package/helpers/init.js.map +1 -1
  36. package/helpers/logging.d.ts +1 -0
  37. package/helpers/logging.js +63 -3
  38. package/helpers/logging.js.map +1 -1
  39. package/helpers/main-entry.d.ts +2 -1
  40. package/helpers/main-entry.js +430 -47
  41. package/helpers/main-entry.js.map +1 -1
  42. package/helpers/nativeclass-esbuild-plugin.d.ts +2 -1
  43. package/helpers/nativeclass-esbuild-plugin.js.map +1 -1
  44. package/helpers/nativeclass-transform.js.map +1 -1
  45. package/helpers/nativeclass-transformer-plugin.d.ts +9 -2
  46. package/helpers/nativeclass-transformer-plugin.js +157 -14
  47. package/helpers/nativeclass-transformer-plugin.js.map +1 -1
  48. package/helpers/nativescript-package-resolver.js +8 -3
  49. package/helpers/nativescript-package-resolver.js.map +1 -1
  50. package/helpers/normalize-id.d.ts +42 -0
  51. package/helpers/normalize-id.js +60 -0
  52. package/helpers/normalize-id.js.map +1 -0
  53. package/helpers/ns-core-url.d.ts +88 -0
  54. package/helpers/ns-core-url.js +191 -0
  55. package/helpers/ns-core-url.js.map +1 -0
  56. package/helpers/package-platform-aliases.js +4 -3
  57. package/helpers/package-platform-aliases.js.map +1 -1
  58. package/helpers/platform-types.d.ts +2 -0
  59. package/helpers/platform-types.js +2 -0
  60. package/helpers/platform-types.js.map +1 -0
  61. package/helpers/project.d.ts +35 -0
  62. package/helpers/project.js +120 -2
  63. package/helpers/project.js.map +1 -1
  64. package/helpers/resolver.js +17 -2
  65. package/helpers/resolver.js.map +1 -1
  66. package/helpers/ts-config-paths.d.ts +14 -0
  67. package/helpers/ts-config-paths.js +89 -8
  68. package/helpers/ts-config-paths.js.map +1 -1
  69. package/helpers/typescript-check.d.ts +2 -1
  70. package/helpers/typescript-check.js.map +1 -1
  71. package/helpers/workers.d.ts +20 -19
  72. package/helpers/workers.js +624 -4
  73. package/helpers/workers.js.map +1 -1
  74. package/hmr/client/css-handler.d.ts +1 -0
  75. package/hmr/client/css-handler.js +33 -20
  76. package/hmr/client/css-handler.js.map +1 -1
  77. package/hmr/client/css-update-overlay.d.ts +18 -0
  78. package/hmr/client/css-update-overlay.js +27 -0
  79. package/hmr/client/css-update-overlay.js.map +1 -0
  80. package/hmr/client/framework-client-strategy.d.ts +73 -0
  81. package/hmr/client/framework-client-strategy.js +19 -0
  82. package/hmr/client/framework-client-strategy.js.map +1 -0
  83. package/hmr/client/hmr-pending-overlay.d.ts +27 -0
  84. package/hmr/client/hmr-pending-overlay.js +50 -0
  85. package/hmr/client/hmr-pending-overlay.js.map +1 -0
  86. package/hmr/client/index.js +459 -164
  87. package/hmr/client/index.js.map +1 -1
  88. package/hmr/client/utils.d.ts +6 -1
  89. package/hmr/client/utils.js +184 -8
  90. package/hmr/client/utils.js.map +1 -1
  91. package/hmr/entry-runtime.d.ts +2 -1
  92. package/hmr/entry-runtime.js +252 -65
  93. package/hmr/entry-runtime.js.map +1 -1
  94. package/hmr/frameworks/angular/build/angular-linker.d.ts +12 -0
  95. package/hmr/frameworks/angular/build/angular-linker.js +109 -0
  96. package/hmr/frameworks/angular/build/angular-linker.js.map +1 -0
  97. package/hmr/frameworks/angular/build/inject-component-hmr-registration.d.ts +112 -0
  98. package/hmr/frameworks/angular/build/inject-component-hmr-registration.js +291 -0
  99. package/hmr/frameworks/angular/build/inject-component-hmr-registration.js.map +1 -0
  100. package/hmr/frameworks/angular/build/inject-hmr-vite-ignore.d.ts +75 -0
  101. package/hmr/frameworks/angular/build/inject-hmr-vite-ignore.js +221 -0
  102. package/hmr/frameworks/angular/build/inject-hmr-vite-ignore.js.map +1 -0
  103. package/{helpers/angular → hmr/frameworks/angular/build}/inline-decorator-component-templates.js +1 -170
  104. package/hmr/frameworks/angular/build/inline-decorator-component-templates.js.map +1 -0
  105. package/hmr/frameworks/angular/build/js-lexer.d.ts +4 -0
  106. package/{helpers/angular/synthesize-decorator-ctor-parameters.js → hmr/frameworks/angular/build/js-lexer.js} +22 -96
  107. package/hmr/frameworks/angular/build/js-lexer.js.map +1 -0
  108. package/hmr/frameworks/angular/build/shared-linker.d.ts +39 -0
  109. package/hmr/frameworks/angular/build/shared-linker.js +128 -0
  110. package/hmr/frameworks/angular/build/shared-linker.js.map +1 -0
  111. package/hmr/frameworks/angular/build/synthesize-decorator-ctor-parameters.js +88 -0
  112. package/hmr/frameworks/angular/build/synthesize-decorator-ctor-parameters.js.map +1 -0
  113. package/{helpers/angular → hmr/frameworks/angular/build}/synthesize-injectable-factories.js +1 -174
  114. package/hmr/frameworks/angular/build/synthesize-injectable-factories.js.map +1 -0
  115. package/{helpers/angular → hmr/frameworks/angular/build}/util.d.ts +1 -0
  116. package/hmr/frameworks/angular/build/util.js +155 -0
  117. package/hmr/frameworks/angular/build/util.js.map +1 -0
  118. package/hmr/frameworks/angular/client/index.d.ts +1 -0
  119. package/hmr/frameworks/angular/client/index.js +778 -20
  120. package/hmr/frameworks/angular/client/index.js.map +1 -1
  121. package/hmr/frameworks/angular/client/strategy.d.ts +9 -0
  122. package/hmr/frameworks/angular/client/strategy.js +19 -0
  123. package/hmr/frameworks/angular/client/strategy.js.map +1 -0
  124. package/hmr/frameworks/angular/server/angular-root-component.d.ts +79 -0
  125. package/hmr/frameworks/angular/server/angular-root-component.js +149 -0
  126. package/hmr/frameworks/angular/server/angular-root-component.js.map +1 -0
  127. package/hmr/frameworks/angular/server/linker.js +1 -4
  128. package/hmr/frameworks/angular/server/linker.js.map +1 -1
  129. package/hmr/frameworks/angular/server/strategy.js +448 -12
  130. package/hmr/frameworks/angular/server/strategy.js.map +1 -1
  131. package/hmr/{server → frameworks/angular/server}/websocket-angular-entry.js +2 -2
  132. package/hmr/frameworks/angular/server/websocket-angular-entry.js.map +1 -0
  133. package/hmr/{server → frameworks/angular/server}/websocket-angular-hot-update.d.ts +17 -11
  134. package/hmr/frameworks/angular/server/websocket-angular-hot-update.js +336 -0
  135. package/hmr/frameworks/angular/server/websocket-angular-hot-update.js.map +1 -0
  136. package/hmr/frameworks/solid/build/solid-jsx-deps.d.ts +15 -0
  137. package/hmr/frameworks/solid/build/solid-jsx-deps.js +178 -0
  138. package/hmr/frameworks/solid/build/solid-jsx-deps.js.map +1 -0
  139. package/hmr/frameworks/solid/server/strategy.js +360 -16
  140. package/hmr/frameworks/solid/server/strategy.js.map +1 -1
  141. package/hmr/frameworks/typescript/server/strategy.js +28 -14
  142. package/hmr/frameworks/typescript/server/strategy.js.map +1 -1
  143. package/hmr/frameworks/vue/client/index.js +30 -199
  144. package/hmr/frameworks/vue/client/index.js.map +1 -1
  145. package/hmr/frameworks/vue/client/strategy.d.ts +7 -0
  146. package/hmr/frameworks/vue/client/strategy.js +83 -0
  147. package/hmr/frameworks/vue/client/strategy.js.map +1 -0
  148. package/hmr/frameworks/vue/client/vue-sfc-update-overlay.d.ts +82 -0
  149. package/hmr/frameworks/vue/client/vue-sfc-update-overlay.js +133 -0
  150. package/hmr/frameworks/vue/client/vue-sfc-update-overlay.js.map +1 -0
  151. package/hmr/frameworks/vue/server/sfc-route-assemble.d.ts +7 -0
  152. package/hmr/frameworks/vue/server/sfc-route-assemble.js +706 -0
  153. package/hmr/frameworks/vue/server/sfc-route-assemble.js.map +1 -0
  154. package/hmr/frameworks/vue/server/sfc-route-meta.d.ts +7 -0
  155. package/hmr/frameworks/vue/server/sfc-route-meta.js +80 -0
  156. package/hmr/frameworks/vue/server/sfc-route-meta.js.map +1 -0
  157. package/hmr/frameworks/vue/server/sfc-route-serve.d.ts +8 -0
  158. package/hmr/frameworks/vue/server/sfc-route-serve.js +457 -0
  159. package/hmr/frameworks/vue/server/sfc-route-serve.js.map +1 -0
  160. package/hmr/frameworks/vue/server/sfc-route-shared.d.ts +19 -0
  161. package/hmr/frameworks/vue/server/sfc-route-shared.js +14 -0
  162. package/hmr/frameworks/vue/server/sfc-route-shared.js.map +1 -0
  163. package/hmr/frameworks/vue/server/strategy.js +244 -0
  164. package/hmr/frameworks/vue/server/strategy.js.map +1 -1
  165. package/hmr/frameworks/vue/server/websocket-sfc.d.ts +15 -0
  166. package/hmr/frameworks/vue/server/websocket-sfc.js +20 -0
  167. package/hmr/frameworks/vue/server/websocket-sfc.js.map +1 -0
  168. package/hmr/helpers/ast-normalizer.js +52 -5
  169. package/hmr/helpers/ast-normalizer.js.map +1 -1
  170. package/hmr/helpers/cjs-named-exports.d.ts +23 -0
  171. package/hmr/helpers/cjs-named-exports.js +152 -0
  172. package/hmr/helpers/cjs-named-exports.js.map +1 -0
  173. package/hmr/helpers/package-exports.d.ts +16 -0
  174. package/hmr/helpers/package-exports.js +396 -0
  175. package/hmr/helpers/package-exports.js.map +1 -0
  176. package/hmr/server/constants.js +13 -4
  177. package/hmr/server/constants.js.map +1 -1
  178. package/hmr/server/core-sanitize.d.ts +90 -7
  179. package/hmr/server/core-sanitize.js +211 -56
  180. package/hmr/server/core-sanitize.js.map +1 -1
  181. package/hmr/server/device-transform-helpers.d.ts +24 -0
  182. package/hmr/server/device-transform-helpers.js +327 -0
  183. package/hmr/server/device-transform-helpers.js.map +1 -0
  184. package/hmr/server/framework-strategy.d.ts +95 -11
  185. package/hmr/server/hmr-module-graph.d.ts +37 -0
  186. package/hmr/server/hmr-module-graph.js +214 -0
  187. package/hmr/server/hmr-module-graph.js.map +1 -0
  188. package/hmr/server/import-map.d.ts +11 -2
  189. package/hmr/server/import-map.js +59 -40
  190. package/hmr/server/import-map.js.map +1 -1
  191. package/hmr/server/index.js +7 -16
  192. package/hmr/server/index.js.map +1 -1
  193. package/hmr/server/ns-core-cjs-shape.d.ts +204 -0
  194. package/hmr/server/ns-core-cjs-shape.js +271 -0
  195. package/hmr/server/ns-core-cjs-shape.js.map +1 -0
  196. package/hmr/server/ns-rt-bridge.d.ts +51 -0
  197. package/hmr/server/ns-rt-bridge.js +131 -0
  198. package/hmr/server/ns-rt-bridge.js.map +1 -0
  199. package/hmr/server/ns-rt-route.d.ts +5 -0
  200. package/hmr/server/ns-rt-route.js +35 -0
  201. package/hmr/server/ns-rt-route.js.map +1 -0
  202. package/hmr/server/perf-instrumentation.d.ts +114 -0
  203. package/hmr/server/perf-instrumentation.js +195 -0
  204. package/hmr/server/perf-instrumentation.js.map +1 -0
  205. package/hmr/server/process-code-for-device.d.ts +15 -0
  206. package/hmr/server/process-code-for-device.js +654 -0
  207. package/hmr/server/process-code-for-device.js.map +1 -0
  208. package/hmr/server/require-guard.d.ts +1 -0
  209. package/hmr/server/require-guard.js +12 -0
  210. package/hmr/server/require-guard.js.map +1 -0
  211. package/hmr/server/rewrite-imports.d.ts +2 -0
  212. package/hmr/server/rewrite-imports.js +604 -0
  213. package/hmr/server/rewrite-imports.js.map +1 -0
  214. package/hmr/server/route-helpers.d.ts +7 -0
  215. package/hmr/server/route-helpers.js +13 -0
  216. package/hmr/server/route-helpers.js.map +1 -0
  217. package/hmr/server/server-origin.d.ts +12 -0
  218. package/hmr/server/server-origin.js +66 -0
  219. package/hmr/server/server-origin.js.map +1 -0
  220. package/hmr/server/shared-transform-request.js +12 -5
  221. package/hmr/server/shared-transform-request.js.map +1 -1
  222. package/hmr/server/transform-cache-invalidation.d.ts +11 -0
  223. package/hmr/server/transform-cache-invalidation.js +84 -0
  224. package/hmr/server/transform-cache-invalidation.js.map +1 -0
  225. package/hmr/server/vendor-bare-module-shims.d.ts +4 -0
  226. package/hmr/server/vendor-bare-module-shims.js +80 -0
  227. package/hmr/server/vendor-bare-module-shims.js.map +1 -0
  228. package/hmr/server/vite-plugin.js +60 -42
  229. package/hmr/server/vite-plugin.js.map +1 -1
  230. package/hmr/server/websocket-core-bridge.d.ts +41 -6
  231. package/hmr/server/websocket-core-bridge.js +72 -75
  232. package/hmr/server/websocket-core-bridge.js.map +1 -1
  233. package/hmr/server/websocket-css-hot-update.d.ts +33 -0
  234. package/hmr/server/websocket-css-hot-update.js +65 -0
  235. package/hmr/server/websocket-css-hot-update.js.map +1 -0
  236. package/hmr/server/websocket-device-transform.d.ts +3 -0
  237. package/hmr/server/websocket-device-transform.js +7 -0
  238. package/hmr/server/websocket-device-transform.js.map +1 -0
  239. package/hmr/server/websocket-graph-upsert.d.ts +15 -0
  240. package/hmr/server/websocket-graph-upsert.js +20 -0
  241. package/hmr/server/websocket-graph-upsert.js.map +1 -1
  242. package/hmr/server/websocket-hmr-pending.d.ts +37 -0
  243. package/hmr/server/websocket-hmr-pending.js +55 -0
  244. package/hmr/server/websocket-hmr-pending.js.map +1 -0
  245. package/hmr/server/websocket-hot-update.d.ts +77 -0
  246. package/hmr/server/websocket-hot-update.js +330 -0
  247. package/hmr/server/websocket-hot-update.js.map +1 -0
  248. package/hmr/server/websocket-import-map-route.d.ts +15 -0
  249. package/hmr/server/websocket-import-map-route.js +46 -0
  250. package/hmr/server/websocket-import-map-route.js.map +1 -0
  251. package/hmr/server/websocket-module-bindings.js +3 -3
  252. package/hmr/server/websocket-module-bindings.js.map +1 -1
  253. package/hmr/server/websocket-module-specifiers.d.ts +66 -2
  254. package/hmr/server/websocket-module-specifiers.js +202 -19
  255. package/hmr/server/websocket-module-specifiers.js.map +1 -1
  256. package/hmr/server/websocket-ns-core.d.ts +21 -0
  257. package/hmr/server/websocket-ns-core.js +306 -0
  258. package/hmr/server/websocket-ns-core.js.map +1 -0
  259. package/hmr/server/websocket-ns-entry.d.ts +21 -0
  260. package/hmr/server/websocket-ns-entry.js +150 -0
  261. package/hmr/server/websocket-ns-entry.js.map +1 -0
  262. package/hmr/server/websocket-ns-m-paths.d.ts +3 -0
  263. package/hmr/server/websocket-ns-m-paths.js +92 -0
  264. package/hmr/server/websocket-ns-m-paths.js.map +1 -0
  265. package/hmr/server/websocket-ns-m-request.d.ts +45 -0
  266. package/hmr/server/websocket-ns-m-request.js +196 -0
  267. package/hmr/server/websocket-ns-m-request.js.map +1 -0
  268. package/hmr/server/websocket-ns-m.d.ts +33 -0
  269. package/hmr/server/websocket-ns-m.js +748 -0
  270. package/hmr/server/websocket-ns-m.js.map +1 -0
  271. package/hmr/server/websocket-served-module-helpers.d.ts +39 -0
  272. package/hmr/server/websocket-served-module-helpers.js +654 -0
  273. package/hmr/server/websocket-served-module-helpers.js.map +1 -0
  274. package/hmr/server/websocket-txn.d.ts +6 -0
  275. package/hmr/server/websocket-txn.js +39 -0
  276. package/hmr/server/websocket-txn.js.map +1 -0
  277. package/hmr/server/websocket-vendor-unifier.d.ts +9 -0
  278. package/hmr/server/websocket-vendor-unifier.js +46 -0
  279. package/hmr/server/websocket-vendor-unifier.js.map +1 -0
  280. package/hmr/server/websocket.d.ts +8 -39
  281. package/hmr/server/websocket.js +602 -6049
  282. package/hmr/server/websocket.js.map +1 -1
  283. package/hmr/shared/ns-globals.d.ts +118 -0
  284. package/hmr/shared/ns-globals.js +27 -0
  285. package/hmr/shared/ns-globals.js.map +1 -0
  286. package/hmr/shared/protocol.d.ts +136 -0
  287. package/hmr/shared/protocol.js +28 -0
  288. package/hmr/shared/protocol.js.map +1 -0
  289. package/hmr/shared/runtime/boot-placeholder-ui.d.ts +69 -0
  290. package/hmr/shared/runtime/boot-placeholder-ui.js +101 -0
  291. package/hmr/shared/runtime/boot-placeholder-ui.js.map +1 -0
  292. package/hmr/shared/runtime/boot-progress.d.ts +40 -0
  293. package/hmr/shared/runtime/boot-progress.js +128 -0
  294. package/hmr/shared/runtime/boot-progress.js.map +1 -0
  295. package/hmr/shared/runtime/boot-timeline.d.ts +18 -0
  296. package/hmr/shared/runtime/boot-timeline.js +52 -0
  297. package/hmr/shared/runtime/boot-timeline.js.map +1 -0
  298. package/hmr/shared/runtime/dev-overlay-snapshots.d.ts +31 -0
  299. package/hmr/shared/runtime/dev-overlay-snapshots.js +324 -0
  300. package/hmr/shared/runtime/dev-overlay-snapshots.js.map +1 -0
  301. package/hmr/shared/runtime/dev-overlay.d.ts +75 -26
  302. package/hmr/shared/runtime/dev-overlay.js +990 -260
  303. package/hmr/shared/runtime/dev-overlay.js.map +1 -1
  304. package/hmr/shared/runtime/module-provenance.js +1 -4
  305. package/hmr/shared/runtime/module-provenance.js.map +1 -1
  306. package/hmr/shared/runtime/root-placeholder-view.d.ts +19 -0
  307. package/hmr/shared/runtime/root-placeholder-view.js +310 -0
  308. package/hmr/shared/runtime/root-placeholder-view.js.map +1 -0
  309. package/hmr/shared/runtime/root-placeholder.js +352 -194
  310. package/hmr/shared/runtime/root-placeholder.js.map +1 -1
  311. package/hmr/shared/runtime/session-bootstrap.js +164 -1
  312. package/hmr/shared/runtime/session-bootstrap.js.map +1 -1
  313. package/hmr/shared/runtime/vendor-bootstrap.js +1 -9
  314. package/hmr/shared/runtime/vendor-bootstrap.js.map +1 -1
  315. package/hmr/shared/vendor/manifest-collect.d.ts +4 -0
  316. package/hmr/shared/vendor/manifest-collect.js +512 -0
  317. package/hmr/shared/vendor/manifest-collect.js.map +1 -0
  318. package/hmr/shared/vendor/manifest-loader.d.ts +2 -1
  319. package/hmr/shared/vendor/manifest-loader.js +3 -2
  320. package/hmr/shared/vendor/manifest-loader.js.map +1 -1
  321. package/hmr/shared/vendor/manifest.d.ts +1 -7
  322. package/hmr/shared/vendor/manifest.js +102 -741
  323. package/hmr/shared/vendor/manifest.js.map +1 -1
  324. package/hmr/shared/vendor/vendor-device-shim.d.ts +1 -0
  325. package/hmr/shared/vendor/vendor-device-shim.js +208 -0
  326. package/hmr/shared/vendor/vendor-device-shim.js.map +1 -0
  327. package/hmr/shared/vendor/vendor-esbuild-plugins.d.ts +16 -0
  328. package/hmr/shared/vendor/vendor-esbuild-plugins.js +203 -0
  329. package/hmr/shared/vendor/vendor-esbuild-plugins.js.map +1 -0
  330. package/index.d.ts +1 -0
  331. package/index.js +5 -0
  332. package/index.js.map +1 -1
  333. package/package.json +55 -11
  334. package/runtime/core-aliases-early.js +17 -41
  335. package/runtime/core-aliases-early.js.map +1 -1
  336. package/helpers/angular/angular-linker.d.ts +0 -13
  337. package/helpers/angular/angular-linker.js +0 -194
  338. package/helpers/angular/angular-linker.js.map +0 -1
  339. package/helpers/angular/inline-decorator-component-templates.js.map +0 -1
  340. package/helpers/angular/shared-linker.d.ts +0 -11
  341. package/helpers/angular/shared-linker.js +0 -75
  342. package/helpers/angular/shared-linker.js.map +0 -1
  343. package/helpers/angular/synthesize-decorator-ctor-parameters.js.map +0 -1
  344. package/helpers/angular/synthesize-injectable-factories.js.map +0 -1
  345. package/helpers/angular/util.js +0 -67
  346. package/helpers/angular/util.js.map +0 -1
  347. package/helpers/prelink-angular.d.ts +0 -2
  348. package/helpers/prelink-angular.js +0 -117
  349. package/helpers/prelink-angular.js.map +0 -1
  350. package/hmr/server/websocket-angular-entry.js.map +0 -1
  351. package/hmr/server/websocket-angular-hot-update.js +0 -239
  352. package/hmr/server/websocket-angular-hot-update.js.map +0 -1
  353. /package/{helpers/angular → hmr/frameworks/angular/build}/inline-decorator-component-templates.d.ts +0 -0
  354. /package/{helpers/angular → hmr/frameworks/angular/build}/synthesize-decorator-ctor-parameters.d.ts +0 -0
  355. /package/{helpers/angular → hmr/frameworks/angular/build}/synthesize-injectable-factories.d.ts +0 -0
  356. /package/hmr/{server → frameworks/angular/server}/websocket-angular-entry.d.ts +0 -0
@@ -5,8 +5,9 @@
5
5
  * Always resolve core classes and Application from the vendor realm or globalThis at runtime.
6
6
  * The HMR client is evaluated via HTTP ESM on device; static imports would create secondary instances.
7
7
  */
8
- import { setHMRWsUrl, getHMRWsUrl, pendingModuleFetches, deriveHttpOrigin, setHttpOriginForVite, moduleFetchCache, requestModuleFromServer, getHttpOriginForVite, normalizeSpec, hmrMetrics, graph, setGraphVersion, getGraphVersion, getCurrentApp, getRootFrame, setCurrentApp, setRootFrame, getCore } from './utils.js';
8
+ import { setHMRWsUrl, getHMRWsUrl, pendingModuleFetches, deriveHttpOrigin, setHttpOriginForVite, moduleFetchCache, requestModuleFromServer, getHttpOriginForVite, normalizeSpec, hmrMetrics, graph, setGraphVersion, getGraphVersion, getCurrentApp, getRootFrame, setCurrentApp, setRootFrame, getCore, hasExplicitEviction, invalidateModulesByUrls, buildEvictionUrls, emitHmrModeBannerOnce } from './utils.js';
9
9
  import { handleCssUpdates } from './css-handler.js';
10
+ import { buildCssApplyingDetail, buildCssAppliedDetail } from './css-update-overlay.js';
10
11
  const VERBOSE = typeof __NS_ENV_VERBOSE__ !== 'undefined' && __NS_ENV_VERBOSE__;
11
12
  function resolveTargetFlavor() {
12
13
  try {
@@ -101,6 +102,79 @@ function hideConnectionOverlay() {
101
102
  }
102
103
  catch { }
103
104
  }
105
+ function setUpdateOverlayStage(stage, info) {
106
+ try {
107
+ const api = getHmrOverlayApi();
108
+ if (api && typeof api.setUpdateStage === 'function') {
109
+ api.setUpdateStage(stage, info);
110
+ }
111
+ }
112
+ catch { }
113
+ }
114
+ // Store the listener registry on globalThis (rather than in a module-private
115
+ // closure) because in NativeScript the HMR client module and the user app
116
+ // modules can resolve to different module instances depending on how the
117
+ // dev runtime loads them (HTTP client URL vs. the bundled vendor realm).
118
+ // A module-local Set would not be shared across instances; the global one
119
+ // is.
120
+ function getNsSolidHmrListenerSet() {
121
+ const g = globalThis;
122
+ let set = g.__ns_solid_hmr_listener_set;
123
+ if (!set) {
124
+ set = new Set();
125
+ g.__ns_solid_hmr_listener_set = set;
126
+ }
127
+ return set;
128
+ }
129
+ function nsSolidHmrSubscribe(fn) {
130
+ const listeners = getNsSolidHmrListenerSet();
131
+ listeners.add(fn);
132
+ if (VERBOSE)
133
+ console.log('[hmr][solid] subscribe — listeners=', listeners.size);
134
+ return () => listeners.delete(fn);
135
+ }
136
+ function nsSolidHmrEmit(ev) {
137
+ const listeners = getNsSolidHmrListenerSet();
138
+ if (VERBOSE)
139
+ console.log('[hmr][solid] emit listeners=', listeners.size, 'changedFiles=', ev.changedFiles);
140
+ for (const fn of Array.from(listeners)) {
141
+ try {
142
+ fn(ev);
143
+ }
144
+ catch (err) {
145
+ if (VERBOSE)
146
+ console.warn('[hmr][solid] listener threw', err);
147
+ }
148
+ }
149
+ }
150
+ try {
151
+ const g = globalThis;
152
+ g.__ns_solid_hmr_subscribe = nsSolidHmrSubscribe;
153
+ // Eagerly create the listener set so the global exists at module load time.
154
+ getNsSolidHmrListenerSet();
155
+ if (VERBOSE)
156
+ console.log('[hmr][solid] HMR client loaded. global set=', typeof g.__ns_solid_hmr_subscribe, 'listenerSet=', typeof g.__ns_solid_hmr_listener_set);
157
+ }
158
+ catch (err) {
159
+ console.warn('[hmr][solid] could not install global __ns_solid_hmr_subscribe', err);
160
+ }
161
+ // Eagerly drive the HMR-applying overlay's 'received' frame as soon
162
+ // as the server emits `ns:hmr-pending`, BEFORE the framework-specific
163
+ // (`ns:angular-update` / `ns:css-updates`) payload arrives. The
164
+ // flavor-specific handler later walks through 'evicting' →
165
+ // 'reimporting' → 'rebooting' → 'complete'. Calling 'received' twice
166
+ // in the same cycle is safe: the overlay preserves
167
+ // `updateCycleStartedAt` when a 'received' frame replaces an existing
168
+ // 'received' frame so the minimum-visible window is still timed
169
+ // against the FIRST frame.
170
+ //
171
+ // Soft-fails when the overlay isn't installed (production builds,
172
+ // vitest, etc.) or when the user opted out via
173
+ // `__NS_HMR_PROGRESS_OVERLAY_ENABLED__ === false`.
174
+ import { applyHmrPendingFrame } from './hmr-pending-overlay.js';
175
+ function setHmrPendingOverlay(filePath) {
176
+ applyHmrPendingFrame(filePath, { getOverlay: getHmrOverlayApi });
177
+ }
104
178
  let connectionOverlayTimer = null;
105
179
  let connectionOverlayVisible = false;
106
180
  let hasOpenedHmrSocket = false;
@@ -142,19 +216,19 @@ function markHmrConnectionHealthy() {
142
216
  hideConnectionOverlay();
143
217
  }
144
218
  }
145
- /**
146
- * Flavor hooks
147
- */
148
- import { installNsVueDevShims, ensureBackWrapperInstalled, getRootForVue, loadSfcComponent, ensureVueGlobals, ensurePiniaOnApp, addSfcMapping, recordVuePayloadChanges, handleVueSfcRegistry, handleVueSfcRegistryUpdate, sfcArtifactMap } from '../frameworks/vue/client/index.js';
149
- import { handleAngularHotUpdateMessage, installAngularHmrClientHooks } from '../frameworks/angular/client/index.js';
150
- switch (TARGET_FLAVOR) {
151
- case 'vue':
152
- installNsVueDevShims();
153
- break;
154
- case 'angular':
155
- installAngularHmrClientHooks();
156
- break;
157
- }
219
+ let CLIENT_STRATEGY;
220
+ const CLIENT_STRATEGY_READY = TARGET_FLAVOR === 'vue' || TARGET_FLAVOR === 'angular'
221
+ ? import(`../frameworks/${TARGET_FLAVOR}/client/strategy.js`)
222
+ .then((mod) => {
223
+ CLIENT_STRATEGY = mod && (mod[`${TARGET_FLAVOR}ClientStrategy`] ?? mod.default);
224
+ if (VERBOSE)
225
+ console.log('[hmr-client] client strategy loaded for flavor:', TARGET_FLAVOR);
226
+ CLIENT_STRATEGY?.install();
227
+ })
228
+ .catch((err) => {
229
+ console.warn('[hmr-client] failed to load client strategy for', TARGET_FLAVOR, err);
230
+ })
231
+ : Promise.resolve();
158
232
  // Track whether we've mounted an initial app root yet in HTTP-only boot
159
233
  let initialMounted = !!globalThis.__NS_HMR_BOOT_COMPLETE__;
160
234
  // Prevent duplicate initial-mount scheduling across rapid full-graph broadcasts and re-evaluations
@@ -317,39 +391,7 @@ function applyFullGraph(payload) {
317
391
  }
318
392
  return;
319
393
  }
320
- let candidate = null;
321
- switch (TARGET_FLAVOR) {
322
- case 'vue': {
323
- const appEntry = graph.get(APP_MAIN_ENTRY_SPEC);
324
- if (appEntry && Array.isArray(appEntry.deps)) {
325
- const vueDep = appEntry.deps.find((d) => typeof d === 'string' && /\.vue$/i.test(d));
326
- if (vueDep)
327
- candidate = vueDep;
328
- }
329
- if (!candidate) {
330
- for (const id of graph.keys()) {
331
- if (/\.vue$/i.test(id)) {
332
- candidate = id;
333
- break;
334
- }
335
- }
336
- }
337
- // Fallback: when the module graph is empty (Vite 7+ may not populate it
338
- // before the first full-graph broadcast), check the SFC artifact registry
339
- // which is populated from the ns:vue-sfc-registry message.
340
- if (!candidate && sfcArtifactMap.size > 0) {
341
- for (const id of sfcArtifactMap.keys()) {
342
- if (/\.vue$/i.test(id)) {
343
- candidate = id;
344
- if (VERBOSE)
345
- console.log('[hmr][init] rescue candidate from SFC registry:', id);
346
- break;
347
- }
348
- }
349
- }
350
- break;
351
- }
352
- }
394
+ const candidate = CLIENT_STRATEGY?.selectMountCandidate?.({ graph, appMainEntrySpec: APP_MAIN_ENTRY_SPEC }) ?? null;
353
395
  if (!candidate)
354
396
  return;
355
397
  initialMounting = true;
@@ -360,10 +402,8 @@ function applyFullGraph(payload) {
360
402
  (async () => {
361
403
  try {
362
404
  let comp = null;
363
- switch (TARGET_FLAVOR) {
364
- case 'vue':
365
- comp = await loadSfcComponent(candidate, 'initial_mount_rescue');
366
- break;
405
+ if (CLIENT_STRATEGY?.loadComponentForMount) {
406
+ comp = await CLIENT_STRATEGY.loadComponentForMount(candidate, 'initial_mount_rescue');
367
407
  }
368
408
  if (!comp)
369
409
  return;
@@ -404,41 +444,11 @@ function applyFullGraph(payload) {
404
444
  // Only allow initial mount when explicitly enabled. Rely on the app's own main entry start() for the first mount
405
445
  // to avoid double-mount races that can cause duplicate navigation logs.
406
446
  if (ALLOW_INITIAL_MOUNT && !initialMounted && !bootDone && !bootInProgress && !getCurrentApp() && !getRootFrame()) {
407
- let candidate = null;
408
- switch (TARGET_FLAVOR) {
409
- case 'vue': {
410
- const appEntry = graph.get(APP_MAIN_ENTRY_SPEC);
411
- if (appEntry && Array.isArray(appEntry.deps)) {
412
- const vueDep = appEntry.deps.find((d) => typeof d === 'string' && /\.vue$/i.test(d));
413
- if (vueDep)
414
- candidate = vueDep;
415
- }
416
- if (!candidate) {
417
- for (const id of graph.keys()) {
418
- if (/\.vue$/i.test(id)) {
419
- candidate = id;
420
- break;
421
- }
422
- }
423
- }
424
- // Fallback: SFC registry (same as rescue mount above)
425
- if (!candidate && sfcArtifactMap.size > 0) {
426
- for (const id of sfcArtifactMap.keys()) {
427
- if (/\.vue$/i.test(id)) {
428
- candidate = id;
429
- if (VERBOSE)
430
- console.log('[hmr][init] initial mount candidate from SFC registry:', id);
431
- break;
432
- }
433
- }
434
- }
435
- break;
436
- }
437
- case 'typescript': {
438
- // For TS flavor, do not perform client-driven initial mount; rely on Application.run.
439
- return;
440
- }
447
+ if (TARGET_FLAVOR === 'typescript') {
448
+ // For TS flavor, do not perform client-driven initial mount; rely on Application.run.
449
+ return;
441
450
  }
451
+ const candidate = CLIENT_STRATEGY?.selectMountCandidate?.({ graph, appMainEntrySpec: APP_MAIN_ENTRY_SPEC }) ?? null;
442
452
  if (candidate) {
443
453
  // Mark initial-mount in progress (both module-local and global) BEFORE scheduling async work
444
454
  initialMounting = true;
@@ -483,21 +493,19 @@ function applyFullGraph(payload) {
483
493
  }
484
494
  catch { }
485
495
  let comp = null;
486
- switch (TARGET_FLAVOR) {
487
- case 'vue':
488
- comp = await loadSfcComponent(candidate, 'initial_mount');
489
- break;
490
- case 'typescript':
491
- try {
492
- const url = await requestModuleFromServer(candidate);
493
- const mod = await import(/* @vite-ignore */ url);
494
- comp = mod && (mod.default || mod);
495
- }
496
- catch (e) {
497
- if (VERBOSE)
498
- console.warn('[hmr][init] TS initial mount failed to import', candidate, e);
499
- }
500
- break;
496
+ if (TARGET_FLAVOR === 'typescript') {
497
+ try {
498
+ const url = await requestModuleFromServer(candidate);
499
+ const mod = await import(/* @vite-ignore */ url);
500
+ comp = mod && (mod.default || mod);
501
+ }
502
+ catch (e) {
503
+ if (VERBOSE)
504
+ console.warn('[hmr][init] TS initial mount failed to import', candidate, e);
505
+ }
506
+ }
507
+ else if (CLIENT_STRATEGY?.loadComponentForMount) {
508
+ comp = await CLIENT_STRATEGY.loadComponentForMount(candidate, 'initial_mount');
501
509
  }
502
510
  if (comp) {
503
511
  const ok = await performResetRoot(comp);
@@ -558,11 +566,7 @@ function applyDelta(payload) {
558
566
  setGraphVersion(payload.newVersion);
559
567
  }
560
568
  const changed = payload.changed || [];
561
- switch (TARGET_FLAVOR) {
562
- case 'vue':
563
- recordVuePayloadChanges(changed, getGraphVersion());
564
- break;
565
- }
569
+ CLIENT_STRATEGY?.recordPayloadChanges?.(changed, getGraphVersion());
566
570
  (payload.changed || []).forEach((m) => {
567
571
  if (!m || !m.id)
568
572
  return;
@@ -648,11 +652,7 @@ function applyDelta(payload) {
648
652
  // Deterministic navigation using the current Vue app instance rather than vendor-held rootApp
649
653
  function __nsNavigateUsingApp(comp, opts = {}) {
650
654
  const g = globalThis;
651
- switch (TARGET_FLAVOR) {
652
- case 'vue':
653
- ensureVueGlobals();
654
- break;
655
- }
655
+ CLIENT_STRATEGY?.beforeNavigateBuild?.();
656
656
  const AppFactory = g.createApp;
657
657
  const RootCtor = g.NSVRoot;
658
658
  if (typeof AppFactory !== 'function' || typeof RootCtor !== 'function') {
@@ -675,12 +675,14 @@ function __nsNavigateUsingApp(comp, opts = {}) {
675
675
  const buildTarget = () => {
676
676
  const existingApp = getCurrentApp();
677
677
  const baseProvides = (existingApp && existingApp._context && existingApp._context.provides) || {};
678
- const app = AppFactory(normalizeComponent(comp, comp && (comp.__name || comp.name)));
679
- switch (TARGET_FLAVOR) {
680
- case 'vue':
681
- ensurePiniaOnApp(app);
682
- break;
683
- }
678
+ // Forward `opts.props` as Vue's rootProps so `$navigateTo(Comp, { props: { } })`
679
+ // reaches the destination component. nativescript-vue's stock `$navigateTo`
680
+ // does the same via `createNativeView(target, options?.props, …)` →
681
+ // `renderer.createApp(component, props)`. Dropping props here would surface
682
+ // at the destination as `[Vue warn]: Missing required prop` and any
683
+ // required-prop component would render with `undefined` bindings.
684
+ const app = AppFactory(normalizeComponent(comp, comp && (comp.__name || comp.name)), opts && opts.props);
685
+ CLIENT_STRATEGY?.onNavAppCreated?.(app);
684
686
  try {
685
687
  const registry = g.__nsVendorRegistry;
686
688
  const req = registry?.get ? g.__nsVendorRequire || g.__nsRequire || g.require : g.__nsRequire || g.require;
@@ -810,7 +812,42 @@ async function processQueue() {
810
812
  return;
811
813
  if (VERBOSE)
812
814
  console.log('[hmr][queue] processing changed ids', drained);
815
+ // Track wall-clock so the 'complete' frame can show a meaningful
816
+ // total. Only the Solid + TypeScript flavors drive the overlay
817
+ // from here; Angular has its own flow inside
818
+ // `frameworks/angular/client/index.ts`.
819
+ const tQueueStart = Date.now();
820
+ const driveSolidOverlay = TARGET_FLAVOR === 'solid';
821
+ // Explicit eviction step.
822
+ //
823
+ // On modern runtimes the URL canonicalizer collapses any
824
+ // `__ns_hmr__/<tag>/` segment back to a stable cache key, so
825
+ // without explicit eviction the upcoming `import(url)` would
826
+ // resolve via V8's `g_moduleRegistry` and return the cached
827
+ // stale module — making the queue drain a silent no-op for
828
+ // every save after the first.
829
+ //
830
+ // We hand the canonical eviction URLs to the runtime first;
831
+ // `invalidateModulesByUrls` is a no-op on older runtimes and
832
+ // `requestModuleFromServer` automatically falls back to the
833
+ // legacy `/ns/m/__ns_hmr__/v<N>/` URL versioning path in that
834
+ // case. node_modules and virtual specs are filtered out by
835
+ // `buildEvictionUrls` so vendor modules stay hot.
836
+ if (driveSolidOverlay) {
837
+ setUpdateOverlayStage('evicting', {
838
+ detail: drained.length === 1 ? `Invalidating ${drained[0]}` : `Invalidating ${drained.length} modules`,
839
+ });
840
+ }
841
+ const evictUrls = buildEvictionUrls(drained);
842
+ const evicted = invalidateModulesByUrls(evictUrls);
843
+ if (VERBOSE)
844
+ console.log(`[hmr][queue] eviction count=${evictUrls.length} ok=${evicted}`);
813
845
  // Evaluate changed modules best-effort; failures shouldn't completely break HMR.
846
+ if (driveSolidOverlay) {
847
+ setUpdateOverlayStage('reimporting', {
848
+ detail: drained.length === 1 ? `Re-importing ${drained[0]}` : `Re-importing ${drained.length} modules`,
849
+ });
850
+ }
814
851
  for (const id of drained) {
815
852
  try {
816
853
  const spec = normalizeSpec(id);
@@ -829,9 +866,16 @@ async function processQueue() {
829
866
  // After evaluating the batch, perform flavor-specific UI refresh.
830
867
  switch (TARGET_FLAVOR) {
831
868
  case 'vue':
832
- // Vue SFCs are handled via the registry update path; nothing to do here.
869
+ await CLIENT_STRATEGY?.refreshAfterBatch?.(drained, { setUpdateOverlayStage, startedAt: tQueueStart });
833
870
  break;
834
871
  case 'solid': {
872
+ // Boundaries discovered in this HMR cycle (tsx files reachable
873
+ // via the reverse import graph from any changed file, plus route
874
+ // files reachable from any tsx start point). Declared at the top
875
+ // of the case block so the emit step below can include the
876
+ // complete set in the listener event — framework integrations
877
+ // use it to map route boundaries → fresh component references.
878
+ const boundaries = new Set();
835
879
  // Solid .tsx components are self-accepting via solid-refresh's inline
836
880
  // patchRegistry — re-importing them is sufficient. For non-component
837
881
  // .ts utility modules, we must propagate up the import graph to find
@@ -850,8 +894,10 @@ async function processQueue() {
850
894
  arr.push(id);
851
895
  }
852
896
  }
853
- // BFS from each non-tsx changed module up to tsx/jsx boundaries
854
- const boundaries = new Set();
897
+ // Pass 1: BFS from each non-tsx changed module up to tsx/jsx
898
+ // boundaries. These get re-imported below so solid-refresh's
899
+ // inline patchRegistry runs and (best-effort) swaps the proxy
900
+ // signals for any components defined in those tsx boundaries.
855
901
  for (const id of drained) {
856
902
  if (/\.(tsx|jsx)$/i.test(id))
857
903
  continue; // already self-accepting
@@ -875,6 +921,51 @@ async function processQueue() {
875
921
  }
876
922
  }
877
923
  }
924
+ // Pass 2: walk further from any tsx starting point (a tsx file
925
+ // in `drained` OR a tsx boundary discovered in pass 1) to find
926
+ // route files (`/src/routes/*.{tsx,jsx}`) that transitively
927
+ // import them. Re-importing a route file refreshes its
928
+ // `Route.options.component` to the freshly-imported reference
929
+ // and the existing boundary loop below patches the live router
930
+ // with that fresh reference.
931
+ //
932
+ // This is the key fix for "edit home.tsx → save → no visual
933
+ // update": the old BFS skipped tsx files in `drained` (assuming
934
+ // solid-refresh's in-place proxy patch was sufficient), but in
935
+ // the universal-renderer + nested-context configuration that
936
+ // patch does not always propagate to the visible page tree.
937
+ // Adding the route file as a boundary lets us patch
938
+ // `route.options.component` directly to a fresh module export,
939
+ // which the framework subscriber then passes through to the
940
+ // page remount — making the cycle robust to the proxy patch
941
+ // silently failing.
942
+ const tsxStarts = new Set();
943
+ for (const id of drained) {
944
+ if (/\.(tsx|jsx)$/i.test(id))
945
+ tsxStarts.add(id);
946
+ }
947
+ for (const b of boundaries)
948
+ tsxStarts.add(b);
949
+ const ROUTE_FILE_RE = /\/src\/routes\/.+\.(tsx|jsx)$/i;
950
+ for (const start of tsxStarts) {
951
+ const visited = new Set();
952
+ const queue = [start];
953
+ while (queue.length) {
954
+ const cur = queue.shift();
955
+ if (visited.has(cur))
956
+ continue;
957
+ visited.add(cur);
958
+ if (cur !== start && ROUTE_FILE_RE.test(cur)) {
959
+ boundaries.add(cur);
960
+ }
961
+ const importers = reverseIndex.get(cur);
962
+ if (!importers)
963
+ continue;
964
+ for (const imp of importers) {
965
+ queue.push(imp);
966
+ }
967
+ }
968
+ }
878
969
  // Re-import each boundary so solid-refresh patchRegistry fires.
879
970
  // For route files (TanStack Router), capture the new Route export
880
971
  // and patch the router's existing route with the fresh loader.
@@ -924,6 +1015,15 @@ async function processQueue() {
924
1015
  }
925
1016
  return null;
926
1017
  };
1018
+ // Evict the boundary set so re-importing each .tsx
1019
+ // component actually picks up the new transitive
1020
+ // dependency code; without this V8 returns the
1021
+ // cached boundary module unchanged.
1022
+ const boundaryIds = Array.from(boundaries);
1023
+ const solidEvictUrls = buildEvictionUrls(boundaryIds);
1024
+ const solidEvicted = invalidateModulesByUrls(solidEvictUrls);
1025
+ if (VERBOSE)
1026
+ console.log(`[hmr][solid] eviction count=${solidEvictUrls.length} ok=${solidEvicted}`);
927
1027
  for (const id of boundaries) {
928
1028
  if (seen.has(id))
929
1029
  continue;
@@ -935,22 +1035,28 @@ async function processQueue() {
935
1035
  if (VERBOSE)
936
1036
  console.log('[hmr][solid] propagated to boundary', { id, url });
937
1037
  const mod = await import(/* @vite-ignore */ url);
938
- // Patch TanStack Router route loaders
1038
+ // Patch TanStack Router route options for any module
1039
+ // that exports a `Route`. We patch BOTH the component
1040
+ // and the loader (when present); components-only routes
1041
+ // were previously skipped because the gate required a
1042
+ // loader, which left their `options.component` pointing
1043
+ // at the stale module's exports after HMR.
939
1044
  try {
940
1045
  const newRoute = mod?.Route;
941
- if (newRoute?.options?.loader) {
1046
+ if (newRoute?.options) {
942
1047
  const router = findRouter();
943
1048
  const fullPath = boundaryToFullPath(id);
944
1049
  if (VERBOSE)
945
- console.log('[hmr][solid][diag] route patch attempt', { id, fullPath, hasRouter: !!router, routesByIdKeys: router?.routesById ? Object.keys(router.routesById) : 'none' });
1050
+ console.log('[hmr][solid][diag] route patch attempt', { id, fullPath, hasRouter: !!router, hasLoader: !!newRoute.options.loader, hasComponent: !!newRoute.options.component });
946
1051
  const existingRoute = fullPath && router ? findRouteByFullPath(router, fullPath) : null;
947
1052
  if (existingRoute?.options) {
948
- existingRoute.options.loader = newRoute.options.loader;
1053
+ if (newRoute.options.loader)
1054
+ existingRoute.options.loader = newRoute.options.loader;
949
1055
  if (newRoute.options.component)
950
1056
  existingRoute.options.component = newRoute.options.component;
951
1057
  routesPatchCount++;
952
1058
  if (VERBOSE)
953
- console.log('[hmr][solid] patched route loader', existingRoute.id, 'fullPath=', fullPath);
1059
+ console.log('[hmr][solid] patched route', existingRoute.id, 'fullPath=', fullPath);
954
1060
  }
955
1061
  else if (VERBOSE) {
956
1062
  console.log('[hmr][solid] no matching route for fullPath', fullPath);
@@ -986,6 +1092,44 @@ async function processQueue() {
986
1092
  if (VERBOSE)
987
1093
  console.warn('[hmr][solid] propagation failed', e);
988
1094
  }
1095
+ // Notify any framework integrations (e.g.
1096
+ // `@nativescript/tanstack-router`) that a Solid HMR
1097
+ // cycle has completed. They use this signal to perform
1098
+ // framework-specific UI refresh (e.g. remount the active
1099
+ // router page) when solid-refresh's own reactive
1100
+ // propagation does not reach the visible tree under
1101
+ // the current renderer/context configuration.
1102
+ //
1103
+ // Boundaries include both the directly-changed tsx files
1104
+ // AND every tsx ancestor reachable via the reverse import
1105
+ // graph (route files in particular). The framework
1106
+ // listener uses the route-file boundaries to look up the
1107
+ // freshly-patched `route.options.component` and pass it
1108
+ // through to the page remount.
1109
+ try {
1110
+ const tsxChangedInDrained = drained.filter((id) => /\.(tsx|jsx)$/i.test(id));
1111
+ const allBoundaries = Array.from(new Set([...tsxChangedInDrained, ...boundaries]));
1112
+ nsSolidHmrEmit({
1113
+ kind: 'solid',
1114
+ changedFiles: drained.slice(),
1115
+ boundaries: allBoundaries,
1116
+ });
1117
+ }
1118
+ catch (err) {
1119
+ if (VERBOSE)
1120
+ console.warn('[hmr][solid] emit failed', err);
1121
+ }
1122
+ // Tell the overlay the cycle is done. solid-refresh's
1123
+ // inline patchRegistry has already flushed the new
1124
+ // component bodies into the live tree (the `case
1125
+ // 'solid'` block above re-imports each .tsx
1126
+ // boundary), so by the time we get here the user is
1127
+ // already looking at the new render. The 'complete'
1128
+ // frame surfaces the wall-clock total and triggers
1129
+ // the overlay's auto-hide.
1130
+ setUpdateOverlayStage('complete', {
1131
+ detail: `Total ${Math.max(0, Date.now() - tQueueStart)}ms`,
1132
+ });
989
1133
  break;
990
1134
  }
991
1135
  case 'typescript': {
@@ -1274,6 +1418,14 @@ function connectHmr() {
1274
1418
  showConnectionOverlayNow('synchronizing', 'Connected. Synchronizing the HMR graph.');
1275
1419
  }
1276
1420
  VERBOSE && console.log('[hmr-client] Connected to HMR WebSocket');
1421
+ // Print the active module reload mode once on first
1422
+ // successful connect so the user can correlate HMR latency
1423
+ // with runtime capability without grepping for protocol
1424
+ // details. The banner is verbose-gated.
1425
+ try {
1426
+ emitHmrModeBannerOnce();
1427
+ }
1428
+ catch { }
1277
1429
  };
1278
1430
  sock.onmessage = handleHmrMessage;
1279
1431
  sock.onerror = (error) => {
@@ -1333,6 +1485,22 @@ async function handleHmrMessage(ev) {
1333
1485
  catch { }
1334
1486
  }
1335
1487
  if (msg) {
1488
+ // `ns:hmr-pending` is a fire-and-forget UX hint emitted by the
1489
+ // server at the START of handleHotUpdate. We drive the
1490
+ // HMR-applying overlay's 'received' frame here (synchronously),
1491
+ // well before the authoritative payload (`ns:angular-update` /
1492
+ // `ns:css-updates`) lands. Skip running any other handlers —
1493
+ // the pending message has no module payload and intentionally
1494
+ // does not bump the graph version.
1495
+ if (msg.type === 'ns:hmr-pending' && typeof msg.path === 'string') {
1496
+ setHmrPendingOverlay(msg.path);
1497
+ return;
1498
+ }
1499
+ // The per-flavor client strategy is loaded by a dynamic import(); make
1500
+ // sure it has resolved (and `install()` has run) before any handler that
1501
+ // delegates through it. After the first message this is an already-settled
1502
+ // promise (microtask only); for Solid/TypeScript it is `Promise.resolve()`.
1503
+ await CLIENT_STRATEGY_READY;
1336
1504
  if (msg.type === 'ns:hmr-full-graph') {
1337
1505
  // Bump a monotonic nonce so HTTP ESM imports can always be cache-busted per update.
1338
1506
  try {
@@ -1402,6 +1570,14 @@ async function handleHmrMessage(ev) {
1402
1570
  });
1403
1571
  if (toReimport.length && VERBOSE)
1404
1572
  console.log('[hmr][full-graph] inferred changed modules; re-importing', toReimport);
1573
+ // Evict the inferred changed set before re-importing.
1574
+ // See `processQueue` for the architectural rationale; the
1575
+ // full-graph code path is the resync fallback (server chose
1576
+ // not to send a delta) and shares the same V8 cache pitfall.
1577
+ const fgEvictUrls = buildEvictionUrls(toReimport);
1578
+ const fgEvicted = invalidateModulesByUrls(fgEvictUrls);
1579
+ if (VERBOSE)
1580
+ console.log(`[hmr][full-graph] eviction count=${fgEvictUrls.length} ok=${fgEvicted}`);
1405
1581
  for (const id of toReimport) {
1406
1582
  try {
1407
1583
  const spec = normalizeSpec(id);
@@ -1475,10 +1651,108 @@ async function handleHmrMessage(ev) {
1475
1651
  return;
1476
1652
  }
1477
1653
  else {
1654
+ // Vite custom-event dispatch.
1655
+ //
1656
+ // `server.ws.send('event-name', payload)` from any Vite plugin lands
1657
+ // on the wire as `{ type: 'custom', event: 'event-name', data: payload }`.
1658
+ // On the web, Vite's stock client owns a `customListenersMap` that
1659
+ // fires every `import.meta.hot.on('event-name', cb)` callback. We
1660
+ // don't run Vite's stock client on device — the iOS runtime owns
1661
+ // the listener registry via `__NS_DISPATCH_HOT_EVENT__` (the
1662
+ // counterpart to `import.meta.hot.on` populated by user code +
1663
+ // compiled Angular components). Forwarding `type: 'custom'` here
1664
+ // is the only thing standing between server-emitted events and
1665
+ // the listeners they were meant for.
1666
+ //
1667
+ // `angular:component-update` is the canonical example. Analog's
1668
+ // plugin sends it on `.html` / component-style edits; the
1669
+ // compiled component `.mjs` registered a listener that
1670
+ // dynamic-imports `/@ng/component?c=<id>&t=<ts>` and calls
1671
+ // `ɵɵreplaceMetadata` on the live class — swapping the template
1672
+ // definition AND walking live `LView`s to recreate matching views
1673
+ // in-place. The page stays mounted and only the changed bits
1674
+ // re-render. We MUST `return` after dispatch so the reboot path
1675
+ // (`handleAngularHotUpdateMessage` → `__reboot_ng_modules__`)
1676
+ // never runs for these updates — that's the whole point of the
1677
+ // component-replacement pipeline.
1678
+ //
1679
+ // All other custom events are forwarded but NOT short-circuited
1680
+ // (Vite spec: custom events are additive — they don't replace
1681
+ // any framework-specific handling). The reboot path falls through
1682
+ // for `ns:angular-update` (the legacy/`.ts`-edit broadcast) and
1683
+ // for any framework not yet using the in-place replacement path.
1684
+ if (msg.type === 'custom' && typeof msg.event === 'string') {
1685
+ // Dispatch every Vite "custom" event through the runtime's
1686
+ // `__NS_DISPATCH_HOT_EVENT__` bridge so `import.meta.hot.on(event, cb)`
1687
+ // callbacks fire on the device. Critical contract: this is the
1688
+ // ONLY route by which Analog's `angular:component-update` reaches
1689
+ // the compiled component's `(d) => d.id === id && Component_HmrLoad(...)`
1690
+ // listener — without it, server-side broadcasts log green
1691
+ // (`(client) hmr update`) while the device sees nothing happen.
1692
+ //
1693
+ // Diagnostic policy: log "no dispatcher" loud (boot-time rt-bridge
1694
+ // failure), and listener exceptions loud (compiled HmrLoad
1695
+ // fetch/parse error). Successful dispatches are silent — the
1696
+ // runtime's `[import.meta.hot] dispatch summary` line carries
1697
+ // the per-event match-count diagnostic.
1698
+ try {
1699
+ const dispatch = globalThis.__NS_DISPATCH_HOT_EVENT__;
1700
+ if (typeof dispatch === 'function') {
1701
+ dispatch(msg.event, msg.data);
1702
+ }
1703
+ else {
1704
+ console.warn(`[hmr-client][custom] no __NS_DISPATCH_HOT_EVENT__ available for '${msg.event}'`);
1705
+ }
1706
+ }
1707
+ catch (err) {
1708
+ console.warn('[hmr-client][custom] dispatch threw for', msg.event, err);
1709
+ }
1710
+ if (msg.event === 'angular:component-update') {
1711
+ if (VERBOSE)
1712
+ console.log('[hmr-client][custom] dispatched angular:component-update — skipping reboot path');
1713
+ // Walk the apply-progress overlay through its
1714
+ // remaining stages for the in-place template-swap
1715
+ // path. The full reboot path
1716
+ // (`handleAngularHotUpdateMessage`) drives the
1717
+ // overlay itself ('received' → 'evicting' →
1718
+ // 'reimporting' → 'rebooting' → 'complete'); the
1719
+ // in-place path bypasses that handler entirely
1720
+ // because the work happens inside Angular's
1721
+ // `ɵɵreplaceMetadata` after the runtime forwards the
1722
+ // `angular:component-update` event to the compiled
1723
+ // component's listener. Without this update the
1724
+ // overlay would freeze at 5% ('received') even
1725
+ // though the visual swap completes a few frames
1726
+ // later — exactly the "Preparing update (5%)" stuck
1727
+ // frame we have been chasing.
1728
+ //
1729
+ // We transition straight to 'reimporting' to
1730
+ // communicate that metadata is being fetched (the
1731
+ // runtime listener fires `__ns_import('/@ng/component?c=...&t=...')`),
1732
+ // then schedule 'complete' on the next macrotask so
1733
+ // the auto-hide timer kicks in. The actual
1734
+ // template swap is fire-and-forget from this point;
1735
+ // the user sees the overlay close at the same time
1736
+ // as Angular re-renders the bound text/structure.
1737
+ try {
1738
+ const filePath = typeof msg.data?.id === 'string' ? decodeURIComponent(msg.data.id).split('@')[0] : undefined;
1739
+ const detail = filePath ? `Applying template update to ${filePath}` : 'Applying template update';
1740
+ setUpdateOverlayStage('reimporting', { detail });
1741
+ setTimeout(() => {
1742
+ try {
1743
+ setUpdateOverlayStage('complete', { detail: filePath ? `Updated ${filePath}` : 'Update applied' });
1744
+ }
1745
+ catch { }
1746
+ }, 16);
1747
+ }
1748
+ catch { }
1749
+ return;
1750
+ }
1751
+ }
1478
1752
  if (msg.type === 'ns:angular-update' && typeof msg.version === 'number') {
1479
1753
  setGraphVersion(Number(msg.version || getGraphVersion() || 0));
1480
1754
  }
1481
- if (await handleAngularHotUpdateMessage(msg, { getCore, verbose: VERBOSE })) {
1755
+ if (CLIENT_STRATEGY?.handleHotUpdateMessage && (await CLIENT_STRATEGY.handleHotUpdateMessage(msg, { getCore, verbose: VERBOSE, performResetRoot, getOverlay: getHmrOverlayApi }))) {
1482
1756
  return;
1483
1757
  }
1484
1758
  }
@@ -1512,27 +1786,47 @@ async function handleHmrMessage(ev) {
1512
1786
  return;
1513
1787
  }
1514
1788
  if (msg.type === 'ns:css-updates' && Array.isArray(msg.updates)) {
1789
+ // Drive the HMR-applying overlay past the 'received' (5%) frame
1790
+ // that `ns:hmr-pending` set earlier in the cycle. Without this
1791
+ // the overlay sticks at "Preparing update" forever for CSS-only
1792
+ // edits because `handleCssUpdates` is a leaf — there's no
1793
+ // downstream module-evaluation path that would hit the queue's
1794
+ // 'complete' transition.
1795
+ const cssCount = msg.updates.length;
1796
+ try {
1797
+ setUpdateOverlayStage('reimporting', { detail: buildCssApplyingDetail(cssCount) });
1798
+ }
1799
+ catch { }
1515
1800
  try {
1516
1801
  const origin = msg.origin || getHttpOriginForVite() || deriveHttpOrigin(getHMRWsUrl());
1517
1802
  await handleCssUpdates(msg.updates, origin);
1803
+ try {
1804
+ setUpdateOverlayStage('complete', { detail: buildCssAppliedDetail(cssCount) });
1805
+ }
1806
+ catch { }
1518
1807
  return;
1519
1808
  }
1520
1809
  catch (e) {
1521
1810
  console.warn('[hmr-client] CSS updates handling failed:', e);
1811
+ try {
1812
+ setUpdateOverlayStage('complete', { detail: 'CSS update failed' });
1813
+ }
1814
+ catch { }
1522
1815
  return;
1523
1816
  }
1524
1817
  }
1525
1818
  if (msg.type === 'ns:vue-sfc-registry') {
1526
- handleVueSfcRegistry(msg);
1819
+ CLIENT_STRATEGY?.handleSfcRegistry?.(msg);
1527
1820
  return;
1528
1821
  }
1529
1822
  if (msg.type === 'ns:vue-sfc-registry-update') {
1530
1823
  if (typeof msg.version === 'number')
1531
1824
  setGraphVersion(msg.version);
1532
- const comp = await handleVueSfcRegistryUpdate(msg, getGraphVersion());
1533
- if (comp) {
1534
- await performResetRoot(comp);
1535
- }
1825
+ // `ns:hmr-pending` already set the overlay to 'received' (5%). The Vue
1826
+ // strategy walks 'evicting' → 'reimporting' → 'rebooting' → 'complete'
1827
+ // around the SFC load + reset so the toast always lands on 'complete'
1828
+ // (or a failure detail) and the auto-hide timer can dismiss it.
1829
+ await CLIENT_STRATEGY?.handleSfcRegistryUpdate?.(msg, getGraphVersion(), { getCore, verbose: VERBOSE, performResetRoot, getOverlay: getHmrOverlayApi });
1536
1830
  return;
1537
1831
  }
1538
1832
  }
@@ -1552,7 +1846,7 @@ function normalizeComponent(input, nameHint) {
1552
1846
  }
1553
1847
  // If provided a render function, wrap with defineComponent
1554
1848
  if (typeof input === 'function') {
1555
- ensureVueGlobals();
1849
+ CLIENT_STRATEGY?.beforeNavigateBuild?.();
1556
1850
  const comp = globalThis.defineComponent
1557
1851
  ? globalThis.defineComponent({
1558
1852
  name: nameHint || input.name || 'AnonymousSFC',
@@ -1563,7 +1857,7 @@ function normalizeComponent(input, nameHint) {
1563
1857
  }
1564
1858
  // If object has a render function property
1565
1859
  if (input?.render && typeof input.render === 'function') {
1566
- ensureVueGlobals();
1860
+ CLIENT_STRATEGY?.beforeNavigateBuild?.();
1567
1861
  const comp = globalThis.defineComponent
1568
1862
  ? globalThis.defineComponent({
1569
1863
  name: nameHint || input.name || 'AnonymousSFC',
@@ -1621,35 +1915,32 @@ async function performResetRoot(newComponent) {
1621
1915
  if (cachedRoot)
1622
1916
  return cachedRoot;
1623
1917
  try {
1624
- switch (TARGET_FLAVOR) {
1625
- case 'vue':
1626
- cachedRoot = getRootForVue(newComponent, state);
1627
- break;
1628
- case 'typescript': {
1629
- // For TS flavor, treat the component as a factory or direct NS view.
1630
- let root = null;
1631
- try {
1632
- if (typeof newComponent === 'function') {
1633
- root = newComponent();
1634
- }
1635
- else {
1636
- root = newComponent;
1637
- }
1918
+ if (CLIENT_STRATEGY?.createRoot) {
1919
+ cachedRoot = CLIENT_STRATEGY.createRoot(newComponent, state);
1920
+ }
1921
+ else if (TARGET_FLAVOR === 'typescript') {
1922
+ // For TS flavor, treat the component as a factory or direct NS view.
1923
+ let root = null;
1924
+ try {
1925
+ if (typeof newComponent === 'function') {
1926
+ root = newComponent();
1638
1927
  }
1639
- catch (e) {
1640
- console.warn('[hmr-client][ts] root factory invocation failed', e);
1928
+ else {
1929
+ root = newComponent;
1641
1930
  }
1642
- cachedRoot = root || {};
1643
- // Heuristic: if the root "looks" like a Frame, prefer frame semantics
1644
- try {
1645
- const name = String(cachedRoot?.constructor?.name || '').replace(/^_+/, '');
1646
- if (/^Frame(\$\d+)?$/.test(name)) {
1647
- rootKind = 'frame';
1648
- }
1931
+ }
1932
+ catch (e) {
1933
+ console.warn('[hmr-client][ts] root factory invocation failed', e);
1934
+ }
1935
+ cachedRoot = root || {};
1936
+ // Heuristic: if the root "looks" like a Frame, prefer frame semantics
1937
+ try {
1938
+ const name = String(cachedRoot?.constructor?.name || '').replace(/^_+/, '');
1939
+ if (/^Frame(\$\d+)?$/.test(name)) {
1940
+ rootKind = 'frame';
1649
1941
  }
1650
- catch { }
1651
- break;
1652
1942
  }
1943
+ catch { }
1653
1944
  }
1654
1945
  return cachedRoot;
1655
1946
  }
@@ -1794,7 +2085,14 @@ async function performResetRoot(newComponent) {
1794
2085
  }
1795
2086
  catch { }
1796
2087
  const isAuthoritativeFrame = !!existingAppFrame && existingAppFrame !== placeholderFrame;
1797
- if (!hadPlaceholder && !isFrameRoot && isAuthoritativeFrame && typeof existingAppFrame.navigate === 'function') {
2088
+ // Vue: skip the in-place navigate path. After `app.mount(NSVRoot)` in getRootForVue the
2089
+ // new Page already has a parent (the freshly-constructed NSVRoot), so an attempt to navigate
2090
+ // the existing app Frame to that same Page completes silently without ever rebinding the
2091
+ // page to the Frame — the screen keeps showing the previous render. resetRootView with a
2092
+ // fresh Frame correctly reparents the Page and is the proven path that produces visible
2093
+ // in-place updates for SFC HMR cycles. Non-Vue flavors keep the legacy navigate fast path.
2094
+ const allowNavigateFastPath = CLIENT_STRATEGY?.allowNavigateFastPath ?? true;
2095
+ if (allowNavigateFastPath && !hadPlaceholder && !isFrameRoot && isAuthoritativeFrame && typeof existingAppFrame.navigate === 'function') {
1798
2096
  try {
1799
2097
  const navEntry = {
1800
2098
  create: () => preparedRoot,
@@ -1957,12 +2255,9 @@ export function initHmrClient(opts) {
1957
2255
  console.log('[hmr-client] deferring WebSocket connection until boot completes');
1958
2256
  setTimeout(waitForBoot, 100);
1959
2257
  }
1960
- // Best-effort: install back wrapper even before first remount; original root may be captured later
1961
- switch (TARGET_FLAVOR) {
1962
- case 'vue':
1963
- ensureBackWrapperInstalled(performResetRoot, getCore);
1964
- break;
1965
- }
2258
+ // Best-effort: install back wrapper even before first remount; original root may be captured later.
2259
+ // Deferred until the dynamically-imported strategy resolves.
2260
+ void CLIENT_STRATEGY_READY.then(() => CLIENT_STRATEGY?.installBackWrapper?.(performResetRoot, getCore));
1966
2261
  }
1967
2262
  export default function startViteHMR(opts) {
1968
2263
  if (VERBOSE)