@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/dist/index.mjs CHANGED
@@ -2,14 +2,14 @@ import path from "node:path";
2
2
  import process from "node:process";
3
3
  import { pathToFileURL, fileURLToPath } from "node:url";
4
4
  import fs from "node:fs";
5
+ import * as compilerDom from "@vue/compiler-dom";
6
+ import { parse as parse$2 } from "@vue/compiler-dom";
7
+ import { parse as parse$1, compileScript } from "@vue/compiler-sfc";
5
8
  import { parseExpression, parse } from "@babel/parser";
6
9
  import { JSDOM } from "jsdom";
7
10
  import { NodeTypes, stringifyExpression, ConstantTypes, createSimpleExpression } from "@vue/compiler-core";
8
11
  import { isArrayExpression, isStringLiteral, isTemplateLiteral, isAssignmentExpression, isIdentifier, isMemberExpression, isCallExpression, isExpressionStatement, isArrowFunctionExpression, isOptionalMemberExpression, isObjectExpression, isFile, isBlockStatement, isOptionalCallExpression, isLogicalExpression, isConditionalExpression, isSequenceExpression, isAssignmentPattern, isRestElement, isObjectPattern, isObjectProperty, isProgram, VISITOR_KEYS, isBooleanLiteral, isNumericLiteral, isNullLiteral } from "@babel/types";
9
12
  import { performance } from "node:perf_hooks";
10
- import * as compilerDom from "@vue/compiler-dom";
11
- import { parse as parse$2 } from "@vue/compiler-dom";
12
- import { parse as parse$1 } from "@vue/compiler-sfc";
13
13
  import virtualImport from "vite-plugin-virtual";
14
14
  import vue from "@vitejs/plugin-vue";
15
15
  const VUE_POM_GENERATOR_LOG_PREFIX = "[vue-pom-generator]";
@@ -4727,148 +4727,6 @@ function getConstructor(childrenComponent, componentHierarchyMap, attachmentsFor
4727
4727
  return `${content}
4728
4728
  `;
4729
4729
  }
