@nativescript/vite 0.0.1 → 1.0.0
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/LICENSE +19 -0
- package/README.md +81 -0
- package/{dist/configuration → configuration}/angular.d.ts +1 -1
- package/configuration/angular.js +371 -0
- package/configuration/angular.js.map +1 -0
- package/configuration/base.d.ts +5 -0
- package/configuration/base.js +491 -0
- package/configuration/base.js.map +1 -0
- package/configuration/javascript.d.ts +4 -0
- package/configuration/javascript.js +152 -0
- package/configuration/javascript.js.map +1 -0
- package/{dist/configuration → configuration}/react.d.ts +1 -1
- package/{dist/configuration → configuration}/react.js +18 -17
- package/configuration/react.js.map +1 -0
- package/{dist/configuration → configuration}/solid.d.ts +1 -1
- package/{dist/configuration → configuration}/solid.js +17 -16
- package/configuration/solid.js.map +1 -0
- package/configuration/typescript.d.ts +4 -0
- package/configuration/typescript.js +176 -0
- package/configuration/typescript.js.map +1 -0
- package/{dist/configuration → configuration}/vue.d.ts +1 -1
- package/configuration/vue.js +163 -0
- package/configuration/vue.js.map +1 -0
- package/helpers/angular/angular-linker.d.ts +13 -0
- package/helpers/angular/angular-linker.js +189 -0
- package/helpers/angular/angular-linker.js.map +1 -0
- package/helpers/angular/shared-linker.d.ts +4 -0
- package/helpers/angular/shared-linker.js +39 -0
- package/helpers/angular/shared-linker.js.map +1 -0
- package/helpers/angular/util.d.ts +1 -0
- package/helpers/angular/util.js +67 -0
- package/helpers/angular/util.js.map +1 -0
- package/helpers/cli-flags.d.ts +1 -0
- package/helpers/cli-flags.js +15 -0
- package/helpers/cli-flags.js.map +1 -0
- package/{dist/helpers → helpers}/commonjs-plugins.js +14 -13
- package/helpers/commonjs-plugins.js.map +1 -0
- package/{dist/helpers → helpers}/config-as-json.d.ts +1 -1
- package/{dist/helpers → helpers}/config-as-json.js +7 -6
- package/helpers/config-as-json.js.map +1 -0
- package/helpers/css-platform-plugin.d.ts +10 -0
- package/helpers/css-platform-plugin.js +76 -0
- package/helpers/css-platform-plugin.js.map +1 -0
- package/helpers/css-tree.js +22 -0
- package/helpers/css-tree.js.map +1 -0
- package/{dist/helpers → helpers}/dynamic-import-plugin.js +8 -7
- package/helpers/dynamic-import-plugin.js.map +1 -0
- package/helpers/esbuild-platform-resolver.d.ts +14 -0
- package/helpers/esbuild-platform-resolver.js +93 -0
- package/helpers/esbuild-platform-resolver.js.map +1 -0
- package/helpers/external-configs.d.ts +6 -0
- package/helpers/external-configs.js +34 -0
- package/helpers/external-configs.js.map +1 -0
- package/{dist/helpers → helpers}/flavor.d.ts +1 -0
- package/helpers/flavor.js +51 -0
- package/helpers/flavor.js.map +1 -0
- package/helpers/global-defines.d.ts +25 -0
- package/helpers/global-defines.js +29 -0
- package/helpers/global-defines.js.map +1 -0
- package/helpers/init.d.ts +1 -0
- package/helpers/init.js +119 -0
- package/helpers/init.js.map +1 -0
- package/helpers/logging.d.ts +13 -0
- package/helpers/logging.js +115 -0
- package/helpers/logging.js.map +1 -0
- package/helpers/main-entry.d.ts +10 -0
- package/helpers/main-entry.js +223 -0
- package/helpers/main-entry.js.map +1 -0
- package/{dist/helpers → helpers}/module-resolution.js +4 -3
- package/helpers/module-resolution.js.map +1 -0
- package/helpers/module-runner-patch.d.ts +3 -0
- package/helpers/module-runner-patch.js +63 -0
- package/helpers/module-runner-patch.js.map +1 -0
- package/helpers/nativeclass-transform.d.ts +7 -0
- package/helpers/nativeclass-transform.js +158 -0
- package/helpers/nativeclass-transform.js.map +1 -0
- package/helpers/nativeclass-transformer-plugin.d.ts +5 -0
- package/helpers/nativeclass-transformer-plugin.js +23 -0
- package/helpers/nativeclass-transformer-plugin.js.map +1 -0
- package/{dist/helpers → helpers}/nativescript-package-resolver.js +18 -17
- package/helpers/nativescript-package-resolver.js.map +1 -0
- package/helpers/ns-cli-plugins.d.ts +14 -0
- package/helpers/ns-cli-plugins.js +165 -0
- package/helpers/ns-cli-plugins.js.map +1 -0
- package/helpers/package-platform-aliases.d.ts +10 -0
- package/{dist/helpers → helpers}/package-platform-aliases.js +19 -23
- package/helpers/package-platform-aliases.js.map +1 -0
- package/helpers/postcss-platform-config.d.ts +13 -0
- package/helpers/postcss-platform-config.js +97 -0
- package/helpers/postcss-platform-config.js.map +1 -0
- package/helpers/prelink-angular.d.ts +2 -0
- package/helpers/prelink-angular.js +117 -0
- package/helpers/prelink-angular.js.map +1 -0
- package/helpers/preserve-imports.d.ts +2 -0
- package/helpers/preserve-imports.js +38 -0
- package/helpers/preserve-imports.js.map +1 -0
- package/{dist/helpers → helpers}/project.js +2 -4
- package/helpers/project.js.map +1 -0
- package/helpers/resolver.d.ts +4 -0
- package/{dist/helpers → helpers}/resolver.js +7 -6
- package/helpers/resolver.js.map +1 -0
- package/helpers/theme-core-plugins.d.ts +14 -0
- package/helpers/theme-core-plugins.js +121 -0
- package/helpers/theme-core-plugins.js.map +1 -0
- package/helpers/ts-config-paths.d.ts +10 -0
- package/{dist/helpers → helpers}/ts-config-paths.js +73 -72
- package/helpers/ts-config-paths.js.map +1 -0
- package/{dist/helpers → helpers}/utils.d.ts +10 -0
- package/helpers/utils.js +143 -0
- package/helpers/utils.js.map +1 -0
- package/{dist/helpers → helpers}/workers.js +15 -16
- package/helpers/workers.js.map +1 -0
- package/hmr/client/css-handler.d.ts +4 -0
- package/hmr/client/css-handler.js +78 -0
- package/hmr/client/css-handler.js.map +1 -0
- package/hmr/client/index.d.ts +13 -0
- package/hmr/client/index.js +1723 -0
- package/hmr/client/index.js.map +1 -0
- package/hmr/client/utils.d.ts +38 -0
- package/hmr/client/utils.js +426 -0
- package/hmr/client/utils.js.map +1 -0
- package/hmr/entry-runtime.d.ts +8 -0
- package/hmr/entry-runtime.js +135 -0
- package/hmr/entry-runtime.js.map +1 -0
- package/hmr/frameworks/angular/client/index.d.ts +8 -0
- package/hmr/frameworks/angular/client/index.js +59 -0
- package/hmr/frameworks/angular/client/index.js.map +1 -0
- package/hmr/frameworks/angular/server/linker.d.ts +1 -0
- package/hmr/frameworks/angular/server/linker.js +101 -0
- package/hmr/frameworks/angular/server/linker.js.map +1 -0
- package/hmr/frameworks/angular/server/strategy.d.ts +2 -0
- package/hmr/frameworks/angular/server/strategy.js +187 -0
- package/hmr/frameworks/angular/server/strategy.js.map +1 -0
- package/hmr/frameworks/solid/server/strategy.d.ts +2 -0
- package/hmr/frameworks/solid/server/strategy.js +56 -0
- package/hmr/frameworks/solid/server/strategy.js.map +1 -0
- package/hmr/frameworks/typescript/server/strategy.d.ts +2 -0
- package/hmr/frameworks/typescript/server/strategy.js +125 -0
- package/hmr/frameworks/typescript/server/strategy.js.map +1 -0
- package/hmr/frameworks/vue/client/index.d.ts +22 -0
- package/hmr/frameworks/vue/client/index.js +1541 -0
- package/hmr/frameworks/vue/client/index.js.map +1 -0
- package/hmr/frameworks/vue/server/compiler.d.ts +11 -0
- package/hmr/frameworks/vue/server/compiler.js +26 -0
- package/hmr/frameworks/vue/server/compiler.js.map +1 -0
- package/hmr/frameworks/vue/server/sfc-transforms.d.ts +14 -0
- package/hmr/frameworks/vue/server/sfc-transforms.js +282 -0
- package/hmr/frameworks/vue/server/sfc-transforms.js.map +1 -0
- package/hmr/frameworks/vue/server/strategy.d.ts +2 -0
- package/hmr/frameworks/vue/server/strategy.js +272 -0
- package/hmr/frameworks/vue/server/strategy.js.map +1 -0
- package/hmr/helpers/ast-extract.d.ts +6 -0
- package/hmr/helpers/ast-extract.js +72 -0
- package/hmr/helpers/ast-extract.js.map +1 -0
- package/hmr/helpers/ast-normalizer.d.ts +7 -0
- package/hmr/helpers/ast-normalizer.js +772 -0
- package/hmr/helpers/ast-normalizer.js.map +1 -0
- package/hmr/helpers/babel.d.ts +3 -0
- package/hmr/helpers/babel.js +17 -0
- package/hmr/helpers/babel.js.map +1 -0
- package/hmr/helpers/sanitize.d.ts +6 -0
- package/hmr/helpers/sanitize.js +55 -0
- package/hmr/helpers/sanitize.js.map +1 -0
- package/hmr/helpers/vendor-rewrite.d.ts +1 -0
- package/hmr/helpers/vendor-rewrite.js +35 -0
- package/hmr/helpers/vendor-rewrite.js.map +1 -0
- package/hmr/server/compiler.d.ts +2 -0
- package/hmr/server/compiler.js +75 -0
- package/hmr/server/compiler.js.map +1 -0
- package/hmr/server/constants.d.ts +14 -0
- package/hmr/server/constants.js +23 -0
- package/hmr/server/constants.js.map +1 -0
- package/hmr/server/core-sanitize.d.ts +32 -0
- package/hmr/server/core-sanitize.js +134 -0
- package/hmr/server/core-sanitize.js.map +1 -0
- package/hmr/server/framework-strategy.d.ts +68 -0
- package/hmr/server/framework-strategy.js +2 -0
- package/hmr/server/framework-strategy.js.map +1 -0
- package/hmr/server/index.d.ts +5 -0
- package/hmr/server/index.js +23 -0
- package/hmr/server/index.js.map +1 -0
- package/hmr/server/vite-plugin.d.ts +5 -0
- package/hmr/server/vite-plugin.js +44 -0
- package/hmr/server/vite-plugin.js.map +1 -0
- package/hmr/server/websocket.d.ts +21 -0
- package/hmr/server/websocket.js +5619 -0
- package/hmr/server/websocket.js.map +1 -0
- package/hmr/shared/runtime/http-only-boot.d.ts +1 -0
- package/hmr/shared/runtime/http-only-boot.js +107 -0
- package/hmr/shared/runtime/http-only-boot.js.map +1 -0
- package/hmr/shared/runtime/root-placeholder.d.ts +1 -0
- package/hmr/shared/runtime/root-placeholder.js +142 -0
- package/hmr/shared/runtime/root-placeholder.js.map +1 -0
- package/hmr/shared/runtime/vendor-bootstrap.d.ts +1 -0
- package/hmr/shared/runtime/vendor-bootstrap.js +134 -0
- package/hmr/shared/runtime/vendor-bootstrap.js.map +1 -0
- package/hmr/shared/vendor/manifest-loader.d.ts +9 -0
- package/hmr/shared/vendor/manifest-loader.js +38 -0
- package/hmr/shared/vendor/manifest-loader.js.map +1 -0
- package/hmr/shared/vendor/manifest.d.ts +35 -0
- package/hmr/shared/vendor/manifest.js +811 -0
- package/hmr/shared/vendor/manifest.js.map +1 -0
- package/hmr/shared/vendor/registry.d.ts +9 -0
- package/hmr/shared/vendor/registry.js +62 -0
- package/hmr/shared/vendor/registry.js.map +1 -0
- package/hmr/vendor-bootstrap.d.ts +3 -0
- package/hmr/vendor-bootstrap.js +32 -0
- package/hmr/vendor-bootstrap.js.map +1 -0
- package/{dist/index.d.ts → index.d.ts} +2 -0
- package/index.js +19 -0
- package/index.js.map +1 -0
- package/package.json +42 -30
- package/{dist/polyfills → polyfills}/mdn-data-at-rules.js +1 -0
- package/polyfills/mdn-data-at-rules.js.map +1 -0
- package/{dist/polyfills → polyfills}/mdn-data-properties.js +1 -0
- package/polyfills/mdn-data-properties.js.map +1 -0
- package/{dist/polyfills → polyfills}/mdn-data-syntaxes.js +1 -0
- package/polyfills/mdn-data-syntaxes.js.map +1 -0
- package/{dist/polyfills → polyfills}/module.js +1 -0
- package/polyfills/module.js.map +1 -0
- package/runtime/core-aliases-early.d.ts +1 -0
- package/runtime/core-aliases-early.js +334 -0
- package/runtime/core-aliases-early.js.map +1 -0
- package/shims/angular-animations-stub.d.ts +68 -0
- package/shims/angular-animations-stub.js +140 -0
- package/shims/angular-animations-stub.js.map +1 -0
- package/shims/node-module.d.ts +5 -0
- package/shims/node-module.js +13 -0
- package/shims/node-module.js.map +1 -0
- package/{dist/shims → shims}/react-reconciler-constants.js +2 -1
- package/shims/react-reconciler-constants.js.map +1 -0
- package/{dist/shims → shims}/react-reconciler.js +1 -0
- package/shims/react-reconciler.js.map +1 -0
- package/{dist/shims → shims}/set-value.js +5 -1
- package/shims/set-value.js.map +1 -0
- package/transformers/NativeClass/index.d.ts +2 -0
- package/transformers/NativeClass/index.js +222 -0
- package/transformers/NativeClass/index.js.map +1 -0
- package/dist/configuration/angular.js +0 -30
- package/dist/configuration/base.d.ts +0 -13
- package/dist/configuration/base.js +0 -228
- package/dist/configuration/old-without-merge-base.d.ts +0 -13
- package/dist/configuration/old-without-merge-base.js +0 -249
- package/dist/configuration/vue.js +0 -45
- package/dist/helpers/css-tree.js +0 -21
- package/dist/helpers/flavor.js +0 -40
- package/dist/helpers/global-defines.d.ts +0 -14
- package/dist/helpers/global-defines.js +0 -18
- package/dist/helpers/main-entry.d.ts +0 -5
- package/dist/helpers/main-entry.js +0 -75
- package/dist/helpers/ns-cli-plugins.d.ts +0 -17
- package/dist/helpers/ns-cli-plugins.js +0 -128
- package/dist/helpers/package-platform-aliases.d.ts +0 -4
- package/dist/helpers/resolver.d.ts +0 -4
- package/dist/helpers/ts-config-paths.d.ts +0 -4
- package/dist/helpers/utils.js +0 -94
- package/dist/hmr/hmr-angular.d.ts +0 -1
- package/dist/hmr/hmr-angular.js +0 -34
- package/dist/hmr/hmr-bridge.d.ts +0 -18
- package/dist/hmr/hmr-bridge.js +0 -154
- package/dist/hmr/hmr-client.d.ts +0 -5
- package/dist/hmr/hmr-client.js +0 -93
- package/dist/hmr/hmr-server.d.ts +0 -20
- package/dist/hmr/hmr-server.js +0 -179
- package/dist/index.js +0 -5
- package/dist/transformers/NativeClass/index.d.ts +0 -5
- package/dist/transformers/NativeClass/index.js +0 -46
- /package/{dist/helpers → helpers}/commonjs-plugins.d.ts +0 -0
- /package/{dist/helpers → helpers}/css-tree.d.ts +0 -0
- /package/{dist/helpers → helpers}/dynamic-import-plugin.d.ts +0 -0
- /package/{dist/helpers → helpers}/module-resolution.d.ts +0 -0
- /package/{dist/helpers → helpers}/nativescript-package-resolver.d.ts +0 -0
- /package/{dist/helpers → helpers}/project.d.ts +0 -0
- /package/{dist/helpers → helpers}/workers.d.ts +0 -0
- /package/{dist/polyfills → polyfills}/mdn-data-at-rules.d.ts +0 -0
- /package/{dist/polyfills → polyfills}/mdn-data-properties.d.ts +0 -0
- /package/{dist/polyfills → polyfills}/mdn-data-syntaxes.d.ts +0 -0
- /package/{dist/polyfills → polyfills}/module.d.ts +0 -0
- /package/{dist/shims → shims}/react-reconciler-constants.d.ts +0 -0
- /package/{dist/shims → shims}/react-reconciler.d.ts +0 -0
- /package/{dist/shims → shims}/set-value.d.ts +0 -0
|
@@ -0,0 +1,772 @@
|
|
|
1
|
+
// AST-first normalization helpers for HMR HTTP ESM runtime
|
|
2
|
+
// - Ensures a single default import from '/ns/rt' with one destructure of underscored helpers
|
|
3
|
+
// - Filters $navigateTo/$navigateBack from any /ns/rt named imports at the AST boundary
|
|
4
|
+
// - Adds a verification pass to annotate duplicate top-level const/let bindings
|
|
5
|
+
import { parse as babelParse } from '@babel/parser';
|
|
6
|
+
import traverse from '@babel/traverse';
|
|
7
|
+
import * as t from '@babel/types';
|
|
8
|
+
import { genCode } from './babel.js';
|
|
9
|
+
// Ensure traverse callable across CJS/ESM builds
|
|
10
|
+
const babelTraverse = traverse?.default || traverse;
|
|
11
|
+
// Normalize imports and helper aliases deterministically.
|
|
12
|
+
// Contract:
|
|
13
|
+
// - Input: arbitrary JS/TS module text
|
|
14
|
+
// - Output: JS with a single default import from '/ns/rt' and one destructure for any underscored helpers used
|
|
15
|
+
// - Navigation helpers are stripped from any /ns/rt named imports
|
|
16
|
+
// - A marker comment '/* [ast-normalized] */' is injected at the top
|
|
17
|
+
export function astNormalizeModuleImportsAndHelpers(code) {
|
|
18
|
+
try {
|
|
19
|
+
// Pre-scan for underscored helper usages to inform aliasing during import rewrite
|
|
20
|
+
const needAlias = new Set();
|
|
21
|
+
try {
|
|
22
|
+
const re = /(^|[^.\w$])_([A-Za-z]\w*)\b/g;
|
|
23
|
+
let m;
|
|
24
|
+
while ((m = re.exec(code))) {
|
|
25
|
+
const base = m[2].replace(/^_+/, '');
|
|
26
|
+
if (!/(^|_)(ctx|cache)$/.test(base) && !/^(hoisted_|component_|directive_|sfc_main|ns_sfc__|ns_sfc|sfc)/.test(base)) {
|
|
27
|
+
needAlias.add(base);
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
catch { }
|
|
32
|
+
const ast = babelParse(code, {
|
|
33
|
+
sourceType: 'module',
|
|
34
|
+
plugins: ['typescript', 'jsx', 'importMeta', 'topLevelAwait'],
|
|
35
|
+
errorRecovery: true,
|
|
36
|
+
allowReturnOutsideFunction: true,
|
|
37
|
+
allowUndeclaredExports: true,
|
|
38
|
+
});
|
|
39
|
+
const underscoreUses = new Set();
|
|
40
|
+
const declared = new Set();
|
|
41
|
+
let navToUsed = false;
|
|
42
|
+
let navBackUsed = false;
|
|
43
|
+
let defineStoreUsed = false;
|
|
44
|
+
let showModalUsed = false;
|
|
45
|
+
const isRtLike = (src) => !!src && /(?:https?:\/\/[^"']+)?\/ns\/rt(?:\/[\d]+)?(?:\?p=[^"']+)?$/.test(src);
|
|
46
|
+
const isCoreLike = (src) => !!src && /(?:https?:\/\/[^"']+)?\/ns\/core(?:\/[\d]+)?(?:\?p=[^"']+)?$/.test(src);
|
|
47
|
+
const isSfcPath = (src) => !!src && /\.vue(?:\?|$)/.test(src);
|
|
48
|
+
const isVuePrebundle = (src) => !!src && /\.vite\/deps\/(?:vue|nativescript-vue)[^/]*\.js/.test(src);
|
|
49
|
+
const isVuePackage = (src) => !!src && (src === 'vue' || src.startsWith('vue/') || src.includes('nativescript-vue'));
|
|
50
|
+
const isVueLike = (src) => (isVuePackage(src) || isVuePrebundle(src)) && !isSfcPath(src);
|
|
51
|
+
const isViteVirtual = (src) => !!src && (/\/\@id\//.test(src) || /\0/.test(src) || /__x00__/.test(src));
|
|
52
|
+
const isVitePrebundle = (src) => !!src && /node_modules\/\.vite\/deps\//.test(src);
|
|
53
|
+
const vitePrebundleId = (src) => {
|
|
54
|
+
if (!src)
|
|
55
|
+
return null;
|
|
56
|
+
const m = src.match(/\.vite\/deps\/([^?]+?)\.[mc]?js/);
|
|
57
|
+
return m ? m[1] : null;
|
|
58
|
+
};
|
|
59
|
+
const isNsCorePackage = (src) => !!src && /^@nativescript\/core(\/.*)?$/.test(src);
|
|
60
|
+
let seq = 0;
|
|
61
|
+
const makeUid = (hint) => `__ns_${hint}_${++seq}`;
|
|
62
|
+
const uniqueRtLocal = (preferred) => {
|
|
63
|
+
let name = preferred && !declared.has(preferred) ? preferred : '';
|
|
64
|
+
if (!name) {
|
|
65
|
+
let i = 1;
|
|
66
|
+
while (declared.has(`__ns_rt_ns_${i}`))
|
|
67
|
+
i++;
|
|
68
|
+
name = `__ns_rt_ns_${i}`;
|
|
69
|
+
}
|
|
70
|
+
return name;
|
|
71
|
+
};
|
|
72
|
+
let existingRtImport = null;
|
|
73
|
+
let existingRtDefaultLocal = null;
|
|
74
|
+
const existingRtLocals = new Set();
|
|
75
|
+
babelTraverse(ast, {
|
|
76
|
+
Program(path) {
|
|
77
|
+
Object.keys(path.scope.bindings).forEach((b) => declared.add(b));
|
|
78
|
+
},
|
|
79
|
+
ImportDeclaration(path) {
|
|
80
|
+
const src = path.node.source?.value;
|
|
81
|
+
if (src === '@') {
|
|
82
|
+
path.node.source = t.stringLiteral('/ns/m/__invalid_at__.mjs');
|
|
83
|
+
}
|
|
84
|
+
if (isVueLike(src)) {
|
|
85
|
+
path.node.source = t.stringLiteral('/ns/rt');
|
|
86
|
+
}
|
|
87
|
+
else if (isNsCorePackage(src)) {
|
|
88
|
+
// Rewrite any @nativescript/core[/*] to the HTTP-ESM bridge
|
|
89
|
+
path.node.source = t.stringLiteral('/ns/core');
|
|
90
|
+
}
|
|
91
|
+
else if (isVitePrebundle(src)) {
|
|
92
|
+
const id = vitePrebundleId(src);
|
|
93
|
+
if (id && /^(?:pinia)(?:$|[_\.-])/.test(id)) {
|
|
94
|
+
// Rewrite pinia prebundles to bare 'pinia' so vendor binding can handle it later
|
|
95
|
+
path.node.source = t.stringLiteral('pinia');
|
|
96
|
+
}
|
|
97
|
+
else if (isVuePrebundle(src)) {
|
|
98
|
+
// Route vue prebundles to runtime bridge
|
|
99
|
+
path.node.source = t.stringLiteral('/ns/rt');
|
|
100
|
+
}
|
|
101
|
+
else {
|
|
102
|
+
// Keep other prebundles as-is; they may be fetchable directly from the dev server
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
else if (isViteVirtual(src) || src === '@vite/client' || src === '/@vite/client') {
|
|
106
|
+
path.remove();
|
|
107
|
+
return;
|
|
108
|
+
}
|
|
109
|
+
const isRt = isRtLike(path.node.source?.value);
|
|
110
|
+
const isCore = isCoreLike(path.node.source?.value);
|
|
111
|
+
// Ensure any generated binding names are valid identifiers and not reserved like 'this'
|
|
112
|
+
const isValidLocal = (n) => {
|
|
113
|
+
try {
|
|
114
|
+
return t.isValidIdentifier(n) && n !== 'this';
|
|
115
|
+
}
|
|
116
|
+
catch {
|
|
117
|
+
return /^[A-Za-z_$][\w$]*$/.test(n) && n !== 'this';
|
|
118
|
+
}
|
|
119
|
+
};
|
|
120
|
+
const makeUniqueLocal = (base) => {
|
|
121
|
+
let name = base;
|
|
122
|
+
if (!isValidLocal(name)) {
|
|
123
|
+
name = `__ns_${name.replace(/[^A-Za-z0-9_$]+/g, '_') || 'id'}`;
|
|
124
|
+
}
|
|
125
|
+
let i = 1;
|
|
126
|
+
let cand = name;
|
|
127
|
+
while (declared.has(cand)) {
|
|
128
|
+
cand = `${name}_${i++}`;
|
|
129
|
+
}
|
|
130
|
+
declared.add(cand);
|
|
131
|
+
return cand;
|
|
132
|
+
};
|
|
133
|
+
if (isRt || isCore) {
|
|
134
|
+
let named = (path.node.specifiers || []).filter((s) => t.isImportSpecifier(s));
|
|
135
|
+
if (isRt && named.length) {
|
|
136
|
+
named = named.filter((s) => {
|
|
137
|
+
const imp = s.imported;
|
|
138
|
+
const name = (imp && (imp.name || String(imp)));
|
|
139
|
+
return name !== '$navigateTo' && name !== '$navigateBack';
|
|
140
|
+
});
|
|
141
|
+
}
|
|
142
|
+
const hasDefault = path.node.specifiers.some((s) => t.isImportDefaultSpecifier(s));
|
|
143
|
+
const hasNamespace = path.node.specifiers.some((s) => t.isImportNamespaceSpecifier(s));
|
|
144
|
+
if (isRt) {
|
|
145
|
+
// If we already have a default /ns/rt local chosen, rewrite this import to use it and remove the import
|
|
146
|
+
if (existingRtDefaultLocal) {
|
|
147
|
+
// If this import has a default with a different local, create an alias const newLocal = existingLocal;
|
|
148
|
+
const def = path.node.specifiers.find((s) => t.isImportDefaultSpecifier(s));
|
|
149
|
+
if (def) {
|
|
150
|
+
const newLocal = def.local.name;
|
|
151
|
+
if (newLocal !== existingRtDefaultLocal) {
|
|
152
|
+
const alias = t.variableDeclaration('const', [t.variableDeclarator(t.identifier(newLocal), t.identifier(existingRtDefaultLocal))]);
|
|
153
|
+
path.insertAfter(alias);
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
// If there are named specifiers, emit a destructure off existing default
|
|
157
|
+
if (named.length) {
|
|
158
|
+
const props = named.map((s) => {
|
|
159
|
+
const imp = s.imported;
|
|
160
|
+
const importedName = (imp && (imp.name || imp.value || String(imp)));
|
|
161
|
+
// Skip internal bridge sentinels that would collide with explicit core imports
|
|
162
|
+
if (importedName === 'ns_core_ns_1') {
|
|
163
|
+
return null;
|
|
164
|
+
}
|
|
165
|
+
// Also skip any accidental rt sentinel properties (e.g., 'ns_rt_ns_1')
|
|
166
|
+
if (/^ns_rt_ns_\d+$/.test(importedName)) {
|
|
167
|
+
return null;
|
|
168
|
+
}
|
|
169
|
+
const wantAlias = needAlias.has(importedName);
|
|
170
|
+
const localName = wantAlias ? `_${importedName}` : s.local.name;
|
|
171
|
+
existingRtLocals.add(localName);
|
|
172
|
+
// build safe property (string key if not valid identifier or is 'this')
|
|
173
|
+
const keyIsId = (() => {
|
|
174
|
+
try {
|
|
175
|
+
return t.isValidIdentifier(importedName) && importedName !== 'this';
|
|
176
|
+
}
|
|
177
|
+
catch {
|
|
178
|
+
return /^[A-Za-z_$][\w$]*$/.test(importedName) && importedName !== 'this';
|
|
179
|
+
}
|
|
180
|
+
})();
|
|
181
|
+
const key = keyIsId ? t.identifier(importedName) : t.stringLiteral(importedName);
|
|
182
|
+
const shorthand = keyIsId && localName === importedName;
|
|
183
|
+
return t.objectProperty(key, t.identifier(localName), false, shorthand);
|
|
184
|
+
});
|
|
185
|
+
const safeProps = props.filter(Boolean);
|
|
186
|
+
if (safeProps.length) {
|
|
187
|
+
const decl = t.variableDeclaration('const', [t.variableDeclarator(t.objectPattern(safeProps), t.identifier(existingRtDefaultLocal))]);
|
|
188
|
+
path.insertAfter(decl);
|
|
189
|
+
}
|
|
190
|
+
}
|
|
191
|
+
// Remove this import entirely (dedupe)
|
|
192
|
+
path.remove();
|
|
193
|
+
return;
|
|
194
|
+
}
|
|
195
|
+
// First time we see /ns/rt: capture default or synthesize one
|
|
196
|
+
if (!existingRtImport)
|
|
197
|
+
existingRtImport = path.node;
|
|
198
|
+
const def = path.node.specifiers.find((s) => t.isImportDefaultSpecifier(s));
|
|
199
|
+
if (def)
|
|
200
|
+
existingRtDefaultLocal = def.local.name;
|
|
201
|
+
if (!existingRtDefaultLocal) {
|
|
202
|
+
// No default present: add one
|
|
203
|
+
const tmp = uniqueRtLocal();
|
|
204
|
+
path.node.specifiers.unshift(t.importDefaultSpecifier(t.identifier(tmp)));
|
|
205
|
+
existingRtDefaultLocal = tmp;
|
|
206
|
+
}
|
|
207
|
+
// Convert any named specifiers to destructure and drop them from the import
|
|
208
|
+
if (named.length) {
|
|
209
|
+
const props = named.map((s) => {
|
|
210
|
+
const imp = s.imported;
|
|
211
|
+
const importedName = (imp && (imp.name || imp.value || String(imp)));
|
|
212
|
+
// Skip internal bridge sentinels that would collide with explicit core imports
|
|
213
|
+
if (importedName === 'ns_core_ns_1') {
|
|
214
|
+
return null;
|
|
215
|
+
}
|
|
216
|
+
// Also skip any accidental rt sentinel properties (e.g., 'ns_rt_ns_1')
|
|
217
|
+
if (/^ns_rt_ns_\d+$/.test(importedName)) {
|
|
218
|
+
return null;
|
|
219
|
+
}
|
|
220
|
+
const wantAlias = needAlias.has(importedName);
|
|
221
|
+
const localName = wantAlias ? `_${importedName}` : s.local.name;
|
|
222
|
+
existingRtLocals.add(localName);
|
|
223
|
+
const keyIsId = (() => {
|
|
224
|
+
try {
|
|
225
|
+
return t.isValidIdentifier(importedName) && importedName !== 'this';
|
|
226
|
+
}
|
|
227
|
+
catch {
|
|
228
|
+
return /^[A-Za-z_$][\w$]*$/.test(importedName) && importedName !== 'this';
|
|
229
|
+
}
|
|
230
|
+
})();
|
|
231
|
+
const key = keyIsId ? t.identifier(importedName) : t.stringLiteral(importedName);
|
|
232
|
+
const shorthand = keyIsId && localName === importedName;
|
|
233
|
+
return t.objectProperty(key, t.identifier(localName), false, shorthand);
|
|
234
|
+
});
|
|
235
|
+
const safeProps = props.filter(Boolean);
|
|
236
|
+
if (safeProps.length) {
|
|
237
|
+
const decl = t.variableDeclaration('const', [t.variableDeclarator(t.objectPattern(safeProps), t.identifier(existingRtDefaultLocal))]);
|
|
238
|
+
path.insertAfter(decl);
|
|
239
|
+
}
|
|
240
|
+
path.node.specifiers = path.node.specifiers.filter((s) => !t.isImportSpecifier(s));
|
|
241
|
+
}
|
|
242
|
+
// Collect any local names introduced by this import for declared set
|
|
243
|
+
for (const s of path.node.specifiers) {
|
|
244
|
+
if (s.local?.name)
|
|
245
|
+
declared.add(s.local.name);
|
|
246
|
+
}
|
|
247
|
+
return;
|
|
248
|
+
}
|
|
249
|
+
// Non-rt core path: handle like before
|
|
250
|
+
if (named.length) {
|
|
251
|
+
let tmpName = hasDefault && !hasNamespace ? path.node.specifiers.find((s) => t.isImportDefaultSpecifier(s)).local.name : makeUid(isCore ? 'core_ns' : 'ns');
|
|
252
|
+
if (!hasDefault || hasNamespace) {
|
|
253
|
+
path.node.specifiers = [t.importDefaultSpecifier(t.identifier(tmpName))];
|
|
254
|
+
}
|
|
255
|
+
const props = named.map((s) => {
|
|
256
|
+
const imp = s.imported;
|
|
257
|
+
const importedName = (imp && (imp.name || imp.value || String(imp)));
|
|
258
|
+
const keyIsId = (() => {
|
|
259
|
+
try {
|
|
260
|
+
return t.isValidIdentifier(importedName) && importedName !== 'this';
|
|
261
|
+
}
|
|
262
|
+
catch {
|
|
263
|
+
return /^[A-Za-z_$][\w$]*$/.test(importedName) && importedName !== 'this';
|
|
264
|
+
}
|
|
265
|
+
})();
|
|
266
|
+
const key = keyIsId ? t.identifier(importedName) : t.stringLiteral(importedName);
|
|
267
|
+
const shorthand = keyIsId && s.local.name === importedName;
|
|
268
|
+
return t.objectProperty(key, t.identifier(s.local.name), false, shorthand);
|
|
269
|
+
});
|
|
270
|
+
const decl = t.variableDeclaration('const', [t.variableDeclarator(t.objectPattern(props), t.identifier(tmpName))]);
|
|
271
|
+
path.insertAfter(decl);
|
|
272
|
+
path.node.specifiers = path.node.specifiers.filter((s) => !t.isImportSpecifier(s));
|
|
273
|
+
}
|
|
274
|
+
}
|
|
275
|
+
},
|
|
276
|
+
ImportExpression(path) {
|
|
277
|
+
const arg = path.node.source;
|
|
278
|
+
if (t.isStringLiteral(arg)) {
|
|
279
|
+
const src = arg.value;
|
|
280
|
+
if (isVueLike(src)) {
|
|
281
|
+
path.node.source = t.stringLiteral('/ns/rt');
|
|
282
|
+
}
|
|
283
|
+
else if (isNsCorePackage(src)) {
|
|
284
|
+
path.node.source = t.stringLiteral('/ns/core');
|
|
285
|
+
}
|
|
286
|
+
}
|
|
287
|
+
},
|
|
288
|
+
CallExpression(path) {
|
|
289
|
+
if (t.isImport(path.node.callee) || (t.isIdentifier(path.node.callee) && path.node.callee.name === 'import')) {
|
|
290
|
+
const first = path.node.arguments[0];
|
|
291
|
+
if (t.isStringLiteral(first)) {
|
|
292
|
+
if (isVueLike(first.value)) {
|
|
293
|
+
path.node.arguments[0] = t.stringLiteral('/ns/rt');
|
|
294
|
+
}
|
|
295
|
+
else if (isNsCorePackage(first.value)) {
|
|
296
|
+
path.node.arguments[0] = t.stringLiteral('/ns/core');
|
|
297
|
+
}
|
|
298
|
+
}
|
|
299
|
+
return;
|
|
300
|
+
}
|
|
301
|
+
if (t.isIdentifier(path.node.callee) && path.node.callee.name === 'require') {
|
|
302
|
+
const first = path.node.arguments[0];
|
|
303
|
+
if (t.isStringLiteral(first)) {
|
|
304
|
+
const v = first.value;
|
|
305
|
+
if (isVueLike(v)) {
|
|
306
|
+
path.node.arguments[0] = t.stringLiteral('/ns/rt');
|
|
307
|
+
}
|
|
308
|
+
else if (isNsCorePackage(v)) {
|
|
309
|
+
path.node.arguments[0] = t.stringLiteral('/ns/core');
|
|
310
|
+
}
|
|
311
|
+
}
|
|
312
|
+
}
|
|
313
|
+
},
|
|
314
|
+
VariableDeclarator(path) {
|
|
315
|
+
const id = path.node.id;
|
|
316
|
+
if (t.isIdentifier(id)) {
|
|
317
|
+
declared.add(id.name);
|
|
318
|
+
}
|
|
319
|
+
else if (t.isObjectPattern(id)) {
|
|
320
|
+
for (const prop of id.properties) {
|
|
321
|
+
if (t.isObjectProperty(prop)) {
|
|
322
|
+
const val = prop.value;
|
|
323
|
+
if (t.isIdentifier(val))
|
|
324
|
+
declared.add(val.name);
|
|
325
|
+
else if (t.isAssignmentPattern(val) && t.isIdentifier(val.left))
|
|
326
|
+
declared.add(val.left.name);
|
|
327
|
+
}
|
|
328
|
+
else if (t.isRestElement(prop)) {
|
|
329
|
+
const arg = prop.argument;
|
|
330
|
+
if (t.isIdentifier(arg))
|
|
331
|
+
declared.add(arg.name);
|
|
332
|
+
}
|
|
333
|
+
}
|
|
334
|
+
}
|
|
335
|
+
},
|
|
336
|
+
FunctionDeclaration(path) {
|
|
337
|
+
if (path.node.id?.name)
|
|
338
|
+
declared.add(path.node.id.name);
|
|
339
|
+
},
|
|
340
|
+
Identifier(path) {
|
|
341
|
+
const name = path.node.name;
|
|
342
|
+
if (!name || !name.startsWith('_'))
|
|
343
|
+
return;
|
|
344
|
+
if (/^__ns_(?:rt|core)_ns(?:\d+|_re)$/.test(name))
|
|
345
|
+
return;
|
|
346
|
+
if (path.scope.hasBinding(name))
|
|
347
|
+
return;
|
|
348
|
+
if (t.isObjectProperty(path.parent) && path.parent.key === path.node && !path.parent.computed)
|
|
349
|
+
return;
|
|
350
|
+
if (t.isMemberExpression(path.parent) && path.parent.property === path.node && !path.parent.computed)
|
|
351
|
+
return;
|
|
352
|
+
if (/^(ctx|cache)$/.test(name))
|
|
353
|
+
return;
|
|
354
|
+
if (/^(sfc_main|ns_sfc__|sfc)/.test(name))
|
|
355
|
+
return;
|
|
356
|
+
if (/^(hoisted_|component_|directive_)/.test(name))
|
|
357
|
+
return;
|
|
358
|
+
underscoreUses.add(name);
|
|
359
|
+
},
|
|
360
|
+
});
|
|
361
|
+
// Detect free uses of $navigateTo/$navigateBack (not declared at top-level)
|
|
362
|
+
try {
|
|
363
|
+
babelTraverse(ast, {
|
|
364
|
+
Identifier(path) {
|
|
365
|
+
const nm = path.node.name;
|
|
366
|
+
// detect defineStore and navigation helpers as free uses
|
|
367
|
+
if (nm !== '$navigateTo' && nm !== '$navigateBack' && nm !== '$showModal' && nm !== 'defineStore')
|
|
368
|
+
return;
|
|
369
|
+
// Ignore property keys like obj.$navigateTo or { $navigateTo: ... }
|
|
370
|
+
if (t.isObjectProperty(path.parent) && path.parent.key === path.node && !path.parent.computed)
|
|
371
|
+
return;
|
|
372
|
+
if (t.isMemberExpression(path.parent) && path.parent.property === path.node && !path.parent.computed)
|
|
373
|
+
return;
|
|
374
|
+
// If any scope provides a binding, treat it as declared (avoid shadowing locals)
|
|
375
|
+
if (path.scope.hasBinding(nm))
|
|
376
|
+
return;
|
|
377
|
+
if (nm === '$navigateTo')
|
|
378
|
+
navToUsed = true;
|
|
379
|
+
if (nm === '$navigateBack')
|
|
380
|
+
navBackUsed = true;
|
|
381
|
+
if (nm === '$showModal')
|
|
382
|
+
showModalUsed = true;
|
|
383
|
+
if (nm === 'defineStore')
|
|
384
|
+
defineStoreUsed = true;
|
|
385
|
+
},
|
|
386
|
+
});
|
|
387
|
+
}
|
|
388
|
+
catch { }
|
|
389
|
+
// Fallback: if traversal didn't detect underscored helper uses, do a conservative text scan
|
|
390
|
+
if (!underscoreUses.size) {
|
|
391
|
+
try {
|
|
392
|
+
const re = /(^|[^.\w$])_([A-Za-z]\w*)\b/g;
|
|
393
|
+
let m;
|
|
394
|
+
while ((m = re.exec(code))) {
|
|
395
|
+
const name = m[2];
|
|
396
|
+
// Never consider `_this` as a helper alias
|
|
397
|
+
if (name === 'this')
|
|
398
|
+
continue;
|
|
399
|
+
if (/(^|_)(ctx|cache)$/.test(name))
|
|
400
|
+
continue;
|
|
401
|
+
if (/^(hoisted_|component_|directive_|sfc_main|ns_sfc__|ns_sfc|sfc)/.test(name))
|
|
402
|
+
continue;
|
|
403
|
+
underscoreUses.add(name);
|
|
404
|
+
}
|
|
405
|
+
}
|
|
406
|
+
catch { }
|
|
407
|
+
}
|
|
408
|
+
if (underscoreUses.size) {
|
|
409
|
+
let defLocal = existingRtDefaultLocal;
|
|
410
|
+
if (!defLocal) {
|
|
411
|
+
defLocal = uniqueRtLocal();
|
|
412
|
+
if (existingRtImport) {
|
|
413
|
+
existingRtImport.specifiers.unshift(t.importDefaultSpecifier(t.identifier(defLocal)));
|
|
414
|
+
existingRtDefaultLocal = defLocal;
|
|
415
|
+
}
|
|
416
|
+
else {
|
|
417
|
+
const imp = t.importDeclaration([t.importDefaultSpecifier(t.identifier(defLocal))], t.stringLiteral('/ns/rt'));
|
|
418
|
+
ast.program.body.unshift(imp);
|
|
419
|
+
existingRtImport = imp;
|
|
420
|
+
existingRtDefaultLocal = defLocal;
|
|
421
|
+
}
|
|
422
|
+
}
|
|
423
|
+
const props = [];
|
|
424
|
+
for (const underscored of underscoreUses) {
|
|
425
|
+
// Never alias our own generated internals
|
|
426
|
+
if (/^__ns_(?:rt|core)_ns(?:\d+|_re)$/.test(underscored))
|
|
427
|
+
continue;
|
|
428
|
+
const base = underscored.replace(/^_+/, '');
|
|
429
|
+
// Do not attempt to destructure a property named 'this' from /ns/rt
|
|
430
|
+
if (base === 'this')
|
|
431
|
+
continue;
|
|
432
|
+
// Ensure local binding is a valid, non-reserved identifier
|
|
433
|
+
let localName = underscored;
|
|
434
|
+
if (!t.isIdentifier(t.identifier(localName)) || localName === 'this') {
|
|
435
|
+
localName = `__ns_${base || 'id'}`;
|
|
436
|
+
}
|
|
437
|
+
while (declared.has(localName)) {
|
|
438
|
+
localName = `${localName}_1`;
|
|
439
|
+
}
|
|
440
|
+
declared.add(localName);
|
|
441
|
+
existingRtLocals.add(localName);
|
|
442
|
+
// Safe key: use identifier if valid and not 'this', otherwise string literal
|
|
443
|
+
const keyIsId = (() => {
|
|
444
|
+
try {
|
|
445
|
+
return t.isValidIdentifier(base) && base !== 'this';
|
|
446
|
+
}
|
|
447
|
+
catch {
|
|
448
|
+
return /^[A-Za-z_$][\w$]*$/.test(base) && base !== 'this';
|
|
449
|
+
}
|
|
450
|
+
})();
|
|
451
|
+
const key = keyIsId ? t.identifier(base) : t.stringLiteral(base);
|
|
452
|
+
const shorthand = keyIsId && localName === base;
|
|
453
|
+
props.push(t.objectProperty(key, t.identifier(localName), false, shorthand));
|
|
454
|
+
}
|
|
455
|
+
if (props.length) {
|
|
456
|
+
const decl = t.variableDeclaration('const', [t.variableDeclarator(t.objectPattern(props), t.identifier(defLocal))]);
|
|
457
|
+
const body = ast.program.body;
|
|
458
|
+
const idx = existingRtImport ? body.indexOf(existingRtImport) : -1;
|
|
459
|
+
if (idx >= 0)
|
|
460
|
+
body.splice(idx + 1, 0, decl);
|
|
461
|
+
else
|
|
462
|
+
body.unshift(decl);
|
|
463
|
+
}
|
|
464
|
+
}
|
|
465
|
+
// Final clean-up: dedupe any remaining /ns/rt default imports
|
|
466
|
+
try {
|
|
467
|
+
const prog = ast.program;
|
|
468
|
+
const body = prog.body;
|
|
469
|
+
let keptDefaultLocal = null;
|
|
470
|
+
const newBody = [];
|
|
471
|
+
for (const node of body) {
|
|
472
|
+
if (t.isImportDeclaration(node) && isRtLike(node.source?.value)) {
|
|
473
|
+
const def = node.specifiers.find((s) => t.isImportDefaultSpecifier(s));
|
|
474
|
+
if (def) {
|
|
475
|
+
const local = def.local.name;
|
|
476
|
+
if (!keptDefaultLocal) {
|
|
477
|
+
keptDefaultLocal = local;
|
|
478
|
+
newBody.push(node);
|
|
479
|
+
continue;
|
|
480
|
+
}
|
|
481
|
+
if (local === keptDefaultLocal) {
|
|
482
|
+
// duplicate identical default import -> drop
|
|
483
|
+
continue;
|
|
484
|
+
}
|
|
485
|
+
// different local -> alias and drop import
|
|
486
|
+
newBody.push(t.variableDeclaration('const', [t.variableDeclarator(t.identifier(local), t.identifier(keptDefaultLocal))]));
|
|
487
|
+
continue;
|
|
488
|
+
}
|
|
489
|
+
// no default specifier -> drop (named-only imports should have been rewritten)
|
|
490
|
+
continue;
|
|
491
|
+
}
|
|
492
|
+
newBody.push(node);
|
|
493
|
+
}
|
|
494
|
+
prog.body = newBody;
|
|
495
|
+
}
|
|
496
|
+
catch { }
|
|
497
|
+
// Merge multiple destructures from the same /ns/rt namespace and strip navigation helpers from them
|
|
498
|
+
try {
|
|
499
|
+
const rtNames = new Set();
|
|
500
|
+
if (existingRtDefaultLocal)
|
|
501
|
+
rtNames.add(existingRtDefaultLocal);
|
|
502
|
+
// Also add any obvious temp namespace names we generate
|
|
503
|
+
rtNames.add('__ns_rt_ns_1');
|
|
504
|
+
rtNames.add('__ns_rt_ns_2'); // heuristic; real merges keyed by actual matches below
|
|
505
|
+
const collected = new Map();
|
|
506
|
+
const toRemove = [];
|
|
507
|
+
const body = ast.program.body;
|
|
508
|
+
const defaultLocal = existingRtDefaultLocal || '__ns_rt_ns_1';
|
|
509
|
+
for (const stmt of body) {
|
|
510
|
+
if (t.isVariableDeclaration(stmt)) {
|
|
511
|
+
const remaining = [];
|
|
512
|
+
for (const d of stmt.declarations) {
|
|
513
|
+
if (t.isObjectPattern(d.id) && t.isIdentifier(d.init)) {
|
|
514
|
+
const initName = d.init.name;
|
|
515
|
+
if (rtNames.has(initName) || /^__ns_rt_ns(?:\d+|_re)$/.test(initName)) {
|
|
516
|
+
for (const p of d.id.properties) {
|
|
517
|
+
if (t.isObjectProperty(p)) {
|
|
518
|
+
const key = p.key.name || String(p.key);
|
|
519
|
+
if (key === '$navigateTo' || key === '$navigateBack')
|
|
520
|
+
continue;
|
|
521
|
+
// Skip internal core bridge sentinel(s) to avoid duplicate locals like __ns_core_ns_1/__ns_core_ns_2
|
|
522
|
+
if (/^ns_core_ns_\d+$/.test(key))
|
|
523
|
+
continue;
|
|
524
|
+
// Skip any accidental runtime sentinel property mappings (e.g., ns_rt_ns_1)
|
|
525
|
+
if (/^ns_rt_ns_\d+$/.test(key))
|
|
526
|
+
continue;
|
|
527
|
+
const localId = p.value.name || String(p.value);
|
|
528
|
+
// Never collect bindings that shadow the default import local
|
|
529
|
+
if (localId === defaultLocal || key === defaultLocal)
|
|
530
|
+
continue;
|
|
531
|
+
if (/^__ns_rt_ns(?:\d+|_re)$/.test(localId) || /^__ns_rt_ns(?:\d+|_re)$/.test(key))
|
|
532
|
+
continue;
|
|
533
|
+
// Also skip any locals that look like core bridge internals to prevent shadowing
|
|
534
|
+
if (/^__ns_core_ns(?:\d+|_re)$/.test(localId) || /^__ns_core_ns(?:\d+|_re)$/.test(key))
|
|
535
|
+
continue;
|
|
536
|
+
if (!collected.has(localId)) {
|
|
537
|
+
collected.set(localId, t.objectProperty(t.identifier(key), t.identifier(localId)));
|
|
538
|
+
}
|
|
539
|
+
}
|
|
540
|
+
}
|
|
541
|
+
continue; // drop this declarator
|
|
542
|
+
}
|
|
543
|
+
}
|
|
544
|
+
remaining.push(d);
|
|
545
|
+
}
|
|
546
|
+
stmt.declarations = remaining;
|
|
547
|
+
if (remaining.length === 0)
|
|
548
|
+
toRemove.push(stmt);
|
|
549
|
+
}
|
|
550
|
+
}
|
|
551
|
+
if (toRemove.length) {
|
|
552
|
+
ast.program.body = body.filter((n) => !toRemove.includes(n));
|
|
553
|
+
}
|
|
554
|
+
if (collected.size) {
|
|
555
|
+
const props = Array.from(collected.values());
|
|
556
|
+
const defLocal = existingRtDefaultLocal || '__ns_rt_ns_1';
|
|
557
|
+
const merged = t.variableDeclaration('const', [t.variableDeclarator(t.objectPattern(props), t.identifier(defLocal))]);
|
|
558
|
+
const prog = ast.program;
|
|
559
|
+
const body2 = prog.body;
|
|
560
|
+
const idx = existingRtImport ? body2.indexOf(existingRtImport) : -1;
|
|
561
|
+
if (idx >= 0)
|
|
562
|
+
body2.splice(idx + 1, 0, merged);
|
|
563
|
+
else
|
|
564
|
+
body2.unshift(merged);
|
|
565
|
+
}
|
|
566
|
+
}
|
|
567
|
+
catch { }
|
|
568
|
+
// Targeted cleanup: remove any ns_core_ns_<n> property from destructures of /ns/rt default locals.
|
|
569
|
+
// This prevents creating locals like __ns_core_ns_1/__ns_core_ns_2 that could collide with an explicit core default import.
|
|
570
|
+
try {
|
|
571
|
+
babelTraverse(ast, {
|
|
572
|
+
VariableDeclarator(path) {
|
|
573
|
+
const id = path.node.id;
|
|
574
|
+
const init = path.node.init;
|
|
575
|
+
if (!t.isObjectPattern(id) || !t.isIdentifier(init))
|
|
576
|
+
return;
|
|
577
|
+
const initName = init.name;
|
|
578
|
+
if (!(initName && (/^__ns_rt_ns(?:\d+|_re)$/.test(initName) || initName === existingRtDefaultLocal)))
|
|
579
|
+
return;
|
|
580
|
+
const props = id.properties.filter((p) => !(t.isObjectProperty(p) && /^ns_core_ns_\d+$/.test((p.key.name || String(p.key)))));
|
|
581
|
+
if (props.length === 0) {
|
|
582
|
+
path.remove();
|
|
583
|
+
}
|
|
584
|
+
else if (props.length !== id.properties.length) {
|
|
585
|
+
path.node.id = t.objectPattern(props);
|
|
586
|
+
}
|
|
587
|
+
},
|
|
588
|
+
});
|
|
589
|
+
}
|
|
590
|
+
catch { }
|
|
591
|
+
// Inject navigation wrappers and defineStore destructure if referenced but not declared at top level
|
|
592
|
+
try {
|
|
593
|
+
const needTo = navToUsed && !declared.has('$navigateTo');
|
|
594
|
+
const needBack = navBackUsed && !declared.has('$navigateBack');
|
|
595
|
+
const needShow = showModalUsed && !declared.has('$showModal');
|
|
596
|
+
const needDefineStore = defineStoreUsed && !declared.has('defineStore');
|
|
597
|
+
if (needTo || needBack || needShow || needDefineStore) {
|
|
598
|
+
// Ensure a default /ns/rt local exists to source wrappers from
|
|
599
|
+
if (!existingRtDefaultLocal) {
|
|
600
|
+
const tmp = uniqueRtLocal();
|
|
601
|
+
const imp = t.importDeclaration([t.importDefaultSpecifier(t.identifier(tmp))], t.stringLiteral('/ns/rt'));
|
|
602
|
+
ast.program.body.unshift(imp);
|
|
603
|
+
existingRtDefaultLocal = tmp;
|
|
604
|
+
existingRtImport = imp;
|
|
605
|
+
}
|
|
606
|
+
const rtId = t.identifier(existingRtDefaultLocal);
|
|
607
|
+
const decls = [];
|
|
608
|
+
if (needTo) {
|
|
609
|
+
const param = t.restElement(t.identifier('args'));
|
|
610
|
+
const call = t.callExpression(t.memberExpression(rtId, t.identifier('$navigateTo')), [t.spreadElement(t.identifier('args'))]);
|
|
611
|
+
const arrow = t.arrowFunctionExpression([param], call);
|
|
612
|
+
decls.push(t.variableDeclaration('const', [t.variableDeclarator(t.identifier('$navigateTo'), arrow)]));
|
|
613
|
+
}
|
|
614
|
+
if (needBack) {
|
|
615
|
+
const param = t.restElement(t.identifier('args'));
|
|
616
|
+
const call = t.callExpression(t.memberExpression(rtId, t.identifier('$navigateBack')), [t.spreadElement(t.identifier('args'))]);
|
|
617
|
+
const arrow = t.arrowFunctionExpression([param], call);
|
|
618
|
+
decls.push(t.variableDeclaration('const', [t.variableDeclarator(t.identifier('$navigateBack'), arrow)]));
|
|
619
|
+
}
|
|
620
|
+
if (needDefineStore) {
|
|
621
|
+
// const { defineStore } = __ns_rt_ns_X;
|
|
622
|
+
const prop = t.objectProperty(t.identifier('defineStore'), t.identifier('defineStore'), false, true);
|
|
623
|
+
decls.push(t.variableDeclaration('const', [t.variableDeclarator(t.objectPattern([prop]), rtId)]));
|
|
624
|
+
declared.add('defineStore');
|
|
625
|
+
}
|
|
626
|
+
if (needShow) {
|
|
627
|
+
// const { $showModal } = __ns_rt_ns_X;
|
|
628
|
+
const prop = t.objectProperty(t.identifier('$showModal'), t.identifier('$showModal'), false, true);
|
|
629
|
+
decls.push(t.variableDeclaration('const', [t.variableDeclarator(t.objectPattern([prop]), rtId)]));
|
|
630
|
+
declared.add('$showModal');
|
|
631
|
+
}
|
|
632
|
+
// Insert wrappers immediately after the rt import if present, else at top
|
|
633
|
+
const bodyArr = ast.program.body;
|
|
634
|
+
const idx = existingRtImport ? bodyArr.indexOf(existingRtImport) : -1;
|
|
635
|
+
if (idx >= 0) {
|
|
636
|
+
bodyArr.splice(idx + 1, 0, ...decls);
|
|
637
|
+
}
|
|
638
|
+
else {
|
|
639
|
+
ast.program.body = [...decls, ...bodyArr];
|
|
640
|
+
}
|
|
641
|
+
}
|
|
642
|
+
}
|
|
643
|
+
catch { }
|
|
644
|
+
let { code: out } = genCode(ast, { retainLines: true, compact: false });
|
|
645
|
+
// Textual safety net: drop duplicate identical default imports from /ns/rt
|
|
646
|
+
try {
|
|
647
|
+
const seen = new Set();
|
|
648
|
+
out = out.replace(/\bimport\s+(\w+)\s+from\s+["']\/ns\/rt["'];?/g, (match, local) => {
|
|
649
|
+
if (seen.has(local)) {
|
|
650
|
+
return '';
|
|
651
|
+
}
|
|
652
|
+
seen.add(local);
|
|
653
|
+
return match;
|
|
654
|
+
});
|
|
655
|
+
}
|
|
656
|
+
catch { }
|
|
657
|
+
// Textual safety net: remove ns_core_ns_<n> and ns_rt_ns_* destructures off __ns_rt_ns_* (and off the actual /ns/rt local) to avoid local collisions or bogus aliasing
|
|
658
|
+
try {
|
|
659
|
+
// If we can detect the actual default local imported from /ns/rt, also heal destructures off that identifier
|
|
660
|
+
try {
|
|
661
|
+
const m = out.match(/import\s+([A-Za-z_$][\w$]*)\s+from\s+["']\/ns\/rt["']/);
|
|
662
|
+
const rtLocal = m ? m[1] : null;
|
|
663
|
+
if (rtLocal) {
|
|
664
|
+
// Remove any ns_core_ns_<n> mapping inside destructures off that local (standalone and multi-prop positions)
|
|
665
|
+
const rtId = rtLocal.replace(/[$]/g, '\\$&');
|
|
666
|
+
const reStandalone = new RegExp(`(^|\\n)\\s*const\\s*\\{[^}]*ns_core_ns_\\d+\\s*:\\s*__ns_core_ns_(?:\\d+|re)[^}]*\\}\\s*=\\s*${rtId}\\s*;\\s*`, 'g');
|
|
667
|
+
out = out.replace(reStandalone, '$1');
|
|
668
|
+
const reLead = new RegExp(`(\\{\\s*)ns_core_ns_\\d+\\s*:\\s*__ns_core_ns_(?:\\d+|re)\\s*,\\s*([^}]*\\}\\s*=\\s*${rtId}\\s*;)`, 'g');
|
|
669
|
+
out = out.replace(reLead, '{$2');
|
|
670
|
+
const reTrail = new RegExp(`(\\{[^}]*?,)\\s*ns_core_ns_\\d+\\s*:\\s*__ns_core_ns_(?:\\d+|re)\\s*(\\}\\s*=\\s*${rtId}\\s*;)`, 'g');
|
|
671
|
+
out = out.replace(reTrail, '$1$2');
|
|
672
|
+
const reMid = new RegExp(`(\\{[^}]*?,)\\s*ns_core_ns_\\d+\\s*:\\s*__ns_core_ns_(?:\\d+|re)\\s*,\\s*([^}]*\\}\\s*=\\s*${rtId}\\s*;)`, 'g');
|
|
673
|
+
out = out.replace(reMid, '$1$2');
|
|
674
|
+
}
|
|
675
|
+
}
|
|
676
|
+
catch { }
|
|
677
|
+
// Remove the standalone form: const { ns_core_ns_<n>: __ns_core_ns_<n> } = __ns_rt_ns_X;
|
|
678
|
+
out = out.replace(/(^|\n)\s*const\s*\{[^}]*ns_core_ns_\d+\s*:\s*__ns_core_ns_(?:\d+|re)[^}]*\}\s*=\s*__ns_rt_ns(?:\d+|_re)\s*;\s*/g, '$1');
|
|
679
|
+
// Remove leading property in a multi-prop destructure
|
|
680
|
+
out = out.replace(/(\{\s*)ns_core_ns_\d+\s*:\s*__ns_core_ns_(?:\d+|re)\s*,\s*([^}]*\}\s*=\s*__ns_rt_ns(?:\d+|_re)\s*;)/g, '{$2');
|
|
681
|
+
// Remove trailing property in a multi-prop destructure
|
|
682
|
+
out = out.replace(/(\{[^}]*?,)\s*ns_core_ns_\d+\s*:\s*__ns_core_ns_(?:\d+|re)\s*(\}\s*=\s*__ns_rt_ns(?:\d+|_re)\s*;)/g, '$1$2');
|
|
683
|
+
// Remove middle property in a multi-prop destructure
|
|
684
|
+
out = out.replace(/(\{[^}]*?,)\s*ns_core_ns_\d+\s*:\s*__ns_core_ns_(?:\d+|re)\s*,\s*([^}]*\}\s*=\s*__ns_rt_ns(?:\d+|_re)\s*;)/g, '$1$2');
|
|
685
|
+
// Ultra-conservative fallback: strip any 'ns_core_ns_<n>: __ns_core_ns_<m>' occurrences
|
|
686
|
+
out = out.replace(/ns_core_ns_\d+\s*:\s*__ns_core_ns_(?:\d+|re)\s*,?\s*/g, () => '');
|
|
687
|
+
// Also strip any accidental 'ns_rt_ns_<n>: __ns_rt_ns_<m>' property mappings
|
|
688
|
+
out = out.replace(/(^|\n)\s*const\s*\{[^}]*ns_rt_ns_\d+\s*:\s*__ns_rt_ns_(?:\d+|re)[^}]*\}\s*=\s*__ns_rt_ns(?:\d+|_re)\s*;\s*/g, '$1');
|
|
689
|
+
out = out.replace(/(\{\s*)ns_rt_ns_\d+\s*:\s*__ns_rt_ns_(?:\d+|re)\s*,\s*([^}]*\}\s*=\s*__ns_rt_ns(?:\d+|_re)\s*;)/g, '{$2');
|
|
690
|
+
out = out.replace(/(\{[^}]*?,)\s*ns_rt_ns_\d+\s*:\s*__ns_rt_ns_(?:\d+|re)\s*(\}\s*=\s*__ns_rt_ns(?:\d+|_re)\s*;)/g, '$1$2');
|
|
691
|
+
out = out.replace(/(\{[^}]*?,)\s*ns_rt_ns_\d+\s*:\s*__ns_rt_ns_(?:\d+|re)\s*,\s*([^}]*\}\s*=\s*__ns_rt_ns(?:\d+|_re)\s*;)/g, '$1$2');
|
|
692
|
+
// Remove empty destructures that may result: const { } = __ns_rt_nsX;
|
|
693
|
+
out = out.replace(/(^|\n)\s*const\s*\{\s*\}\s*=\s*__ns_rt_ns(?:\d+|_re)\s*;\s*/g, '$1');
|
|
694
|
+
}
|
|
695
|
+
catch { }
|
|
696
|
+
return `/* [ast-normalized] */\n${out}`;
|
|
697
|
+
}
|
|
698
|
+
catch {
|
|
699
|
+
// Fallback: attempt minimal textual dedupe of /ns/rt default imports
|
|
700
|
+
try {
|
|
701
|
+
const seen = new Set();
|
|
702
|
+
const deduped = code.replace(/\bimport\s+(\w+)\s+from\s+["']\/ns\/rt["'];?/g, (match, local) => {
|
|
703
|
+
if (seen.has(local))
|
|
704
|
+
return '';
|
|
705
|
+
seen.add(local);
|
|
706
|
+
return match;
|
|
707
|
+
});
|
|
708
|
+
return deduped;
|
|
709
|
+
}
|
|
710
|
+
catch {
|
|
711
|
+
return code;
|
|
712
|
+
}
|
|
713
|
+
}
|
|
714
|
+
}
|
|
715
|
+
// Verification: duplicate top-level bindings annotated for fast diagnostics
|
|
716
|
+
export function astVerifyAndAnnotateDuplicates(code) {
|
|
717
|
+
try {
|
|
718
|
+
const ast = babelParse(code, {
|
|
719
|
+
sourceType: 'module',
|
|
720
|
+
plugins: ['typescript', 'jsx'],
|
|
721
|
+
errorRecovery: true,
|
|
722
|
+
});
|
|
723
|
+
const seen = new Map();
|
|
724
|
+
ast.program.body.forEach((node) => {
|
|
725
|
+
// Count variable declarations (const/let) including object pattern bindings
|
|
726
|
+
if (node?.type === 'VariableDeclaration' && (node.kind === 'const' || node.kind === 'let')) {
|
|
727
|
+
for (const d of node.declarations || []) {
|
|
728
|
+
const id = d?.id;
|
|
729
|
+
if (id?.type === 'Identifier') {
|
|
730
|
+
const name = id.name;
|
|
731
|
+
seen.set(name, (seen.get(name) || 0) + 1);
|
|
732
|
+
}
|
|
733
|
+
else if (id?.type === 'ObjectPattern') {
|
|
734
|
+
for (const p of id.properties || []) {
|
|
735
|
+
if (p?.type === 'ObjectProperty') {
|
|
736
|
+
const v = p.value;
|
|
737
|
+
if (v?.type === 'Identifier') {
|
|
738
|
+
const name = v.name;
|
|
739
|
+
seen.set(name, (seen.get(name) || 0) + 1);
|
|
740
|
+
}
|
|
741
|
+
}
|
|
742
|
+
}
|
|
743
|
+
}
|
|
744
|
+
}
|
|
745
|
+
}
|
|
746
|
+
// Count import specifier bindings (default, namespace, named), excluding type-only imports
|
|
747
|
+
if (node?.type === 'ImportDeclaration' && node.importKind !== 'type') {
|
|
748
|
+
for (const s of node.specifiers || []) {
|
|
749
|
+
if (s.type === 'ImportDefaultSpecifier' || s.type === 'ImportNamespaceSpecifier' || s.type === 'ImportSpecifier') {
|
|
750
|
+
const local = (s.local && s.local.name) || null;
|
|
751
|
+
if (local)
|
|
752
|
+
seen.set(local, (seen.get(local) || 0) + 1);
|
|
753
|
+
}
|
|
754
|
+
}
|
|
755
|
+
}
|
|
756
|
+
});
|
|
757
|
+
const dups = Array.from(seen.entries()).filter(([_, c]) => c > 1);
|
|
758
|
+
if (dups.length) {
|
|
759
|
+
const note = dups.map(([n, c]) => `${n} x${c}`).join(', ');
|
|
760
|
+
return `// [ast-verify][duplicate-bindings] ${note}\n` + code;
|
|
761
|
+
}
|
|
762
|
+
return code;
|
|
763
|
+
}
|
|
764
|
+
catch {
|
|
765
|
+
return code;
|
|
766
|
+
}
|
|
767
|
+
}
|
|
768
|
+
export default {
|
|
769
|
+
astNormalizeModuleImportsAndHelpers,
|
|
770
|
+
astVerifyAndAnnotateDuplicates,
|
|
771
|
+
};
|
|
772
|
+
//# sourceMappingURL=ast-normalizer.js.map
|