@immense/vue-pom-generator 1.0.55 → 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 +14 -12
- package/dist/index.cjs +163 -93
- package/dist/index.cjs.map +1 -1
- package/dist/index.mjs +163 -93
- package/dist/index.mjs.map +1 -1
- package/dist/router-introspection.d.ts.map +1 -1
- package/dist/utils.d.ts.map +1 -1
- package/package.json +1 -1
package/RELEASE_NOTES.md
CHANGED
|
@@ -1,28 +1,30 @@
|
|
|
1
1
|
● ## Highlights
|
|
2
2
|
|
|
3
|
-
- Fixed
|
|
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
|
-
-
|
|
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
|
|
11
13
|
|
|
12
|
-
|
|
13
|
-
-
|
|
14
|
+
### Testing
|
|
15
|
+
- Added comprehensive test coverage for router DOM global restoration behavior
|
|
14
16
|
|
|
15
17
|
## Breaking Changes
|
|
16
18
|
|
|
17
|
-
None
|
|
19
|
+
None
|
|
18
20
|
|
|
19
21
|
## Pull Requests Included
|
|
20
22
|
|
|
21
|
-
- #
|
|
22
|
-
(
|
|
23
|
+
- #18 fix: restore router DOM globals after introspection
|
|
24
|
+
(https://github.com/immense/vue-pom-generator/pull/18)
|
|
23
25
|
|
|
24
26
|
## Testing
|
|
25
27
|
|
|
26
|
-
|
|
27
|
-
|
|
28
|
+
Added 83 lines of test coverage for router introspection DOM global handling. All existing tests
|
|
29
|
+
continue to pass.
|
|
28
30
|
|
package/dist/index.cjs
CHANGED
|
@@ -1265,6 +1265,12 @@ function nodeHandlerAttributeInfo(node) {
|
|
|
1265
1265
|
const n = node2;
|
|
1266
1266
|
return typeof n.callee === "object" && n.callee !== null && Array.isArray(n.arguments);
|
|
1267
1267
|
};
|
|
1268
|
+
const isAwaitExpressionNode = (node2) => {
|
|
1269
|
+
if (!isNodeType(node2, "AwaitExpression"))
|
|
1270
|
+
return false;
|
|
1271
|
+
const n = node2;
|
|
1272
|
+
return typeof n.argument === "object" && n.argument !== null;
|
|
1273
|
+
};
|
|
1268
1274
|
const isAssignmentExpressionNode = (node2) => {
|
|
1269
1275
|
if (!isNodeType(node2, "AssignmentExpression"))
|
|
1270
1276
|
return false;
|
|
@@ -1471,14 +1477,15 @@ function nodeHandlerAttributeInfo(node) {
|
|
|
1471
1477
|
if (isArrowFunctionExpressionNode(expr)) {
|
|
1472
1478
|
const body = expr.body;
|
|
1473
1479
|
const tryFromCallExpression = (call) => {
|
|
1474
|
-
|
|
1480
|
+
const resolvedCall = isAwaitExpressionNode(call) ? call.argument : call;
|
|
1481
|
+
if (!isCallExpressionNode(resolvedCall)) {
|
|
1475
1482
|
return null;
|
|
1476
1483
|
}
|
|
1477
|
-
const name = getLastIdentifierFromMemberChain(
|
|
1484
|
+
const name = getLastIdentifierFromMemberChain(resolvedCall.callee);
|
|
1478
1485
|
if (!name) {
|
|
1479
1486
|
return null;
|
|
1480
1487
|
}
|
|
1481
|
-
const suffix = getStableSuffixFromCall(
|
|
1488
|
+
const suffix = getStableSuffixFromCall(resolvedCall);
|
|
1482
1489
|
const semanticNameHint = suffix ? `${toPascalCase(name)}${suffix}` : toPascalCase(name);
|
|
1483
1490
|
return semanticNameHint;
|
|
1484
1491
|
};
|
|
@@ -3150,6 +3157,56 @@ function createRouterIntrospectionVueStubPlugin(options) {
|
|
|
3150
3157
|
}
|
|
3151
3158
|
};
|
|
3152
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
|
+
}
|
|
3153
3210
|
const PARAM_TOKEN_PREFIX = "__VUE_TESTID_PARAM__";
|
|
3154
3211
|
function getParamToken(name) {
|
|
3155
3212
|
return `${PARAM_TOKEN_PREFIX}${name}__`;
|
|
@@ -3498,12 +3555,18 @@ function createMinimalLocation() {
|
|
|
3498
3555
|
ancestorOrigins: { length: 0, contains: () => false, item: () => null, [Symbol.iterator]: [][Symbol.iterator] }
|
|
3499
3556
|
};
|
|
3500
3557
|
}
|
|
3501
|
-
|
|
3558
|
+
function ensureDomShim() {
|
|
3502
3559
|
const g = globalThis;
|
|
3503
3560
|
if (typeof document !== "undefined" && typeof window !== "undefined")
|
|
3504
|
-
return
|
|
3561
|
+
return () => {
|
|
3562
|
+
};
|
|
3505
3563
|
const minimalDoc = createMinimalDocument();
|
|
3506
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
|
+
};
|
|
3507
3570
|
const win = {
|
|
3508
3571
|
document: minimalDoc,
|
|
3509
3572
|
location: minimalLocation,
|
|
@@ -3548,17 +3611,17 @@ async function ensureDomShim() {
|
|
|
3548
3611
|
queueMicrotask,
|
|
3549
3612
|
performance: globalThis.performance
|
|
3550
3613
|
};
|
|
3551
|
-
|
|
3552
|
-
|
|
3553
|
-
|
|
3614
|
+
setGlobal("window", win);
|
|
3615
|
+
setGlobal("document", minimalDoc);
|
|
3616
|
+
setGlobal("location", minimalLocation);
|
|
3554
3617
|
if (!g.self)
|
|
3555
|
-
|
|
3618
|
+
setGlobal("self", win);
|
|
3556
3619
|
if (!g.navigator)
|
|
3557
|
-
|
|
3620
|
+
setGlobal("navigator", win.navigator);
|
|
3558
3621
|
if (!g.history)
|
|
3559
|
-
|
|
3622
|
+
setGlobal("history", win.history);
|
|
3560
3623
|
if (!g.MutationObserver) {
|
|
3561
|
-
|
|
3624
|
+
setGlobal("MutationObserver", class {
|
|
3562
3625
|
disconnect() {
|
|
3563
3626
|
}
|
|
3564
3627
|
observe() {
|
|
@@ -3566,20 +3629,20 @@ async function ensureDomShim() {
|
|
|
3566
3629
|
takeRecords() {
|
|
3567
3630
|
return [];
|
|
3568
3631
|
}
|
|
3569
|
-
};
|
|
3632
|
+
});
|
|
3570
3633
|
}
|
|
3571
3634
|
if (!g.ResizeObserver) {
|
|
3572
|
-
|
|
3635
|
+
setGlobal("ResizeObserver", class {
|
|
3573
3636
|
disconnect() {
|
|
3574
3637
|
}
|
|
3575
3638
|
observe() {
|
|
3576
3639
|
}
|
|
3577
3640
|
unobserve() {
|
|
3578
3641
|
}
|
|
3579
|
-
};
|
|
3642
|
+
});
|
|
3580
3643
|
}
|
|
3581
3644
|
if (!g.IntersectionObserver) {
|
|
3582
|
-
|
|
3645
|
+
setGlobal("IntersectionObserver", class {
|
|
3583
3646
|
disconnect() {
|
|
3584
3647
|
}
|
|
3585
3648
|
observe() {
|
|
@@ -3589,10 +3652,10 @@ async function ensureDomShim() {
|
|
|
3589
3652
|
takeRecords() {
|
|
3590
3653
|
return [];
|
|
3591
3654
|
}
|
|
3592
|
-
};
|
|
3655
|
+
});
|
|
3593
3656
|
}
|
|
3594
3657
|
if (!g.requestIdleCallback) {
|
|
3595
|
-
|
|
3658
|
+
setGlobal("requestIdleCallback", (cb) => setTimeout(() => cb({ didTimeout: false, timeRemaining: () => 0 }), 1));
|
|
3596
3659
|
}
|
|
3597
3660
|
if (!g.localStorage || !g.sessionStorage) {
|
|
3598
3661
|
const storageFactory = () => {
|
|
@@ -3615,12 +3678,15 @@ async function ensureDomShim() {
|
|
|
3615
3678
|
};
|
|
3616
3679
|
};
|
|
3617
3680
|
if (!g.localStorage)
|
|
3618
|
-
|
|
3681
|
+
setGlobal("localStorage", storageFactory());
|
|
3619
3682
|
if (!g.sessionStorage)
|
|
3620
|
-
|
|
3683
|
+
setGlobal("sessionStorage", storageFactory());
|
|
3621
3684
|
}
|
|
3622
3685
|
if (!g.requestAnimationFrame)
|
|
3623
|
-
|
|
3686
|
+
setGlobal("requestAnimationFrame", (cb) => setTimeout(() => cb(Date.now()), 16));
|
|
3687
|
+
return () => {
|
|
3688
|
+
restoreTemporaryGlobals(snapshots);
|
|
3689
|
+
};
|
|
3624
3690
|
}
|
|
3625
3691
|
function unwrapNuxtPageSegment(segment, prefix, suffix) {
|
|
3626
3692
|
if (!segment.startsWith(prefix) || !segment.endsWith(suffix))
|
|
@@ -3738,85 +3804,89 @@ async function parseRouterFileFromCwd(routerEntryPath, options = {}) {
|
|
|
3738
3804
|
}
|
|
3739
3805
|
const cwd = path.dirname(routerEntry);
|
|
3740
3806
|
const moduleShims = normalizeRouterIntrospectionModuleShims(options.moduleShims);
|
|
3741
|
-
|
|
3742
|
-
debugLog(`parseRouterFileFromCwd cwd=${cwd}`);
|
|
3743
|
-
const vite = await import("vite");
|
|
3744
|
-
const server = await vite.createServer({
|
|
3745
|
-
root: cwd,
|
|
3746
|
-
configFile: false,
|
|
3747
|
-
logLevel: "error",
|
|
3748
|
-
// This server is created only to SSR-load the router module. Disable HMR/WebSocket
|
|
3749
|
-
// to avoid port conflicts in dev/test environments.
|
|
3750
|
-
server: { middlewareMode: true, hmr: false, ws: false },
|
|
3751
|
-
appType: "custom",
|
|
3752
|
-
// IMPORTANT:
|
|
3753
|
-
// This internal, short-lived Vite server exists only to `ssrLoadModule()` the router entry.
|
|
3754
|
-
// We close it immediately after reading routes.
|
|
3755
|
-
//
|
|
3756
|
-
// Vite's dependency optimizer (vite:dep-scan / optimizeDeps) runs asynchronously and can
|
|
3757
|
-
// still have pending resolve requests when we call `server.close()`, which surfaces as:
|
|
3758
|
-
// "The server is being restarted or closed. Request is outdated [plugin vite:dep-scan]"
|
|
3759
|
-
//
|
|
3760
|
-
// Disable optimizeDeps entirely for this internal server to avoid that race.
|
|
3761
|
-
optimizeDeps: {
|
|
3762
|
-
disabled: true
|
|
3763
|
-
},
|
|
3764
|
-
resolve: {
|
|
3765
|
-
alias: {
|
|
3766
|
-
"@": cwd
|
|
3767
|
-
}
|
|
3768
|
-
},
|
|
3769
|
-
// Important: Do NOT include @vitejs/plugin-vue here.
|
|
3770
|
-
// We stub all `.vue` imports ourselves, and including the Vue plugin would attempt to parse
|
|
3771
|
-
// those stubbed modules as real SFCs (and fail).
|
|
3772
|
-
plugins: [createRouterIntrospectionVueStubPlugin({ routerEntryAbs: routerEntry, moduleShims })]
|
|
3773
|
-
});
|
|
3807
|
+
const restoreDomShim = ensureDomShim();
|
|
3774
3808
|
try {
|
|
3775
|
-
|
|
3776
|
-
|
|
3777
|
-
const
|
|
3778
|
-
|
|
3779
|
-
|
|
3780
|
-
|
|
3781
|
-
|
|
3782
|
-
|
|
3783
|
-
|
|
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
|
+
});
|
|
3784
3841
|
try {
|
|
3785
|
-
|
|
3786
|
-
|
|
3787
|
-
|
|
3788
|
-
|
|
3789
|
-
|
|
3790
|
-
|
|
3791
|
-
|
|
3792
|
-
for (const r of router.getRoutes()) {
|
|
3793
|
-
const componentInfo = await getComponentInfoFromRouteRecord(r, { rootDir: cwd });
|
|
3794
|
-
const componentName = resolveIntrospectedComponentName(componentInfo, options.componentNaming);
|
|
3795
|
-
if (!componentName)
|
|
3796
|
-
continue;
|
|
3797
|
-
if (typeof r.path === "string" && r.path.length) {
|
|
3798
|
-
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).`);
|
|
3799
3849
|
}
|
|
3800
|
-
|
|
3801
|
-
|
|
3802
|
-
|
|
3850
|
+
let router;
|
|
3851
|
+
try {
|
|
3852
|
+
router = makeRouter();
|
|
3853
|
+
} catch (err) {
|
|
3854
|
+
throw new Error(`[vue-pom-generator] makeRouter() invocation failed: ${String(err)}`);
|
|
3803
3855
|
}
|
|
3804
|
-
const
|
|
3805
|
-
const
|
|
3806
|
-
const
|
|
3807
|
-
|
|
3808
|
-
|
|
3809
|
-
|
|
3810
|
-
|
|
3811
|
-
|
|
3812
|
-
|
|
3813
|
-
|
|
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
|
+
}
|
|
3814
3882
|
}
|
|
3883
|
+
return { routeNameMap, routePathMap, routeMetaEntries };
|
|
3884
|
+
} finally {
|
|
3885
|
+
debugLog("closing internal vite server");
|
|
3886
|
+
await server.close();
|
|
3815
3887
|
}
|
|
3816
|
-
return { routeNameMap, routePathMap, routeMetaEntries };
|
|
3817
3888
|
} finally {
|
|
3818
|
-
|
|
3819
|
-
await server.close();
|
|
3889
|
+
restoreDomShim();
|
|
3820
3890
|
}
|
|
3821
3891
|
});
|
|
3822
3892
|
}
|