@immense/vue-pom-generator 1.0.41 → 1.0.43
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 +22 -26
- package/dist/index.cjs +369 -223
- package/dist/index.cjs.map +1 -1
- package/dist/index.mjs +370 -224
- package/dist/index.mjs.map +1 -1
- package/dist/plugin/create-vue-pom-generator-plugins.d.ts.map +1 -1
- package/dist/plugin/support/build-plugin.d.ts +12 -2
- package/dist/plugin/support/build-plugin.d.ts.map +1 -1
- package/dist/plugin/support/dev-plugin.d.ts +2 -0
- package/dist/plugin/support/dev-plugin.d.ts.map +1 -1
- package/dist/plugin/support-plugins.d.ts +2 -0
- package/dist/plugin/support-plugins.d.ts.map +1 -1
- package/dist/tests/build-serve-parity.test.d.ts +2 -0
- package/dist/tests/build-serve-parity.test.d.ts.map +1 -0
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -26,13 +26,13 @@ const path = require("node:path");
|
|
|
26
26
|
const process = require("node:process");
|
|
27
27
|
const node_url = require("node:url");
|
|
28
28
|
const fs = require("node:fs");
|
|
29
|
+
const compilerDom = require("@vue/compiler-dom");
|
|
30
|
+
const compilerSfc = require("@vue/compiler-sfc");
|
|
29
31
|
const parser = require("@babel/parser");
|
|
30
32
|
const jsdom = require("jsdom");
|
|
31
33
|
const compilerCore = require("@vue/compiler-core");
|
|
32
34
|
const types = require("@babel/types");
|
|
33
35
|
const node_perf_hooks = require("node:perf_hooks");
|
|
34
|
-
const compilerDom = require("@vue/compiler-dom");
|
|
35
|
-
const compilerSfc = require("@vue/compiler-sfc");
|
|
36
36
|
const virtualImport = require("vite-plugin-virtual");
|
|
37
37
|
const vue = require("@vitejs/plugin-vue");
|
|
38
38
|
var _documentCurrentScript = typeof document !== "undefined" ? document.currentScript : null;
|
|
@@ -4768,148 +4768,6 @@ function getConstructor(childrenComponent, componentHierarchyMap, attachmentsFor
|
|
|
4768
4768
|
return `${content}
|
|
4769
4769
|
`;
|
|
4770
4770
|
}
|
|
4771
|
-
function summarizeHierarchyMap(componentHierarchyMap) {
|
|
4772
|
-
let interactiveComponentCount = 0;
|
|
4773
|
-
let dataTestIdCount = 0;
|
|
4774
|
-
for (const dependencies of componentHierarchyMap.values()) {
|
|
4775
|
-
const selectorCount = dependencies.dataTestIdSet?.size ?? 0;
|
|
4776
|
-
if (selectorCount > 0) {
|
|
4777
|
-
interactiveComponentCount += 1;
|
|
4778
|
-
dataTestIdCount += selectorCount;
|
|
4779
|
-
}
|
|
4780
|
-
}
|
|
4781
|
-
return {
|
|
4782
|
-
entryCount: componentHierarchyMap.size,
|
|
4783
|
-
interactiveComponentCount,
|
|
4784
|
-
dataTestIdCount
|
|
4785
|
-
};
|
|
4786
|
-
}
|
|
4787
|
-
function isLessRich(candidate, previous) {
|
|
4788
|
-
if (candidate.dataTestIdCount !== previous.dataTestIdCount) {
|
|
4789
|
-
return candidate.dataTestIdCount < previous.dataTestIdCount;
|
|
4790
|
-
}
|
|
4791
|
-
if (candidate.interactiveComponentCount !== previous.interactiveComponentCount) {
|
|
4792
|
-
return candidate.interactiveComponentCount < previous.interactiveComponentCount;
|
|
4793
|
-
}
|
|
4794
|
-
return candidate.entryCount < previous.entryCount;
|
|
4795
|
-
}
|
|
4796
|
-
function createBuildProcessorPlugin(options) {
|
|
4797
|
-
const {
|
|
4798
|
-
componentHierarchyMap,
|
|
4799
|
-
vueFilesPathMap,
|
|
4800
|
-
viewsDir,
|
|
4801
|
-
scanDirs,
|
|
4802
|
-
basePageClassPath,
|
|
4803
|
-
normalizedBasePagePath,
|
|
4804
|
-
outDir,
|
|
4805
|
-
emitLanguages,
|
|
4806
|
-
csharp,
|
|
4807
|
-
generateFixtures,
|
|
4808
|
-
customPomAttachments,
|
|
4809
|
-
projectRootRef,
|
|
4810
|
-
customPomDir,
|
|
4811
|
-
customPomImportAliases,
|
|
4812
|
-
customPomImportNameCollisionBehavior,
|
|
4813
|
-
testIdAttribute,
|
|
4814
|
-
routerAwarePoms,
|
|
4815
|
-
resolvedRouterEntry,
|
|
4816
|
-
routerType,
|
|
4817
|
-
routerModuleShims,
|
|
4818
|
-
loggerRef
|
|
4819
|
-
} = options;
|
|
4820
|
-
let lastGeneratedMetrics = {
|
|
4821
|
-
entryCount: 0,
|
|
4822
|
-
interactiveComponentCount: 0,
|
|
4823
|
-
dataTestIdCount: 0
|
|
4824
|
-
};
|
|
4825
|
-
return {
|
|
4826
|
-
name: "vue-pom-generator-build",
|
|
4827
|
-
// This plugin exists to generate code on build output; it is not needed during dev-server HMR.
|
|
4828
|
-
apply: "build",
|
|
4829
|
-
enforce: "pre",
|
|
4830
|
-
async buildStart() {
|
|
4831
|
-
if (!routerAwarePoms) {
|
|
4832
|
-
setRouteNameToComponentNameMap(/* @__PURE__ */ new Map());
|
|
4833
|
-
setResolveToComponentNameFn(() => null);
|
|
4834
|
-
return;
|
|
4835
|
-
}
|
|
4836
|
-
let result;
|
|
4837
|
-
if (routerType === "nuxt") {
|
|
4838
|
-
result = await introspectNuxtPages(projectRootRef.current);
|
|
4839
|
-
} else {
|
|
4840
|
-
if (!resolvedRouterEntry)
|
|
4841
|
-
throw new Error("[vue-pom-generator] router.entry is required when router introspection is enabled.");
|
|
4842
|
-
result = await parseRouterFileFromCwd(resolvedRouterEntry, {
|
|
4843
|
-
moduleShims: routerModuleShims,
|
|
4844
|
-
componentNaming: {
|
|
4845
|
-
projectRoot: projectRootRef.current,
|
|
4846
|
-
viewsDirAbs: path.isAbsolute(viewsDir) ? viewsDir : path.resolve(projectRootRef.current, viewsDir),
|
|
4847
|
-
scanDirs
|
|
4848
|
-
}
|
|
4849
|
-
});
|
|
4850
|
-
}
|
|
4851
|
-
const { routeNameMap, routePathMap } = result;
|
|
4852
|
-
setRouteNameToComponentNameMap(routeNameMap);
|
|
4853
|
-
setResolveToComponentNameFn((to) => {
|
|
4854
|
-
if (typeof to === "string") {
|
|
4855
|
-
return routePathMap.get(to) ?? null;
|
|
4856
|
-
}
|
|
4857
|
-
const maybe = to;
|
|
4858
|
-
if (typeof maybe.name === "string" && maybe.name.length) {
|
|
4859
|
-
const key = toPascalCase(maybe.name);
|
|
4860
|
-
return routeNameMap.get(key) ?? null;
|
|
4861
|
-
}
|
|
4862
|
-
if (typeof maybe.path === "string" && maybe.path.length) {
|
|
4863
|
-
return routePathMap.get(maybe.path) ?? null;
|
|
4864
|
-
}
|
|
4865
|
-
return null;
|
|
4866
|
-
});
|
|
4867
|
-
if (!fs.existsSync(basePageClassPath)) {
|
|
4868
|
-
this.error(`BasePage.ts not found at ${basePageClassPath}. Ensure it is included in the build.`);
|
|
4869
|
-
}
|
|
4870
|
-
this.addWatchFile(basePageClassPath);
|
|
4871
|
-
const pointerPath = path.resolve(path.dirname(basePageClassPath), "Pointer.ts");
|
|
4872
|
-
if (!fs.existsSync(pointerPath)) {
|
|
4873
|
-
this.error(`Pointer.ts not found at ${pointerPath}. Ensure it is included in the build.`);
|
|
4874
|
-
}
|
|
4875
|
-
this.addWatchFile(pointerPath);
|
|
4876
|
-
},
|
|
4877
|
-
async buildEnd(error) {
|
|
4878
|
-
if (error) {
|
|
4879
|
-
return;
|
|
4880
|
-
}
|
|
4881
|
-
const metrics = summarizeHierarchyMap(componentHierarchyMap);
|
|
4882
|
-
if (metrics.dataTestIdCount <= 0) {
|
|
4883
|
-
return;
|
|
4884
|
-
}
|
|
4885
|
-
if (isLessRich(metrics, lastGeneratedMetrics)) {
|
|
4886
|
-
return;
|
|
4887
|
-
}
|
|
4888
|
-
await generateFiles(componentHierarchyMap, vueFilesPathMap, normalizedBasePagePath, {
|
|
4889
|
-
outDir,
|
|
4890
|
-
emitLanguages,
|
|
4891
|
-
csharp,
|
|
4892
|
-
generateFixtures,
|
|
4893
|
-
customPomAttachments,
|
|
4894
|
-
projectRoot: projectRootRef.current,
|
|
4895
|
-
customPomDir,
|
|
4896
|
-
customPomImportAliases,
|
|
4897
|
-
customPomImportNameCollisionBehavior,
|
|
4898
|
-
testIdAttribute,
|
|
4899
|
-
vueRouterFluentChaining: routerAwarePoms,
|
|
4900
|
-
routerEntry: resolvedRouterEntry,
|
|
4901
|
-
routerType,
|
|
4902
|
-
viewsDir,
|
|
4903
|
-
scanDirs
|
|
4904
|
-
});
|
|
4905
|
-
lastGeneratedMetrics = metrics;
|
|
4906
|
-
loggerRef.current.info(`generated POMs (${metrics.entryCount} entries, ${metrics.interactiveComponentCount} interactive components, ${metrics.dataTestIdCount} selectors)`);
|
|
4907
|
-
},
|
|
4908
|
-
closeBundle() {
|
|
4909
|
-
loggerRef.current.info("build complete");
|
|
4910
|
-
}
|
|
4911
|
-
};
|
|
4912
|
-
}
|
|
4913
4771
|
const TESTID_CLICK_EVENT_NAME = "__testid_event__";
|
|
4914
4772
|
const TESTID_CLICK_EVENT_STRICT_FLAG = "__testid_click_event_strict__";
|
|
4915
4773
|
const CLICK_EVENT_NAME = TESTID_CLICK_EVENT_NAME;
|
|
@@ -5992,6 +5850,265 @@ Fix: remove the explicit ${attrLabel}, or change existingIdBehavior to "overwrit
|
|
|
5992
5850
|
}
|
|
5993
5851
|
};
|
|
5994
5852
|
}
|
|
5853
|
+
function summarizeHierarchyMap(componentHierarchyMap) {
|
|
5854
|
+
let interactiveComponentCount = 0;
|
|
5855
|
+
let dataTestIdCount = 0;
|
|
5856
|
+
for (const dependencies of componentHierarchyMap.values()) {
|
|
5857
|
+
const selectorCount = dependencies.dataTestIdSet?.size ?? 0;
|
|
5858
|
+
if (selectorCount > 0) {
|
|
5859
|
+
interactiveComponentCount += 1;
|
|
5860
|
+
dataTestIdCount += selectorCount;
|
|
5861
|
+
}
|
|
5862
|
+
}
|
|
5863
|
+
return {
|
|
5864
|
+
entryCount: componentHierarchyMap.size,
|
|
5865
|
+
interactiveComponentCount,
|
|
5866
|
+
dataTestIdCount
|
|
5867
|
+
};
|
|
5868
|
+
}
|
|
5869
|
+
function isLessRich(candidate, previous) {
|
|
5870
|
+
if (candidate.dataTestIdCount !== previous.dataTestIdCount) {
|
|
5871
|
+
return candidate.dataTestIdCount < previous.dataTestIdCount;
|
|
5872
|
+
}
|
|
5873
|
+
if (candidate.interactiveComponentCount !== previous.interactiveComponentCount) {
|
|
5874
|
+
return candidate.interactiveComponentCount < previous.interactiveComponentCount;
|
|
5875
|
+
}
|
|
5876
|
+
return candidate.entryCount < previous.entryCount;
|
|
5877
|
+
}
|
|
5878
|
+
function createBuildProcessorPlugin(options) {
|
|
5879
|
+
const {
|
|
5880
|
+
componentHierarchyMap,
|
|
5881
|
+
vueFilesPathMap,
|
|
5882
|
+
viewsDir,
|
|
5883
|
+
scanDirs,
|
|
5884
|
+
basePageClassPath,
|
|
5885
|
+
normalizedBasePagePath,
|
|
5886
|
+
outDir,
|
|
5887
|
+
emitLanguages,
|
|
5888
|
+
csharp,
|
|
5889
|
+
generateFixtures,
|
|
5890
|
+
customPomAttachments,
|
|
5891
|
+
projectRootRef,
|
|
5892
|
+
customPomDir,
|
|
5893
|
+
customPomImportAliases,
|
|
5894
|
+
customPomImportNameCollisionBehavior,
|
|
5895
|
+
testIdAttribute,
|
|
5896
|
+
nameCollisionBehavior,
|
|
5897
|
+
existingIdBehavior,
|
|
5898
|
+
nativeWrappers,
|
|
5899
|
+
excludedComponents,
|
|
5900
|
+
getWrapperSearchRoots,
|
|
5901
|
+
routerAwarePoms,
|
|
5902
|
+
resolvedRouterEntry,
|
|
5903
|
+
routerType,
|
|
5904
|
+
routerModuleShims,
|
|
5905
|
+
loggerRef
|
|
5906
|
+
} = options;
|
|
5907
|
+
let lastGeneratedMetrics = {
|
|
5908
|
+
entryCount: 0,
|
|
5909
|
+
interactiveComponentCount: 0,
|
|
5910
|
+
dataTestIdCount: 0
|
|
5911
|
+
};
|
|
5912
|
+
const getViewsDirAbs = () => path.isAbsolute(viewsDir) ? viewsDir : path.resolve(projectRootRef.current, viewsDir);
|
|
5913
|
+
const getScriptInfo = (source, filename) => {
|
|
5914
|
+
try {
|
|
5915
|
+
const { descriptor } = compilerSfc.parse(source, { filename });
|
|
5916
|
+
if (!descriptor.script && !descriptor.scriptSetup)
|
|
5917
|
+
return { bindings: void 0, isScriptSetup: false };
|
|
5918
|
+
const scriptBlock = compilerSfc.compileScript(descriptor, { id: filename });
|
|
5919
|
+
return { bindings: scriptBlock.bindings, isScriptSetup: !!descriptor.scriptSetup };
|
|
5920
|
+
} catch {
|
|
5921
|
+
return { bindings: void 0, isScriptSetup: false };
|
|
5922
|
+
}
|
|
5923
|
+
};
|
|
5924
|
+
const supplementHierarchyFromFilesystem = () => {
|
|
5925
|
+
const walkFilesRecursive = (rootDir) => {
|
|
5926
|
+
const out = [];
|
|
5927
|
+
const stack = [rootDir];
|
|
5928
|
+
while (stack.length) {
|
|
5929
|
+
const dir = stack.pop();
|
|
5930
|
+
if (!dir) continue;
|
|
5931
|
+
let entries = [];
|
|
5932
|
+
try {
|
|
5933
|
+
entries = fs.readdirSync(dir, { withFileTypes: true });
|
|
5934
|
+
} catch {
|
|
5935
|
+
continue;
|
|
5936
|
+
}
|
|
5937
|
+
for (const ent of entries) {
|
|
5938
|
+
if (ent.isDirectory()) {
|
|
5939
|
+
if (ent.name === "node_modules" || ent.name === ".git" || ent.name === "dist")
|
|
5940
|
+
continue;
|
|
5941
|
+
stack.push(path.join(dir, ent.name));
|
|
5942
|
+
continue;
|
|
5943
|
+
}
|
|
5944
|
+
if (ent.isFile() && ent.name.endsWith(".vue")) {
|
|
5945
|
+
out.push(path.join(dir, ent.name));
|
|
5946
|
+
}
|
|
5947
|
+
}
|
|
5948
|
+
}
|
|
5949
|
+
return out;
|
|
5950
|
+
};
|
|
5951
|
+
let supplemented = 0;
|
|
5952
|
+
for (const dir of scanDirs) {
|
|
5953
|
+
const absDir = path.resolve(projectRootRef.current, dir);
|
|
5954
|
+
if (!fs.existsSync(absDir))
|
|
5955
|
+
continue;
|
|
5956
|
+
for (const filePath of walkFilesRecursive(absDir)) {
|
|
5957
|
+
const absolutePath = path.resolve(filePath);
|
|
5958
|
+
const componentName = resolveComponentNameFromPath({
|
|
5959
|
+
filename: absolutePath,
|
|
5960
|
+
projectRoot: projectRootRef.current,
|
|
5961
|
+
viewsDirAbs: getViewsDirAbs(),
|
|
5962
|
+
scanDirs,
|
|
5963
|
+
extraRoots: [process.cwd()]
|
|
5964
|
+
});
|
|
5965
|
+
if (componentHierarchyMap.has(componentName))
|
|
5966
|
+
continue;
|
|
5967
|
+
let sfc = "";
|
|
5968
|
+
try {
|
|
5969
|
+
sfc = fs.readFileSync(absolutePath, "utf8");
|
|
5970
|
+
} catch {
|
|
5971
|
+
continue;
|
|
5972
|
+
}
|
|
5973
|
+
const { descriptor } = compilerSfc.parse(sfc, { filename: absolutePath });
|
|
5974
|
+
const template = descriptor.template?.content ?? "";
|
|
5975
|
+
if (!template.trim()) {
|
|
5976
|
+
vueFilesPathMap.set(componentName, absolutePath);
|
|
5977
|
+
componentHierarchyMap.set(componentName, {
|
|
5978
|
+
filePath: absolutePath,
|
|
5979
|
+
childrenComponentSet: /* @__PURE__ */ new Set(),
|
|
5980
|
+
usedComponentSet: /* @__PURE__ */ new Set(),
|
|
5981
|
+
dataTestIdSet: /* @__PURE__ */ new Set(),
|
|
5982
|
+
isView: false,
|
|
5983
|
+
methodsContent: ""
|
|
5984
|
+
});
|
|
5985
|
+
supplemented++;
|
|
5986
|
+
continue;
|
|
5987
|
+
}
|
|
5988
|
+
const { bindings: bindingMetadata, isScriptSetup } = getScriptInfo(sfc, absolutePath);
|
|
5989
|
+
vueFilesPathMap.set(componentName, absolutePath);
|
|
5990
|
+
try {
|
|
5991
|
+
compilerDom__namespace.compile(template, {
|
|
5992
|
+
filename: absolutePath,
|
|
5993
|
+
prefixIdentifiers: true,
|
|
5994
|
+
inline: isScriptSetup,
|
|
5995
|
+
bindingMetadata,
|
|
5996
|
+
nodeTransforms: [
|
|
5997
|
+
createTestIdTransform(
|
|
5998
|
+
componentName,
|
|
5999
|
+
componentHierarchyMap,
|
|
6000
|
+
nativeWrappers,
|
|
6001
|
+
excludedComponents,
|
|
6002
|
+
getViewsDirAbs(),
|
|
6003
|
+
{
|
|
6004
|
+
existingIdBehavior: existingIdBehavior ?? "preserve",
|
|
6005
|
+
testIdAttribute,
|
|
6006
|
+
nameCollisionBehavior,
|
|
6007
|
+
warn: (message) => loggerRef.current.warn(message),
|
|
6008
|
+
vueFilesPathMap,
|
|
6009
|
+
wrapperSearchRoots: getWrapperSearchRoots()
|
|
6010
|
+
}
|
|
6011
|
+
)
|
|
6012
|
+
]
|
|
6013
|
+
});
|
|
6014
|
+
} catch {
|
|
6015
|
+
}
|
|
6016
|
+
supplemented++;
|
|
6017
|
+
}
|
|
6018
|
+
}
|
|
6019
|
+
if (supplemented > 0) {
|
|
6020
|
+
loggerRef.current.info(`supplemented ${supplemented} components from filesystem walk (not in build graph)`);
|
|
6021
|
+
}
|
|
6022
|
+
};
|
|
6023
|
+
return {
|
|
6024
|
+
name: "vue-pom-generator-build",
|
|
6025
|
+
// This plugin exists to generate code on build output; it is not needed during dev-server HMR.
|
|
6026
|
+
apply: "build",
|
|
6027
|
+
enforce: "pre",
|
|
6028
|
+
async buildStart() {
|
|
6029
|
+
if (!routerAwarePoms) {
|
|
6030
|
+
setRouteNameToComponentNameMap(/* @__PURE__ */ new Map());
|
|
6031
|
+
setResolveToComponentNameFn(() => null);
|
|
6032
|
+
return;
|
|
6033
|
+
}
|
|
6034
|
+
let result;
|
|
6035
|
+
if (routerType === "nuxt") {
|
|
6036
|
+
result = await introspectNuxtPages(projectRootRef.current);
|
|
6037
|
+
} else {
|
|
6038
|
+
if (!resolvedRouterEntry)
|
|
6039
|
+
throw new Error("[vue-pom-generator] router.entry is required when router introspection is enabled.");
|
|
6040
|
+
result = await parseRouterFileFromCwd(resolvedRouterEntry, {
|
|
6041
|
+
moduleShims: routerModuleShims,
|
|
6042
|
+
componentNaming: {
|
|
6043
|
+
projectRoot: projectRootRef.current,
|
|
6044
|
+
viewsDirAbs: path.isAbsolute(viewsDir) ? viewsDir : path.resolve(projectRootRef.current, viewsDir),
|
|
6045
|
+
scanDirs
|
|
6046
|
+
}
|
|
6047
|
+
});
|
|
6048
|
+
}
|
|
6049
|
+
const { routeNameMap, routePathMap } = result;
|
|
6050
|
+
setRouteNameToComponentNameMap(routeNameMap);
|
|
6051
|
+
setResolveToComponentNameFn((to) => {
|
|
6052
|
+
if (typeof to === "string") {
|
|
6053
|
+
return routePathMap.get(to) ?? null;
|
|
6054
|
+
}
|
|
6055
|
+
const maybe = to;
|
|
6056
|
+
if (typeof maybe.name === "string" && maybe.name.length) {
|
|
6057
|
+
const key = toPascalCase(maybe.name);
|
|
6058
|
+
return routeNameMap.get(key) ?? null;
|
|
6059
|
+
}
|
|
6060
|
+
if (typeof maybe.path === "string" && maybe.path.length) {
|
|
6061
|
+
return routePathMap.get(maybe.path) ?? null;
|
|
6062
|
+
}
|
|
6063
|
+
return null;
|
|
6064
|
+
});
|
|
6065
|
+
if (!fs.existsSync(basePageClassPath)) {
|
|
6066
|
+
this.error(`BasePage.ts not found at ${basePageClassPath}. Ensure it is included in the build.`);
|
|
6067
|
+
}
|
|
6068
|
+
this.addWatchFile(basePageClassPath);
|
|
6069
|
+
const pointerPath = path.resolve(path.dirname(basePageClassPath), "Pointer.ts");
|
|
6070
|
+
if (!fs.existsSync(pointerPath)) {
|
|
6071
|
+
this.error(`Pointer.ts not found at ${pointerPath}. Ensure it is included in the build.`);
|
|
6072
|
+
}
|
|
6073
|
+
this.addWatchFile(pointerPath);
|
|
6074
|
+
},
|
|
6075
|
+
async buildEnd(error) {
|
|
6076
|
+
if (error) {
|
|
6077
|
+
return;
|
|
6078
|
+
}
|
|
6079
|
+
supplementHierarchyFromFilesystem();
|
|
6080
|
+
const metrics = summarizeHierarchyMap(componentHierarchyMap);
|
|
6081
|
+
if (metrics.dataTestIdCount <= 0) {
|
|
6082
|
+
return;
|
|
6083
|
+
}
|
|
6084
|
+
if (isLessRich(metrics, lastGeneratedMetrics)) {
|
|
6085
|
+
return;
|
|
6086
|
+
}
|
|
6087
|
+
await generateFiles(componentHierarchyMap, vueFilesPathMap, normalizedBasePagePath, {
|
|
6088
|
+
outDir,
|
|
6089
|
+
emitLanguages,
|
|
6090
|
+
csharp,
|
|
6091
|
+
generateFixtures,
|
|
6092
|
+
customPomAttachments,
|
|
6093
|
+
projectRoot: projectRootRef.current,
|
|
6094
|
+
customPomDir,
|
|
6095
|
+
customPomImportAliases,
|
|
6096
|
+
customPomImportNameCollisionBehavior,
|
|
6097
|
+
testIdAttribute,
|
|
6098
|
+
vueRouterFluentChaining: routerAwarePoms,
|
|
6099
|
+
routerEntry: resolvedRouterEntry,
|
|
6100
|
+
routerType,
|
|
6101
|
+
viewsDir,
|
|
6102
|
+
scanDirs
|
|
6103
|
+
});
|
|
6104
|
+
lastGeneratedMetrics = metrics;
|
|
6105
|
+
loggerRef.current.info(`generated POMs (${metrics.entryCount} entries, ${metrics.interactiveComponentCount} interactive components, ${metrics.dataTestIdCount} selectors)`);
|
|
6106
|
+
},
|
|
6107
|
+
closeBundle() {
|
|
6108
|
+
loggerRef.current.info("build complete");
|
|
6109
|
+
}
|
|
6110
|
+
};
|
|
6111
|
+
}
|
|
5995
6112
|
function createDevProcessorPlugin(options) {
|
|
5996
6113
|
const {
|
|
5997
6114
|
nativeWrappers,
|
|
@@ -6011,6 +6128,7 @@ function createDevProcessorPlugin(options) {
|
|
|
6011
6128
|
customPomImportAliases,
|
|
6012
6129
|
customPomImportNameCollisionBehavior,
|
|
6013
6130
|
nameCollisionBehavior = "suffix",
|
|
6131
|
+
existingIdBehavior,
|
|
6014
6132
|
testIdAttribute,
|
|
6015
6133
|
routerAwarePoms,
|
|
6016
6134
|
resolvedRouterEntry,
|
|
@@ -6037,7 +6155,7 @@ function createDevProcessorPlugin(options) {
|
|
|
6037
6155
|
return;
|
|
6038
6156
|
scheduleVueFileRegen(ctx.file, "hmr");
|
|
6039
6157
|
},
|
|
6040
|
-
configureServer(server) {
|
|
6158
|
+
async configureServer(server) {
|
|
6041
6159
|
const getViewsDirAbs = () => path.isAbsolute(viewsDir) ? viewsDir : path.resolve(projectRootRef.current, viewsDir);
|
|
6042
6160
|
const routerInitPromise = (async () => {
|
|
6043
6161
|
if (!routerAwarePoms) {
|
|
@@ -6088,6 +6206,17 @@ function createDevProcessorPlugin(options) {
|
|
|
6088
6206
|
});
|
|
6089
6207
|
return descriptor.template?.content ?? "";
|
|
6090
6208
|
};
|
|
6209
|
+
const getScriptInfo = (source, filename) => {
|
|
6210
|
+
try {
|
|
6211
|
+
const { descriptor } = compilerSfc.parse(source, { filename });
|
|
6212
|
+
if (!descriptor.script && !descriptor.scriptSetup)
|
|
6213
|
+
return { bindings: void 0, isScriptSetup: false };
|
|
6214
|
+
const scriptBlock = compilerSfc.compileScript(descriptor, { id: filename });
|
|
6215
|
+
return { bindings: scriptBlock.bindings, isScriptSetup: !!descriptor.scriptSetup };
|
|
6216
|
+
} catch {
|
|
6217
|
+
return { bindings: void 0, isScriptSetup: false };
|
|
6218
|
+
}
|
|
6219
|
+
};
|
|
6091
6220
|
const walkFilesRecursive = (rootDir) => {
|
|
6092
6221
|
const out = [];
|
|
6093
6222
|
const stack = [rootDir];
|
|
@@ -6114,8 +6243,8 @@ function createDevProcessorPlugin(options) {
|
|
|
6114
6243
|
}
|
|
6115
6244
|
return out;
|
|
6116
6245
|
};
|
|
6117
|
-
|
|
6118
|
-
|
|
6246
|
+
let snapshotHierarchy = /* @__PURE__ */ new Map();
|
|
6247
|
+
let snapshotVuePathMap = /* @__PURE__ */ new Map();
|
|
6119
6248
|
const filePathToComponentName = /* @__PURE__ */ new Map();
|
|
6120
6249
|
const getComponentNameForFile = (filePath) => {
|
|
6121
6250
|
const normalized = path.resolve(filePath);
|
|
@@ -6132,12 +6261,12 @@ function createDevProcessorPlugin(options) {
|
|
|
6132
6261
|
filePathToComponentName.set(normalized, name);
|
|
6133
6262
|
return name;
|
|
6134
6263
|
};
|
|
6135
|
-
const compileVueFileIntoSnapshot = (filePath) => {
|
|
6264
|
+
const compileVueFileIntoSnapshot = (filePath, targetHierarchy = snapshotHierarchy, targetVuePathMap = snapshotVuePathMap) => {
|
|
6136
6265
|
const started = node_perf_hooks.performance.now();
|
|
6137
6266
|
const absolutePath = path.resolve(filePath);
|
|
6138
6267
|
const componentName = getComponentNameForFile(absolutePath);
|
|
6139
|
-
|
|
6140
|
-
|
|
6268
|
+
targetVuePathMap.set(componentName, absolutePath);
|
|
6269
|
+
targetHierarchy.delete(componentName);
|
|
6141
6270
|
let sfc = "";
|
|
6142
6271
|
try {
|
|
6143
6272
|
sfc = fs.readFileSync(absolutePath, "utf8");
|
|
@@ -6147,36 +6276,36 @@ function createDevProcessorPlugin(options) {
|
|
|
6147
6276
|
const template = extractTemplateFromSfc(sfc, absolutePath);
|
|
6148
6277
|
if (!template.trim())
|
|
6149
6278
|
return { componentName, ms: node_perf_hooks.performance.now() - started, compiled: true };
|
|
6150
|
-
|
|
6151
|
-
|
|
6152
|
-
|
|
6153
|
-
|
|
6154
|
-
|
|
6155
|
-
|
|
6156
|
-
|
|
6157
|
-
|
|
6158
|
-
|
|
6159
|
-
|
|
6160
|
-
|
|
6161
|
-
|
|
6162
|
-
|
|
6163
|
-
|
|
6164
|
-
|
|
6165
|
-
|
|
6166
|
-
|
|
6167
|
-
|
|
6168
|
-
|
|
6169
|
-
|
|
6170
|
-
|
|
6171
|
-
|
|
6172
|
-
|
|
6173
|
-
}
|
|
6279
|
+
const { bindings: bindingMetadata, isScriptSetup } = getScriptInfo(sfc, absolutePath);
|
|
6280
|
+
compilerDom__namespace.compile(template, {
|
|
6281
|
+
filename: absolutePath,
|
|
6282
|
+
prefixIdentifiers: true,
|
|
6283
|
+
inline: isScriptSetup,
|
|
6284
|
+
bindingMetadata,
|
|
6285
|
+
nodeTransforms: [
|
|
6286
|
+
createTestIdTransform(
|
|
6287
|
+
componentName,
|
|
6288
|
+
targetHierarchy,
|
|
6289
|
+
nativeWrappers,
|
|
6290
|
+
excludedComponents,
|
|
6291
|
+
getViewsDirAbs(),
|
|
6292
|
+
{
|
|
6293
|
+
existingIdBehavior: existingIdBehavior ?? "preserve",
|
|
6294
|
+
nameCollisionBehavior,
|
|
6295
|
+
testIdAttribute,
|
|
6296
|
+
warn: (message) => loggerRef.current.warn(message),
|
|
6297
|
+
vueFilesPathMap: targetVuePathMap,
|
|
6298
|
+
wrapperSearchRoots: getWrapperSearchRoots()
|
|
6299
|
+
}
|
|
6300
|
+
)
|
|
6301
|
+
]
|
|
6302
|
+
});
|
|
6174
6303
|
return { componentName, ms: node_perf_hooks.performance.now() - started, compiled: true };
|
|
6175
6304
|
};
|
|
6176
6305
|
const fullRebuildSnapshotFromFilesystem = () => {
|
|
6177
6306
|
const t0 = node_perf_hooks.performance.now();
|
|
6178
|
-
|
|
6179
|
-
|
|
6307
|
+
const nextHierarchy = /* @__PURE__ */ new Map();
|
|
6308
|
+
const nextVuePathMap = /* @__PURE__ */ new Map();
|
|
6180
6309
|
filePathToComponentName.clear();
|
|
6181
6310
|
let totalVueFiles = 0;
|
|
6182
6311
|
let compiledCount = 0;
|
|
@@ -6187,11 +6316,13 @@ function createDevProcessorPlugin(options) {
|
|
|
6187
6316
|
const vueFiles = walkFilesRecursive(absDir);
|
|
6188
6317
|
totalVueFiles += vueFiles.length;
|
|
6189
6318
|
for (const file of vueFiles) {
|
|
6190
|
-
const res = compileVueFileIntoSnapshot(file);
|
|
6319
|
+
const res = compileVueFileIntoSnapshot(file, nextHierarchy, nextVuePathMap);
|
|
6191
6320
|
if (res.compiled)
|
|
6192
6321
|
compiledCount++;
|
|
6193
6322
|
}
|
|
6194
6323
|
}
|
|
6324
|
+
snapshotHierarchy = nextHierarchy;
|
|
6325
|
+
snapshotVuePathMap = nextVuePathMap;
|
|
6195
6326
|
const t1 = node_perf_hooks.performance.now();
|
|
6196
6327
|
logInfo(`initial scan: found ${totalVueFiles} .vue files in ${scanDirs.join(", ")}`);
|
|
6197
6328
|
logInfo(`initial compile: ${compiledCount}/${totalVueFiles} files in ${formatMs(t1 - t0)} (components=${snapshotHierarchy.size})`);
|
|
@@ -6218,6 +6349,10 @@ function createDevProcessorPlugin(options) {
|
|
|
6218
6349
|
const t1 = node_perf_hooks.performance.now();
|
|
6219
6350
|
logInfo(`generate(${reason}): components=${snapshotHierarchy.size} in ${formatMs(t1 - t0)}`);
|
|
6220
6351
|
};
|
|
6352
|
+
let timer = null;
|
|
6353
|
+
let maxWaitTimer = null;
|
|
6354
|
+
const pendingChangedVueFiles = /* @__PURE__ */ new Set();
|
|
6355
|
+
const pendingDeletedComponents = /* @__PURE__ */ new Set();
|
|
6221
6356
|
const initialBuildPromise = (async () => {
|
|
6222
6357
|
const t0 = node_perf_hooks.performance.now();
|
|
6223
6358
|
await routerInitPromise;
|
|
@@ -6226,13 +6361,44 @@ function createDevProcessorPlugin(options) {
|
|
|
6226
6361
|
const t1 = node_perf_hooks.performance.now();
|
|
6227
6362
|
logInfo(`startup total: ${formatMs(t1 - t0)}`);
|
|
6228
6363
|
})();
|
|
6364
|
+
const logGenerationError = (reason, message) => {
|
|
6365
|
+
server.config.logger.error(`[vue-pom-generator] dev generation failed during ${reason}: ${message}`);
|
|
6366
|
+
};
|
|
6367
|
+
const regenerateFromPending = async (reason) => {
|
|
6368
|
+
const t0 = node_perf_hooks.performance.now();
|
|
6369
|
+
await initialBuildPromise;
|
|
6370
|
+
const nextHierarchy = new Map(snapshotHierarchy);
|
|
6371
|
+
const nextVuePathMap = new Map(snapshotVuePathMap);
|
|
6372
|
+
for (const componentName of pendingDeletedComponents) {
|
|
6373
|
+
nextHierarchy.delete(componentName);
|
|
6374
|
+
nextVuePathMap.delete(componentName);
|
|
6375
|
+
}
|
|
6376
|
+
const files = Array.from(pendingChangedVueFiles);
|
|
6377
|
+
const deletedCount = pendingDeletedComponents.size;
|
|
6378
|
+
pendingChangedVueFiles.clear();
|
|
6379
|
+
pendingDeletedComponents.clear();
|
|
6380
|
+
let compileMs = 0;
|
|
6381
|
+
for (const f of files) {
|
|
6382
|
+
const res = compileVueFileIntoSnapshot(f, nextHierarchy, nextVuePathMap);
|
|
6383
|
+
compileMs += res.ms;
|
|
6384
|
+
}
|
|
6385
|
+
snapshotHierarchy = nextHierarchy;
|
|
6386
|
+
snapshotVuePathMap = nextVuePathMap;
|
|
6387
|
+
const t1 = node_perf_hooks.performance.now();
|
|
6388
|
+
generateAggregatedFromSnapshot(reason);
|
|
6389
|
+
const t2 = node_perf_hooks.performance.now();
|
|
6390
|
+
return {
|
|
6391
|
+
files,
|
|
6392
|
+
deletedCount,
|
|
6393
|
+
compileMs,
|
|
6394
|
+
preGenerateMs: t1 - t0,
|
|
6395
|
+
generateMs: t2 - t1,
|
|
6396
|
+
totalMs: t2 - t0
|
|
6397
|
+
};
|
|
6398
|
+
};
|
|
6229
6399
|
const watchedVueGlobs = scanDirs.map((dir) => path.resolve(projectRootRef.current, dir, "**", "*.vue"));
|
|
6230
6400
|
const watchedPluginGlob = path.resolve(projectRootRef.current, "vite-plugins", "vue-pom-generator", "**", "*.ts");
|
|
6231
6401
|
server.watcher.add([...watchedVueGlobs, watchedPluginGlob, basePageClassPath]);
|
|
6232
|
-
let timer = null;
|
|
6233
|
-
let maxWaitTimer = null;
|
|
6234
|
-
const pendingChangedVueFiles = /* @__PURE__ */ new Set();
|
|
6235
|
-
const pendingDeletedComponents = /* @__PURE__ */ new Set();
|
|
6236
6402
|
scheduleVueFileRegenLocal = (filePath, source) => {
|
|
6237
6403
|
pendingChangedVueFiles.add(filePath);
|
|
6238
6404
|
logDebug(`queued(${source}): files=${pendingChangedVueFiles.size} deleted=${pendingDeletedComponents.size}`);
|
|
@@ -6249,29 +6415,14 @@ function createDevProcessorPlugin(options) {
|
|
|
6249
6415
|
timer = null;
|
|
6250
6416
|
}
|
|
6251
6417
|
maxWaitTimer = null;
|
|
6252
|
-
void (
|
|
6253
|
-
const t0 = node_perf_hooks.performance.now();
|
|
6254
|
-
await initialBuildPromise;
|
|
6255
|
-
for (const componentName of pendingDeletedComponents) {
|
|
6256
|
-
snapshotHierarchy.delete(componentName);
|
|
6257
|
-
snapshotVuePathMap.delete(componentName);
|
|
6258
|
-
}
|
|
6259
|
-
const files = Array.from(pendingChangedVueFiles);
|
|
6260
|
-
const deletedCount = pendingDeletedComponents.size;
|
|
6261
|
-
pendingChangedVueFiles.clear();
|
|
6262
|
-
pendingDeletedComponents.clear();
|
|
6263
|
-
let compileMs = 0;
|
|
6264
|
-
for (const f of files) {
|
|
6265
|
-
const res = compileVueFileIntoSnapshot(f);
|
|
6266
|
-
compileMs += res.ms;
|
|
6267
|
-
}
|
|
6268
|
-
const t1 = node_perf_hooks.performance.now();
|
|
6269
|
-
generateAggregatedFromSnapshot("max-wait");
|
|
6270
|
-
const t2 = node_perf_hooks.performance.now();
|
|
6418
|
+
void regenerateFromPending("max-wait").then(({ files, deletedCount, compileMs, preGenerateMs, generateMs, totalMs }) => {
|
|
6271
6419
|
logInfo(
|
|
6272
|
-
`max-wait: files=${files.length} deleted=${deletedCount} compile=${formatMs(compileMs)} wall=${formatMs(
|
|
6420
|
+
`max-wait: files=${files.length} deleted=${deletedCount} compile=${formatMs(compileMs)} wall=${formatMs(preGenerateMs)} gen=${formatMs(generateMs)} total=${formatMs(totalMs)}`
|
|
6273
6421
|
);
|
|
6274
|
-
})()
|
|
6422
|
+
}).catch((error) => {
|
|
6423
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
6424
|
+
logGenerationError("max-wait", message);
|
|
6425
|
+
});
|
|
6275
6426
|
}, MAX_WAIT_MS);
|
|
6276
6427
|
}
|
|
6277
6428
|
if (wasEmpty) {
|
|
@@ -6287,31 +6438,17 @@ function createDevProcessorPlugin(options) {
|
|
|
6287
6438
|
clearTimeout(maxWaitTimer);
|
|
6288
6439
|
maxWaitTimer = null;
|
|
6289
6440
|
}
|
|
6290
|
-
|
|
6291
|
-
|
|
6292
|
-
await initialBuildPromise;
|
|
6293
|
-
for (const componentName of pendingDeletedComponents) {
|
|
6294
|
-
snapshotHierarchy.delete(componentName);
|
|
6295
|
-
snapshotVuePathMap.delete(componentName);
|
|
6296
|
-
}
|
|
6297
|
-
const files = Array.from(pendingChangedVueFiles);
|
|
6298
|
-
const deletedCount = pendingDeletedComponents.size;
|
|
6299
|
-
pendingChangedVueFiles.clear();
|
|
6300
|
-
pendingDeletedComponents.clear();
|
|
6301
|
-
let compileMs = 0;
|
|
6302
|
-
for (const f of files) {
|
|
6303
|
-
const res = compileVueFileIntoSnapshot(f);
|
|
6304
|
-
compileMs += res.ms;
|
|
6305
|
-
}
|
|
6306
|
-
const t1 = node_perf_hooks.performance.now();
|
|
6307
|
-
generateAggregatedFromSnapshot(files.length || deletedCount ? "batched" : "noop");
|
|
6308
|
-
const t2 = node_perf_hooks.performance.now();
|
|
6441
|
+
const reason = pendingChangedVueFiles.size || pendingDeletedComponents.size ? "batched" : "noop";
|
|
6442
|
+
void regenerateFromPending(reason).then(({ files, deletedCount, compileMs, preGenerateMs, generateMs, totalMs }) => {
|
|
6309
6443
|
if (files.length || deletedCount) {
|
|
6310
6444
|
logInfo(
|
|
6311
|
-
`batched: files=${files.length} deleted=${deletedCount} compile=${formatMs(compileMs)} wall=${formatMs(
|
|
6445
|
+
`batched: files=${files.length} deleted=${deletedCount} compile=${formatMs(compileMs)} wall=${formatMs(preGenerateMs)} gen=${formatMs(generateMs)} total=${formatMs(totalMs)}`
|
|
6312
6446
|
);
|
|
6313
6447
|
}
|
|
6314
|
-
})()
|
|
6448
|
+
}).catch((error) => {
|
|
6449
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
6450
|
+
logGenerationError(reason, message);
|
|
6451
|
+
});
|
|
6315
6452
|
}, 75);
|
|
6316
6453
|
}
|
|
6317
6454
|
server.watcher.on("change", async (changedPath) => {
|
|
@@ -6363,6 +6500,7 @@ function createDevProcessorPlugin(options) {
|
|
|
6363
6500
|
});
|
|
6364
6501
|
setTimeout(() => {
|
|
6365
6502
|
}, 250);
|
|
6503
|
+
await initialBuildPromise;
|
|
6366
6504
|
}
|
|
6367
6505
|
};
|
|
6368
6506
|
}
|
|
@@ -6394,6 +6532,7 @@ function createSupportPlugins(options) {
|
|
|
6394
6532
|
scanDirs,
|
|
6395
6533
|
getWrapperSearchRoots,
|
|
6396
6534
|
nameCollisionBehavior = "suffix",
|
|
6535
|
+
existingIdBehavior,
|
|
6397
6536
|
outDir,
|
|
6398
6537
|
emitLanguages,
|
|
6399
6538
|
csharp,
|
|
@@ -6447,6 +6586,11 @@ function createSupportPlugins(options) {
|
|
|
6447
6586
|
customPomImportAliases,
|
|
6448
6587
|
customPomImportNameCollisionBehavior,
|
|
6449
6588
|
testIdAttribute,
|
|
6589
|
+
nameCollisionBehavior,
|
|
6590
|
+
existingIdBehavior,
|
|
6591
|
+
nativeWrappers,
|
|
6592
|
+
excludedComponents,
|
|
6593
|
+
getWrapperSearchRoots,
|
|
6450
6594
|
routerAwarePoms,
|
|
6451
6595
|
routerType,
|
|
6452
6596
|
resolvedRouterEntry,
|
|
@@ -6471,6 +6615,7 @@ function createSupportPlugins(options) {
|
|
|
6471
6615
|
customPomImportAliases,
|
|
6472
6616
|
customPomImportNameCollisionBehavior,
|
|
6473
6617
|
nameCollisionBehavior,
|
|
6618
|
+
existingIdBehavior,
|
|
6474
6619
|
testIdAttribute,
|
|
6475
6620
|
routerAwarePoms,
|
|
6476
6621
|
routerType,
|
|
@@ -7052,6 +7197,7 @@ function createVuePomGeneratorPlugins(options = {}) {
|
|
|
7052
7197
|
scanDirs,
|
|
7053
7198
|
getWrapperSearchRoots: getWrapperSearchRootsAbs,
|
|
7054
7199
|
nameCollisionBehavior,
|
|
7200
|
+
existingIdBehavior,
|
|
7055
7201
|
outDir,
|
|
7056
7202
|
emitLanguages,
|
|
7057
7203
|
csharp,
|