4730
- function summarizeHierarchyMap(componentHierarchyMap) {
4731
- let interactiveComponentCount = 0;
4732
- let dataTestIdCount = 0;
4733
- for (const dependencies of componentHierarchyMap.values()) {
4734
- const selectorCount = dependencies.dataTestIdSet?.size ?? 0;
4735
- if (selectorCount > 0) {
4736
- interactiveComponentCount += 1;
4737
- dataTestIdCount += selectorCount;
4738
- }
4739
- }
4740
- return {
4741
- entryCount: componentHierarchyMap.size,
4742
- interactiveComponentCount,
4743
- dataTestIdCount
4744
- };
4745
- }
4746
- function isLessRich(candidate, previous) {
4747
- if (candidate.dataTestIdCount !== previous.dataTestIdCount) {
4748
- return candidate.dataTestIdCount < previous.dataTestIdCount;
4749
- }
4750
- if (candidate.interactiveComponentCount !== previous.interactiveComponentCount) {
4751
- return candidate.interactiveComponentCount < previous.interactiveComponentCount;
4752
- }
4753
- return candidate.entryCount < previous.entryCount;
4754
- }
4755
- function createBuildProcessorPlugin(options) {
4756
- const {
4757
- componentHierarchyMap,
4758
- vueFilesPathMap,
4759
- viewsDir,
4760
- scanDirs,
4761
- basePageClassPath,
4762
- normalizedBasePagePath,
4763
- outDir,
4764
- emitLanguages,
4765
- csharp,
4766
- generateFixtures,
4767
- customPomAttachments,
4768
- projectRootRef,
4769
- customPomDir,
4770
- customPomImportAliases,
4771
- customPomImportNameCollisionBehavior,
4772
- testIdAttribute,
4773
- routerAwarePoms,
4774
- resolvedRouterEntry,
4775
- routerType,
4776
- routerModuleShims,
4777
- loggerRef
4778
- } = options;
4779
- let lastGeneratedMetrics = {
4780
- entryCount: 0,
4781
- interactiveComponentCount: 0,
4782
- dataTestIdCount: 0
4783
- };
4784
- return {
4785
- name: "vue-pom-generator-build",
4786
- // This plugin exists to generate code on build output; it is not needed during dev-server HMR.
4787
- apply: "build",
4788
- enforce: "pre",
4789
- async buildStart() {
4790
- if (!routerAwarePoms) {
4791
- setRouteNameToComponentNameMap(/* @__PURE__ */ new Map());
4792
- setResolveToComponentNameFn(() => null);
4793
- return;
4794
- }
4795
- let result;
4796
- if (routerType === "nuxt") {
4797
- result = await introspectNuxtPages(projectRootRef.current);
4798
- } else {
4799
- if (!resolvedRouterEntry)
4800
- throw new Error("[vue-pom-generator] router.entry is required when router introspection is enabled.");
4801
- result = await parseRouterFileFromCwd(resolvedRouterEntry, {
4802
- moduleShims: routerModuleShims,
4803
- componentNaming: {
4804
- projectRoot: projectRootRef.current,
4805
- viewsDirAbs: path.isAbsolute(viewsDir) ? viewsDir : path.resolve(projectRootRef.current, viewsDir),
4806
- scanDirs
4807
- }
4808
- });
4809
- }
4810
- const { routeNameMap, routePathMap } = result;
4811
- setRouteNameToComponentNameMap(routeNameMap);
4812
- setResolveToComponentNameFn((to) => {
4813
- if (typeof to === "string") {
4814
- return routePathMap.get(to) ?? null;
4815
- }
4816
- const maybe = to;
4817
- if (typeof maybe.name === "string" && maybe.name.length) {
4818
- const key = toPascalCase(maybe.name);
4819
- return routeNameMap.get(key) ?? null;
4820
- }
4821
- if (typeof maybe.path === "string" && maybe.path.length) {
4822
- return routePathMap.get(maybe.path) ?? null;
4823
- }
4824
- return null;
4825
- });
4826
- if (!fs.existsSync(basePageClassPath)) {
4827
- this.error(`BasePage.ts not found at ${basePageClassPath}. Ensure it is included in the build.`);
4828
- }
4829
- this.addWatchFile(basePageClassPath);
4830
- const pointerPath = path.resolve(path.dirname(basePageClassPath), "Pointer.ts");
4831
- if (!fs.existsSync(pointerPath)) {
4832
- this.error(`Pointer.ts not found at ${pointerPath}. Ensure it is included in the build.`);
4833
- }
4834
- this.addWatchFile(pointerPath);
4835
- },
4836
- async buildEnd(error) {
4837
- if (error) {
4838
- return;
4839
- }
4840
- const metrics = summarizeHierarchyMap(componentHierarchyMap);
4841
- if (metrics.dataTestIdCount <= 0) {
4842
- return;
4843
- }
4844
- if (isLessRich(metrics, lastGeneratedMetrics)) {
4845
- return;
4846
- }
4847
- await generateFiles(componentHierarchyMap, vueFilesPathMap, normalizedBasePagePath, {
4848
- outDir,
4849
- emitLanguages,
4850
- csharp,
4851
- generateFixtures,
4852
- customPomAttachments,
4853
- projectRoot: projectRootRef.current,
4854
- customPomDir,
4855
- customPomImportAliases,
4856
- customPomImportNameCollisionBehavior,
4857
- testIdAttribute,
4858
- vueRouterFluentChaining: routerAwarePoms,
4859
- routerEntry: resolvedRouterEntry,
4860
- routerType,
4861
- viewsDir,
4862
- scanDirs
4863
- });
4864
- lastGeneratedMetrics = metrics;
4865
- loggerRef.current.info(`generated POMs (${metrics.entryCount} entries, ${metrics.interactiveComponentCount} interactive components, ${metrics.dataTestIdCount} selectors)`);
4866
- },
4867
- closeBundle() {
4868
- loggerRef.current.info("build complete");
4869
- }
4870
- };
4871
- }
4872
4730
  const TESTID_CLICK_EVENT_NAME = "__testid_event__";
4873
4731
  const TESTID_CLICK_EVENT_STRICT_FLAG = "__testid_click_event_strict__";
4874
4732
  const CLICK_EVENT_NAME = TESTID_CLICK_EVENT_NAME;
@@ -5951,6 +5809,265 @@ Fix: remove the explicit ${attrLabel}, or change existingIdBehavior to "overwrit
5951
5809
  }
5952
5810
  };
5953
5811
  }
