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

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 (295) hide show
  1. package/README.md +51 -11
  2. package/configuration/angular.d.ts +34 -1
  3. package/configuration/angular.js +369 -159
  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/angular/angular-linker.d.ts +5 -6
  14. package/helpers/angular/angular-linker.js +36 -121
  15. package/helpers/angular/angular-linker.js.map +1 -1
  16. package/helpers/angular/inject-component-hmr-registration.d.ts +112 -0
  17. package/helpers/angular/inject-component-hmr-registration.js +291 -0
  18. package/helpers/angular/inject-component-hmr-registration.js.map +1 -0
  19. package/helpers/angular/inject-hmr-vite-ignore.d.ts +75 -0
  20. package/helpers/angular/inject-hmr-vite-ignore.js +221 -0
  21. package/helpers/angular/inject-hmr-vite-ignore.js.map +1 -0
  22. package/helpers/angular/inline-decorator-component-templates.js +1 -170
  23. package/helpers/angular/inline-decorator-component-templates.js.map +1 -1
  24. package/helpers/angular/js-lexer.d.ts +4 -0
  25. package/helpers/angular/js-lexer.js +182 -0
  26. package/helpers/angular/js-lexer.js.map +1 -0
  27. package/helpers/angular/shared-linker.d.ts +31 -3
  28. package/helpers/angular/shared-linker.js +67 -14
  29. package/helpers/angular/shared-linker.js.map +1 -1
  30. package/helpers/angular/synthesize-decorator-ctor-parameters.js +2 -170
  31. package/helpers/angular/synthesize-decorator-ctor-parameters.js.map +1 -1
  32. package/helpers/angular/synthesize-injectable-factories.js +1 -174
  33. package/helpers/angular/synthesize-injectable-factories.js.map +1 -1
  34. package/helpers/angular/util.d.ts +1 -0
  35. package/helpers/angular/util.js +88 -0
  36. package/helpers/angular/util.js.map +1 -1
  37. package/helpers/app-components.d.ts +2 -1
  38. package/helpers/app-components.js.map +1 -1
  39. package/helpers/app-css-state.d.ts +8 -0
  40. package/helpers/app-css-state.js +8 -0
  41. package/helpers/app-css-state.js.map +1 -0
  42. package/helpers/bundler-context.d.ts +11 -0
  43. package/helpers/bundler-context.js +71 -0
  44. package/helpers/bundler-context.js.map +1 -0
  45. package/helpers/config-as-json.js +10 -0
  46. package/helpers/config-as-json.js.map +1 -1
  47. package/helpers/dev-host.d.ts +341 -0
  48. package/helpers/dev-host.js +617 -0
  49. package/helpers/dev-host.js.map +1 -0
  50. package/helpers/esbuild-platform-resolver.js +4 -1
  51. package/helpers/esbuild-platform-resolver.js.map +1 -1
  52. package/helpers/global-defines.d.ts +51 -0
  53. package/helpers/global-defines.js +77 -0
  54. package/helpers/global-defines.js.map +1 -1
  55. package/helpers/hmr-scope.d.ts +26 -0
  56. package/helpers/hmr-scope.js +67 -0
  57. package/helpers/hmr-scope.js.map +1 -0
  58. package/helpers/init.js +0 -18
  59. package/helpers/init.js.map +1 -1
  60. package/helpers/logging.d.ts +1 -0
  61. package/helpers/logging.js +63 -3
  62. package/helpers/logging.js.map +1 -1
  63. package/helpers/main-entry.d.ts +2 -1
  64. package/helpers/main-entry.js +430 -47
  65. package/helpers/main-entry.js.map +1 -1
  66. package/helpers/nativeclass-esbuild-plugin.d.ts +2 -1
  67. package/helpers/nativeclass-esbuild-plugin.js.map +1 -1
  68. package/helpers/nativeclass-transform.js.map +1 -1
  69. package/helpers/nativeclass-transformer-plugin.d.ts +9 -2
  70. package/helpers/nativeclass-transformer-plugin.js +157 -14
  71. package/helpers/nativeclass-transformer-plugin.js.map +1 -1
  72. package/helpers/nativescript-package-resolver.js +8 -3
  73. package/helpers/nativescript-package-resolver.js.map +1 -1
  74. package/helpers/normalize-id.d.ts +42 -0
  75. package/helpers/normalize-id.js +60 -0
  76. package/helpers/normalize-id.js.map +1 -0
  77. package/helpers/ns-core-url.d.ts +88 -0
  78. package/helpers/ns-core-url.js +191 -0
  79. package/helpers/ns-core-url.js.map +1 -0
  80. package/helpers/package-platform-aliases.js +4 -3
  81. package/helpers/package-platform-aliases.js.map +1 -1
  82. package/helpers/platform-types.d.ts +2 -0
  83. package/helpers/platform-types.js +2 -0
  84. package/helpers/platform-types.js.map +1 -0
  85. package/helpers/prelink-angular.js +12 -33
  86. package/helpers/prelink-angular.js.map +1 -1
  87. package/helpers/project.d.ts +35 -0
  88. package/helpers/project.js +120 -2
  89. package/helpers/project.js.map +1 -1
  90. package/helpers/resolver.js +17 -2
  91. package/helpers/resolver.js.map +1 -1
  92. package/helpers/solid-jsx-deps.d.ts +15 -0
  93. package/helpers/solid-jsx-deps.js +178 -0
  94. package/helpers/solid-jsx-deps.js.map +1 -0
  95. package/helpers/ts-config-paths.d.ts +14 -0
  96. package/helpers/ts-config-paths.js +89 -8
  97. package/helpers/ts-config-paths.js.map +1 -1
  98. package/helpers/typescript-check.d.ts +2 -1
  99. package/helpers/typescript-check.js.map +1 -1
  100. package/helpers/workers.d.ts +20 -19
  101. package/helpers/workers.js +624 -4
  102. package/helpers/workers.js.map +1 -1
  103. package/hmr/client/css-handler.d.ts +1 -0
  104. package/hmr/client/css-handler.js +33 -20
  105. package/hmr/client/css-handler.js.map +1 -1
  106. package/hmr/client/css-update-overlay.d.ts +18 -0
  107. package/hmr/client/css-update-overlay.js +27 -0
  108. package/hmr/client/css-update-overlay.js.map +1 -0
  109. package/hmr/client/hmr-pending-overlay.d.ts +27 -0
  110. package/hmr/client/hmr-pending-overlay.js +50 -0
  111. package/hmr/client/hmr-pending-overlay.js.map +1 -0
  112. package/hmr/client/index.js +419 -15
  113. package/hmr/client/index.js.map +1 -1
  114. package/hmr/client/utils.d.ts +6 -1
  115. package/hmr/client/utils.js +184 -8
  116. package/hmr/client/utils.js.map +1 -1
  117. package/hmr/client/vue-sfc-update-overlay.d.ts +82 -0
  118. package/hmr/client/vue-sfc-update-overlay.js +133 -0
  119. package/hmr/client/vue-sfc-update-overlay.js.map +1 -0
  120. package/hmr/entry-runtime.d.ts +2 -1
  121. package/hmr/entry-runtime.js +252 -65
  122. package/hmr/entry-runtime.js.map +1 -1
  123. package/hmr/frameworks/angular/client/index.d.ts +1 -0
  124. package/hmr/frameworks/angular/client/index.js +778 -20
  125. package/hmr/frameworks/angular/client/index.js.map +1 -1
  126. package/hmr/frameworks/angular/server/linker.js +1 -4
  127. package/hmr/frameworks/angular/server/linker.js.map +1 -1
  128. package/hmr/frameworks/angular/server/strategy.js +13 -15
  129. package/hmr/frameworks/angular/server/strategy.js.map +1 -1
  130. package/hmr/frameworks/solid/server/strategy.js +3 -18
  131. package/hmr/frameworks/solid/server/strategy.js.map +1 -1
  132. package/hmr/frameworks/typescript/server/strategy.js +2 -15
  133. package/hmr/frameworks/typescript/server/strategy.js.map +1 -1
  134. package/hmr/frameworks/vue/client/index.js +30 -199
  135. package/hmr/frameworks/vue/client/index.js.map +1 -1
  136. package/hmr/helpers/ast-normalizer.js +52 -5
  137. package/hmr/helpers/ast-normalizer.js.map +1 -1
  138. package/hmr/helpers/cjs-named-exports.d.ts +23 -0
  139. package/hmr/helpers/cjs-named-exports.js +152 -0
  140. package/hmr/helpers/cjs-named-exports.js.map +1 -0
  141. package/hmr/helpers/package-exports.d.ts +16 -0
  142. package/hmr/helpers/package-exports.js +396 -0
  143. package/hmr/helpers/package-exports.js.map +1 -0
  144. package/hmr/server/angular-root-component.d.ts +79 -0
  145. package/hmr/server/angular-root-component.js +149 -0
  146. package/hmr/server/angular-root-component.js.map +1 -0
  147. package/hmr/server/constants.js +13 -4
  148. package/hmr/server/constants.js.map +1 -1
  149. package/hmr/server/core-sanitize.d.ts +90 -7
  150. package/hmr/server/core-sanitize.js +211 -56
  151. package/hmr/server/core-sanitize.js.map +1 -1
  152. package/hmr/server/framework-strategy.d.ts +9 -19
  153. package/hmr/server/hmr-module-graph.d.ts +37 -0
  154. package/hmr/server/hmr-module-graph.js +214 -0
  155. package/hmr/server/hmr-module-graph.js.map +1 -0
  156. package/hmr/server/import-map.js +60 -8
  157. package/hmr/server/import-map.js.map +1 -1
  158. package/hmr/server/index.js +1 -0
  159. package/hmr/server/index.js.map +1 -1
  160. package/hmr/server/ns-core-cjs-shape.d.ts +204 -0
  161. package/hmr/server/ns-core-cjs-shape.js +271 -0
  162. package/hmr/server/ns-core-cjs-shape.js.map +1 -0
  163. package/hmr/server/ns-rt-bridge.d.ts +51 -0
  164. package/hmr/server/ns-rt-bridge.js +131 -0
  165. package/hmr/server/ns-rt-bridge.js.map +1 -0
  166. package/hmr/server/ns-rt-route.d.ts +5 -0
  167. package/hmr/server/ns-rt-route.js +35 -0
  168. package/hmr/server/ns-rt-route.js.map +1 -0
  169. package/hmr/server/perf-instrumentation.d.ts +114 -0
  170. package/hmr/server/perf-instrumentation.js +195 -0
  171. package/hmr/server/perf-instrumentation.js.map +1 -0
  172. package/hmr/server/require-guard.d.ts +1 -0
  173. package/hmr/server/require-guard.js +12 -0
  174. package/hmr/server/require-guard.js.map +1 -0
  175. package/hmr/server/route-helpers.d.ts +7 -0
  176. package/hmr/server/route-helpers.js +13 -0
  177. package/hmr/server/route-helpers.js.map +1 -0
  178. package/hmr/server/server-origin.d.ts +12 -0
  179. package/hmr/server/server-origin.js +66 -0
  180. package/hmr/server/server-origin.js.map +1 -0
  181. package/hmr/server/shared-transform-request.js +12 -5
  182. package/hmr/server/shared-transform-request.js.map +1 -1
  183. package/hmr/server/vendor-bare-module-shims.d.ts +4 -0
  184. package/hmr/server/vendor-bare-module-shims.js +80 -0
  185. package/hmr/server/vendor-bare-module-shims.js.map +1 -0
  186. package/hmr/server/vite-plugin.js +60 -42
  187. package/hmr/server/vite-plugin.js.map +1 -1
  188. package/hmr/server/websocket-angular-entry.js +1 -1
  189. package/hmr/server/websocket-angular-entry.js.map +1 -1
  190. package/hmr/server/websocket-angular-hot-update.d.ts +17 -0
  191. package/hmr/server/websocket-angular-hot-update.js +176 -2
  192. package/hmr/server/websocket-angular-hot-update.js.map +1 -1
  193. package/hmr/server/websocket-core-bridge.d.ts +41 -6
  194. package/hmr/server/websocket-core-bridge.js +72 -75
  195. package/hmr/server/websocket-core-bridge.js.map +1 -1
  196. package/hmr/server/websocket-css-hot-update.d.ts +33 -0
  197. package/hmr/server/websocket-css-hot-update.js +65 -0
  198. package/hmr/server/websocket-css-hot-update.js.map +1 -0
  199. package/hmr/server/websocket-device-transform.d.ts +21 -0
  200. package/hmr/server/websocket-device-transform.js +1570 -0
  201. package/hmr/server/websocket-device-transform.js.map +1 -0
  202. package/hmr/server/websocket-graph-upsert.d.ts +15 -0
  203. package/hmr/server/websocket-graph-upsert.js +20 -0
  204. package/hmr/server/websocket-graph-upsert.js.map +1 -1
  205. package/hmr/server/websocket-hmr-pending.d.ts +43 -0
  206. package/hmr/server/websocket-hmr-pending.js +55 -0
  207. package/hmr/server/websocket-hmr-pending.js.map +1 -0
  208. package/hmr/server/websocket-hot-update.d.ts +51 -0
  209. package/hmr/server/websocket-hot-update.js +1160 -0
  210. package/hmr/server/websocket-hot-update.js.map +1 -0
  211. package/hmr/server/websocket-import-map-route.d.ts +15 -0
  212. package/hmr/server/websocket-import-map-route.js +44 -0
  213. package/hmr/server/websocket-import-map-route.js.map +1 -0
  214. package/hmr/server/websocket-module-bindings.js +3 -3
  215. package/hmr/server/websocket-module-bindings.js.map +1 -1
  216. package/hmr/server/websocket-module-specifiers.d.ts +66 -2
  217. package/hmr/server/websocket-module-specifiers.js +202 -19
  218. package/hmr/server/websocket-module-specifiers.js.map +1 -1
  219. package/hmr/server/websocket-ns-core.d.ts +21 -0
  220. package/hmr/server/websocket-ns-core.js +305 -0
  221. package/hmr/server/websocket-ns-core.js.map +1 -0
  222. package/hmr/server/websocket-ns-entry.d.ts +22 -0
  223. package/hmr/server/websocket-ns-entry.js +150 -0
  224. package/hmr/server/websocket-ns-entry.js.map +1 -0
  225. package/hmr/server/websocket-ns-m-paths.d.ts +3 -0
  226. package/hmr/server/websocket-ns-m-paths.js +92 -0
  227. package/hmr/server/websocket-ns-m-paths.js.map +1 -0
  228. package/hmr/server/websocket-ns-m-request.d.ts +45 -0
  229. package/hmr/server/websocket-ns-m-request.js +196 -0
  230. package/hmr/server/websocket-ns-m-request.js.map +1 -0
  231. package/hmr/server/websocket-ns-m.d.ts +34 -0
  232. package/hmr/server/websocket-ns-m.js +853 -0
  233. package/hmr/server/websocket-ns-m.js.map +1 -0
  234. package/hmr/server/websocket-served-module-helpers.d.ts +39 -0
  235. package/hmr/server/websocket-served-module-helpers.js +654 -0
  236. package/hmr/server/websocket-served-module-helpers.js.map +1 -0
  237. package/hmr/server/websocket-sfc.d.ts +24 -0
  238. package/hmr/server/websocket-sfc.js +1223 -0
  239. package/hmr/server/websocket-sfc.js.map +1 -0
  240. package/hmr/server/websocket-txn.d.ts +6 -0
  241. package/hmr/server/websocket-txn.js +39 -0
  242. package/hmr/server/websocket-txn.js.map +1 -0
  243. package/hmr/server/websocket-vendor-unifier.d.ts +10 -0
  244. package/hmr/server/websocket-vendor-unifier.js +45 -0
  245. package/hmr/server/websocket-vendor-unifier.js.map +1 -0
  246. package/hmr/server/websocket.d.ts +0 -30
  247. package/hmr/server/websocket.js +599 -6038
  248. package/hmr/server/websocket.js.map +1 -1
  249. package/hmr/shared/runtime/boot-placeholder-ui.d.ts +69 -0
  250. package/hmr/shared/runtime/boot-placeholder-ui.js +101 -0
  251. package/hmr/shared/runtime/boot-placeholder-ui.js.map +1 -0
  252. package/hmr/shared/runtime/boot-progress.d.ts +40 -0
  253. package/hmr/shared/runtime/boot-progress.js +128 -0
  254. package/hmr/shared/runtime/boot-progress.js.map +1 -0
  255. package/hmr/shared/runtime/boot-timeline.d.ts +18 -0
  256. package/hmr/shared/runtime/boot-timeline.js +52 -0
  257. package/hmr/shared/runtime/boot-timeline.js.map +1 -0
  258. package/hmr/shared/runtime/dev-overlay-snapshots.d.ts +31 -0
  259. package/hmr/shared/runtime/dev-overlay-snapshots.js +324 -0
  260. package/hmr/shared/runtime/dev-overlay-snapshots.js.map +1 -0
  261. package/hmr/shared/runtime/dev-overlay.d.ts +75 -26
  262. package/hmr/shared/runtime/dev-overlay.js +990 -260
  263. package/hmr/shared/runtime/dev-overlay.js.map +1 -1
  264. package/hmr/shared/runtime/module-provenance.js +1 -4
  265. package/hmr/shared/runtime/module-provenance.js.map +1 -1
  266. package/hmr/shared/runtime/root-placeholder-view.d.ts +19 -0
  267. package/hmr/shared/runtime/root-placeholder-view.js +310 -0
  268. package/hmr/shared/runtime/root-placeholder-view.js.map +1 -0
  269. package/hmr/shared/runtime/root-placeholder.js +352 -194
  270. package/hmr/shared/runtime/root-placeholder.js.map +1 -1
  271. package/hmr/shared/runtime/session-bootstrap.js +164 -1
  272. package/hmr/shared/runtime/session-bootstrap.js.map +1 -1
  273. package/hmr/shared/runtime/vendor-bootstrap.js +1 -9
  274. package/hmr/shared/runtime/vendor-bootstrap.js.map +1 -1
  275. package/hmr/shared/vendor/manifest-collect.d.ts +32 -0
  276. package/hmr/shared/vendor/manifest-collect.js +512 -0
  277. package/hmr/shared/vendor/manifest-collect.js.map +1 -0
  278. package/hmr/shared/vendor/manifest-loader.d.ts +2 -1
  279. package/hmr/shared/vendor/manifest-loader.js +3 -2
  280. package/hmr/shared/vendor/manifest-loader.js.map +1 -1
  281. package/hmr/shared/vendor/manifest.d.ts +1 -5
  282. package/hmr/shared/vendor/manifest.js +102 -739
  283. package/hmr/shared/vendor/manifest.js.map +1 -1
  284. package/hmr/shared/vendor/vendor-device-shim.d.ts +1 -0
  285. package/hmr/shared/vendor/vendor-device-shim.js +208 -0
  286. package/hmr/shared/vendor/vendor-device-shim.js.map +1 -0
  287. package/hmr/shared/vendor/vendor-esbuild-plugins.d.ts +16 -0
  288. package/hmr/shared/vendor/vendor-esbuild-plugins.js +203 -0
  289. package/hmr/shared/vendor/vendor-esbuild-plugins.js.map +1 -0
  290. package/index.d.ts +1 -0
  291. package/index.js +5 -0
  292. package/index.js.map +1 -1
  293. package/package.json +55 -11
  294. package/runtime/core-aliases-early.js +17 -41
  295. package/runtime/core-aliases-early.js.map +1 -1
