@nativescript/vite 8.0.0-alpha.29 → 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.
- package/hmr/server/angular-root-component.d.ts +79 -0
- package/hmr/server/angular-root-component.js +149 -0
- package/hmr/server/angular-root-component.js.map +1 -0
- package/hmr/server/hmr-module-graph.d.ts +37 -0
- package/hmr/server/hmr-module-graph.js +214 -0
- package/hmr/server/hmr-module-graph.js.map +1 -0
- package/hmr/server/index.js +1 -0
- package/hmr/server/index.js.map +1 -1
- package/hmr/server/ns-rt-route.d.ts +5 -0
- package/hmr/server/ns-rt-route.js +35 -0
- package/hmr/server/ns-rt-route.js.map +1 -0
- package/hmr/server/require-guard.d.ts +1 -0
- package/hmr/server/require-guard.js +12 -0
- package/hmr/server/require-guard.js.map +1 -0
- package/hmr/server/route-helpers.d.ts +7 -0
- package/hmr/server/route-helpers.js +13 -0
- package/hmr/server/route-helpers.js.map +1 -0
- package/hmr/server/server-origin.d.ts +12 -0
- package/hmr/server/server-origin.js +66 -0
- package/hmr/server/server-origin.js.map +1 -0
- package/hmr/server/websocket-core-bridge.js +0 -11
- package/hmr/server/websocket-core-bridge.js.map +1 -1
- package/hmr/server/websocket-device-transform.d.ts +21 -0
- package/hmr/server/websocket-device-transform.js +1570 -0
- package/hmr/server/websocket-device-transform.js.map +1 -0
- package/hmr/server/websocket-hot-update.d.ts +51 -0
- package/hmr/server/websocket-hot-update.js +1160 -0
- package/hmr/server/websocket-hot-update.js.map +1 -0
- package/hmr/server/websocket-import-map-route.d.ts +15 -0
- package/hmr/server/websocket-import-map-route.js +44 -0
- package/hmr/server/websocket-import-map-route.js.map +1 -0
- package/hmr/server/websocket-ns-core.d.ts +21 -0
- package/hmr/server/websocket-ns-core.js +305 -0
- package/hmr/server/websocket-ns-core.js.map +1 -0
- package/hmr/server/websocket-ns-entry.d.ts +22 -0
- package/hmr/server/websocket-ns-entry.js +150 -0
- package/hmr/server/websocket-ns-entry.js.map +1 -0
- package/hmr/server/websocket-ns-m.d.ts +34 -0
- package/hmr/server/websocket-ns-m.js +853 -0
- package/hmr/server/websocket-ns-m.js.map +1 -0
- package/hmr/server/websocket-served-module-helpers.d.ts +1 -1
- package/hmr/server/websocket-served-module-helpers.js +1 -1
- package/hmr/server/websocket-served-module-helpers.js.map +1 -1
- package/hmr/server/websocket-sfc.d.ts +24 -0
- package/hmr/server/websocket-sfc.js +1223 -0
- package/hmr/server/websocket-sfc.js.map +1 -0
- package/hmr/server/websocket-txn.js +2 -8
- package/hmr/server/websocket-txn.js.map +1 -1
- package/hmr/server/websocket-vendor-unifier.js +2 -8
- package/hmr/server/websocket-vendor-unifier.js.map +1 -1
- package/hmr/server/websocket.d.ts +1 -44
- package/hmr/server/websocket.js +588 -6691
- package/hmr/server/websocket.js.map +1 -1
- package/hmr/shared/runtime/root-placeholder-view.d.ts +19 -0
- package/hmr/shared/runtime/root-placeholder-view.js +310 -0
- package/hmr/shared/runtime/root-placeholder-view.js.map +1 -0
- package/hmr/shared/runtime/root-placeholder.js +1 -309
- package/hmr/shared/runtime/root-placeholder.js.map +1 -1
- package/hmr/shared/vendor/manifest-collect.d.ts +32 -0
- package/hmr/shared/vendor/manifest-collect.js +512 -0
- package/hmr/shared/vendor/manifest-collect.js.map +1 -0
- package/hmr/shared/vendor/manifest.d.ts +1 -35
- package/hmr/shared/vendor/manifest.js +3 -914
- package/hmr/shared/vendor/manifest.js.map +1 -1
- package/hmr/shared/vendor/vendor-device-shim.d.ts +1 -0
- package/hmr/shared/vendor/vendor-device-shim.js +208 -0
- package/hmr/shared/vendor/vendor-device-shim.js.map +1 -0
- package/hmr/shared/vendor/vendor-esbuild-plugins.d.ts +16 -0
- package/hmr/shared/vendor/vendor-esbuild-plugins.js +203 -0
- package/hmr/shared/vendor/vendor-esbuild-plugins.js.map +1 -0
- package/package.json +1 -1
- package/hmr/server/websocket-vue-sfc.d.ts +0 -26
- package/hmr/server/websocket-vue-sfc.js +0 -1053
- package/hmr/server/websocket-vue-sfc.js.map +0 -1
|
@@ -1,14 +1,12 @@
|
|
|
1
1
|
import * as esbuild from 'esbuild';
|
|
2
|
-
import { readFile } from 'fs/promises';
|
|
3
2
|
import path from 'path';
|
|
4
|
-
import fs, { readFileSync } from 'fs';
|
|
5
3
|
import { createHash } from 'crypto';
|
|
6
|
-
import { createRequire } from 'node:module';
|
|
7
|
-
import { getAngularLinkerFactory, runAngularLinker } from '../../../helpers/angular/shared-linker.js';
|
|
8
4
|
import { registerVendorManifest, clearVendorManifest, getVendorManifest } from './registry.js';
|
|
5
|
+
import { collectVendorModules } from './manifest-collect.js';
|
|
9
6
|
import { generatePlatformPolyfills } from '../runtime/platform-polyfills.js';
|
|
10
7
|
import { createNativeClassEsbuildPlugin } from '../../../helpers/nativeclass-esbuild-plugin.js';
|
|
11
8
|
import { getGlobalDefines } from '../../../helpers/global-defines.js';
|
|
9
|
+
import { createVendorEsbuildPlugin, createSolidJsxEsbuildPlugin, angularLinkerEsbuildPlugin } from './vendor-esbuild-plugins.js';
|
|
12
10
|
export const VENDOR_MANIFEST_ID = '@nativescript/vendor-manifest';
|
|
13
11
|
export const VENDOR_MANIFEST_VIRTUAL_ID = '\0' + VENDOR_MANIFEST_ID;
|
|
14
12
|
export const VENDOR_BUNDLE_ID = '@nativescript/vendor';
|
|
@@ -17,105 +15,6 @@ export const SERVER_VENDOR_PATH = '/@nativescript/vendor.mjs';
|
|
|
17
15
|
export const SERVER_MANIFEST_PATH = '/@nativescript/vendor-manifest.json';
|
|
18
16
|
export const DEFAULT_VENDOR_FILENAME = 'ns-vendor.mjs';
|
|
19
17
|
export const DEFAULT_MANIFEST_FILENAME = 'ns-vendor-manifest.json';
|
|
20
|
-
// Do not force-include @nativescript/core in the dev vendor bundle.
|
|
21
|
-
// Keeping core out of vendor avoids duplicate side-effect registrations (e.g.,
|
|
22
|
-
// com.tns.FragmentClass, com.tns.NativeScriptActivity) across bundle.mjs and vendor.
|
|
23
|
-
// Force runtime-sensitive packages onto the vendor path so they do not drift
|
|
24
|
-
// between startup bundle, HTTP-wrapped CommonJS, and base-require semantics
|
|
25
|
-
// during HMR sessions.
|
|
26
|
-
const ALWAYS_INCLUDE = new Set(['stacktrace-js']);
|
|
27
|
-
const ALWAYS_EXCLUDE = new Set([
|
|
28
|
-
'@nativescript/android',
|
|
29
|
-
'@nativescript/ios',
|
|
30
|
-
'@nativescript/types',
|
|
31
|
-
'@nativescript/webpack',
|
|
32
|
-
// Angular browser animations are not used in NativeScript; excluding reduces
|
|
33
|
-
// memory pressure and avoids bringing partial declarations into vendor.
|
|
34
|
-
'@angular/animations',
|
|
35
|
-
'@angular/platform-browser/animations',
|
|
36
|
-
// Not needed at runtime with linked partials; reduce vendor size/memory.
|
|
37
|
-
'@angular/platform-browser-dynamic',
|
|
38
|
-
// Native add-on helpers pulled by ws or others; exclude in NS dev vendor
|
|
39
|
-
'bufferutil',
|
|
40
|
-
'utf-8-validate',
|
|
41
|
-
'node-gyp-build',
|
|
42
|
-
'bufferutil',
|
|
43
|
-
'utf-8-validate',
|
|
44
|
-
'node-gyp-build',
|
|
45
|
-
// All @babel/* and babel-* packages are build-time tools, never runtime deps.
|
|
46
|
-
// They get pulled in as peer deps of packages like @nativescript-community/solid-js
|
|
47
|
-
// but should never be in the vendor bundle (they require 'fs', 'path', etc.).
|
|
48
|
-
'@babel/core',
|
|
49
|
-
'@babel/helper-plugin-utils',
|
|
50
|
-
'@babel/generator',
|
|
51
|
-
'@babel/helper-string-parser',
|
|
52
|
-
'@babel/helper-validator-identifier',
|
|
53
|
-
'@babel/parser',
|
|
54
|
-
'@babel/plugin-syntax-typescript',
|
|
55
|
-
'@babel/plugin-transform-typescript',
|
|
56
|
-
'@babel/preset-typescript',
|
|
57
|
-
'@babel/preset-env',
|
|
58
|
-
'@babel/types',
|
|
59
|
-
'babel-preset-solid',
|
|
60
|
-
'babel-plugin-jsx-dom-expressions',
|
|
61
|
-
// Heavy dependency not needed in vendor dev bundle; fetch via HTTP loader instead
|
|
62
|
-
'rxjs',
|
|
63
|
-
'nativescript',
|
|
64
|
-
'typescript',
|
|
65
|
-
'ts-node',
|
|
66
|
-
'vue-tsc',
|
|
67
|
-
'ws',
|
|
68
|
-
'@types/node',
|
|
69
|
-
'nativescript-theme-core',
|
|
70
|
-
// Build-time tools that get pulled in as transitive dependencies but should
|
|
71
|
-
// never be in the device vendor bundle (they require Node built-ins like fs,
|
|
72
|
-
// path, child_process, etc.). Now that we collect transitive runtime deps,
|
|
73
|
-
// these need explicit exclusion.
|
|
74
|
-
'esbuild',
|
|
75
|
-
'prettier',
|
|
76
|
-
'acorn',
|
|
77
|
-
'recast',
|
|
78
|
-
'source-map',
|
|
79
|
-
'source-map-js',
|
|
80
|
-
'tsx',
|
|
81
|
-
'diff',
|
|
82
|
-
'esprima',
|
|
83
|
-
// TanStack build-time router tooling (code generation, file-based routing)
|
|
84
|
-
'@tanstack/router-plugin',
|
|
85
|
-
'@tanstack/router-generator',
|
|
86
|
-
'@tanstack/router-utils',
|
|
87
|
-
'@tanstack/virtual-file-routes',
|
|
88
|
-
// File system / glob utilities — build-time only, require Node fs
|
|
89
|
-
'fdir',
|
|
90
|
-
'picomatch',
|
|
91
|
-
'tinyglobby',
|
|
92
|
-
// SSR-only library (bot detection) — not needed on device
|
|
93
|
-
'isbot',
|
|
94
|
-
// Type-only packages with no runtime JavaScript
|
|
95
|
-
'csstype',
|
|
96
|
-
// NativeScript CLI hook system — build-time only, requires Node os/path
|
|
97
|
-
'@nativescript/hook',
|
|
98
|
-
// Test runner uses webpack's require.context API which doesn't exist in Vite.
|
|
99
|
-
// Including it in the vendor bundle causes __require.context crashes at runtime.
|
|
100
|
-
'@nativescript/unit-test-runner',
|
|
101
|
-
'nativescript-unit-test-runner',
|
|
102
|
-
// CSS build tools — postcss, tailwindcss, and related tooling are exclusively
|
|
103
|
-
// build-time processors. They require Node APIs (process, fs, path) and must
|
|
104
|
-
// never run on device. esbuild bundles their transitive deps (picocolors,
|
|
105
|
-
// nanoid, etc.) which reference `process` and crash at runtime.
|
|
106
|
-
'tailwindcss',
|
|
107
|
-
'@nativescript/tailwind',
|
|
108
|
-
'postcss',
|
|
109
|
-
'autoprefixer',
|
|
110
|
-
'postcss-import',
|
|
111
|
-
'postcss-url',
|
|
112
|
-
'postcss-nested',
|
|
113
|
-
'picocolors',
|
|
114
|
-
'nanoid',
|
|
115
|
-
// Server-side SDKs that require Node networking APIs (net, tls, dns, crypto).
|
|
116
|
-
// These are backend tools, not device-side.
|
|
117
|
-
'mongodb',
|
|
118
|
-
]);
|
|
119
18
|
const INDEX_ALIAS_SUFFIXES = ['/index', '/index.js', '/index.android.js', '/index.ios.js', '/index.visionos.js'];
|
|
120
19
|
export function vendorManifestPlugin(options) {
|
|
121
20
|
let cachedResult = null;
|
|
@@ -532,419 +431,8 @@ async function generateVendorBundle(options) {
|
|
|
532
431
|
entries: collected.entries,
|
|
533
432
|
};
|
|
534
433
|
}
|
|
535
|
-
function collectVendorModules(projectRoot, platform, flavor) {
|
|
536
|
-
const packageJsonPath = path.resolve(projectRoot, 'package.json');
|
|
537
|
-
const pkg = JSON.parse(readFileSync(packageJsonPath, 'utf-8'));
|
|
538
|
-
const projectRequire = createRequire(packageJsonPath);
|
|
539
|
-
const debug = process.env.VITE_DEBUG_LOGS === 'true' || process.env.VITE_DEBUG_LOGS === '1';
|
|
540
|
-
const vendor = new Set();
|
|
541
|
-
const visited = new Set();
|
|
542
|
-
const queue = [];
|
|
543
|
-
// Local-source deps (file: pointing to a directory, link:, workspace:) are
|
|
544
|
-
// app code, not pre-packaged libraries. esbuild's vendor pipeline has none
|
|
545
|
-
// of the user's tsconfig path aliases or other Vite plugin resolvers, so
|
|
546
|
-
// any aliased import inside their source will fail with "Could not
|
|
547
|
-
// resolve". We collect their names here so that peer-dep traversal can
|
|
548
|
-
// also skip them.
|
|
549
|
-
const localSourceNames = new Set();
|
|
550
|
-
const isPackageRootSpecifier = (name) => {
|
|
551
|
-
if (!name)
|
|
552
|
-
return false;
|
|
553
|
-
if (name.startsWith('@')) {
|
|
554
|
-
// Scoped: @scope/name is root; anything deeper is subpath
|
|
555
|
-
const parts = name.split('/');
|
|
556
|
-
return parts.length === 2;
|
|
557
|
-
}
|
|
558
|
-
// Unscoped: no slash means root; any slash means subpath
|
|
559
|
-
return !name.includes('/');
|
|
560
|
-
};
|
|
561
|
-
const isAngularFlavor = flavor === 'angular';
|
|
562
|
-
const isSolidFlavor = flavor === 'solid';
|
|
563
|
-
const addCandidate = (name) => {
|
|
564
|
-
if (!name || shouldSkipDependency(name)) {
|
|
565
|
-
return;
|
|
566
|
-
}
|
|
567
|
-
// Avoid pulling Angular compiler/runtime into the dev vendor bundle when
|
|
568
|
-
// the current project flavor is not Angular (for example, solid). This
|
|
569
|
-
// prevents esbuild from trying to bundle @angular/compiler and its Babel
|
|
570
|
-
// toolchain, which requires Node built-ins like fs/path/url.
|
|
571
|
-
if (!isAngularFlavor && (name === '@angular/compiler' || name.startsWith('@angular/'))) {
|
|
572
|
-
return;
|
|
573
|
-
}
|
|
574
|
-
// For the Solid flavor, keep `solid-js` itself OUT of the vendor bundle.
|
|
575
|
-
//
|
|
576
|
-
// Both `@solid-refresh` (served via HTTP) and Vite-aliased user code
|
|
577
|
-
// import `solid-js` through the dev server, while the vendor bundle
|
|
578
|
-
// pulls it in as a peerDependency of `@nativescript-community/solid-js`.
|
|
579
|
-
// Two copies → two `Owner` module-locals → the proxy memo created by
|
|
580
|
-
// `solid-refresh`'s `HMRComp` is registered on the HTTP copy's Owner
|
|
581
|
-
// (which is always null — hence the
|
|
582
|
-
// `computations created outside a createRoot or render` warning), while
|
|
583
|
-
// `render(App, doc)` runs against the vendor copy's Owner. Same chain
|
|
584
|
-
// breaks HMR propagation: `patchRegistry`'s `setComp` ticks the HTTP
|
|
585
|
-
// copy's signal but the live page tree subscribes through the vendor
|
|
586
|
-
// copy's reactive graph, so the new component body never reaches the
|
|
587
|
-
// screen.
|
|
588
|
-
//
|
|
589
|
-
// We pair this skip with the matching esbuild externalization
|
|
590
|
-
// (`nsSolidJsExternalPlugin`) and an import-map redirect in
|
|
591
|
-
// `import-map.ts` that points `solid-js` at the HTTP URL. All three
|
|
592
|
-
// converge on the same dev-server URL, V8 dedupes by URL, and the
|
|
593
|
-
// app sees a single `solid-js` realm.
|
|
594
|
-
if (isSolidFlavor && name === 'solid-js') {
|
|
595
|
-
return;
|
|
596
|
-
}
|
|
597
|
-
// Skip already-visited packages to avoid redundant queue processing
|
|
598
|
-
if (visited.has(name)) {
|
|
599
|
-
return;
|
|
600
|
-
}
|
|
601
|
-
visited.add(name);
|
|
602
|
-
vendor.add(name);
|
|
603
|
-
const isRoot = isPackageRootSpecifier(name);
|
|
604
|
-
// Only traverse deps for package roots; subpaths should not attempt package.json resolution
|
|
605
|
-
if (isRoot) {
|
|
606
|
-
queue.push(name);
|
|
607
|
-
}
|
|
608
|
-
};
|
|
609
|
-
const addDeps = (deps) => {
|
|
610
|
-
if (!deps) {
|
|
611
|
-
return;
|
|
612
|
-
}
|
|
613
|
-
for (const [name, spec] of Object.entries(deps)) {
|
|
614
|
-
if (isUnvendorableLocalSource(name, spec, projectRequire, platform)) {
|
|
615
|
-
// Defer to the regular Vite/Rolldown pipeline (HTTP-served in
|
|
616
|
-
// dev, bundled in production) where the
|
|
617
|
-
// ns-tsconfig-paths-resolver and the rest of the plugin chain
|
|
618
|
-
// can handle aliased imports. Local .tgz file: refs ARE proper
|
|
619
|
-
// packaged libraries and DO stay in vendor; so do file:
|
|
620
|
-
// directory refs that point at packages with compiled JS
|
|
621
|
-
// entry points (a common NativeScript monorepo pattern that
|
|
622
|
-
// hoists installs and re-exposes them from the app's
|
|
623
|
-
// package.json via `file:../../node_modules/<name>`).
|
|
624
|
-
localSourceNames.add(name);
|
|
625
|
-
if (debug) {
|
|
626
|
-
console.log(`[vendor] skipping local source dependency ${name} (spec: ${String(spec)})`);
|
|
627
|
-
}
|
|
628
|
-
continue;
|
|
629
|
-
}
|
|
630
|
-
addCandidate(name);
|
|
631
|
-
}
|
|
632
|
-
};
|
|
633
|
-
addDeps(pkg.dependencies);
|
|
634
|
-
addDeps(pkg.optionalDependencies);
|
|
635
|
-
for (const name of ALWAYS_INCLUDE) {
|
|
636
|
-
// Some force-included packages are only present transitively in apps that
|
|
637
|
-
// actually use them. Skip missing packages quietly so unrelated projects do
|
|
638
|
-
// not fail vendor collection just because the policy list names them.
|
|
639
|
-
if (canResolveDependencyPackageJson(name, projectRequire)) {
|
|
640
|
-
addCandidate(name);
|
|
641
|
-
}
|
|
642
|
-
}
|
|
643
|
-
// Ensure Android Activity proxy is present for SBG scanning in dev/HMR
|
|
644
|
-
// and non-HMR builds alike: explicitly include the side-effect module
|
|
645
|
-
// that registers `com.tns.NativeScriptActivity`.
|
|
646
|
-
if (platform === 'android') {
|
|
647
|
-
addCandidate('@nativescript/core/ui/frame/activity.android');
|
|
648
|
-
}
|
|
649
|
-
if (pkg.dependencies?.['nativescript-vue'] && pkg.devDependencies?.vue) {
|
|
650
|
-
addCandidate('vue');
|
|
651
|
-
}
|
|
652
|
-
// Angular framework packages are intentionally NOT added to vendor. They are
|
|
653
|
-
// served via HTTP only so every importer resolves to a single module realm.
|
|
654
|
-
// See shouldSkipDependency() for the full rationale. RxJS is also left out of
|
|
655
|
-
// vendor (large, and not required in the vendor bundle for dev HMR).
|
|
656
|
-
if (pkg.dependencies?.['react-nativescript']) {
|
|
657
|
-
if (pkg.dependencies?.react) {
|
|
658
|
-
addCandidate('react');
|
|
659
|
-
}
|
|
660
|
-
if (pkg.dependencies?.['react-dom']) {
|
|
661
|
-
addCandidate('react-dom');
|
|
662
|
-
}
|
|
663
|
-
}
|
|
664
|
-
// SolidJS / TanStack Router: when @nativescript/tanstack-router is a dependency,
|
|
665
|
-
// its runtime deps (@tanstack/solid-router, @tanstack/router-core, @tanstack/history)
|
|
666
|
-
// MUST be in the vendor bundle. These packages:
|
|
667
|
-
// 1. Use browser APIs (window.dispatchEvent) that don't exist in NativeScript — they
|
|
668
|
-
// must be bundled where the NativeScript wrapper intercepts those calls
|
|
669
|
-
// 2. Contain JSX source that needs Solid compilation (dist/source/*.jsx) — the HTTP
|
|
670
|
-
// fallback can't compile node_modules JSX since vite-plugin-solid skips it
|
|
671
|
-
// 3. Import solid-js internally — loading via HTTP creates a separate solid-js instance
|
|
672
|
-
// esbuild uses the 'import' condition (not 'solid'), resolving to pre-compiled
|
|
673
|
-
// dist/esm/*.js which avoids all three issues.
|
|
674
|
-
if (pkg.dependencies?.['@nativescript/tanstack-router']) {
|
|
675
|
-
addCandidate('@tanstack/solid-router');
|
|
676
|
-
addCandidate('@tanstack/router-core');
|
|
677
|
-
addCandidate('@tanstack/history');
|
|
678
|
-
}
|
|
679
|
-
parseEnvList(process.env.NS_VENDOR_INCLUDE).forEach(addCandidate);
|
|
680
|
-
const projectDeps = {
|
|
681
|
-
dependencies: new Set(Object.keys(pkg.dependencies ?? {})),
|
|
682
|
-
optional: new Set(Object.keys(pkg.optionalDependencies ?? {})),
|
|
683
|
-
dev: new Set(Object.keys(pkg.devDependencies ?? {})),
|
|
684
|
-
};
|
|
685
|
-
while (queue.length) {
|
|
686
|
-
const specifier = queue.shift();
|
|
687
|
-
const dependencyPkg = readDependencyPackageJson(specifier, projectRequire);
|
|
688
|
-
if (!dependencyPkg) {
|
|
689
|
-
continue;
|
|
690
|
-
}
|
|
691
|
-
const peerDependencies = Object.keys(dependencyPkg.peerDependencies ?? {});
|
|
692
|
-
for (const peer of peerDependencies) {
|
|
693
|
-
if (shouldSkipDependency(peer) || localSourceNames.has(peer)) {
|
|
694
|
-
continue;
|
|
695
|
-
}
|
|
696
|
-
if (projectDeps.dependencies.has(peer) || projectDeps.optional.has(peer) || projectDeps.dev.has(peer)) {
|
|
697
|
-
addCandidate(peer);
|
|
698
|
-
}
|
|
699
|
-
}
|
|
700
|
-
// NOTE: We intentionally do NOT collect transitive runtime dependencies
|
|
701
|
-
// here. The import map + runtime specifier normalization handles non-vendor
|
|
702
|
-
// packages by routing them through HTTP to the Vite dev server. This avoids
|
|
703
|
-
// the fragility of trying to esbuild-bundle every transitive dep (which can
|
|
704
|
-
// fail due to Node built-ins, type-only packages, duplicate module instances,
|
|
705
|
-
// etc.). Only direct project dependencies go into the vendor bundle.
|
|
706
|
-
}
|
|
707
|
-
parseEnvList(process.env.NS_VENDOR_EXCLUDE).forEach((name) => {
|
|
708
|
-
vendor.delete(name);
|
|
709
|
-
});
|
|
710
|
-
return {
|
|
711
|
-
entries: Array.from(vendor).sort(),
|
|
712
|
-
};
|
|
713
|
-
}
|
|
714
|
-
function shouldSkipDependency(name) {
|
|
715
|
-
if (!name) {
|
|
716
|
-
return true;
|
|
717
|
-
}
|
|
718
|
-
if (ALWAYS_EXCLUDE.has(name)) {
|
|
719
|
-
return true;
|
|
720
|
-
}
|
|
721
|
-
// Angular framework packages must only be served via the HTTP path so every
|
|
722
|
-
// importer resolves to a single module realm. When these packages are present
|
|
723
|
-
// in the vendor bundle AND imported by app modules via HTTP subpath, every
|
|
724
|
-
// @Component/@Injectable gets defined twice (once per realm), producing NG0912
|
|
725
|
-
// selector collisions, cross-realm `instanceof` failures, and dual class
|
|
726
|
-
// identities throughout Angular's DI container. HTTP-only is the single-realm
|
|
727
|
-
// invariant for user-level framework code.
|
|
728
|
-
if (name === '@nativescript/angular' || name === 'nativescript-angular' || name.startsWith('@angular/')) {
|
|
729
|
-
return true;
|
|
730
|
-
}
|
|
731
|
-
// All Babel packages are build tools — never bundle into device runtime.
|
|
732
|
-
// They require Node built-ins (fs, path, url) that don't exist on device.
|
|
733
|
-
if (name.startsWith('@babel/') || name.startsWith('babel-')) {
|
|
734
|
-
return true;
|
|
735
|
-
}
|
|
736
|
-
// Dev tools and type-only packages — not needed on device
|
|
737
|
-
if (name.startsWith('@solid-devtools/')) {
|
|
738
|
-
return true;
|
|
739
|
-
}
|
|
740
|
-
if (name.startsWith('@types/')) {
|
|
741
|
-
return true;
|
|
742
|
-
}
|
|
743
|
-
// PostCSS ecosystem — all build-time CSS processing
|
|
744
|
-
if (name === 'postcss' || name.startsWith('postcss-')) {
|
|
745
|
-
return true;
|
|
746
|
-
}
|
|
747
|
-
// Tailwind ecosystem — build-time only CSS framework
|
|
748
|
-
if (name.includes('tailwind')) {
|
|
749
|
-
return true;
|
|
750
|
-
}
|
|
751
|
-
// Test runners and frameworks — never needed on device
|
|
752
|
-
if (name.includes('test-runner') || name.includes('unit-test')) {
|
|
753
|
-
return true;
|
|
754
|
-
}
|
|
755
|
-
// Linters and formatters — build-time tools
|
|
756
|
-
if (name.includes('eslint') || name.includes('stylelint')) {
|
|
757
|
-
return true;
|
|
758
|
-
}
|
|
759
|
-
if (name.startsWith('.')) {
|
|
760
|
-
return true;
|
|
761
|
-
}
|
|
762
|
-
if (name.startsWith('file:')) {
|
|
763
|
-
return true;
|
|
764
|
-
}
|
|
765
|
-
if (name.startsWith('workspace:')) {
|
|
766
|
-
return true;
|
|
767
|
-
}
|
|
768
|
-
if (name.startsWith('link:')) {
|
|
769
|
-
return true;
|
|
770
|
-
}
|
|
771
|
-
return false;
|
|
772
|
-
}
|
|
773
|
-
const COMPILED_JS_ENTRY_EXTENSIONS = ['.js', '.mjs', '.cjs'];
|
|
774
|
-
const COMPILED_JS_ENTRY_REGEX = /\.(?:c|m)?jsx?$/;
|
|
775
|
-
function compiledJsExtensionsForPlatform(platform) {
|
|
776
|
-
const exts = [...COMPILED_JS_ENTRY_EXTENSIONS];
|
|
777
|
-
switch (platform) {
|
|
778
|
-
case 'android':
|
|
779
|
-
exts.push('.android.js');
|
|
780
|
-
break;
|
|
781
|
-
case 'ios':
|
|
782
|
-
exts.push('.ios.js', '.visionos.js');
|
|
783
|
-
break;
|
|
784
|
-
case 'visionos':
|
|
785
|
-
exts.push('.visionos.js', '.ios.js');
|
|
786
|
-
break;
|
|
787
|
-
}
|
|
788
|
-
return exts;
|
|
789
|
-
}
|
|
790
|
-
/**
|
|
791
|
-
* Determine whether a `package.json` dependency must be excluded from the
|
|
792
|
-
* HMR vendor bundle because esbuild's standalone vendor pipeline can't
|
|
793
|
-
* resolve its source.
|
|
794
|
-
*
|
|
795
|
-
* The HMR vendor bundle is generated by a standalone esbuild build that
|
|
796
|
-
* has none of the Vite plugin chain (most notably
|
|
797
|
-
* `ns-tsconfig-paths-resolver`), so any aliased import inside the
|
|
798
|
-
* package's **source** files will fail with "Could not resolve" and abort
|
|
799
|
-
* the whole bundle.
|
|
800
|
-
*
|
|
801
|
-
* Skip:
|
|
802
|
-
* - `link:` and `workspace:` refs (always app-side source).
|
|
803
|
-
* - `file:` refs to a directory whose installed package only ships
|
|
804
|
-
* TypeScript/JSX source (no compiled `.js`/`.mjs`/`.cjs` entry).
|
|
805
|
-
*
|
|
806
|
-
* Keep (return false):
|
|
807
|
-
* - Regular semver / git / url specs (normal third-party libraries).
|
|
808
|
-
* - Local `.tgz` file refs (pre-packaged libraries extracted at install).
|
|
809
|
-
* - `file:` directory refs that resolve to a package with a compiled JS
|
|
810
|
-
* entry — a common NativeScript monorepo convention where the app's
|
|
811
|
-
* `package.json` redirects to `../../node_modules/<name>` to avoid
|
|
812
|
-
* duplicate installs while letting the NativeScript CLI discover
|
|
813
|
-
* plugins from the app directory.
|
|
814
|
-
*/
|
|
815
|
-
export function isUnvendorableLocalSource(name, spec, projectRequire, platform) {
|
|
816
|
-
if (typeof spec !== 'string')
|
|
817
|
-
return false;
|
|
818
|
-
if (spec.startsWith('link:') || spec.startsWith('workspace:'))
|
|
819
|
-
return true;
|
|
820
|
-
if (!spec.startsWith('file:'))
|
|
821
|
-
return false;
|
|
822
|
-
// Tarballs are already pre-packaged libraries — install extracts them
|
|
823
|
-
// into a normal node_modules entry.
|
|
824
|
-
if (/\.t(?:ar\.)?gz(?:[?#].*)?$/.test(spec))
|
|
825
|
-
return false;
|
|
826
|
-
// Directory file: refs need a deeper check: peek at the installed
|
|
827
|
-
// package.json and ask "does this ship compiled JS?". If yes, vendor
|
|
828
|
-
// it. If no (TS source only), defer to the regular Vite pipeline.
|
|
829
|
-
return !packageHasCompiledJsEntry(name, projectRequire, platform);
|
|
830
|
-
}
|
|
831
|
-
function packageHasCompiledJsEntry(name, projectRequire, platform) {
|
|
832
|
-
let pkgJsonPath;
|
|
833
|
-
try {
|
|
834
|
-
pkgJsonPath = projectRequire.resolve(`${name}/package.json`);
|
|
835
|
-
}
|
|
836
|
-
catch {
|
|
837
|
-
return false;
|
|
838
|
-
}
|
|
839
|
-
let pkg;
|
|
840
|
-
try {
|
|
841
|
-
pkg = JSON.parse(readFileSync(pkgJsonPath, 'utf-8'));
|
|
842
|
-
}
|
|
843
|
-
catch {
|
|
844
|
-
return false;
|
|
845
|
-
}
|
|
846
|
-
const pkgDir = path.dirname(pkgJsonPath);
|
|
847
|
-
const candidates = [];
|
|
848
|
-
const pushCandidate = (value) => {
|
|
849
|
-
if (typeof value === 'string' && value)
|
|
850
|
-
candidates.push(value);
|
|
851
|
-
};
|
|
852
|
-
pushCandidate(pkg.module);
|
|
853
|
-
pushCandidate(pkg.main);
|
|
854
|
-
// Recursively flatten conditional `exports` maps to surface concrete
|
|
855
|
-
// file paths. We only need `string` leaves; anything else (function-
|
|
856
|
-
// based exports, etc.) doesn't apply to esbuild's resolution.
|
|
857
|
-
const visitExports = (node) => {
|
|
858
|
-
if (!node)
|
|
859
|
-
return;
|
|
860
|
-
if (typeof node === 'string') {
|
|
861
|
-
pushCandidate(node);
|
|
862
|
-
return;
|
|
863
|
-
}
|
|
864
|
-
if (Array.isArray(node)) {
|
|
865
|
-
for (const item of node)
|
|
866
|
-
visitExports(item);
|
|
867
|
-
return;
|
|
868
|
-
}
|
|
869
|
-
if (typeof node === 'object') {
|
|
870
|
-
for (const value of Object.values(node))
|
|
871
|
-
visitExports(value);
|
|
872
|
-
}
|
|
873
|
-
};
|
|
874
|
-
visitExports(pkg.exports);
|
|
875
|
-
if (candidates.length === 0) {
|
|
876
|
-
// node's default lookup falls back to `index.js`.
|
|
877
|
-
candidates.push('index');
|
|
878
|
-
}
|
|
879
|
-
const extensionsToTry = compiledJsExtensionsForPlatform(platform);
|
|
880
|
-
for (const cand of candidates) {
|
|
881
|
-
const abs = path.resolve(pkgDir, cand);
|
|
882
|
-
const ext = path.extname(cand);
|
|
883
|
-
if (COMPILED_JS_ENTRY_REGEX.test(cand)) {
|
|
884
|
-
// Explicit JS extension. If the file exists, vendor it. If not
|
|
885
|
-
// (a NativeScript plugin commonly declares `main: "index.js"`
|
|
886
|
-
// but ships only platform variants like `index.ios.js`), try
|
|
887
|
-
// the platform-specific variants which esbuild's
|
|
888
|
-
// `resolveExtensions` will pick up at bundle time.
|
|
889
|
-
if (fs.existsSync(abs))
|
|
890
|
-
return true;
|
|
891
|
-
const baseAbs = abs.slice(0, -ext.length);
|
|
892
|
-
for (const e of extensionsToTry) {
|
|
893
|
-
if (fs.existsSync(baseAbs + e))
|
|
894
|
-
return true;
|
|
895
|
-
}
|
|
896
|
-
continue;
|
|
897
|
-
}
|
|
898
|
-
if (!ext) {
|
|
899
|
-
// Extensionless main — try plain JS variants AND the
|
|
900
|
-
// platform-specific variants NativeScript plugins commonly use
|
|
901
|
-
// (`index.ios.js`, `index.android.js`, `index.visionos.js`).
|
|
902
|
-
for (const e of extensionsToTry) {
|
|
903
|
-
if (fs.existsSync(abs + e))
|
|
904
|
-
return true;
|
|
905
|
-
}
|
|
906
|
-
continue;
|
|
907
|
-
}
|
|
908
|
-
// A non-JS extension (typically `.ts`/`.tsx`) means the package
|
|
909
|
-
// only ships TS source — esbuild's vendor pipeline can't resolve
|
|
910
|
-
// any tsconfig-aliased imports inside it.
|
|
911
|
-
}
|
|
912
|
-
return false;
|
|
913
|
-
}
|
|
914
|
-
export const __test_collectVendorModules = collectVendorModules;
|
|
915
434
|
export const __test_createVendorBundleRuntimeModule = createVendorBundleRuntimeModule;
|
|
916
|
-
export
|
|
917
|
-
export const __test_packageHasCompiledJsEntry = packageHasCompiledJsEntry;
|
|
918
|
-
function canResolveDependencyPackageJson(specifier, projectRequire) {
|
|
919
|
-
try {
|
|
920
|
-
projectRequire.resolve(`${specifier}/package.json`);
|
|
921
|
-
return true;
|
|
922
|
-
}
|
|
923
|
-
catch {
|
|
924
|
-
return false;
|
|
925
|
-
}
|
|
926
|
-
}
|
|
927
|
-
function readDependencyPackageJson(specifier, projectRequire) {
|
|
928
|
-
try {
|
|
929
|
-
const packageJsonPath = projectRequire.resolve(`${specifier}/package.json`);
|
|
930
|
-
return JSON.parse(readFileSync(packageJsonPath, 'utf-8'));
|
|
931
|
-
}
|
|
932
|
-
catch (error) {
|
|
933
|
-
if (process.env.VITE_DEBUG_LOGS) {
|
|
934
|
-
console.warn(`[vendor] unable to resolve ${specifier} package.json`, error);
|
|
935
|
-
}
|
|
936
|
-
return null;
|
|
937
|
-
}
|
|
938
|
-
}
|
|
939
|
-
function parseEnvList(value) {
|
|
940
|
-
if (!value) {
|
|
941
|
-
return [];
|
|
942
|
-
}
|
|
943
|
-
return value
|
|
944
|
-
.split(',')
|
|
945
|
-
.map((token) => token.trim())
|
|
946
|
-
.filter(Boolean);
|
|
947
|
-
}
|
|
435
|
+
export { collectVendorModules as __test_collectVendorModules, isUnvendorableLocalSource as __test_isUnvendorableLocalSource, packageHasCompiledJsEntry as __test_packageHasCompiledJsEntry } from './manifest-collect.js';
|
|
948
436
|
function createVendorEntry(entries) {
|
|
949
437
|
if (!entries.length) {
|
|
950
438
|
return `export const __nsVendorModuleMap = {};
|
|
@@ -1033,405 +521,6 @@ function createSbgVendorAssetCode(platform) {
|
|
|
1033
521
|
lines.push('export const __nsVendorModuleMap = {};\nexport default {};\n');
|
|
1034
522
|
return lines.join('\n');
|
|
1035
523
|
}
|
|
1036
|
-
function createVendorEsbuildPlugin(projectRoot) {
|
|
1037
|
-
return {
|
|
1038
|
-
name: 'ns-vendor-resolver',
|
|
1039
|
-
setup(build) {
|
|
1040
|
-
const debug = process.env.VITE_DEBUG_LOGS === 'true' || process.env.VITE_DEBUG_LOGS === '1';
|
|
1041
|
-
build.onResolve({ filter: /^~\/package\.json$/ }, () => ({
|
|
1042
|
-
path: path.resolve(projectRoot, 'package.json'),
|
|
1043
|
-
}));
|
|
1044
|
-
build.onResolve({ filter: /^module$/ }, () => ({
|
|
1045
|
-
path: 'ns-vendor-module-shim',
|
|
1046
|
-
namespace: 'ns-vendor',
|
|
1047
|
-
}));
|
|
1048
|
-
build.onLoad({ filter: /^ns-vendor-module-shim$/, namespace: 'ns-vendor' }, () => ({
|
|
1049
|
-
contents: vendorModuleShim,
|
|
1050
|
-
loader: 'js',
|
|
1051
|
-
}));
|
|
1052
|
-
// Stub Angular animations in vendor to avoid bundling browser-only code.
|
|
1053
|
-
// Provide named exports expected by @nativescript/angular to satisfy esbuild.
|
|
1054
|
-
const PB_ANIMATIONS_ID = 'ns-animations-pb-shim';
|
|
1055
|
-
const ANIMATIONS_BROWSER_ID = 'ns-animations-browser-shim';
|
|
1056
|
-
const ANIMATIONS_ID = 'ns-animations-noop';
|
|
1057
|
-
// @angular/platform-browser/animations -> provide concrete named stubs
|
|
1058
|
-
build.onResolve({ filter: /^@angular\/platform-browser\/animations(?:\/.*)?$/ }, (args) => {
|
|
1059
|
-
if (debug) {
|
|
1060
|
-
console.log('[vendor] map', args.path, '->', PB_ANIMATIONS_ID);
|
|
1061
|
-
}
|
|
1062
|
-
return { path: PB_ANIMATIONS_ID, namespace: 'ns-vendor' };
|
|
1063
|
-
});
|
|
1064
|
-
build.onLoad({ filter: new RegExp(`^${PB_ANIMATIONS_ID}$`), namespace: 'ns-vendor' }, () => ({
|
|
1065
|
-
contents: [
|
|
1066
|
-
'export default {};',
|
|
1067
|
-
// Commonly imported symbols by @nativescript/angular
|
|
1068
|
-
'export class AnimationBuilder {};',
|
|
1069
|
-
'export const \u0275BrowserAnimationBuilder = class {};',
|
|
1070
|
-
'export const \u0275AnimationEngine = class {};',
|
|
1071
|
-
'export const \u0275AnimationRendererFactory = class {};',
|
|
1072
|
-
'export const \u0275WebAnimationsStyleNormalizer = class {};',
|
|
1073
|
-
// Typical platform-browser/animations APIs exported; safe no-ops
|
|
1074
|
-
'export class BrowserAnimationsModule {};',
|
|
1075
|
-
'export class NoopAnimationsModule {};',
|
|
1076
|
-
'export const provideAnimations = (..._args) => [];',
|
|
1077
|
-
'export const provideNoopAnimations = (..._args) => [];',
|
|
1078
|
-
// Marker used by some Angular internals
|
|
1079
|
-
'export const ANIMATION_MODULE_TYPE = void 0;',
|
|
1080
|
-
].join('\n'),
|
|
1081
|
-
loader: 'js',
|
|
1082
|
-
}));
|
|
1083
|
-
// @angular/animations/browser -> provide ɵ* engine/renderer/style normalizer stubs
|
|
1084
|
-
build.onResolve({ filter: /^@angular\/animations\/browser(?:\/.*)?$/ }, (args) => {
|
|
1085
|
-
if (debug) {
|
|
1086
|
-
console.log('[vendor] map', args.path, '->', ANIMATIONS_BROWSER_ID);
|
|
1087
|
-
}
|
|
1088
|
-
return { path: ANIMATIONS_BROWSER_ID, namespace: 'ns-vendor' };
|
|
1089
|
-
});
|
|
1090
|
-
build.onLoad({ filter: new RegExp(`^${ANIMATIONS_BROWSER_ID}$`), namespace: 'ns-vendor' }, () => ({
|
|
1091
|
-
contents: [
|
|
1092
|
-
'export default {};',
|
|
1093
|
-
'export class AnimationDriver {};',
|
|
1094
|
-
'export const \u0275AnimationRendererFactory = class {};',
|
|
1095
|
-
'export const \u0275AnimationStyleNormalizer = class {};',
|
|
1096
|
-
'export const \u0275WebAnimationsStyleNormalizer = class {};',
|
|
1097
|
-
'export const \u0275AnimationEngine = class {};',
|
|
1098
|
-
// Convenience alias if any consumers import non-ɵ name
|
|
1099
|
-
'export const AnimationStyleNormalizer = \u0275AnimationStyleNormalizer;',
|
|
1100
|
-
].join('\n'),
|
|
1101
|
-
loader: 'js',
|
|
1102
|
-
}));
|
|
1103
|
-
// @angular/animations -> broad no-op surface
|
|
1104
|
-
build.onResolve(
|
|
1105
|
-
// Keep generic mapping for @angular/animations base; /browser is handled above
|
|
1106
|
-
{ filter: /^@angular\/animations(?:$|\/)$/ }, (args) => {
|
|
1107
|
-
if (debug) {
|
|
1108
|
-
console.log('[vendor] map', args.path, '->', ANIMATIONS_ID);
|
|
1109
|
-
}
|
|
1110
|
-
return { path: ANIMATIONS_ID, namespace: 'ns-vendor' };
|
|
1111
|
-
});
|
|
1112
|
-
build.onLoad({ filter: new RegExp(`^${ANIMATIONS_ID}$`), namespace: 'ns-vendor' }, () => ({
|
|
1113
|
-
contents: [
|
|
1114
|
-
'export default {};',
|
|
1115
|
-
// Provide names sometimes (incorrectly) imported from @angular/animations by wrappers
|
|
1116
|
-
'export class AnimationBuilder {};',
|
|
1117
|
-
'export const \u0275BrowserAnimationBuilder = class {};',
|
|
1118
|
-
'export const \u0275AnimationEngine = class {};',
|
|
1119
|
-
'export const \u0275AnimationRendererFactory = class {};',
|
|
1120
|
-
'export const \u0275WebAnimationsStyleNormalizer = class {};',
|
|
1121
|
-
'export const ANIMATION_MODULE_TYPE = void 0;',
|
|
1122
|
-
// Export a few common tokens as harmless stubs
|
|
1123
|
-
'export const animate = (..._a) => ({});',
|
|
1124
|
-
'export const state = (..._a) => ({});',
|
|
1125
|
-
'export const style = (..._a) => ({});',
|
|
1126
|
-
'export const transition = (..._a) => ({});',
|
|
1127
|
-
'export const trigger = (..._a) => ({});',
|
|
1128
|
-
'export const sequence = (..._a) => ({});',
|
|
1129
|
-
'export const group = (..._a) => ({});',
|
|
1130
|
-
'export const query = (..._a) => ({});',
|
|
1131
|
-
'export const stagger = (..._a) => ({});',
|
|
1132
|
-
'export const keyframes = (..._a) => ({});',
|
|
1133
|
-
].join('\n'),
|
|
1134
|
-
loader: 'js',
|
|
1135
|
-
}));
|
|
1136
|
-
},
|
|
1137
|
-
};
|
|
1138
|
-
}
|
|
1139
|
-
/**
|
|
1140
|
-
* esbuild plugin to compile .jsx/.tsx files from Solid packages through
|
|
1141
|
-
* babel-preset-solid. Without this, esbuild uses its default React JSX
|
|
1142
|
-
* transform, producing React.createElement calls that crash at runtime.
|
|
1143
|
-
*
|
|
1144
|
-
* Only applied to files inside node_modules that have .jsx or .tsx extension.
|
|
1145
|
-
*/
|
|
1146
|
-
function createSolidJsxEsbuildPlugin(projectRoot) {
|
|
1147
|
-
// Lazy-load Babel and the Solid preset so they're only required when
|
|
1148
|
-
// the Solid flavor is active.
|
|
1149
|
-
let babel;
|
|
1150
|
-
let solidPreset;
|
|
1151
|
-
return {
|
|
1152
|
-
name: 'ns-vendor-solid-jsx',
|
|
1153
|
-
setup(build) {
|
|
1154
|
-
// Intercept .jsx and .tsx files from node_modules
|
|
1155
|
-
build.onLoad({ filter: /node_modules[\\/].*\.[jt]sx$/ }, async (args) => {
|
|
1156
|
-
try {
|
|
1157
|
-
if (!babel) {
|
|
1158
|
-
babel = await import('@babel/core');
|
|
1159
|
-
// babel-preset-solid is the standard Solid JSX transform
|
|
1160
|
-
solidPreset = (await import('babel-preset-solid')).default;
|
|
1161
|
-
}
|
|
1162
|
-
const source = await readFile(args.path, 'utf-8');
|
|
1163
|
-
const result = await babel.transformAsync(source, {
|
|
1164
|
-
filename: args.path,
|
|
1165
|
-
presets: [
|
|
1166
|
-
[
|
|
1167
|
-
solidPreset,
|
|
1168
|
-
{
|
|
1169
|
-
generate: 'universal',
|
|
1170
|
-
hydratable: false,
|
|
1171
|
-
moduleName: '@nativescript-community/solid-js',
|
|
1172
|
-
},
|
|
1173
|
-
],
|
|
1174
|
-
],
|
|
1175
|
-
parserOpts: {
|
|
1176
|
-
plugins: ['jsx', ...(args.path.endsWith('.tsx') ? ['typescript'] : [])],
|
|
1177
|
-
},
|
|
1178
|
-
ast: false,
|
|
1179
|
-
sourceMaps: false,
|
|
1180
|
-
configFile: false,
|
|
1181
|
-
babelrc: false,
|
|
1182
|
-
});
|
|
1183
|
-
if (result?.code) {
|
|
1184
|
-
return { contents: result.code, loader: 'js' };
|
|
1185
|
-
}
|
|
1186
|
-
}
|
|
1187
|
-
catch (e) {
|
|
1188
|
-
console.warn(`[ns-vendor-solid-jsx] failed to transform ${args.path}:`, e?.message || e);
|
|
1189
|
-
}
|
|
1190
|
-
// Fall through to esbuild's default handling
|
|
1191
|
-
return undefined;
|
|
1192
|
-
});
|
|
1193
|
-
},
|
|
1194
|
-
};
|
|
1195
|
-
}
|
|
1196
|
-
/**
|
|
1197
|
-
* Minimal esbuild plugin to run Angular linker (Babel) over partial-compiled
|
|
1198
|
-
* Angular packages in node_modules. This converts ɵɵngDeclare* calls into
|
|
1199
|
-
* ɵɵdefine* so runtime doesn't require the JIT compiler.
|
|
1200
|
-
*/
|
|
1201
|
-
function angularLinkerEsbuildPlugin(projectRoot) {
|
|
1202
|
-
// Restrict to Angular framework packages to minimize esbuild memory usage.
|
|
1203
|
-
const FILTER = /node_modules[\\/](?:@angular|@nativescript[\\/]angular)[\\/].*\.[mc]?js$/;
|
|
1204
|
-
return {
|
|
1205
|
-
name: 'ns-angular-linker',
|
|
1206
|
-
async setup(build) {
|
|
1207
|
-
const debug = process.env.VITE_DEBUG_LOGS === 'true' || process.env.VITE_DEBUG_LOGS === '1';
|
|
1208
|
-
const { babel, createLinker } = await getAngularLinkerFactory(projectRoot);
|
|
1209
|
-
if (!babel || !createLinker) {
|
|
1210
|
-
// Nothing to do if deps unavailable
|
|
1211
|
-
return;
|
|
1212
|
-
}
|
|
1213
|
-
build.onLoad({ filter: FILTER }, async (args) => {
|
|
1214
|
-
try {
|
|
1215
|
-
const source = await readFile(args.path, 'utf8');
|
|
1216
|
-
// Fast-path: only run linker when partial declarations are present
|
|
1217
|
-
if (!(source.includes('\u0275\u0275ngDeclare') || source.includes('ɵɵngDeclare'))) {
|
|
1218
|
-
return { contents: source, loader: 'js' };
|
|
1219
|
-
}
|
|
1220
|
-
if (debug) {
|
|
1221
|
-
console.log('[ns-angular-linker][vendor] linking', args.path);
|
|
1222
|
-
}
|
|
1223
|
-
const linked = await runAngularLinker(source, { filename: args.path, projectRoot, freshPlugin: true });
|
|
1224
|
-
return { contents: linked || source, loader: 'js' };
|
|
1225
|
-
}
|
|
1226
|
-
catch {
|
|
1227
|
-
return { contents: await readFile(args.path, 'utf8'), loader: 'js' };
|
|
1228
|
-
}
|
|
1229
|
-
});
|
|
1230
|
-
},
|
|
1231
|
-
};
|
|
1232
|
-
}
|
|
1233
|
-
const vendorModuleShim = `
|
|
1234
|
-
const g = globalThis;
|
|
1235
|
-
const BACKSLASH = String.fromCharCode(92);
|
|
1236
|
-
|
|
1237
|
-
function toForwardSlashes(input) {
|
|
1238
|
-
return String(input ?? '').split(BACKSLASH).join('/');
|
|
1239
|
-
}
|
|
1240
|
-
|
|
1241
|
-
function getNativeScriptRequire() {
|
|
1242
|
-
const nsRequire = typeof g.require === "function" ? g.require : null;
|
|
1243
|
-
if (nsRequire) {
|
|
1244
|
-
return nsRequire;
|
|
1245
|
-
}
|
|
1246
|
-
const legacy = g.__nsRequire;
|
|
1247
|
-
if (typeof legacy === "function") {
|
|
1248
|
-
return legacy;
|
|
1249
|
-
}
|
|
1250
|
-
return null;
|
|
1251
|
-
}
|
|
1252
|
-
|
|
1253
|
-
function getDocumentsPath() {
|
|
1254
|
-
const cached = g.__NS_DOCUMENTS_PATH__;
|
|
1255
|
-
if (typeof cached === "string" && cached.length) {
|
|
1256
|
-
return toForwardSlashes(cached);
|
|
1257
|
-
}
|
|
1258
|
-
try {
|
|
1259
|
-
const core = g.require ? g.require("@nativescript/core") : null;
|
|
1260
|
-
const docsFolder = core?.knownFolders?.documents?.();
|
|
1261
|
-
const docPath = docsFolder?.path;
|
|
1262
|
-
if (docPath) {
|
|
1263
|
-
const normalized = toForwardSlashes(docPath);
|
|
1264
|
-
g.__NS_DOCUMENTS_PATH__ = normalized;
|
|
1265
|
-
return normalized;
|
|
1266
|
-
}
|
|
1267
|
-
} catch (_err) {
|
|
1268
|
-
// ignore - fallback to raw specifier
|
|
1269
|
-
}
|
|
1270
|
-
return null;
|
|
1271
|
-
}
|
|
1272
|
-
|
|
1273
|
-
function collapseSegments(input) {
|
|
1274
|
-
const segments = [];
|
|
1275
|
-
const parts = input.split('/');
|
|
1276
|
-
for (const part of parts) {
|
|
1277
|
-
if (!part || part === ".") {
|
|
1278
|
-
continue;
|
|
1279
|
-
}
|
|
1280
|
-
if (part === "..") {
|
|
1281
|
-
if (segments.length && segments[segments.length - 1] !== "..") {
|
|
1282
|
-
segments.pop();
|
|
1283
|
-
continue;
|
|
1284
|
-
}
|
|
1285
|
-
}
|
|
1286
|
-
segments.push(part);
|
|
1287
|
-
}
|
|
1288
|
-
const leadingSlash = input.startsWith('/');
|
|
1289
|
-
return (leadingSlash ? '/' : '') + segments.join('/');
|
|
1290
|
-
}
|
|
1291
|
-
|
|
1292
|
-
function normalizeSpecifier(spec) {
|
|
1293
|
-
let value = String(spec ?? "");
|
|
1294
|
-
value = toForwardSlashes(value);
|
|
1295
|
-
const docsPath = getDocumentsPath();
|
|
1296
|
-
if (value.startsWith("__NSDOC__/")) {
|
|
1297
|
-
if (docsPath) {
|
|
1298
|
-
value = docsPath + '/' + value.slice("__NSDOC__/".length);
|
|
1299
|
-
} else {
|
|
1300
|
-
value = value.slice("__NSDOC__/".length);
|
|
1301
|
-
}
|
|
1302
|
-
}
|
|
1303
|
-
if (value.startsWith("~/") && docsPath) {
|
|
1304
|
-
value = docsPath + '/' + value.slice(2);
|
|
1305
|
-
}
|
|
1306
|
-
if (value.startsWith("file://")) {
|
|
1307
|
-
const stripped = value.slice("file://".length);
|
|
1308
|
-
value = stripped.startsWith('/') ? stripped : '/' + stripped;
|
|
1309
|
-
}
|
|
1310
|
-
if (value.includes("/../") || value.includes("/./")) {
|
|
1311
|
-
value = collapseSegments(value);
|
|
1312
|
-
}
|
|
1313
|
-
return value;
|
|
1314
|
-
}
|
|
1315
|
-
|
|
1316
|
-
function normalizeCoreSubLocal(s) {
|
|
1317
|
-
if (!s) return "";
|
|
1318
|
-
let t = String(s).split("?")[0].split("#")[0].trim();
|
|
1319
|
-
t = t.replace(/^\\/+/, "").replace(/\\/+$/, "");
|
|
1320
|
-
t = t.replace(/\\.(?:mjs|cjs|js)$/, "");
|
|
1321
|
-
if (t.length >= 6 && t.substring(t.length - 6) === "/index") {
|
|
1322
|
-
t = t.substring(0, t.length - 6);
|
|
1323
|
-
}
|
|
1324
|
-
if (!t || t === "index") return "";
|
|
1325
|
-
return t;
|
|
1326
|
-
}
|
|
1327
|
-
|
|
1328
|
-
// Invariant D: shape ESM namespaces before returning to CJS callers.
|
|
1329
|
-
//
|
|
1330
|
-
// The /ns/core handler's registration footer (see websocket.ts) and the
|
|
1331
|
-
// main-entry require shim (see helpers/main-entry.ts) both install the
|
|
1332
|
-
// shape function on globalThis. In practice, entries stored in
|
|
1333
|
-
// __NS_CORE_MODULES__ are ALREADY shaped, so this pass-through is a
|
|
1334
|
-
// fast no-op (the shape function's fast path returns obj as-is when it
|
|
1335
|
-
// already has Object.prototype). We call it anyway as defense-in-depth
|
|
1336
|
-
// against future callers that might populate the registry without
|
|
1337
|
-
// shaping.
|
|
1338
|
-
function shapeForCjs(value) {
|
|
1339
|
-
if (!value || typeof value !== "object") return value;
|
|
1340
|
-
const shape = g.__NS_CJS_SHAPE__;
|
|
1341
|
-
if (typeof shape === "function") {
|
|
1342
|
-
try { return shape(value); } catch (e) {}
|
|
1343
|
-
}
|
|
1344
|
-
return value;
|
|
1345
|
-
}
|
|
1346
|
-
|
|
1347
|
-
function resolveCoreFromRegistry(normalizedId) {
|
|
1348
|
-
if (
|
|
1349
|
-
normalizedId !== "@nativescript/core" &&
|
|
1350
|
-
normalizedId.indexOf("@nativescript/core/") !== 0
|
|
1351
|
-
) {
|
|
1352
|
-
return null;
|
|
1353
|
-
}
|
|
1354
|
-
const table = g.__NS_CORE_MODULES__;
|
|
1355
|
-
if (!table) return null;
|
|
1356
|
-
if (table[normalizedId]) return shapeForCjs(table[normalizedId]);
|
|
1357
|
-
const rawSub =
|
|
1358
|
-
normalizedId === "@nativescript/core"
|
|
1359
|
-
? ""
|
|
1360
|
-
: normalizedId.slice("@nativescript/core/".length);
|
|
1361
|
-
const normSub = normalizeCoreSubLocal(rawSub);
|
|
1362
|
-
const bareKey = normSub ? "@nativescript/core/" + normSub : "@nativescript/core";
|
|
1363
|
-
if (table[bareKey]) return shapeForCjs(table[bareKey]);
|
|
1364
|
-
if (normSub && table[normSub]) return shapeForCjs(table[normSub]);
|
|
1365
|
-
if (!normSub && table[""]) return shapeForCjs(table[""]);
|
|
1366
|
-
return null;
|
|
1367
|
-
}
|
|
1368
|
-
|
|
1369
|
-
export function createRequire(_url) {
|
|
1370
|
-
const nsRequire = getNativeScriptRequire();
|
|
1371
|
-
if (!nsRequire) {
|
|
1372
|
-
return function (id) {
|
|
1373
|
-
// Even without nsRequire, the @nativescript/core registry populated by
|
|
1374
|
-
// the /ns/core bridge may already have the module — return it so
|
|
1375
|
-
// vendor install() hooks that run against the HMR-served core don't
|
|
1376
|
-
// crash at module-instantiation time.
|
|
1377
|
-
const fromRegistry = resolveCoreFromRegistry(normalizeSpecifier(id));
|
|
1378
|
-
if (fromRegistry) return fromRegistry;
|
|
1379
|
-
throw new Error("NativeScript require() is not available in this context");
|
|
1380
|
-
};
|
|
1381
|
-
}
|
|
1382
|
-
const req = function (id) {
|
|
1383
|
-
const normalizedId = normalizeSpecifier(id);
|
|
1384
|
-
// Invariant C: @nativescript/core and its subpaths are served ONCE via
|
|
1385
|
-
// the /ns/core HTTP bridge, which self-registers each module's ESM
|
|
1386
|
-
// namespace on globalThis.__NS_CORE_MODULES__. CommonJS require() from
|
|
1387
|
-
// vendor packages (e.g. \`require('@nativescript/core/ui/core/view').View\`
|
|
1388
|
-
// in @nativescript-community/gesturehandler, or \`require('@nativescript/core').View\`
|
|
1389
|
-
// in @nativescript-community/ui-material-core) MUST resolve to that
|
|
1390
|
-
// same namespace; otherwise we re-trigger class identity splits and
|
|
1391
|
-
// applyMixins() crashes with "Cannot read properties of undefined".
|
|
1392
|
-
const fromRegistry = resolveCoreFromRegistry(normalizedId);
|
|
1393
|
-
if (fromRegistry) return fromRegistry;
|
|
1394
|
-
if (
|
|
1395
|
-
normalizedId.includes("../data/patch.json") ||
|
|
1396
|
-
normalizedId.includes("css-tree/lib/data/patch.json")
|
|
1397
|
-
) {
|
|
1398
|
-
return {
|
|
1399
|
-
atrules: {},
|
|
1400
|
-
properties: {},
|
|
1401
|
-
types: {},
|
|
1402
|
-
};
|
|
1403
|
-
}
|
|
1404
|
-
if (normalizedId.includes("mdn-data/")) {
|
|
1405
|
-
return {};
|
|
1406
|
-
}
|
|
1407
|
-
if (
|
|
1408
|
-
normalizedId.endsWith("/package.json") ||
|
|
1409
|
-
normalizedId.includes("../package.json")
|
|
1410
|
-
) {
|
|
1411
|
-
return { version: "0.0.0" };
|
|
1412
|
-
}
|
|
1413
|
-
if (normalizedId.endsWith(".json")) {
|
|
1414
|
-
return {};
|
|
1415
|
-
}
|
|
1416
|
-
// Shape the native require result too. The NativeScript CJS loader
|
|
1417
|
-
// may serve an @nativescript/core subpath over HTTP before the
|
|
1418
|
-
// /ns/core footer has run (e.g., during initial boot). In that
|
|
1419
|
-
// window, the result is a raw ESM namespace with null [[Prototype]]
|
|
1420
|
-
// and zone.js/vendor install() hooks crash on hasOwnProperty.
|
|
1421
|
-
return shapeForCjs(nsRequire(normalizedId));
|
|
1422
|
-
};
|
|
1423
|
-
req.resolve = nsRequire.resolve
|
|
1424
|
-
? function (id) {
|
|
1425
|
-
return nsRequire.resolve(id);
|
|
1426
|
-
}
|
|
1427
|
-
: function (id) {
|
|
1428
|
-
return id;
|
|
1429
|
-
};
|
|
1430
|
-
return req;
|
|
1431
|
-
}
|
|
1432
|
-
|
|
1433
|
-
export default { createRequire };
|
|
1434
|
-
`;
|
|
1435
524
|
function stripIndexSuffix(specifier) {
|
|
1436
525
|
return specifier.replace(/\/(?:(?:index)(?:\.[^.\/]+)?)$/, '');
|
|
1437
526
|
}
|