5812
+ function summarizeHierarchyMap(componentHierarchyMap) {
5813
+ let interactiveComponentCount = 0;
5814
+ let dataTestIdCount = 0;
5815
+ for (const dependencies of componentHierarchyMap.values()) {
5816
+ const selectorCount = dependencies.dataTestIdSet?.size ?? 0;
5817
+ if (selectorCount > 0) {
5818
+ interactiveComponentCount += 1;
5819
+ dataTestIdCount += selectorCount;
5820
+ }
5821
+ }
5822
+ return {
5823
+ entryCount: componentHierarchyMap.size,
5824
+ interactiveComponentCount,
5825
+ dataTestIdCount
5826
+ };
5827
+ }
5828
+ function isLessRich(candidate, previous) {
5829
+ if (candidate.dataTestIdCount !== previous.dataTestIdCount) {
5830
+ return candidate.dataTestIdCount < previous.dataTestIdCount;
5831
+ }
5832
+ if (candidate.interactiveComponentCount !== previous.interactiveComponentCount) {
5833
+ return candidate.interactiveComponentCount < previous.interactiveComponentCount;
5834
+ }
5835
+ return candidate.entryCount < previous.entryCount;
5836
+ }
5837
+ function createBuildProcessorPlugin(options) {
5838
+ const {
5839
+ componentHierarchyMap,
5840
+ vueFilesPathMap,
5841
+ viewsDir,
5842
+ scanDirs,
5843
+ basePageClassPath,
5844
+ normalizedBasePagePath,
5845
+ outDir,
5846
+ emitLanguages,
5847
+ csharp,
5848
+ generateFixtures,
5849
+ customPomAttachments,
5850
+ projectRootRef,
5851
+ customPomDir,
5852
+ customPomImportAliases,
5853
+ customPomImportNameCollisionBehavior,
5854
+ testIdAttribute,
5855
+ nameCollisionBehavior,
5856
+ existingIdBehavior,
5857
+ nativeWrappers,
5858
+ excludedComponents,
5859
+ getWrapperSearchRoots,
5860
+ routerAwarePoms,
5861
+ resolvedRouterEntry,
5862
+ routerType,
5863
+ routerModuleShims,
5864
+ loggerRef
5865
+ } = options;
5866
+ let lastGeneratedMetrics = {
5867
+ entryCount: 0,
5868
+ interactiveComponentCount: 0,
5869
+ dataTestIdCount: 0
5870
+ };
5871
+ const getViewsDirAbs = () => path.isAbsolute(viewsDir) ? viewsDir : path.resolve(projectRootRef.current, viewsDir);
5872
+ const getScriptInfo = (source, filename) => {
5873
+ try {
5874
+ const { descriptor } = parse$1(source, { filename });
5875
+ if (!descriptor.script && !descriptor.scriptSetup)
5876
+ return { bindings: void 0, isScriptSetup: false };
5877
+ const scriptBlock = compileScript(descriptor, { id: filename });
5878
+ return { bindings: scriptBlock.bindings, isScriptSetup: !!descriptor.scriptSetup };
5879
+ } catch {
5880
+ return { bindings: void 0, isScriptSetup: false };
5881
+ }
5882
+ };
5883
+ const supplementHierarchyFromFilesystem = () => {
5884
+ const walkFilesRecursive = (rootDir) => {
5885
+ const out = [];
5886
+ const stack = [rootDir];
5887
+ while (stack.length) {
5888
+ const dir = stack.pop();
5889
+ if (!dir) continue;
5890
+ let entries = [];
5891
+ try {
5892
+ entries = fs.readdirSync(dir, { withFileTypes: true });
5893
+ } catch {
5894
+ continue;
5895
+ }
5896
+ for (const ent of entries) {
5897
+ if (ent.isDirectory()) {
5898
+ if (ent.name === "node_modules" || ent.name === ".git" || ent.name === "dist")
5899
+ continue;
5900
+ stack.push(path.join(dir, ent.name));
5901
+ continue;
5902
+ }
5903
+ if (ent.isFile() && ent.name.endsWith(".vue")) {
5904
+ out.push(path.join(dir, ent.name));
5905
+ }
5906
+ }
5907
+ }
5908
+ return out;
5909
+ };
5910
+ let supplemented = 0;
5911
+ for (const dir of scanDirs) {
5912
+ const absDir = path.resolve(projectRootRef.current, dir);
5913
+ if (!fs.existsSync(absDir))
5914
+ continue;
5915
+ for (const filePath of walkFilesRecursive(absDir)) {
5916
+ const absolutePath = path.resolve(filePath);
5917
+ const componentName = resolveComponentNameFromPath({
5918
+ filename: absolutePath,
5919
+ projectRoot: projectRootRef.current,
5920
+ viewsDirAbs: getViewsDirAbs(),
5921
+ scanDirs,
5922
+ extraRoots: [process.cwd()]
5923
+ });
5924
+ if (componentHierarchyMap.has(componentName))
5925
+ continue;
5926
+ let sfc = "";
5927
+ try {
5928
+ sfc = fs.readFileSync(absolutePath, "utf8");
5929
+ } catch {
5930
+ continue;
5931
+ }
5932
+ const { descriptor } = parse$1(sfc, { filename: absolutePath });
5933
+ const template = descriptor.template?.content ?? "";
5934
+ if (!template.trim()) {
5935
+ vueFilesPathMap.set(componentName, absolutePath);
5936
+ componentHierarchyMap.set(componentName, {
5937
+ filePath: absolutePath,
5938
+ childrenComponentSet: /* @__PURE__ */ new Set(),
5939
+ usedComponentSet: /* @__PURE__ */ new Set(),
5940
+ dataTestIdSet: /* @__PURE__ */ new Set(),
5941
+ isView: false,
5942
+ methodsContent: ""
5943
+ });
5944
+ supplemented++;
5945
+ continue;
5946
+ }
5947
+ const { bindings: bindingMetadata, isScriptSetup } = getScriptInfo(sfc, absolutePath);
5948
+ vueFilesPathMap.set(componentName, absolutePath);
5949
+ try {
5950
+ compilerDom.compile(template, {
5951
+ filename: absolutePath,
5952
+ prefixIdentifiers: true,
5953
+ inline: isScriptSetup,
5954
+ bindingMetadata,
5955
+ nodeTransforms: [
5956
+ createTestIdTransform(
5957
+ componentName,
5958
+ componentHierarchyMap,
5959
+ nativeWrappers,
5960
+ excludedComponents,
5961
+ getViewsDirAbs(),
5962
+ {
5963
+ existingIdBehavior: existingIdBehavior ?? "preserve",
5964
+ testIdAttribute,
5965
+ nameCollisionBehavior,
5966
+ warn: (message) => loggerRef.current.warn(message),
5967
+ vueFilesPathMap,
5968
+ wrapperSearchRoots: getWrapperSearchRoots()
5969
+ }
5970
+ )
5971
+ ]
5972
+ });
5973
+ } catch {
5974
+ }
5975
+ supplemented++;
5976
+ }
5977
+ }
5978
+ if (supplemented > 0) {
5979
+ loggerRef.current.info(`supplemented ${supplemented} components from filesystem walk (not in build graph)`);
5980
+ }
5981
+ };
5982
+ return {
5983
+ name: "vue-pom-generator-build",
5984
+ // This plugin exists to generate code on build output; it is not needed during dev-server HMR.
5985
+ apply: "build",
5986
+ enforce: "pre",
5987
+ async buildStart() {
5988
+ if (!routerAwarePoms) {
5989
+ setRouteNameToComponentNameMap(/* @__PURE__ */ new Map());
5990
+ setResolveToComponentNameFn(() => null);
5991
+ return;
5992
+ }
5993
+ let result;
5994
+ if (routerType === "nuxt") {
5995
+ result = await introspectNuxtPages(projectRootRef.current);
5996
+ } else {
5997
+ if (!resolvedRouterEntry)
5998
+ throw new Error("[vue-pom-generator] router.entry is required when router introspection is enabled.");
5999
+ result = await parseRouterFileFromCwd(resolvedRouterEntry, {
6000
+ moduleShims: routerModuleShims,
6001
+ componentNaming: {
6002
+ projectRoot: projectRootRef.current,
6003
+ viewsDirAbs: path.isAbsolute(viewsDir) ? viewsDir : path.resolve(projectRootRef.current, viewsDir),
6004
+ scanDirs
6005
+ }
6006
+ });
6007
+ }
6008
+ const { routeNameMap, routePathMap } = result;
6009
+ setRouteNameToComponentNameMap(routeNameMap);
6010
+ setResolveToComponentNameFn((to) => {
6011
+ if (typeof to === "string") {
6012
+ return routePathMap.get(to) ?? null;
6013
+ }
6014
+ const maybe = to;
6015
+ if (typeof maybe.name === "string" && maybe.name.length) {
6016
+ const key = toPascalCase(maybe.name);
6017
+ return routeNameMap.get(key) ?? null;
6018
+ }
6019
+ if (typeof maybe.path === "string" && maybe.path.length) {
6020
+ return routePathMap.get(maybe.path) ?? null;
6021
+ }
6022
+ return null;
6023
+ });
6024
+ if (!fs.existsSync(basePageClassPath)) {
6025
+ this.error(`BasePage.ts not found at ${basePageClassPath}. Ensure it is included in the build.`);
6026
+ }
6027
+ this.addWatchFile(basePageClassPath);
6028
+ const pointerPath = path.resolve(path.dirname(basePageClassPath), "Pointer.ts");
6029
+ if (!fs.existsSync(pointerPath)) {
6030
+ this.error(`Pointer.ts not found at ${pointerPath}. Ensure it is included in the build.`);
6031
+ }
6032
+ this.addWatchFile(pointerPath);
6033
+ },
6034
+ async buildEnd(error) {
6035
+ if (error) {
6036
+ return;
6037
+ }
6038
+ supplementHierarchyFromFilesystem();
6039
+ const metrics = summarizeHierarchyMap(componentHierarchyMap);
6040
+ if (metrics.dataTestIdCount <= 0) {
6041
+ return;
6042
+ }
6043
+ if (isLessRich(metrics, lastGeneratedMetrics)) {
6044
+ return;
6045
+ }
6046
+ await generateFiles(componentHierarchyMap, vueFilesPathMap, normalizedBasePagePath, {
6047
+ outDir,
6048
+ emitLanguages,
6049
+ csharp,
6050
+ generateFixtures,
6051
+ customPomAttachments,
6052
+ projectRoot: projectRootRef.current,
6053
+ customPomDir,
6054
+ customPomImportAliases,
6055
+ customPomImportNameCollisionBehavior,
6056
+ testIdAttribute,
6057
+ vueRouterFluentChaining: routerAwarePoms,
6058
+ routerEntry: resolvedRouterEntry,
6059
+ routerType,
6060
+ viewsDir,
6061
+ scanDirs
6062
+ });
6063
+ lastGeneratedMetrics = metrics;
6064
+ loggerRef.current.info(`generated POMs (${metrics.entryCount} entries, ${metrics.interactiveComponentCount} interactive components, ${metrics.dataTestIdCount} selectors)`);
6065
+ },
6066
+ closeBundle() {
6067
+ loggerRef.current.info("build complete");
6068
+ }
6069
+ };
6070
+ }
5954
6071
  function createDevProcessorPlugin(options) {
5955
6072
  const {
5956
6073
  nativeWrappers,
@@ -5970,6 +6087,7 @@ function createDevProcessorPlugin(options) {
5970
6087
  customPomImportAliases,
5971
6088
  customPomImportNameCollisionBehavior,
5972
6089
  nameCollisionBehavior = "suffix",
6090
+ existingIdBehavior,
5973
6091
  testIdAttribute,
5974
6092
  routerAwarePoms,
5975
6093
  resolvedRouterEntry,
@@ -5996,7 +6114,7 @@ function createDevProcessorPlugin(options) {
5996
6114
  return;
5997
6115
  scheduleVueFileRegen(ctx.file, "hmr");
5998
6116
  },
5999
- configureServer(server) {
6117
+ async configureServer(server) {
6000
6118
  const getViewsDirAbs = () => path.isAbsolute(viewsDir) ? viewsDir : path.resolve(projectRootRef.current, viewsDir);
6001
6119
  const routerInitPromise = (async () => {
6002
6120
  if (!routerAwarePoms) {
@@ -6047,6 +6165,17 @@ function createDevProcessorPlugin(options) {
6047
6165
  });
6048
6166
  return descriptor.template?.content ?? "";
6049
6167
  };
6168
+ const getScriptInfo = (source, filename) => {
6169
+ try {
6170
+ const { descriptor } = parse$1(source, { filename });
6171
+ if (!descriptor.script && !descriptor.scriptSetup)
6172
+ return { bindings: void 0, isScriptSetup: false };
6173
+ const scriptBlock = compileScript(descriptor, { id: filename });
6174
+ return { bindings: scriptBlock.bindings, isScriptSetup: !!descriptor.scriptSetup };
6175
+ } catch {
6176
+ return { bindings: void 0, isScriptSetup: false };
6177
+ }
6178
+ };
6050
6179
  const walkFilesRecursive = (rootDir) => {
6051
6180
  const out = [];
6052
6181
  const stack = [rootDir];
@@ -6073,8 +6202,8 @@ function createDevProcessorPlugin(options) {
6073
6202
  }
6074
6203
  return out;
6075
6204
  };
6076
- const snapshotHierarchy = /* @__PURE__ */ new Map();
6077
- const snapshotVuePathMap = /* @__PURE__ */ new Map();
6205
+ let snapshotHierarchy = /* @__PURE__ */ new Map();
6206
+ let snapshotVuePathMap = /* @__PURE__ */ new Map();
6078
6207
  const filePathToComponentName = /* @__PURE__ */ new Map();
6079
6208
  const getComponentNameForFile = (filePath) => {
6080
6209
  const normalized = path.resolve(filePath);
@@ -6091,12 +6220,12 @@ function createDevProcessorPlugin(options) {
6091
6220
  filePathToComponentName.set(normalized, name);
6092
6221
  return name;
6093
6222
  };
6094
- const compileVueFileIntoSnapshot = (filePath) => {
6223
+ const compileVueFileIntoSnapshot = (filePath, targetHierarchy = snapshotHierarchy, targetVuePathMap = snapshotVuePathMap) => {
6095
6224
  const started = performance.now();
6096
6225
  const absolutePath = path.resolve(filePath);
6097
6226
  const componentName = getComponentNameForFile(absolutePath);
6098
- snapshotVuePathMap.set(componentName, absolutePath);
6099
- snapshotHierarchy.delete(componentName);
6227
+ targetVuePathMap.set(componentName, absolutePath);
6228
+ targetHierarchy.delete(componentName);
6100
6229
  let sfc = "";
6101
6230
  try {
6102
6231
  sfc = fs.readFileSync(absolutePath, "utf8");
@@ -6106,36 +6235,36 @@ function createDevProcessorPlugin(options) {
6106
6235
  const template = extractTemplateFromSfc(sfc, absolutePath);
6107
6236
  if (!template.trim())
6108
6237
  return { componentName, ms: performance.now() - started, compiled: true };
6109
- try {
6110
- compilerDom.compile(template, {
6111
- filename: absolutePath,
6112
- prefixIdentifiers: true,
6113
- nodeTransforms: [
6114
- createTestIdTransform(
6115
- componentName,
6116
- snapshotHierarchy,
6117
- nativeWrappers,
6118
- excludedComponents,
6119
- getViewsDirAbs(),
6120
- {
6121
- existingIdBehavior: "preserve",
6122
- nameCollisionBehavior,
6123
- testIdAttribute,
6124
- warn: (message) => loggerRef.current.warn(message),
6125
- vueFilesPathMap: snapshotVuePathMap,
6126
- wrapperSearchRoots: getWrapperSearchRoots()
6127
- }
6128
- )
6129
- ]
6130
- });
6131
- } catch {
6132
- }
6238
+ const { bindings: bindingMetadata, isScriptSetup } = getScriptInfo(sfc, absolutePath);
6239
+ compilerDom.compile(template, {
6240
+ filename: absolutePath,
6241
+ prefixIdentifiers: true,
6242
+ inline: isScriptSetup,
6243
+ bindingMetadata,
6244
+ nodeTransforms: [
6245
+ createTestIdTransform(
6246
+ componentName,
6247
+ targetHierarchy,
6248
+ nativeWrappers,
6249
+ excludedComponents,
6250
+ getViewsDirAbs(),
6251
+ {
6252
+ existingIdBehavior: existingIdBehavior ?? "preserve",
6253
+ nameCollisionBehavior,
6254
+ testIdAttribute,
6255
+ warn: (message) => loggerRef.current.warn(message),
6256
+ vueFilesPathMap: targetVuePathMap,
6257
+ wrapperSearchRoots: getWrapperSearchRoots()
6258
+ }
6259
+ )
6260
+ ]
6261
+ });
6133
6262
  return { componentName, ms: performance.now() - started, compiled: true };
6134
6263
  };
6135
6264
  const fullRebuildSnapshotFromFilesystem = () => {
6136
6265
  const t0 = performance.now();
6137
- snapshotHierarchy.clear();
6138
- snapshotVuePathMap.clear();
6266
+ const nextHierarchy = /* @__PURE__ */ new Map();
6267
+ const nextVuePathMap = /* @__PURE__ */ new Map();
6139
6268
  filePathToComponentName.clear();
6140
6269
  let totalVueFiles = 0;
6141
6270
  let compiledCount = 0;
@@ -6146,11 +6275,13 @@ function createDevProcessorPlugin(options) {
6146
6275
  const vueFiles = walkFilesRecursive(absDir);
6147
6276
  totalVueFiles += vueFiles.length;
6148
6277
  for (const file of vueFiles) {
6149
- const res = compileVueFileIntoSnapshot(file);
6278
+ const res = compileVueFileIntoSnapshot(file, nextHierarchy, nextVuePathMap);
6150
6279
  if (res.compiled)
6151
6280
  compiledCount++;
6152
6281
  }
6153
6282
  }
6283
+ snapshotHierarchy = nextHierarchy;
6284
+ snapshotVuePathMap = nextVuePathMap;
6154
6285
  const t1 = performance.now();
6155
6286
  logInfo(`initial scan: found ${totalVueFiles} .vue files in ${scanDirs.join(", ")}`);
6156
6287
  logInfo(`initial compile: ${compiledCount}/${totalVueFiles} files in ${formatMs(t1 - t0)} (components=${snapshotHierarchy.size})`);
@@ -6177,6 +6308,10 @@ function createDevProcessorPlugin(options) {
6177
6308
  const t1 = performance.now();
6178
6309
  logInfo(`generate(${reason}): components=${snapshotHierarchy.size} in ${formatMs(t1 - t0)}`);
6179
6310
  };
6311
+ let timer = null;
6312
+ let maxWaitTimer = null;
6313
+ const pendingChangedVueFiles = /* @__PURE__ */ new Set();
6314
+ const pendingDeletedComponents = /* @__PURE__ */ new Set();
6180
6315
  const initialBuildPromise = (async () => {
6181
6316
  const t0 = performance.now();
6182
6317
  await routerInitPromise;
@@ -6185,13 +6320,44 @@ function createDevProcessorPlugin(options) {
6185
6320
  const t1 = performance.now();
6186
6321
  logInfo(`startup total: ${formatMs(t1 - t0)}`);
6187
6322
  })();
6323
+ const logGenerationError = (reason, message) => {
6324
+ server.config.logger.error(`[vue-pom-generator] dev generation failed during ${reason}: ${message}`);
6325
+ };
6326
+ const regenerateFromPending = async (reason) => {
6327
+ const t0 = performance.now();
6328
+ await initialBuildPromise;
6329
+ const nextHierarchy = new Map(snapshotHierarchy);
6330
+ const nextVuePathMap = new Map(snapshotVuePathMap);
6331
+ for (const componentName of pendingDeletedComponents) {
6332
+ nextHierarchy.delete(componentName);
6333
+ nextVuePathMap.delete(componentName);
6334
+ }
6335
+ const files = Array.from(pendingChangedVueFiles);
6336
+ const deletedCount = pendingDeletedComponents.size;
6337
+ pendingChangedVueFiles.clear();
6338
+ pendingDeletedComponents.clear();
6339
+ let compileMs = 0;
6340
+ for (const f of files) {
6341
+ const res = compileVueFileIntoSnapshot(f, nextHierarchy, nextVuePathMap);
6342
+ compileMs += res.ms;
6343
+ }
6344
+ snapshotHierarchy = nextHierarchy;
6345
+ snapshotVuePathMap = nextVuePathMap;
6346
+ const t1 = performance.now();
6347
+ generateAggregatedFromSnapshot(reason);
6348
+ const t2 = performance.now();
6349
+ return {
6350
+ files,
6351
+ deletedCount,
6352
+ compileMs,
6353
+ preGenerateMs: t1 - t0,
6354
+ generateMs: t2 - t1,
6355
+ totalMs: t2 - t0
6356
+ };
6357
+ };
6188
6358
  const watchedVueGlobs = scanDirs.map((dir) => path.resolve(projectRootRef.current, dir, "**", "*.vue"));
6189
6359
  const watchedPluginGlob = path.resolve(projectRootRef.current, "vite-plugins", "vue-pom-generator", "**", "*.ts");
6190
6360
  server.watcher.add([...watchedVueGlobs, watchedPluginGlob, basePageClassPath]);
6191
- let timer = null;
6192
- let maxWaitTimer = null;
6193
- const pendingChangedVueFiles = /* @__PURE__ */ new Set();
6194
- const pendingDeletedComponents = /* @__PURE__ */ new Set();
6195
6361
  scheduleVueFileRegenLocal = (filePath, source) => {
6196
6362
  pendingChangedVueFiles.add(filePath);
6197
6363
  logDebug(`queued(${source}): files=${pendingChangedVueFiles.size} deleted=${pendingDeletedComponents.size}`);
@@ -6208,29 +6374,14 @@ function createDevProcessorPlugin(options) {
6208
6374
  timer = null;
6209
6375
  }
6210
6376
  maxWaitTimer = null;
6211
- void (async () => {
6212
- const t0 = performance.now();
6213
- await initialBuildPromise;
6214
- for (const componentName of pendingDeletedComponents) {
6215
- snapshotHierarchy.delete(componentName);
6216
- snapshotVuePathMap.delete(componentName);
6217
- }
6218
- const files = Array.from(pendingChangedVueFiles);
6219
- const deletedCount = pendingDeletedComponents.size;
6220
- pendingChangedVueFiles.clear();
6221
- pendingDeletedComponents.clear();
6222
- let compileMs = 0;
6223
- for (const f of files) {
6224
- const res = compileVueFileIntoSnapshot(f);
6225
- compileMs += res.ms;
6226
- }
6227
- const t1 = performance.now();
6228
- generateAggregatedFromSnapshot("max-wait");
6229
- const t2 = performance.now();
6377
+ void regenerateFromPending("max-wait").then(({ files, deletedCount, compileMs, preGenerateMs, generateMs, totalMs }) => {
6230
6378
  logInfo(
6231
- `max-wait: files=${files.length} deleted=${deletedCount} compile=${formatMs(compileMs)} wall=${formatMs(t1 - t0)} gen=${formatMs(t2 - t1)} total=${formatMs(t2 - t0)}`
6379
+ `max-wait: files=${files.length} deleted=${deletedCount} compile=${formatMs(compileMs)} wall=${formatMs(preGenerateMs)} gen=${formatMs(generateMs)} total=${formatMs(totalMs)}`
6232
6380
  );
6233
- })();
6381
+ }).catch((error) => {
6382
+ const message = error instanceof Error ? error.message : String(error);
6383
+ logGenerationError("max-wait", message);
6384
+ });
6234
6385
  }, MAX_WAIT_MS);
6235
6386
  }
6236
6387
  if (wasEmpty) {
@@ -6246,31 +6397,17 @@ function createDevProcessorPlugin(options) {
6246
6397
  clearTimeout(maxWaitTimer);
6247
6398
  maxWaitTimer = null;
6248
6399
  }
6249
- void (async () => {
6250
- const t0 = performance.now();
6251
- await initialBuildPromise;
6252
- for (const componentName of pendingDeletedComponents) {
6253
- snapshotHierarchy.delete(componentName);
6254
- snapshotVuePathMap.delete(componentName);
6255
- }
6256
- const files = Array.from(pendingChangedVueFiles);
6257
- const deletedCount = pendingDeletedComponents.size;
6258
- pendingChangedVueFiles.clear();
6259
- pendingDeletedComponents.clear();
6260
- let compileMs = 0;
6261
- for (const f of files) {
6262
- const res = compileVueFileIntoSnapshot(f);
6263
- compileMs += res.ms;
6264
- }
6265
- const t1 = performance.now();
6266
- generateAggregatedFromSnapshot(files.length || deletedCount ? "batched" : "noop");
6267
- const t2 = performance.now();
6400
+ const reason = pendingChangedVueFiles.size || pendingDeletedComponents.size ? "batched" : "noop";
6401
+ void regenerateFromPending(reason).then(({ files, deletedCount, compileMs, preGenerateMs, generateMs, totalMs }) => {
6268
6402
  if (files.length || deletedCount) {
6269
6403
  logInfo(
6270
- `batched: files=${files.length} deleted=${deletedCount} compile=${formatMs(compileMs)} wall=${formatMs(t1 - t0)} gen=${formatMs(t2 - t1)} total=${formatMs(t2 - t0)}`
6404
+ `batched: files=${files.length} deleted=${deletedCount} compile=${formatMs(compileMs)} wall=${formatMs(preGenerateMs)} gen=${formatMs(generateMs)} total=${formatMs(totalMs)}`
6271
6405
  );
6272
6406
  }
6273
- })();
6407
+ }).catch((error) => {
6408
+ const message = error instanceof Error ? error.message : String(error);
6409
+ logGenerationError(reason, message);
6410
+ });
6274
6411
  }, 75);
6275
6412
  }
6276
6413
  server.watcher.on("change", async (changedPath) => {
@@ -6322,6 +6459,7 @@ function createDevProcessorPlugin(options) {
6322
6459
  });
6323
6460
  setTimeout(() => {
6324
6461
  }, 250);
6462
+ await initialBuildPromise;
6325
6463
  }
6326
6464
  };
6327
6465
  }
@@ -6353,6 +6491,7 @@ function createSupportPlugins(options) {
6353
6491
  scanDirs,
6354
6492
  getWrapperSearchRoots,
6355
6493
  nameCollisionBehavior = "suffix",
6494
+ existingIdBehavior,
6356
6495
  outDir,
6357
6496
  emitLanguages,
6358
6497
  csharp,
@@ -6406,6 +6545,11 @@ function createSupportPlugins(options) {
6406
6545
  customPomImportAliases,
6407
6546
  customPomImportNameCollisionBehavior,
6408
6547
  testIdAttribute,
6548
+ nameCollisionBehavior,
6549
+ existingIdBehavior,
6550
+ nativeWrappers,
6551
+ excludedComponents,
6552
+ getWrapperSearchRoots,
6409
6553
  routerAwarePoms,
6410
6554
  routerType,
6411
6555
  resolvedRouterEntry,
@@ -6430,6 +6574,7 @@ function createSupportPlugins(options) {
6430
6574
  customPomImportAliases,
6431
6575
  customPomImportNameCollisionBehavior,
6432
6576
  nameCollisionBehavior,
6577
+ existingIdBehavior,
6433
6578
  testIdAttribute,
6434
6579
  routerAwarePoms,
6435
6580
  routerType,
@@ -7011,6 +7156,7 @@ function createVuePomGeneratorPlugins(options = {}) {
7011
7156
  scanDirs,
7012
7157
  getWrapperSearchRoots: getWrapperSearchRootsAbs,
7013
7158
  nameCollisionBehavior,
7159
+ existingIdBehavior,
7014
7160
  outDir,
7015
7161
  emitLanguages,
7016
7162
  csharp,