@@ -1,7 +1,61 @@
1
1
  import path from 'path';
2
+ import { createRequire } from 'node:module';
2
3
  import { nsConfigToJson, resolveNativeScriptPlatformFile } from './utils.js';
3
- export function getWorkerPlugins(platform) {
4
- return [
4
+ import { createTsConfigPathsResolver, getTsConfigData } from './ts-config-paths.js';
5
+ import { packagePlatformResolverPlugin } from './package-platform-aliases.js';
6
+ import { nativescriptPackageResolver } from './nativescript-package-resolver.js';
7
+ import { findMonorepoWorkspaceRoot, getProjectRootPath } from './project.js';
8
+ import { normalizeModuleId } from './normalize-id.js';
9
+ const nodeRequire = createRequire(import.meta.url);
10
+ // Stub out webpack-style `nativescript-worker-loader!./worker.js` imports.
11
+ // Some packages (e.g. `nativescript-sqlite-commercial`) still ship a webpack 4
12
+ // branch like:
13
+ // if (global.TNS_WEBPACK >= 5) { worker = new Worker("./worker.js"); }
14
+ // else { require("nativescript-worker-loader!./worker.js"); }
15
+ // At runtime under @nativescript/vite, `global.TNS_WEBPACK` is undefined so the
16
+ // loader-prefix branch is never executed — but Rolldown still statically scans
17
+ // it and fails to resolve the webpack-only specifier. Returning a virtual stub
18
+ // module satisfies the static graph without touching runtime semantics.
19
+ const NS_WORKER_LOADER_STUB_ID = '\0ns-worker-loader-stub';
20
+ export function nativescriptWorkerLoaderStubPlugin() {
21
+ return {
22
+ name: 'nativescript-worker-loader-stub',
23
+ enforce: 'pre',
24
+ resolveId(id) {
25
+ if (typeof id === 'string' && id.startsWith('nativescript-worker-loader!')) {
26
+ return NS_WORKER_LOADER_STUB_ID;
27
+ }
28
+ return null;
29
+ },
30
+ load(id) {
31
+ if (id === NS_WORKER_LOADER_STUB_ID) {
32
+ // The default export is a constructor — emulate `new SqliteWorker()`
33
+ // so the legacy code path doesn't crash if it ever runs accidentally.
34
+ return ['const message = "nativescript-worker-loader! is a webpack-only loader prefix and is not supported under Vite. Update the calling package to use `new Worker(new URL(...))` for worker entry points.";', 'function NSWorkerLoaderStub() { throw new Error(message); }', 'export default NSWorkerLoaderStub;'].join('\n');
35
+ }
36
+ return null;
37
+ },
38
+ };
39
+ }
40
+ // Worker bundles run as separate Rolldown builds and do NOT inherit `config.plugins`
41
+ // at build time (see https://vite.dev/config/worker-options#worker-plugins). To match
42
+ // the main bundle's module resolution behavior, mirror the bare-specifier resolvers
43
+ // that the main config registers — most importantly the tsconfig `paths` resolver,
44
+ // without which workspace path aliases (e.g. `@scope/lib/util`) fail to resolve in
45
+ // any code reachable from a `new Worker(new URL(...))` entry point.
46
+ export function getWorkerPlugins(platformOrOpts) {
47
+ const opts = typeof platformOrOpts === 'string' ? { platform: platformOrOpts } : platformOrOpts;
48
+ const { platform, verbose } = opts;
49
+ // Reuse the same tsconfig data the main config does. `getTsConfigData` is internally
50
+ // memoized by config path, so this is essentially free on subsequent calls.
51
+ const tsConfig = getTsConfigData({ platform, verbose });
52
+ const tsConfigResolver = createTsConfigPathsResolver({
53
+ paths: tsConfig.paths,
54
+ baseUrl: tsConfig.baseUrl,
55
+ platform,
56
+ verbose,
57
+ });
58
+ const plugins = [
5
59
  // Handle ~/package.json virtual module for workers
6
60
  {
7
61
  name: 'worker-virtual-package-json',
@@ -37,7 +91,9 @@ export function getWorkerPlugins(platform) {
37
91
  // Use the existing NativeScript platform file resolver
38
92
  const platformResolvedFile = resolveNativeScriptPlatformFile(testPath, platform);
39
93
  if (platformResolvedFile) {
40
- return platformResolvedFile;
94
+ // Canonicalize so the worker bundle dedupes core the same way
95
+ // the main bundle does (forward slash + uppercase Windows drive).
96
+ return normalizeModuleId(platformResolvedFile);
41
97
  }
42
98
  }
43
99
  return null;
@@ -61,6 +117,558 @@ export function getWorkerPlugins(platform) {
61
117
  },
62
118
  },
63
119
  ];
120
+ // Mirror the main-config bare-specifier resolvers for workers. Without these,
121
+ // workspace tsconfig paths and platform-specific package mains fail to resolve
122
+ // when code is pulled into a worker bundle.
123
+ if (tsConfigResolver) {
124
+ plugins.push(tsConfigResolver);
125
+ }
126
+ plugins.push(packagePlatformResolverPlugin({ tsConfig, platform, verbose }));
127
+ plugins.push(nativescriptPackageResolver(platform));
128
+ plugins.push(nativescriptWorkerLoaderStubPlugin());
129
+ return plugins;
130
+ }
131
+ // In Vite dev/HMR mode, Vite's built-in `workerImportMetaUrlPlugin` rewrites
132
+ // `new Worker(new URL('./foo.worker', import.meta.url))` into
133
+ // `new Worker(new URL(/* @vite-ignore */"/src/.../foo.worker.ts?worker_file&type=classic", '' + import.meta.url))`.
134
+ // That output breaks under NativeScript for two independent reasons:
135
+ //
136
+ // 1. TypeError on `new URL(spec, '' + import.meta.url)`. The iOS V8 runtime's
137
+ // `InitializeImportMetaObject` callback (in NativeScript/runtime/Runtime.mm)
138
+ // blindly prefixes the module's registry key with `file://`. For HTTP-served
139
+ // HMR modules the key is already `http://localhost:5173/ns/m/...`, so the
140
+ // callback emits `import.meta.url = "file://http://localhost:5173/ns/m/..."`
141
+ // — a malformed URL that fails the WHATWG URL parser's base check. Other
142
+ // `new URL(spec, import.meta.url)` sites in the served pipeline are wrapped
143
+ // in `try/catch` and silently fall through; the worker creation site is not.
144
+ //
145
+ // 2. Pipeline routing mismatch.
146
+ // Even with a valid `import.meta.url`, the resolved URL points at Vite's
147
+ // `?worker_file&type=classic` middleware, which serves a self-contained
148
+ // worker bundle whose internal imports use `/src/...` and `/@fs/...` URLs
149
+ // that bypass our `/ns/m/` wrapping pipeline. The worker would crash on
150
+ // its first transitive import.
151
+ //
152
+ // We use `__NS_HTTP_ORIGIN__` (set by the entry runtime in
153
+ // `hmr/entry-runtime.ts`) so the URL stays correct when the device connects
154
+ // via a non-localhost origin (e.g. `http://192.168.x.x:5173`).
155
+ //
156
+ // Counterpart for production builds: `workerUrlPlugin()` below, which runs in
157
+ // `generateBundle` and rewrites a similar pattern to `new Worker('~/' + ...)`.
158
+ // Matches Vite-emitted dev shape:
159
+ // new Worker(new URL(/* @vite-ignore */ "/src/.../foo.worker.ts?worker_file&type=classic", '' + import.meta.url))
160
+ // The `/* @vite-ignore */` and `'' +` coercion are constants Vite always emits
161
+ // (see `workerImportMetaUrlPlugin` in vite/dist/node/chunks/node.js), so we
162
+ // match them as fixed structure rather than as optional fragments. The asset
163
+ // path can use single, double, or template-literal quotes.
164
+ const WORKER_VITE_DEV_RE = /new\s+Worker\s*\(\s*new\s+URL\s*\(\s*\/\*\s*@vite-ignore\s*\*\/\s*(['"`])([^'"`]+)\1\s*,\s*(?:'\s*'|"\s*"|`\s*`)\s*\+\s*import\.meta\.url\s*\)\s*(,\s*\{[^}]*\})?\s*\)/g;
165
+ const SKIP_TRANSFORM_ID_RE = /(?:^|\/)(?:node_modules|\.vite)\//;
166
+ // Strip Vite's `?worker_file&type=classic` query suffix (and any extension) so
167
+ // the resulting URL matches the canonical `/ns/m/<rel-without-ext>` shape that
168
+ // the NS HMR pipeline serves. Exported for unit testing.
169
+ export function viteWorkerAssetPathToNsMUrl(assetPath, projectRoot, workspaceRoot) {
170
+ if (typeof assetPath !== 'string' || !assetPath) {
171
+ return null;
172
+ }
173
+ // Vite emits asset paths in two shapes during dev/HMR:
174
+ // 1. Project-relative: "/src/.../foo.worker.ts?worker_file&type=classic"
175
+ // 2. Absolute fs: "/@fs/Users/.../src/.../foo.worker.ts?worker_file&type=classic"
176
+ // We only need to match #1 here — the project-relative form Vite uses for
177
+ // project-local files. Absolute-fs paths come from outside the project root
178
+ // (e.g. workspace libs in a monorepo), and we hand those off to Vite's
179
+ // default behavior rather than try to map them into `/ns/m/`.
180
+ const queryIdx = assetPath.indexOf('?');
181
+ const cleanPath = queryIdx === -1 ? assetPath : assetPath.slice(0, queryIdx);
182
+ const query = queryIdx === -1 ? '' : assetPath.slice(queryIdx);
183
+ // Confirm this is the worker_file query Vite emits — leaves non-worker URLs
184
+ // (e.g. asset URLs from `assetImportMetaUrlPlugin`) alone.
185
+ if (!/[?&]worker_file(?:&|=|$)/.test(query)) {
186
+ return null;
187
+ }
188
+ // Project-relative: "/src/..." → "/ns/m/src/..."
189
+ if (cleanPath.startsWith('/') && !cleanPath.startsWith('/@fs/')) {
190
+ // Strip the rewritable extension so the URL matches the canonical
191
+ // `/ns/m/<rel-without-ext>` shape served by the HMR middleware.
192
+ const noExt = cleanPath.replace(/\.(?:ts|tsx|mjs|cjs|js|jsx)$/, '');
193
+ return `/ns/m${noExt}`;
194
+ }
195
+ // Absolute-fs: "/@fs/abs/path/..." — try to map into project or workspace roots.
196
+ if (cleanPath.startsWith('/@fs/')) {
197
+ const absPath = cleanPath.slice('/@fs'.length); // keep leading '/'
198
+ const toPosix = (value) => value.replace(/\\/g, '/');
199
+ const stripTrailing = (value) => value.replace(/\/+$/, '');
200
+ const target = toPosix(absPath);
201
+ const projectPosix = stripTrailing(toPosix(path.resolve(projectRoot)));
202
+ const workspacePosix = workspaceRoot ? stripTrailing(toPosix(path.resolve(workspaceRoot))) : null;
203
+ const tryRoot = (root) => {
204
+ if (!root)
205
+ return null;
206
+ if (target === root)
207
+ return '/ns/m';
208
+ if (target.startsWith(`${root}/`)) {
209
+ const rel = target.slice(root.length); // includes leading '/'
210
+ const noExt = rel.replace(/\.(?:ts|tsx|mjs|cjs|js|jsx)$/, '');
211
+ return `/ns/m${noExt}`;
212
+ }
213
+ return null;
214
+ };
215
+ return tryRoot(projectPosix) ?? tryRoot(workspacePosix);
216
+ }
217
+ return null;
218
+ }
219
+ // Runtime helper injected at the top of every HMR-transformed module that
220
+ // instantiates a Worker. Wraps each `new Worker(...)` call in
221
+ // `__nsHmrTrackWorker(...)`, which registers the worker for cleanup via
222
+ // TWO complementary mechanisms:
223
+ //
224
+ // 1. STANDARDS-COMPLIANT — `import.meta.hot.dispose(cb)` per Vite spec.
225
+ // The NS iOS runtime's `HMRSupport.mm` registers the callback in
226
+ // `g_hotDispose` (per-module). The Angular HMR client drains it
227
+ // via `globalThis.__nsRunHmrDispose()` before reboot. This is the
228
+ // same primitive every Vite plugin author already knows; users
229
+ // can register their own dispose callbacks the same way.
230
+ //
231
+ // 2. RUNTIME-AUTHORITATIVE — `globalThis.__NS_HMR_WORKERS__` Set
232
+ // drained by the HMR client (or by the runtime's
233
+ // `__nsTerminateAllWorkers()`). This catches workers spawned in
234
+ // modules that aren't being individually re-evaluated (e.g. the
235
+ // `app.component.ts` constructor that re-runs on every Angular
236
+ // reboot, even though `app.component.ts` itself isn't being
237
+ // replaced — its `dispose` callbacks don't fire per Vite spec).
238
+ //
239
+ // ## Why both?
240
+ //
241
+ // `import.meta.hot.dispose()` is correct for modules being replaced.
242
+ // But Angular HMR's `__reboot_ng_modules__` re-creates the component
243
+ // tree without re-evaluating modules — `app.component.ts`'s top-level
244
+ // dispose callback wouldn't fire on a `login.component.html` save,
245
+ // even though Angular re-runs `AppComponent`'s constructor and spawns
246
+ // a fresh worker. The runtime-authoritative path catches this:
247
+ // `__nsTerminateAllWorkers()` walks `Caches::Workers` (the iOS
248
+ // runtime's authoritative worker registry) and kills every live
249
+ // worker regardless of which module spawned it.
250
+ //
251
+ // ## Design notes
252
+ //
253
+ // * Helper injected ONLY in modules that have at least one
254
+ // `new Worker(new URL(...))` call we rewrote. Modules without
255
+ // workers pay no prelude cost.
256
+ // * `terminate()` is the only cleanup primitive. Apps needing
257
+ // graceful shutdown should send a custom message before HMR via
258
+ // their own pre-update hook (e.g.
259
+ // `import.meta.hot.on('vite:beforeUpdate', ...)`).
260
+ // * `try/catch` around `terminate()` so an already-dead worker
261
+ // doesn't break the HMR cycle (e.g. user code already terminated
262
+ // it).
263
+ // * Both mechanisms are best-effort and idempotent: terminating an
264
+ // already-dead worker is a no-op, and clearing an already-empty
265
+ // Set is a no-op. Belt-and-suspenders is the right policy here.
266
+ // * `addEventListener('terminated', ...)` would be nicer than a Set
267
+ // of references, but iOS Worker doesn't fire that event reliably,
268
+ // so we use the Set + opportunistic cleanup approach.
269
+ const HMR_WORKER_DISPOSE_HELPER = [
270
+ '/* Injected by @nativescript/vite workerHmrUrlPlugin (HMR worker auto-dispose) */',
271
+ 'const __nsHmrTrackWorker = /* @__PURE__ */ (function () {',
272
+ // Per-module Set so `import.meta.hot.dispose` only terminates
273
+ // workers SPAWNED BY THIS MODULE — matches Vite spec semantics.
274
+ // The shared `globalThis.__NS_HMR_WORKERS__` Set below is the
275
+ // belt-and-suspenders fallback the runtime can also drain
276
+ // universally on Angular reboot.
277
+ '\tconst __nsModuleWorkers = new Set();',
278
+ '\tlet __nsDisposeRegistered = false;',
279
+ '\treturn function __nsHmrTrackWorker(w) {',
280
+ '\t\tif (!w) return w;',
281
+ // Path 1: register in the legacy global Set. Kept for backward
282
+ // compatibility with older NS runtimes that don't yet ship
283
+ // `__nsTerminateAllWorkers()` or `__nsRunHmrDispose()`. Once those
284
+ // runtime APIs are universally adopted this can be removed —
285
+ // everything else here is standards-compliant.
286
+ '\t\ttry {',
287
+ '\t\t\tconst __nsG = typeof globalThis !== "undefined" ? globalThis : (typeof self !== "undefined" ? self : {});',
288
+ '\t\t\tif (!__nsG.__NS_HMR_WORKERS__) __nsG.__NS_HMR_WORKERS__ = new Set();',
289
+ '\t\t\t__nsG.__NS_HMR_WORKERS__.add(w);',
290
+ '\t\t} catch (_e) {}',
291
+ // Path 2: standards-compliant `import.meta.hot.dispose` registration.
292
+ // We re-register the disposer on EVERY worker spawn rather than
293
+ // just the first, because per Vite spec dispose callbacks are
294
+ // consumed when they fire — the runtime drains them out of its
295
+ // registry on each HMR cycle. The closure-level
296
+ // `__nsDisposeRegistered` flag is reset by the disposer itself
297
+ // after firing, so we register exactly once per HMR cycle (not
298
+ // once per worker spawn within a cycle): the second `add()` in
299
+ // the same cycle sees `__nsDisposeRegistered === true` and skips
300
+ // re-registration. After the cycle completes the flag flips back
301
+ // to false and the next worker spawn registers a fresh disposer.
302
+ // Modules that never instantiate a worker never register a
303
+ // disposer at all.
304
+ '\t\t__nsModuleWorkers.add(w);',
305
+ '\t\tif (!__nsDisposeRegistered && typeof import.meta !== "undefined" && import.meta && import.meta.hot && typeof import.meta.hot.dispose === "function") {',
306
+ '\t\t\t__nsDisposeRegistered = true;',
307
+ '\t\t\timport.meta.hot.dispose(function () {',
308
+ '\t\t\t\tfor (const __nsW of __nsModuleWorkers) {',
309
+ '\t\t\t\t\ttry { typeof __nsW.terminate === "function" && __nsW.terminate(); } catch (_e) {}',
310
+ '\t\t\t\t}',
311
+ '\t\t\t\t__nsModuleWorkers.clear();',
312
+ // Re-arm so the next worker spawn (in the new module instance
313
+ // after the HMR reboot) registers a fresh disposer for the next
314
+ // cycle. Without this re-arm, only cycle #1 uses the dispose
315
+ // path and cycles #2+ fall through to the worker terminator
316
+ // fallback — observable but suboptimal (uses two log lines
317
+ // instead of one and pays the worker terminator's iteration
318
+ // cost unnecessarily).
319
+ '\t\t\t\t__nsDisposeRegistered = false;',
320
+ '\t\t\t});',
321
+ '\t\t}',
322
+ '\t\treturn w;',
323
+ '\t};',
324
+ '})();',
325
+ '',
326
+ ].join('\n');
327
+ export function workerHmrUrlPlugin(opts) {
328
+ const { verbose } = opts || {};
329
+ let projectRoot = '';
330
+ let workspaceRoot = null;
331
+ return {
332
+ name: 'nativescript-worker-hmr-url-transform',
333
+ // Run AFTER Vite's built-in `workerImportMetaUrlPlugin` (and AFTER
334
+ // the Angular plugin, which discards upstream `code` by re-compiling
335
+ // from disk). At this point Vite has already rewritten the user's
336
+ // `new Worker(new URL('./foo', import.meta.url))` into its dev shape
337
+ // `new Worker(new URL(/* @vite-ignore */"/src/.../foo.worker.ts?worker_file&type=classic", '' + import.meta.url))`.
338
+ // We match that shape and replace it with a plain string URL that
339
+ // routes through `/ns/m/` so the worker's internal imports get the
340
+ // same HMR treatment as the main thread.
341
+ enforce: 'post',
342
+ // Dev/HMR only — `workerUrlPlugin()` below handles the production build.
343
+ apply: 'serve',
344
+ configResolved(config) {
345
+ projectRoot = path.resolve(config.root || getProjectRootPath());
346
+ workspaceRoot = findMonorepoWorkspaceRoot(projectRoot);
347
+ },
348
+ transform(code, id) {
349
+ if (!code || code.indexOf('new Worker') === -1 || code.indexOf('import.meta.url') === -1) {
350
+ return null;
351
+ }
352
+ // `id` may carry a Vite query suffix (`?vue&type=script`, `?used`, …);
353
+ // strip it so path matching works against real fs paths.
354
+ const cleanId = id.split('?', 1)[0];
355
+ if (!cleanId || SKIP_TRANSFORM_ID_RE.test(cleanId)) {
356
+ return null;
357
+ }
358
+ let modified = false;
359
+ let workerWraps = 0;
360
+ let newCode = code.replace(WORKER_VITE_DEV_RE, (match, _quote, assetPath, options) => {
361
+ const nsmUrl = viteWorkerAssetPathToNsMUrl(assetPath, projectRoot, workspaceRoot);
362
+ if (!nsmUrl) {
363
+ if (verbose) {
364
+ // eslint-disable-next-line no-console
365
+ console.warn(`[ns-worker-hmr] worker asset path ${JSON.stringify(assetPath)} in ${cleanId} can't be mapped to /ns/m/; leaving Vite's default behavior in place`);
366
+ }
367
+ return match;
368
+ }
369
+ modified = true;
370
+ workerWraps++;
371
+ const optionsTail = options ? options : '';
372
+ // Wrap each `new Worker(...)` in `__nsHmrTrackWorker(...)`
373
+ // so it auto-registers for cleanup on the next HMR
374
+ // dispose. The wrap is transparent — `__nsHmrTrackWorker`
375
+ // returns the worker instance unchanged so callers that
376
+ // assign the result to a variable still get a real
377
+ // Worker.
378
+ return `__nsHmrTrackWorker(new Worker((typeof globalThis !== "undefined" && typeof globalThis.__NS_HTTP_ORIGIN__ === "string" ? globalThis.__NS_HTTP_ORIGIN__ : "") + ${JSON.stringify(nsmUrl)}${optionsTail}))`;
379
+ });
380
+ if (!modified) {
381
+ return null;
382
+ }
383
+ // Inject the helper prelude exactly once at the top of the
384
+ // module. The helper closure self-tracks workers and lazily
385
+ // registers the `import.meta.hot.dispose()` callback on the
386
+ // first wrap, so injecting it unconditionally (whether or not
387
+ // HMR is wired up at module-eval time) is safe.
388
+ newCode = HMR_WORKER_DISPOSE_HELPER + newCode;
389
+ if (verbose) {
390
+ // eslint-disable-next-line no-console
391
+ console.log(`[ns-worker-hmr] rewrote ${workerWraps} Vite worker URL${workerWraps === 1 ? '' : 's'} → /ns/m/ in ${cleanId} (with HMR auto-terminate via globalThis.__NS_HMR_WORKERS__)`);
392
+ }
393
+ // Returning null for the source map keeps Vite's downstream sourcemap
394
+ // composition simple; the per-Worker line shift is small and the
395
+ // frame is rarely the one a developer is debugging.
396
+ return { code: newCode, map: null };
397
+ },
398
+ };
399
+ }
400
+ // Safety-net TypeScript fallback transform.
401
+ //
402
+ // Problem: In HMR mode (where `useAngularCompilationAPI = false`), the
403
+ // `@analogjs/vite-plugin-angular` `config` hook forcibly sets `oxc: false` on
404
+ // the Vite config (see `angular-vite-plugin.js`:
405
+ // `const oxc = pluginOptions.useAngularCompilationAPI ? undefined : (config.oxc ?? false);`).
406
+ // That disables Vite's built-in oxc TypeScript transformer for the whole dev
407
+ // session. The Analog plugin then expects its own `fileEmitter` to strip types
408
+ // from every `.ts` file in the project — but `fileEmitter` only knows about
409
+ // files that are part of the Angular TypeScript program (anything imported
410
+ // directly, or referenced via `templateUrl` / `styleUrls` from a decorated
411
+ // class).
412
+ //
413
+ // Worker entry files fall outside the program. They are only loaded via
414
+ // `new Worker(new URL('./foo.worker', import.meta.url))`, which is NOT an
415
+ // import — it's a URL constructor expression the device resolves at runtime.
416
+ // `fileEmitter(id)` returns nothing for those files, the Analog plugin's
417
+ // transform returns `undefined`, oxc doesn't run (because Analog disabled it),
418
+ // and the raw `.ts` source reaches the device with type annotations intact.
419
+ // V8's parser then chokes on the first `(x: Type)` parameter annotation with
420
+ // `SyntaxError: Unexpected token ':'`.
421
+ //
422
+ // The fix is a small post-enforce transform that re-runs Vite's own
423
+ // `transformWithOxc` on any `.ts`/`.tsx` file that still looks like raw
424
+ // TypeScript after the rest of the pipeline is done. For already-compiled
425
+ // Angular output (pure JS), the detection heuristic short-circuits and we
426
+ // never invoke oxc, so the fast path stays fast.
427
+ //
428
+ // Scope intentionally narrow:
429
+ // * `enforce: 'post'` — only sees final code after every other plugin had a
430
+ // chance to transform.
431
+ // * `apply: 'serve'` — dev/HMR only. Production builds use Rolldown which
432
+ // handles TS natively without needing this net.
433
+ // * Skips `node_modules` / `.vite` — third-party code has its own pipeline,
434
+ // and hitting every transitive dep would be wasteful.
435
+ // * Skips files containing Angular decorators (`@Component`, `@Injectable`,
436
+ // `@NgModule`, `@Directive`, `@Pipe`). Those files belong to the Angular
437
+ // program; if they fell through the Angular plugin we surface Angular's
438
+ // own `"contains Angular decorators but is not in the TypeScript program"`
439
+ // warning rather than silently transforming them with oxc (which would
440
+ // emit a `@oxc-project/runtime/helpers/decorate` import that the app does
441
+ // not depend on, breaking Vite's import-analysis pass).
442
+ // * Regex-based detection — catches the tokens V8 would actually reject.
443
+ // False positives (running oxc on valid JS) are harmless because oxc with
444
+ // `lang: 'ts'` is a no-op on JS; false negatives would only surface as the
445
+ // same error the fix is designed to prevent, so the detector errs toward
446
+ // running the transform when in doubt.
447
+ const TS_ONLY_SYNTAX_RE = new RegExp([
448
+ // `import type { … } from '…'` / `export type { … } from '…'`
449
+ String.raw `\b(?:import|export)\s+type\s`,
450
+ // `interface Foo { … }`
451
+ String.raw `\binterface\s+[A-Z_$][\w$]*\s*[<{]`,
452
+ // `type Foo = …`
453
+ String.raw `\btype\s+[A-Z_$][\w$]*\s*[<=]`,
454
+ // `as Type` assertions — restrict right-hand side to common primitives
455
+ // or PascalCase identifiers to avoid catching unrelated tokens.
456
+ String.raw `\bas\s+(?:string|number|boolean|any|unknown|never|void|[A-Z][\w$]*)\b`,
457
+ // Parameter / destructured type annotations: `(msg: any)`, `(x: T, y: U)`.
458
+ // Anchored to `(` or `,` so we don't match object literal keys like `{ a: 1 }`.
459
+ String.raw `[(,]\s*[\w$]+\s*\??\s*:\s*(?:string|number|boolean|any|unknown|never|void|null|undefined|object|[A-Z][\w$]*(?:<[^>]*>)?(?:\[\])?)\b`,
460
+ // Variable type annotations: `let x: T = …` / `const y: T`
461
+ String.raw `\b(?:const|let|var)\s+[\w$]+\s*:\s*[\w$<>[\]|&., ]+\s*[;=]`,
462
+ // Return type annotations on arrow functions: `): T =>`
463
+ String.raw `\)\s*:\s*(?:string|number|boolean|any|unknown|never|void|[A-Z][\w$]*(?:<[^>]*>)?)\s*(?:=>|\{)`,
464
+ ].join('|'));
465
+ // Decorator shapes that mean "the Angular plugin owns this file, stay out of
466
+ // its way." We do NOT try to compile these ourselves even if the Angular
467
+ // plugin's `fileEmitter` didn't produce output for them — oxc would rewrite
468
+ // the decorators into `import _decorate from "@oxc-project/runtime/helpers/decorate"`
469
+ // calls, Vite's import-analysis would fail to resolve that helper package,
470
+ // and we'd turn a harmless "not in TypeScript program" warning into a fatal
471
+ // import error. Better to let Angular's own warning surface and leave the
472
+ // code untouched.
473
+ const ANGULAR_DECORATOR_RE = /@(?:Component|Directive|Injectable|NgModule|Pipe)\s*\(/;
474
+ const TS_FALLBACK_SKIP_ID_RE = /(?:^|\/)(?:node_modules|\.vite)\//;
475
+ export function tsFallbackTransformPlugin(opts) {
476
+ const { verbose } = opts || {};
477
+ // Cached after the first successful import so repeated transforms don't
478
+ // pay the dynamic-import cost. `null` = not loaded yet; `false` = load
479
+ // attempted and failed (older Vite with no oxc export — we'll skip).
480
+ let cachedTransformWithOxc = null;
481
+ return {
482
+ name: 'nativescript-ts-fallback-transform',
483
+ enforce: 'post',
484
+ apply: 'serve',
485
+ async transform(code, id) {
486
+ if (cachedTransformWithOxc === false)
487
+ return null;
488
+ const cleanId = id.split('?', 1)[0];
489
+ if (!cleanId || !/\.(m?ts|[jt]sx)$/.test(cleanId))
490
+ return null;
491
+ if (TS_FALLBACK_SKIP_ID_RE.test(cleanId))
492
+ return null;
493
+ if (ANGULAR_DECORATOR_RE.test(code))
494
+ return null;
495
+ if (!TS_ONLY_SYNTAX_RE.test(code))
496
+ return null;
497
+ if (cachedTransformWithOxc === null) {
498
+ try {
499
+ // Dynamic import keeps this plugin cross-version-safe: older
500
+ // Vite installs without `transformWithOxc` (pre-Rolldown
501
+ // builds) cleanly disable this fallback instead of crashing.
502
+ const vite = await import('vite');
503
+ if (typeof vite.transformWithOxc === 'function') {
504
+ cachedTransformWithOxc = vite.transformWithOxc;
505
+ }
506
+ else {
507
+ cachedTransformWithOxc = false;
508
+ return null;
509
+ }
510
+ }
511
+ catch {
512
+ cachedTransformWithOxc = false;
513
+ return null;
514
+ }
515
+ }
516
+ try {
517
+ const lang = cleanId.endsWith('tsx') ? 'tsx' : cleanId.endsWith('jsx') ? 'jsx' : 'ts';
518
+ const result = await cachedTransformWithOxc(code, cleanId, { lang });
519
+ if (!result || typeof result.code !== 'string')
520
+ return null;
521
+ if (verbose) {
522
+ // eslint-disable-next-line no-console
523
+ console.log(`[ns-ts-fallback] type-stripped ${cleanId}`);
524
+ }
525
+ return { code: result.code, map: result.map ?? null };
526
+ }
527
+ catch (err) {
528
+ if (verbose) {
529
+ // eslint-disable-next-line no-console
530
+ console.warn(`[ns-ts-fallback] transformWithOxc failed for ${cleanId}:`, err);
531
+ }
532
+ return null;
533
+ }
534
+ },
535
+ };
536
+ }
537
+ export function angularWorkerUrlPreservePlugin(opts) {
538
+ const { verbose } = opts || {};
539
+ let patched = false;
540
+ const applyPatch = () => {
541
+ if (patched)
542
+ return;
543
+ patched = true;
544
+ patchAngularCompilationInitializers({ verbose });
545
+ };
546
+ return {
547
+ name: 'nativescript-angular-worker-url-preserve',
548
+ // `enforce: 'pre'` + eager `config` hook ensures the patch lands
549
+ // before any `buildStart`/`transform` hook runs (i.e. before Angular
550
+ // ever instantiates a compilation class and calls `initialize`).
551
+ enforce: 'pre',
552
+ config() {
553
+ applyPatch();
554
+ return null;
555
+ },
556
+ // Belt-and-suspenders: Vite sometimes skips `config` for inner
557
+ // environments (e.g. `build --environment=<name>`). `configResolved`
558
+ // always runs once per environment, so re-applying here is safe
559
+ // (idempotent) and guarantees the patch lands before compilation.
560
+ configResolved() {
561
+ applyPatch();
562
+ },
563
+ };
564
+ }
565
+ // The three concrete `AngularCompilation` subclasses in `@angular/build`.
566
+ // All three expose an `initialize(tsconfig, hostOptions, compilerOptionsTransformer)`
567
+ // method that forwards `hostOptions.processWebWorker` into either the TS
568
+ // transformer (Aot/Jit) or a worker-thread MessageChannel (Parallel). We
569
+ // wrap `initialize` on each so `hostOptions.processWebWorker` is coerced to
570
+ // identity before any of that happens.
571
+ const ANGULAR_COMPILATION_TARGETS = [
572
+ {
573
+ specifier: 'src/tools/angular/compilation/aot-compilation.js',
574
+ className: 'AotCompilation',
575
+ },
576
+ {
577
+ specifier: 'src/tools/angular/compilation/jit-compilation.js',
578
+ className: 'JitCompilation',
579
+ },
580
+ {
581
+ specifier: 'src/tools/angular/compilation/parallel-compilation.js',
582
+ className: 'ParallelCompilation',
583
+ },
584
+ ];
585
+ function patchAngularCompilationInitializers(opts) {
586
+ const { verbose } = opts;
587
+ // `@angular/build` locks its public `exports` map to `.`, `./private`,
588
+ // and `./package.json`. Deep subpath requires like
589
+ // `@angular/build/src/tools/angular/compilation/aot-compilation.js`
590
+ // fail with `ERR_PACKAGE_PATH_NOT_EXPORTED`. Resolve the package root
591
+ // via the always-allowed `./package.json` export and require the
592
+ // absolute on-disk paths instead — `exports` doesn't gate absolute fs
593
+ // paths.
594
+ let pkgRoot;
595
+ try {
596
+ const pkgJsonPath = nodeRequire.resolve('@angular/build/package.json');
597
+ pkgRoot = path.dirname(pkgJsonPath);
598
+ }
599
+ catch {
600
+ if (verbose) {
601
+ // eslint-disable-next-line no-console
602
+ console.log('[ns-angular-worker-preserve] @angular/build not installed; skipping patch (non-Angular project)');
603
+ }
604
+ return;
605
+ }
606
+ let patchedCount = 0;
607
+ let attemptedCount = 0;
608
+ for (const target of ANGULAR_COMPILATION_TARGETS) {
609
+ attemptedCount++;
610
+ const filePath = path.join(pkgRoot, target.specifier);
611
+ let mod;
612
+ try {
613
+ mod = nodeRequire(filePath);
614
+ }
615
+ catch (err) {
616
+ if (verbose) {
617
+ // eslint-disable-next-line no-console
618
+ console.log(`[ns-angular-worker-preserve] ${target.className} not loadable at ${filePath} (older @angular/build or reorganized layout); skipping:`, err.message);
619
+ }
620
+ continue;
621
+ }
622
+ const klass = mod ? mod[target.className] : null;
623
+ if (typeof klass !== 'function') {
624
+ if (verbose) {
625
+ // eslint-disable-next-line no-console
626
+ console.log(`[ns-angular-worker-preserve] ${target.className} export missing from ${filePath}; skipping`);
627
+ }
628
+ continue;
629
+ }
630
+ if (klass.__nativescriptPatchedProcessWebWorker) {
631
+ patchedCount++;
632
+ continue;
633
+ }
634
+ const originalInitialize = klass.prototype && klass.prototype.initialize;
635
+ if (typeof originalInitialize !== 'function') {
636
+ if (verbose) {
637
+ // eslint-disable-next-line no-console
638
+ console.log(`[ns-angular-worker-preserve] ${target.className}.prototype.initialize missing; skipping`);
639
+ }
640
+ continue;
641
+ }
642
+ klass.prototype.initialize = function nativescriptPatchedInitialize(tsconfig, hostOptions, ...rest) {
643
+ // Wrap `processWebWorker` in place so Angular sees an identity
644
+ // function. When Angular's transformer sees `replacementPath ===
645
+ // filePath` it leaves `new Worker(new URL(...))` nodes unchanged,
646
+ // and Vite's own `workerImportMetaUrlPlugin` handles bundling
647
+ // downstream. Mutating the incoming object is safe: Analog
648
+ // constructs a fresh `hostOptions` on every `performAngularCompilation`
649
+ // call, and the only consumer (this `initialize` call) runs
650
+ // synchronously after our override.
651
+ if (hostOptions && typeof hostOptions.processWebWorker === 'function' && !hostOptions.__nativescriptPatchedProcessWebWorker) {
652
+ hostOptions.processWebWorker = function identityProcessWebWorker(workerFile, _containingFile) {
653
+ return workerFile;
654
+ };
655
+ hostOptions.__nativescriptPatchedProcessWebWorker = true;
656
+ }
657
+ return originalInitialize.call(this, tsconfig, hostOptions, ...rest);
658
+ };
659
+ klass.__nativescriptPatchedProcessWebWorker = true;
660
+ patchedCount++;
661
+ }
662
+ if (verbose) {
663
+ if (patchedCount === 0) {
664
+ // eslint-disable-next-line no-console
665
+ console.warn(`[ns-angular-worker-preserve] no AngularCompilation subclasses patched (tried ${attemptedCount}); worker URLs may be blanked out in the build`);
666
+ }
667
+ else {
668
+ // eslint-disable-next-line no-console
669
+ console.log(`[ns-angular-worker-preserve] patched ${patchedCount}/${attemptedCount} AngularCompilation subclass initializers (${ANGULAR_COMPILATION_TARGETS.map((t) => t.className).join(', ')})`);
670
+ }
671
+ }
64
672
  }
65
673
  export function workerUrlPlugin() {
66
674
  return {
@@ -72,7 +680,19 @@ export function workerUrlPlugin() {
72
680
  // Transform Vite's worker URL pattern to NativeScript's expected format
73
681
  // From: new Worker(new URL(/* @vite-ignore */ "/assets/sample.worker-C6wW8q2-.js", import.meta.url))
74
682
  // To: new Worker('~/' + 'assets/sample.worker-C6wW8q2-.js')
75
- const workerUrlRegex = /new\s+Worker\s*\(\s*new\s+URL\s*\(\s*(?:\/\*[^*]*\*\/\s*)?["']([^"']+)["']\s*,\s*import\.meta\.url\s*\)\s*\)/g;
683
+ //
684
+ // Rolldown (Vite's underlying bundler) emits the asset path as a
685
+ // template-literal (backticks) and prefixes the second URL arg
686
+ // with `\`\` +` to coerce it to a string, e.g.:
687
+ // new Worker(new URL(`/assets/foo.js`, `` + import.meta.url))
688
+ // The regex below accepts either single quotes, double quotes,
689
+ // or backticks for the asset path, and an optional
690
+ // `<emptyString> +` coercion prefix before `import.meta.url`. At
691
+ // NS runtime there's no `import.meta.url` in the main bundle and
692
+ // `new URL("/assets/...", ...)` would resolve to a `file:///...`
693
+ // URL that NS Worker can't load, so this rewrite is the last
694
+ // step that makes worker chunks actually loadable.
695
+ const workerUrlRegex = /new\s+Worker\s*\(\s*new\s+URL\s*\(\s*(?:\/\*[^*]*\*\/\s*)?[`"']([^`"']+)[`"']\s*,\s*(?:[`"'][^`"']*[`"']\s*\+\s*)?import\.meta\.url\s*\)\s*\)/g;
76
696
  if (workerUrlRegex.test(chunk.code)) {
77
697
  chunk.code = chunk.code.replace(workerUrlRegex, (match, assetPath) => {
78
698
  // Use the full asset path including assets/ folder