@immense/vue-pom-generator 1.0.56 → 1.0.57
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/RELEASE_NOTES.md +15 -12
- package/dist/index.cjs +153 -90
- package/dist/index.cjs.map +1 -1
- package/dist/index.mjs +153 -90
- package/dist/index.mjs.map +1 -1
- package/dist/router-introspection.d.ts.map +1 -1
- package/package.json +1 -1
package/RELEASE_NOTES.md
CHANGED
|
@@ -1,27 +1,30 @@
|
|
|
1
1
|
● ## Highlights
|
|
2
2
|
|
|
3
|
-
-
|
|
4
|
-
-
|
|
5
|
-
-
|
|
3
|
+
- Fixed router introspection cleanup to properly restore DOM globals after execution
|
|
4
|
+
- Improved test coverage for router introspection with 83 new test lines
|
|
5
|
+
- Refactored router-introspection implementation for better DOM shim management
|
|
6
6
|
|
|
7
7
|
## Changes
|
|
8
8
|
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
9
|
+
### Bug Fixes
|
|
10
|
+
- **Router introspection**: Restored router DOM globals after introspection to prevent state
|
|
11
|
+
pollution between test runs and avoid interfering with downstream code that depends on these
|
|
12
|
+
globals
|
|
13
|
+
|
|
14
|
+
### Testing
|
|
15
|
+
- Added comprehensive test coverage for router DOM global restoration behavior
|
|
13
16
|
|
|
14
17
|
## Breaking Changes
|
|
15
18
|
|
|
16
|
-
None
|
|
19
|
+
None
|
|
17
20
|
|
|
18
21
|
## Pull Requests Included
|
|
19
22
|
|
|
20
|
-
- #
|
|
21
|
-
(https://github.com/immense/vue-pom-generator/pull/
|
|
23
|
+
- #18 fix: restore router DOM globals after introspection
|
|
24
|
+
(https://github.com/immense/vue-pom-generator/pull/18)
|
|
22
25
|
|
|
23
26
|
## Testing
|
|
24
27
|
|
|
25
|
-
Added
|
|
26
|
-
|
|
28
|
+
Added 83 lines of test coverage for router introspection DOM global handling. All existing tests
|
|
29
|
+
continue to pass.
|
|
27
30
|
|
package/dist/index.cjs
CHANGED
|
@@ -3157,6 +3157,56 @@ function createRouterIntrospectionVueStubPlugin(options) {
|
|
|
3157
3157
|
}
|
|
3158
3158
|
};
|
|
3159
3159
|
}
|
|
3160
|
+
function snapshotGlobalValue(name) {
|
|
3161
|
+
const g = globalThis;
|
|
3162
|
+
return {
|
|
3163
|
+
descriptor: Object.getOwnPropertyDescriptor(globalThis, name),
|
|
3164
|
+
value: g[name]
|
|
3165
|
+
};
|
|
3166
|
+
}
|
|
3167
|
+
function setTemporaryGlobal(name, value, snapshots) {
|
|
3168
|
+
if (!snapshots.has(name))
|
|
3169
|
+
snapshots.set(name, snapshotGlobalValue(name));
|
|
3170
|
+
const snapshot = snapshots.get(name);
|
|
3171
|
+
if (!snapshot)
|
|
3172
|
+
return false;
|
|
3173
|
+
if (!snapshot.descriptor || snapshot.descriptor.configurable) {
|
|
3174
|
+
Object.defineProperty(globalThis, name, {
|
|
3175
|
+
configurable: true,
|
|
3176
|
+
enumerable: snapshot.descriptor?.enumerable ?? true,
|
|
3177
|
+
writable: true,
|
|
3178
|
+
value
|
|
3179
|
+
});
|
|
3180
|
+
return true;
|
|
3181
|
+
}
|
|
3182
|
+
if ("writable" in snapshot.descriptor && snapshot.descriptor.writable) {
|
|
3183
|
+
Reflect.set(globalThis, name, value);
|
|
3184
|
+
return true;
|
|
3185
|
+
}
|
|
3186
|
+
if (snapshot.descriptor.set) {
|
|
3187
|
+
snapshot.descriptor.set.call(globalThis, value);
|
|
3188
|
+
return true;
|
|
3189
|
+
}
|
|
3190
|
+
return false;
|
|
3191
|
+
}
|
|
3192
|
+
function restoreTemporaryGlobals(snapshots) {
|
|
3193
|
+
for (const [name, snapshot] of Array.from(snapshots.entries()).reverse()) {
|
|
3194
|
+
const { descriptor, value } = snapshot;
|
|
3195
|
+
if (!descriptor) {
|
|
3196
|
+
Reflect.deleteProperty(globalThis, name);
|
|
3197
|
+
continue;
|
|
3198
|
+
}
|
|
3199
|
+
if (descriptor.configurable) {
|
|
3200
|
+
Object.defineProperty(globalThis, name, descriptor);
|
|
3201
|
+
continue;
|
|
3202
|
+
}
|
|
3203
|
+
if ("writable" in descriptor && descriptor.writable) {
|
|
3204
|
+
Reflect.set(globalThis, name, value);
|
|
3205
|
+
continue;
|
|
3206
|
+
}
|
|
3207
|
+
descriptor.set?.call(globalThis, value);
|
|
3208
|
+
}
|
|
3209
|
+
}
|
|
3160
3210
|
const PARAM_TOKEN_PREFIX = "__VUE_TESTID_PARAM__";
|
|
3161
3211
|
function getParamToken(name) {
|
|
3162
3212
|
return `${PARAM_TOKEN_PREFIX}${name}__`;
|
|
@@ -3505,12 +3555,18 @@ function createMinimalLocation() {
|
|
|
3505
3555
|
ancestorOrigins: { length: 0, contains: () => false, item: () => null, [Symbol.iterator]: [][Symbol.iterator] }
|
|
3506
3556
|
};
|
|
3507
3557
|
}
|
|
3508
|
-
|
|
3558
|
+
function ensureDomShim() {
|
|
3509
3559
|
const g = globalThis;
|
|
3510
3560
|
if (typeof document !== "undefined" && typeof window !== "undefined")
|
|
3511
|
-
return
|
|
3561
|
+
return () => {
|
|
3562
|
+
};
|
|
3512
3563
|
const minimalDoc = createMinimalDocument();
|
|
3513
3564
|
const minimalLocation = createMinimalLocation();
|
|
3565
|
+
const snapshots = /* @__PURE__ */ new Map();
|
|
3566
|
+
const setGlobal = (name, value) => {
|
|
3567
|
+
if (!setTemporaryGlobal(name, value, snapshots))
|
|
3568
|
+
debugLog(`could not temporarily install global ${name}`);
|
|
3569
|
+
};
|
|
3514
3570
|
const win = {
|
|
3515
3571
|
document: minimalDoc,
|
|
3516
3572
|
location: minimalLocation,
|
|
@@ -3555,17 +3611,17 @@ async function ensureDomShim() {
|
|
|
3555
3611
|
queueMicrotask,
|
|
3556
3612
|
performance: globalThis.performance
|
|
3557
3613
|
};
|
|
3558
|
-
|
|
3559
|
-
|
|
3560
|
-
|
|
3614
|
+
setGlobal("window", win);
|
|
3615
|
+
setGlobal("document", minimalDoc);
|
|
3616
|
+
setGlobal("location", minimalLocation);
|
|
3561
3617
|
if (!g.self)
|
|
3562
|
-
|
|
3618
|
+
setGlobal("self", win);
|
|
3563
3619
|
if (!g.navigator)
|
|
3564
|
-
|
|
3620
|
+
setGlobal("navigator", win.navigator);
|
|
3565
3621
|
if (!g.history)
|
|
3566
|
-
|
|
3622
|
+
setGlobal("history", win.history);
|
|
3567
3623
|
if (!g.MutationObserver) {
|
|
3568
|
-
|
|
3624
|
+
setGlobal("MutationObserver", class {
|
|
3569
3625
|
disconnect() {
|
|
3570
3626
|
}
|
|
3571
3627
|
observe() {
|
|
@@ -3573,20 +3629,20 @@ async function ensureDomShim() {
|
|
|
3573
3629
|
takeRecords() {
|
|
3574
3630
|
return [];
|
|
3575
3631
|
}
|
|
3576
|
-
};
|
|
3632
|
+
});
|
|
3577
3633
|
}
|
|
3578
3634
|
if (!g.ResizeObserver) {
|
|
3579
|
-
|
|
3635
|
+
setGlobal("ResizeObserver", class {
|
|
3580
3636
|
disconnect() {
|
|
3581
3637
|
}
|
|
3582
3638
|
observe() {
|
|
3583
3639
|
}
|
|
3584
3640
|
unobserve() {
|
|
3585
3641
|
}
|
|
3586
|
-
};
|
|
3642
|
+
});
|
|
3587
3643
|
}
|
|
3588
3644
|
if (!g.IntersectionObserver) {
|
|
3589
|
-
|
|
3645
|
+
setGlobal("IntersectionObserver", class {
|
|
3590
3646
|
disconnect() {
|
|
3591
3647
|
}
|
|
3592
3648
|
observe() {
|
|
@@ -3596,10 +3652,10 @@ async function ensureDomShim() {
|
|
|
3596
3652
|
takeRecords() {
|
|
3597
3653
|
return [];
|
|
3598
3654
|
}
|
|
3599
|
-
};
|
|
3655
|
+
});
|
|
3600
3656
|
}
|
|
3601
3657
|
if (!g.requestIdleCallback) {
|
|
3602
|
-
|
|
3658
|
+
setGlobal("requestIdleCallback", (cb) => setTimeout(() => cb({ didTimeout: false, timeRemaining: () => 0 }), 1));
|
|
3603
3659
|
}
|
|
3604
3660
|
if (!g.localStorage || !g.sessionStorage) {
|
|
3605
3661
|
const storageFactory = () => {
|
|
@@ -3622,12 +3678,15 @@ async function ensureDomShim() {
|
|
|
3622
3678
|
};
|
|
3623
3679
|
};
|
|
3624
3680
|
if (!g.localStorage)
|
|
3625
|
-
|
|
3681
|
+
setGlobal("localStorage", storageFactory());
|
|
3626
3682
|
if (!g.sessionStorage)
|
|
3627
|
-
|
|
3683
|
+
setGlobal("sessionStorage", storageFactory());
|
|
3628
3684
|
}
|
|
3629
3685
|
if (!g.requestAnimationFrame)
|
|
3630
|
-
|
|
3686
|
+
setGlobal("requestAnimationFrame", (cb) => setTimeout(() => cb(Date.now()), 16));
|
|
3687
|
+
return () => {
|
|
3688
|
+
restoreTemporaryGlobals(snapshots);
|
|
3689
|
+
};
|
|
3631
3690
|
}
|
|
3632
3691
|
function unwrapNuxtPageSegment(segment, prefix, suffix) {
|
|
3633
3692
|
if (!segment.startsWith(prefix) || !segment.endsWith(suffix))
|
|
@@ -3745,85 +3804,89 @@ async function parseRouterFileFromCwd(routerEntryPath, options = {}) {
|
|
|
3745
3804
|
}
|
|
3746
3805
|
const cwd = path.dirname(routerEntry);
|
|
3747
3806
|
const moduleShims = normalizeRouterIntrospectionModuleShims(options.moduleShims);
|
|
3748
|
-
|
|
3749
|
-
debugLog(`parseRouterFileFromCwd cwd=${cwd}`);
|
|
3750
|
-
const vite = await import("vite");
|
|
3751
|
-
const server = await vite.createServer({
|
|
3752
|
-
root: cwd,
|
|
3753
|
-
configFile: false,
|
|
3754
|
-
logLevel: "error",
|
|
3755
|
-
// This server is created only to SSR-load the router module. Disable HMR/WebSocket
|
|
3756
|
-
// to avoid port conflicts in dev/test environments.
|
|
3757
|
-
server: { middlewareMode: true, hmr: false, ws: false },
|
|
3758
|
-
appType: "custom",
|
|
3759
|
-
// IMPORTANT:
|
|
3760
|
-
// This internal, short-lived Vite server exists only to `ssrLoadModule()` the router entry.
|
|
3761
|
-
// We close it immediately after reading routes.
|
|
3762
|
-
//
|
|
3763
|
-
// Vite's dependency optimizer (vite:dep-scan / optimizeDeps) runs asynchronously and can
|
|
3764
|
-
// still have pending resolve requests when we call `server.close()`, which surfaces as:
|
|
3765
|
-
// "The server is being restarted or closed. Request is outdated [plugin vite:dep-scan]"
|
|
3766
|
-
//
|
|
3767
|
-
// Disable optimizeDeps entirely for this internal server to avoid that race.
|
|
3768
|
-
optimizeDeps: {
|
|
3769
|
-
disabled: true
|
|
3770
|
-
},
|
|
3771
|
-
resolve: {
|
|
3772
|
-
alias: {
|
|
3773
|
-
"@": cwd
|
|
3774
|
-
}
|
|
3775
|
-
},
|
|
3776
|
-
// Important: Do NOT include @vitejs/plugin-vue here.
|
|
3777
|
-
// We stub all `.vue` imports ourselves, and including the Vue plugin would attempt to parse
|
|
3778
|
-
// those stubbed modules as real SFCs (and fail).
|
|
3779
|
-
plugins: [createRouterIntrospectionVueStubPlugin({ routerEntryAbs: routerEntry, moduleShims })]
|
|
3780
|
-
});
|
|
3807
|
+
const restoreDomShim = ensureDomShim();
|
|
3781
3808
|
try {
|
|
3782
|
-
|
|
3783
|
-
|
|
3784
|
-
const
|
|
3785
|
-
|
|
3786
|
-
|
|
3787
|
-
|
|
3788
|
-
|
|
3789
|
-
|
|
3790
|
-
|
|
3809
|
+
debugLog(`parseRouterFileFromCwd cwd=${cwd}`);
|
|
3810
|
+
const vite = await import("vite");
|
|
3811
|
+
const server = await vite.createServer({
|
|
3812
|
+
root: cwd,
|
|
3813
|
+
configFile: false,
|
|
3814
|
+
logLevel: "error",
|
|
3815
|
+
// This server is created only to SSR-load the router module. Disable HMR/WebSocket
|
|
3816
|
+
// to avoid port conflicts in dev/test environments.
|
|
3817
|
+
server: { middlewareMode: true, hmr: false, ws: false },
|
|
3818
|
+
appType: "custom",
|
|
3819
|
+
// IMPORTANT:
|
|
3820
|
+
// This internal, short-lived Vite server exists only to `ssrLoadModule()` the router entry.
|
|
3821
|
+
// We close it immediately after reading routes.
|
|
3822
|
+
//
|
|
3823
|
+
// Vite's dependency optimizer (vite:dep-scan / optimizeDeps) runs asynchronously and can
|
|
3824
|
+
// still have pending resolve requests when we call `server.close()`, which surfaces as:
|
|
3825
|
+
// "The server is being restarted or closed. Request is outdated [plugin vite:dep-scan]"
|
|
3826
|
+
//
|
|
3827
|
+
// Disable optimizeDeps entirely for this internal server to avoid that race.
|
|
3828
|
+
optimizeDeps: {
|
|
3829
|
+
disabled: true
|
|
3830
|
+
},
|
|
3831
|
+
resolve: {
|
|
3832
|
+
alias: {
|
|
3833
|
+
"@": cwd
|
|
3834
|
+
}
|
|
3835
|
+
},
|
|
3836
|
+
// Important: Do NOT include @vitejs/plugin-vue here.
|
|
3837
|
+
// We stub all `.vue` imports ourselves, and including the Vue plugin would attempt to parse
|
|
3838
|
+
// those stubbed modules as real SFCs (and fail).
|
|
3839
|
+
plugins: [createRouterIntrospectionVueStubPlugin({ routerEntryAbs: routerEntry, moduleShims })]
|
|
3840
|
+
});
|
|
3791
3841
|
try {
|
|
3792
|
-
|
|
3793
|
-
|
|
3794
|
-
|
|
3795
|
-
|
|
3796
|
-
|
|
3797
|
-
|
|
3798
|
-
|
|
3799
|
-
for (const r of router.getRoutes()) {
|
|
3800
|
-
const componentInfo = await getComponentInfoFromRouteRecord(r, { rootDir: cwd });
|
|
3801
|
-
const componentName = resolveIntrospectedComponentName(componentInfo, options.componentNaming);
|
|
3802
|
-
if (!componentName)
|
|
3803
|
-
continue;
|
|
3804
|
-
if (typeof r.path === "string" && r.path.length) {
|
|
3805
|
-
routePathMap.set(r.path, componentName);
|
|
3842
|
+
const moduleId = node_url.pathToFileURL(routerEntry).href;
|
|
3843
|
+
debugLog(`ssrLoadModule(${moduleId}) start`);
|
|
3844
|
+
const mod = await server.ssrLoadModule(moduleId);
|
|
3845
|
+
debugLog(`ssrLoadModule(${moduleId}) done; hasDefault=${typeof mod?.default === "function"}`);
|
|
3846
|
+
const makeRouter = mod?.default;
|
|
3847
|
+
if (typeof makeRouter !== "function") {
|
|
3848
|
+
throw new TypeError(`[vue-pom-generator] ${routerEntry} must export a default router factory function (export default makeRouter).`);
|
|
3806
3849
|
}
|
|
3807
|
-
|
|
3808
|
-
|
|
3809
|
-
|
|
3850
|
+
let router;
|
|
3851
|
+
try {
|
|
3852
|
+
router = makeRouter();
|
|
3853
|
+
} catch (err) {
|
|
3854
|
+
throw new Error(`[vue-pom-generator] makeRouter() invocation failed: ${String(err)}`);
|
|
3810
3855
|
}
|
|
3811
|
-
const
|
|
3812
|
-
const
|
|
3813
|
-
const
|
|
3814
|
-
|
|
3815
|
-
|
|
3816
|
-
|
|
3817
|
-
|
|
3818
|
-
|
|
3819
|
-
|
|
3820
|
-
|
|
3856
|
+
const routeNameMap = /* @__PURE__ */ new Map();
|
|
3857
|
+
const routePathMap = /* @__PURE__ */ new Map();
|
|
3858
|
+
const routeMetaEntries = [];
|
|
3859
|
+
for (const r of router.getRoutes()) {
|
|
3860
|
+
const componentInfo = await getComponentInfoFromRouteRecord(r, { rootDir: cwd });
|
|
3861
|
+
const componentName = resolveIntrospectedComponentName(componentInfo, options.componentNaming);
|
|
3862
|
+
if (!componentName)
|
|
3863
|
+
continue;
|
|
3864
|
+
if (typeof r.path === "string" && r.path.length) {
|
|
3865
|
+
routePathMap.set(r.path, componentName);
|
|
3866
|
+
}
|
|
3867
|
+
if (typeof r.name === "string" && r.name.length) {
|
|
3868
|
+
const key = toPascalCase(r.name);
|
|
3869
|
+
routeNameMap.set(key, componentName);
|
|
3870
|
+
}
|
|
3871
|
+
const { paramKeys, queryKeys } = getRoutePropsKeys(r);
|
|
3872
|
+
const paramsMeta = getRouteParamMeta(router, r, paramKeys);
|
|
3873
|
+
const pathTemplate = buildRouteTemplate(router, r, paramsMeta.map((p) => p.name));
|
|
3874
|
+
if (typeof pathTemplate === "string" && pathTemplate.length) {
|
|
3875
|
+
routeMetaEntries.push({
|
|
3876
|
+
componentName,
|
|
3877
|
+
pathTemplate,
|
|
3878
|
+
params: paramsMeta,
|
|
3879
|
+
query: queryKeys
|
|
3880
|
+
});
|
|
3881
|
+
}
|
|
3821
3882
|
}
|
|
3883
|
+
return { routeNameMap, routePathMap, routeMetaEntries };
|
|
3884
|
+
} finally {
|
|
3885
|
+
debugLog("closing internal vite server");
|
|
3886
|
+
await server.close();
|
|
3822
3887
|
}
|
|
3823
|
-
return { routeNameMap, routePathMap, routeMetaEntries };
|
|
3824
3888
|
} finally {
|
|
3825
|
-
|
|
3826
|
-
await server.close();
|
|
3889
|
+
restoreDomShim();
|
|
3827
3890
|
}
|
|
3828
3891
|
});
|
|
3829
3892
|
}
|